diff options
| author | Leandro A. F. Pereira <leandro@hardinfo.org> | 2019-06-29 22:24:21 -0700 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-06-29 22:24:21 -0700 | 
| commit | c9d00c85af88085df1427e72dea11b836f409cd3 (patch) | |
| tree | 03a8ccdeec82ca32059946417442264d46f85109 | |
| parent | 6ee860482e11f0fb042e2da874b095d80106c4f3 (diff) | |
| parent | 91a833a52e0c8b025969b88a9671e99ed8a1bf5e (diff) | |
Merge pull request #382 from bp0/mem9
 Memory Devices: Fix DMI to SPD matching 
| -rw-r--r-- | modules/devices/dmi_memory.c | 128 | ||||
| -rw-r--r-- | modules/devices/spd-decode.c | 39 | 
2 files changed, 122 insertions, 45 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 6250be9d..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) @@ -569,22 +572,47 @@ static gchar *decode_ddr3_sdram_extra(unsigned char *bytes) {      int ranks = 1 + ((bytes[7] >> 3) & 0x7);      int pins = 4 << (bytes[7] & 0x7); +    int die_count = (bytes[33] >> 4) & 0x7; +    int ts = !!(bytes[32] & 0x80);      /* expected to continue an [SPD] section */      return g_strdup_printf("%s=%d\n"                             "%s=%d\n" -                           "%s=%s %s %s\n" +                           "%s=%d %s\n" +                           "%s=[%02x] %s\n" +                           "%s=%s%s%s\n" +                           "%s=" +                              "%s%s%s%s%s%s%s%s" +                              "%s%s%s%s%s%s%s\n"                             "[%s]\n" -                           "tCL=%.2f\n" +                           "tCL=%.0f\n"                             "tRCD=%.3fns\n"                             "tRP=%.3fns\n"                             "tRAS=%.3fns\n",                             _("Ranks"), ranks,                             _("IO Pins per Chip"), pins, +                           _("Die count"), die_count, die_count ? "" : _("(Unspecified)"), +                           _("Thermal Sensor"), bytes[32], ts ? _("Present") : _("Not present"),                             _("Supported Voltages"), -                                (bytes[6] & 4) ? "1.25V" : "", -                                (bytes[6] & 2) ? "1.35V" : "", +                                (bytes[6] & 4) ? "1.25V " : "", +                                (bytes[6] & 2) ? "1.35V " : "",                                  (bytes[6] & 1) ? "" : "1.5V", +                           _("Supported CAS Latencies"), +                                (bytes[15] & 0x40) ? "18 " : "", +                                (bytes[15] & 0x20) ? "17 " : "", +                                (bytes[15] & 0x10) ? "16 " : "", +                                (bytes[15] & 0x08) ? "15 " : "", +                                (bytes[15] & 0x04) ? "14 " : "", +                                (bytes[15] & 0x02) ? "13 " : "", +                                (bytes[15] & 0x01) ? "12 " : "", +                                (bytes[14] & 0x80) ? "11 " : "", +                                (bytes[14] & 0x40) ? "10 " : "", +                                (bytes[14] & 0x20) ? "9 " : "", +                                (bytes[14] & 0x10) ? "8 " : "", +                                (bytes[14] & 0x08) ? "7 " : "", +                                (bytes[14] & 0x04) ? "6 " : "", +                                (bytes[14] & 0x02) ? "5 " : "", +                                (bytes[14] & 0x01) ? "4" : "",                             _("Timings"), tcl, trcd, trp, tras                             );  } @@ -1079,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);          } | 
