Mon Jul 20 19:11:30 2009 UTC ()
Overhaul synchronization in ipmi(4): synchronize all access to
device registers with a mutex.  Convert tsleep/wakeup calls to
cv_wait/cv_signal.

Do not repeatedly malloc/free tiny buffers for sending/receiving
commands, but reserve a command buffer in the softc.

Tickle the watchdog in the sensors-refreshing thread.

I am fairly certain that after the device is attached, every register
access happens in the sensors-refreshing thread.  Moreover, no
software interrupt touches any register, now.  So I may get rid of
the mutex that protects register accesses, sc_cmd_mtx.


(dyoung)
diff -r1.9 -r1.10 src/sys/arch/x86/include/ipmivar.h
diff -r1.38 -r1.39 src/sys/arch/x86/x86/ipmi.c

cvs diff -r1.9 -r1.10 src/sys/arch/x86/include/ipmivar.h (expand / switch to unified diff)

--- src/sys/arch/x86/include/ipmivar.h 2008/11/03 12:25:53 1.9
+++ src/sys/arch/x86/include/ipmivar.h 2009/07/20 19:11:30 1.10
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ipmivar.h,v 1.9 2008/11/03 12:25:53 cegger Exp $ */ 1/* $NetBSD: ipmivar.h,v 1.10 2009/07/20 19:11:30 dyoung Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2005 Jordan Hargrave 4 * Copyright (c) 2005 Jordan Hargrave
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -18,50 +18,44 @@ @@ -18,50 +18,44 @@
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 * 27 *
28 */ 28 */
29 29
30#include <sys/mutex.h> 30#include <sys/mutex.h>
 31#include <sys/condvar.h>
31 32
32#include <dev/sysmon/sysmonvar.h> 33#include <dev/sysmon/sysmonvar.h>
33 34
34#ifndef _IPMIVAR_H_ 35#ifndef _IPMIVAR_H_
35#define _IPMIVAR_H_ 36#define _IPMIVAR_H_
36 37
37#define IPMI_IF_KCS 1 38#define IPMI_IF_KCS 1
38#define IPMI_IF_SMIC 2 39#define IPMI_IF_SMIC 2
39#define IPMI_IF_BT 3 40#define IPMI_IF_BT 3
40 41
41#define IPMI_IF_KCS_NREGS 2 42#define IPMI_IF_KCS_NREGS 2
42#define IPMI_IF_SMIC_NREGS 3 43#define IPMI_IF_SMIC_NREGS 3
43#define IPMI_IF_BT_NREGS 3 44#define IPMI_IF_BT_NREGS 3
44 45
45struct ipmi_thread; 46struct ipmi_thread;
46struct ipmi_softc; 47struct ipmi_softc;
47 48
48struct ipmi_bmc_args{ 
49 int offset; 
50 uint8_t mask; 
51 uint8_t value; 
52 volatile uint8_t *v; 
53}; 
54 
55struct ipmi_attach_args { 49struct ipmi_attach_args {
56 bus_space_tag_t iaa_iot; 50 bus_space_tag_t iaa_iot;
57 bus_space_tag_t iaa_memt; 51 bus_space_tag_t iaa_memt;
58 52
59 int iaa_if_type; 53 int iaa_if_type;
60 int iaa_if_rev; 54 int iaa_if_rev;
61 int iaa_if_iotype; 55 int iaa_if_iotype;
62 int iaa_if_iobase; 56 int iaa_if_iobase;
63 int iaa_if_iospacing; 57 int iaa_if_iospacing;
64 int iaa_if_irq; 58 int iaa_if_irq;
65 int iaa_if_irqlvl; 59 int iaa_if_irqlvl;
66}; 60};
67 61
@@ -82,69 +76,85 @@ struct ipmi_softc { @@ -82,69 +76,85 @@ struct ipmi_softc {
82 struct ipmi_if *sc_if; /* Interface layer */ 76 struct ipmi_if *sc_if; /* Interface layer */
83 int sc_if_iospacing; /* Spacing of I/O ports */ 77 int sc_if_iospacing; /* Spacing of I/O ports */
84 int sc_if_rev; /* IPMI Revision */ 78 int sc_if_rev; /* IPMI Revision */
85 struct ipmi_attach_args sc_ia; 79 struct ipmi_attach_args sc_ia;
86 80
87 void *sc_ih; /* Interrupt/IO handles */ 81 void *sc_ih; /* Interrupt/IO handles */
88 bus_space_tag_t sc_iot; 82 bus_space_tag_t sc_iot;
89 bus_space_handle_t sc_ioh; 83 bus_space_handle_t sc_ioh;
90 84
91 int sc_btseq; 85 int sc_btseq;
92 86
93 struct lwp *sc_kthread; 87 struct lwp *sc_kthread;
94 88
95 struct callout sc_callout; 
96 int sc_max_retries; 89 int sc_max_retries;
97 int sc_retries; 
98 int sc_wakeup; 
99 90
100 kmutex_t sc_lock; 91 kmutex_t sc_poll_mtx;
 92 kcondvar_t sc_poll_cv;
 93
 94 kmutex_t sc_cmd_mtx;
 95 kcondvar_t sc_cmd_sleep;
101 96
102 struct ipmi_bmc_args *sc_iowait_args; 97 struct ipmi_bmc_args *sc_iowait_args;
103 98
104 struct ipmi_sensor *current_sensor; 99 struct ipmi_sensor *current_sensor;
105 volatile int sc_thread_running; 100 volatile bool sc_thread_running;
 101 volatile bool sc_tickle_due;
106 struct sysmon_wdog sc_wdog; 102 struct sysmon_wdog sc_wdog;
107 struct sysmon_envsys *sc_envsys; 103 struct sysmon_envsys *sc_envsys;
108 envsys_data_t *sc_sensor; 104 envsys_data_t *sc_sensor;
109 int sc_nsensors; /* total number of sensors */ 105 int sc_nsensors; /* total number of sensors */
110 int sc_nsensors_typ[ENVSYS_NSENSORS]; /* number per type */ 106 int sc_nsensors_typ[ENVSYS_NSENSORS]; /* number per type */
 107
 108 char sc_buf[64];
 109 bool sc_buf_rsvd;
111}; 110};
112 111
113struct ipmi_thread { 112struct ipmi_thread {
114 struct ipmi_softc *sc; 113 struct ipmi_softc *sc;
115 volatile int running; 114 volatile int running;
116}; 115};
117 116
118#define IPMI_WDOG_USE_NLOG 0x80 117#define IPMI_WDOG_USE_NOLOG __BIT(7)
119#define IPMI_WDOG_USE_NSTOP 0x40 118#define IPMI_WDOG_USE_NOSTOP __BIT(6)
120#define IPMI_WDOG_USE_USE_MASK 0x07 119#define IPMI_WDOG_USE_RSVD1 __BITS(5, 3)
121#define IPMI_WDOG_USE_USE_FRB2 0x01 120#define IPMI_WDOG_USE_USE_MASK __BITS(2, 0)
122#define IPMI_WDOG_USE_USE_POST 0x02 121#define IPMI_WDOG_USE_USE_RSVD __SHIFTIN(0, IPMI_WDOG_USE_USE_MASK);
123#define IPMI_WDOG_USE_USE_OSLOAD 0x03 122#define IPMI_WDOG_USE_USE_FRB2 __SHIFTIN(1, IPMI_WDOG_USE_USE_MASK);
124#define IPMI_WDOG_USE_USE_OS 0x04 123#define IPMI_WDOG_USE_USE_POST __SHIFTIN(2, IPMI_WDOG_USE_USE_MASK);
125#define IPMI_WDOG_USE_USE_EOM 0x05 124#define IPMI_WDOG_USE_USE_OSLOAD __SHIFTIN(3, IPMI_WDOG_USE_USE_MASK);
126 125#define IPMI_WDOG_USE_USE_OS __SHIFTIN(4, IPMI_WDOG_USE_USE_MASK);
127#define IPMI_WDOG_ACT_MASK 0x07 126#define IPMI_WDOG_USE_USE_OEM __SHIFTIN(5, IPMI_WDOG_USE_USE_MASK);
128#define IPMI_WDOG_ACT_DISABLED 0x00 127
129#define IPMI_WDOG_ACT_RESET 0x01 128#define IPMI_WDOG_ACT_PRE_RSVD1 __BIT(7)
130#define IPMI_WDOG_ACT_PWROFF 0x02 129#define IPMI_WDOG_ACT_PRE_MASK __BITS(6, 4)
131#define IPMI_WDOG_ACT_PWRCYCLE 0x03 130#define IPMI_WDOG_ACT_PRE_DISABLED __SHIFTIN(0, IPMI_WDOG_ACT_MASK)
132 131#define IPMI_WDOG_ACT_PRE_SMI __SHIFTIN(1, IPMI_WDOG_ACT_MASK)
133#define IPMI_WDOG_ACT_PRE_MASK 0x70 132#define IPMI_WDOG_ACT_PRE_NMI __SHIFTIN(2, IPMI_WDOG_ACT_MASK)
134#define IPMI_WDOG_ACT_PRE_DISABLED 0x00 133#define IPMI_WDOG_ACT_PRE_INTERRUPT __SHIFTIN(3, IPMI_WDOG_ACT_MASK)
135#define IPMI_WDOG_ACT_PRE_SMI 0x10 134#define IPMI_WDOG_ACT_PRE_RSVD0 __BIT(3)
136#define IPMI_WDOG_ACT_PRE_NMI 0x20 135#define IPMI_WDOG_ACT_MASK __BITS(2, 0)
137#define IPMI_WDOG_ACT_PRE_INTERRUPT 0x30 136#define IPMI_WDOG_ACT_DISABLED __SHIFTIN(0, IPMI_WDOG_ACT_MASK)
 137#define IPMI_WDOG_ACT_RESET __SHIFTIN(1, IPMI_WDOG_ACT_MASK)
 138#define IPMI_WDOG_ACT_PWROFF __SHIFTIN(2, IPMI_WDOG_ACT_MASK)
 139#define IPMI_WDOG_ACT_PWRCYCLE __SHIFTIN(3, IPMI_WDOG_ACT_MASK)
 140
 141#define IPMI_WDOG_FLAGS_RSVD1 __BITS(7, 6)
 142#define IPMI_WDOG_FLAGS_OEM __BIT(5)
 143#define IPMI_WDOG_FLAGS_OS __BIT(4)
 144#define IPMI_WDOG_FLAGS_OSLOAD __BIT(3)
 145#define IPMI_WDOG_FLAGS_POST __BIT(2)
 146#define IPMI_WDOG_FLAGS_FRB2 __BIT(1)
 147#define IPMI_WDOG_FLAGS_RSVD0 __BIT(0)
