Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci support internal PHY temperature sensor



details:   https://anonhg.NetBSD.org/src/rev/36cc60ccab3f
branches:  trunk
changeset: 467189:36cc60ccab3f
user:      ryo <ryo%NetBSD.org@localhost>
date:      Fri Jan 17 05:22:42 2020 +0000

description:
support internal PHY temperature sensor

diffstat:

 sys/dev/pci/files.pci |    4 +-
 sys/dev/pci/if_aq.c   |  161 +++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 148 insertions(+), 17 deletions(-)

diffs (truncated from 339 to 300 lines):

diff -r f26fb46a811d -r 36cc60ccab3f sys/dev/pci/files.pci
--- a/sys/dev/pci/files.pci     Fri Jan 17 05:20:21 2020 +0000
+++ b/sys/dev/pci/files.pci     Fri Jan 17 05:22:42 2020 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.pci,v 1.420 2020/01/16 07:11:50 yamaguchi Exp $
+#      $NetBSD: files.pci,v 1.421 2020/01/17 05:22:42 ryo Exp $
 #
 # Config file and device description for machine-independent PCI code.
 # Included by ports that need it.  Requires that the SCSI files be
@@ -168,7 +168,7 @@
 file   dev/pci/mpii.c                  mpii
 
 # Aquantia/Atlantic 10-Gigabit Ethernet
-device aq: ether, ifnet, arp
+device aq: ether, ifnet, arp, sysmon_envsys
 attach aq at pci
 file   dev/pci/if_aq.c                 aq
 defflag opt_if_aq.h    AQ_EVENT_COUNTERS
diff -r f26fb46a811d -r 36cc60ccab3f sys/dev/pci/if_aq.c
--- a/sys/dev/pci/if_aq.c       Fri Jan 17 05:20:21 2020 +0000
+++ b/sys/dev/pci/if_aq.c       Fri Jan 17 05:22:42 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_aq.c,v 1.3 2020/01/17 05:16:33 ryo Exp $    */
+/*     $NetBSD: if_aq.c,v 1.4 2020/01/17 05:22:42 ryo Exp $    */
 
 /**
  * aQuantia Corporation Network Driver
@@ -62,10 +62,11 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.3 2020/01/17 05:16:33 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.4 2020/01/17 05:22:42 ryo Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_if_aq.h"
+#include "sysmon_envsys.h"
 #endif
 
 #include <sys/param.h>
@@ -87,6 +88,7 @@
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcidevs.h>
+#include <dev/sysmon/sysmonvar.h>
 
 /* driver configuration */
 #define CONFIG_INTR_MODERATION_ENABLE  true    /* delayed interrupt */
@@ -710,11 +712,14 @@
 typedef struct fw2x_mailbox {          /* struct fwHostInterface */
        aq_mailbox_header_t header;
        fw2x_msm_statistics_t msm;      /* msmStatistics_t msm; */
-       uint16_t phy_h_bit;
-       uint16_t phy_fault_code;
-       int16_t phy_temperature;
-       uint8_t cable_len;
-       uint8_t reserved1;
+
+       uint32_t phy_info1;
+#define PHYINFO1_FAULT_CODE    __BITS(31,16)
+#define PHYINFO1_PHY_H_BIT     __BITS(0,15)
+       uint32_t phy_info2;
+#define PHYINFO2_TEMPERATURE   __BITS(15,0)
+#define PHYINFO2_CABLE_LEN     __BITS(23,16)
+
        fw2x_phy_cable_diag_data_t diag_data;
        uint32_t reserved[8];
 
@@ -907,6 +912,9 @@
        int (*get_mode)(struct aq_softc *, aq_hw_fw_mpi_state_t *,
            aq_link_speed_t *, aq_link_fc_t *, aq_link_eee_t *);
        int (*get_stats)(struct aq_softc *, aq_hw_stats_s_t *);
+#if NSYSMON_ENVSYS > 0
+       int (*get_temperature)(struct aq_softc *, uint32_t *);
+#endif
 };
 
 #ifdef AQ_EVENT_COUNTERS
@@ -933,6 +941,11 @@
 #define AQ_LOCK(sc)            mutex_enter(&(sc)->sc_mutex);
 #define AQ_UNLOCK(sc)          mutex_exit(&(sc)->sc_mutex);
 
