1*12163SRamaswamy.Tummala@Sun.COM /*
2*12163SRamaswamy.Tummala@Sun.COM  * CDDL HEADER START
3*12163SRamaswamy.Tummala@Sun.COM  *
4*12163SRamaswamy.Tummala@Sun.COM  * The contents of this file are subject to the terms of the
5*12163SRamaswamy.Tummala@Sun.COM  * Common Development and Distribution License (the "License").
6*12163SRamaswamy.Tummala@Sun.COM  * You may not use this file except in compliance with the License.
7*12163SRamaswamy.Tummala@Sun.COM  *
8*12163SRamaswamy.Tummala@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12163SRamaswamy.Tummala@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*12163SRamaswamy.Tummala@Sun.COM  * See the License for the specific language governing permissions
11*12163SRamaswamy.Tummala@Sun.COM  * and limitations under the License.
12*12163SRamaswamy.Tummala@Sun.COM  *
13*12163SRamaswamy.Tummala@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*12163SRamaswamy.Tummala@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12163SRamaswamy.Tummala@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*12163SRamaswamy.Tummala@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*12163SRamaswamy.Tummala@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*12163SRamaswamy.Tummala@Sun.COM  *
19*12163SRamaswamy.Tummala@Sun.COM  * CDDL HEADER END
20*12163SRamaswamy.Tummala@Sun.COM  */
21*12163SRamaswamy.Tummala@Sun.COM /*
22*12163SRamaswamy.Tummala@Sun.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23*12163SRamaswamy.Tummala@Sun.COM  */
24*12163SRamaswamy.Tummala@Sun.COM 
25*12163SRamaswamy.Tummala@Sun.COM #include <stdio.h>
26*12163SRamaswamy.Tummala@Sun.COM #include <libdevinfo.h>
27*12163SRamaswamy.Tummala@Sun.COM #include <sys/types.h>
28*12163SRamaswamy.Tummala@Sun.COM #include <sys/stat.h>
29*12163SRamaswamy.Tummala@Sun.COM #include <string.h>
30*12163SRamaswamy.Tummala@Sun.COM #include <fcntl.h>
31*12163SRamaswamy.Tummala@Sun.COM #include <unistd.h>
32*12163SRamaswamy.Tummala@Sun.COM #include <stropts.h>
33*12163SRamaswamy.Tummala@Sun.COM #include <stdlib.h>
34*12163SRamaswamy.Tummala@Sun.COM #include <errno.h>
35*12163SRamaswamy.Tummala@Sun.COM #include <strings.h>
36*12163SRamaswamy.Tummala@Sun.COM #include <libintl.h>
37*12163SRamaswamy.Tummala@Sun.COM #include <net/if_types.h>
38*12163SRamaswamy.Tummala@Sun.COM #include <net/if_dl.h>
39*12163SRamaswamy.Tummala@Sun.COM #include <sys/dld.h>
40*12163SRamaswamy.Tummala@Sun.COM #include <sys/ib/ib_types.h>
41*12163SRamaswamy.Tummala@Sun.COM #include <sys/ibpart.h>
42*12163SRamaswamy.Tummala@Sun.COM #include <libdllink.h>
43*12163SRamaswamy.Tummala@Sun.COM #include <libdladm.h>
44*12163SRamaswamy.Tummala@Sun.COM #include <libdlib.h>
45*12163SRamaswamy.Tummala@Sun.COM #include <libdladm_impl.h>
46*12163SRamaswamy.Tummala@Sun.COM 
47*12163SRamaswamy.Tummala@Sun.COM /*
48*12163SRamaswamy.Tummala@Sun.COM  * IP over IB administration API; see PSARC/2010/085
49*12163SRamaswamy.Tummala@Sun.COM  */
50*12163SRamaswamy.Tummala@Sun.COM 
51*12163SRamaswamy.Tummala@Sun.COM /*
52*12163SRamaswamy.Tummala@Sun.COM  * Function prototypes
53*12163SRamaswamy.Tummala@Sun.COM  */
54*12163SRamaswamy.Tummala@Sun.COM dladm_status_t dladm_part_create(dladm_handle_t, datalink_id_t, ib_pkey_t,
55*12163SRamaswamy.Tummala@Sun.COM     uint32_t, char *, datalink_id_t *, dladm_arg_list_t *);
56*12163SRamaswamy.Tummala@Sun.COM static int	dladm_ibd_get_instance(char *);
57*12163SRamaswamy.Tummala@Sun.COM static dladm_status_t	i_dladm_part_create(dladm_handle_t,
58*12163SRamaswamy.Tummala@Sun.COM     dladm_part_attr_t *);
59*12163SRamaswamy.Tummala@Sun.COM dladm_status_t	dladm_part_persist_conf(dladm_handle_t, dladm_part_attr_t *);
60*12163SRamaswamy.Tummala@Sun.COM static dladm_status_t i_dladm_part_delete(dladm_handle_t, datalink_id_t);
61*12163SRamaswamy.Tummala@Sun.COM dladm_status_t	dladm_part_delete(dladm_handle_t, datalink_id_t, int);
62*12163SRamaswamy.Tummala@Sun.COM static int	i_dladm_part_up(dladm_handle_t, datalink_id_t, void *);
63*12163SRamaswamy.Tummala@Sun.COM dladm_status_t	dladm_part_up(dladm_handle_t, datalink_id_t, uint32_t);
64*12163SRamaswamy.Tummala@Sun.COM 
65*12163SRamaswamy.Tummala@Sun.COM /*
66*12163SRamaswamy.Tummala@Sun.COM  * Convert a error status returned by the IP over IB kernel driver to a
67*12163SRamaswamy.Tummala@Sun.COM  * valid dladm status.
68*12163SRamaswamy.Tummala@Sun.COM  */
69*12163SRamaswamy.Tummala@Sun.COM static dladm_status_t
70*12163SRamaswamy.Tummala@Sun.COM dladm_ib_ioctl_err2status(int err)
71*12163SRamaswamy.Tummala@Sun.COM {
72*12163SRamaswamy.Tummala@Sun.COM 	switch (err) {
73*12163SRamaswamy.Tummala@Sun.COM 	case 0:
74*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_OK);
75*12163SRamaswamy.Tummala@Sun.COM 	case IBD_INVALID_PORT_INST:
76*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_INVALID_PORT_INSTANCE);
77*12163SRamaswamy.Tummala@Sun.COM 	case IBD_PORT_IS_DOWN:
78*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_PORT_IS_DOWN);
79*12163SRamaswamy.Tummala@Sun.COM 	case IBD_PKEY_NOT_PRESENT:
80*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_PKEY_NOT_PRESENT);
81*12163SRamaswamy.Tummala@Sun.COM 	case IBD_PARTITION_EXISTS:
82*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_PARTITION_EXISTS);
83*12163SRamaswamy.Tummala@Sun.COM 	case IBD_INVALID_PKEY:
84*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_INVALID_PKEY);
85*12163SRamaswamy.Tummala@Sun.COM 	case IBD_NO_HW_RESOURCE:
86*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_NO_IB_HW_RESOURCE);
87*12163SRamaswamy.Tummala@Sun.COM 	case IBD_INVALID_PKEY_TBL_SIZE:
88*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_INVALID_PKEY_TBL_SIZE);
89*12163SRamaswamy.Tummala@Sun.COM 	default:
90*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_FAILED);
91*12163SRamaswamy.Tummala@Sun.COM 	}
92*12163SRamaswamy.Tummala@Sun.COM }
93*12163SRamaswamy.Tummala@Sun.COM 
94*12163SRamaswamy.Tummala@Sun.COM static dladm_status_t
95*12163SRamaswamy.Tummala@Sun.COM i_dladm_ib_ioctl(dladm_handle_t handle, int ioccmd, ibd_ioctl_t *iocp)
96*12163SRamaswamy.Tummala@Sun.COM {
97*12163SRamaswamy.Tummala@Sun.COM 	if (ioctl(dladm_dld_fd(handle), ioccmd, iocp) == 0)
98*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_OK);
99*12163SRamaswamy.Tummala@Sun.COM 
100*12163SRamaswamy.Tummala@Sun.COM 	if (iocp->ioc_status == 0)
101*12163SRamaswamy.Tummala@Sun.COM 		return (dladm_errno2status(errno));
102*12163SRamaswamy.Tummala@Sun.COM 
103*12163SRamaswamy.Tummala@Sun.COM 	return (dladm_ib_ioctl_err2status(iocp->ioc_status));
104*12163SRamaswamy.Tummala@Sun.COM }
105*12163SRamaswamy.Tummala@Sun.COM 
106*12163SRamaswamy.Tummala@Sun.COM /*
107*12163SRamaswamy.Tummala@Sun.COM  * Get the active configuration information for the partition given by
108*12163SRamaswamy.Tummala@Sun.COM  * the 'linkid'.
109*12163SRamaswamy.Tummala@Sun.COM  */
110*12163SRamaswamy.Tummala@Sun.COM static dladm_status_t
111*12163SRamaswamy.Tummala@Sun.COM i_dladm_part_info_active(dladm_handle_t handle, datalink_id_t linkid,
112*12163SRamaswamy.Tummala@Sun.COM     dladm_part_attr_t *attrp)
113*12163SRamaswamy.Tummala@Sun.COM {
114*12163SRamaswamy.Tummala@Sun.COM 	ibpart_ioctl_t ioc;
115*12163SRamaswamy.Tummala@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
116*12163SRamaswamy.Tummala@Sun.COM 
117*12163SRamaswamy.Tummala@Sun.COM 	bzero(&ioc, sizeof (ioc));
118*12163SRamaswamy.Tummala@Sun.COM 	bzero(attrp, sizeof (*attrp));
119*12163SRamaswamy.Tummala@Sun.COM 	/*
120*12163SRamaswamy.Tummala@Sun.COM 	 * The ioc_linkid here will contain the data link id of the IB partition
121*12163SRamaswamy.Tummala@Sun.COM 	 * object.
122*12163SRamaswamy.Tummala@Sun.COM 	 */
123*12163SRamaswamy.Tummala@Sun.COM 	ioc.ibdioc.ioc_linkid = linkid;
124*12163SRamaswamy.Tummala@Sun.COM 	ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_IBPART;
125*12163SRamaswamy.Tummala@Sun.COM 
126*12163SRamaswamy.Tummala@Sun.COM 	status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc);
127*12163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK)
128*12163SRamaswamy.Tummala@Sun.COM 		goto bail;
129*12163SRamaswamy.Tummala@Sun.COM 
130*12163SRamaswamy.Tummala@Sun.COM 	/*
131*12163SRamaswamy.Tummala@Sun.COM 	 * On return from the ioctl ioc_linkid field contains the IB port's
132*12163SRamaswamy.Tummala@Sun.COM 	 * linkid.
133*12163SRamaswamy.Tummala@Sun.COM 	 */
134*12163SRamaswamy.Tummala@Sun.COM 	attrp->dia_physlinkid = ioc.ibdioc.ioc_linkid;
135*12163SRamaswamy.Tummala@Sun.COM 	attrp->dia_partlinkid = ioc.ioc_partid;
136*12163SRamaswamy.Tummala@Sun.COM 	attrp->dia_pkey = ioc.ioc_pkey;
137*12163SRamaswamy.Tummala@Sun.COM 	attrp->dia_portnum = ioc.ibdioc.ioc_portnum;
138*12163SRamaswamy.Tummala@Sun.COM 	attrp->dia_hca_guid = ioc.ibdioc.ioc_hcaguid;
139*12163SRamaswamy.Tummala@Sun.COM 	attrp->dia_port_guid = ioc.ibdioc.ioc_portguid;
140*12163SRamaswamy.Tummala@Sun.COM 	attrp->dia_instance = ioc.ibdioc.ioc_port_inst;
141*12163SRamaswamy.Tummala@Sun.COM 
142*12163SRamaswamy.Tummala@Sun.COM 	/*
143*12163SRamaswamy.Tummala@Sun.COM 	 * If the IP over IB driver reports that this partition was created
144*12163SRamaswamy.Tummala@Sun.COM 	 * forcibly, then set the force create flag.
145*12163SRamaswamy.Tummala@Sun.COM 	 */
146*12163SRamaswamy.Tummala@Sun.COM 	if (ioc.ioc_force_create)
147*12163SRamaswamy.Tummala@Sun.COM 		attrp->dia_flags |= DLADM_IBPART_FORCE_CREATE;
148*12163SRamaswamy.Tummala@Sun.COM 
149*12163SRamaswamy.Tummala@Sun.COM bail:
150*12163SRamaswamy.Tummala@Sun.COM 	return (status);
151*12163SRamaswamy.Tummala@Sun.COM }
152*12163SRamaswamy.Tummala@Sun.COM 
153*12163SRamaswamy.Tummala@Sun.COM /*
154*12163SRamaswamy.Tummala@Sun.COM  * Get the configuration information about the IB partition 'linkid' from the
155*12163SRamaswamy.Tummala@Sun.COM  * persistent configuration.
156*12163SRamaswamy.Tummala@Sun.COM  */
157*12163SRamaswamy.Tummala@Sun.COM static dladm_status_t
158*12163SRamaswamy.Tummala@Sun.COM i_dladm_part_info_persist(dladm_handle_t handle, datalink_id_t linkid,
159*12163SRamaswamy.Tummala@Sun.COM     dladm_part_attr_t *attrp)
160*12163SRamaswamy.Tummala@Sun.COM {
161*12163SRamaswamy.Tummala@Sun.COM 	dladm_conf_t conf;
162*12163SRamaswamy.Tummala@Sun.COM 	dladm_status_t status;
163*12163SRamaswamy.Tummala@Sun.COM 	char linkover[MAXLINKNAMELEN];
164*12163SRamaswamy.Tummala@Sun.COM 	datalink_class_t class;
165*12163SRamaswamy.Tummala@Sun.COM 	boolean_t force = B_FALSE;
166*12163SRamaswamy.Tummala@Sun.COM 
167*12163SRamaswamy.Tummala@Sun.COM 	/* Get the IB partition's datalink ID */
168*12163SRamaswamy.Tummala@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class,
169*12163SRamaswamy.Tummala@Sun.COM 	    NULL, NULL, 0)) != DLADM_STATUS_OK)
170*12163SRamaswamy.Tummala@Sun.COM 		goto done;
171*12163SRamaswamy.Tummala@Sun.COM 
172*12163SRamaswamy.Tummala@Sun.COM 	bzero(attrp, sizeof (*attrp));
173*12163SRamaswamy.Tummala@Sun.COM 	attrp->dia_partlinkid = linkid;
174*12163SRamaswamy.Tummala@Sun.COM 	if ((status = dladm_read_conf(handle, linkid, &conf)) !=
175*12163SRamaswamy.Tummala@Sun.COM 	    DLADM_STATUS_OK)
176*12163SRamaswamy.Tummala@Sun.COM 		return (status);
177*12163SRamaswamy.Tummala@Sun.COM 
178*12163SRamaswamy.Tummala@Sun.COM 	/*
179*12163SRamaswamy.Tummala@Sun.COM 	 * Get the name of the IB Phys link over which IB partition was
180*12163SRamaswamy.Tummala@Sun.COM 	 * created.
181*12163SRamaswamy.Tummala@Sun.COM 	 */
182*12163SRamaswamy.Tummala@Sun.COM 	status = dladm_get_conf_field(handle, conf, FLINKOVER, linkover,
183*12163SRamaswamy.Tummala@Sun.COM 	    sizeof (linkover));
184*12163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK) {
185*12163SRamaswamy.Tummala@Sun.COM 		attrp->dia_physlinkid = DATALINK_INVALID_LINKID;
186*12163SRamaswamy.Tummala@Sun.COM 		goto done;
187*12163SRamaswamy.Tummala@Sun.COM 	} else {
188*12163SRamaswamy.Tummala@Sun.COM 		/* Get the IB Phys link's datalink ID */
189*12163SRamaswamy.Tummala@Sun.COM 		if ((status = dladm_name2info(handle, linkover,
190*12163SRamaswamy.Tummala@Sun.COM 		    &attrp->dia_physlinkid, NULL, NULL, NULL)) !=
191*12163SRamaswamy.Tummala@Sun.COM 		    DLADM_STATUS_OK)
192*12163SRamaswamy.Tummala@Sun.COM 			goto done;
193*12163SRamaswamy.Tummala@Sun.COM 	}
194*12163SRamaswamy.Tummala@Sun.COM 
195*12163SRamaswamy.Tummala@Sun.COM 	/* Get the IB partition's P_Key */
196*12163SRamaswamy.Tummala@Sun.COM 	status = dladm_get_conf_field(handle, conf, FPORTPKEY,
197*12163SRamaswamy.Tummala@Sun.COM 	    &attrp->dia_pkey, sizeof (uint64_t));
198*12163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK)
199*12163SRamaswamy.Tummala@Sun.COM 		goto done;
200*12163SRamaswamy.Tummala@Sun.COM 
201*12163SRamaswamy.Tummala@Sun.COM 	if (class != DATALINK_CLASS_PART) {
202*12163SRamaswamy.Tummala@Sun.COM 		status = DLADM_STATUS_BADARG;
203*12163SRamaswamy.Tummala@Sun.COM 		goto done;
204*12163SRamaswamy.Tummala@Sun.COM 	}
205*12163SRamaswamy.Tummala@Sun.COM 
206*12163SRamaswamy.Tummala@Sun.COM 	/*
207*12163SRamaswamy.Tummala@Sun.COM 	 * If the FFORCE field is set in the persistent configuration database
208*12163SRamaswamy.Tummala@Sun.COM 	 * set the force create flag in the partition attributes.
209*12163SRamaswamy.Tummala@Sun.COM 	 */
210*12163SRamaswamy.Tummala@Sun.COM 	status = dladm_get_conf_field(handle, conf, FFORCE, &force,
211*12163SRamaswamy.Tummala@Sun.COM 	    sizeof (boolean_t));
212*12163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK) {
213*12163SRamaswamy.Tummala@Sun.COM 		if (status != DLADM_STATUS_NOTFOUND)
214*12163SRamaswamy.Tummala@Sun.COM 			goto done;
215*12163SRamaswamy.Tummala@Sun.COM 	} else if (force == B_TRUE) {
216*12163SRamaswamy.Tummala@Sun.COM 		attrp->dia_flags |= DLADM_IBPART_FORCE_CREATE;
217*12163SRamaswamy.Tummala@Sun.COM 	}
218*12163SRamaswamy.Tummala@Sun.COM 
219*12163SRamaswamy.Tummala@Sun.COM 	status = DLADM_STATUS_OK;
220*12163SRamaswamy.Tummala@Sun.COM done:
221*12163SRamaswamy.Tummala@Sun.COM 	dladm_destroy_conf(handle, conf);
222*12163SRamaswamy.Tummala@Sun.COM 	return (status);
223*12163SRamaswamy.Tummala@Sun.COM }
224*12163SRamaswamy.Tummala@Sun.COM 
225*12163SRamaswamy.Tummala@Sun.COM /*
226*12163SRamaswamy.Tummala@Sun.COM  * Get the configuration information for the IB partition given by the datalink
227*12163SRamaswamy.Tummala@Sun.COM  * ID 'linkid'. Based on the 'flags' field the information is either from the
228*12163SRamaswamy.Tummala@Sun.COM  * active system (DLADM_OPT_ACTIVE) or from the persistent configuration
229*12163SRamaswamy.Tummala@Sun.COM  * database.
230*12163SRamaswamy.Tummala@Sun.COM  */
231*12163SRamaswamy.Tummala@Sun.COM dladm_status_t
232*12163SRamaswamy.Tummala@Sun.COM dladm_part_info(dladm_handle_t handle, datalink_id_t linkid,
233*12163SRamaswamy.Tummala@Sun.COM     dladm_part_attr_t *attrp, uint32_t flags)
234*12163SRamaswamy.Tummala@Sun.COM {
235*12163SRamaswamy.Tummala@Sun.COM 	if (flags == DLADM_OPT_ACTIVE)
236*12163SRamaswamy.Tummala@Sun.COM 		return (i_dladm_part_info_active(handle, linkid, attrp));
237*12163SRamaswamy.Tummala@Sun.COM 	else if (flags == DLADM_OPT_PERSIST)
238*12163SRamaswamy.Tummala@Sun.COM 		return (i_dladm_part_info_persist(handle, linkid, attrp));
239*12163SRamaswamy.Tummala@Sun.COM 	else
240*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_BADARG);
241*12163SRamaswamy.Tummala@Sun.COM }
242*12163SRamaswamy.Tummala@Sun.COM 
243*12163SRamaswamy.Tummala@Sun.COM /*
244*12163SRamaswamy.Tummala@Sun.COM  * Get the configuration information for the IB Phys link given by the datalink
245*12163SRamaswamy.Tummala@Sun.COM  * ID 'linkid'.
246*12163SRamaswamy.Tummala@Sun.COM  */
247*12163SRamaswamy.Tummala@Sun.COM /* ARGSUSED */
248*12163SRamaswamy.Tummala@Sun.COM dladm_status_t
249*12163SRamaswamy.Tummala@Sun.COM dladm_ib_info(dladm_handle_t handle, datalink_id_t linkid,
250*12163SRamaswamy.Tummala@Sun.COM     dladm_ib_attr_t *attrp, uint32_t flags)
251*12163SRamaswamy.Tummala@Sun.COM {
252*12163SRamaswamy.Tummala@Sun.COM 	int instance;
253*12163SRamaswamy.Tummala@Sun.COM 	ibport_ioctl_t ioc;
254*12163SRamaswamy.Tummala@Sun.COM 	dladm_phys_attr_t	dpa;
255*12163SRamaswamy.Tummala@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
256*12163SRamaswamy.Tummala@Sun.COM 
257*12163SRamaswamy.Tummala@Sun.COM 	/*
258*12163SRamaswamy.Tummala@Sun.COM 	 * We need to get the device name of the IB Phys link to get the
259*12163SRamaswamy.Tummala@Sun.COM 	 * correct instance number of the IP over IB driver instance.
260*12163SRamaswamy.Tummala@Sun.COM 	 */
261*12163SRamaswamy.Tummala@Sun.COM 	if (dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE)
262*12163SRamaswamy.Tummala@Sun.COM 	    != DLADM_STATUS_OK)
263*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_BADARG);
264*12163SRamaswamy.Tummala@Sun.COM 
265*12163SRamaswamy.Tummala@Sun.COM 	/*
266*12163SRamaswamy.Tummala@Sun.COM 	 * Get the instance number of the IP over IB driver instance which
267*12163SRamaswamy.Tummala@Sun.COM 	 * represents this IB Phys link.
268*12163SRamaswamy.Tummala@Sun.COM 	 */
269*12163SRamaswamy.Tummala@Sun.COM 	instance = dladm_ibd_get_instance(dpa.dp_dev);
270*12163SRamaswamy.Tummala@Sun.COM 	if (instance == -1)
271*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_FAILED);
272*12163SRamaswamy.Tummala@Sun.COM 
273*12163SRamaswamy.Tummala@Sun.COM 	bzero(&ioc, sizeof (ioc));
274*12163SRamaswamy.Tummala@Sun.COM 	/*
275*12163SRamaswamy.Tummala@Sun.COM 	 * The ioc_linkid here will contain IB port linkid here. We make the
276*12163SRamaswamy.Tummala@Sun.COM 	 * first ioctl call to get the P_Key table size for this HCA port.
277*12163SRamaswamy.Tummala@Sun.COM 	 */
278*12163SRamaswamy.Tummala@Sun.COM 	ioc.ibdioc.ioc_linkid = linkid;
279*12163SRamaswamy.Tummala@Sun.COM 	ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_PKEYTBLSZ;
280*12163SRamaswamy.Tummala@Sun.COM 	ioc.ioc_pkey_tbl_sz = 0;
281*12163SRamaswamy.Tummala@Sun.COM 	ioc.ibdioc.ioc_port_inst = instance;
282*12163SRamaswamy.Tummala@Sun.COM 
283*12163SRamaswamy.Tummala@Sun.COM 	status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc);
284*12163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK)
285*12163SRamaswamy.Tummala@Sun.COM 		return (status);
286*12163SRamaswamy.Tummala@Sun.COM 
287*12163SRamaswamy.Tummala@Sun.COM 	/*
288*12163SRamaswamy.Tummala@Sun.COM 	 * Now allocate the memory for the P_Key table based on the table size
289*12163SRamaswamy.Tummala@Sun.COM 	 * return by the ioctl.
290*12163SRamaswamy.Tummala@Sun.COM 	 */
291*12163SRamaswamy.Tummala@Sun.COM 	ioc.ioc_pkeys = calloc(sizeof (ib_pkey_t), ioc.ioc_pkey_tbl_sz);
292*12163SRamaswamy.Tummala@Sun.COM 	if (ioc.ioc_pkeys == NULL) {
293*12163SRamaswamy.Tummala@Sun.COM 		status = dladm_errno2status(errno);
294*12163SRamaswamy.Tummala@Sun.COM 		goto bail;
295*12163SRamaswamy.Tummala@Sun.COM 	}
296*12163SRamaswamy.Tummala@Sun.COM 
297*12163SRamaswamy.Tummala@Sun.COM 	/*
298*12163SRamaswamy.Tummala@Sun.COM 	 * Call the ioctl again to get the P_Key table and other IB Phys link
299*12163SRamaswamy.Tummala@Sun.COM 	 * attributes.
300*12163SRamaswamy.Tummala@Sun.COM 	 */
301*12163SRamaswamy.Tummala@Sun.COM 	ioc.ibdioc.ioc_linkid = linkid;
302*12163SRamaswamy.Tummala@Sun.COM 	ioc.ibdioc.ioc_port_inst = instance;
303*12163SRamaswamy.Tummala@Sun.COM 	ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_IBPORT;
304*12163SRamaswamy.Tummala@Sun.COM 
305*12163SRamaswamy.Tummala@Sun.COM 	status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc);
306*12163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK)
307*12163SRamaswamy.Tummala@Sun.COM 		goto bail;
308*12163SRamaswamy.Tummala@Sun.COM 
309*12163SRamaswamy.Tummala@Sun.COM 	attrp->dia_physlinkid = ioc.ibdioc.ioc_linkid;
310*12163SRamaswamy.Tummala@Sun.COM 	attrp->dia_portnum = ioc.ibdioc.ioc_portnum;
311*12163SRamaswamy.Tummala@Sun.COM 	attrp->dia_port_pkey_tbl_sz = ioc.ioc_pkey_tbl_sz;
312*12163SRamaswamy.Tummala@Sun.COM 	attrp->dia_port_pkeys = ioc.ioc_pkeys;
313*12163SRamaswamy.Tummala@Sun.COM 	attrp->dia_hca_guid = ioc.ibdioc.ioc_hcaguid;
314*12163SRamaswamy.Tummala@Sun.COM 	attrp->dia_port_guid = ioc.ibdioc.ioc_portguid;
315*12163SRamaswamy.Tummala@Sun.COM 	attrp->dia_instance = ioc.ibdioc.ioc_port_inst;
316*12163SRamaswamy.Tummala@Sun.COM 	return (status);
317*12163SRamaswamy.Tummala@Sun.COM bail:
318*12163SRamaswamy.Tummala@Sun.COM 	free(ioc.ioc_pkeys);
319*12163SRamaswamy.Tummala@Sun.COM 	return (status);
320*12163SRamaswamy.Tummala@Sun.COM }
321*12163SRamaswamy.Tummala@Sun.COM 
322*12163SRamaswamy.Tummala@Sun.COM /*
323*12163SRamaswamy.Tummala@Sun.COM  * Free the memory allocated for the IB HCA port's P_Key table by
324*12163SRamaswamy.Tummala@Sun.COM  * dladm_ib_info library call.
325*12163SRamaswamy.Tummala@Sun.COM  */
326*12163SRamaswamy.Tummala@Sun.COM void
327*12163SRamaswamy.Tummala@Sun.COM dladm_free_ib_info(dladm_ib_attr_t *attr)
328*12163SRamaswamy.Tummala@Sun.COM {
329*12163SRamaswamy.Tummala@Sun.COM 	if (attr && attr->dia_port_pkeys)
330*12163SRamaswamy.Tummala@Sun.COM 		free(attr->dia_port_pkeys);
331*12163SRamaswamy.Tummala@Sun.COM }
332*12163SRamaswamy.Tummala@Sun.COM 
333*12163SRamaswamy.Tummala@Sun.COM /*
334*12163SRamaswamy.Tummala@Sun.COM  * Call into the IP over IB driver to create a partition object.
335*12163SRamaswamy.Tummala@Sun.COM  */
336*12163SRamaswamy.Tummala@Sun.COM static dladm_status_t
337*12163SRamaswamy.Tummala@Sun.COM i_dladm_part_create(dladm_handle_t handle, dladm_part_attr_t *pattr)
338*12163SRamaswamy.Tummala@Sun.COM {
339*12163SRamaswamy.Tummala@Sun.COM 	ibpart_ioctl_t	ioc;
340*12163SRamaswamy.Tummala@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
341*12163SRamaswamy.Tummala@Sun.COM 
342*12163SRamaswamy.Tummala@Sun.COM 	bzero(&ioc, sizeof (ioc));
343*12163SRamaswamy.Tummala@Sun.COM 
344*12163SRamaswamy.Tummala@Sun.COM 	/* IB Physical datalink ID */
345*12163SRamaswamy.Tummala@Sun.COM 	ioc.ibdioc.ioc_linkid		= pattr->dia_physlinkid;
346*12163SRamaswamy.Tummala@Sun.COM 	/* IB Partition datalink ID */
347*12163SRamaswamy.Tummala@Sun.COM 	ioc.ioc_partid			= pattr->dia_partlinkid;
348*12163SRamaswamy.Tummala@Sun.COM 	ioc.ioc_pkey			= pattr->dia_pkey;
349*12163SRamaswamy.Tummala@Sun.COM 	ioc.ibdioc.ioc_port_inst	= pattr->dia_instance;
350*12163SRamaswamy.Tummala@Sun.COM 	ioc.ioc_force_create		= ((pattr->dia_flags & DLADM_OPT_FORCE)
351*12163SRamaswamy.Tummala@Sun.COM 	    != 0);
352*12163SRamaswamy.Tummala@Sun.COM 
353*12163SRamaswamy.Tummala@Sun.COM 	status = i_dladm_ib_ioctl(handle, IBD_CREATE_IBPART,
354*12163SRamaswamy.Tummala@Sun.COM 	    (ibd_ioctl_t *)&ioc);
355*12163SRamaswamy.Tummala@Sun.COM 	return (status);
356*12163SRamaswamy.Tummala@Sun.COM }
357*12163SRamaswamy.Tummala@Sun.COM 
358*12163SRamaswamy.Tummala@Sun.COM /*
359*12163SRamaswamy.Tummala@Sun.COM  * Create an entry in the dladm persistent configuration database for the
360*12163SRamaswamy.Tummala@Sun.COM  * partition specified by pattr.
361*12163SRamaswamy.Tummala@Sun.COM  */
362*12163SRamaswamy.Tummala@Sun.COM dladm_status_t
363*12163SRamaswamy.Tummala@Sun.COM dladm_part_persist_conf(dladm_handle_t handle, dladm_part_attr_t *pattr)
364*12163SRamaswamy.Tummala@Sun.COM {
365*12163SRamaswamy.Tummala@Sun.COM 
366*12163SRamaswamy.Tummala@Sun.COM 	dladm_conf_t	conf;
367*12163SRamaswamy.Tummala@Sun.COM 	dladm_status_t	status;
368*12163SRamaswamy.Tummala@Sun.COM 	char 		linkover[MAXLINKNAMELEN];
369*12163SRamaswamy.Tummala@Sun.COM 	uint64_t	u64;
370*12163SRamaswamy.Tummala@Sun.COM 
371*12163SRamaswamy.Tummala@Sun.COM 	status = dladm_create_conf(handle, pattr->dia_pname,
372*12163SRamaswamy.Tummala@Sun.COM 	    pattr->dia_partlinkid, DATALINK_CLASS_PART, DL_IB, &conf);
373*12163SRamaswamy.Tummala@Sun.COM 
374*12163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK)
375*12163SRamaswamy.Tummala@Sun.COM 		return (status);
376*12163SRamaswamy.Tummala@Sun.COM 
377*12163SRamaswamy.Tummala@Sun.COM 	/*
378*12163SRamaswamy.Tummala@Sun.COM 	 * Get the name of the IB Phys link over which this partition was
379*12163SRamaswamy.Tummala@Sun.COM 	 * created.
380*12163SRamaswamy.Tummala@Sun.COM 	 */
381*12163SRamaswamy.Tummala@Sun.COM 	status = dladm_datalink_id2info(handle, pattr->dia_physlinkid,
382*12163SRamaswamy.Tummala@Sun.COM 	    NULL, NULL, NULL, linkover, sizeof (linkover));
383*12163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK)
384*12163SRamaswamy.Tummala@Sun.COM 		return (status);
385*12163SRamaswamy.Tummala@Sun.COM 
386*12163SRamaswamy.Tummala@Sun.COM 	/* Store IB Phys link name (linkover) */
387*12163SRamaswamy.Tummala@Sun.COM 	status = dladm_set_conf_field(handle, conf, FLINKOVER, DLADM_TYPE_STR,
388*12163SRamaswamy.Tummala@Sun.COM 	    linkover);
389*12163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK)
390*12163SRamaswamy.Tummala@Sun.COM 		return (status);
391*12163SRamaswamy.Tummala@Sun.COM 
392*12163SRamaswamy.Tummala@Sun.COM 	u64 = pattr->dia_pkey;
393*12163SRamaswamy.Tummala@Sun.COM 
394*12163SRamaswamy.Tummala@Sun.COM 	/* Store the IB Partitions P_Key */
395*12163SRamaswamy.Tummala@Sun.COM 	status = dladm_set_conf_field(handle, conf, FPORTPKEY,
396*12163SRamaswamy.Tummala@Sun.COM 	    DLADM_TYPE_UINT64, &u64);
397*12163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK)
398*12163SRamaswamy.Tummala@Sun.COM 		return (status);
399*12163SRamaswamy.Tummala@Sun.COM 
400*12163SRamaswamy.Tummala@Sun.COM 	if (pattr->dia_flags & DLADM_OPT_FORCE) {
401*12163SRamaswamy.Tummala@Sun.COM 		boolean_t force = B_TRUE;
402*12163SRamaswamy.Tummala@Sun.COM 		/* Store the force create flag. */
403*12163SRamaswamy.Tummala@Sun.COM 		status = dladm_set_conf_field(handle, conf, FFORCE,
404*12163SRamaswamy.Tummala@Sun.COM 		    DLADM_TYPE_BOOLEAN, &force);
405*12163SRamaswamy.Tummala@Sun.COM 		if (status != DLADM_STATUS_OK)
406*12163SRamaswamy.Tummala@Sun.COM 			goto done;
407*12163SRamaswamy.Tummala@Sun.COM 	}
408*12163SRamaswamy.Tummala@Sun.COM 
409*12163SRamaswamy.Tummala@Sun.COM 	status = dladm_write_conf(handle, conf);
410*12163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK)
411*12163SRamaswamy.Tummala@Sun.COM 		return (status);
412*12163SRamaswamy.Tummala@Sun.COM 
413*12163SRamaswamy.Tummala@Sun.COM 	dladm_destroy_conf(handle, conf);
414*12163SRamaswamy.Tummala@Sun.COM done:
415*12163SRamaswamy.Tummala@Sun.COM 	return (status);
416*12163SRamaswamy.Tummala@Sun.COM }
417*12163SRamaswamy.Tummala@Sun.COM 
418*12163SRamaswamy.Tummala@Sun.COM /*
419*12163SRamaswamy.Tummala@Sun.COM  * Create a new IB Partition datalink of name 'pname' over the IB Physical link
420*12163SRamaswamy.Tummala@Sun.COM  * given in 'physlinkid' with the P_key 'pkey' and return the datalink ID in
421*12163SRamaswamy.Tummala@Sun.COM  * 'partlinkid'. If the 'force' option is set in the 'flags' argument, the
422*12163SRamaswamy.Tummala@Sun.COM  * partition will be created even if the P_Key 'pkey' does not exist or if the
423*12163SRamaswamy.Tummala@Sun.COM  * HCA port represented by the IB Phys link is down. If the 'temporary' flag is
424*12163SRamaswamy.Tummala@Sun.COM  * set, then the configuration information is not added to the persistent
425*12163SRamaswamy.Tummala@Sun.COM  * database.
426*12163SRamaswamy.Tummala@Sun.COM  */
427*12163SRamaswamy.Tummala@Sun.COM dladm_status_t
428*12163SRamaswamy.Tummala@Sun.COM dladm_part_create(dladm_handle_t handle, datalink_id_t physlinkid,
429*12163SRamaswamy.Tummala@Sun.COM     ib_pkey_t pkey, uint32_t flags, char *pname, datalink_id_t *partlinkid,
430*12163SRamaswamy.Tummala@Sun.COM     dladm_arg_list_t *proplist)
431*12163SRamaswamy.Tummala@Sun.COM {
432*12163SRamaswamy.Tummala@Sun.COM 	int			i;
433*12163SRamaswamy.Tummala@Sun.COM 	dladm_status_t		status;
434*12163SRamaswamy.Tummala@Sun.COM 	uint_t			media;
435*12163SRamaswamy.Tummala@Sun.COM 	boolean_t		part_created = B_FALSE;
436*12163SRamaswamy.Tummala@Sun.COM 	boolean_t		conf_set = B_FALSE;
437*12163SRamaswamy.Tummala@Sun.COM 	dladm_phys_attr_t	dpa;
438*12163SRamaswamy.Tummala@Sun.COM 	dladm_part_attr_t	pattr;
439*12163SRamaswamy.Tummala@Sun.COM 
440*12163SRamaswamy.Tummala@Sun.COM 	pattr.dia_pkey = pkey;
441*12163SRamaswamy.Tummala@Sun.COM 	pattr.dia_physlinkid = physlinkid; /* IB Phys link's datalink id */
442*12163SRamaswamy.Tummala@Sun.COM 	pattr.dia_flags = flags;
443*12163SRamaswamy.Tummala@Sun.COM 	pattr.dia_pname = pname;
444*12163SRamaswamy.Tummala@Sun.COM 
445*12163SRamaswamy.Tummala@Sun.COM 	flags &= ~DLADM_OPT_FORCE;
446*12163SRamaswamy.Tummala@Sun.COM 
447*12163SRamaswamy.Tummala@Sun.COM 	/*
448*12163SRamaswamy.Tummala@Sun.COM 	 * Check whether the PKEY is valid. If not, return immediately
449*12163SRamaswamy.Tummala@Sun.COM 	 * Only full members are allowed as per the IPoIB specification
450*12163SRamaswamy.Tummala@Sun.COM 	 */
451*12163SRamaswamy.Tummala@Sun.COM 	if (pattr.dia_pkey <= IB_PKEY_INVALID_FULL)
452*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_INVALID_PKEY);
453*12163SRamaswamy.Tummala@Sun.COM 
454*12163SRamaswamy.Tummala@Sun.COM 	/*
455*12163SRamaswamy.Tummala@Sun.COM 	 * Get the media type of the Phys link datalink ID provided and
456*12163SRamaswamy.Tummala@Sun.COM 	 * make sure that it is Infiniband media DL_IB)
457*12163SRamaswamy.Tummala@Sun.COM 	 */
458*12163SRamaswamy.Tummala@Sun.COM 	if ((status = dladm_datalink_id2info(handle, pattr.dia_physlinkid, NULL,
459*12163SRamaswamy.Tummala@Sun.COM 	    NULL, &media, NULL, 0)) != DLADM_STATUS_OK)
460*12163SRamaswamy.Tummala@Sun.COM 		return (status);
461*12163SRamaswamy.Tummala@Sun.COM 
462*12163SRamaswamy.Tummala@Sun.COM 	if (media != DL_IB)
463*12163SRamaswamy.Tummala@Sun.COM 		return (dladm_errno2status(ENOTSUP));
464*12163SRamaswamy.Tummala@Sun.COM 
465*12163SRamaswamy.Tummala@Sun.COM 	/*
466*12163SRamaswamy.Tummala@Sun.COM 	 * Get the instance number of the IP over IB driver instance which the
467*12163SRamaswamy.Tummala@Sun.COM 	 * IB Phys link 'physlinkid' over which we will be creating our IB
468*12163SRamaswamy.Tummala@Sun.COM 	 * partition.
469*12163SRamaswamy.Tummala@Sun.COM 	 */
470*12163SRamaswamy.Tummala@Sun.COM 	if ((status = dladm_phys_info(handle, pattr.dia_physlinkid, &dpa,
471*12163SRamaswamy.Tummala@Sun.COM 	    DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK)
472*12163SRamaswamy.Tummala@Sun.COM 		return (status);
473*12163SRamaswamy.Tummala@Sun.COM 
474*12163SRamaswamy.Tummala@Sun.COM 	pattr.dia_instance = dladm_ibd_get_instance(dpa.dp_dev);
475*12163SRamaswamy.Tummala@Sun.COM 	if (pattr.dia_instance == -1)
476*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_FAILED);
477*12163SRamaswamy.Tummala@Sun.COM 
478*12163SRamaswamy.Tummala@Sun.COM 
479*12163SRamaswamy.Tummala@Sun.COM 	if ((status = dladm_create_datalink_id(handle, pattr.dia_pname,
480*12163SRamaswamy.Tummala@Sun.COM 	    DATALINK_CLASS_PART, DL_IB, flags, &pattr.dia_partlinkid)) !=
481*12163SRamaswamy.Tummala@Sun.COM 	    DLADM_STATUS_OK)
482*12163SRamaswamy.Tummala@Sun.COM 		return (status);
483*12163SRamaswamy.Tummala@Sun.COM 
484*12163SRamaswamy.Tummala@Sun.COM 	/*
485*12163SRamaswamy.Tummala@Sun.COM 	 * Create the IB partition object.
486*12163SRamaswamy.Tummala@Sun.COM 	 */
487*12163SRamaswamy.Tummala@Sun.COM 	status = i_dladm_part_create(handle, &pattr);
488*12163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK)
489*12163SRamaswamy.Tummala@Sun.COM 		goto done;
490*12163SRamaswamy.Tummala@Sun.COM 
491*12163SRamaswamy.Tummala@Sun.COM 	part_created = B_TRUE;
492*12163SRamaswamy.Tummala@Sun.COM 
493*12163SRamaswamy.Tummala@Sun.COM 	/*
494*12163SRamaswamy.Tummala@Sun.COM 	 * If the persist flag is set then write this partition information
495*12163SRamaswamy.Tummala@Sun.COM 	 * to the persistent configuration.
496*12163SRamaswamy.Tummala@Sun.COM 	 */
497*12163SRamaswamy.Tummala@Sun.COM 	if (pattr.dia_flags & DLADM_OPT_PERSIST) {
498*12163SRamaswamy.Tummala@Sun.COM 		status = dladm_part_persist_conf(handle, &pattr);
499*12163SRamaswamy.Tummala@Sun.COM 		if (status != DLADM_STATUS_OK)
500*12163SRamaswamy.Tummala@Sun.COM 			goto done;
501*12163SRamaswamy.Tummala@Sun.COM 		conf_set = B_TRUE;
502*12163SRamaswamy.Tummala@Sun.COM 	}
503*12163SRamaswamy.Tummala@Sun.COM 
504*12163SRamaswamy.Tummala@Sun.COM 	/*
505*12163SRamaswamy.Tummala@Sun.COM 	 * If the name-value pair list of properties were provided set those
506*12163SRamaswamy.Tummala@Sun.COM 	 * properties over the datalink.
507*12163SRamaswamy.Tummala@Sun.COM 	 */
508*12163SRamaswamy.Tummala@Sun.COM 	if (proplist != NULL) {
509*12163SRamaswamy.Tummala@Sun.COM 		for (i = 0; i < proplist->al_count; i++) {
510*12163SRamaswamy.Tummala@Sun.COM 			dladm_arg_info_t *aip = &proplist->al_info[i];
511*12163SRamaswamy.Tummala@Sun.COM 
512*12163SRamaswamy.Tummala@Sun.COM 			status = dladm_set_linkprop(handle,
513*12163SRamaswamy.Tummala@Sun.COM 			    pattr.dia_partlinkid, aip->ai_name, aip->ai_val,
514*12163SRamaswamy.Tummala@Sun.COM 			    aip->ai_count, pattr.dia_flags);
515*12163SRamaswamy.Tummala@Sun.COM 			if (status != DLADM_STATUS_OK)
516*12163SRamaswamy.Tummala@Sun.COM 				break;
517*12163SRamaswamy.Tummala@Sun.COM 		}
518*12163SRamaswamy.Tummala@Sun.COM 	}
519*12163SRamaswamy.Tummala@Sun.COM done:
520*12163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK) {
521*12163SRamaswamy.Tummala@Sun.COM 		if (conf_set)
522*12163SRamaswamy.Tummala@Sun.COM 			(void) dladm_remove_conf(handle, pattr.dia_partlinkid);
523*12163SRamaswamy.Tummala@Sun.COM 		if (part_created)
524*12163SRamaswamy.Tummala@Sun.COM 			(void) i_dladm_part_delete(handle,
525*12163SRamaswamy.Tummala@Sun.COM 			    pattr.dia_partlinkid);
526*12163SRamaswamy.Tummala@Sun.COM 		(void) dladm_destroy_datalink_id(handle, pattr.dia_partlinkid,
527*12163SRamaswamy.Tummala@Sun.COM 		    flags);
528*12163SRamaswamy.Tummala@Sun.COM 	}
529*12163SRamaswamy.Tummala@Sun.COM 
530*12163SRamaswamy.Tummala@Sun.COM 	if (partlinkid != NULL)
531*12163SRamaswamy.Tummala@Sun.COM 		*partlinkid = pattr.dia_partlinkid;
532*12163SRamaswamy.Tummala@Sun.COM 
533*12163SRamaswamy.Tummala@Sun.COM 	return (status);
534*12163SRamaswamy.Tummala@Sun.COM }
535*12163SRamaswamy.Tummala@Sun.COM 
536*12163SRamaswamy.Tummala@Sun.COM /*
537*12163SRamaswamy.Tummala@Sun.COM  * Call into the IP over IB driver to delete the IB partition and free up all
538*12163SRamaswamy.Tummala@Sun.COM  * the resources allocated for it.
539*12163SRamaswamy.Tummala@Sun.COM  */
540*12163SRamaswamy.Tummala@Sun.COM static dladm_status_t
541*12163SRamaswamy.Tummala@Sun.COM i_dladm_part_delete(dladm_handle_t handle, datalink_id_t partid)
542*12163SRamaswamy.Tummala@Sun.COM {
543*12163SRamaswamy.Tummala@Sun.COM 	ibpart_ioctl_t ioc;
544*12163SRamaswamy.Tummala@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
545*12163SRamaswamy.Tummala@Sun.COM 
546*12163SRamaswamy.Tummala@Sun.COM 	bzero(&ioc, sizeof (ioc));
547*12163SRamaswamy.Tummala@Sun.COM 	ioc.ioc_partid = partid;
548*12163SRamaswamy.Tummala@Sun.COM 	status = i_dladm_ib_ioctl(handle, IBD_DELETE_IBPART,
549*12163SRamaswamy.Tummala@Sun.COM 	    (ibd_ioctl_t *)&ioc);
550*12163SRamaswamy.Tummala@Sun.COM 	return (status);
551*12163SRamaswamy.Tummala@Sun.COM }
552*12163SRamaswamy.Tummala@Sun.COM 
553*12163SRamaswamy.Tummala@Sun.COM /*
554*12163SRamaswamy.Tummala@Sun.COM  * Delete an IB partition if 'flags' contains the active flag. Update the
555*12163SRamaswamy.Tummala@Sun.COM  * persistent configuration if 'flags' contains the persist flag.
556*12163SRamaswamy.Tummala@Sun.COM  */
557*12163SRamaswamy.Tummala@Sun.COM dladm_status_t
558*12163SRamaswamy.Tummala@Sun.COM dladm_part_delete(dladm_handle_t handle, datalink_id_t partid, int flags)
559*12163SRamaswamy.Tummala@Sun.COM {
560*12163SRamaswamy.Tummala@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
561*12163SRamaswamy.Tummala@Sun.COM 	datalink_class_t class;
562*12163SRamaswamy.Tummala@Sun.COM 
563*12163SRamaswamy.Tummala@Sun.COM 	if (flags == 0)
564*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_BADARG);
565*12163SRamaswamy.Tummala@Sun.COM 
566*12163SRamaswamy.Tummala@Sun.COM 	/*
567*12163SRamaswamy.Tummala@Sun.COM 	 * Make sure that the datalinkid provided is an IB partition class
568*12163SRamaswamy.Tummala@Sun.COM 	 * datalink ID.
569*12163SRamaswamy.Tummala@Sun.COM 	 */
570*12163SRamaswamy.Tummala@Sun.COM 	if ((dladm_datalink_id2info(handle, partid, NULL, &class, NULL, NULL, 0)
571*12163SRamaswamy.Tummala@Sun.COM 	    != DLADM_STATUS_OK))
572*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_BADARG);
573*12163SRamaswamy.Tummala@Sun.COM 
574*12163SRamaswamy.Tummala@Sun.COM 	if (class != DATALINK_CLASS_PART)
575*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_BADARG);
576*12163SRamaswamy.Tummala@Sun.COM 
577*12163SRamaswamy.Tummala@Sun.COM 	if ((flags & DLADM_OPT_ACTIVE) != 0) {
578*12163SRamaswamy.Tummala@Sun.COM 		status = i_dladm_part_delete(handle, partid);
579*12163SRamaswamy.Tummala@Sun.COM 		if (status == DLADM_STATUS_OK) {
580*12163SRamaswamy.Tummala@Sun.COM 			(void) dladm_set_linkprop(handle, partid, NULL, NULL, 0,
581*12163SRamaswamy.Tummala@Sun.COM 			    DLADM_OPT_ACTIVE);
582*12163SRamaswamy.Tummala@Sun.COM 			(void) dladm_destroy_datalink_id(handle, partid,
583*12163SRamaswamy.Tummala@Sun.COM 			    DLADM_OPT_ACTIVE);
584*12163SRamaswamy.Tummala@Sun.COM 		} else if (status != DLADM_STATUS_NOTFOUND ||
585*12163SRamaswamy.Tummala@Sun.COM 		    !(flags & DLADM_OPT_PERSIST)) {
586*12163SRamaswamy.Tummala@Sun.COM 			return (status);
587*12163SRamaswamy.Tummala@Sun.COM 		}
588*12163SRamaswamy.Tummala@Sun.COM 	}
589*12163SRamaswamy.Tummala@Sun.COM 
590*12163SRamaswamy.Tummala@Sun.COM 	if ((flags & DLADM_OPT_PERSIST) != 0) {
591*12163SRamaswamy.Tummala@Sun.COM 		dladm_status_t db_status;
592*12163SRamaswamy.Tummala@Sun.COM 		db_status = dladm_remove_conf(handle, partid);
593*12163SRamaswamy.Tummala@Sun.COM 
594*12163SRamaswamy.Tummala@Sun.COM 		/*
595*12163SRamaswamy.Tummala@Sun.COM 		 * A partition could have been temporarily deleted in which
596*12163SRamaswamy.Tummala@Sun.COM 		 * case the delete of the active partition above would have
597*12163SRamaswamy.Tummala@Sun.COM 		 * failed. In that case, we update the status to be returned
598*12163SRamaswamy.Tummala@Sun.COM 		 * to that of the status returned for deleting the persistent
599*12163SRamaswamy.Tummala@Sun.COM 		 * database entry.
600*12163SRamaswamy.Tummala@Sun.COM 		 */
601*12163SRamaswamy.Tummala@Sun.COM 		if (status == DLADM_STATUS_NOTFOUND)
602*12163SRamaswamy.Tummala@Sun.COM 			status = db_status;
603*12163SRamaswamy.Tummala@Sun.COM 
604*12163SRamaswamy.Tummala@Sun.COM 		(void) dladm_destroy_datalink_id(handle, partid,
605*12163SRamaswamy.Tummala@Sun.COM 		    DLADM_OPT_PERSIST);
606*12163SRamaswamy.Tummala@Sun.COM 	}
607*12163SRamaswamy.Tummala@Sun.COM 
608*12163SRamaswamy.Tummala@Sun.COM 	return (status);
609*12163SRamaswamy.Tummala@Sun.COM }
610*12163SRamaswamy.Tummala@Sun.COM 
611*12163SRamaswamy.Tummala@Sun.COM /*
612*12163SRamaswamy.Tummala@Sun.COM  * Call into the IP over IB driver to create the active instances of one or all
613*12163SRamaswamy.Tummala@Sun.COM  * IB partitions present in the persistent configuration.
614*12163SRamaswamy.Tummala@Sun.COM  */
615*12163SRamaswamy.Tummala@Sun.COM /* ARGSUSED */
616*12163SRamaswamy.Tummala@Sun.COM static int
617*12163SRamaswamy.Tummala@Sun.COM i_dladm_part_up(dladm_handle_t handle, datalink_id_t plinkid, void *arg)
618*12163SRamaswamy.Tummala@Sun.COM {
619*12163SRamaswamy.Tummala@Sun.COM 	dladm_conf_t	conf;
620*12163SRamaswamy.Tummala@Sun.COM 	datalink_id_t	linkid;
621*12163SRamaswamy.Tummala@Sun.COM 	ib_pkey_t	pkey;
622*12163SRamaswamy.Tummala@Sun.COM 	uint64_t	u64;
623*12163SRamaswamy.Tummala@Sun.COM 	char linkover[MAXLINKNAMELEN];
624*12163SRamaswamy.Tummala@Sun.COM 	dladm_status_t	status;
625*12163SRamaswamy.Tummala@Sun.COM 	dladm_phys_attr_t dpa;
626*12163SRamaswamy.Tummala@Sun.COM 	dladm_part_attr_t pattr;
627*12163SRamaswamy.Tummala@Sun.COM 
628*12163SRamaswamy.Tummala@Sun.COM 	/*
629*12163SRamaswamy.Tummala@Sun.COM 	 * plinkid is the IB partition datalink's ID. Get an handle to the
630*12163SRamaswamy.Tummala@Sun.COM 	 * persistent configuration entry for this datalink ID. If this datalink
631*12163SRamaswamy.Tummala@Sun.COM 	 * ID is not present in the persistent configuration return.
632*12163SRamaswamy.Tummala@Sun.COM 	 */
633*12163SRamaswamy.Tummala@Sun.COM 	if ((status = dladm_read_conf(handle, plinkid, &conf)) !=
634*12163SRamaswamy.Tummala@Sun.COM 	    DLADM_STATUS_OK)
635*12163SRamaswamy.Tummala@Sun.COM 		return (status);
636*12163SRamaswamy.Tummala@Sun.COM 
637*12163SRamaswamy.Tummala@Sun.COM 	/*
638*12163SRamaswamy.Tummala@Sun.COM 	 * Get the name of the IB Phys link over which this partition was
639*12163SRamaswamy.Tummala@Sun.COM 	 * created.
640*12163SRamaswamy.Tummala@Sun.COM 	 */
641*12163SRamaswamy.Tummala@Sun.COM 	status = dladm_get_conf_field(handle, conf, FLINKOVER, linkover,
642*12163SRamaswamy.Tummala@Sun.COM 	    sizeof (linkover));
643*12163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK)
644*12163SRamaswamy.Tummala@Sun.COM 		goto done;
645*12163SRamaswamy.Tummala@Sun.COM 
646*12163SRamaswamy.Tummala@Sun.COM 	if ((status = dladm_name2info(handle, linkover, &linkid, NULL, NULL,
647*12163SRamaswamy.Tummala@Sun.COM 	    NULL)) != DLADM_STATUS_OK)
648*12163SRamaswamy.Tummala@Sun.COM 		goto done;
649*12163SRamaswamy.Tummala@Sun.COM 
650*12163SRamaswamy.Tummala@Sun.COM 	/*
651*12163SRamaswamy.Tummala@Sun.COM 	 * Get the phys attribute of the IB Phys link to get the device name
652*12163SRamaswamy.Tummala@Sun.COM 	 * associated with the phys link. We need this to get the IP over IB
653*12163SRamaswamy.Tummala@Sun.COM 	 * driver instance number.
654*12163SRamaswamy.Tummala@Sun.COM 	 */
655*12163SRamaswamy.Tummala@Sun.COM 	if (dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE)
656*12163SRamaswamy.Tummala@Sun.COM 	    != DLADM_STATUS_OK)
657*12163SRamaswamy.Tummala@Sun.COM 		goto done;
658*12163SRamaswamy.Tummala@Sun.COM 
659*12163SRamaswamy.Tummala@Sun.COM 	/* Get the IB partition's P_key */
660*12163SRamaswamy.Tummala@Sun.COM 	status = dladm_get_conf_field(handle, conf, FPORTPKEY, &u64,
661*12163SRamaswamy.Tummala@Sun.COM 	    sizeof (u64));
662*12163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK)
663*12163SRamaswamy.Tummala@Sun.COM 		goto done;
664*12163SRamaswamy.Tummala@Sun.COM 
665*12163SRamaswamy.Tummala@Sun.COM 	pkey = (ib_pkey_t)u64;
666*12163SRamaswamy.Tummala@Sun.COM 
667*12163SRamaswamy.Tummala@Sun.COM 	/*
668*12163SRamaswamy.Tummala@Sun.COM 	 * We always set the force flag during dladm_part_up because we want
669*12163SRamaswamy.Tummala@Sun.COM 	 * the partition creation to succeed even if the IB HCA port over which
670*12163SRamaswamy.Tummala@Sun.COM 	 * the partition is being created is still down. Since dladm_part_up
671*12163SRamaswamy.Tummala@Sun.COM 	 * is usually invoked during early boot sequence, it is possible under
672*12163SRamaswamy.Tummala@Sun.COM 	 * some IB subnet configurations for dladm_up_part to be called before
673*12163SRamaswamy.Tummala@Sun.COM 	 * the IB link negotiation is completed and port state is set to active
674*12163SRamaswamy.Tummala@Sun.COM 	 * and P_Key table is updated.
675*12163SRamaswamy.Tummala@Sun.COM 	 */
676*12163SRamaswamy.Tummala@Sun.COM 	pattr.dia_flags = DLADM_OPT_FORCE | DLADM_OPT_ACTIVE |
677*12163SRamaswamy.Tummala@Sun.COM 	    DLADM_OPT_PERSIST;
678*12163SRamaswamy.Tummala@Sun.COM 	/* IB Phys link's datalink ID. */
679*12163SRamaswamy.Tummala@Sun.COM 	pattr.dia_physlinkid = linkid;
680*12163SRamaswamy.Tummala@Sun.COM 	/* IB Partition's datalink ID. */
681*12163SRamaswamy.Tummala@Sun.COM 	pattr.dia_partlinkid = plinkid;
682*12163SRamaswamy.Tummala@Sun.COM 	pattr.dia_pkey = pkey;
683*12163SRamaswamy.Tummala@Sun.COM 	pattr.dia_instance = dladm_ibd_get_instance(dpa.dp_dev);
684*12163SRamaswamy.Tummala@Sun.COM 	if (pattr.dia_instance == -1)
685*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_WALK_CONTINUE);
686*12163SRamaswamy.Tummala@Sun.COM 
687*12163SRamaswamy.Tummala@Sun.COM 	/* Create the active IB Partition object. */
688*12163SRamaswamy.Tummala@Sun.COM 	if (i_dladm_part_create(handle, &pattr) == DLADM_STATUS_OK &&
689*12163SRamaswamy.Tummala@Sun.COM 	    dladm_up_datalink_id(handle, plinkid) != DLADM_STATUS_OK)
690*12163SRamaswamy.Tummala@Sun.COM 			(void) i_dladm_part_delete(handle, linkid);
691*12163SRamaswamy.Tummala@Sun.COM 
692*12163SRamaswamy.Tummala@Sun.COM done:
693*12163SRamaswamy.Tummala@Sun.COM 	dladm_destroy_conf(handle, conf);
694*12163SRamaswamy.Tummala@Sun.COM 	return (DLADM_WALK_CONTINUE);
695*12163SRamaswamy.Tummala@Sun.COM }
696*12163SRamaswamy.Tummala@Sun.COM 
697*12163SRamaswamy.Tummala@Sun.COM /*
698*12163SRamaswamy.Tummala@Sun.COM  * Bring up one or all IB partition(s) present in the persistent configuration
699*12163SRamaswamy.Tummala@Sun.COM  * database. If we need to bring up one IB Partition, its datalink ID is
700*12163SRamaswamy.Tummala@Sun.COM  * provided in 'linkid'.
701*12163SRamaswamy.Tummala@Sun.COM  */
702*12163SRamaswamy.Tummala@Sun.COM /* ARGSUSED */
703*12163SRamaswamy.Tummala@Sun.COM dladm_status_t
704*12163SRamaswamy.Tummala@Sun.COM dladm_part_up(dladm_handle_t handle, datalink_id_t linkid, uint32_t flags)
705*12163SRamaswamy.Tummala@Sun.COM {
706*12163SRamaswamy.Tummala@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
707*12163SRamaswamy.Tummala@Sun.COM 
708*12163SRamaswamy.Tummala@Sun.COM 	if (linkid == DATALINK_ALL_LINKID) {
709*12163SRamaswamy.Tummala@Sun.COM 		(void) dladm_walk_datalink_id(i_dladm_part_up, handle,
710*12163SRamaswamy.Tummala@Sun.COM 		    &status, DATALINK_CLASS_PART, DATALINK_ANY_MEDIATYPE,
711*12163SRamaswamy.Tummala@Sun.COM 		    DLADM_OPT_PERSIST);
712*12163SRamaswamy.Tummala@Sun.COM 		return (DLADM_STATUS_OK);
713*12163SRamaswamy.Tummala@Sun.COM 	} else {
714*12163SRamaswamy.Tummala@Sun.COM 		(void) i_dladm_part_up(handle, linkid, &status);
715*12163SRamaswamy.Tummala@Sun.COM 		return (status);
716*12163SRamaswamy.Tummala@Sun.COM 	}
717*12163SRamaswamy.Tummala@Sun.COM }
718*12163SRamaswamy.Tummala@Sun.COM 
719*12163SRamaswamy.Tummala@Sun.COM static int
720*12163SRamaswamy.Tummala@Sun.COM dladm_ibd_get_instance(char *devname)
721*12163SRamaswamy.Tummala@Sun.COM {
722*12163SRamaswamy.Tummala@Sun.COM 	int instance;
723*12163SRamaswamy.Tummala@Sun.COM 
724*12163SRamaswamy.Tummala@Sun.COM 	/*
725*12163SRamaswamy.Tummala@Sun.COM 	 * The devname contains the driver name followed by the instance
726*12163SRamaswamy.Tummala@Sun.COM 	 * number. Lets just skip the driver name and get the instance. We use
727*12163SRamaswamy.Tummala@Sun.COM 	 * strlen of ibp here to get the driver name length.
728*12163SRamaswamy.Tummala@Sun.COM 	 */
729*12163SRamaswamy.Tummala@Sun.COM 	instance = atoi(devname + strlen("ibp"));
730*12163SRamaswamy.Tummala@Sun.COM 
731*12163SRamaswamy.Tummala@Sun.COM 	return (instance);
732*12163SRamaswamy.Tummala@Sun.COM }
733