25e8c5aa2b496d9026e958ac731a610167574f59vikram/*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * CDDL HEADER START
25e8c5aa2b496d9026e958ac731a610167574f59vikram *
25e8c5aa2b496d9026e958ac731a610167574f59vikram * The contents of this file are subject to the terms of the
25e8c5aa2b496d9026e958ac731a610167574f59vikram * Common Development and Distribution License (the "License").
25e8c5aa2b496d9026e958ac731a610167574f59vikram * You may not use this file except in compliance with the License.
25e8c5aa2b496d9026e958ac731a610167574f59vikram *
25e8c5aa2b496d9026e958ac731a610167574f59vikram * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
25e8c5aa2b496d9026e958ac731a610167574f59vikram * or http://www.opensolaris.org/os/licensing.
25e8c5aa2b496d9026e958ac731a610167574f59vikram * See the License for the specific language governing permissions
25e8c5aa2b496d9026e958ac731a610167574f59vikram * and limitations under the License.
25e8c5aa2b496d9026e958ac731a610167574f59vikram *
25e8c5aa2b496d9026e958ac731a610167574f59vikram * When distributing Covered Code, include this CDDL HEADER in each
25e8c5aa2b496d9026e958ac731a610167574f59vikram * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
25e8c5aa2b496d9026e958ac731a610167574f59vikram * If applicable, add the following below this CDDL HEADER, with the
25e8c5aa2b496d9026e958ac731a610167574f59vikram * fields enclosed by brackets "[]" replaced with your own identifying
25e8c5aa2b496d9026e958ac731a610167574f59vikram * information: Portions Copyright [yyyy] [name of copyright owner]
25e8c5aa2b496d9026e958ac731a610167574f59vikram *
25e8c5aa2b496d9026e958ac731a610167574f59vikram * CDDL HEADER END
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram/*
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram#include <libdevinfo.h>
25e8c5aa2b496d9026e958ac731a610167574f59vikram#include <sys/modctl.h>
25e8c5aa2b496d9026e958ac731a610167574f59vikram#include <sys/stat.h>
25e8c5aa2b496d9026e958ac731a610167574f59vikram#include <string.h>
25e8c5aa2b496d9026e958ac731a610167574f59vikram#include <librcm.h>
25e8c5aa2b496d9026e958ac731a610167574f59vikram#include <dlfcn.h>
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram#undef NDEBUG
25e8c5aa2b496d9026e958ac731a610167574f59vikram#include <assert.h>
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikramtypedef struct rio_path {
25e8c5aa2b496d9026e958ac731a610167574f59vikram char rpt_path[PATH_MAX];
25e8c5aa2b496d9026e958ac731a610167574f59vikram struct rio_path *rpt_next;
25e8c5aa2b496d9026e958ac731a610167574f59vikram} rio_path_t;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikramtypedef struct rcm_arg {
25e8c5aa2b496d9026e958ac731a610167574f59vikram char *rcm_root;
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_node_t rcm_node;
25e8c5aa2b496d9026e958ac731a610167574f59vikram int rcm_supp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram rcm_handle_t *rcm_handle;
25e8c5aa2b496d9026e958ac731a610167574f59vikram int rcm_retcode;
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_retire_t *rcm_dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram rio_path_t *rcm_cons_nodes;
25e8c5aa2b496d9026e958ac731a610167574f59vikram rio_path_t *rcm_rsrc_minors;
25e8c5aa2b496d9026e958ac731a610167574f59vikram int (*rcm_offline)();
25e8c5aa2b496d9026e958ac731a610167574f59vikram int (*rcm_online)();
25e8c5aa2b496d9026e958ac731a610167574f59vikram int (*rcm_remove)();
25e8c5aa2b496d9026e958ac731a610167574f59vikram} rcm_arg_t;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikramtypedef struct selector {
25e8c5aa2b496d9026e958ac731a610167574f59vikram char *sel_name;
25e8c5aa2b496d9026e958ac731a610167574f59vikram int (*sel_selector)(di_node_t node, rcm_arg_t *rp);
25e8c5aa2b496d9026e958ac731a610167574f59vikram} di_selector_t;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikramstatic void rio_assert(di_retire_t *dp, const char *EXstr, int line,
25e8c5aa2b496d9026e958ac731a610167574f59vikram const char *file);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram#define LIBRCM_PATH "/usr/lib/librcm.so"
25e8c5aa2b496d9026e958ac731a610167574f59vikram#define RIO_ASSERT(d, x) \
25e8c5aa2b496d9026e958ac731a610167574f59vikram {if (!(x)) rio_assert(d, #x, __LINE__, __FILE__); }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikramstatic int disk_select(di_node_t node, rcm_arg_t *rp);
25e8c5aa2b496d9026e958ac731a610167574f59vikramstatic int nexus_select(di_node_t node, rcm_arg_t *rp);
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hansonstatic int enclosure_select(di_node_t node, rcm_arg_t *rp);
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hansonstatic int smp_select(di_node_t node, rcm_arg_t *rp);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikramdi_selector_t supported_devices[] = {
25e8c5aa2b496d9026e958ac731a610167574f59vikram {"disk", disk_select},
25e8c5aa2b496d9026e958ac731a610167574f59vikram {"nexus", nexus_select},
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson {"enclosure", enclosure_select},
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson {"smp", smp_select},
25e8c5aa2b496d9026e958ac731a610167574f59vikram {NULL, NULL}
25e8c5aa2b496d9026e958ac731a610167574f59vikram};
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikramvoid *
25e8c5aa2b496d9026e958ac731a610167574f59vikrams_calloc(size_t nelem, size_t elsize, int fail)
25e8c5aa2b496d9026e958ac731a610167574f59vikram{
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (fail) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram errno = ENOMEM;
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (NULL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram } else {
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (calloc(nelem, elsize));
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram}
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikramstatic void
25e8c5aa2b496d9026e958ac731a610167574f59vikramrio_assert(di_retire_t *dp, const char *EXstr, int line, const char *file)
25e8c5aa2b496d9026e958ac731a610167574f59vikram{
25e8c5aa2b496d9026e958ac731a610167574f59vikram char buf[PATH_MAX];
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (dp->rt_abort == NULL)
25e8c5aa2b496d9026e958ac731a610167574f59vikram assert(0);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram (void) snprintf(buf, sizeof (buf),
25e8c5aa2b496d9026e958ac731a610167574f59vikram "Assertion failed: %s, file %s, line %d\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram EXstr, file, line);
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_abort(dp->rt_hdl, buf);
25e8c5aa2b496d9026e958ac731a610167574f59vikram}
25e8c5aa2b496d9026e958ac731a610167574f59vikram
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson/*ARGSUSED*/
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hansonstatic int
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hansonenclosure_minor(di_node_t node, di_minor_t minor, void *arg)
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson{
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson rcm_arg_t *rp = (rcm_arg_t *)arg;
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson di_retire_t *dp = rp->rcm_dp;
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson rp->rcm_supp = 1;
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson dp->rt_debug(dp->rt_hdl, "[INFO]: enclosure_minor: "
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson "IDed this node as enclosure\n");
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson return (DI_WALK_TERMINATE);
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson}
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hansonstatic int
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hansonenclosure_select(di_node_t node, rcm_arg_t *rp)
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson{
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson rcm_arg_t rarg;
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson di_retire_t *dp = rp->rcm_dp;
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson rarg.rcm_dp = dp;
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson /*
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson * Check if this is an enclosure minor. If any one minor is DDI_NT_SGEN
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson * or DDI_NT_SCSI_ENCLOSURE we assume it is an enclosure.
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson */
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson rarg.rcm_supp = 0;
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson if (di_walk_minor(node, DDI_NT_SCSI_ENCLOSURE, 0, &rarg,
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson enclosure_minor) != 0) {
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson dp->rt_debug(dp->rt_hdl, "[INFO]: enclosure_select:"
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson "di_walk_minor failed. Returning NOTSUP\n");
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson return (0);
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson }
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson if (di_walk_minor(node, "ddi_generic:scsi", 0, &rarg,
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson enclosure_minor) != 0) {
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson dp->rt_debug(dp->rt_hdl, "[INFO]: enclosure_select:"
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson "di_walk_minor failed. Returning NOTSUP\n");
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson return (0);
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson }
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson return (rarg.rcm_supp);
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson}
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson/*ARGSUSED*/
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hansonstatic int
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hansonsmp_minor(di_node_t node, di_minor_t minor, void *arg)
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson{
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson rcm_arg_t *rp = (rcm_arg_t *)arg;
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson di_retire_t *dp = rp->rcm_dp;
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson rp->rcm_supp = 1;
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson dp->rt_debug(dp->rt_hdl, "[INFO]: smp_minor: "
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson "IDed this node as smp\n");
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson return (DI_WALK_TERMINATE);
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson}
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hansonstatic int
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hansonsmp_select(di_node_t node, rcm_arg_t *rp)
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson{
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson rcm_arg_t rarg;
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson di_retire_t *dp = rp->rcm_dp;
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson rarg.rcm_dp = dp;
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson /*
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson * Check if this is an smp minor. If any one minor is DDI_NT_SMP
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson * we assume it is an smp.
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson */
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson rarg.rcm_supp = 0;
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson if (di_walk_minor(node, DDI_NT_SMP, 0, &rarg, smp_minor) != 0) {
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson dp->rt_debug(dp->rt_hdl, "[INFO]: smp_select:"
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson "di_walk_minor failed. Returning NOTSUP\n");
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson return (0);
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson }
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson return (rarg.rcm_supp);
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson}
f76de7499b0498d120c0c5ba970d061ccb587552Stephen Hanson
25e8c5aa2b496d9026e958ac731a610167574f59vikram/*ARGSUSED*/
25e8c5aa2b496d9026e958ac731a610167574f59vikramstatic int
25e8c5aa2b496d9026e958ac731a610167574f59vikramdisk_minor(di_node_t node, di_minor_t minor, void *arg)
25e8c5aa2b496d9026e958ac731a610167574f59vikram{
25e8c5aa2b496d9026e958ac731a610167574f59vikram rcm_arg_t *rp = (rcm_arg_t *)arg;
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_retire_t *dp = rp->rcm_dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (di_minor_spectype(minor) == S_IFBLK) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_supp = 1;
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: disk_minor: is disk minor. "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "IDed this node as disk\n");
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (DI_WALK_TERMINATE);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: disk_minor: Not a disk minor. "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "Continuing minor walk\n");
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (DI_WALK_CONTINUE);
25e8c5aa2b496d9026e958ac731a610167574f59vikram}
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikramstatic int
25e8c5aa2b496d9026e958ac731a610167574f59vikramdisk_select(di_node_t node, rcm_arg_t *rp)
25e8c5aa2b496d9026e958ac731a610167574f59vikram{
25e8c5aa2b496d9026e958ac731a610167574f59vikram rcm_arg_t rarg;
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_retire_t *dp = rp->rcm_dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram rarg.rcm_dp = dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram /*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * Check if this is a disk minor. If any one minor is DDI_NT_BLOCK
25e8c5aa2b496d9026e958ac731a610167574f59vikram * we assume it is a disk
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram rarg.rcm_supp = 0;
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (di_walk_minor(node, DDI_NT_BLOCK, 0, &rarg, disk_minor) != 0) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: disk_select: di_walk_minor "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "failed. Returning NOTSUP\n");
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (0);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (rarg.rcm_supp);
25e8c5aa2b496d9026e958ac731a610167574f59vikram}
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikramstatic int
25e8c5aa2b496d9026e958ac731a610167574f59vikramnexus_select(di_node_t node, rcm_arg_t *rp)
25e8c5aa2b496d9026e958ac731a610167574f59vikram{
25e8c5aa2b496d9026e958ac731a610167574f59vikram int select;
25e8c5aa2b496d9026e958ac731a610167574f59vikram char *path;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_retire_t *dp = rp->rcm_dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram path = di_devfs_path(node);
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (path == NULL) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: nexus_select: "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "di_devfs_path() is NULL. Returning NOTSUP\n");
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (0);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram /*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * Check if it is a nexus
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (di_driver_ops(node) & DI_BUS_OPS) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: nexus_select: is nexus %s\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram select = 1;
25e8c5aa2b496d9026e958ac731a610167574f59vikram } else {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: nexus_select: not nexus %s\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram select = 0;
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_devfs_path_free(path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (select);
25e8c5aa2b496d9026e958ac731a610167574f59vikram}
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikramstatic int
25e8c5aa2b496d9026e958ac731a610167574f59vikramnode_select(di_node_t node, void *arg)
25e8c5aa2b496d9026e958ac731a610167574f59vikram{
25e8c5aa2b496d9026e958ac731a610167574f59vikram rcm_arg_t *rp = (rcm_arg_t *)arg;
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_retire_t *dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram int sel;
25e8c5aa2b496d9026e958ac731a610167574f59vikram int i;
25e8c5aa2b496d9026e958ac731a610167574f59vikram char *path;
25e8c5aa2b496d9026e958ac731a610167574f59vikram uint_t state;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp = rp->rcm_dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram /* skip pseudo nodes - we only retire real hardware */
25e8c5aa2b496d9026e958ac731a610167574f59vikram path = di_devfs_path(node);
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (strncmp(path, "/pseudo/", strlen("/pseudo/")) == 0 ||
25e8c5aa2b496d9026e958ac731a610167574f59vikram strcmp(path, "/pseudo") == 0) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: node_select: "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "pseudo device in subtree - returning NOTSUP: %s\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_supp = 0;
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_devfs_path_free(path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (DI_WALK_TERMINATE);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_devfs_path_free(path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram /*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * If a device is offline/detached/down it is
25e8c5aa2b496d9026e958ac731a610167574f59vikram * retireable irrespective of the type of device,
25e8c5aa2b496d9026e958ac731a610167574f59vikram * presumably the system is able to function without
25e8c5aa2b496d9026e958ac731a610167574f59vikram * it.
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram state = di_state(node);
25e8c5aa2b496d9026e958ac731a610167574f59vikram if ((state & DI_DRIVER_DETACHED) || (state & DI_DEVICE_OFFLINE) ||
25e8c5aa2b496d9026e958ac731a610167574f59vikram (state & DI_BUS_DOWN)) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: node_select: device "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "is offline/detached. Assuming retire supported\n");
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (DI_WALK_CONTINUE);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram sel = 0;
25e8c5aa2b496d9026e958ac731a610167574f59vikram for (i = 0; supported_devices[i].sel_name != NULL; i++) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram sel = supported_devices[i].sel_selector(node, rp);
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (sel == 1) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: node_select: "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "found supported device: %s\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram supported_devices[i].sel_name);
25e8c5aa2b496d9026e958ac731a610167574f59vikram break;
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (sel != 1) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram /*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * This node is not a supported device. Retire cannot proceed
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: node_select: found "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "unsupported device. Returning NOTSUP\n");
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_supp = 0;
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (DI_WALK_TERMINATE);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram /*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * This node is supported. Check other nodes in this subtree.
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: node_select: This node supported. "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "Checking other nodes in subtree: %s\n", rp->rcm_root);
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (DI_WALK_CONTINUE);
25e8c5aa2b496d9026e958ac731a610167574f59vikram}
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram/*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * when in doubt assume that retire is not supported for this device.
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikramstatic int
25e8c5aa2b496d9026e958ac731a610167574f59vikramretire_supported(rcm_arg_t *rp)
25e8c5aa2b496d9026e958ac731a610167574f59vikram{
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_retire_t *dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_node_t rnode = rp->rcm_node;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp = rp->rcm_dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram /*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * We should not be here if devinfo snapshot is NULL.
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram RIO_ASSERT(dp, rnode != DI_NODE_NIL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram /*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * Note: We initally set supported to 1, then walk the
25e8c5aa2b496d9026e958ac731a610167574f59vikram * subtree rooted at devpath, allowing each node the
25e8c5aa2b496d9026e958ac731a610167574f59vikram * opportunity to veto the support. We cannot do things
25e8c5aa2b496d9026e958ac731a610167574f59vikram * the other way around i.e. assume "not supported" and
25e8c5aa2b496d9026e958ac731a610167574f59vikram * let individual nodes indicate that they are supported.
25e8c5aa2b496d9026e958ac731a610167574f59vikram * In the latter case, the supported flag would be set
25e8c5aa2b496d9026e958ac731a610167574f59vikram * if any one node in the subtree was supported which is
25e8c5aa2b496d9026e958ac731a610167574f59vikram * not what we want.
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_supp = 1;
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (di_walk_node(rnode, DI_WALK_CLDFIRST, rp, node_select) != 0) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: retire_supported: "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "di_walk_node: failed. Returning NOTSUP\n");
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_supp = 0;
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (rp->rcm_supp) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: retire IS supported\n");
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (rp->rcm_supp);
25e8c5aa2b496d9026e958ac731a610167574f59vikram}
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikramstatic void
25e8c5aa2b496d9026e958ac731a610167574f59vikramrcm_finalize(rcm_arg_t *rp, int retcode)
25e8c5aa2b496d9026e958ac731a610167574f59vikram{
25e8c5aa2b496d9026e958ac731a610167574f59vikram rio_path_t *p;
25e8c5aa2b496d9026e958ac731a610167574f59vikram rio_path_t *tmp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram int flags = RCM_RETIRE_NOTIFY;
25e8c5aa2b496d9026e958ac731a610167574f59vikram int retval;
25e8c5aa2b496d9026e958ac731a610167574f59vikram int error;
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_retire_t *dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp = rp->rcm_dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram RIO_ASSERT(dp, retcode == 0 || retcode == -1);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: rcm_finalize: retcode=%d: dev=%s\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram retcode, rp->rcm_root);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram for (p = rp->rcm_cons_nodes; p; ) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram tmp = p;
25e8c5aa2b496d9026e958ac731a610167574f59vikram p = tmp->rpt_next;
25e8c5aa2b496d9026e958ac731a610167574f59vikram free(tmp);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_cons_nodes = NULL;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: rcm_finalize: cons_nodes NULL\n");
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram for (p = rp->rcm_rsrc_minors; p; ) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram tmp = p;
25e8c5aa2b496d9026e958ac731a610167574f59vikram p = tmp->rpt_next;
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (retcode == 0) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram retval = rp->rcm_remove(rp->rcm_handle,
25e8c5aa2b496d9026e958ac731a610167574f59vikram tmp->rpt_path, flags, NULL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram error = errno;
25e8c5aa2b496d9026e958ac731a610167574f59vikram } else {
25e8c5aa2b496d9026e958ac731a610167574f59vikram RIO_ASSERT(dp, retcode == -1);
25e8c5aa2b496d9026e958ac731a610167574f59vikram retval = rp->rcm_online(rp->rcm_handle,
25e8c5aa2b496d9026e958ac731a610167574f59vikram tmp->rpt_path, flags, NULL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram error = errno;
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (retval != RCM_SUCCESS) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: rcm_finalize: "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "rcm_%s: retval=%d: error=%s: path=%s\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram retcode == 0 ? "remove" : "online", retval,
25e8c5aa2b496d9026e958ac731a610167574f59vikram strerror(error), tmp->rpt_path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram } else {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: rcm_finalize: "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "rcm_%s: SUCCESS: path=%s\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram retcode == 0 ? "remove" : "online", tmp->rpt_path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram free(tmp);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_rsrc_minors = NULL;
25e8c5aa2b496d9026e958ac731a610167574f59vikram}
25e8c5aa2b496d9026e958ac731a610167574f59vikram/*ARGSUSED*/
25e8c5aa2b496d9026e958ac731a610167574f59vikramstatic int
25e8c5aa2b496d9026e958ac731a610167574f59vikramcall_offline(di_node_t node, di_minor_t minor, void *arg)
25e8c5aa2b496d9026e958ac731a610167574f59vikram{
25e8c5aa2b496d9026e958ac731a610167574f59vikram rcm_arg_t *rp = (rcm_arg_t *)arg;
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_retire_t *dp = rp->rcm_dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram char *mnp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram rio_path_t *rpt;
25e8c5aa2b496d9026e958ac731a610167574f59vikram int retval;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram mnp = di_devfs_minor_path(minor);
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (mnp == NULL) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: di_devfs_minor_path "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "failed. Returning RCM FAILURE: %s\n", rp->rcm_root);
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_retcode = RCM_FAILURE;
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (DI_WALK_TERMINATE);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram rpt = s_calloc(1, sizeof (rio_path_t), 0);
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (rpt == NULL) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: calloc failed. "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "Returning RCM FAILURE: %s\n", rp->rcm_root);
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_devfs_path_free(mnp);
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_retcode = RCM_FAILURE;
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (DI_WALK_TERMINATE);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram (void) snprintf(rpt->rpt_path, sizeof (rpt->rpt_path),
25e8c5aa2b496d9026e958ac731a610167574f59vikram "/devices%s", mnp);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_devfs_path_free(mnp);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram retval = rp->rcm_offline(rp->rcm_handle, rpt->rpt_path,
25e8c5aa2b496d9026e958ac731a610167574f59vikram RCM_RETIRE_REQUEST, NULL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram rpt->rpt_next = rp->rcm_rsrc_minors;
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_rsrc_minors = rpt;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (retval == RCM_FAILURE) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: RCM OFFLINE failed "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "for: %s\n", rpt->rpt_path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_retcode = RCM_FAILURE;
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (DI_WALK_TERMINATE);
25e8c5aa2b496d9026e958ac731a610167574f59vikram } else if (retval == RCM_SUCCESS) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_retcode = RCM_SUCCESS;
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: RCM OFFLINE returned "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "RCM_SUCCESS: %s\n", rpt->rpt_path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram } else if (retval != RCM_NO_CONSTRAINT) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: RCM OFFLINE returned "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "invalid value for: %s\n", rpt->rpt_path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_retcode = RCM_FAILURE;
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (DI_WALK_TERMINATE);
25e8c5aa2b496d9026e958ac731a610167574f59vikram } else {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: RCM OFFLINE returned "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "RCM_NO_CONSTRAINT: %s\n", rpt->rpt_path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (DI_WALK_CONTINUE);
25e8c5aa2b496d9026e958ac731a610167574f59vikram}
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikramstatic int
25e8c5aa2b496d9026e958ac731a610167574f59vikramoffline_one(di_node_t node, void *arg)
25e8c5aa2b496d9026e958ac731a610167574f59vikram{
25e8c5aa2b496d9026e958ac731a610167574f59vikram rcm_arg_t *rp = (rcm_arg_t *)arg;
25e8c5aa2b496d9026e958ac731a610167574f59vikram rio_path_t *rpt;
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_retire_t *dp = rp->rcm_dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram char *path;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram /*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * We should already have terminated the walk
25e8c5aa2b496d9026e958ac731a610167574f59vikram * in case of failure
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram RIO_ASSERT(dp, rp->rcm_retcode == RCM_SUCCESS ||
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_retcode == RCM_NO_CONSTRAINT);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: offline_one: entered\n");
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_retcode = RCM_NO_CONSTRAINT;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram rpt = s_calloc(1, sizeof (rio_path_t), 0);
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (rpt == NULL) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: rio_path_t calloc "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "failed: error: %s\n", strerror(errno));
25e8c5aa2b496d9026e958ac731a610167574f59vikram goto fail;
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram path = di_devfs_path(node);
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (path == NULL) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: di_devfs_path "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "failed: error: %s\n", strerror(errno));
25e8c5aa2b496d9026e958ac731a610167574f59vikram free(rpt);
25e8c5aa2b496d9026e958ac731a610167574f59vikram goto fail;
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram (void) strlcpy(rpt->rpt_path, path, sizeof (rpt->rpt_path));
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_devfs_path_free(path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (di_walk_minor(node, NULL, 0, rp, call_offline) != 0) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: di_walk_minor "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "failed: error: %s: %s\n", strerror(errno), path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram free(rpt);
25e8c5aa2b496d9026e958ac731a610167574f59vikram goto fail;
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (rp->rcm_retcode == RCM_FAILURE) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: di_walk_minor "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "returned: RCM_FAILURE: %s\n", rpt->rpt_path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram free(rpt);
25e8c5aa2b496d9026e958ac731a610167574f59vikram goto fail;
25e8c5aa2b496d9026e958ac731a610167574f59vikram } else if (rp->rcm_retcode == RCM_SUCCESS) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: di_walk_minor "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "returned: RCM_SUCCESS: %s\n", rpt->rpt_path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram rpt->rpt_next = rp->rcm_cons_nodes;
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_cons_nodes = rpt;
25e8c5aa2b496d9026e958ac731a610167574f59vikram } else if (rp->rcm_retcode != RCM_NO_CONSTRAINT) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: di_walk_minor "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "returned: unknown RCM error code: %d, %s\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_retcode, rpt->rpt_path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram free(rpt);
25e8c5aa2b496d9026e958ac731a610167574f59vikram goto fail;
25e8c5aa2b496d9026e958ac731a610167574f59vikram } else {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: di_walk_minor "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "returned: RCM_NO_CONSTRAINT: %s\n", rpt->rpt_path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram free(rpt);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram /*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * RCM_SUCCESS or RCM_NO_CONSTRAINT.
25e8c5aa2b496d9026e958ac731a610167574f59vikram * RCM_SUCCESS implies we overcame a constraint, so keep walking.
25e8c5aa2b496d9026e958ac731a610167574f59vikram * RCM_NO_CONSTRAINT implies no constraints applied via RCM.
25e8c5aa2b496d9026e958ac731a610167574f59vikram * Continue walking in the hope that contracts or LDI will
25e8c5aa2b496d9026e958ac731a610167574f59vikram * apply constraints
25e8c5aa2b496d9026e958ac731a610167574f59vikram * set retcode to RCM_SUCCESS to show that at least 1 node
25e8c5aa2b496d9026e958ac731a610167574f59vikram * completely walked
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_retcode = RCM_SUCCESS;
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (DI_WALK_CONTINUE);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikramfail:
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_retcode = RCM_FAILURE;
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (DI_WALK_TERMINATE);
25e8c5aa2b496d9026e958ac731a610167574f59vikram}
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram/*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * Returns:
25e8c5aa2b496d9026e958ac731a610167574f59vikram * RCM_SUCCESS: RCM constraints (if any) were applied. The
25e8c5aa2b496d9026e958ac731a610167574f59vikram * device paths for which constraints were applied is passed
25e8c5aa2b496d9026e958ac731a610167574f59vikram * back via the pp argument
25e8c5aa2b496d9026e958ac731a610167574f59vikram *
25e8c5aa2b496d9026e958ac731a610167574f59vikram * RCM_FAILURE: Either RCM constraints prevent a retire or
25e8c5aa2b496d9026e958ac731a610167574f59vikram * an error occurred
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikramstatic int
25e8c5aa2b496d9026e958ac731a610167574f59vikramrcm_notify(rcm_arg_t *rp, char **pp, size_t *clen)
25e8c5aa2b496d9026e958ac731a610167574f59vikram{
25e8c5aa2b496d9026e958ac731a610167574f59vikram size_t len;
25e8c5aa2b496d9026e958ac731a610167574f59vikram rio_path_t *p;
25e8c5aa2b496d9026e958ac731a610167574f59vikram rio_path_t *tmp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram char *plistp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram char *s;
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_retire_t *dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_node_t rnode;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp = rp->rcm_dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: rcm_notify() entered\n");
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram RIO_ASSERT(dp, rp->rcm_root);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram *pp = NULL;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram rnode = rp->rcm_node;
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (rnode == DI_NODE_NIL) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: devinfo snapshot "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "NULL. Returning no RCM constraint: %s\n", rp->rcm_root);
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (RCM_NO_CONSTRAINT);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_retcode = RCM_NO_CONSTRAINT;
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_cons_nodes = NULL;
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_rsrc_minors = NULL;
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (di_walk_node(rnode, DI_WALK_CLDFIRST, rp, offline_one) != 0) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: di_walk_node "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "failed: error: %s: %s\n", strerror(errno), rp->rcm_root);
25e8c5aa2b496d9026e958ac731a610167574f59vikram /* online is idempotent - safe to online non-offlined nodes */
25e8c5aa2b496d9026e958ac731a610167574f59vikram rcm_finalize(rp, -1);
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_retcode = RCM_FAILURE;
25e8c5aa2b496d9026e958ac731a610167574f59vikram goto out;
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (rp->rcm_retcode == RCM_FAILURE) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: walk_node "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "returned retcode of RCM_FAILURE: %s\n", rp->rcm_root);
25e8c5aa2b496d9026e958ac731a610167574f59vikram rcm_finalize(rp, -1);
25e8c5aa2b496d9026e958ac731a610167574f59vikram goto out;
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (rp->rcm_retcode == RCM_NO_CONSTRAINT) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: di_walk_node "
25e8c5aa2b496d9026e958ac731a610167574f59vikram " - no nodes walked: RCM_NO_CONSTRAINT: %s\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_root);
25e8c5aa2b496d9026e958ac731a610167574f59vikram } else {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: walk_node: RCM_SUCCESS\n");
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram /*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * Convert to a sequence of NUL separated strings terminated by '\0'\0'
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram for (len = 0, p = rp->rcm_cons_nodes; p; p = p->rpt_next) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram RIO_ASSERT(dp, p->rpt_path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram RIO_ASSERT(dp, strlen(p->rpt_path) > 0);
25e8c5aa2b496d9026e958ac731a610167574f59vikram len += (strlen(p->rpt_path) + 1);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram len++; /* list terminating '\0' */
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: len of constraint str = %lu\n", len);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram plistp = s_calloc(1, len, 0);
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (plistp == NULL) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: fail to alloc "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "constraint list: error: %s: %s\n", strerror(errno),
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_root);
25e8c5aa2b496d9026e958ac731a610167574f59vikram rcm_finalize(rp, -1);
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_retcode = RCM_FAILURE;
25e8c5aa2b496d9026e958ac731a610167574f59vikram goto out;
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram for (s = plistp, p = rp->rcm_cons_nodes; p; ) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram tmp = p;
25e8c5aa2b496d9026e958ac731a610167574f59vikram p = tmp->rpt_next;
25e8c5aa2b496d9026e958ac731a610167574f59vikram (void) strcpy(s, tmp->rpt_path);
25e8c5aa2b496d9026e958ac731a610167574f59vikram s += strlen(s) + 1;
25e8c5aa2b496d9026e958ac731a610167574f59vikram RIO_ASSERT(dp, s - plistp < len);
25e8c5aa2b496d9026e958ac731a610167574f59vikram free(tmp);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_cons_nodes = NULL;
25e8c5aa2b496d9026e958ac731a610167574f59vikram RIO_ASSERT(dp, s - plistp == len - 1);
25e8c5aa2b496d9026e958ac731a610167574f59vikram *s = '\0';
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: constraint str = %p\n", plistp);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram *pp = plistp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram *clen = len;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram rp->rcm_retcode = RCM_SUCCESS;
25e8c5aa2b496d9026e958ac731a610167574f59vikramout:
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (rp->rcm_retcode);
25e8c5aa2b496d9026e958ac731a610167574f59vikram}
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram/*ARGSUSED*/
25e8c5aa2b496d9026e958ac731a610167574f59vikramint
25e8c5aa2b496d9026e958ac731a610167574f59vikramdi_retire_device(char *devpath, di_retire_t *dp, int flags)
25e8c5aa2b496d9026e958ac731a610167574f59vikram{
25e8c5aa2b496d9026e958ac731a610167574f59vikram char path[PATH_MAX];
25e8c5aa2b496d9026e958ac731a610167574f59vikram struct stat sb;
25e8c5aa2b496d9026e958ac731a610167574f59vikram int retval = EINVAL;
25e8c5aa2b496d9026e958ac731a610167574f59vikram char *constraint = NULL;
25e8c5aa2b496d9026e958ac731a610167574f59vikram size_t clen;
25e8c5aa2b496d9026e958ac731a610167574f59vikram void *librcm_hdl;
25e8c5aa2b496d9026e958ac731a610167574f59vikram rcm_arg_t rarg = {0};
25e8c5aa2b496d9026e958ac731a610167574f59vikram int (*librcm_alloc_handle)();
25e8c5aa2b496d9026e958ac731a610167574f59vikram int (*librcm_free_handle)();
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (dp == NULL || dp->rt_debug == NULL || dp->rt_hdl == NULL)
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (EINVAL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (devpath == NULL || devpath[0] == '\0') {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: NULL argument(s)\n");
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (EINVAL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (devpath[0] != '/' || strlen(devpath) >= PATH_MAX ||
25e8c5aa2b496d9026e958ac731a610167574f59vikram strncmp(devpath, "/devices/", strlen("/devices/")) == 0 ||
25e8c5aa2b496d9026e958ac731a610167574f59vikram strstr(devpath, "../devices/") || strrchr(devpath, ':')) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: invalid devpath: %s\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram devpath);
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (EINVAL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (flags != 0) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: flags should be 0: %d\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram flags);
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (EINVAL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram /*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * dlopen rather than link against librcm since libdevinfo
25e8c5aa2b496d9026e958ac731a610167574f59vikram * resides in / and librcm resides in /usr. The dlopen is
25e8c5aa2b496d9026e958ac731a610167574f59vikram * safe to do since fmd which invokes the retire code
25e8c5aa2b496d9026e958ac731a610167574f59vikram * resides on /usr and will not come here until /usr is
25e8c5aa2b496d9026e958ac731a610167574f59vikram * mounted.
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram librcm_hdl = dlopen(LIBRCM_PATH, RTLD_LAZY);
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (librcm_hdl == NULL) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram char *errstr = dlerror();
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: Cannot dlopen librcm: %s\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram errstr ? errstr : "Unknown error");
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (ENOSYS);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram librcm_alloc_handle = (int (*)())dlsym(librcm_hdl, "rcm_alloc_handle");
25e8c5aa2b496d9026e958ac731a610167574f59vikram rarg.rcm_offline = (int (*)())dlsym(librcm_hdl, "rcm_request_offline");
25e8c5aa2b496d9026e958ac731a610167574f59vikram rarg.rcm_online = (int (*)())dlsym(librcm_hdl, "rcm_notify_online");
25e8c5aa2b496d9026e958ac731a610167574f59vikram rarg.rcm_remove = (int (*)())dlsym(librcm_hdl, "rcm_notify_remove");
25e8c5aa2b496d9026e958ac731a610167574f59vikram librcm_free_handle = (int (*)())dlsym(librcm_hdl, "rcm_free_handle");
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (librcm_alloc_handle == NULL ||
25e8c5aa2b496d9026e958ac731a610167574f59vikram rarg.rcm_offline == NULL ||
25e8c5aa2b496d9026e958ac731a610167574f59vikram rarg.rcm_online == NULL ||
25e8c5aa2b496d9026e958ac731a610167574f59vikram rarg.rcm_remove == NULL ||
25e8c5aa2b496d9026e958ac731a610167574f59vikram librcm_free_handle == NULL) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: dlsym failed\n");
25e8c5aa2b496d9026e958ac731a610167574f59vikram retval = ENOSYS;
25e8c5aa2b496d9026e958ac731a610167574f59vikram goto out;
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram /*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * Take a libdevinfo snapshot here because we cannot do so
25e8c5aa2b496d9026e958ac731a610167574f59vikram * after device is retired. If device doesn't attach, we retire
25e8c5aa2b496d9026e958ac731a610167574f59vikram * anyway i.e. it is not fatal.
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram rarg.rcm_node = di_init(devpath, DINFOCPYALL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (rarg.rcm_node == DI_NODE_NIL) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: device doesn't attach, "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "retiring anyway: %s\n", devpath);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram rarg.rcm_handle = NULL;
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (librcm_alloc_handle(NULL, 0, NULL, &rarg.rcm_handle)
25e8c5aa2b496d9026e958ac731a610167574f59vikram != RCM_SUCCESS) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram retval = errno;
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: failed to alloc "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "RCM handle. Returning RCM failure: %s\n", devpath);
25e8c5aa2b496d9026e958ac731a610167574f59vikram rarg.rcm_handle = NULL;
25e8c5aa2b496d9026e958ac731a610167574f59vikram goto out;
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram rarg.rcm_root = devpath;
25e8c5aa2b496d9026e958ac731a610167574f59vikram rarg.rcm_dp = dp;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram /*
25e8c5aa2b496d9026e958ac731a610167574f59vikram * If device is already detached/nonexistent and cannot be
25e8c5aa2b496d9026e958ac731a610167574f59vikram * attached, allow retire without checking device type.
25e8c5aa2b496d9026e958ac731a610167574f59vikram * XXX
25e8c5aa2b496d9026e958ac731a610167574f59vikram * Else, check if retire is supported for this device type.
25e8c5aa2b496d9026e958ac731a610167574f59vikram */
25e8c5aa2b496d9026e958ac731a610167574f59vikram (void) snprintf(path, sizeof (path), "/devices%s", devpath);
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (stat(path, &sb) == -1 || !S_ISDIR(sb.st_mode)) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: detached or nonexistent "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "device. Bypassing retire_supported: %s\n", devpath);
25e8c5aa2b496d9026e958ac731a610167574f59vikram } else if (!retire_supported(&rarg)) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: retire not supported for "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "device type: %s\n", devpath);
25e8c5aa2b496d9026e958ac731a610167574f59vikram retval = ENOTSUP;
25e8c5aa2b496d9026e958ac731a610167574f59vikram goto out;
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram clen = 0;
25e8c5aa2b496d9026e958ac731a610167574f59vikram constraint = NULL;
25e8c5aa2b496d9026e958ac731a610167574f59vikram retval = rcm_notify(&rarg, &constraint, &clen);
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (retval == RCM_FAILURE) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram /* retire not permitted */
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: RCM constraints block "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "retire: %s\n", devpath);
25e8c5aa2b496d9026e958ac731a610167574f59vikram retval = EBUSY;
25e8c5aa2b496d9026e958ac731a610167574f59vikram goto out;
25e8c5aa2b496d9026e958ac731a610167574f59vikram } else if (retval == RCM_SUCCESS) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: RCM constraints applied"
25e8c5aa2b496d9026e958ac731a610167574f59vikram ": %s\n", devpath);
25e8c5aa2b496d9026e958ac731a610167574f59vikram } else if (retval == RCM_NO_CONSTRAINT) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: No RCM constraints applied"
25e8c5aa2b496d9026e958ac731a610167574f59vikram ": %s\n", devpath);
25e8c5aa2b496d9026e958ac731a610167574f59vikram } else {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: notify returned unknown "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "return code: %d: %s\n", retval, devpath);
25e8c5aa2b496d9026e958ac731a610167574f59vikram retval = ESRCH;
25e8c5aa2b496d9026e958ac731a610167574f59vikram goto out;
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (modctl(MODRETIRE, devpath, constraint, clen) != 0) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram retval = errno;
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: retire modctl() failed: "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "%s: %s\n", devpath, strerror(retval));
25e8c5aa2b496d9026e958ac731a610167574f59vikram rcm_finalize(&rarg, -1);
25e8c5aa2b496d9026e958ac731a610167574f59vikram goto out;
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: retire modctl() succeeded: %s\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram devpath);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram rcm_finalize(&rarg, 0);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram retval = 0;
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikramout:
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (rarg.rcm_handle)
25e8c5aa2b496d9026e958ac731a610167574f59vikram (void) librcm_free_handle(rarg.rcm_handle);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram RIO_ASSERT(dp, rarg.rcm_cons_nodes == NULL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram RIO_ASSERT(dp, rarg.rcm_rsrc_minors == NULL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram (void) dlclose(librcm_hdl);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram free(constraint);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (rarg.rcm_node != DI_NODE_NIL)
25e8c5aa2b496d9026e958ac731a610167574f59vikram di_fini(rarg.rcm_node);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (retval);
25e8c5aa2b496d9026e958ac731a610167574f59vikram}
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram/*ARGSUSED*/
25e8c5aa2b496d9026e958ac731a610167574f59vikramint
25e8c5aa2b496d9026e958ac731a610167574f59vikramdi_unretire_device(char *devpath, di_retire_t *dp)
25e8c5aa2b496d9026e958ac731a610167574f59vikram{
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (dp == NULL || dp->rt_debug == NULL || dp->rt_hdl == NULL)
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (EINVAL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (devpath == NULL || devpath[0] == '\0') {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: NULL devpath\n");
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (EINVAL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (devpath[0] != '/' || strlen(devpath) >= PATH_MAX ||
25e8c5aa2b496d9026e958ac731a610167574f59vikram strncmp(devpath, "/devices/", strlen("/devices/")) == 0 ||
25e8c5aa2b496d9026e958ac731a610167574f59vikram strstr(devpath, "../devices/") || strrchr(devpath, ':')) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: invalid devpath: %s\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram devpath);
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (EINVAL);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram if (modctl(MODUNRETIRE, devpath) != 0) {
25e8c5aa2b496d9026e958ac731a610167574f59vikram int err = errno;
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[ERROR]: unretire modctl() failed: "
25e8c5aa2b496d9026e958ac731a610167574f59vikram "%s: %s\n", devpath, strerror(err));
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (err);
25e8c5aa2b496d9026e958ac731a610167574f59vikram }
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram dp->rt_debug(dp->rt_hdl, "[INFO]: unretire modctl() done: %s\n",
25e8c5aa2b496d9026e958ac731a610167574f59vikram devpath);
25e8c5aa2b496d9026e958ac731a610167574f59vikram
25e8c5aa2b496d9026e958ac731a610167574f59vikram return (0);
25e8c5aa2b496d9026e958ac731a610167574f59vikram}