diff options
author | tsien <none@none> | 2008-04-14 10:59:07 -0700 |
---|---|---|
committer | tsien <none@none> | 2008-04-14 10:59:07 -0700 |
commit | d30c532def6a53800f4c4926a0b726cb23b1e6df (patch) | |
tree | b2c4f3e4c78844fdd7f2739afe65e75e4a5a9d13 | |
parent | a6e6969cf9cfe2070eae4cd6071f76b0fa4f539f (diff) | |
download | illumos-gate-d30c532def6a53800f4c4926a0b726cb23b1e6df.tar.gz |
6677931 mem scheme assumes certain relationship between memory-segment and memory-bank nodes in PRI
-rw-r--r-- | usr/src/cmd/fm/schemes/mem/mem.c | 10 | ||||
-rw-r--r-- | usr/src/cmd/fm/schemes/mem/mem.h | 38 | ||||
-rw-r--r-- | usr/src/cmd/fm/schemes/mem/sparc/mem_disc.c | 236 |
3 files changed, 213 insertions, 71 deletions
diff --git a/usr/src/cmd/fm/schemes/mem/mem.c b/usr/src/cmd/fm/schemes/mem/mem.c index c17e7e333e..5df8b1a798 100644 --- a/usr/src/cmd/fm/schemes/mem/mem.c +++ b/usr/src/cmd/fm/schemes/mem/mem.c @@ -390,6 +390,8 @@ void fmd_fmri_fini(void) { mem_dimm_map_t *dm, *em; + mem_bank_map_t *bm, *cm; + mem_grp_t *gm, *hm; mem_seg_map_t *sm, *tm; for (dm = mem.mem_dm; dm != NULL; dm = em) { @@ -399,6 +401,14 @@ fmd_fmri_fini(void) fmd_fmri_strfree(dm->dm_device); fmd_fmri_free(dm, sizeof (mem_dimm_map_t)); } + for (bm = mem.mem_bank; bm != NULL; bm = cm) { + cm = bm->bm_next; + fmd_fmri_free(bm, sizeof (mem_bank_map_t)); + } + for (gm = mem.mem_group; gm != NULL; gm = hm) { + hm = gm->mg_next; + fmd_fmri_free(gm, sizeof (mem_grp_t)); + } for (sm = mem.mem_seg; sm != NULL; sm = tm) { tm = sm->sm_next; fmd_fmri_free(sm, sizeof (mem_seg_map_t)); diff --git a/usr/src/cmd/fm/schemes/mem/mem.h b/usr/src/cmd/fm/schemes/mem/mem.h index 781c034c69..288bd2a6d1 100644 --- a/usr/src/cmd/fm/schemes/mem/mem.h +++ b/usr/src/cmd/fm/schemes/mem/mem.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -106,15 +106,7 @@ extern "C" { * 18 for Sun Partnumber, 18 partner partnumber, 12 serialnumber for OPL. */ #define MEM_SERID_MAXLEN 64 - -typedef struct mem_seg_map { - struct mem_seg_map *sm_next; /* the next segment map */ - uint64_t sm_base; /* base address for this segment */ - uint64_t sm_size; /* size for this segment */ - uint64_t sm_mask; /* mask denoting dimm selection bits */ - uint64_t sm_match; /* value selecting this set of DIMMs */ - uint16_t sm_shift; /* dimms-per-reference shift */ -} mem_seg_map_t; +#define MAX_DIMMS_PER_BANK 4 typedef struct mem_dimm_map { struct mem_dimm_map *dm_next; /* The next DIMM map */ @@ -123,13 +115,37 @@ typedef struct mem_dimm_map { char dm_serid[MEM_SERID_MAXLEN]; /* Cached serial number */ char *dm_part; /* DIMM part number */ uint64_t dm_drgen; /* DR gen count for cached S/N */ - mem_seg_map_t *dm_seg; /* segment for this DIMM */ } mem_dimm_map_t; +typedef struct mem_bank_map { + struct mem_bank_map *bm_next; /* the next bank map overall */ + struct mem_bank_map *bm_grp; /* next bank map in group */ + uint64_t bm_mask; + uint64_t bm_match; + uint16_t bm_shift; /* dimms-per-reference shift */ + mem_dimm_map_t *bm_dimm[MAX_DIMMS_PER_BANK]; +} mem_bank_map_t; + +typedef struct mem_grp { + struct mem_grp *mg_next; + size_t mg_size; + mem_bank_map_t *mg_bank; +} mem_grp_t; + +typedef struct mem_seg_map { + struct mem_seg_map *sm_next; /* the next segment map */ + uint64_t sm_base; /* base address for this segment */ + uint64_t sm_size; /* size for this segment */ + mem_grp_t *sm_grp; +} mem_seg_map_t; + + typedef struct mem { mem_dimm_map_t *mem_dm; /* List supported DIMMs */ uint64_t mem_memconfig; /* HV memory-configuration-id# */ mem_seg_map_t *mem_seg; /* list of defined segments */ + mem_bank_map_t *mem_bank; + mem_grp_t *mem_group; /* groups of banks for a segment */ } mem_t; extern int mem_discover(void); diff --git a/usr/src/cmd/fm/schemes/mem/sparc/mem_disc.c b/usr/src/cmd/fm/schemes/mem/sparc/mem_disc.c index 396f39c1cf..b8bb1af458 100644 --- a/usr/src/cmd/fm/schemes/mem/sparc/mem_disc.c +++ b/usr/src/cmd/fm/schemes/mem/sparc/mem_disc.c @@ -371,6 +371,60 @@ get_dimm_by_sn(char *sn) return (NULL); } +mem_grp_t * +find_grp(mde_cookie_t *listp, size_t n, mde_cookie_t *bclist, + mem_bank_map_t **banklist, size_t mem_bank_count) { + + mem_grp_t *mg; + mem_bank_map_t *bp; + size_t i, j; + int err; + + for (mg = mem.mem_group; mg != NULL; mg = mg->mg_next) { + if (mg->mg_size == n) { + err = 0; + for (i = 0, bp = mg->mg_bank; + i < n && bp != NULL; + i++, bp = bp->bm_grp) { + for (j = 0; j < mem_bank_count; j++) { + if (listp[i] == *(bclist+j) && + bp == *(banklist+j)) + break; + } + if (bp == NULL) err++; + } + } + else + err++; + if (err == 0) + return (mg); + } + return (NULL); +} + +mem_grp_t * +create_grp(mde_cookie_t *listp, size_t n, mde_cookie_t *bclist, + mem_bank_map_t **banklist, size_t mem_bank_count) { + + mem_grp_t *mg; + size_t i, j; + + mg = fmd_fmri_zalloc(sizeof (mem_grp_t)); + mg->mg_size = n; + mg->mg_next = mem.mem_group; + mem.mem_group = mg; + + for (i = 0; i < n; i++) { + for (j = 0; j < mem_bank_count; j++) { + if (listp[i] == *(bclist+j)) { + (*(banklist+j))->bm_grp = mg->mg_bank; + mg->mg_bank = *(banklist+j); + } + } + } + return (mg); +} + #define MEM_BYTES_PER_CACHELINE 64 static void @@ -385,6 +439,8 @@ mdesc_init_n1(md_t *mdp, mde_cookie_t *listp) uint64_t rank_mask, rank_value; char *unum, *serial, *part; mem_seg_map_t *seg; + mem_bank_map_t *bm; + mem_grp_t *mg; char s[20]; /* @@ -473,6 +529,16 @@ mdesc_init_n1(md_t *mdp, mde_cookie_t *listp) else chan_step = max_chan - min_chan; + seg = fmd_fmri_zalloc(sizeof (mem_seg_map_t)); + seg->sm_next = mem.mem_seg; + mem.mem_seg = seg; + seg->sm_base = 0; + seg->sm_size = sysmem_size; + + mg = fmd_fmri_zalloc(sizeof (mem_grp_t)); + seg->sm_grp = mg; + mem.mem_group = mg; + for (rank = min_rank, rank_value = 0; rank <= max_rank; rank++, rank_value += rank_mask) { @@ -480,18 +546,19 @@ mdesc_init_n1(md_t *mdp, mde_cookie_t *listp) chan <= max_chan; chan += chan_step, chan_value += MEM_BYTES_PER_CACHELINE) { - seg = fmd_fmri_zalloc(sizeof (mem_seg_map_t)); - seg->sm_next = mem.mem_seg; - mem.mem_seg = seg; - seg->sm_base = 0; - seg->sm_size = sysmem_size; - seg->sm_mask = mask; - seg->sm_match = chan_value | rank_value; - seg->sm_shift = 1; + bm = fmd_fmri_zalloc(sizeof (mem_bank_map_t)); + bm->bm_mask = mask; + bm->bm_match = chan_value | rank_value; + bm->bm_shift = 1; + bm->bm_grp = mg->mg_bank; + mg->mg_bank = bm; + bm->bm_next = mem.mem_bank; + mem.mem_bank = bm; (void) sprintf(s, "MB/CMP0/CH%1d/R%1d", chan, rank); + idx = 0; for (d = mem.mem_dm; d != NULL; d = d->dm_next) { if (strncmp(s, d->dm_label, strlen(s)) == 0) - d->dm_seg = seg; + bm->bm_dimm[idx++] = d; } } } @@ -500,14 +567,16 @@ mdesc_init_n1(md_t *mdp, mde_cookie_t *listp) static void mdesc_init_n2(md_t *mdp, mde_cookie_t *listp, int num_comps) { - mde_cookie_t *dl, t; - int idx, mdesc_dimm_count, mdesc_bank_count; + mde_cookie_t *dl, *bl, *bclist; + int bc, idx, mdesc_dimm_count, mdesc_bank_count; mem_dimm_map_t *dm, *dp; uint64_t i, drgen = fmd_fmri_get_drgen(); int n; uint64_t mask, match, base, size; char *unum, *serial, *part, *dash; mem_seg_map_t *smp; + mem_bank_map_t *bmp, **banklist; + mem_grp_t *gmp; char *type, *sp, *jnum, *nac; size_t ss; @@ -569,6 +638,17 @@ mdesc_init_n2(md_t *mdp, mde_cookie_t *listp, int num_comps) md_find_name(mdp, "fwd"), listp); + /* + * banklist and bclist will be parallel arrays. For a given bank, + * bclist[i] will be the PRI node id, and *banklist+i will point to the + * mem_bank_map_t for that bank. + */ + + banklist = fmd_fmri_zalloc(mdesc_bank_count * + sizeof (mem_bank_map_t *)); + bclist = fmd_fmri_zalloc(mdesc_bank_count * + sizeof (mde_cookie_t)); + dl = fmd_fmri_zalloc(mdesc_dimm_count * sizeof (mde_cookie_t)); for (idx = 0; idx < mdesc_bank_count; idx++) { @@ -576,27 +656,20 @@ mdesc_init_n2(md_t *mdp, mde_cookie_t *listp, int num_comps) mask = 0; if (md_get_prop_val(mdp, listp[idx], "match", &match) < 0) match = 0; - n = md_scan_dag(mdp, listp[idx], - md_find_name(mdp, "memory-segment"), - md_find_name(mdp, "back"), - &t); /* only 1 "back" arc, so n must equal 1 here */ - if (md_get_prop_val(mdp, t, "base", &base) < 0) - base = 0; - if (md_get_prop_val(mdp, t, "size", &size) < 0) - size = 0; - smp = fmd_fmri_zalloc(sizeof (mem_seg_map_t)); - smp->sm_next = mem.mem_seg; - mem.mem_seg = smp; - smp->sm_base = base; - smp->sm_size = size; - smp->sm_mask = mask; - smp->sm_match = match; - + bmp = fmd_fmri_zalloc(sizeof (mem_bank_map_t)); + bmp->bm_next = mem.mem_bank; + mem.mem_bank = bmp; + bmp->bm_mask = mask; + bmp->bm_match = match; + /* link this bank to its dimms */ n = md_scan_dag(mdp, listp[idx], md_find_name(mdp, "component"), md_find_name(mdp, "fwd"), dl); - smp->sm_shift = mem_log2(n); + bmp->bm_shift = mem_log2(n); + + bclist[idx] = listp[idx]; + *(banklist+idx) = bmp; for (i = 0; i < n; i++) { if (md_get_prop_str(mdp, dl[i], @@ -604,10 +677,40 @@ mdesc_init_n2(md_t *mdp, mde_cookie_t *listp, int num_comps) continue; if ((dp = get_dimm_by_sn(serial)) == NULL) continue; - dp->dm_seg = smp; + bmp->bm_dimm[i] = dp; } } fmd_fmri_free(dl, mdesc_dimm_count * sizeof (mde_cookie_t)); + + bl = fmd_fmri_zalloc(mdesc_bank_count * sizeof (mde_cookie_t)); + n = md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE, + md_find_name(mdp, "memory-segment"), + md_find_name(mdp, "fwd"), + listp); + for (idx = 0; idx < n; idx++) { + if (md_get_prop_val(mdp, listp[idx], "base", &base) < 0) + base = 0; + if (md_get_prop_val(mdp, listp[idx], "size", &size) < 0) + size = 0; + bc = md_scan_dag(mdp, listp[idx], + md_find_name(mdp, "memory-bank"), + md_find_name(mdp, "fwd"), + bl); + smp = fmd_fmri_zalloc(sizeof (mem_seg_map_t)); + smp->sm_next = mem.mem_seg; + mem.mem_seg = smp; + smp->sm_base = base; + smp->sm_size = size; + gmp = find_grp(bl, bc, bclist, banklist, mdesc_bank_count); + if (gmp == NULL) + smp->sm_grp = create_grp(bl, bc, + bclist, banklist, mdesc_bank_count); + else + smp->sm_grp = gmp; + } + fmd_fmri_free(bl, mdesc_bank_count * sizeof (mde_cookie_t)); + fmd_fmri_free(bclist, mdesc_bank_count * sizeof (mde_cookie_t)); + fmd_fmri_free(banklist, mdesc_bank_count * sizeof (mem_bank_map_t *)); } int @@ -1067,20 +1170,6 @@ mem_get_parts_by_unum(const char *unum, char ***partp, uint_t *npartp) return (mem_get_parts_from_mdesc(unum, partp, npartp)); } -static int -get_seg_by_sn(char *sn, mem_seg_map_t **segmap) -{ - mem_dimm_map_t *dm; - - for (dm = mem.mem_dm; dm != NULL; dm = dm->dm_next) { - if (strcmp(sn, dm->dm_serid) == 0) { - *segmap = dm->dm_seg; - return (0); - } - } - return (-1); -} - /* * Niagara-1, Niagara-2, and Victoria Falls all have physical address * spaces of 40 bits. @@ -1155,10 +1244,28 @@ mem_get_serids_by_unum(const char *unum, char ***seridsp, size_t *nseridsp) return (mem_get_serids_from_cache(unum, seridsp, nseridsp)); } +uint64_t +calc_phys_addr(mem_seg_map_t *seg, char *ds, uint64_t offset) +{ + mem_bank_map_t *bm; + size_t i; + + for (bm = seg->sm_grp->mg_bank; bm != NULL; bm = bm->bm_grp) { + for (i = 0; i < MAX_DIMMS_PER_BANK && + bm->bm_dimm[i] != NULL; i++) { + if (strcmp(bm->bm_dimm[i]->dm_serid, ds) == 0) + return (insert_bits(offset<<bm->bm_shift, + bm->bm_mask, bm->bm_match)); + } + } + return ((uint64_t)-1); +} + void mem_expand_opt(nvlist_t *nvl, char *unum, char **serids) { mem_seg_map_t *seg; + mem_bank_map_t *bm; uint64_t offset, physaddr; char **parts; uint_t nparts; @@ -1170,23 +1277,32 @@ mem_expand_opt(nvlist_t *nvl, char *unum, char **serids) * fmd_fmri_expand. All optional expansions will be attempted * once expand_opt is entered. */ - - if ((mem.mem_seg != NULL) && - (get_seg_by_sn(*serids, &seg) == 0) && - (seg != NULL)) { /* seg can be NULL if segment missing from PRI */ - - if (nvlist_lookup_uint64(nvl, - FM_FMRI_MEM_OFFSET, &offset) == 0) { - physaddr = insert_bits((offset<<seg->sm_shift), - seg->sm_mask, seg->sm_match); - (void) nvlist_add_uint64(nvl, FM_FMRI_MEM_PHYSADDR, - physaddr); /* displaces any previous physaddr */ - } else if (nvlist_lookup_uint64(nvl, - FM_FMRI_MEM_PHYSADDR, &physaddr) == 0) { - offset = extract_bits(physaddr, - seg->sm_mask) >> seg->sm_shift; - (void) (nvlist_add_uint64(nvl, FM_FMRI_MEM_OFFSET, - offset)); + if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_OFFSET, &offset) == 0) { + for (seg = mem.mem_seg; seg != NULL; seg = seg->sm_next) { + physaddr = calc_phys_addr(seg, *serids, offset); + if (physaddr >= seg->sm_base && + physaddr < seg->sm_base + seg->sm_size) { + (void) nvlist_add_uint64(nvl, + FM_FMRI_MEM_PHYSADDR, physaddr); + } + } + } else if (nvlist_lookup_uint64(nvl, + FM_FMRI_MEM_PHYSADDR, &physaddr) == 0) { + for (seg = mem.mem_seg; seg != NULL; seg = seg->sm_next) { + if (physaddr >= seg->sm_base && + physaddr < seg->sm_base + seg->sm_size) { + bm = seg->sm_grp->mg_bank; + /* + * The mask & shift values for all banks in a + * segment are always the same; only the match + * values differ, in order to specify a + * dimm-pair. But we already have a full unum. + */ + offset = extract_bits(physaddr, + bm->bm_mask) >> bm->bm_shift; + (void) (nvlist_add_uint64(nvl, + FM_FMRI_MEM_OFFSET, offset)); + } } } |