Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/sys Add experimental userland interface to IPMI driver. ...



details:   https://anonhg.NetBSD.org/src/rev/78c8ceb0fc45
branches:  trunk
changeset: 999100:78c8ceb0fc45
user:      mlelstv <mlelstv%NetBSD.org@localhost>
date:      Sat May 18 08:38:00 2019 +0000

description:
Add experimental userland interface to IPMI driver. Currently, transactions
(like sensor readout) are locked, so that a userland program may interfere with
envsys operation.

To use this you need a program like ipmitool built with OpenIPMI support.

diffstat:

 distrib/sets/lists/comp/mi |    3 +-
 etc/MAKEDEV.tmpl           |    8 +-
 sys/conf/majors            |    4 +-
 sys/dev/ipmi.c             |  280 ++++++++++++++++++++++++++++++++++++++++++++-
 sys/dev/ipmivar.h          |   21 +++-
 sys/sys/Makefile           |    4 +-
 sys/sys/ipmi.h             |  105 ++++++++++++++++
 7 files changed, 411 insertions(+), 14 deletions(-)

diffs (truncated from 586 to 300 lines):

diff -r 6c45e776bfb8 -r 78c8ceb0fc45 distrib/sets/lists/comp/mi
--- a/distrib/sets/lists/comp/mi        Sat May 18 08:17:39 2019 +0000
+++ b/distrib/sets/lists/comp/mi        Sat May 18 08:38:00 2019 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: mi,v 1.2273 2019/05/08 14:25:38 isaki Exp $
+#      $NetBSD: mi,v 1.2274 2019/05/18 08:38:00 mlelstv Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 ./etc/mtree/set.comp                           comp-sys-root
@@ -3016,6 +3016,7 @@
 ./usr/include/sys/ioctl_compat.h               comp-c-include
 ./usr/include/sys/iostat.h                     comp-c-include
 ./usr/include/sys/ipc.h                                comp-c-include
+./usr/include/sys/ipmi.h                       comp-c-include
 ./usr/include/sys/joystick.h                   comp-c-include
 ./usr/include/sys/kcore.h                      comp-c-include
 ./usr/include/sys/kcov.h                       comp-c-include
diff -r 6c45e776bfb8 -r 78c8ceb0fc45 etc/MAKEDEV.tmpl
--- a/etc/MAKEDEV.tmpl  Sat May 18 08:17:39 2019 +0000
+++ b/etc/MAKEDEV.tmpl  Sat May 18 08:38:00 2019 +0000
@@ -1,5 +1,5 @@
 #!/bin/sh -
-#      $NetBSD: MAKEDEV.tmpl,v 1.202 2019/04/01 13:08:24 martin Exp $
+#      $NetBSD: MAKEDEV.tmpl,v 1.203 2019/05/18 08:38:00 mlelstv Exp $
 #
 # Copyright (c) 2003,2007,2008 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -242,6 +242,7 @@
 #      iic*    IIC bus device
 #      io      x86 IOPL access for COMPAT_10, COMPAT_FREEBSD
 #      iop*    I2O IOP control interface
+#      ipmi*   OpenIPMI compatible interface
 #      ipl     IP Filter
 #      irframe* IrDA physical frame
 #      ite*    terminal emulator interface to HP300 graphics devices
@@ -2228,6 +2229,11 @@
         mkdev kcov c %kcov_chr% 0
         ;;
 
+ipmi[0-9]*)
+       unit=${i#ipmi}
+       mkdev ipmi${unit} c %ipmi_chr% $unit 600
+       ;;
+
 midevend)
 %MI_DEVICES_END%
 local)
diff -r 6c45e776bfb8 -r 78c8ceb0fc45 sys/conf/majors
--- a/sys/conf/majors   Sat May 18 08:17:39 2019 +0000
+++ b/sys/conf/majors   Sat May 18 08:38:00 2019 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: majors,v 1.86 2019/05/05 17:24:00 mlelstv Exp $
+# $NetBSD: majors,v 1.87 2019/05/18 08:38:00 mlelstv Exp $
 #
 # Device majors for Machine-Independent drivers.
 #