138 148
139struct ipmi_set_watchdog { 149struct ipmi_set_watchdog {
140 uint8_t wdog_use; 150 uint8_t wdog_use;
141 uint8_t wdog_action; 151 uint8_t wdog_action;
142 uint8_t wdog_pretimeout; 152 uint8_t wdog_pretimeout;
143 uint8_t wdog_flags; 153 uint8_t wdog_flags;
144 uint16_t wdog_timeout; 154 uint16_t wdog_timeout;
145} __packed; 155} __packed;
146 156
147struct ipmi_get_watchdog { 157struct ipmi_get_watchdog {
148 uint8_t wdog_use; 158 uint8_t wdog_use;
149 uint8_t wdog_action; 159 uint8_t wdog_action;
150 uint8_t wdog_pretimeout; 160 uint8_t wdog_pretimeout;

cvs diff -r1.38 -r1.39 src/sys/arch/x86/x86/Attic/ipmi.c (expand / switch to unified diff)

--- src/sys/arch/x86/x86/Attic/ipmi.c 2009/07/11 05:03:11 1.38
+++ src/sys/arch/x86/x86/Attic/ipmi.c 2009/07/20 19:11:30 1.39
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ipmi.c,v 1.38 2009/07/11 05:03:11 pgoyette Exp $ */ 1/* $NetBSD: ipmi.c,v 1.39 2009/07/20 19:11:30 dyoung Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Manuel Bouyer. 4 * Copyright (c) 2006 Manuel Bouyer.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software 14 * 3. All advertising materials mentioning features or use of this software
@@ -47,27 +47,27 @@ @@ -47,27 +47,27 @@
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR 49 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
50 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE. 56 * SUCH DAMAGE.
57 */ 57 */
58 58
59#include <sys/cdefs.h> 59#include <sys/cdefs.h>
60__KERNEL_RCSID(0, "$NetBSD: ipmi.c,v 1.38 2009/07/11 05:03:11 pgoyette Exp $"); 60__KERNEL_RCSID(0, "$NetBSD: ipmi.c,v 1.39 2009/07/20 19:11:30 dyoung Exp $");
61 61
62#include <sys/types.h> 62#include <sys/types.h>
63#include <sys/param.h> 63#include <sys/param.h>
64#include <sys/systm.h> 64#include <sys/systm.h>
65#include <sys/kernel.h> 65#include <sys/kernel.h>
66#include <sys/device.h> 66#include <sys/device.h>
67#include <sys/extent.h> 67#include <sys/extent.h>
68#include <sys/callout.h> 68#include <sys/callout.h>
69#include <sys/envsys.h> 69#include <sys/envsys.h>
70#include <sys/malloc.h> 70#include <sys/malloc.h>
71#include <sys/kthread.h> 71#include <sys/kthread.h>
72#include <sys/bus.h> 72#include <sys/bus.h>
73#include <sys/intr.h> 73#include <sys/intr.h>
@@ -85,27 +85,26 @@ struct ipmi_sensor { @@ -85,27 +85,26 @@ struct ipmi_sensor {
85 uint8_t *i_sdr; 85 uint8_t *i_sdr;
86 int i_num; 86 int i_num;
87 int i_stype; 87 int i_stype;
88 int i_etype; 88 int i_etype;
89 char i_envdesc[64]; 89 char i_envdesc[64];
90 int i_envtype; /* envsys compatible type */ 90 int i_envtype; /* envsys compatible type */
91 int i_envnum; /* envsys index */ 91 int i_envnum; /* envsys index */
92 sysmon_envsys_lim_t i_limits; 92 sysmon_envsys_lim_t i_limits;
93 SLIST_ENTRY(ipmi_sensor) i_list; 93 SLIST_ENTRY(ipmi_sensor) i_list;
94}; 94};
95 95
96int ipmi_nintr; 96int ipmi_nintr;
97int ipmi_dbg = 0; 97int ipmi_dbg = 0;
98int ipmi_poll = 1; 
99int ipmi_enabled = 0; 98int ipmi_enabled = 0;
100 99
101#define SENSOR_REFRESH_RATE (5 * hz) 100#define SENSOR_REFRESH_RATE (5 * hz)
102 101
103#define SMBIOS_TYPE_IPMI 0x26 102#define SMBIOS_TYPE_IPMI 0x26
104 103
105/* 104/*
106 * Format of SMBIOS IPMI Flags 105 * Format of SMBIOS IPMI Flags
107 * 106 *
108 * bit0: interrupt trigger mode (1=level, 0=edge) 107 * bit0: interrupt trigger mode (1=level, 0=edge)
109 * bit1: interrupt polarity (1=active high, 0=active low) 108 * bit1: interrupt polarity (1=active high, 0=active low)
110 * bit2: reserved 109 * bit2: reserved
111 * bit3: address LSB (1=odd,0=even) 110 * bit3: address LSB (1=odd,0=even)
@@ -168,49 +167,51 @@ long signextend(unsigned long, int); @@ -168,49 +167,51 @@ long signextend(unsigned long, int);
168 167
169SLIST_HEAD(ipmi_sensors_head, ipmi_sensor); 168SLIST_HEAD(ipmi_sensors_head, ipmi_sensor);
170struct ipmi_sensors_head ipmi_sensor_list = 169struct ipmi_sensors_head ipmi_sensor_list =
171 SLIST_HEAD_INITIALIZER(&ipmi_sensor_list); 170 SLIST_HEAD_INITIALIZER(&ipmi_sensor_list);
172 171
173void dumpb(const char *, int, const uint8_t *); 172void dumpb(const char *, int, const uint8_t *);
174 173
175int read_sensor(struct ipmi_softc *, struct ipmi_sensor *); 174int read_sensor(struct ipmi_softc *, struct ipmi_sensor *);
176int add_sdr_sensor(struct ipmi_softc *, uint8_t *); 175int add_sdr_sensor(struct ipmi_softc *, uint8_t *);
177int get_sdr_partial(struct ipmi_softc *, uint16_t, uint16_t, 176int get_sdr_partial(struct ipmi_softc *, uint16_t, uint16_t,
178 uint8_t, uint8_t, void *, uint16_t *); 177 uint8_t, uint8_t, void *, uint16_t *);
179int get_sdr(struct ipmi_softc *, uint16_t, uint16_t *); 178int get_sdr(struct ipmi_softc *, uint16_t, uint16_t *);
180 179
 180char *ipmi_buf_acquire(struct ipmi_softc *, size_t);
 181void ipmi_buf_release(struct ipmi_softc *, char *);
181int ipmi_sendcmd(struct ipmi_softc *, int, int, int, int, int, const void*); 182int ipmi_sendcmd(struct ipmi_softc *, int, int, int, int, int, const void*);
182int ipmi_recvcmd(struct ipmi_softc *, int, int *, void *); 183int ipmi_recvcmd(struct ipmi_softc *, int, int *, void *);
183void ipmi_delay(struct ipmi_softc *, int); 184void ipmi_delay(struct ipmi_softc *, int);
184 185
185int ipmi_watchdog_setmode(struct sysmon_wdog *); 186int ipmi_watchdog_setmode(struct sysmon_wdog *);
186int ipmi_watchdog_tickle(struct sysmon_wdog *); 187int ipmi_watchdog_tickle(struct sysmon_wdog *);
 188void ipmi_dotickle(struct ipmi_softc *);
187 189
188int ipmi_intr(void *); 190int ipmi_intr(void *);
189int ipmi_match(device_t, cfdata_t, void *); 191int ipmi_match(device_t, cfdata_t, void *);
190void ipmi_attach(device_t, device_t, void *); 192void ipmi_attach(device_t, device_t, void *);
191static int ipmi_detach(device_t, int); 193static int ipmi_detach(device_t, int);
192 194
193long ipow(long, int); 195long ipow(long, int);
194long ipmi_convert(uint8_t, struct sdrtype1 *, long); 196long ipmi_convert(uint8_t, struct sdrtype1 *, long);
195void ipmi_sensor_name(char *, int, uint8_t, uint8_t *); 197void ipmi_sensor_name(char *, int, uint8_t, uint8_t *);
196 198
197/* BMC Helper Functions */ 199/* BMC Helper Functions */
198uint8_t bmc_read(struct ipmi_softc *, int); 200uint8_t bmc_read(struct ipmi_softc *, int);
199void bmc_write(struct ipmi_softc *, int, uint8_t); 201void bmc_write(struct ipmi_softc *, int, uint8_t);
200int bmc_io_wait(struct ipmi_softc *, int, uint8_t, uint8_t, const char *); 202int bmc_io_wait(struct ipmi_softc *, int, uint8_t, uint8_t, const char *);
201int bmc_io_wait_spin(struct ipmi_softc *, int, uint8_t, uint8_t, 203int bmc_io_wait_spin(struct ipmi_softc *, int, uint8_t, uint8_t);
202 const char *); 204int bmc_io_wait_sleep(struct ipmi_softc *, int, uint8_t, uint8_t);
203void _bmc_io_wait(void *); 
204 205
205void *bt_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *); 206void *bt_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *);
206void *cmn_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *); 207void *cmn_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *);
207 208
208int getbits(uint8_t *, int, int); 209int getbits(uint8_t *, int, int);
209int ipmi_sensor_type(int, int, int); 210int ipmi_sensor_type(int, int, int);
210 211
211void ipmi_smbios_probe(struct smbios_ipmi *, struct ipmi_attach_args *); 212void ipmi_smbios_probe(struct smbios_ipmi *, struct ipmi_attach_args *);
212void ipmi_refresh_sensors(struct ipmi_softc *sc); 213void ipmi_refresh_sensors(struct ipmi_softc *sc);
213int ipmi_map_regs(struct ipmi_softc *sc, struct ipmi_attach_args *ia); 214int ipmi_map_regs(struct ipmi_softc *sc, struct ipmi_attach_args *ia);
214void ipmi_unmap_regs(struct ipmi_softc *sc); 215void ipmi_unmap_regs(struct ipmi_softc *sc);
215 216
216void *scan_sig(long, long, int, int, const void *); 217void *scan_sig(long, long, int, int, const void *);
@@ -282,88 +283,62 @@ uint8_t @@ -282,88 +283,62 @@ uint8_t
282bmc_read(struct ipmi_softc *sc, int offset) 283bmc_read(struct ipmi_softc *sc, int offset)
283{ 284{
284 return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, 285 return (bus_space_read_1(sc->sc_iot, sc->sc_ioh,
285 offset * sc->sc_if_iospacing)); 286 offset * sc->sc_if_iospacing));
286} 287}
287 288
288void 289void
289bmc_write(struct ipmi_softc *sc, int offset, uint8_t val) 290bmc_write(struct ipmi_softc *sc, int offset, uint8_t val)
290{ 291{
291 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 292 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
292 offset * sc->sc_if_iospacing, val); 293 offset * sc->sc_if_iospacing, val);
293} 294}
294 295
295void 296int
296_bmc_io_wait(void *arg) 297bmc_io_wait_sleep(struct ipmi_softc *sc, int offset, uint8_t mask,
 298 uint8_t value)
