Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/x86 sc_cmd_mtx protects a command sequence, no long...
details: https://anonhg.NetBSD.org/src/rev/e91dc5a3c54a
branches: trunk
changeset: 756781:e91dc5a3c54a
user: mlelstv <mlelstv%NetBSD.org@localhost>
date: Sun Aug 01 08:16:14 2010 +0000
description:
sc_cmd_mtx protects a command sequence, no longer abuse it for delays.
Initialize mutexes and condition variables in attach and not in the
asynchronously started kernel thread.
Increase BMC spin timeout from 5ms to 15ms, this is necessary to detect
the BMC in a HP ML110G4 reliably.
Implement non-linear sensors as defined in IPMIv2.0 with some crude
32.32 fixed point arithmetic. This adds some small errors as logarithm
and power functions are only approximated.
Fix sensor index mapping so that sensor limits are computed correctly.
diffstat:
sys/arch/x86/include/ipmivar.h | 4 +-
sys/arch/x86/x86/ipmi.c | 248 ++++++++++++++++++++++++++++++++--------
2 files changed, 200 insertions(+), 52 deletions(-)
diffs (truncated from 416 to 300 lines):
diff -r 6704ef393bc2 -r e91dc5a3c54a sys/arch/x86/include/ipmivar.h
--- a/sys/arch/x86/include/ipmivar.h Sun Aug 01 07:38:17 2010 +0000
+++ b/sys/arch/x86/include/ipmivar.h Sun Aug 01 08:16:14 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ipmivar.h,v 1.10 2009/07/20 19:11:30 dyoung Exp $ */
+/* $NetBSD: ipmivar.h,v 1.11 2010/08/01 08:16:14 mlelstv Exp $ */
/*
* Copyright (c) 2005 Jordan Hargrave
@@ -92,6 +92,7 @@
kcondvar_t sc_poll_cv;
kmutex_t sc_cmd_mtx;
+ kmutex_t sc_sleep_mtx;
kcondvar_t sc_cmd_sleep;
struct ipmi_bmc_args *sc_iowait_args;
@@ -103,7 +104,6 @@
struct sysmon_envsys *sc_envsys;
envsys_data_t *sc_sensor;
int sc_nsensors; /* total number of sensors */
- int sc_nsensors_typ[ENVSYS_NSENSORS]; /* number per type */
char sc_buf[64];
bool sc_buf_rsvd;
diff -r 6704ef393bc2 -r e91dc5a3c54a sys/arch/x86/x86/ipmi.c
--- a/sys/arch/x86/x86/ipmi.c Sun Aug 01 07:38:17 2010 +0000
+++ b/sys/arch/x86/x86/ipmi.c Sun Aug 01 08:16:14 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ipmi.c,v 1.47 2010/07/17 21:34:39 pgoyette Exp $ */
+/* $NetBSD: ipmi.c,v 1.48 2010/08/01 08:16:14 mlelstv Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -52,7 +52,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipmi.c,v 1.47 2010/07/17 21:34:39 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipmi.c,v 1.48 2010/08/01 08:16:14 mlelstv Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -188,7 +188,6 @@
void ipmi_attach(device_t, device_t, void *);
static int ipmi_detach(device_t, int);
-long ipow(long, int);
long ipmi_convert(uint8_t, struct sdrtype1 *, long);
void ipmi_sensor_name(char *, int, uint8_t, uint8_t *);
@@ -304,7 +303,9 @@
v = bmc_read(sc, offset);
if ((v & mask) == value)
return v;
- cv_timedwait(&sc->sc_cmd_sleep, &sc->sc_cmd_mtx, 1);
+ mutex_enter(&sc->sc_sleep_mtx);
+ cv_timedwait(&sc->sc_cmd_sleep, &sc->sc_sleep_mtx, 1);
+ mutex_exit(&sc->sc_sleep_mtx);
}
return -1;
}
@@ -327,7 +328,7 @@
uint8_t value)
{
uint8_t v;
- int count = cold ? 5000 : 500;
+ int count = cold ? 15000 : 500;
/* ~us */
while (count--) {
@@ -1113,8 +1114,11 @@
{
if (cold)
delay(ms * 1000);
- else
- cv_timedwait(&sc->sc_cmd_sleep, &sc->sc_cmd_mtx, mstohz(ms));
+ else {
+ mutex_enter(&sc->sc_sleep_mtx);
+ cv_timedwait(&sc->sc_cmd_sleep, &sc->sc_sleep_mtx, mstohz(ms));
+ mutex_exit(&sc->sc_sleep_mtx);
+ }
}
/* Read a partial SDR entry */
@@ -1271,23 +1275,6 @@
*name = 0;
}
-/* Calculate val * 10^exp */
-long
-ipow(long val, int exp)
-{
- while (exp > 0) {
- val *= 10;
- exp--;
- }
-
- while (exp < 0) {
- val /= 10;
- exp++;
- }
-
- return (val);
-}
-
/* Sign extend a n-bit value */
long
signextend(unsigned long val, int bits)
@@ -1297,13 +1284,159 @@
return (-(val & ~msk) | val);
}
+
+/* fixpoint arithmetic */
+#define FIX2INT(x) ((int64_t)((x) >> 32))
+#define INT2FIX(x) ((int64_t)((int64_t)(x) << 32))
+
+#define FIX2 0x0000000200000000ll /* 2.0 */
+#define FIX3 0x0000000300000000ll /* 3.0 */
+#define FIXE 0x00000002b7e15163ll /* 2.71828182845904523536 */
+#define FIX10 0x0000000a00000000ll /* 10.0 */
+#define FIXMONE 0xffffffff00000000ll /* -1.0 */
+#define FIXHALF 0x0000000080000000ll /* 0.5 */
+#define FIXTHIRD 0x0000000055555555ll /* 0.33333333333333333333 */
+
+#define FIX1LOG2 0x0000000171547653ll /* 1.0/log(2) */
+#define FIX1LOGE 0x0000000100000000ll /* 1.0/log(2.71828182845904523536) */
+#define FIX1LOG10 0x000000006F2DEC55ll /* 1.0/log(10) */
+
+#define FIX1E 0x000000005E2D58D9ll /* 1.0/2.71828182845904523536 */
+
+static int64_t fixlog_a[] = {
+ 0x0000000100000000ll /* 1.0/1.0 */,
+ 0xffffffff80000000ll /* -1.0/2.0 */,
+ 0x0000000055555555ll /* 1.0/3.0 */,
+ 0xffffffffc0000000ll /* -1.0/4.0 */,
+ 0x0000000033333333ll /* 1.0/5.0 */,
+ 0x000000002aaaaaabll /* -1.0/6.0 */,
+ 0x0000000024924925ll /* 1.0/7.0 */,
+ 0x0000000020000000ll /* -1.0/8.0 */,
+ 0x000000001c71c71cll /* 1.0/9.0 */
+};
+
+static int64_t fixexp_a[] = {
+ 0x0000000100000000ll /* 1.0/1.0 */,
+ 0x0000000100000000ll /* 1.0/1.0 */,
+ 0x0000000080000000ll /* 1.0/2.0 */,
+ 0x000000002aaaaaabll /* 1.0/6.0 */,
+ 0x000000000aaaaaabll /* 1.0/24.0 */,
+ 0x0000000002222222ll /* 1.0/120.0 */,
+ 0x00000000005b05b0ll /* 1.0/720.0 */,
+ 0x00000000000d00d0ll /* 1.0/5040.0 */,
+ 0x000000000001a01all /* 1.0/40320.0 */
+};
+
+static int64_t
+fixmul(int64_t x, int64_t y)
+{
+ int64_t z;
+ int64_t a,b,c,d;
+ int neg;
+
+ neg = 0;
+ if (x < 0) {
+ x = -x;
+ neg = !neg;
+ }
+ if (y < 0) {
+ y = -y;
+ neg = !neg;
+ }
+
+ a = FIX2INT(x);
+ b = x - INT2FIX(a);
+ c = FIX2INT(y);
+ d = y - INT2FIX(c);
+
+ z = INT2FIX(a*c) + a * d + b * c + (b/2 * d/2 >> 30);
+
+ return neg ? -z : z;
+}
+
+static int64_t
+poly(int64_t x0, int64_t x, int64_t a[], int n)
+{
+ int64_t z;
+ int i;
+
+ z = fixmul(x0, a[0]);
+ for (i=1; i<n; ++i) {
+ x0 = fixmul(x0, x);
+ z = fixmul(x0, a[i]) + z;
+ }
+ return z;
+}
+
+static int64_t
+logx(int64_t x, int64_t y)
+{
+ int64_t z;
+
+ if (x <= INT2FIX(0)) {
+ z = INT2FIX(-99999);
+ goto done;
+ }
+
+ z = INT2FIX(0);
+ while (x >= FIXE) {
+ x = fixmul(x, FIX1E);
+ z += INT2FIX(1);
+ }
+ while (x < INT2FIX(1)) {
+ x = fixmul(x, FIXE);
+ z -= INT2FIX(1);
+ }
+
+ x -= INT2FIX(1);
+ z += poly(x, x, fixlog_a, sizeof(fixlog_a)/sizeof(fixlog_a[0]));
+ z = fixmul(z, y);
+
+done:
+ return z;
+}
+
+static int64_t
+powx(int64_t x, int64_t y)
+{
+ int64_t k;
+
+ if (x == INT2FIX(0))
+ goto done;
+
+ x = logx(x,y);
+
+ if (x < INT2FIX(0)) {
+ x = INT2FIX(0) - x;
+ k = -FIX2INT(x);
+ x = INT2FIX(-k) - x;
+ } else {
+ k = FIX2INT(x);
+ x = x - INT2FIX(k);
+ }
+
+ x = poly(INT2FIX(1), x, fixexp_a, sizeof(fixexp_a)/sizeof(fixexp_a[0]));
+
+ while (k < 0) {
+ x = fixmul(x, FIX1E);
+ ++k;
+ }
+ while (k > 0) {
+ x = fixmul(x, FIXE);
+ --k;
+ }
+
+done:
+ return x;
+}
+
/* Convert IPMI reading from sensor factors */
long
ipmi_convert(uint8_t v, struct sdrtype1 *s1, long adj)
{
- short M, B;
+ int64_t M, B;
char K1, K2;
- long val;
+ int64_t val, v1, v2;
/* Calculate linear reading variables */
M = signextend((((short)(s1->m_tolerance & 0xC0)) << 2) + s1->m, 10);
@@ -1316,13 +1449,30 @@
*
* This commutes out to:
* y = L(M*v * 10^(K2+adj) + B * 10^(K1+K2+adj)); */
- val = ipow(M * v, K2 + adj) + ipow(B, K1 + K2 + adj);
+ v1 = powx(FIX10, INT2FIX(K2 + adj));
+ v2 = powx(FIX10, INT2FIX(K1 + K2 + adj));
+ val = M * v * v1 + B * v2;
/* Linearization function: y = f(x) 0 : y = x 1 : y = ln(x) 2 : y =
* log10(x) 3 : y = log2(x) 4 : y = e^x 5 : y = 10^x 6 : y = 2^x 7 : y
* = 1/x 8 : y = x^2 9 : y = x^3 10 : y = square root(x) 11 : y = cube
* root(x) */
- return (val);
+ switch (s1->linear & 0x7f) {
+ case 0: break;
+ case 1: val = logx(val,FIX1LOGE); break;
+ case 2: val = logx(val,FIX1LOG10); break;
+ case 3: val = logx(val,FIX1LOG2); break;
+ case 4: val = powx(FIXE,val); break;
+ case 5: val = powx(FIX10,val); break;
+ case 6: val = powx(FIX2,val); break;
+ case 7: val = powx(val,FIXMONE); break;
+ case 8: val = powx(val,FIX2); break;
+ case 9: val = powx(val,FIX3); break;
+ case 10: val = powx(val,FIXHALF); break;
+ case 11: val = powx(val,FIXTHIRD); break;
+ }
+
Home |
Main Index |
Thread Index |
Old Index