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 /*
22*11878SVenu.Iyer@Sun.COM * Copyright 2010 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>
35*11878SVenu.Iyer@Sun.COM #include <sys/mac_client_priv.h>
368275SEric Cheng #include <sys/mac_soft_ring.h>
378275SEric Cheng
388275SEric Cheng
398275SEric Cheng /*
408275SEric Cheng * Return the number of shares supported by the specified MAC.
418275SEric Cheng */
428275SEric Cheng int
mac_share_capable(mac_handle_t mh)438275SEric Cheng mac_share_capable(mac_handle_t mh)
448275SEric Cheng {
458275SEric Cheng mac_impl_t *mip = (mac_impl_t *)mh;
468275SEric Cheng
478275SEric Cheng return (mip->mi_share_capab.ms_snum);
488275SEric Cheng }
498275SEric Cheng
508275SEric Cheng
518275SEric Cheng /*
528275SEric Cheng * Allocate a share to the specified MAC client. Invoked when
538275SEric Cheng * mac_client_open() is invoked with MAC_OPEN_FLAGS_SHARES_DESIRED set.
548275SEric Cheng */
558275SEric Cheng void
i_mac_share_alloc(mac_client_impl_t * mcip)568275SEric Cheng i_mac_share_alloc(mac_client_impl_t *mcip)
578275SEric Cheng {
588275SEric Cheng mac_impl_t *mip = mcip->mci_mip;
598275SEric Cheng int rv;
608275SEric Cheng
618275SEric Cheng i_mac_perim_enter(mip);
628275SEric Cheng
638275SEric Cheng ASSERT(mcip->mci_share == NULL);
648275SEric Cheng
658275SEric Cheng if (mac_share_capable((mac_handle_t)mcip->mci_mip) == 0) {
668275SEric Cheng DTRACE_PROBE1(i__mac__share__alloc__not__sup,
678275SEric Cheng mac_client_impl_t *, mcip);
688275SEric Cheng i_mac_perim_exit(mip);
698275SEric Cheng return;
708275SEric Cheng }
718275SEric Cheng
728275SEric Cheng rv = mip->mi_share_capab.ms_salloc(mip->mi_share_capab.ms_handle,
738275SEric Cheng &mcip->mci_share);
748275SEric Cheng DTRACE_PROBE3(i__mac__share__alloc, mac_client_impl_t *, mcip,
758275SEric Cheng int, rv, mac_share_handle_t, mcip->mci_share);
768275SEric Cheng
778400SNicolas.Droux@Sun.COM mcip->mci_state_flags &= ~MCIS_SHARE_BOUND;
788275SEric Cheng
798275SEric Cheng i_mac_perim_exit(mip);
808275SEric Cheng }
818275SEric Cheng
828275SEric Cheng
838275SEric Cheng /*
848275SEric Cheng * Free a share previously allocated through i_mac_share_alloc().
858275SEric Cheng * Safely handles the case when no shares were allocated to the MAC client.
868275SEric Cheng */
878275SEric Cheng void
i_mac_share_free(mac_client_impl_t * mcip)888275SEric Cheng i_mac_share_free(mac_client_impl_t *mcip)
898275SEric Cheng {
908275SEric Cheng mac_impl_t *mip = mcip->mci_mip;
918275SEric Cheng
928275SEric Cheng i_mac_perim_enter(mip);
938275SEric Cheng
948275SEric Cheng /* MAC clients are required to unbind they shares before freeing them */
958400SNicolas.Droux@Sun.COM ASSERT((mcip->mci_state_flags & MCIS_SHARE_BOUND) == 0);
968275SEric Cheng
978275SEric Cheng if (mcip->mci_share == NULL) {
988275SEric Cheng i_mac_perim_exit(mip);
998275SEric Cheng return;
1008275SEric Cheng }
1018275SEric Cheng
1028275SEric Cheng mip->mi_share_capab.ms_sfree(mcip->mci_share);
1038275SEric Cheng i_mac_perim_exit(mip);
1048275SEric Cheng }
1058275SEric Cheng
1068275SEric Cheng
1078275SEric Cheng /*
1088275SEric Cheng * Bind a share. After this operation the rings that were associated
1098275SEric Cheng * with the MAC client are mapped directly into the corresponding
1108275SEric Cheng * guest domain.
1118275SEric Cheng */
1128275SEric Cheng int
mac_share_bind(mac_client_handle_t mch,uint64_t cookie,uint64_t * rcookie)1138275SEric Cheng mac_share_bind(mac_client_handle_t mch, uint64_t cookie, uint64_t *rcookie)
1148275SEric Cheng {
1158275SEric Cheng mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
1168275SEric Cheng mac_impl_t *mip = mcip->mci_mip;
1178275SEric Cheng int rv;
1188275SEric Cheng
1198275SEric Cheng i_mac_perim_enter(mip);
1208275SEric Cheng
1218275SEric Cheng if (mcip->mci_share == NULL) {
1228275SEric Cheng i_mac_perim_exit(mip);
1238275SEric Cheng return (ENOTSUP);
1248275SEric Cheng }
1258275SEric Cheng
1268400SNicolas.Droux@Sun.COM ASSERT((mcip->mci_state_flags & MCIS_SHARE_BOUND) == 0);
1278275SEric Cheng
1288275SEric Cheng /*
1298275SEric Cheng * Temporarly suspend the TX traffic for that client to make sure
1308275SEric Cheng * there are no in flight packets through a transmit ring
1318275SEric Cheng * which is being bound to another domain.
1328275SEric Cheng */
133*11878SVenu.Iyer@Sun.COM mac_tx_client_quiesce(mch);
1348275SEric Cheng
1358275SEric Cheng /*
1368275SEric Cheng * For the receive path, no traffic will be sent up through
1378275SEric Cheng * the rings to the IO domain. For TX, we need to ensure
1388275SEric Cheng * that traffic sent by the MAC client are sent through
1398275SEric Cheng * the default ring.
1408275SEric Cheng *
1418400SNicolas.Droux@Sun.COM * For the transmit path we ensure that packets are sent through the
1428400SNicolas.Droux@Sun.COM * default ring if the share of the MAC client is bound, see MAC_TX().
1438275SEric Cheng */
1448275SEric Cheng
1458275SEric Cheng rv = mip->mi_share_capab.ms_sbind(mcip->mci_share, cookie, rcookie);
1468275SEric Cheng if (rv == 0)
1478400SNicolas.Droux@Sun.COM mcip->mci_state_flags |= MCIS_SHARE_BOUND;
1488275SEric Cheng
1498275SEric Cheng /*
1508400SNicolas.Droux@Sun.COM * Resume transmit traffic for the MAC client.
1518275SEric Cheng */
152*11878SVenu.Iyer@Sun.COM mac_tx_client_restart(mch);
1538275SEric Cheng
1548275SEric Cheng i_mac_perim_exit(mip);
1558275SEric Cheng
1568275SEric Cheng return (rv);
1578275SEric Cheng }
1588275SEric Cheng
1598275SEric Cheng
1608275SEric Cheng /*
1618275SEric Cheng * Unbind a share.
1628275SEric Cheng */
1638275SEric Cheng void
mac_share_unbind(mac_client_handle_t mch)1648275SEric Cheng mac_share_unbind(mac_client_handle_t mch)
1658275SEric Cheng {
1668275SEric Cheng mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
1678275SEric Cheng mac_impl_t *mip = mcip->mci_mip;
1688275SEric Cheng
1698275SEric Cheng i_mac_perim_enter(mip);
1708275SEric Cheng
1718275SEric Cheng if (mcip->mci_share == NULL) {
1728275SEric Cheng i_mac_perim_exit(mip);
1738275SEric Cheng return;
1748275SEric Cheng }
1758275SEric Cheng
1768275SEric Cheng mip->mi_share_capab.ms_sunbind(mcip->mci_share);
1778275SEric Cheng
1788400SNicolas.Droux@Sun.COM mcip->mci_state_flags &= ~MCIS_SHARE_BOUND;
1798400SNicolas.Droux@Sun.COM
1808400SNicolas.Droux@Sun.COM /*
1818400SNicolas.Droux@Sun.COM * If the link state changed while the share was bound, the
1828400SNicolas.Droux@Sun.COM * soft rings fanout associated with the client would have not
1838400SNicolas.Droux@Sun.COM * been updated by mac_fanout_recompute(). Do the check here
1848400SNicolas.Droux@Sun.COM * now that the share has been unbound.
1858400SNicolas.Droux@Sun.COM */
186*11878SVenu.Iyer@Sun.COM mac_fanout_recompute_client(mcip, NULL);
1878275SEric Cheng
1888275SEric Cheng i_mac_perim_exit(mip);
1898275SEric Cheng }
190