297{ 299{
298 struct ipmi_softc *sc = arg; 300 int retries;
299 struct ipmi_bmc_args *a = sc->sc_iowait_args; 301 uint8_t v;
300 302
301 *a->v = bmc_read(sc, a->offset); 303 KASSERT(mutex_owned(&sc->sc_cmd_mtx));
302 if ((*a->v & a->mask) == a->value) { 
303 sc->sc_wakeup = 0; 
304 wakeup(sc); 
305 return; 
306 } 
307 304
308 if (++sc->sc_retries > sc->sc_max_retries) { 305 for (retries = 0; retries < sc->sc_max_retries; retries++) {
309 sc->sc_wakeup = 0; 306 v = bmc_read(sc, offset);
310 wakeup(sc); 307 if ((v & mask) == value)
311 return; 308 return v;
 309 cv_timedwait(&sc->sc_cmd_sleep, &sc->sc_cmd_mtx, 1);
312 } 310 }
313 311 return -1;
314 callout_schedule(&sc->sc_callout, 1); 
315} 312}
316 313
317int 314int
318bmc_io_wait(struct ipmi_softc *sc, int offset, uint8_t mask, uint8_t value, 315bmc_io_wait(struct ipmi_softc *sc, int offset, uint8_t mask, uint8_t value,
319 const char *lbl) 316 const char *lbl)
320{ 317{
321 volatile uint8_t v; 318 int v;
322 int u; 
323 struct ipmi_bmc_args args; 
324 
325 u = bmc_io_wait_spin(sc, offset, mask, value, lbl); 
326 if (cold || u != -1) 
327 return u; 
328 
329 sc->sc_retries = 0; 
330 sc->sc_wakeup = 1; 
331 
332 args.offset = offset; 
333 args.mask = mask; 
334 args.value = value; 
335 args.v = &v; 
336 sc->sc_iowait_args = &args; 
337 
338 _bmc_io_wait(sc); 
339 
340 while (sc->sc_wakeup) 
341 tsleep(sc, PWAIT, lbl, 0); 
342 
343 if (sc->sc_retries > sc->sc_max_retries) { 
344 dbg_printf(1, "ipmi: bmc_io_wait fails : v=%.2x m=%.2x " 
345 "b=%.2x %s\n", v, mask, value, lbl); 
346 return (-1); 
347 } 
348 319
349 return (v); 320 v = bmc_io_wait_spin(sc, offset, mask, value);
 321 if (cold || v != -1)
 322 return v;
 323
 324 return bmc_io_wait_sleep(sc, offset, mask, value);
350} 325}
351 326
352int 327int
353bmc_io_wait_spin(struct ipmi_softc *sc, int offset, uint8_t mask, 328bmc_io_wait_spin(struct ipmi_softc *sc, int offset, uint8_t mask,
354 uint8_t value, const char *lbl) 329 uint8_t value)
355{ 330{
356 volatile uint8_t v; 331 uint8_t v;
357 int count = cold ? 5000 : 500; 332 int count = cold ? 5000 : 500;
358 /* ~us */ 333 /* ~us */
359 334
360 while (count--) { 335 while (count--) {
361 v = bmc_read(sc, offset); 336 v = bmc_read(sc, offset);
362 if ((v & mask) == value) 337 if ((v & mask) == value)
363 return v; 338 return v;
364 339
365 delay(1); 340 delay(1);
366 } 341 }
367 342
368 return (-1); 343 return (-1);
369 344
@@ -971,27 +946,27 @@ ipmi_smbios_probe(struct smbios_ipmi *pi @@ -971,27 +946,27 @@ ipmi_smbios_probe(struct smbios_ipmi *pi
971 * This is used by BT protocol 946 * This is used by BT protocol
972 * 947 *
973 * Returns a buffer to an allocated message, txlen contains length 948 * Returns a buffer to an allocated message, txlen contains length
974 * of allocated message 949 * of allocated message
975 */ 950 */
976void * 951void *
977bt_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len, 952bt_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len,
978 const void *data, int *txlen) 953 const void *data, int *txlen)
979{ 954{
980 uint8_t *buf; 955 uint8_t *buf;
981 956
982 /* Block transfer needs 4 extra bytes: length/netfn/seq/cmd + data */ 957 /* Block transfer needs 4 extra bytes: length/netfn/seq/cmd + data */
983 *txlen = len + 4; 958 *txlen = len + 4;
984 buf = malloc(*txlen, M_DEVBUF, M_WAITOK|M_CANFAIL); 959 buf = ipmi_buf_acquire(sc, *txlen);
985 if (buf == NULL) 960 if (buf == NULL)
986 return (NULL); 961 return (NULL);
987 962
988 buf[IPMI_BTMSG_LEN] = len + 3; 963 buf[IPMI_BTMSG_LEN] = len + 3;
989 buf[IPMI_BTMSG_NFLN] = nfLun; 964 buf[IPMI_BTMSG_NFLN] = nfLun;
990 buf[IPMI_BTMSG_SEQ] = sc->sc_btseq++; 965 buf[IPMI_BTMSG_SEQ] = sc->sc_btseq++;
991 buf[IPMI_BTMSG_CMD] = cmd; 966 buf[IPMI_BTMSG_CMD] = cmd;
992 if (len && data) 967 if (len && data)
993 memcpy(buf + IPMI_BTMSG_DATASND, data, len); 968 memcpy(buf + IPMI_BTMSG_DATASND, data, len);
994 969
995 return (buf); 970 return (buf);
996} 971}
997 972
@@ -1000,39 +975,43 @@ bt_buildmsg(struct ipmi_softc *sc, int n @@ -1000,39 +975,43 @@ bt_buildmsg(struct ipmi_softc *sc, int n
1000 * This is used by both SMIC and KCS protocols 975 * This is used by both SMIC and KCS protocols
1001 * 976 *
1002 * Returns a buffer to an allocated message, txlen contains length 977 * Returns a buffer to an allocated message, txlen contains length
1003 * of allocated message 978 * of allocated message
1004 */ 979 */
1005void * 980void *
1006cmn_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len, 981cmn_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len,
1007 const void *data, int *txlen) 982 const void *data, int *txlen)
1008{ 983{
1009 uint8_t *buf; 984 uint8_t *buf;
1010 985
1011 /* Common needs two extra bytes: nfLun/cmd + data */ 986 /* Common needs two extra bytes: nfLun/cmd + data */
1012 *txlen = len + 2; 987 *txlen = len + 2;
1013 buf = malloc(*txlen, M_DEVBUF, M_WAITOK|M_CANFAIL); 988 buf = ipmi_buf_acquire(sc, *txlen);
1014 if (buf == NULL) 989 if (buf == NULL)
1015 return (NULL); 990 return (NULL);
1016 991
1017 buf[IPMI_MSG_NFLN] = nfLun; 992 buf[IPMI_MSG_NFLN] = nfLun;
1018 buf[IPMI_MSG_CMD] = cmd; 993 buf[IPMI_MSG_CMD] = cmd;
1019 if (len && data) 994 if (len && data)
1020 memcpy(buf + IPMI_MSG_DATASND, data, len); 995 memcpy(buf + IPMI_MSG_DATASND, data, len);
1021 996
1022 return (buf); 997 return (buf);
1023} 998}
1024 999
1025/* Send an IPMI command */ 1000/*
 1001 * ipmi_sendcmd: caller must hold sc_cmd_mtx.
 1002 *
 1003 * Send an IPMI command
 1004 */
1026int 1005int
1027ipmi_sendcmd(struct ipmi_softc *sc, int rssa, int rslun, int netfn, int cmd, 1006ipmi_sendcmd(struct ipmi_softc *sc, int rssa, int rslun, int netfn, int cmd,
1028 int txlen, const void *data) 1007 int txlen, const void *data)
1029{ 1008{
1030 uint8_t *buf; 1009 uint8_t *buf;
1031 int rc = -1; 1010 int rc = -1;
1032 1011
1033 dbg_printf(50, "ipmi_sendcmd: rssa=%.2x nfln=%.2x cmd=%.2x len=%.2x\n", 1012 dbg_printf(50, "ipmi_sendcmd: rssa=%.2x nfln=%.2x cmd=%.2x len=%.2x\n",
1034 rssa, NETFN_LUN(netfn, rslun), cmd, txlen); 1013 rssa, NETFN_LUN(netfn, rslun), cmd, txlen);
1035 dbg_dump(10, " send", txlen, data); 1014 dbg_dump(10, " send", txlen, data);
1036 if (rssa != BMC_SA) { 1015 if (rssa != BMC_SA) {
1037#if 0 1016#if 0
1038 buf = sc->sc_if->buildmsg(sc, NETFN_LUN(APP_NETFN, BMC_LUN), 1017 buf = sc->sc_if->buildmsg(sc, NETFN_LUN(APP_NETFN, BMC_LUN),
@@ -1052,126 +1031,159 @@ ipmi_sendcmd(struct ipmi_softc *sc, int  @@ -1052,126 +1031,159 @@ ipmi_sendcmd(struct ipmi_softc *sc, int
1052 /* Set message checksum */ 1031 /* Set message checksum */
1053 imbreq->data[txlen] = cksum8(&imbreq->rqSa, txlen + 3); 1032 imbreq->data[txlen] = cksum8(&imbreq->rqSa, txlen + 3);
1054#endif 1033#endif
1055 goto done; 1034 goto done;
1056 } else 1035 } else
1057 buf = sc->sc_if->buildmsg(sc, NETFN_LUN(netfn, rslun), cmd, 1036 buf = sc->sc_if->buildmsg(sc, NETFN_LUN(netfn, rslun), cmd,
1058 txlen, data, &txlen); 1037 txlen, data, &txlen);
1059 1038
1060 if (buf == NULL) { 1039 if (buf == NULL) {
1061 printf("ipmi: sendcmd malloc fails\n"); 1040 printf("ipmi: sendcmd malloc fails\n");
1062 goto done; 1041 goto done;
1063 } 1042 }
1064 rc = sc->sc_if->sendmsg(sc, txlen, buf); 1043 rc = sc->sc_if->sendmsg(sc, txlen, buf);
1065 free(buf, M_DEVBUF); 1044 ipmi_buf_release(sc, buf);
1066 1045
1067 ipmi_delay(sc, 50); /* give bmc chance to digest command */ 1046 ipmi_delay(sc, 50); /* give bmc chance to digest command */
1068 1047
1069done: 1048done:
1070 return (rc); 1049 return (rc);
1071} 1050}
1072 1051
 1052void
 1053ipmi_buf_release(struct ipmi_softc *sc, char *buf)
 1054{
 1055 KASSERT(sc->sc_buf_rsvd);
 1056 KASSERT(sc->sc_buf == buf);
 1057 sc->sc_buf_rsvd = false;
 1058}
 1059
 1060char *
 1061ipmi_buf_acquire(struct ipmi_softc *sc, size_t len)
 1062{
 1063 KASSERT(len <= sizeof(sc->sc_buf));
 1064
 1065 if (sc->sc_buf_rsvd || len > sizeof(sc->sc_buf))
 1066 return NULL;
 1067 sc->sc_buf_rsvd = true;
 1068 return sc->sc_buf;
 1069}
 1070
 1071/*
 1072 * ipmi_recvcmd: caller must hold sc_cmd_mtx.
 1073 */
1073int 1074int
1074ipmi_recvcmd(struct ipmi_softc *sc, int maxlen, int *rxlen, void *data) 1075ipmi_recvcmd(struct ipmi_softc *sc, int maxlen, int *rxlen, void *data)
1075{ 1076{
1076 uint8_t *buf, rc = 0; 1077 uint8_t *buf, rc = 0;
1077 int rawlen; 1078 int rawlen;
1078 1079
1079 /* Need three extra bytes: netfn/cmd/ccode + data */ 1080 /* Need three extra bytes: netfn/cmd/ccode + data */
1080 buf = malloc(maxlen + 3, M_DEVBUF, M_WAITOK|M_CANFAIL); 1081 buf = ipmi_buf_acquire(sc, maxlen + 3);
1081 if (buf == NULL) { 1082 if (buf == NULL) {
1082 printf("ipmi: ipmi_recvcmd: malloc fails\n"); 1083 printf("ipmi: ipmi_recvcmd: malloc fails\n");
1083 return (-1); 1084 return (-1);
1084 } 1085 }
1085 /* Receive message from interface, copy out result data */ 1086 /* Receive message from interface, copy out result data */
1086 if (sc->sc_if->recvmsg(sc, maxlen + 3, &rawlen, buf)) 1087 if (sc->sc_if->recvmsg(sc, maxlen + 3, &rawlen, buf))
1087 return (-1); 1088 return (-1);
1088 1089
1089 *rxlen = rawlen - IPMI_MSG_DATARCV; 1090 *rxlen = rawlen - IPMI_MSG_DATARCV;
1090 if (*rxlen > 0 && data) 1091 if (*rxlen > 0 && data)
1091 memcpy(data, buf + IPMI_MSG_DATARCV, *rxlen); 1092 memcpy(data, buf + IPMI_MSG_DATARCV, *rxlen);
1092 1093
1093 if ((rc = buf[IPMI_MSG_CCODE]) != 0) 1094 if ((rc = buf[IPMI_MSG_CCODE]) != 0)
1094 dbg_printf(1, "ipmi_recvmsg: nfln=%.2x cmd=%.2x err=%.2x\n", 1095 dbg_printf(1, "ipmi_recvmsg: nfln=%.2x cmd=%.2x err=%.2x\n",
1095 buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], buf[IPMI_MSG_CCODE]); 1096 buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], buf[IPMI_MSG_CCODE]);
1096 1097
1097 dbg_printf(50, "ipmi_recvcmd: nfln=%.2x cmd=%.2x err=%.2x len=%.2x\n", 1098 dbg_printf(50, "ipmi_recvcmd: nfln=%.2x cmd=%.2x err=%.2x len=%.2x\n",
1098 buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], buf[IPMI_MSG_CCODE], 1099 buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], buf[IPMI_MSG_CCODE],
1099 *rxlen); 1100 *rxlen);
1100 dbg_dump(10, " recv", *rxlen, data); 1101 dbg_dump(10, " recv", *rxlen, data);
1101 1102
1102 free(buf, M_DEVBUF); 1103 ipmi_buf_release(sc, buf);
1103 1104
1104 return (rc); 1105 return (rc);
1105} 1106}
1106 1107
 1108/*
 1109 * ipmi_delay: caller must hold sc_cmd_mtx.
 1110 */
1107void 1111void
1108ipmi_delay(struct ipmi_softc *sc, int ms) 1112ipmi_delay(struct ipmi_softc *sc, int ms)
1109{ 1113{
1110 if (cold) 1114 if (cold)
1111 delay(ms * 1000); 1115 delay(ms * 1000);
1112 else 1116 else
1113 while (tsleep(sc, PWAIT, "ipmicmd", mstohz(ms)) != EWOULDBLOCK); 1117 cv_timedwait(&sc->sc_cmd_sleep, &sc->sc_cmd_mtx, mstohz(ms));
1114} 1118}
1115 1119
1116/* Read a partial SDR entry */ 1120/* Read a partial SDR entry */
1117int 1121int
1118get_sdr_partial(struct ipmi_softc *sc, uint16_t recordId, uint16_t reserveId, 1122get_sdr_partial(struct ipmi_softc *sc, uint16_t recordId, uint16_t reserveId,
1119 uint8_t offset, uint8_t length, void *buffer, uint16_t *nxtRecordId) 1123 uint8_t offset, uint8_t length, void *buffer, uint16_t *nxtRecordId)
1120{ 1124{
1121 uint8_t cmd[256 + 8]; 1125 uint8_t cmd[256 + 8];
1122 int len; 1126 int len;
1123 1127
1124 ((uint16_t *) cmd)[0] = reserveId; 1128 ((uint16_t *) cmd)[0] = reserveId;
1125 ((uint16_t *) cmd)[1] = recordId; 1129 ((uint16_t *) cmd)[1] = recordId;
1126 cmd[4] = offset; 1130 cmd[4] = offset;
1127 cmd[5] = length; 1131 cmd[5] = length;
 1132 mutex_enter(&sc->sc_cmd_mtx);
1128 if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_GET_SDR, 6, 1133 if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_GET_SDR, 6,
1129 cmd)) { 1134 cmd)) {
 1135 mutex_exit(&sc->sc_cmd_mtx);
1130 printf("ipmi: sendcmd fails\n"); 1136 printf("ipmi: sendcmd fails\n");
1131 return (-1); 1137 return (-1);
1132 } 1138 }
1133 if (ipmi_recvcmd(sc, 8 + length, &len, cmd)) { 1139 if (ipmi_recvcmd(sc, 8 + length, &len, cmd)) {
 1140 mutex_exit(&sc->sc_cmd_mtx);
1134 printf("ipmi: getSdrPartial: recvcmd fails\n"); 1141 printf("ipmi: getSdrPartial: recvcmd fails\n");
1135 return (-1); 1142 return (-1);
1136 } 1143 }
 1144 mutex_exit(&sc->sc_cmd_mtx);
