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