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