1137 if (nxtRecordId) 1145 if (nxtRecordId)
1138 *nxtRecordId = *(uint16_t *) cmd; 1146 *nxtRecordId = *(uint16_t *) cmd;
1139 memcpy(buffer, cmd + 2, len - 2); 1147 memcpy(buffer, cmd + 2, len - 2);
1140 1148
1141 return (0); 1149 return (0);
1142} 1150}
1143 1151
1144int maxsdrlen = 0x10; 1152int maxsdrlen = 0x10;
1145 1153
1146/* Read an entire SDR; pass to add sensor */ 1154/* Read an entire SDR; pass to add sensor */
1147int 1155int
1148get_sdr(struct ipmi_softc *sc, uint16_t recid, uint16_t *nxtrec) 1156get_sdr(struct ipmi_softc *sc, uint16_t recid, uint16_t *nxtrec)
1149{ 1157{
1150 uint16_t resid = 0; 1158 uint16_t resid = 0;
1151 int len, sdrlen, offset; 1159 int len, sdrlen, offset;
1152 uint8_t *psdr; 1160 uint8_t *psdr;
1153 struct sdrhdr shdr; 1161 struct sdrhdr shdr;
1154 1162
 1163 mutex_enter(&sc->sc_cmd_mtx);
1155 /* Reserve SDR */ 1164 /* Reserve SDR */
1156 if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_RESERVE_SDR, 1165 if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_RESERVE_SDR,
1157 0, NULL)) { 1166 0, NULL)) {
 1167 mutex_exit(&sc->sc_cmd_mtx);
1158 printf("ipmi: reserve send fails\n"); 1168 printf("ipmi: reserve send fails\n");
1159 return (-1); 1169 return (-1);
1160 } 1170 }
1161 if (ipmi_recvcmd(sc, sizeof(resid), &len, &resid)) { 1171 if (ipmi_recvcmd(sc, sizeof(resid), &len, &resid)) {
 1172 mutex_exit(&sc->sc_cmd_mtx);
1162 printf("ipmi: reserve recv fails\n"); 1173 printf("ipmi: reserve recv fails\n");
1163 return (-1); 1174 return (-1);
1164 } 1175 }
 1176 mutex_exit(&sc->sc_cmd_mtx);