+/* lock for FW2X_MPI_{CONTROL,STATE]_REG read-modify-write */
+#define AQ_MPI_LOCK(sc)                mutex_enter(&(sc)->sc_mpi_mutex);
+#define AQ_MPI_UNLOCK(sc)      mutex_exit(&(sc)->sc_mpi_mutex);
+
+
 struct aq_softc {
        device_t sc_dev;
 
@@ -951,6 +964,11 @@
        bool sc_poll_linkstat;
        bool sc_detect_linkstat;
 
+#if NSYSMON_ENVSYS > 0
+       struct sysmon_envsys *sc_sme;
+       envsys_data_t sc_sensor_temp;
+#endif
+
        callout_t sc_tick_ch;
 
        int sc_nintrs;
@@ -965,6 +983,7 @@
        uint16_t sc_revision;
 
        kmutex_t sc_mutex;
+       kmutex_t sc_mpi_mutex;
 
        struct aq_firmware_ops *sc_fw_ops;
        uint64_t sc_fw_caps;
@@ -1063,6 +1082,9 @@
 static void aq_initmedia(struct aq_softc *);
 static void aq_enable_intr(struct aq_softc *, bool, bool);
 
+#if NSYSMON_ENVSYS > 0
+static void aq_temp_refresh(struct sysmon_envsys *, envsys_data_t *);
+#endif
 static void aq_tick(void *);
 static int aq_legacy_intr(void *);
 static int aq_link_intr(void *);
@@ -1099,19 +1121,28 @@
 static int fw2x_get_mode(struct aq_softc *, aq_hw_fw_mpi_state_t *,
     aq_link_speed_t *, aq_link_fc_t *, aq_link_eee_t *);
 static int fw2x_get_stats(struct aq_softc *, aq_hw_stats_s_t *);
+#if NSYSMON_ENVSYS > 0
+static int fw2x_get_temperature(struct aq_softc *, uint32_t *);
+#endif
 
 static struct aq_firmware_ops aq_fw1x_ops = {
        .reset = fw1x_reset,
        .set_mode = fw1x_set_mode,
        .get_mode = fw1x_get_mode,
-       .get_stats = fw1x_get_stats
+       .get_stats = fw1x_get_stats,
+#if NSYSMON_ENVSYS > 0
+       .get_temperature = NULL
+#endif
 };
 
 static struct aq_firmware_ops aq_fw2x_ops = {
        .reset = fw2x_reset,
        .set_mode = fw2x_set_mode,
        .get_mode = fw2x_get_mode,
-       .get_stats = fw2x_get_stats
+       .get_stats = fw2x_get_stats,
+#if NSYSMON_ENVSYS > 0
+       .get_temperature = fw2x_get_temperature
+#endif
 };
 
 CFATTACH_DECL3_NEW(aq, sizeof(struct aq_softc),
@@ -1216,6 +1247,7 @@
 
        sc->sc_dev = self;
        mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NET);
+       mutex_init(&sc->sc_mpi_mutex, MUTEX_DEFAULT, IPL_NET);
 
        sc->sc_pc = pc = pa->pa_pc;
        sc->sc_pcitag = tag = pa->pa_tag;
@@ -1433,6 +1465,31 @@
        /* update media */
        aq_ifmedia_change(ifp);
 
+#if NSYSMON_ENVSYS > 0
+       /* temperature monitoring */
+       if (sc->sc_fw_ops != NULL && sc->sc_fw_ops->get_temperature != NULL &&
+           (sc->sc_fw_caps & FW2X_CTRL_TEMPERATURE) != 0) {
+
+               sc->sc_sme = sysmon_envsys_create();
+               sc->sc_sme->sme_name = device_xname(self);
+               sc->sc_sme->sme_cookie = sc;
+               sc->sc_sme->sme_flags = 0;
+               sc->sc_sme->sme_refresh = aq_temp_refresh;
+               sc->sc_sensor_temp.units = ENVSYS_STEMP;
+               sc->sc_sensor_temp.state = ENVSYS_SINVALID;
+               snprintf(sc->sc_sensor_temp.desc, ENVSYS_DESCLEN, "PHY");
+
+               sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor_temp);
+               sysmon_envsys_register(sc->sc_sme);
+
+               /*
+                * for unknown reasons, the first call of fw2x_get_temperature()
+                * will always fail (firmware matter?), so run once now.
+                */
+               aq_temp_refresh(sc->sc_sme, &sc->sc_sensor_temp);
+       }
+#endif
+
 #ifdef AQ_EVENT_COUNTERS
        /* get starting statistics values */
        if (sc->sc_fw_ops != NULL && sc->sc_fw_ops->get_stats != NULL &&
@@ -1507,6 +1564,14 @@
 
        callout_stop(&sc->sc_tick_ch);
 
+#if NSYSMON_ENVSYS > 0
+       if (sc->sc_sme != NULL) {
+               /* all sensors associated with this will also be detached */
+               sysmon_envsys_unregister(sc->sc_sme);
+               sc->sc_sme = NULL;
+       }
+#endif
+
 #ifdef AQ_EVENT_COUNTERS
        AQ_EVCNT_DETACH(sc, uprc);
        AQ_EVCNT_DETACH(sc, mprc);
@@ -1528,6 +1593,7 @@
        AQ_EVCNT_DETACH(sc, cprc);
 #endif
 
+       mutex_destroy(&sc->sc_mpi_mutex);
        mutex_destroy(&sc->sc_mutex);
 
        return 0;
@@ -2216,7 +2282,12 @@
 fw2x_set_mode(struct aq_softc *sc, aq_hw_fw_mpi_state_t mode,
     aq_link_speed_t speed, aq_link_fc_t fc, aq_link_eee_t eee)
 {
-       uint64_t mpi_ctrl = AQ_READ64_REG(sc, FW2X_MPI_CONTROL_REG);
+       uint64_t mpi_ctrl;
+       int error = 0;
+
+       AQ_MPI_LOCK(sc);
+
+       mpi_ctrl = AQ_READ64_REG(sc, FW2X_MPI_CONTROL_REG);
 
        switch (mode) {
        case MPI_INIT:
@@ -2250,11 +2321,14 @@
                break;
        default:
                device_printf(sc->sc_dev, "fw2x> unknown MPI state %d\n", mode);
-               return EINVAL;
+               error =  EINVAL;
+               goto failure;
        }
-
        AQ_WRITE64_REG(sc, FW2X_MPI_CONTROL_REG, mpi_ctrl);
-       return 0;
+
+ failure:
+       AQ_MPI_UNLOCK(sc);
+       return error;
 }
 
 static int
@@ -2344,12 +2418,13 @@
 {
        int error;
 
+       AQ_MPI_LOCK(sc);
        /* Say to F/W to update the statistics */
        error = toggle_mpi_ctrl_and_wait(sc, FW2X_CTRL_STATISTICS, 1, 25);
        if (error != 0) {
                device_printf(sc->sc_dev,
                    "fw2x> statistics update error %d\n", error);
-               return error;
+               goto failure;
        }
 
        CTASSERT(sizeof(fw2x_msm_statistics_t) <= sizeof(struct aq_hw_stats_s));
@@ -2359,13 +2434,49 @@
        if (error != 0) {
                device_printf(sc->sc_dev,
                    "fw2x> download statistics data FAILED, error %d", error);
-               return error;
+               goto failure;
        }
        stats->dpc = AQ_READ_REG(sc, RX_DMA_DROP_PKT_CNT_REG);
        stats->cprc = AQ_READ_REG(sc, RX_DMA_COALESCED_PKT_CNT_REG);
 
+ failure:
+       AQ_MPI_UNLOCK(sc);
+       return error;
+}
+
+#if NSYSMON_ENVSYS > 0
+static int
+fw2x_get_temperature(struct aq_softc *sc, uint32_t *temp)
+{
+       int error;
+       uint32_t value, celsius;
+
+       AQ_MPI_LOCK(sc);
+
+       /* Say to F/W to update the temperature */
+       error = toggle_mpi_ctrl_and_wait(sc, FW2X_CTRL_TEMPERATURE, 1, 25);
+       if (error != 0)
+               goto failure;
+
+       error = aq_fw_downld_dwords(sc,
+           sc->sc_mbox_addr + offsetof(fw2x_mailbox_t, phy_info2),
+           &value, sizeof(value) / sizeof(uint32_t));
+       if (error != 0)
+               goto failure;
+
+       /* 1/256 decrees C to microkelvin */
+       celsius = __SHIFTOUT(value, PHYINFO2_TEMPERATURE);
+       if (celsius == 0) {
+               error = EIO;



Home | Main Index | Thread Index | Old Index