18275SEric Cheng /* 28275SEric Cheng * CDDL HEADER START 38275SEric Cheng * 48275SEric Cheng * The contents of this file are subject to the terms of the 58275SEric Cheng * Common Development and Distribution License (the "License"). 68275SEric Cheng * You may not use this file except in compliance with the License. 78275SEric Cheng * 88275SEric Cheng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 98275SEric Cheng * or http://www.opensolaris.org/os/licensing. 108275SEric Cheng * See the License for the specific language governing permissions 118275SEric Cheng * and limitations under the License. 128275SEric Cheng * 138275SEric Cheng * When distributing Covered Code, include this CDDL HEADER in each 148275SEric Cheng * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 158275SEric Cheng * If applicable, add the following below this CDDL HEADER, with the 168275SEric Cheng * fields enclosed by brackets "[]" replaced with your own identifying 178275SEric Cheng * information: Portions Copyright [yyyy] [name of copyright owner] 188275SEric Cheng * 198275SEric Cheng * CDDL HEADER END 208275SEric Cheng */ 218275SEric Cheng /* 228275SEric Cheng * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 238275SEric Cheng * Use is subject to license terms. 248275SEric Cheng */ 258275SEric Cheng 268275SEric Cheng /* 278275SEric Cheng * MAC Hybrid I/O related code. 288275SEric Cheng */ 298275SEric Cheng 308275SEric Cheng #include <sys/types.h> 318275SEric Cheng #include <sys/sdt.h> 328275SEric Cheng #include <sys/mac.h> 338275SEric Cheng #include <sys/mac_impl.h> 348275SEric Cheng #include <sys/mac_client_impl.h> 358275SEric Cheng #include <sys/mac_soft_ring.h> 368275SEric Cheng 378275SEric Cheng 388275SEric Cheng /* 398275SEric Cheng * Return the number of shares supported by the specified MAC. 408275SEric Cheng */ 418275SEric Cheng int 428275SEric Cheng mac_share_capable(mac_handle_t mh) 438275SEric Cheng { 448275SEric Cheng mac_impl_t *mip = (mac_impl_t *)mh; 458275SEric Cheng 468275SEric Cheng return (mip->mi_share_capab.ms_snum); 478275SEric Cheng } 488275SEric Cheng 498275SEric Cheng 508275SEric Cheng /* 518275SEric Cheng * Allocate a share to the specified MAC client. Invoked when 528275SEric Cheng * mac_client_open() is invoked with MAC_OPEN_FLAGS_SHARES_DESIRED set. 538275SEric Cheng */ 548275SEric Cheng void 558275SEric Cheng i_mac_share_alloc(mac_client_impl_t *mcip) 568275SEric Cheng { 578275SEric Cheng mac_impl_t *mip = mcip->mci_mip; 588275SEric Cheng int rv; 598275SEric Cheng 608275SEric Cheng i_mac_perim_enter(mip); 618275SEric Cheng 628275SEric Cheng ASSERT(mcip->mci_share == NULL); 638275SEric Cheng 648275SEric Cheng if (mac_share_capable((mac_handle_t)mcip->mci_mip) == 0) { 658275SEric Cheng DTRACE_PROBE1(i__mac__share__alloc__not__sup, 668275SEric Cheng mac_client_impl_t *, mcip); 678275SEric Cheng i_mac_perim_exit(mip); 688275SEric Cheng return; 698275SEric Cheng } 708275SEric Cheng 718275SEric Cheng rv = mip->mi_share_capab.ms_salloc(mip->mi_share_capab.ms_handle, 728275SEric Cheng &mcip->mci_share); 738275SEric Cheng DTRACE_PROBE3(i__mac__share__alloc, mac_client_impl_t *, mcip, 748275SEric Cheng int, rv, mac_share_handle_t, mcip->mci_share); 758275SEric Cheng 76*8400SNicolas.Droux@Sun.COM mcip->mci_state_flags &= ~MCIS_SHARE_BOUND; 778275SEric Cheng 788275SEric Cheng i_mac_perim_exit(mip); 798275SEric Cheng } 808275SEric Cheng 818275SEric Cheng 828275SEric Cheng /* 838275SEric Cheng * Free a share previously allocated through i_mac_share_alloc(). 848275SEric Cheng * Safely handles the case when no shares were allocated to the MAC client. 858275SEric Cheng */ 868275SEric Cheng void 878275SEric Cheng i_mac_share_free(mac_client_impl_t *mcip) 888275SEric Cheng { 898275SEric Cheng mac_impl_t *mip = mcip->mci_mip; 908275SEric Cheng 918275SEric Cheng i_mac_perim_enter(mip); 928275SEric Cheng 938275SEric Cheng /* MAC clients are required to unbind they shares before freeing them */ 94*8400SNicolas.Droux@Sun.COM ASSERT((mcip->mci_state_flags & MCIS_SHARE_BOUND) == 0); 958275SEric Cheng 968275SEric Cheng if (mcip->mci_share == NULL) { 978275SEric Cheng i_mac_perim_exit(mip); 988275SEric Cheng return; 998275SEric Cheng } 1008275SEric Cheng 1018275SEric Cheng mip->mi_share_capab.ms_sfree(mcip->mci_share); 1028275SEric Cheng i_mac_perim_exit(mip); 1038275SEric Cheng } 1048275SEric Cheng 1058275SEric Cheng 1068275SEric Cheng /* 1078275SEric Cheng * Bind a share. After this operation the rings that were associated 1088275SEric Cheng * with the MAC client are mapped directly into the corresponding 1098275SEric Cheng * guest domain. 1108275SEric Cheng */ 1118275SEric Cheng int 1128275SEric Cheng mac_share_bind(mac_client_handle_t mch, uint64_t cookie, uint64_t *rcookie) 1138275SEric Cheng { 1148275SEric Cheng mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 1158275SEric Cheng mac_impl_t *mip = mcip->mci_mip; 1168275SEric Cheng int rv; 1178275SEric Cheng 1188275SEric Cheng i_mac_perim_enter(mip); 1198275SEric Cheng 1208275SEric Cheng if (mcip->mci_share == NULL) { 1218275SEric Cheng i_mac_perim_exit(mip); 1228275SEric Cheng return (ENOTSUP); 1238275SEric Cheng } 1248275SEric Cheng 125*8400SNicolas.Droux@Sun.COM ASSERT((mcip->mci_state_flags & MCIS_SHARE_BOUND) == 0); 1268275SEric Cheng 1278275SEric Cheng /* 1288275SEric Cheng * Temporarly suspend the TX traffic for that client to make sure 1298275SEric Cheng * there are no in flight packets through a transmit ring 1308275SEric Cheng * which is being bound to another domain. 1318275SEric Cheng */ 1328275SEric Cheng mac_tx_client_quiesce(mcip, SRS_QUIESCE); 1338275SEric Cheng 1348275SEric Cheng /* 1358275SEric Cheng * For the receive path, no traffic will be sent up through 1368275SEric Cheng * the rings to the IO domain. For TX, we need to ensure 1378275SEric Cheng * that traffic sent by the MAC client are sent through 1388275SEric Cheng * the default ring. 1398275SEric Cheng * 140*8400SNicolas.Droux@Sun.COM * For the transmit path we ensure that packets are sent through the 141*8400SNicolas.Droux@Sun.COM * default ring if the share of the MAC client is bound, see MAC_TX(). 1428275SEric Cheng */ 1438275SEric Cheng 1448275SEric Cheng rv = mip->mi_share_capab.ms_sbind(mcip->mci_share, cookie, rcookie); 1458275SEric Cheng if (rv == 0) 146*8400SNicolas.Droux@Sun.COM mcip->mci_state_flags |= MCIS_SHARE_BOUND; 1478275SEric Cheng 1488275SEric Cheng /* 149*8400SNicolas.Droux@Sun.COM * Resume transmit traffic for the MAC client. 1508275SEric Cheng */ 1518275SEric Cheng mac_tx_client_restart(mcip); 1528275SEric Cheng 1538275SEric Cheng i_mac_perim_exit(mip); 1548275SEric Cheng 1558275SEric Cheng return (rv); 1568275SEric Cheng } 1578275SEric Cheng 1588275SEric Cheng 1598275SEric Cheng /* 1608275SEric Cheng * Unbind a share. 1618275SEric Cheng */ 1628275SEric Cheng void 1638275SEric Cheng mac_share_unbind(mac_client_handle_t mch) 1648275SEric Cheng { 1658275SEric Cheng mac_client_impl_t *mcip = (mac_client_impl_t *)mch; 1668275SEric Cheng mac_impl_t *mip = mcip->mci_mip; 1678275SEric Cheng 1688275SEric Cheng i_mac_perim_enter(mip); 1698275SEric Cheng 1708275SEric Cheng if (mcip->mci_share == NULL) { 1718275SEric Cheng i_mac_perim_exit(mip); 1728275SEric Cheng return; 1738275SEric Cheng } 1748275SEric Cheng 1758275SEric Cheng mip->mi_share_capab.ms_sunbind(mcip->mci_share); 1768275SEric Cheng 177*8400SNicolas.Droux@Sun.COM mcip->mci_state_flags &= ~MCIS_SHARE_BOUND; 178*8400SNicolas.Droux@Sun.COM 179*8400SNicolas.Droux@Sun.COM /* 180*8400SNicolas.Droux@Sun.COM * If the link state changed while the share was bound, the 181*8400SNicolas.Droux@Sun.COM * soft rings fanout associated with the client would have not 182*8400SNicolas.Droux@Sun.COM * been updated by mac_fanout_recompute(). Do the check here 183*8400SNicolas.Droux@Sun.COM * now that the share has been unbound. 184*8400SNicolas.Droux@Sun.COM */ 185*8400SNicolas.Droux@Sun.COM mac_fanout_recompute_client(mcip); 1868275SEric Cheng 1878275SEric Cheng i_mac_perim_exit(mip); 1888275SEric Cheng } 189