1165 /* Get SDR Header */ 1177 /* Get SDR Header */
1166 if (get_sdr_partial(sc, recid, resid, 0, sizeof shdr, &shdr, nxtrec)) { 1178 if (get_sdr_partial(sc, recid, resid, 0, sizeof shdr, &shdr, nxtrec)) {
1167 printf("ipmi: get header fails\n"); 1179 printf("ipmi: get header fails\n");
1168 return (-1); 1180 return (-1);
1169 } 1181 }
1170 /* Allocate space for entire SDR Length of SDR in header does not 1182 /* Allocate space for entire SDR Length of SDR in header does not
1171 * include header length */ 1183 * include header length */
1172 sdrlen = sizeof(shdr) + shdr.record_length; 1184 sdrlen = sizeof(shdr) + shdr.record_length;
1173 psdr = malloc(sdrlen, M_DEVBUF, M_WAITOK|M_CANFAIL); 1185 psdr = malloc(sdrlen, M_DEVBUF, M_WAITOK|M_CANFAIL);
1174 if (psdr == NULL) 1186 if (psdr == NULL)
1175 return -1; 1187 return -1;
1176 1188
1177 memcpy(psdr, &shdr, sizeof(shdr)); 1189 memcpy(psdr, &shdr, sizeof(shdr));
@@ -1370,34 +1382,39 @@ ipmi_get_limits(struct sysmon_envsys *sm @@ -1370,34 +1382,39 @@ ipmi_get_limits(struct sysmon_envsys *sm
1370 ipmi_get_sensor_limits(sc, ipmi_s, limits); 1382 ipmi_get_sensor_limits(sc, ipmi_s, limits);
1371 ipmi_s->i_limits = *limits; 1383 ipmi_s->i_limits = *limits;
1372 return; 1384 return;
1373 } 1385 }
1374 } 1386 }
1375 return; 1387 return;
1376} 1388}
1377 1389
1378void 1390void
1379ipmi_get_sensor_limits(struct ipmi_softc *sc, struct ipmi_sensor *psensor, 1391ipmi_get_sensor_limits(struct ipmi_softc *sc, struct ipmi_sensor *psensor,
1380 sysmon_envsys_lim_t *limits) 1392 sysmon_envsys_lim_t *limits)
1381{ 1393{
1382 struct sdrtype1 *s1 = (struct sdrtype1 *)psensor->i_sdr; 1394 struct sdrtype1 *s1 = (struct sdrtype1 *)psensor->i_sdr;
 1395 bool failure;
1383 int rxlen; 1396 int rxlen;
1384 uint8_t data[32]; 1397 uint8_t data[32];
1385 1398
1386 limits->sel_flags = 0; 1399 limits->sel_flags = 0;
1387 data[0] = psensor->i_num; 1400 data[0] = psensor->i_num;
1388 if (ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun, 1401 mutex_enter(&sc->sc_cmd_mtx);
 1402 failure =
 1403 ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun,
1389 SE_NETFN, SE_GET_SENSOR_THRESHOLD, 1, data) || 1404 SE_NETFN, SE_GET_SENSOR_THRESHOLD, 1, data) ||
1390 ipmi_recvcmd(sc, sizeof(data), &rxlen, data)) 1405 ipmi_recvcmd(sc, sizeof(data), &rxlen, data);
 1406 mutex_exit(&sc->sc_cmd_mtx);
 1407 if (failure)
