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 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/errno.h> 29 #include <sys/sysmacros.h> 30 #include <sys/param.h> 31 #include <sys/stream.h> 32 #include <sys/strsubr.h> 33 #include <sys/kmem.h> 34 #include <sys/conf.h> 35 #include <sys/devops.h> 36 #include <sys/ksynch.h> 37 #include <sys/stat.h> 38 #include <sys/modctl.h> 39 #include <sys/debug.h> 40 #include <sys/ethernet.h> 41 #include <sys/ddi.h> 42 #include <sys/sunddi.h> 43 #include <sys/strsun.h> 44 #include <sys/note.h> 45 #include <sys/mac_provider.h> 46 #include <sys/mac_ether.h> 47 #include <sys/ldc.h> 48 #include <sys/mach_descrip.h> 49 #include <sys/mdeg.h> 50 #include <net/if.h> 51 #include <sys/vnet.h> 52 #include <sys/vio_mailbox.h> 53 #include <sys/vio_common.h> 54 #include <sys/vnet_common.h> 55 #include <sys/vnet_mailbox.h> 56 #include <sys/vio_util.h> 57 #include <sys/vnet_gen.h> 58 #include <sys/atomic.h> 59 #include <sys/callb.h> 60 #include <sys/sdt.h> 61 #include <sys/intr.h> 62 #include <sys/pattr.h> 63 #include <sys/vlan.h> 64 65 /* 66 * Implementation of the mac functionality for vnet using the 67 * generic(default) transport layer of sun4v Logical Domain Channels(LDC). 68 */ 69 70 /* 71 * Function prototypes. 72 */ 73 /* vgen proxy entry points */ 74 int vgen_init(void *vnetp, uint64_t regprop, dev_info_t *vnetdip, 75 const uint8_t *macaddr, void **vgenhdl); 76 int vgen_init_mdeg(void *arg); 77 void vgen_uninit(void *arg); 78 int vgen_dds_tx(void *arg, void *dmsg); 79 void vgen_mod_init(void); 80 int vgen_mod_cleanup(void); 81 void vgen_mod_fini(void); 82 int vgen_enable_intr(void *arg); 83 int vgen_disable_intr(void *arg); 84 mblk_t *vgen_poll(void *arg, int bytes_to_pickup); 85 static int vgen_start(void *arg); 86 static void vgen_stop(void *arg); 87 static mblk_t *vgen_tx(void *arg, mblk_t *mp); 88 static int vgen_multicst(void *arg, boolean_t add, 89 const uint8_t *mca); 90 static int vgen_promisc(void *arg, boolean_t on); 91 static int vgen_unicst(void *arg, const uint8_t *mca); 92 static int vgen_stat(void *arg, uint_t stat, uint64_t *val); 93 static void vgen_ioctl(void *arg, queue_t *q, mblk_t *mp); 94 #ifdef VNET_IOC_DEBUG 95 static int vgen_force_link_state(vgen_port_t *portp, int link_state); 96 #endif 97 98 /* vgen internal functions */ 99 static int vgen_read_mdprops(vgen_t *vgenp); 100 static void vgen_update_md_prop(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex); 101 static void vgen_read_pri_eth_types(vgen_t *vgenp, md_t *mdp, 102 mde_cookie_t node); 103 static void vgen_mtu_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node, 104 uint32_t *mtu); 105 static void vgen_linkprop_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node, 106 boolean_t *pls); 107 static void vgen_detach_ports(vgen_t *vgenp); 108 static void vgen_port_detach(vgen_port_t *portp); 109 static void vgen_port_list_insert(vgen_port_t *portp); 110 static void vgen_port_list_remove(vgen_port_t *portp); 111 static vgen_port_t *vgen_port_lookup(vgen_portlist_t *plistp, 112 int port_num); 113 static int vgen_mdeg_reg(vgen_t *vgenp); 114 static void vgen_mdeg_unreg(vgen_t *vgenp); 115 static int vgen_mdeg_cb(void *cb_argp, mdeg_result_t *resp); 116 static int vgen_mdeg_port_cb(void *cb_argp, mdeg_result_t *resp); 117 static int vgen_add_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex); 118 static int vgen_port_read_props(vgen_port_t *portp, vgen_t *vgenp, md_t *mdp, 119 mde_cookie_t mdex); 120 static int vgen_remove_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex); 121 static int vgen_port_attach(vgen_port_t *portp); 122 static void vgen_port_detach_mdeg(vgen_port_t *portp); 123 static void vgen_port_detach_mdeg(vgen_port_t *portp); 124 static int vgen_update_port(vgen_t *vgenp, md_t *curr_mdp, 125 mde_cookie_t curr_mdex, md_t *prev_mdp, mde_cookie_t prev_mdex); 126 static uint64_t vgen_port_stat(vgen_port_t *portp, uint_t stat); 127 static void vgen_port_reset(vgen_port_t *portp); 128 static void vgen_reset_vsw_port(vgen_t *vgenp); 129 static void vgen_ldc_reset(vgen_ldc_t *ldcp); 130 static int vgen_ldc_attach(vgen_port_t *portp, uint64_t ldc_id); 131 static void vgen_ldc_detach(vgen_ldc_t *ldcp); 132 static int vgen_alloc_tx_ring(vgen_ldc_t *ldcp); 133 static void vgen_free_tx_ring(vgen_ldc_t *ldcp); 134 static void vgen_init_ports(vgen_t *vgenp); 135 static void vgen_port_init(vgen_port_t *portp); 136 static void vgen_uninit_ports(vgen_t *vgenp); 137 static void vgen_port_uninit(vgen_port_t *portp); 138 static void vgen_init_ldcs(vgen_port_t *portp); 139 static void vgen_uninit_ldcs(vgen_port_t *portp); 140 static int vgen_ldc_init(vgen_ldc_t *ldcp); 141 static void vgen_ldc_uninit(vgen_ldc_t *ldcp); 142 static int vgen_init_tbufs(vgen_ldc_t *ldcp); 143 static void vgen_uninit_tbufs(vgen_ldc_t *ldcp); 144 static void vgen_clobber_tbufs(vgen_ldc_t *ldcp); 145 static void vgen_clobber_rxds(vgen_ldc_t *ldcp); 146 static uint64_t vgen_ldc_stat(vgen_ldc_t *ldcp, uint_t stat); 147 static uint_t vgen_ldc_cb(uint64_t event, caddr_t arg); 148 static int vgen_portsend(vgen_port_t *portp, mblk_t *mp); 149 static int vgen_ldcsend(void *arg, mblk_t *mp); 150 static void vgen_ldcsend_pkt(void *arg, mblk_t *mp); 151 static int vgen_ldcsend_dring(void *arg, mblk_t *mp); 152 static void vgen_reclaim(vgen_ldc_t *ldcp); 153 static void vgen_reclaim_dring(vgen_ldc_t *ldcp); 154 static int vgen_num_txpending(vgen_ldc_t *ldcp); 155 static int vgen_tx_dring_full(vgen_ldc_t *ldcp); 156 static int vgen_ldc_txtimeout(vgen_ldc_t *ldcp); 157 static void vgen_ldc_watchdog(void *arg); 158 static mblk_t *vgen_ldc_poll(vgen_ldc_t *ldcp, int bytes_to_pickup); 159 160 /* vgen handshake functions */ 161 static vgen_ldc_t *vh_nextphase(vgen_ldc_t *ldcp); 162 static int vgen_sendmsg(vgen_ldc_t *ldcp, caddr_t msg, size_t msglen, 163 boolean_t caller_holds_lock); 164 static int vgen_send_version_negotiate(vgen_ldc_t *ldcp); 165 static int vgen_send_attr_info(vgen_ldc_t *ldcp); 166 static int vgen_send_dring_reg(vgen_ldc_t *ldcp); 167 static int vgen_send_rdx_info(vgen_ldc_t *ldcp); 168 static int vgen_send_dring_data(vgen_ldc_t *ldcp, uint32_t start, int32_t end); 169 static int vgen_send_mcast_info(vgen_ldc_t *ldcp); 170 static int vgen_handshake_phase2(vgen_ldc_t *ldcp); 171 static void vgen_handshake_reset(vgen_ldc_t *ldcp); 172 static void vgen_reset_hphase(vgen_ldc_t *ldcp); 173 static void vgen_handshake(vgen_ldc_t *ldcp); 174 static int vgen_handshake_done(vgen_ldc_t *ldcp); 175 static void vgen_handshake_retry(vgen_ldc_t *ldcp); 176 static int vgen_handle_version_negotiate(vgen_ldc_t *ldcp, 177 vio_msg_tag_t *tagp); 178 static int vgen_handle_attr_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 179 static int vgen_handle_dring_reg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 180 static int vgen_handle_rdx_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 181 static int vgen_handle_mcast_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 182 static int vgen_handle_ctrlmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 183 static void vgen_handle_pkt_data_nop(void *arg1, void *arg2, uint32_t msglen); 184 static void vgen_handle_pkt_data(void *arg1, void *arg2, uint32_t msglen); 185 static int vgen_handle_dring_data(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 186 static int vgen_handle_dring_data_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 187 static int vgen_process_dring_data(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 188 static int vgen_handle_dring_data_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 189 static int vgen_handle_dring_data_nack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 190 static int vgen_send_dring_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp, 191 uint32_t start, int32_t end, uint8_t pstate); 192 static int vgen_handle_datamsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp, 193 uint32_t msglen); 194 static void vgen_handle_errmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 195 static void vgen_handle_evt_up(vgen_ldc_t *ldcp); 196 static void vgen_handle_evt_reset(vgen_ldc_t *ldcp); 197 static int vgen_check_sid(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 198 static int vgen_check_datamsg_seq(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 199 static caddr_t vgen_print_ethaddr(uint8_t *a, char *ebuf); 200 static void vgen_hwatchdog(void *arg); 201 static void vgen_print_attr_info(vgen_ldc_t *ldcp, int endpoint); 202 static void vgen_print_hparams(vgen_hparams_t *hp); 203 static void vgen_print_ldcinfo(vgen_ldc_t *ldcp); 204 static void vgen_stop_rcv_thread(vgen_ldc_t *ldcp); 205 static void vgen_drain_rcv_thread(vgen_ldc_t *ldcp); 206 static void vgen_ldc_rcv_worker(void *arg); 207 static void vgen_handle_evt_read(vgen_ldc_t *ldcp); 208 static void vgen_rx(vgen_ldc_t *ldcp, mblk_t *bp, mblk_t *bpt); 209 static void vgen_set_vnet_proto_ops(vgen_ldc_t *ldcp); 210 static void vgen_reset_vnet_proto_ops(vgen_ldc_t *ldcp); 211 static void vgen_link_update(vgen_t *vgenp, link_state_t link_state); 212 213 /* VLAN routines */ 214 static void vgen_vlan_read_ids(void *arg, int type, md_t *mdp, 215 mde_cookie_t node, uint16_t *pvidp, uint16_t **vidspp, 216 uint16_t *nvidsp, uint16_t *default_idp); 217 static void vgen_vlan_create_hash(vgen_port_t *portp); 218 static void vgen_vlan_destroy_hash(vgen_port_t *portp); 219 static void vgen_vlan_add_ids(vgen_port_t *portp); 220 static void vgen_vlan_remove_ids(vgen_port_t *portp); 221 static boolean_t vgen_vlan_lookup(mod_hash_t *vlan_hashp, uint16_t vid); 222 static boolean_t vgen_frame_lookup_vid(vnet_t *vnetp, struct ether_header *ehp, 223 uint16_t *vidp); 224 static mblk_t *vgen_vlan_frame_fixtag(vgen_port_t *portp, mblk_t *mp, 225 boolean_t is_tagged, uint16_t vid); 226 static void vgen_vlan_unaware_port_reset(vgen_port_t *portp); 227 static void vgen_reset_vlan_unaware_ports(vgen_t *vgenp); 228 static int vgen_dds_rx(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 229 230 /* externs */ 231 extern void vnet_dds_rx(void *arg, void *dmsg); 232 extern void vnet_dds_cleanup_hio(vnet_t *vnetp); 233 extern int vnet_mtu_update(vnet_t *vnetp, uint32_t mtu); 234 extern void vnet_link_update(vnet_t *vnetp, link_state_t link_state); 235 236 /* 237 * The handshake process consists of 5 phases defined below, with VH_PHASE0 238 * being the pre-handshake phase and VH_DONE is the phase to indicate 239 * successful completion of all phases. 240 * Each phase may have one to several handshake states which are required 241 * to complete successfully to move to the next phase. 242 * Refer to the functions vgen_handshake() and vgen_handshake_done() for 243 * more details. 244 */ 245 /* handshake phases */ 246 enum { VH_PHASE0, VH_PHASE1, VH_PHASE2, VH_PHASE3, VH_DONE = 0x80 }; 247 248 /* handshake states */ 249 enum { 250 251 VER_INFO_SENT = 0x1, 252 VER_ACK_RCVD = 0x2, 253 VER_INFO_RCVD = 0x4, 254 VER_ACK_SENT = 0x8, 255 VER_NEGOTIATED = (VER_ACK_RCVD | VER_ACK_SENT), 256 257 ATTR_INFO_SENT = 0x10, 258 ATTR_ACK_RCVD = 0x20, 259 ATTR_INFO_RCVD = 0x40, 260 ATTR_ACK_SENT = 0x80, 261 ATTR_INFO_EXCHANGED = (ATTR_ACK_RCVD | ATTR_ACK_SENT), 262 263 DRING_INFO_SENT = 0x100, 264 DRING_ACK_RCVD = 0x200, 265 DRING_INFO_RCVD = 0x400, 266 DRING_ACK_SENT = 0x800, 267 DRING_INFO_EXCHANGED = (DRING_ACK_RCVD | DRING_ACK_SENT), 268 269 RDX_INFO_SENT = 0x1000, 270 RDX_ACK_RCVD = 0x2000, 271 RDX_INFO_RCVD = 0x4000, 272 RDX_ACK_SENT = 0x8000, 273 RDX_EXCHANGED = (RDX_ACK_RCVD | RDX_ACK_SENT) 274 275 }; 276 277 #define VGEN_PRI_ETH_DEFINED(vgenp) ((vgenp)->pri_num_types != 0) 278 279 #define LDC_LOCK(ldcp) \ 280 mutex_enter(&((ldcp)->cblock));\ 281 mutex_enter(&((ldcp)->rxlock));\ 282 mutex_enter(&((ldcp)->wrlock));\ 283 mutex_enter(&((ldcp)->txlock));\ 284 mutex_enter(&((ldcp)->tclock)); 285 #define LDC_UNLOCK(ldcp) \ 286 mutex_exit(&((ldcp)->tclock));\ 287 mutex_exit(&((ldcp)->txlock));\ 288 mutex_exit(&((ldcp)->wrlock));\ 289 mutex_exit(&((ldcp)->rxlock));\ 290 mutex_exit(&((ldcp)->cblock)); 291 292 #define VGEN_VER_EQ(ldcp, major, minor) \ 293 ((ldcp)->local_hparams.ver_major == (major) && \ 294 (ldcp)->local_hparams.ver_minor == (minor)) 295 296 #define VGEN_VER_LT(ldcp, major, minor) \ 297 (((ldcp)->local_hparams.ver_major < (major)) || \ 298 ((ldcp)->local_hparams.ver_major == (major) && \ 299 (ldcp)->local_hparams.ver_minor < (minor))) 300 301 #define VGEN_VER_GTEQ(ldcp, major, minor) \ 302 (((ldcp)->local_hparams.ver_major > (major)) || \ 303 ((ldcp)->local_hparams.ver_major == (major) && \ 304 (ldcp)->local_hparams.ver_minor >= (minor))) 305 306 static struct ether_addr etherbroadcastaddr = { 307 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 308 }; 309 /* 310 * MIB II broadcast/multicast packets 311 */ 312 #define IS_BROADCAST(ehp) \ 313 (ether_cmp(&ehp->ether_dhost, ðerbroadcastaddr) == 0) 314 #define IS_MULTICAST(ehp) \ 315 ((ehp->ether_dhost.ether_addr_octet[0] & 01) == 1) 316 317 /* 318 * Property names 319 */ 320 static char macaddr_propname[] = "mac-address"; 321 static char rmacaddr_propname[] = "remote-mac-address"; 322 static char channel_propname[] = "channel-endpoint"; 323 static char reg_propname[] = "reg"; 324 static char port_propname[] = "port"; 325 static char swport_propname[] = "switch-port"; 326 static char id_propname[] = "id"; 327 static char vdev_propname[] = "virtual-device"; 328 static char vnet_propname[] = "network"; 329 static char pri_types_propname[] = "priority-ether-types"; 330 static char vgen_pvid_propname[] = "port-vlan-id"; 331 static char vgen_vid_propname[] = "vlan-id"; 332 static char vgen_dvid_propname[] = "default-vlan-id"; 333 static char port_pvid_propname[] = "remote-port-vlan-id"; 334 static char port_vid_propname[] = "remote-vlan-id"; 335 static char vgen_mtu_propname[] = "mtu"; 336 static char vgen_linkprop_propname[] = "linkprop"; 337 338 /* 339 * VIO Protocol Version Info: 340 * 341 * The version specified below represents the version of protocol currently 342 * supported in the driver. It means the driver can negotiate with peers with 343 * versions <= this version. Here is a summary of the feature(s) that are 344 * supported at each version of the protocol: 345 * 346 * 1.0 Basic VIO protocol. 347 * 1.1 vDisk protocol update (no virtual network update). 348 * 1.2 Support for priority frames (priority-ether-types). 349 * 1.3 VLAN and HybridIO support. 350 * 1.4 Jumbo Frame support. 351 * 1.5 Link State Notification support with optional support 352 * for Physical Link information. 353 */ 354 static vgen_ver_t vgen_versions[VGEN_NUM_VER] = { {1, 5} }; 355 356 /* Tunables */ 357 uint32_t vgen_hwd_interval = 5; /* handshake watchdog freq in sec */ 358 uint32_t vgen_max_hretries = VNET_NUM_HANDSHAKES; /* # of handshake retries */ 359 uint32_t vgen_ldcwr_retries = 10; /* max # of ldc_write() retries */ 360 uint32_t vgen_ldcup_retries = 5; /* max # of ldc_up() retries */ 361 uint32_t vgen_ldccl_retries = 5; /* max # of ldc_close() retries */ 362 uint32_t vgen_recv_delay = 1; /* delay when rx descr not ready */ 363 uint32_t vgen_recv_retries = 10; /* retry when rx descr not ready */ 364 uint32_t vgen_tx_retries = 0x4; /* retry when tx descr not available */ 365 uint32_t vgen_tx_delay = 0x30; /* delay when tx descr not available */ 366 367 int vgen_rcv_thread_enabled = 1; /* Enable Recieve thread */ 368 369 static vio_mblk_pool_t *vgen_rx_poolp = NULL; 370 static krwlock_t vgen_rw; 371 372 /* 373 * max # of packets accumulated prior to sending them up. It is best 374 * to keep this at 60% of the number of recieve buffers. 375 */ 376 uint32_t vgen_chain_len = (VGEN_NRBUFS * 0.6); 377 378 /* 379 * Internal tunables for receive buffer pools, that is, the size and number of 380 * mblks for each pool. At least 3 sizes must be specified if these are used. 381 * The sizes must be specified in increasing order. Non-zero value of the first 382 * size will be used as a hint to use these values instead of the algorithm 383 * that determines the sizes based on MTU. 384 */ 385 uint32_t vgen_rbufsz1 = 0; 386 uint32_t vgen_rbufsz2 = 0; 387 uint32_t vgen_rbufsz3 = 0; 388 uint32_t vgen_rbufsz4 = 0; 389 390 uint32_t vgen_nrbufs1 = VGEN_NRBUFS; 391 uint32_t vgen_nrbufs2 = VGEN_NRBUFS; 392 uint32_t vgen_nrbufs3 = VGEN_NRBUFS; 393 uint32_t vgen_nrbufs4 = VGEN_NRBUFS; 394 395 /* 396 * In the absence of "priority-ether-types" property in MD, the following 397 * internal tunable can be set to specify a single priority ethertype. 398 */ 399 uint64_t vgen_pri_eth_type = 0; 400 401 /* 402 * Number of transmit priority buffers that are preallocated per device. 403 * This number is chosen to be a small value to throttle transmission 404 * of priority packets. Note: Must be a power of 2 for vio_create_mblks(). 405 */ 406 uint32_t vgen_pri_tx_nmblks = 64; 407 408 uint32_t vgen_vlan_nchains = 4; /* # of chains in vlan id hash table */ 409 410 #ifdef DEBUG 411 /* flags to simulate error conditions for debugging */ 412 int vgen_trigger_txtimeout = 0; 413 int vgen_trigger_rxlost = 0; 414 #endif 415 416 /* 417 * Matching criteria passed to the MDEG to register interest 418 * in changes to 'virtual-device' nodes (i.e. vnet nodes) identified 419 * by their 'name' and 'cfg-handle' properties. 420 */ 421 static md_prop_match_t vdev_prop_match[] = { 422 { MDET_PROP_STR, "name" }, 423 { MDET_PROP_VAL, "cfg-handle" }, 424 { MDET_LIST_END, NULL } 425 }; 426 427 static mdeg_node_match_t vdev_match = { "virtual-device", 428 vdev_prop_match }; 429 430 /* MD update matching structure */ 431 static md_prop_match_t vport_prop_match[] = { 432 { MDET_PROP_VAL, "id" }, 433 { MDET_LIST_END, NULL } 434 }; 435 436 static mdeg_node_match_t vport_match = { "virtual-device-port", 437 vport_prop_match }; 438 439 /* template for matching a particular vnet instance */ 440 static mdeg_prop_spec_t vgen_prop_template[] = { 441 { MDET_PROP_STR, "name", "network" }, 442 { MDET_PROP_VAL, "cfg-handle", NULL }, 443 { MDET_LIST_END, NULL, NULL } 444 }; 445 446 #define VGEN_SET_MDEG_PROP_INST(specp, val) (specp)[1].ps_val = (val) 447 448 static int vgen_mdeg_port_cb(void *cb_argp, mdeg_result_t *resp); 449 450 #ifdef VNET_IOC_DEBUG 451 #define VGEN_M_CALLBACK_FLAGS (MC_IOCTL) 452 #else 453 #define VGEN_M_CALLBACK_FLAGS (0) 454 #endif 455 456 static mac_callbacks_t vgen_m_callbacks = { 457 VGEN_M_CALLBACK_FLAGS, 458 vgen_stat, 459 vgen_start, 460 vgen_stop, 461 vgen_promisc, 462 vgen_multicst, 463 vgen_unicst, 464 vgen_tx, 465 vgen_ioctl, 466 NULL, 467 NULL 468 }; 469 470 /* externs */ 471 extern pri_t maxclsyspri; 472 extern proc_t p0; 473 extern uint32_t vnet_ntxds; 474 extern uint32_t vnet_ldcwd_interval; 475 extern uint32_t vnet_ldcwd_txtimeout; 476 extern uint32_t vnet_ldc_mtu; 477 extern uint32_t vnet_nrbufs; 478 extern uint32_t vnet_ethermtu; 479 extern uint16_t vnet_default_vlan_id; 480 extern boolean_t vnet_jumbo_rxpools; 481 482 #ifdef DEBUG 483 484 extern int vnet_dbglevel; 485 static void debug_printf(const char *fname, vgen_t *vgenp, 486 vgen_ldc_t *ldcp, const char *fmt, ...); 487 488 /* -1 for all LDCs info, or ldc_id for a specific LDC info */ 489 int vgendbg_ldcid = -1; 490 491 /* simulate handshake error conditions for debug */ 492 uint32_t vgen_hdbg; 493 #define HDBG_VERSION 0x1 494 #define HDBG_TIMEOUT 0x2 495 #define HDBG_BAD_SID 0x4 496 #define HDBG_OUT_STATE 0x8 497 498 #endif 499 500 /* 501 * vgen_init() is called by an instance of vnet driver to initialize the 502 * corresponding generic proxy transport layer. The arguments passed by vnet 503 * are - an opaque pointer to the vnet instance, pointers to dev_info_t and 504 * the mac address of the vnet device, and a pointer to vgen_t is passed 505 * back as a handle to vnet. 506 */ 507 int 508 vgen_init(void *vnetp, uint64_t regprop, dev_info_t *vnetdip, 509 const uint8_t *macaddr, void **vgenhdl) 510 { 511 vgen_t *vgenp; 512 int instance; 513 int rv; 514 515 if ((vnetp == NULL) || (vnetdip == NULL)) 516 return (DDI_FAILURE); 517 518 instance = ddi_get_instance(vnetdip); 519 520 DBG1(NULL, NULL, "vnet(%d): enter\n", instance); 521 522 vgenp = kmem_zalloc(sizeof (vgen_t), KM_SLEEP); 523 524 vgenp->vnetp = vnetp; 525 vgenp->instance = instance; 526 vgenp->regprop = regprop; 527 vgenp->vnetdip = vnetdip; 528 bcopy(macaddr, &(vgenp->macaddr), ETHERADDRL); 529 vgenp->phys_link_state = LINK_STATE_UNKNOWN; 530 531 /* allocate multicast table */ 532 vgenp->mctab = kmem_zalloc(VGEN_INIT_MCTAB_SIZE * 533 sizeof (struct ether_addr), KM_SLEEP); 534 vgenp->mccount = 0; 535 vgenp->mcsize = VGEN_INIT_MCTAB_SIZE; 536 537 mutex_init(&vgenp->lock, NULL, MUTEX_DRIVER, NULL); 538 rw_init(&vgenp->vgenports.rwlock, NULL, RW_DRIVER, NULL); 539 540 rv = vgen_read_mdprops(vgenp); 541 if (rv != 0) { 542 goto vgen_init_fail; 543 } 544 *vgenhdl = (void *)vgenp; 545 546 DBG1(NULL, NULL, "vnet(%d): exit\n", instance); 547 return (DDI_SUCCESS); 548 549 vgen_init_fail: 550 rw_destroy(&vgenp->vgenports.rwlock); 551 mutex_destroy(&vgenp->lock); 552 kmem_free(vgenp->mctab, VGEN_INIT_MCTAB_SIZE * 553 sizeof (struct ether_addr)); 554 if (VGEN_PRI_ETH_DEFINED(vgenp)) { 555 kmem_free(vgenp->pri_types, 556 sizeof (uint16_t) * vgenp->pri_num_types); 557 (void) vio_destroy_mblks(vgenp->pri_tx_vmp); 558 } 559 KMEM_FREE(vgenp); 560 return (DDI_FAILURE); 561 } 562 563 int 564 vgen_init_mdeg(void *arg) 565 { 566 vgen_t *vgenp = (vgen_t *)arg; 567 568 /* register with MD event generator */ 569 return (vgen_mdeg_reg(vgenp)); 570 } 571 572 /* 573 * Called by vnet to undo the initializations done by vgen_init(). 574 * The handle provided by generic transport during vgen_init() is the argument. 575 */ 576 void 577 vgen_uninit(void *arg) 578 { 579 vgen_t *vgenp = (vgen_t *)arg; 580 vio_mblk_pool_t *rp; 581 vio_mblk_pool_t *nrp; 582 583 if (vgenp == NULL) { 584 return; 585 } 586 587 DBG1(vgenp, NULL, "enter\n"); 588 589 /* unregister with MD event generator */ 590 vgen_mdeg_unreg(vgenp); 591 592 mutex_enter(&vgenp->lock); 593 594 /* detach all ports from the device */ 595 vgen_detach_ports(vgenp); 596 597 /* 598 * free any pending rx mblk pools, 599 * that couldn't be freed previously during channel detach. 600 */ 601 rp = vgenp->rmp; 602 while (rp != NULL) { 603 nrp = vgenp->rmp = rp->nextp; 604 if (vio_destroy_mblks(rp)) { 605 WRITE_ENTER(&vgen_rw); 606 rp->nextp = vgen_rx_poolp; 607 vgen_rx_poolp = rp; 608 RW_EXIT(&vgen_rw); 609 } 610 rp = nrp; 611 } 612 613 /* free multicast table */ 614 kmem_free(vgenp->mctab, vgenp->mcsize * sizeof (struct ether_addr)); 615 616 /* free pri_types table */ 617 if (VGEN_PRI_ETH_DEFINED(vgenp)) { 618 kmem_free(vgenp->pri_types, 619 sizeof (uint16_t) * vgenp->pri_num_types); 620 (void) vio_destroy_mblks(vgenp->pri_tx_vmp); 621 } 622 623 mutex_exit(&vgenp->lock); 624 625 rw_destroy(&vgenp->vgenports.rwlock); 626 mutex_destroy(&vgenp->lock); 627 628 DBG1(vgenp, NULL, "exit\n"); 629 KMEM_FREE(vgenp); 630 } 631 632 /* 633 * module specific initialization common to all instances of vnet/vgen. 634 */ 635 void 636 vgen_mod_init(void) 637 { 638 rw_init(&vgen_rw, NULL, RW_DRIVER, NULL); 639 } 640 641 /* 642 * module specific cleanup common to all instances of vnet/vgen. 643 */ 644 int 645 vgen_mod_cleanup(void) 646 { 647 vio_mblk_pool_t *poolp, *npoolp; 648 649 /* 650 * If any rx mblk pools are still in use, return 651 * error and stop the module from unloading. 652 */ 653 WRITE_ENTER(&vgen_rw); 654 poolp = vgen_rx_poolp; 655 while (poolp != NULL) { 656 npoolp = vgen_rx_poolp = poolp->nextp; 657 if (vio_destroy_mblks(poolp) != 0) { 658 vgen_rx_poolp = poolp; 659 RW_EXIT(&vgen_rw); 660 return (EBUSY); 661 } 662 poolp = npoolp; 663 } 664 RW_EXIT(&vgen_rw); 665 666 return (0); 667 } 668 669 /* 670 * module specific uninitialization common to all instances of vnet/vgen. 671 */ 672 void 673 vgen_mod_fini(void) 674 { 675 rw_destroy(&vgen_rw); 676 } 677 678 /* enable transmit/receive for the device */ 679 int 680 vgen_start(void *arg) 681 { 682 vgen_port_t *portp = (vgen_port_t *)arg; 683 vgen_t *vgenp = portp->vgenp; 684 685 DBG1(vgenp, NULL, "enter\n"); 686 mutex_enter(&portp->lock); 687 vgen_port_init(portp); 688 portp->flags |= VGEN_STARTED; 689 mutex_exit(&portp->lock); 690 DBG1(vgenp, NULL, "exit\n"); 691 692 return (DDI_SUCCESS); 693 } 694 695 /* stop transmit/receive */ 696 void 697 vgen_stop(void *arg) 698 { 699 vgen_port_t *portp = (vgen_port_t *)arg; 700 vgen_t *vgenp = portp->vgenp; 701 702 DBG1(vgenp, NULL, "enter\n"); 703 704 mutex_enter(&portp->lock); 705 vgen_port_uninit(portp); 706 portp->flags &= ~(VGEN_STARTED); 707 mutex_exit(&portp->lock); 708 DBG1(vgenp, NULL, "exit\n"); 709 710 } 711 712 /* vgen transmit function */ 713 static mblk_t * 714 vgen_tx(void *arg, mblk_t *mp) 715 { 716 int i; 717 vgen_port_t *portp; 718 int status = VGEN_FAILURE; 719 720 portp = (vgen_port_t *)arg; 721 /* 722 * Retry so that we avoid reporting a failure 723 * to the upper layer. Returning a failure may cause the 724 * upper layer to go into single threaded mode there by 725 * causing performance degradation, especially for a large 726 * number of connections. 727 */ 728 for (i = 0; i < vgen_tx_retries; ) { 729 status = vgen_portsend(portp, mp); 730 if (status == VGEN_SUCCESS) { 731 break; 732 } 733 if (++i < vgen_tx_retries) 734 delay(drv_usectohz(vgen_tx_delay)); 735 } 736 if (status != VGEN_SUCCESS) { 737 /* failure */ 738 return (mp); 739 } 740 /* success */ 741 return (NULL); 742 } 743 744 /* 745 * This function provides any necessary tagging/untagging of the frames 746 * that are being transmitted over the port. It first verifies the vlan 747 * membership of the destination(port) and drops the packet if the 748 * destination doesn't belong to the given vlan. 749 * 750 * Arguments: 751 * portp: port over which the frames should be transmitted 752 * mp: frame to be transmitted 753 * is_tagged: 754 * B_TRUE: indicates frame header contains the vlan tag already. 755 * B_FALSE: indicates frame is untagged. 756 * vid: vlan in which the frame should be transmitted. 757 * 758 * Returns: 759 * Sucess: frame(mblk_t *) after doing the necessary tag/untag. 760 * Failure: NULL 761 */ 762 static mblk_t * 763 vgen_vlan_frame_fixtag(vgen_port_t *portp, mblk_t *mp, boolean_t is_tagged, 764 uint16_t vid) 765 { 766 vgen_t *vgenp; 767 boolean_t dst_tagged; 768 int rv; 769 770 vgenp = portp->vgenp; 771 772 /* 773 * If the packet is going to a vnet: 774 * Check if the destination vnet is in the same vlan. 775 * Check the frame header if tag or untag is needed. 776 * 777 * We do not check the above conditions if the packet is going to vsw: 778 * vsw must be present implicitly in all the vlans that a vnet device 779 * is configured into; even if vsw itself is not assigned to those 780 * vlans as an interface. For instance, the packet might be destined 781 * to another vnet(indirectly through vsw) or to an external host 782 * which is in the same vlan as this vnet and vsw itself may not be 783 * present in that vlan. Similarly packets going to vsw must be 784 * always tagged(unless in the default-vlan) if not already tagged, 785 * as we do not know the final destination. This is needed because 786 * vsw must always invoke its switching function only after tagging 787 * the packet; otherwise after switching function determines the 788 * destination we cannot figure out if the destination belongs to the 789 * the same vlan that the frame originated from and if it needs tag/ 790 * untag. Note that vsw will tag the packet itself when it receives 791 * it over the channel from a client if needed. However, that is 792 * needed only in the case of vlan unaware clients such as obp or 793 * earlier versions of vnet. 794 * 795 */ 796 if (portp != vgenp->vsw_portp) { 797 /* 798 * Packet going to a vnet. Check if the destination vnet is in 799 * the same vlan. Then check the frame header if tag/untag is 800 * needed. 801 */ 802 rv = vgen_vlan_lookup(portp->vlan_hashp, vid); 803 if (rv == B_FALSE) { 804 /* drop the packet */ 805 freemsg(mp); 806 return (NULL); 807 } 808 809 /* is the destination tagged or untagged in this vlan? */ 810 (vid == portp->pvid) ? (dst_tagged = B_FALSE) : 811 (dst_tagged = B_TRUE); 812 813 if (is_tagged == dst_tagged) { 814 /* no tagging/untagging needed */ 815 return (mp); 816 } 817 818 if (is_tagged == B_TRUE) { 819 /* frame is tagged; destination needs untagged */ 820 mp = vnet_vlan_remove_tag(mp); 821 return (mp); 822 } 823 824 /* (is_tagged == B_FALSE): fallthru to tag tx packet: */ 825 } 826 827 /* 828 * Packet going to a vnet needs tagging. 829 * OR 830 * If the packet is going to vsw, then it must be tagged in all cases: 831 * unknown unicast, broadcast/multicast or to vsw interface. 832 */ 833 834 if (is_tagged == B_FALSE) { 835 mp = vnet_vlan_insert_tag(mp, vid); 836 } 837 838 return (mp); 839 } 840 841 /* transmit packets over the given port */ 842 static int 843 vgen_portsend(vgen_port_t *portp, mblk_t *mp) 844 { 845 vgen_ldclist_t *ldclp; 846 vgen_ldc_t *ldcp; 847 int status; 848 int rv = VGEN_SUCCESS; 849 vgen_t *vgenp = portp->vgenp; 850 vnet_t *vnetp = vgenp->vnetp; 851 boolean_t is_tagged; 852 boolean_t dec_refcnt = B_FALSE; 853 uint16_t vlan_id; 854 struct ether_header *ehp; 855 856 if (portp->use_vsw_port) { 857 (void) atomic_inc_32(&vgenp->vsw_port_refcnt); 858 portp = portp->vgenp->vsw_portp; 859 dec_refcnt = B_TRUE; 860 } 861 if (portp == NULL) { 862 return (VGEN_FAILURE); 863 } 864 865 /* 866 * Determine the vlan id that the frame belongs to. 867 */ 868 ehp = (struct ether_header *)mp->b_rptr; 869 is_tagged = vgen_frame_lookup_vid(vnetp, ehp, &vlan_id); 870 871 if (vlan_id == vnetp->default_vlan_id) { 872 873 /* Frames in default vlan must be untagged */ 874 ASSERT(is_tagged == B_FALSE); 875 876 /* 877 * If the destination is a vnet-port verify it belongs to the 878 * default vlan; otherwise drop the packet. We do not need 879 * this check for vsw-port, as it should implicitly belong to 880 * this vlan; see comments in vgen_vlan_frame_fixtag(). 881 */ 882 if (portp != vgenp->vsw_portp && 883 portp->pvid != vnetp->default_vlan_id) { 884 freemsg(mp); 885 goto portsend_ret; 886 } 887 888 } else { /* frame not in default-vlan */ 889 890 mp = vgen_vlan_frame_fixtag(portp, mp, is_tagged, vlan_id); 891 if (mp == NULL) { 892 goto portsend_ret; 893 } 894 895 } 896 897 ldclp = &portp->ldclist; 898 READ_ENTER(&ldclp->rwlock); 899 /* 900 * NOTE: for now, we will assume we have a single channel. 901 */ 902 if (ldclp->headp == NULL) { 903 RW_EXIT(&ldclp->rwlock); 904 rv = VGEN_FAILURE; 905 goto portsend_ret; 906 } 907 ldcp = ldclp->headp; 908 909 status = ldcp->tx(ldcp, mp); 910 911 RW_EXIT(&ldclp->rwlock); 912 913 if (status != VGEN_TX_SUCCESS) { 914 rv = VGEN_FAILURE; 915 } 916 917 portsend_ret: 918 if (dec_refcnt == B_TRUE) { 919 (void) atomic_dec_32(&vgenp->vsw_port_refcnt); 920 } 921 return (rv); 922 } 923 924 /* 925 * Wrapper function to transmit normal and/or priority frames over the channel. 926 */ 927 static int 928 vgen_ldcsend(void *arg, mblk_t *mp) 929 { 930 vgen_ldc_t *ldcp = (vgen_ldc_t *)arg; 931 int status; 932 struct ether_header *ehp; 933 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 934 uint32_t num_types; 935 uint16_t *types; 936 int i; 937 938 ASSERT(VGEN_PRI_ETH_DEFINED(vgenp)); 939 940 num_types = vgenp->pri_num_types; 941 types = vgenp->pri_types; 942 ehp = (struct ether_header *)mp->b_rptr; 943 944 for (i = 0; i < num_types; i++) { 945 946 if (ehp->ether_type == types[i]) { 947 /* priority frame, use pri tx function */ 948 vgen_ldcsend_pkt(ldcp, mp); 949 return (VGEN_SUCCESS); 950 } 951 952 } 953 954 status = vgen_ldcsend_dring(ldcp, mp); 955 956 return (status); 957 } 958 959 /* 960 * This functions handles ldc channel reset while in the context 961 * of transmit routines: vgen_ldcsend_pkt() or vgen_ldcsend_dring(). 962 */ 963 static void 964 vgen_ldcsend_process_reset(vgen_ldc_t *ldcp) 965 { 966 ldc_status_t istatus; 967 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 968 969 if (mutex_tryenter(&ldcp->cblock)) { 970 if (ldc_status(ldcp->ldc_handle, &istatus) != 0) { 971 DWARN(vgenp, ldcp, "ldc_status() error\n"); 972 } else { 973 ldcp->ldc_status = istatus; 974 } 975 if (ldcp->ldc_status != LDC_UP) { 976 vgen_handle_evt_reset(ldcp); 977 } 978 mutex_exit(&ldcp->cblock); 979 } 980 } 981 982 /* 983 * This function transmits the frame in the payload of a raw data 984 * (VIO_PKT_DATA) message. Thus, it provides an Out-Of-Band path to 985 * send special frames with high priorities, without going through 986 * the normal data path which uses descriptor ring mechanism. 987 */ 988 static void 989 vgen_ldcsend_pkt(void *arg, mblk_t *mp) 990 { 991 vgen_ldc_t *ldcp = (vgen_ldc_t *)arg; 992 vio_raw_data_msg_t *pkt; 993 mblk_t *bp; 994 mblk_t *nmp = NULL; 995 caddr_t dst; 996 uint32_t mblksz; 997 uint32_t size; 998 uint32_t nbytes; 999 int rv; 1000 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 1001 vgen_stats_t *statsp = &ldcp->stats; 1002 1003 /* drop the packet if ldc is not up or handshake is not done */ 1004 if (ldcp->ldc_status != LDC_UP) { 1005 (void) atomic_inc_32(&statsp->tx_pri_fail); 1006 DWARN(vgenp, ldcp, "status(%d), dropping packet\n", 1007 ldcp->ldc_status); 1008 goto send_pkt_exit; 1009 } 1010 1011 if (ldcp->hphase != VH_DONE) { 1012 (void) atomic_inc_32(&statsp->tx_pri_fail); 1013 DWARN(vgenp, ldcp, "hphase(%x), dropping packet\n", 1014 ldcp->hphase); 1015 goto send_pkt_exit; 1016 } 1017 1018 size = msgsize(mp); 1019 1020 /* frame size bigger than available payload len of raw data msg ? */ 1021 if (size > (size_t)(ldcp->msglen - VIO_PKT_DATA_HDRSIZE)) { 1022 (void) atomic_inc_32(&statsp->tx_pri_fail); 1023 DWARN(vgenp, ldcp, "invalid size(%d)\n", size); 1024 goto send_pkt_exit; 1025 } 1026 1027 if (size < ETHERMIN) 1028 size = ETHERMIN; 1029 1030 /* alloc space for a raw data message */ 1031 nmp = vio_allocb(vgenp->pri_tx_vmp); 1032 if (nmp == NULL) { 1033 (void) atomic_inc_32(&statsp->tx_pri_fail); 1034 DWARN(vgenp, ldcp, "vio_allocb failed\n"); 1035 goto send_pkt_exit; 1036 } 1037 pkt = (vio_raw_data_msg_t *)nmp->b_rptr; 1038 1039 /* copy frame into the payload of raw data message */ 1040 dst = (caddr_t)pkt->data; 1041 for (bp = mp; bp != NULL; bp = bp->b_cont) { 1042 mblksz = MBLKL(bp); 1043 bcopy(bp->b_rptr, dst, mblksz); 1044 dst += mblksz; 1045 } 1046 1047 /* setup the raw data msg */ 1048 pkt->tag.vio_msgtype = VIO_TYPE_DATA; 1049 pkt->tag.vio_subtype = VIO_SUBTYPE_INFO; 1050 pkt->tag.vio_subtype_env = VIO_PKT_DATA; 1051 pkt->tag.vio_sid = ldcp->local_sid; 1052 nbytes = VIO_PKT_DATA_HDRSIZE + size; 1053 1054 /* send the msg over ldc */ 1055 rv = vgen_sendmsg(ldcp, (caddr_t)pkt, nbytes, B_FALSE); 1056 if (rv != VGEN_SUCCESS) { 1057 (void) atomic_inc_32(&statsp->tx_pri_fail); 1058 DWARN(vgenp, ldcp, "Error sending priority frame\n"); 1059 if (rv == ECONNRESET) { 1060 vgen_ldcsend_process_reset(ldcp); 1061 } 1062 goto send_pkt_exit; 1063 } 1064 1065 /* update stats */ 1066 (void) atomic_inc_64(&statsp->tx_pri_packets); 1067 (void) atomic_add_64(&statsp->tx_pri_bytes, size); 1068 1069 send_pkt_exit: 1070 if (nmp != NULL) 1071 freemsg(nmp); 1072 freemsg(mp); 1073 } 1074 1075 /* 1076 * This function transmits normal (non-priority) data frames over 1077 * the channel. It queues the frame into the transmit descriptor ring 1078 * and sends a VIO_DRING_DATA message if needed, to wake up the 1079 * peer to (re)start processing. 1080 */ 1081 static int 1082 vgen_ldcsend_dring(void *arg, mblk_t *mp) 1083 { 1084 vgen_ldc_t *ldcp = (vgen_ldc_t *)arg; 1085 vgen_private_desc_t *tbufp; 1086 vgen_private_desc_t *rtbufp; 1087 vnet_public_desc_t *rtxdp; 1088 vgen_private_desc_t *ntbufp; 1089 vnet_public_desc_t *txdp; 1090 vio_dring_entry_hdr_t *hdrp; 1091 vgen_stats_t *statsp; 1092 struct ether_header *ehp; 1093 boolean_t is_bcast = B_FALSE; 1094 boolean_t is_mcast = B_FALSE; 1095 size_t mblksz; 1096 caddr_t dst; 1097 mblk_t *bp; 1098 size_t size; 1099 int rv = 0; 1100 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 1101 vgen_hparams_t *lp = &ldcp->local_hparams; 1102 1103 statsp = &ldcp->stats; 1104 size = msgsize(mp); 1105 1106 DBG1(vgenp, ldcp, "enter\n"); 1107 1108 if (ldcp->ldc_status != LDC_UP) { 1109 DWARN(vgenp, ldcp, "status(%d), dropping packet\n", 1110 ldcp->ldc_status); 1111 /* retry ldc_up() if needed */ 1112 #ifdef VNET_IOC_DEBUG 1113 if (ldcp->flags & CHANNEL_STARTED && !ldcp->link_down_forced) { 1114 #else 1115 if (ldcp->flags & CHANNEL_STARTED) { 1116 #endif 1117 (void) ldc_up(ldcp->ldc_handle); 1118 } 1119 goto send_dring_exit; 1120 } 1121 1122 /* drop the packet if ldc is not up or handshake is not done */ 1123 if (ldcp->hphase != VH_DONE) { 1124 DWARN(vgenp, ldcp, "hphase(%x), dropping packet\n", 1125 ldcp->hphase); 1126 goto send_dring_exit; 1127 } 1128 1129 if (size > (size_t)lp->mtu) { 1130 DWARN(vgenp, ldcp, "invalid size(%d)\n", size); 1131 goto send_dring_exit; 1132 } 1133 if (size < ETHERMIN) 1134 size = ETHERMIN; 1135 1136 ehp = (struct ether_header *)mp->b_rptr; 1137 is_bcast = IS_BROADCAST(ehp); 1138 is_mcast = IS_MULTICAST(ehp); 1139 1140 mutex_enter(&ldcp->txlock); 1141 /* 1142 * allocate a descriptor 1143 */ 1144 tbufp = ldcp->next_tbufp; 1145 ntbufp = NEXTTBUF(ldcp, tbufp); 1146 if (ntbufp == ldcp->cur_tbufp) { /* out of tbufs/txds */ 1147 1148 mutex_enter(&ldcp->tclock); 1149 /* Try reclaiming now */ 1150 vgen_reclaim_dring(ldcp); 1151 ldcp->reclaim_lbolt = ddi_get_lbolt(); 1152 1153 if (ntbufp == ldcp->cur_tbufp) { 1154 /* Now we are really out of tbuf/txds */ 1155 ldcp->need_resched = B_TRUE; 1156 mutex_exit(&ldcp->tclock); 1157 1158 statsp->tx_no_desc++; 1159 mutex_exit(&ldcp->txlock); 1160 1161 return (VGEN_TX_NORESOURCES); 1162 } 1163 mutex_exit(&ldcp->tclock); 1164 } 1165 /* update next available tbuf in the ring and update tx index */ 1166 ldcp->next_tbufp = ntbufp; 1167 INCR_TXI(ldcp->next_txi, ldcp); 1168 1169 /* Mark the buffer busy before releasing the lock */ 1170 tbufp->flags = VGEN_PRIV_DESC_BUSY; 1171 mutex_exit(&ldcp->txlock); 1172 1173 /* copy data into pre-allocated transmit buffer */ 1174 dst = tbufp->datap + VNET_IPALIGN; 1175 for (bp = mp; bp != NULL; bp = bp->b_cont) { 1176 mblksz = MBLKL(bp); 1177 bcopy(bp->b_rptr, dst, mblksz); 1178 dst += mblksz; 1179 } 1180 1181 tbufp->datalen = size; 1182 1183 /* initialize the corresponding public descriptor (txd) */ 1184 txdp = tbufp->descp; 1185 hdrp = &txdp->hdr; 1186 txdp->nbytes = size; 1187 txdp->ncookies = tbufp->ncookies; 1188 bcopy((tbufp->memcookie), (txdp->memcookie), 1189 tbufp->ncookies * sizeof (ldc_mem_cookie_t)); 1190 1191 mutex_enter(&ldcp->wrlock); 1192 /* 1193 * If the flags not set to BUSY, it implies that the clobber 1194 * was done while we were copying the data. In such case, 1195 * discard the packet and return. 1196 */ 1197 if (tbufp->flags != VGEN_PRIV_DESC_BUSY) { 1198 statsp->oerrors++; 1199 mutex_exit(&ldcp->wrlock); 1200 goto send_dring_exit; 1201 } 1202 hdrp->dstate = VIO_DESC_READY; 1203 1204 /* update stats */ 1205 statsp->opackets++; 1206 statsp->obytes += size; 1207 if (is_bcast) 1208 statsp->brdcstxmt++; 1209 else if (is_mcast) 1210 statsp->multixmt++; 1211 1212 /* send dring datamsg to the peer */ 1213 if (ldcp->resched_peer) { 1214 1215 rtbufp = &ldcp->tbufp[ldcp->resched_peer_txi]; 1216 rtxdp = rtbufp->descp; 1217 1218 if (rtxdp->hdr.dstate == VIO_DESC_READY) { 1219 1220 rv = vgen_send_dring_data(ldcp, 1221 (uint32_t)ldcp->resched_peer_txi, -1); 1222 if (rv != 0) { 1223 /* error: drop the packet */ 1224 DWARN(vgenp, ldcp, "vgen_send_dring_data " 1225 "failed: rv(%d) len(%d)\n", 1226 ldcp->ldc_id, rv, size); 1227 statsp->oerrors++; 1228 } else { 1229 ldcp->resched_peer = B_FALSE; 1230 } 1231 1232 } 1233 1234 } 1235 1236 mutex_exit(&ldcp->wrlock); 1237 1238 send_dring_exit: 1239 if (rv == ECONNRESET) { 1240 vgen_ldcsend_process_reset(ldcp); 1241 } 1242 freemsg(mp); 1243 DBG1(vgenp, ldcp, "exit\n"); 1244 return (VGEN_TX_SUCCESS); 1245 } 1246 1247 /* enable/disable a multicast address */ 1248 int 1249 vgen_multicst(void *arg, boolean_t add, const uint8_t *mca) 1250 { 1251 vgen_t *vgenp; 1252 vnet_mcast_msg_t mcastmsg; 1253 vio_msg_tag_t *tagp; 1254 vgen_port_t *portp; 1255 vgen_portlist_t *plistp; 1256 vgen_ldc_t *ldcp; 1257 vgen_ldclist_t *ldclp; 1258 struct ether_addr *addrp; 1259 int rv = DDI_FAILURE; 1260 uint32_t i; 1261 1262 portp = (vgen_port_t *)arg; 1263 vgenp = portp->vgenp; 1264 1265 if (portp != vgenp->vsw_portp) { 1266 return (DDI_SUCCESS); 1267 } 1268 1269 addrp = (struct ether_addr *)mca; 1270 tagp = &mcastmsg.tag; 1271 bzero(&mcastmsg, sizeof (mcastmsg)); 1272 1273 mutex_enter(&vgenp->lock); 1274 1275 plistp = &(vgenp->vgenports); 1276 1277 READ_ENTER(&plistp->rwlock); 1278 1279 portp = vgenp->vsw_portp; 1280 if (portp == NULL) { 1281 RW_EXIT(&plistp->rwlock); 1282 mutex_exit(&vgenp->lock); 1283 return (rv); 1284 } 1285 ldclp = &portp->ldclist; 1286 1287 READ_ENTER(&ldclp->rwlock); 1288 1289 ldcp = ldclp->headp; 1290 if (ldcp == NULL) 1291 goto vgen_mcast_exit; 1292 1293 mutex_enter(&ldcp->cblock); 1294 1295 if (ldcp->hphase == VH_DONE) { 1296 /* 1297 * If handshake is done, send a msg to vsw to add/remove 1298 * the multicast address. Otherwise, we just update this 1299 * mcast address in our table and the table will be sync'd 1300 * with vsw when handshake completes. 1301 */ 1302 tagp->vio_msgtype = VIO_TYPE_CTRL; 1303 tagp->vio_subtype = VIO_SUBTYPE_INFO; 1304 tagp->vio_subtype_env = VNET_MCAST_INFO; 1305 tagp->vio_sid = ldcp->local_sid; 1306 bcopy(mca, &(mcastmsg.mca), ETHERADDRL); 1307 mcastmsg.set = add; 1308 mcastmsg.count = 1; 1309 if (vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (mcastmsg), 1310 B_FALSE) != VGEN_SUCCESS) { 1311 DWARN(vgenp, ldcp, "vgen_sendmsg failed\n"); 1312 mutex_exit(&ldcp->cblock); 1313 goto vgen_mcast_exit; 1314 } 1315 } 1316 1317 mutex_exit(&ldcp->cblock); 1318 1319 if (add) { 1320 1321 /* expand multicast table if necessary */ 1322 if (vgenp->mccount >= vgenp->mcsize) { 1323 struct ether_addr *newtab; 1324 uint32_t newsize; 1325 1326 1327 newsize = vgenp->mcsize * 2; 1328 1329 newtab = kmem_zalloc(newsize * 1330 sizeof (struct ether_addr), KM_NOSLEEP); 1331 if (newtab == NULL) 1332 goto vgen_mcast_exit; 1333 bcopy(vgenp->mctab, newtab, vgenp->mcsize * 1334 sizeof (struct ether_addr)); 1335 kmem_free(vgenp->mctab, 1336 vgenp->mcsize * sizeof (struct ether_addr)); 1337 1338 vgenp->mctab = newtab; 1339 vgenp->mcsize = newsize; 1340 } 1341 1342 /* add address to the table */ 1343 vgenp->mctab[vgenp->mccount++] = *addrp; 1344 1345 } else { 1346 1347 /* delete address from the table */ 1348 for (i = 0; i < vgenp->mccount; i++) { 1349 if (ether_cmp(addrp, &(vgenp->mctab[i])) == 0) { 1350 1351 /* 1352 * If there's more than one address in this 1353 * table, delete the unwanted one by moving 1354 * the last one in the list over top of it; 1355 * otherwise, just remove it. 1356 */ 1357 if (vgenp->mccount > 1) { 1358 vgenp->mctab[i] = 1359 vgenp->mctab[vgenp->mccount-1]; 1360 } 1361 vgenp->mccount--; 1362 break; 1363 } 1364 } 1365 } 1366 1367 rv = DDI_SUCCESS; 1368 1369 vgen_mcast_exit: 1370 RW_EXIT(&ldclp->rwlock); 1371 RW_EXIT(&plistp->rwlock); 1372 1373 mutex_exit(&vgenp->lock); 1374 return (rv); 1375 } 1376 1377 /* set or clear promiscuous mode on the device */ 1378 static int 1379 vgen_promisc(void *arg, boolean_t on) 1380 { 1381 _NOTE(ARGUNUSED(arg, on)) 1382 return (DDI_SUCCESS); 1383 } 1384 1385 /* set the unicast mac address of the device */ 1386 static int 1387 vgen_unicst(void *arg, const uint8_t *mca) 1388 { 1389 _NOTE(ARGUNUSED(arg, mca)) 1390 return (DDI_SUCCESS); 1391 } 1392 1393 /* get device statistics */ 1394 int 1395 vgen_stat(void *arg, uint_t stat, uint64_t *val) 1396 { 1397 vgen_port_t *portp = (vgen_port_t *)arg; 1398 1399 *val = vgen_port_stat(portp, stat); 1400 1401 return (0); 1402 } 1403 1404 /* vgen internal functions */ 1405 /* detach all ports from the device */ 1406 static void 1407 vgen_detach_ports(vgen_t *vgenp) 1408 { 1409 vgen_port_t *portp; 1410 vgen_portlist_t *plistp; 1411 1412 plistp = &(vgenp->vgenports); 1413 WRITE_ENTER(&plistp->rwlock); 1414 while ((portp = plistp->headp) != NULL) { 1415 vgen_port_detach(portp); 1416 } 1417 RW_EXIT(&plistp->rwlock); 1418 } 1419 1420 /* 1421 * detach the given port. 1422 */ 1423 static void 1424 vgen_port_detach(vgen_port_t *portp) 1425 { 1426 vgen_t *vgenp; 1427 vgen_ldclist_t *ldclp; 1428 int port_num; 1429 1430 vgenp = portp->vgenp; 1431 port_num = portp->port_num; 1432 1433 DBG1(vgenp, NULL, "port(%d):enter\n", port_num); 1434 1435 /* 1436 * If this port is connected to the vswitch, then 1437 * potentially there could be ports that may be using 1438 * this port to transmit packets. To address this do 1439 * the following: 1440 * - First set vgenp->vsw_portp to NULL, so that 1441 * its not used after that. 1442 * - Then wait for the refcnt to go down to 0. 1443 * - Now we can safely detach this port. 1444 */ 1445 if (vgenp->vsw_portp == portp) { 1446 vgenp->vsw_portp = NULL; 1447 while (vgenp->vsw_port_refcnt > 0) { 1448 delay(drv_usectohz(vgen_tx_delay)); 1449 } 1450 (void) atomic_swap_32(&vgenp->vsw_port_refcnt, 0); 1451 } 1452 1453 if (portp->vhp != NULL) { 1454 vio_net_resource_unreg(portp->vhp); 1455 portp->vhp = NULL; 1456 } 1457 1458 vgen_vlan_destroy_hash(portp); 1459 1460 /* remove it from port list */ 1461 vgen_port_list_remove(portp); 1462 1463 /* detach channels from this port */ 1464 ldclp = &portp->ldclist; 1465 WRITE_ENTER(&ldclp->rwlock); 1466 while (ldclp->headp) { 1467 vgen_ldc_detach(ldclp->headp); 1468 } 1469 RW_EXIT(&ldclp->rwlock); 1470 rw_destroy(&ldclp->rwlock); 1471 1472 if (portp->num_ldcs != 0) { 1473 kmem_free(portp->ldc_ids, portp->num_ldcs * sizeof (uint64_t)); 1474 portp->num_ldcs = 0; 1475 } 1476 1477 mutex_destroy(&portp->lock); 1478 KMEM_FREE(portp); 1479 1480 DBG1(vgenp, NULL, "port(%d):exit\n", port_num); 1481 } 1482 1483 /* add a port to port list */ 1484 static void 1485 vgen_port_list_insert(vgen_port_t *portp) 1486 { 1487 vgen_portlist_t *plistp; 1488 vgen_t *vgenp; 1489 1490 vgenp = portp->vgenp; 1491 plistp = &(vgenp->vgenports); 1492 1493 if (plistp->headp == NULL) { 1494 plistp->headp = portp; 1495 } else { 1496 plistp->tailp->nextp = portp; 1497 } 1498 plistp->tailp = portp; 1499 portp->nextp = NULL; 1500 } 1501 1502 /* remove a port from port list */ 1503 static void 1504 vgen_port_list_remove(vgen_port_t *portp) 1505 { 1506 vgen_port_t *prevp; 1507 vgen_port_t *nextp; 1508 vgen_portlist_t *plistp; 1509 vgen_t *vgenp; 1510 1511 vgenp = portp->vgenp; 1512 1513 plistp = &(vgenp->vgenports); 1514 1515 if (plistp->headp == NULL) 1516 return; 1517 1518 if (portp == plistp->headp) { 1519 plistp->headp = portp->nextp; 1520 if (portp == plistp->tailp) 1521 plistp->tailp = plistp->headp; 1522 } else { 1523 for (prevp = plistp->headp; 1524 ((nextp = prevp->nextp) != NULL) && (nextp != portp); 1525 prevp = nextp) 1526 ; 1527 if (nextp == portp) { 1528 prevp->nextp = portp->nextp; 1529 } 1530 if (portp == plistp->tailp) 1531 plistp->tailp = prevp; 1532 } 1533 } 1534 1535 /* lookup a port in the list based on port_num */ 1536 static vgen_port_t * 1537 vgen_port_lookup(vgen_portlist_t *plistp, int port_num) 1538 { 1539 vgen_port_t *portp = NULL; 1540 1541 for (portp = plistp->headp; portp != NULL; portp = portp->nextp) { 1542 if (portp->port_num == port_num) { 1543 break; 1544 } 1545 } 1546 1547 return (portp); 1548 } 1549 1550 /* enable ports for transmit/receive */ 1551 static void 1552 vgen_init_ports(vgen_t *vgenp) 1553 { 1554 vgen_port_t *portp; 1555 vgen_portlist_t *plistp; 1556 1557 plistp = &(vgenp->vgenports); 1558 READ_ENTER(&plistp->rwlock); 1559 1560 for (portp = plistp->headp; portp != NULL; portp = portp->nextp) { 1561 vgen_port_init(portp); 1562 } 1563 1564 RW_EXIT(&plistp->rwlock); 1565 } 1566 1567 static void 1568 vgen_port_init(vgen_port_t *portp) 1569 { 1570 /* Add the port to the specified vlans */ 1571 vgen_vlan_add_ids(portp); 1572 1573 /* Bring up the channels of this port */ 1574 vgen_init_ldcs(portp); 1575 } 1576 1577 /* disable transmit/receive on ports */ 1578 static void 1579 vgen_uninit_ports(vgen_t *vgenp) 1580 { 1581 vgen_port_t *portp; 1582 vgen_portlist_t *plistp; 1583 1584 plistp = &(vgenp->vgenports); 1585 READ_ENTER(&plistp->rwlock); 1586 1587 for (portp = plistp->headp; portp != NULL; portp = portp->nextp) { 1588 vgen_port_uninit(portp); 1589 } 1590 1591 RW_EXIT(&plistp->rwlock); 1592 } 1593 1594 static void 1595 vgen_port_uninit(vgen_port_t *portp) 1596 { 1597 vgen_uninit_ldcs(portp); 1598 1599 /* remove the port from vlans it has been assigned to */ 1600 vgen_vlan_remove_ids(portp); 1601 } 1602 1603 /* 1604 * Scan the machine description for this instance of vnet 1605 * and read its properties. Called only from vgen_init(). 1606 * Returns: 0 on success, 1 on failure. 1607 */ 1608 static int 1609 vgen_read_mdprops(vgen_t *vgenp) 1610 { 1611 vnet_t *vnetp = vgenp->vnetp; 1612 md_t *mdp = NULL; 1613 mde_cookie_t rootnode; 1614 mde_cookie_t *listp = NULL; 1615 uint64_t cfgh; 1616 char *name; 1617 int rv = 1; 1618 int num_nodes = 0; 1619 int num_devs = 0; 1620 int listsz = 0; 1621 int i; 1622 1623 if ((mdp = md_get_handle()) == NULL) { 1624 return (rv); 1625 } 1626 1627 num_nodes = md_node_count(mdp); 1628 ASSERT(num_nodes > 0); 1629 1630 listsz = num_nodes * sizeof (mde_cookie_t); 1631 listp = (mde_cookie_t *)kmem_zalloc(listsz, KM_SLEEP); 1632 1633 rootnode = md_root_node(mdp); 1634 1635 /* search for all "virtual_device" nodes */ 1636 num_devs = md_scan_dag(mdp, rootnode, 1637 md_find_name(mdp, vdev_propname), 1638 md_find_name(mdp, "fwd"), listp); 1639 if (num_devs <= 0) { 1640 goto vgen_readmd_exit; 1641 } 1642 1643 /* 1644 * Now loop through the list of virtual-devices looking for 1645 * devices with name "network" and for each such device compare 1646 * its instance with what we have from the 'reg' property to 1647 * find the right node in MD and then read all its properties. 1648 */ 1649 for (i = 0; i < num_devs; i++) { 1650 1651 if (md_get_prop_str(mdp, listp[i], "name", &name) != 0) { 1652 goto vgen_readmd_exit; 1653 } 1654 1655 /* is this a "network" device? */ 1656 if (strcmp(name, vnet_propname) != 0) 1657 continue; 1658 1659 if (md_get_prop_val(mdp, listp[i], "cfg-handle", &cfgh) != 0) { 1660 goto vgen_readmd_exit; 1661 } 1662 1663 /* is this the required instance of vnet? */ 1664 if (vgenp->regprop != cfgh) 1665 continue; 1666 1667 /* 1668 * Read the 'linkprop' property to know if this vnet 1669 * device should get physical link updates from vswitch. 1670 */ 1671 vgen_linkprop_read(vgenp, mdp, listp[i], 1672 &vnetp->pls_update); 1673 1674 /* 1675 * Read the mtu. Note that we set the mtu of vnet device within 1676 * this routine itself, after validating the range. 1677 */ 1678 vgen_mtu_read(vgenp, mdp, listp[i], &vnetp->mtu); 1679 if (vnetp->mtu < ETHERMTU || vnetp->mtu > VNET_MAX_MTU) { 1680 vnetp->mtu = ETHERMTU; 1681 } 1682 vgenp->max_frame_size = vnetp->mtu + 1683 sizeof (struct ether_header) + VLAN_TAGSZ; 1684 1685 /* read priority ether types */ 1686 vgen_read_pri_eth_types(vgenp, mdp, listp[i]); 1687 1688 /* read vlan id properties of this vnet instance */ 1689 vgen_vlan_read_ids(vgenp, VGEN_LOCAL, mdp, listp[i], 1690 &vnetp->pvid, &vnetp->vids, &vnetp->nvids, 1691 &vnetp->default_vlan_id); 1692 1693 rv = 0; 1694 break; 1695 } 1696 1697 vgen_readmd_exit: 1698 1699 kmem_free(listp, listsz); 1700 (void) md_fini_handle(mdp); 1701 return (rv); 1702 } 1703 1704 /* 1705 * Read vlan id properties of the given MD node. 1706 * Arguments: 1707 * arg: device argument(vnet device or a port) 1708 * type: type of arg; VGEN_LOCAL(vnet device) or VGEN_PEER(port) 1709 * mdp: machine description 1710 * node: md node cookie 1711 * 1712 * Returns: 1713 * pvidp: port-vlan-id of the node 1714 * vidspp: list of vlan-ids of the node 1715 * nvidsp: # of vlan-ids in the list 1716 * default_idp: default-vlan-id of the node(if node is vnet device) 1717 */ 1718 static void 1719 vgen_vlan_read_ids(void *arg, int type, md_t *mdp, mde_cookie_t node, 1720 uint16_t *pvidp, uint16_t **vidspp, uint16_t *nvidsp, 1721 uint16_t *default_idp) 1722 { 1723 vgen_t *vgenp; 1724 vnet_t *vnetp; 1725 vgen_port_t *portp; 1726 char *pvid_propname; 1727 char *vid_propname; 1728 uint_t nvids; 1729 uint32_t vids_size; 1730 int rv; 1731 int i; 1732 uint64_t *data; 1733 uint64_t val; 1734 int size; 1735 int inst; 1736 1737 if (type == VGEN_LOCAL) { 1738 1739 vgenp = (vgen_t *)arg; 1740 vnetp = vgenp->vnetp; 1741 pvid_propname = vgen_pvid_propname; 1742 vid_propname = vgen_vid_propname; 1743 inst = vnetp->instance; 1744 1745 } else if (type == VGEN_PEER) { 1746 1747 portp = (vgen_port_t *)arg; 1748 vgenp = portp->vgenp; 1749 vnetp = vgenp->vnetp; 1750 pvid_propname = port_pvid_propname; 1751 vid_propname = port_vid_propname; 1752 inst = portp->port_num; 1753 1754 } else { 1755 return; 1756 } 1757 1758 if (type == VGEN_LOCAL && default_idp != NULL) { 1759 rv = md_get_prop_val(mdp, node, vgen_dvid_propname, &val); 1760 if (rv != 0) { 1761 DWARN(vgenp, NULL, "prop(%s) not found", 1762 vgen_dvid_propname); 1763 1764 *default_idp = vnet_default_vlan_id; 1765 } else { 1766 *default_idp = val & 0xFFF; 1767 DBG2(vgenp, NULL, "%s(%d): (%d)\n", vgen_dvid_propname, 1768 inst, *default_idp); 1769 } 1770 } 1771 1772 rv = md_get_prop_val(mdp, node, pvid_propname, &val); 1773 if (rv != 0) { 1774 DWARN(vgenp, NULL, "prop(%s) not found", pvid_propname); 1775 *pvidp = vnet_default_vlan_id; 1776 } else { 1777 1778 *pvidp = val & 0xFFF; 1779 DBG2(vgenp, NULL, "%s(%d): (%d)\n", 1780 pvid_propname, inst, *pvidp); 1781 } 1782 1783 rv = md_get_prop_data(mdp, node, vid_propname, (uint8_t **)&data, 1784 &size); 1785 if (rv != 0) { 1786 DBG2(vgenp, NULL, "prop(%s) not found", vid_propname); 1787 size = 0; 1788 } else { 1789 size /= sizeof (uint64_t); 1790 } 1791 nvids = size; 1792 1793 if (nvids != 0) { 1794 DBG2(vgenp, NULL, "%s(%d): ", vid_propname, inst); 1795 vids_size = sizeof (uint16_t) * nvids; 1796 *vidspp = kmem_zalloc(vids_size, KM_SLEEP); 1797 for (i = 0; i < nvids; i++) { 1798 (*vidspp)[i] = data[i] & 0xFFFF; 1799 DBG2(vgenp, NULL, " %d ", (*vidspp)[i]); 1800 } 1801 DBG2(vgenp, NULL, "\n"); 1802 } 1803 1804 *nvidsp = nvids; 1805 } 1806 1807 /* 1808 * Create a vlan id hash table for the given port. 1809 */ 1810 static void 1811 vgen_vlan_create_hash(vgen_port_t *portp) 1812 { 1813 char hashname[MAXNAMELEN]; 1814 1815 (void) snprintf(hashname, MAXNAMELEN, "port%d-vlan-hash", 1816 portp->port_num); 1817 1818 portp->vlan_nchains = vgen_vlan_nchains; 1819 portp->vlan_hashp = mod_hash_create_idhash(hashname, 1820 portp->vlan_nchains, mod_hash_null_valdtor); 1821 } 1822 1823 /* 1824 * Destroy the vlan id hash table in the given port. 1825 */ 1826 static void 1827 vgen_vlan_destroy_hash(vgen_port_t *portp) 1828 { 1829 if (portp->vlan_hashp != NULL) { 1830 mod_hash_destroy_hash(portp->vlan_hashp); 1831 portp->vlan_hashp = NULL; 1832 portp->vlan_nchains = 0; 1833 } 1834 } 1835 1836 /* 1837 * Add a port to the vlans specified in its port properites. 1838 */ 1839 static void 1840 vgen_vlan_add_ids(vgen_port_t *portp) 1841 { 1842 int rv; 1843 int i; 1844 1845 rv = mod_hash_insert(portp->vlan_hashp, 1846 (mod_hash_key_t)VLAN_ID_KEY(portp->pvid), 1847 (mod_hash_val_t)B_TRUE); 1848 ASSERT(rv == 0); 1849 1850 for (i = 0; i < portp->nvids; i++) { 1851 rv = mod_hash_insert(portp->vlan_hashp, 1852 (mod_hash_key_t)VLAN_ID_KEY(portp->vids[i]), 1853 (mod_hash_val_t)B_TRUE); 1854 ASSERT(rv == 0); 1855 } 1856 } 1857 1858 /* 1859 * Remove a port from the vlans it has been assigned to. 1860 */ 1861 static void 1862 vgen_vlan_remove_ids(vgen_port_t *portp) 1863 { 1864 int rv; 1865 int i; 1866 mod_hash_val_t vp; 1867 1868 rv = mod_hash_remove(portp->vlan_hashp, 1869 (mod_hash_key_t)VLAN_ID_KEY(portp->pvid), 1870 (mod_hash_val_t *)&vp); 1871 ASSERT(rv == 0); 1872 1873 for (i = 0; i < portp->nvids; i++) { 1874 rv = mod_hash_remove(portp->vlan_hashp, 1875 (mod_hash_key_t)VLAN_ID_KEY(portp->vids[i]), 1876 (mod_hash_val_t *)&vp); 1877 ASSERT(rv == 0); 1878 } 1879 } 1880 1881 /* 1882 * Lookup the vlan id of the given tx frame. If it is a vlan-tagged frame, 1883 * then the vlan-id is available in the tag; otherwise, its vlan id is 1884 * implicitly obtained from the port-vlan-id of the vnet device. 1885 * The vlan id determined is returned in vidp. 1886 * Returns: B_TRUE if it is a tagged frame; B_FALSE if it is untagged. 1887 */ 1888 static boolean_t 1889 vgen_frame_lookup_vid(vnet_t *vnetp, struct ether_header *ehp, uint16_t *vidp) 1890 { 1891 struct ether_vlan_header *evhp; 1892 1893 /* If it's a tagged frame, get the vlan id from vlan header */ 1894 if (ehp->ether_type == ETHERTYPE_VLAN) { 1895 1896 evhp = (struct ether_vlan_header *)ehp; 1897 *vidp = VLAN_ID(ntohs(evhp->ether_tci)); 1898 return (B_TRUE); 1899 } 1900 1901 /* Untagged frame, vlan-id is the pvid of vnet device */ 1902 *vidp = vnetp->pvid; 1903 return (B_FALSE); 1904 } 1905 1906 /* 1907 * Find the given vlan id in the hash table. 1908 * Return: B_TRUE if the id is found; B_FALSE if not found. 1909 */ 1910 static boolean_t 1911 vgen_vlan_lookup(mod_hash_t *vlan_hashp, uint16_t vid) 1912 { 1913 int rv; 1914 mod_hash_val_t vp; 1915 1916 rv = mod_hash_find(vlan_hashp, VLAN_ID_KEY(vid), (mod_hash_val_t *)&vp); 1917 1918 if (rv != 0) 1919 return (B_FALSE); 1920 1921 return (B_TRUE); 1922 } 1923 1924 /* 1925 * This function reads "priority-ether-types" property from md. This property 1926 * is used to enable support for priority frames. Applications which need 1927 * guaranteed and timely delivery of certain high priority frames to/from 1928 * a vnet or vsw within ldoms, should configure this property by providing 1929 * the ether type(s) for which the priority facility is needed. 1930 * Normal data frames are delivered over a ldc channel using the descriptor 1931 * ring mechanism which is constrained by factors such as descriptor ring size, 1932 * the rate at which the ring is processed at the peer ldc end point, etc. 1933 * The priority mechanism provides an Out-Of-Band path to send/receive frames 1934 * as raw pkt data (VIO_PKT_DATA) messages over the channel, avoiding the 1935 * descriptor ring path and enables a more reliable and timely delivery of 1936 * frames to the peer. 1937 */ 1938 static void 1939 vgen_read_pri_eth_types(vgen_t *vgenp, md_t *mdp, mde_cookie_t node) 1940 { 1941 int rv; 1942 uint16_t *types; 1943 uint64_t *data; 1944 int size; 1945 int i; 1946 size_t mblk_sz; 1947 1948 rv = md_get_prop_data(mdp, node, pri_types_propname, 1949 (uint8_t **)&data, &size); 1950 if (rv != 0) { 1951 /* 1952 * Property may not exist if we are running pre-ldoms1.1 f/w. 1953 * Check if 'vgen_pri_eth_type' has been set in that case. 1954 */ 1955 if (vgen_pri_eth_type != 0) { 1956 size = sizeof (vgen_pri_eth_type); 1957 data = &vgen_pri_eth_type; 1958 } else { 1959 DBG2(vgenp, NULL, 1960 "prop(%s) not found", pri_types_propname); 1961 size = 0; 1962 } 1963 } 1964 1965 if (size == 0) { 1966 vgenp->pri_num_types = 0; 1967 return; 1968 } 1969 1970 /* 1971 * we have some priority-ether-types defined; 1972 * allocate a table of these types and also 1973 * allocate a pool of mblks to transmit these 1974 * priority packets. 1975 */ 1976 size /= sizeof (uint64_t); 1977 vgenp->pri_num_types = size; 1978 vgenp->pri_types = kmem_zalloc(size * sizeof (uint16_t), KM_SLEEP); 1979 for (i = 0, types = vgenp->pri_types; i < size; i++) { 1980 types[i] = data[i] & 0xFFFF; 1981 } 1982 mblk_sz = (VIO_PKT_DATA_HDRSIZE + vgenp->max_frame_size + 7) & ~7; 1983 (void) vio_create_mblks(vgen_pri_tx_nmblks, mblk_sz, 1984 &vgenp->pri_tx_vmp); 1985 } 1986 1987 static void 1988 vgen_mtu_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node, uint32_t *mtu) 1989 { 1990 int rv; 1991 uint64_t val; 1992 char *mtu_propname; 1993 1994 mtu_propname = vgen_mtu_propname; 1995 1996 rv = md_get_prop_val(mdp, node, mtu_propname, &val); 1997 if (rv != 0) { 1998 DWARN(vgenp, NULL, "prop(%s) not found", mtu_propname); 1999 *mtu = vnet_ethermtu; 2000 } else { 2001 2002 *mtu = val & 0xFFFF; 2003 DBG2(vgenp, NULL, "%s(%d): (%d)\n", mtu_propname, 2004 vgenp->instance, *mtu); 2005 } 2006 } 2007 2008 static void 2009 vgen_linkprop_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node, 2010 boolean_t *pls) 2011 { 2012 int rv; 2013 uint64_t val; 2014 char *linkpropname; 2015 2016 linkpropname = vgen_linkprop_propname; 2017 2018 rv = md_get_prop_val(mdp, node, linkpropname, &val); 2019 if (rv != 0) { 2020 DWARN(vgenp, NULL, "prop(%s) not found", linkpropname); 2021 *pls = B_FALSE; 2022 } else { 2023 2024 *pls = (val & 0x1) ? B_TRUE : B_FALSE; 2025 DBG2(vgenp, NULL, "%s(%d): (%d)\n", linkpropname, 2026 vgenp->instance, *pls); 2027 } 2028 } 2029 2030 /* register with MD event generator */ 2031 static int 2032 vgen_mdeg_reg(vgen_t *vgenp) 2033 { 2034 mdeg_prop_spec_t *pspecp; 2035 mdeg_node_spec_t *parentp; 2036 uint_t templatesz; 2037 int rv; 2038 mdeg_handle_t dev_hdl = NULL; 2039 mdeg_handle_t port_hdl = NULL; 2040 2041 templatesz = sizeof (vgen_prop_template); 2042 pspecp = kmem_zalloc(templatesz, KM_NOSLEEP); 2043 if (pspecp == NULL) { 2044 return (DDI_FAILURE); 2045 } 2046 parentp = kmem_zalloc(sizeof (mdeg_node_spec_t), KM_NOSLEEP); 2047 if (parentp == NULL) { 2048 kmem_free(pspecp, templatesz); 2049 return (DDI_FAILURE); 2050 } 2051 2052 bcopy(vgen_prop_template, pspecp, templatesz); 2053 2054 /* 2055 * NOTE: The instance here refers to the value of "reg" property and 2056 * not the dev_info instance (ddi_get_instance()) of vnet. 2057 */ 2058 VGEN_SET_MDEG_PROP_INST(pspecp, vgenp->regprop); 2059 2060 parentp->namep = "virtual-device"; 2061 parentp->specp = pspecp; 2062 2063 /* save parentp in vgen_t */ 2064 vgenp->mdeg_parentp = parentp; 2065 2066 /* 2067 * Register an interest in 'virtual-device' nodes with a 2068 * 'name' property of 'network' 2069 */ 2070 rv = mdeg_register(parentp, &vdev_match, vgen_mdeg_cb, vgenp, &dev_hdl); 2071 if (rv != MDEG_SUCCESS) { 2072 DERR(vgenp, NULL, "mdeg_register failed\n"); 2073 goto mdeg_reg_fail; 2074 } 2075 2076 /* Register an interest in 'port' nodes */ 2077 rv = mdeg_register(parentp, &vport_match, vgen_mdeg_port_cb, vgenp, 2078 &port_hdl); 2079 if (rv != MDEG_SUCCESS) { 2080 DERR(vgenp, NULL, "mdeg_register failed\n"); 2081 goto mdeg_reg_fail; 2082 } 2083 2084 /* save mdeg handle in vgen_t */ 2085 vgenp->mdeg_dev_hdl = dev_hdl; 2086 vgenp->mdeg_port_hdl = port_hdl; 2087 2088 return (DDI_SUCCESS); 2089 2090 mdeg_reg_fail: 2091 if (dev_hdl != NULL) { 2092 (void) mdeg_unregister(dev_hdl); 2093 } 2094 KMEM_FREE(parentp); 2095 kmem_free(pspecp, templatesz); 2096 vgenp->mdeg_parentp = NULL; 2097 return (DDI_FAILURE); 2098 } 2099 2100 /* unregister with MD event generator */ 2101 static void 2102 vgen_mdeg_unreg(vgen_t *vgenp) 2103 { 2104 if (vgenp->mdeg_dev_hdl != NULL) { 2105 (void) mdeg_unregister(vgenp->mdeg_dev_hdl); 2106 vgenp->mdeg_dev_hdl = NULL; 2107 } 2108 if (vgenp->mdeg_port_hdl != NULL) { 2109 (void) mdeg_unregister(vgenp->mdeg_port_hdl); 2110 vgenp->mdeg_port_hdl = NULL; 2111 } 2112 2113 if (vgenp->mdeg_parentp != NULL) { 2114 kmem_free(vgenp->mdeg_parentp->specp, 2115 sizeof (vgen_prop_template)); 2116 KMEM_FREE(vgenp->mdeg_parentp); 2117 vgenp->mdeg_parentp = NULL; 2118 } 2119 } 2120 2121 /* mdeg callback function for the port node */ 2122 static int 2123 vgen_mdeg_port_cb(void *cb_argp, mdeg_result_t *resp) 2124 { 2125 int idx; 2126 int vsw_idx = -1; 2127 uint64_t val; 2128 vgen_t *vgenp; 2129 2130 if ((resp == NULL) || (cb_argp == NULL)) { 2131 return (MDEG_FAILURE); 2132 } 2133 2134 vgenp = (vgen_t *)cb_argp; 2135 DBG1(vgenp, NULL, "enter\n"); 2136 2137 mutex_enter(&vgenp->lock); 2138 2139 DBG1(vgenp, NULL, "ports: removed(%x), " 2140 "added(%x), updated(%x)\n", resp->removed.nelem, 2141 resp->added.nelem, resp->match_curr.nelem); 2142 2143 for (idx = 0; idx < resp->removed.nelem; idx++) { 2144 (void) vgen_remove_port(vgenp, resp->removed.mdp, 2145 resp->removed.mdep[idx]); 2146 } 2147 2148 if (vgenp->vsw_portp == NULL) { 2149 /* 2150 * find vsw_port and add it first, because other ports need 2151 * this when adding fdb entry (see vgen_port_init()). 2152 */ 2153 for (idx = 0; idx < resp->added.nelem; idx++) { 2154 if (!(md_get_prop_val(resp->added.mdp, 2155 resp->added.mdep[idx], swport_propname, &val))) { 2156 if (val == 0) { 2157 /* 2158 * This port is connected to the 2159 * vsw on service domain. 2160 */ 2161 vsw_idx = idx; 2162 if (vgen_add_port(vgenp, 2163 resp->added.mdp, 2164 resp->added.mdep[idx]) != 2165 DDI_SUCCESS) { 2166 cmn_err(CE_NOTE, "vnet%d Could " 2167 "not initialize virtual " 2168 "switch port.", 2169 vgenp->instance); 2170 mutex_exit(&vgenp->lock); 2171 return (MDEG_FAILURE); 2172 } 2173 break; 2174 } 2175 } 2176 } 2177 if (vsw_idx == -1) { 2178 DWARN(vgenp, NULL, "can't find vsw_port\n"); 2179 mutex_exit(&vgenp->lock); 2180 return (MDEG_FAILURE); 2181 } 2182 } 2183 2184 for (idx = 0; idx < resp->added.nelem; idx++) { 2185 if ((vsw_idx != -1) && (vsw_idx == idx)) /* skip vsw_port */ 2186 continue; 2187 2188 /* If this port can't be added just skip it. */ 2189 (void) vgen_add_port(vgenp, resp->added.mdp, 2190 resp->added.mdep[idx]); 2191 } 2192 2193 for (idx = 0; idx < resp->match_curr.nelem; idx++) { 2194 (void) vgen_update_port(vgenp, resp->match_curr.mdp, 2195 resp->match_curr.mdep[idx], 2196 resp->match_prev.mdp, 2197 resp->match_prev.mdep[idx]); 2198 } 2199 2200 mutex_exit(&vgenp->lock); 2201 DBG1(vgenp, NULL, "exit\n"); 2202 return (MDEG_SUCCESS); 2203 } 2204 2205 /* mdeg callback function for the vnet node */ 2206 static int 2207 vgen_mdeg_cb(void *cb_argp, mdeg_result_t *resp) 2208 { 2209 vgen_t *vgenp; 2210 vnet_t *vnetp; 2211 md_t *mdp; 2212 mde_cookie_t node; 2213 uint64_t inst; 2214 char *node_name = NULL; 2215 2216 if ((resp == NULL) || (cb_argp == NULL)) { 2217 return (MDEG_FAILURE); 2218 } 2219 2220 vgenp = (vgen_t *)cb_argp; 2221 vnetp = vgenp->vnetp; 2222 2223 DBG1(vgenp, NULL, "added %d : removed %d : curr matched %d" 2224 " : prev matched %d", resp->added.nelem, resp->removed.nelem, 2225 resp->match_curr.nelem, resp->match_prev.nelem); 2226 2227 mutex_enter(&vgenp->lock); 2228 2229 /* 2230 * We get an initial callback for this node as 'added' after 2231 * registering with mdeg. Note that we would have already gathered 2232 * information about this vnet node by walking MD earlier during attach 2233 * (in vgen_read_mdprops()). So, there is a window where the properties 2234 * of this node might have changed when we get this initial 'added' 2235 * callback. We handle this as if an update occured and invoke the same 2236 * function which handles updates to the properties of this vnet-node 2237 * if any. A non-zero 'match' value indicates that the MD has been 2238 * updated and that a 'network' node is present which may or may not 2239 * have been updated. It is up to the clients to examine their own 2240 * nodes and determine if they have changed. 2241 */ 2242 if (resp->added.nelem != 0) { 2243 2244 if (resp->added.nelem != 1) { 2245 cmn_err(CE_NOTE, "!vnet%d: number of nodes added " 2246 "invalid: %d\n", vnetp->instance, 2247 resp->added.nelem); 2248 goto vgen_mdeg_cb_err; 2249 } 2250 2251 mdp = resp->added.mdp; 2252 node = resp->added.mdep[0]; 2253 2254 } else if (resp->match_curr.nelem != 0) { 2255 2256 if (resp->match_curr.nelem != 1) { 2257 cmn_err(CE_NOTE, "!vnet%d: number of nodes updated " 2258 "invalid: %d\n", vnetp->instance, 2259 resp->match_curr.nelem); 2260 goto vgen_mdeg_cb_err; 2261 } 2262 2263 mdp = resp->match_curr.mdp; 2264 node = resp->match_curr.mdep[0]; 2265 2266 } else { 2267 goto vgen_mdeg_cb_err; 2268 } 2269 2270 /* Validate name and instance */ 2271 if (md_get_prop_str(mdp, node, "name", &node_name) != 0) { 2272 DERR(vgenp, NULL, "unable to get node name\n"); 2273 goto vgen_mdeg_cb_err; 2274 } 2275 2276 /* is this a virtual-network device? */ 2277 if (strcmp(node_name, vnet_propname) != 0) { 2278 DERR(vgenp, NULL, "%s: Invalid node name: %s\n", node_name); 2279 goto vgen_mdeg_cb_err; 2280 } 2281 2282 if (md_get_prop_val(mdp, node, "cfg-handle", &inst)) { 2283 DERR(vgenp, NULL, "prop(cfg-handle) not found\n"); 2284 goto vgen_mdeg_cb_err; 2285 } 2286 2287 /* is this the right instance of vnet? */ 2288 if (inst != vgenp->regprop) { 2289 DERR(vgenp, NULL, "Invalid cfg-handle: %lx\n", inst); 2290 goto vgen_mdeg_cb_err; 2291 } 2292 2293 vgen_update_md_prop(vgenp, mdp, node); 2294 2295 mutex_exit(&vgenp->lock); 2296 return (MDEG_SUCCESS); 2297 2298 vgen_mdeg_cb_err: 2299 mutex_exit(&vgenp->lock); 2300 return (MDEG_FAILURE); 2301 } 2302 2303 /* 2304 * Check to see if the relevant properties in the specified node have 2305 * changed, and if so take the appropriate action. 2306 */ 2307 static void 2308 vgen_update_md_prop(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex) 2309 { 2310 uint16_t pvid; 2311 uint16_t *vids; 2312 uint16_t nvids; 2313 vnet_t *vnetp = vgenp->vnetp; 2314 uint32_t mtu; 2315 boolean_t pls_update; 2316 enum { MD_init = 0x1, 2317 MD_vlans = 0x2, 2318 MD_mtu = 0x4, 2319 MD_pls = 0x8 } updated; 2320 int rv; 2321 2322 updated = MD_init; 2323 2324 /* Read the vlan ids */ 2325 vgen_vlan_read_ids(vgenp, VGEN_LOCAL, mdp, mdex, &pvid, &vids, 2326 &nvids, NULL); 2327 2328 /* Determine if there are any vlan id updates */ 2329 if ((pvid != vnetp->pvid) || /* pvid changed? */ 2330 (nvids != vnetp->nvids) || /* # of vids changed? */ 2331 ((nvids != 0) && (vnetp->nvids != 0) && /* vids changed? */ 2332 bcmp(vids, vnetp->vids, sizeof (uint16_t) * nvids))) { 2333 updated |= MD_vlans; 2334 } 2335 2336 /* Read mtu */ 2337 vgen_mtu_read(vgenp, mdp, mdex, &mtu); 2338 if (mtu != vnetp->mtu) { 2339 if (mtu >= ETHERMTU && mtu <= VNET_MAX_MTU) { 2340 updated |= MD_mtu; 2341 } else { 2342 cmn_err(CE_NOTE, "!vnet%d: Unable to process mtu update" 2343 " as the specified value:%d is invalid\n", 2344 vnetp->instance, mtu); 2345 } 2346 } 2347 2348 /* 2349 * Read the 'linkprop' property. 2350 */ 2351 vgen_linkprop_read(vgenp, mdp, mdex, &pls_update); 2352 if (pls_update != vnetp->pls_update) { 2353 updated |= MD_pls; 2354 } 2355 2356 /* Now process the updated props */ 2357 2358 if (updated & MD_vlans) { 2359 2360 /* save the new vlan ids */ 2361 vnetp->pvid = pvid; 2362 if (vnetp->nvids != 0) { 2363 kmem_free(vnetp->vids, 2364 sizeof (uint16_t) * vnetp->nvids); 2365 vnetp->nvids = 0; 2366 } 2367 if (nvids != 0) { 2368 vnetp->nvids = nvids; 2369 vnetp->vids = vids; 2370 } 2371 2372 /* reset vlan-unaware peers (ver < 1.3) and restart handshake */ 2373 vgen_reset_vlan_unaware_ports(vgenp); 2374 2375 } else { 2376 2377 if (nvids != 0) { 2378 kmem_free(vids, sizeof (uint16_t) * nvids); 2379 } 2380 } 2381 2382 if (updated & MD_mtu) { 2383 2384 DBG2(vgenp, NULL, "curr_mtu(%d) new_mtu(%d)\n", 2385 vnetp->mtu, mtu); 2386 2387 rv = vnet_mtu_update(vnetp, mtu); 2388 if (rv == 0) { 2389 vgenp->max_frame_size = mtu + 2390 sizeof (struct ether_header) + VLAN_TAGSZ; 2391 } 2392 } 2393 2394 if (updated & MD_pls) { 2395 /* enable/disable physical link state updates */ 2396 vnetp->pls_update = pls_update; 2397 mutex_exit(&vgenp->lock); 2398 2399 /* reset vsw-port to re-negotiate with the updated prop. */ 2400 vgen_reset_vsw_port(vgenp); 2401 2402 mutex_enter(&vgenp->lock); 2403 } 2404 } 2405 2406 /* add a new port to the device */ 2407 static int 2408 vgen_add_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex) 2409 { 2410 vgen_port_t *portp; 2411 int rv; 2412 2413 portp = kmem_zalloc(sizeof (vgen_port_t), KM_SLEEP); 2414 2415 rv = vgen_port_read_props(portp, vgenp, mdp, mdex); 2416 if (rv != DDI_SUCCESS) { 2417 KMEM_FREE(portp); 2418 return (DDI_FAILURE); 2419 } 2420 2421 rv = vgen_port_attach(portp); 2422 if (rv != DDI_SUCCESS) { 2423 return (DDI_FAILURE); 2424 } 2425 2426 return (DDI_SUCCESS); 2427 } 2428 2429 /* read properties of the port from its md node */ 2430 static int 2431 vgen_port_read_props(vgen_port_t *portp, vgen_t *vgenp, md_t *mdp, 2432 mde_cookie_t mdex) 2433 { 2434 uint64_t port_num; 2435 uint64_t *ldc_ids; 2436 uint64_t macaddr; 2437 uint64_t val; 2438 int num_ldcs; 2439 int i; 2440 int addrsz; 2441 int num_nodes = 0; 2442 int listsz = 0; 2443 mde_cookie_t *listp = NULL; 2444 uint8_t *addrp; 2445 struct ether_addr ea; 2446 2447 /* read "id" property to get the port number */ 2448 if (md_get_prop_val(mdp, mdex, id_propname, &port_num)) { 2449 DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname); 2450 return (DDI_FAILURE); 2451 } 2452 2453 /* 2454 * Find the channel endpoint node(s) under this port node. 2455 */ 2456 if ((num_nodes = md_node_count(mdp)) <= 0) { 2457 DWARN(vgenp, NULL, "invalid number of nodes found (%d)", 2458 num_nodes); 2459 return (DDI_FAILURE); 2460 } 2461 2462 /* allocate space for node list */ 2463 listsz = num_nodes * sizeof (mde_cookie_t); 2464 listp = kmem_zalloc(listsz, KM_NOSLEEP); 2465 if (listp == NULL) 2466 return (DDI_FAILURE); 2467 2468 num_ldcs = md_scan_dag(mdp, mdex, 2469 md_find_name(mdp, channel_propname), 2470 md_find_name(mdp, "fwd"), listp); 2471 2472 if (num_ldcs <= 0) { 2473 DWARN(vgenp, NULL, "can't find %s nodes", channel_propname); 2474 kmem_free(listp, listsz); 2475 return (DDI_FAILURE); 2476 } 2477 2478 DBG2(vgenp, NULL, "num_ldcs %d", num_ldcs); 2479 2480 ldc_ids = kmem_zalloc(num_ldcs * sizeof (uint64_t), KM_NOSLEEP); 2481 if (ldc_ids == NULL) { 2482 kmem_free(listp, listsz); 2483 return (DDI_FAILURE); 2484 } 2485 2486 for (i = 0; i < num_ldcs; i++) { 2487 /* read channel ids */ 2488 if (md_get_prop_val(mdp, listp[i], id_propname, &ldc_ids[i])) { 2489 DWARN(vgenp, NULL, "prop(%s) not found\n", 2490 id_propname); 2491 kmem_free(listp, listsz); 2492 kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t)); 2493 return (DDI_FAILURE); 2494 } 2495 DBG2(vgenp, NULL, "ldc_id 0x%llx", ldc_ids[i]); 2496 } 2497 2498 kmem_free(listp, listsz); 2499 2500 if (md_get_prop_data(mdp, mdex, rmacaddr_propname, &addrp, 2501 &addrsz)) { 2502 DWARN(vgenp, NULL, "prop(%s) not found\n", rmacaddr_propname); 2503 kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t)); 2504 return (DDI_FAILURE); 2505 } 2506 2507 if (addrsz < ETHERADDRL) { 2508 DWARN(vgenp, NULL, "invalid address size (%d)\n", addrsz); 2509 kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t)); 2510 return (DDI_FAILURE); 2511 } 2512 2513 macaddr = *((uint64_t *)addrp); 2514 2515 DBG2(vgenp, NULL, "remote mac address 0x%llx\n", macaddr); 2516 2517 for (i = ETHERADDRL - 1; i >= 0; i--) { 2518 ea.ether_addr_octet[i] = macaddr & 0xFF; 2519 macaddr >>= 8; 2520 } 2521 2522 if (!(md_get_prop_val(mdp, mdex, swport_propname, &val))) { 2523 if (val == 0) { 2524 /* This port is connected to the vswitch */ 2525 portp->is_vsw_port = B_TRUE; 2526 } else { 2527 portp->is_vsw_port = B_FALSE; 2528 } 2529 } 2530 2531 /* now update all properties into the port */ 2532 portp->vgenp = vgenp; 2533 portp->port_num = port_num; 2534 ether_copy(&ea, &portp->macaddr); 2535 portp->ldc_ids = kmem_zalloc(sizeof (uint64_t) * num_ldcs, KM_SLEEP); 2536 bcopy(ldc_ids, portp->ldc_ids, sizeof (uint64_t) * num_ldcs); 2537 portp->num_ldcs = num_ldcs; 2538 2539 /* read vlan id properties of this port node */ 2540 vgen_vlan_read_ids(portp, VGEN_PEER, mdp, mdex, &portp->pvid, 2541 &portp->vids, &portp->nvids, NULL); 2542 2543 kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t)); 2544 2545 return (DDI_SUCCESS); 2546 } 2547 2548 /* remove a port from the device */ 2549 static int 2550 vgen_remove_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex) 2551 { 2552 uint64_t port_num; 2553 vgen_port_t *portp; 2554 vgen_portlist_t *plistp; 2555 2556 /* read "id" property to get the port number */ 2557 if (md_get_prop_val(mdp, mdex, id_propname, &port_num)) { 2558 DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname); 2559 return (DDI_FAILURE); 2560 } 2561 2562 plistp = &(vgenp->vgenports); 2563 2564 WRITE_ENTER(&plistp->rwlock); 2565 portp = vgen_port_lookup(plistp, (int)port_num); 2566 if (portp == NULL) { 2567 DWARN(vgenp, NULL, "can't find port(%lx)\n", port_num); 2568 RW_EXIT(&plistp->rwlock); 2569 return (DDI_FAILURE); 2570 } 2571 2572 vgen_port_detach_mdeg(portp); 2573 RW_EXIT(&plistp->rwlock); 2574 2575 return (DDI_SUCCESS); 2576 } 2577 2578 /* attach a port to the device based on mdeg data */ 2579 static int 2580 vgen_port_attach(vgen_port_t *portp) 2581 { 2582 int i; 2583 vgen_portlist_t *plistp; 2584 vgen_t *vgenp; 2585 uint64_t *ldcids; 2586 uint32_t num_ldcs; 2587 mac_register_t *macp; 2588 vio_net_res_type_t type; 2589 int rv; 2590 2591 ASSERT(portp != NULL); 2592 2593 vgenp = portp->vgenp; 2594 ldcids = portp->ldc_ids; 2595 num_ldcs = portp->num_ldcs; 2596 2597 DBG1(vgenp, NULL, "port_num(%d)\n", portp->port_num); 2598 2599 mutex_init(&portp->lock, NULL, MUTEX_DRIVER, NULL); 2600 rw_init(&portp->ldclist.rwlock, NULL, RW_DRIVER, NULL); 2601 portp->ldclist.headp = NULL; 2602 2603 for (i = 0; i < num_ldcs; i++) { 2604 DBG2(vgenp, NULL, "ldcid (%lx)\n", ldcids[i]); 2605 if (vgen_ldc_attach(portp, ldcids[i]) == DDI_FAILURE) { 2606 vgen_port_detach(portp); 2607 return (DDI_FAILURE); 2608 } 2609 } 2610 2611 /* create vlan id hash table */ 2612 vgen_vlan_create_hash(portp); 2613 2614 if (portp->is_vsw_port == B_TRUE) { 2615 /* This port is connected to the switch port */ 2616 (void) atomic_swap_32(&portp->use_vsw_port, B_FALSE); 2617 type = VIO_NET_RES_LDC_SERVICE; 2618 } else { 2619 (void) atomic_swap_32(&portp->use_vsw_port, B_TRUE); 2620 type = VIO_NET_RES_LDC_GUEST; 2621 } 2622 2623 if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 2624 vgen_port_detach(portp); 2625 return (DDI_FAILURE); 2626 } 2627 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 2628 macp->m_driver = portp; 2629 macp->m_dip = vgenp->vnetdip; 2630 macp->m_src_addr = (uint8_t *)&(vgenp->macaddr); 2631 macp->m_callbacks = &vgen_m_callbacks; 2632 macp->m_min_sdu = 0; 2633 macp->m_max_sdu = ETHERMTU; 2634 2635 mutex_enter(&portp->lock); 2636 rv = vio_net_resource_reg(macp, type, vgenp->macaddr, 2637 portp->macaddr, &portp->vhp, &portp->vcb); 2638 mutex_exit(&portp->lock); 2639 mac_free(macp); 2640 2641 if (rv == 0) { 2642 /* link it into the list of ports */ 2643 plistp = &(vgenp->vgenports); 2644 WRITE_ENTER(&plistp->rwlock); 2645 vgen_port_list_insert(portp); 2646 RW_EXIT(&plistp->rwlock); 2647 2648 if (portp->is_vsw_port == B_TRUE) { 2649 /* We now have the vswitch port attached */ 2650 vgenp->vsw_portp = portp; 2651 (void) atomic_swap_32(&vgenp->vsw_port_refcnt, 0); 2652 } 2653 } else { 2654 DERR(vgenp, NULL, "vio_net_resource_reg failed for portp=0x%p", 2655 portp); 2656 vgen_port_detach(portp); 2657 } 2658 2659 DBG1(vgenp, NULL, "exit: port_num(%d)\n", portp->port_num); 2660 return (DDI_SUCCESS); 2661 } 2662 2663 /* detach a port from the device based on mdeg data */ 2664 static void 2665 vgen_port_detach_mdeg(vgen_port_t *portp) 2666 { 2667 vgen_t *vgenp = portp->vgenp; 2668 2669 DBG1(vgenp, NULL, "enter: port_num(%d)\n", portp->port_num); 2670 2671 mutex_enter(&portp->lock); 2672 2673 /* stop the port if needed */ 2674 if (portp->flags & VGEN_STARTED) { 2675 vgen_port_uninit(portp); 2676 } 2677 2678 mutex_exit(&portp->lock); 2679 vgen_port_detach(portp); 2680 2681 DBG1(vgenp, NULL, "exit: port_num(%d)\n", portp->port_num); 2682 } 2683 2684 static int 2685 vgen_update_port(vgen_t *vgenp, md_t *curr_mdp, mde_cookie_t curr_mdex, 2686 md_t *prev_mdp, mde_cookie_t prev_mdex) 2687 { 2688 uint64_t cport_num; 2689 uint64_t pport_num; 2690 vgen_portlist_t *plistp; 2691 vgen_port_t *portp; 2692 boolean_t updated_vlans = B_FALSE; 2693 uint16_t pvid; 2694 uint16_t *vids; 2695 uint16_t nvids; 2696 2697 /* 2698 * For now, we get port updates only if vlan ids changed. 2699 * We read the port num and do some sanity check. 2700 */ 2701 if (md_get_prop_val(curr_mdp, curr_mdex, id_propname, &cport_num)) { 2702 DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname); 2703 return (DDI_FAILURE); 2704 } 2705 2706 if (md_get_prop_val(prev_mdp, prev_mdex, id_propname, &pport_num)) { 2707 DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname); 2708 return (DDI_FAILURE); 2709 } 2710 if (cport_num != pport_num) 2711 return (DDI_FAILURE); 2712 2713 plistp = &(vgenp->vgenports); 2714 2715 READ_ENTER(&plistp->rwlock); 2716 2717 portp = vgen_port_lookup(plistp, (int)cport_num); 2718 if (portp == NULL) { 2719 DWARN(vgenp, NULL, "can't find port(%lx)\n", cport_num); 2720 RW_EXIT(&plistp->rwlock); 2721 return (DDI_FAILURE); 2722 } 2723 2724 /* Read the vlan ids */ 2725 vgen_vlan_read_ids(portp, VGEN_PEER, curr_mdp, curr_mdex, &pvid, &vids, 2726 &nvids, NULL); 2727 2728 /* Determine if there are any vlan id updates */ 2729 if ((pvid != portp->pvid) || /* pvid changed? */ 2730 (nvids != portp->nvids) || /* # of vids changed? */ 2731 ((nvids != 0) && (portp->nvids != 0) && /* vids changed? */ 2732 bcmp(vids, portp->vids, sizeof (uint16_t) * nvids))) { 2733 updated_vlans = B_TRUE; 2734 } 2735 2736 if (updated_vlans == B_FALSE) { 2737 RW_EXIT(&plistp->rwlock); 2738 return (DDI_FAILURE); 2739 } 2740 2741 /* remove the port from vlans it has been assigned to */ 2742 vgen_vlan_remove_ids(portp); 2743 2744 /* save the new vlan ids */ 2745 portp->pvid = pvid; 2746 if (portp->nvids != 0) { 2747 kmem_free(portp->vids, sizeof (uint16_t) * portp->nvids); 2748 portp->nvids = 0; 2749 } 2750 if (nvids != 0) { 2751 portp->vids = kmem_zalloc(sizeof (uint16_t) * nvids, KM_SLEEP); 2752 bcopy(vids, portp->vids, sizeof (uint16_t) * nvids); 2753 portp->nvids = nvids; 2754 kmem_free(vids, sizeof (uint16_t) * nvids); 2755 } 2756 2757 /* add port to the new vlans */ 2758 vgen_vlan_add_ids(portp); 2759 2760 /* reset the port if it is vlan unaware (ver < 1.3) */ 2761 vgen_vlan_unaware_port_reset(portp); 2762 2763 RW_EXIT(&plistp->rwlock); 2764 2765 return (DDI_SUCCESS); 2766 } 2767 2768 static uint64_t 2769 vgen_port_stat(vgen_port_t *portp, uint_t stat) 2770 { 2771 vgen_ldclist_t *ldclp; 2772 vgen_ldc_t *ldcp; 2773 uint64_t val; 2774 2775 val = 0; 2776 ldclp = &portp->ldclist; 2777 2778 READ_ENTER(&ldclp->rwlock); 2779 for (ldcp = ldclp->headp; ldcp != NULL; ldcp = ldcp->nextp) { 2780 val += vgen_ldc_stat(ldcp, stat); 2781 } 2782 RW_EXIT(&ldclp->rwlock); 2783 2784 return (val); 2785 } 2786 2787 /* allocate receive resources */ 2788 static int 2789 vgen_init_multipools(vgen_ldc_t *ldcp) 2790 { 2791 size_t data_sz; 2792 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 2793 int status; 2794 uint32_t sz1 = 0; 2795 uint32_t sz2 = 0; 2796 uint32_t sz3 = 0; 2797 uint32_t sz4 = 0; 2798 2799 /* 2800 * We round up the mtu specified to be a multiple of 2K. 2801 * We then create rx pools based on the rounded up size. 2802 */ 2803 data_sz = vgenp->max_frame_size + VNET_IPALIGN + VNET_LDCALIGN; 2804 data_sz = VNET_ROUNDUP_2K(data_sz); 2805 2806 /* 2807 * If pool sizes are specified, use them. Note that the presence of 2808 * the first tunable will be used as a hint. 2809 */ 2810 if (vgen_rbufsz1 != 0) { 2811 2812 sz1 = vgen_rbufsz1; 2813 sz2 = vgen_rbufsz2; 2814 sz3 = vgen_rbufsz3; 2815 sz4 = vgen_rbufsz4; 2816 2817 if (sz4 == 0) { /* need 3 pools */ 2818 2819 ldcp->max_rxpool_size = sz3; 2820 status = vio_init_multipools(&ldcp->vmp, 2821 VGEN_NUM_VMPOOLS, sz1, sz2, sz3, vgen_nrbufs1, 2822 vgen_nrbufs2, vgen_nrbufs3); 2823 2824 } else { 2825 2826 ldcp->max_rxpool_size = sz4; 2827 status = vio_init_multipools(&ldcp->vmp, 2828 VGEN_NUM_VMPOOLS + 1, sz1, sz2, sz3, sz4, 2829 vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3, 2830 vgen_nrbufs4); 2831 } 2832 return (status); 2833 } 2834 2835 /* 2836 * Pool sizes are not specified. We select the pool sizes based on the 2837 * mtu if vnet_jumbo_rxpools is enabled. 2838 */ 2839 if (vnet_jumbo_rxpools == B_FALSE || data_sz == VNET_2K) { 2840 /* 2841 * Receive buffer pool allocation based on mtu is disabled. 2842 * Use the default mechanism of standard size pool allocation. 2843 */ 2844 sz1 = VGEN_DBLK_SZ_128; 2845 sz2 = VGEN_DBLK_SZ_256; 2846 sz3 = VGEN_DBLK_SZ_2048; 2847 ldcp->max_rxpool_size = sz3; 2848 2849 status = vio_init_multipools(&ldcp->vmp, VGEN_NUM_VMPOOLS, 2850 sz1, sz2, sz3, 2851 vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3); 2852 2853 return (status); 2854 } 2855 2856 switch (data_sz) { 2857 2858 case VNET_4K: 2859 2860 sz1 = VGEN_DBLK_SZ_128; 2861 sz2 = VGEN_DBLK_SZ_256; 2862 sz3 = VGEN_DBLK_SZ_2048; 2863 sz4 = sz3 << 1; /* 4K */ 2864 ldcp->max_rxpool_size = sz4; 2865 2866 status = vio_init_multipools(&ldcp->vmp, VGEN_NUM_VMPOOLS + 1, 2867 sz1, sz2, sz3, sz4, 2868 vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3, vgen_nrbufs4); 2869 break; 2870 2871 default: /* data_sz: 4K+ to 16K */ 2872 2873 sz1 = VGEN_DBLK_SZ_256; 2874 sz2 = VGEN_DBLK_SZ_2048; 2875 sz3 = data_sz >> 1; /* Jumbo-size/2 */ 2876 sz4 = data_sz; /* Jumbo-size */ 2877 ldcp->max_rxpool_size = sz4; 2878 2879 status = vio_init_multipools(&ldcp->vmp, VGEN_NUM_VMPOOLS + 1, 2880 sz1, sz2, sz3, sz4, 2881 vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3, vgen_nrbufs4); 2882 break; 2883 2884 } 2885 2886 return (status); 2887 } 2888 2889 /* attach the channel corresponding to the given ldc_id to the port */ 2890 static int 2891 vgen_ldc_attach(vgen_port_t *portp, uint64_t ldc_id) 2892 { 2893 vgen_t *vgenp; 2894 vgen_ldclist_t *ldclp; 2895 vgen_ldc_t *ldcp, **prev_ldcp; 2896 ldc_attr_t attr; 2897 int status; 2898 ldc_status_t istatus; 2899 char kname[MAXNAMELEN]; 2900 int instance; 2901 enum {AST_init = 0x0, AST_ldc_alloc = 0x1, 2902 AST_mutex_init = 0x2, AST_ldc_init = 0x4, 2903 AST_ldc_reg_cb = 0x8, AST_alloc_tx_ring = 0x10, 2904 AST_create_rxmblks = 0x20, 2905 AST_create_rcv_thread = 0x40} attach_state; 2906 2907 attach_state = AST_init; 2908 vgenp = portp->vgenp; 2909 ldclp = &portp->ldclist; 2910 2911 ldcp = kmem_zalloc(sizeof (vgen_ldc_t), KM_NOSLEEP); 2912 if (ldcp == NULL) { 2913 goto ldc_attach_failed; 2914 } 2915 ldcp->ldc_id = ldc_id; 2916 ldcp->portp = portp; 2917 2918 attach_state |= AST_ldc_alloc; 2919 2920 mutex_init(&ldcp->txlock, NULL, MUTEX_DRIVER, NULL); 2921 mutex_init(&ldcp->cblock, NULL, MUTEX_DRIVER, NULL); 2922 mutex_init(&ldcp->tclock, NULL, MUTEX_DRIVER, NULL); 2923 mutex_init(&ldcp->wrlock, NULL, MUTEX_DRIVER, NULL); 2924 mutex_init(&ldcp->rxlock, NULL, MUTEX_DRIVER, NULL); 2925 mutex_init(&ldcp->pollq_lock, NULL, MUTEX_DRIVER, NULL); 2926 2927 attach_state |= AST_mutex_init; 2928 2929 attr.devclass = LDC_DEV_NT; 2930 attr.instance = vgenp->instance; 2931 attr.mode = LDC_MODE_UNRELIABLE; 2932 attr.mtu = vnet_ldc_mtu; 2933 status = ldc_init(ldc_id, &attr, &ldcp->ldc_handle); 2934 if (status != 0) { 2935 DWARN(vgenp, ldcp, "ldc_init failed,rv (%d)\n", status); 2936 goto ldc_attach_failed; 2937 } 2938 attach_state |= AST_ldc_init; 2939 2940 if (vgen_rcv_thread_enabled) { 2941 ldcp->rcv_thr_flags = 0; 2942 2943 mutex_init(&ldcp->rcv_thr_lock, NULL, MUTEX_DRIVER, NULL); 2944 cv_init(&ldcp->rcv_thr_cv, NULL, CV_DRIVER, NULL); 2945 ldcp->rcv_thread = thread_create(NULL, 2 * DEFAULTSTKSZ, 2946 vgen_ldc_rcv_worker, ldcp, 0, &p0, TS_RUN, maxclsyspri); 2947 2948 attach_state |= AST_create_rcv_thread; 2949 if (ldcp->rcv_thread == NULL) { 2950 DWARN(vgenp, ldcp, "Failed to create worker thread"); 2951 goto ldc_attach_failed; 2952 } 2953 } 2954 2955 status = ldc_reg_callback(ldcp->ldc_handle, vgen_ldc_cb, (caddr_t)ldcp); 2956 if (status != 0) { 2957 DWARN(vgenp, ldcp, "ldc_reg_callback failed, rv (%d)\n", 2958 status); 2959 goto ldc_attach_failed; 2960 } 2961 /* 2962 * allocate a message for ldc_read()s, big enough to hold ctrl and 2963 * data msgs, including raw data msgs used to recv priority frames. 2964 */ 2965 ldcp->msglen = VIO_PKT_DATA_HDRSIZE + vgenp->max_frame_size; 2966 ldcp->ldcmsg = kmem_alloc(ldcp->msglen, KM_SLEEP); 2967 attach_state |= AST_ldc_reg_cb; 2968 2969 (void) ldc_status(ldcp->ldc_handle, &istatus); 2970 ASSERT(istatus == LDC_INIT); 2971 ldcp->ldc_status = istatus; 2972 2973 /* allocate transmit resources */ 2974 status = vgen_alloc_tx_ring(ldcp); 2975 if (status != 0) { 2976 goto ldc_attach_failed; 2977 } 2978 attach_state |= AST_alloc_tx_ring; 2979 2980 /* allocate receive resources */ 2981 status = vgen_init_multipools(ldcp); 2982 if (status != 0) { 2983 /* 2984 * We do not return failure if receive mblk pools can't be 2985 * allocated; instead allocb(9F) will be used to dynamically 2986 * allocate buffers during receive. 2987 */ 2988 DWARN(vgenp, ldcp, 2989 "vnet%d: status(%d), failed to allocate rx mblk pools for " 2990 "channel(0x%lx)\n", 2991 vgenp->instance, status, ldcp->ldc_id); 2992 } else { 2993 attach_state |= AST_create_rxmblks; 2994 } 2995 2996 /* Setup kstats for the channel */ 2997 instance = vgenp->instance; 2998 (void) sprintf(kname, "vnetldc0x%lx", ldcp->ldc_id); 2999 ldcp->ksp = vgen_setup_kstats("vnet", instance, kname, &ldcp->stats); 3000 if (ldcp->ksp == NULL) { 3001 goto ldc_attach_failed; 3002 } 3003 3004 /* initialize vgen_versions supported */ 3005 bcopy(vgen_versions, ldcp->vgen_versions, sizeof (ldcp->vgen_versions)); 3006 vgen_reset_vnet_proto_ops(ldcp); 3007 3008 /* link it into the list of channels for this port */ 3009 WRITE_ENTER(&ldclp->rwlock); 3010 prev_ldcp = (vgen_ldc_t **)(&ldclp->headp); 3011 ldcp->nextp = *prev_ldcp; 3012 *prev_ldcp = ldcp; 3013 RW_EXIT(&ldclp->rwlock); 3014 3015 ldcp->link_state = LINK_STATE_UNKNOWN; 3016 #ifdef VNET_IOC_DEBUG 3017 ldcp->link_down_forced = B_FALSE; 3018 #endif 3019 ldcp->flags |= CHANNEL_ATTACHED; 3020 return (DDI_SUCCESS); 3021 3022 ldc_attach_failed: 3023 if (attach_state & AST_ldc_reg_cb) { 3024 (void) ldc_unreg_callback(ldcp->ldc_handle); 3025 kmem_free(ldcp->ldcmsg, ldcp->msglen); 3026 } 3027 if (attach_state & AST_create_rcv_thread) { 3028 if (ldcp->rcv_thread != NULL) { 3029 vgen_stop_rcv_thread(ldcp); 3030 } 3031 mutex_destroy(&ldcp->rcv_thr_lock); 3032 cv_destroy(&ldcp->rcv_thr_cv); 3033 } 3034 if (attach_state & AST_create_rxmblks) { 3035 vio_mblk_pool_t *fvmp = NULL; 3036 vio_destroy_multipools(&ldcp->vmp, &fvmp); 3037 ASSERT(fvmp == NULL); 3038 } 3039 if (attach_state & AST_alloc_tx_ring) { 3040 vgen_free_tx_ring(ldcp); 3041 } 3042 if (attach_state & AST_ldc_init) { 3043 (void) ldc_fini(ldcp->ldc_handle); 3044 } 3045 if (attach_state & AST_mutex_init) { 3046 mutex_destroy(&ldcp->tclock); 3047 mutex_destroy(&ldcp->txlock); 3048 mutex_destroy(&ldcp->cblock); 3049 mutex_destroy(&ldcp->wrlock); 3050 mutex_destroy(&ldcp->rxlock); 3051 mutex_destroy(&ldcp->pollq_lock); 3052 } 3053 if (attach_state & AST_ldc_alloc) { 3054 KMEM_FREE(ldcp); 3055 } 3056 return (DDI_FAILURE); 3057 } 3058 3059 /* detach a channel from the port */ 3060 static void 3061 vgen_ldc_detach(vgen_ldc_t *ldcp) 3062 { 3063 vgen_port_t *portp; 3064 vgen_t *vgenp; 3065 vgen_ldc_t *pldcp; 3066 vgen_ldc_t **prev_ldcp; 3067 vgen_ldclist_t *ldclp; 3068 3069 portp = ldcp->portp; 3070 vgenp = portp->vgenp; 3071 ldclp = &portp->ldclist; 3072 3073 prev_ldcp = (vgen_ldc_t **)&ldclp->headp; 3074 for (; (pldcp = *prev_ldcp) != NULL; prev_ldcp = &pldcp->nextp) { 3075 if (pldcp == ldcp) { 3076 break; 3077 } 3078 } 3079 3080 if (pldcp == NULL) { 3081 /* invalid ldcp? */ 3082 return; 3083 } 3084 3085 if (ldcp->ldc_status != LDC_INIT) { 3086 DWARN(vgenp, ldcp, "ldc_status is not INIT\n"); 3087 } 3088 3089 if (ldcp->flags & CHANNEL_ATTACHED) { 3090 ldcp->flags &= ~(CHANNEL_ATTACHED); 3091 3092 (void) ldc_unreg_callback(ldcp->ldc_handle); 3093 if (ldcp->rcv_thread != NULL) { 3094 /* First stop the receive thread */ 3095 vgen_stop_rcv_thread(ldcp); 3096 mutex_destroy(&ldcp->rcv_thr_lock); 3097 cv_destroy(&ldcp->rcv_thr_cv); 3098 } 3099 kmem_free(ldcp->ldcmsg, ldcp->msglen); 3100 3101 vgen_destroy_kstats(ldcp->ksp); 3102 ldcp->ksp = NULL; 3103 3104 /* 3105 * if we cannot reclaim all mblks, put this 3106 * on the list of pools(vgenp->rmp) to be reclaimed when the 3107 * device gets detached (see vgen_uninit()). 3108 */ 3109 vio_destroy_multipools(&ldcp->vmp, &vgenp->rmp); 3110 3111 /* free transmit resources */ 3112 vgen_free_tx_ring(ldcp); 3113 3114 (void) ldc_fini(ldcp->ldc_handle); 3115 mutex_destroy(&ldcp->tclock); 3116 mutex_destroy(&ldcp->txlock); 3117 mutex_destroy(&ldcp->cblock); 3118 mutex_destroy(&ldcp->wrlock); 3119 mutex_destroy(&ldcp->rxlock); 3120 mutex_destroy(&ldcp->pollq_lock); 3121 3122 /* unlink it from the list */ 3123 *prev_ldcp = ldcp->nextp; 3124 KMEM_FREE(ldcp); 3125 } 3126 } 3127 3128 /* 3129 * This function allocates transmit resources for the channel. 3130 * The resources consist of a transmit descriptor ring and an associated 3131 * transmit buffer ring. 3132 */ 3133 static int 3134 vgen_alloc_tx_ring(vgen_ldc_t *ldcp) 3135 { 3136 void *tbufp; 3137 ldc_mem_info_t minfo; 3138 uint32_t txdsize; 3139 uint32_t tbufsize; 3140 int status; 3141 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3142 3143 ldcp->num_txds = vnet_ntxds; 3144 txdsize = sizeof (vnet_public_desc_t); 3145 tbufsize = sizeof (vgen_private_desc_t); 3146 3147 /* allocate transmit buffer ring */ 3148 tbufp = kmem_zalloc(ldcp->num_txds * tbufsize, KM_NOSLEEP); 3149 if (tbufp == NULL) { 3150 return (DDI_FAILURE); 3151 } 3152 3153 /* create transmit descriptor ring */ 3154 status = ldc_mem_dring_create(ldcp->num_txds, txdsize, 3155 &ldcp->tx_dhandle); 3156 if (status) { 3157 DWARN(vgenp, ldcp, "ldc_mem_dring_create() failed\n"); 3158 kmem_free(tbufp, ldcp->num_txds * tbufsize); 3159 return (DDI_FAILURE); 3160 } 3161 3162 /* get the addr of descripror ring */ 3163 status = ldc_mem_dring_info(ldcp->tx_dhandle, &minfo); 3164 if (status) { 3165 DWARN(vgenp, ldcp, "ldc_mem_dring_info() failed\n"); 3166 kmem_free(tbufp, ldcp->num_txds * tbufsize); 3167 (void) ldc_mem_dring_destroy(ldcp->tx_dhandle); 3168 ldcp->tbufp = NULL; 3169 return (DDI_FAILURE); 3170 } 3171 ldcp->txdp = (vnet_public_desc_t *)(minfo.vaddr); 3172 ldcp->tbufp = tbufp; 3173 3174 ldcp->txdendp = &((ldcp->txdp)[ldcp->num_txds]); 3175 ldcp->tbufendp = &((ldcp->tbufp)[ldcp->num_txds]); 3176 3177 return (DDI_SUCCESS); 3178 } 3179 3180 /* Free transmit resources for the channel */ 3181 static void 3182 vgen_free_tx_ring(vgen_ldc_t *ldcp) 3183 { 3184 int tbufsize = sizeof (vgen_private_desc_t); 3185 3186 /* free transmit descriptor ring */ 3187 (void) ldc_mem_dring_destroy(ldcp->tx_dhandle); 3188 3189 /* free transmit buffer ring */ 3190 kmem_free(ldcp->tbufp, ldcp->num_txds * tbufsize); 3191 ldcp->txdp = ldcp->txdendp = NULL; 3192 ldcp->tbufp = ldcp->tbufendp = NULL; 3193 } 3194 3195 /* enable transmit/receive on the channels for the port */ 3196 static void 3197 vgen_init_ldcs(vgen_port_t *portp) 3198 { 3199 vgen_ldclist_t *ldclp = &portp->ldclist; 3200 vgen_ldc_t *ldcp; 3201 3202 READ_ENTER(&ldclp->rwlock); 3203 ldcp = ldclp->headp; 3204 for (; ldcp != NULL; ldcp = ldcp->nextp) { 3205 (void) vgen_ldc_init(ldcp); 3206 } 3207 RW_EXIT(&ldclp->rwlock); 3208 } 3209 3210 /* stop transmit/receive on the channels for the port */ 3211 static void 3212 vgen_uninit_ldcs(vgen_port_t *portp) 3213 { 3214 vgen_ldclist_t *ldclp = &portp->ldclist; 3215 vgen_ldc_t *ldcp; 3216 3217 READ_ENTER(&ldclp->rwlock); 3218 ldcp = ldclp->headp; 3219 for (; ldcp != NULL; ldcp = ldcp->nextp) { 3220 vgen_ldc_uninit(ldcp); 3221 } 3222 RW_EXIT(&ldclp->rwlock); 3223 } 3224 3225 /* enable transmit/receive on the channel */ 3226 static int 3227 vgen_ldc_init(vgen_ldc_t *ldcp) 3228 { 3229 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3230 ldc_status_t istatus; 3231 int rv; 3232 uint32_t retries = 0; 3233 enum { ST_init = 0x0, ST_ldc_open = 0x1, 3234 ST_init_tbufs = 0x2, ST_cb_enable = 0x4} init_state; 3235 init_state = ST_init; 3236 3237 DBG1(vgenp, ldcp, "enter\n"); 3238 LDC_LOCK(ldcp); 3239 3240 rv = ldc_open(ldcp->ldc_handle); 3241 if (rv != 0) { 3242 DWARN(vgenp, ldcp, "ldc_open failed: rv(%d)\n", rv); 3243 goto ldcinit_failed; 3244 } 3245 init_state |= ST_ldc_open; 3246 3247 (void) ldc_status(ldcp->ldc_handle, &istatus); 3248 if (istatus != LDC_OPEN && istatus != LDC_READY) { 3249 DWARN(vgenp, ldcp, "status(%d) is not OPEN/READY\n", istatus); 3250 goto ldcinit_failed; 3251 } 3252 ldcp->ldc_status = istatus; 3253 3254 rv = vgen_init_tbufs(ldcp); 3255 if (rv != 0) { 3256 DWARN(vgenp, ldcp, "vgen_init_tbufs() failed\n"); 3257 goto ldcinit_failed; 3258 } 3259 init_state |= ST_init_tbufs; 3260 3261 rv = ldc_set_cb_mode(ldcp->ldc_handle, LDC_CB_ENABLE); 3262 if (rv != 0) { 3263 DWARN(vgenp, ldcp, "ldc_set_cb_mode failed: rv(%d)\n", rv); 3264 goto ldcinit_failed; 3265 } 3266 3267 init_state |= ST_cb_enable; 3268 3269 do { 3270 rv = ldc_up(ldcp->ldc_handle); 3271 if ((rv != 0) && (rv == EWOULDBLOCK)) { 3272 DBG2(vgenp, ldcp, "ldc_up err rv(%d)\n", rv); 3273 drv_usecwait(VGEN_LDC_UP_DELAY); 3274 } 3275 if (retries++ >= vgen_ldcup_retries) 3276 break; 3277 } while (rv == EWOULDBLOCK); 3278 3279 (void) ldc_status(ldcp->ldc_handle, &istatus); 3280 if (istatus == LDC_UP) { 3281 DWARN(vgenp, ldcp, "status(%d) is UP\n", istatus); 3282 } 3283 3284 ldcp->ldc_status = istatus; 3285 3286 /* initialize transmit watchdog timeout */ 3287 ldcp->wd_tid = timeout(vgen_ldc_watchdog, (caddr_t)ldcp, 3288 drv_usectohz(vnet_ldcwd_interval * 1000)); 3289 3290 ldcp->hphase = -1; 3291 ldcp->flags |= CHANNEL_STARTED; 3292 3293 /* if channel is already UP - start handshake */ 3294 if (istatus == LDC_UP) { 3295 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3296 if (ldcp->portp != vgenp->vsw_portp) { 3297 /* 3298 * As the channel is up, use this port from now on. 3299 */ 3300 (void) atomic_swap_32( 3301 &ldcp->portp->use_vsw_port, B_FALSE); 3302 } 3303 3304 /* Initialize local session id */ 3305 ldcp->local_sid = ddi_get_lbolt(); 3306 3307 /* clear peer session id */ 3308 ldcp->peer_sid = 0; 3309 ldcp->hretries = 0; 3310 3311 /* Initiate Handshake process with peer ldc endpoint */ 3312 vgen_reset_hphase(ldcp); 3313 3314 mutex_exit(&ldcp->tclock); 3315 mutex_exit(&ldcp->txlock); 3316 mutex_exit(&ldcp->wrlock); 3317 mutex_exit(&ldcp->rxlock); 3318 vgen_handshake(vh_nextphase(ldcp)); 3319 mutex_exit(&ldcp->cblock); 3320 } else { 3321 LDC_UNLOCK(ldcp); 3322 } 3323 3324 return (DDI_SUCCESS); 3325 3326 ldcinit_failed: 3327 if (init_state & ST_cb_enable) { 3328 (void) ldc_set_cb_mode(ldcp->ldc_handle, LDC_CB_DISABLE); 3329 } 3330 if (init_state & ST_init_tbufs) { 3331 vgen_uninit_tbufs(ldcp); 3332 } 3333 if (init_state & ST_ldc_open) { 3334 (void) ldc_close(ldcp->ldc_handle); 3335 } 3336 LDC_UNLOCK(ldcp); 3337 DBG1(vgenp, ldcp, "exit\n"); 3338 return (DDI_FAILURE); 3339 } 3340 3341 /* stop transmit/receive on the channel */ 3342 static void 3343 vgen_ldc_uninit(vgen_ldc_t *ldcp) 3344 { 3345 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3346 int rv; 3347 uint_t retries = 0; 3348 3349 DBG1(vgenp, ldcp, "enter\n"); 3350 LDC_LOCK(ldcp); 3351 3352 if ((ldcp->flags & CHANNEL_STARTED) == 0) { 3353 LDC_UNLOCK(ldcp); 3354 DWARN(vgenp, ldcp, "CHANNEL_STARTED flag is not set\n"); 3355 return; 3356 } 3357 3358 /* disable further callbacks */ 3359 rv = ldc_set_cb_mode(ldcp->ldc_handle, LDC_CB_DISABLE); 3360 if (rv != 0) { 3361 DWARN(vgenp, ldcp, "ldc_set_cb_mode failed\n"); 3362 } 3363 3364 /* 3365 * clear handshake done bit and wait for pending tx and cb to finish. 3366 * release locks before untimeout(9F) is invoked to cancel timeouts. 3367 */ 3368 ldcp->hphase &= ~(VH_DONE); 3369 LDC_UNLOCK(ldcp); 3370 3371 if (vgenp->vsw_portp == ldcp->portp) { 3372 vio_net_report_err_t rep_err = 3373 ldcp->portp->vcb.vio_net_report_err; 3374 rep_err(ldcp->portp->vhp, VIO_NET_RES_DOWN); 3375 } 3376 3377 /* cancel handshake watchdog timeout */ 3378 if (ldcp->htid) { 3379 (void) untimeout(ldcp->htid); 3380 ldcp->htid = 0; 3381 } 3382 3383 if (ldcp->cancel_htid) { 3384 (void) untimeout(ldcp->cancel_htid); 3385 ldcp->cancel_htid = 0; 3386 } 3387 3388 /* cancel transmit watchdog timeout */ 3389 if (ldcp->wd_tid) { 3390 (void) untimeout(ldcp->wd_tid); 3391 ldcp->wd_tid = 0; 3392 } 3393 3394 drv_usecwait(1000); 3395 3396 if (ldcp->rcv_thread != NULL) { 3397 /* 3398 * Note that callbacks have been disabled already(above). The 3399 * drain function takes care of the condition when an already 3400 * executing callback signals the worker to start processing or 3401 * the worker has already been signalled and is in the middle of 3402 * processing. 3403 */ 3404 vgen_drain_rcv_thread(ldcp); 3405 } 3406 3407 /* acquire locks again; any pending transmits and callbacks are done */ 3408 LDC_LOCK(ldcp); 3409 3410 vgen_reset_hphase(ldcp); 3411 3412 vgen_uninit_tbufs(ldcp); 3413 3414 /* close the channel - retry on EAGAIN */ 3415 while ((rv = ldc_close(ldcp->ldc_handle)) == EAGAIN) { 3416 if (++retries > vgen_ldccl_retries) { 3417 break; 3418 } 3419 drv_usecwait(VGEN_LDC_CLOSE_DELAY); 3420 } 3421 if (rv != 0) { 3422 cmn_err(CE_NOTE, 3423 "!vnet%d: Error(%d) closing the channel(0x%lx)\n", 3424 vgenp->instance, rv, ldcp->ldc_id); 3425 } 3426 3427 ldcp->ldc_status = LDC_INIT; 3428 ldcp->flags &= ~(CHANNEL_STARTED); 3429 3430 LDC_UNLOCK(ldcp); 3431 3432 DBG1(vgenp, ldcp, "exit\n"); 3433 } 3434 3435 /* Initialize the transmit buffer ring for the channel */ 3436 static int 3437 vgen_init_tbufs(vgen_ldc_t *ldcp) 3438 { 3439 vgen_private_desc_t *tbufp; 3440 vnet_public_desc_t *txdp; 3441 vio_dring_entry_hdr_t *hdrp; 3442 int i; 3443 int rv; 3444 caddr_t datap = NULL; 3445 int ci; 3446 uint32_t ncookies; 3447 size_t data_sz; 3448 vgen_t *vgenp; 3449 3450 vgenp = LDC_TO_VGEN(ldcp); 3451 3452 bzero(ldcp->tbufp, sizeof (*tbufp) * (ldcp->num_txds)); 3453 bzero(ldcp->txdp, sizeof (*txdp) * (ldcp->num_txds)); 3454 3455 /* 3456 * In order to ensure that the number of ldc cookies per descriptor is 3457 * limited to be within the default MAX_COOKIES (2), we take the steps 3458 * outlined below: 3459 * 3460 * Align the entire data buffer area to 8K and carve out per descriptor 3461 * data buffers starting from this 8K aligned base address. 3462 * 3463 * We round up the mtu specified to be a multiple of 2K or 4K. 3464 * For sizes up to 12K we round up the size to the next 2K. 3465 * For sizes > 12K we round up to the next 4K (otherwise sizes such as 3466 * 14K could end up needing 3 cookies, with the buffer spread across 3467 * 3 8K pages: 8K+6K, 2K+8K+2K, 6K+8K, ...). 3468 */ 3469 data_sz = vgenp->max_frame_size + VNET_IPALIGN + VNET_LDCALIGN; 3470 if (data_sz <= VNET_12K) { 3471 data_sz = VNET_ROUNDUP_2K(data_sz); 3472 } else { 3473 data_sz = VNET_ROUNDUP_4K(data_sz); 3474 } 3475 3476 /* allocate extra 8K bytes for alignment */ 3477 ldcp->tx_data_sz = (data_sz * ldcp->num_txds) + VNET_8K; 3478 datap = kmem_zalloc(ldcp->tx_data_sz, KM_SLEEP); 3479 ldcp->tx_datap = datap; 3480 3481 3482 /* align the starting address of the data area to 8K */ 3483 datap = (caddr_t)VNET_ROUNDUP_8K((uintptr_t)datap); 3484 3485 /* 3486 * for each private descriptor, allocate a ldc mem_handle which is 3487 * required to map the data during transmit, set the flags 3488 * to free (available for use by transmit routine). 3489 */ 3490 3491 for (i = 0; i < ldcp->num_txds; i++) { 3492 3493 tbufp = &(ldcp->tbufp[i]); 3494 rv = ldc_mem_alloc_handle(ldcp->ldc_handle, 3495 &(tbufp->memhandle)); 3496 if (rv) { 3497 tbufp->memhandle = 0; 3498 goto init_tbufs_failed; 3499 } 3500 3501 /* 3502 * bind ldc memhandle to the corresponding transmit buffer. 3503 */ 3504 ci = ncookies = 0; 3505 rv = ldc_mem_bind_handle(tbufp->memhandle, 3506 (caddr_t)datap, data_sz, LDC_SHADOW_MAP, 3507 LDC_MEM_R, &(tbufp->memcookie[ci]), &ncookies); 3508 if (rv != 0) { 3509 goto init_tbufs_failed; 3510 } 3511 3512 /* 3513 * successful in binding the handle to tx data buffer. 3514 * set datap in the private descr to this buffer. 3515 */ 3516 tbufp->datap = datap; 3517 3518 if ((ncookies == 0) || 3519 (ncookies > MAX_COOKIES)) { 3520 goto init_tbufs_failed; 3521 } 3522 3523 for (ci = 1; ci < ncookies; ci++) { 3524 rv = ldc_mem_nextcookie(tbufp->memhandle, 3525 &(tbufp->memcookie[ci])); 3526 if (rv != 0) { 3527 goto init_tbufs_failed; 3528 } 3529 } 3530 3531 tbufp->ncookies = ncookies; 3532 datap += data_sz; 3533 3534 tbufp->flags = VGEN_PRIV_DESC_FREE; 3535 txdp = &(ldcp->txdp[i]); 3536 hdrp = &txdp->hdr; 3537 hdrp->dstate = VIO_DESC_FREE; 3538 hdrp->ack = B_FALSE; 3539 tbufp->descp = txdp; 3540 3541 } 3542 3543 /* reset tbuf walking pointers */ 3544 ldcp->next_tbufp = ldcp->tbufp; 3545 ldcp->cur_tbufp = ldcp->tbufp; 3546 3547 /* initialize tx seqnum and index */ 3548 ldcp->next_txseq = VNET_ISS; 3549 ldcp->next_txi = 0; 3550 3551 ldcp->resched_peer = B_TRUE; 3552 ldcp->resched_peer_txi = 0; 3553 3554 return (DDI_SUCCESS); 3555 3556 init_tbufs_failed:; 3557 vgen_uninit_tbufs(ldcp); 3558 return (DDI_FAILURE); 3559 } 3560 3561 /* Uninitialize transmit buffer ring for the channel */ 3562 static void 3563 vgen_uninit_tbufs(vgen_ldc_t *ldcp) 3564 { 3565 vgen_private_desc_t *tbufp = ldcp->tbufp; 3566 int i; 3567 3568 /* for each tbuf (priv_desc), free ldc mem_handle */ 3569 for (i = 0; i < ldcp->num_txds; i++) { 3570 3571 tbufp = &(ldcp->tbufp[i]); 3572 3573 if (tbufp->datap) { /* if bound to a ldc memhandle */ 3574 (void) ldc_mem_unbind_handle(tbufp->memhandle); 3575 tbufp->datap = NULL; 3576 } 3577 if (tbufp->memhandle) { 3578 (void) ldc_mem_free_handle(tbufp->memhandle); 3579 tbufp->memhandle = 0; 3580 } 3581 } 3582 3583 if (ldcp->tx_datap) { 3584 /* prealloc'd tx data buffer */ 3585 kmem_free(ldcp->tx_datap, ldcp->tx_data_sz); 3586 ldcp->tx_datap = NULL; 3587 ldcp->tx_data_sz = 0; 3588 } 3589 3590 bzero(ldcp->tbufp, sizeof (vgen_private_desc_t) * (ldcp->num_txds)); 3591 bzero(ldcp->txdp, sizeof (vnet_public_desc_t) * (ldcp->num_txds)); 3592 } 3593 3594 /* clobber tx descriptor ring */ 3595 static void 3596 vgen_clobber_tbufs(vgen_ldc_t *ldcp) 3597 { 3598 vnet_public_desc_t *txdp; 3599 vgen_private_desc_t *tbufp; 3600 vio_dring_entry_hdr_t *hdrp; 3601 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3602 int i; 3603 #ifdef DEBUG 3604 int ndone = 0; 3605 #endif 3606 3607 for (i = 0; i < ldcp->num_txds; i++) { 3608 3609 tbufp = &(ldcp->tbufp[i]); 3610 txdp = tbufp->descp; 3611 hdrp = &txdp->hdr; 3612 3613 if (tbufp->flags & VGEN_PRIV_DESC_BUSY) { 3614 tbufp->flags = VGEN_PRIV_DESC_FREE; 3615 #ifdef DEBUG 3616 if (hdrp->dstate == VIO_DESC_DONE) 3617 ndone++; 3618 #endif 3619 hdrp->dstate = VIO_DESC_FREE; 3620 hdrp->ack = B_FALSE; 3621 } 3622 } 3623 /* reset tbuf walking pointers */ 3624 ldcp->next_tbufp = ldcp->tbufp; 3625 ldcp->cur_tbufp = ldcp->tbufp; 3626 3627 /* reset tx seqnum and index */ 3628 ldcp->next_txseq = VNET_ISS; 3629 ldcp->next_txi = 0; 3630 3631 ldcp->resched_peer = B_TRUE; 3632 ldcp->resched_peer_txi = 0; 3633 3634 DBG2(vgenp, ldcp, "num descrs done (%d)\n", ndone); 3635 } 3636 3637 /* clobber receive descriptor ring */ 3638 static void 3639 vgen_clobber_rxds(vgen_ldc_t *ldcp) 3640 { 3641 ldcp->rx_dhandle = 0; 3642 bzero(&ldcp->rx_dcookie, sizeof (ldcp->rx_dcookie)); 3643 ldcp->rxdp = NULL; 3644 ldcp->next_rxi = 0; 3645 ldcp->num_rxds = 0; 3646 ldcp->next_rxseq = VNET_ISS; 3647 } 3648 3649 /* initialize receive descriptor ring */ 3650 static int 3651 vgen_init_rxds(vgen_ldc_t *ldcp, uint32_t num_desc, uint32_t desc_size, 3652 ldc_mem_cookie_t *dcookie, uint32_t ncookies) 3653 { 3654 int rv; 3655 ldc_mem_info_t minfo; 3656 3657 rv = ldc_mem_dring_map(ldcp->ldc_handle, dcookie, ncookies, num_desc, 3658 desc_size, LDC_DIRECT_MAP, &(ldcp->rx_dhandle)); 3659 if (rv != 0) { 3660 return (DDI_FAILURE); 3661 } 3662 3663 /* 3664 * sucessfully mapped, now try to 3665 * get info about the mapped dring 3666 */ 3667 rv = ldc_mem_dring_info(ldcp->rx_dhandle, &minfo); 3668 if (rv != 0) { 3669 (void) ldc_mem_dring_unmap(ldcp->rx_dhandle); 3670 return (DDI_FAILURE); 3671 } 3672 3673 /* 3674 * save ring address, number of descriptors. 3675 */ 3676 ldcp->rxdp = (vnet_public_desc_t *)(minfo.vaddr); 3677 bcopy(dcookie, &(ldcp->rx_dcookie), sizeof (*dcookie)); 3678 ldcp->num_rxdcookies = ncookies; 3679 ldcp->num_rxds = num_desc; 3680 ldcp->next_rxi = 0; 3681 ldcp->next_rxseq = VNET_ISS; 3682 ldcp->dring_mtype = minfo.mtype; 3683 3684 return (DDI_SUCCESS); 3685 } 3686 3687 /* get channel statistics */ 3688 static uint64_t 3689 vgen_ldc_stat(vgen_ldc_t *ldcp, uint_t stat) 3690 { 3691 vgen_stats_t *statsp; 3692 uint64_t val; 3693 3694 val = 0; 3695 statsp = &ldcp->stats; 3696 switch (stat) { 3697 3698 case MAC_STAT_MULTIRCV: 3699 val = statsp->multircv; 3700 break; 3701 3702 case MAC_STAT_BRDCSTRCV: 3703 val = statsp->brdcstrcv; 3704 break; 3705 3706 case MAC_STAT_MULTIXMT: 3707 val = statsp->multixmt; 3708 break; 3709 3710 case MAC_STAT_BRDCSTXMT: 3711 val = statsp->brdcstxmt; 3712 break; 3713 3714 case MAC_STAT_NORCVBUF: 3715 val = statsp->norcvbuf; 3716 break; 3717 3718 case MAC_STAT_IERRORS: 3719 val = statsp->ierrors; 3720 break; 3721 3722 case MAC_STAT_NOXMTBUF: 3723 val = statsp->noxmtbuf; 3724 break; 3725 3726 case MAC_STAT_OERRORS: 3727 val = statsp->oerrors; 3728 break; 3729 3730 case MAC_STAT_COLLISIONS: 3731 break; 3732 3733 case MAC_STAT_RBYTES: 3734 val = statsp->rbytes; 3735 break; 3736 3737 case MAC_STAT_IPACKETS: 3738 val = statsp->ipackets; 3739 break; 3740 3741 case MAC_STAT_OBYTES: 3742 val = statsp->obytes; 3743 break; 3744 3745 case MAC_STAT_OPACKETS: 3746 val = statsp->opackets; 3747 break; 3748 3749 /* stats not relevant to ldc, return 0 */ 3750 case MAC_STAT_IFSPEED: 3751 case ETHER_STAT_ALIGN_ERRORS: 3752 case ETHER_STAT_FCS_ERRORS: 3753 case ETHER_STAT_FIRST_COLLISIONS: 3754 case ETHER_STAT_MULTI_COLLISIONS: 3755 case ETHER_STAT_DEFER_XMTS: 3756 case ETHER_STAT_TX_LATE_COLLISIONS: 3757 case ETHER_STAT_EX_COLLISIONS: 3758 case ETHER_STAT_MACXMT_ERRORS: 3759 case ETHER_STAT_CARRIER_ERRORS: 3760 case ETHER_STAT_TOOLONG_ERRORS: 3761 case ETHER_STAT_XCVR_ADDR: 3762 case ETHER_STAT_XCVR_ID: 3763 case ETHER_STAT_XCVR_INUSE: 3764 case ETHER_STAT_CAP_1000FDX: 3765 case ETHER_STAT_CAP_1000HDX: 3766 case ETHER_STAT_CAP_100FDX: 3767 case ETHER_STAT_CAP_100HDX: 3768 case ETHER_STAT_CAP_10FDX: 3769 case ETHER_STAT_CAP_10HDX: 3770 case ETHER_STAT_CAP_ASMPAUSE: 3771 case ETHER_STAT_CAP_PAUSE: 3772 case ETHER_STAT_CAP_AUTONEG: 3773 case ETHER_STAT_ADV_CAP_1000FDX: 3774 case ETHER_STAT_ADV_CAP_1000HDX: 3775 case ETHER_STAT_ADV_CAP_100FDX: 3776 case ETHER_STAT_ADV_CAP_100HDX: 3777 case ETHER_STAT_ADV_CAP_10FDX: 3778 case ETHER_STAT_ADV_CAP_10HDX: 3779 case ETHER_STAT_ADV_CAP_ASMPAUSE: 3780 case ETHER_STAT_ADV_CAP_PAUSE: 3781 case ETHER_STAT_ADV_CAP_AUTONEG: 3782 case ETHER_STAT_LP_CAP_1000FDX: 3783 case ETHER_STAT_LP_CAP_1000HDX: 3784 case ETHER_STAT_LP_CAP_100FDX: 3785 case ETHER_STAT_LP_CAP_100HDX: 3786 case ETHER_STAT_LP_CAP_10FDX: 3787 case ETHER_STAT_LP_CAP_10HDX: 3788 case ETHER_STAT_LP_CAP_ASMPAUSE: 3789 case ETHER_STAT_LP_CAP_PAUSE: 3790 case ETHER_STAT_LP_CAP_AUTONEG: 3791 case ETHER_STAT_LINK_ASMPAUSE: 3792 case ETHER_STAT_LINK_PAUSE: 3793 case ETHER_STAT_LINK_AUTONEG: 3794 case ETHER_STAT_LINK_DUPLEX: 3795 default: 3796 val = 0; 3797 break; 3798 3799 } 3800 return (val); 3801 } 3802 3803 /* 3804 * LDC channel is UP, start handshake process with peer. 3805 */ 3806 static void 3807 vgen_handle_evt_up(vgen_ldc_t *ldcp) 3808 { 3809 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3810 3811 DBG1(vgenp, ldcp, "enter\n"); 3812 3813 ASSERT(MUTEX_HELD(&ldcp->cblock)); 3814 3815 if (ldcp->portp != vgenp->vsw_portp) { 3816 /* 3817 * As the channel is up, use this port from now on. 3818 */ 3819 (void) atomic_swap_32(&ldcp->portp->use_vsw_port, B_FALSE); 3820 } 3821 3822 /* Initialize local session id */ 3823 ldcp->local_sid = ddi_get_lbolt(); 3824 3825 /* clear peer session id */ 3826 ldcp->peer_sid = 0; 3827 ldcp->hretries = 0; 3828 3829 if (ldcp->hphase != VH_PHASE0) { 3830 vgen_handshake_reset(ldcp); 3831 } 3832 3833 /* Initiate Handshake process with peer ldc endpoint */ 3834 vgen_handshake(vh_nextphase(ldcp)); 3835 3836 DBG1(vgenp, ldcp, "exit\n"); 3837 } 3838 3839 /* 3840 * LDC channel is Reset, terminate connection with peer and try to 3841 * bring the channel up again. 3842 */ 3843 static void 3844 vgen_handle_evt_reset(vgen_ldc_t *ldcp) 3845 { 3846 ldc_status_t istatus; 3847 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3848 int rv; 3849 3850 DBG1(vgenp, ldcp, "enter\n"); 3851 3852 ASSERT(MUTEX_HELD(&ldcp->cblock)); 3853 3854 if ((ldcp->portp != vgenp->vsw_portp) && 3855 (vgenp->vsw_portp != NULL)) { 3856 /* 3857 * As the channel is down, use the switch port until 3858 * the channel becomes ready to be used. 3859 */ 3860 (void) atomic_swap_32(&ldcp->portp->use_vsw_port, B_TRUE); 3861 } 3862 3863 if (vgenp->vsw_portp == ldcp->portp) { 3864 vio_net_report_err_t rep_err = 3865 ldcp->portp->vcb.vio_net_report_err; 3866 3867 /* Post a reset message */ 3868 rep_err(ldcp->portp->vhp, VIO_NET_RES_DOWN); 3869 } 3870 3871 if (ldcp->hphase != VH_PHASE0) { 3872 vgen_handshake_reset(ldcp); 3873 } 3874 3875 /* try to bring the channel up */ 3876 #ifdef VNET_IOC_DEBUG 3877 if (ldcp->link_down_forced == B_FALSE) { 3878 rv = ldc_up(ldcp->ldc_handle); 3879 if (rv != 0) { 3880 DWARN(vgenp, ldcp, "ldc_up err rv(%d)\n", rv); 3881 } 3882 } 3883 #else 3884 rv = ldc_up(ldcp->ldc_handle); 3885 if (rv != 0) { 3886 DWARN(vgenp, ldcp, "ldc_up err rv(%d)\n", rv); 3887 } 3888 #endif 3889 3890 if (ldc_status(ldcp->ldc_handle, &istatus) != 0) { 3891 DWARN(vgenp, ldcp, "ldc_status err\n"); 3892 } else { 3893 ldcp->ldc_status = istatus; 3894 } 3895 3896 /* if channel is already UP - restart handshake */ 3897 if (ldcp->ldc_status == LDC_UP) { 3898 vgen_handle_evt_up(ldcp); 3899 } 3900 3901 DBG1(vgenp, ldcp, "exit\n"); 3902 } 3903 3904 /* Interrupt handler for the channel */ 3905 static uint_t 3906 vgen_ldc_cb(uint64_t event, caddr_t arg) 3907 { 3908 _NOTE(ARGUNUSED(event)) 3909 vgen_ldc_t *ldcp; 3910 vgen_t *vgenp; 3911 ldc_status_t istatus; 3912 vgen_stats_t *statsp; 3913 timeout_id_t cancel_htid = 0; 3914 uint_t ret = LDC_SUCCESS; 3915 3916 ldcp = (vgen_ldc_t *)arg; 3917 vgenp = LDC_TO_VGEN(ldcp); 3918 statsp = &ldcp->stats; 3919 3920 DBG1(vgenp, ldcp, "enter\n"); 3921 3922 mutex_enter(&ldcp->cblock); 3923 statsp->callbacks++; 3924 if ((ldcp->ldc_status == LDC_INIT) || (ldcp->ldc_handle == NULL)) { 3925 DWARN(vgenp, ldcp, "status(%d) is LDC_INIT\n", 3926 ldcp->ldc_status); 3927 mutex_exit(&ldcp->cblock); 3928 return (LDC_SUCCESS); 3929 } 3930 3931 /* 3932 * cache cancel_htid before the events specific 3933 * code may overwrite it. Do not clear ldcp->cancel_htid 3934 * as it is also used to indicate the timer to quit immediately. 3935 */ 3936 cancel_htid = ldcp->cancel_htid; 3937 3938 /* 3939 * NOTE: not using switch() as event could be triggered by 3940 * a state change and a read request. Also the ordering of the 3941 * check for the event types is deliberate. 3942 */ 3943 if (event & LDC_EVT_UP) { 3944 if (ldc_status(ldcp->ldc_handle, &istatus) != 0) { 3945 DWARN(vgenp, ldcp, "ldc_status err\n"); 3946 /* status couldn't be determined */ 3947 ret = LDC_FAILURE; 3948 goto ldc_cb_ret; 3949 } 3950 ldcp->ldc_status = istatus; 3951 if (ldcp->ldc_status != LDC_UP) { 3952 DWARN(vgenp, ldcp, "LDC_EVT_UP received " 3953 " but ldc status is not UP(0x%x)\n", 3954 ldcp->ldc_status); 3955 /* spurious interrupt, return success */ 3956 goto ldc_cb_ret; 3957 } 3958 DWARN(vgenp, ldcp, "event(%lx) UP, status(%d)\n", 3959 event, ldcp->ldc_status); 3960 3961 vgen_handle_evt_up(ldcp); 3962 3963 ASSERT((event & (LDC_EVT_RESET | LDC_EVT_DOWN)) == 0); 3964 } 3965 3966 /* Handle RESET/DOWN before READ event */ 3967 if (event & (LDC_EVT_RESET | LDC_EVT_DOWN)) { 3968 if (ldc_status(ldcp->ldc_handle, &istatus) != 0) { 3969 DWARN(vgenp, ldcp, "ldc_status error\n"); 3970 /* status couldn't be determined */ 3971 ret = LDC_FAILURE; 3972 goto ldc_cb_ret; 3973 } 3974 ldcp->ldc_status = istatus; 3975 DWARN(vgenp, ldcp, "event(%lx) RESET/DOWN, status(%d)\n", 3976 event, ldcp->ldc_status); 3977 3978 vgen_handle_evt_reset(ldcp); 3979 3980 /* 3981 * As the channel is down/reset, ignore READ event 3982 * but print a debug warning message. 3983 */ 3984 if (event & LDC_EVT_READ) { 3985 DWARN(vgenp, ldcp, 3986 "LDC_EVT_READ set along with RESET/DOWN\n"); 3987 event &= ~LDC_EVT_READ; 3988 } 3989 } 3990 3991 if (event & LDC_EVT_READ) { 3992 DBG2(vgenp, ldcp, "event(%lx) READ, status(%d)\n", 3993 event, ldcp->ldc_status); 3994 3995 ASSERT((event & (LDC_EVT_RESET | LDC_EVT_DOWN)) == 0); 3996 3997 if (ldcp->rcv_thread != NULL) { 3998 /* 3999 * If the receive thread is enabled, then 4000 * wakeup the receive thread to process the 4001 * LDC messages. 4002 */ 4003 mutex_exit(&ldcp->cblock); 4004 mutex_enter(&ldcp->rcv_thr_lock); 4005 if (!(ldcp->rcv_thr_flags & VGEN_WTHR_DATARCVD)) { 4006 ldcp->rcv_thr_flags |= VGEN_WTHR_DATARCVD; 4007 cv_signal(&ldcp->rcv_thr_cv); 4008 } 4009 mutex_exit(&ldcp->rcv_thr_lock); 4010 mutex_enter(&ldcp->cblock); 4011 } else { 4012 vgen_handle_evt_read(ldcp); 4013 } 4014 } 4015 4016 ldc_cb_ret: 4017 /* 4018 * Check to see if the status of cancel_htid has 4019 * changed. If another timer needs to be cancelled, 4020 * then let the next callback to clear it. 4021 */ 4022 if (cancel_htid == 0) { 4023 cancel_htid = ldcp->cancel_htid; 4024 } 4025 mutex_exit(&ldcp->cblock); 4026 4027 if (cancel_htid) { 4028 /* 4029 * Cancel handshake timer. 4030 * untimeout(9F) will not return until the pending callback is 4031 * cancelled or has run. No problems will result from calling 4032 * untimeout if the handler has already completed. 4033 * If the timeout handler did run, then it would just 4034 * return as cancel_htid is set. 4035 */ 4036 DBG2(vgenp, ldcp, "cancel_htid =0x%X \n", cancel_htid); 4037 (void) untimeout(cancel_htid); 4038 mutex_enter(&ldcp->cblock); 4039 /* clear it only if its the same as the one we cancelled */ 4040 if (ldcp->cancel_htid == cancel_htid) { 4041 ldcp->cancel_htid = 0; 4042 } 4043 mutex_exit(&ldcp->cblock); 4044 } 4045 DBG1(vgenp, ldcp, "exit\n"); 4046 return (ret); 4047 } 4048 4049 static void 4050 vgen_handle_evt_read(vgen_ldc_t *ldcp) 4051 { 4052 int rv; 4053 uint64_t *ldcmsg; 4054 size_t msglen; 4055 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4056 vio_msg_tag_t *tagp; 4057 ldc_status_t istatus; 4058 boolean_t has_data; 4059 4060 DBG1(vgenp, ldcp, "enter\n"); 4061 4062 ldcmsg = ldcp->ldcmsg; 4063 /* 4064 * If the receive thread is enabled, then the cblock 4065 * need to be acquired here. If not, the vgen_ldc_cb() 4066 * calls this function with cblock held already. 4067 */ 4068 if (ldcp->rcv_thread != NULL) { 4069 mutex_enter(&ldcp->cblock); 4070 } else { 4071 ASSERT(MUTEX_HELD(&ldcp->cblock)); 4072 } 4073 4074 vgen_evt_read: 4075 do { 4076 msglen = ldcp->msglen; 4077 rv = ldc_read(ldcp->ldc_handle, (caddr_t)ldcmsg, &msglen); 4078 4079 if (rv != 0) { 4080 DWARN(vgenp, ldcp, "err rv(%d) len(%d)\n", 4081 rv, msglen); 4082 if (rv == ECONNRESET) 4083 goto vgen_evtread_error; 4084 break; 4085 } 4086 if (msglen == 0) { 4087 DBG2(vgenp, ldcp, "ldc_read NODATA"); 4088 break; 4089 } 4090 DBG2(vgenp, ldcp, "ldc_read msglen(%d)", msglen); 4091 4092 tagp = (vio_msg_tag_t *)ldcmsg; 4093 4094 if (ldcp->peer_sid) { 4095 /* 4096 * check sid only after we have received peer's sid 4097 * in the version negotiate msg. 4098 */ 4099 #ifdef DEBUG 4100 if (vgen_hdbg & HDBG_BAD_SID) { 4101 /* simulate bad sid condition */ 4102 tagp->vio_sid = 0; 4103 vgen_hdbg &= ~(HDBG_BAD_SID); 4104 } 4105 #endif 4106 rv = vgen_check_sid(ldcp, tagp); 4107 if (rv != VGEN_SUCCESS) { 4108 /* 4109 * If sid mismatch is detected, 4110 * reset the channel. 4111 */ 4112 goto vgen_evtread_error; 4113 } 4114 } 4115 4116 switch (tagp->vio_msgtype) { 4117 case VIO_TYPE_CTRL: 4118 rv = vgen_handle_ctrlmsg(ldcp, tagp); 4119 break; 4120 4121 case VIO_TYPE_DATA: 4122 rv = vgen_handle_datamsg(ldcp, tagp, msglen); 4123 break; 4124 4125 case VIO_TYPE_ERR: 4126 vgen_handle_errmsg(ldcp, tagp); 4127 break; 4128 4129 default: 4130 DWARN(vgenp, ldcp, "Unknown VIO_TYPE(%x)\n", 4131 tagp->vio_msgtype); 4132 break; 4133 } 4134 4135 /* 4136 * If an error is encountered, stop processing and 4137 * handle the error. 4138 */ 4139 if (rv != 0) { 4140 goto vgen_evtread_error; 4141 } 4142 4143 } while (msglen); 4144 4145 /* check once more before exiting */ 4146 rv = ldc_chkq(ldcp->ldc_handle, &has_data); 4147 if ((rv == 0) && (has_data == B_TRUE)) { 4148 DTRACE_PROBE(vgen_chkq); 4149 goto vgen_evt_read; 4150 } 4151 4152 vgen_evtread_error: 4153 if (rv == ECONNRESET) { 4154 if (ldc_status(ldcp->ldc_handle, &istatus) != 0) { 4155 DWARN(vgenp, ldcp, "ldc_status err\n"); 4156 } else { 4157 ldcp->ldc_status = istatus; 4158 } 4159 vgen_handle_evt_reset(ldcp); 4160 } else if (rv) { 4161 vgen_ldc_reset(ldcp); 4162 } 4163 4164 /* 4165 * If the receive thread is enabled, then cancel the 4166 * handshake timeout here. 4167 */ 4168 if (ldcp->rcv_thread != NULL) { 4169 timeout_id_t cancel_htid = ldcp->cancel_htid; 4170 4171 mutex_exit(&ldcp->cblock); 4172 if (cancel_htid) { 4173 /* 4174 * Cancel handshake timer. untimeout(9F) will 4175 * not return until the pending callback is cancelled 4176 * or has run. No problems will result from calling 4177 * untimeout if the handler has already completed. 4178 * If the timeout handler did run, then it would just 4179 * return as cancel_htid is set. 4180 */ 4181 DBG2(vgenp, ldcp, "cancel_htid =0x%X \n", cancel_htid); 4182 (void) untimeout(cancel_htid); 4183 4184 /* 4185 * clear it only if its the same as the one we 4186 * cancelled 4187 */ 4188 mutex_enter(&ldcp->cblock); 4189 if (ldcp->cancel_htid == cancel_htid) { 4190 ldcp->cancel_htid = 0; 4191 } 4192 mutex_exit(&ldcp->cblock); 4193 } 4194 } 4195 4196 DBG1(vgenp, ldcp, "exit\n"); 4197 } 4198 4199 /* vgen handshake functions */ 4200 4201 /* change the hphase for the channel to the next phase */ 4202 static vgen_ldc_t * 4203 vh_nextphase(vgen_ldc_t *ldcp) 4204 { 4205 if (ldcp->hphase == VH_PHASE3) { 4206 ldcp->hphase = VH_DONE; 4207 } else { 4208 ldcp->hphase++; 4209 } 4210 return (ldcp); 4211 } 4212 4213 /* 4214 * wrapper routine to send the given message over ldc using ldc_write(). 4215 */ 4216 static int 4217 vgen_sendmsg(vgen_ldc_t *ldcp, caddr_t msg, size_t msglen, 4218 boolean_t caller_holds_lock) 4219 { 4220 int rv; 4221 size_t len; 4222 uint32_t retries = 0; 4223 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4224 vio_msg_tag_t *tagp = (vio_msg_tag_t *)msg; 4225 vio_dring_msg_t *dmsg; 4226 vio_raw_data_msg_t *rmsg; 4227 boolean_t data_msg = B_FALSE; 4228 4229 len = msglen; 4230 if ((len == 0) || (msg == NULL)) 4231 return (VGEN_FAILURE); 4232 4233 if (!caller_holds_lock) { 4234 mutex_enter(&ldcp->wrlock); 4235 } 4236 4237 if (tagp->vio_subtype == VIO_SUBTYPE_INFO) { 4238 if (tagp->vio_subtype_env == VIO_DRING_DATA) { 4239 dmsg = (vio_dring_msg_t *)tagp; 4240 dmsg->seq_num = ldcp->next_txseq; 4241 data_msg = B_TRUE; 4242 } else if (tagp->vio_subtype_env == VIO_PKT_DATA) { 4243 rmsg = (vio_raw_data_msg_t *)tagp; 4244 rmsg->seq_num = ldcp->next_txseq; 4245 data_msg = B_TRUE; 4246 } 4247 } 4248 4249 do { 4250 len = msglen; 4251 rv = ldc_write(ldcp->ldc_handle, (caddr_t)msg, &len); 4252 if (retries++ >= vgen_ldcwr_retries) 4253 break; 4254 } while (rv == EWOULDBLOCK); 4255 4256 if (rv == 0 && data_msg == B_TRUE) { 4257 ldcp->next_txseq++; 4258 } 4259 4260 if (!caller_holds_lock) { 4261 mutex_exit(&ldcp->wrlock); 4262 } 4263 4264 if (rv != 0) { 4265 DWARN(vgenp, ldcp, "ldc_write failed: rv(%d)\n", 4266 rv, msglen); 4267 return (rv); 4268 } 4269 4270 if (len != msglen) { 4271 DWARN(vgenp, ldcp, "ldc_write failed: rv(%d) msglen (%d)\n", 4272 rv, msglen); 4273 return (VGEN_FAILURE); 4274 } 4275 4276 return (VGEN_SUCCESS); 4277 } 4278 4279 /* send version negotiate message to the peer over ldc */ 4280 static int 4281 vgen_send_version_negotiate(vgen_ldc_t *ldcp) 4282 { 4283 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4284 vio_ver_msg_t vermsg; 4285 vio_msg_tag_t *tagp = &vermsg.tag; 4286 int rv; 4287 4288 bzero(&vermsg, sizeof (vermsg)); 4289 4290 tagp->vio_msgtype = VIO_TYPE_CTRL; 4291 tagp->vio_subtype = VIO_SUBTYPE_INFO; 4292 tagp->vio_subtype_env = VIO_VER_INFO; 4293 tagp->vio_sid = ldcp->local_sid; 4294 4295 /* get version msg payload from ldcp->local */ 4296 vermsg.ver_major = ldcp->local_hparams.ver_major; 4297 vermsg.ver_minor = ldcp->local_hparams.ver_minor; 4298 vermsg.dev_class = ldcp->local_hparams.dev_class; 4299 4300 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (vermsg), B_FALSE); 4301 if (rv != VGEN_SUCCESS) { 4302 DWARN(vgenp, ldcp, "vgen_sendmsg failed\n"); 4303 return (rv); 4304 } 4305 4306 ldcp->hstate |= VER_INFO_SENT; 4307 DBG2(vgenp, ldcp, "VER_INFO_SENT ver(%d,%d)\n", 4308 vermsg.ver_major, vermsg.ver_minor); 4309 4310 return (VGEN_SUCCESS); 4311 } 4312 4313 /* send attr info message to the peer over ldc */ 4314 static int 4315 vgen_send_attr_info(vgen_ldc_t *ldcp) 4316 { 4317 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4318 vnet_attr_msg_t attrmsg; 4319 vio_msg_tag_t *tagp = &attrmsg.tag; 4320 int rv; 4321 4322 bzero(&attrmsg, sizeof (attrmsg)); 4323 4324 tagp->vio_msgtype = VIO_TYPE_CTRL; 4325 tagp->vio_subtype = VIO_SUBTYPE_INFO; 4326 tagp->vio_subtype_env = VIO_ATTR_INFO; 4327 tagp->vio_sid = ldcp->local_sid; 4328 4329 /* get attr msg payload from ldcp->local */ 4330 attrmsg.mtu = ldcp->local_hparams.mtu; 4331 attrmsg.addr = ldcp->local_hparams.addr; 4332 attrmsg.addr_type = ldcp->local_hparams.addr_type; 4333 attrmsg.xfer_mode = ldcp->local_hparams.xfer_mode; 4334 attrmsg.ack_freq = ldcp->local_hparams.ack_freq; 4335 attrmsg.physlink_update = ldcp->local_hparams.physlink_update; 4336 4337 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (attrmsg), B_FALSE); 4338 if (rv != VGEN_SUCCESS) { 4339 DWARN(vgenp, ldcp, "vgen_sendmsg failed\n"); 4340 return (rv); 4341 } 4342 4343 ldcp->hstate |= ATTR_INFO_SENT; 4344 DBG2(vgenp, ldcp, "ATTR_INFO_SENT\n"); 4345 4346 return (VGEN_SUCCESS); 4347 } 4348 4349 /* send descriptor ring register message to the peer over ldc */ 4350 static int 4351 vgen_send_dring_reg(vgen_ldc_t *ldcp) 4352 { 4353 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4354 vio_dring_reg_msg_t msg; 4355 vio_msg_tag_t *tagp = &msg.tag; 4356 int rv; 4357 4358 bzero(&msg, sizeof (msg)); 4359 4360 tagp->vio_msgtype = VIO_TYPE_CTRL; 4361 tagp->vio_subtype = VIO_SUBTYPE_INFO; 4362 tagp->vio_subtype_env = VIO_DRING_REG; 4363 tagp->vio_sid = ldcp->local_sid; 4364 4365 /* get dring info msg payload from ldcp->local */ 4366 bcopy(&(ldcp->local_hparams.dring_cookie), (msg.cookie), 4367 sizeof (ldc_mem_cookie_t)); 4368 msg.ncookies = ldcp->local_hparams.num_dcookies; 4369 msg.num_descriptors = ldcp->local_hparams.num_desc; 4370 msg.descriptor_size = ldcp->local_hparams.desc_size; 4371 4372 /* 4373 * dring_ident is set to 0. After mapping the dring, peer sets this 4374 * value and sends it in the ack, which is saved in 4375 * vgen_handle_dring_reg(). 4376 */ 4377 msg.dring_ident = 0; 4378 4379 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (msg), B_FALSE); 4380 if (rv != VGEN_SUCCESS) { 4381 DWARN(vgenp, ldcp, "vgen_sendmsg failed\n"); 4382 return (rv); 4383 } 4384 4385 ldcp->hstate |= DRING_INFO_SENT; 4386 DBG2(vgenp, ldcp, "DRING_INFO_SENT \n"); 4387 4388 return (VGEN_SUCCESS); 4389 } 4390 4391 static int 4392 vgen_send_rdx_info(vgen_ldc_t *ldcp) 4393 { 4394 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4395 vio_rdx_msg_t rdxmsg; 4396 vio_msg_tag_t *tagp = &rdxmsg.tag; 4397 int rv; 4398 4399 bzero(&rdxmsg, sizeof (rdxmsg)); 4400 4401 tagp->vio_msgtype = VIO_TYPE_CTRL; 4402 tagp->vio_subtype = VIO_SUBTYPE_INFO; 4403 tagp->vio_subtype_env = VIO_RDX; 4404 tagp->vio_sid = ldcp->local_sid; 4405 4406 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (rdxmsg), B_FALSE); 4407 if (rv != VGEN_SUCCESS) { 4408 DWARN(vgenp, ldcp, "vgen_sendmsg failed\n"); 4409 return (rv); 4410 } 4411 4412 ldcp->hstate |= RDX_INFO_SENT; 4413 DBG2(vgenp, ldcp, "RDX_INFO_SENT\n"); 4414 4415 return (VGEN_SUCCESS); 4416 } 4417 4418 /* send descriptor ring data message to the peer over ldc */ 4419 static int 4420 vgen_send_dring_data(vgen_ldc_t *ldcp, uint32_t start, int32_t end) 4421 { 4422 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4423 vio_dring_msg_t dringmsg, *msgp = &dringmsg; 4424 vio_msg_tag_t *tagp = &msgp->tag; 4425 vgen_stats_t *statsp = &ldcp->stats; 4426 int rv; 4427 4428 bzero(msgp, sizeof (*msgp)); 4429 4430 tagp->vio_msgtype = VIO_TYPE_DATA; 4431 tagp->vio_subtype = VIO_SUBTYPE_INFO; 4432 tagp->vio_subtype_env = VIO_DRING_DATA; 4433 tagp->vio_sid = ldcp->local_sid; 4434 4435 msgp->dring_ident = ldcp->local_hparams.dring_ident; 4436 msgp->start_idx = start; 4437 msgp->end_idx = end; 4438 4439 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (dringmsg), B_TRUE); 4440 if (rv != VGEN_SUCCESS) { 4441 DWARN(vgenp, ldcp, "vgen_sendmsg failed\n"); 4442 return (rv); 4443 } 4444 4445 statsp->dring_data_msgs++; 4446 4447 DBG2(vgenp, ldcp, "DRING_DATA_SENT \n"); 4448 4449 return (VGEN_SUCCESS); 4450 } 4451 4452 /* send multicast addr info message to vsw */ 4453 static int 4454 vgen_send_mcast_info(vgen_ldc_t *ldcp) 4455 { 4456 vnet_mcast_msg_t mcastmsg; 4457 vnet_mcast_msg_t *msgp; 4458 vio_msg_tag_t *tagp; 4459 vgen_t *vgenp; 4460 struct ether_addr *mca; 4461 int rv; 4462 int i; 4463 uint32_t size; 4464 uint32_t mccount; 4465 uint32_t n; 4466 4467 msgp = &mcastmsg; 4468 tagp = &msgp->tag; 4469 vgenp = LDC_TO_VGEN(ldcp); 4470 4471 mccount = vgenp->mccount; 4472 i = 0; 4473 4474 do { 4475 tagp->vio_msgtype = VIO_TYPE_CTRL; 4476 tagp->vio_subtype = VIO_SUBTYPE_INFO; 4477 tagp->vio_subtype_env = VNET_MCAST_INFO; 4478 tagp->vio_sid = ldcp->local_sid; 4479 4480 n = ((mccount >= VNET_NUM_MCAST) ? VNET_NUM_MCAST : mccount); 4481 size = n * sizeof (struct ether_addr); 4482 4483 mca = &(vgenp->mctab[i]); 4484 bcopy(mca, (msgp->mca), size); 4485 msgp->set = B_TRUE; 4486 msgp->count = n; 4487 4488 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msgp), 4489 B_FALSE); 4490 if (rv != VGEN_SUCCESS) { 4491 DWARN(vgenp, ldcp, "vgen_sendmsg err(%d)\n", rv); 4492 return (rv); 4493 } 4494 4495 mccount -= n; 4496 i += n; 4497 4498 } while (mccount); 4499 4500 return (VGEN_SUCCESS); 4501 } 4502 4503 /* Initiate Phase 2 of handshake */ 4504 static int 4505 vgen_handshake_phase2(vgen_ldc_t *ldcp) 4506 { 4507 int rv; 4508 uint32_t ncookies = 0; 4509 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4510 4511 #ifdef DEBUG 4512 if (vgen_hdbg & HDBG_OUT_STATE) { 4513 /* simulate out of state condition */ 4514 vgen_hdbg &= ~(HDBG_OUT_STATE); 4515 rv = vgen_send_rdx_info(ldcp); 4516 return (rv); 4517 } 4518 if (vgen_hdbg & HDBG_TIMEOUT) { 4519 /* simulate timeout condition */ 4520 vgen_hdbg &= ~(HDBG_TIMEOUT); 4521 return (VGEN_SUCCESS); 4522 } 4523 #endif 4524 rv = vgen_send_attr_info(ldcp); 4525 if (rv != VGEN_SUCCESS) { 4526 return (rv); 4527 } 4528 4529 /* Bind descriptor ring to the channel */ 4530 if (ldcp->num_txdcookies == 0) { 4531 rv = ldc_mem_dring_bind(ldcp->ldc_handle, ldcp->tx_dhandle, 4532 LDC_DIRECT_MAP | LDC_SHADOW_MAP, LDC_MEM_RW, 4533 &ldcp->tx_dcookie, &ncookies); 4534 if (rv != 0) { 4535 DWARN(vgenp, ldcp, "ldc_mem_dring_bind failed " 4536 "rv(%x)\n", rv); 4537 return (rv); 4538 } 4539 ASSERT(ncookies == 1); 4540 ldcp->num_txdcookies = ncookies; 4541 } 4542 4543 /* update local dring_info params */ 4544 bcopy(&(ldcp->tx_dcookie), &(ldcp->local_hparams.dring_cookie), 4545 sizeof (ldc_mem_cookie_t)); 4546 ldcp->local_hparams.num_dcookies = ldcp->num_txdcookies; 4547 ldcp->local_hparams.num_desc = ldcp->num_txds; 4548 ldcp->local_hparams.desc_size = sizeof (vnet_public_desc_t); 4549 4550 rv = vgen_send_dring_reg(ldcp); 4551 if (rv != VGEN_SUCCESS) { 4552 return (rv); 4553 } 4554 4555 return (VGEN_SUCCESS); 4556 } 4557 4558 /* 4559 * Set vnet-protocol-version dependent functions based on version. 4560 */ 4561 static void 4562 vgen_set_vnet_proto_ops(vgen_ldc_t *ldcp) 4563 { 4564 vgen_hparams_t *lp = &ldcp->local_hparams; 4565 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4566 4567 if (VGEN_VER_GTEQ(ldcp, 1, 5)) { 4568 vgen_port_t *portp = ldcp->portp; 4569 vnet_t *vnetp = vgenp->vnetp; 4570 /* 4571 * If the version negotiated with vswitch is >= 1.5 (link 4572 * status update support), set the required bits in our 4573 * attributes if this vnet device has been configured to get 4574 * physical link state updates. 4575 */ 4576 if (portp == vgenp->vsw_portp && vnetp->pls_update == B_TRUE) { 4577 lp->physlink_update = PHYSLINK_UPDATE_STATE; 4578 } else { 4579 lp->physlink_update = PHYSLINK_UPDATE_NONE; 4580 } 4581 } 4582 4583 if (VGEN_VER_GTEQ(ldcp, 1, 4)) { 4584 /* 4585 * If the version negotiated with peer is >= 1.4(Jumbo Frame 4586 * Support), set the mtu in our attributes to max_frame_size. 4587 */ 4588 lp->mtu = vgenp->max_frame_size; 4589 } else if (VGEN_VER_EQ(ldcp, 1, 3)) { 4590 /* 4591 * If the version negotiated with peer is == 1.3 (Vlan Tag 4592 * Support) set the attr.mtu to ETHERMAX + VLAN_TAGSZ. 4593 */ 4594 lp->mtu = ETHERMAX + VLAN_TAGSZ; 4595 } else { 4596 vgen_port_t *portp = ldcp->portp; 4597 vnet_t *vnetp = vgenp->vnetp; 4598 /* 4599 * Pre-1.3 peers expect max frame size of ETHERMAX. 4600 * We can negotiate that size with those peers provided the 4601 * following conditions are true: 4602 * - Only pvid is defined for our peer and there are no vids. 4603 * - pvids are equal. 4604 * If the above conditions are true, then we can send/recv only 4605 * untagged frames of max size ETHERMAX. 4606 */ 4607 if (portp->nvids == 0 && portp->pvid == vnetp->pvid) { 4608 lp->mtu = ETHERMAX; 4609 } 4610 } 4611 4612 if (VGEN_VER_GTEQ(ldcp, 1, 2)) { 4613 /* Versions >= 1.2 */ 4614 4615 if (VGEN_PRI_ETH_DEFINED(vgenp)) { 4616 /* 4617 * enable priority routines and pkt mode only if 4618 * at least one pri-eth-type is specified in MD. 4619 */ 4620 4621 ldcp->tx = vgen_ldcsend; 4622 ldcp->rx_pktdata = vgen_handle_pkt_data; 4623 4624 /* set xfer mode for vgen_send_attr_info() */ 4625 lp->xfer_mode = VIO_PKT_MODE | VIO_DRING_MODE_V1_2; 4626 4627 } else { 4628 /* no priority eth types defined in MD */ 4629 4630 ldcp->tx = vgen_ldcsend_dring; 4631 ldcp->rx_pktdata = vgen_handle_pkt_data_nop; 4632 4633 /* set xfer mode for vgen_send_attr_info() */ 4634 lp->xfer_mode = VIO_DRING_MODE_V1_2; 4635 4636 } 4637 } else { 4638 /* Versions prior to 1.2 */ 4639 4640 vgen_reset_vnet_proto_ops(ldcp); 4641 } 4642 } 4643 4644 /* 4645 * Reset vnet-protocol-version dependent functions to pre-v1.2. 4646 */ 4647 static void 4648 vgen_reset_vnet_proto_ops(vgen_ldc_t *ldcp) 4649 { 4650 vgen_hparams_t *lp = &ldcp->local_hparams; 4651 4652 ldcp->tx = vgen_ldcsend_dring; 4653 ldcp->rx_pktdata = vgen_handle_pkt_data_nop; 4654 4655 /* set xfer mode for vgen_send_attr_info() */ 4656 lp->xfer_mode = VIO_DRING_MODE_V1_0; 4657 } 4658 4659 static void 4660 vgen_vlan_unaware_port_reset(vgen_port_t *portp) 4661 { 4662 vgen_ldclist_t *ldclp; 4663 vgen_ldc_t *ldcp; 4664 vgen_t *vgenp = portp->vgenp; 4665 vnet_t *vnetp = vgenp->vnetp; 4666 4667 ldclp = &portp->ldclist; 4668 4669 READ_ENTER(&ldclp->rwlock); 4670 4671 /* 4672 * NOTE: for now, we will assume we have a single channel. 4673 */ 4674 if (ldclp->headp == NULL) { 4675 RW_EXIT(&ldclp->rwlock); 4676 return; 4677 } 4678 ldcp = ldclp->headp; 4679 4680 mutex_enter(&ldcp->cblock); 4681 4682 /* 4683 * If the peer is vlan_unaware(ver < 1.3), reset channel and terminate 4684 * the connection. See comments in vgen_set_vnet_proto_ops(). 4685 */ 4686 if (ldcp->hphase == VH_DONE && VGEN_VER_LT(ldcp, 1, 3) && 4687 (portp->nvids != 0 || portp->pvid != vnetp->pvid)) { 4688 vgen_ldc_reset(ldcp); 4689 } 4690 4691 mutex_exit(&ldcp->cblock); 4692 4693 RW_EXIT(&ldclp->rwlock); 4694 } 4695 4696 static void 4697 vgen_port_reset(vgen_port_t *portp) 4698 { 4699 vgen_ldclist_t *ldclp; 4700 vgen_ldc_t *ldcp; 4701 4702 ldclp = &portp->ldclist; 4703 4704 READ_ENTER(&ldclp->rwlock); 4705 4706 /* 4707 * NOTE: for now, we will assume we have a single channel. 4708 */ 4709 if (ldclp->headp == NULL) { 4710 RW_EXIT(&ldclp->rwlock); 4711 return; 4712 } 4713 ldcp = ldclp->headp; 4714 4715 mutex_enter(&ldcp->cblock); 4716 4717 vgen_ldc_reset(ldcp); 4718 4719 mutex_exit(&ldcp->cblock); 4720 4721 RW_EXIT(&ldclp->rwlock); 4722 } 4723 4724 static void 4725 vgen_reset_vlan_unaware_ports(vgen_t *vgenp) 4726 { 4727 vgen_port_t *portp; 4728 vgen_portlist_t *plistp; 4729 4730 plistp = &(vgenp->vgenports); 4731 READ_ENTER(&plistp->rwlock); 4732 4733 for (portp = plistp->headp; portp != NULL; portp = portp->nextp) { 4734 4735 vgen_vlan_unaware_port_reset(portp); 4736 4737 } 4738 4739 RW_EXIT(&plistp->rwlock); 4740 } 4741 4742 static void 4743 vgen_reset_vsw_port(vgen_t *vgenp) 4744 { 4745 vgen_port_t *portp; 4746 4747 if ((portp = vgenp->vsw_portp) != NULL) { 4748 vgen_port_reset(portp); 4749 } 4750 } 4751 4752 /* 4753 * This function resets the handshake phase to VH_PHASE0(pre-handshake phase). 4754 * This can happen after a channel comes up (status: LDC_UP) or 4755 * when handshake gets terminated due to various conditions. 4756 */ 4757 static void 4758 vgen_reset_hphase(vgen_ldc_t *ldcp) 4759 { 4760 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4761 ldc_status_t istatus; 4762 int rv; 4763 4764 DBG1(vgenp, ldcp, "enter\n"); 4765 /* reset hstate and hphase */ 4766 ldcp->hstate = 0; 4767 ldcp->hphase = VH_PHASE0; 4768 4769 vgen_reset_vnet_proto_ops(ldcp); 4770 4771 /* 4772 * Save the id of pending handshake timer in cancel_htid. 4773 * This will be checked in vgen_ldc_cb() and the handshake timer will 4774 * be cancelled after releasing cblock. 4775 */ 4776 if (ldcp->htid) { 4777 ldcp->cancel_htid = ldcp->htid; 4778 ldcp->htid = 0; 4779 } 4780 4781 if (ldcp->local_hparams.dring_ready) { 4782 ldcp->local_hparams.dring_ready = B_FALSE; 4783 } 4784 4785 /* Unbind tx descriptor ring from the channel */ 4786 if (ldcp->num_txdcookies) { 4787 rv = ldc_mem_dring_unbind(ldcp->tx_dhandle); 4788 if (rv != 0) { 4789 DWARN(vgenp, ldcp, "ldc_mem_dring_unbind failed\n"); 4790 } 4791 ldcp->num_txdcookies = 0; 4792 } 4793 4794 if (ldcp->peer_hparams.dring_ready) { 4795 ldcp->peer_hparams.dring_ready = B_FALSE; 4796 /* Unmap peer's dring */ 4797 (void) ldc_mem_dring_unmap(ldcp->rx_dhandle); 4798 vgen_clobber_rxds(ldcp); 4799 } 4800 4801 vgen_clobber_tbufs(ldcp); 4802 4803 /* 4804 * clear local handshake params and initialize. 4805 */ 4806 bzero(&(ldcp->local_hparams), sizeof (ldcp->local_hparams)); 4807 4808 /* set version to the highest version supported */ 4809 ldcp->local_hparams.ver_major = 4810 ldcp->vgen_versions[0].ver_major; 4811 ldcp->local_hparams.ver_minor = 4812 ldcp->vgen_versions[0].ver_minor; 4813 ldcp->local_hparams.dev_class = VDEV_NETWORK; 4814 4815 /* set attr_info params */ 4816 ldcp->local_hparams.mtu = vgenp->max_frame_size; 4817 ldcp->local_hparams.addr = 4818 vnet_macaddr_strtoul(vgenp->macaddr); 4819 ldcp->local_hparams.addr_type = ADDR_TYPE_MAC; 4820 ldcp->local_hparams.xfer_mode = VIO_DRING_MODE_V1_0; 4821 ldcp->local_hparams.ack_freq = 0; /* don't need acks */ 4822 ldcp->local_hparams.physlink_update = PHYSLINK_UPDATE_NONE; 4823 4824 /* 4825 * Note: dring is created, but not bound yet. 4826 * local dring_info params will be updated when we bind the dring in 4827 * vgen_handshake_phase2(). 4828 * dring_ident is set to 0. After mapping the dring, peer sets this 4829 * value and sends it in the ack, which is saved in 4830 * vgen_handle_dring_reg(). 4831 */ 4832 ldcp->local_hparams.dring_ident = 0; 4833 4834 /* clear peer_hparams */ 4835 bzero(&(ldcp->peer_hparams), sizeof (ldcp->peer_hparams)); 4836 4837 /* reset the channel if required */ 4838 #ifdef VNET_IOC_DEBUG 4839 if (ldcp->need_ldc_reset && !ldcp->link_down_forced) { 4840 #else 4841 if (ldcp->need_ldc_reset) { 4842 #endif 4843 DWARN(vgenp, ldcp, "Doing Channel Reset...\n"); 4844 ldcp->need_ldc_reset = B_FALSE; 4845 (void) ldc_down(ldcp->ldc_handle); 4846 (void) ldc_status(ldcp->ldc_handle, &istatus); 4847 DBG2(vgenp, ldcp, "Reset Done,ldc_status(%x)\n", istatus); 4848 ldcp->ldc_status = istatus; 4849 4850 /* clear sids */ 4851 ldcp->local_sid = 0; 4852 ldcp->peer_sid = 0; 4853 4854 /* try to bring the channel up */ 4855 rv = ldc_up(ldcp->ldc_handle); 4856 if (rv != 0) { 4857 DWARN(vgenp, ldcp, "ldc_up err rv(%d)\n", rv); 4858 } 4859 4860 if (ldc_status(ldcp->ldc_handle, &istatus) != 0) { 4861 DWARN(vgenp, ldcp, "ldc_status err\n"); 4862 } else { 4863 ldcp->ldc_status = istatus; 4864 } 4865 } 4866 } 4867 4868 /* wrapper function for vgen_reset_hphase */ 4869 static void 4870 vgen_handshake_reset(vgen_ldc_t *ldcp) 4871 { 4872 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4873 4874 ASSERT(MUTEX_HELD(&ldcp->cblock)); 4875 mutex_enter(&ldcp->rxlock); 4876 mutex_enter(&ldcp->wrlock); 4877 mutex_enter(&ldcp->txlock); 4878 mutex_enter(&ldcp->tclock); 4879 4880 vgen_reset_hphase(ldcp); 4881 4882 mutex_exit(&ldcp->tclock); 4883 mutex_exit(&ldcp->txlock); 4884 mutex_exit(&ldcp->wrlock); 4885 mutex_exit(&ldcp->rxlock); 4886 4887 /* 4888 * As the connection is now reset, mark the channel 4889 * link_state as 'down' and notify the stack if needed. 4890 */ 4891 if (ldcp->link_state != LINK_STATE_DOWN) { 4892 ldcp->link_state = LINK_STATE_DOWN; 4893 4894 if (ldcp->portp == vgenp->vsw_portp) { /* vswitch port ? */ 4895 /* 4896 * As the channel link is down, mark physical link also 4897 * as down. After the channel comes back up and 4898 * handshake completes, we will get an update on the 4899 * physlink state from vswitch (if this device has been 4900 * configured to get phys link updates). 4901 */ 4902 vgenp->phys_link_state = LINK_STATE_DOWN; 4903 4904 /* Now update the stack */ 4905 mutex_exit(&ldcp->cblock); 4906 vgen_link_update(vgenp, ldcp->link_state); 4907 mutex_enter(&ldcp->cblock); 4908 } 4909 } 4910 } 4911 4912 /* 4913 * Initiate handshake with the peer by sending various messages 4914 * based on the handshake-phase that the channel is currently in. 4915 */ 4916 static void 4917 vgen_handshake(vgen_ldc_t *ldcp) 4918 { 4919 uint32_t hphase = ldcp->hphase; 4920 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4921 ldc_status_t istatus; 4922 int rv = 0; 4923 4924 switch (hphase) { 4925 4926 case VH_PHASE1: 4927 4928 /* 4929 * start timer, for entire handshake process, turn this timer 4930 * off if all phases of handshake complete successfully and 4931 * hphase goes to VH_DONE(below) or 4932 * vgen_reset_hphase() gets called or 4933 * channel is reset due to errors or 4934 * vgen_ldc_uninit() is invoked(vgen_stop). 4935 */ 4936 ASSERT(ldcp->htid == 0); 4937 ldcp->htid = timeout(vgen_hwatchdog, (caddr_t)ldcp, 4938 drv_usectohz(vgen_hwd_interval * MICROSEC)); 4939 4940 /* Phase 1 involves negotiating the version */ 4941 rv = vgen_send_version_negotiate(ldcp); 4942 break; 4943 4944 case VH_PHASE2: 4945 rv = vgen_handshake_phase2(ldcp); 4946 break; 4947 4948 case VH_PHASE3: 4949 rv = vgen_send_rdx_info(ldcp); 4950 break; 4951 4952 case VH_DONE: 4953 /* 4954 * Save the id of pending handshake timer in cancel_htid. 4955 * This will be checked in vgen_ldc_cb() and the handshake 4956 * timer will be cancelled after releasing cblock. 4957 */ 4958 if (ldcp->htid) { 4959 ldcp->cancel_htid = ldcp->htid; 4960 ldcp->htid = 0; 4961 } 4962 ldcp->hretries = 0; 4963 DBG1(vgenp, ldcp, "Handshake Done\n"); 4964 4965 /* 4966 * The channel is up and handshake is done successfully. Now we 4967 * can mark the channel link_state as 'up'. We also notify the 4968 * stack if the channel is connected to vswitch. 4969 */ 4970 ldcp->link_state = LINK_STATE_UP; 4971 4972 if (ldcp->portp == vgenp->vsw_portp) { 4973 /* 4974 * If this channel(port) is connected to vsw, 4975 * need to sync multicast table with vsw. 4976 */ 4977 mutex_exit(&ldcp->cblock); 4978 4979 mutex_enter(&vgenp->lock); 4980 rv = vgen_send_mcast_info(ldcp); 4981 mutex_exit(&vgenp->lock); 4982 4983 if (vgenp->pls_negotiated == B_FALSE) { 4984 /* 4985 * We haven't negotiated with vswitch to get 4986 * physical link state updates. We can update 4987 * update the stack at this point as the 4988 * channel to vswitch is up and the handshake 4989 * is done successfully. 4990 * 4991 * If we have negotiated to get physical link 4992 * state updates, then we won't notify the 4993 * the stack here; we do that as soon as 4994 * vswitch sends us the initial phys link state 4995 * (see vgen_handle_physlink_info()). 4996 */ 4997 vgen_link_update(vgenp, ldcp->link_state); 4998 } 4999 5000 mutex_enter(&ldcp->cblock); 5001 if (rv != VGEN_SUCCESS) 5002 break; 5003 } 5004 5005 /* 5006 * Check if mac layer should be notified to restart 5007 * transmissions. This can happen if the channel got 5008 * reset and vgen_clobber_tbufs() is called, while 5009 * need_resched is set. 5010 */ 5011 mutex_enter(&ldcp->tclock); 5012 if (ldcp->need_resched) { 5013 vio_net_tx_update_t vtx_update = 5014 ldcp->portp->vcb.vio_net_tx_update; 5015 5016 ldcp->need_resched = B_FALSE; 5017 vtx_update(ldcp->portp->vhp); 5018 } 5019 mutex_exit(&ldcp->tclock); 5020 5021 break; 5022 5023 default: 5024 break; 5025 } 5026 5027 if (rv == ECONNRESET) { 5028 if (ldc_status(ldcp->ldc_handle, &istatus) != 0) { 5029 DWARN(vgenp, ldcp, "ldc_status err\n"); 5030 } else { 5031 ldcp->ldc_status = istatus; 5032 } 5033 vgen_handle_evt_reset(ldcp); 5034 } else if (rv) { 5035 vgen_handshake_reset(ldcp); 5036 } 5037 } 5038 5039 /* 5040 * Check if the current handshake phase has completed successfully and 5041 * return the status. 5042 */ 5043 static int 5044 vgen_handshake_done(vgen_ldc_t *ldcp) 5045 { 5046 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5047 uint32_t hphase = ldcp->hphase; 5048 int status = 0; 5049 5050 switch (hphase) { 5051 5052 case VH_PHASE1: 5053 /* 5054 * Phase1 is done, if version negotiation 5055 * completed successfully. 5056 */ 5057 status = ((ldcp->hstate & VER_NEGOTIATED) == 5058 VER_NEGOTIATED); 5059 break; 5060 5061 case VH_PHASE2: 5062 /* 5063 * Phase 2 is done, if attr info and dring info 5064 * have been exchanged successfully. 5065 */ 5066 status = (((ldcp->hstate & ATTR_INFO_EXCHANGED) == 5067 ATTR_INFO_EXCHANGED) && 5068 ((ldcp->hstate & DRING_INFO_EXCHANGED) == 5069 DRING_INFO_EXCHANGED)); 5070 break; 5071 5072 case VH_PHASE3: 5073 /* Phase 3 is done, if rdx msg has been exchanged */ 5074 status = ((ldcp->hstate & RDX_EXCHANGED) == 5075 RDX_EXCHANGED); 5076 break; 5077 5078 default: 5079 break; 5080 } 5081 5082 if (status == 0) { 5083 return (VGEN_FAILURE); 5084 } 5085 DBG2(vgenp, ldcp, "PHASE(%d)\n", hphase); 5086 return (VGEN_SUCCESS); 5087 } 5088 5089 /* retry handshake on failure */ 5090 static void 5091 vgen_handshake_retry(vgen_ldc_t *ldcp) 5092 { 5093 /* reset handshake phase */ 5094 vgen_handshake_reset(ldcp); 5095 5096 /* handshake retry is specified and the channel is UP */ 5097 if (vgen_max_hretries && (ldcp->ldc_status == LDC_UP)) { 5098 if (ldcp->hretries++ < vgen_max_hretries) { 5099 ldcp->local_sid = ddi_get_lbolt(); 5100 vgen_handshake(vh_nextphase(ldcp)); 5101 } 5102 } 5103 } 5104 5105 5106 /* 5107 * Link State Update Notes: 5108 * The link state of the channel connected to vswitch is reported as the link 5109 * state of the vnet device, by default. If the channel is down or reset, then 5110 * the link state is marked 'down'. If the channel is 'up' *and* handshake 5111 * between the vnet and vswitch is successful, then the link state is marked 5112 * 'up'. If physical network link state is desired, then the vnet device must 5113 * be configured to get physical link updates and the 'linkprop' property 5114 * in the virtual-device MD node indicates this. As part of attribute exchange 5115 * the vnet device negotiates with the vswitch to obtain physical link state 5116 * updates. If it successfully negotiates, vswitch sends an initial physlink 5117 * msg once the handshake is done and further whenever the physical link state 5118 * changes. Currently we don't have mac layer interfaces to report two distinct 5119 * link states - virtual and physical. Thus, if the vnet has been configured to 5120 * get physical link updates, then the link status will be reported as 'up' 5121 * only when both the virtual and physical links are up. 5122 */ 5123 static void 5124 vgen_link_update(vgen_t *vgenp, link_state_t link_state) 5125 { 5126 vnet_link_update(vgenp->vnetp, link_state); 5127 } 5128 5129 /* 5130 * Handle a version info msg from the peer or an ACK/NACK from the peer 5131 * to a version info msg that we sent. 5132 */ 5133 static int 5134 vgen_handle_version_negotiate(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 5135 { 5136 vgen_t *vgenp; 5137 vio_ver_msg_t *vermsg = (vio_ver_msg_t *)tagp; 5138 int ack = 0; 5139 int failed = 0; 5140 int idx; 5141 vgen_ver_t *versions = ldcp->vgen_versions; 5142 int rv = 0; 5143 5144 vgenp = LDC_TO_VGEN(ldcp); 5145 DBG1(vgenp, ldcp, "enter\n"); 5146 switch (tagp->vio_subtype) { 5147 case VIO_SUBTYPE_INFO: 5148 5149 /* Cache sid of peer if this is the first time */ 5150 if (ldcp->peer_sid == 0) { 5151 DBG2(vgenp, ldcp, "Caching peer_sid(%x)\n", 5152 tagp->vio_sid); 5153 ldcp->peer_sid = tagp->vio_sid; 5154 } 5155 5156 if (ldcp->hphase != VH_PHASE1) { 5157 /* 5158 * If we are not already in VH_PHASE1, reset to 5159 * pre-handshake state, and initiate handshake 5160 * to the peer too. 5161 */ 5162 vgen_handshake_reset(ldcp); 5163 vgen_handshake(vh_nextphase(ldcp)); 5164 } 5165 ldcp->hstate |= VER_INFO_RCVD; 5166 5167 /* save peer's requested values */ 5168 ldcp->peer_hparams.ver_major = vermsg->ver_major; 5169 ldcp->peer_hparams.ver_minor = vermsg->ver_minor; 5170 ldcp->peer_hparams.dev_class = vermsg->dev_class; 5171 5172 if ((vermsg->dev_class != VDEV_NETWORK) && 5173 (vermsg->dev_class != VDEV_NETWORK_SWITCH)) { 5174 /* unsupported dev_class, send NACK */ 5175 5176 DWARN(vgenp, ldcp, "Version Negotiation Failed\n"); 5177 5178 tagp->vio_subtype = VIO_SUBTYPE_NACK; 5179 tagp->vio_sid = ldcp->local_sid; 5180 /* send reply msg back to peer */ 5181 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, 5182 sizeof (*vermsg), B_FALSE); 5183 if (rv != VGEN_SUCCESS) { 5184 return (rv); 5185 } 5186 return (VGEN_FAILURE); 5187 } 5188 5189 DBG2(vgenp, ldcp, "VER_INFO_RCVD, ver(%d,%d)\n", 5190 vermsg->ver_major, vermsg->ver_minor); 5191 5192 idx = 0; 5193 5194 for (;;) { 5195 5196 if (vermsg->ver_major > versions[idx].ver_major) { 5197 5198 /* nack with next lower version */ 5199 tagp->vio_subtype = VIO_SUBTYPE_NACK; 5200 vermsg->ver_major = versions[idx].ver_major; 5201 vermsg->ver_minor = versions[idx].ver_minor; 5202 break; 5203 } 5204 5205 if (vermsg->ver_major == versions[idx].ver_major) { 5206 5207 /* major version match - ACK version */ 5208 tagp->vio_subtype = VIO_SUBTYPE_ACK; 5209 ack = 1; 5210 5211 /* 5212 * lower minor version to the one this endpt 5213 * supports, if necessary 5214 */ 5215 if (vermsg->ver_minor > 5216 versions[idx].ver_minor) { 5217 vermsg->ver_minor = 5218 versions[idx].ver_minor; 5219 ldcp->peer_hparams.ver_minor = 5220 versions[idx].ver_minor; 5221 } 5222 break; 5223 } 5224 5225 idx++; 5226 5227 if (idx == VGEN_NUM_VER) { 5228 5229 /* no version match - send NACK */ 5230 tagp->vio_subtype = VIO_SUBTYPE_NACK; 5231 vermsg->ver_major = 0; 5232 vermsg->ver_minor = 0; 5233 failed = 1; 5234 break; 5235 } 5236 5237 } 5238 5239 tagp->vio_sid = ldcp->local_sid; 5240 5241 /* send reply msg back to peer */ 5242 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*vermsg), 5243 B_FALSE); 5244 if (rv != VGEN_SUCCESS) { 5245 return (rv); 5246 } 5247 5248 if (ack) { 5249 ldcp->hstate |= VER_ACK_SENT; 5250 DBG2(vgenp, ldcp, "VER_ACK_SENT, ver(%d,%d) \n", 5251 vermsg->ver_major, vermsg->ver_minor); 5252 } 5253 if (failed) { 5254 DWARN(vgenp, ldcp, "Negotiation Failed\n"); 5255 return (VGEN_FAILURE); 5256 } 5257 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 5258 5259 /* VER_ACK_SENT and VER_ACK_RCVD */ 5260 5261 /* local and peer versions match? */ 5262 ASSERT((ldcp->local_hparams.ver_major == 5263 ldcp->peer_hparams.ver_major) && 5264 (ldcp->local_hparams.ver_minor == 5265 ldcp->peer_hparams.ver_minor)); 5266 5267 vgen_set_vnet_proto_ops(ldcp); 5268 5269 /* move to the next phase */ 5270 vgen_handshake(vh_nextphase(ldcp)); 5271 } 5272 5273 break; 5274 5275 case VIO_SUBTYPE_ACK: 5276 5277 if (ldcp->hphase != VH_PHASE1) { 5278 /* This should not happen. */ 5279 DWARN(vgenp, ldcp, "Invalid Phase(%u)\n", ldcp->hphase); 5280 return (VGEN_FAILURE); 5281 } 5282 5283 /* SUCCESS - we have agreed on a version */ 5284 ldcp->local_hparams.ver_major = vermsg->ver_major; 5285 ldcp->local_hparams.ver_minor = vermsg->ver_minor; 5286 ldcp->hstate |= VER_ACK_RCVD; 5287 5288 DBG2(vgenp, ldcp, "VER_ACK_RCVD, ver(%d,%d) \n", 5289 vermsg->ver_major, vermsg->ver_minor); 5290 5291 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 5292 5293 /* VER_ACK_SENT and VER_ACK_RCVD */ 5294 5295 /* local and peer versions match? */ 5296 ASSERT((ldcp->local_hparams.ver_major == 5297 ldcp->peer_hparams.ver_major) && 5298 (ldcp->local_hparams.ver_minor == 5299 ldcp->peer_hparams.ver_minor)); 5300 5301 vgen_set_vnet_proto_ops(ldcp); 5302 5303 /* move to the next phase */ 5304 vgen_handshake(vh_nextphase(ldcp)); 5305 } 5306 break; 5307 5308 case VIO_SUBTYPE_NACK: 5309 5310 if (ldcp->hphase != VH_PHASE1) { 5311 /* This should not happen. */ 5312 DWARN(vgenp, ldcp, "VER_NACK_RCVD Invalid " 5313 "Phase(%u)\n", ldcp->hphase); 5314 return (VGEN_FAILURE); 5315 } 5316 5317 DBG2(vgenp, ldcp, "VER_NACK_RCVD next ver(%d,%d)\n", 5318 vermsg->ver_major, vermsg->ver_minor); 5319 5320 /* check if version in NACK is zero */ 5321 if (vermsg->ver_major == 0 && vermsg->ver_minor == 0) { 5322 /* 5323 * Version Negotiation has failed. 5324 */ 5325 DWARN(vgenp, ldcp, "Version Negotiation Failed\n"); 5326 return (VGEN_FAILURE); 5327 } 5328 5329 idx = 0; 5330 5331 for (;;) { 5332 5333 if (vermsg->ver_major > versions[idx].ver_major) { 5334 /* select next lower version */ 5335 5336 ldcp->local_hparams.ver_major = 5337 versions[idx].ver_major; 5338 ldcp->local_hparams.ver_minor = 5339 versions[idx].ver_minor; 5340 break; 5341 } 5342 5343 if (vermsg->ver_major == versions[idx].ver_major) { 5344 /* major version match */ 5345 5346 ldcp->local_hparams.ver_major = 5347 versions[idx].ver_major; 5348 5349 ldcp->local_hparams.ver_minor = 5350 versions[idx].ver_minor; 5351 break; 5352 } 5353 5354 idx++; 5355 5356 if (idx == VGEN_NUM_VER) { 5357 /* 5358 * no version match. 5359 * Version Negotiation has failed. 5360 */ 5361 DWARN(vgenp, ldcp, 5362 "Version Negotiation Failed\n"); 5363 return (VGEN_FAILURE); 5364 } 5365 5366 } 5367 5368 rv = vgen_send_version_negotiate(ldcp); 5369 if (rv != VGEN_SUCCESS) { 5370 return (rv); 5371 } 5372 5373 break; 5374 } 5375 5376 DBG1(vgenp, ldcp, "exit\n"); 5377 return (VGEN_SUCCESS); 5378 } 5379 5380 /* Check if the attributes are supported */ 5381 static int 5382 vgen_check_attr_info(vgen_ldc_t *ldcp, vnet_attr_msg_t *msg) 5383 { 5384 vgen_hparams_t *lp = &ldcp->local_hparams; 5385 5386 if ((msg->addr_type != ADDR_TYPE_MAC) || 5387 (msg->ack_freq > 64) || 5388 (msg->xfer_mode != lp->xfer_mode)) { 5389 return (VGEN_FAILURE); 5390 } 5391 5392 if (VGEN_VER_LT(ldcp, 1, 4)) { 5393 /* versions < 1.4, mtu must match */ 5394 if (msg->mtu != lp->mtu) { 5395 return (VGEN_FAILURE); 5396 } 5397 } else { 5398 /* Ver >= 1.4, validate mtu of the peer is at least ETHERMAX */ 5399 if (msg->mtu < ETHERMAX) { 5400 return (VGEN_FAILURE); 5401 } 5402 } 5403 5404 return (VGEN_SUCCESS); 5405 } 5406 5407 /* 5408 * Handle an attribute info msg from the peer or an ACK/NACK from the peer 5409 * to an attr info msg that we sent. 5410 */ 5411 static int 5412 vgen_handle_attr_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 5413 { 5414 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5415 vnet_attr_msg_t *msg = (vnet_attr_msg_t *)tagp; 5416 vgen_hparams_t *lp = &ldcp->local_hparams; 5417 vgen_hparams_t *rp = &ldcp->peer_hparams; 5418 int ack = 1; 5419 int rv = 0; 5420 uint32_t mtu; 5421 5422 DBG1(vgenp, ldcp, "enter\n"); 5423 if (ldcp->hphase != VH_PHASE2) { 5424 DWARN(vgenp, ldcp, "Rcvd ATTR_INFO subtype(%d)," 5425 " Invalid Phase(%u)\n", 5426 tagp->vio_subtype, ldcp->hphase); 5427 return (VGEN_FAILURE); 5428 } 5429 switch (tagp->vio_subtype) { 5430 case VIO_SUBTYPE_INFO: 5431 5432 DBG2(vgenp, ldcp, "ATTR_INFO_RCVD \n"); 5433 ldcp->hstate |= ATTR_INFO_RCVD; 5434 5435 /* save peer's values */ 5436 rp->mtu = msg->mtu; 5437 rp->addr = msg->addr; 5438 rp->addr_type = msg->addr_type; 5439 rp->xfer_mode = msg->xfer_mode; 5440 rp->ack_freq = msg->ack_freq; 5441 5442 rv = vgen_check_attr_info(ldcp, msg); 5443 if (rv == VGEN_FAILURE) { 5444 /* unsupported attr, send NACK */ 5445 ack = 0; 5446 } else { 5447 5448 if (VGEN_VER_GTEQ(ldcp, 1, 4)) { 5449 5450 /* 5451 * Versions >= 1.4: 5452 * The mtu is negotiated down to the 5453 * minimum of our mtu and peer's mtu. 5454 */ 5455 mtu = MIN(msg->mtu, vgenp->max_frame_size); 5456 5457 /* 5458 * If we have received an ack for the attr info 5459 * that we sent, then check if the mtu computed 5460 * above matches the mtu that the peer had ack'd 5461 * (saved in local hparams). If they don't 5462 * match, we fail the handshake. 5463 */ 5464 if (ldcp->hstate & ATTR_ACK_RCVD) { 5465 if (mtu != lp->mtu) { 5466 /* send NACK */ 5467 ack = 0; 5468 } 5469 } else { 5470 /* 5471 * Save the mtu computed above in our 5472 * attr parameters, so it gets sent in 5473 * the attr info from us to the peer. 5474 */ 5475 lp->mtu = mtu; 5476 } 5477 5478 /* save the MIN mtu in the msg to be replied */ 5479 msg->mtu = mtu; 5480 5481 } 5482 } 5483 5484 5485 if (ack) { 5486 tagp->vio_subtype = VIO_SUBTYPE_ACK; 5487 } else { 5488 tagp->vio_subtype = VIO_SUBTYPE_NACK; 5489 } 5490 tagp->vio_sid = ldcp->local_sid; 5491 5492 /* send reply msg back to peer */ 5493 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msg), 5494 B_FALSE); 5495 if (rv != VGEN_SUCCESS) { 5496 return (rv); 5497 } 5498 5499 if (ack) { 5500 ldcp->hstate |= ATTR_ACK_SENT; 5501 DBG2(vgenp, ldcp, "ATTR_ACK_SENT \n"); 5502 } else { 5503 /* failed */ 5504 DWARN(vgenp, ldcp, "ATTR_NACK_SENT \n"); 5505 return (VGEN_FAILURE); 5506 } 5507 5508 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 5509 vgen_handshake(vh_nextphase(ldcp)); 5510 } 5511 5512 break; 5513 5514 case VIO_SUBTYPE_ACK: 5515 5516 if (VGEN_VER_GTEQ(ldcp, 1, 5) && 5517 ldcp->portp == vgenp->vsw_portp) { 5518 /* 5519 * Versions >= 1.5: 5520 * If the vnet device has been configured to get 5521 * physical link state updates, check the corresponding 5522 * bits in the ack msg, if the peer is vswitch. 5523 */ 5524 if (((lp->physlink_update & 5525 PHYSLINK_UPDATE_STATE_MASK) == 5526 PHYSLINK_UPDATE_STATE) && 5527 5528 ((msg->physlink_update & 5529 PHYSLINK_UPDATE_STATE_MASK) == 5530 PHYSLINK_UPDATE_STATE_ACK)) { 5531 vgenp->pls_negotiated = B_TRUE; 5532 } else { 5533 vgenp->pls_negotiated = B_FALSE; 5534 } 5535 } 5536 5537 if (VGEN_VER_GTEQ(ldcp, 1, 4)) { 5538 /* 5539 * Versions >= 1.4: 5540 * The ack msg sent by the peer contains the minimum of 5541 * our mtu (that we had sent in our attr info) and the 5542 * peer's mtu. 5543 * 5544 * If we have sent an ack for the attr info msg from 5545 * the peer, check if the mtu that was computed then 5546 * (saved in local hparams) matches the mtu that the 5547 * peer has ack'd. If they don't match, we fail the 5548 * handshake. 5549 */ 5550 if (ldcp->hstate & ATTR_ACK_SENT) { 5551 if (lp->mtu != msg->mtu) { 5552 return (VGEN_FAILURE); 5553 } 5554 } else { 5555 /* 5556 * If the mtu ack'd by the peer is > our mtu 5557 * fail handshake. Otherwise, save the mtu, so 5558 * we can validate it when we receive attr info 5559 * from our peer. 5560 */ 5561 if (msg->mtu > lp->mtu) { 5562 return (VGEN_FAILURE); 5563 } 5564 if (msg->mtu <= lp->mtu) { 5565 lp->mtu = msg->mtu; 5566 } 5567 } 5568 } 5569 5570 ldcp->hstate |= ATTR_ACK_RCVD; 5571 5572 DBG2(vgenp, ldcp, "ATTR_ACK_RCVD \n"); 5573 5574 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 5575 vgen_handshake(vh_nextphase(ldcp)); 5576 } 5577 break; 5578 5579 case VIO_SUBTYPE_NACK: 5580 5581 DBG2(vgenp, ldcp, "ATTR_NACK_RCVD \n"); 5582 return (VGEN_FAILURE); 5583 } 5584 DBG1(vgenp, ldcp, "exit\n"); 5585 return (VGEN_SUCCESS); 5586 } 5587 5588 /* Check if the dring info msg is ok */ 5589 static int 5590 vgen_check_dring_reg(vio_dring_reg_msg_t *msg) 5591 { 5592 /* check if msg contents are ok */ 5593 if ((msg->num_descriptors < 128) || (msg->descriptor_size < 5594 sizeof (vnet_public_desc_t))) { 5595 return (VGEN_FAILURE); 5596 } 5597 return (VGEN_SUCCESS); 5598 } 5599 5600 /* 5601 * Handle a descriptor ring register msg from the peer or an ACK/NACK from 5602 * the peer to a dring register msg that we sent. 5603 */ 5604 static int 5605 vgen_handle_dring_reg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 5606 { 5607 vio_dring_reg_msg_t *msg = (vio_dring_reg_msg_t *)tagp; 5608 ldc_mem_cookie_t dcookie; 5609 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5610 int ack = 0; 5611 int rv = 0; 5612 5613 DBG1(vgenp, ldcp, "enter\n"); 5614 if (ldcp->hphase < VH_PHASE2) { 5615 /* dring_info can be rcvd in any of the phases after Phase1 */ 5616 DWARN(vgenp, ldcp, 5617 "Rcvd DRING_INFO Subtype (%d), Invalid Phase(%u)\n", 5618 tagp->vio_subtype, ldcp->hphase); 5619 return (VGEN_FAILURE); 5620 } 5621 switch (tagp->vio_subtype) { 5622 case VIO_SUBTYPE_INFO: 5623 5624 DBG2(vgenp, ldcp, "DRING_INFO_RCVD \n"); 5625 ldcp->hstate |= DRING_INFO_RCVD; 5626 bcopy((msg->cookie), &dcookie, sizeof (dcookie)); 5627 5628 ASSERT(msg->ncookies == 1); 5629 5630 if (vgen_check_dring_reg(msg) == VGEN_SUCCESS) { 5631 /* 5632 * verified dring info msg to be ok, 5633 * now try to map the remote dring. 5634 */ 5635 rv = vgen_init_rxds(ldcp, msg->num_descriptors, 5636 msg->descriptor_size, &dcookie, 5637 msg->ncookies); 5638 if (rv == DDI_SUCCESS) { 5639 /* now we can ack the peer */ 5640 ack = 1; 5641 } 5642 } 5643 if (ack == 0) { 5644 /* failed, send NACK */ 5645 tagp->vio_subtype = VIO_SUBTYPE_NACK; 5646 } else { 5647 if (!(ldcp->peer_hparams.dring_ready)) { 5648 5649 /* save peer's dring_info values */ 5650 bcopy(&dcookie, 5651 &(ldcp->peer_hparams.dring_cookie), 5652 sizeof (dcookie)); 5653 ldcp->peer_hparams.num_desc = 5654 msg->num_descriptors; 5655 ldcp->peer_hparams.desc_size = 5656 msg->descriptor_size; 5657 ldcp->peer_hparams.num_dcookies = 5658 msg->ncookies; 5659 5660 /* set dring_ident for the peer */ 5661 ldcp->peer_hparams.dring_ident = 5662 (uint64_t)ldcp->rxdp; 5663 /* return the dring_ident in ack msg */ 5664 msg->dring_ident = 5665 (uint64_t)ldcp->rxdp; 5666 5667 ldcp->peer_hparams.dring_ready = B_TRUE; 5668 } 5669 tagp->vio_subtype = VIO_SUBTYPE_ACK; 5670 } 5671 tagp->vio_sid = ldcp->local_sid; 5672 /* send reply msg back to peer */ 5673 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msg), 5674 B_FALSE); 5675 if (rv != VGEN_SUCCESS) { 5676 return (rv); 5677 } 5678 5679 if (ack) { 5680 ldcp->hstate |= DRING_ACK_SENT; 5681 DBG2(vgenp, ldcp, "DRING_ACK_SENT"); 5682 } else { 5683 DWARN(vgenp, ldcp, "DRING_NACK_SENT"); 5684 return (VGEN_FAILURE); 5685 } 5686 5687 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 5688 vgen_handshake(vh_nextphase(ldcp)); 5689 } 5690 5691 break; 5692 5693 case VIO_SUBTYPE_ACK: 5694 5695 ldcp->hstate |= DRING_ACK_RCVD; 5696 5697 DBG2(vgenp, ldcp, "DRING_ACK_RCVD"); 5698 5699 if (!(ldcp->local_hparams.dring_ready)) { 5700 /* local dring is now ready */ 5701 ldcp->local_hparams.dring_ready = B_TRUE; 5702 5703 /* save dring_ident acked by peer */ 5704 ldcp->local_hparams.dring_ident = 5705 msg->dring_ident; 5706 } 5707 5708 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 5709 vgen_handshake(vh_nextphase(ldcp)); 5710 } 5711 5712 break; 5713 5714 case VIO_SUBTYPE_NACK: 5715 5716 DBG2(vgenp, ldcp, "DRING_NACK_RCVD"); 5717 return (VGEN_FAILURE); 5718 } 5719 DBG1(vgenp, ldcp, "exit\n"); 5720 return (VGEN_SUCCESS); 5721 } 5722 5723 /* 5724 * Handle a rdx info msg from the peer or an ACK/NACK 5725 * from the peer to a rdx info msg that we sent. 5726 */ 5727 static int 5728 vgen_handle_rdx_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 5729 { 5730 int rv = 0; 5731 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5732 5733 DBG1(vgenp, ldcp, "enter\n"); 5734 if (ldcp->hphase != VH_PHASE3) { 5735 DWARN(vgenp, ldcp, 5736 "Rcvd RDX_INFO Subtype (%d), Invalid Phase(%u)\n", 5737 tagp->vio_subtype, ldcp->hphase); 5738 return (VGEN_FAILURE); 5739 } 5740 switch (tagp->vio_subtype) { 5741 case VIO_SUBTYPE_INFO: 5742 5743 DBG2(vgenp, ldcp, "RDX_INFO_RCVD \n"); 5744 ldcp->hstate |= RDX_INFO_RCVD; 5745 5746 tagp->vio_subtype = VIO_SUBTYPE_ACK; 5747 tagp->vio_sid = ldcp->local_sid; 5748 /* send reply msg back to peer */ 5749 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (vio_rdx_msg_t), 5750 B_FALSE); 5751 if (rv != VGEN_SUCCESS) { 5752 return (rv); 5753 } 5754 5755 ldcp->hstate |= RDX_ACK_SENT; 5756 DBG2(vgenp, ldcp, "RDX_ACK_SENT \n"); 5757 5758 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 5759 vgen_handshake(vh_nextphase(ldcp)); 5760 } 5761 5762 break; 5763 5764 case VIO_SUBTYPE_ACK: 5765 5766 ldcp->hstate |= RDX_ACK_RCVD; 5767 5768 DBG2(vgenp, ldcp, "RDX_ACK_RCVD \n"); 5769 5770 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 5771 vgen_handshake(vh_nextphase(ldcp)); 5772 } 5773 break; 5774 5775 case VIO_SUBTYPE_NACK: 5776 5777 DBG2(vgenp, ldcp, "RDX_NACK_RCVD \n"); 5778 return (VGEN_FAILURE); 5779 } 5780 DBG1(vgenp, ldcp, "exit\n"); 5781 return (VGEN_SUCCESS); 5782 } 5783 5784 /* Handle ACK/NACK from vsw to a set multicast msg that we sent */ 5785 static int 5786 vgen_handle_mcast_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 5787 { 5788 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5789 vnet_mcast_msg_t *msgp = (vnet_mcast_msg_t *)tagp; 5790 struct ether_addr *addrp; 5791 int count; 5792 int i; 5793 5794 DBG1(vgenp, ldcp, "enter\n"); 5795 switch (tagp->vio_subtype) { 5796 5797 case VIO_SUBTYPE_INFO: 5798 5799 /* vnet shouldn't recv set mcast msg, only vsw handles it */ 5800 DWARN(vgenp, ldcp, "rcvd SET_MCAST_INFO \n"); 5801 break; 5802 5803 case VIO_SUBTYPE_ACK: 5804 5805 /* success adding/removing multicast addr */ 5806 DBG1(vgenp, ldcp, "rcvd SET_MCAST_ACK \n"); 5807 break; 5808 5809 case VIO_SUBTYPE_NACK: 5810 5811 DWARN(vgenp, ldcp, "rcvd SET_MCAST_NACK \n"); 5812 if (!(msgp->set)) { 5813 /* multicast remove request failed */ 5814 break; 5815 } 5816 5817 /* multicast add request failed */ 5818 for (count = 0; count < msgp->count; count++) { 5819 addrp = &(msgp->mca[count]); 5820 5821 /* delete address from the table */ 5822 for (i = 0; i < vgenp->mccount; i++) { 5823 if (ether_cmp(addrp, 5824 &(vgenp->mctab[i])) == 0) { 5825 if (vgenp->mccount > 1) { 5826 int t = vgenp->mccount - 1; 5827 vgenp->mctab[i] = 5828 vgenp->mctab[t]; 5829 } 5830 vgenp->mccount--; 5831 break; 5832 } 5833 } 5834 } 5835 break; 5836 5837 } 5838 DBG1(vgenp, ldcp, "exit\n"); 5839 5840 return (VGEN_SUCCESS); 5841 } 5842 5843 /* 5844 * Physical link information message from the peer. Only vswitch should send 5845 * us this message; if the vnet device has been configured to get physical link 5846 * state updates. Note that we must have already negotiated this with the 5847 * vswitch during attribute exchange phase of handshake. 5848 */ 5849 static int 5850 vgen_handle_physlink_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 5851 { 5852 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5853 vnet_physlink_msg_t *msgp = (vnet_physlink_msg_t *)tagp; 5854 link_state_t link_state; 5855 int rv; 5856 5857 if (ldcp->portp != vgenp->vsw_portp) { 5858 /* 5859 * drop the message and don't process; as we should 5860 * receive physlink_info message from only vswitch. 5861 */ 5862 return (VGEN_SUCCESS); 5863 } 5864 5865 if (vgenp->pls_negotiated == B_FALSE) { 5866 /* 5867 * drop the message and don't process; as we should receive 5868 * physlink_info message only if physlink update is enabled for 5869 * the device and negotiated with vswitch. 5870 */ 5871 return (VGEN_SUCCESS); 5872 } 5873 5874 switch (tagp->vio_subtype) { 5875 5876 case VIO_SUBTYPE_INFO: 5877 5878 if ((msgp->physlink_info & VNET_PHYSLINK_STATE_MASK) == 5879 VNET_PHYSLINK_STATE_UP) { 5880 link_state = LINK_STATE_UP; 5881 } else { 5882 link_state = LINK_STATE_DOWN; 5883 } 5884 5885 if (vgenp->phys_link_state != link_state) { 5886 vgenp->phys_link_state = link_state; 5887 mutex_exit(&ldcp->cblock); 5888 5889 /* Now update the stack */ 5890 vgen_link_update(vgenp, link_state); 5891 5892 mutex_enter(&ldcp->cblock); 5893 } 5894 5895 tagp->vio_subtype = VIO_SUBTYPE_ACK; 5896 tagp->vio_sid = ldcp->local_sid; 5897 5898 /* send reply msg back to peer */ 5899 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, 5900 sizeof (vnet_physlink_msg_t), B_FALSE); 5901 if (rv != VGEN_SUCCESS) { 5902 return (rv); 5903 } 5904 break; 5905 5906 case VIO_SUBTYPE_ACK: 5907 5908 /* vnet shouldn't recv physlink acks */ 5909 DWARN(vgenp, ldcp, "rcvd PHYSLINK_ACK \n"); 5910 break; 5911 5912 case VIO_SUBTYPE_NACK: 5913 5914 /* vnet shouldn't recv physlink nacks */ 5915 DWARN(vgenp, ldcp, "rcvd PHYSLINK_NACK \n"); 5916 break; 5917 5918 } 5919 DBG1(vgenp, ldcp, "exit\n"); 5920 5921 return (VGEN_SUCCESS); 5922 } 5923 5924 /* handler for control messages received from the peer ldc end-point */ 5925 static int 5926 vgen_handle_ctrlmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 5927 { 5928 int rv = 0; 5929 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5930 5931 DBG1(vgenp, ldcp, "enter\n"); 5932 switch (tagp->vio_subtype_env) { 5933 5934 case VIO_VER_INFO: 5935 rv = vgen_handle_version_negotiate(ldcp, tagp); 5936 break; 5937 5938 case VIO_ATTR_INFO: 5939 rv = vgen_handle_attr_info(ldcp, tagp); 5940 break; 5941 5942 case VIO_DRING_REG: 5943 rv = vgen_handle_dring_reg(ldcp, tagp); 5944 break; 5945 5946 case VIO_RDX: 5947 rv = vgen_handle_rdx_info(ldcp, tagp); 5948 break; 5949 5950 case VNET_MCAST_INFO: 5951 rv = vgen_handle_mcast_info(ldcp, tagp); 5952 break; 5953 5954 case VIO_DDS_INFO: 5955 /* 5956 * If we are in the process of resetting the vswitch channel, 5957 * drop the dds message. A new handshake will be initiated 5958 * when the channel comes back up after the reset and dds 5959 * negotiation can then continue. 5960 */ 5961 if (ldcp->need_ldc_reset == B_TRUE) { 5962 break; 5963 } 5964 rv = vgen_dds_rx(ldcp, tagp); 5965 break; 5966 5967 case VNET_PHYSLINK_INFO: 5968 rv = vgen_handle_physlink_info(ldcp, tagp); 5969 break; 5970 } 5971 5972 DBG1(vgenp, ldcp, "exit rv(%d)\n", rv); 5973 return (rv); 5974 } 5975 5976 /* handler for data messages received from the peer ldc end-point */ 5977 static int 5978 vgen_handle_datamsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp, uint32_t msglen) 5979 { 5980 int rv = 0; 5981 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5982 5983 DBG1(vgenp, ldcp, "enter\n"); 5984 5985 if (ldcp->hphase != VH_DONE) 5986 return (rv); 5987 5988 if (tagp->vio_subtype == VIO_SUBTYPE_INFO) { 5989 rv = vgen_check_datamsg_seq(ldcp, tagp); 5990 if (rv != 0) { 5991 return (rv); 5992 } 5993 } 5994 5995 switch (tagp->vio_subtype_env) { 5996 case VIO_DRING_DATA: 5997 rv = vgen_handle_dring_data(ldcp, tagp); 5998 break; 5999 6000 case VIO_PKT_DATA: 6001 ldcp->rx_pktdata((void *)ldcp, (void *)tagp, msglen); 6002 break; 6003 default: 6004 break; 6005 } 6006 6007 DBG1(vgenp, ldcp, "exit rv(%d)\n", rv); 6008 return (rv); 6009 } 6010 6011 /* 6012 * dummy pkt data handler function for vnet protocol version 1.0 6013 */ 6014 static void 6015 vgen_handle_pkt_data_nop(void *arg1, void *arg2, uint32_t msglen) 6016 { 6017 _NOTE(ARGUNUSED(arg1, arg2, msglen)) 6018 } 6019 6020 /* 6021 * This function handles raw pkt data messages received over the channel. 6022 * Currently, only priority-eth-type frames are received through this mechanism. 6023 * In this case, the frame(data) is present within the message itself which 6024 * is copied into an mblk before sending it up the stack. 6025 */ 6026 static void 6027 vgen_handle_pkt_data(void *arg1, void *arg2, uint32_t msglen) 6028 { 6029 vgen_ldc_t *ldcp = (vgen_ldc_t *)arg1; 6030 vio_raw_data_msg_t *pkt = (vio_raw_data_msg_t *)arg2; 6031 uint32_t size; 6032 mblk_t *mp; 6033 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 6034 vgen_stats_t *statsp = &ldcp->stats; 6035 vgen_hparams_t *lp = &ldcp->local_hparams; 6036 vio_net_rx_cb_t vrx_cb; 6037 6038 ASSERT(MUTEX_HELD(&ldcp->cblock)); 6039 6040 mutex_exit(&ldcp->cblock); 6041 6042 size = msglen - VIO_PKT_DATA_HDRSIZE; 6043 if (size < ETHERMIN || size > lp->mtu) { 6044 (void) atomic_inc_32(&statsp->rx_pri_fail); 6045 goto exit; 6046 } 6047 6048 mp = vio_multipool_allocb(&ldcp->vmp, size); 6049 if (mp == NULL) { 6050 mp = allocb(size, BPRI_MED); 6051 if (mp == NULL) { 6052 (void) atomic_inc_32(&statsp->rx_pri_fail); 6053 DWARN(vgenp, ldcp, "allocb failure, " 6054 "unable to process priority frame\n"); 6055 goto exit; 6056 } 6057 } 6058 6059 /* copy the frame from the payload of raw data msg into the mblk */ 6060 bcopy(pkt->data, mp->b_rptr, size); 6061 mp->b_wptr = mp->b_rptr + size; 6062 6063 /* update stats */ 6064 (void) atomic_inc_64(&statsp->rx_pri_packets); 6065 (void) atomic_add_64(&statsp->rx_pri_bytes, size); 6066 6067 /* send up; call vrx_cb() as cblock is already released */ 6068 vrx_cb = ldcp->portp->vcb.vio_net_rx_cb; 6069 vrx_cb(ldcp->portp->vhp, mp); 6070 6071 exit: 6072 mutex_enter(&ldcp->cblock); 6073 } 6074 6075 static int 6076 vgen_send_dring_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp, uint32_t start, 6077 int32_t end, uint8_t pstate) 6078 { 6079 int rv = 0; 6080 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 6081 vio_dring_msg_t *msgp = (vio_dring_msg_t *)tagp; 6082 6083 tagp->vio_subtype = VIO_SUBTYPE_ACK; 6084 tagp->vio_sid = ldcp->local_sid; 6085 msgp->start_idx = start; 6086 msgp->end_idx = end; 6087 msgp->dring_process_state = pstate; 6088 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msgp), B_FALSE); 6089 if (rv != VGEN_SUCCESS) { 6090 DWARN(vgenp, ldcp, "vgen_sendmsg failed\n"); 6091 } 6092 return (rv); 6093 } 6094 6095 static int 6096 vgen_handle_dring_data(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 6097 { 6098 int rv = 0; 6099 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 6100 6101 6102 DBG1(vgenp, ldcp, "enter\n"); 6103 switch (tagp->vio_subtype) { 6104 6105 case VIO_SUBTYPE_INFO: 6106 /* 6107 * To reduce the locking contention, release the 6108 * cblock here and re-acquire it once we are done 6109 * receiving packets. 6110 */ 6111 mutex_exit(&ldcp->cblock); 6112 mutex_enter(&ldcp->rxlock); 6113 rv = vgen_handle_dring_data_info(ldcp, tagp); 6114 mutex_exit(&ldcp->rxlock); 6115 mutex_enter(&ldcp->cblock); 6116 break; 6117 6118 case VIO_SUBTYPE_ACK: 6119 rv = vgen_handle_dring_data_ack(ldcp, tagp); 6120 break; 6121 6122 case VIO_SUBTYPE_NACK: 6123 rv = vgen_handle_dring_data_nack(ldcp, tagp); 6124 break; 6125 } 6126 DBG1(vgenp, ldcp, "exit rv(%d)\n", rv); 6127 return (rv); 6128 } 6129 6130 static int 6131 vgen_handle_dring_data_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 6132 { 6133 uint32_t start; 6134 int32_t end; 6135 int rv = 0; 6136 vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp; 6137 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 6138 #ifdef VGEN_HANDLE_LOST_PKTS 6139 vgen_stats_t *statsp = &ldcp->stats; 6140 uint32_t rxi; 6141 int n; 6142 #endif 6143 6144 DBG1(vgenp, ldcp, "enter\n"); 6145 6146 start = dringmsg->start_idx; 6147 end = dringmsg->end_idx; 6148 /* 6149 * received a data msg, which contains the start and end 6150 * indices of the descriptors within the rx ring holding data, 6151 * the seq_num of data packet corresponding to the start index, 6152 * and the dring_ident. 6153 * We can now read the contents of each of these descriptors 6154 * and gather data from it. 6155 */ 6156 DBG1(vgenp, ldcp, "INFO: start(%d), end(%d)\n", 6157 start, end); 6158 6159 /* validate rx start and end indeces */ 6160 if (!(CHECK_RXI(start, ldcp)) || ((end != -1) && 6161 !(CHECK_RXI(end, ldcp)))) { 6162 DWARN(vgenp, ldcp, "Invalid Rx start(%d) or end(%d)\n", 6163 start, end); 6164 /* drop the message if invalid index */ 6165 return (rv); 6166 } 6167 6168 /* validate dring_ident */ 6169 if (dringmsg->dring_ident != ldcp->peer_hparams.dring_ident) { 6170 DWARN(vgenp, ldcp, "Invalid dring ident 0x%x\n", 6171 dringmsg->dring_ident); 6172 /* invalid dring_ident, drop the msg */ 6173 return (rv); 6174 } 6175 #ifdef DEBUG 6176 if (vgen_trigger_rxlost) { 6177 /* drop this msg to simulate lost pkts for debugging */ 6178 vgen_trigger_rxlost = 0; 6179 return (rv); 6180 } 6181 #endif 6182 6183 #ifdef VGEN_HANDLE_LOST_PKTS 6184 6185 /* receive start index doesn't match expected index */ 6186 if (ldcp->next_rxi != start) { 6187 DWARN(vgenp, ldcp, "next_rxi(%d) != start(%d)\n", 6188 ldcp->next_rxi, start); 6189 6190 /* calculate the number of pkts lost */ 6191 if (start >= ldcp->next_rxi) { 6192 n = start - ldcp->next_rxi; 6193 } else { 6194 n = ldcp->num_rxds - (ldcp->next_rxi - start); 6195 } 6196 6197 statsp->rx_lost_pkts += n; 6198 tagp->vio_subtype = VIO_SUBTYPE_NACK; 6199 tagp->vio_sid = ldcp->local_sid; 6200 /* indicate the range of lost descriptors */ 6201 dringmsg->start_idx = ldcp->next_rxi; 6202 rxi = start; 6203 DECR_RXI(rxi, ldcp); 6204 dringmsg->end_idx = rxi; 6205 /* dring ident is left unchanged */ 6206 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, 6207 sizeof (*dringmsg), B_FALSE); 6208 if (rv != VGEN_SUCCESS) { 6209 DWARN(vgenp, ldcp, 6210 "vgen_sendmsg failed, stype:NACK\n"); 6211 return (rv); 6212 } 6213 /* 6214 * treat this range of descrs/pkts as dropped 6215 * and set the new expected value of next_rxi 6216 * and continue(below) to process from the new 6217 * start index. 6218 */ 6219 ldcp->next_rxi = start; 6220 } 6221 6222 #endif /* VGEN_HANDLE_LOST_PKTS */ 6223 6224 /* Now receive messages */ 6225 rv = vgen_process_dring_data(ldcp, tagp); 6226 6227 DBG1(vgenp, ldcp, "exit rv(%d)\n", rv); 6228 return (rv); 6229 } 6230 6231 static int 6232 vgen_process_dring_data(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 6233 { 6234 boolean_t set_ack_start = B_FALSE; 6235 uint32_t start; 6236 uint32_t ack_end; 6237 uint32_t next_rxi; 6238 uint32_t rxi; 6239 int count = 0; 6240 int rv = 0; 6241 uint32_t retries = 0; 6242 vgen_stats_t *statsp; 6243 vnet_public_desc_t rxd; 6244 vio_dring_entry_hdr_t *hdrp; 6245 mblk_t *bp = NULL; 6246 mblk_t *bpt = NULL; 6247 uint32_t ack_start; 6248 boolean_t rxd_err = B_FALSE; 6249 mblk_t *mp = NULL; 6250 size_t nbytes; 6251 boolean_t ack_needed = B_FALSE; 6252 size_t nread; 6253 uint64_t off = 0; 6254 struct ether_header *ehp; 6255 vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp; 6256 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 6257 vgen_hparams_t *lp = &ldcp->local_hparams; 6258 6259 DBG1(vgenp, ldcp, "enter\n"); 6260 6261 statsp = &ldcp->stats; 6262 start = dringmsg->start_idx; 6263 6264 /* 6265 * start processing the descriptors from the specified 6266 * start index, up to the index a descriptor is not ready 6267 * to be processed or we process the entire descriptor ring 6268 * and wrap around upto the start index. 6269 */ 6270 6271 /* need to set the start index of descriptors to be ack'd */ 6272 set_ack_start = B_TRUE; 6273 6274 /* index upto which we have ack'd */ 6275 ack_end = start; 6276 DECR_RXI(ack_end, ldcp); 6277 6278 next_rxi = rxi = start; 6279 do { 6280 vgen_recv_retry: 6281 rv = vnet_dring_entry_copy(&(ldcp->rxdp[rxi]), &rxd, 6282 ldcp->dring_mtype, ldcp->rx_dhandle, rxi, rxi); 6283 if (rv != 0) { 6284 DWARN(vgenp, ldcp, "ldc_mem_dring_acquire() failed" 6285 " rv(%d)\n", rv); 6286 statsp->ierrors++; 6287 return (rv); 6288 } 6289 6290 hdrp = &rxd.hdr; 6291 6292 if (hdrp->dstate != VIO_DESC_READY) { 6293 /* 6294 * Before waiting and retry here, send up 6295 * the packets that are received already 6296 */ 6297 if (bp != NULL) { 6298 DTRACE_PROBE1(vgen_rcv_msgs, int, count); 6299 vgen_rx(ldcp, bp, bpt); 6300 count = 0; 6301 bp = bpt = NULL; 6302 } 6303 /* 6304 * descriptor is not ready. 6305 * retry descriptor acquire, stop processing 6306 * after max # retries. 6307 */ 6308 if (retries == vgen_recv_retries) 6309 break; 6310 retries++; 6311 drv_usecwait(vgen_recv_delay); 6312 goto vgen_recv_retry; 6313 } 6314 retries = 0; 6315 6316 if (set_ack_start) { 6317 /* 6318 * initialize the start index of the range 6319 * of descriptors to be ack'd. 6320 */ 6321 ack_start = rxi; 6322 set_ack_start = B_FALSE; 6323 } 6324 6325 if ((rxd.nbytes < ETHERMIN) || 6326 (rxd.nbytes > lp->mtu) || 6327 (rxd.ncookies == 0) || 6328 (rxd.ncookies > MAX_COOKIES)) { 6329 rxd_err = B_TRUE; 6330 } else { 6331 /* 6332 * Try to allocate an mblk from the free pool 6333 * of recv mblks for the channel. 6334 * If this fails, use allocb(). 6335 */ 6336 nbytes = (VNET_IPALIGN + rxd.nbytes + 7) & ~7; 6337 if (nbytes > ldcp->max_rxpool_size) { 6338 mp = allocb(VNET_IPALIGN + rxd.nbytes + 8, 6339 BPRI_MED); 6340 } else { 6341 mp = vio_multipool_allocb(&ldcp->vmp, nbytes); 6342 if (mp == NULL) { 6343 statsp->rx_vio_allocb_fail++; 6344 /* 6345 * Data buffer returned by allocb(9F) 6346 * is 8byte aligned. We allocate extra 6347 * 8 bytes to ensure size is multiple 6348 * of 8 bytes for ldc_mem_copy(). 6349 */ 6350 mp = allocb(VNET_IPALIGN + 6351 rxd.nbytes + 8, BPRI_MED); 6352 } 6353 } 6354 } 6355 if ((rxd_err) || (mp == NULL)) { 6356 /* 6357 * rxd_err or allocb() failure, 6358 * drop this packet, get next. 6359 */ 6360 if (rxd_err) { 6361 statsp->ierrors++; 6362 rxd_err = B_FALSE; 6363 } else { 6364 statsp->rx_allocb_fail++; 6365 } 6366 6367 ack_needed = hdrp->ack; 6368 6369 /* set descriptor done bit */ 6370 rv = vnet_dring_entry_set_dstate(&(ldcp->rxdp[rxi]), 6371 ldcp->dring_mtype, ldcp->rx_dhandle, rxi, rxi, 6372 VIO_DESC_DONE); 6373 if (rv != 0) { 6374 DWARN(vgenp, ldcp, 6375 "vnet_dring_entry_set_dstate err rv(%d)\n", 6376 rv); 6377 return (rv); 6378 } 6379 6380 if (ack_needed) { 6381 ack_needed = B_FALSE; 6382 /* 6383 * sender needs ack for this packet, 6384 * ack pkts upto this index. 6385 */ 6386 ack_end = rxi; 6387 6388 rv = vgen_send_dring_ack(ldcp, tagp, 6389 ack_start, ack_end, 6390 VIO_DP_ACTIVE); 6391 if (rv != VGEN_SUCCESS) { 6392 goto error_ret; 6393 } 6394 6395 /* need to set new ack start index */ 6396 set_ack_start = B_TRUE; 6397 } 6398 goto vgen_next_rxi; 6399 } 6400 6401 nread = nbytes; 6402 rv = ldc_mem_copy(ldcp->ldc_handle, 6403 (caddr_t)mp->b_rptr, off, &nread, 6404 rxd.memcookie, rxd.ncookies, LDC_COPY_IN); 6405 6406 /* if ldc_mem_copy() failed */ 6407 if (rv) { 6408 DWARN(vgenp, ldcp, "ldc_mem_copy err rv(%d)\n", rv); 6409 statsp->ierrors++; 6410 freemsg(mp); 6411 goto error_ret; 6412 } 6413 6414 ack_needed = hdrp->ack; 6415 6416 rv = vnet_dring_entry_set_dstate(&(ldcp->rxdp[rxi]), 6417 ldcp->dring_mtype, ldcp->rx_dhandle, rxi, rxi, 6418 VIO_DESC_DONE); 6419 if (rv != 0) { 6420 DWARN(vgenp, ldcp, 6421 "vnet_dring_entry_set_dstate err rv(%d)\n", rv); 6422 goto error_ret; 6423 } 6424 6425 mp->b_rptr += VNET_IPALIGN; 6426 6427 if (ack_needed) { 6428 ack_needed = B_FALSE; 6429 /* 6430 * sender needs ack for this packet, 6431 * ack pkts upto this index. 6432 */ 6433 ack_end = rxi; 6434 6435 rv = vgen_send_dring_ack(ldcp, tagp, 6436 ack_start, ack_end, VIO_DP_ACTIVE); 6437 if (rv != VGEN_SUCCESS) { 6438 goto error_ret; 6439 } 6440 6441 /* need to set new ack start index */ 6442 set_ack_start = B_TRUE; 6443 } 6444 6445 if (nread != nbytes) { 6446 DWARN(vgenp, ldcp, 6447 "ldc_mem_copy nread(%lx), nbytes(%lx)\n", 6448 nread, nbytes); 6449 statsp->ierrors++; 6450 freemsg(mp); 6451 goto vgen_next_rxi; 6452 } 6453 6454 /* point to the actual end of data */ 6455 mp->b_wptr = mp->b_rptr + rxd.nbytes; 6456 6457 /* update stats */ 6458 statsp->ipackets++; 6459 statsp->rbytes += rxd.nbytes; 6460 ehp = (struct ether_header *)mp->b_rptr; 6461 if (IS_BROADCAST(ehp)) 6462 statsp->brdcstrcv++; 6463 else if (IS_MULTICAST(ehp)) 6464 statsp->multircv++; 6465 6466 /* build a chain of received packets */ 6467 if (bp == NULL) { 6468 /* first pkt */ 6469 bp = mp; 6470 bpt = bp; 6471 bpt->b_next = NULL; 6472 } else { 6473 mp->b_next = NULL; 6474 bpt->b_next = mp; 6475 bpt = mp; 6476 } 6477 6478 if (count++ > vgen_chain_len) { 6479 DTRACE_PROBE1(vgen_rcv_msgs, int, count); 6480 vgen_rx(ldcp, bp, bpt); 6481 count = 0; 6482 bp = bpt = NULL; 6483 } 6484 6485 vgen_next_rxi: 6486 /* update end index of range of descrs to be ack'd */ 6487 ack_end = rxi; 6488 6489 /* update the next index to be processed */ 6490 INCR_RXI(next_rxi, ldcp); 6491 if (next_rxi == start) { 6492 /* 6493 * processed the entire descriptor ring upto 6494 * the index at which we started. 6495 */ 6496 break; 6497 } 6498 6499 rxi = next_rxi; 6500 6501 _NOTE(CONSTCOND) 6502 } while (1); 6503 6504 /* 6505 * send an ack message to peer indicating that we have stopped 6506 * processing descriptors. 6507 */ 6508 if (set_ack_start) { 6509 /* 6510 * We have ack'd upto some index and we have not 6511 * processed any descriptors beyond that index. 6512 * Use the last ack'd index as both the start and 6513 * end of range of descrs being ack'd. 6514 * Note: This results in acking the last index twice 6515 * and should be harmless. 6516 */ 6517 ack_start = ack_end; 6518 } 6519 6520 rv = vgen_send_dring_ack(ldcp, tagp, ack_start, ack_end, 6521 VIO_DP_STOPPED); 6522 if (rv != VGEN_SUCCESS) { 6523 goto error_ret; 6524 } 6525 6526 /* save new recv index of next dring msg */ 6527 ldcp->next_rxi = next_rxi; 6528 6529 error_ret: 6530 /* send up packets received so far */ 6531 if (bp != NULL) { 6532 DTRACE_PROBE1(vgen_rcv_msgs, int, count); 6533 vgen_rx(ldcp, bp, bpt); 6534 bp = bpt = NULL; 6535 } 6536 DBG1(vgenp, ldcp, "exit rv(%d)\n", rv); 6537 return (rv); 6538 6539 } 6540 6541 static int 6542 vgen_handle_dring_data_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 6543 { 6544 int rv = 0; 6545 uint32_t start; 6546 int32_t end; 6547 uint32_t txi; 6548 boolean_t ready_txd = B_FALSE; 6549 vgen_stats_t *statsp; 6550 vgen_private_desc_t *tbufp; 6551 vnet_public_desc_t *txdp; 6552 vio_dring_entry_hdr_t *hdrp; 6553 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 6554 vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp; 6555 6556 DBG1(vgenp, ldcp, "enter\n"); 6557 start = dringmsg->start_idx; 6558 end = dringmsg->end_idx; 6559 statsp = &ldcp->stats; 6560 6561 /* 6562 * received an ack corresponding to a specific descriptor for 6563 * which we had set the ACK bit in the descriptor (during 6564 * transmit). This enables us to reclaim descriptors. 6565 */ 6566 6567 DBG2(vgenp, ldcp, "ACK: start(%d), end(%d)\n", start, end); 6568 6569 /* validate start and end indeces in the tx ack msg */ 6570 if (!(CHECK_TXI(start, ldcp)) || !(CHECK_TXI(end, ldcp))) { 6571 /* drop the message if invalid index */ 6572 DWARN(vgenp, ldcp, "Invalid Tx ack start(%d) or end(%d)\n", 6573 start, end); 6574 return (rv); 6575 } 6576 /* validate dring_ident */ 6577 if (dringmsg->dring_ident != ldcp->local_hparams.dring_ident) { 6578 /* invalid dring_ident, drop the msg */ 6579 DWARN(vgenp, ldcp, "Invalid dring ident 0x%x\n", 6580 dringmsg->dring_ident); 6581 return (rv); 6582 } 6583 statsp->dring_data_acks++; 6584 6585 /* reclaim descriptors that are done */ 6586 vgen_reclaim(ldcp); 6587 6588 if (dringmsg->dring_process_state != VIO_DP_STOPPED) { 6589 /* 6590 * receiver continued processing descriptors after 6591 * sending us the ack. 6592 */ 6593 return (rv); 6594 } 6595 6596 statsp->dring_stopped_acks++; 6597 6598 /* receiver stopped processing descriptors */ 6599 mutex_enter(&ldcp->wrlock); 6600 mutex_enter(&ldcp->tclock); 6601 6602 /* 6603 * determine if there are any pending tx descriptors 6604 * ready to be processed by the receiver(peer) and if so, 6605 * send a message to the peer to restart receiving. 6606 */ 6607 ready_txd = B_FALSE; 6608 6609 /* 6610 * using the end index of the descriptor range for which 6611 * we received the ack, check if the next descriptor is 6612 * ready. 6613 */ 6614 txi = end; 6615 INCR_TXI(txi, ldcp); 6616 tbufp = &ldcp->tbufp[txi]; 6617 txdp = tbufp->descp; 6618 hdrp = &txdp->hdr; 6619 if (hdrp->dstate == VIO_DESC_READY) { 6620 ready_txd = B_TRUE; 6621 } else { 6622 /* 6623 * descr next to the end of ack'd descr range is not 6624 * ready. 6625 * starting from the current reclaim index, check 6626 * if any descriptor is ready. 6627 */ 6628 6629 txi = ldcp->cur_tbufp - ldcp->tbufp; 6630 tbufp = &ldcp->tbufp[txi]; 6631 6632 txdp = tbufp->descp; 6633 hdrp = &txdp->hdr; 6634 if (hdrp->dstate == VIO_DESC_READY) { 6635 ready_txd = B_TRUE; 6636 } 6637 6638 } 6639 6640 if (ready_txd) { 6641 /* 6642 * we have tx descriptor(s) ready to be 6643 * processed by the receiver. 6644 * send a message to the peer with the start index 6645 * of ready descriptors. 6646 */ 6647 rv = vgen_send_dring_data(ldcp, txi, -1); 6648 if (rv != VGEN_SUCCESS) { 6649 ldcp->resched_peer = B_TRUE; 6650 ldcp->resched_peer_txi = txi; 6651 mutex_exit(&ldcp->tclock); 6652 mutex_exit(&ldcp->wrlock); 6653 return (rv); 6654 } 6655 } else { 6656 /* 6657 * no ready tx descriptors. set the flag to send a 6658 * message to peer when tx descriptors are ready in 6659 * transmit routine. 6660 */ 6661 ldcp->resched_peer = B_TRUE; 6662 ldcp->resched_peer_txi = ldcp->cur_tbufp - ldcp->tbufp; 6663 } 6664 6665 mutex_exit(&ldcp->tclock); 6666 mutex_exit(&ldcp->wrlock); 6667 DBG1(vgenp, ldcp, "exit rv(%d)\n", rv); 6668 return (rv); 6669 } 6670 6671 static int 6672 vgen_handle_dring_data_nack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 6673 { 6674 int rv = 0; 6675 uint32_t start; 6676 int32_t end; 6677 uint32_t txi; 6678 vnet_public_desc_t *txdp; 6679 vio_dring_entry_hdr_t *hdrp; 6680 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 6681 vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp; 6682 6683 DBG1(vgenp, ldcp, "enter\n"); 6684 start = dringmsg->start_idx; 6685 end = dringmsg->end_idx; 6686 6687 /* 6688 * peer sent a NACK msg to indicate lost packets. 6689 * The start and end correspond to the range of descriptors 6690 * for which the peer didn't receive a dring data msg and so 6691 * didn't receive the corresponding data. 6692 */ 6693 DWARN(vgenp, ldcp, "NACK: start(%d), end(%d)\n", start, end); 6694 6695 /* validate start and end indeces in the tx nack msg */ 6696 if (!(CHECK_TXI(start, ldcp)) || !(CHECK_TXI(end, ldcp))) { 6697 /* drop the message if invalid index */ 6698 DWARN(vgenp, ldcp, "Invalid Tx nack start(%d) or end(%d)\n", 6699 start, end); 6700 return (rv); 6701 } 6702 /* validate dring_ident */ 6703 if (dringmsg->dring_ident != ldcp->local_hparams.dring_ident) { 6704 /* invalid dring_ident, drop the msg */ 6705 DWARN(vgenp, ldcp, "Invalid dring ident 0x%x\n", 6706 dringmsg->dring_ident); 6707 return (rv); 6708 } 6709 mutex_enter(&ldcp->txlock); 6710 mutex_enter(&ldcp->tclock); 6711 6712 if (ldcp->next_tbufp == ldcp->cur_tbufp) { 6713 /* no busy descriptors, bogus nack ? */ 6714 mutex_exit(&ldcp->tclock); 6715 mutex_exit(&ldcp->txlock); 6716 return (rv); 6717 } 6718 6719 /* we just mark the descrs as done so they can be reclaimed */ 6720 for (txi = start; txi <= end; ) { 6721 txdp = &(ldcp->txdp[txi]); 6722 hdrp = &txdp->hdr; 6723 if (hdrp->dstate == VIO_DESC_READY) 6724 hdrp->dstate = VIO_DESC_DONE; 6725 INCR_TXI(txi, ldcp); 6726 } 6727 mutex_exit(&ldcp->tclock); 6728 mutex_exit(&ldcp->txlock); 6729 DBG1(vgenp, ldcp, "exit rv(%d)\n", rv); 6730 return (rv); 6731 } 6732 6733 static void 6734 vgen_reclaim(vgen_ldc_t *ldcp) 6735 { 6736 mutex_enter(&ldcp->tclock); 6737 6738 vgen_reclaim_dring(ldcp); 6739 ldcp->reclaim_lbolt = ddi_get_lbolt(); 6740 6741 mutex_exit(&ldcp->tclock); 6742 } 6743 6744 /* 6745 * transmit reclaim function. starting from the current reclaim index 6746 * look for descriptors marked DONE and reclaim the descriptor and the 6747 * corresponding buffers (tbuf). 6748 */ 6749 static void 6750 vgen_reclaim_dring(vgen_ldc_t *ldcp) 6751 { 6752 int count = 0; 6753 vnet_public_desc_t *txdp; 6754 vgen_private_desc_t *tbufp; 6755 vio_dring_entry_hdr_t *hdrp; 6756 6757 #ifdef DEBUG 6758 if (vgen_trigger_txtimeout) 6759 return; 6760 #endif 6761 6762 tbufp = ldcp->cur_tbufp; 6763 txdp = tbufp->descp; 6764 hdrp = &txdp->hdr; 6765 6766 while ((hdrp->dstate == VIO_DESC_DONE) && 6767 (tbufp != ldcp->next_tbufp)) { 6768 tbufp->flags = VGEN_PRIV_DESC_FREE; 6769 hdrp->dstate = VIO_DESC_FREE; 6770 hdrp->ack = B_FALSE; 6771 6772 tbufp = NEXTTBUF(ldcp, tbufp); 6773 txdp = tbufp->descp; 6774 hdrp = &txdp->hdr; 6775 count++; 6776 } 6777 6778 ldcp->cur_tbufp = tbufp; 6779 6780 /* 6781 * Check if mac layer should be notified to restart transmissions 6782 */ 6783 if ((ldcp->need_resched) && (count > 0)) { 6784 vio_net_tx_update_t vtx_update = 6785 ldcp->portp->vcb.vio_net_tx_update; 6786 6787 ldcp->need_resched = B_FALSE; 6788 vtx_update(ldcp->portp->vhp); 6789 } 6790 } 6791 6792 /* return the number of pending transmits for the channel */ 6793 static int 6794 vgen_num_txpending(vgen_ldc_t *ldcp) 6795 { 6796 int n; 6797 6798 if (ldcp->next_tbufp >= ldcp->cur_tbufp) { 6799 n = ldcp->next_tbufp - ldcp->cur_tbufp; 6800 } else { 6801 /* cur_tbufp > next_tbufp */ 6802 n = ldcp->num_txds - (ldcp->cur_tbufp - ldcp->next_tbufp); 6803 } 6804 6805 return (n); 6806 } 6807 6808 /* determine if the transmit descriptor ring is full */ 6809 static int 6810 vgen_tx_dring_full(vgen_ldc_t *ldcp) 6811 { 6812 vgen_private_desc_t *tbufp; 6813 vgen_private_desc_t *ntbufp; 6814 6815 tbufp = ldcp->next_tbufp; 6816 ntbufp = NEXTTBUF(ldcp, tbufp); 6817 if (ntbufp == ldcp->cur_tbufp) { /* out of tbufs/txds */ 6818 return (VGEN_SUCCESS); 6819 } 6820 return (VGEN_FAILURE); 6821 } 6822 6823 /* determine if timeout condition has occured */ 6824 static int 6825 vgen_ldc_txtimeout(vgen_ldc_t *ldcp) 6826 { 6827 if (((ddi_get_lbolt() - ldcp->reclaim_lbolt) > 6828 drv_usectohz(vnet_ldcwd_txtimeout * 1000)) && 6829 (vnet_ldcwd_txtimeout) && 6830 (vgen_tx_dring_full(ldcp) == VGEN_SUCCESS)) { 6831 return (VGEN_SUCCESS); 6832 } else { 6833 return (VGEN_FAILURE); 6834 } 6835 } 6836 6837 /* transmit watchdog timeout handler */ 6838 static void 6839 vgen_ldc_watchdog(void *arg) 6840 { 6841 vgen_ldc_t *ldcp; 6842 vgen_t *vgenp; 6843 int rv; 6844 6845 ldcp = (vgen_ldc_t *)arg; 6846 vgenp = LDC_TO_VGEN(ldcp); 6847 6848 rv = vgen_ldc_txtimeout(ldcp); 6849 if (rv == VGEN_SUCCESS) { 6850 DWARN(vgenp, ldcp, "transmit timeout\n"); 6851 #ifdef DEBUG 6852 if (vgen_trigger_txtimeout) { 6853 /* tx timeout triggered for debugging */ 6854 vgen_trigger_txtimeout = 0; 6855 } 6856 #endif 6857 mutex_enter(&ldcp->cblock); 6858 vgen_ldc_reset(ldcp); 6859 mutex_exit(&ldcp->cblock); 6860 if (ldcp->need_resched) { 6861 vio_net_tx_update_t vtx_update = 6862 ldcp->portp->vcb.vio_net_tx_update; 6863 6864 ldcp->need_resched = B_FALSE; 6865 vtx_update(ldcp->portp->vhp); 6866 } 6867 } 6868 6869 ldcp->wd_tid = timeout(vgen_ldc_watchdog, (caddr_t)ldcp, 6870 drv_usectohz(vnet_ldcwd_interval * 1000)); 6871 } 6872 6873 /* handler for error messages received from the peer ldc end-point */ 6874 static void 6875 vgen_handle_errmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 6876 { 6877 _NOTE(ARGUNUSED(ldcp, tagp)) 6878 } 6879 6880 static int 6881 vgen_check_datamsg_seq(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 6882 { 6883 vio_raw_data_msg_t *rmsg; 6884 vio_dring_msg_t *dmsg; 6885 uint64_t seq_num; 6886 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 6887 6888 if (tagp->vio_subtype_env == VIO_DRING_DATA) { 6889 dmsg = (vio_dring_msg_t *)tagp; 6890 seq_num = dmsg->seq_num; 6891 } else if (tagp->vio_subtype_env == VIO_PKT_DATA) { 6892 rmsg = (vio_raw_data_msg_t *)tagp; 6893 seq_num = rmsg->seq_num; 6894 } else { 6895 return (EINVAL); 6896 } 6897 6898 if (seq_num != ldcp->next_rxseq) { 6899 6900 /* seqnums don't match */ 6901 DWARN(vgenp, ldcp, 6902 "next_rxseq(0x%lx) != seq_num(0x%lx)\n", 6903 ldcp->next_rxseq, seq_num); 6904 6905 return (EINVAL); 6906 6907 } 6908 6909 ldcp->next_rxseq++; 6910 6911 return (0); 6912 } 6913 6914 /* Check if the session id in the received message is valid */ 6915 static int 6916 vgen_check_sid(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 6917 { 6918 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 6919 6920 if (tagp->vio_sid != ldcp->peer_sid) { 6921 DWARN(vgenp, ldcp, "sid mismatch: expected(%x), rcvd(%x)\n", 6922 ldcp->peer_sid, tagp->vio_sid); 6923 return (VGEN_FAILURE); 6924 } 6925 else 6926 return (VGEN_SUCCESS); 6927 } 6928 6929 static caddr_t 6930 vgen_print_ethaddr(uint8_t *a, char *ebuf) 6931 { 6932 (void) sprintf(ebuf, 6933 "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]); 6934 return (ebuf); 6935 } 6936 6937 /* Handshake watchdog timeout handler */ 6938 static void 6939 vgen_hwatchdog(void *arg) 6940 { 6941 vgen_ldc_t *ldcp = (vgen_ldc_t *)arg; 6942 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 6943 6944 DWARN(vgenp, ldcp, "handshake timeout phase(%x) state(%x)\n", 6945 ldcp->hphase, ldcp->hstate); 6946 6947 mutex_enter(&ldcp->cblock); 6948 if (ldcp->cancel_htid) { 6949 ldcp->cancel_htid = 0; 6950 mutex_exit(&ldcp->cblock); 6951 return; 6952 } 6953 ldcp->htid = 0; 6954 vgen_ldc_reset(ldcp); 6955 mutex_exit(&ldcp->cblock); 6956 } 6957 6958 static void 6959 vgen_print_hparams(vgen_hparams_t *hp) 6960 { 6961 uint8_t addr[6]; 6962 char ea[6]; 6963 ldc_mem_cookie_t *dc; 6964 6965 cmn_err(CE_CONT, "version_info:\n"); 6966 cmn_err(CE_CONT, 6967 "\tver_major: %d, ver_minor: %d, dev_class: %d\n", 6968 hp->ver_major, hp->ver_minor, hp->dev_class); 6969 6970 vnet_macaddr_ultostr(hp->addr, addr); 6971 cmn_err(CE_CONT, "attr_info:\n"); 6972 cmn_err(CE_CONT, "\tMTU: %lx, addr: %s\n", hp->mtu, 6973 vgen_print_ethaddr(addr, ea)); 6974 cmn_err(CE_CONT, 6975 "\taddr_type: %x, xfer_mode: %x, ack_freq: %x\n", 6976 hp->addr_type, hp->xfer_mode, hp->ack_freq); 6977 6978 dc = &hp->dring_cookie; 6979 cmn_err(CE_CONT, "dring_info:\n"); 6980 cmn_err(CE_CONT, 6981 "\tlength: %d, dsize: %d\n", hp->num_desc, hp->desc_size); 6982 cmn_err(CE_CONT, 6983 "\tldc_addr: 0x%lx, ldc_size: %ld\n", 6984 dc->addr, dc->size); 6985 cmn_err(CE_CONT, "\tdring_ident: 0x%lx\n", hp->dring_ident); 6986 } 6987 6988 static void 6989 vgen_print_ldcinfo(vgen_ldc_t *ldcp) 6990 { 6991 vgen_hparams_t *hp; 6992 6993 cmn_err(CE_CONT, "Channel Information:\n"); 6994 cmn_err(CE_CONT, 6995 "\tldc_id: 0x%lx, ldc_status: 0x%x\n", 6996 ldcp->ldc_id, ldcp->ldc_status); 6997 cmn_err(CE_CONT, 6998 "\tlocal_sid: 0x%x, peer_sid: 0x%x\n", 6999 ldcp->local_sid, ldcp->peer_sid); 7000 cmn_err(CE_CONT, 7001 "\thphase: 0x%x, hstate: 0x%x\n", 7002 ldcp->hphase, ldcp->hstate); 7003 7004 cmn_err(CE_CONT, "Local handshake params:\n"); 7005 hp = &ldcp->local_hparams; 7006 vgen_print_hparams(hp); 7007 7008 cmn_err(CE_CONT, "Peer handshake params:\n"); 7009 hp = &ldcp->peer_hparams; 7010 vgen_print_hparams(hp); 7011 } 7012 7013 /* 7014 * Send received packets up the stack. 7015 */ 7016 static void 7017 vgen_rx(vgen_ldc_t *ldcp, mblk_t *bp, mblk_t *bpt) 7018 { 7019 vio_net_rx_cb_t vrx_cb = ldcp->portp->vcb.vio_net_rx_cb; 7020 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 7021 7022 if (ldcp->rcv_thread != NULL) { 7023 ASSERT(MUTEX_HELD(&ldcp->rxlock)); 7024 } else { 7025 ASSERT(MUTEX_HELD(&ldcp->cblock)); 7026 } 7027 7028 mutex_enter(&ldcp->pollq_lock); 7029 7030 if (ldcp->polling_on == B_TRUE) { 7031 /* 7032 * If we are in polling mode, simply queue 7033 * the packets onto the poll queue and return. 7034 */ 7035 if (ldcp->pollq_headp == NULL) { 7036 ldcp->pollq_headp = bp; 7037 ldcp->pollq_tailp = bpt; 7038 } else { 7039 ldcp->pollq_tailp->b_next = bp; 7040 ldcp->pollq_tailp = bpt; 7041 } 7042 7043 mutex_exit(&ldcp->pollq_lock); 7044 return; 7045 } 7046 7047 /* 7048 * Prepend any pending mblks in the poll queue, now that we 7049 * are in interrupt mode, before sending up the chain of pkts. 7050 */ 7051 if (ldcp->pollq_headp != NULL) { 7052 DBG2(vgenp, ldcp, "vgen_rx(%lx), pending pollq_headp\n", 7053 (uintptr_t)ldcp); 7054 ldcp->pollq_tailp->b_next = bp; 7055 bp = ldcp->pollq_headp; 7056 ldcp->pollq_headp = ldcp->pollq_tailp = NULL; 7057 } 7058 7059 mutex_exit(&ldcp->pollq_lock); 7060 7061 if (ldcp->rcv_thread != NULL) { 7062 mutex_exit(&ldcp->rxlock); 7063 } else { 7064 mutex_exit(&ldcp->cblock); 7065 } 7066 7067 /* Send up the packets */ 7068 vrx_cb(ldcp->portp->vhp, bp); 7069 7070 if (ldcp->rcv_thread != NULL) { 7071 mutex_enter(&ldcp->rxlock); 7072 } else { 7073 mutex_enter(&ldcp->cblock); 7074 } 7075 } 7076 7077 /* 7078 * vgen_ldc_rcv_worker -- A per LDC worker thread to receive data. 7079 * This thread is woken up by the LDC interrupt handler to process 7080 * LDC packets and receive data. 7081 */ 7082 static void 7083 vgen_ldc_rcv_worker(void *arg) 7084 { 7085 callb_cpr_t cprinfo; 7086 vgen_ldc_t *ldcp = (vgen_ldc_t *)arg; 7087 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 7088 7089 DBG1(vgenp, ldcp, "enter\n"); 7090 CALLB_CPR_INIT(&cprinfo, &ldcp->rcv_thr_lock, callb_generic_cpr, 7091 "vnet_rcv_thread"); 7092 mutex_enter(&ldcp->rcv_thr_lock); 7093 while (!(ldcp->rcv_thr_flags & VGEN_WTHR_STOP)) { 7094 7095 CALLB_CPR_SAFE_BEGIN(&cprinfo); 7096 /* 7097 * Wait until the data is received or a stop 7098 * request is received. 7099 */ 7100 while (!(ldcp->rcv_thr_flags & 7101 (VGEN_WTHR_DATARCVD | VGEN_WTHR_STOP))) { 7102 cv_wait(&ldcp->rcv_thr_cv, &ldcp->rcv_thr_lock); 7103 } 7104 CALLB_CPR_SAFE_END(&cprinfo, &ldcp->rcv_thr_lock) 7105 7106 /* 7107 * First process the stop request. 7108 */ 7109 if (ldcp->rcv_thr_flags & VGEN_WTHR_STOP) { 7110 DBG2(vgenp, ldcp, "stopped\n"); 7111 break; 7112 } 7113 ldcp->rcv_thr_flags &= ~VGEN_WTHR_DATARCVD; 7114 ldcp->rcv_thr_flags |= VGEN_WTHR_PROCESSING; 7115 mutex_exit(&ldcp->rcv_thr_lock); 7116 DBG2(vgenp, ldcp, "calling vgen_handle_evt_read\n"); 7117 vgen_handle_evt_read(ldcp); 7118 mutex_enter(&ldcp->rcv_thr_lock); 7119 ldcp->rcv_thr_flags &= ~VGEN_WTHR_PROCESSING; 7120 } 7121 7122 /* 7123 * Update the run status and wakeup the thread that 7124 * has sent the stop request. 7125 */ 7126 ldcp->rcv_thr_flags &= ~VGEN_WTHR_STOP; 7127 ldcp->rcv_thread = NULL; 7128 CALLB_CPR_EXIT(&cprinfo); 7129 7130 thread_exit(); 7131 DBG1(vgenp, ldcp, "exit\n"); 7132 } 7133 7134 /* vgen_stop_rcv_thread -- Co-ordinate with receive thread to stop it */ 7135 static void 7136 vgen_stop_rcv_thread(vgen_ldc_t *ldcp) 7137 { 7138 kt_did_t tid = 0; 7139 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 7140 7141 DBG1(vgenp, ldcp, "enter\n"); 7142 /* 7143 * Send a stop request by setting the stop flag and 7144 * wait until the receive thread stops. 7145 */ 7146 mutex_enter(&ldcp->rcv_thr_lock); 7147 if (ldcp->rcv_thread != NULL) { 7148 tid = ldcp->rcv_thread->t_did; 7149 ldcp->rcv_thr_flags |= VGEN_WTHR_STOP; 7150 cv_signal(&ldcp->rcv_thr_cv); 7151 } 7152 mutex_exit(&ldcp->rcv_thr_lock); 7153 7154 if (tid != 0) { 7155 thread_join(tid); 7156 } 7157 DBG1(vgenp, ldcp, "exit\n"); 7158 } 7159 7160 /* 7161 * Wait for the channel rx-queue to be drained by allowing the receive 7162 * worker thread to read all messages from the rx-queue of the channel. 7163 * Assumption: further callbacks are disabled at this time. 7164 */ 7165 static void 7166 vgen_drain_rcv_thread(vgen_ldc_t *ldcp) 7167 { 7168 clock_t tm; 7169 clock_t wt; 7170 clock_t rv; 7171 7172 /* 7173 * If there is data in ldc rx queue, wait until the rx 7174 * worker thread runs and drains all msgs in the queue. 7175 */ 7176 wt = drv_usectohz(MILLISEC); 7177 7178 mutex_enter(&ldcp->rcv_thr_lock); 7179 7180 tm = ddi_get_lbolt() + wt; 7181 7182 /* 7183 * We need to check both bits - DATARCVD and PROCESSING, to be cleared. 7184 * If DATARCVD is set, that means the callback has signalled the worker 7185 * thread, but the worker hasn't started processing yet. If PROCESSING 7186 * is set, that means the thread is awake and processing. Note that the 7187 * DATARCVD state can only be seen once, as the assumption is that 7188 * further callbacks have been disabled at this point. 7189 */ 7190 while (ldcp->rcv_thr_flags & 7191 (VGEN_WTHR_DATARCVD | VGEN_WTHR_PROCESSING)) { 7192 rv = cv_timedwait(&ldcp->rcv_thr_cv, &ldcp->rcv_thr_lock, tm); 7193 if (rv == -1) { /* timeout */ 7194 /* 7195 * Note that the only way we return is due to a timeout; 7196 * we set the new time to wait, before we go back and 7197 * check the condition. The other(unlikely) possibility 7198 * is a premature wakeup(see cv_timedwait(9F)) in which 7199 * case we just continue to use the same time to wait. 7200 */ 7201 tm = ddi_get_lbolt() + wt; 7202 } 7203 } 7204 7205 mutex_exit(&ldcp->rcv_thr_lock); 7206 } 7207 7208 /* 7209 * vgen_dds_rx -- post DDS messages to vnet. 7210 */ 7211 static int 7212 vgen_dds_rx(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 7213 { 7214 vio_dds_msg_t *dmsg = (vio_dds_msg_t *)tagp; 7215 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 7216 7217 if (dmsg->dds_class != DDS_VNET_NIU) { 7218 DWARN(vgenp, ldcp, "Unknown DDS class, dropping"); 7219 return (EBADMSG); 7220 } 7221 vnet_dds_rx(vgenp->vnetp, dmsg); 7222 return (0); 7223 } 7224 7225 /* 7226 * vgen_dds_tx -- an interface called by vnet to send DDS messages. 7227 */ 7228 int 7229 vgen_dds_tx(void *arg, void *msg) 7230 { 7231 vgen_t *vgenp = arg; 7232 vio_dds_msg_t *dmsg = msg; 7233 vgen_portlist_t *plistp = &vgenp->vgenports; 7234 vgen_ldc_t *ldcp; 7235 vgen_ldclist_t *ldclp; 7236 int rv = EIO; 7237 7238 7239 READ_ENTER(&plistp->rwlock); 7240 ldclp = &(vgenp->vsw_portp->ldclist); 7241 READ_ENTER(&ldclp->rwlock); 7242 ldcp = ldclp->headp; 7243 if ((ldcp == NULL) || (ldcp->hphase != VH_DONE)) { 7244 goto vgen_dsend_exit; 7245 } 7246 7247 dmsg->tag.vio_sid = ldcp->local_sid; 7248 rv = vgen_sendmsg(ldcp, (caddr_t)dmsg, sizeof (vio_dds_msg_t), B_FALSE); 7249 if (rv != VGEN_SUCCESS) { 7250 rv = EIO; 7251 } else { 7252 rv = 0; 7253 } 7254 7255 vgen_dsend_exit: 7256 RW_EXIT(&ldclp->rwlock); 7257 RW_EXIT(&plistp->rwlock); 7258 return (rv); 7259 7260 } 7261 7262 static void 7263 vgen_ldc_reset(vgen_ldc_t *ldcp) 7264 { 7265 vnet_t *vnetp = LDC_TO_VNET(ldcp); 7266 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 7267 7268 ASSERT(MUTEX_HELD(&ldcp->cblock)); 7269 7270 if (ldcp->need_ldc_reset == B_TRUE) { 7271 /* another thread is already in the process of resetting */ 7272 return; 7273 } 7274 7275 /* Set the flag to indicate reset is in progress */ 7276 ldcp->need_ldc_reset = B_TRUE; 7277 7278 if (ldcp->portp == vgenp->vsw_portp) { 7279 mutex_exit(&ldcp->cblock); 7280 /* 7281 * Now cleanup any HIO resources; the above flag also tells 7282 * the code that handles dds messages to drop any new msgs 7283 * that arrive while we are cleaning up and resetting the 7284 * channel. 7285 */ 7286 vnet_dds_cleanup_hio(vnetp); 7287 mutex_enter(&ldcp->cblock); 7288 } 7289 7290 vgen_handshake_retry(ldcp); 7291 } 7292 7293 int 7294 vgen_enable_intr(void *arg) 7295 { 7296 vgen_port_t *portp = (vgen_port_t *)arg; 7297 vgen_ldclist_t *ldclp; 7298 vgen_ldc_t *ldcp; 7299 7300 ldclp = &portp->ldclist; 7301 READ_ENTER(&ldclp->rwlock); 7302 /* 7303 * NOTE: for now, we will assume we have a single channel. 7304 */ 7305 if (ldclp->headp == NULL) { 7306 RW_EXIT(&ldclp->rwlock); 7307 return (1); 7308 } 7309 ldcp = ldclp->headp; 7310 7311 mutex_enter(&ldcp->pollq_lock); 7312 ldcp->polling_on = B_FALSE; 7313 mutex_exit(&ldcp->pollq_lock); 7314 7315 RW_EXIT(&ldclp->rwlock); 7316 7317 return (0); 7318 } 7319 7320 int 7321 vgen_disable_intr(void *arg) 7322 { 7323 vgen_port_t *portp = (vgen_port_t *)arg; 7324 vgen_ldclist_t *ldclp; 7325 vgen_ldc_t *ldcp; 7326 7327 ldclp = &portp->ldclist; 7328 READ_ENTER(&ldclp->rwlock); 7329 /* 7330 * NOTE: for now, we will assume we have a single channel. 7331 */ 7332 if (ldclp->headp == NULL) { 7333 RW_EXIT(&ldclp->rwlock); 7334 return (1); 7335 } 7336 ldcp = ldclp->headp; 7337 7338 7339 mutex_enter(&ldcp->pollq_lock); 7340 ldcp->polling_on = B_TRUE; 7341 mutex_exit(&ldcp->pollq_lock); 7342 7343 RW_EXIT(&ldclp->rwlock); 7344 7345 return (0); 7346 } 7347 7348 mblk_t * 7349 vgen_poll(void *arg, int bytes_to_pickup) 7350 { 7351 vgen_port_t *portp = (vgen_port_t *)arg; 7352 vgen_ldclist_t *ldclp; 7353 vgen_ldc_t *ldcp; 7354 mblk_t *mp = NULL; 7355 7356 ldclp = &portp->ldclist; 7357 READ_ENTER(&ldclp->rwlock); 7358 /* 7359 * NOTE: for now, we will assume we have a single channel. 7360 */ 7361 if (ldclp->headp == NULL) { 7362 RW_EXIT(&ldclp->rwlock); 7363 return (NULL); 7364 } 7365 ldcp = ldclp->headp; 7366 7367 mp = vgen_ldc_poll(ldcp, bytes_to_pickup); 7368 7369 RW_EXIT(&ldclp->rwlock); 7370 return (mp); 7371 } 7372 7373 static mblk_t * 7374 vgen_ldc_poll(vgen_ldc_t *ldcp, int bytes_to_pickup) 7375 { 7376 mblk_t *bp = NULL; 7377 mblk_t *bpt = NULL; 7378 mblk_t *mp = NULL; 7379 size_t mblk_sz = 0; 7380 size_t sz = 0; 7381 uint_t count = 0; 7382 7383 mutex_enter(&ldcp->pollq_lock); 7384 7385 bp = ldcp->pollq_headp; 7386 while (bp != NULL) { 7387 /* get the size of this packet */ 7388 mblk_sz = msgdsize(bp); 7389 7390 /* if adding this pkt, exceeds the size limit, we are done. */ 7391 if (sz + mblk_sz > bytes_to_pickup) { 7392 break; 7393 } 7394 7395 /* we have room for this packet */ 7396 sz += mblk_sz; 7397 7398 /* increment the # of packets being sent up */ 7399 count++; 7400 7401 /* track the last processed pkt */ 7402 bpt = bp; 7403 7404 /* get the next pkt */ 7405 bp = bp->b_next; 7406 } 7407 7408 if (count != 0) { 7409 /* 7410 * picked up some packets; save the head of pkts to be sent up. 7411 */ 7412 mp = ldcp->pollq_headp; 7413 7414 /* move the pollq_headp to skip over the pkts being sent up */ 7415 ldcp->pollq_headp = bp; 7416 7417 /* picked up all pending pkts in the queue; reset tail also */ 7418 if (ldcp->pollq_headp == NULL) { 7419 ldcp->pollq_tailp = NULL; 7420 } 7421 7422 /* terminate the tail of pkts to be sent up */ 7423 bpt->b_next = NULL; 7424 } 7425 7426 mutex_exit(&ldcp->pollq_lock); 7427 7428 DTRACE_PROBE1(vgen_poll_pkts, uint_t, count); 7429 return (mp); 7430 } 7431 7432 #if DEBUG 7433 7434 /* 7435 * Print debug messages - set to 0xf to enable all msgs 7436 */ 7437 static void 7438 debug_printf(const char *fname, vgen_t *vgenp, 7439 vgen_ldc_t *ldcp, const char *fmt, ...) 7440 { 7441 char buf[256]; 7442 char *bufp = buf; 7443 va_list ap; 7444 7445 if ((vgenp != NULL) && (vgenp->vnetp != NULL)) { 7446 (void) sprintf(bufp, "vnet%d:", 7447 ((vnet_t *)(vgenp->vnetp))->instance); 7448 bufp += strlen(bufp); 7449 } 7450 if (ldcp != NULL) { 7451 (void) sprintf(bufp, "ldc(%ld):", ldcp->ldc_id); 7452 bufp += strlen(bufp); 7453 } 7454 (void) sprintf(bufp, "%s: ", fname); 7455 bufp += strlen(bufp); 7456 7457 va_start(ap, fmt); 7458 (void) vsprintf(bufp, fmt, ap); 7459 va_end(ap); 7460 7461 if ((ldcp == NULL) ||(vgendbg_ldcid == -1) || 7462 (vgendbg_ldcid == ldcp->ldc_id)) { 7463 cmn_err(CE_CONT, "%s\n", buf); 7464 } 7465 } 7466 #endif 7467 7468 #ifdef VNET_IOC_DEBUG 7469 7470 static void 7471 vgen_ioctl(void *arg, queue_t *q, mblk_t *mp) 7472 { 7473 struct iocblk *iocp; 7474 vgen_port_t *portp; 7475 enum ioc_reply { 7476 IOC_INVAL = -1, /* bad, NAK with EINVAL */ 7477 IOC_ACK /* OK, just send ACK */ 7478 } status; 7479 int rv; 7480 7481 iocp = (struct iocblk *)(uintptr_t)mp->b_rptr; 7482 iocp->ioc_error = 0; 7483 portp = (vgen_port_t *)arg; 7484 7485 if (portp == NULL) { 7486 status = IOC_INVAL; 7487 goto vgen_ioc_exit; 7488 } 7489 7490 mutex_enter(&portp->lock); 7491 7492 switch (iocp->ioc_cmd) { 7493 7494 case VNET_FORCE_LINK_DOWN: 7495 case VNET_FORCE_LINK_UP: 7496 rv = vgen_force_link_state(portp, iocp->ioc_cmd); 7497 (rv == 0) ? (status = IOC_ACK) : (status = IOC_INVAL); 7498 break; 7499 7500 default: 7501 status = IOC_INVAL; 7502 break; 7503 7504 } 7505 7506 mutex_exit(&portp->lock); 7507 7508 vgen_ioc_exit: 7509 7510 switch (status) { 7511 default: 7512 case IOC_INVAL: 7513 /* Error, reply with a NAK and EINVAL error */ 7514 miocnak(q, mp, 0, EINVAL); 7515 break; 7516 case IOC_ACK: 7517 /* OK, reply with an ACK */ 7518 miocack(q, mp, 0, 0); 7519 break; 7520 } 7521 } 7522 7523 static int 7524 vgen_force_link_state(vgen_port_t *portp, int cmd) 7525 { 7526 ldc_status_t istatus; 7527 vgen_ldclist_t *ldclp; 7528 vgen_ldc_t *ldcp; 7529 vgen_t *vgenp = portp->vgenp; 7530 int rv; 7531 7532 ldclp = &portp->ldclist; 7533 READ_ENTER(&ldclp->rwlock); 7534 7535 /* 7536 * NOTE: for now, we will assume we have a single channel. 7537 */ 7538 if (ldclp->headp == NULL) { 7539 RW_EXIT(&ldclp->rwlock); 7540 return (1); 7541 } 7542 ldcp = ldclp->headp; 7543 mutex_enter(&ldcp->cblock); 7544 7545 switch (cmd) { 7546 7547 case VNET_FORCE_LINK_DOWN: 7548 (void) ldc_down(ldcp->ldc_handle); 7549 ldcp->link_down_forced = B_TRUE; 7550 break; 7551 7552 case VNET_FORCE_LINK_UP: 7553 rv = ldc_up(ldcp->ldc_handle); 7554 if (rv != 0) { 7555 DWARN(vgenp, ldcp, "ldc_up err rv(%d)\n", rv); 7556 } 7557 ldcp->link_down_forced = B_FALSE; 7558 7559 if (ldc_status(ldcp->ldc_handle, &istatus) != 0) { 7560 DWARN(vgenp, ldcp, "ldc_status err\n"); 7561 } else { 7562 ldcp->ldc_status = istatus; 7563 } 7564 7565 /* if channel is already UP - restart handshake */ 7566 if (ldcp->ldc_status == LDC_UP) { 7567 vgen_handle_evt_up(ldcp); 7568 } 7569 break; 7570 7571 } 7572 7573 mutex_exit(&ldcp->cblock); 7574 RW_EXIT(&ldclp->rwlock); 7575 7576 return (0); 7577 } 7578 7579 #else 7580 7581 static void 7582 vgen_ioctl(void *arg, queue_t *q, mblk_t *mp) 7583 { 7584 vgen_port_t *portp; 7585 7586 portp = (vgen_port_t *)arg; 7587 7588 if (portp == NULL) { 7589 miocnak(q, mp, 0, EINVAL); 7590 return; 7591 } 7592 7593 miocnak(q, mp, 0, ENOTSUP); 7594 } 7595 7596 #endif 7597