11cfa752fSRamaswamy Tummala /*
21cfa752fSRamaswamy Tummala  * CDDL HEADER START
31cfa752fSRamaswamy Tummala  *
41cfa752fSRamaswamy Tummala  * The contents of this file are subject to the terms of the
51cfa752fSRamaswamy Tummala  * Common Development and Distribution License (the "License").
61cfa752fSRamaswamy Tummala  * You may not use this file except in compliance with the License.
71cfa752fSRamaswamy Tummala  *
81cfa752fSRamaswamy Tummala  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91cfa752fSRamaswamy Tummala  * or http://www.opensolaris.org/os/licensing.
101cfa752fSRamaswamy Tummala  * See the License for the specific language governing permissions
111cfa752fSRamaswamy Tummala  * and limitations under the License.
121cfa752fSRamaswamy Tummala  *
131cfa752fSRamaswamy Tummala  * When distributing Covered Code, include this CDDL HEADER in each
141cfa752fSRamaswamy Tummala  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151cfa752fSRamaswamy Tummala  * If applicable, add the following below this CDDL HEADER, with the
161cfa752fSRamaswamy Tummala  * fields enclosed by brackets "[]" replaced with your own identifying
171cfa752fSRamaswamy Tummala  * information: Portions Copyright [yyyy] [name of copyright owner]
181cfa752fSRamaswamy Tummala  *
191cfa752fSRamaswamy Tummala  * CDDL HEADER END
201cfa752fSRamaswamy Tummala  */
211cfa752fSRamaswamy Tummala /*
221cfa752fSRamaswamy Tummala  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
231cfa752fSRamaswamy Tummala  */
241cfa752fSRamaswamy Tummala 
251cfa752fSRamaswamy Tummala /*
261cfa752fSRamaswamy Tummala  * This RCM module adds support to the RCM framework for IBPART links
271cfa752fSRamaswamy Tummala  */
281cfa752fSRamaswamy Tummala 
291cfa752fSRamaswamy Tummala #include <stdio.h>
301cfa752fSRamaswamy Tummala #include <stdlib.h>
311cfa752fSRamaswamy Tummala #include <string.h>
321cfa752fSRamaswamy Tummala #include <errno.h>
331cfa752fSRamaswamy Tummala #include <sys/types.h>
341cfa752fSRamaswamy Tummala #include <synch.h>
351cfa752fSRamaswamy Tummala #include <assert.h>
361cfa752fSRamaswamy Tummala #include <strings.h>
371cfa752fSRamaswamy Tummala #include "rcm_module.h"
381cfa752fSRamaswamy Tummala #include <libintl.h>
391cfa752fSRamaswamy Tummala #include <libdllink.h>
401cfa752fSRamaswamy Tummala #include <libdlib.h>
411cfa752fSRamaswamy Tummala #include <libdlpi.h>
421cfa752fSRamaswamy Tummala 
431cfa752fSRamaswamy Tummala /*
441cfa752fSRamaswamy Tummala  * Definitions
451cfa752fSRamaswamy Tummala  */
461cfa752fSRamaswamy Tummala #ifndef lint
471cfa752fSRamaswamy Tummala #define	_(x)	gettext(x)
481cfa752fSRamaswamy Tummala #else
491cfa752fSRamaswamy Tummala #define	_(x)	x
501cfa752fSRamaswamy Tummala #endif
511cfa752fSRamaswamy Tummala 
521cfa752fSRamaswamy Tummala /* Some generic well-knowns and defaults used in this module */
531cfa752fSRamaswamy Tummala #define	RCM_LINK_PREFIX		"SUNW_datalink"	/* RCM datalink name prefix */
541cfa752fSRamaswamy Tummala #define	RCM_LINK_RESOURCE_MAX	(13 + LINKID_STR_WIDTH)
551cfa752fSRamaswamy Tummala 
561cfa752fSRamaswamy Tummala /* IBPART link flags */
571cfa752fSRamaswamy Tummala typedef enum {
581cfa752fSRamaswamy Tummala 	IBPART_OFFLINED			= 0x1,
591cfa752fSRamaswamy Tummala 	IBPART_CONSUMER_OFFLINED	= 0x2,
601cfa752fSRamaswamy Tummala 	IBPART_STALE			= 0x4
611cfa752fSRamaswamy Tummala } ibpart_flag_t;
621cfa752fSRamaswamy Tummala 
631cfa752fSRamaswamy Tummala /* link representation */
641cfa752fSRamaswamy Tummala typedef struct dl_ibpart {
651cfa752fSRamaswamy Tummala 	struct dl_ibpart	*dlib_next;	/* next IBPART on this link */
661cfa752fSRamaswamy Tummala 	struct dl_ibpart	*dlib_prev;	/* prev IBPART on this link */
671cfa752fSRamaswamy Tummala 	datalink_id_t	dlib_ibpart_id;
681cfa752fSRamaswamy Tummala 	ibpart_flag_t	dlib_flags;		/* IBPART link flags */
691cfa752fSRamaswamy Tummala } dl_ibpart_t;
701cfa752fSRamaswamy Tummala 
711cfa752fSRamaswamy Tummala /* IBPART Cache state flags */
721cfa752fSRamaswamy Tummala typedef enum {
731cfa752fSRamaswamy Tummala 	CACHE_NODE_STALE	= 0x1,		/* stale cached data */
741cfa752fSRamaswamy Tummala 	CACHE_NODE_NEW		= 0x2,		/* new cached nodes */
751cfa752fSRamaswamy Tummala 	CACHE_NODE_OFFLINED	= 0x4		/* nodes offlined */
761cfa752fSRamaswamy Tummala } cache_node_state_t;
771cfa752fSRamaswamy Tummala 
781cfa752fSRamaswamy Tummala /* Network Cache lookup options */
791cfa752fSRamaswamy Tummala #define	CACHE_NO_REFRESH	0x1		/* cache refresh not needed */
801cfa752fSRamaswamy Tummala #define	CACHE_REFRESH		0x2		/* refresh cache */
811cfa752fSRamaswamy Tummala 
821cfa752fSRamaswamy Tummala /* Cache element */
831cfa752fSRamaswamy Tummala typedef struct link_cache {
841cfa752fSRamaswamy Tummala 	struct link_cache	*pc_next;	/* next cached resource */
851cfa752fSRamaswamy Tummala 	struct link_cache	*pc_prev;	/* prev cached resource */
861cfa752fSRamaswamy Tummala 	char			*pc_resource;	/* resource name */
871cfa752fSRamaswamy Tummala 	datalink_id_t		pc_linkid;	/* linkid */
881cfa752fSRamaswamy Tummala 	dl_ibpart_t		*pc_ibpart;	/* IBPART list on this link */
891cfa752fSRamaswamy Tummala 	cache_node_state_t	pc_state;	/* cache state flags */
901cfa752fSRamaswamy Tummala } link_cache_t;
911cfa752fSRamaswamy Tummala 
921cfa752fSRamaswamy Tummala /*
931cfa752fSRamaswamy Tummala  * Global cache for network IBPARTs
941cfa752fSRamaswamy Tummala  */
951cfa752fSRamaswamy Tummala static link_cache_t	cache_head;
961cfa752fSRamaswamy Tummala static link_cache_t	cache_tail;
971cfa752fSRamaswamy Tummala static mutex_t		cache_lock;
981cfa752fSRamaswamy Tummala static int		events_registered = 0;
991cfa752fSRamaswamy Tummala 
1001cfa752fSRamaswamy Tummala static dladm_handle_t	dld_handle = NULL;
1011cfa752fSRamaswamy Tummala 
1021cfa752fSRamaswamy Tummala /*
1031cfa752fSRamaswamy Tummala  * RCM module interface prototypes
1041cfa752fSRamaswamy Tummala  */
1051cfa752fSRamaswamy Tummala static int		ibpart_register(rcm_handle_t *);
1061cfa752fSRamaswamy Tummala static int		ibpart_unregister(rcm_handle_t *);
1071cfa752fSRamaswamy Tummala static int		ibpart_get_info(rcm_handle_t *, char *, id_t, uint_t,
1081cfa752fSRamaswamy Tummala 			    char **, char **, nvlist_t *, rcm_info_t **);
1091cfa752fSRamaswamy Tummala static int		ibpart_suspend(rcm_handle_t *, char *, id_t,
1101cfa752fSRamaswamy Tummala 			    timespec_t *, uint_t, char **, rcm_info_t **);
1111cfa752fSRamaswamy Tummala static int		ibpart_resume(rcm_handle_t *, char *, id_t, uint_t,
1121cfa752fSRamaswamy Tummala 			    char **, rcm_info_t **);
1131cfa752fSRamaswamy Tummala static int		ibpart_offline(rcm_handle_t *, char *, id_t, uint_t,
1141cfa752fSRamaswamy Tummala 			    char **, rcm_info_t **);
1151cfa752fSRamaswamy Tummala static int		ibpart_undo_offline(rcm_handle_t *, char *, id_t,
1161cfa752fSRamaswamy Tummala 			    uint_t, char **, rcm_info_t **);
1171cfa752fSRamaswamy Tummala static int		ibpart_remove(rcm_handle_t *, char *, id_t, uint_t,
1181cfa752fSRamaswamy Tummala 			    char **, rcm_info_t **);
1191cfa752fSRamaswamy Tummala static int		ibpart_notify_event(rcm_handle_t *, char *, id_t,
1201cfa752fSRamaswamy Tummala 			    uint_t, char **, nvlist_t *, rcm_info_t **);
1211cfa752fSRamaswamy Tummala static int		ibpart_configure(rcm_handle_t *, datalink_id_t);
1221cfa752fSRamaswamy Tummala 
1231cfa752fSRamaswamy Tummala /* Module private routines */
1241cfa752fSRamaswamy Tummala static void 		cache_free();
1251cfa752fSRamaswamy Tummala static int 		cache_update(rcm_handle_t *);
1261cfa752fSRamaswamy Tummala static void 		cache_remove(link_cache_t *);
1271cfa752fSRamaswamy Tummala static void 		node_free(link_cache_t *);
1281cfa752fSRamaswamy Tummala static void 		cache_insert(link_cache_t *);
1291cfa752fSRamaswamy Tummala static link_cache_t	*cache_lookup(rcm_handle_t *, char *, char);
1301cfa752fSRamaswamy Tummala static int		ibpart_consumer_offline(rcm_handle_t *, link_cache_t *,
1311cfa752fSRamaswamy Tummala 			    char **, uint_t, rcm_info_t **);
1321cfa752fSRamaswamy Tummala static void		ibpart_consumer_online(rcm_handle_t *, link_cache_t *,
1331cfa752fSRamaswamy Tummala 			    char **, uint_t, rcm_info_t **);
1341cfa752fSRamaswamy Tummala static int		ibpart_offline_ibpart(link_cache_t *, uint32_t,
1351cfa752fSRamaswamy Tummala 			    cache_node_state_t);
1361cfa752fSRamaswamy Tummala static void		ibpart_online_ibpart(link_cache_t *);
1371cfa752fSRamaswamy Tummala static char 		*ibpart_usage(link_cache_t *);
1381cfa752fSRamaswamy Tummala static void 		ibpart_log_err(datalink_id_t, char **, char *);
1391cfa752fSRamaswamy Tummala static int		ibpart_consumer_notify(rcm_handle_t *, datalink_id_t,
1401cfa752fSRamaswamy Tummala 			    char **, uint_t, rcm_info_t **);
1411cfa752fSRamaswamy Tummala 
1421cfa752fSRamaswamy Tummala /* Module-Private data */
1431cfa752fSRamaswamy Tummala static struct rcm_mod_ops ibpart_ops =
1441cfa752fSRamaswamy Tummala {
1451cfa752fSRamaswamy Tummala 	RCM_MOD_OPS_VERSION,
1461cfa752fSRamaswamy Tummala 	ibpart_register,
1471cfa752fSRamaswamy Tummala 	ibpart_unregister,
1481cfa752fSRamaswamy Tummala 	ibpart_get_info,
1491cfa752fSRamaswamy Tummala 	ibpart_suspend,
1501cfa752fSRamaswamy Tummala 	ibpart_resume,
1511cfa752fSRamaswamy Tummala 	ibpart_offline,
1521cfa752fSRamaswamy Tummala 	ibpart_undo_offline,
1531cfa752fSRamaswamy Tummala 	ibpart_remove,
1541cfa752fSRamaswamy Tummala 	NULL,
1551cfa752fSRamaswamy Tummala 	NULL,
1561cfa752fSRamaswamy Tummala 	ibpart_notify_event
1571cfa752fSRamaswamy Tummala };
1581cfa752fSRamaswamy Tummala 
1591cfa752fSRamaswamy Tummala /*
1601cfa752fSRamaswamy Tummala  * rcm_mod_init() - Update registrations, and return the ops structure.
1611cfa752fSRamaswamy Tummala  */
1621cfa752fSRamaswamy Tummala struct rcm_mod_ops *
rcm_mod_init(void)1631cfa752fSRamaswamy Tummala rcm_mod_init(void)
1641cfa752fSRamaswamy Tummala {
1651cfa752fSRamaswamy Tummala 	char errmsg[DLADM_STRSIZE];
1661cfa752fSRamaswamy Tummala 	dladm_status_t status;
1671cfa752fSRamaswamy Tummala 
1681cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: mod_init\n");
1691cfa752fSRamaswamy Tummala 
1701cfa752fSRamaswamy Tummala 	cache_head.pc_next = &cache_tail;
1711cfa752fSRamaswamy Tummala 	cache_head.pc_prev = NULL;
1721cfa752fSRamaswamy Tummala 	cache_tail.pc_prev = &cache_head;
1731cfa752fSRamaswamy Tummala 	cache_tail.pc_next = NULL;
1741cfa752fSRamaswamy Tummala 	(void) mutex_init(&cache_lock, 0, NULL);
1751cfa752fSRamaswamy Tummala 
1761cfa752fSRamaswamy Tummala 	if ((status = dladm_open(&dld_handle)) != DLADM_STATUS_OK) {
1771cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_WARNING,
1781cfa752fSRamaswamy Tummala 		    "IBPART: mod_init failed: cannot open datalink "
1791cfa752fSRamaswamy Tummala 		    "handle: %s\n", dladm_status2str(status, errmsg));
1801cfa752fSRamaswamy Tummala 		return (NULL);
1811cfa752fSRamaswamy Tummala 	}
1821cfa752fSRamaswamy Tummala 
1831cfa752fSRamaswamy Tummala 	/* Return the ops vectors */
1841cfa752fSRamaswamy Tummala 	return (&ibpart_ops);
1851cfa752fSRamaswamy Tummala }
1861cfa752fSRamaswamy Tummala 
1871cfa752fSRamaswamy Tummala /*
1881cfa752fSRamaswamy Tummala  * rcm_mod_info() - Return a string describing this module.
1891cfa752fSRamaswamy Tummala  */
1901cfa752fSRamaswamy Tummala const char *
rcm_mod_info(void)1911cfa752fSRamaswamy Tummala rcm_mod_info(void)
1921cfa752fSRamaswamy Tummala {
1931cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: mod_info\n");
1941cfa752fSRamaswamy Tummala 
1951cfa752fSRamaswamy Tummala 	return ("IBPART module");
1961cfa752fSRamaswamy Tummala }
1971cfa752fSRamaswamy Tummala 
1981cfa752fSRamaswamy Tummala /*
1991cfa752fSRamaswamy Tummala  * rcm_mod_fini() - Destroy the network IBPART cache.
2001cfa752fSRamaswamy Tummala  */
2011cfa752fSRamaswamy Tummala int
rcm_mod_fini(void)2021cfa752fSRamaswamy Tummala rcm_mod_fini(void)
2031cfa752fSRamaswamy Tummala {
2041cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: mod_fini\n");
2051cfa752fSRamaswamy Tummala 
2061cfa752fSRamaswamy Tummala 	/*
2071cfa752fSRamaswamy Tummala 	 * Note that ibpart_unregister() does not seem to be called anywhere,
2081cfa752fSRamaswamy Tummala 	 * therefore we free the cache nodes here. In theory we should call
2091cfa752fSRamaswamy Tummala 	 * rcm_register_interest() for each node before we free it, the
2101cfa752fSRamaswamy Tummala 	 * framework does not provide the rcm_handle to allow us to do so.
2111cfa752fSRamaswamy Tummala 	 */
2121cfa752fSRamaswamy Tummala 	cache_free();
2131cfa752fSRamaswamy Tummala 	(void) mutex_destroy(&cache_lock);
2141cfa752fSRamaswamy Tummala 
2151cfa752fSRamaswamy Tummala 	dladm_close(dld_handle);
2161cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
2171cfa752fSRamaswamy Tummala }
2181cfa752fSRamaswamy Tummala 
2191cfa752fSRamaswamy Tummala /*
2201cfa752fSRamaswamy Tummala  * ibpart_register() - Make sure the cache is properly sync'ed, and its
2211cfa752fSRamaswamy Tummala  *		 registrations are in order.
2221cfa752fSRamaswamy Tummala  */
2231cfa752fSRamaswamy Tummala static int
ibpart_register(rcm_handle_t * hd)2241cfa752fSRamaswamy Tummala ibpart_register(rcm_handle_t *hd)
2251cfa752fSRamaswamy Tummala {
2261cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: register\n");
2271cfa752fSRamaswamy Tummala 
2281cfa752fSRamaswamy Tummala 	if (cache_update(hd) < 0)
2291cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
2301cfa752fSRamaswamy Tummala 
2311cfa752fSRamaswamy Tummala 	/*
2321cfa752fSRamaswamy Tummala 	 * Need to register interest in all new resources
2331cfa752fSRamaswamy Tummala 	 * getting attached, so we get attach event notifications
2341cfa752fSRamaswamy Tummala 	 */
2351cfa752fSRamaswamy Tummala 	if (!events_registered) {
2361cfa752fSRamaswamy Tummala 		if (rcm_register_event(hd, RCM_RESOURCE_LINK_NEW, 0, NULL)
2371cfa752fSRamaswamy Tummala 		    != RCM_SUCCESS) {
2381cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR,
2391cfa752fSRamaswamy Tummala 			    _("IBPART: failed to register %s\n"),
2401cfa752fSRamaswamy Tummala 			    RCM_RESOURCE_LINK_NEW);
2411cfa752fSRamaswamy Tummala 			return (RCM_FAILURE);
2421cfa752fSRamaswamy Tummala 		} else {
2431cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_DEBUG, "IBPART: registered %s\n",
2441cfa752fSRamaswamy Tummala 			    RCM_RESOURCE_LINK_NEW);
2451cfa752fSRamaswamy Tummala 			events_registered++;
2461cfa752fSRamaswamy Tummala 		}
2471cfa752fSRamaswamy Tummala 	}
2481cfa752fSRamaswamy Tummala 
2491cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
2501cfa752fSRamaswamy Tummala }
2511cfa752fSRamaswamy Tummala 
2521cfa752fSRamaswamy Tummala /*
2531cfa752fSRamaswamy Tummala  * ibpart_unregister() - Walk the cache, unregistering all the networks.
2541cfa752fSRamaswamy Tummala  */
2551cfa752fSRamaswamy Tummala static int
ibpart_unregister(rcm_handle_t * hd)2561cfa752fSRamaswamy Tummala ibpart_unregister(rcm_handle_t *hd)
2571cfa752fSRamaswamy Tummala {
2581cfa752fSRamaswamy Tummala 	link_cache_t *node;
2591cfa752fSRamaswamy Tummala 
2601cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: unregister\n");
2611cfa752fSRamaswamy Tummala 
2621cfa752fSRamaswamy Tummala 	/* Walk the cache, unregistering everything */
2631cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
2641cfa752fSRamaswamy Tummala 	node = cache_head.pc_next;
2651cfa752fSRamaswamy Tummala 	while (node != &cache_tail) {
2661cfa752fSRamaswamy Tummala 		if (rcm_unregister_interest(hd, node->pc_resource, 0)
2671cfa752fSRamaswamy Tummala 		    != RCM_SUCCESS) {
2681cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR,
2691cfa752fSRamaswamy Tummala 			    _("IBPART: failed to unregister %s\n"),
2701cfa752fSRamaswamy Tummala 			    node->pc_resource);
2711cfa752fSRamaswamy Tummala 			(void) mutex_unlock(&cache_lock);
2721cfa752fSRamaswamy Tummala 			return (RCM_FAILURE);
2731cfa752fSRamaswamy Tummala 		}
2741cfa752fSRamaswamy Tummala 		cache_remove(node);
2751cfa752fSRamaswamy Tummala 		node_free(node);
2761cfa752fSRamaswamy Tummala 		node = cache_head.pc_next;
2771cfa752fSRamaswamy Tummala 	}
2781cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
2791cfa752fSRamaswamy Tummala 
2801cfa752fSRamaswamy Tummala 	/*
2811cfa752fSRamaswamy Tummala 	 * Unregister interest in all new resources
2821cfa752fSRamaswamy Tummala 	 */
2831cfa752fSRamaswamy Tummala 	if (events_registered) {
2841cfa752fSRamaswamy Tummala 		if (rcm_unregister_event(hd, RCM_RESOURCE_LINK_NEW, 0)
2851cfa752fSRamaswamy Tummala 		    != RCM_SUCCESS) {
2861cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR,
2871cfa752fSRamaswamy Tummala 			    _("IBPART: failed to unregister %s\n"),
2881cfa752fSRamaswamy Tummala 			    RCM_RESOURCE_LINK_NEW);
2891cfa752fSRamaswamy Tummala 			return (RCM_FAILURE);
2901cfa752fSRamaswamy Tummala 		} else {
2911cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_DEBUG, "IBPART: unregistered %s\n",
2921cfa752fSRamaswamy Tummala 			    RCM_RESOURCE_LINK_NEW);
2931cfa752fSRamaswamy Tummala 			events_registered--;
2941cfa752fSRamaswamy Tummala 		}
2951cfa752fSRamaswamy Tummala 	}
2961cfa752fSRamaswamy Tummala 
2971cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
2981cfa752fSRamaswamy Tummala }
2991cfa752fSRamaswamy Tummala 
3001cfa752fSRamaswamy Tummala /*
3011cfa752fSRamaswamy Tummala  * ibpart_offline() - Offline IBPARTs on a specific node.
3021cfa752fSRamaswamy Tummala  */
3031cfa752fSRamaswamy Tummala static int
ibpart_offline(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)3041cfa752fSRamaswamy Tummala ibpart_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
3051cfa752fSRamaswamy Tummala     char **errorp, rcm_info_t **info)
3061cfa752fSRamaswamy Tummala {
3071cfa752fSRamaswamy Tummala 	link_cache_t *node;
3081cfa752fSRamaswamy Tummala 
3091cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: offline(%s)\n", rsrc);
3101cfa752fSRamaswamy Tummala 
3111cfa752fSRamaswamy Tummala 	/* Lock the cache and lookup the resource */
3121cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
3131cfa752fSRamaswamy Tummala 	node = cache_lookup(hd, rsrc, CACHE_REFRESH);
3141cfa752fSRamaswamy Tummala 	if (node == NULL) {
3151cfa752fSRamaswamy Tummala 		/* should not happen because the resource is registered. */
3161cfa752fSRamaswamy Tummala 		ibpart_log_err(node->pc_linkid, errorp,
3171cfa752fSRamaswamy Tummala 		    "unrecognized resource");
3181cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
3191cfa752fSRamaswamy Tummala 		return (RCM_SUCCESS);
3201cfa752fSRamaswamy Tummala 	}
3211cfa752fSRamaswamy Tummala 
3221cfa752fSRamaswamy Tummala 	/*
3231cfa752fSRamaswamy Tummala 	 * Inform consumers (IP interfaces) of associated IBPARTs to be offlined
3241cfa752fSRamaswamy Tummala 	 */
3251cfa752fSRamaswamy Tummala 	if (ibpart_consumer_offline(hd, node, errorp, flags, info) ==
3261cfa752fSRamaswamy Tummala 	    RCM_SUCCESS) {
3271cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_DEBUG,
3281cfa752fSRamaswamy Tummala 		    "IBPART: consumers agreed on offline\n");
3291cfa752fSRamaswamy Tummala 	} else {
3301cfa752fSRamaswamy Tummala 		ibpart_log_err(node->pc_linkid, errorp,
3311cfa752fSRamaswamy Tummala 		    "consumers failed to offline");
3321cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
3331cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
3341cfa752fSRamaswamy Tummala 	}
3351cfa752fSRamaswamy Tummala 
3361cfa752fSRamaswamy Tummala 	/* Check if it's a query */
3371cfa752fSRamaswamy Tummala 	if (flags & RCM_QUERY) {
3381cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE1,
3391cfa752fSRamaswamy Tummala 		    "IBPART: offline query succeeded(%s)\n", rsrc);
3401cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
3411cfa752fSRamaswamy Tummala 		return (RCM_SUCCESS);
3421cfa752fSRamaswamy Tummala 	}
3431cfa752fSRamaswamy Tummala 
3441cfa752fSRamaswamy Tummala 	if (ibpart_offline_ibpart(node, IBPART_OFFLINED, CACHE_NODE_OFFLINED) !=
3451cfa752fSRamaswamy Tummala 	    RCM_SUCCESS) {
3461cfa752fSRamaswamy Tummala 		ibpart_online_ibpart(node);
3471cfa752fSRamaswamy Tummala 		ibpart_log_err(node->pc_linkid, errorp, "offline failed");
3481cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
3491cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
3501cfa752fSRamaswamy Tummala 	}
3511cfa752fSRamaswamy Tummala 
3521cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: Offline succeeded(%s)\n", rsrc);
3531cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
3541cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
3551cfa752fSRamaswamy Tummala }
3561cfa752fSRamaswamy Tummala 
3571cfa752fSRamaswamy Tummala /*
3581cfa752fSRamaswamy Tummala  * ibpart_undo_offline() - Undo offline of a previously offlined node.
3591cfa752fSRamaswamy Tummala  */
3601cfa752fSRamaswamy Tummala /*ARGSUSED*/
3611cfa752fSRamaswamy Tummala static int
ibpart_undo_offline(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)3621cfa752fSRamaswamy Tummala ibpart_undo_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
3631cfa752fSRamaswamy Tummala     char **errorp, rcm_info_t **info)
3641cfa752fSRamaswamy Tummala {
3651cfa752fSRamaswamy Tummala 	link_cache_t *node;
3661cfa752fSRamaswamy Tummala 
3671cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: online(%s)\n", rsrc);
3681cfa752fSRamaswamy Tummala 
3691cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
3701cfa752fSRamaswamy Tummala 	node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
3711cfa752fSRamaswamy Tummala 	if (node == NULL) {
3721cfa752fSRamaswamy Tummala 		ibpart_log_err(DATALINK_INVALID_LINKID, errorp, "no such link");
3731cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
3741cfa752fSRamaswamy Tummala 		errno = ENOENT;
3751cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
3761cfa752fSRamaswamy Tummala 	}
3771cfa752fSRamaswamy Tummala 
3781cfa752fSRamaswamy Tummala 	/* Check if no attempt should be made to online the link here */
3791cfa752fSRamaswamy Tummala 	if (!(node->pc_state & CACHE_NODE_OFFLINED)) {
3801cfa752fSRamaswamy Tummala 		ibpart_log_err(node->pc_linkid, errorp, "link not offlined");
3811cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
3821cfa752fSRamaswamy Tummala 		errno = ENOTSUP;
3831cfa752fSRamaswamy Tummala 		return (RCM_SUCCESS);
3841cfa752fSRamaswamy Tummala 	}
3851cfa752fSRamaswamy Tummala 
3861cfa752fSRamaswamy Tummala 	ibpart_online_ibpart(node);
3871cfa752fSRamaswamy Tummala 
3881cfa752fSRamaswamy Tummala 	/*
3891cfa752fSRamaswamy Tummala 	 * Inform IP interfaces on associated IBPARTs to be onlined
3901cfa752fSRamaswamy Tummala 	 */
3911cfa752fSRamaswamy Tummala 	ibpart_consumer_online(hd, node, errorp, flags, info);
3921cfa752fSRamaswamy Tummala 
3931cfa752fSRamaswamy Tummala 	node->pc_state &= ~CACHE_NODE_OFFLINED;
3941cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: online succeeded(%s)\n", rsrc);
3951cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
3961cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
3971cfa752fSRamaswamy Tummala }
3981cfa752fSRamaswamy Tummala 
3991cfa752fSRamaswamy Tummala static void
ibpart_online_ibpart(link_cache_t * node)4001cfa752fSRamaswamy Tummala ibpart_online_ibpart(link_cache_t *node)
4011cfa752fSRamaswamy Tummala {
4021cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
4031cfa752fSRamaswamy Tummala 	dladm_status_t status;
4041cfa752fSRamaswamy Tummala 	char errmsg[DLADM_STRSIZE];
4051cfa752fSRamaswamy Tummala 
4061cfa752fSRamaswamy Tummala 	/*
4071cfa752fSRamaswamy Tummala 	 * Try to bring on all offlined IBPARTs
4081cfa752fSRamaswamy Tummala 	 */
4091cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
4101cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
4111cfa752fSRamaswamy Tummala 		if (!(ibpart->dlib_flags & IBPART_OFFLINED))
4121cfa752fSRamaswamy Tummala 			continue;
4131cfa752fSRamaswamy Tummala 
4141cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE1, "IBPART: online DLID %d\n",
4151cfa752fSRamaswamy Tummala 		    ibpart->dlib_ibpart_id);
4161cfa752fSRamaswamy Tummala 		if ((status = dladm_part_up(dld_handle,
4171cfa752fSRamaswamy Tummala 		    ibpart->dlib_ibpart_id, 0)) != DLADM_STATUS_OK) {
4181cfa752fSRamaswamy Tummala 			/*
4191cfa752fSRamaswamy Tummala 			 * Print a warning message and continue to online
4201cfa752fSRamaswamy Tummala 			 * other IBPARTs.
4211cfa752fSRamaswamy Tummala 			 */
4221cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_WARNING,
4231cfa752fSRamaswamy Tummala 			    _("IBPART: IBPART online failed (%u): %s\n"),
4241cfa752fSRamaswamy Tummala 			    ibpart->dlib_ibpart_id,
4251cfa752fSRamaswamy Tummala 			    dladm_status2str(status, errmsg));
4261cfa752fSRamaswamy Tummala 		} else {
4271cfa752fSRamaswamy Tummala 			ibpart->dlib_flags &= ~IBPART_OFFLINED;
4281cfa752fSRamaswamy Tummala 		}
4291cfa752fSRamaswamy Tummala 	}
4301cfa752fSRamaswamy Tummala }
4311cfa752fSRamaswamy Tummala 
4321cfa752fSRamaswamy Tummala static int
ibpart_offline_ibpart(link_cache_t * node,uint32_t flags,cache_node_state_t state)4331cfa752fSRamaswamy Tummala ibpart_offline_ibpart(link_cache_t *node, uint32_t flags,
4341cfa752fSRamaswamy Tummala     cache_node_state_t state)
4351cfa752fSRamaswamy Tummala {
4361cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
4371cfa752fSRamaswamy Tummala 	dladm_status_t status;
4381cfa752fSRamaswamy Tummala 	char errmsg[DLADM_STRSIZE];
4391cfa752fSRamaswamy Tummala 
4401cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_offline_ibpart "
4411cfa752fSRamaswamy Tummala 	    "(%s %u %u)\n", node->pc_resource, flags, state);
4421cfa752fSRamaswamy Tummala 
4431cfa752fSRamaswamy Tummala 	/*
4441cfa752fSRamaswamy Tummala 	 * Try to delete all explicit created IBPART
4451cfa752fSRamaswamy Tummala 	 */
4461cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
4471cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
4481cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE1, "IBPART: offline DLID %d\n",
4491cfa752fSRamaswamy Tummala 		    ibpart->dlib_ibpart_id);
4501cfa752fSRamaswamy Tummala 		if ((status = dladm_part_delete(dld_handle,
4511cfa752fSRamaswamy Tummala 		    ibpart->dlib_ibpart_id, DLADM_OPT_ACTIVE)) !=
4521cfa752fSRamaswamy Tummala 		    DLADM_STATUS_OK) {
4531cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_WARNING,
4541cfa752fSRamaswamy Tummala 			    _("IBPART: IBPART offline failed (%u): %s\n"),
4551cfa752fSRamaswamy Tummala 			    ibpart->dlib_ibpart_id,
4561cfa752fSRamaswamy Tummala 			    dladm_status2str(status, errmsg));
4571cfa752fSRamaswamy Tummala 			return (RCM_FAILURE);
4581cfa752fSRamaswamy Tummala 		} else {
4591cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_TRACE1,
4601cfa752fSRamaswamy Tummala 			    "IBPART: IBPART offline succeeded(%u)\n",
4611cfa752fSRamaswamy Tummala 			    ibpart->dlib_ibpart_id);
4621cfa752fSRamaswamy Tummala 			ibpart->dlib_flags |= flags;
4631cfa752fSRamaswamy Tummala 		}
4641cfa752fSRamaswamy Tummala 	}
4651cfa752fSRamaswamy Tummala 
4661cfa752fSRamaswamy Tummala 	node->pc_state |= state;
4671cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
4681cfa752fSRamaswamy Tummala }
4691cfa752fSRamaswamy Tummala 
4701cfa752fSRamaswamy Tummala /*
4711cfa752fSRamaswamy Tummala  * ibpart_get_info() - Gather usage information for this resource.
4721cfa752fSRamaswamy Tummala  */
4731cfa752fSRamaswamy Tummala /*ARGSUSED*/
4741cfa752fSRamaswamy 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)4751cfa752fSRamaswamy Tummala ibpart_get_info(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
4761cfa752fSRamaswamy Tummala     char **usagep, char **errorp, nvlist_t *props, rcm_info_t **info)
4771cfa752fSRamaswamy Tummala {
4781cfa752fSRamaswamy Tummala 	link_cache_t *node;
4791cfa752fSRamaswamy Tummala 
4801cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: get_info(%s)\n", rsrc);
4811cfa752fSRamaswamy Tummala 
4821cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
4831cfa752fSRamaswamy Tummala 	node = cache_lookup(hd, rsrc, CACHE_REFRESH);
4841cfa752fSRamaswamy Tummala 	if (node == NULL) {
4851cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_INFO,
4861cfa752fSRamaswamy Tummala 		    _("IBPART: get_info(%s) unrecognized resource\n"), rsrc);
4871cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
4881cfa752fSRamaswamy Tummala 		errno = ENOENT;
4891cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
4901cfa752fSRamaswamy Tummala 	}
4911cfa752fSRamaswamy Tummala 
4921cfa752fSRamaswamy Tummala 	*usagep = ibpart_usage(node);
4931cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
4941cfa752fSRamaswamy Tummala 	if (*usagep == NULL) {
4951cfa752fSRamaswamy Tummala 		/* most likely malloc failure */
4961cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_ERROR,
4971cfa752fSRamaswamy Tummala 		    _("IBPART: get_info(%s) malloc failure\n"), rsrc);
4981cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
4991cfa752fSRamaswamy Tummala 		errno = ENOMEM;
5001cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
5011cfa752fSRamaswamy Tummala 	}
5021cfa752fSRamaswamy Tummala 
5031cfa752fSRamaswamy Tummala 	/* Set client/role properties */
5041cfa752fSRamaswamy Tummala 	(void) nvlist_add_string(props, RCM_CLIENT_NAME, "IBPART");
5051cfa752fSRamaswamy Tummala 
5061cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: get_info(%s) info = %s\n",
5071cfa752fSRamaswamy Tummala 	    rsrc, *usagep);
5081cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
5091cfa752fSRamaswamy Tummala }
5101cfa752fSRamaswamy Tummala 
5111cfa752fSRamaswamy Tummala /*
5121cfa752fSRamaswamy Tummala  * ibpart_suspend() - Nothing to do, always okay
5131cfa752fSRamaswamy Tummala  */
5141cfa752fSRamaswamy Tummala /*ARGSUSED*/
5151cfa752fSRamaswamy 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)5161cfa752fSRamaswamy Tummala ibpart_suspend(rcm_handle_t *hd, char *rsrc, id_t id, timespec_t *interval,
5171cfa752fSRamaswamy Tummala     uint_t flags, char **errorp, rcm_info_t **info)
5181cfa752fSRamaswamy Tummala {
5191cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: suspend(%s)\n", rsrc);
5201cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
5211cfa752fSRamaswamy Tummala }
5221cfa752fSRamaswamy Tummala 
5231cfa752fSRamaswamy Tummala /*
5241cfa752fSRamaswamy Tummala  * ibpart_resume() - Nothing to do, always okay
5251cfa752fSRamaswamy Tummala  */
5261cfa752fSRamaswamy Tummala /*ARGSUSED*/
5271cfa752fSRamaswamy Tummala static int
ibpart_resume(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)5281cfa752fSRamaswamy Tummala ibpart_resume(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
5291cfa752fSRamaswamy Tummala     char **errorp, rcm_info_t **info)
5301cfa752fSRamaswamy Tummala {
5311cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: resume(%s)\n", rsrc);
5321cfa752fSRamaswamy Tummala 	return (RCM_SUCCESS);
5331cfa752fSRamaswamy Tummala }
5341cfa752fSRamaswamy Tummala 
5351cfa752fSRamaswamy Tummala /*
5361cfa752fSRamaswamy Tummala  * ibpart_consumer_remove()
5371cfa752fSRamaswamy Tummala  *
5381cfa752fSRamaswamy Tummala  *	Notify IBPART consumers to remove cache.
5391cfa752fSRamaswamy Tummala  */
5401cfa752fSRamaswamy Tummala static int
ibpart_consumer_remove(rcm_handle_t * hd,link_cache_t * node,uint_t flags,rcm_info_t ** info)5411cfa752fSRamaswamy Tummala ibpart_consumer_remove(rcm_handle_t *hd, link_cache_t *node, uint_t flags,
5421cfa752fSRamaswamy Tummala     rcm_info_t **info)
5431cfa752fSRamaswamy Tummala {
5441cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart = NULL;
5451cfa752fSRamaswamy Tummala 	char rsrc[RCM_LINK_RESOURCE_MAX];
5461cfa752fSRamaswamy Tummala 	int ret = RCM_SUCCESS;
5471cfa752fSRamaswamy Tummala 
5481cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_remove (%s)\n",
5491cfa752fSRamaswamy Tummala 	    node->pc_resource);
5501cfa752fSRamaswamy Tummala 
5511cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
5521cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
5531cfa752fSRamaswamy Tummala 
5541cfa752fSRamaswamy Tummala 		/*
5551cfa752fSRamaswamy Tummala 		 * This will only be called when the offline operation
5561cfa752fSRamaswamy Tummala 		 * succeeds, so the IBPART consumers must have been offlined
5571cfa752fSRamaswamy Tummala 		 * at this point.
5581cfa752fSRamaswamy Tummala 		 */
5591cfa752fSRamaswamy Tummala 		assert(ibpart->dlib_flags & IBPART_CONSUMER_OFFLINED);
5601cfa752fSRamaswamy Tummala 
5611cfa752fSRamaswamy Tummala 		(void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
5621cfa752fSRamaswamy Tummala 		    RCM_LINK_PREFIX, ibpart->dlib_ibpart_id);
5631cfa752fSRamaswamy Tummala 
5641cfa752fSRamaswamy Tummala 		ret = rcm_notify_remove(hd, rsrc, flags, info);
5651cfa752fSRamaswamy Tummala 		if (ret != RCM_SUCCESS) {
5661cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_WARNING,
5671cfa752fSRamaswamy Tummala 			    _("IBPART: notify remove failed (%s)\n"), rsrc);
5681cfa752fSRamaswamy Tummala 			break;
5691cfa752fSRamaswamy Tummala 		}
5701cfa752fSRamaswamy Tummala 	}
5711cfa752fSRamaswamy Tummala 
5721cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_remove done\n");
5731cfa752fSRamaswamy Tummala 	return (ret);
5741cfa752fSRamaswamy Tummala }
5751cfa752fSRamaswamy Tummala 
5761cfa752fSRamaswamy Tummala /*
5771cfa752fSRamaswamy Tummala  * ibpart_remove() - remove a resource from cache
5781cfa752fSRamaswamy Tummala  */
5791cfa752fSRamaswamy Tummala /*ARGSUSED*/
5801cfa752fSRamaswamy Tummala static int
ibpart_remove(rcm_handle_t * hd,char * rsrc,id_t id,uint_t flags,char ** errorp,rcm_info_t ** info)5811cfa752fSRamaswamy Tummala ibpart_remove(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
5821cfa752fSRamaswamy Tummala     char **errorp, rcm_info_t **info)
5831cfa752fSRamaswamy Tummala {
5841cfa752fSRamaswamy Tummala 	link_cache_t *node;
5851cfa752fSRamaswamy Tummala 	int rv;
5861cfa752fSRamaswamy Tummala 
5871cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: remove(%s)\n", rsrc);
5881cfa752fSRamaswamy Tummala 
5891cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
5901cfa752fSRamaswamy Tummala 	node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
5911cfa752fSRamaswamy Tummala 	if (node == NULL) {
5921cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_INFO,
5931cfa752fSRamaswamy Tummala 		    _("IBPART: remove(%s) unrecognized resource\n"), rsrc);
5941cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
5951cfa752fSRamaswamy Tummala 		errno = ENOENT;
5961cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
5971cfa752fSRamaswamy Tummala 	}
5981cfa752fSRamaswamy Tummala 
5991cfa752fSRamaswamy Tummala 	/* remove the cached entry for the resource */
6001cfa752fSRamaswamy Tummala 	cache_remove(node);
6011cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
6021cfa752fSRamaswamy Tummala 
6031cfa752fSRamaswamy Tummala 	rv = ibpart_consumer_remove(hd, node, flags, info);
6041cfa752fSRamaswamy Tummala 	node_free(node);
6051cfa752fSRamaswamy Tummala 	return (rv);
6061cfa752fSRamaswamy Tummala }
6071cfa752fSRamaswamy Tummala 
6081cfa752fSRamaswamy Tummala /*
6091cfa752fSRamaswamy Tummala  * ibpart_notify_event - Project private implementation to receive new resource
6101cfa752fSRamaswamy Tummala  *		   events. It intercepts all new resource events. If the
6111cfa752fSRamaswamy Tummala  *		   new resource is a network resource, pass up a notify
6121cfa752fSRamaswamy Tummala  *		   for it too. The new resource need not be cached, since
6131cfa752fSRamaswamy Tummala  *		   it is done at register again.
6141cfa752fSRamaswamy Tummala  */
6151cfa752fSRamaswamy Tummala /*ARGSUSED*/
6161cfa752fSRamaswamy 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)6171cfa752fSRamaswamy Tummala ibpart_notify_event(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
6181cfa752fSRamaswamy Tummala     char **errorp, nvlist_t *nvl, rcm_info_t **info)
6191cfa752fSRamaswamy Tummala {
6201cfa752fSRamaswamy Tummala 	nvpair_t	*nvp = NULL;
6211cfa752fSRamaswamy Tummala 	datalink_id_t	linkid;
6221cfa752fSRamaswamy Tummala 	uint64_t	id64;
6231cfa752fSRamaswamy Tummala 	int		rv = RCM_SUCCESS;
6241cfa752fSRamaswamy Tummala 
6251cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1, "IBPART: notify_event(%s)\n", rsrc);
6261cfa752fSRamaswamy Tummala 
6271cfa752fSRamaswamy Tummala 	if (strcmp(rsrc, RCM_RESOURCE_LINK_NEW) != 0) {
6281cfa752fSRamaswamy Tummala 		ibpart_log_err(DATALINK_INVALID_LINKID, errorp,
6291cfa752fSRamaswamy Tummala 		    "unrecognized event");
6301cfa752fSRamaswamy Tummala 		errno = EINVAL;
6311cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
6321cfa752fSRamaswamy Tummala 	}
6331cfa752fSRamaswamy Tummala 
6341cfa752fSRamaswamy Tummala 	/* Update cache to reflect latest IBPARTs */
6351cfa752fSRamaswamy Tummala 	if (cache_update(hd) < 0) {
6361cfa752fSRamaswamy Tummala 		ibpart_log_err(DATALINK_INVALID_LINKID, errorp,
6371cfa752fSRamaswamy Tummala 		    "private Cache update failed");
6381cfa752fSRamaswamy Tummala 		return (RCM_FAILURE);
6391cfa752fSRamaswamy Tummala 	}
6401cfa752fSRamaswamy Tummala 
6411cfa752fSRamaswamy Tummala 	/*
6421cfa752fSRamaswamy Tummala 	 * Try best to recover all configuration.
6431cfa752fSRamaswamy Tummala 	 */
6441cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_DEBUG, "IBPART: process_nvlist\n");
6451cfa752fSRamaswamy Tummala 	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
6461cfa752fSRamaswamy Tummala 		if (strcmp(nvpair_name(nvp), RCM_NV_LINKID) != 0)
6471cfa752fSRamaswamy Tummala 			continue;
6481cfa752fSRamaswamy Tummala 
6491cfa752fSRamaswamy Tummala 		if (nvpair_value_uint64(nvp, &id64) != 0) {
6501cfa752fSRamaswamy Tummala 			ibpart_log_err(DATALINK_INVALID_LINKID, errorp,
6511cfa752fSRamaswamy Tummala 			    "cannot get linkid");
6521cfa752fSRamaswamy Tummala 			rv = RCM_FAILURE;
6531cfa752fSRamaswamy Tummala 			continue;
6541cfa752fSRamaswamy Tummala 		}
6551cfa752fSRamaswamy Tummala 
6561cfa752fSRamaswamy Tummala 		linkid = (datalink_id_t)id64;
6571cfa752fSRamaswamy Tummala 		if (ibpart_configure(hd, linkid) != 0) {
6581cfa752fSRamaswamy Tummala 			ibpart_log_err(linkid, errorp, "configuring failed");
6591cfa752fSRamaswamy Tummala 			rv = RCM_FAILURE;
6601cfa752fSRamaswamy Tummala 			continue;
6611cfa752fSRamaswamy Tummala 		}
6621cfa752fSRamaswamy Tummala 
6631cfa752fSRamaswamy Tummala 		/* Notify all IBPART consumers */
6641cfa752fSRamaswamy Tummala 		if (ibpart_consumer_notify(hd, linkid, errorp, flags,
6651cfa752fSRamaswamy Tummala 		    info) != 0) {
6661cfa752fSRamaswamy Tummala 			ibpart_log_err(linkid, errorp,
6671cfa752fSRamaswamy Tummala 			    "consumer notify failed");
6681cfa752fSRamaswamy Tummala 			rv = RCM_FAILURE;
6691cfa752fSRamaswamy Tummala 		}
6701cfa752fSRamaswamy Tummala 	}
6711cfa752fSRamaswamy Tummala 
6721cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE1,
6731cfa752fSRamaswamy Tummala 	    "IBPART: notify_event: link configuration complete\n");
6741cfa752fSRamaswamy Tummala 	return (rv);
6751cfa752fSRamaswamy Tummala }
6761cfa752fSRamaswamy Tummala 
6771cfa752fSRamaswamy Tummala /*
6781cfa752fSRamaswamy Tummala  * ibpart_usage - Determine the usage of a link.
6791cfa752fSRamaswamy Tummala  *	    The returned buffer is owned by caller, and the caller
6801cfa752fSRamaswamy Tummala  *	    must free it up when done.
6811cfa752fSRamaswamy Tummala  */
6821cfa752fSRamaswamy Tummala static char *
ibpart_usage(link_cache_t * node)6831cfa752fSRamaswamy Tummala ibpart_usage(link_cache_t *node)
6841cfa752fSRamaswamy Tummala {
6851cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
6861cfa752fSRamaswamy Tummala 	int nibpart;
6871cfa752fSRamaswamy Tummala 	char *buf;
6881cfa752fSRamaswamy Tummala 	const char *fmt;
6891cfa752fSRamaswamy Tummala 	char *sep;
6901cfa752fSRamaswamy Tummala 	char errmsg[DLADM_STRSIZE];
6911cfa752fSRamaswamy Tummala 	char name[MAXLINKNAMELEN];
6921cfa752fSRamaswamy Tummala 	dladm_status_t status;
6931cfa752fSRamaswamy Tummala 	size_t bufsz;
6941cfa752fSRamaswamy Tummala 
6951cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: usage(%s)\n", node->pc_resource);
6961cfa752fSRamaswamy Tummala 
6971cfa752fSRamaswamy Tummala 	assert(MUTEX_HELD(&cache_lock));
6981cfa752fSRamaswamy Tummala 	if ((status = dladm_datalink_id2info(dld_handle, node->pc_linkid, NULL,
6991cfa752fSRamaswamy Tummala 	    NULL, NULL, name, sizeof (name))) != DLADM_STATUS_OK) {
7001cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_ERROR,
7011cfa752fSRamaswamy Tummala 		    _("IBPART: usage(%s) get link name failure(%s)\n"),
7021cfa752fSRamaswamy Tummala 		    node->pc_resource, dladm_status2str(status, errmsg));
7031cfa752fSRamaswamy Tummala 		return (NULL);
7041cfa752fSRamaswamy Tummala 	}
7051cfa752fSRamaswamy Tummala 
7061cfa752fSRamaswamy Tummala 	if (node->pc_state & CACHE_NODE_OFFLINED)
7071cfa752fSRamaswamy Tummala 		fmt = _("%1$s offlined");
7081cfa752fSRamaswamy Tummala 	else
7091cfa752fSRamaswamy Tummala 		fmt = _("%1$s IBPART: ");
7101cfa752fSRamaswamy Tummala 
7111cfa752fSRamaswamy Tummala 	/* TRANSLATION_NOTE: separator used between IBPART linkids */
7121cfa752fSRamaswamy Tummala 	sep = _(", ");
7131cfa752fSRamaswamy Tummala 
7141cfa752fSRamaswamy Tummala 	nibpart = 0;
7151cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
7161cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next)
7171cfa752fSRamaswamy Tummala 		nibpart++;
7181cfa752fSRamaswamy Tummala 
7191cfa752fSRamaswamy Tummala 	/* space for IBPARTs and separators, plus message */
7201cfa752fSRamaswamy Tummala 	bufsz = nibpart * (MAXLINKNAMELEN + strlen(sep)) +
7211cfa752fSRamaswamy Tummala 	    strlen(fmt) + MAXLINKNAMELEN + 1;
7221cfa752fSRamaswamy Tummala 	if ((buf = malloc(bufsz)) == NULL) {
7231cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_ERROR,
7241cfa752fSRamaswamy Tummala 		    _("IBPART: usage(%s) malloc failure(%s)\n"),
7251cfa752fSRamaswamy Tummala 		    node->pc_resource, strerror(errno));
7261cfa752fSRamaswamy Tummala 		return (NULL);
7271cfa752fSRamaswamy Tummala 	}
7281cfa752fSRamaswamy Tummala 	(void) snprintf(buf, bufsz, fmt, name);
7291cfa752fSRamaswamy Tummala 
7301cfa752fSRamaswamy Tummala 	if (node->pc_state & CACHE_NODE_OFFLINED) {
7311cfa752fSRamaswamy Tummala 		/* Nothing else to do */
7321cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE2, "IBPART: usage (%s) info = %s\n",
7331cfa752fSRamaswamy Tummala 		    node->pc_resource, buf);
7341cfa752fSRamaswamy Tummala 		return (buf);
7351cfa752fSRamaswamy Tummala 	}
7361cfa752fSRamaswamy Tummala 
7371cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
7381cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
7391cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_DEBUG, "IBPART:= %u\n",
7401cfa752fSRamaswamy Tummala 		    ibpart->dlib_ibpart_id);
7411cfa752fSRamaswamy Tummala 
7421cfa752fSRamaswamy Tummala 		if ((status = dladm_datalink_id2info(dld_handle,
7431cfa752fSRamaswamy Tummala 		    ibpart->dlib_ibpart_id, NULL, NULL, NULL, name,
7441cfa752fSRamaswamy Tummala 		    sizeof (name))) != DLADM_STATUS_OK) {
7451cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR,
7461cfa752fSRamaswamy Tummala 			    _("IBPART: usage(%s) get ibpart %u name "
7471cfa752fSRamaswamy Tummala 			    "failure(%s)\n"), node->pc_resource,
7481cfa752fSRamaswamy Tummala 			    ibpart->dlib_ibpart_id,
7491cfa752fSRamaswamy Tummala 			    dladm_status2str(status, errmsg));
7501cfa752fSRamaswamy Tummala 			free(buf);
7511cfa752fSRamaswamy Tummala 			return (NULL);
7521cfa752fSRamaswamy Tummala 		}
7531cfa752fSRamaswamy Tummala 
7541cfa752fSRamaswamy Tummala 		(void) strlcat(buf, name, bufsz);
7551cfa752fSRamaswamy Tummala 		if (ibpart->dlib_next != NULL)
7561cfa752fSRamaswamy Tummala 			(void) strlcat(buf, sep, bufsz);
7571cfa752fSRamaswamy Tummala 	}
7581cfa752fSRamaswamy Tummala 
7591cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: usage (%s) info = %s\n",
7601cfa752fSRamaswamy Tummala 	    node->pc_resource, buf);
7611cfa752fSRamaswamy Tummala 
7621cfa752fSRamaswamy Tummala 	return (buf);
7631cfa752fSRamaswamy Tummala }
7641cfa752fSRamaswamy Tummala 
7651cfa752fSRamaswamy Tummala /*
7661cfa752fSRamaswamy Tummala  * Cache management routines, all cache management functions should be
7671cfa752fSRamaswamy Tummala  * be called with cache_lock held.
7681cfa752fSRamaswamy Tummala  */
7691cfa752fSRamaswamy Tummala 
7701cfa752fSRamaswamy Tummala /*
7711cfa752fSRamaswamy Tummala  * cache_lookup() - Get a cache node for a resource.
7721cfa752fSRamaswamy Tummala  *		  Call with cache lock held.
7731cfa752fSRamaswamy Tummala  *
7741cfa752fSRamaswamy Tummala  * This ensures that the cache is consistent with the system state and
7751cfa752fSRamaswamy Tummala  * returns a pointer to the cache element corresponding to the resource.
7761cfa752fSRamaswamy Tummala  */
7771cfa752fSRamaswamy Tummala static link_cache_t *
cache_lookup(rcm_handle_t * hd,char * rsrc,char options)7781cfa752fSRamaswamy Tummala cache_lookup(rcm_handle_t *hd, char *rsrc, char options)
7791cfa752fSRamaswamy Tummala {
7801cfa752fSRamaswamy Tummala 	link_cache_t *node;
7811cfa752fSRamaswamy Tummala 
7821cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: cache lookup(%s)\n", rsrc);
7831cfa752fSRamaswamy Tummala 
7841cfa752fSRamaswamy Tummala 	assert(MUTEX_HELD(&cache_lock));
7851cfa752fSRamaswamy Tummala 	if (options & CACHE_REFRESH) {
7861cfa752fSRamaswamy Tummala 		/* drop lock since update locks cache again */
7871cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
7881cfa752fSRamaswamy Tummala 		(void) cache_update(hd);
7891cfa752fSRamaswamy Tummala 		(void) mutex_lock(&cache_lock);
7901cfa752fSRamaswamy Tummala 	}
7911cfa752fSRamaswamy Tummala 
7921cfa752fSRamaswamy Tummala 	node = cache_head.pc_next;
7931cfa752fSRamaswamy Tummala 	for (; node != &cache_tail; node = node->pc_next) {
7941cfa752fSRamaswamy Tummala 		if (strcmp(rsrc, node->pc_resource) == 0) {
7951cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_TRACE2,
7961cfa752fSRamaswamy Tummala 			    "IBPART: cache lookup succeeded(%s)\n", rsrc);
7971cfa752fSRamaswamy Tummala 			return (node);
7981cfa752fSRamaswamy Tummala 		}
7991cfa752fSRamaswamy Tummala 	}
8001cfa752fSRamaswamy Tummala 	return (NULL);
8011cfa752fSRamaswamy Tummala }
8021cfa752fSRamaswamy Tummala 
8031cfa752fSRamaswamy Tummala /*
8041cfa752fSRamaswamy Tummala  * node_free - Free a node from the cache
8051cfa752fSRamaswamy Tummala  */
8061cfa752fSRamaswamy Tummala static void
node_free(link_cache_t * node)8071cfa752fSRamaswamy Tummala node_free(link_cache_t *node)
8081cfa752fSRamaswamy Tummala {
8091cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart, *next;
8101cfa752fSRamaswamy Tummala 
8111cfa752fSRamaswamy Tummala 	if (node != NULL) {
8121cfa752fSRamaswamy Tummala 		free(node->pc_resource);
8131cfa752fSRamaswamy Tummala 
8141cfa752fSRamaswamy Tummala 		/* free the IBPART list */
8151cfa752fSRamaswamy Tummala 		for (ibpart = node->pc_ibpart; ibpart != NULL; ibpart = next) {
8161cfa752fSRamaswamy Tummala 			next = ibpart->dlib_next;
8171cfa752fSRamaswamy Tummala 			free(ibpart);
8181cfa752fSRamaswamy Tummala 		}
8191cfa752fSRamaswamy Tummala 		free(node);
8201cfa752fSRamaswamy Tummala 	}
8211cfa752fSRamaswamy Tummala }
8221cfa752fSRamaswamy Tummala 
8231cfa752fSRamaswamy Tummala /*
8241cfa752fSRamaswamy Tummala  * cache_insert - Insert a resource node in cache
8251cfa752fSRamaswamy Tummala  */
8261cfa752fSRamaswamy Tummala static void
cache_insert(link_cache_t * node)8271cfa752fSRamaswamy Tummala cache_insert(link_cache_t *node)
8281cfa752fSRamaswamy Tummala {
8291cfa752fSRamaswamy Tummala 	assert(MUTEX_HELD(&cache_lock));
8301cfa752fSRamaswamy Tummala 
8311cfa752fSRamaswamy Tummala 	/* insert at the head for best performance */
8321cfa752fSRamaswamy Tummala 	node->pc_next = cache_head.pc_next;
8331cfa752fSRamaswamy Tummala 	node->pc_prev = &cache_head;
8341cfa752fSRamaswamy Tummala 
8351cfa752fSRamaswamy Tummala 	node->pc_next->pc_prev = node;
8361cfa752fSRamaswamy Tummala 	node->pc_prev->pc_next = node;
8371cfa752fSRamaswamy Tummala }
8381cfa752fSRamaswamy Tummala 
8391cfa752fSRamaswamy Tummala /*
8401cfa752fSRamaswamy Tummala  * cache_remove() - Remove a resource node from cache.
8411cfa752fSRamaswamy Tummala  */
8421cfa752fSRamaswamy Tummala static void
cache_remove(link_cache_t * node)8431cfa752fSRamaswamy Tummala cache_remove(link_cache_t *node)
8441cfa752fSRamaswamy Tummala {
8451cfa752fSRamaswamy Tummala 	assert(MUTEX_HELD(&cache_lock));
8461cfa752fSRamaswamy Tummala 	node->pc_next->pc_prev = node->pc_prev;
8471cfa752fSRamaswamy Tummala 	node->pc_prev->pc_next = node->pc_next;
8481cfa752fSRamaswamy Tummala 	node->pc_next = NULL;
8491cfa752fSRamaswamy Tummala 	node->pc_prev = NULL;
8501cfa752fSRamaswamy Tummala }
8511cfa752fSRamaswamy Tummala 
8521cfa752fSRamaswamy Tummala typedef struct ibpart_update_arg_s {
8531cfa752fSRamaswamy Tummala 	rcm_handle_t	*hd;
8541cfa752fSRamaswamy Tummala 	int		retval;
8551cfa752fSRamaswamy Tummala } ibpart_update_arg_t;
8561cfa752fSRamaswamy Tummala 
8571cfa752fSRamaswamy Tummala /*
8581cfa752fSRamaswamy Tummala  * ibpart_update() - Update physical interface properties
8591cfa752fSRamaswamy Tummala  */
8601cfa752fSRamaswamy Tummala static int
ibpart_update(dladm_handle_t handle,datalink_id_t ibpartid,void * arg)8611cfa752fSRamaswamy Tummala ibpart_update(dladm_handle_t handle, datalink_id_t ibpartid, void *arg)
8621cfa752fSRamaswamy Tummala {
8631cfa752fSRamaswamy Tummala 	ibpart_update_arg_t *ibpart_update_argp = arg;
8641cfa752fSRamaswamy Tummala 	rcm_handle_t *hd = ibpart_update_argp->hd;
8651cfa752fSRamaswamy Tummala 	link_cache_t *node;
8661cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
8671cfa752fSRamaswamy Tummala 	char *rsrc;
8681cfa752fSRamaswamy Tummala 	dladm_ib_attr_t ibpart_attr;
8691cfa752fSRamaswamy Tummala 	dladm_status_t status;
8701cfa752fSRamaswamy Tummala 	char errmsg[DLADM_STRSIZE];
8711cfa752fSRamaswamy Tummala 	boolean_t newnode = B_FALSE;
8721cfa752fSRamaswamy Tummala 	int ret = -1;
8731cfa752fSRamaswamy Tummala 
8741cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_update(%u)\n", ibpartid);
8751cfa752fSRamaswamy Tummala 
8761cfa752fSRamaswamy Tummala 	assert(MUTEX_HELD(&cache_lock));
8771cfa752fSRamaswamy Tummala 	status = dladm_part_info(handle, ibpartid, &ibpart_attr,
8781cfa752fSRamaswamy Tummala 	    DLADM_OPT_ACTIVE);
8791cfa752fSRamaswamy Tummala 	if (status != DLADM_STATUS_OK) {
8801cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE1,
8811cfa752fSRamaswamy Tummala 		    "IBPART: ibpart_update() cannot get ibpart information for "
8821cfa752fSRamaswamy Tummala 		    "%u(%s)\n", ibpartid, dladm_status2str(status, errmsg));
8831cfa752fSRamaswamy Tummala 		return (DLADM_WALK_CONTINUE);
8841cfa752fSRamaswamy Tummala 	}
8851cfa752fSRamaswamy Tummala 
8861cfa752fSRamaswamy Tummala 	if (ibpart_attr.dia_physlinkid == DATALINK_INVALID_LINKID) {
8871cfa752fSRamaswamy Tummala 		/*
8881cfa752fSRamaswamy Tummala 		 * Skip the IB port nodes.
8891cfa752fSRamaswamy Tummala 		 */
8901cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE1,
8911cfa752fSRamaswamy Tummala 		    "IBPART: ibpart_update(): skip the PORT nodes %u\n",
8921cfa752fSRamaswamy Tummala 		    ibpartid);
8931cfa752fSRamaswamy Tummala 		return (DLADM_WALK_CONTINUE);
8941cfa752fSRamaswamy Tummala 	}
8951cfa752fSRamaswamy Tummala 
8961cfa752fSRamaswamy Tummala 	rsrc = malloc(RCM_LINK_RESOURCE_MAX);
8971cfa752fSRamaswamy Tummala 	if (rsrc == NULL) {
8981cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_ERROR, _("IBPART: malloc error(%s): %u\n"),
8991cfa752fSRamaswamy Tummala 		    strerror(errno), ibpartid);
9001cfa752fSRamaswamy Tummala 		goto done;
9011cfa752fSRamaswamy Tummala 	}
9021cfa752fSRamaswamy Tummala 
9031cfa752fSRamaswamy Tummala 	(void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
9041cfa752fSRamaswamy Tummala 	    RCM_LINK_PREFIX, ibpart_attr.dia_physlinkid);
9051cfa752fSRamaswamy Tummala 
9061cfa752fSRamaswamy Tummala 	node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
9071cfa752fSRamaswamy Tummala 	if (node != NULL) {
9081cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_DEBUG,
9091cfa752fSRamaswamy Tummala 		    "IBPART: %s already registered (ibpartid:%d)\n",
9101cfa752fSRamaswamy Tummala 		    rsrc, ibpart_attr.dia_partlinkid);
9111cfa752fSRamaswamy Tummala 		free(rsrc);
9121cfa752fSRamaswamy Tummala 	} else {
9131cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_DEBUG,
9141cfa752fSRamaswamy Tummala 		    "IBPART: %s is a new resource (ibpartid:%d)\n",
9151cfa752fSRamaswamy Tummala 		    rsrc, ibpart_attr.dia_partlinkid);
9161cfa752fSRamaswamy Tummala 		if ((node = calloc(1, sizeof (link_cache_t))) == NULL) {
9171cfa752fSRamaswamy Tummala 			free(rsrc);
9181cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR, _("IBPART: calloc: %s\n"),
9191cfa752fSRamaswamy Tummala 			    strerror(errno));
9201cfa752fSRamaswamy Tummala 			goto done;
9211cfa752fSRamaswamy Tummala 		}
9221cfa752fSRamaswamy Tummala 
9231cfa752fSRamaswamy Tummala 		node->pc_resource = rsrc;
9241cfa752fSRamaswamy Tummala 		node->pc_ibpart = NULL;
9251cfa752fSRamaswamy Tummala 		node->pc_linkid = ibpart_attr.dia_physlinkid;
9261cfa752fSRamaswamy Tummala 		node->pc_state |= CACHE_NODE_NEW;
9271cfa752fSRamaswamy Tummala 		newnode = B_TRUE;
9281cfa752fSRamaswamy Tummala 	}
9291cfa752fSRamaswamy Tummala 
9301cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
9311cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
9321cfa752fSRamaswamy Tummala 		if (ibpart->dlib_ibpart_id == ibpartid) {
9331cfa752fSRamaswamy Tummala 			ibpart->dlib_flags &= ~IBPART_STALE;
9341cfa752fSRamaswamy Tummala 			break;
9351cfa752fSRamaswamy Tummala 		}
9361cfa752fSRamaswamy Tummala 	}
9371cfa752fSRamaswamy Tummala 
9381cfa752fSRamaswamy Tummala 	if (ibpart == NULL) {
9391cfa752fSRamaswamy Tummala 		if ((ibpart = calloc(1, sizeof (dl_ibpart_t))) == NULL) {
9401cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR, _("IBPART: malloc: %s\n"),
9411cfa752fSRamaswamy Tummala 			    strerror(errno));
9421cfa752fSRamaswamy Tummala 			if (newnode) {
9431cfa752fSRamaswamy Tummala 				free(rsrc);
9441cfa752fSRamaswamy Tummala 				free(node);
9451cfa752fSRamaswamy Tummala 			}
9461cfa752fSRamaswamy Tummala 			goto done;
9471cfa752fSRamaswamy Tummala 		}
9481cfa752fSRamaswamy Tummala 		ibpart->dlib_ibpart_id = ibpartid;
9491cfa752fSRamaswamy Tummala 		ibpart->dlib_next = node->pc_ibpart;
9501cfa752fSRamaswamy Tummala 		ibpart->dlib_prev = NULL;
9511cfa752fSRamaswamy Tummala 		if (node->pc_ibpart != NULL)
9521cfa752fSRamaswamy Tummala 			node->pc_ibpart->dlib_prev = ibpart;
9531cfa752fSRamaswamy Tummala 		node->pc_ibpart = ibpart;
9541cfa752fSRamaswamy Tummala 	}
9551cfa752fSRamaswamy Tummala 
9561cfa752fSRamaswamy Tummala 	node->pc_state &= ~CACHE_NODE_STALE;
9571cfa752fSRamaswamy Tummala 
9581cfa752fSRamaswamy Tummala 	if (newnode)
9591cfa752fSRamaswamy Tummala 		cache_insert(node);
9601cfa752fSRamaswamy Tummala 
9611cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE3, "IBPART: ibpart_update: succeeded(%u)\n",
9621cfa752fSRamaswamy Tummala 	    ibpartid);
9631cfa752fSRamaswamy Tummala 	ret = 0;
9641cfa752fSRamaswamy Tummala done:
9651cfa752fSRamaswamy Tummala 	ibpart_update_argp->retval = ret;
9661cfa752fSRamaswamy Tummala 	return (ret == 0 ? DLADM_WALK_CONTINUE : DLADM_WALK_TERMINATE);
9671cfa752fSRamaswamy Tummala }
9681cfa752fSRamaswamy Tummala 
9691cfa752fSRamaswamy Tummala /*
9701cfa752fSRamaswamy Tummala  * ibpart_update_all() - Determine all IBPART links in the system
9711cfa752fSRamaswamy Tummala  */
9721cfa752fSRamaswamy Tummala static int
ibpart_update_all(rcm_handle_t * hd)9731cfa752fSRamaswamy Tummala ibpart_update_all(rcm_handle_t *hd)
9741cfa752fSRamaswamy Tummala {
9751cfa752fSRamaswamy Tummala 	ibpart_update_arg_t arg = {NULL, 0};
9761cfa752fSRamaswamy Tummala 
9771cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_update_all\n");
9781cfa752fSRamaswamy Tummala 
9791cfa752fSRamaswamy Tummala 	assert(MUTEX_HELD(&cache_lock));
9801cfa752fSRamaswamy Tummala 	arg.hd = hd;
9811cfa752fSRamaswamy Tummala 	(void) dladm_walk_datalink_id(ibpart_update, dld_handle, &arg,
9821cfa752fSRamaswamy Tummala 	    DATALINK_CLASS_PART, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
9831cfa752fSRamaswamy Tummala 	return (arg.retval);
9841cfa752fSRamaswamy Tummala }
9851cfa752fSRamaswamy Tummala 
9861cfa752fSRamaswamy Tummala /*
9871cfa752fSRamaswamy Tummala  * cache_update() - Update cache with latest interface info
9881cfa752fSRamaswamy Tummala  */
9891cfa752fSRamaswamy Tummala static int
cache_update(rcm_handle_t * hd)9901cfa752fSRamaswamy Tummala cache_update(rcm_handle_t *hd)
9911cfa752fSRamaswamy Tummala {
9921cfa752fSRamaswamy Tummala 	link_cache_t *node, *nnode;
9931cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
9941cfa752fSRamaswamy Tummala 	int rv;
9951cfa752fSRamaswamy Tummala 
9961cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: cache_update\n");
9971cfa752fSRamaswamy Tummala 
9981cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
9991cfa752fSRamaswamy Tummala 
10001cfa752fSRamaswamy Tummala 	/* first we walk the entire cache, marking each entry stale */
10011cfa752fSRamaswamy Tummala 	node = cache_head.pc_next;
10021cfa752fSRamaswamy Tummala 	for (; node != &cache_tail; node = node->pc_next) {
10031cfa752fSRamaswamy Tummala 		node->pc_state |= CACHE_NODE_STALE;
10041cfa752fSRamaswamy Tummala 		for (ibpart = node->pc_ibpart; ibpart != NULL;
10051cfa752fSRamaswamy Tummala 		    ibpart = ibpart->dlib_next)
10061cfa752fSRamaswamy Tummala 			ibpart->dlib_flags |= IBPART_STALE;
10071cfa752fSRamaswamy Tummala 	}
10081cfa752fSRamaswamy Tummala 
10091cfa752fSRamaswamy Tummala 	rv = ibpart_update_all(hd);
10101cfa752fSRamaswamy Tummala 
10111cfa752fSRamaswamy Tummala 	/*
10121cfa752fSRamaswamy Tummala 	 * Continue to delete all stale nodes from the cache even
10131cfa752fSRamaswamy Tummala 	 * ibpart_update_all() failed. Unregister link that are not offlined
10141cfa752fSRamaswamy Tummala 	 * and still in cache
10151cfa752fSRamaswamy Tummala 	 */
10161cfa752fSRamaswamy Tummala 	for (node = cache_head.pc_next; node != &cache_tail; node = nnode) {
10171cfa752fSRamaswamy Tummala 		dl_ibpart_t *ibpart, *next;
10181cfa752fSRamaswamy Tummala 
10191cfa752fSRamaswamy Tummala 		for (ibpart = node->pc_ibpart; ibpart != NULL; ibpart = next) {
10201cfa752fSRamaswamy Tummala 			next = ibpart->dlib_next;
10211cfa752fSRamaswamy Tummala 
10221cfa752fSRamaswamy Tummala 			/* clear stale IBPARTs */
10231cfa752fSRamaswamy Tummala 			if (ibpart->dlib_flags & IBPART_STALE) {
10241cfa752fSRamaswamy Tummala 				if (ibpart->dlib_prev != NULL)
10251cfa752fSRamaswamy Tummala 					ibpart->dlib_prev->dlib_next = next;
10261cfa752fSRamaswamy Tummala 				else
10271cfa752fSRamaswamy Tummala 					node->pc_ibpart = next;
10281cfa752fSRamaswamy Tummala 
10291cfa752fSRamaswamy Tummala 				if (next != NULL)
10301cfa752fSRamaswamy Tummala 					next->dlib_prev = ibpart->dlib_prev;
10311cfa752fSRamaswamy Tummala 				free(ibpart);
10321cfa752fSRamaswamy Tummala 			}
10331cfa752fSRamaswamy Tummala 		}
10341cfa752fSRamaswamy Tummala 
10351cfa752fSRamaswamy Tummala 		nnode = node->pc_next;
10361cfa752fSRamaswamy Tummala 		if (node->pc_state & CACHE_NODE_STALE) {
10371cfa752fSRamaswamy Tummala 			(void) rcm_unregister_interest(hd, node->pc_resource,
10381cfa752fSRamaswamy Tummala 			    0);
10391cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_DEBUG, "IBPART: unregistered %s\n",
10401cfa752fSRamaswamy Tummala 			    node->pc_resource);
10411cfa752fSRamaswamy Tummala 			assert(node->pc_ibpart == NULL);
10421cfa752fSRamaswamy Tummala 			cache_remove(node);
10431cfa752fSRamaswamy Tummala 			node_free(node);
10441cfa752fSRamaswamy Tummala 			continue;
10451cfa752fSRamaswamy Tummala 		}
10461cfa752fSRamaswamy Tummala 
10471cfa752fSRamaswamy Tummala 		if (!(node->pc_state & CACHE_NODE_NEW))
10481cfa752fSRamaswamy Tummala 			continue;
10491cfa752fSRamaswamy Tummala 
10501cfa752fSRamaswamy Tummala 		if (rcm_register_interest(hd, node->pc_resource, 0, NULL) !=
10511cfa752fSRamaswamy Tummala 		    RCM_SUCCESS) {
10521cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR,
10531cfa752fSRamaswamy Tummala 			    _("IBPART: failed to register %s\n"),
10541cfa752fSRamaswamy Tummala 			    node->pc_resource);
10551cfa752fSRamaswamy Tummala 			rv = -1;
10561cfa752fSRamaswamy Tummala 		} else {
10571cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_DEBUG, "IBPART: registered %s\n",
10581cfa752fSRamaswamy Tummala 			    node->pc_resource);
10591cfa752fSRamaswamy Tummala 			node->pc_state &= ~CACHE_NODE_NEW;
10601cfa752fSRamaswamy Tummala 		}
10611cfa752fSRamaswamy Tummala 	}
10621cfa752fSRamaswamy Tummala 
10631cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
10641cfa752fSRamaswamy Tummala 	return (rv);
10651cfa752fSRamaswamy Tummala }
10661cfa752fSRamaswamy Tummala 
10671cfa752fSRamaswamy Tummala /*
10681cfa752fSRamaswamy Tummala  * cache_free() - Empty the cache
10691cfa752fSRamaswamy Tummala  */
10701cfa752fSRamaswamy Tummala static void
cache_free()10711cfa752fSRamaswamy Tummala cache_free()
10721cfa752fSRamaswamy Tummala {
10731cfa752fSRamaswamy Tummala 	link_cache_t *node;
10741cfa752fSRamaswamy Tummala 
10751cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: cache_free\n");
10761cfa752fSRamaswamy Tummala 
10771cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
10781cfa752fSRamaswamy Tummala 	node = cache_head.pc_next;
10791cfa752fSRamaswamy Tummala 	while (node != &cache_tail) {
10801cfa752fSRamaswamy Tummala 		cache_remove(node);
10811cfa752fSRamaswamy Tummala 		node_free(node);
10821cfa752fSRamaswamy Tummala 		node = cache_head.pc_next;
10831cfa752fSRamaswamy Tummala 	}
10841cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
10851cfa752fSRamaswamy Tummala }
10861cfa752fSRamaswamy Tummala 
10871cfa752fSRamaswamy Tummala /*
10881cfa752fSRamaswamy Tummala  * ibpart_log_err() - RCM error log wrapper
10891cfa752fSRamaswamy Tummala  */
10901cfa752fSRamaswamy Tummala static void
ibpart_log_err(datalink_id_t linkid,char ** errorp,char * errmsg)10911cfa752fSRamaswamy Tummala ibpart_log_err(datalink_id_t linkid, char **errorp, char *errmsg)
10921cfa752fSRamaswamy Tummala {
10931cfa752fSRamaswamy Tummala 	char link[MAXLINKNAMELEN];
10941cfa752fSRamaswamy Tummala 	char errstr[DLADM_STRSIZE];
10951cfa752fSRamaswamy Tummala 	dladm_status_t status;
10961cfa752fSRamaswamy Tummala 	int len;
10971cfa752fSRamaswamy Tummala 	const char *errfmt;
10981cfa752fSRamaswamy Tummala 	char *error;
10991cfa752fSRamaswamy Tummala 
11001cfa752fSRamaswamy Tummala 	link[0] = '\0';
11011cfa752fSRamaswamy Tummala 	if (linkid != DATALINK_INVALID_LINKID) {
11021cfa752fSRamaswamy Tummala 		char rsrc[RCM_LINK_RESOURCE_MAX];
11031cfa752fSRamaswamy Tummala 
11041cfa752fSRamaswamy Tummala 		(void) snprintf(rsrc, sizeof (rsrc), "%s/%u",
11051cfa752fSRamaswamy Tummala 		    RCM_LINK_PREFIX, linkid);
11061cfa752fSRamaswamy Tummala 
11071cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_ERROR, _("IBPART: %s(%s)\n"), errmsg, rsrc);
11081cfa752fSRamaswamy Tummala 		if ((status = dladm_datalink_id2info(dld_handle, linkid, NULL,
11091cfa752fSRamaswamy Tummala 		    NULL, NULL, link, sizeof (link))) != DLADM_STATUS_OK) {
11101cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_WARNING,
11111cfa752fSRamaswamy Tummala 			    _("IBPART: cannot get link name for (%s) %s\n"),
11121cfa752fSRamaswamy Tummala 			    rsrc, dladm_status2str(status, errstr));
11131cfa752fSRamaswamy Tummala 		}
11141cfa752fSRamaswamy Tummala 	} else {
11151cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_ERROR, _("IBPART: %s\n"), errmsg);
11161cfa752fSRamaswamy Tummala 	}
11171cfa752fSRamaswamy Tummala 
11181cfa752fSRamaswamy Tummala 	errfmt = strlen(link) > 0 ? _("IBPART: %s(%s)") : _("IBPART: %s");
11191cfa752fSRamaswamy Tummala 	len = strlen(errfmt) + strlen(errmsg) + MAXLINKNAMELEN + 1;
11201cfa752fSRamaswamy Tummala 	if ((error = malloc(len)) != NULL) {
11211cfa752fSRamaswamy Tummala 		if (strlen(link) > 0)
11221cfa752fSRamaswamy Tummala 			(void) snprintf(error, len, errfmt, errmsg, link);
11231cfa752fSRamaswamy Tummala 		else
11241cfa752fSRamaswamy Tummala 			(void) snprintf(error, len, errfmt, errmsg);
11251cfa752fSRamaswamy Tummala 	}
11261cfa752fSRamaswamy Tummala 
11271cfa752fSRamaswamy Tummala 	if (errorp != NULL)
11281cfa752fSRamaswamy Tummala 		*errorp = error;
11291cfa752fSRamaswamy Tummala }
11301cfa752fSRamaswamy Tummala 
11311cfa752fSRamaswamy Tummala /*
11321cfa752fSRamaswamy Tummala  * ibpart_consumer_online()
11331cfa752fSRamaswamy Tummala  *
11341cfa752fSRamaswamy Tummala  *	Notify online to IBPART consumers.
11351cfa752fSRamaswamy Tummala  */
11361cfa752fSRamaswamy Tummala /* ARGSUSED */
11371cfa752fSRamaswamy Tummala static void
ibpart_consumer_online(rcm_handle_t * hd,link_cache_t * node,char ** errorp,uint_t flags,rcm_info_t ** info)11381cfa752fSRamaswamy Tummala ibpart_consumer_online(rcm_handle_t *hd, link_cache_t *node, char **errorp,
11391cfa752fSRamaswamy Tummala     uint_t flags, rcm_info_t **info)
11401cfa752fSRamaswamy Tummala {
11411cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
11421cfa752fSRamaswamy Tummala 	char rsrc[RCM_LINK_RESOURCE_MAX];
11431cfa752fSRamaswamy Tummala 
11441cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_online (%s)\n",
11451cfa752fSRamaswamy Tummala 	    node->pc_resource);
11461cfa752fSRamaswamy Tummala 
11471cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
11481cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
11491cfa752fSRamaswamy Tummala 		if (!(ibpart->dlib_flags & IBPART_CONSUMER_OFFLINED))
11501cfa752fSRamaswamy Tummala 			continue;
11511cfa752fSRamaswamy Tummala 
11521cfa752fSRamaswamy Tummala 		(void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
11531cfa752fSRamaswamy Tummala 		    RCM_LINK_PREFIX, ibpart->dlib_ibpart_id);
11541cfa752fSRamaswamy Tummala 
11551cfa752fSRamaswamy Tummala 		if (rcm_notify_online(hd, rsrc, flags, info) == RCM_SUCCESS)
11561cfa752fSRamaswamy Tummala 			ibpart->dlib_flags &= ~IBPART_CONSUMER_OFFLINED;
11571cfa752fSRamaswamy Tummala 	}
11581cfa752fSRamaswamy Tummala 
11591cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_online done\n");
11601cfa752fSRamaswamy Tummala }
11611cfa752fSRamaswamy Tummala 
11621cfa752fSRamaswamy Tummala /*
11631cfa752fSRamaswamy Tummala  * ibpart_consumer_offline()
11641cfa752fSRamaswamy Tummala  *
11651cfa752fSRamaswamy Tummala  *	Offline IBPART consumers.
11661cfa752fSRamaswamy Tummala  */
11671cfa752fSRamaswamy Tummala static int
ibpart_consumer_offline(rcm_handle_t * hd,link_cache_t * node,char ** errorp,uint_t flags,rcm_info_t ** info)11681cfa752fSRamaswamy Tummala ibpart_consumer_offline(rcm_handle_t *hd, link_cache_t *node, char **errorp,
11691cfa752fSRamaswamy Tummala     uint_t flags, rcm_info_t **info)
11701cfa752fSRamaswamy Tummala {
11711cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
11721cfa752fSRamaswamy Tummala 	char rsrc[RCM_LINK_RESOURCE_MAX];
11731cfa752fSRamaswamy Tummala 	int ret = RCM_SUCCESS;
11741cfa752fSRamaswamy Tummala 
11751cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_offline (%s)\n",
11761cfa752fSRamaswamy Tummala 	    node->pc_resource);
11771cfa752fSRamaswamy Tummala 
11781cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
11791cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
11801cfa752fSRamaswamy Tummala 		(void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
11811cfa752fSRamaswamy Tummala 		    RCM_LINK_PREFIX, ibpart->dlib_ibpart_id);
11821cfa752fSRamaswamy Tummala 
11831cfa752fSRamaswamy Tummala 		ret = rcm_request_offline(hd, rsrc, flags, info);
11841cfa752fSRamaswamy Tummala 		if (ret != RCM_SUCCESS)
11851cfa752fSRamaswamy Tummala 			break;
11861cfa752fSRamaswamy Tummala 
11871cfa752fSRamaswamy Tummala 		ibpart->dlib_flags |= IBPART_CONSUMER_OFFLINED;
11881cfa752fSRamaswamy Tummala 	}
11891cfa752fSRamaswamy Tummala 
11901cfa752fSRamaswamy Tummala 	if (ibpart != NULL)
11911cfa752fSRamaswamy Tummala 		ibpart_consumer_online(hd, node, errorp, flags, info);
11921cfa752fSRamaswamy Tummala 
11931cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_offline done\n");
11941cfa752fSRamaswamy Tummala 	return (ret);
11951cfa752fSRamaswamy Tummala }
11961cfa752fSRamaswamy Tummala 
11971cfa752fSRamaswamy Tummala /*
11981cfa752fSRamaswamy Tummala  * Send RCM_RESOURCE_LINK_NEW events to other modules about new IBPARTs.
11991cfa752fSRamaswamy Tummala  * Return 0 on success, -1 on failure.
12001cfa752fSRamaswamy Tummala  */
12011cfa752fSRamaswamy Tummala static int
ibpart_notify_new_ibpart(rcm_handle_t * hd,char * rsrc)12021cfa752fSRamaswamy Tummala ibpart_notify_new_ibpart(rcm_handle_t *hd, char *rsrc)
12031cfa752fSRamaswamy Tummala {
12041cfa752fSRamaswamy Tummala 	link_cache_t *node;
12051cfa752fSRamaswamy Tummala 	dl_ibpart_t *ibpart;
12061cfa752fSRamaswamy Tummala 	nvlist_t *nvl = NULL;
12071cfa752fSRamaswamy Tummala 	uint64_t id;
12081cfa752fSRamaswamy Tummala 	int ret = -1;
12091cfa752fSRamaswamy Tummala 
12101cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_notify_new_ibpart (%s)\n",
12111cfa752fSRamaswamy Tummala 	    rsrc);
12121cfa752fSRamaswamy Tummala 
12131cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
12141cfa752fSRamaswamy Tummala 	if ((node = cache_lookup(hd, rsrc, CACHE_REFRESH)) == NULL) {
12151cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
12161cfa752fSRamaswamy Tummala 		return (0);
12171cfa752fSRamaswamy Tummala 	}
12181cfa752fSRamaswamy Tummala 
12191cfa752fSRamaswamy Tummala 	if (nvlist_alloc(&nvl, 0, 0) != 0) {
12201cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
12211cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_WARNING,
12221cfa752fSRamaswamy Tummala 		    _("IBPART: failed to allocate nvlist\n"));
12231cfa752fSRamaswamy Tummala 		goto done;
12241cfa752fSRamaswamy Tummala 	}
12251cfa752fSRamaswamy Tummala 
12261cfa752fSRamaswamy Tummala 	for (ibpart = node->pc_ibpart; ibpart != NULL;
12271cfa752fSRamaswamy Tummala 	    ibpart = ibpart->dlib_next) {
12281cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE2, "IBPART: ibpart_notify_new_ibpart "
12291cfa752fSRamaswamy Tummala 		    "add (%u)\n", ibpart->dlib_ibpart_id);
12301cfa752fSRamaswamy Tummala 
12311cfa752fSRamaswamy Tummala 		id = ibpart->dlib_ibpart_id;
12321cfa752fSRamaswamy Tummala 		if (nvlist_add_uint64(nvl, RCM_NV_LINKID, id) != 0) {
12331cfa752fSRamaswamy Tummala 			rcm_log_message(RCM_ERROR,
12341cfa752fSRamaswamy Tummala 			    _("IBPART: failed to construct nvlist\n"));
12351cfa752fSRamaswamy Tummala 			(void) mutex_unlock(&cache_lock);
12361cfa752fSRamaswamy Tummala 			goto done;
12371cfa752fSRamaswamy Tummala 		}
12381cfa752fSRamaswamy Tummala 	}
12391cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
12401cfa752fSRamaswamy Tummala 
12411cfa752fSRamaswamy Tummala 	if (rcm_notify_event(hd, RCM_RESOURCE_LINK_NEW, 0, nvl, NULL) !=
12421cfa752fSRamaswamy Tummala 	    RCM_SUCCESS) {
12431cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_ERROR,
12441cfa752fSRamaswamy Tummala 		    _("IBPART: failed to notify %s event for %s\n"),
12451cfa752fSRamaswamy Tummala 		    RCM_RESOURCE_LINK_NEW, node->pc_resource);
12461cfa752fSRamaswamy Tummala 		goto done;
12471cfa752fSRamaswamy Tummala 	}
12481cfa752fSRamaswamy Tummala 
12491cfa752fSRamaswamy Tummala 	ret = 0;
12501cfa752fSRamaswamy Tummala done:
1251*aab83bb8SJosef 'Jeff' Sipek 	nvlist_free(nvl);
12521cfa752fSRamaswamy Tummala 	return (ret);
12531cfa752fSRamaswamy Tummala }
12541cfa752fSRamaswamy Tummala 
12551cfa752fSRamaswamy Tummala /*
12561cfa752fSRamaswamy Tummala  * ibpart_consumer_notify() - Notify consumers of IBPARTs coming back online.
12571cfa752fSRamaswamy Tummala  */
12581cfa752fSRamaswamy Tummala static int
ibpart_consumer_notify(rcm_handle_t * hd,datalink_id_t linkid,char ** errorp,uint_t flags,rcm_info_t ** info)12591cfa752fSRamaswamy Tummala ibpart_consumer_notify(rcm_handle_t *hd, datalink_id_t linkid, char **errorp,
12601cfa752fSRamaswamy Tummala     uint_t flags, rcm_info_t **info)
12611cfa752fSRamaswamy Tummala {
12621cfa752fSRamaswamy Tummala 	char rsrc[RCM_LINK_RESOURCE_MAX];
12631cfa752fSRamaswamy Tummala 	link_cache_t *node;
12641cfa752fSRamaswamy Tummala 
12651cfa752fSRamaswamy Tummala 	/* Check for the interface in the cache */
12661cfa752fSRamaswamy Tummala 	(void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u", RCM_LINK_PREFIX,
12671cfa752fSRamaswamy Tummala 	    linkid);
12681cfa752fSRamaswamy Tummala 
12691cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_notify(%s)\n",
12701cfa752fSRamaswamy Tummala 	    rsrc);
12711cfa752fSRamaswamy Tummala 
12721cfa752fSRamaswamy Tummala 	/*
12731cfa752fSRamaswamy Tummala 	 * Inform IP consumers of the new link.
12741cfa752fSRamaswamy Tummala 	 */
12751cfa752fSRamaswamy Tummala 	if (ibpart_notify_new_ibpart(hd, rsrc) != 0) {
12761cfa752fSRamaswamy Tummala 		(void) mutex_lock(&cache_lock);
12771cfa752fSRamaswamy Tummala 		if ((node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH)) != NULL) {
12781cfa752fSRamaswamy Tummala 			(void) ibpart_offline_ibpart(node, IBPART_STALE,
12791cfa752fSRamaswamy Tummala 			    CACHE_NODE_STALE);
12801cfa752fSRamaswamy Tummala 		}
12811cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
12821cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE2,
12831cfa752fSRamaswamy Tummala 		    "IBPART: ibpart_notify_new_ibpart failed(%s)\n", rsrc);
12841cfa752fSRamaswamy Tummala 		return (-1);
12851cfa752fSRamaswamy Tummala 	}
12861cfa752fSRamaswamy Tummala 
12871cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_consumer_notify "
12881cfa752fSRamaswamy Tummala 	    "succeeded\n");
12891cfa752fSRamaswamy Tummala 	return (0);
12901cfa752fSRamaswamy Tummala }
12911cfa752fSRamaswamy Tummala 
12921cfa752fSRamaswamy Tummala typedef struct ibpart_up_arg_s {
12931cfa752fSRamaswamy Tummala 	datalink_id_t	linkid;
12941cfa752fSRamaswamy Tummala 	int		retval;
12951cfa752fSRamaswamy Tummala } ibpart_up_arg_t;
12961cfa752fSRamaswamy Tummala 
12971cfa752fSRamaswamy Tummala static int
ibpart_up(dladm_handle_t handle,datalink_id_t ibpartid,void * arg)12981cfa752fSRamaswamy Tummala ibpart_up(dladm_handle_t handle, datalink_id_t ibpartid, void *arg)
12991cfa752fSRamaswamy Tummala {
13001cfa752fSRamaswamy Tummala 	ibpart_up_arg_t *ibpart_up_argp = arg;
13011cfa752fSRamaswamy Tummala 	dladm_status_t status;
13021cfa752fSRamaswamy Tummala 	dladm_ib_attr_t ibpart_attr;
13031cfa752fSRamaswamy Tummala 	char errmsg[DLADM_STRSIZE];
13041cfa752fSRamaswamy Tummala 
13051cfa752fSRamaswamy Tummala 	status = dladm_part_info(handle, ibpartid, &ibpart_attr,
13061cfa752fSRamaswamy Tummala 	    DLADM_OPT_PERSIST);
13071cfa752fSRamaswamy Tummala 	if (status != DLADM_STATUS_OK) {
13081cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE1,
13091cfa752fSRamaswamy Tummala 		    "IBPART: ibpart_up(): cannot get information for IBPART %u "
13101cfa752fSRamaswamy Tummala 		    "(%s)\n", ibpartid, dladm_status2str(status, errmsg));
13111cfa752fSRamaswamy Tummala 		return (DLADM_WALK_CONTINUE);
13121cfa752fSRamaswamy Tummala 	}
13131cfa752fSRamaswamy Tummala 
13141cfa752fSRamaswamy Tummala 	if (ibpart_attr.dia_physlinkid != ibpart_up_argp->linkid)
13151cfa752fSRamaswamy Tummala 		return (DLADM_WALK_CONTINUE);
13161cfa752fSRamaswamy Tummala 
13171cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE3, "IBPART: ibpart_up(%u)\n", ibpartid);
13181cfa752fSRamaswamy Tummala 	if ((status = dladm_part_up(handle, ibpartid, 0)) == DLADM_STATUS_OK)
13191cfa752fSRamaswamy Tummala 		return (DLADM_WALK_CONTINUE);
13201cfa752fSRamaswamy Tummala 
13211cfa752fSRamaswamy Tummala 	/*
13221cfa752fSRamaswamy Tummala 	 * Prompt the warning message and continue to UP other IBPARTs.
13231cfa752fSRamaswamy Tummala 	 */
13241cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_WARNING,
13251cfa752fSRamaswamy Tummala 	    _("IBPART: IBPART up failed (%u): %s\n"),
13261cfa752fSRamaswamy Tummala 	    ibpartid, dladm_status2str(status, errmsg));
13271cfa752fSRamaswamy Tummala 
13281cfa752fSRamaswamy Tummala 	ibpart_up_argp->retval = -1;
13291cfa752fSRamaswamy Tummala 	return (DLADM_WALK_CONTINUE);
13301cfa752fSRamaswamy Tummala }
13311cfa752fSRamaswamy Tummala 
13321cfa752fSRamaswamy Tummala /*
13331cfa752fSRamaswamy Tummala  * ibpart_configure() - Configure IBPARTs over a physical link after it attaches
13341cfa752fSRamaswamy Tummala  */
13351cfa752fSRamaswamy Tummala static int
ibpart_configure(rcm_handle_t * hd,datalink_id_t linkid)13361cfa752fSRamaswamy Tummala ibpart_configure(rcm_handle_t *hd, datalink_id_t linkid)
13371cfa752fSRamaswamy Tummala {
13381cfa752fSRamaswamy Tummala 	char rsrc[RCM_LINK_RESOURCE_MAX];
13391cfa752fSRamaswamy Tummala 	link_cache_t *node;
13401cfa752fSRamaswamy Tummala 	ibpart_up_arg_t arg = {DATALINK_INVALID_LINKID, 0};
13411cfa752fSRamaswamy Tummala 
13421cfa752fSRamaswamy Tummala 	/* Check for the IBPARTs in the cache */
13431cfa752fSRamaswamy Tummala 	(void) snprintf(rsrc, sizeof (rsrc), "%s/%u", RCM_LINK_PREFIX, linkid);
13441cfa752fSRamaswamy Tummala 
13451cfa752fSRamaswamy Tummala 	rcm_log_message(RCM_TRACE2, "IBPART: ibpart_configure(%s)\n", rsrc);
13461cfa752fSRamaswamy Tummala 
13471cfa752fSRamaswamy Tummala 	/* Check if the link is new or was previously offlined */
13481cfa752fSRamaswamy Tummala 	(void) mutex_lock(&cache_lock);
13491cfa752fSRamaswamy Tummala 	if (((node = cache_lookup(hd, rsrc, CACHE_REFRESH)) != NULL) &&
13501cfa752fSRamaswamy Tummala 	    (!(node->pc_state & CACHE_NODE_OFFLINED))) {
13511cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE2,
13521cfa752fSRamaswamy Tummala 		    "IBPART: Skipping configured interface(%s)\n", rsrc);
13531cfa752fSRamaswamy Tummala 		(void) mutex_unlock(&cache_lock);
13541cfa752fSRamaswamy Tummala 		return (0);
13551cfa752fSRamaswamy Tummala 	}
13561cfa752fSRamaswamy Tummala 	(void) mutex_unlock(&cache_lock);
13571cfa752fSRamaswamy Tummala 
13581cfa752fSRamaswamy Tummala 	arg.linkid = linkid;
13591cfa752fSRamaswamy Tummala 	(void) dladm_walk_datalink_id(ibpart_up, dld_handle, &arg,
13601cfa752fSRamaswamy Tummala 	    DATALINK_CLASS_PART, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
13611cfa752fSRamaswamy Tummala 
13621cfa752fSRamaswamy Tummala 	if (arg.retval == 0) {
13631cfa752fSRamaswamy Tummala 		rcm_log_message(RCM_TRACE2,
13641cfa752fSRamaswamy Tummala 		    "IBPART: ibpart_configure succeeded(%s)\n", rsrc);
13651cfa752fSRamaswamy Tummala 	}
13661cfa752fSRamaswamy Tummala 	return (arg.retval);
13671cfa752fSRamaswamy Tummala }
1368