2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License, Version 1.0 only
2N/A * (the "License"). You may not use this file except in compliance
2N/A * with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A#pragma ident "%Z%%M% %I% %E% SMI"
2N/A
2N/A
2N/A#include "cfga_ib.h"
2N/A
2N/A
2N/A#define MAX_FORMAT 80 /* for info table */
2N/A
2N/Acfga_ib_ret_t ib_rcm_offline(const char *, char **, char *,
2N/A cfga_flags_t);
2N/Acfga_ib_ret_t ib_rcm_online(const char *, char **, char *,
2N/A cfga_flags_t);
2N/Acfga_ib_ret_t ib_rcm_remove(const char *, char **, char *,
2N/A cfga_flags_t);
2N/Astatic cfga_ib_ret_t ib_rcm_info_table(rcm_info_t *, char **);
2N/Astatic cfga_ib_ret_t ib_rcm_init(const char *, cfga_flags_t, char **,
2N/A uint_t *);
2N/A
2N/A
2N/Astatic rcm_handle_t *rcm_handle = NULL;
2N/Astatic mutex_t rcm_handle_lock = DEFAULTMUTEX;
2N/A
2N/A
2N/A/*
2N/A * Function:
2N/A * ib_rcm_offline
2N/A * Input:
2N/A * rsrc - Resource name (typically an ap_id)
2N/A * errstring - Error message filled in case of a failure
2N/A * rsrc_fixed - Pointer to fixed path
2N/A * flags - flags to RCM
2N/A * Output:
2N/A * NONE
2N/A * Returns:
2N/A * CFGA_IB_OK on success or an appropriate error
2N/A * Description:
2N/A * Offline IB resource consumers.
2N/A */
2N/Acfga_ib_ret_t
2N/Aib_rcm_offline(const char *rsrc, char **errstring, char *rsrc_fixed,
2N/A cfga_flags_t flags)
2N/A{
2N/A int rret;
2N/A uint_t rflags = 0;
2N/A rcm_info_t *rinfo = NULL;
2N/A cfga_ib_ret_t ret = CFGA_IB_OK;
2N/A
2N/A DPRINTF("ib_rcm_offline:\n");
2N/A
2N/A if ((ret = ib_rcm_init(rsrc, flags, errstring, &rflags)) !=
2N/A CFGA_IB_OK) {
2N/A return (ret);
2N/A }
2N/A
2N/A DPRINTF("ib_rcm_offline: rsrc_fixed: %s\n", rsrc_fixed);
2N/A
2N/A if ((rret = rcm_request_offline(rcm_handle, rsrc_fixed, rflags, &rinfo))
2N/A != RCM_SUCCESS) {
2N/A DPRINTF("ib_rcm_offline: rcm_request_offline failed\n");
2N/A
2N/A if (rinfo) {
2N/A (void) ib_rcm_info_table(rinfo, errstring);
2N/A rcm_free_info(rinfo);
2N/A rinfo = NULL;
2N/A }
2N/A
2N/A DPRINTF("ib_rcm_offline: table = %s\n", *errstring);
2N/A
2N/A if (rret == RCM_FAILURE) {
2N/A (void) ib_rcm_online(rsrc, errstring,
2N/A rsrc_fixed, flags);
2N/A }
2N/A ret = CFGA_IB_RCM_OFFLINE_ERR;
2N/A }
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function:
2N/A * ib_rcm_online
2N/A * Input:
2N/A * rsrc - Resource name (typically an ap_id)
2N/A * errstring - Error message filled in case of a failure
2N/A * rsrc_fixed - Pointer to fixed path
2N/A * flags - flags to RCM
2N/A * Output:
2N/A * NONE
2N/A * Returns:
2N/A * CFGA_IB_OK on success or an appropriate error
2N/A * Description:
2N/A * Online IB resource consumers that were previously offlined.
2N/A */
2N/Acfga_ib_ret_t
2N/Aib_rcm_online(const char *rsrc, char **errstring, char *rsrc_fixed,
2N/A cfga_flags_t flags)
2N/A{
2N/A rcm_info_t *rinfo = NULL;
2N/A cfga_ib_ret_t ret = CFGA_IB_OK;
2N/A
2N/A DPRINTF("ib_rcm_online:\n");
2N/A
2N/A if ((ret = ib_rcm_init(rsrc, flags, errstring, NULL)) != CFGA_IB_OK) {
2N/A return (ret);
2N/A }
2N/A
2N/A if (rcm_notify_online(rcm_handle, rsrc_fixed, 0, &rinfo) !=
2N/A RCM_SUCCESS && (rinfo != NULL)) {
2N/A DPRINTF("ib_rcm_online: rcm_notify_online failed\n");
2N/A
2N/A (void) ib_rcm_info_table(rinfo, errstring);
2N/A rcm_free_info(rinfo);
2N/A rinfo = NULL;
2N/A ret = CFGA_IB_RCM_ONLINE_ERR;
2N/A }
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function:
2N/A * ib_rcm_remove
2N/A * Input:
2N/A * rsrc - Resource name (typically an ap_id)
2N/A * errstring - Error message filled in case of a failure
2N/A * rsrc_fixed - Pointer to fixed path
2N/A * flags - flags to RCM
2N/A * Output:
2N/A * NONE
2N/A * Returns:
2N/A * CFGA_IB_OK on success or an appropriate error
2N/A * Description:
2N/A * Remove IB resource consumers after their kernel removal.
2N/A */
2N/Acfga_ib_ret_t
2N/Aib_rcm_remove(const char *rsrc, char **errstring, char *rsrc_fixed,
2N/A cfga_flags_t flags)
2N/A{
2N/A rcm_info_t *rinfo = NULL;
2N/A cfga_ib_ret_t ret = CFGA_IB_OK;
2N/A
2N/A DPRINTF("ib_rcm_remove:\n");
2N/A
2N/A if ((ret = ib_rcm_init(rsrc, flags, errstring, NULL)) != CFGA_IB_OK) {
2N/A return (ret);
2N/A }
2N/A
2N/A if (rcm_notify_remove(rcm_handle, rsrc_fixed, 0, &rinfo) !=
2N/A RCM_SUCCESS && (rinfo != NULL)) {
2N/A DPRINTF("ib_rcm_remove: rcm_notify_remove failed\n");
2N/A
2N/A (void) ib_rcm_info_table(rinfo, errstring);
2N/A rcm_free_info(rinfo);
2N/A rinfo = NULL;
2N/A ret = CFGA_IB_RCM_ONLINE_ERR;
2N/A }
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function:
2N/A * ib_rcm_init
2N/A * Input:
2N/A * rsrc - Resource name (typically an ap_id)
2N/A * flags - flags to RCM
2N/A * errstring - Error message filled in case of a failure
2N/A * rflags - Flags filled up in case of a failure
2N/A * Output:
2N/A * NONE
2N/A * Returns:
2N/A * CFGA_IB_OK on success or an appropriate error
2N/A * Description:
2N/A * Contains common initialization code for entering a ib_rcm_xx() routine.
2N/A */
2N/A/* ARGSUSED */
2N/Astatic cfga_ib_ret_t
2N/Aib_rcm_init(const char *rsrc, cfga_flags_t flags, char **errstring,
2N/A uint_t *rflags)
2N/A{
2N/A DPRINTF("ib_rcm_init:\n");
2N/A
2N/A /* Validate the rsrc argument */
2N/A if (rsrc == NULL) {
2N/A DPRINTF("ib_rcm_init: rsrc is NULL\n");
2N/A return (CFGA_IB_INTERNAL_ERR);
2N/A }
2N/A
2N/A /* Translate the cfgadm flags to RCM flags */
2N/A if (rflags && (flags & CFGA_FLAG_FORCE)) {
2N/A *rflags |= RCM_FORCE;
2N/A }
2N/A
2N/A /* Get a handle for the RCM operations */
2N/A (void) mutex_lock(&rcm_handle_lock);
2N/A if (rcm_handle == NULL) {
2N/A if (rcm_alloc_handle(NULL, RCM_NOPID, NULL, &rcm_handle) !=
2N/A RCM_SUCCESS) {
2N/A DPRINTF("ib_rcm_init: alloc_handle failed\n");
2N/A (void) mutex_unlock(&rcm_handle_lock);
2N/A return (CFGA_IB_RCM_HANDLE_ERR);
2N/A }
2N/A }
2N/A (void) mutex_unlock(&rcm_handle_lock);
2N/A return (CFGA_IB_OK);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function:
2N/A * ib_rcm_info_table
2N/A * Input:
2N/A * rinfo - Resource information
2N/A * table - table to be printed
2N/A * Output:
2N/A * NONE
2N/A * Returns:
2N/A * CFGA_IB_OK on success or an appropriate error
2N/A * Description:
2N/A * Takes an opaque rcm_info_t pointer and a character pointer,
2N/A * and appends the rcm_info_t data in the form of a table to the
2N/A * given character pointer.
2N/A */
2N/Astatic cfga_ib_ret_t
2N/Aib_rcm_info_table(rcm_info_t *rinfo, char **table)
2N/A{
2N/A int i;
2N/A size_t w;
2N/A size_t width = 0;
2N/A size_t w_rsrc = 0;
2N/A size_t w_info = 0;
2N/A size_t table_size = 0;
2N/A uint_t tuples = 0;
2N/A rcm_info_tuple_t *tuple = NULL;
2N/A char *rsrc;
2N/A char *info;
2N/A char *newtable;
2N/A static char format[MAX_FORMAT];
2N/A const char *infostr;
2N/A
2N/A DPRINTF("ib_rcm_info_table:\n");
2N/A
2N/A /* Protect against invalid arguments */
2N/A if (rinfo == NULL || table == NULL) {
2N/A return (CFGA_IB_INTERNAL_ERR);
2N/A }
2N/A
2N/A /* Set localized table header strings */
2N/A rsrc = dgettext(TEXT_DOMAIN, "Resource");
2N/A info = dgettext(TEXT_DOMAIN, "Information");
2N/A
2N/A /* A first pass, to size up the RCM information */
2N/A while (tuple = rcm_info_next(rinfo, tuple)) {
2N/A if ((infostr = rcm_info_info(tuple)) != NULL) {
2N/A tuples++;
2N/A if ((w = strlen(rcm_info_rsrc(tuple))) > w_rsrc)
2N/A w_rsrc = w;
2N/A if ((w = strlen(infostr)) > w_info)
2N/A w_info = w;
2N/A }
2N/A }
2N/A
2N/A /* If nothing was sized up above, stop early */
2N/A if (tuples == 0) {
2N/A DPRINTF("ib_rcm_info_table: no tuples\n");
2N/A return (CFGA_IB_OK);
2N/A }
2N/A
2N/A /* Adjust column widths for column headings */
2N/A if ((w = strlen(rsrc)) > w_rsrc) {
2N/A w_rsrc = w;
2N/A } else if ((w_rsrc - w) % 2) {
2N/A w_rsrc++;
2N/A }
2N/A
2N/A if ((w = strlen(info)) > w_info) {
2N/A w_info = w;
2N/A } else if ((w_info - w) % 2) {
2N/A w_info++;
2N/A }
2N/A
2N/A /*
2N/A * Compute the total line width of each line,
2N/A * accounting for intercolumn spacing.
2N/A */
2N/A width = w_info + w_rsrc + 4;
2N/A
2N/A /* Allocate space for the table */
2N/A table_size = (2 + tuples) * (width + 1) + 2;
2N/A if (*table == NULL) {
2N/A *table = malloc(table_size);
2N/A } else {
2N/A newtable = realloc(*table, strlen(*table) + table_size);
2N/A if (newtable != NULL)
2N/A *table = newtable;
2N/A else {
2N/A free(*table);
2N/A *table = NULL;
2N/A return (CFGA_IB_ALLOC_FAIL);
2N/A }
2N/A }
2N/A
2N/A if (*table == NULL) {
2N/A DPRINTF("ib_rcm_info_table: no table\n");
2N/A return (CFGA_IB_ALLOC_FAIL);
2N/A }
2N/A
2N/A /* Place a table header into the string */
2N/A
2N/A /* The resource header */
2N/A (void) strlcat(*table, "\n", sizeof (*table));
2N/A w = strlen(rsrc);
2N/A
2N/A for (i = 0; i < ((w_rsrc - w) / 2); i++) {
2N/A (void) strcat(*table, " ");
2N/A }
2N/A (void) strlcat(*table, rsrc, sizeof (*table));
2N/A
2N/A for (i = 0; i < ((w_rsrc - w) / 2); i++) {
2N/A (void) strcat(*table, " ");
2N/A }
2N/A
2N/A /* The information header */
2N/A (void) strcat(*table, " ");
2N/A w = strlen(info);
2N/A for (i = 0; i < ((w_info - w) / 2); i++) {
2N/A (void) strcat(*table, " ");
2N/A }
2N/A (void) strlcat(*table, info, sizeof (*table));
2N/A
2N/A for (i = 0; i < ((w_info - w) / 2); i++) {
2N/A (void) strcat(*table, " ");
2N/A }
2N/A
2N/A (void) strcat(*table, "\n");
2N/A
2N/A /* Underline the headers */
2N/A for (i = 0; i < w_rsrc; i++) {
2N/A (void) strcat(*table, "-");
2N/A }
2N/A
2N/A (void) strcat(*table, " ");
2N/A for (i = 0; i < w_info; i++) {
2N/A (void) strcat(*table, "-");
2N/A }
2N/A
2N/A (void) strcat(*table, "\n");
2N/A
2N/A /* Construct the format string */
2N/A (void) snprintf(format, MAX_FORMAT, "%%-%ds %%-%ds",
2N/A (int)w_rsrc, (int)w_info);
2N/A
2N/A /* Add the tuples to the table string */
2N/A tuple = NULL;
2N/A while ((tuple = rcm_info_next(rinfo, tuple)) != NULL) {
2N/A if ((infostr = rcm_info_info(tuple)) != NULL) {
2N/A (void) sprintf(&((*table)[strlen(*table)]),
2N/A format, rcm_info_rsrc(tuple), infostr);
2N/A (void) strcat(*table, "\n");
2N/A }
2N/A }
2N/A
2N/A return (CFGA_IB_OK);
2N/A}