1391 return; 1408 return;
1392 1409
1393 dbg_printf(25, "recvdata: %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", 1410 dbg_printf(25, "recvdata: %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n",
1394 data[0], data[1], data[2], data[3], data[4], data[5], data[6]); 1411 data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
1395 1412
1396 if (data[0] & 0x20 && data[6] != 0xff) { 1413 if (data[0] & 0x20 && data[6] != 0xff) {
1397 limits->sel_critmax = ipmi_convert_sensor(&data[6], psensor); 1414 limits->sel_critmax = ipmi_convert_sensor(&data[6], psensor);
1398 limits->sel_flags |= PROP_CRITMAX; 1415 limits->sel_flags |= PROP_CRITMAX;
1399 } 1416 }
1400 if (data[0] & 0x10 && data[5] != 0xff) { 1417 if (data[0] & 0x10 && data[5] != 0xff) {
1401 limits->sel_critmax = ipmi_convert_sensor(&data[5], psensor); 1418 limits->sel_critmax = ipmi_convert_sensor(&data[5], psensor);
1402 limits->sel_flags |= PROP_CRITMAX; 1419 limits->sel_flags |= PROP_CRITMAX;
1403 } 1420 }
@@ -1475,50 +1492,53 @@ ipmi_sensor_status(struct ipmi_softc *sc @@ -1475,50 +1492,53 @@ ipmi_sensor_status(struct ipmi_softc *sc
1475 return ENVSYS_SWARNOVER; 1492 return ENVSYS_SWARNOVER;
1476 } 1493 }
1477 break; 1494 break;
1478 } 1495 }
1479 1496
1480 return ENVSYS_SVALID; 1497 return ENVSYS_SVALID;
1481} 1498}
1482 1499
1483int 1500int
1484read_sensor(struct ipmi_softc *sc, struct ipmi_sensor *psensor) 1501read_sensor(struct ipmi_softc *sc, struct ipmi_sensor *psensor)
1485{ 1502{
1486 struct sdrtype1 *s1 = (struct sdrtype1 *) psensor->i_sdr; 1503 struct sdrtype1 *s1 = (struct sdrtype1 *) psensor->i_sdr;
1487 uint8_t data[8]; 1504 uint8_t data[8];
1488 int rxlen, rv = -1; 1505 int rxlen;
1489 envsys_data_t *edata = &sc->sc_sensor[psensor->i_envnum]; 1506 envsys_data_t *edata = &sc->sc_sensor[psensor->i_envnum];
1490 1507
1491 mutex_enter(&sc->sc_lock); 
1492 memset(data, 0, sizeof(data)); 1508 memset(data, 0, sizeof(data));
1493 data[0] = psensor->i_num; 1509 data[0] = psensor->i_num;
 1510
 1511 mutex_enter(&sc->sc_cmd_mtx);
1494 if (ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun, SE_NETFN, 1512 if (ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun, SE_NETFN,
1495 SE_GET_SENSOR_READING, 1, data)) 1513 SE_GET_SENSOR_READING, 1, data))
1496 goto done; 1514 goto err;
1497 1515
1498 if (ipmi_recvcmd(sc, sizeof(data), &rxlen, data)) 1516 if (ipmi_recvcmd(sc, sizeof(data), &rxlen, data))
1499 goto done; 1517 goto err;
 1518 mutex_exit(&sc->sc_cmd_mtx);
 1519
