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