aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBurt P <pburt0@gmail.com>2019-06-29 22:22:16 -0500
committerBurt P <pburt0@gmail.com>2019-06-29 22:44:46 -0500
commit91a833a52e0c8b025969b88a9671e99ed8a1bf5e (patch)
tree6b0b27de58982ed72d9366aa5a4f5f956c8817dc
parentec3c0e9098b0491ac6032c06f691e45d4bd12299 (diff)
Memory Devices: Fix DMI to SPD matching
Should fix https://github.com/lpereira/hardinfo/issues/380 Signed-off-by: Burt P <pburt0@gmail.com>
-rw-r--r--modules/devices/dmi_memory.c128
-rw-r--r--modules/devices/spd-decode.c6
2 files changed, 93 insertions, 41 deletions
diff --git a/modules/devices/dmi_memory.c b/modules/devices/dmi_memory.c
index abc47c45..ad200875 100644
--- a/modules/devices/dmi_memory.c
+++ b/modules/devices/dmi_memory.c
@@ -23,6 +23,7 @@
#include <inttypes.h>
#include "dt_util.h" /* for appf() */
+#define dmi_spd_msg(...) /* fprintf (stderr, __VA_ARGS__) */
#include "spd-decode.c"
@@ -106,7 +107,7 @@ void dmi_mem_array_free(dmi_mem_array* s) {
}
}
-typedef struct {
+typedef struct dmi_mem_socket {
unsigned long handle;
unsigned long array_handle;
gboolean populated;
@@ -144,8 +145,8 @@ typedef struct {
long int spd_size_MiB;
int spd_ram_types; /* bits using enum RamType */
- int system_memory_ram_types; /* bits using enum RamType */
long int system_memory_MiB;
+ int system_memory_ram_types; /* bits using enum RamType */
} dmi_mem;
gboolean null_if_empty(gchar **str) {
@@ -281,6 +282,37 @@ dmi_mem_array *dmi_mem_find_array(dmi_mem *s, unsigned int handle) {
return NULL;
}
+static int dmi_spd_match_score(dmi_mem_socket *s, spd_data *e) {
+ int score = 0;
+ if (SEQ(s->partno, e->partno))
+ score += 20;
+ if (s->size_MiB == e->size_MiB)
+ score += 10;
+ if (s->vendor == e->vendor)
+ score += 5;
+ return score;
+}
+
+/* fill in missing from SPD */
+static void dmi_fill_from_spd(dmi_mem_socket *s) {
+ if (!s->spd)
+ return;
+
+ if (!s->mfgr && s->spd->vendor_str) {
+ s->mfgr = g_strdup(s->spd->vendor_str);
+ s->vendor = s->spd->vendor;
+ }
+
+ if (!s->partno && s->spd->partno)
+ s->partno = g_strdup(s->spd->partno);
+
+ if (!s->form_factor && s->spd->form_factor)
+ s->form_factor = g_strdup(s->spd->form_factor);
+
+ if (!s->type_detail && s->spd->type_detail)
+ s->type_detail = g_strdup(s->spd->type_detail);
+}
+
dmi_mem *dmi_mem_new() {
dmi_mem *m = g_new0(dmi_mem, 1);
@@ -333,49 +365,65 @@ dmi_mem *dmi_mem_new() {
if (s->ram_type)
a->ram_types |= (1 << s->ram_type-1);
}
+ }
- if (!s->populated) continue;
- if (!m->spd) continue;
-
- /* match SPD */
- spd_data *best = NULL;
- int best_score = 0;
- for(l2 = m->spd; l2; l2 = l2->next) {
- spd_data *e = (spd_data*)l2->data;
-
- int score = 0;
- if (!e->claimed_by_dmi) {
- if (SEQ(s->partno, e->partno))
- score += 20;
- if (s->size_MiB == e->size_MiB)
- score += 10;
- if (s->vendor == e->vendor)
- score += 5;
-
- if (score > best_score)
- best = e;
+ if (m->sockets && m->spd) {
+ /* attempt to match DMI and SPD data */
+ GSList *sock_queue = g_slist_copy(m->sockets);
+ int loops = g_slist_length(sock_queue) * 4;
+ while(sock_queue) {
+ if (loops-- <= 0) break; /* something is wrong, give up */
+ dmi_spd_msg("match queue has %d\n", g_slist_length(sock_queue) );
+ spd_data *best = NULL;
+ int best_score = 0;
+ dmi_mem_socket *s = (dmi_mem_socket*)sock_queue->data;
+ /* pop that one off */
+ sock_queue = g_slist_delete_link(sock_queue, sock_queue);
+ if (!s->populated)
+ continue;
+ for(l2 = m->spd; l2; l2 = l2->next) {
+ spd_data *e = (spd_data*)l2->data;
+ int score = dmi_spd_match_score(s, e);
+ dmi_spd_msg("... s:%s vs e:%s%s = %d (best_score = %d)\n", s->full_locator, e->dev, e->dmi_socket ? "*" : "", score, best_score);
+ if (score > best_score) {
+ if (score > e->match_score) {
+ dmi_spd_msg("----- new best!\n");
+ best = e;
+ best_score = score;
+ }
+ }
}
+ if (best) {
+ dmi_spd_msg("*** best for s:%s was e:%s with %d\n", s->full_locator, best->dev, best_score);
+ if (best->dmi_socket) {
+ /* displace */
+ dmi_mem_socket *old_sock = best->dmi_socket;
+ old_sock->spd = NULL;
+ sock_queue = g_slist_append(sock_queue, old_sock);
+
+ best->dmi_socket = s;
+ best->match_score = best_score;
+ s->spd = best;
+ } else {
+ dmi_spd_msg("*** no conflict!\n");
+ best->dmi_socket = s;
+ best->match_score = best_score;
+ s->spd = best;
+ }
+ } else
+ dmi_spd_msg("no match!\n");
}
- if (best) {
- s->spd = best;
- best->claimed_by_dmi = 1;
-
- /* fill in missing from SPD */
- if (!s->mfgr && s->spd->vendor_str) {
- s->mfgr = g_strdup(s->spd->vendor_str);
- s->vendor = s->spd->vendor;
- }
-
- if (!s->partno && s->spd->partno)
- s->partno = g_strdup(s->spd->partno);
- if (!s->form_factor && s->spd->form_factor)
- s->form_factor = g_strdup(s->spd->form_factor);
+ dmi_spd_msg("------- done matching.\n");
- if (!s->type_detail && s->spd->type_detail)
- s->type_detail = g_strdup(s->spd->type_detail);
+ /* fill any missing data in DMI that is
+ * provided by the matched SPD */
+ for(l = m->sockets; l; l = l->next) {
+ dmi_mem_socket *s = (dmi_mem_socket*)l->data;
+ dmi_fill_from_spd(s);
}
- }
+
+ } /* end if (m->sockets && m->spd) */
/* Look for arrays with "System Memory" use,
* or Mainboard as locator */
@@ -684,7 +732,7 @@ gchar *memory_devices_get_info() {
/* Unmatched SPD */
for(l = mem->spd; l; l = l->next) {
spd_data *s = (spd_data*)l->data;
- if (s->claimed_by_dmi) continue;
+ if (s->dmi_socket) continue; /* claimed by DMI */
gchar *key = g_strdup_printf("SPD:%s", s->dev);
gchar *vendor_str = NULL;
if (s->vendor) {
diff --git a/modules/devices/spd-decode.c b/modules/devices/spd-decode.c
index 4c34882f..164ad9dc 100644
--- a/modules/devices/spd-decode.c
+++ b/modules/devices/spd-decode.c
@@ -62,6 +62,7 @@ static const char *ram_types[] = {"Unknown", "Direct Rambus", "Rambus",
#include "spd-vendors.c"
+struct dmi_mem_socket;
typedef struct {
unsigned char bytes[512];
unsigned char dev[32]; /* %1d-%04d\0 */
@@ -92,7 +93,9 @@ typedef struct {
int week, year;
gboolean ddr4_no_ee1004;
- gboolean claimed_by_dmi;
+
+ struct dmi_mem_socket *dmi_socket;
+ int match_score;
} spd_data;
#define spd_data_new() g_new0(spd_data, 1)
@@ -1104,6 +1107,7 @@ static GSList *decode_dimms2(GSList *eeprom_list, gboolean use_sysfs, int max_si
s->spd_rev_minor = bytes[1] & 0xf;
break;
}
+ s->vendor = vendor_match(s->vendor_str, NULL);
s->dram_vendor = vendor_match(s->dram_vendor_str, NULL);
dimm_list = g_slist_append(dimm_list, s);
}