Module Name:    src
Committed By:   ryo
Date:           Fri Jan 17 05:22:42 UTC 2020

Modified Files:
        src/sys/dev/pci: files.pci if_aq.c

Log Message:
support internal PHY temperature sensor


To generate a diff of this commit:
cvs rdiff -u -r1.420 -r1.421 src/sys/dev/pci/files.pci
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/pci/if_aq.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/files.pci
diff -u src/sys/dev/pci/files.pci:1.420 src/sys/dev/pci/files.pci:1.421
--- src/sys/dev/pci/files.pci:1.420	Thu Jan 16 07:11:50 2020
+++ src/sys/dev/pci/files.pci	Fri Jan 17 05:22:42 2020
@@ -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 @@ attach	mpii at pci
 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

Index: src/sys/dev/pci/if_aq.c
diff -u src/sys/dev/pci/if_aq.c:1.3 src/sys/dev/pci/if_aq.c:1.4
--- src/sys/dev/pci/if_aq.c:1.3	Fri Jan 17 05:16:33 2020
+++ src/sys/dev/pci/if_aq.c	Fri Jan 17 05:22:42 2020
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.
 #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_capabilities {
 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 @@ struct aq_firmware_ops {
 	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 @@ struct aq_firmware_ops {
 #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 @@ struct aq_softc {
 	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 @@ struct aq_softc {
 	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_tx_pcq_free(struct aq_sof
 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_set_mode(struct aq_softc
 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 @@ aq_attach(device_t parent, device_t self
 
 	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 @@ aq_attach(device_t parent, device_t self
 	/* 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 @@ aq_detach(device_t self, int flags __unu
 
 	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_detach(device_t self, int flags __unu
 	AQ_EVCNT_DETACH(sc, cprc);
 #endif
 
+	mutex_destroy(&sc->sc_mpi_mutex);
 	mutex_destroy(&sc->sc_mutex);
 
 	return 0;
@@ -2216,7 +2282,12 @@ static int
 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 @@ fw2x_set_mode(struct aq_softc *sc, aq_hw
 		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 @@ fw2x_get_stats(struct aq_softc *sc, aq_h
 {
 	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 @@ fw2x_get_stats(struct aq_softc *sc, aq_h
 	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;
+		goto failure;
+	}
+	*temp = celsius * (1000000 / 256) + 273150000;
+
+ failure:
+	AQ_MPI_UNLOCK(sc);
 	return 0;
 }
+#endif
 
 static int
 aq_fw_downld_dwords(struct aq_softc *sc, uint32_t addr, uint32_t *p,
@@ -3644,6 +3755,26 @@ aq_tx_pcq_free(struct aq_softc *sc, stru
 	}
 }
 
+#if NSYSMON_ENVSYS > 0
+static void
+aq_temp_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
+{
+	struct aq_softc *sc;
+	uint32_t temp;
+	int error;
+
+	sc = sme->sme_cookie;
+
+	error = sc->sc_fw_ops->get_temperature(sc, &temp);
+	if (error == 0) {
+		edata->value_cur = temp;
+		edata->state = ENVSYS_SVALID;
+	} else {
+		edata->state = ENVSYS_SINVALID;
+	}
+}
+#endif
+
 static void
 aq_tick(void *arg)
 {

Reply via email to