xref: /onnv-gate/usr/src/uts/common/io/ib/adapters/hermon/hermon_fcoib.c (revision 12965:b65a8427f8fe)
1*12965SWilliam.Taylor@Oracle.COM /*
2*12965SWilliam.Taylor@Oracle.COM  * CDDL HEADER START
3*12965SWilliam.Taylor@Oracle.COM  *
4*12965SWilliam.Taylor@Oracle.COM  * The contents of this file are subject to the terms of the
5*12965SWilliam.Taylor@Oracle.COM  * Common Development and Distribution License (the "License").
6*12965SWilliam.Taylor@Oracle.COM  * You may not use this file except in compliance with the License.
7*12965SWilliam.Taylor@Oracle.COM  *
8*12965SWilliam.Taylor@Oracle.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12965SWilliam.Taylor@Oracle.COM  * or http://www.opensolaris.org/os/licensing.
10*12965SWilliam.Taylor@Oracle.COM  * See the License for the specific language governing permissions
11*12965SWilliam.Taylor@Oracle.COM  * and limitations under the License.
12*12965SWilliam.Taylor@Oracle.COM  *
13*12965SWilliam.Taylor@Oracle.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*12965SWilliam.Taylor@Oracle.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12965SWilliam.Taylor@Oracle.COM  * If applicable, add the following below this CDDL HEADER, with the
16*12965SWilliam.Taylor@Oracle.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*12965SWilliam.Taylor@Oracle.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*12965SWilliam.Taylor@Oracle.COM  *
19*12965SWilliam.Taylor@Oracle.COM  * CDDL HEADER END
20*12965SWilliam.Taylor@Oracle.COM  */
21*12965SWilliam.Taylor@Oracle.COM 
22*12965SWilliam.Taylor@Oracle.COM /*
23*12965SWilliam.Taylor@Oracle.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*12965SWilliam.Taylor@Oracle.COM  */
25*12965SWilliam.Taylor@Oracle.COM 
26*12965SWilliam.Taylor@Oracle.COM /*
27*12965SWilliam.Taylor@Oracle.COM  * hermon_fcoib.c
28*12965SWilliam.Taylor@Oracle.COM  *    Hermon Fibre Channel over IB routines
29*12965SWilliam.Taylor@Oracle.COM  *
30*12965SWilliam.Taylor@Oracle.COM  *    Implements all the routines necessary for setting up, using, and
31*12965SWilliam.Taylor@Oracle.COM  *    (later) tearing down all the FCoIB state.
32*12965SWilliam.Taylor@Oracle.COM  */
33*12965SWilliam.Taylor@Oracle.COM 
34*12965SWilliam.Taylor@Oracle.COM #include <sys/ib/adapters/hermon/hermon.h>
35*12965SWilliam.Taylor@Oracle.COM 
36*12965SWilliam.Taylor@Oracle.COM /*
37*12965SWilliam.Taylor@Oracle.COM  * hermon_fcoib_enable()
38*12965SWilliam.Taylor@Oracle.COM  *    Context: user or kernel context
39*12965SWilliam.Taylor@Oracle.COM  */
40*12965SWilliam.Taylor@Oracle.COM static int
hermon_fcoib_enable(hermon_state_t * state,int port)41*12965SWilliam.Taylor@Oracle.COM hermon_fcoib_enable(hermon_state_t *state, int port)
42*12965SWilliam.Taylor@Oracle.COM {
43*12965SWilliam.Taylor@Oracle.COM 	hermon_fcoib_t	*fcoib;
44*12965SWilliam.Taylor@Oracle.COM 	hermon_hw_config_fc_basic_t config_fc_basic;
45*12965SWilliam.Taylor@Oracle.COM 	int		status;
46*12965SWilliam.Taylor@Oracle.COM 
47*12965SWilliam.Taylor@Oracle.COM 	port--;		/* passed in as 1 or 2, used as 0 or 1 */
48*12965SWilliam.Taylor@Oracle.COM 	ASSERT(port >= 0 && port < HERMON_MAX_PORTS);
49*12965SWilliam.Taylor@Oracle.COM 	fcoib = &state->hs_fcoib;
50*12965SWilliam.Taylor@Oracle.COM 
51*12965SWilliam.Taylor@Oracle.COM 	/* Configure FCoIB on the port */
52*12965SWilliam.Taylor@Oracle.COM 	bzero(&config_fc_basic, sizeof (config_fc_basic));
53*12965SWilliam.Taylor@Oracle.COM 	config_fc_basic.fexch_base_hi = fcoib->hfc_fexch_base[port] >> 16;
54*12965SWilliam.Taylor@Oracle.COM 	config_fc_basic.fx_base_mpt_hi = fcoib->hfc_mpt_base[port] >> 17;
55*12965SWilliam.Taylor@Oracle.COM 	config_fc_basic.fx_base_mpt_lo = 0;
56*12965SWilliam.Taylor@Oracle.COM 	config_fc_basic.log2_num_rfci =
57*12965SWilliam.Taylor@Oracle.COM 	    state->hs_ibtfinfo.hca_attr->hca_rfci_max_log2_qp;
58*12965SWilliam.Taylor@Oracle.COM 	config_fc_basic.rfci_base = fcoib->hfc_rfci_qps_per_port * port +
59*12965SWilliam.Taylor@Oracle.COM 	    fcoib->hfc_rfci_rsrc->hr_indx;
60*12965SWilliam.Taylor@Oracle.COM #if 1
61*12965SWilliam.Taylor@Oracle.COM 	status = hermon_config_fc_cmd_post(state, &config_fc_basic, 1,
62*12965SWilliam.Taylor@Oracle.COM 	    HERMON_HW_FC_CONF_BASIC, 0, port + 1, HERMON_CMD_NOSLEEP_SPIN);
63*12965SWilliam.Taylor@Oracle.COM #else
64*12965SWilliam.Taylor@Oracle.COM 	status = hermon_config_fc_cmd_post(state, &config_fc_basic, 1,
65*12965SWilliam.Taylor@Oracle.COM 	    HERMON_HW_FC_CONF_BASIC, 0, 0, HERMON_CMD_NOSLEEP_SPIN);
66*12965SWilliam.Taylor@Oracle.COM #endif
67*12965SWilliam.Taylor@Oracle.COM 	if (status != HERMON_CMD_SUCCESS) {
68*12965SWilliam.Taylor@Oracle.COM 		cmn_err(CE_CONT, "fcoib_enable failed: status 0x%x\n", status);
69*12965SWilliam.Taylor@Oracle.COM 		HERMON_WARNING(state, "fcoib_enable failed");
70*12965SWilliam.Taylor@Oracle.COM 		return (DDI_FAILURE);
71*12965SWilliam.Taylor@Oracle.COM 	}
72*12965SWilliam.Taylor@Oracle.COM 	fcoib->hfc_port_enabled[port] = 1;
73*12965SWilliam.Taylor@Oracle.COM 	state->hs_fcoib_may_be_running = B_TRUE;
74*12965SWilliam.Taylor@Oracle.COM 	return (DDI_SUCCESS);
75*12965SWilliam.Taylor@Oracle.COM }
76*12965SWilliam.Taylor@Oracle.COM 
77*12965SWilliam.Taylor@Oracle.COM /*
78*12965SWilliam.Taylor@Oracle.COM  * hermon_fcoib_set_id()
79*12965SWilliam.Taylor@Oracle.COM  *    Context: user or kernel context
80*12965SWilliam.Taylor@Oracle.COM  */
81*12965SWilliam.Taylor@Oracle.COM int
hermon_fcoib_set_id(hermon_state_t * state,int port,uint32_t rfci_qpn,uint32_t src_id)82*12965SWilliam.Taylor@Oracle.COM hermon_fcoib_set_id(hermon_state_t *state, int port, uint32_t rfci_qpn,
83*12965SWilliam.Taylor@Oracle.COM     uint32_t src_id)
84*12965SWilliam.Taylor@Oracle.COM {
85*12965SWilliam.Taylor@Oracle.COM 	hermon_fcoib_t	*fcoib;
86*12965SWilliam.Taylor@Oracle.COM 	int		status;
87*12965SWilliam.Taylor@Oracle.COM 	int		offset;
88*12965SWilliam.Taylor@Oracle.COM 	uint32_t	*n_port_ids;
89*12965SWilliam.Taylor@Oracle.COM 
90*12965SWilliam.Taylor@Oracle.COM 	port--;		/* passed in as 1 or 2, used as 0 or 1 */
91*12965SWilliam.Taylor@Oracle.COM 	ASSERT(port >= 0 && port < HERMON_MAX_PORTS);
92*12965SWilliam.Taylor@Oracle.COM 	fcoib = &state->hs_fcoib;
93*12965SWilliam.Taylor@Oracle.COM 	mutex_enter(&fcoib->hfc_lock);
94*12965SWilliam.Taylor@Oracle.COM 
95*12965SWilliam.Taylor@Oracle.COM 	if (fcoib->hfc_port_enabled[port] == 0) {
96*12965SWilliam.Taylor@Oracle.COM 		if (hermon_fcoib_enable(state, port + 1) != DDI_SUCCESS) {
97*12965SWilliam.Taylor@Oracle.COM 			mutex_exit(&fcoib->hfc_lock);
98*12965SWilliam.Taylor@Oracle.COM 			return (DDI_FAILURE);
99*12965SWilliam.Taylor@Oracle.COM 		}
100*12965SWilliam.Taylor@Oracle.COM 	}
101*12965SWilliam.Taylor@Oracle.COM 
102*12965SWilliam.Taylor@Oracle.COM 	n_port_ids = fcoib->hfc_n_port_ids[port];
103*12965SWilliam.Taylor@Oracle.COM 	offset = rfci_qpn - fcoib->hfc_rfci_base[port];
104*12965SWilliam.Taylor@Oracle.COM 	ASSERT(offset >= 0 && offset < fcoib->hfc_rfci_qps_per_port);
105*12965SWilliam.Taylor@Oracle.COM 	n_port_ids[offset] = src_id;
106*12965SWilliam.Taylor@Oracle.COM 
107*12965SWilliam.Taylor@Oracle.COM 	status = hermon_config_fc_cmd_post(state, n_port_ids, 1,
108*12965SWilliam.Taylor@Oracle.COM 	    HERMON_HW_FC_CONF_NPORT, fcoib->hfc_rfci_qps_per_port,
109*12965SWilliam.Taylor@Oracle.COM 	    port + 1, HERMON_CMD_NOSLEEP_SPIN);
110*12965SWilliam.Taylor@Oracle.COM 	if (status != HERMON_CMD_SUCCESS) {
111*12965SWilliam.Taylor@Oracle.COM 		HERMON_WARNING(state, "fcoib_set_id failed");
112*12965SWilliam.Taylor@Oracle.COM 		mutex_exit(&fcoib->hfc_lock);
113*12965SWilliam.Taylor@Oracle.COM 		return (DDI_FAILURE);
114*12965SWilliam.Taylor@Oracle.COM 	}
115*12965SWilliam.Taylor@Oracle.COM 	mutex_exit(&fcoib->hfc_lock);
116*12965SWilliam.Taylor@Oracle.COM 	return (DDI_SUCCESS);
117*12965SWilliam.Taylor@Oracle.COM }
118*12965SWilliam.Taylor@Oracle.COM 
119*12965SWilliam.Taylor@Oracle.COM /*
120*12965SWilliam.Taylor@Oracle.COM  * hermon_fcoib_get_id_idx()
121*12965SWilliam.Taylor@Oracle.COM  *    Context: user or kernel context
122*12965SWilliam.Taylor@Oracle.COM  */
123*12965SWilliam.Taylor@Oracle.COM int
hermon_fcoib_get_id_idx(hermon_state_t * state,int port,ibt_fc_attr_t * fcp)124*12965SWilliam.Taylor@Oracle.COM hermon_fcoib_get_id_idx(hermon_state_t *state, int port, ibt_fc_attr_t *fcp)
125*12965SWilliam.Taylor@Oracle.COM {
126*12965SWilliam.Taylor@Oracle.COM 	hermon_fcoib_t	*fcoib;
127*12965SWilliam.Taylor@Oracle.COM 	int		idx;
128*12965SWilliam.Taylor@Oracle.COM 
129*12965SWilliam.Taylor@Oracle.COM 	port--;		/* passed in as 1 or 2, used as 0 or 1 */
130*12965SWilliam.Taylor@Oracle.COM 	ASSERT(port >= 0 && port < HERMON_MAX_PORTS);
131*12965SWilliam.Taylor@Oracle.COM 	fcoib = &state->hs_fcoib;
132*12965SWilliam.Taylor@Oracle.COM 
133*12965SWilliam.Taylor@Oracle.COM 	idx = fcp->fc_rfci_qpn - fcoib->hfc_rfci_base[port];
134*12965SWilliam.Taylor@Oracle.COM 	if (idx < 0 || idx >= fcoib->hfc_rfci_qps_per_port)
135*12965SWilliam.Taylor@Oracle.COM 		idx = -1;
136*12965SWilliam.Taylor@Oracle.COM 
137*12965SWilliam.Taylor@Oracle.COM 	return (idx);
138*12965SWilliam.Taylor@Oracle.COM }
139*12965SWilliam.Taylor@Oracle.COM 
140*12965SWilliam.Taylor@Oracle.COM /*
141*12965SWilliam.Taylor@Oracle.COM  * hermon_fcoib_get_exch_base()
142*12965SWilliam.Taylor@Oracle.COM  *    Context: user or kernel context
143*12965SWilliam.Taylor@Oracle.COM  */
144*12965SWilliam.Taylor@Oracle.COM int
hermon_fcoib_check_exch_base_off(hermon_state_t * state,int port,ibt_fc_attr_t * fcp)145*12965SWilliam.Taylor@Oracle.COM hermon_fcoib_check_exch_base_off(hermon_state_t *state, int port,
146*12965SWilliam.Taylor@Oracle.COM     ibt_fc_attr_t *fcp)
147*12965SWilliam.Taylor@Oracle.COM {
148*12965SWilliam.Taylor@Oracle.COM 	hermon_fcoib_t	*fcoib;
149*12965SWilliam.Taylor@Oracle.COM 	int		exch_base_off;
150*12965SWilliam.Taylor@Oracle.COM 
151*12965SWilliam.Taylor@Oracle.COM 	port--;		/* passed in as 1 or 2, used as 0 or 1 */
152*12965SWilliam.Taylor@Oracle.COM 	ASSERT(port >= 0 && port < HERMON_MAX_PORTS);
153*12965SWilliam.Taylor@Oracle.COM 	fcoib = &state->hs_fcoib;
154*12965SWilliam.Taylor@Oracle.COM 
155*12965SWilliam.Taylor@Oracle.COM 	exch_base_off = fcp->fc_exch_base_off;
156*12965SWilliam.Taylor@Oracle.COM 	if (exch_base_off >= fcoib->hfc_fexch_qps_per_port)
157*12965SWilliam.Taylor@Oracle.COM 		exch_base_off = -1;
158*12965SWilliam.Taylor@Oracle.COM 
159*12965SWilliam.Taylor@Oracle.COM 	return (exch_base_off);
160*12965SWilliam.Taylor@Oracle.COM }
161*12965SWilliam.Taylor@Oracle.COM 
162*12965SWilliam.Taylor@Oracle.COM /*
163*12965SWilliam.Taylor@Oracle.COM  * hermon_fcoib_qpnum_from_fexch()
164*12965SWilliam.Taylor@Oracle.COM  *    Context: user, kernel, or interrupt context
165*12965SWilliam.Taylor@Oracle.COM  */
166*12965SWilliam.Taylor@Oracle.COM int
hermon_fcoib_is_fexch_qpn(hermon_state_t * state,uint_t qpnum)167*12965SWilliam.Taylor@Oracle.COM hermon_fcoib_is_fexch_qpn(hermon_state_t *state, uint_t qpnum)
168*12965SWilliam.Taylor@Oracle.COM {
169*12965SWilliam.Taylor@Oracle.COM 	hermon_fcoib_t	*fcoib;
170*12965SWilliam.Taylor@Oracle.COM 
171*12965SWilliam.Taylor@Oracle.COM 	fcoib = &state->hs_fcoib;
172*12965SWilliam.Taylor@Oracle.COM 	qpnum -= fcoib->hfc_fexch_rsrc->hr_indx;
173*12965SWilliam.Taylor@Oracle.COM 	return (qpnum < fcoib->hfc_nports * fcoib->hfc_fexch_qps_per_port);
174*12965SWilliam.Taylor@Oracle.COM }
175*12965SWilliam.Taylor@Oracle.COM 
176*12965SWilliam.Taylor@Oracle.COM /*
177*12965SWilliam.Taylor@Oracle.COM  * hermon_fcoib_qpnum_from_fexch()
178*12965SWilliam.Taylor@Oracle.COM  *    Context: user, kernel, or interrupt context
179*12965SWilliam.Taylor@Oracle.COM  */
180*12965SWilliam.Taylor@Oracle.COM uint_t
hermon_fcoib_qpnum_from_fexch(hermon_state_t * state,int port,uint16_t fexch)181*12965SWilliam.Taylor@Oracle.COM hermon_fcoib_qpnum_from_fexch(hermon_state_t *state, int port,
182*12965SWilliam.Taylor@Oracle.COM     uint16_t fexch)
183*12965SWilliam.Taylor@Oracle.COM {
184*12965SWilliam.Taylor@Oracle.COM 	hermon_fcoib_t	*fcoib;
185*12965SWilliam.Taylor@Oracle.COM 	uint_t		qpnum;
186*12965SWilliam.Taylor@Oracle.COM 
187*12965SWilliam.Taylor@Oracle.COM 	port--;		/* passed in as 1 or 2, used as 0 or 1 */
188*12965SWilliam.Taylor@Oracle.COM 	ASSERT(port >= 0 && port < HERMON_MAX_PORTS);
189*12965SWilliam.Taylor@Oracle.COM 	fcoib = &state->hs_fcoib;
190*12965SWilliam.Taylor@Oracle.COM 	qpnum = fexch + fcoib->hfc_fexch_base[port];
191*12965SWilliam.Taylor@Oracle.COM 	return (qpnum);
192*12965SWilliam.Taylor@Oracle.COM }
193*12965SWilliam.Taylor@Oracle.COM 
194*12965SWilliam.Taylor@Oracle.COM /*
195*12965SWilliam.Taylor@Oracle.COM  * hermon_fcoib_qpn_to_mkey
196*12965SWilliam.Taylor@Oracle.COM  *    Context: user or kernel context
197*12965SWilliam.Taylor@Oracle.COM  */
198*12965SWilliam.Taylor@Oracle.COM uint32_t
hermon_fcoib_qpn_to_mkey(hermon_state_t * state,uint_t qpnum)199*12965SWilliam.Taylor@Oracle.COM hermon_fcoib_qpn_to_mkey(hermon_state_t *state, uint_t qpnum)
200*12965SWilliam.Taylor@Oracle.COM {
201*12965SWilliam.Taylor@Oracle.COM 	int		i;
202*12965SWilliam.Taylor@Oracle.COM 	hermon_fcoib_t	*fcoib;
203*12965SWilliam.Taylor@Oracle.COM 	uint32_t	qp_indx;
204*12965SWilliam.Taylor@Oracle.COM 
205*12965SWilliam.Taylor@Oracle.COM 	fcoib = &state->hs_fcoib;
206*12965SWilliam.Taylor@Oracle.COM 	for (i = 0; i < fcoib->hfc_nports; i++) {
207*12965SWilliam.Taylor@Oracle.COM 		qp_indx = qpnum - fcoib->hfc_fexch_base[i];
208*12965SWilliam.Taylor@Oracle.COM 		if (qp_indx < fcoib->hfc_fexch_qps_per_port)
209*12965SWilliam.Taylor@Oracle.COM 			return ((qp_indx + fcoib->hfc_mpt_base[i]) << 8);
210*12965SWilliam.Taylor@Oracle.COM 	}
211*12965SWilliam.Taylor@Oracle.COM 	return ((uint32_t)-1);	/* cannot get here with valid qpnum argument */
212*12965SWilliam.Taylor@Oracle.COM }
213*12965SWilliam.Taylor@Oracle.COM 
214*12965SWilliam.Taylor@Oracle.COM /*
215*12965SWilliam.Taylor@Oracle.COM  * hermon_fcoib_fexch_relative_qpn()
216*12965SWilliam.Taylor@Oracle.COM  *    Context: user or kernel context
217*12965SWilliam.Taylor@Oracle.COM  */
218*12965SWilliam.Taylor@Oracle.COM uint32_t
hermon_fcoib_fexch_relative_qpn(hermon_state_t * state,uint8_t port,uint32_t qp_indx)219*12965SWilliam.Taylor@Oracle.COM hermon_fcoib_fexch_relative_qpn(hermon_state_t *state, uint8_t port,
220*12965SWilliam.Taylor@Oracle.COM     uint32_t qp_indx)
221*12965SWilliam.Taylor@Oracle.COM {
222*12965SWilliam.Taylor@Oracle.COM 	port--;
223*12965SWilliam.Taylor@Oracle.COM 	ASSERT(port < HERMON_MAX_PORTS);
224*12965SWilliam.Taylor@Oracle.COM 	qp_indx -= state->hs_fcoib.hfc_fexch_base[port];
225*12965SWilliam.Taylor@Oracle.COM 	return (qp_indx);
226*12965SWilliam.Taylor@Oracle.COM }
227*12965SWilliam.Taylor@Oracle.COM 
228*12965SWilliam.Taylor@Oracle.COM /*
229*12965SWilliam.Taylor@Oracle.COM  * hermon_fcoib_fexch_mkey_init()
230*12965SWilliam.Taylor@Oracle.COM  *    Context: user or kernel context
231*12965SWilliam.Taylor@Oracle.COM  */
232*12965SWilliam.Taylor@Oracle.COM int
hermon_fcoib_fexch_mkey_init(hermon_state_t * state,hermon_pdhdl_t pd,uint8_t port,uint32_t qp_indx,uint_t sleep)233*12965SWilliam.Taylor@Oracle.COM hermon_fcoib_fexch_mkey_init(hermon_state_t *state, hermon_pdhdl_t pd,
234*12965SWilliam.Taylor@Oracle.COM     uint8_t port, uint32_t qp_indx, uint_t sleep)
235*12965SWilliam.Taylor@Oracle.COM {
236*12965SWilliam.Taylor@Oracle.COM 	int		status;
237*12965SWilliam.Taylor@Oracle.COM 	uint32_t	mpt_indx;
238*12965SWilliam.Taylor@Oracle.COM 	uint_t		nummtt;
239*12965SWilliam.Taylor@Oracle.COM 	uint64_t	mtt_addr;
240*12965SWilliam.Taylor@Oracle.COM 	hermon_fcoib_t	*fcoib;
241*12965SWilliam.Taylor@Oracle.COM 
242*12965SWilliam.Taylor@Oracle.COM 	port--;
243*12965SWilliam.Taylor@Oracle.COM 	ASSERT(port < HERMON_MAX_PORTS);
244*12965SWilliam.Taylor@Oracle.COM 	fcoib = &state->hs_fcoib;
245*12965SWilliam.Taylor@Oracle.COM 	qp_indx -= fcoib->hfc_fexch_base[port];	/* relative to FEXCH base */
246*12965SWilliam.Taylor@Oracle.COM 	if (qp_indx > fcoib->hfc_fexch_qps_per_port)
247*12965SWilliam.Taylor@Oracle.COM 		return (IBT_INVALID_PARAM);
248*12965SWilliam.Taylor@Oracle.COM 	mpt_indx = qp_indx + fcoib->hfc_mpt_base[port];
249*12965SWilliam.Taylor@Oracle.COM 	nummtt = fcoib->hfc_mtts_per_mpt;
250*12965SWilliam.Taylor@Oracle.COM 	mtt_addr = ((uint64_t)qp_indx * nummtt + fcoib->hfc_mtt_base[port]) <<
251*12965SWilliam.Taylor@Oracle.COM 	    HERMON_MTT_SIZE_SHIFT;
252*12965SWilliam.Taylor@Oracle.COM 
253*12965SWilliam.Taylor@Oracle.COM 	status = hermon_mr_fexch_mpt_init(state, pd, mpt_indx,
254*12965SWilliam.Taylor@Oracle.COM 	    nummtt, mtt_addr, sleep);
255*12965SWilliam.Taylor@Oracle.COM 	return (status);
256*12965SWilliam.Taylor@Oracle.COM }
257*12965SWilliam.Taylor@Oracle.COM 
258*12965SWilliam.Taylor@Oracle.COM /*
259*12965SWilliam.Taylor@Oracle.COM  * hermon_fcoib_fexch_mkey_fini()
260*12965SWilliam.Taylor@Oracle.COM  *    Context: user or kernel context
261*12965SWilliam.Taylor@Oracle.COM  */
262*12965SWilliam.Taylor@Oracle.COM int
hermon_fcoib_fexch_mkey_fini(hermon_state_t * state,hermon_pdhdl_t pd,uint32_t qpnum,uint_t sleep)263*12965SWilliam.Taylor@Oracle.COM hermon_fcoib_fexch_mkey_fini(hermon_state_t *state, hermon_pdhdl_t pd,
264*12965SWilliam.Taylor@Oracle.COM     uint32_t qpnum, uint_t sleep)
265*12965SWilliam.Taylor@Oracle.COM {
266*12965SWilliam.Taylor@Oracle.COM 	int		status;
267*12965SWilliam.Taylor@Oracle.COM 	uint8_t		port;
268*12965SWilliam.Taylor@Oracle.COM 	uint32_t	qp_indx;
269*12965SWilliam.Taylor@Oracle.COM 	uint32_t	mpt_indx;
270*12965SWilliam.Taylor@Oracle.COM 	hermon_fcoib_t	*fcoib;
271*12965SWilliam.Taylor@Oracle.COM 
272*12965SWilliam.Taylor@Oracle.COM 	fcoib = &state->hs_fcoib;
273*12965SWilliam.Taylor@Oracle.COM 	for (port = 0; port < fcoib->hfc_nports; port++) {
274*12965SWilliam.Taylor@Oracle.COM 		qp_indx = qpnum - fcoib->hfc_fexch_base[port];
275*12965SWilliam.Taylor@Oracle.COM 		if (qp_indx < fcoib->hfc_fexch_qps_per_port)
276*12965SWilliam.Taylor@Oracle.COM 			goto found;
277*12965SWilliam.Taylor@Oracle.COM 	}
278*12965SWilliam.Taylor@Oracle.COM 	return (IBT_INVALID_PARAM);
279*12965SWilliam.Taylor@Oracle.COM found:
280*12965SWilliam.Taylor@Oracle.COM 	/* qp_indx relative to FEXCH base */
281*12965SWilliam.Taylor@Oracle.COM 	mpt_indx = qp_indx + fcoib->hfc_mpt_base[port];
282*12965SWilliam.Taylor@Oracle.COM 
283*12965SWilliam.Taylor@Oracle.COM 	status = hermon_mr_fexch_mpt_fini(state, pd, mpt_indx, sleep);
284*12965SWilliam.Taylor@Oracle.COM 	return (status);
285*12965SWilliam.Taylor@Oracle.COM }
286*12965SWilliam.Taylor@Oracle.COM 
287*12965SWilliam.Taylor@Oracle.COM /*
288*12965SWilliam.Taylor@Oracle.COM  * hermon_fcoib_query_fc()
289*12965SWilliam.Taylor@Oracle.COM  *    Context: user or kernel context
290*12965SWilliam.Taylor@Oracle.COM  */
291*12965SWilliam.Taylor@Oracle.COM void
hermon_fcoib_query_fc(hermon_state_t * state,hermon_fcoib_t * fcoib)292*12965SWilliam.Taylor@Oracle.COM hermon_fcoib_query_fc(hermon_state_t *state, hermon_fcoib_t *fcoib)
293*12965SWilliam.Taylor@Oracle.COM {
294*12965SWilliam.Taylor@Oracle.COM 	int status;
295*12965SWilliam.Taylor@Oracle.COM 	struct hermon_hw_query_fc_s query_fc;
296*12965SWilliam.Taylor@Oracle.COM 
297*12965SWilliam.Taylor@Oracle.COM 	status = hermon_cmn_query_cmd_post(state, QUERY_FC, 0, 0, &query_fc,
298*12965SWilliam.Taylor@Oracle.COM 	    sizeof (query_fc), HERMON_CMD_NOSLEEP_SPIN);
299*12965SWilliam.Taylor@Oracle.COM 	if (status == HERMON_CMD_SUCCESS) {
300*12965SWilliam.Taylor@Oracle.COM 		fcoib->hfc_log2_max_port_ids_queried = query_fc.log2_max_nports;
301*12965SWilliam.Taylor@Oracle.COM 		fcoib->hfc_log2_max_fexch_queried = query_fc.log2_max_fexch;
302*12965SWilliam.Taylor@Oracle.COM 		fcoib->hfc_log2_max_rfci_queried = query_fc.log2_max_rfci;
303*12965SWilliam.Taylor@Oracle.COM 	} else
304*12965SWilliam.Taylor@Oracle.COM 		cmn_err(CE_CONT, "!query_fc status 0x%x\n", status);
305*12965SWilliam.Taylor@Oracle.COM }
306*12965SWilliam.Taylor@Oracle.COM 
307*12965SWilliam.Taylor@Oracle.COM /*
308*12965SWilliam.Taylor@Oracle.COM  * hermon_fcoib_init()
309*12965SWilliam.Taylor@Oracle.COM  *    Context: Only called from attach() path context
310*12965SWilliam.Taylor@Oracle.COM  */
311*12965SWilliam.Taylor@Oracle.COM int
hermon_fcoib_init(hermon_state_t * state)312*12965SWilliam.Taylor@Oracle.COM hermon_fcoib_init(hermon_state_t *state)
313*12965SWilliam.Taylor@Oracle.COM {
314*12965SWilliam.Taylor@Oracle.COM 	hermon_fcoib_t	*fcoib;
315*12965SWilliam.Taylor@Oracle.COM 	uint_t		numports;
316*12965SWilliam.Taylor@Oracle.COM 	char		string[128];
317*12965SWilliam.Taylor@Oracle.COM 	int		i;
318*12965SWilliam.Taylor@Oracle.COM 	uintptr_t	vmemstart = (uintptr_t)0x10000000;
319*12965SWilliam.Taylor@Oracle.COM 
320*12965SWilliam.Taylor@Oracle.COM 	/* used for fast checking for FCoIB during cqe_consume */
321*12965SWilliam.Taylor@Oracle.COM 	state->hs_fcoib_may_be_running = B_FALSE;
322*12965SWilliam.Taylor@Oracle.COM 
323*12965SWilliam.Taylor@Oracle.COM 	if ((state->hs_ibtfinfo.hca_attr->hca_flags2 & IBT_HCA2_FC) == 0)
324*12965SWilliam.Taylor@Oracle.COM 		return (DDI_SUCCESS);
325*12965SWilliam.Taylor@Oracle.COM 
326*12965SWilliam.Taylor@Oracle.COM 	fcoib = &state->hs_fcoib;
327*12965SWilliam.Taylor@Oracle.COM 	bzero(fcoib, sizeof (*fcoib));
328*12965SWilliam.Taylor@Oracle.COM 
329*12965SWilliam.Taylor@Oracle.COM 	hermon_fcoib_query_fc(state, fcoib);
330*12965SWilliam.Taylor@Oracle.COM 
331*12965SWilliam.Taylor@Oracle.COM 	mutex_init(&fcoib->hfc_lock, NULL, MUTEX_DRIVER, NULL);
332*12965SWilliam.Taylor@Oracle.COM 	mutex_enter(&fcoib->hfc_lock);
333*12965SWilliam.Taylor@Oracle.COM 
334*12965SWilliam.Taylor@Oracle.COM 	/* use a ROUND value that works on both 32 and 64-bit kernels */
335*12965SWilliam.Taylor@Oracle.COM 	fcoib->hfc_vmemstart = vmemstart;
336*12965SWilliam.Taylor@Oracle.COM 
337*12965SWilliam.Taylor@Oracle.COM 	fcoib->hfc_nports = numports = state->hs_cfg_profile->cp_num_ports;
338*12965SWilliam.Taylor@Oracle.COM 	fcoib->hfc_fexch_qps_per_port =
339*12965SWilliam.Taylor@Oracle.COM 	    1 << state->hs_ibtfinfo.hca_attr->hca_fexch_max_log2_qp;
340*12965SWilliam.Taylor@Oracle.COM 	fcoib->hfc_mpts_per_port = fcoib->hfc_fexch_qps_per_port * 2;
341*12965SWilliam.Taylor@Oracle.COM 	fcoib->hfc_mtts_per_mpt =
342*12965SWilliam.Taylor@Oracle.COM 	    (1 << state->hs_ibtfinfo.hca_attr->hca_fexch_max_log2_mem) >>
343*12965SWilliam.Taylor@Oracle.COM 	    PAGESHIFT;
344*12965SWilliam.Taylor@Oracle.COM 	fcoib->hfc_rfci_qps_per_port =
345*12965SWilliam.Taylor@Oracle.COM 	    1 << state->hs_ibtfinfo.hca_attr->hca_rfci_max_log2_qp;
346*12965SWilliam.Taylor@Oracle.COM 
347*12965SWilliam.Taylor@Oracle.COM 	if (hermon_rsrc_reserve(state, HERMON_DMPT, numports *
348*12965SWilliam.Taylor@Oracle.COM 	    fcoib->hfc_mpts_per_port, HERMON_SLEEP,
349*12965SWilliam.Taylor@Oracle.COM 	    &fcoib->hfc_mpt_rsrc) != DDI_SUCCESS) {
350*12965SWilliam.Taylor@Oracle.COM 		mutex_exit(&fcoib->hfc_lock);
351*12965SWilliam.Taylor@Oracle.COM 		hermon_fcoib_fini(state);
352*12965SWilliam.Taylor@Oracle.COM 		return (DDI_FAILURE);
353*12965SWilliam.Taylor@Oracle.COM 	}
354*12965SWilliam.Taylor@Oracle.COM 
355*12965SWilliam.Taylor@Oracle.COM 	/*
356*12965SWilliam.Taylor@Oracle.COM 	 * Only reserve MTTs for the Primary MPTs (first half of the
357*12965SWilliam.Taylor@Oracle.COM 	 * range for each port).
358*12965SWilliam.Taylor@Oracle.COM 	 */
359*12965SWilliam.Taylor@Oracle.COM 	if (hermon_rsrc_reserve(state, HERMON_MTT, numports *
360*12965SWilliam.Taylor@Oracle.COM 	    fcoib->hfc_mpts_per_port * fcoib->hfc_mtts_per_mpt / 2,
361*12965SWilliam.Taylor@Oracle.COM 	    HERMON_SLEEP, &fcoib->hfc_mtt_rsrc) != DDI_SUCCESS) {
362*12965SWilliam.Taylor@Oracle.COM 		mutex_exit(&fcoib->hfc_lock);
363*12965SWilliam.Taylor@Oracle.COM 		hermon_fcoib_fini(state);
364*12965SWilliam.Taylor@Oracle.COM 		return (DDI_FAILURE);
365*12965SWilliam.Taylor@Oracle.COM 	}
366*12965SWilliam.Taylor@Oracle.COM 	if (hermon_rsrc_reserve(state, HERMON_QPC, numports *
367*12965SWilliam.Taylor@Oracle.COM 	    fcoib->hfc_fexch_qps_per_port, HERMON_SLEEP,
368*12965SWilliam.Taylor@Oracle.COM 	    &fcoib->hfc_fexch_rsrc) != DDI_SUCCESS) {
369*12965SWilliam.Taylor@Oracle.COM 		mutex_exit(&fcoib->hfc_lock);
370*12965SWilliam.Taylor@Oracle.COM 		hermon_fcoib_fini(state);
371*12965SWilliam.Taylor@Oracle.COM 		return (DDI_FAILURE);
372*12965SWilliam.Taylor@Oracle.COM 	}
373*12965SWilliam.Taylor@Oracle.COM 	if (hermon_rsrc_reserve(state, HERMON_QPC, numports *
374*12965SWilliam.Taylor@Oracle.COM 	    fcoib->hfc_rfci_qps_per_port, HERMON_SLEEP,
375*12965SWilliam.Taylor@Oracle.COM 	    &fcoib->hfc_rfci_rsrc) != DDI_SUCCESS) {
376*12965SWilliam.Taylor@Oracle.COM 		mutex_exit(&fcoib->hfc_lock);
377*12965SWilliam.Taylor@Oracle.COM 		hermon_fcoib_fini(state);
378*12965SWilliam.Taylor@Oracle.COM 		return (DDI_FAILURE);
379*12965SWilliam.Taylor@Oracle.COM 	}
380*12965SWilliam.Taylor@Oracle.COM 
381*12965SWilliam.Taylor@Oracle.COM 	for (i = 0; i < numports; i++) {
382*12965SWilliam.Taylor@Oracle.COM 		fcoib->hfc_port_enabled[i] = 0;
383*12965SWilliam.Taylor@Oracle.COM 		fcoib->hfc_n_port_ids[i] = kmem_zalloc(sizeof (uint32_t) *
384*12965SWilliam.Taylor@Oracle.COM 		    fcoib->hfc_rfci_qps_per_port, KM_SLEEP);
385*12965SWilliam.Taylor@Oracle.COM 
386*12965SWilliam.Taylor@Oracle.COM 		fcoib->hfc_mpt_base[i] = i * fcoib->hfc_mpts_per_port +
387*12965SWilliam.Taylor@Oracle.COM 		    fcoib->hfc_mpt_rsrc->hr_indx;
388*12965SWilliam.Taylor@Oracle.COM 		/* "/ 2" is for Secondary MKEYs never used on Client side */
389*12965SWilliam.Taylor@Oracle.COM 		fcoib->hfc_mtt_base[i] = (i * fcoib->hfc_mpts_per_port *
390*12965SWilliam.Taylor@Oracle.COM 		    fcoib->hfc_mtts_per_mpt / 2) + fcoib->hfc_mtt_rsrc->hr_indx;
391*12965SWilliam.Taylor@Oracle.COM 		fcoib->hfc_fexch_base[i] = i * fcoib->hfc_fexch_qps_per_port +
392*12965SWilliam.Taylor@Oracle.COM 		    fcoib->hfc_fexch_rsrc->hr_indx;
393*12965SWilliam.Taylor@Oracle.COM 		fcoib->hfc_rfci_base[i] = i * fcoib->hfc_rfci_qps_per_port +
394*12965SWilliam.Taylor@Oracle.COM 		    fcoib->hfc_rfci_rsrc->hr_indx;
395*12965SWilliam.Taylor@Oracle.COM 
396*12965SWilliam.Taylor@Oracle.COM 		/* init FEXCH QP rsrc pool */
397*12965SWilliam.Taylor@Oracle.COM 		(void) sprintf(string, "hermon%d_port%d_fexch_vmem",
398*12965SWilliam.Taylor@Oracle.COM 		    state->hs_instance, i + 1);
399*12965SWilliam.Taylor@Oracle.COM 		fcoib->hfc_fexch_vmemp[i] = vmem_create(string,
400*12965SWilliam.Taylor@Oracle.COM 		    (void *)vmemstart, fcoib->hfc_fexch_qps_per_port,
401*12965SWilliam.Taylor@Oracle.COM 		    1, NULL, NULL, NULL, 0, VM_SLEEP);
402*12965SWilliam.Taylor@Oracle.COM 
403*12965SWilliam.Taylor@Oracle.COM 		/* init RFCI QP rsrc pool */
404*12965SWilliam.Taylor@Oracle.COM 		(void) sprintf(string, "hermon%d_port%d_rfci_vmem",
405*12965SWilliam.Taylor@Oracle.COM 		    state->hs_instance, i + 1);
406*12965SWilliam.Taylor@Oracle.COM 		fcoib->hfc_rfci_vmemp[i] = vmem_create(string,
407*12965SWilliam.Taylor@Oracle.COM 		    (void *)vmemstart, fcoib->hfc_rfci_qps_per_port,
408*12965SWilliam.Taylor@Oracle.COM 		    1, NULL, NULL, NULL, 0, VM_SLEEP);
409*12965SWilliam.Taylor@Oracle.COM 	}
410*12965SWilliam.Taylor@Oracle.COM 
411*12965SWilliam.Taylor@Oracle.COM 	mutex_exit(&fcoib->hfc_lock);
412*12965SWilliam.Taylor@Oracle.COM 
413*12965SWilliam.Taylor@Oracle.COM 	return (DDI_SUCCESS);
414*12965SWilliam.Taylor@Oracle.COM }
415*12965SWilliam.Taylor@Oracle.COM 
416*12965SWilliam.Taylor@Oracle.COM 
417*12965SWilliam.Taylor@Oracle.COM /*
418*12965SWilliam.Taylor@Oracle.COM  * hermon_fcoib_fini()
419*12965SWilliam.Taylor@Oracle.COM  *    Context: Only called from attach() and/or detach() path contexts
420*12965SWilliam.Taylor@Oracle.COM  */
421*12965SWilliam.Taylor@Oracle.COM void
hermon_fcoib_fini(hermon_state_t * state)422*12965SWilliam.Taylor@Oracle.COM hermon_fcoib_fini(hermon_state_t *state)
423*12965SWilliam.Taylor@Oracle.COM {
424*12965SWilliam.Taylor@Oracle.COM 	hermon_fcoib_t	*fcoib;
425*12965SWilliam.Taylor@Oracle.COM 	uint_t		numports;
426*12965SWilliam.Taylor@Oracle.COM 	int		i;
427*12965SWilliam.Taylor@Oracle.COM 
428*12965SWilliam.Taylor@Oracle.COM 	if ((state->hs_ibtfinfo.hca_attr->hca_flags2 & IBT_HCA2_FC) == 0)
429*12965SWilliam.Taylor@Oracle.COM 		return;
430*12965SWilliam.Taylor@Oracle.COM 
431*12965SWilliam.Taylor@Oracle.COM 	fcoib = &state->hs_fcoib;
432*12965SWilliam.Taylor@Oracle.COM 
433*12965SWilliam.Taylor@Oracle.COM 	mutex_enter(&fcoib->hfc_lock);
434*12965SWilliam.Taylor@Oracle.COM 
435*12965SWilliam.Taylor@Oracle.COM 	numports = fcoib->hfc_nports;
436*12965SWilliam.Taylor@Oracle.COM 
437*12965SWilliam.Taylor@Oracle.COM 	for (i = 0; i < numports; i++) {
438*12965SWilliam.Taylor@Oracle.COM 		if (fcoib->hfc_rfci_vmemp[i])
439*12965SWilliam.Taylor@Oracle.COM 			vmem_destroy(fcoib->hfc_rfci_vmemp[i]);
440*12965SWilliam.Taylor@Oracle.COM 		if (fcoib->hfc_fexch_vmemp[i])
441*12965SWilliam.Taylor@Oracle.COM 			vmem_destroy(fcoib->hfc_fexch_vmemp[i]);
442*12965SWilliam.Taylor@Oracle.COM 		if (fcoib->hfc_n_port_ids[i])
443*12965SWilliam.Taylor@Oracle.COM 			kmem_free(fcoib->hfc_n_port_ids[i], sizeof (uint32_t) *
444*12965SWilliam.Taylor@Oracle.COM 			    fcoib->hfc_rfci_qps_per_port);
445*12965SWilliam.Taylor@Oracle.COM 
446*12965SWilliam.Taylor@Oracle.COM 		/* XXX --- should we issue HERMON_HW_FC_CONF_BASIC disable? */
447*12965SWilliam.Taylor@Oracle.COM 		fcoib->hfc_port_enabled[i] = 0;
448*12965SWilliam.Taylor@Oracle.COM 	}
449*12965SWilliam.Taylor@Oracle.COM 	if (fcoib->hfc_rfci_rsrc)
450*12965SWilliam.Taylor@Oracle.COM 		hermon_rsrc_free(state, &fcoib->hfc_rfci_rsrc);
451*12965SWilliam.Taylor@Oracle.COM 	if (fcoib->hfc_fexch_rsrc)
452*12965SWilliam.Taylor@Oracle.COM 		hermon_rsrc_free(state, &fcoib->hfc_fexch_rsrc);
453*12965SWilliam.Taylor@Oracle.COM 	if (fcoib->hfc_mpt_rsrc)
454*12965SWilliam.Taylor@Oracle.COM 		hermon_rsrc_free(state, &fcoib->hfc_mpt_rsrc);
455*12965SWilliam.Taylor@Oracle.COM 	if (fcoib->hfc_mtt_rsrc)
456*12965SWilliam.Taylor@Oracle.COM 		hermon_rsrc_free(state, &fcoib->hfc_mtt_rsrc);
457*12965SWilliam.Taylor@Oracle.COM 
458*12965SWilliam.Taylor@Oracle.COM 	mutex_exit(&fcoib->hfc_lock);
459*12965SWilliam.Taylor@Oracle.COM 	mutex_destroy(&fcoib->hfc_lock);
460*12965SWilliam.Taylor@Oracle.COM 
461*12965SWilliam.Taylor@Oracle.COM 	bzero(fcoib, sizeof (*fcoib));
462*12965SWilliam.Taylor@Oracle.COM }
463