@@ -85,4 +85,4 @@
 # Major 351 is reserved for sys/modules/examples
 # Major 352 is reserved for external/cddl/osnet/dev/fbt/fbt.c
 # Major 353 is reserved for external/cddl/osnet/dev/sdt/sdt.c
-# Major 354 is reserved for IPMI userland driver
+device-major ipmi      char 354                   ipmi
diff -r 6c45e776bfb8 -r 78c8ceb0fc45 sys/dev/ipmi.c
--- a/sys/dev/ipmi.c    Sat May 18 08:17:39 2019 +0000
+++ b/sys/dev/ipmi.c    Sat May 18 08:38:00 2019 +0000
@@ -1,6 +1,30 @@
-/*     $NetBSD: ipmi.c,v 1.3 2018/12/28 12:44:15 mlelstv Exp $ */
+/*     $NetBSD: ipmi.c,v 1.4 2019/05/18 08:38:00 mlelstv Exp $ */
 
 /*
+ * Copyright (c) 2019 Michael van Elst
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
  * Copyright (c) 2006 Manuel Bouyer.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -52,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipmi.c,v 1.3 2018/12/28 12:44:15 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipmi.c,v 1.4 2019/05/18 08:38:00 mlelstv Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -66,14 +90,42 @@
 #include <sys/kthread.h>
 #include <sys/bus.h>
 #include <sys/intr.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/conf.h>
 
 #include <dev/isa/isareg.h>
 #include <dev/isa/isavar.h>
 
+#include <sys/ipmi.h>
 #include <dev/ipmivar.h>
 
 #include <uvm/uvm_extern.h>
 
+#include "ioconf.h"
+
+static dev_type_open(ipmi_open);
+static dev_type_close(ipmi_close);
+static dev_type_ioctl(ipmi_ioctl);
+static dev_type_poll(ipmi_poll);
+
+const struct cdevsw ipmi_cdevsw = {
+       .d_open = ipmi_open,
+       .d_close = ipmi_close,
+       .d_read = noread,
+       .d_write = nowrite,
+       .d_ioctl = ipmi_ioctl,
+       .d_stop = nostop,
+       .d_tty = notty,
+       .d_poll = ipmi_poll,
+       .d_mmap = nommap,
+       .d_kqfilter = nokqfilter,
+       .d_discard = nodiscard,
+       .d_flag = D_OTHER
+};
+
+#define IPMIUNIT(n) (minor(n))
+
 struct ipmi_sensor {
        uint8_t *i_sdr;
        int             i_num;
@@ -344,6 +396,8 @@
 }
 
 #define NETFN_LUN(nf,ln) (((nf) << 2) | ((ln) & 0x3))
+#define GET_NETFN(m) (((m) >> 2)
+#define GET_LUN(m) ((m) & 0x03)
 
 /*
  * BT interface
@@ -1014,7 +1068,7 @@
                return -1;
        }
 
-       *rxlen = rawlen - IPMI_MSG_DATARCV;
+       *rxlen = rawlen >= IPMI_MSG_DATARCV ? rawlen - IPMI_MSG_DATARCV : 0;
        if (*rxlen > 0 && data)
                memcpy(data, buf + IPMI_MSG_DATARCV, *rxlen);
 
@@ -2037,13 +2091,20 @@
 
        mutex_enter(&sc->sc_poll_mtx);
        while (sc->sc_thread_running) {
-               ipmi_refresh_sensors(sc);
-               cv_timedwait(&sc->sc_poll_cv, &sc->sc_poll_mtx,
-                   SENSOR_REFRESH_RATE);
+               while (sc->sc_mode == IPMI_MODE_COMMAND)
+                       cv_wait(&sc->sc_mode_cv, &sc->sc_poll_mtx);
+               sc->sc_mode = IPMI_MODE_ENVSYS;
+
                if (sc->sc_tickle_due) {
                        ipmi_dotickle(sc);
                        sc->sc_tickle_due = false;
                }
+               ipmi_refresh_sensors(sc);
+
+               sc->sc_mode = IPMI_MODE_IDLE;
+               cv_broadcast(&sc->sc_mode_cv);
+               cv_timedwait(&sc->sc_poll_cv, &sc->sc_poll_mtx,
+                   SENSOR_REFRESH_RATE);
        }
        mutex_exit(&sc->sc_poll_mtx);
        self->dv_flags &= ~DVF_ATTACH_INPROGRESS;
@@ -2067,6 +2128,7 @@
 
        mutex_init(&sc->sc_poll_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK);
        cv_init(&sc->sc_poll_cv, "ipmipoll");
+       cv_init(&sc->sc_mode_cv, "ipmimode");
 
        if (kthread_create(PRI_NONE, 0, NULL, ipmi_thread, self,
            &sc->sc_kthread, "%s", device_xname(self)) != 0) {
@@ -2121,6 +2183,7 @@
 
        ipmi_unmap_regs(sc);
 
+       cv_destroy(&sc->sc_mode_cv);
        cv_destroy(&sc->sc_poll_cv);
        mutex_destroy(&sc->sc_poll_mtx);
        cv_destroy(&sc->sc_cmd_sleep);
@@ -2247,3 +2310,208 @@
                return false;
        return true;
 }
+
+static int
+ipmi_open(dev_t dev, int flag, int fmt, lwp_t *l)
+{
+       return 0;
+}
+
+static int
+ipmi_close(dev_t dev, int flag, int fmt, lwp_t *l)
+{
+       struct ipmi_softc *sc;
+       int unit;
+
+       unit = IPMIUNIT(dev);
+       if ((sc = device_lookup_private(&ipmi_cd, unit)) == NULL)
+               return (ENXIO);
+
+       mutex_enter(&sc->sc_poll_mtx);
+       if (sc->sc_mode == IPMI_MODE_COMMAND) {
+               sc->sc_mode = IPMI_MODE_IDLE;
+               cv_broadcast(&sc->sc_mode_cv);
+       }
+       mutex_exit(&sc->sc_poll_mtx);
+       return 0;
+}
+
+static int
+ipmi_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
+{
+       struct ipmi_softc *sc;
+       int unit, error = 0, len;
+       struct ipmi_req *req;
+       struct ipmi_recv *recv;
+       struct ipmi_addr addr;
+       unsigned char ccode, *buf = NULL;
+
+       unit = IPMIUNIT(dev);
+       if ((sc = device_lookup_private(&ipmi_cd, unit)) == NULL)
+               return (ENXIO);
+
+       switch (cmd) {
+       case IPMICTL_SEND_COMMAND:
+               mutex_enter(&sc->sc_poll_mtx);
+               while (sc->sc_mode == IPMI_MODE_ENVSYS) {
+                       error = cv_wait_sig(&sc->sc_mode_cv, &sc->sc_poll_mtx);
+                       if (error == EINTR) {
+                               mutex_exit(&sc->sc_poll_mtx);
+                               return error;
+                       }
+               }
+               sc->sc_mode = IPMI_MODE_COMMAND;
+               mutex_exit(&sc->sc_poll_mtx);
+               break;
+       }
+
+       mutex_enter(&sc->sc_cmd_mtx);
+
+       switch (cmd) {
+       case IPMICTL_SEND_COMMAND:
+               req = data;
+               buf = malloc(IPMI_MAX_RX, M_DEVBUF, M_WAITOK);
+
+               len = req->msg.data_len;
+               if (len < 0 || len > IPMI_MAX_RX) {
+                       error = EINVAL;
+                       break;
+               }
+
+               /* clear pending result */
+               if (sc->sc_sent)
+                       (void)ipmi_recvcmd(sc, IPMI_MAX_RX, &len, buf);
+
+               /* XXX */
+               error = copyin(req->addr, &addr, sizeof(addr));
+               if (error)
+                       break;
+
+               error = copyin(req->msg.data, buf, len);
+               if (error)
+                       break;
+
+               /* save for receive */
+               sc->sc_msgid = req->msgid;
+               sc->sc_netfn = req->msg.netfn;
+               sc->sc_cmd = req->msg.cmd;
+
+               if (ipmi_sendcmd(sc, BMC_SA, 0, req->msg.netfn,
+                   req->msg.cmd, len, buf)) {
+                       error = EIO;



Home | Main Index | Thread Index | Old Index