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