xref: /onnv-gate/usr/src/uts/common/io/ib/clients/eoib/eib_mac.c (revision 13101:da7b13ec3a28)
1*13101SVenki.Rajagopalan@Sun.COM /*
2*13101SVenki.Rajagopalan@Sun.COM  * CDDL HEADER START
3*13101SVenki.Rajagopalan@Sun.COM  *
4*13101SVenki.Rajagopalan@Sun.COM  * The contents of this file are subject to the terms of the
5*13101SVenki.Rajagopalan@Sun.COM  * Common Development and Distribution License (the "License").
6*13101SVenki.Rajagopalan@Sun.COM  * You may not use this file except in compliance with the License.
7*13101SVenki.Rajagopalan@Sun.COM  *
8*13101SVenki.Rajagopalan@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*13101SVenki.Rajagopalan@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*13101SVenki.Rajagopalan@Sun.COM  * See the License for the specific language governing permissions
11*13101SVenki.Rajagopalan@Sun.COM  * and limitations under the License.
12*13101SVenki.Rajagopalan@Sun.COM  *
13*13101SVenki.Rajagopalan@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*13101SVenki.Rajagopalan@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*13101SVenki.Rajagopalan@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*13101SVenki.Rajagopalan@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*13101SVenki.Rajagopalan@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*13101SVenki.Rajagopalan@Sun.COM  *
19*13101SVenki.Rajagopalan@Sun.COM  * CDDL HEADER END
20*13101SVenki.Rajagopalan@Sun.COM  */
21*13101SVenki.Rajagopalan@Sun.COM 
22*13101SVenki.Rajagopalan@Sun.COM /*
23*13101SVenki.Rajagopalan@Sun.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*13101SVenki.Rajagopalan@Sun.COM  */
25*13101SVenki.Rajagopalan@Sun.COM 
26*13101SVenki.Rajagopalan@Sun.COM #include <sys/types.h>
27*13101SVenki.Rajagopalan@Sun.COM #include <sys/conf.h>
28*13101SVenki.Rajagopalan@Sun.COM #include <sys/devops.h>
29*13101SVenki.Rajagopalan@Sun.COM #include <sys/kmem.h>
30*13101SVenki.Rajagopalan@Sun.COM #include <sys/ksynch.h>
31*13101SVenki.Rajagopalan@Sun.COM #include <sys/modctl.h>
32*13101SVenki.Rajagopalan@Sun.COM #include <sys/stat.h>
33*13101SVenki.Rajagopalan@Sun.COM #include <sys/ddi.h>
34*13101SVenki.Rajagopalan@Sun.COM #include <sys/sunddi.h>
35*13101SVenki.Rajagopalan@Sun.COM #include <sys/mac_provider.h>
36*13101SVenki.Rajagopalan@Sun.COM #include <sys/mac_ether.h>
37*13101SVenki.Rajagopalan@Sun.COM 
38*13101SVenki.Rajagopalan@Sun.COM #include <sys/ib/clients/eoib/eib_impl.h>
39*13101SVenki.Rajagopalan@Sun.COM 
40*13101SVenki.Rajagopalan@Sun.COM /*
41*13101SVenki.Rajagopalan@Sun.COM  * Declarations private to this file
42*13101SVenki.Rajagopalan@Sun.COM  */
43*13101SVenki.Rajagopalan@Sun.COM static void eib_rb_mac_start(eib_t *, eib_vnic_t *);
44*13101SVenki.Rajagopalan@Sun.COM 
45*13101SVenki.Rajagopalan@Sun.COM /*
46*13101SVenki.Rajagopalan@Sun.COM  * This set of routines are used to set/clear the condition that the
47*13101SVenki.Rajagopalan@Sun.COM  * caller is about to do something that affects the state of the nic.
48*13101SVenki.Rajagopalan@Sun.COM  * If there's already someone doing either a start or a stop (possibly
49*13101SVenki.Rajagopalan@Sun.COM  * due to the async handler, a plumb or a dlpi_open happening, or an
50*13101SVenki.Rajagopalan@Sun.COM  * unplumb or dlpi_close coming in), we wait until that's done.
51*13101SVenki.Rajagopalan@Sun.COM  */
52*13101SVenki.Rajagopalan@Sun.COM void
eib_mac_set_nic_state(eib_t * ss,uint_t flags)53*13101SVenki.Rajagopalan@Sun.COM eib_mac_set_nic_state(eib_t *ss, uint_t flags)
54*13101SVenki.Rajagopalan@Sun.COM {
55*13101SVenki.Rajagopalan@Sun.COM 	eib_node_state_t *ns = ss->ei_node_state;
56*13101SVenki.Rajagopalan@Sun.COM 
57*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ns->ns_lock);
58*13101SVenki.Rajagopalan@Sun.COM 
59*13101SVenki.Rajagopalan@Sun.COM 	while ((ns->ns_nic_state & EIB_NIC_STARTING) ||
60*13101SVenki.Rajagopalan@Sun.COM 	    (ns->ns_nic_state & EIB_NIC_STOPPING)) {
61*13101SVenki.Rajagopalan@Sun.COM 		cv_wait(&ns->ns_cv, &ns->ns_lock);
62*13101SVenki.Rajagopalan@Sun.COM 	}
63*13101SVenki.Rajagopalan@Sun.COM 	ns->ns_nic_state |= flags;
64*13101SVenki.Rajagopalan@Sun.COM 
65*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ns->ns_lock);
66*13101SVenki.Rajagopalan@Sun.COM }
67*13101SVenki.Rajagopalan@Sun.COM 
68*13101SVenki.Rajagopalan@Sun.COM void
eib_mac_clr_nic_state(eib_t * ss,uint_t flags)69*13101SVenki.Rajagopalan@Sun.COM eib_mac_clr_nic_state(eib_t *ss, uint_t flags)
70*13101SVenki.Rajagopalan@Sun.COM {
71*13101SVenki.Rajagopalan@Sun.COM 	eib_node_state_t *ns = ss->ei_node_state;
72*13101SVenki.Rajagopalan@Sun.COM 
73*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ns->ns_lock);
74*13101SVenki.Rajagopalan@Sun.COM 
75*13101SVenki.Rajagopalan@Sun.COM 	ns->ns_nic_state &= (~flags);
76*13101SVenki.Rajagopalan@Sun.COM 
77*13101SVenki.Rajagopalan@Sun.COM 	cv_broadcast(&ns->ns_cv);
78*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ns->ns_lock);
79*13101SVenki.Rajagopalan@Sun.COM }
80*13101SVenki.Rajagopalan@Sun.COM 
81*13101SVenki.Rajagopalan@Sun.COM void
eib_mac_upd_nic_state(eib_t * ss,uint_t clr_flags,uint_t set_flags)82*13101SVenki.Rajagopalan@Sun.COM eib_mac_upd_nic_state(eib_t *ss, uint_t clr_flags, uint_t set_flags)
83*13101SVenki.Rajagopalan@Sun.COM {
84*13101SVenki.Rajagopalan@Sun.COM 	eib_node_state_t *ns = ss->ei_node_state;
85*13101SVenki.Rajagopalan@Sun.COM 
86*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ns->ns_lock);
87*13101SVenki.Rajagopalan@Sun.COM 
88*13101SVenki.Rajagopalan@Sun.COM 	ns->ns_nic_state &= (~clr_flags);
89*13101SVenki.Rajagopalan@Sun.COM 	ns->ns_nic_state |= set_flags;
90*13101SVenki.Rajagopalan@Sun.COM 
91*13101SVenki.Rajagopalan@Sun.COM 	cv_broadcast(&ns->ns_cv);
92*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ns->ns_lock);
93*13101SVenki.Rajagopalan@Sun.COM }
94*13101SVenki.Rajagopalan@Sun.COM 
95*13101SVenki.Rajagopalan@Sun.COM uint_t
eib_mac_get_nic_state(eib_t * ss)96*13101SVenki.Rajagopalan@Sun.COM eib_mac_get_nic_state(eib_t *ss)
97*13101SVenki.Rajagopalan@Sun.COM {
98*13101SVenki.Rajagopalan@Sun.COM 	eib_node_state_t *ns = ss->ei_node_state;
99*13101SVenki.Rajagopalan@Sun.COM 	uint_t nic_state;
100*13101SVenki.Rajagopalan@Sun.COM 
101*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ns->ns_lock);
102*13101SVenki.Rajagopalan@Sun.COM 	nic_state = ns->ns_nic_state;
103*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ns->ns_lock);
104*13101SVenki.Rajagopalan@Sun.COM 
105*13101SVenki.Rajagopalan@Sun.COM 	return (nic_state);
106*13101SVenki.Rajagopalan@Sun.COM }
107*13101SVenki.Rajagopalan@Sun.COM 
108*13101SVenki.Rajagopalan@Sun.COM void
eib_mac_link_state(eib_t * ss,link_state_t new_link_state,boolean_t force)109*13101SVenki.Rajagopalan@Sun.COM eib_mac_link_state(eib_t *ss, link_state_t new_link_state,
110*13101SVenki.Rajagopalan@Sun.COM     boolean_t force)
111*13101SVenki.Rajagopalan@Sun.COM {
112*13101SVenki.Rajagopalan@Sun.COM 	eib_node_state_t *ns = ss->ei_node_state;
113*13101SVenki.Rajagopalan@Sun.COM 	boolean_t state_changed = B_FALSE;
114*13101SVenki.Rajagopalan@Sun.COM 
115*13101SVenki.Rajagopalan@Sun.COM 	mutex_enter(&ns->ns_lock);
116*13101SVenki.Rajagopalan@Sun.COM 
117*13101SVenki.Rajagopalan@Sun.COM 	/*
118*13101SVenki.Rajagopalan@Sun.COM 	 * We track the link state only if the current link state is
119*13101SVenki.Rajagopalan@Sun.COM 	 * not unknown.  Obviously therefore, the first calls to set
120*13101SVenki.Rajagopalan@Sun.COM 	 * the link state from eib_mac_start() have to pass an explicit
121*13101SVenki.Rajagopalan@Sun.COM 	 * 'force' flag to force the state change tracking.
122*13101SVenki.Rajagopalan@Sun.COM 	 */
123*13101SVenki.Rajagopalan@Sun.COM 	if (ns->ns_link_state != LINK_STATE_UNKNOWN)
124*13101SVenki.Rajagopalan@Sun.COM 		force = B_TRUE;
125*13101SVenki.Rajagopalan@Sun.COM 
126*13101SVenki.Rajagopalan@Sun.COM 	if ((force) && (new_link_state != ns->ns_link_state)) {
127*13101SVenki.Rajagopalan@Sun.COM 		ns->ns_link_state = new_link_state;
128*13101SVenki.Rajagopalan@Sun.COM 		state_changed = B_TRUE;
129*13101SVenki.Rajagopalan@Sun.COM 	}
130*13101SVenki.Rajagopalan@Sun.COM 	mutex_exit(&ns->ns_lock);
131*13101SVenki.Rajagopalan@Sun.COM 
132*13101SVenki.Rajagopalan@Sun.COM 	if (state_changed) {
133*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
134*13101SVenki.Rajagopalan@Sun.COM 		    "eib_mac_link_state: changing link state to %d",
135*13101SVenki.Rajagopalan@Sun.COM 		    new_link_state);
136*13101SVenki.Rajagopalan@Sun.COM 
137*13101SVenki.Rajagopalan@Sun.COM 		mac_link_update(ss->ei_mac_hdl, new_link_state);
138*13101SVenki.Rajagopalan@Sun.COM 	} else  {
139*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_DEBUG(ss->ei_instance,
140*13101SVenki.Rajagopalan@Sun.COM 		    "eib_mac_link_state: link state already %d",
141*13101SVenki.Rajagopalan@Sun.COM 		    new_link_state);
142*13101SVenki.Rajagopalan@Sun.COM 	}
143*13101SVenki.Rajagopalan@Sun.COM }
144*13101SVenki.Rajagopalan@Sun.COM 
145*13101SVenki.Rajagopalan@Sun.COM void
eib_mac_link_up(eib_t * ss,boolean_t force)146*13101SVenki.Rajagopalan@Sun.COM eib_mac_link_up(eib_t *ss, boolean_t force)
147*13101SVenki.Rajagopalan@Sun.COM {
148*13101SVenki.Rajagopalan@Sun.COM 	eib_mac_link_state(ss, LINK_STATE_UP, force);
149*13101SVenki.Rajagopalan@Sun.COM }
150*13101SVenki.Rajagopalan@Sun.COM 
151*13101SVenki.Rajagopalan@Sun.COM void
eib_mac_link_down(eib_t * ss,boolean_t force)152*13101SVenki.Rajagopalan@Sun.COM eib_mac_link_down(eib_t *ss, boolean_t force)
153*13101SVenki.Rajagopalan@Sun.COM {
154*13101SVenki.Rajagopalan@Sun.COM 	eib_mac_link_state(ss, LINK_STATE_DOWN, force);
155*13101SVenki.Rajagopalan@Sun.COM }
156*13101SVenki.Rajagopalan@Sun.COM 
157*13101SVenki.Rajagopalan@Sun.COM int
eib_mac_start(eib_t * ss)158*13101SVenki.Rajagopalan@Sun.COM eib_mac_start(eib_t *ss)
159*13101SVenki.Rajagopalan@Sun.COM {
160*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_t *vnic0 = NULL;
161*13101SVenki.Rajagopalan@Sun.COM 	eib_login_data_t *ld;
162*13101SVenki.Rajagopalan@Sun.COM 	int err;
163*13101SVenki.Rajagopalan@Sun.COM 
164*13101SVenki.Rajagopalan@Sun.COM 	/*
165*13101SVenki.Rajagopalan@Sun.COM 	 * Perform HCA related initializations
166*13101SVenki.Rajagopalan@Sun.COM 	 */
167*13101SVenki.Rajagopalan@Sun.COM 	if (eib_ibt_hca_init(ss) != EIB_E_SUCCESS)
168*13101SVenki.Rajagopalan@Sun.COM 		goto start_fail;
169*13101SVenki.Rajagopalan@Sun.COM 
170*13101SVenki.Rajagopalan@Sun.COM 	/*
171*13101SVenki.Rajagopalan@Sun.COM 	 * Make sure port is up. Also record the port base lid if it's up.
172*13101SVenki.Rajagopalan@Sun.COM 	 */
173*13101SVenki.Rajagopalan@Sun.COM 	if (eib_mac_hca_portstate(ss, &ss->ei_props->ep_blid,
174*13101SVenki.Rajagopalan@Sun.COM 	    &err) != EIB_E_SUCCESS) {
175*13101SVenki.Rajagopalan@Sun.COM 		goto start_fail;
176*13101SVenki.Rajagopalan@Sun.COM 	}
177*13101SVenki.Rajagopalan@Sun.COM 
178*13101SVenki.Rajagopalan@Sun.COM 	/*
179*13101SVenki.Rajagopalan@Sun.COM 	 * Set up tx and rx buffer pools
180*13101SVenki.Rajagopalan@Sun.COM 	 */
181*13101SVenki.Rajagopalan@Sun.COM 	if (eib_rsrc_setup_bufs(ss, &err) != EIB_E_SUCCESS)
182*13101SVenki.Rajagopalan@Sun.COM 		goto start_fail;
183*13101SVenki.Rajagopalan@Sun.COM 
184*13101SVenki.Rajagopalan@Sun.COM 	/*
185*13101SVenki.Rajagopalan@Sun.COM 	 * Set up admin qp for logins and logouts
186*13101SVenki.Rajagopalan@Sun.COM 	 */
187*13101SVenki.Rajagopalan@Sun.COM 	if (eib_adm_setup_qp(ss, &err) != EIB_E_SUCCESS)
188*13101SVenki.Rajagopalan@Sun.COM 		goto start_fail;
189*13101SVenki.Rajagopalan@Sun.COM 
190*13101SVenki.Rajagopalan@Sun.COM 	/*
191*13101SVenki.Rajagopalan@Sun.COM 	 * Create the vnic for physlink (instance 0)
192*13101SVenki.Rajagopalan@Sun.COM 	 */
193*13101SVenki.Rajagopalan@Sun.COM 	if (eib_vnic_create(ss, 0, 0, &vnic0, &err) != EIB_E_SUCCESS)
194*13101SVenki.Rajagopalan@Sun.COM 		goto start_fail;
195*13101SVenki.Rajagopalan@Sun.COM 
196*13101SVenki.Rajagopalan@Sun.COM 	/*
197*13101SVenki.Rajagopalan@Sun.COM 	 * Update the mac layer about the correct values for MTU and
198*13101SVenki.Rajagopalan@Sun.COM 	 * unicast MAC address.  Note that we've already verified that the
199*13101SVenki.Rajagopalan@Sun.COM 	 * vhub mtu (plus the eoib encapsulation header) is not greater
200*13101SVenki.Rajagopalan@Sun.COM 	 * than our port mtu, so we can go ahead and report the vhub mtu
201*13101SVenki.Rajagopalan@Sun.COM 	 * (of vnic0) directly.
202*13101SVenki.Rajagopalan@Sun.COM 	 */
203*13101SVenki.Rajagopalan@Sun.COM 	ld = &(vnic0->vn_login_data);
204*13101SVenki.Rajagopalan@Sun.COM 	(void) mac_maxsdu_update(ss->ei_mac_hdl, ld->ld_vhub_mtu);
205*13101SVenki.Rajagopalan@Sun.COM 	mac_unicst_update(ss->ei_mac_hdl, ld->ld_assigned_mac);
206*13101SVenki.Rajagopalan@Sun.COM 
207*13101SVenki.Rajagopalan@Sun.COM 	/*
208*13101SVenki.Rajagopalan@Sun.COM 	 * Report that the link is up and ready
209*13101SVenki.Rajagopalan@Sun.COM 	 */
210*13101SVenki.Rajagopalan@Sun.COM 	eib_mac_link_up(ss, B_TRUE);
211*13101SVenki.Rajagopalan@Sun.COM 	return (0);
212*13101SVenki.Rajagopalan@Sun.COM 
213*13101SVenki.Rajagopalan@Sun.COM start_fail:
214*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_mac_start(ss, vnic0);
215*13101SVenki.Rajagopalan@Sun.COM 	eib_mac_link_down(ss, B_TRUE);
216*13101SVenki.Rajagopalan@Sun.COM 	return (err);
217*13101SVenki.Rajagopalan@Sun.COM }
218*13101SVenki.Rajagopalan@Sun.COM 
219*13101SVenki.Rajagopalan@Sun.COM void
eib_mac_stop(eib_t * ss)220*13101SVenki.Rajagopalan@Sun.COM eib_mac_stop(eib_t *ss)
221*13101SVenki.Rajagopalan@Sun.COM {
222*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_t *vnic;
223*13101SVenki.Rajagopalan@Sun.COM 	link_state_t cur_link_state = ss->ei_node_state->ns_link_state;
224*13101SVenki.Rajagopalan@Sun.COM 	int ndx;
225*13101SVenki.Rajagopalan@Sun.COM 
226*13101SVenki.Rajagopalan@Sun.COM 	/*
227*13101SVenki.Rajagopalan@Sun.COM 	 * Stopping an EoIB device instance is somewhat different from starting
228*13101SVenki.Rajagopalan@Sun.COM 	 * it. Between the time the device instance was started and the call to
229*13101SVenki.Rajagopalan@Sun.COM 	 * eib_m_stop() now, a number of vnics could've been created. All of
230*13101SVenki.Rajagopalan@Sun.COM 	 * these will need to be destroyed before we can stop the device.
231*13101SVenki.Rajagopalan@Sun.COM 	 */
232*13101SVenki.Rajagopalan@Sun.COM 	for (ndx = EIB_MAX_VNICS - 1; ndx >= 0; ndx--) {
233*13101SVenki.Rajagopalan@Sun.COM 		if ((vnic = ss->ei_vnic[ndx]) != NULL)
234*13101SVenki.Rajagopalan@Sun.COM 			eib_vnic_delete(ss, vnic);
235*13101SVenki.Rajagopalan@Sun.COM 	}
236*13101SVenki.Rajagopalan@Sun.COM 
237*13101SVenki.Rajagopalan@Sun.COM 	/*
238*13101SVenki.Rajagopalan@Sun.COM 	 * And now, to undo the things we did in start (other than creation
239*13101SVenki.Rajagopalan@Sun.COM 	 * of vnics itself)
240*13101SVenki.Rajagopalan@Sun.COM 	 */
241*13101SVenki.Rajagopalan@Sun.COM 	eib_rb_mac_start(ss, NULL);
242*13101SVenki.Rajagopalan@Sun.COM 
243*13101SVenki.Rajagopalan@Sun.COM 	/*
244*13101SVenki.Rajagopalan@Sun.COM 	 * Now that we're completed stopped, there's no mac address assigned
245*13101SVenki.Rajagopalan@Sun.COM 	 * to us.  Update the mac layer with this information. Note that we
246*13101SVenki.Rajagopalan@Sun.COM 	 * can let the old max mtu information remain as-is, since we're likely
247*13101SVenki.Rajagopalan@Sun.COM 	 * to get that same mtu on a later plumb.
248*13101SVenki.Rajagopalan@Sun.COM 	 */
249*13101SVenki.Rajagopalan@Sun.COM 	mac_unicst_update(ss->ei_mac_hdl, eib_zero_mac);
250*13101SVenki.Rajagopalan@Sun.COM 
251*13101SVenki.Rajagopalan@Sun.COM 	/*
252*13101SVenki.Rajagopalan@Sun.COM 	 * If our link state was up when the eib_m_stop() callback was called,
253*13101SVenki.Rajagopalan@Sun.COM 	 * we'll mark the link state as unknown now.  Otherwise, we'll leave
254*13101SVenki.Rajagopalan@Sun.COM 	 * the link state as-is (down).
255*13101SVenki.Rajagopalan@Sun.COM 	 */
256*13101SVenki.Rajagopalan@Sun.COM 	if (cur_link_state == LINK_STATE_UP)
257*13101SVenki.Rajagopalan@Sun.COM 		eib_mac_link_state(ss, LINK_STATE_UNKNOWN, B_TRUE);
258*13101SVenki.Rajagopalan@Sun.COM }
259*13101SVenki.Rajagopalan@Sun.COM 
260*13101SVenki.Rajagopalan@Sun.COM int
eib_mac_multicast(eib_t * ss,boolean_t add,uint8_t * mcast_mac)261*13101SVenki.Rajagopalan@Sun.COM eib_mac_multicast(eib_t *ss, boolean_t add, uint8_t *mcast_mac)
262*13101SVenki.Rajagopalan@Sun.COM {
263*13101SVenki.Rajagopalan@Sun.COM 	int ret = EIB_E_SUCCESS;
264*13101SVenki.Rajagopalan@Sun.COM 	int err = 0;
265*13101SVenki.Rajagopalan@Sun.COM 
266*13101SVenki.Rajagopalan@Sun.COM 	/*
267*13101SVenki.Rajagopalan@Sun.COM 	 * If it's a broadcast group join, each vnic needs to and is always
268*13101SVenki.Rajagopalan@Sun.COM 	 * joined to the broadcast address, so we return success immediately.
269*13101SVenki.Rajagopalan@Sun.COM 	 * If it's a broadcast group leave, we fail immediately for the same
270*13101SVenki.Rajagopalan@Sun.COM 	 * reason as above.
271*13101SVenki.Rajagopalan@Sun.COM 	 */
272*13101SVenki.Rajagopalan@Sun.COM 	if (bcmp(mcast_mac, eib_broadcast_mac, ETHERADDRL) == 0) {
273*13101SVenki.Rajagopalan@Sun.COM 		if (add)
274*13101SVenki.Rajagopalan@Sun.COM 			return (0);
275*13101SVenki.Rajagopalan@Sun.COM 		else
276*13101SVenki.Rajagopalan@Sun.COM 			return (EINVAL);
277*13101SVenki.Rajagopalan@Sun.COM 	}
278*13101SVenki.Rajagopalan@Sun.COM 
279*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_vnic[0]) {
280*13101SVenki.Rajagopalan@Sun.COM 		if (add) {
281*13101SVenki.Rajagopalan@Sun.COM 			ret = eib_vnic_join_data_mcg(ss, ss->ei_vnic[0],
282*13101SVenki.Rajagopalan@Sun.COM 			    mcast_mac, B_FALSE, &err);
283*13101SVenki.Rajagopalan@Sun.COM 		} else {
284*13101SVenki.Rajagopalan@Sun.COM 			eib_vnic_leave_data_mcg(ss, ss->ei_vnic[0], mcast_mac);
285*13101SVenki.Rajagopalan@Sun.COM 			ret = EIB_E_SUCCESS;
286*13101SVenki.Rajagopalan@Sun.COM 		}
287*13101SVenki.Rajagopalan@Sun.COM 	}
288*13101SVenki.Rajagopalan@Sun.COM 
289*13101SVenki.Rajagopalan@Sun.COM 	if (ret == EIB_E_SUCCESS)
290*13101SVenki.Rajagopalan@Sun.COM 		return (0);
291*13101SVenki.Rajagopalan@Sun.COM 	else
292*13101SVenki.Rajagopalan@Sun.COM 		return (err);
293*13101SVenki.Rajagopalan@Sun.COM }
294*13101SVenki.Rajagopalan@Sun.COM 
295*13101SVenki.Rajagopalan@Sun.COM int
eib_mac_promisc(eib_t * ss,boolean_t set)296*13101SVenki.Rajagopalan@Sun.COM eib_mac_promisc(eib_t *ss, boolean_t set)
297*13101SVenki.Rajagopalan@Sun.COM {
298*13101SVenki.Rajagopalan@Sun.COM 	int ret = EIB_E_SUCCESS;
299*13101SVenki.Rajagopalan@Sun.COM 	int err = 0;
300*13101SVenki.Rajagopalan@Sun.COM 
301*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_vnic[0]) {
302*13101SVenki.Rajagopalan@Sun.COM 		if (set) {
303*13101SVenki.Rajagopalan@Sun.COM 			ret = eib_vnic_join_data_mcg(ss, ss->ei_vnic[0],
304*13101SVenki.Rajagopalan@Sun.COM 			    eib_zero_mac, B_FALSE, &err);
305*13101SVenki.Rajagopalan@Sun.COM 		} else {
306*13101SVenki.Rajagopalan@Sun.COM 			eib_vnic_leave_data_mcg(ss, ss->ei_vnic[0],
307*13101SVenki.Rajagopalan@Sun.COM 			    eib_zero_mac);
308*13101SVenki.Rajagopalan@Sun.COM 			ret = EIB_E_SUCCESS;
309*13101SVenki.Rajagopalan@Sun.COM 		}
310*13101SVenki.Rajagopalan@Sun.COM 	}
311*13101SVenki.Rajagopalan@Sun.COM 
312*13101SVenki.Rajagopalan@Sun.COM 	if (ret == EIB_E_SUCCESS)
313*13101SVenki.Rajagopalan@Sun.COM 		return (0);
314*13101SVenki.Rajagopalan@Sun.COM 	else
315*13101SVenki.Rajagopalan@Sun.COM 		return (err);
316*13101SVenki.Rajagopalan@Sun.COM }
317*13101SVenki.Rajagopalan@Sun.COM 
318*13101SVenki.Rajagopalan@Sun.COM int
eib_mac_tx(eib_t * ss,mblk_t * mp)319*13101SVenki.Rajagopalan@Sun.COM eib_mac_tx(eib_t *ss, mblk_t *mp)
320*13101SVenki.Rajagopalan@Sun.COM {
321*13101SVenki.Rajagopalan@Sun.COM 	eib_ether_hdr_t evh;
322*13101SVenki.Rajagopalan@Sun.COM 	eib_vnic_t *vnic = NULL;
323*13101SVenki.Rajagopalan@Sun.COM 	eib_wqe_t *swqe = NULL;
324*13101SVenki.Rajagopalan@Sun.COM 	boolean_t failed_vnic;
325*13101SVenki.Rajagopalan@Sun.COM 	int found;
326*13101SVenki.Rajagopalan@Sun.COM 	int ret;
327*13101SVenki.Rajagopalan@Sun.COM 
328*13101SVenki.Rajagopalan@Sun.COM 	/*
329*13101SVenki.Rajagopalan@Sun.COM 	 * Grab a send wqe.  If we cannot get one, wake up a service
330*13101SVenki.Rajagopalan@Sun.COM 	 * thread to monitor the swqe status and let the mac layer know
331*13101SVenki.Rajagopalan@Sun.COM 	 * as soon as we have enough tx wqes to start the traffic again.
332*13101SVenki.Rajagopalan@Sun.COM 	 */
333*13101SVenki.Rajagopalan@Sun.COM 	if ((swqe = eib_rsrc_grab_swqe(ss, EIB_WPRI_LO)) == NULL) {
334*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_mac_tx: "
335*13101SVenki.Rajagopalan@Sun.COM 		    "no swqe available, holding tx until resource "
336*13101SVenki.Rajagopalan@Sun.COM 		    "becomes available");
337*13101SVenki.Rajagopalan@Sun.COM 		eib_rsrc_txwqes_needed(ss);
338*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
339*13101SVenki.Rajagopalan@Sun.COM 	}
340*13101SVenki.Rajagopalan@Sun.COM 
341*13101SVenki.Rajagopalan@Sun.COM 	/*
342*13101SVenki.Rajagopalan@Sun.COM 	 * Determine dmac, smac and vlan information
343*13101SVenki.Rajagopalan@Sun.COM 	 */
344*13101SVenki.Rajagopalan@Sun.COM 	eib_data_parse_ether_hdr(mp, &evh);
345*13101SVenki.Rajagopalan@Sun.COM 
346*13101SVenki.Rajagopalan@Sun.COM 	/*
347*13101SVenki.Rajagopalan@Sun.COM 	 * Lookup the {smac, vlan} tuple in our vnic list. If it isn't
348*13101SVenki.Rajagopalan@Sun.COM 	 * there, this is obviously a new packet on a vnic/vlan that
349*13101SVenki.Rajagopalan@Sun.COM 	 * we haven't been informed about. So go ahead and file a request
350*13101SVenki.Rajagopalan@Sun.COM 	 * to create a new vnic. This is obviously not a clean thing to
351*13101SVenki.Rajagopalan@Sun.COM 	 * do - we should be informed when a vnic/vlan is being created
352*13101SVenki.Rajagopalan@Sun.COM 	 * and should be given a proper opportunity to login to the gateway
353*13101SVenki.Rajagopalan@Sun.COM 	 * and do the creation.  But we don't have that luxury now, and
354*13101SVenki.Rajagopalan@Sun.COM 	 * this is the next best thing to do.  Note that we return failure
355*13101SVenki.Rajagopalan@Sun.COM 	 * from here, so tx flow control should prevent further packets
356*13101SVenki.Rajagopalan@Sun.COM 	 * from coming in until the vnic creation has completed.
357*13101SVenki.Rajagopalan@Sun.COM 	 */
358*13101SVenki.Rajagopalan@Sun.COM 	found = eib_data_lookup_vnic(ss, evh.eh_smac, evh.eh_vlan, &vnic,
359*13101SVenki.Rajagopalan@Sun.COM 	    &failed_vnic);
360*13101SVenki.Rajagopalan@Sun.COM 	if (found != EIB_E_SUCCESS) {
361*13101SVenki.Rajagopalan@Sun.COM 		uint8_t *m = evh.eh_smac;
362*13101SVenki.Rajagopalan@Sun.COM 
363*13101SVenki.Rajagopalan@Sun.COM 		/*
364*13101SVenki.Rajagopalan@Sun.COM 		 * Return the swqe back to the pool
365*13101SVenki.Rajagopalan@Sun.COM 		 */
366*13101SVenki.Rajagopalan@Sun.COM 		eib_rsrc_return_swqe(ss, swqe, NULL);
367*13101SVenki.Rajagopalan@Sun.COM 
368*13101SVenki.Rajagopalan@Sun.COM 		/*
369*13101SVenki.Rajagopalan@Sun.COM 		 * If we had previously tried creating this vnic and had
370*13101SVenki.Rajagopalan@Sun.COM 		 * failed, we'll simply drop the packets on this vnic.
371*13101SVenki.Rajagopalan@Sun.COM 		 * Otherwise, we'll queue up a request to create this vnic.
372*13101SVenki.Rajagopalan@Sun.COM 		 */
373*13101SVenki.Rajagopalan@Sun.COM 		if (failed_vnic) {
374*13101SVenki.Rajagopalan@Sun.COM 			EIB_DPRINTF_VERBOSE(ss->ei_instance, "eib_mac_tx: "
375*13101SVenki.Rajagopalan@Sun.COM 			    "vnic creation for mac=%x:%x:%x:%x:%x:%x "
376*13101SVenki.Rajagopalan@Sun.COM 			    "vlan=0x%x failed previously, dropping pkt",
377*13101SVenki.Rajagopalan@Sun.COM 			    m[0], m[1], m[2], m[3], m[4], m[5], evh.eh_vlan);
378*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_SUCCESS);
379*13101SVenki.Rajagopalan@Sun.COM 		} else {
380*13101SVenki.Rajagopalan@Sun.COM 			eib_vnic_need_new(ss, evh.eh_smac, evh.eh_vlan);
381*13101SVenki.Rajagopalan@Sun.COM 			return (EIB_E_FAILURE);
382*13101SVenki.Rajagopalan@Sun.COM 		}
383*13101SVenki.Rajagopalan@Sun.COM 	}
384*13101SVenki.Rajagopalan@Sun.COM 
385*13101SVenki.Rajagopalan@Sun.COM 	/*
386*13101SVenki.Rajagopalan@Sun.COM 	 * We'll try to setup the destination in the swqe for this dmac
387*13101SVenki.Rajagopalan@Sun.COM 	 * and vlan.  If we don't succeed, there's no need to undo any
388*13101SVenki.Rajagopalan@Sun.COM 	 * vnic-creation we might've made above (if we didn't find the
389*13101SVenki.Rajagopalan@Sun.COM 	 * vnic corresponding to the {smac, vlan} originally). Note that
390*13101SVenki.Rajagopalan@Sun.COM 	 * this is not a resource issue, so we'll issue a warning and
391*13101SVenki.Rajagopalan@Sun.COM 	 * drop the packet, but won't return failure from here.
392*13101SVenki.Rajagopalan@Sun.COM 	 */
393*13101SVenki.Rajagopalan@Sun.COM 	ret = eib_vnic_setup_dest(vnic, swqe, evh.eh_dmac, evh.eh_vlan);
394*13101SVenki.Rajagopalan@Sun.COM 	if (ret != EIB_E_SUCCESS) {
395*13101SVenki.Rajagopalan@Sun.COM 		uint8_t *dmac;
396*13101SVenki.Rajagopalan@Sun.COM 
397*13101SVenki.Rajagopalan@Sun.COM 		dmac = evh.eh_dmac;
398*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_mac_tx: "
399*13101SVenki.Rajagopalan@Sun.COM 		    "eib_vnic_setup_dest() failed for mac=%x:%x:%x:%x:%x:%x, "
400*13101SVenki.Rajagopalan@Sun.COM 		    "vlan=0x%x, dropping pkt", dmac[0], dmac[1], dmac[2],
401*13101SVenki.Rajagopalan@Sun.COM 		    dmac[3], dmac[4], dmac[5]);
402*13101SVenki.Rajagopalan@Sun.COM 
403*13101SVenki.Rajagopalan@Sun.COM 		eib_rsrc_return_swqe(ss, swqe, NULL);
404*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_SUCCESS);
405*13101SVenki.Rajagopalan@Sun.COM 	}
406*13101SVenki.Rajagopalan@Sun.COM 
407*13101SVenki.Rajagopalan@Sun.COM 	/*
408*13101SVenki.Rajagopalan@Sun.COM 	 * The only reason why this would fail is if we needed LSO buffer(s)
409*13101SVenki.Rajagopalan@Sun.COM 	 * to prepare this frame and couldn't find enough of those.
410*13101SVenki.Rajagopalan@Sun.COM 	 */
411*13101SVenki.Rajagopalan@Sun.COM 	ret = eib_data_prepare_frame(vnic, swqe, mp, &evh);
412*13101SVenki.Rajagopalan@Sun.COM 	if (ret != EIB_E_SUCCESS) {
413*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_mac_tx: "
414*13101SVenki.Rajagopalan@Sun.COM 		    "eib_data_prepare_frame() failed (no LSO bufs?), "
415*13101SVenki.Rajagopalan@Sun.COM 		    "holding tx until resource becomes available");
416*13101SVenki.Rajagopalan@Sun.COM 
417*13101SVenki.Rajagopalan@Sun.COM 		eib_rsrc_return_swqe(ss, swqe, NULL);
418*13101SVenki.Rajagopalan@Sun.COM 		eib_rsrc_lsobufs_needed(ss);
419*13101SVenki.Rajagopalan@Sun.COM 		return (EIB_E_FAILURE);
420*13101SVenki.Rajagopalan@Sun.COM 	}
421*13101SVenki.Rajagopalan@Sun.COM 
422*13101SVenki.Rajagopalan@Sun.COM 	eib_data_post_tx(vnic, swqe);
423*13101SVenki.Rajagopalan@Sun.COM 
424*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
425*13101SVenki.Rajagopalan@Sun.COM }
426*13101SVenki.Rajagopalan@Sun.COM 
427*13101SVenki.Rajagopalan@Sun.COM int
eib_mac_hca_portstate(eib_t * ss,ib_lid_t * blid,int * err)428*13101SVenki.Rajagopalan@Sun.COM eib_mac_hca_portstate(eib_t *ss, ib_lid_t *blid, int *err)
429*13101SVenki.Rajagopalan@Sun.COM {
430*13101SVenki.Rajagopalan@Sun.COM 	ibt_hca_portinfo_t *pi;
431*13101SVenki.Rajagopalan@Sun.COM 	ibt_status_t ret;
432*13101SVenki.Rajagopalan@Sun.COM 	uint_t num_pi;
433*13101SVenki.Rajagopalan@Sun.COM 	uint_t sz_pi;
434*13101SVenki.Rajagopalan@Sun.COM 
435*13101SVenki.Rajagopalan@Sun.COM 	ret = ibt_query_hca_ports(ss->ei_hca_hdl, ss->ei_props->ep_port_num,
436*13101SVenki.Rajagopalan@Sun.COM 	    &pi, &num_pi, &sz_pi);
437*13101SVenki.Rajagopalan@Sun.COM 	if (ret != IBT_SUCCESS) {
438*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance,
439*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_query_hca_ports(hca_hdl=0x%llx, "
440*13101SVenki.Rajagopalan@Sun.COM 		    "port=0x%x) failed, ret=%d", ss->ei_hca_hdl,
441*13101SVenki.Rajagopalan@Sun.COM 		    ss->ei_props->ep_port_num, ret);
442*13101SVenki.Rajagopalan@Sun.COM 		goto mac_hca_portstate_fail;
443*13101SVenki.Rajagopalan@Sun.COM 	}
444*13101SVenki.Rajagopalan@Sun.COM 	if (num_pi != 1) {
445*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_ERR(ss->ei_instance,
446*13101SVenki.Rajagopalan@Sun.COM 		    "ibt_query_hca_ports(hca_hdl=0x%llx, "
447*13101SVenki.Rajagopalan@Sun.COM 		    "port=0x%x) returned num_pi=%d", ss->ei_hca_hdl,
448*13101SVenki.Rajagopalan@Sun.COM 		    ss->ei_props->ep_port_num, num_pi);
449*13101SVenki.Rajagopalan@Sun.COM 		goto mac_hca_portstate_fail;
450*13101SVenki.Rajagopalan@Sun.COM 	}
451*13101SVenki.Rajagopalan@Sun.COM 
452*13101SVenki.Rajagopalan@Sun.COM 	if (pi->p_linkstate != IBT_PORT_ACTIVE)
453*13101SVenki.Rajagopalan@Sun.COM 		goto mac_hca_portstate_fail;
454*13101SVenki.Rajagopalan@Sun.COM 
455*13101SVenki.Rajagopalan@Sun.COM 	/*
456*13101SVenki.Rajagopalan@Sun.COM 	 * Return the port's base lid if asked
457*13101SVenki.Rajagopalan@Sun.COM 	 */
458*13101SVenki.Rajagopalan@Sun.COM 	if (blid) {
459*13101SVenki.Rajagopalan@Sun.COM 		*blid = pi->p_base_lid;
460*13101SVenki.Rajagopalan@Sun.COM 	}
461*13101SVenki.Rajagopalan@Sun.COM 
462*13101SVenki.Rajagopalan@Sun.COM 	ibt_free_portinfo(pi, sz_pi);
463*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_SUCCESS);
464*13101SVenki.Rajagopalan@Sun.COM 
465*13101SVenki.Rajagopalan@Sun.COM mac_hca_portstate_fail:
466*13101SVenki.Rajagopalan@Sun.COM 	if (pi) {
467*13101SVenki.Rajagopalan@Sun.COM 		ibt_free_portinfo(pi, sz_pi);
468*13101SVenki.Rajagopalan@Sun.COM 	}
469*13101SVenki.Rajagopalan@Sun.COM 	if (err) {
470*13101SVenki.Rajagopalan@Sun.COM 		*err = ENETDOWN;
471*13101SVenki.Rajagopalan@Sun.COM 	}
472*13101SVenki.Rajagopalan@Sun.COM 	return (EIB_E_FAILURE);
473*13101SVenki.Rajagopalan@Sun.COM }
474*13101SVenki.Rajagopalan@Sun.COM 
475*13101SVenki.Rajagopalan@Sun.COM static void
eib_rb_mac_start(eib_t * ss,eib_vnic_t * vnic0)476*13101SVenki.Rajagopalan@Sun.COM eib_rb_mac_start(eib_t *ss, eib_vnic_t *vnic0)
477*13101SVenki.Rajagopalan@Sun.COM {
478*13101SVenki.Rajagopalan@Sun.COM 	int ntries;
479*13101SVenki.Rajagopalan@Sun.COM 
480*13101SVenki.Rajagopalan@Sun.COM 	/*
481*13101SVenki.Rajagopalan@Sun.COM 	 * If vnic0 is non-null, delete it
482*13101SVenki.Rajagopalan@Sun.COM 	 */
483*13101SVenki.Rajagopalan@Sun.COM 	if (vnic0) {
484*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_vnic_create(ss, vnic0, ~0);
485*13101SVenki.Rajagopalan@Sun.COM 	}
486*13101SVenki.Rajagopalan@Sun.COM 
487*13101SVenki.Rajagopalan@Sun.COM 	/*
488*13101SVenki.Rajagopalan@Sun.COM 	 * At this point, we're pretty much done with all communication that
489*13101SVenki.Rajagopalan@Sun.COM 	 * we need to do for vnic-logout, etc. so we can get rid of any address
490*13101SVenki.Rajagopalan@Sun.COM 	 * vectors we might've allocated to send control/data packets.
491*13101SVenki.Rajagopalan@Sun.COM 	 */
492*13101SVenki.Rajagopalan@Sun.COM 	eib_ibt_free_avects(ss);
493*13101SVenki.Rajagopalan@Sun.COM 
494*13101SVenki.Rajagopalan@Sun.COM 	/*
495*13101SVenki.Rajagopalan@Sun.COM 	 * Tear down the rest of it
496*13101SVenki.Rajagopalan@Sun.COM 	 */
497*13101SVenki.Rajagopalan@Sun.COM 	if (ss->ei_admin_chan) {
498*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_adm_setup_qp(ss);
499*13101SVenki.Rajagopalan@Sun.COM 	}
500*13101SVenki.Rajagopalan@Sun.COM 
501*13101SVenki.Rajagopalan@Sun.COM 	/*
502*13101SVenki.Rajagopalan@Sun.COM 	 * If (say) the network layer has been holding onto our rx buffers, we
503*13101SVenki.Rajagopalan@Sun.COM 	 * wait a reasonable time for it to hand them back to us.  If we don't
504*13101SVenki.Rajagopalan@Sun.COM 	 * get it still, we have nothing to do but avoid rolling back hca init
505*13101SVenki.Rajagopalan@Sun.COM 	 * since we cannot unregister the memory, release the pd or close the
506*13101SVenki.Rajagopalan@Sun.COM 	 * hca.  We'll try to reuse it if there's a plumb again.
507*13101SVenki.Rajagopalan@Sun.COM 	 */
508*13101SVenki.Rajagopalan@Sun.COM 	for (ntries = 0; ntries < EIB_MAX_ATTEMPTS; ntries++) {
509*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_rsrc_setup_bufs(ss, B_FALSE);
510*13101SVenki.Rajagopalan@Sun.COM 		if ((ss->ei_tx == NULL) && (ss->ei_rx == NULL) &&
511*13101SVenki.Rajagopalan@Sun.COM 		    (ss->ei_lso == NULL)) {
512*13101SVenki.Rajagopalan@Sun.COM 			break;
513*13101SVenki.Rajagopalan@Sun.COM 		}
514*13101SVenki.Rajagopalan@Sun.COM 
515*13101SVenki.Rajagopalan@Sun.COM 		delay(drv_usectohz(EIB_DELAY_HALF_SECOND));
516*13101SVenki.Rajagopalan@Sun.COM 	}
517*13101SVenki.Rajagopalan@Sun.COM 
518*13101SVenki.Rajagopalan@Sun.COM 	if (ntries == EIB_MAX_ATTEMPTS) {
519*13101SVenki.Rajagopalan@Sun.COM 		EIB_DPRINTF_WARN(ss->ei_instance, "eib_rb_mac_start: "
520*13101SVenki.Rajagopalan@Sun.COM 		    "bufs outstanding, tx=0x%llx, rx=0x%llx, lso=0x%llx",
521*13101SVenki.Rajagopalan@Sun.COM 		    ss->ei_tx, ss->ei_rx, ss->ei_lso);
522*13101SVenki.Rajagopalan@Sun.COM 	} else if (ss->ei_hca_hdl) {
523*13101SVenki.Rajagopalan@Sun.COM 		eib_rb_ibt_hca_init(ss, ~0);
524*13101SVenki.Rajagopalan@Sun.COM 	}
525*13101SVenki.Rajagopalan@Sun.COM 	ss->ei_props->ep_blid = 0;
526*13101SVenki.Rajagopalan@Sun.COM 
527*13101SVenki.Rajagopalan@Sun.COM 	/*
528*13101SVenki.Rajagopalan@Sun.COM 	 * Pending vnic creation requests (and failed-vnic records) will have
529*13101SVenki.Rajagopalan@Sun.COM 	 * to be cleaned up in any case
530*13101SVenki.Rajagopalan@Sun.COM 	 */
531*13101SVenki.Rajagopalan@Sun.COM 	eib_flush_vnic_reqs(ss);
532*13101SVenki.Rajagopalan@Sun.COM }
533