xref: /titanic_44/usr/src/cmd/rcm_daemon/common/ibpart_rcm.c (revision e2dcee5754c56d91c6e1ff847db294541069ca0d)
1*1cfa752fSRamaswamy Tummala /*
2*1cfa752fSRamaswamy Tummala  * CDDL HEADER START
3*1cfa752fSRamaswamy Tummala  *
4*1cfa752fSRamaswamy Tummala  * The contents of this file are subject to the terms of the
5*1cfa752fSRamaswamy Tummala  * Common Development and Distribution License (the "License").
6*1cfa752fSRamaswamy Tummala  * You may not use this file except in compliance with the License.
7*1cfa752fSRamaswamy Tummala  *
8*1cfa752fSRamaswamy Tummala  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*1cfa752fSRamaswamy Tummala  * or http://www.opensolaris.org/os/licensing.
10*1cfa752fSRamaswamy Tummala  * See the License for the specific language governing permissions
11*1cfa752fSRamaswamy Tummala  * and limitations under the License.
12*1cfa752fSRamaswamy Tummala  *
13*1cfa752fSRamaswamy Tummala  * When distributing Covered Code, include this CDDL HEADER in each
14*1cfa752fSRamaswamy Tummala  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*1cfa752fSRamaswamy Tummala  * If applicable, add the following below this CDDL HEADER, with the
16*1cfa752fSRamaswamy Tummala  * fields enclosed by brackets "[]" replaced with your own identifying
17*1cfa752fSRamaswamy Tummala  * information: Portions Copyright [yyyy] [name of copyright owner]
18*1cfa752fSRamaswamy Tummala  *
19*1cfa752fSRamaswamy Tummala  * CDDL HEADER END
20*1cfa752fSRamaswamy Tummala  */
21*1cfa752fSRamaswamy Tummala /*
22*1cfa752fSRamaswamy Tummala  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23*1cfa752fSRamaswamy Tummala  */
24*1cfa752fSRamaswamy Tummala 
25*1cfa752fSRamaswamy Tummala /*
26*1cfa752fSRamaswamy Tummala  * This RCM module adds support to the RCM framework for IBPART links
27*1cfa752fSRamaswamy Tummala  */
28*1cfa752fSRamaswamy Tummala 
29*1cfa752fSRamaswamy Tummala #include <stdio.h>
30*1cfa752fSRamaswamy Tummala #include <stdlib.h>
31*1cfa752fSRamaswamy Tummala #include <string.h>
32*1cfa752fSRamaswamy Tummala #include <errno.h>
33*1cfa752fSRamaswamy Tummala #include <sys/types.h>
34*1cfa752fSRamaswamy Tummala #include <synch.h>
35*1cfa752fSRamaswamy Tummala #include <assert.h>
36*1cfa752fSRamaswamy Tummala #include <strings.h>
37*1cfa752fSRamaswamy Tummala #include "rcm_module.h"
38*1cfa752fSRamaswamy Tummala #include <libintl.h>
39*1cfa752fSRamaswamy Tummala #include <libdllink.h>
40*1cfa752fSRamaswamy Tummala #include <libdlib.h>
41*1cfa752fSRamaswamy Tummala #include <libdlpi.h>
42*1cfa752fSRamaswamy Tummala 
43*1cfa752fSRamaswamy Tummala /*
44*1cfa752fSRamaswamy Tummala  * Definitions
45*1cfa752fSRamaswamy Tummala  */
46*1cfa752fSRamaswamy Tummala #ifndef lint
47*1cfa752fSRamaswamy Tummala #define	_(x)	gettext(x)
48*1cfa752fSRamaswamy Tummala #else
49*1cfa752fSRamaswamy Tummala #define	_(x)	x
50*1cfa752fSRamaswamy Tummala #endif
51*1cfa752fSRamaswamy Tummala 
52*1cfa752fSRamaswamy Tummala /* Some generic well-knowns and defaults used in this module */
53*1cfa752fSRamaswamy Tummala #define	RCM_LINK_PREFIX		"SUNW_datalink"	/* RCM datalink name prefix */
54*1cfa752fSRamaswamy Tummala #define	RCM_LINK_RESOURCE_MAX	(13 + LINKID_STR_WIDTH)
55*1cfa752fSRamaswamy Tummala 
56*1cfa752fSRamaswamy Tummala /* IBPART link flags */
57*1cfa752fSRamaswamy Tummala typedef enum {
58*1cfa752fSRamaswamy Tummala 	IBPART_OFFLINED			= 0x1,
59*1cfa752fSRamaswamy Tummala 	IBPART_CONSUMER_OFFLINED	= 0x2,
60*1cfa752fSRamaswamy Tummala 	IBPART_STALE			= 0x4
61*1cfa752fSRamaswamy Tummala } ibpart_flag_t;
62*1cfa752fSRamaswamy Tummala 
63*1cfa752fSRamaswamy Tummala /* link representation */
64*1cfa752fSRamaswamy Tummala typedef struct dl_ibpart {
65*1cfa752fSRamaswamy Tummala 	struct dl_ibpart	*dlib_next;	/* next IBPART on this link */
66*1cfa752fSRamaswamy Tummala 	struct dl_ibpart	*dlib_prev;	/* prev IBPART on this link */
67*1cfa752fSRamaswamy Tummala 	datalink_id_t	dlib_ibpart_id;
68*1cfa752fSRamaswamy Tummala 	ibpart_flag_t	dlib_flags;		/* IBPART link flags */
69*1cfa752fSRamaswamy Tummala } dl_ibpart_t;
70*1cfa752fSRamaswamy Tummala 
71*1cfa752fSRamaswamy Tummala /* IBPART Cache state flags */
72*1cfa752fSRamaswamy Tummala typedef enum {
73*1cfa752fSRamaswamy Tummala 	CACHE_NODE_STALE	= 0x1,		/* stale cached data */
74*1cfa752fSRamaswamy Tummala 	CACHE_NODE_NEW		= 0x2,		/* new cached nodes */
75*1cfa752fSRamaswamy Tummala 	CACHE_NODE_OFFLINED	= 0x4		/* nodes offlined */
76*1cfa752fSRamaswamy Tummala } cache_node_state_t;
77*1cfa752fSRamaswamy Tummala 
78*1cfa752fSRamaswamy Tummala /* Network Cache lookup options */
79*1cfa752fSRamaswamy Tummala #define	CACHE_NO_REFRESH	0x1		/* cache refresh not needed */
80*1cfa752fSRamaswamy Tummala #define	CACHE_REFRESH		0x2		/* refresh cache */
81*1cfa752fSRamaswamy Tummala 
82*1cfa752fSRamaswamy Tummala /* Cache element */
83*1cfa752fSRamaswamy Tummala typedef struct link_cache {
84*1cfa752fSRamaswamy Tummala 	struct link_cache	*pc_next;	/* next cached resource */
85*1cfa752fSRamaswamy Tummala 	struct link_cache	*pc_prev;	/* prev cached resource */
86*1cfa752fSRamaswamy Tummala 	char			*pc_resource;	/* resource name */
87*1cfa752fSRamaswamy Tummala 	datalink_id_t		pc_linkid;	/* linkid */
88*1cfa752fSRamaswamy Tummala 	dl_ibpart_t		*pc_ibpart;	/* IBPART list on this link */
89*1cfa752fSRamaswamy Tummala 	cache_node_state_t	pc_state;	/* cache state flags */
90*1cfa752fSRamaswamy Tummala } link_cache_t;
91*1cfa752fSRamaswamy Tummala 
92*1cfa752fSRamaswamy Tummala /*
93*1cfa752fSRamaswamy Tummala  * Global cache for network IBPARTs
94*1cfa752fSRamaswamy Tummala  */
95*1cfa752fSRamaswamy Tummala static link_cache_t	cache_head;
96*1cfa752fSRamaswamy Tummala static link_cache_t	cache_tail;
97*1cfa752fSRamaswamy Tummala static mutex_t		cache_lock;
98*1cfa752fSRamaswamy Tummala static int		events_registered = 0;
99*1cfa752fSRamaswamy Tummala 
100*1cfa752fSRamaswamy Tummala static dladm_handle_t	dld_handle = NULL;
101*1cfa752fSRamaswamy Tummala 
102*1cfa752fSRamaswamy Tummala /*
103*1cfa752fSRamaswamy Tummala  * RCM module interface prototypes
104*1cfa752fSRamaswamy Tummala  */
105*1cfa752fSRamaswamy Tummala static int		ibpart_register(rcm_handle_t *);
106*1cfa752fSRamaswamy Tummala static int		ibpart_unregister(rcm_handle_t *);
107*1cfa752fSRamaswamy Tummala static int		ibpart_get_info(rcm_handle_t *, char *, id_t, uint_t,
108*1cfa752fSRamaswamy Tummala 			    char **, char **, nvlist_t *, rcm_info_t **);
109*1cfa752fSRamaswamy Tummala static int		ibpart_suspend(rcm_handle_t *, char *, id_t,
110*1cfa752fSRamaswamy Tummala 			    timespec_t *, uint_t, char **, rcm_info_t **);
111*1cfa752fSRamaswamy Tummala static int		ibpart_resume(rcm_handle_t *, char *, id_t, uint_t,
112*1cfa752fSRamaswamy Tummala 			    char **, rcm_info_t **);
113*1cfa752fSRamaswamy Tummala static int		ibpart_offline(rcm_handle_t *, char *, id_t, uint_t,
114*1cfa752fSRamaswamy Tummala 			    char **, rcm_info_t **);
115*1cfa752fSRamaswamy Tummala static int		ibpart_undo_offline(rcm_handle_t *, char *, id_t,
116*1cfa752fSRamaswamy Tummala 			    uint_t, char **, rcm_info_t **);
117*1cfa752fSRamaswamy Tummala static int		ibpart_remove(rcm_handle_t *, char *, id_t, uint_t,
118*1cfa752fSRamaswamy Tummala 			    char **, rcm_info_t **);
119*1cfa752fSRamaswamy Tummala static int		ibpart_notify_event(rcm_handle_t *, char *, id_t,
120*1cfa752fSRamaswamy Tummala 			    uint_t, char **, nvlist_t *, rcm_info_t **);
121*1cfa752fSRamaswamy Tummala static int		ibpart_configure(rcm_handle_t *, datalink_id_t);
122*1cfa752fSRamaswamy Tummala 
123*1cfa752fSRamaswamy Tummala /* Module private routines */
124*1cfa752fSRamaswamy Tummala static void 		cache_free();
125*1cfa752fSRamaswamy Tummala static int 		cache_update(rcm_handle_t *);
126*1cfa752fSRamaswamy Tummala static void 		cache_remove(link_cache_t *);
127*1cfa752fSRamaswamy Tummala static void 		node_free(link_cache_t *);
128*1cfa752fSRamaswamy Tummala static void 		cache_insert(link_cache_t *);
129*1cfa752fSRamaswamy Tummala static link_cache_t	*cache_lookup(rcm_handle_t *, char *, char);
130*1cfa752fSRamaswamy Tummala static int		ibpart_consumer_offline(rcm_handle_t *, link_cache_t *,
131*1cfa752fSRamaswamy Tummala 			    char **, uint_t, rcm_info_t **);
132*1cfa752fSRamaswamy Tummala static void		ibpart_consumer_online(rcm_handle_t *, link_cache_t *,
133*1cfa752fSRamaswamy Tummala 			    char **, uint_t, rcm_info_t **);
134*1cfa752fSRamaswamy Tummala static int		ibpart_offline_ibpart(link_cache_t *, uint32_t,
135*1cfa752fSRamaswamy Tummala 			    cache_node_state_t);
136*1cfa752fSRamaswamy Tummala static void		ibpart_online_ibpart(link_cache_t *);
137*1cfa752fSRamaswamy Tummala static char 		*ibpart_usage(link_cache_t *);
138*1cfa752fSRamaswamy Tummala static void 		ibpart_log_err(datalink_id_t, char **, char *);
139*1cfa752fSRamaswamy Tummala static int		ibpart_consumer_notify(rcm_handle_t *, datalink_id_t,
140*1cfa752fSRamaswamy Tummala 			    char **, uint_t, rcm_info_t **);
141*1cfa752fSRamaswamy Tummala 
142*1cfa752fSRamaswamy Tummala /* Module-Private data */
143*1cfa752fSRamaswamy Tummala static struct rcm_mod_ops ibpart_ops =
144*1cfa752fSRamaswamy Tummala {
145*1cfa752fSRamaswamy Tummala 	RCM_MOD_OPS_VERSION,
146*1cfa752fSRamaswamy Tummala 	ibpart_register,
147*1cfa752fSRamaswamy Tummala 	ibpart_unregister,
148*1cfa752fSRamaswamy Tummala 	ibpart_get_info,
149*1cfa752fSRamaswamy Tummala 	ibpart_suspend,
150*1cfa752fSRamaswamy Tummala 	ibpart_resume,
151*1cfa752fSRamaswamy Tummala 	ibpart_offline,
152*1cfa752fSRamaswamy Tummala 	ibpart_undo_offline,
153*1cfa752fSRamaswamy Tummala 	ibpart_remove,
154*1cfa752fSRamaswamy Tummala 	NULL,
155*1cfa752fSRamaswamy Tummala 	NULL,
156*1cfa752fSRamaswamy Tummala 	ibpart_notify_event
157*1cfa752fSRamaswamy Tummala };
158*1cfa752fSRamaswamy Tummala 
159*1cfa752fSRamaswamy Tummala /*
160*1cfa752fSRamaswamy Tummala  * rcm_mod_init() - Update registrations, and return the ops structure.
161*1cfa752fSRamaswamy Tummala  */
162*1cfa752fSRamaswamy Tummala struct rcm_mod_ops *
rcm_mod_init(void)163*1cfa752fSRamaswamy Tummala rcm_mod_init(void)
164*1cfa752fSRamaswamy Tummala {
165*1cfa752fSRamaswamy Tummala 	char errmsg[DLADM_STRSIZE];
166*1cfa752fSRamaswamy Tummala 	dladm_status_t status;
167*1cfa752fSRamaswamy Tummala 
168*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: mod_init\n");
169*1cfa752fSRamaswamy Tummala 
170*1cfa752fSRamaswamy Tummala 	cache_head.pc_next = &cache_tail;
171*1cfa752fSRamaswamy Tummala 	cache_head.pc_prev = NULL;
172*1cfa752fSRamaswamy Tummala 	cache_tail.pc_prev = &cache_head;
173*1cfa752fSRamaswamy Tummala 	cache_tail.pc_next = NULL;
174*1cfa752fSRamaswamy Tummala 	(void) mutex_init(&cache_lock, 0, NULL);
175*1cfa752fSRamaswamy Tummala 
176*1cfa752fSRamaswamy Tummala 	if ((status = dladm_open(&dld_handle)) != DLADM_STATUS_OK) {
177*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_WARNING,
178*1cfa752fSRamaswamy Tummala 		    "IBPART: mod_init failed: cannot open datalink "
179*1cfa752fSRamaswamy Tummala 		    "handle: %s\n", dladm_status2str(status, errmsg));
180*1cfa752fSRamaswamy Tummala 		return (NULL);
181*1cfa752fSRamaswamy Tummala 	}
182*1cfa752fSRamaswamy Tummala 
183*1cfa752fSRamaswamy Tummala 	/* Return the ops vectors */
184*1cfa752fSRamaswamy Tummala 	return (&ibpart_ops);
185*1cfa752fSRamaswamy Tummala }
186*1cfa752fSRamaswamy Tummala 
187*1cfa752fSRamaswamy Tummala /*
188*1cfa752fSRamaswamy Tummala  * rcm_mod_info() - Return a string describing this module.
189*1cfa752fSRamaswamy Tummala  */
190*1cfa752fSRamaswamy Tummala const char *
rcm_mod_info(void)191*1cfa752fSRamaswamy Tummala rcm_mod_info(void)
192*1cfa752fSRamaswamy Tummala {
193*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: mod_info\n");
194*1cfa752fSRamaswamy Tummala 
195*1cfa752fSRamaswamy Tummala 	return ("IBPART module");
196*1cfa752fSRamaswamy Tummala }
197*1cfa752fSRamaswamy Tummala 
198*1cfa752fSRamaswamy Tummala /*
199*1cfa752fSRamaswamy Tummala  * rcm_mod_fini() - Destroy the network IBPART cache.
200*1cfa752fSRamaswamy Tummala  */
201*1cfa752fSRamaswamy Tummala int
rcm_mod_fini(void)202*1cfa752fSRamaswamy Tummala rcm_mod_fini(void)
203*1cfa752fSRamaswamy Tummala {
204*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: mod_fini\n");
205*1cfa752fSRamaswamy Tummala 
206*1cfa752fSRamaswamy Tummala 	/*
207*1cfa752fSRamaswamy Tummala 	 * Note that ibpart_unregister() does not seem to be called anywhere,
208*1cfa752fSRamaswamy Tummala 	 * therefore we free the cache nodes here. In theory we should call
209*1cfa752fSRamaswamy Tummala 	 * rcm_register_interest() for each node before we free it, the
210*1cfa752fSRamaswamy Tummala 	 * framework does not provide the rcm_handle to allow us to do so.
211*1cfa752fSRamaswamy Tummala 	 */
212*1cfa752fSRamaswamy Tummala 	cache_free();
213*1cfa752fSRamaswamy Tummala 	(void) mutex_destroy(&cache_lock);
214*1cfa752fSRamaswamy Tummala 
215*1cfa752fSRamaswamy Tummala 	dladm_close(dld_handle);
216*1cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
217*1cfa752fSRamaswamy Tummala }
218*1cfa752fSRamaswamy Tummala 
219*1cfa752fSRamaswamy Tummala /*
220*1cfa752fSRamaswamy Tummala  * ibpart_register() - Make sure the cache is properly sync'ed, and its
221*1cfa752fSRamaswamy Tummala  *		 registrations are in order.
222*1cfa752fSRamaswamy Tummala  */
223*1cfa752fSRamaswamy Tummala static int
ibpart_register(rcm_handle_t * hd)224*1cfa752fSRamaswamy Tummala ibpart_register(rcm_handle_t *hd)
225*1cfa752fSRamaswamy Tummala {
226*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: register\n");
227*1cfa752fSRamaswamy Tummala 
228*1cfa752fSRamaswamy Tummala 	if (cache_update(hd) < 0)
229*1cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
230*1cfa752fSRamaswamy Tummala 
231*1cfa752fSRamaswamy Tummala 	/*
232*1cfa752fSRamaswamy Tummala 	 * Need to register interest in all new resources
233*1cfa752fSRamaswamy Tummala 	 * getting attached, so we get attach event notifications
234*1cfa752fSRamaswamy Tummala 	 */
235*1cfa752fSRamaswamy Tummala 	if (!events_registered) {
236*1cfa752fSRamaswamy Tummala 		if (rcm_register_event(hd, RCM_RESOURCE_LINK_NEW, 0, NULL)
237*1cfa752fSRamaswamy Tummala 		    != RCM_SUCCESS) {
238*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR,
239*1cfa752fSRamaswamy Tummala 			    _("IBPART: failed to register %s\n"),
240*1cfa752fSRamaswamy Tummala 			    RCM_RESOURCE_LINK_NEW);
241*1cfa752fSRamaswamy Tummala 			return (RCM_FAILURE);
242*1cfa752fSRamaswamy Tummala 		} else {
243*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_DEBUG, "IBPART: registered %s\n",
244*1cfa752fSRamaswamy Tummala 			    RCM_RESOURCE_LINK_NEW);
245*1cfa752fSRamaswamy Tummala 			events_registered++;
246*1cfa752fSRamaswamy Tummala 		}
247*1cfa752fSRamaswamy Tummala 	}
248*1cfa752fSRamaswamy Tummala 
249*1cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
250*1cfa752fSRamaswamy Tummala }
251*1cfa752fSRamaswamy Tummala 
252*1cfa752fSRamaswamy Tummala /*
253*1cfa752fSRamaswamy Tummala  * ibpart_unregister() - Walk the cache, unregistering all the networks.
254*1cfa752fSRamaswamy Tummala  */
255*1cfa752fSRamaswamy Tummala static int
ibpart_unregister(rcm_handle_t * hd)256*1cfa752fSRamaswamy Tummala ibpart_unregister(rcm_handle_t *hd)
257*1cfa752fSRamaswamy Tummala {
258*1cfa752fSRamaswamy Tummala 	link_cache_t *node;
259*1cfa752fSRamaswamy Tummala 
260*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: unregister\n");
261*1cfa752fSRamaswamy Tummala 
262*1cfa752fSRamaswamy Tummala 	/* Walk the cache, unregistering everything */
263*1cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
264*1cfa752fSRamaswamy Tummala 	node = cache_head.pc_next;
265*1cfa752fSRamaswamy Tummala 	while (node != &cache_tail) {
266*1cfa752fSRamaswamy Tummala 		if (rcm_unregister_interest(hd, node->pc_resource, 0)
267*1cfa752fSRamaswamy Tummala 		    != RCM_SUCCESS) {
268*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR,
269*1cfa752fSRamaswamy Tummala 			    _("IBPART: failed to unregister %s\n"),
270*1cfa752fSRamaswamy Tummala 			    node->pc_resource);
271*1cfa752fSRamaswamy Tummala 			(void) mutex_unlock(&cache_lock);
272*1cfa752fSRamaswamy Tummala 			return (RCM_FAILURE);
273*1cfa752fSRamaswamy Tummala 		}
274*1cfa752fSRamaswamy Tummala 		cache_remove(node);
275*1cfa752fSRamaswamy Tummala 		node_free(node);
276*1cfa752fSRamaswamy Tummala 		node = cache_head.pc_next;
277*1cfa752fSRamaswamy Tummala 	}
278*1cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
279*1cfa752fSRamaswamy Tummala 
280*1cfa752fSRamaswamy Tummala 	/*
281*1cfa752fSRamaswamy Tummala 	 * Unregister interest in all new resources
282*1cfa752fSRamaswamy Tummala 	 */
283*1cfa752fSRamaswamy Tummala 	if (events_registered) {
284*1cfa752fSRamaswamy Tummala 		if (rcm_unregister_event(hd, RCM_RESOURCE_LINK_NEW, 0)
285*1cfa752fSRamaswamy Tummala 		    != RCM_SUCCESS) {
286*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR,
287*1cfa752fSRamaswamy Tummala 			    _("IBPART: failed to unregister %s\n"),
288*1cfa752fSRamaswamy Tummala 			    RCM_RESOURCE_LINK_NEW);
289*1cfa752fSRamaswamy Tummala 			return (RCM_FAILURE);
290*1cfa752fSRamaswamy Tummala 		} else {
291*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_DEBUG, "IBPART: unregistered %s\n",
292*1cfa752fSRamaswamy Tummala 			    RCM_RESOURCE_LINK_NEW);
293*1cfa752fSRamaswamy Tummala 			events_registered--;
294*1cfa752fSRamaswamy Tummala 		}
295*1cfa752fSRamaswamy Tummala 	}
296*1cfa752fSRamaswamy Tummala 
297*1cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
298*1cfa752fSRamaswamy Tummala }
299*1cfa752fSRamaswamy Tummala 
300*1cfa752fSRamaswamy Tummala /*
301*1cfa752fSRamaswamy Tummala  * ibpart_offline() - Offline IBPARTs on a specific node.
302*1cfa752fSRamaswamy Tummala  */
303*1cfa752fSRamaswamy Tummala static int
ibpart_offline(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)304*1cfa752fSRamaswamy Tummala ibpart_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
305*1cfa752fSRamaswamy Tummala     char **errorp, rcm_info_t **info)
306*1cfa752fSRamaswamy Tummala {
307*1cfa752fSRamaswamy Tummala 	link_cache_t *node;
308*1cfa752fSRamaswamy Tummala 
309*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: offline(%s)\n", rsrc);
310*1cfa752fSRamaswamy Tummala 
311*1cfa752fSRamaswamy Tummala 	/* Lock the cache and lookup the resource */
312*1cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
313*1cfa752fSRamaswamy Tummala 	node = cache_lookup(hd, rsrc, CACHE_REFRESH);
314*1cfa752fSRamaswamy Tummala 	if (node == NULL) {
315*1cfa752fSRamaswamy Tummala 		/* should not happen because the resource is registered. */
316*1cfa752fSRamaswamy Tummala 		ibpart_log_err(node->pc_linkid, errorp,
317*1cfa752fSRamaswamy Tummala 		    "unrecognized resource");
318*1cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
319*1cfa752fSRamaswamy Tummala 		return (RCM_SUCCESS);
320*1cfa752fSRamaswamy Tummala 	}
321*1cfa752fSRamaswamy Tummala 
322*1cfa752fSRamaswamy Tummala 	/*
323*1cfa752fSRamaswamy Tummala 	 * Inform consumers (IP interfaces) of associated IBPARTs to be offlined
324*1cfa752fSRamaswamy Tummala 	 */
325*1cfa752fSRamaswamy Tummala 	if (ibpart_consumer_offline(hd, node, errorp, flags, info) ==
326*1cfa752fSRamaswamy Tummala 	    RCM_SUCCESS) {
327*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_DEBUG,
328*1cfa752fSRamaswamy Tummala 		    "IBPART: consumers agreed on offline\n");
329*1cfa752fSRamaswamy Tummala 	} else {
330*1cfa752fSRamaswamy Tummala 		ibpart_log_err(node->pc_linkid, errorp,
331*1cfa752fSRamaswamy Tummala 		    "consumers failed to offline");
332*1cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
333*1cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
334*1cfa752fSRamaswamy Tummala 	}
335*1cfa752fSRamaswamy Tummala 
336*1cfa752fSRamaswamy Tummala 	/* Check if it's a query */
337*1cfa752fSRamaswamy Tummala 	if (flags & RCM_QUERY) {
338*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE1,
339*1cfa752fSRamaswamy Tummala 		    "IBPART: offline query succeeded(%s)\n", rsrc);
340*1cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
341*1cfa752fSRamaswamy Tummala 		return (RCM_SUCCESS);
342*1cfa752fSRamaswamy Tummala 	}
343*1cfa752fSRamaswamy Tummala 
344*1cfa752fSRamaswamy Tummala 	if (ibpart_offline_ibpart(node, IBPART_OFFLINED, CACHE_NODE_OFFLINED) !=
345*1cfa752fSRamaswamy Tummala 	    RCM_SUCCESS) {
346*1cfa752fSRamaswamy Tummala 		ibpart_online_ibpart(node);
347*1cfa752fSRamaswamy Tummala 		ibpart_log_err(node->pc_linkid, errorp, "offline failed");
348*1cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
349*1cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
350*1cfa752fSRamaswamy Tummala 	}
351*1cfa752fSRamaswamy Tummala 
352*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: Offline succeeded(%s)\n", rsrc);
353*1cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
354*1cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
355*1cfa752fSRamaswamy Tummala }
356*1cfa752fSRamaswamy Tummala 
357*1cfa752fSRamaswamy Tummala /*
358*1cfa752fSRamaswamy Tummala  * ibpart_undo_offline() - Undo offline of a previously offlined node.
359*1cfa752fSRamaswamy Tummala  */
360*1cfa752fSRamaswamy Tummala /*ARGSUSED*/
361*1cfa752fSRamaswamy Tummala static int
ibpart_undo_offline(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)362*1cfa752fSRamaswamy Tummala ibpart_undo_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
363*1cfa752fSRamaswamy Tummala     char **errorp, rcm_info_t **info)
364*1cfa752fSRamaswamy Tummala {
365*1cfa752fSRamaswamy Tummala 	link_cache_t *node;
366*1cfa752fSRamaswamy Tummala 
367*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: online(%s)\n", rsrc);
368*1cfa752fSRamaswamy Tummala 
369*1cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
370*1cfa752fSRamaswamy Tummala 	node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
371*1cfa752fSRamaswamy Tummala 	if (node == NULL) {
372*1cfa752fSRamaswamy Tummala 		ibpart_log_err(DATALINK_INVALID_LINKID, errorp, "no such link");
373*1cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
374*1cfa752fSRamaswamy Tummala 		errno = ENOENT;
375*1cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
376*1cfa752fSRamaswamy Tummala 	}
377*1cfa752fSRamaswamy Tummala 
378*1cfa752fSRamaswamy Tummala 	/* Check if no attempt should be made to online the link here */
379*1cfa752fSRamaswamy Tummala 	if (!(node->pc_state & CACHE_NODE_OFFLINED)) {
380*1cfa752fSRamaswamy Tummala 		ibpart_log_err(node->pc_linkid, errorp, "link not offlined");
381*1cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
382*1cfa752fSRamaswamy Tummala 		errno = ENOTSUP;
383*1cfa752fSRamaswamy Tummala 		return (RCM_SUCCESS);
384*1cfa752fSRamaswamy Tummala 	}
385*1cfa752fSRamaswamy Tummala 
386*1cfa752fSRamaswamy Tummala 	ibpart_online_ibpart(node);
387*1cfa752fSRamaswamy Tummala 
388*1cfa752fSRamaswamy Tummala 	/*
389*1cfa752fSRamaswamy Tummala 	 * Inform IP interfaces on associated IBPARTs to be onlined
390*1cfa752fSRamaswamy Tummala 	 */
391*1cfa752fSRamaswamy Tummala 	ibpart_consumer_online(hd, node, errorp, flags, info);
392*1cfa752fSRamaswamy Tummala 
393*1cfa752fSRamaswamy Tummala 	node->pc_state &= ~CACHE_NODE_OFFLINED;
394*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: online succeeded(%s)\n", rsrc);
395*1cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
396*1cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
397*1cfa752fSRamaswamy Tummala }
398*1cfa752fSRamaswamy Tummala 
399*1cfa752fSRamaswamy Tummala static void
ibpart_online_ibpart(link_cache_t * node)400*1cfa752fSRamaswamy Tummala ibpart_online_ibpart(link_cache_t *node)
401*1cfa752fSRamaswamy Tummala {
402*1cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
403*1cfa752fSRamaswamy Tummala 	dladm_status_t status;
404*1cfa752fSRamaswamy Tummala 	char errmsg[DLADM_STRSIZE];
405*1cfa752fSRamaswamy Tummala 
406*1cfa752fSRamaswamy Tummala 	/*
407*1cfa752fSRamaswamy Tummala 	 * Try to bring on all offlined IBPARTs
408*1cfa752fSRamaswamy Tummala 	 */
409*1cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
410*1cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
411*1cfa752fSRamaswamy Tummala 		if (!(ibpart->dlib_flags & IBPART_OFFLINED))
412*1cfa752fSRamaswamy Tummala 			continue;
413*1cfa752fSRamaswamy Tummala 
414*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE1, "IBPART: online DLID %d\n",
415*1cfa752fSRamaswamy Tummala 		    ibpart->dlib_ibpart_id);
416*1cfa752fSRamaswamy Tummala 		if ((status = dladm_part_up(dld_handle,
417*1cfa752fSRamaswamy Tummala 		    ibpart->dlib_ibpart_id, 0)) != DLADM_STATUS_OK) {
418*1cfa752fSRamaswamy Tummala 			/*
419*1cfa752fSRamaswamy Tummala 			 * Print a warning message and continue to online
420*1cfa752fSRamaswamy Tummala 			 * other IBPARTs.
421*1cfa752fSRamaswamy Tummala 			 */
422*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_WARNING,
423*1cfa752fSRamaswamy Tummala 			    _("IBPART: IBPART online failed (%u): %s\n"),
424*1cfa752fSRamaswamy Tummala 			    ibpart->dlib_ibpart_id,
425*1cfa752fSRamaswamy Tummala 			    dladm_status2str(status, errmsg));
426*1cfa752fSRamaswamy Tummala 		} else {
427*1cfa752fSRamaswamy Tummala 			ibpart->dlib_flags &= ~IBPART_OFFLINED;
428*1cfa752fSRamaswamy Tummala 		}
429*1cfa752fSRamaswamy Tummala 	}
430*1cfa752fSRamaswamy Tummala }
431*1cfa752fSRamaswamy Tummala 
432*1cfa752fSRamaswamy Tummala static int
ibpart_offline_ibpart(link_cache_t * node,uint32_t flags,cache_node_state_t state)433*1cfa752fSRamaswamy Tummala ibpart_offline_ibpart(link_cache_t *node, uint32_t flags,
434*1cfa752fSRamaswamy Tummala     cache_node_state_t state)
435*1cfa752fSRamaswamy Tummala {
436*1cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
437*1cfa752fSRamaswamy Tummala 	dladm_status_t status;
438*1cfa752fSRamaswamy Tummala 	char errmsg[DLADM_STRSIZE];
439*1cfa752fSRamaswamy Tummala 
440*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_offline_ibpart "
441*1cfa752fSRamaswamy Tummala 	    "(%s %u %u)\n", node->pc_resource, flags, state);
442*1cfa752fSRamaswamy Tummala 
443*1cfa752fSRamaswamy Tummala 	/*
444*1cfa752fSRamaswamy Tummala 	 * Try to delete all explicit created IBPART
445*1cfa752fSRamaswamy Tummala 	 */
446*1cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
447*1cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
448*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE1, "IBPART: offline DLID %d\n",
449*1cfa752fSRamaswamy Tummala 		    ibpart->dlib_ibpart_id);
450*1cfa752fSRamaswamy Tummala 		if ((status = dladm_part_delete(dld_handle,
451*1cfa752fSRamaswamy Tummala 		    ibpart->dlib_ibpart_id, DLADM_OPT_ACTIVE)) !=
452*1cfa752fSRamaswamy Tummala 		    DLADM_STATUS_OK) {
453*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_WARNING,
454*1cfa752fSRamaswamy Tummala 			    _("IBPART: IBPART offline failed (%u): %s\n"),
455*1cfa752fSRamaswamy Tummala 			    ibpart->dlib_ibpart_id,
456*1cfa752fSRamaswamy Tummala 			    dladm_status2str(status, errmsg));
457*1cfa752fSRamaswamy Tummala 			return (RCM_FAILURE);
458*1cfa752fSRamaswamy Tummala 		} else {
459*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_TRACE1,
460*1cfa752fSRamaswamy Tummala 			    "IBPART: IBPART offline succeeded(%u)\n",
461*1cfa752fSRamaswamy Tummala 			    ibpart->dlib_ibpart_id);
462*1cfa752fSRamaswamy Tummala 			ibpart->dlib_flags |= flags;
463*1cfa752fSRamaswamy Tummala 		}
464*1cfa752fSRamaswamy Tummala 	}
465*1cfa752fSRamaswamy Tummala 
466*1cfa752fSRamaswamy Tummala 	node->pc_state |= state;
467*1cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
468*1cfa752fSRamaswamy Tummala }
469*1cfa752fSRamaswamy Tummala 
470*1cfa752fSRamaswamy Tummala /*
471*1cfa752fSRamaswamy Tummala  * ibpart_get_info() - Gather usage information for this resource.
472*1cfa752fSRamaswamy Tummala  */
473*1cfa752fSRamaswamy Tummala /*ARGSUSED*/
474*1cfa752fSRamaswamy Tummala int
ibpart_get_info(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** usagep,char ** errorp,nvlist_t * props,rcm_info_t ** info)475*1cfa752fSRamaswamy Tummala ibpart_get_info(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
476*1cfa752fSRamaswamy Tummala     char **usagep, char **errorp, nvlist_t *props, rcm_info_t **info)
477*1cfa752fSRamaswamy Tummala {
478*1cfa752fSRamaswamy Tummala 	link_cache_t *node;
479*1cfa752fSRamaswamy Tummala 
480*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: get_info(%s)\n", rsrc);
481*1cfa752fSRamaswamy Tummala 
482*1cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
483*1cfa752fSRamaswamy Tummala 	node = cache_lookup(hd, rsrc, CACHE_REFRESH);
484*1cfa752fSRamaswamy Tummala 	if (node == NULL) {
485*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_INFO,
486*1cfa752fSRamaswamy Tummala 		    _("IBPART: get_info(%s) unrecognized resource\n"), rsrc);
487*1cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
488*1cfa752fSRamaswamy Tummala 		errno = ENOENT;
489*1cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
490*1cfa752fSRamaswamy Tummala 	}
491*1cfa752fSRamaswamy Tummala 
492*1cfa752fSRamaswamy Tummala 	*usagep = ibpart_usage(node);
493*1cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
494*1cfa752fSRamaswamy Tummala 	if (*usagep == NULL) {
495*1cfa752fSRamaswamy Tummala 		/* most likely malloc failure */
496*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_ERROR,
497*1cfa752fSRamaswamy Tummala 		    _("IBPART: get_info(%s) malloc failure\n"), rsrc);
498*1cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
499*1cfa752fSRamaswamy Tummala 		errno = ENOMEM;
500*1cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
501*1cfa752fSRamaswamy Tummala 	}
502*1cfa752fSRamaswamy Tummala 
503*1cfa752fSRamaswamy Tummala 	/* Set client/role properties */
504*1cfa752fSRamaswamy Tummala 	(void) nvlist_add_string(props, RCM_CLIENT_NAME, "IBPART");
505*1cfa752fSRamaswamy Tummala 
506*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: get_info(%s) info = %s\n",
507*1cfa752fSRamaswamy Tummala 	    rsrc, *usagep);
508*1cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
509*1cfa752fSRamaswamy Tummala }
510*1cfa752fSRamaswamy Tummala 
511*1cfa752fSRamaswamy Tummala /*
512*1cfa752fSRamaswamy Tummala  * ibpart_suspend() - Nothing to do, always okay
513*1cfa752fSRamaswamy Tummala  */
514*1cfa752fSRamaswamy Tummala /*ARGSUSED*/
515*1cfa752fSRamaswamy Tummala static int
ibpart_suspend(rcm_handle_t * hd,char * rsrc,id_t id,timespec_t * interval,uint_t flags,char ** errorp,rcm_info_t ** info)516*1cfa752fSRamaswamy Tummala ibpart_suspend(rcm_handle_t *hd, char *rsrc, id_t id, timespec_t *interval,
517*1cfa752fSRamaswamy Tummala     uint_t flags, char **errorp, rcm_info_t **info)
518*1cfa752fSRamaswamy Tummala {
519*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: suspend(%s)\n", rsrc);
520*1cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
521*1cfa752fSRamaswamy Tummala }
522*1cfa752fSRamaswamy Tummala 
523*1cfa752fSRamaswamy Tummala /*
524*1cfa752fSRamaswamy Tummala  * ibpart_resume() - Nothing to do, always okay
525*1cfa752fSRamaswamy Tummala  */
526*1cfa752fSRamaswamy Tummala /*ARGSUSED*/
527*1cfa752fSRamaswamy Tummala static int
ibpart_resume(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)528*1cfa752fSRamaswamy Tummala ibpart_resume(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
529*1cfa752fSRamaswamy Tummala     char **errorp, rcm_info_t **info)
530*1cfa752fSRamaswamy Tummala {
531*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: resume(%s)\n", rsrc);
532*1cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
533*1cfa752fSRamaswamy Tummala }
534*1cfa752fSRamaswamy Tummala 
535*1cfa752fSRamaswamy Tummala /*
536*1cfa752fSRamaswamy Tummala  * ibpart_consumer_remove()
537*1cfa752fSRamaswamy Tummala  *
538*1cfa752fSRamaswamy Tummala  *	Notify IBPART consumers to remove cache.
539*1cfa752fSRamaswamy Tummala  */
540*1cfa752fSRamaswamy Tummala static int
ibpart_consumer_remove(rcm_handle_t * hd,link_cache_t * node,uint_t flags,rcm_info_t ** info)541*1cfa752fSRamaswamy Tummala ibpart_consumer_remove(rcm_handle_t *hd, link_cache_t *node, uint_t flags,
542*1cfa752fSRamaswamy Tummala     rcm_info_t **info)
543*1cfa752fSRamaswamy Tummala {
544*1cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart = NULL;
545*1cfa752fSRamaswamy Tummala 	char rsrc[RCM_LINK_RESOURCE_MAX];
546*1cfa752fSRamaswamy Tummala 	int ret = RCM_SUCCESS;
547*1cfa752fSRamaswamy Tummala 
548*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_remove (%s)\n",
549*1cfa752fSRamaswamy Tummala 	    node->pc_resource);
550*1cfa752fSRamaswamy Tummala 
551*1cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
552*1cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
553*1cfa752fSRamaswamy Tummala 
554*1cfa752fSRamaswamy Tummala 		/*
555*1cfa752fSRamaswamy Tummala 		 * This will only be called when the offline operation
556*1cfa752fSRamaswamy Tummala 		 * succeeds, so the IBPART consumers must have been offlined
557*1cfa752fSRamaswamy Tummala 		 * at this point.
558*1cfa752fSRamaswamy Tummala 		 */
559*1cfa752fSRamaswamy Tummala 		assert(ibpart->dlib_flags & IBPART_CONSUMER_OFFLINED);
560*1cfa752fSRamaswamy Tummala 
561*1cfa752fSRamaswamy Tummala 		(void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
562*1cfa752fSRamaswamy Tummala 		    RCM_LINK_PREFIX, ibpart->dlib_ibpart_id);
563*1cfa752fSRamaswamy Tummala 
564*1cfa752fSRamaswamy Tummala 		ret = rcm_notify_remove(hd, rsrc, flags, info);
565*1cfa752fSRamaswamy Tummala 		if (ret != RCM_SUCCESS) {
566*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_WARNING,
567*1cfa752fSRamaswamy Tummala 			    _("IBPART: notify remove failed (%s)\n"), rsrc);
568*1cfa752fSRamaswamy Tummala 			break;
569*1cfa752fSRamaswamy Tummala 		}
570*1cfa752fSRamaswamy Tummala 	}
571*1cfa752fSRamaswamy Tummala 
572*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_remove done\n");
573*1cfa752fSRamaswamy Tummala 	return (ret);
574*1cfa752fSRamaswamy Tummala }
575*1cfa752fSRamaswamy Tummala 
576*1cfa752fSRamaswamy Tummala /*
577*1cfa752fSRamaswamy Tummala  * ibpart_remove() - remove a resource from cache
578*1cfa752fSRamaswamy Tummala  */
579*1cfa752fSRamaswamy Tummala /*ARGSUSED*/
580*1cfa752fSRamaswamy Tummala static int
ibpart_remove(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)581*1cfa752fSRamaswamy Tummala ibpart_remove(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
582*1cfa752fSRamaswamy Tummala     char **errorp, rcm_info_t **info)
583*1cfa752fSRamaswamy Tummala {
584*1cfa752fSRamaswamy Tummala 	link_cache_t *node;
585*1cfa752fSRamaswamy Tummala 	int rv;
586*1cfa752fSRamaswamy Tummala 
587*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: remove(%s)\n", rsrc);
588*1cfa752fSRamaswamy Tummala 
589*1cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
590*1cfa752fSRamaswamy Tummala 	node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
591*1cfa752fSRamaswamy Tummala 	if (node == NULL) {
592*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_INFO,
593*1cfa752fSRamaswamy Tummala 		    _("IBPART: remove(%s) unrecognized resource\n"), rsrc);
594*1cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
595*1cfa752fSRamaswamy Tummala 		errno = ENOENT;
596*1cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
597*1cfa752fSRamaswamy Tummala 	}
598*1cfa752fSRamaswamy Tummala 
599*1cfa752fSRamaswamy Tummala 	/* remove the cached entry for the resource */
600*1cfa752fSRamaswamy Tummala 	cache_remove(node);
601*1cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
602*1cfa752fSRamaswamy Tummala 
603*1cfa752fSRamaswamy Tummala 	rv = ibpart_consumer_remove(hd, node, flags, info);
604*1cfa752fSRamaswamy Tummala 	node_free(node);
605*1cfa752fSRamaswamy Tummala 	return (rv);
606*1cfa752fSRamaswamy Tummala }
607*1cfa752fSRamaswamy Tummala 
608*1cfa752fSRamaswamy Tummala /*
609*1cfa752fSRamaswamy Tummala  * ibpart_notify_event - Project private implementation to receive new resource
610*1cfa752fSRamaswamy Tummala  *		   events. It intercepts all new resource events. If the
611*1cfa752fSRamaswamy Tummala  *		   new resource is a network resource, pass up a notify
612*1cfa752fSRamaswamy Tummala  *		   for it too. The new resource need not be cached, since
613*1cfa752fSRamaswamy Tummala  *		   it is done at register again.
614*1cfa752fSRamaswamy Tummala  */
615*1cfa752fSRamaswamy Tummala /*ARGSUSED*/
616*1cfa752fSRamaswamy Tummala static int
ibpart_notify_event(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,nvlist_t * nvl,rcm_info_t ** info)617*1cfa752fSRamaswamy Tummala ibpart_notify_event(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
618*1cfa752fSRamaswamy Tummala     char **errorp, nvlist_t *nvl, rcm_info_t **info)
619*1cfa752fSRamaswamy Tummala {
620*1cfa752fSRamaswamy Tummala 	nvpair_t	*nvp = NULL;
621*1cfa752fSRamaswamy Tummala 	datalink_id_t	linkid;
622*1cfa752fSRamaswamy Tummala 	uint64_t	id64;
623*1cfa752fSRamaswamy Tummala 	int		rv = RCM_SUCCESS;
624*1cfa752fSRamaswamy Tummala 
625*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: notify_event(%s)\n", rsrc);
626*1cfa752fSRamaswamy Tummala 
627*1cfa752fSRamaswamy Tummala 	if (strcmp(rsrc, RCM_RESOURCE_LINK_NEW) != 0) {
628*1cfa752fSRamaswamy Tummala 		ibpart_log_err(DATALINK_INVALID_LINKID, errorp,
629*1cfa752fSRamaswamy Tummala 		    "unrecognized event");
630*1cfa752fSRamaswamy Tummala 		errno = EINVAL;
631*1cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
632*1cfa752fSRamaswamy Tummala 	}
633*1cfa752fSRamaswamy Tummala 
634*1cfa752fSRamaswamy Tummala 	/* Update cache to reflect latest IBPARTs */
635*1cfa752fSRamaswamy Tummala 	if (cache_update(hd) < 0) {
636*1cfa752fSRamaswamy Tummala 		ibpart_log_err(DATALINK_INVALID_LINKID, errorp,
637*1cfa752fSRamaswamy Tummala 		    "private Cache update failed");
638*1cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
639*1cfa752fSRamaswamy Tummala 	}
640*1cfa752fSRamaswamy Tummala 
641*1cfa752fSRamaswamy Tummala 	/*
642*1cfa752fSRamaswamy Tummala 	 * Try best to recover all configuration.
643*1cfa752fSRamaswamy Tummala 	 */
644*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_DEBUG, "IBPART: process_nvlist\n");
645*1cfa752fSRamaswamy Tummala 	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
646*1cfa752fSRamaswamy Tummala 		if (strcmp(nvpair_name(nvp), RCM_NV_LINKID) != 0)
647*1cfa752fSRamaswamy Tummala 			continue;
648*1cfa752fSRamaswamy Tummala 
649*1cfa752fSRamaswamy Tummala 		if (nvpair_value_uint64(nvp, &id64) != 0) {
650*1cfa752fSRamaswamy Tummala 			ibpart_log_err(DATALINK_INVALID_LINKID, errorp,
651*1cfa752fSRamaswamy Tummala 			    "cannot get linkid");
652*1cfa752fSRamaswamy Tummala 			rv = RCM_FAILURE;
653*1cfa752fSRamaswamy Tummala 			continue;
654*1cfa752fSRamaswamy Tummala 		}
655*1cfa752fSRamaswamy Tummala 
656*1cfa752fSRamaswamy Tummala 		linkid = (datalink_id_t)id64;
657*1cfa752fSRamaswamy Tummala 		if (ibpart_configure(hd, linkid) != 0) {
658*1cfa752fSRamaswamy Tummala 			ibpart_log_err(linkid, errorp, "configuring failed");
659*1cfa752fSRamaswamy Tummala 			rv = RCM_FAILURE;
660*1cfa752fSRamaswamy Tummala 			continue;
661*1cfa752fSRamaswamy Tummala 		}
662*1cfa752fSRamaswamy Tummala 
663*1cfa752fSRamaswamy Tummala 		/* Notify all IBPART consumers */
664*1cfa752fSRamaswamy Tummala 		if (ibpart_consumer_notify(hd, linkid, errorp, flags,
665*1cfa752fSRamaswamy Tummala 		    info) != 0) {
666*1cfa752fSRamaswamy Tummala 			ibpart_log_err(linkid, errorp,
667*1cfa752fSRamaswamy Tummala 			    "consumer notify failed");
668*1cfa752fSRamaswamy Tummala 			rv = RCM_FAILURE;
669*1cfa752fSRamaswamy Tummala 		}
670*1cfa752fSRamaswamy Tummala 	}
671*1cfa752fSRamaswamy Tummala 
672*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1,
673*1cfa752fSRamaswamy Tummala 	    "IBPART: notify_event: link configuration complete\n");
674*1cfa752fSRamaswamy Tummala 	return (rv);
675*1cfa752fSRamaswamy Tummala }
676*1cfa752fSRamaswamy Tummala 
677*1cfa752fSRamaswamy Tummala /*
678*1cfa752fSRamaswamy Tummala  * ibpart_usage - Determine the usage of a link.
679*1cfa752fSRamaswamy Tummala  *	    The returned buffer is owned by caller, and the caller
680*1cfa752fSRamaswamy Tummala  *	    must free it up when done.
681*1cfa752fSRamaswamy Tummala  */
682*1cfa752fSRamaswamy Tummala static char *
ibpart_usage(link_cache_t * node)683*1cfa752fSRamaswamy Tummala ibpart_usage(link_cache_t *node)
684*1cfa752fSRamaswamy Tummala {
685*1cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
686*1cfa752fSRamaswamy Tummala 	int nibpart;
687*1cfa752fSRamaswamy Tummala 	char *buf;
688*1cfa752fSRamaswamy Tummala 	const char *fmt;
689*1cfa752fSRamaswamy Tummala 	char *sep;
690*1cfa752fSRamaswamy Tummala 	char errmsg[DLADM_STRSIZE];
691*1cfa752fSRamaswamy Tummala 	char name[MAXLINKNAMELEN];
692*1cfa752fSRamaswamy Tummala 	dladm_status_t status;
693*1cfa752fSRamaswamy Tummala 	size_t bufsz;
694*1cfa752fSRamaswamy Tummala 
695*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: usage(%s)\n", node->pc_resource);
696*1cfa752fSRamaswamy Tummala 
697*1cfa752fSRamaswamy Tummala 	assert(MUTEX_HELD(&cache_lock));
698*1cfa752fSRamaswamy Tummala 	if ((status = dladm_datalink_id2info(dld_handle, node->pc_linkid, NULL,
699*1cfa752fSRamaswamy Tummala 	    NULL, NULL, name, sizeof (name))) != DLADM_STATUS_OK) {
700*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_ERROR,
701*1cfa752fSRamaswamy Tummala 		    _("IBPART: usage(%s) get link name failure(%s)\n"),
702*1cfa752fSRamaswamy Tummala 		    node->pc_resource, dladm_status2str(status, errmsg));
703*1cfa752fSRamaswamy Tummala 		return (NULL);
704*1cfa752fSRamaswamy Tummala 	}
705*1cfa752fSRamaswamy Tummala 
706*1cfa752fSRamaswamy Tummala 	if (node->pc_state & CACHE_NODE_OFFLINED)
707*1cfa752fSRamaswamy Tummala 		fmt = _("%1$s offlined");
708*1cfa752fSRamaswamy Tummala 	else
709*1cfa752fSRamaswamy Tummala 		fmt = _("%1$s IBPART: ");
710*1cfa752fSRamaswamy Tummala 
711*1cfa752fSRamaswamy Tummala 	/* TRANSLATION_NOTE: separator used between IBPART linkids */
712*1cfa752fSRamaswamy Tummala 	sep = _(", ");
713*1cfa752fSRamaswamy Tummala 
714*1cfa752fSRamaswamy Tummala 	nibpart = 0;
715*1cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
716*1cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next)
717*1cfa752fSRamaswamy Tummala 		nibpart++;
718*1cfa752fSRamaswamy Tummala 
719*1cfa752fSRamaswamy Tummala 	/* space for IBPARTs and separators, plus message */
720*1cfa752fSRamaswamy Tummala 	bufsz = nibpart * (MAXLINKNAMELEN + strlen(sep)) +
721*1cfa752fSRamaswamy Tummala 	    strlen(fmt) + MAXLINKNAMELEN + 1;
722*1cfa752fSRamaswamy Tummala 	if ((buf = malloc(bufsz)) == NULL) {
723*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_ERROR,
724*1cfa752fSRamaswamy Tummala 		    _("IBPART: usage(%s) malloc failure(%s)\n"),
725*1cfa752fSRamaswamy Tummala 		    node->pc_resource, strerror(errno));
726*1cfa752fSRamaswamy Tummala 		return (NULL);
727*1cfa752fSRamaswamy Tummala 	}
728*1cfa752fSRamaswamy Tummala 	(void) snprintf(buf, bufsz, fmt, name);
729*1cfa752fSRamaswamy Tummala 
730*1cfa752fSRamaswamy Tummala 	if (node->pc_state & CACHE_NODE_OFFLINED) {
731*1cfa752fSRamaswamy Tummala 		/* Nothing else to do */
732*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE2, "IBPART: usage (%s) info = %s\n",
733*1cfa752fSRamaswamy Tummala 		    node->pc_resource, buf);
734*1cfa752fSRamaswamy Tummala 		return (buf);
735*1cfa752fSRamaswamy Tummala 	}
736*1cfa752fSRamaswamy Tummala 
737*1cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
738*1cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
739*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_DEBUG, "IBPART:= %u\n",
740*1cfa752fSRamaswamy Tummala 		    ibpart->dlib_ibpart_id);
741*1cfa752fSRamaswamy Tummala 
742*1cfa752fSRamaswamy Tummala 		if ((status = dladm_datalink_id2info(dld_handle,
743*1cfa752fSRamaswamy Tummala 		    ibpart->dlib_ibpart_id, NULL, NULL, NULL, name,
744*1cfa752fSRamaswamy Tummala 		    sizeof (name))) != DLADM_STATUS_OK) {
745*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR,
746*1cfa752fSRamaswamy Tummala 			    _("IBPART: usage(%s) get ibpart %u name "
747*1cfa752fSRamaswamy Tummala 			    "failure(%s)\n"), node->pc_resource,
748*1cfa752fSRamaswamy Tummala 			    ibpart->dlib_ibpart_id,
749*1cfa752fSRamaswamy Tummala 			    dladm_status2str(status, errmsg));
750*1cfa752fSRamaswamy Tummala 			free(buf);
751*1cfa752fSRamaswamy Tummala 			return (NULL);
752*1cfa752fSRamaswamy Tummala 		}
753*1cfa752fSRamaswamy Tummala 
754*1cfa752fSRamaswamy Tummala 		(void) strlcat(buf, name, bufsz);
755*1cfa752fSRamaswamy Tummala 		if (ibpart->dlib_next != NULL)
756*1cfa752fSRamaswamy Tummala 			(void) strlcat(buf, sep, bufsz);
757*1cfa752fSRamaswamy Tummala 	}
758*1cfa752fSRamaswamy Tummala 
759*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: usage (%s) info = %s\n",
760*1cfa752fSRamaswamy Tummala 	    node->pc_resource, buf);
761*1cfa752fSRamaswamy Tummala 
762*1cfa752fSRamaswamy Tummala 	return (buf);
763*1cfa752fSRamaswamy Tummala }
764*1cfa752fSRamaswamy Tummala 
765*1cfa752fSRamaswamy Tummala /*
766*1cfa752fSRamaswamy Tummala  * Cache management routines, all cache management functions should be
767*1cfa752fSRamaswamy Tummala  * be called with cache_lock held.
768*1cfa752fSRamaswamy Tummala  */
769*1cfa752fSRamaswamy Tummala 
770*1cfa752fSRamaswamy Tummala /*
771*1cfa752fSRamaswamy Tummala  * cache_lookup() - Get a cache node for a resource.
772*1cfa752fSRamaswamy Tummala  *		  Call with cache lock held.
773*1cfa752fSRamaswamy Tummala  *
774*1cfa752fSRamaswamy Tummala  * This ensures that the cache is consistent with the system state and
775*1cfa752fSRamaswamy Tummala  * returns a pointer to the cache element corresponding to the resource.
776*1cfa752fSRamaswamy Tummala  */
777*1cfa752fSRamaswamy Tummala static link_cache_t *
cache_lookup(rcm_handle_t * hd,char * rsrc,char options)778*1cfa752fSRamaswamy Tummala cache_lookup(rcm_handle_t *hd, char *rsrc, char options)
779*1cfa752fSRamaswamy Tummala {
780*1cfa752fSRamaswamy Tummala 	link_cache_t *node;
781*1cfa752fSRamaswamy Tummala 
782*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: cache lookup(%s)\n", rsrc);
783*1cfa752fSRamaswamy Tummala 
784*1cfa752fSRamaswamy Tummala 	assert(MUTEX_HELD(&cache_lock));
785*1cfa752fSRamaswamy Tummala 	if (options & CACHE_REFRESH) {
786*1cfa752fSRamaswamy Tummala 		/* drop lock since update locks cache again */
787*1cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
788*1cfa752fSRamaswamy Tummala 		(void) cache_update(hd);
789*1cfa752fSRamaswamy Tummala 		(void) mutex_lock(&cache_lock);
790*1cfa752fSRamaswamy Tummala 	}
791*1cfa752fSRamaswamy Tummala 
792*1cfa752fSRamaswamy Tummala 	node = cache_head.pc_next;
793*1cfa752fSRamaswamy Tummala 	for (; node != &cache_tail; node = node->pc_next) {
794*1cfa752fSRamaswamy Tummala 		if (strcmp(rsrc, node->pc_resource) == 0) {
795*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_TRACE2,
796*1cfa752fSRamaswamy Tummala 			    "IBPART: cache lookup succeeded(%s)\n", rsrc);
797*1cfa752fSRamaswamy Tummala 			return (node);
798*1cfa752fSRamaswamy Tummala 		}
799*1cfa752fSRamaswamy Tummala 	}
800*1cfa752fSRamaswamy Tummala 	return (NULL);
801*1cfa752fSRamaswamy Tummala }
802*1cfa752fSRamaswamy Tummala 
803*1cfa752fSRamaswamy Tummala /*
804*1cfa752fSRamaswamy Tummala  * node_free - Free a node from the cache
805*1cfa752fSRamaswamy Tummala  */
806*1cfa752fSRamaswamy Tummala static void
node_free(link_cache_t * node)807*1cfa752fSRamaswamy Tummala node_free(link_cache_t *node)
808*1cfa752fSRamaswamy Tummala {
809*1cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart, *next;
810*1cfa752fSRamaswamy Tummala 
811*1cfa752fSRamaswamy Tummala 	if (node != NULL) {
812*1cfa752fSRamaswamy Tummala 		free(node->pc_resource);
813*1cfa752fSRamaswamy Tummala 
814*1cfa752fSRamaswamy Tummala 		/* free the IBPART list */
815*1cfa752fSRamaswamy Tummala 		for (ibpart = node->pc_ibpart; ibpart != NULL; ibpart = next) {
816*1cfa752fSRamaswamy Tummala 			next = ibpart->dlib_next;
817*1cfa752fSRamaswamy Tummala 			free(ibpart);
818*1cfa752fSRamaswamy Tummala 		}
819*1cfa752fSRamaswamy Tummala 		free(node);
820*1cfa752fSRamaswamy Tummala 	}
821*1cfa752fSRamaswamy Tummala }
822*1cfa752fSRamaswamy Tummala 
823*1cfa752fSRamaswamy Tummala /*
824*1cfa752fSRamaswamy Tummala  * cache_insert - Insert a resource node in cache
825*1cfa752fSRamaswamy Tummala  */
826*1cfa752fSRamaswamy Tummala static void
cache_insert(link_cache_t * node)827*1cfa752fSRamaswamy Tummala cache_insert(link_cache_t *node)
828*1cfa752fSRamaswamy Tummala {
829*1cfa752fSRamaswamy Tummala 	assert(MUTEX_HELD(&cache_lock));
830*1cfa752fSRamaswamy Tummala 
831*1cfa752fSRamaswamy Tummala 	/* insert at the head for best performance */
832*1cfa752fSRamaswamy Tummala 	node->pc_next = cache_head.pc_next;
833*1cfa752fSRamaswamy Tummala 	node->pc_prev = &cache_head;
834*1cfa752fSRamaswamy Tummala 
835*1cfa752fSRamaswamy Tummala 	node->pc_next->pc_prev = node;
836*1cfa752fSRamaswamy Tummala 	node->pc_prev->pc_next = node;
837*1cfa752fSRamaswamy Tummala }
838*1cfa752fSRamaswamy Tummala 
839*1cfa752fSRamaswamy Tummala /*
840*1cfa752fSRamaswamy Tummala  * cache_remove() - Remove a resource node from cache.
841*1cfa752fSRamaswamy Tummala  */
842*1cfa752fSRamaswamy Tummala static void
cache_remove(link_cache_t * node)843*1cfa752fSRamaswamy Tummala cache_remove(link_cache_t *node)
844*1cfa752fSRamaswamy Tummala {
845*1cfa752fSRamaswamy Tummala 	assert(MUTEX_HELD(&cache_lock));
846*1cfa752fSRamaswamy Tummala 	node->pc_next->pc_prev = node->pc_prev;
847*1cfa752fSRamaswamy Tummala 	node->pc_prev->pc_next = node->pc_next;
848*1cfa752fSRamaswamy Tummala 	node->pc_next = NULL;
849*1cfa752fSRamaswamy Tummala 	node->pc_prev = NULL;
850*1cfa752fSRamaswamy Tummala }
851*1cfa752fSRamaswamy Tummala 
852*1cfa752fSRamaswamy Tummala typedef struct ibpart_update_arg_s {
853*1cfa752fSRamaswamy Tummala 	rcm_handle_t	*hd;
854*1cfa752fSRamaswamy Tummala 	int		retval;
855*1cfa752fSRamaswamy Tummala } ibpart_update_arg_t;
856*1cfa752fSRamaswamy Tummala 
857*1cfa752fSRamaswamy Tummala /*
858*1cfa752fSRamaswamy Tummala  * ibpart_update() - Update physical interface properties
859*1cfa752fSRamaswamy Tummala  */
860*1cfa752fSRamaswamy Tummala static int
ibpart_update(dladm_handle_t handle,datalink_id_t ibpartid,void * arg)861*1cfa752fSRamaswamy Tummala ibpart_update(dladm_handle_t handle, datalink_id_t ibpartid, void *arg)
862*1cfa752fSRamaswamy Tummala {
863*1cfa752fSRamaswamy Tummala 	ibpart_update_arg_t *ibpart_update_argp = arg;
864*1cfa752fSRamaswamy Tummala 	rcm_handle_t *hd = ibpart_update_argp->hd;
865*1cfa752fSRamaswamy Tummala 	link_cache_t *node;
866*1cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
867*1cfa752fSRamaswamy Tummala 	char *rsrc;
868*1cfa752fSRamaswamy Tummala 	dladm_ib_attr_t ibpart_attr;
869*1cfa752fSRamaswamy Tummala 	dladm_status_t status;
870*1cfa752fSRamaswamy Tummala 	char errmsg[DLADM_STRSIZE];
871*1cfa752fSRamaswamy Tummala 	boolean_t newnode = B_FALSE;
872*1cfa752fSRamaswamy Tummala 	int ret = -1;
873*1cfa752fSRamaswamy Tummala 
874*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_update(%u)\n", ibpartid);
875*1cfa752fSRamaswamy Tummala 
876*1cfa752fSRamaswamy Tummala 	assert(MUTEX_HELD(&cache_lock));
877*1cfa752fSRamaswamy Tummala 	status = dladm_part_info(handle, ibpartid, &ibpart_attr,
878*1cfa752fSRamaswamy Tummala 	    DLADM_OPT_ACTIVE);
879*1cfa752fSRamaswamy Tummala 	if (status != DLADM_STATUS_OK) {
880*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE1,
881*1cfa752fSRamaswamy Tummala 		    "IBPART: ibpart_update() cannot get ibpart information for "
882*1cfa752fSRamaswamy Tummala 		    "%u(%s)\n", ibpartid, dladm_status2str(status, errmsg));
883*1cfa752fSRamaswamy Tummala 		return (DLADM_WALK_CONTINUE);
884*1cfa752fSRamaswamy Tummala 	}
885*1cfa752fSRamaswamy Tummala 
886*1cfa752fSRamaswamy Tummala 	if (ibpart_attr.dia_physlinkid == DATALINK_INVALID_LINKID) {
887*1cfa752fSRamaswamy Tummala 		/*
888*1cfa752fSRamaswamy Tummala 		 * Skip the IB port nodes.
889*1cfa752fSRamaswamy Tummala 		 */
890*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE1,
891*1cfa752fSRamaswamy Tummala 		    "IBPART: ibpart_update(): skip the PORT nodes %u\n",
892*1cfa752fSRamaswamy Tummala 		    ibpartid);
893*1cfa752fSRamaswamy Tummala 		return (DLADM_WALK_CONTINUE);
894*1cfa752fSRamaswamy Tummala 	}
895*1cfa752fSRamaswamy Tummala 
896*1cfa752fSRamaswamy Tummala 	rsrc = malloc(RCM_LINK_RESOURCE_MAX);
897*1cfa752fSRamaswamy Tummala 	if (rsrc == NULL) {
898*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_ERROR, _("IBPART: malloc error(%s): %u\n"),
899*1cfa752fSRamaswamy Tummala 		    strerror(errno), ibpartid);
900*1cfa752fSRamaswamy Tummala 		goto done;
901*1cfa752fSRamaswamy Tummala 	}
902*1cfa752fSRamaswamy Tummala 
903*1cfa752fSRamaswamy Tummala 	(void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
904*1cfa752fSRamaswamy Tummala 	    RCM_LINK_PREFIX, ibpart_attr.dia_physlinkid);
905*1cfa752fSRamaswamy Tummala 
906*1cfa752fSRamaswamy Tummala 	node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
907*1cfa752fSRamaswamy Tummala 	if (node != NULL) {
908*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_DEBUG,
909*1cfa752fSRamaswamy Tummala 		    "IBPART: %s already registered (ibpartid:%d)\n",
910*1cfa752fSRamaswamy Tummala 		    rsrc, ibpart_attr.dia_partlinkid);
911*1cfa752fSRamaswamy Tummala 		free(rsrc);
912*1cfa752fSRamaswamy Tummala 	} else {
913*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_DEBUG,
914*1cfa752fSRamaswamy Tummala 		    "IBPART: %s is a new resource (ibpartid:%d)\n",
915*1cfa752fSRamaswamy Tummala 		    rsrc, ibpart_attr.dia_partlinkid);
916*1cfa752fSRamaswamy Tummala 		if ((node = calloc(1, sizeof (link_cache_t))) == NULL) {
917*1cfa752fSRamaswamy Tummala 			free(rsrc);
918*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR, _("IBPART: calloc: %s\n"),
919*1cfa752fSRamaswamy Tummala 			    strerror(errno));
920*1cfa752fSRamaswamy Tummala 			goto done;
921*1cfa752fSRamaswamy Tummala 		}
922*1cfa752fSRamaswamy Tummala 
923*1cfa752fSRamaswamy Tummala 		node->pc_resource = rsrc;
924*1cfa752fSRamaswamy Tummala 		node->pc_ibpart = NULL;
925*1cfa752fSRamaswamy Tummala 		node->pc_linkid = ibpart_attr.dia_physlinkid;
926*1cfa752fSRamaswamy Tummala 		node->pc_state |= CACHE_NODE_NEW;
927*1cfa752fSRamaswamy Tummala 		newnode = B_TRUE;
928*1cfa752fSRamaswamy Tummala 	}
929*1cfa752fSRamaswamy Tummala 
930*1cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
931*1cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
932*1cfa752fSRamaswamy Tummala 		if (ibpart->dlib_ibpart_id == ibpartid) {
933*1cfa752fSRamaswamy Tummala 			ibpart->dlib_flags &= ~IBPART_STALE;
934*1cfa752fSRamaswamy Tummala 			break;
935*1cfa752fSRamaswamy Tummala 		}
936*1cfa752fSRamaswamy Tummala 	}
937*1cfa752fSRamaswamy Tummala 
938*1cfa752fSRamaswamy Tummala 	if (ibpart == NULL) {
939*1cfa752fSRamaswamy Tummala 		if ((ibpart = calloc(1, sizeof (dl_ibpart_t))) == NULL) {
940*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR, _("IBPART: malloc: %s\n"),
941*1cfa752fSRamaswamy Tummala 			    strerror(errno));
942*1cfa752fSRamaswamy Tummala 			if (newnode) {
943*1cfa752fSRamaswamy Tummala 				free(rsrc);
944*1cfa752fSRamaswamy Tummala 				free(node);
945*1cfa752fSRamaswamy Tummala 			}
946*1cfa752fSRamaswamy Tummala 			goto done;
947*1cfa752fSRamaswamy Tummala 		}
948*1cfa752fSRamaswamy Tummala 		ibpart->dlib_ibpart_id = ibpartid;
949*1cfa752fSRamaswamy Tummala 		ibpart->dlib_next = node->pc_ibpart;
950*1cfa752fSRamaswamy Tummala 		ibpart->dlib_prev = NULL;
951*1cfa752fSRamaswamy Tummala 		if (node->pc_ibpart != NULL)
952*1cfa752fSRamaswamy Tummala 			node->pc_ibpart->dlib_prev = ibpart;
953*1cfa752fSRamaswamy Tummala 		node->pc_ibpart = ibpart;
954*1cfa752fSRamaswamy Tummala 	}
955*1cfa752fSRamaswamy Tummala 
956*1cfa752fSRamaswamy Tummala 	node->pc_state &= ~CACHE_NODE_STALE;
957*1cfa752fSRamaswamy Tummala 
958*1cfa752fSRamaswamy Tummala 	if (newnode)
959*1cfa752fSRamaswamy Tummala 		cache_insert(node);
960*1cfa752fSRamaswamy Tummala 
961*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE3, "IBPART: ibpart_update: succeeded(%u)\n",
962*1cfa752fSRamaswamy Tummala 	    ibpartid);
963*1cfa752fSRamaswamy Tummala 	ret = 0;
964*1cfa752fSRamaswamy Tummala done:
965*1cfa752fSRamaswamy Tummala 	ibpart_update_argp->retval = ret;
966*1cfa752fSRamaswamy Tummala 	return (ret == 0 ? DLADM_WALK_CONTINUE : DLADM_WALK_TERMINATE);
967*1cfa752fSRamaswamy Tummala }
968*1cfa752fSRamaswamy Tummala 
969*1cfa752fSRamaswamy Tummala /*
970*1cfa752fSRamaswamy Tummala  * ibpart_update_all() - Determine all IBPART links in the system
971*1cfa752fSRamaswamy Tummala  */
972*1cfa752fSRamaswamy Tummala static int
ibpart_update_all(rcm_handle_t * hd)973*1cfa752fSRamaswamy Tummala ibpart_update_all(rcm_handle_t *hd)
974*1cfa752fSRamaswamy Tummala {
975*1cfa752fSRamaswamy Tummala 	ibpart_update_arg_t arg = {NULL, 0};
976*1cfa752fSRamaswamy Tummala 
977*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_update_all\n");
978*1cfa752fSRamaswamy Tummala 
979*1cfa752fSRamaswamy Tummala 	assert(MUTEX_HELD(&cache_lock));
980*1cfa752fSRamaswamy Tummala 	arg.hd = hd;
981*1cfa752fSRamaswamy Tummala 	(void) dladm_walk_datalink_id(ibpart_update, dld_handle, &arg,
982*1cfa752fSRamaswamy Tummala 	    DATALINK_CLASS_PART, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
983*1cfa752fSRamaswamy Tummala 	return (arg.retval);
984*1cfa752fSRamaswamy Tummala }
985*1cfa752fSRamaswamy Tummala 
986*1cfa752fSRamaswamy Tummala /*
987*1cfa752fSRamaswamy Tummala  * cache_update() - Update cache with latest interface info
988*1cfa752fSRamaswamy Tummala  */
989*1cfa752fSRamaswamy Tummala static int
cache_update(rcm_handle_t * hd)990*1cfa752fSRamaswamy Tummala cache_update(rcm_handle_t *hd)
991*1cfa752fSRamaswamy Tummala {
992*1cfa752fSRamaswamy Tummala 	link_cache_t *node, *nnode;
993*1cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
994*1cfa752fSRamaswamy Tummala 	int rv;
995*1cfa752fSRamaswamy Tummala 
996*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: cache_update\n");
997*1cfa752fSRamaswamy Tummala 
998*1cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
999*1cfa752fSRamaswamy Tummala 
1000*1cfa752fSRamaswamy Tummala 	/* first we walk the entire cache, marking each entry stale */
1001*1cfa752fSRamaswamy Tummala 	node = cache_head.pc_next;
1002*1cfa752fSRamaswamy Tummala 	for (; node != &cache_tail; node = node->pc_next) {
1003*1cfa752fSRamaswamy Tummala 		node->pc_state |= CACHE_NODE_STALE;
1004*1cfa752fSRamaswamy Tummala 		for (ibpart = node->pc_ibpart; ibpart != NULL;
1005*1cfa752fSRamaswamy Tummala 		    ibpart = ibpart->dlib_next)
1006*1cfa752fSRamaswamy Tummala 			ibpart->dlib_flags |= IBPART_STALE;
1007*1cfa752fSRamaswamy Tummala 	}
1008*1cfa752fSRamaswamy Tummala 
1009*1cfa752fSRamaswamy Tummala 	rv = ibpart_update_all(hd);
1010*1cfa752fSRamaswamy Tummala 
1011*1cfa752fSRamaswamy Tummala 	/*
1012*1cfa752fSRamaswamy Tummala 	 * Continue to delete all stale nodes from the cache even
1013*1cfa752fSRamaswamy Tummala 	 * ibpart_update_all() failed. Unregister link that are not offlined
1014*1cfa752fSRamaswamy Tummala 	 * and still in cache
1015*1cfa752fSRamaswamy Tummala 	 */
1016*1cfa752fSRamaswamy Tummala 	for (node = cache_head.pc_next; node != &cache_tail; node = nnode) {
1017*1cfa752fSRamaswamy Tummala 		dl_ibpart_t *ibpart, *next;
1018*1cfa752fSRamaswamy Tummala 
1019*1cfa752fSRamaswamy Tummala 		for (ibpart = node->pc_ibpart; ibpart != NULL; ibpart = next) {
1020*1cfa752fSRamaswamy Tummala 			next = ibpart->dlib_next;
1021*1cfa752fSRamaswamy Tummala 
1022*1cfa752fSRamaswamy Tummala 			/* clear stale IBPARTs */
1023*1cfa752fSRamaswamy Tummala 			if (ibpart->dlib_flags & IBPART_STALE) {
1024*1cfa752fSRamaswamy Tummala 				if (ibpart->dlib_prev != NULL)
1025*1cfa752fSRamaswamy Tummala 					ibpart->dlib_prev->dlib_next = next;
1026*1cfa752fSRamaswamy Tummala 				else
1027*1cfa752fSRamaswamy Tummala 					node->pc_ibpart = next;
1028*1cfa752fSRamaswamy Tummala 
1029*1cfa752fSRamaswamy Tummala 				if (next != NULL)
1030*1cfa752fSRamaswamy Tummala 					next->dlib_prev = ibpart->dlib_prev;
1031*1cfa752fSRamaswamy Tummala 				free(ibpart);
1032*1cfa752fSRamaswamy Tummala 			}
1033*1cfa752fSRamaswamy Tummala 		}
1034*1cfa752fSRamaswamy Tummala 
1035*1cfa752fSRamaswamy Tummala 		nnode = node->pc_next;
1036*1cfa752fSRamaswamy Tummala 		if (node->pc_state & CACHE_NODE_STALE) {
1037*1cfa752fSRamaswamy Tummala 			(void) rcm_unregister_interest(hd, node->pc_resource,
1038*1cfa752fSRamaswamy Tummala 			    0);
1039*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_DEBUG, "IBPART: unregistered %s\n",
1040*1cfa752fSRamaswamy Tummala 			    node->pc_resource);
1041*1cfa752fSRamaswamy Tummala 			assert(node->pc_ibpart == NULL);
1042*1cfa752fSRamaswamy Tummala 			cache_remove(node);
1043*1cfa752fSRamaswamy Tummala 			node_free(node);
1044*1cfa752fSRamaswamy Tummala 			continue;
1045*1cfa752fSRamaswamy Tummala 		}
1046*1cfa752fSRamaswamy Tummala 
1047*1cfa752fSRamaswamy Tummala 		if (!(node->pc_state & CACHE_NODE_NEW))
1048*1cfa752fSRamaswamy Tummala 			continue;
1049*1cfa752fSRamaswamy Tummala 
1050*1cfa752fSRamaswamy Tummala 		if (rcm_register_interest(hd, node->pc_resource, 0, NULL) !=
1051*1cfa752fSRamaswamy Tummala 		    RCM_SUCCESS) {
1052*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR,
1053*1cfa752fSRamaswamy Tummala 			    _("IBPART: failed to register %s\n"),
1054*1cfa752fSRamaswamy Tummala 			    node->pc_resource);
1055*1cfa752fSRamaswamy Tummala 			rv = -1;
1056*1cfa752fSRamaswamy Tummala 		} else {
1057*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_DEBUG, "IBPART: registered %s\n",
1058*1cfa752fSRamaswamy Tummala 			    node->pc_resource);
1059*1cfa752fSRamaswamy Tummala 			node->pc_state &= ~CACHE_NODE_NEW;
1060*1cfa752fSRamaswamy Tummala 		}
1061*1cfa752fSRamaswamy Tummala 	}
1062*1cfa752fSRamaswamy Tummala 
1063*1cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
1064*1cfa752fSRamaswamy Tummala 	return (rv);
1065*1cfa752fSRamaswamy Tummala }
1066*1cfa752fSRamaswamy Tummala 
1067*1cfa752fSRamaswamy Tummala /*
1068*1cfa752fSRamaswamy Tummala  * cache_free() - Empty the cache
1069*1cfa752fSRamaswamy Tummala  */
1070*1cfa752fSRamaswamy Tummala static void
cache_free()1071*1cfa752fSRamaswamy Tummala cache_free()
1072*1cfa752fSRamaswamy Tummala {
1073*1cfa752fSRamaswamy Tummala 	link_cache_t *node;
1074*1cfa752fSRamaswamy Tummala 
1075*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: cache_free\n");
1076*1cfa752fSRamaswamy Tummala 
1077*1cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
1078*1cfa752fSRamaswamy Tummala 	node = cache_head.pc_next;
1079*1cfa752fSRamaswamy Tummala 	while (node != &cache_tail) {
1080*1cfa752fSRamaswamy Tummala 		cache_remove(node);
1081*1cfa752fSRamaswamy Tummala 		node_free(node);
1082*1cfa752fSRamaswamy Tummala 		node = cache_head.pc_next;
1083*1cfa752fSRamaswamy Tummala 	}
1084*1cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
1085*1cfa752fSRamaswamy Tummala }
1086*1cfa752fSRamaswamy Tummala 
1087*1cfa752fSRamaswamy Tummala /*
1088*1cfa752fSRamaswamy Tummala  * ibpart_log_err() - RCM error log wrapper
1089*1cfa752fSRamaswamy Tummala  */
1090*1cfa752fSRamaswamy Tummala static void
ibpart_log_err(datalink_id_t linkid,char ** errorp,char * errmsg)1091*1cfa752fSRamaswamy Tummala ibpart_log_err(datalink_id_t linkid, char **errorp, char *errmsg)
1092*1cfa752fSRamaswamy Tummala {
1093*1cfa752fSRamaswamy Tummala 	char link[MAXLINKNAMELEN];
1094*1cfa752fSRamaswamy Tummala 	char errstr[DLADM_STRSIZE];
1095*1cfa752fSRamaswamy Tummala 	dladm_status_t status;
1096*1cfa752fSRamaswamy Tummala 	int len;
1097*1cfa752fSRamaswamy Tummala 	const char *errfmt;
1098*1cfa752fSRamaswamy Tummala 	char *error;
1099*1cfa752fSRamaswamy Tummala 
1100*1cfa752fSRamaswamy Tummala 	link[0] = '\0';
1101*1cfa752fSRamaswamy Tummala 	if (linkid != DATALINK_INVALID_LINKID) {
1102*1cfa752fSRamaswamy Tummala 		char rsrc[RCM_LINK_RESOURCE_MAX];
1103*1cfa752fSRamaswamy Tummala 
1104*1cfa752fSRamaswamy Tummala 		(void) snprintf(rsrc, sizeof (rsrc), "%s/%u",
1105*1cfa752fSRamaswamy Tummala 		    RCM_LINK_PREFIX, linkid);
1106*1cfa752fSRamaswamy Tummala 
1107*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_ERROR, _("IBPART: %s(%s)\n"), errmsg, rsrc);
1108*1cfa752fSRamaswamy Tummala 		if ((status = dladm_datalink_id2info(dld_handle, linkid, NULL,
1109*1cfa752fSRamaswamy Tummala 		    NULL, NULL, link, sizeof (link))) != DLADM_STATUS_OK) {
1110*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_WARNING,
1111*1cfa752fSRamaswamy Tummala 			    _("IBPART: cannot get link name for (%s) %s\n"),
1112*1cfa752fSRamaswamy Tummala 			    rsrc, dladm_status2str(status, errstr));
1113*1cfa752fSRamaswamy Tummala 		}
1114*1cfa752fSRamaswamy Tummala 	} else {
1115*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_ERROR, _("IBPART: %s\n"), errmsg);
1116*1cfa752fSRamaswamy Tummala 	}
1117*1cfa752fSRamaswamy Tummala 
1118*1cfa752fSRamaswamy Tummala 	errfmt = strlen(link) > 0 ? _("IBPART: %s(%s)") : _("IBPART: %s");
1119*1cfa752fSRamaswamy Tummala 	len = strlen(errfmt) + strlen(errmsg) + MAXLINKNAMELEN + 1;
1120*1cfa752fSRamaswamy Tummala 	if ((error = malloc(len)) != NULL) {
1121*1cfa752fSRamaswamy Tummala 		if (strlen(link) > 0)
1122*1cfa752fSRamaswamy Tummala 			(void) snprintf(error, len, errfmt, errmsg, link);
1123*1cfa752fSRamaswamy Tummala 		else
1124*1cfa752fSRamaswamy Tummala 			(void) snprintf(error, len, errfmt, errmsg);
1125*1cfa752fSRamaswamy Tummala 	}
1126*1cfa752fSRamaswamy Tummala 
1127*1cfa752fSRamaswamy Tummala 	if (errorp != NULL)
1128*1cfa752fSRamaswamy Tummala 		*errorp = error;
1129*1cfa752fSRamaswamy Tummala }
1130*1cfa752fSRamaswamy Tummala 
1131*1cfa752fSRamaswamy Tummala /*
1132*1cfa752fSRamaswamy Tummala  * ibpart_consumer_online()
1133*1cfa752fSRamaswamy Tummala  *
1134*1cfa752fSRamaswamy Tummala  *	Notify online to IBPART consumers.
1135*1cfa752fSRamaswamy Tummala  */
1136*1cfa752fSRamaswamy Tummala /* ARGSUSED */
1137*1cfa752fSRamaswamy Tummala static void
ibpart_consumer_online(rcm_handle_t * hd,link_cache_t * node,char ** errorp,uint_t flags,rcm_info_t ** info)1138*1cfa752fSRamaswamy Tummala ibpart_consumer_online(rcm_handle_t *hd, link_cache_t *node, char **errorp,
1139*1cfa752fSRamaswamy Tummala     uint_t flags, rcm_info_t **info)
1140*1cfa752fSRamaswamy Tummala {
1141*1cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
1142*1cfa752fSRamaswamy Tummala 	char rsrc[RCM_LINK_RESOURCE_MAX];
1143*1cfa752fSRamaswamy Tummala 
1144*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_online (%s)\n",
1145*1cfa752fSRamaswamy Tummala 	    node->pc_resource);
1146*1cfa752fSRamaswamy Tummala 
1147*1cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
1148*1cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
1149*1cfa752fSRamaswamy Tummala 		if (!(ibpart->dlib_flags & IBPART_CONSUMER_OFFLINED))
1150*1cfa752fSRamaswamy Tummala 			continue;
1151*1cfa752fSRamaswamy Tummala 
1152*1cfa752fSRamaswamy Tummala 		(void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
1153*1cfa752fSRamaswamy Tummala 		    RCM_LINK_PREFIX, ibpart->dlib_ibpart_id);
1154*1cfa752fSRamaswamy Tummala 
1155*1cfa752fSRamaswamy Tummala 		if (rcm_notify_online(hd, rsrc, flags, info) == RCM_SUCCESS)
1156*1cfa752fSRamaswamy Tummala 			ibpart->dlib_flags &= ~IBPART_CONSUMER_OFFLINED;
1157*1cfa752fSRamaswamy Tummala 	}
1158*1cfa752fSRamaswamy Tummala 
1159*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_online done\n");
1160*1cfa752fSRamaswamy Tummala }
1161*1cfa752fSRamaswamy Tummala 
1162*1cfa752fSRamaswamy Tummala /*
1163*1cfa752fSRamaswamy Tummala  * ibpart_consumer_offline()
1164*1cfa752fSRamaswamy Tummala  *
1165*1cfa752fSRamaswamy Tummala  *	Offline IBPART consumers.
1166*1cfa752fSRamaswamy Tummala  */
1167*1cfa752fSRamaswamy Tummala static int
ibpart_consumer_offline(rcm_handle_t * hd,link_cache_t * node,char ** errorp,uint_t flags,rcm_info_t ** info)1168*1cfa752fSRamaswamy Tummala ibpart_consumer_offline(rcm_handle_t *hd, link_cache_t *node, char **errorp,
1169*1cfa752fSRamaswamy Tummala     uint_t flags, rcm_info_t **info)
1170*1cfa752fSRamaswamy Tummala {
1171*1cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
1172*1cfa752fSRamaswamy Tummala 	char rsrc[RCM_LINK_RESOURCE_MAX];
1173*1cfa752fSRamaswamy Tummala 	int ret = RCM_SUCCESS;
1174*1cfa752fSRamaswamy Tummala 
1175*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_offline (%s)\n",
1176*1cfa752fSRamaswamy Tummala 	    node->pc_resource);
1177*1cfa752fSRamaswamy Tummala 
1178*1cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
1179*1cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
1180*1cfa752fSRamaswamy Tummala 		(void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
1181*1cfa752fSRamaswamy Tummala 		    RCM_LINK_PREFIX, ibpart->dlib_ibpart_id);
1182*1cfa752fSRamaswamy Tummala 
1183*1cfa752fSRamaswamy Tummala 		ret = rcm_request_offline(hd, rsrc, flags, info);
1184*1cfa752fSRamaswamy Tummala 		if (ret != RCM_SUCCESS)
1185*1cfa752fSRamaswamy Tummala 			break;
1186*1cfa752fSRamaswamy Tummala 
1187*1cfa752fSRamaswamy Tummala 		ibpart->dlib_flags |= IBPART_CONSUMER_OFFLINED;
1188*1cfa752fSRamaswamy Tummala 	}
1189*1cfa752fSRamaswamy Tummala 
1190*1cfa752fSRamaswamy Tummala 	if (ibpart != NULL)
1191*1cfa752fSRamaswamy Tummala 		ibpart_consumer_online(hd, node, errorp, flags, info);
1192*1cfa752fSRamaswamy Tummala 
1193*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_offline done\n");
1194*1cfa752fSRamaswamy Tummala 	return (ret);
1195*1cfa752fSRamaswamy Tummala }
1196*1cfa752fSRamaswamy Tummala 
1197*1cfa752fSRamaswamy Tummala /*
1198*1cfa752fSRamaswamy Tummala  * Send RCM_RESOURCE_LINK_NEW events to other modules about new IBPARTs.
1199*1cfa752fSRamaswamy Tummala  * Return 0 on success, -1 on failure.
1200*1cfa752fSRamaswamy Tummala  */
1201*1cfa752fSRamaswamy Tummala static int
ibpart_notify_new_ibpart(rcm_handle_t * hd,char * rsrc)1202*1cfa752fSRamaswamy Tummala ibpart_notify_new_ibpart(rcm_handle_t *hd, char *rsrc)
1203*1cfa752fSRamaswamy Tummala {
1204*1cfa752fSRamaswamy Tummala 	link_cache_t *node;
1205*1cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
1206*1cfa752fSRamaswamy Tummala 	nvlist_t *nvl = NULL;
1207*1cfa752fSRamaswamy Tummala 	uint64_t id;
1208*1cfa752fSRamaswamy Tummala 	int ret = -1;
1209*1cfa752fSRamaswamy Tummala 
1210*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_notify_new_ibpart (%s)\n",
1211*1cfa752fSRamaswamy Tummala 	    rsrc);
1212*1cfa752fSRamaswamy Tummala 
1213*1cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
1214*1cfa752fSRamaswamy Tummala 	if ((node = cache_lookup(hd, rsrc, CACHE_REFRESH)) == NULL) {
1215*1cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
1216*1cfa752fSRamaswamy Tummala 		return (0);
1217*1cfa752fSRamaswamy Tummala 	}
1218*1cfa752fSRamaswamy Tummala 
1219*1cfa752fSRamaswamy Tummala 	if (nvlist_alloc(&nvl, 0, 0) != 0) {
1220*1cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
1221*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_WARNING,
1222*1cfa752fSRamaswamy Tummala 		    _("IBPART: failed to allocate nvlist\n"));
1223*1cfa752fSRamaswamy Tummala 		goto done;
1224*1cfa752fSRamaswamy Tummala 	}
1225*1cfa752fSRamaswamy Tummala 
1226*1cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
1227*1cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
1228*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE2, "IBPART: ibpart_notify_new_ibpart "
1229*1cfa752fSRamaswamy Tummala 		    "add (%u)\n", ibpart->dlib_ibpart_id);
1230*1cfa752fSRamaswamy Tummala 
1231*1cfa752fSRamaswamy Tummala 		id = ibpart->dlib_ibpart_id;
1232*1cfa752fSRamaswamy Tummala 		if (nvlist_add_uint64(nvl, RCM_NV_LINKID, id) != 0) {
1233*1cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR,
1234*1cfa752fSRamaswamy Tummala 			    _("IBPART: failed to construct nvlist\n"));
1235*1cfa752fSRamaswamy Tummala 			(void) mutex_unlock(&cache_lock);
1236*1cfa752fSRamaswamy Tummala 			goto done;
1237*1cfa752fSRamaswamy Tummala 		}
1238*1cfa752fSRamaswamy Tummala 	}
1239*1cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
1240*1cfa752fSRamaswamy Tummala 
1241*1cfa752fSRamaswamy Tummala 	if (rcm_notify_event(hd, RCM_RESOURCE_LINK_NEW, 0, nvl, NULL) !=
1242*1cfa752fSRamaswamy Tummala 	    RCM_SUCCESS) {
1243*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_ERROR,
1244*1cfa752fSRamaswamy Tummala 		    _("IBPART: failed to notify %s event for %s\n"),
1245*1cfa752fSRamaswamy Tummala 		    RCM_RESOURCE_LINK_NEW, node->pc_resource);
1246*1cfa752fSRamaswamy Tummala 		goto done;
1247*1cfa752fSRamaswamy Tummala 	}
1248*1cfa752fSRamaswamy Tummala 
1249*1cfa752fSRamaswamy Tummala 	ret = 0;
1250*1cfa752fSRamaswamy Tummala done:
1251*1cfa752fSRamaswamy Tummala 	nvlist_free(nvl);
1252*1cfa752fSRamaswamy Tummala 	return (ret);
1253*1cfa752fSRamaswamy Tummala }
1254*1cfa752fSRamaswamy Tummala 
1255*1cfa752fSRamaswamy Tummala /*
1256*1cfa752fSRamaswamy Tummala  * ibpart_consumer_notify() - Notify consumers of IBPARTs coming back online.
1257*1cfa752fSRamaswamy Tummala  */
1258*1cfa752fSRamaswamy Tummala static int
ibpart_consumer_notify(rcm_handle_t * hd,datalink_id_t linkid,char ** errorp,uint_t flags,rcm_info_t ** info)1259*1cfa752fSRamaswamy Tummala ibpart_consumer_notify(rcm_handle_t *hd, datalink_id_t linkid, char **errorp,
1260*1cfa752fSRamaswamy Tummala     uint_t flags, rcm_info_t **info)
1261*1cfa752fSRamaswamy Tummala {
1262*1cfa752fSRamaswamy Tummala 	char rsrc[RCM_LINK_RESOURCE_MAX];
1263*1cfa752fSRamaswamy Tummala 	link_cache_t *node;
1264*1cfa752fSRamaswamy Tummala 
1265*1cfa752fSRamaswamy Tummala 	/* Check for the interface in the cache */
1266*1cfa752fSRamaswamy Tummala 	(void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u", RCM_LINK_PREFIX,
1267*1cfa752fSRamaswamy Tummala 	    linkid);
1268*1cfa752fSRamaswamy Tummala 
1269*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_notify(%s)\n",
1270*1cfa752fSRamaswamy Tummala 	    rsrc);
1271*1cfa752fSRamaswamy Tummala 
1272*1cfa752fSRamaswamy Tummala 	/*
1273*1cfa752fSRamaswamy Tummala 	 * Inform IP consumers of the new link.
1274*1cfa752fSRamaswamy Tummala 	 */
1275*1cfa752fSRamaswamy Tummala 	if (ibpart_notify_new_ibpart(hd, rsrc) != 0) {
1276*1cfa752fSRamaswamy Tummala 		(void) mutex_lock(&cache_lock);
1277*1cfa752fSRamaswamy Tummala 		if ((node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH)) != NULL) {
1278*1cfa752fSRamaswamy Tummala 			(void) ibpart_offline_ibpart(node, IBPART_STALE,
1279*1cfa752fSRamaswamy Tummala 			    CACHE_NODE_STALE);
1280*1cfa752fSRamaswamy Tummala 		}
1281*1cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
1282*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE2,
1283*1cfa752fSRamaswamy Tummala 		    "IBPART: ibpart_notify_new_ibpart failed(%s)\n", rsrc);
1284*1cfa752fSRamaswamy Tummala 		return (-1);
1285*1cfa752fSRamaswamy Tummala 	}
1286*1cfa752fSRamaswamy Tummala 
1287*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_notify "
1288*1cfa752fSRamaswamy Tummala 	    "succeeded\n");
1289*1cfa752fSRamaswamy Tummala 	return (0);
1290*1cfa752fSRamaswamy Tummala }
1291*1cfa752fSRamaswamy Tummala 
1292*1cfa752fSRamaswamy Tummala typedef struct ibpart_up_arg_s {
1293*1cfa752fSRamaswamy Tummala 	datalink_id_t	linkid;
1294*1cfa752fSRamaswamy Tummala 	int		retval;
1295*1cfa752fSRamaswamy Tummala } ibpart_up_arg_t;
1296*1cfa752fSRamaswamy Tummala 
1297*1cfa752fSRamaswamy Tummala static int
ibpart_up(dladm_handle_t handle,datalink_id_t ibpartid,void * arg)1298*1cfa752fSRamaswamy Tummala ibpart_up(dladm_handle_t handle, datalink_id_t ibpartid, void *arg)
1299*1cfa752fSRamaswamy Tummala {
1300*1cfa752fSRamaswamy Tummala 	ibpart_up_arg_t *ibpart_up_argp = arg;
1301*1cfa752fSRamaswamy Tummala 	dladm_status_t status;
1302*1cfa752fSRamaswamy Tummala 	dladm_ib_attr_t ibpart_attr;
1303*1cfa752fSRamaswamy Tummala 	char errmsg[DLADM_STRSIZE];
1304*1cfa752fSRamaswamy Tummala 
1305*1cfa752fSRamaswamy Tummala 	status = dladm_part_info(handle, ibpartid, &ibpart_attr,
1306*1cfa752fSRamaswamy Tummala 	    DLADM_OPT_PERSIST);
1307*1cfa752fSRamaswamy Tummala 	if (status != DLADM_STATUS_OK) {
1308*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE1,
1309*1cfa752fSRamaswamy Tummala 		    "IBPART: ibpart_up(): cannot get information for IBPART %u "
1310*1cfa752fSRamaswamy Tummala 		    "(%s)\n", ibpartid, dladm_status2str(status, errmsg));
1311*1cfa752fSRamaswamy Tummala 		return (DLADM_WALK_CONTINUE);
1312*1cfa752fSRamaswamy Tummala 	}
1313*1cfa752fSRamaswamy Tummala 
1314*1cfa752fSRamaswamy Tummala 	if (ibpart_attr.dia_physlinkid != ibpart_up_argp->linkid)
1315*1cfa752fSRamaswamy Tummala 		return (DLADM_WALK_CONTINUE);
1316*1cfa752fSRamaswamy Tummala 
1317*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE3, "IBPART: ibpart_up(%u)\n", ibpartid);
1318*1cfa752fSRamaswamy Tummala 	if ((status = dladm_part_up(handle, ibpartid, 0)) == DLADM_STATUS_OK)
1319*1cfa752fSRamaswamy Tummala 		return (DLADM_WALK_CONTINUE);
1320*1cfa752fSRamaswamy Tummala 
1321*1cfa752fSRamaswamy Tummala 	/*
1322*1cfa752fSRamaswamy Tummala 	 * Prompt the warning message and continue to UP other IBPARTs.
1323*1cfa752fSRamaswamy Tummala 	 */
1324*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_WARNING,
1325*1cfa752fSRamaswamy Tummala 	    _("IBPART: IBPART up failed (%u): %s\n"),
1326*1cfa752fSRamaswamy Tummala 	    ibpartid, dladm_status2str(status, errmsg));
1327*1cfa752fSRamaswamy Tummala 
1328*1cfa752fSRamaswamy Tummala 	ibpart_up_argp->retval = -1;
1329*1cfa752fSRamaswamy Tummala 	return (DLADM_WALK_CONTINUE);
1330*1cfa752fSRamaswamy Tummala }
1331*1cfa752fSRamaswamy Tummala 
1332*1cfa752fSRamaswamy Tummala /*
1333*1cfa752fSRamaswamy Tummala  * ibpart_configure() - Configure IBPARTs over a physical link after it attaches
1334*1cfa752fSRamaswamy Tummala  */
1335*1cfa752fSRamaswamy Tummala static int
ibpart_configure(rcm_handle_t * hd,datalink_id_t linkid)1336*1cfa752fSRamaswamy Tummala ibpart_configure(rcm_handle_t *hd, datalink_id_t linkid)
1337*1cfa752fSRamaswamy Tummala {
1338*1cfa752fSRamaswamy Tummala 	char rsrc[RCM_LINK_RESOURCE_MAX];
1339*1cfa752fSRamaswamy Tummala 	link_cache_t *node;
1340*1cfa752fSRamaswamy Tummala 	ibpart_up_arg_t arg = {DATALINK_INVALID_LINKID, 0};
1341*1cfa752fSRamaswamy Tummala 
1342*1cfa752fSRamaswamy Tummala 	/* Check for the IBPARTs in the cache */
1343*1cfa752fSRamaswamy Tummala 	(void) snprintf(rsrc, sizeof (rsrc), "%s/%u", RCM_LINK_PREFIX, linkid);
1344*1cfa752fSRamaswamy Tummala 
1345*1cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_configure(%s)\n", rsrc);
1346*1cfa752fSRamaswamy Tummala 
1347*1cfa752fSRamaswamy Tummala 	/* Check if the link is new or was previously offlined */
1348*1cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
1349*1cfa752fSRamaswamy Tummala 	if (((node = cache_lookup(hd, rsrc, CACHE_REFRESH)) != NULL) &&
1350*1cfa752fSRamaswamy Tummala 	    (!(node->pc_state & CACHE_NODE_OFFLINED))) {
1351*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE2,
1352*1cfa752fSRamaswamy Tummala 		    "IBPART: Skipping configured interface(%s)\n", rsrc);
1353*1cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
1354*1cfa752fSRamaswamy Tummala 		return (0);
1355*1cfa752fSRamaswamy Tummala 	}
1356*1cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
1357*1cfa752fSRamaswamy Tummala 
1358*1cfa752fSRamaswamy Tummala 	arg.linkid = linkid;
1359*1cfa752fSRamaswamy Tummala 	(void) dladm_walk_datalink_id(ibpart_up, dld_handle, &arg,
1360*1cfa752fSRamaswamy Tummala 	    DATALINK_CLASS_PART, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
1361*1cfa752fSRamaswamy Tummala 
1362*1cfa752fSRamaswamy Tummala 	if (arg.retval == 0) {
1363*1cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE2,
1364*1cfa752fSRamaswamy Tummala 		    "IBPART: ibpart_configure succeeded(%s)\n", rsrc);
1365*1cfa752fSRamaswamy Tummala 	}
1366*1cfa752fSRamaswamy Tummala 	return (arg.retval);
1367*1cfa752fSRamaswamy Tummala }
1368