1500 dbg_printf(10, "values=%.2x %.2x %.2x %.2x %s\n", 1520 dbg_printf(10, "values=%.2x %.2x %.2x %.2x %s\n",
1501 data[0],data[1],data[2],data[3], edata->desc); 1521 data[0],data[1],data[2],data[3], edata->desc);
1502 if (data[1] & IPMI_INVALID_SENSOR) { 1522 if (data[1] & IPMI_INVALID_SENSOR) {
1503 /* Check if sensor is valid */ 1523 /* Check if sensor is valid */
1504 edata->state = ENVSYS_SINVALID; 1524 edata->state = ENVSYS_SINVALID;
1505 } else { 1525 } else {
1506 edata->state = ipmi_sensor_status(sc, psensor, edata, data); 1526 edata->state = ipmi_sensor_status(sc, psensor, edata, data);
1507 } 1527 }
1508 rv = 0; 1528 return 0;
1509done: 1529err:
1510 mutex_exit(&sc->sc_lock); 1530 mutex_exit(&sc->sc_cmd_mtx);
1511 return (rv); 1531 return -1;
1512} 1532}
1513 1533
1514int 1534int
1515ipmi_sensor_type(int type, int ext_type, int entity) 1535ipmi_sensor_type(int type, int ext_type, int entity)
1516{ 1536{
1517 switch (ext_type << 8L | type) { 1537 switch (ext_type << 8L | type) {
1518 case IPMI_SENSOR_TYPE_TEMP: 1538 case IPMI_SENSOR_TYPE_TEMP:
1519 return (ENVSYS_STEMP); 1539 return (ENVSYS_STEMP);
1520 1540
1521 case IPMI_SENSOR_TYPE_VOLT: 1541 case IPMI_SENSOR_TYPE_VOLT:
1522 return (ENVSYS_SVOLTS_DC); 1542 return (ENVSYS_SVOLTS_DC);
1523 1543
1524 case IPMI_SENSOR_TYPE_FAN: 1544 case IPMI_SENSOR_TYPE_FAN:
@@ -1665,29 +1685,26 @@ ipmi_intr(void *arg) @@ -1665,29 +1685,26 @@ ipmi_intr(void *arg)
1665 1685
1666 v = bmc_read(sc, _KCS_STATUS_REGISTER); 1686 v = bmc_read(sc, _KCS_STATUS_REGISTER);
1667 if (v & KCS_OBF) 1687 if (v & KCS_OBF)
1668 ++ipmi_nintr; 1688 ++ipmi_nintr;
1669 1689
1670 return (0); 1690 return (0);
1671} 1691}
1672 1692
1673/* Handle IPMI Timer - reread sensor values */ 1693/* Handle IPMI Timer - reread sensor values */
1674void 1694void
1675ipmi_refresh_sensors(struct ipmi_softc *sc) 1695ipmi_refresh_sensors(struct ipmi_softc *sc)
1676{ 1696{
1677 1697
1678 if (!ipmi_poll) 
1679 return; 
1680 
1681 if (SLIST_EMPTY(&ipmi_sensor_list)) 1698 if (SLIST_EMPTY(&ipmi_sensor_list))
1682 return; 1699 return;
1683 1700
1684 sc->current_sensor = SLIST_NEXT(sc->current_sensor, i_list); 1701 sc->current_sensor = SLIST_NEXT(sc->current_sensor, i_list);
1685 if (sc->current_sensor == NULL) 1702 if (sc->current_sensor == NULL)
1686 sc->current_sensor = SLIST_FIRST(&ipmi_sensor_list); 1703 sc->current_sensor = SLIST_FIRST(&ipmi_sensor_list);
1687 1704
1688 if (read_sensor(sc, sc->current_sensor)) { 1705 if (read_sensor(sc, sc->current_sensor)) {
1689 dbg_printf(1, "ipmi: error reading\n"); 1706 dbg_printf(1, "ipmi: error reading\n");
1690 } 1707 }
1691} 1708}
1692 1709
1693int 1710int
@@ -1754,74 +1771,82 @@ ipmi_probe(struct ipmi_attach_args *ia) @@ -1754,74 +1771,82 @@ ipmi_probe(struct ipmi_attach_args *ia)
1754 1771
1755 return (1); 1772 return (1);
1756} 1773}
1757 1774
1758int 1775int
1759ipmi_match(device_t parent, cfdata_t cf, void *aux) 1776ipmi_match(device_t parent, cfdata_t cf, void *aux)
1760{ 1777{
1761 struct ipmi_softc sc; 1778 struct ipmi_softc sc;
1762 struct ipmi_attach_args *ia = aux; 1779 struct ipmi_attach_args *ia = aux;
1763 uint8_t cmd[32]; 1780 uint8_t cmd[32];
1764 int len; 1781 int len;
1765 int rv = 0; 1782 int rv = 0;
1766 1783
 1784 memset(&sc, 0, sizeof(sc));
 1785
1767 /* Map registers */ 1786 /* Map registers */
1768 if (ipmi_map_regs(&sc, ia) != 0) 1787 if (ipmi_map_regs(&sc, ia) != 0)
1769 return 0; 1788 return 0;
1770 1789
1771 sc.sc_if->probe(&sc); 1790 sc.sc_if->probe(&sc);
1772 1791
 1792 mutex_init(&sc.sc_cmd_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK);
 1793 mutex_enter(&sc.sc_cmd_mtx);
1773 /* Identify BMC device early to detect lying bios */ 1794 /* Identify BMC device early to detect lying bios */
1774 if (ipmi_sendcmd(&sc, BMC_SA, 0, APP_NETFN, APP_GET_DEVICE_ID, 1795 if (ipmi_sendcmd(&sc, BMC_SA, 0, APP_NETFN, APP_GET_DEVICE_ID,
1775 0, NULL)) { 1796 0, NULL)) {
 1797 mutex_exit(&sc.sc_cmd_mtx);
1776 dbg_printf(1, ": unable to send get device id " 1798 dbg_printf(1, ": unable to send get device id "
1777 "command\n"); 1799 "command\n");
1778 goto unmap; 1800 goto unmap;
1779 } 1801 }
1780 if (ipmi_recvcmd(&sc, sizeof(cmd), &len, cmd)) { 1802 if (ipmi_recvcmd(&sc, sizeof(cmd), &len, cmd)) {
 1803 mutex_exit(&sc.sc_cmd_mtx);
1781 dbg_printf(1, ": unable to retrieve device id\n"); 1804 dbg_printf(1, ": unable to retrieve device id\n");
1782 goto unmap; 1805 goto unmap;
1783 } 1806 }
 1807 mutex_exit(&sc.sc_cmd_mtx);
1784 1808
1785 dbg_dump(1, "bmc data", len, cmd); 1809 dbg_dump(1, "bmc data", len, cmd);
1786 rv = 1; /* GETID worked, we got IPMI */ 1810 rv = 1; /* GETID worked, we got IPMI */
1787unmap: 1811unmap:
 1812 mutex_destroy(&sc.sc_cmd_mtx);
1788 ipmi_unmap_regs(&sc); 1813 ipmi_unmap_regs(&sc);
1789 1814
1790 return rv; 1815 return rv;
1791} 1816}
1792 1817
1793static void 1818static void
1794ipmi_thread(void *cookie) 1819ipmi_thread(void *cookie)
1795{ 1820{
1796 device_t self = cookie; 1821 device_t self = cookie;
1797 struct ipmi_softc *sc = device_private(self); 1822 struct ipmi_softc *sc = device_private(self);
1798 struct ipmi_attach_args *ia = &sc->sc_ia; 1823 struct ipmi_attach_args *ia = &sc->sc_ia;
1799 uint16_t rec; 1824 uint16_t rec;
1800 struct ipmi_sensor *ipmi_s; 1825 struct ipmi_sensor *ipmi_s;
1801 int i; 1826 int i;
1802 int current_index_typ[ENVSYS_NSENSORS]; 1827 int current_index_typ[ENVSYS_NSENSORS];
1803 1828
1804 sc->sc_thread_running = 1; 1829 sc->sc_thread_running = true;
1805 1830
1806 /* lock around read_sensor so that no one messes with the bmc regs */ 1831 /* lock around read_sensor so that no one messes with the bmc regs */
1807 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 1832 mutex_init(&sc->sc_cmd_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK);
 1833 cv_init(&sc->sc_cmd_sleep, "ipmicmd");
 1834
 1835 mutex_init(&sc->sc_poll_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK);
 1836 cv_init(&sc->sc_poll_cv, "ipmi_poll");
1808 1837
1809 /* setup ticker */ 1838 /* setup ticker */
1810 sc->sc_retries = 0; 
1811 sc->sc_wakeup = 0; 
1812 sc->sc_max_retries = hz * 90; /* 90 seconds max */ 1839 sc->sc_max_retries = hz * 90; /* 90 seconds max */
1813 callout_init(&sc->sc_callout, 0); 
1814 callout_setfunc(&sc->sc_callout, _bmc_io_wait, sc); 
1815 1840
1816 /* Map registers */ 1841 /* Map registers */
1817 ipmi_map_regs(sc, ia); 1842 ipmi_map_regs(sc, ia);
1818 1843
1819 /* Scan SDRs, add sensors to list */ 1844 /* Scan SDRs, add sensors to list */
1820 for (rec = 0; rec != 0xFFFF;) 1845 for (rec = 0; rec != 0xFFFF;)
1821 if (get_sdr(sc, rec, &rec)) 1846 if (get_sdr(sc, rec, &rec))
1822 break; 1847 break;
1823 1848
1824 /* fill in sensor infos: */ 1849 /* fill in sensor infos: */
1825 /* get indexes for each unit, and number of units */ 1850 /* get indexes for each unit, and number of units */
1826 current_index_typ[0] = 0; 1851 current_index_typ[0] = 0;
1827 for (i = 1; i < ENVSYS_NSENSORS; i++) { 1852 for (i = 1; i < ENVSYS_NSENSORS; i++) {
@@ -1890,58 +1915,66 @@ ipmi_thread(void *cookie) @@ -1890,58 +1915,66 @@ ipmi_thread(void *cookie)
1890 if (ia->iaa_if_irq != -1) 1915 if (ia->iaa_if_irq != -1)
1891 aprint_verbose_dev(self, " irq %d\n", ia->iaa_if_irq); 1916 aprint_verbose_dev(self, " irq %d\n", ia->iaa_if_irq);
1892 1917
1893 /* setup flag to exclude iic */ 1918 /* setup flag to exclude iic */
1894 ipmi_enabled = 1; 1919 ipmi_enabled = 1;
1895 1920
1896 /* Setup Watchdog timer */ 1921 /* Setup Watchdog timer */
1897 sc->sc_wdog.smw_name = device_xname(sc->sc_dev); 1922 sc->sc_wdog.smw_name = device_xname(sc->sc_dev);
1898 sc->sc_wdog.smw_cookie = sc; 1923 sc->sc_wdog.smw_cookie = sc;
1899 sc->sc_wdog.smw_setmode = ipmi_watchdog_setmode; 1924 sc->sc_wdog.smw_setmode = ipmi_watchdog_setmode;
1900 sc->sc_wdog.smw_tickle = ipmi_watchdog_tickle; 1925 sc->sc_wdog.smw_tickle = ipmi_watchdog_tickle;
1901 sysmon_wdog_register(&sc->sc_wdog); 1926 sysmon_wdog_register(&sc->sc_wdog);
1902 1927
 1928 mutex_enter(&sc->sc_poll_mtx);
1903 while (sc->sc_thread_running) { 1929 while (sc->sc_thread_running) {
1904 ipmi_refresh_sensors(sc); 1930 ipmi_refresh_sensors(sc);
1905 tsleep(&sc->sc_thread_running, PWAIT, "ipmi_poll", 1931 cv_timedwait(&sc->sc_poll_cv, &sc->sc_poll_mtx,
1906 SENSOR_REFRESH_RATE); 1932 SENSOR_REFRESH_RATE);
 1933 if (sc->sc_tickle_due) {
 1934 ipmi_dotickle(sc);
 1935 sc->sc_tickle_due = false;
 1936 }
1907 } 1937 }
 1938 mutex_exit(&sc->sc_poll_mtx);
1908 kthread_exit(0); 1939 kthread_exit(0);
1909} 1940}
1910 1941
1911void 1942void
1912ipmi_attach(device_t parent, device_t self, void *aux) 1943ipmi_attach(device_t parent, device_t self, void *aux)
1913{ 1944{
1914 struct ipmi_softc *sc = device_private(self); 1945 struct ipmi_softc *sc = device_private(self);
1915 1946
1916 sc->sc_ia = *(struct ipmi_attach_args *)aux; 1947 sc->sc_ia = *(struct ipmi_attach_args *)aux;
1917 sc->sc_dev = self; 1948 sc->sc_dev = self;
1918 aprint_normal("\n"); 1949 aprint_normal("\n");
1919 1950
1920 if (kthread_create(PRI_NONE, 0, NULL, ipmi_thread, self, 1951 if (kthread_create(PRI_NONE, 0, NULL, ipmi_thread, self,
1921 &sc->sc_kthread, "ipmi") != 0) { 1952 &sc->sc_kthread, "ipmi") != 0) {
1922 aprint_error("ipmi: unable to create thread, disabled\n"); 1953 aprint_error("ipmi: unable to create thread, disabled\n");
1923 } 1954 }
1924} 1955}
1925 1956
1926static int 1957static int
1927ipmi_detach(device_t self, int flags) 1958ipmi_detach(device_t self, int flags)
1928{ 1959{
1929 struct ipmi_sensor *i; 1960 struct ipmi_sensor *i;
1930 int rc; 1961 int rc;
1931 struct ipmi_softc *sc = device_private(self); 1962 struct ipmi_softc *sc = device_private(self);
1932 1963
1933 sc->sc_thread_running = 0; 1964 mutex_enter(&sc->sc_poll_mtx);
1934 wakeup(&sc->sc_thread_running); 1965 sc->sc_thread_running = false;
 1966 cv_signal(&sc->sc_poll_cv);
 1967 mutex_exit(&sc->sc_poll_mtx);
1935 1968
1936 if ((rc = sysmon_wdog_unregister(&sc->sc_wdog)) != 0) { 1969 if ((rc = sysmon_wdog_unregister(&sc->sc_wdog)) != 0) {
1937 if (rc == ERESTART) 1970 if (rc == ERESTART)
1938 rc = EINTR; 1971 rc = EINTR;
1939 return rc; 1972 return rc;
1940 } 1973 }
1941 1974
1942 /* cancel any pending countdown */ 1975 /* cancel any pending countdown */
1943 sc->sc_wdog.smw_mode &= ~WDOG_MODE_MASK; 1976 sc->sc_wdog.smw_mode &= ~WDOG_MODE_MASK;
1944 sc->sc_wdog.smw_mode |= WDOG_MODE_DISARMED; 1977 sc->sc_wdog.smw_mode |= WDOG_MODE_DISARMED;
1945 sc->sc_wdog.smw_period = WDOG_PERIOD_DEFAULT; 1978 sc->sc_wdog.smw_period = WDOG_PERIOD_DEFAULT;
1946 1979
1947 if ((rc = ipmi_watchdog_setmode(&sc->sc_wdog)) != 0) 1980 if ((rc = ipmi_watchdog_setmode(&sc->sc_wdog)) != 0)
@@ -1957,86 +1990,97 @@ ipmi_detach(device_t self, int flags) @@ -1957,86 +1990,97 @@ ipmi_detach(device_t self, int flags)
1957 1990
1958 while ((i = SLIST_FIRST(&ipmi_sensor_list)) != NULL) { 1991 while ((i = SLIST_FIRST(&ipmi_sensor_list)) != NULL) {
1959 SLIST_REMOVE_HEAD(&ipmi_sensor_list, i_list); 1992 SLIST_REMOVE_HEAD(&ipmi_sensor_list, i_list);
1960 free(i, M_DEVBUF); 1993 free(i, M_DEVBUF);
1961 } 1994 }
1962 1995
1963 if (sc->sc_sensor != NULL) { 1996 if (sc->sc_sensor != NULL) {
1964 free(sc->sc_sensor, M_DEVBUF); 1997 free(sc->sc_sensor, M_DEVBUF);
1965 sc->sc_sensor = NULL; 1998 sc->sc_sensor = NULL;
1966 } 1999 }
1967 2000
1968 ipmi_unmap_regs(sc); 2001 ipmi_unmap_regs(sc);
1969 2002
1970 callout_destroy(&sc->sc_callout); 2003 cv_destroy(&sc->sc_poll_cv);
1971 mutex_destroy(&sc->sc_lock); 2004 mutex_destroy(&sc->sc_poll_mtx);
 2005 cv_destroy(&sc->sc_cmd_sleep);
 2006 mutex_destroy(&sc->sc_cmd_mtx);
1972 2007
1973 return 0; 2008 return 0;
1974} 2009}
1975 2010
1976int 2011int
1977ipmi_watchdog_setmode(struct sysmon_wdog *smwdog) 2012ipmi_watchdog_setmode(struct sysmon_wdog *smwdog)
1978{ 2013{
1979 struct ipmi_softc *sc = smwdog->smw_cookie; 2014 struct ipmi_softc *sc = smwdog->smw_cookie;
1980 struct ipmi_get_watchdog gwdog; 2015 struct ipmi_get_watchdog gwdog;
1981 struct ipmi_set_watchdog swdog; 2016 struct ipmi_set_watchdog swdog;
1982 int s, rc, len; 2017 int rc, len;
1983 2018
1984 if (smwdog->smw_period < 10) 2019 if (smwdog->smw_period < 10)
1985 return EINVAL; 2020 return EINVAL;
1986 if (smwdog->smw_period == WDOG_PERIOD_DEFAULT) 2021 if (smwdog->smw_period == WDOG_PERIOD_DEFAULT)
1987 sc->sc_wdog.smw_period = 10; 2022 sc->sc_wdog.smw_period = 10;
1988 else 2023 else
1989 sc->sc_wdog.smw_period = smwdog->smw_period; 2024 sc->sc_wdog.smw_period = smwdog->smw_period;
1990 2025
1991 s = splsoftclock(); 2026 mutex_enter(&sc->sc_cmd_mtx);
1992 /* see if we can properly task to the watchdog */ 2027 /* see if we can properly task to the watchdog */
1993 rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN, 2028 rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN,
1994 APP_GET_WATCHDOG_TIMER, 0, NULL); 2029 APP_GET_WATCHDOG_TIMER, 0, NULL);
1995 rc = ipmi_recvcmd(sc, sizeof(gwdog), &len, &gwdog); 2030 rc = ipmi_recvcmd(sc, sizeof(gwdog), &len, &gwdog);
 2031 mutex_exit(&sc->sc_cmd_mtx);
1996 if (rc) { 2032 if (rc) {
1997 printf("ipmi: APP_GET_WATCHDOG_TIMER returned 0x%x\n", rc); 2033 printf("ipmi: APP_GET_WATCHDOG_TIMER returned 0x%x\n", rc);
1998 splx(s); 
1999 return EIO; 2034 return EIO;
2000 } 2035 }
2001 2036
2002 memset(&swdog, 0, sizeof(swdog)); 2037 memset(&swdog, 0, sizeof(swdog));
2003 /* Period is 10ths/sec */ 2038 /* Period is 10ths/sec */
2004 swdog.wdog_timeout = htole32(sc->sc_wdog.smw_period * 10); 2039 swdog.wdog_timeout = htole16(sc->sc_wdog.smw_period * 10);
2005 swdog.wdog_action = 0; 2040 if ((smwdog->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED)
2006 if ((smwdog->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { 2041 swdog.wdog_action = IPMI_WDOG_ACT_DISABLED;
2007 swdog.wdog_action |= IPMI_WDOG_ACT_DISABLED; 2042 else
2008 } else { 2043 swdog.wdog_action = IPMI_WDOG_ACT_RESET;
2009 swdog.wdog_action |= IPMI_WDOG_ACT_RESET; 
2010 } 
2011 swdog.wdog_use = IPMI_WDOG_USE_USE_OS; 2044 swdog.wdog_use = IPMI_WDOG_USE_USE_OS;
2012 2045
2013 rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN, 2046 mutex_enter(&sc->sc_cmd_mtx);
2014 APP_SET_WATCHDOG_TIMER, sizeof(swdog), &swdog); 2047 if ((rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN,
2015 rc = ipmi_recvcmd(sc, 0, &len, NULL); 2048 APP_SET_WATCHDOG_TIMER, sizeof(swdog), &swdog)) == 0)
2016 splx(s); 2049 rc = ipmi_recvcmd(sc, 0, &len, NULL);
 2050 mutex_exit(&sc->sc_cmd_mtx);
2017 if (rc) { 2051 if (rc) {
2018 printf("ipmi: APP_SET_WATCHDOG_TIMER returned 0x%x\n", rc); 2052 printf("ipmi: APP_SET_WATCHDOG_TIMER returned 0x%x\n", rc);
2019 return EIO; 2053 return EIO;
2020 } 2054 }
2021 2055
2022 return (0); 2056 return (0);
2023} 2057}
2024 2058
2025int 2059int
2026ipmi_watchdog_tickle(struct sysmon_wdog *smwdog) 2060ipmi_watchdog_tickle(struct sysmon_wdog *smwdog)
2027{ 2061{
2028 struct ipmi_softc *sc = smwdog->smw_cookie; 2062 struct ipmi_softc *sc = smwdog->smw_cookie;
2029 int s, rc, len; 
2030 2063
2031 s = splsoftclock(); 2064 mutex_enter(&sc->sc_poll_mtx);
 2065 sc->sc_tickle_due = true;
 2066 cv_signal(&sc->sc_poll_cv);
 2067 mutex_exit(&sc->sc_poll_mtx);
 2068 return 0;
 2069}
 2070
 2071void
 2072ipmi_dotickle(struct ipmi_softc *sc)
 2073{
 2074 int rc, len;
 2075
 2076 mutex_enter(&sc->sc_cmd_mtx);
2032 /* tickle the watchdog */ 2077 /* tickle the watchdog */
2033 rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN, 2078 if ((rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN,
2034 APP_RESET_WATCHDOG, 0, NULL); 2079 APP_RESET_WATCHDOG, 0, NULL)) == 0)
2035 rc = ipmi_recvcmd(sc, 0, &len, NULL); 2080 rc = ipmi_recvcmd(sc, 0, &len, NULL);
2036 splx(s); 2081 mutex_exit(&sc->sc_cmd_mtx);
2037 if (rc) { 2082 if (rc != 0) {
2038 printf("ipmi: watchdog tickle returned 0x%x\n", rc); 2083 printf("%s: watchdog tickle returned 0x%x\n",
2039 return EIO; 2084 device_xname(sc->sc_dev), rc);
2040 } 2085 }
2041 return (0); 
2042} 2086}