xref: /illumos-gate/usr/src/cmd/pcidr/plugins/default/pcidr_plugin.c (revision c51cb4bc539e1650eb5bb4f805cc779bfce99c06)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <strings.h>
33 #include <errno.h>
34 #include <sys/param.h>
35 #include <sys/systeminfo.h>
36 #include <sys/sysevent/eventdefs.h>
37 #include <sys/sysevent/dr.h>
38 #include <syslog.h>
39 #include <libnvpair.h>
40 #include <stdarg.h>
41 #include <assert.h>
42 #include <sys/stat.h>
43 #include <dlfcn.h>
44 #include <pcidr.h>
45 #include <pcidr_cfga.h>
46 
47 
48 PCIDR_PLUGIN_PROTO(attrlistp, optp)
49 {
50 	char *fn = PCIDR_PLUGIN_SYMSTR;
51 	int rv = 0;
52 	char *cfga_errstr = NULL;
53 	char *str, *apid;
54 	cfga_list_data_t *cfga_listp = NULL;
55 	cfga_cmd_t cmd;
56 	int cfga_list_len;
57 	pcidr_attrs_t dr;
58 
59 	pcidr_set_logopt(&optp->logopt);
60 
61 	if (pcidr_get_attrs(attrlistp, &dr) != 0 ||
62 	    pcidr_check_attrs(&dr) != 0) {
63 		dprint(DWARN, "%s: invalid or missing attributes\n", fn);
64 		return (EINVAL);
65 	}
66 
67 	/*
68 	 * get state of APID; enforce the cfgadm pci plugin implementation of
69 	 * returning one matching AP per supplied apid string
70 	 */
71 	rv = config_list_ext(1, &dr.dr_ap_id, &cfga_listp, &cfga_list_len,
72 	    NULL, NULL, &cfga_errstr, CFGA_FLAG_LIST_ALL);
73 	if (rv != CFGA_OK) {
74 		str = pcidr_cfga_err_name(rv);
75 		if (str == NULL)
76 			str = "unrecognized rv!";
77 		dprint(DDEBUG, "%s: config_list_ext() on apid = \"%s\" "
78 		    "failed: rv = %d (%s)", fn, dr.dr_ap_id, rv, str);
79 
80 		if (cfga_errstr != NULL) {
81 			dprint(DDEBUG, ", error string = \"%s\"",
82 			    cfga_errstr);
83 			free(cfga_errstr);
84 		}
85 		dprint(DDEBUG, "\n");
86 		rv = EINVAL;
87 		goto OUT;
88 	}
89 	if (cfga_list_len != 1) {
90 		dprint(DWARN, "%s: invalid condition - more than one AP was "
91 		    "found for the APID \"%s\"\n", fn, dr.dr_ap_id);
92 		rv = EINVAL;
93 		goto OUT;
94 	}
95 
96 	/*
97 	 * perform DR
98 	 */
99 	dprint(DINFO, "%s: showing info and performing DR on APID(s) "
100 	    "matching \"%s\"\n", fn, dr.dr_ap_id);
101 
102 	cmd = CFGA_CMD_NONE;
103 	dprint(DINFO, "===========================================\n", fn);
104 	pcidr_print_cfga(DINFO, &cfga_listp[0], "  .. ");
105 	apid = cfga_listp[0].ap_phys_id;
106 
107 	if (strcmp(dr.dr_req_type, DR_REQ_OUTGOING_RES) == 0) {
108 		cmd = CFGA_CMD_DISCONNECT;
109 		dprint(DINFO, "%s: disconnecting ...\n", fn, apid);
110 
111 		rv = pcidr_cfga_do_cmd(cmd, &cfga_listp[0]);
112 		if (rv < 0) {
113 			dprint(DINFO, "%s: disconnect FAILED\n", fn);
114 			rv = EIO;
115 		}
116 		else
117 			dprint(DINFO, "%s: disconnect OK\n", fn);
118 
119 		goto OUT;
120 	}
121 	if (strcmp(dr.dr_req_type, DR_REQ_INCOMING_RES) == 0) {
122 		cmd = CFGA_CMD_CONFIGURE;
123 		dprint(DINFO, "%s: configuring ...\n", fn, apid);
124 
125 		rv = pcidr_cfga_do_cmd(cmd, &cfga_listp[0]);
126 		if (rv < 0) {
127 			dprint(DINFO, "%s: configure FAILED\n", fn);
128 			rv = EIO;
129 		} else
130 			dprint(DINFO, "%s: configure OK\n", fn);
131 
132 		goto OUT;
133 	}
134 
135 	/* we should not get here if pcidr_check_attrs() is correct */
136 	dprint(DWARN, "%s: invalid dr_req_type = %s\n", fn, dr.dr_req_type);
137 	assert(cmd != CFGA_CMD_NONE);
138 	return (EINVAL);
139 	/*NOTREACHED*/
140 OUT:
141 	if (cfga_listp != NULL)
142 		free(cfga_listp);
143 	return (rv);
144 }
145