support internal PHY temperature sensor
This commit is contained in:
parent
d9566e9681
commit
b03841d7c9
@ -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
|
||||
|
@ -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.3 2020/01/17 05:16:33 ryo Exp $");
|
||||
#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_softc *, struct aq_txring *);
|
||||
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 *, aq_hw_fw_mpi_state_t,
|
||||
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, void *aux)
|
||||
|
||||
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, void *aux)
|
||||
/* 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 __unused)
|
||||
|
||||
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 __unused)
|
||||
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_fw_mpi_state_t mode,
|
||||
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_hw_stats_s_t *stats)
|
||||
{
|
||||
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_hw_stats_s_t *stats)
|
||||
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, struct aq_txring *txring)
|
||||
}
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user