1881f7bffSSepherosa Ziehau /*
2881f7bffSSepherosa Ziehau * Copyright (c) 2015 The DragonFly Project. All rights reserved.
3881f7bffSSepherosa Ziehau *
4881f7bffSSepherosa Ziehau * This code is derived from software contributed to The DragonFly Project
5881f7bffSSepherosa Ziehau * by Sepherosa Ziehau <sepherosa@gmail.com>
6881f7bffSSepherosa Ziehau *
7881f7bffSSepherosa Ziehau * Redistribution and use in source and binary forms, with or without
8881f7bffSSepherosa Ziehau * modification, are permitted provided that the following conditions
9881f7bffSSepherosa Ziehau * are met:
10881f7bffSSepherosa Ziehau *
11881f7bffSSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright
12881f7bffSSepherosa Ziehau * notice, this list of conditions and the following disclaimer.
13881f7bffSSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright
14881f7bffSSepherosa Ziehau * notice, this list of conditions and the following disclaimer in
15881f7bffSSepherosa Ziehau * the documentation and/or other materials provided with the
16881f7bffSSepherosa Ziehau * distribution.
17881f7bffSSepherosa Ziehau * 3. Neither the name of The DragonFly Project nor the names of its
18881f7bffSSepherosa Ziehau * contributors may be used to endorse or promote products derived
19881f7bffSSepherosa Ziehau * from this software without specific, prior written permission.
20881f7bffSSepherosa Ziehau *
21881f7bffSSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22881f7bffSSepherosa Ziehau * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23881f7bffSSepherosa Ziehau * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24881f7bffSSepherosa Ziehau * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25881f7bffSSepherosa Ziehau * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26881f7bffSSepherosa Ziehau * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27881f7bffSSepherosa Ziehau * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28881f7bffSSepherosa Ziehau * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29881f7bffSSepherosa Ziehau * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30881f7bffSSepherosa Ziehau * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31881f7bffSSepherosa Ziehau * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32881f7bffSSepherosa Ziehau * SUCH DAMAGE.
33881f7bffSSepherosa Ziehau */
34881f7bffSSepherosa Ziehau
35881f7bffSSepherosa Ziehau #include <sys/param.h>
36881f7bffSSepherosa Ziehau #include <sys/bus.h>
37881f7bffSSepherosa Ziehau #include <sys/kernel.h>
38881f7bffSSepherosa Ziehau #include <sys/lock.h>
39881f7bffSSepherosa Ziehau #include <sys/malloc.h>
40881f7bffSSepherosa Ziehau #include <sys/module.h>
41881f7bffSSepherosa Ziehau #include <sys/sensors.h>
42881f7bffSSepherosa Ziehau #include <sys/sysctl.h>
43881f7bffSSepherosa Ziehau #include <sys/systm.h>
44881f7bffSSepherosa Ziehau
45881f7bffSSepherosa Ziehau #include <dev/misc/dimm/dimm.h>
46881f7bffSSepherosa Ziehau
47881f7bffSSepherosa Ziehau #define DIMM_TEMP_HIWAT_DEFAULT 85
48881f7bffSSepherosa Ziehau #define DIMM_TEMP_LOWAT_DEFAULT 75
49881f7bffSSepherosa Ziehau
507ee0de79SSepherosa Ziehau #define DIMM_ECC_THRESH_DEFAULT 5
517ee0de79SSepherosa Ziehau
52881f7bffSSepherosa Ziehau struct dimm_softc {
53881f7bffSSepherosa Ziehau TAILQ_ENTRY(dimm_softc) dimm_link;
54881f7bffSSepherosa Ziehau int dimm_node;
55881f7bffSSepherosa Ziehau int dimm_chan;
56881f7bffSSepherosa Ziehau int dimm_slot;
57881f7bffSSepherosa Ziehau int dimm_temp_hiwat;
58881f7bffSSepherosa Ziehau int dimm_temp_lowat;
59881f7bffSSepherosa Ziehau int dimm_id;
60881f7bffSSepherosa Ziehau int dimm_ref;
6123832f75SSepherosa Ziehau int dimm_ecc_cnt;
627ee0de79SSepherosa Ziehau int dimm_ecc_thresh;
63881f7bffSSepherosa Ziehau
64881f7bffSSepherosa Ziehau struct ksensordev dimm_sensdev;
65881f7bffSSepherosa Ziehau uint32_t dimm_sens_taskflags; /* DIMM_SENS_TF_ */
66881f7bffSSepherosa Ziehau
67881f7bffSSepherosa Ziehau struct sysctl_ctx_list dimm_sysctl_ctx;
68881f7bffSSepherosa Ziehau struct sysctl_oid *dimm_sysctl_tree;
69881f7bffSSepherosa Ziehau };
70881f7bffSSepherosa Ziehau TAILQ_HEAD(dimm_softc_list, dimm_softc);
71881f7bffSSepherosa Ziehau
72881f7bffSSepherosa Ziehau #define DIMM_SENS_TF_TEMP_CRIT 0x1
7323832f75SSepherosa Ziehau #define DIMM_SENS_TF_ECC_CRIT 0x2
74881f7bffSSepherosa Ziehau
75881f7bffSSepherosa Ziehau static void dimm_mod_unload(void);
76*e30371b4SSepherosa Ziehau static void dimm_sensor_ecc(struct dimm_softc *, struct ksensor *,
77*e30371b4SSepherosa Ziehau boolean_t);
78881f7bffSSepherosa Ziehau
79881f7bffSSepherosa Ziehau /* In the ascending order of dimm_softc.dimm_id */
80881f7bffSSepherosa Ziehau static struct dimm_softc_list dimm_softc_list;
81881f7bffSSepherosa Ziehau
82881f7bffSSepherosa Ziehau static SYSCTL_NODE(_hw, OID_AUTO, dimminfo, CTLFLAG_RD, NULL,
83881f7bffSSepherosa Ziehau "DIMM information");
84881f7bffSSepherosa Ziehau
85881f7bffSSepherosa Ziehau struct dimm_softc *
dimm_create(int node,int chan,int slot)86881f7bffSSepherosa Ziehau dimm_create(int node, int chan, int slot)
87881f7bffSSepherosa Ziehau {
88881f7bffSSepherosa Ziehau struct dimm_softc *sc, *after = NULL;
89881f7bffSSepherosa Ziehau int dimm_id = 0;
90881f7bffSSepherosa Ziehau
91881f7bffSSepherosa Ziehau SYSCTL_XLOCK();
92881f7bffSSepherosa Ziehau
93881f7bffSSepherosa Ziehau TAILQ_FOREACH(sc, &dimm_softc_list, dimm_link) {
94881f7bffSSepherosa Ziehau /*
95881f7bffSSepherosa Ziehau * Already exists; done.
96881f7bffSSepherosa Ziehau */
97881f7bffSSepherosa Ziehau if (sc->dimm_node == node && sc->dimm_chan == chan &&
98881f7bffSSepherosa Ziehau sc->dimm_slot == slot) {
99881f7bffSSepherosa Ziehau KASSERT(sc->dimm_ref > 0, ("invalid dimm reference %d",
100881f7bffSSepherosa Ziehau sc->dimm_ref));
101881f7bffSSepherosa Ziehau sc->dimm_ref++;
102881f7bffSSepherosa Ziehau SYSCTL_XUNLOCK();
103881f7bffSSepherosa Ziehau return sc;
104881f7bffSSepherosa Ziehau }
105881f7bffSSepherosa Ziehau
106881f7bffSSepherosa Ziehau /*
107881f7bffSSepherosa Ziehau * Find the lowest usable id.
108881f7bffSSepherosa Ziehau */
109881f7bffSSepherosa Ziehau if (sc->dimm_id == dimm_id) {
110881f7bffSSepherosa Ziehau ++dimm_id;
111881f7bffSSepherosa Ziehau after = sc;
112881f7bffSSepherosa Ziehau }
113881f7bffSSepherosa Ziehau }
114881f7bffSSepherosa Ziehau
115881f7bffSSepherosa Ziehau sc = kmalloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
116881f7bffSSepherosa Ziehau sc->dimm_node = node;
117881f7bffSSepherosa Ziehau sc->dimm_chan = chan;
118881f7bffSSepherosa Ziehau sc->dimm_slot = slot;
119881f7bffSSepherosa Ziehau sc->dimm_id = dimm_id;
120881f7bffSSepherosa Ziehau sc->dimm_ref = 1;
121881f7bffSSepherosa Ziehau sc->dimm_temp_hiwat = DIMM_TEMP_HIWAT_DEFAULT;
122881f7bffSSepherosa Ziehau sc->dimm_temp_lowat = DIMM_TEMP_LOWAT_DEFAULT;
1237ee0de79SSepherosa Ziehau sc->dimm_ecc_thresh = DIMM_ECC_THRESH_DEFAULT;
124881f7bffSSepherosa Ziehau
125881f7bffSSepherosa Ziehau ksnprintf(sc->dimm_sensdev.xname, sizeof(sc->dimm_sensdev.xname),
126881f7bffSSepherosa Ziehau "dimm%d", sc->dimm_id);
127881f7bffSSepherosa Ziehau
128881f7bffSSepherosa Ziehau /*
129881f7bffSSepherosa Ziehau * Create sysctl tree for the location information. Use
130881f7bffSSepherosa Ziehau * same name as the sensor device.
131881f7bffSSepherosa Ziehau */
132881f7bffSSepherosa Ziehau sysctl_ctx_init(&sc->dimm_sysctl_ctx);
133881f7bffSSepherosa Ziehau sc->dimm_sysctl_tree = SYSCTL_ADD_NODE(&sc->dimm_sysctl_ctx,
134881f7bffSSepherosa Ziehau SYSCTL_STATIC_CHILDREN(_hw_dimminfo), OID_AUTO,
135881f7bffSSepherosa Ziehau sc->dimm_sensdev.xname, CTLFLAG_RD, 0, "");
136881f7bffSSepherosa Ziehau if (sc->dimm_sysctl_tree != NULL) {
137881f7bffSSepherosa Ziehau SYSCTL_ADD_INT(&sc->dimm_sysctl_ctx,
138881f7bffSSepherosa Ziehau SYSCTL_CHILDREN(sc->dimm_sysctl_tree), OID_AUTO,
139881f7bffSSepherosa Ziehau "node", CTLFLAG_RD, &sc->dimm_node, 0,
140881f7bffSSepherosa Ziehau "CPU node of this DIMM");
141881f7bffSSepherosa Ziehau SYSCTL_ADD_INT(&sc->dimm_sysctl_ctx,
142881f7bffSSepherosa Ziehau SYSCTL_CHILDREN(sc->dimm_sysctl_tree), OID_AUTO,
143881f7bffSSepherosa Ziehau "chan", CTLFLAG_RD, &sc->dimm_chan, 0,
144881f7bffSSepherosa Ziehau "channel of this DIMM");
145881f7bffSSepherosa Ziehau SYSCTL_ADD_INT(&sc->dimm_sysctl_ctx,
146881f7bffSSepherosa Ziehau SYSCTL_CHILDREN(sc->dimm_sysctl_tree), OID_AUTO,
147881f7bffSSepherosa Ziehau "slot", CTLFLAG_RD, &sc->dimm_slot, 0,
148881f7bffSSepherosa Ziehau "slot of this DIMM");
149881f7bffSSepherosa Ziehau SYSCTL_ADD_INT(&sc->dimm_sysctl_ctx,
150881f7bffSSepherosa Ziehau SYSCTL_CHILDREN(sc->dimm_sysctl_tree), OID_AUTO,
151881f7bffSSepherosa Ziehau "temp_hiwat", CTLFLAG_RW, &sc->dimm_temp_hiwat, 0,
152881f7bffSSepherosa Ziehau "Raise alarm once DIMM temperature is above this value "
153881f7bffSSepherosa Ziehau "(unit: C)");
154881f7bffSSepherosa Ziehau SYSCTL_ADD_INT(&sc->dimm_sysctl_ctx,
155881f7bffSSepherosa Ziehau SYSCTL_CHILDREN(sc->dimm_sysctl_tree), OID_AUTO,
156881f7bffSSepherosa Ziehau "temp_lowat", CTLFLAG_RW, &sc->dimm_temp_lowat, 0,
157881f7bffSSepherosa Ziehau "Cancel alarm once DIMM temperature is below this value "
158881f7bffSSepherosa Ziehau "(unit: C)");
1597ee0de79SSepherosa Ziehau SYSCTL_ADD_INT(&sc->dimm_sysctl_ctx,
1607ee0de79SSepherosa Ziehau SYSCTL_CHILDREN(sc->dimm_sysctl_tree), OID_AUTO,
1617ee0de79SSepherosa Ziehau "ecc_thresh", CTLFLAG_RW, &sc->dimm_ecc_thresh, 0,
1627ee0de79SSepherosa Ziehau "Raise alarm once number ECC errors go above this value");
163881f7bffSSepherosa Ziehau }
164881f7bffSSepherosa Ziehau
165881f7bffSSepherosa Ziehau if (after == NULL) {
166881f7bffSSepherosa Ziehau KKASSERT(sc->dimm_id == 0);
167881f7bffSSepherosa Ziehau TAILQ_INSERT_HEAD(&dimm_softc_list, sc, dimm_link);
168881f7bffSSepherosa Ziehau } else {
169881f7bffSSepherosa Ziehau TAILQ_INSERT_AFTER(&dimm_softc_list, after, sc, dimm_link);
170881f7bffSSepherosa Ziehau }
171881f7bffSSepherosa Ziehau
172881f7bffSSepherosa Ziehau sensordev_install(&sc->dimm_sensdev);
173881f7bffSSepherosa Ziehau
174881f7bffSSepherosa Ziehau SYSCTL_XUNLOCK();
175881f7bffSSepherosa Ziehau return sc;
176881f7bffSSepherosa Ziehau }
177881f7bffSSepherosa Ziehau
178881f7bffSSepherosa Ziehau int
dimm_destroy(struct dimm_softc * sc)179881f7bffSSepherosa Ziehau dimm_destroy(struct dimm_softc *sc)
180881f7bffSSepherosa Ziehau {
181881f7bffSSepherosa Ziehau SYSCTL_XLOCK();
182881f7bffSSepherosa Ziehau
183881f7bffSSepherosa Ziehau KASSERT(sc->dimm_ref > 0, ("invalid dimm reference %d", sc->dimm_ref));
184881f7bffSSepherosa Ziehau sc->dimm_ref--;
185881f7bffSSepherosa Ziehau if (sc->dimm_ref > 0) {
186881f7bffSSepherosa Ziehau SYSCTL_XUNLOCK();
187881f7bffSSepherosa Ziehau return EAGAIN;
188881f7bffSSepherosa Ziehau }
189881f7bffSSepherosa Ziehau
190881f7bffSSepherosa Ziehau sensordev_deinstall(&sc->dimm_sensdev);
191881f7bffSSepherosa Ziehau
192881f7bffSSepherosa Ziehau TAILQ_REMOVE(&dimm_softc_list, sc, dimm_link);
193881f7bffSSepherosa Ziehau if (sc->dimm_sysctl_tree != NULL)
194881f7bffSSepherosa Ziehau sysctl_ctx_free(&sc->dimm_sysctl_ctx);
195881f7bffSSepherosa Ziehau kfree(sc, M_DEVBUF);
196881f7bffSSepherosa Ziehau
197881f7bffSSepherosa Ziehau SYSCTL_XUNLOCK();
198881f7bffSSepherosa Ziehau return 0;
199881f7bffSSepherosa Ziehau }
200881f7bffSSepherosa Ziehau
201881f7bffSSepherosa Ziehau void
dimm_sensor_attach(struct dimm_softc * sc,struct ksensor * sens)202881f7bffSSepherosa Ziehau dimm_sensor_attach(struct dimm_softc *sc, struct ksensor *sens)
203881f7bffSSepherosa Ziehau {
204881f7bffSSepherosa Ziehau sensor_attach(&sc->dimm_sensdev, sens);
205881f7bffSSepherosa Ziehau }
206881f7bffSSepherosa Ziehau
207881f7bffSSepherosa Ziehau void
dimm_sensor_detach(struct dimm_softc * sc,struct ksensor * sens)208881f7bffSSepherosa Ziehau dimm_sensor_detach(struct dimm_softc *sc, struct ksensor *sens)
209881f7bffSSepherosa Ziehau {
210881f7bffSSepherosa Ziehau sensor_detach(&sc->dimm_sensdev, sens);
211881f7bffSSepherosa Ziehau }
212881f7bffSSepherosa Ziehau
213881f7bffSSepherosa Ziehau void
dimm_set_temp_thresh(struct dimm_softc * sc,int hiwat,int lowat)214881f7bffSSepherosa Ziehau dimm_set_temp_thresh(struct dimm_softc *sc, int hiwat, int lowat)
215881f7bffSSepherosa Ziehau {
216881f7bffSSepherosa Ziehau sc->dimm_temp_hiwat = hiwat;
217881f7bffSSepherosa Ziehau sc->dimm_temp_lowat = lowat;
218881f7bffSSepherosa Ziehau }
219881f7bffSSepherosa Ziehau
220881f7bffSSepherosa Ziehau void
dimm_set_ecc_thresh(struct dimm_softc * sc,int thresh)2217ee0de79SSepherosa Ziehau dimm_set_ecc_thresh(struct dimm_softc *sc, int thresh)
2227ee0de79SSepherosa Ziehau {
2237ee0de79SSepherosa Ziehau sc->dimm_ecc_thresh = thresh;
2247ee0de79SSepherosa Ziehau }
2257ee0de79SSepherosa Ziehau
2267ee0de79SSepherosa Ziehau void
dimm_sensor_temp(struct dimm_softc * sc,struct ksensor * sens,int temp)227881f7bffSSepherosa Ziehau dimm_sensor_temp(struct dimm_softc *sc, struct ksensor *sens, int temp)
228881f7bffSSepherosa Ziehau {
2297273d7b8SSepherosa Ziehau enum sensor_status status;
2307273d7b8SSepherosa Ziehau
231881f7bffSSepherosa Ziehau if (temp >= sc->dimm_temp_hiwat &&
232881f7bffSSepherosa Ziehau (sc->dimm_sens_taskflags & DIMM_SENS_TF_TEMP_CRIT) == 0) {
233881f7bffSSepherosa Ziehau char temp_str[16], data[64];
234881f7bffSSepherosa Ziehau
235881f7bffSSepherosa Ziehau ksnprintf(temp_str, sizeof(temp_str), "%d", temp);
236881f7bffSSepherosa Ziehau ksnprintf(data, sizeof(data), "node=%d channel=%d dimm=%d",
237881f7bffSSepherosa Ziehau sc->dimm_node, sc->dimm_chan, sc->dimm_slot);
238881f7bffSSepherosa Ziehau devctl_notify("memtemp", "Thermal", temp_str, data);
239881f7bffSSepherosa Ziehau
240881f7bffSSepherosa Ziehau kprintf("dimm%d: node%d channel%d DIMM%d "
241881f7bffSSepherosa Ziehau "temperature (%dC) is too high (>= %dC)\n",
242881f7bffSSepherosa Ziehau sc->dimm_id, sc->dimm_node, sc->dimm_chan, sc->dimm_slot,
243881f7bffSSepherosa Ziehau temp, sc->dimm_temp_hiwat);
244881f7bffSSepherosa Ziehau
245881f7bffSSepherosa Ziehau sc->dimm_sens_taskflags |= DIMM_SENS_TF_TEMP_CRIT;
246881f7bffSSepherosa Ziehau } else if ((sc->dimm_sens_taskflags & DIMM_SENS_TF_TEMP_CRIT) &&
247881f7bffSSepherosa Ziehau temp < sc->dimm_temp_lowat) {
248881f7bffSSepherosa Ziehau sc->dimm_sens_taskflags &= ~DIMM_SENS_TF_TEMP_CRIT;
249881f7bffSSepherosa Ziehau }
250881f7bffSSepherosa Ziehau
251881f7bffSSepherosa Ziehau if (sc->dimm_sens_taskflags & DIMM_SENS_TF_TEMP_CRIT)
2527273d7b8SSepherosa Ziehau status = SENSOR_S_CRIT;
253881f7bffSSepherosa Ziehau else
2547273d7b8SSepherosa Ziehau status = SENSOR_S_OK;
2557273d7b8SSepherosa Ziehau sensor_set_temp_degc(sens, temp, status);
256881f7bffSSepherosa Ziehau }
257881f7bffSSepherosa Ziehau
25823832f75SSepherosa Ziehau void
dimm_sensor_ecc_set(struct dimm_softc * sc,struct ksensor * sens,int ecc_cnt,boolean_t crit)25923832f75SSepherosa Ziehau dimm_sensor_ecc_set(struct dimm_softc *sc, struct ksensor *sens,
26023832f75SSepherosa Ziehau int ecc_cnt, boolean_t crit)
26123832f75SSepherosa Ziehau {
2627273d7b8SSepherosa Ziehau sc->dimm_ecc_cnt = ecc_cnt;
263*e30371b4SSepherosa Ziehau dimm_sensor_ecc(sc, sens, crit);
264*e30371b4SSepherosa Ziehau }
265*e30371b4SSepherosa Ziehau
266*e30371b4SSepherosa Ziehau void
dimm_sensor_ecc_add(struct dimm_softc * sc,struct ksensor * sens,int ecc_cnt,boolean_t crit)267*e30371b4SSepherosa Ziehau dimm_sensor_ecc_add(struct dimm_softc *sc, struct ksensor *sens,
268*e30371b4SSepherosa Ziehau int ecc_cnt, boolean_t crit)
269*e30371b4SSepherosa Ziehau {
270*e30371b4SSepherosa Ziehau sc->dimm_ecc_cnt += ecc_cnt;
271*e30371b4SSepherosa Ziehau dimm_sensor_ecc(sc, sens, crit);
272*e30371b4SSepherosa Ziehau }
273*e30371b4SSepherosa Ziehau
274*e30371b4SSepherosa Ziehau static void
dimm_sensor_ecc(struct dimm_softc * sc,struct ksensor * sens,boolean_t crit)275*e30371b4SSepherosa Ziehau dimm_sensor_ecc(struct dimm_softc *sc, struct ksensor *sens, boolean_t crit)
276*e30371b4SSepherosa Ziehau {
277*e30371b4SSepherosa Ziehau enum sensor_status status;
2787ee0de79SSepherosa Ziehau
2797ee0de79SSepherosa Ziehau if (!crit && sc->dimm_ecc_cnt >= sc->dimm_ecc_thresh)
2807ee0de79SSepherosa Ziehau crit = TRUE;
2817ee0de79SSepherosa Ziehau
28223832f75SSepherosa Ziehau if (crit && (sc->dimm_sens_taskflags & DIMM_SENS_TF_ECC_CRIT) == 0) {
283ca981007SSepherosa Ziehau char ecc_str[16], data[64];
284ca981007SSepherosa Ziehau
285ca981007SSepherosa Ziehau ksnprintf(ecc_str, sizeof(ecc_str), "%d", sc->dimm_ecc_cnt);
286ca981007SSepherosa Ziehau ksnprintf(data, sizeof(data), "node=%d channel=%d dimm=%d",
287ca981007SSepherosa Ziehau sc->dimm_node, sc->dimm_chan, sc->dimm_slot);
288ca981007SSepherosa Ziehau devctl_notify("ecc", "ECC", ecc_str, data);
289ca981007SSepherosa Ziehau
290ca981007SSepherosa Ziehau kprintf("dimm%d: node%d channel%d DIMM%d "
291ca981007SSepherosa Ziehau "too many ECC errors %d\n",
292ca981007SSepherosa Ziehau sc->dimm_id, sc->dimm_node, sc->dimm_chan, sc->dimm_slot,
293ca981007SSepherosa Ziehau sc->dimm_ecc_cnt);
294ca981007SSepherosa Ziehau
29523832f75SSepherosa Ziehau sc->dimm_sens_taskflags |= DIMM_SENS_TF_ECC_CRIT;
29623832f75SSepherosa Ziehau }
29723832f75SSepherosa Ziehau
29823832f75SSepherosa Ziehau if (sc->dimm_sens_taskflags & DIMM_SENS_TF_ECC_CRIT)
2997273d7b8SSepherosa Ziehau status = SENSOR_S_CRIT;
30023832f75SSepherosa Ziehau else
3017273d7b8SSepherosa Ziehau status = SENSOR_S_OK;
3027273d7b8SSepherosa Ziehau sensor_set(sens, sc->dimm_ecc_cnt, status);
30323832f75SSepherosa Ziehau }
30423832f75SSepherosa Ziehau
305881f7bffSSepherosa Ziehau static void
dimm_mod_unload(void)306881f7bffSSepherosa Ziehau dimm_mod_unload(void)
307881f7bffSSepherosa Ziehau {
308881f7bffSSepherosa Ziehau struct dimm_softc *sc;
309881f7bffSSepherosa Ziehau
310881f7bffSSepherosa Ziehau SYSCTL_XLOCK();
311881f7bffSSepherosa Ziehau
312881f7bffSSepherosa Ziehau while ((sc = TAILQ_FIRST(&dimm_softc_list)) != NULL) {
313881f7bffSSepherosa Ziehau int error;
314881f7bffSSepherosa Ziehau
315881f7bffSSepherosa Ziehau error = dimm_destroy(sc);
316881f7bffSSepherosa Ziehau KASSERT(!error, ("dimm%d is still referenced, ref %d",
317881f7bffSSepherosa Ziehau sc->dimm_id, sc->dimm_ref));
318881f7bffSSepherosa Ziehau }
319881f7bffSSepherosa Ziehau
320881f7bffSSepherosa Ziehau SYSCTL_XUNLOCK();
321881f7bffSSepherosa Ziehau }
322881f7bffSSepherosa Ziehau
323881f7bffSSepherosa Ziehau static int
dimm_mod_event(module_t mod,int type,void * unused)324881f7bffSSepherosa Ziehau dimm_mod_event(module_t mod, int type, void *unused)
325881f7bffSSepherosa Ziehau {
326881f7bffSSepherosa Ziehau switch (type) {
327881f7bffSSepherosa Ziehau case MOD_LOAD:
328881f7bffSSepherosa Ziehau TAILQ_INIT(&dimm_softc_list);
329881f7bffSSepherosa Ziehau return 0;
330881f7bffSSepherosa Ziehau
331881f7bffSSepherosa Ziehau case MOD_UNLOAD:
332881f7bffSSepherosa Ziehau dimm_mod_unload();
333881f7bffSSepherosa Ziehau return 0;
334881f7bffSSepherosa Ziehau
335881f7bffSSepherosa Ziehau default:
336881f7bffSSepherosa Ziehau return 0;
337881f7bffSSepherosa Ziehau }
338881f7bffSSepherosa Ziehau }
339881f7bffSSepherosa Ziehau
340881f7bffSSepherosa Ziehau static moduledata_t dimm_mod = {
341881f7bffSSepherosa Ziehau "dimm",
342881f7bffSSepherosa Ziehau dimm_mod_event,
343881f7bffSSepherosa Ziehau 0
344881f7bffSSepherosa Ziehau };
345881f7bffSSepherosa Ziehau DECLARE_MODULE(dimm, dimm_mod, SI_SUB_PRE_DRIVERS, SI_ORDER_ANY);
346881f7bffSSepherosa Ziehau MODULE_VERSION(dimm, 1);
347