1678453a8Sspeer /* 2678453a8Sspeer * CDDL HEADER START 3678453a8Sspeer * 4678453a8Sspeer * The contents of this file are subject to the terms of the 5678453a8Sspeer * Common Development and Distribution License (the "License"). 6678453a8Sspeer * You may not use this file except in compliance with the License. 7678453a8Sspeer * 8678453a8Sspeer * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9678453a8Sspeer * or http://www.opensolaris.org/os/licensing. 10678453a8Sspeer * See the License for the specific language governing permissions 11678453a8Sspeer * and limitations under the License. 12678453a8Sspeer * 13678453a8Sspeer * When distributing Covered Code, include this CDDL HEADER in each 14678453a8Sspeer * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15678453a8Sspeer * If applicable, add the following below this CDDL HEADER, with the 16678453a8Sspeer * fields enclosed by brackets "[]" replaced with your own identifying 17678453a8Sspeer * information: Portions Copyright [yyyy] [name of copyright owner] 18678453a8Sspeer * 19678453a8Sspeer * CDDL HEADER END 20678453a8Sspeer */ 21678453a8Sspeer 22678453a8Sspeer /* 23678453a8Sspeer * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24678453a8Sspeer * Use is subject to license terms. 25678453a8Sspeer */ 26678453a8Sspeer 27678453a8Sspeer /* 28678453a8Sspeer * nxge_hio_guest.c 29678453a8Sspeer * 30678453a8Sspeer * This file manages the virtualization resources for a guest domain. 31678453a8Sspeer * 32678453a8Sspeer */ 33678453a8Sspeer 34678453a8Sspeer #include <sys/nxge/nxge_impl.h> 35678453a8Sspeer #include <sys/nxge/nxge_fzc.h> 36678453a8Sspeer #include <sys/nxge/nxge_rxdma.h> 37678453a8Sspeer #include <sys/nxge/nxge_txdma.h> 38678453a8Sspeer 39678453a8Sspeer #include <sys/nxge/nxge_hio.h> 40678453a8Sspeer 41678453a8Sspeer /* 42678453a8Sspeer * nxge_hio_unregister 43678453a8Sspeer * 44678453a8Sspeer * Unregister with the VNET module. 45678453a8Sspeer * 46678453a8Sspeer * Arguments: 47678453a8Sspeer * nxge 48678453a8Sspeer * 49678453a8Sspeer * Notes: 50678453a8Sspeer * We must uninitialize all DMA channels associated with the VR, too. 51678453a8Sspeer * 52678453a8Sspeer * We're assuming that the channels will be disabled & unassigned 53678453a8Sspeer * in the service domain, after we're done here. 54678453a8Sspeer * 55678453a8Sspeer * Context: 56678453a8Sspeer * Guest domain 57678453a8Sspeer */ 58678453a8Sspeer void 59678453a8Sspeer nxge_hio_unregister( 60678453a8Sspeer nxge_t *nxge) 61678453a8Sspeer { 62678453a8Sspeer nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio; 63678453a8Sspeer 64678453a8Sspeer if (nhd == 0) { 65678453a8Sspeer return; 66678453a8Sspeer } 67678453a8Sspeer 68678453a8Sspeer #if defined(sun4v) 69678453a8Sspeer /* Unregister with vNet. */ 70678453a8Sspeer if (nhd->hio.vio.unregister) { 71678453a8Sspeer if (nxge->hio_vr) 72678453a8Sspeer (*nhd->hio.vio.unregister)(nxge->hio_vr->vhp); 73678453a8Sspeer } 74678453a8Sspeer #endif 75678453a8Sspeer } 76678453a8Sspeer 77678453a8Sspeer /* 78678453a8Sspeer * nxge_guest_regs_map 79678453a8Sspeer * 80678453a8Sspeer * Map in a guest domain's register set(s). 81678453a8Sspeer * 82678453a8Sspeer * Arguments: 83678453a8Sspeer * nxge 84678453a8Sspeer * 85678453a8Sspeer * Notes: 86678453a8Sspeer * Note that we set <is_vraddr> to TRUE. 87678453a8Sspeer * 88678453a8Sspeer * Context: 89678453a8Sspeer * Guest domain 90678453a8Sspeer */ 91678453a8Sspeer static ddi_device_acc_attr_t nxge_guest_register_access_attributes = { 92678453a8Sspeer DDI_DEVICE_ATTR_V0, 93678453a8Sspeer DDI_STRUCTURE_LE_ACC, 94678453a8Sspeer DDI_STRICTORDER_ACC, 95678453a8Sspeer }; 96678453a8Sspeer 97678453a8Sspeer int 98678453a8Sspeer nxge_guest_regs_map( 99678453a8Sspeer nxge_t *nxge) 100678453a8Sspeer { 101678453a8Sspeer dev_regs_t *regs; 102678453a8Sspeer off_t regsize; 103678453a8Sspeer int rv; 104678453a8Sspeer 105678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_guest_regs_map")); 106678453a8Sspeer 107678453a8Sspeer /* So we can allocate properly-aligned memory. */ 108678453a8Sspeer nxge->niu_type = N2_NIU; /* Version 1.0 only */ 109678453a8Sspeer nxge->function_num = nxge->instance; /* HIOXXX Looking for ideas. */ 110678453a8Sspeer 111678453a8Sspeer nxge->dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP); 112678453a8Sspeer regs = nxge->dev_regs; 113678453a8Sspeer 114678453a8Sspeer if ((rv = ddi_dev_regsize(nxge->dip, 0, ®size)) != DDI_SUCCESS) { 115678453a8Sspeer NXGE_ERROR_MSG((nxge, HIO_CTL, "ddi_dev_regsize() failed")); 116678453a8Sspeer return (NXGE_ERROR); 117678453a8Sspeer } 118678453a8Sspeer 119678453a8Sspeer rv = ddi_regs_map_setup(nxge->dip, 0, (caddr_t *)®s->nxge_regp, 0, 0, 120678453a8Sspeer &nxge_guest_register_access_attributes, ®s->nxge_regh); 121678453a8Sspeer 122678453a8Sspeer if (rv != DDI_SUCCESS) { 123678453a8Sspeer NXGE_ERROR_MSG((nxge, HIO_CTL, "ddi_regs_map_setup() failed")); 124678453a8Sspeer return (NXGE_ERROR); 125678453a8Sspeer } 126678453a8Sspeer 127678453a8Sspeer nxge->npi_handle.regh = regs->nxge_regh; 128678453a8Sspeer nxge->npi_handle.regp = (npi_reg_ptr_t)regs->nxge_regp; 129678453a8Sspeer nxge->npi_handle.is_vraddr = B_TRUE; 130678453a8Sspeer nxge->npi_handle.function.instance = nxge->instance; 131678453a8Sspeer nxge->npi_handle.function.function = nxge->function_num; 132678453a8Sspeer nxge->npi_handle.nxgep = (void *)nxge; 133678453a8Sspeer 134678453a8Sspeer /* NPI_REG_ADD_HANDLE_SET() */ 135678453a8Sspeer nxge->npi_reg_handle.regh = regs->nxge_regh; 136678453a8Sspeer nxge->npi_reg_handle.regp = (npi_reg_ptr_t)regs->nxge_regp; 137678453a8Sspeer nxge->npi_reg_handle.is_vraddr = B_TRUE; 138678453a8Sspeer nxge->npi_reg_handle.function.instance = nxge->instance; 139678453a8Sspeer nxge->npi_reg_handle.function.function = nxge->function_num; 140678453a8Sspeer nxge->npi_reg_handle.nxgep = (void *)nxge; 141678453a8Sspeer 142678453a8Sspeer /* NPI_VREG_ADD_HANDLE_SET() */ 143678453a8Sspeer nxge->npi_vreg_handle.regh = regs->nxge_regh; 144678453a8Sspeer nxge->npi_vreg_handle.regp = (npi_reg_ptr_t)regs->nxge_regp; 145678453a8Sspeer nxge->npi_vreg_handle.is_vraddr = B_TRUE; 146678453a8Sspeer nxge->npi_vreg_handle.function.instance = nxge->instance; 147678453a8Sspeer nxge->npi_vreg_handle.function.function = nxge->function_num; 148678453a8Sspeer nxge->npi_vreg_handle.nxgep = (void *)nxge; 149678453a8Sspeer 150678453a8Sspeer regs->nxge_vir_regp = regs->nxge_regp; 151678453a8Sspeer regs->nxge_vir_regh = regs->nxge_regh; 152678453a8Sspeer 153678453a8Sspeer /* 154678453a8Sspeer * We do NOT set the PCI, MSI-X, 2nd Virtualization, 155678453a8Sspeer * or FCODE reg variables. 156678453a8Sspeer */ 157678453a8Sspeer 158678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_guest_regs_map")); 159678453a8Sspeer 160678453a8Sspeer return (NXGE_OK); 161678453a8Sspeer } 162678453a8Sspeer 163678453a8Sspeer void 164678453a8Sspeer nxge_guest_regs_map_free( 165678453a8Sspeer nxge_t *nxge) 166678453a8Sspeer { 167678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_guest_regs_map_free")); 168678453a8Sspeer 169678453a8Sspeer if (nxge->dev_regs) { 170678453a8Sspeer if (nxge->dev_regs->nxge_regh) { 171678453a8Sspeer NXGE_DEBUG_MSG((nxge, DDI_CTL, 172678453a8Sspeer "==> nxge_unmap_regs: device registers")); 173678453a8Sspeer ddi_regs_map_free(&nxge->dev_regs->nxge_regh); 174678453a8Sspeer nxge->dev_regs->nxge_regh = NULL; 175678453a8Sspeer } 176678453a8Sspeer kmem_free(nxge->dev_regs, sizeof (dev_regs_t)); 177678453a8Sspeer nxge->dev_regs = 0; 178678453a8Sspeer } 179678453a8Sspeer 180678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_guest_regs_map_free")); 181678453a8Sspeer } 182678453a8Sspeer 183678453a8Sspeer #if defined(sun4v) 184678453a8Sspeer 185678453a8Sspeer /* 186678453a8Sspeer * ------------------------------------------------------------- 187678453a8Sspeer * Local prototypes 188678453a8Sspeer * ------------------------------------------------------------- 189678453a8Sspeer */ 190678453a8Sspeer static nxge_hio_dc_t *nxge_guest_dc_alloc( 191678453a8Sspeer nxge_t *, nxge_hio_vr_t *, nxge_grp_type_t); 192678453a8Sspeer 193678453a8Sspeer static void res_map_parse(nxge_t *, nxge_grp_type_t, uint64_t); 194678453a8Sspeer static void nxge_check_guest_state(nxge_hio_vr_t *); 195678453a8Sspeer 196678453a8Sspeer /* 197678453a8Sspeer * nxge_hio_vr_add 198678453a8Sspeer * 199678453a8Sspeer * If we have been given a virtualization region (VR), 200678453a8Sspeer * then initialize it. 201678453a8Sspeer * 202678453a8Sspeer * Arguments: 203678453a8Sspeer * nxge 204678453a8Sspeer * 205678453a8Sspeer * Notes: 206678453a8Sspeer * 207678453a8Sspeer * Context: 208678453a8Sspeer * Guest domain 209678453a8Sspeer */ 210678453a8Sspeer /* ARGSUSED */ 211678453a8Sspeer int 212678453a8Sspeer nxge_hio_vr_add( 213678453a8Sspeer nxge_t *nxge) 214678453a8Sspeer { 215678453a8Sspeer extern mac_callbacks_t nxge_m_callbacks; 216678453a8Sspeer 217678453a8Sspeer nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio; 218678453a8Sspeer nxge_hio_vr_t *vr; 219678453a8Sspeer nxge_hio_dc_t *dc; 220678453a8Sspeer 221678453a8Sspeer int *reg_val; 222678453a8Sspeer uint_t reg_len; 223678453a8Sspeer uint8_t vr_index; 224678453a8Sspeer 225678453a8Sspeer nxhv_vr_fp_t *fp; 226678453a8Sspeer uint64_t cookie, vr_address, vr_size; 227678453a8Sspeer 228678453a8Sspeer nxhv_dc_fp_t *tx, *rx; 229678453a8Sspeer uint64_t tx_map, rx_map; 230678453a8Sspeer 231678453a8Sspeer uint64_t hv_rv; 232678453a8Sspeer 233678453a8Sspeer /* Variables needed to register with vnet. */ 234678453a8Sspeer mac_register_t *mac_info; 235678453a8Sspeer ether_addr_t mac_addr; 236678453a8Sspeer nx_vio_fp_t *vio; 237678453a8Sspeer 238678453a8Sspeer int i; 239678453a8Sspeer 240678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_vr_add")); 241678453a8Sspeer 242678453a8Sspeer /* 243678453a8Sspeer * Get our HV cookie. 244678453a8Sspeer */ 245678453a8Sspeer if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxge->dip, 246678453a8Sspeer 0, "reg", ®_val, ®_len) != DDI_PROP_SUCCESS) { 247678453a8Sspeer NXGE_DEBUG_MSG((nxge, VPD_CTL, "`reg' property not found")); 248678453a8Sspeer return (NXGE_ERROR); 249678453a8Sspeer } 250678453a8Sspeer 251678453a8Sspeer cookie = (uint64_t)(reg_val[0]); 252678453a8Sspeer ddi_prop_free(reg_val); 253678453a8Sspeer 254678453a8Sspeer fp = &nhd->hio.vr; 255678453a8Sspeer hv_rv = (*fp->getinfo)(cookie, &vr_address, &vr_size); 256678453a8Sspeer if (hv_rv != 0) { 257678453a8Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 258678453a8Sspeer "vr->getinfo() failed")); 259678453a8Sspeer return (NXGE_ERROR); 260678453a8Sspeer } 261678453a8Sspeer 262678453a8Sspeer /* 263678453a8Sspeer * In the guest domain, we can use any VR data structure 264678453a8Sspeer * we want, because we're not supposed to know which VR 265678453a8Sspeer * the service domain has allocated to us. 266678453a8Sspeer * 267678453a8Sspeer * In the current version, the least significant nybble of 268678453a8Sspeer * the cookie is the VR region, but that could change 269678453a8Sspeer * very easily. 270678453a8Sspeer * 271678453a8Sspeer * In the future, a guest may have more than one VR allocated 272678453a8Sspeer * to it, which is why we go through this exercise. 273678453a8Sspeer */ 274678453a8Sspeer MUTEX_ENTER(&nhd->lock); 275678453a8Sspeer for (vr_index = 0; vr_index < FUNC_VIR_MAX; vr_index++) { 276678453a8Sspeer if (nhd->vr[vr_index].nxge == 0) { 277678453a8Sspeer nhd->vr[vr_index].nxge = (uintptr_t)nxge; 278678453a8Sspeer break; 279678453a8Sspeer } 280678453a8Sspeer } 281678453a8Sspeer MUTEX_EXIT(&nhd->lock); 282678453a8Sspeer 283678453a8Sspeer if (vr_index == FUNC_VIR_MAX) { 284678453a8Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_hio_vr_add " 285678453a8Sspeer "no VRs available")); 286678453a8Sspeer return (NXGE_ERROR); 287678453a8Sspeer } 288678453a8Sspeer 289678453a8Sspeer vr = &nhd->vr[vr_index]; 290678453a8Sspeer 291678453a8Sspeer vr->nxge = (uintptr_t)nxge; 292678453a8Sspeer vr->cookie = (uint32_t)cookie; 293678453a8Sspeer vr->address = vr_address; 294678453a8Sspeer vr->size = vr_size; 295678453a8Sspeer vr->region = vr_index; 296678453a8Sspeer 297678453a8Sspeer /* 298678453a8Sspeer * This is redundant data, but useful nonetheless. It helps 299678453a8Sspeer * us to keep track of which RDCs & TDCs belong to us. 300678453a8Sspeer */ 301678453a8Sspeer if (nxge->tx_set.lg.count == 0) 302678453a8Sspeer (void) nxge_grp_add(nxge, NXGE_TRANSMIT_GROUP); 303678453a8Sspeer if (nxge->rx_set.lg.count == 0) 304678453a8Sspeer (void) nxge_grp_add(nxge, NXGE_RECEIVE_GROUP); 305678453a8Sspeer 306678453a8Sspeer /* 307678453a8Sspeer * See nxge_intr.c. 308678453a8Sspeer */ 309678453a8Sspeer if (nxge_hio_intr_init(nxge) != NXGE_OK) { 310678453a8Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 311678453a8Sspeer "nxge_hio_intr_init() failed")); 312678453a8Sspeer return (NXGE_ERROR); 313678453a8Sspeer } 314678453a8Sspeer 315678453a8Sspeer /* 316678453a8Sspeer * Now we find out which RDCs & TDCs have been allocated to us. 317678453a8Sspeer */ 318678453a8Sspeer tx = &nhd->hio.tx; 319678453a8Sspeer if (tx->get_map) { 320678453a8Sspeer /* 321678453a8Sspeer * The map we get back is a bitmap of the 322678453a8Sspeer * virtual Tx DMA channels we own - 323678453a8Sspeer * they are NOT real channel numbers. 324678453a8Sspeer */ 325678453a8Sspeer hv_rv = (*tx->get_map)(vr->cookie, &tx_map); 326678453a8Sspeer if (hv_rv != 0) { 327678453a8Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 328678453a8Sspeer "tx->get_map() failed")); 329678453a8Sspeer return (NXGE_ERROR); 330678453a8Sspeer } 331678453a8Sspeer res_map_parse(nxge, NXGE_TRANSMIT_GROUP, tx_map); 332678453a8Sspeer 333678453a8Sspeer /* 334678453a8Sspeer * For each channel, mark these two fields 335678453a8Sspeer * while we have the VR data structure. 336678453a8Sspeer */ 337678453a8Sspeer for (i = 0; i < VP_CHANNEL_MAX; i++) { 338678453a8Sspeer if ((1 << i) & tx_map) { 339678453a8Sspeer dc = nxge_guest_dc_alloc(nxge, vr, 340678453a8Sspeer NXGE_TRANSMIT_GROUP); 341678453a8Sspeer if (dc == 0) { 342678453a8Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 343678453a8Sspeer "DC add failed")); 344678453a8Sspeer return (NXGE_ERROR); 345678453a8Sspeer } 346678453a8Sspeer dc->channel = (nxge_channel_t)i; 347678453a8Sspeer } 348678453a8Sspeer } 349678453a8Sspeer } 350678453a8Sspeer 351678453a8Sspeer rx = &nhd->hio.rx; 352678453a8Sspeer if (rx->get_map) { 353678453a8Sspeer /* 354678453a8Sspeer * I repeat, the map we get back is a bitmap of 355678453a8Sspeer * the virtual Rx DMA channels we own - 356678453a8Sspeer * they are NOT real channel numbers. 357678453a8Sspeer */ 358678453a8Sspeer hv_rv = (*rx->get_map)(vr->cookie, &rx_map); 359678453a8Sspeer if (hv_rv != 0) { 360678453a8Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 361678453a8Sspeer "rx->get_map() failed")); 362678453a8Sspeer return (NXGE_ERROR); 363678453a8Sspeer } 364678453a8Sspeer res_map_parse(nxge, NXGE_RECEIVE_GROUP, rx_map); 365678453a8Sspeer 366678453a8Sspeer /* 367678453a8Sspeer * For each channel, mark these two fields 368678453a8Sspeer * while we have the VR data structure. 369678453a8Sspeer */ 370678453a8Sspeer for (i = 0; i < VP_CHANNEL_MAX; i++) { 371678453a8Sspeer if ((1 << i) & rx_map) { 372678453a8Sspeer dc = nxge_guest_dc_alloc(nxge, vr, 373678453a8Sspeer NXGE_RECEIVE_GROUP); 374678453a8Sspeer if (dc == 0) { 375678453a8Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 376678453a8Sspeer "DC add failed")); 377678453a8Sspeer return (NXGE_ERROR); 378678453a8Sspeer } 379678453a8Sspeer dc->channel = (nxge_channel_t)i; 380678453a8Sspeer } 381678453a8Sspeer } 382678453a8Sspeer } 383678453a8Sspeer 384678453a8Sspeer /* 385678453a8Sspeer * Register with vnet. 386678453a8Sspeer */ 387678453a8Sspeer if ((mac_info = mac_alloc(MAC_VERSION)) == NULL) 388678453a8Sspeer return (NXGE_ERROR); 389678453a8Sspeer 390678453a8Sspeer mac_info->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 391678453a8Sspeer mac_info->m_driver = nxge; 392678453a8Sspeer mac_info->m_dip = nxge->dip; 393678453a8Sspeer mac_info->m_src_addr = KMEM_ZALLOC(MAXMACADDRLEN, KM_SLEEP); 394678453a8Sspeer mac_info->m_dst_addr = KMEM_ZALLOC(MAXMACADDRLEN, KM_SLEEP); 395678453a8Sspeer (void) memset(mac_info->m_src_addr, 0xff, sizeof (MAXMACADDRLEN)); 396678453a8Sspeer mac_info->m_callbacks = &nxge_m_callbacks; 397678453a8Sspeer mac_info->m_min_sdu = 0; 398678453a8Sspeer mac_info->m_max_sdu = NXGE_MTU_DEFAULT_MAX - 399678453a8Sspeer sizeof (struct ether_header) - ETHERFCSL - 4; 400678453a8Sspeer 401678453a8Sspeer (void) memset(&mac_addr, 0xff, sizeof (mac_addr)); 402678453a8Sspeer 403678453a8Sspeer /* Register with vio_net. */ 404678453a8Sspeer vio = &nhd->hio.vio; 405678453a8Sspeer if ((*vio->__register)(mac_info, VIO_NET_RES_HYBRID, 406678453a8Sspeer nxge->hio_mac_addr, mac_addr, &vr->vhp, &vio->cb)) { 407678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "HIO registration() failed")); 408678453a8Sspeer return (NXGE_ERROR); 409678453a8Sspeer } 410678453a8Sspeer 411678453a8Sspeer nxge->hio_vr = vr; /* For faster lookups. */ 412678453a8Sspeer 413678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_vr_add")); 414678453a8Sspeer 415678453a8Sspeer return (NXGE_OK); 416678453a8Sspeer } 417678453a8Sspeer 418678453a8Sspeer /* 419678453a8Sspeer * nxge_guest_dc_alloc 420678453a8Sspeer * 421678453a8Sspeer * Find a free nxge_hio_dc_t data structure. 422678453a8Sspeer * 423678453a8Sspeer * Arguments: 424678453a8Sspeer * nxge 425678453a8Sspeer * type TRANSMIT or RECEIVE. 426678453a8Sspeer * 427678453a8Sspeer * Notes: 428678453a8Sspeer * 429678453a8Sspeer * Context: 430678453a8Sspeer * Guest domain 431678453a8Sspeer */ 432678453a8Sspeer nxge_hio_dc_t * 433678453a8Sspeer nxge_guest_dc_alloc( 434678453a8Sspeer nxge_t *nxge, 435678453a8Sspeer nxge_hio_vr_t *vr, 436678453a8Sspeer nxge_grp_type_t type) 437678453a8Sspeer { 438678453a8Sspeer nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio; 439678453a8Sspeer nxge_hio_dc_t *dc; 440678453a8Sspeer int limit, i; 441678453a8Sspeer 442678453a8Sspeer /* 443678453a8Sspeer * In the guest domain, there may be more than one VR. 444678453a8Sspeer * each one of which will be using the same slots, or 445678453a8Sspeer * virtual channel numbers. So the <nhd>'s rdc & tdc 446678453a8Sspeer * tables must be shared. 447678453a8Sspeer */ 448678453a8Sspeer if (type == NXGE_TRANSMIT_GROUP) { 449678453a8Sspeer dc = &nhd->tdc[0]; 450678453a8Sspeer limit = NXGE_MAX_TDCS; 451678453a8Sspeer } else { 452678453a8Sspeer dc = &nhd->rdc[0]; 453678453a8Sspeer limit = NXGE_MAX_RDCS; 454678453a8Sspeer } 455678453a8Sspeer 456678453a8Sspeer MUTEX_ENTER(&nhd->lock); 457678453a8Sspeer for (i = 0; i < limit; i++, dc++) { 458678453a8Sspeer if (dc->vr == 0) { 459678453a8Sspeer dc->vr = vr; 460678453a8Sspeer dc->cookie = vr->cookie; 461678453a8Sspeer MUTEX_EXIT(&nhd->lock); 462678453a8Sspeer return (dc); 463678453a8Sspeer } 464678453a8Sspeer } 465678453a8Sspeer MUTEX_EXIT(&nhd->lock); 466678453a8Sspeer 467678453a8Sspeer return (0); 468678453a8Sspeer } 469678453a8Sspeer 470678453a8Sspeer /* 471678453a8Sspeer * res_map_parse 472678453a8Sspeer * 473678453a8Sspeer * Parse a resource map. The resources are DMA channels, receive 474678453a8Sspeer * or transmit, depending on <type>. 475678453a8Sspeer * 476678453a8Sspeer * Arguments: 477678453a8Sspeer * nxge 478678453a8Sspeer * type Transmit or receive. 479678453a8Sspeer * res_map The resource map to parse. 480678453a8Sspeer * 481678453a8Sspeer * Notes: 482678453a8Sspeer * 483678453a8Sspeer * Context: 484678453a8Sspeer * Guest domain 485678453a8Sspeer */ 486678453a8Sspeer void 487678453a8Sspeer res_map_parse( 488678453a8Sspeer nxge_t *nxge, 489678453a8Sspeer nxge_grp_type_t type, 490678453a8Sspeer uint64_t res_map) 491678453a8Sspeer { 492678453a8Sspeer uint8_t slots, mask, slot; 493678453a8Sspeer int first, count; 494678453a8Sspeer 495678453a8Sspeer nxge_hw_pt_cfg_t *hardware; 496678453a8Sspeer nxge_grp_t *group; 497678453a8Sspeer 498678453a8Sspeer /* Slots are numbered 0 - 7. */ 499678453a8Sspeer slots = (uint8_t)(res_map & 0xff); 500678453a8Sspeer 501678453a8Sspeer /* Count the number of bits in the bitmap. */ 502678453a8Sspeer for (slot = 0, count = 0, mask = 1; slot < 8; slot++) { 503678453a8Sspeer if (slots & mask) 504678453a8Sspeer count++; 505678453a8Sspeer if (count == 1) 506678453a8Sspeer first = slot; 507678453a8Sspeer mask <<= 1; 508678453a8Sspeer } 509678453a8Sspeer 510678453a8Sspeer hardware = &nxge->pt_config.hw_config; 511678453a8Sspeer group = (type == NXGE_TRANSMIT_GROUP) ? 512678453a8Sspeer nxge->tx_set.group[0] : nxge->rx_set.group[0]; 513678453a8Sspeer 514678453a8Sspeer /* 515678453a8Sspeer * A guest domain has one Tx & one Rx group, so far. 516678453a8Sspeer * In the future, there may be more than one. 517678453a8Sspeer */ 518678453a8Sspeer if (type == NXGE_TRANSMIT_GROUP) { 519678453a8Sspeer nxge_dma_pt_cfg_t *port = &nxge->pt_config; 520678453a8Sspeer 521678453a8Sspeer hardware->tdc.start = first; 522678453a8Sspeer hardware->tdc.count = count; 523678453a8Sspeer hardware->tdc.owned = count; 524678453a8Sspeer 525678453a8Sspeer group->map = slots; 526678453a8Sspeer 527678453a8Sspeer /* 528678453a8Sspeer * Pointless in a guest domain. This bitmap is used 529678453a8Sspeer * in only one place: nxge_txc_init(), 530678453a8Sspeer * a service-domain-only function. 531678453a8Sspeer */ 532678453a8Sspeer port->tx_dma_map = slots; 533678453a8Sspeer 534678453a8Sspeer nxge->tx_set.owned.map |= slots; 535678453a8Sspeer } else { 536678453a8Sspeer nxge_rdc_grp_t *rdc_grp = &nxge->pt_config.rdc_grps[0]; 537678453a8Sspeer 538678453a8Sspeer hardware->start_rdc = first; 539678453a8Sspeer hardware->max_rdcs = count; 540678453a8Sspeer 541678453a8Sspeer rdc_grp->start_rdc = (uint8_t)first; 542678453a8Sspeer rdc_grp->max_rdcs = (uint8_t)count; 543678453a8Sspeer rdc_grp->def_rdc = (uint8_t)first; 544678453a8Sspeer 545678453a8Sspeer rdc_grp->map = slots; 546678453a8Sspeer group->map = slots; 547678453a8Sspeer 548678453a8Sspeer nxge->rx_set.owned.map |= slots; 549678453a8Sspeer } 550678453a8Sspeer } 551678453a8Sspeer 552678453a8Sspeer /* 553678453a8Sspeer * nxge_hio_vr_release 554678453a8Sspeer * 555678453a8Sspeer * Release a virtualization region (VR). 556678453a8Sspeer * 557678453a8Sspeer * Arguments: 558678453a8Sspeer * nxge 559678453a8Sspeer * 560678453a8Sspeer * Notes: 561678453a8Sspeer * We must uninitialize all DMA channels associated with the VR, too. 562678453a8Sspeer * 563678453a8Sspeer * The service domain will re-initialize these DMA channels later. 564678453a8Sspeer * See nxge_hio.c:nxge_hio_share_free() for details. 565678453a8Sspeer * 566678453a8Sspeer * Context: 567678453a8Sspeer * Guest domain 568678453a8Sspeer */ 569678453a8Sspeer int 570678453a8Sspeer nxge_hio_vr_release( 571678453a8Sspeer nxge_t *nxge) 572678453a8Sspeer { 573678453a8Sspeer NXGE_DEBUG_MSG((nxge, MEM2_CTL, "==> nxge_hio_vr_release")); 574678453a8Sspeer 575678453a8Sspeer /* 576678453a8Sspeer * Uninitialize interrupts. 577678453a8Sspeer */ 578678453a8Sspeer nxge_hio_intr_uninit(nxge); 579678453a8Sspeer 580678453a8Sspeer /* 581678453a8Sspeer * Uninitialize the receive DMA channels. 582678453a8Sspeer */ 583678453a8Sspeer nxge_uninit_rxdma_channels(nxge); 584678453a8Sspeer 585678453a8Sspeer /* 586678453a8Sspeer * Uninitialize the transmit DMA channels. 587678453a8Sspeer */ 588678453a8Sspeer nxge_uninit_txdma_channels(nxge); 589678453a8Sspeer 5909d5b8bc5SMichael Speer /* 5919d5b8bc5SMichael Speer * Remove both groups. Assumption: only two groups! 5929d5b8bc5SMichael Speer */ 5939d5b8bc5SMichael Speer if (nxge->rx_set.group[0] != NULL) 594*6920a987SMisaki Miyashita nxge_grp_remove(nxge, nxge->rx_set.group[0]); 5959d5b8bc5SMichael Speer if (nxge->tx_set.group[0] != NULL) 596*6920a987SMisaki Miyashita nxge_grp_remove(nxge, nxge->tx_set.group[0]); 597678453a8Sspeer 598678453a8Sspeer NXGE_DEBUG_MSG((nxge, MEM2_CTL, "<== nxge_hio_vr_release")); 599678453a8Sspeer 600678453a8Sspeer return (NXGE_OK); 601678453a8Sspeer } 602678453a8Sspeer 603678453a8Sspeer #if defined(NIU_LP_WORKAROUND) 604678453a8Sspeer /* 605678453a8Sspeer * nxge_tdc_lp_conf 606678453a8Sspeer * 607678453a8Sspeer * Configure the logical pages for a TDC. 608678453a8Sspeer * 609678453a8Sspeer * Arguments: 610678453a8Sspeer * nxge 611678453a8Sspeer * channel The TDC to configure. 612678453a8Sspeer * 613678453a8Sspeer * Notes: 614678453a8Sspeer * 615678453a8Sspeer * Context: 616678453a8Sspeer * Guest domain 617678453a8Sspeer */ 618678453a8Sspeer nxge_status_t 619678453a8Sspeer nxge_tdc_lp_conf( 620678453a8Sspeer p_nxge_t nxge, 621678453a8Sspeer int channel) 622678453a8Sspeer { 623678453a8Sspeer nxge_hio_dc_t *dc; 624678453a8Sspeer nxge_dma_common_t *data; 625678453a8Sspeer nxge_dma_common_t *control; 626678453a8Sspeer tx_ring_t *ring; 627678453a8Sspeer 628678453a8Sspeer uint64_t hv_rv; 629678453a8Sspeer uint64_t ra, size; 630678453a8Sspeer 631678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_tdc_lp_conf")); 632678453a8Sspeer 633678453a8Sspeer ring = nxge->tx_rings->rings[channel]; 634678453a8Sspeer 635678453a8Sspeer if (ring->hv_set) { 636678453a8Sspeer /* This shouldn't happen. */ 637678453a8Sspeer return (NXGE_OK); 638678453a8Sspeer } 639678453a8Sspeer 640678453a8Sspeer if (!(dc = nxge_grp_dc_find(nxge, VP_BOUND_TX, channel))) 641678453a8Sspeer return (NXGE_ERROR); 642678453a8Sspeer 643678453a8Sspeer /* 644678453a8Sspeer * Initialize logical page 0 for data buffers. 645678453a8Sspeer * 646678453a8Sspeer * <orig_ioaddr_pp> & <orig_alength> are initialized in 647678453a8Sspeer * nxge_main.c:nxge_dma_mem_alloc(). 648678453a8Sspeer */ 649678453a8Sspeer data = nxge->tx_buf_pool_p->dma_buf_pool_p[channel]; 650678453a8Sspeer ring->hv_tx_buf_base_ioaddr_pp = (uint64_t)data->orig_ioaddr_pp; 651678453a8Sspeer ring->hv_tx_buf_ioaddr_size = (uint64_t)data->orig_alength; 652678453a8Sspeer 653678453a8Sspeer hv_rv = hv_niu_vrtx_logical_page_conf(dc->cookie, 654678453a8Sspeer (uint64_t)channel, 0, 655678453a8Sspeer ring->hv_tx_buf_base_ioaddr_pp, 656678453a8Sspeer ring->hv_tx_buf_ioaddr_size); 657678453a8Sspeer 658678453a8Sspeer if (hv_rv != 0) { 659678453a8Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 660678453a8Sspeer "<== nxge_tdc_lp_conf: channel %d " 661678453a8Sspeer "(page 0 data buf) hv: %d " 662678453a8Sspeer "ioaddr_pp $%p size 0x%llx ", 663678453a8Sspeer channel, hv_rv, 664678453a8Sspeer ring->hv_tx_buf_base_ioaddr_pp, 665678453a8Sspeer ring->hv_tx_buf_ioaddr_size)); 666678453a8Sspeer return (NXGE_ERROR | hv_rv); 667678453a8Sspeer } 668678453a8Sspeer 669678453a8Sspeer ra = size = 0; 670678453a8Sspeer hv_rv = hv_niu_vrtx_logical_page_info(dc->cookie, 671678453a8Sspeer (uint64_t)channel, 0, &ra, &size); 672678453a8Sspeer 673678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, 674678453a8Sspeer "==> nxge_tdc_lp_conf: channel %d " 675678453a8Sspeer "(page 0 data buf) hv_rv 0x%llx " 676678453a8Sspeer "set ioaddr_pp $%p set size 0x%llx " 677678453a8Sspeer "get ra ioaddr_pp $%p get size 0x%llx ", 678678453a8Sspeer channel, hv_rv, ring->hv_tx_buf_base_ioaddr_pp, 679678453a8Sspeer ring->hv_tx_buf_ioaddr_size, ra, size)); 680678453a8Sspeer 681678453a8Sspeer /* 682678453a8Sspeer * Initialize logical page 1 for control buffers. 683678453a8Sspeer */ 684678453a8Sspeer control = nxge->tx_cntl_pool_p->dma_buf_pool_p[channel]; 685678453a8Sspeer ring->hv_tx_cntl_base_ioaddr_pp = (uint64_t)control->orig_ioaddr_pp; 686678453a8Sspeer ring->hv_tx_cntl_ioaddr_size = (uint64_t)control->orig_alength; 687678453a8Sspeer 688678453a8Sspeer hv_rv = hv_niu_vrtx_logical_page_conf(dc->cookie, 689678453a8Sspeer (uint64_t)channel, (uint64_t)1, 690678453a8Sspeer ring->hv_tx_cntl_base_ioaddr_pp, 691678453a8Sspeer ring->hv_tx_cntl_ioaddr_size); 692678453a8Sspeer 693678453a8Sspeer if (hv_rv != 0) { 694678453a8Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 695678453a8Sspeer "<== nxge_tdc_lp_conf: channel %d " 696678453a8Sspeer "(page 1 cntl buf) hv_rv 0x%llx " 697678453a8Sspeer "ioaddr_pp $%p size 0x%llx ", 698678453a8Sspeer channel, hv_rv, 699678453a8Sspeer ring->hv_tx_cntl_base_ioaddr_pp, 700678453a8Sspeer ring->hv_tx_cntl_ioaddr_size)); 701678453a8Sspeer return (NXGE_ERROR | hv_rv); 702678453a8Sspeer } 703678453a8Sspeer 704678453a8Sspeer ra = size = 0; 705678453a8Sspeer hv_rv = hv_niu_vrtx_logical_page_info(dc->cookie, 706678453a8Sspeer (uint64_t)channel, (uint64_t)1, &ra, &size); 707678453a8Sspeer 708678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, 709678453a8Sspeer "==> nxge_tdc_lp_conf: channel %d " 710678453a8Sspeer "(page 1 cntl buf) hv_rv 0x%llx " 711678453a8Sspeer "set ioaddr_pp $%p set size 0x%llx " 712678453a8Sspeer "get ra ioaddr_pp $%p get size 0x%llx ", 713678453a8Sspeer channel, hv_rv, ring->hv_tx_cntl_base_ioaddr_pp, 714678453a8Sspeer ring->hv_tx_cntl_ioaddr_size, ra, size)); 715678453a8Sspeer 716678453a8Sspeer ring->hv_set = B_TRUE; 717678453a8Sspeer 718678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_tdc_lp_conf")); 719678453a8Sspeer 720678453a8Sspeer return (NXGE_OK); 721678453a8Sspeer } 722678453a8Sspeer 723678453a8Sspeer /* 724678453a8Sspeer * nxge_rdc_lp_conf 725678453a8Sspeer * 726678453a8Sspeer * Configure an RDC's logical pages. 727678453a8Sspeer * 728678453a8Sspeer * Arguments: 729678453a8Sspeer * nxge 730678453a8Sspeer * channel The RDC to configure. 731678453a8Sspeer * 732678453a8Sspeer * Notes: 733678453a8Sspeer * 734678453a8Sspeer * Context: 735678453a8Sspeer * Guest domain 736678453a8Sspeer */ 737678453a8Sspeer nxge_status_t 738678453a8Sspeer nxge_rdc_lp_conf( 739678453a8Sspeer p_nxge_t nxge, 740678453a8Sspeer int channel) 741678453a8Sspeer { 742678453a8Sspeer nxge_hio_dc_t *dc; 743678453a8Sspeer nxge_dma_common_t *data; 744678453a8Sspeer nxge_dma_common_t *control; 745678453a8Sspeer rx_rbr_ring_t *ring; 746678453a8Sspeer 747678453a8Sspeer uint64_t hv_rv; 748678453a8Sspeer uint64_t ra, size; 749678453a8Sspeer 750678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_rdc_lp_conf")); 751678453a8Sspeer 752678453a8Sspeer ring = nxge->rx_rbr_rings->rbr_rings[channel]; 753678453a8Sspeer 754678453a8Sspeer if (ring->hv_set) { 755678453a8Sspeer return (NXGE_OK); 756678453a8Sspeer } 757678453a8Sspeer 758678453a8Sspeer if (!(dc = nxge_grp_dc_find(nxge, VP_BOUND_RX, channel))) 759678453a8Sspeer return (NXGE_ERROR); 760678453a8Sspeer 761678453a8Sspeer /* 762678453a8Sspeer * Initialize logical page 0 for data buffers. 763678453a8Sspeer * 764678453a8Sspeer * <orig_ioaddr_pp> & <orig_alength> are initialized in 765678453a8Sspeer * nxge_main.c:nxge_dma_mem_alloc(). 766678453a8Sspeer */ 767678453a8Sspeer data = nxge->rx_buf_pool_p->dma_buf_pool_p[channel]; 768678453a8Sspeer ring->hv_rx_buf_base_ioaddr_pp = (uint64_t)data->orig_ioaddr_pp; 769678453a8Sspeer ring->hv_rx_buf_ioaddr_size = (uint64_t)data->orig_alength; 770678453a8Sspeer 771678453a8Sspeer hv_rv = hv_niu_vrrx_logical_page_conf(dc->cookie, 772678453a8Sspeer (uint64_t)channel, 0, 773678453a8Sspeer ring->hv_rx_buf_base_ioaddr_pp, 774678453a8Sspeer ring->hv_rx_buf_ioaddr_size); 775678453a8Sspeer 776678453a8Sspeer if (hv_rv != 0) { 777678453a8Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 778678453a8Sspeer "<== nxge_rdc_lp_conf: channel %d " 779678453a8Sspeer "(page 0 data buf) hv_rv 0x%llx " 780678453a8Sspeer "ioaddr_pp $%p size 0x%llx ", 781678453a8Sspeer channel, hv_rv, 782678453a8Sspeer ring->hv_rx_buf_base_ioaddr_pp, 783678453a8Sspeer ring->hv_rx_buf_ioaddr_size)); 784678453a8Sspeer return (NXGE_ERROR | hv_rv); 785678453a8Sspeer } 786678453a8Sspeer 787678453a8Sspeer ra = size = 0; 788678453a8Sspeer hv_rv = hv_niu_vrrx_logical_page_info(dc->cookie, 789678453a8Sspeer (uint64_t)channel, 0, &ra, &size); 790678453a8Sspeer 791678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, 792678453a8Sspeer "==> nxge_rdc_lp_conf: channel %d " 793678453a8Sspeer "(page 0 data buf) hv_rv 0x%llx " 794678453a8Sspeer "set ioaddr_pp $%p set size 0x%llx " 795678453a8Sspeer "get ra ioaddr_pp $%p get size 0x%llx ", 796678453a8Sspeer channel, hv_rv, ring->hv_rx_buf_base_ioaddr_pp, 797678453a8Sspeer ring->hv_rx_buf_ioaddr_size, ra, size)); 798678453a8Sspeer 799678453a8Sspeer /* 800678453a8Sspeer * Initialize logical page 1 for control buffers. 801678453a8Sspeer */ 802678453a8Sspeer control = nxge->rx_cntl_pool_p->dma_buf_pool_p[channel]; 803678453a8Sspeer ring->hv_rx_cntl_base_ioaddr_pp = (uint64_t)control->orig_ioaddr_pp; 804678453a8Sspeer ring->hv_rx_cntl_ioaddr_size = (uint64_t)control->orig_alength; 805678453a8Sspeer 806678453a8Sspeer hv_rv = hv_niu_vrrx_logical_page_conf(dc->cookie, 807678453a8Sspeer (uint64_t)channel, (uint64_t)1, 808678453a8Sspeer ring->hv_rx_cntl_base_ioaddr_pp, 809678453a8Sspeer ring->hv_rx_cntl_ioaddr_size); 810678453a8Sspeer 811678453a8Sspeer if (hv_rv != 0) { 812678453a8Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 813678453a8Sspeer "<== nxge_rdc_lp_conf: channel %d " 814678453a8Sspeer "(page 1 cntl buf) hv_rv 0x%llx " 815678453a8Sspeer "ioaddr_pp $%p size 0x%llx ", 816678453a8Sspeer channel, hv_rv, 817678453a8Sspeer ring->hv_rx_cntl_base_ioaddr_pp, 818678453a8Sspeer ring->hv_rx_cntl_ioaddr_size)); 819678453a8Sspeer return (NXGE_ERROR | hv_rv); 820678453a8Sspeer } 821678453a8Sspeer 822678453a8Sspeer ra = size = 0; 823678453a8Sspeer hv_rv = hv_niu_vrrx_logical_page_info(dc->cookie, 824678453a8Sspeer (uint64_t)channel, (uint64_t)1, &ra, &size); 825678453a8Sspeer 826678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, 827678453a8Sspeer "==> nxge_rdc_lp_conf: channel %d " 828678453a8Sspeer "(page 1 cntl buf) hv_rv 0x%llx " 829678453a8Sspeer "set ioaddr_pp $%p set size 0x%llx " 830678453a8Sspeer "get ra ioaddr_pp $%p get size 0x%llx ", 831678453a8Sspeer channel, hv_rv, ring->hv_rx_cntl_base_ioaddr_pp, 832678453a8Sspeer ring->hv_rx_cntl_ioaddr_size, ra, size)); 833678453a8Sspeer 834678453a8Sspeer ring->hv_set = B_TRUE; 835678453a8Sspeer 836678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_rdc_lp_conf")); 837678453a8Sspeer 838678453a8Sspeer return (NXGE_OK); 839678453a8Sspeer } 840678453a8Sspeer #endif /* defined(NIU_LP_WORKAROUND) */ 841678453a8Sspeer 842678453a8Sspeer /* 843678453a8Sspeer * This value is in milliseconds. 844678453a8Sspeer */ 845678453a8Sspeer #define NXGE_GUEST_TIMER 500 /* 1/2 second, for now */ 846678453a8Sspeer 847678453a8Sspeer /* 848678453a8Sspeer * nxge_hio_start_timer 849678453a8Sspeer * 850678453a8Sspeer * Start the timer which checks for Tx hangs. 851678453a8Sspeer * 852678453a8Sspeer * Arguments: 853678453a8Sspeer * nxge 854678453a8Sspeer * 855678453a8Sspeer * Notes: 856678453a8Sspeer * This function is called from nxge_attach(). 857678453a8Sspeer * 858678453a8Sspeer * This function kicks off the guest domain equivalent of 859678453a8Sspeer * nxge_check_hw_state(). It is called only once, from attach. 860678453a8Sspeer * 861678453a8Sspeer * Context: 862678453a8Sspeer * Guest domain 863678453a8Sspeer */ 864678453a8Sspeer void 865678453a8Sspeer nxge_hio_start_timer( 866678453a8Sspeer nxge_t *nxge) 867678453a8Sspeer { 868678453a8Sspeer nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio; 869678453a8Sspeer nxge_hio_vr_t *vr; 870678453a8Sspeer int region; 871678453a8Sspeer 872678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_timer_start")); 873678453a8Sspeer 874678453a8Sspeer MUTEX_ENTER(&nhd->lock); 875678453a8Sspeer 876678453a8Sspeer /* 877678453a8Sspeer * Find our VR data structure. (We are currently assuming 878678453a8Sspeer * one VR per guest domain. That may change in the future.) 879678453a8Sspeer */ 880678453a8Sspeer for (region = FUNC0_VIR0; region < NXGE_VR_SR_MAX; region++) { 881678453a8Sspeer if (nhd->vr[region].nxge == (uintptr_t)nxge) 882678453a8Sspeer break; 883678453a8Sspeer } 884678453a8Sspeer 885678453a8Sspeer MUTEX_EXIT(&nhd->lock); 886678453a8Sspeer 887678453a8Sspeer if (region == NXGE_VR_SR_MAX) { 888678453a8Sspeer return; 889678453a8Sspeer } 890678453a8Sspeer 891678453a8Sspeer vr = (nxge_hio_vr_t *)&nhd->vr[region]; 892678453a8Sspeer 893678453a8Sspeer nxge->nxge_timerid = timeout((void(*)(void *))nxge_check_guest_state, 894678453a8Sspeer (void *)vr, drv_usectohz(1000 * NXGE_GUEST_TIMER)); 895678453a8Sspeer 896678453a8Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_timer_start")); 897678453a8Sspeer } 898678453a8Sspeer 899678453a8Sspeer /* 900678453a8Sspeer * nxge_check_guest_state 901678453a8Sspeer * 902678453a8Sspeer * Essentially, check for Tx hangs. In the future, if we are 903678453a8Sspeer * polling the hardware, we may do so here. 904678453a8Sspeer * 905678453a8Sspeer * Arguments: 906678453a8Sspeer * vr The virtualization region (VR) data structure. 907678453a8Sspeer * 908678453a8Sspeer * Notes: 909678453a8Sspeer * This function is the guest domain equivalent of 910678453a8Sspeer * nxge_check_hw_state(). Since we have no hardware to 911678453a8Sspeer * check, we simply call nxge_check_tx_hang(). 912678453a8Sspeer * 913678453a8Sspeer * Context: 914678453a8Sspeer * Guest domain 915678453a8Sspeer */ 916678453a8Sspeer void 917678453a8Sspeer nxge_check_guest_state( 918678453a8Sspeer nxge_hio_vr_t *vr) 919678453a8Sspeer { 920678453a8Sspeer nxge_t *nxge = (nxge_t *)vr->nxge; 921678453a8Sspeer 922678453a8Sspeer NXGE_DEBUG_MSG((nxge, SYSERR_CTL, "==> nxge_check_guest_state")); 923678453a8Sspeer 924678453a8Sspeer MUTEX_ENTER(nxge->genlock); 925678453a8Sspeer 926678453a8Sspeer nxge->nxge_timerid = 0; 927678453a8Sspeer 928d7cf53fcSmisaki Miyashita if (nxge->nxge_mac_state == NXGE_MAC_STARTED) { 929d7cf53fcSmisaki Miyashita nxge_check_tx_hang(nxge); 930678453a8Sspeer 931d7cf53fcSmisaki Miyashita nxge->nxge_timerid = timeout((void(*)(void *)) 932d7cf53fcSmisaki Miyashita nxge_check_guest_state, (caddr_t)vr, 933d7cf53fcSmisaki Miyashita drv_usectohz(1000 * NXGE_GUEST_TIMER)); 934d7cf53fcSmisaki Miyashita } 935678453a8Sspeer 936678453a8Sspeer nxge_check_guest_state_exit: 937678453a8Sspeer MUTEX_EXIT(nxge->genlock); 938678453a8Sspeer NXGE_DEBUG_MSG((nxge, SYSERR_CTL, "<== nxge_check_guest_state")); 939678453a8Sspeer } 940678453a8Sspeer 941678453a8Sspeer #endif /* defined(sun4v) */ 942