hddtemp: add patch to support nvme drives

patch: https://bugzilla.redhat.com/show_bug.cgi?id=1801116
This commit is contained in:
heitbaum 2021-01-09 10:17:18 +00:00
parent 865f29181c
commit 0f6038529a
2 changed files with 411 additions and 1 deletions

View File

@ -2,7 +2,7 @@
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="hddtemp"
PKG_VERSION="e16aed6d0145d7ad8b3308dd0b9199fc701c0417"
PKG_VERSION="e16aed6d0145d7ad8b3308dd0b9199fc701c0417" # Jul 6, 2010
PKG_SHA256="5d5af74ba7449b6e56a8f872a0e10d654a512ed65d62beaef1575b0c1826d9f3"
PKG_LICENSE="GPL"
PKG_SITE="https://savannah.nongnu.org/projects/hddtemp"

View File

@ -0,0 +1,410 @@
https://bugzilla.redhat.com/show_bug.cgi?id=1801116
Description Constantine Gavrilov 2020-02-10 10:09:18 UTC
Created attachment 1662111 [details]
Patch that adds NVMe Drives Support
Description of problem: HDDTEMP cannot read temperature of MVME drives.
All versions are affected.
How reproducible: always (missing support)
Steps to Reproduce:
1. Try to read temperature of NVME drive
Actual results:
1. Error is reported (only SATA or SCSI drives supported).
Expected results:
1. A temperature report would be appreciated, many GUI sensor frontends depend on HDDTEMP.
Additional info:
I have crated a patch that adds NVME drives support to HDDTEMP.
diff -uNr hddtemp-0.3-beta15.old/src/hddtemp.c hddtemp-0.3-beta15/src/hddtemp.c
--- hddtemp-0.3-beta15.old/src/hddtemp.c 2020-02-03 14:23:19.781566750 +0200
+++ hddtemp-0.3-beta15/src/hddtemp.c 2020-02-03 14:31:03.526209746 +0200
@@ -61,6 +61,7 @@
#include "utf8.h"
#include "sata.h"
#include "scsi.h"
+#include "nvme.h"
#include "db.h"
#include "hddtemp.h"
#include "backtrace.h"
@@ -87,6 +88,7 @@
bus[BUS_SATA] = &sata_bus;
bus[BUS_ATA] = &ata_bus;
bus[BUS_SCSI] = &scsi_bus;
+ bus[BUS_NVME] = &nvme_bus;
}
/*******************************************************
@@ -130,6 +132,8 @@
return BUS_ATA;
else if(bus[BUS_SCSI]->probe(dsk->fd))
return BUS_SCSI;
+ else if (bus[BUS_NVME]->probe(dsk->fd))
+ return BUS_NVME;
else
return BUS_UNKNOWN;
}
diff -uNr hddtemp-0.3-beta15.old/src/hddtemp.h hddtemp-0.3-beta15/src/hddtemp.h
--- hddtemp-0.3-beta15.old/src/hddtemp.h 2020-02-03 14:23:19.781566750 +0200
+++ hddtemp-0.3-beta15/src/hddtemp.h 2020-02-03 08:50:34.755411875 +0200
@@ -35,7 +35,7 @@
#define F_to_C(val) (int)(((double)(val)-32.0)/1.8)
#define C_to_F(val) (int)(((double)(val)*(double)1.8) + (double)32.0)
-enum e_bustype { ERROR = 0, BUS_UNKNOWN, BUS_SATA, BUS_ATA, BUS_SCSI, BUS_TYPE_MAX };
+enum e_bustype { ERROR = 0, BUS_UNKNOWN, BUS_SATA, BUS_ATA, BUS_SCSI, BUS_NVME, BUS_TYPE_MAX };
enum e_gettemp {
GETTEMP_ERROR, /* Error */
GETTEMP_NOT_APPLICABLE, /* */
diff -uNr hddtemp-0.3-beta15.old/src/Makefile.am hddtemp-0.3-beta15/src/Makefile.am
--- hddtemp-0.3-beta15.old/src/Makefile.am 2005-03-15 02:23:13.000000000 +0200
+++ hddtemp-0.3-beta15/src/Makefile.am 2020-02-03 08:50:34.737411657 +0200
@@ -13,7 +13,7 @@
scsi.c scsi.h \
scsicmds.c scsicmds.h \
backtrace.c backtrace.h \
- utf8.c utf8.h
+ utf8.c utf8.h nvme.o
hddtemp_CFLAGS = -Wall -W -rdynamic
#hddtemp_CFLAGS = -Wall -fomit-frame-pointer -rdynamic
diff -uNr hddtemp-0.3-beta15.old/src/Makefile.in hddtemp-0.3-beta15/src/Makefile.in
--- hddtemp-0.3-beta15.old/src/Makefile.in 2005-10-17 21:20:28.000000000 +0200
+++ hddtemp-0.3-beta15/src/Makefile.in 2020-02-03 08:50:34.790412300 +0200
@@ -157,7 +157,7 @@
scsi.c scsi.h \
scsicmds.c scsicmds.h \
backtrace.c backtrace.h \
- utf8.c utf8.h
+ utf8.c utf8.h nvme.c
hddtemp_CFLAGS = -Wall -W -rdynamic
@@ -180,7 +180,7 @@
hddtemp-hddtemp.$(OBJEXT) hddtemp-sata.$(OBJEXT) \
hddtemp-satacmds.$(OBJEXT) hddtemp-scsi.$(OBJEXT) \
hddtemp-scsicmds.$(OBJEXT) hddtemp-backtrace.$(OBJEXT) \
- hddtemp-utf8.$(OBJEXT)
+ hddtemp-utf8.$(OBJEXT) hddtemp-nvme.$(OBJEXT)
hddtemp_OBJECTS = $(am_hddtemp_OBJECTS)
hddtemp_DEPENDENCIES =
hddtemp_LDFLAGS =
@@ -195,6 +195,7 @@
@AMDEP_TRUE@ ./$(DEPDIR)/hddtemp-db.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/hddtemp-hddtemp.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/hddtemp-sata.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/hddtemp-nvme.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/hddtemp-satacmds.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/hddtemp-scsi.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/hddtemp-scsicmds.Po \
@@ -257,6 +258,7 @@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp-db.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp-hddtemp.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp-sata.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp-nvme.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp-satacmds.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp-scsi.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp-scsicmds.Po@am__quote@
@@ -416,6 +418,28 @@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hddtemp_CFLAGS) $(CFLAGS) -c -o hddtemp-sata.obj `if test -f 'sata.c'; then $(CYGPATH_W) 'sata.c'; else $(CYGPATH_W) '$(srcdir)/sata.c'; fi`
+hddtemp-nvme.o: nvme.c
+@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hddtemp_CFLAGS) $(CFLAGS) -MT hddtemp-nvme.o -MD -MP -MF "$(DEPDIR)/hddtemp-nvme.Tpo" \
+@am__fastdepCC_TRUE@ -c -o hddtemp-nvme.o `test -f 'nvme.c' || echo '$(srcdir)/'`nvme.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/hddtemp-nvme.Tpo" "$(DEPDIR)/hddtemp-nvme.Po"; \
+@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/hddtemp-nvme.Tpo"; exit 1; \
+@am__fastdepCC_TRUE@ fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nvme.c' object='hddtemp-nvme.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/hddtemp-nvme.Po' tmpdepfile='$(DEPDIR)/hddtemp-nvme.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hddtemp_CFLAGS) $(CFLAGS) -c -o hddtemp-nvme.o `test -f 'nvme.c' || echo '$(srcdir)/'`nvme.c
+
+hddtemp-nvme.obj: nvme.c
+@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hddtemp_CFLAGS) $(CFLAGS) -MT hddtemp-nvme.obj -MD -MP -MF "$(DEPDIR)/hddtemp-nvme.Tpo" \
+@am__fastdepCC_TRUE@ -c -o hddtemp-nvme.obj `if test -f 'nvme.c'; then $(CYGPATH_W) 'nvme.c'; else $(CYGPATH_W) '$(srcdir)/nvme.c'; fi`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/hddtemp-nvme.Tpo" "$(DEPDIR)/hddtemp-nvme.Po"; \
+@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/hddtemp-nvme.Tpo"; exit 1; \
+@am__fastdepCC_TRUE@ fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nvme.c' object='hddtemp-nvme.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/hddtemp-nvme.Po' tmpdepfile='$(DEPDIR)/hddtemp-nvme.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hddtemp_CFLAGS) $(CFLAGS) -c -o hddtemp-nvme.obj `if test -f 'nvme.c'; then $(CYGPATH_W) 'nvme.c'; else $(CYGPATH_W) '$(srcdir)/nvme.c'; fi`
+
hddtemp-satacmds.o: satacmds.c
@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hddtemp_CFLAGS) $(CFLAGS) -MT hddtemp-satacmds.o -MD -MP -MF "$(DEPDIR)/hddtemp-satacmds.Tpo" \
@am__fastdepCC_TRUE@ -c -o hddtemp-satacmds.o `test -f 'satacmds.c' || echo '$(srcdir)/'`satacmds.c; \
diff -uNr hddtemp-0.3-beta15.old/src/nvme.c hddtemp-0.3-beta15/src/nvme.c
--- hddtemp-0.3-beta15.old/src/nvme.c 1970-01-01 02:00:00.000000000 +0200
+++ hddtemp-0.3-beta15/src/nvme.c 2020-02-03 15:36:20.217181895 +0200
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2020 Constantine Gavrilov <constantine.gavrilov@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "hddtemp.h"
+#include <sys/ioctl.h>
+#include <linux/nvme_ioctl.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+struct nvme_smart_log {
+ unsigned char critical_warning;
+ unsigned char temperature[2];
+ unsigned char avail_spare;
+ unsigned char spare_thresh;
+ unsigned char percent_used;
+ unsigned char rsvd6[26];
+ unsigned char data_units_read[16];
+ unsigned char data_units_written[16];
+ unsigned char host_reads[16];
+ unsigned char host_writes[16];
+ unsigned char ctrl_busy_time[16];
+ unsigned char power_cycles[16];
+ unsigned char power_on_hours[16];
+ unsigned char unsafe_shutdowns[16];
+ unsigned char media_errors[16];
+ unsigned char num_err_log_entries[16];
+ unsigned int warning_temp_time;
+ unsigned int critical_comp_time;
+ unsigned short temp_sensor[8];
+ unsigned int thm_temp1_trans_count;
+ unsigned int thm_temp2_trans_count;
+ unsigned int thm_temp1_total_time;
+ unsigned int thm_temp2_total_time;
+ unsigned char rsvd232[280];
+};
+
+struct nvme_id_power_state {
+ unsigned short max_power; // centiwatts
+ unsigned char rsvd2;
+ unsigned char flags;
+ unsigned int entry_lat; // microseconds
+ unsigned int exit_lat; // microseconds
+ unsigned char read_tput;
+ unsigned char read_lat;
+ unsigned char write_tput;
+ unsigned char write_lat;
+ unsigned short idle_power;
+ unsigned char idle_scale;
+ unsigned char rsvd19;
+ unsigned short active_power;
+ unsigned char active_work_scale;
+ unsigned char rsvd23[9];
+};
+
+struct nvme_id_ctrl {
+ unsigned short vid;
+ unsigned short ssvid;
+ char sn[20];
+ char mn[40];
+ char fr[8];
+ unsigned char rab;
+ unsigned char ieee[3];
+ unsigned char cmic;
+ unsigned char mdts;
+ unsigned short cntlid;
+ unsigned int ver;
+ unsigned int rtd3r;
+ unsigned int rtd3e;
+ unsigned int oaes;
+ unsigned int ctratt;
+ unsigned char rsvd100[156];
+ unsigned short oacs;
+ unsigned char acl;
+ unsigned char aerl;
+ unsigned char frmw;
+ unsigned char lpa;
+ unsigned char elpe;
+ unsigned char npss;
+ unsigned char avscc;
+ unsigned char apsta;
+ unsigned short wctemp;
+ unsigned short cctemp;
+ unsigned short mtfa;
+ unsigned int hmpre;
+ unsigned int hmmin;
+ unsigned char tnvmcap[16];
+ unsigned char unvmcap[16];
+ unsigned int rpmbs;
+ unsigned short edstt;
+ unsigned char dsto;
+ unsigned char fwug;
+ unsigned short kas;
+ unsigned short hctma;
+ unsigned short mntmt;
+ unsigned short mxtmt;
+ unsigned int sanicap;
+ unsigned char rsvd332[180];
+ unsigned char sqes;
+ unsigned char cqes;
+ unsigned short maxcmd;
+ unsigned int nn;
+ unsigned short oncs;
+ unsigned short fuses;
+ unsigned char fna;
+ unsigned char vwc;
+ unsigned short awun;
+ unsigned short awupf;
+ unsigned char nvscc;
+ unsigned char rsvd531;
+ unsigned short acwu;
+ unsigned char rsvd534[2];
+ unsigned int sgls;
+ unsigned char rsvd540[228];
+ char subnqn[256];
+ unsigned char rsvd1024[768];
+ unsigned int ioccsz;
+ unsigned int iorcsz;
+ unsigned short icdoff;
+ unsigned char ctrattr;
+ unsigned char msdbd;
+ unsigned char rsvd1804[244];
+ struct nvme_id_power_state psd[32];
+ unsigned char vs[1024];
+};
+
+#include <stdio.h>
+
+static int nvme_probe(int fd)
+{
+ return (ioctl(fd, NVME_IOCTL_ID, NULL) > 0);
+}
+
+static bool nvme_read_smart_log(int fd, struct nvme_smart_log *smart_log)
+{
+ unsigned int size = sizeof(*smart_log);
+ struct nvme_passthru_cmd pt = { 0 };
+
+ memset(smart_log, 0, size);
+ pt.opcode = 0x02;
+ pt.nsid = 0xffffffff;
+ pt.addr = (uint64_t)smart_log;
+ pt.data_len = size;
+ pt.cdw10 = 0x02 | (((size / 4) - 1) << 16);
+ if (ioctl(fd, NVME_IOCTL_ADMIN_CMD, &pt) < 0)
+ return false;
+ return true;
+}
+
+static bool nvme_read_id_ctrl(int fd, struct nvme_id_ctrl *id)
+{
+ memset(id, 0, sizeof(*id));
+ struct nvme_passthru_cmd pt = { 0 };
+ pt.opcode = 0x06;
+ pt.nsid = 0;
+ pt.addr = (uint64_t)id;
+ pt.data_len = sizeof(*id);
+ pt.cdw10 = 0x01;
+ if (ioctl(fd, NVME_IOCTL_ADMIN_CMD, &pt) < 0)
+ return false;
+ return true;
+}
+
+
+const char *nvme_model(int fd)
+{
+ struct nvme_id_ctrl id;
+ unsigned int i;
+ char *p;
+ const unsigned int name_len = sizeof(id.mn);
+
+ if (nvme_read_id_ctrl(fd, &id) == false)
+ return "NVME Disk";
+ id.mn[name_len-1] = '\0';
+ for (i = name_len - 2; i > 0; i--) {
+ if (id.mn[i] == ' ')
+ id.mn[i] = '\0';
+ else
+ break;
+ }
+ p = id.mn;
+ for (i = 0; i < name_len; i++) {
+ if (id.mn[i] == ' ')
+ id.mn[i] = '\0';
+ else
+ break;
+ }
+ p = strdup(p);
+ if (!p || strlen(p) == 0)
+ return "NVME Disk";
+ for (i = 0; p[i]; i++) {
+ if (p[i] < 0x20 || p[i] > 0x7e)
+ p[i] = '?';
+ }
+ return p;
+}
+
+enum e_gettemp nvme_get_temperature(struct disk *disk)
+{
+ struct nvme_smart_log smart_log;
+ if (nvme_read_smart_log(disk->fd, &smart_log) == false)
+ return GETTEMP_UNKNOWN;
+ disk->value = smart_log.temperature[0] + (smart_log.temperature[1] << 8) - 273;
+ return GETTEMP_KNOWN;
+}
+
+struct bustype nvme_bus = {
+ "NVME",
+ nvme_probe,
+ nvme_model,
+ nvme_get_temperature
+};
+
+
diff -uNr hddtemp-0.3-beta15.old/src/nvme.h hddtemp-0.3-beta15/src/nvme.h
--- hddtemp-0.3-beta15.old/src/nvme.h 1970-01-01 02:00:00.000000000 +0200
+++ hddtemp-0.3-beta15/src/nvme.h 2020-02-03 08:08:03.708300652 +0200
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2020 Constnatine Gavrilov <constantine.gavrilov@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _HDDTEMP_NVME_H_
+#define _HDDTEMP_NVME_H_
+
+extern struct bustype nvme_bus;
+
+#endif
+