Skip to content

Commit e2f631f

Browse files
jordanhendricksrmustacc
authored andcommitted
11576 Want support for ahci LED entries in topo
Reviewed by: Rob Johnston <rob.johnston@joyent.com> Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: C Fraire <cfraire@me.com> Approved by: Gordon Ross <gwr@nexenta.com>
1 parent c580674 commit e2f631f

File tree

7 files changed

+336
-2
lines changed

7 files changed

+336
-2
lines changed

usr/src/lib/fm/topo/libtopo/common/topo_hc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ extern "C" {
137137
#define TOPO_BINDING_DEVCTL "devctl"
138138
#define TOPO_BINDING_ENCLOSURE "enclosure"
139139
#define TOPO_BINDING_SLOT "slot"
140+
#define TOPO_BINDING_PORT "port"
140141

141142
#define TOPO_PGROUP_STORAGE "storage"
142143
#define TOPO_STORAGE_INITIATOR_PORT "initiator-port"

usr/src/lib/fm/topo/maps/SMCI,SSG-2029P-ACR24L/SSG-2029P-ACR24L-disk-hc-topology.xmlgenksh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,28 @@ function do_sata_node
7878
(( target = bay + 4 ))
7979
hpath="/pci@0,0/pci15d9,981@11,5"
8080
tpath="/disk@${target},0"
81+
devctl="/devices/pci@0,0/pci15d9,981@11,5:devctl"
8182
cat <<EOF
8283
<node instance='$bay_inst'>
84+
<facility name='fail' type='indicator' provider='fac_prov_ahci' >
85+
<propgroup name='facility' version='1' name-stability='Private'
86+
data-stability='Private' >
87+
<propval name='type' type='uint32' value='0' />
88+
<propmethod name='ahci_led_mode' version='0' propname='mode'
89+
proptype='uint32' mutable='1'>
90+
</propmethod>
91+
</propgroup>
92+
</facility>
93+
<facility name='ident' type='indicator' provider='fac_prov_ahci' >
94+
<propgroup name='facility' version='1' name-stability='Private'
95+
data-stability='Private' >
96+
<propval name='type' type='uint32' value='1' />
97+
<propmethod name='ahci_led_mode' version='0' propname='mode'
98+
proptype='uint32' mutable='1'>
99+
</propmethod>
100+
</propgroup>
101+
</facility>
102+
83103
<propgroup name='protocol' version='1' name-stability='Private'
84104
data-stability='Private'>
85105
<propval name='label' type='string' value='Rear Disk $bay' />
@@ -92,6 +112,9 @@ function do_sata_node
92112
data-stability='Private'>
93113
<propval name='occupant-path' type='string'
94114
value='$hpath$tpath' />
115+
<propval name='devctl' type='string'
116+
value='$devctl' />
117+
<propval name='port' type='uint32' value='$target' />
95118
</propgroup>
96119
</node>
97120
EOF

usr/src/lib/fm/topo/modules/common/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
SUBDIRS = \
2929
disk \
30+
fac_prov_ahci \
3031
fac_prov_ipmi \
3132
fac_prov_mptsas \
3233
ipmi \
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#
2+
# This file and its contents are supplied under the terms of the
3+
# Common Development and Distribution License ("CDDL"), version 1.0.
4+
# You may only use this file in accordance with the terms of version
5+
# 1.0 of the CDDL.
6+
#
7+
# A full copy of the text of the CDDL should have accompanied this
8+
# source. A copy of the CDDL is also available via the Internet at
9+
# http://www.illumos.org/license/CDDL.
10+
#
11+
12+
#
13+
# Copyright 2018, Joyent, Inc.
14+
#
15+
16+
MODULE = fac_prov_ahci
17+
CLASS = common
18+
19+
MODULESRCS = fac_prov_ahci.c
20+
21+
include ../../Makefile.plugin
22+
23+
CPPFLAGS += -I$(SRC)/uts/common
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
/*
2+
* This file and its contents are supplied under the terms of the
3+
* Common Development and Distribution License ("CDDL"), version 1.0.
4+
* You may only use this file in accordance with the terms of version
5+
* 1.0 of the CDDL.
6+
*
7+
* A full copy of the text of the CDDL should have accompanied this
8+
* source. A copy of the CDDL is also available via the Internet at
9+
* http://www.illumos.org/license/CDDL.
10+
*/
11+
12+
/*
13+
* Copyright (c) 2018, Joyent, Inc.
14+
*/
15+
16+
#include <unistd.h>
17+
#include <stropts.h>
18+
#include <fcntl.h>
19+
#include <libnvpair.h>
20+
#include <string.h>
21+
#include <strings.h>
22+
#include <sys/fm/protocol.h>
23+
#include <sys/stat.h>
24+
#include <sys/types.h>
25+
#include <fm/libtopo.h>
26+
#include <fm/topo_mod.h>
27+
#include <libgen.h>
28+
29+
#include "sys/sata/adapters/ahci/ahciem.h"
30+
31+
#define TOPO_METH_AHCI_LED_MODE_VERSION 0
32+
33+
/*
34+
* This enum is used to more clearly demonstrate the mapping between libtopo's
35+
* concept of LED types and the types represented in AHCI.
36+
*/
37+
typedef enum {
38+
AHCI_FAC_IDENT,
39+
AHCI_FAC_FAULT
40+
} ahci_fac_led_t;
41+
42+
static int fac_prov_ahci_enum(topo_mod_t *, tnode_t *, const char *,
43+
topo_instance_t, topo_instance_t, void *, void *);
44+
45+
/*
46+
* ahci facility provider methods
47+
*/
48+
static int ahci_led_mode(topo_mod_t *, tnode_t *, topo_version_t,
49+
nvlist_t *, nvlist_t **);
50+
51+
static const topo_modops_t ahci_ops = { fac_prov_ahci_enum, NULL };
52+
53+
static const topo_modinfo_t ahci_info =
54+
{ "ahci facility provider", FM_FMRI_SCHEME_HC, TOPO_VERSION,
55+
&ahci_ops };
56+
57+
static const topo_method_t ahci_fac_methods[] = {
58+
{ "ahci_led_mode", TOPO_PROP_METH_DESC,
59+
TOPO_METH_AHCI_LED_MODE_VERSION,
60+
TOPO_STABILITY_INTERNAL, ahci_led_mode },
61+
{ NULL }
62+
};
63+
64+
int
65+
_topo_init(topo_mod_t *mod, topo_version_t version)
66+
{
67+
if (getenv("TOPOFACAHCIDEBUG") != NULL)
68+
topo_mod_setdebug(mod);
69+
70+
return (topo_mod_register(mod, &ahci_info, TOPO_VERSION));
71+
}
72+
73+
void
74+
_topo_fini(topo_mod_t *mod)
75+
{
76+
topo_mod_unregister(mod);
77+
}
78+
79+
/*
80+
* Get or set the LED state for a given LED of type (facility node type, port).
81+
* This function returns -1 on error.
82+
*/
83+
static int
84+
do_led_control(topo_mod_t *mod, const char *devctl, uint32_t port,
85+
ahci_fac_led_t fac_type, uint32_t *ledmode, boolean_t set)
86+
{
87+
int fd = -1, ret = -1;
88+
89+
if ((fd = open(devctl, (set ? O_RDWR : O_RDONLY))) == -1) {
90+
topo_mod_dprintf(mod, "devctl open failed: %s",
91+
strerror(errno));
92+
goto out;
93+
}
94+
95+
if (set) {
96+
ahci_ioc_em_set_t ahci_set;
97+
uint32_t led_status = *ledmode;
98+
uint_t op, leds;
99+
100+
switch (fac_type) {
101+
case AHCI_FAC_IDENT:
102+
leds = AHCI_EM_LED_IDENT_ENABLE;
103+
break;
104+
case AHCI_FAC_FAULT:
105+
leds = AHCI_EM_LED_FAULT_ENABLE;
106+
break;
107+
default:
108+
topo_mod_dprintf(mod, "invalid facility node type: %d",
109+
fac_type);
110+
goto out;
111+
}
112+
113+
if (led_status) {
114+
op = AHCI_EM_IOC_SET_OP_ADD;
115+
} else {
116+
op = AHCI_EM_IOC_SET_OP_REM;
117+
}
118+
119+
bzero(&ahci_set, sizeof (ahci_set));
120+
ahci_set.aiems_port = port;
121+
ahci_set.aiems_op = op;
122+
ahci_set.aiems_leds = leds;
123+
124+
if (ioctl(fd, AHCI_EM_IOC_SET, &ahci_set) == -1) {
125+
topo_mod_dprintf(mod, "ioctl failed: %s",
126+
strerror(errno));
127+
goto out;
128+
}
129+
} else {
130+
uint_t led_set = 0;
131+
ahci_ioc_em_get_t ahci_get;
132+
133+
bzero(&ahci_get, sizeof (ahci_get));
134+
if (ioctl(fd, AHCI_EM_IOC_GET, &ahci_get) == -1) {
135+
topo_mod_dprintf(mod, "led control ioctl failed: %s",
136+
strerror(errno));
137+
goto out;
138+
}
139+
140+
switch (fac_type) {
141+
case AHCI_FAC_IDENT:
142+
led_set = ahci_get.aiemg_status[port] &
143+
AHCI_EM_LED_IDENT_ENABLE;
144+
break;
145+
case AHCI_FAC_FAULT:
146+
led_set = ahci_get.aiemg_status[port] &
147+
AHCI_EM_LED_FAULT_ENABLE;
148+
break;
149+
default:
150+
topo_mod_dprintf(mod, "invalid facility node type: %d",
151+
fac_type);
152+
goto out;
153+
}
154+
155+
*ledmode = (led_set != 0) ?
156+
TOPO_LED_STATE_ON : TOPO_LED_STATE_OFF;
157+
}
158+
ret = 0;
159+
160+
out:
161+
if (fd >= 0) {
162+
(void) close(fd);
163+
}
164+
return (ret);
165+
}
166+
167+
static int
168+
ahci_led_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
169+
nvlist_t *in, nvlist_t **nvout)
170+
{
171+
int err, ret = 0;
172+
tnode_t *pnode = topo_node_parent(node);
173+
uint32_t type, ledmode = 0, ahci_port;
174+
nvlist_t *pargs, *nvl;
175+
char *devctl = NULL;
176+
boolean_t set;
177+
ahci_fac_led_t fac_type;
178+
179+
if (vers > TOPO_METH_AHCI_LED_MODE_VERSION) {
180+
return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
181+
}
182+
183+
if (topo_prop_get_uint32(node, TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE,
184+
&type, &err) != 0) {
185+
topo_mod_dprintf(mod, "%s: Failed to lookup %s property "
186+
"(%s)", __func__, TOPO_FACILITY_TYPE, topo_strerror(err));
187+
return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
188+
}
189+
190+
/*
191+
* While the AHCI specification includes bits for locate, fault, and
192+
* activity LEDs, we generally only need to account for locate and fault
193+
* LEDs, as activity LEDs are typically disabled in hardware.
194+
*/
195+
switch (type) {
196+
case (TOPO_LED_TYPE_SERVICE):
197+
fac_type = AHCI_FAC_FAULT;
198+
break;
199+
case (TOPO_LED_TYPE_LOCATE):
200+
fac_type = AHCI_FAC_IDENT;
201+
break;
202+
default:
203+
topo_mod_dprintf(mod, "%s: Invalid LED type: 0x%x\n", __func__,
204+
type);
205+
ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL);
206+
return (ret);
207+
}
208+
209+
if (topo_prop_get_string(pnode, TOPO_PGROUP_BINDING,
210+
TOPO_BINDING_DEVCTL, &devctl, &err) != 0 ||
211+
topo_prop_get_uint32(pnode, TOPO_PGROUP_BINDING,
212+
TOPO_BINDING_PORT, &ahci_port, &err) != 0) {
213+
topo_mod_dprintf(mod, "%s: Facility was missing ahci binding "
214+
"properties\n", __func__);
215+
ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL);
216+
goto out;
217+
}
218+
219+
if ((nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &pargs) == 0) &&
220+
nvlist_exists(pargs, TOPO_PROP_VAL_VAL)) {
221+
/*
222+
* Set the LED mode.
223+
*/
224+
set = B_TRUE;
225+
226+
if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL,
227+
&ledmode)) != 0) {
228+
topo_mod_dprintf(mod, "%s: Failed to lookup %s nvpair "
229+
"(%s)\n", __func__, TOPO_PROP_VAL_VAL,
230+
strerror(ret));
231+
ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL);
232+
goto out;
233+
234+
}
235+
topo_mod_dprintf(mod, "%s: Setting LED mode to %s\n", __func__,
236+
ledmode ? "ON" : "OFF");
237+
} else {
238+
/*
239+
* Get the LED mode
240+
*/
241+
set = B_FALSE;
242+
topo_mod_dprintf(mod, "%s: Getting LED mode\n", __func__);
243+
}
244+
ret = do_led_control(mod, devctl, ahci_port, fac_type, &ledmode, set);
245+
246+
if (ret == -1) {
247+
topo_mod_dprintf(mod, "%s: do_led_control failed", __func__);
248+
ret = topo_mod_seterrno(mod, EMOD_UNKNOWN);
249+
goto out;
250+
}
251+
252+
if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 ||
253+
nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, TOPO_LED_MODE) != 0 ||
254+
nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 ||
255+
nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, ledmode) != 0) {
256+
topo_mod_dprintf(mod, "%s: Failed to allocate 'out' nvlist\n",
257+
__func__);
258+
nvlist_free(nvl);
259+
ret = topo_mod_seterrno(mod, EMOD_NOMEM);
260+
goto out;
261+
}
262+
*nvout = nvl;
263+
264+
out:
265+
topo_mod_strfree(mod, devctl);
266+
return (ret);
267+
}
268+
269+
static int
270+
fac_prov_ahci_enum(topo_mod_t *mod, tnode_t *rnode, const char *name,
271+
topo_instance_t min, topo_instance_t max, void *arg, void *unused)
272+
{
273+
274+
if (topo_node_flags(rnode) == TOPO_NODE_FACILITY) {
275+
if (topo_method_register(mod, rnode, ahci_fac_methods) != 0) {
276+
topo_mod_dprintf(mod, "%s: topo_method_register() "
277+
"failed: %s", __func__, topo_mod_errmsg(mod));
278+
return (-1);
279+
}
280+
return (0);
281+
}
282+
283+
topo_mod_dprintf(mod, "%s: unexpected node flags 0x%x", __func__,
284+
topo_node_flags(rnode));
285+
return (-1);
286+
}

