xref: /onnv-gate/usr/src/uts/common/io/mac/mac_hio.c (revision 11878:ac93462db6d7)
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