xref: /illumos-gate/usr/src/uts/common/io/mac/mac_hio.c (revision da14cebe459d3275048785f25bd869cb09b5307f)
1*da14cebeSEric Cheng /*
2*da14cebeSEric Cheng  * CDDL HEADER START
3*da14cebeSEric Cheng  *
4*da14cebeSEric Cheng  * The contents of this file are subject to the terms of the
5*da14cebeSEric Cheng  * Common Development and Distribution License (the "License").
6*da14cebeSEric Cheng  * You may not use this file except in compliance with the License.
7*da14cebeSEric Cheng  *
8*da14cebeSEric Cheng  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*da14cebeSEric Cheng  * or http://www.opensolaris.org/os/licensing.
10*da14cebeSEric Cheng  * See the License for the specific language governing permissions
11*da14cebeSEric Cheng  * and limitations under the License.
12*da14cebeSEric Cheng  *
13*da14cebeSEric Cheng  * When distributing Covered Code, include this CDDL HEADER in each
14*da14cebeSEric Cheng  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*da14cebeSEric Cheng  * If applicable, add the following below this CDDL HEADER, with the
16*da14cebeSEric Cheng  * fields enclosed by brackets "[]" replaced with your own identifying
17*da14cebeSEric Cheng  * information: Portions Copyright [yyyy] [name of copyright owner]
18*da14cebeSEric Cheng  *
19*da14cebeSEric Cheng  * CDDL HEADER END
20*da14cebeSEric Cheng  */
21*da14cebeSEric Cheng /*
22*da14cebeSEric Cheng  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*da14cebeSEric Cheng  * Use is subject to license terms.
24*da14cebeSEric Cheng  */
25*da14cebeSEric Cheng 
26*da14cebeSEric Cheng /*
27*da14cebeSEric Cheng  * MAC Hybrid I/O related code.
28*da14cebeSEric Cheng  */
29*da14cebeSEric Cheng 
30*da14cebeSEric Cheng #include <sys/types.h>
31*da14cebeSEric Cheng #include <sys/sdt.h>
32*da14cebeSEric Cheng #include <sys/mac.h>
33*da14cebeSEric Cheng #include <sys/mac_impl.h>
34*da14cebeSEric Cheng #include <sys/mac_client_impl.h>
35*da14cebeSEric Cheng #include <sys/mac_soft_ring.h>
36*da14cebeSEric Cheng 
37*da14cebeSEric Cheng 
38*da14cebeSEric Cheng /*
39*da14cebeSEric Cheng  * Return the number of shares supported by the specified MAC.
40*da14cebeSEric Cheng  */
41*da14cebeSEric Cheng int
42*da14cebeSEric Cheng mac_share_capable(mac_handle_t mh)
43*da14cebeSEric Cheng {
44*da14cebeSEric Cheng 	mac_impl_t *mip = (mac_impl_t *)mh;
45*da14cebeSEric Cheng 
46*da14cebeSEric Cheng 	return (mip->mi_share_capab.ms_snum);
47*da14cebeSEric Cheng }
48*da14cebeSEric Cheng 
49*da14cebeSEric Cheng 
50*da14cebeSEric Cheng /*
51*da14cebeSEric Cheng  * Allocate a share to the specified MAC client. Invoked when
52*da14cebeSEric Cheng  * mac_client_open() is invoked with MAC_OPEN_FLAGS_SHARES_DESIRED set.
53*da14cebeSEric Cheng  */
54*da14cebeSEric Cheng void
55*da14cebeSEric Cheng i_mac_share_alloc(mac_client_impl_t *mcip)
56*da14cebeSEric Cheng {
57*da14cebeSEric Cheng 	mac_impl_t *mip = mcip->mci_mip;
58*da14cebeSEric Cheng 	int rv;
59*da14cebeSEric Cheng 
60*da14cebeSEric Cheng 	i_mac_perim_enter(mip);
61*da14cebeSEric Cheng 
62*da14cebeSEric Cheng 	ASSERT(mcip->mci_share == NULL);
63*da14cebeSEric Cheng 
64*da14cebeSEric Cheng 	if (mac_share_capable((mac_handle_t)mcip->mci_mip) == 0) {
65*da14cebeSEric Cheng 		DTRACE_PROBE1(i__mac__share__alloc__not__sup,
66*da14cebeSEric Cheng 		    mac_client_impl_t *, mcip);
67*da14cebeSEric Cheng 		i_mac_perim_exit(mip);
68*da14cebeSEric Cheng 		return;
69*da14cebeSEric Cheng 	}
70*da14cebeSEric Cheng 
71*da14cebeSEric Cheng 	rv = mip->mi_share_capab.ms_salloc(mip->mi_share_capab.ms_handle,
72*da14cebeSEric Cheng 	    &mcip->mci_share);
73*da14cebeSEric Cheng 	DTRACE_PROBE3(i__mac__share__alloc, mac_client_impl_t *, mcip,
74*da14cebeSEric Cheng 	    int, rv, mac_share_handle_t, mcip->mci_share);
75*da14cebeSEric Cheng 
76*da14cebeSEric Cheng 	mcip->mci_share_bound = B_FALSE;
77*da14cebeSEric Cheng 
78*da14cebeSEric Cheng 	i_mac_perim_exit(mip);
79*da14cebeSEric Cheng }
80*da14cebeSEric Cheng 
81*da14cebeSEric Cheng 
82*da14cebeSEric Cheng /*
83*da14cebeSEric Cheng  * Free a share previously allocated through i_mac_share_alloc().
84*da14cebeSEric Cheng  * Safely handles the case when no shares were allocated to the MAC client.
85*da14cebeSEric Cheng  */
86*da14cebeSEric Cheng void
87*da14cebeSEric Cheng i_mac_share_free(mac_client_impl_t *mcip)
88*da14cebeSEric Cheng {
89*da14cebeSEric Cheng 	mac_impl_t *mip = mcip->mci_mip;
90*da14cebeSEric Cheng 
91*da14cebeSEric Cheng 	i_mac_perim_enter(mip);
92*da14cebeSEric Cheng 
93*da14cebeSEric Cheng 	/* MAC clients are required to unbind they shares before freeing them */
94*da14cebeSEric Cheng 	ASSERT(!mcip->mci_share_bound);
95*da14cebeSEric Cheng 
96*da14cebeSEric Cheng 	if (mcip->mci_share == NULL) {
97*da14cebeSEric Cheng 		i_mac_perim_exit(mip);
98*da14cebeSEric Cheng 		return;
99*da14cebeSEric Cheng 	}
100*da14cebeSEric Cheng 
101*da14cebeSEric Cheng 	mip->mi_share_capab.ms_sfree(mcip->mci_share);
102*da14cebeSEric Cheng 	i_mac_perim_exit(mip);
103*da14cebeSEric Cheng }
104*da14cebeSEric Cheng 
105*da14cebeSEric Cheng 
106*da14cebeSEric Cheng /*
107*da14cebeSEric Cheng  * Bind a share. After this operation the rings that were associated
108*da14cebeSEric Cheng  * with the MAC client are mapped directly into the corresponding
109*da14cebeSEric Cheng  * guest domain.
110*da14cebeSEric Cheng  */
111*da14cebeSEric Cheng int
112*da14cebeSEric Cheng mac_share_bind(mac_client_handle_t mch, uint64_t cookie, uint64_t *rcookie)
113*da14cebeSEric Cheng {
114*da14cebeSEric Cheng 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
115*da14cebeSEric Cheng 	mac_impl_t *mip = mcip->mci_mip;
116*da14cebeSEric Cheng 	int rv;
117*da14cebeSEric Cheng 
118*da14cebeSEric Cheng 	i_mac_perim_enter(mip);
119*da14cebeSEric Cheng 
120*da14cebeSEric Cheng 	if (mcip->mci_share == NULL) {
121*da14cebeSEric Cheng 		i_mac_perim_exit(mip);
122*da14cebeSEric Cheng 		return (ENOTSUP);
123*da14cebeSEric Cheng 	}
124*da14cebeSEric Cheng 
125*da14cebeSEric Cheng 	ASSERT(!mcip->mci_share_bound);
126*da14cebeSEric Cheng 
127*da14cebeSEric Cheng 	/*
128*da14cebeSEric Cheng 	 * Temporarly suspend the TX traffic for that client to make sure
129*da14cebeSEric Cheng 	 * there are no in flight packets through a transmit ring
130*da14cebeSEric Cheng 	 * which is being bound to another domain.
131*da14cebeSEric Cheng 	 */
132*da14cebeSEric Cheng 	mac_tx_client_quiesce(mcip, SRS_QUIESCE);
133*da14cebeSEric Cheng 
134*da14cebeSEric Cheng 	/*
135*da14cebeSEric Cheng 	 * For the receive path, no traffic will be sent up through
136*da14cebeSEric Cheng 	 * the rings to the IO domain. For TX, we need to ensure
137*da14cebeSEric Cheng 	 * that traffic sent by the MAC client are sent through
138*da14cebeSEric Cheng 	 * the default ring.
139*da14cebeSEric Cheng 	 *
140*da14cebeSEric Cheng 	 * For TX XXX will ensure that packets are sent through the
141*da14cebeSEric Cheng 	 * default ring if the share of the MAC client is bound.
142*da14cebeSEric Cheng 	 */
143*da14cebeSEric Cheng 
144*da14cebeSEric Cheng 	rv = mip->mi_share_capab.ms_sbind(mcip->mci_share, cookie, rcookie);
145*da14cebeSEric Cheng 	if (rv == 0)
146*da14cebeSEric Cheng 		mcip->mci_share_bound = B_TRUE;
147*da14cebeSEric Cheng 
148*da14cebeSEric Cheng 	/*
149*da14cebeSEric Cheng 	 * Resume TX traffic for the MAC client. Since mci_share_bound is set
150*da14cebeSEric Cheng 	 * to B_TRUE, mac_tx_send() will not send traffic to individual TX
151*da14cebeSEric Cheng 	 * rings until the share is unbound.
152*da14cebeSEric Cheng 	 */
153*da14cebeSEric Cheng 	mac_tx_client_restart(mcip);
154*da14cebeSEric Cheng 
155*da14cebeSEric Cheng 	i_mac_perim_exit(mip);
156*da14cebeSEric Cheng 
157*da14cebeSEric Cheng 	return (rv);
158*da14cebeSEric Cheng }
159*da14cebeSEric Cheng 
160*da14cebeSEric Cheng 
161*da14cebeSEric Cheng /*
162*da14cebeSEric Cheng  * Unbind a share.
163*da14cebeSEric Cheng  */
164*da14cebeSEric Cheng void
165*da14cebeSEric Cheng mac_share_unbind(mac_client_handle_t mch)
166*da14cebeSEric Cheng {
167*da14cebeSEric Cheng 	mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
168*da14cebeSEric Cheng 	mac_impl_t *mip = mcip->mci_mip;
169*da14cebeSEric Cheng 
170*da14cebeSEric Cheng 	i_mac_perim_enter(mip);
171*da14cebeSEric Cheng 
172*da14cebeSEric Cheng 	if (mcip->mci_share == NULL) {
173*da14cebeSEric Cheng 		i_mac_perim_exit(mip);
174*da14cebeSEric Cheng 		return;
175*da14cebeSEric Cheng 	}
176*da14cebeSEric Cheng 
177*da14cebeSEric Cheng 	mip->mi_share_capab.ms_sunbind(mcip->mci_share);
178*da14cebeSEric Cheng 
179*da14cebeSEric Cheng 	mcip->mci_share_bound = B_FALSE;
180*da14cebeSEric Cheng 
181*da14cebeSEric Cheng 	i_mac_perim_exit(mip);
182*da14cebeSEric Cheng }
183