usr/src/pkg/manifests/service-fault-management.mf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ file path=usr/lib/fm/libtopo.so.1 variant.opensolaris.zone=__NODEFAULT
506506
#
507507
file path=usr/lib/fm/topo/maps/xfp-hc-topology.xml mode=0444
508508
file path=usr/lib/fm/topo/plugins/disk.so mode=0555
509+
file path=usr/lib/fm/topo/plugins/fac_prov_ahci.so mode=0555
509510
file path=usr/lib/fm/topo/plugins/fac_prov_ipmi.so mode=0555
510511
file path=usr/lib/fm/topo/plugins/fac_prov_mptsas.so mode=0555
511512
file path=usr/lib/fm/topo/plugins/ipmi.so mode=0555

usr/src/uts/common/io/sata/adapters/ahci/ahci.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10552,8 +10552,7 @@ ahci_em_led_task(void *arg)
1055210552

1055310553
mutex_enter(&led->aelta_ctl->ahcictl_mutex);
1055410554
if (ret) {
10555-
led->aelta_ctl->ahcictl_em_state[led->aelta_port] =
10556-
led->aelta_state;
10555+
led->aelta_ctl->ahcictl_em_state[led->aelta_port] = state;
1055710556
led->aelta_ret = 0;
1055810557
} else {
1055910558
led->aelta_ret = EIO;

0 commit comments

Comments
 (0)