Print this page
10097 indenting fixes in usr/src/{lib,common}
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/common/mc/mc-amd/mcamd_rowcol.c
+++ new/usr/src/common/mc/mc-amd/mcamd_rowcol.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 *
21 21 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
22 22 * Use is subject to license terms.
23 23 */
24 24
25 -#pragma ident "%Z%%M% %I% %E% SMI"
25 +/*
26 + * Copyright (c) 2018, Joyent, Inc.
27 + */
26 28
27 29 #include <mcamd_api.h>
28 30 #include <mcamd_err.h>
29 31 #include <mcamd_rowcol_impl.h>
30 32
31 33 /*
32 34 * Convenience structures to stash MC and CS properties in.
33 35 */
34 36 struct mcprops {
35 37 mcamd_prop_t num; /* corresponding chip number */
36 38 mcamd_prop_t rev; /* revision */
37 39 mcamd_prop_t width; /* access width */
38 40 mcamd_prop_t base; /* MC base address */
39 41 mcamd_prop_t lim; /* MC limit address */
40 42 mcamd_prop_t csbnkmap_reg; /* chip-select bank map */
41 43 mcamd_prop_t intlven; /* Node-intlv mask */
42 44 mcamd_prop_t intlvsel; /* Node-intlv selection for this node */
43 45 mcamd_prop_t csintlvfctr; /* cs intlv factor on this node */
44 46 mcamd_prop_t bnkswzl; /* bank-swizzle mode */
45 47 mcamd_prop_t sparecs; /* spare cs#, if any */
46 48 mcamd_prop_t badcs; /* substituted cs#, if any */
47 49 };
48 50
49 51 struct csprops {
50 52 mcamd_prop_t num; /* chip-select number */
51 53 mcamd_prop_t base; /* chip-select base address */
52 54 mcamd_prop_t mask; /* chip-select mask */
53 55 mcamd_prop_t testfail; /* marked testFail */
54 56 mcamd_prop_t dimmrank; /* rank number on dimm(s) */
55 57 };
56 58
57 59 static int
58 60 getmcprops(struct mcamd_hdl *hdl, mcamd_node_t *mc, const char *caller,
59 61 struct mcprops *pp)
60 62 {
61 63 if (!mcamd_get_numprops(hdl,
62 64 mc, MCAMD_PROP_NUM, &pp->num,
63 65 mc, MCAMD_PROP_REV, &pp->rev,
64 66 mc, MCAMD_PROP_ACCESS_WIDTH, &pp->width,
65 67 mc, MCAMD_PROP_BASE_ADDR, &pp->base,
66 68 mc, MCAMD_PROP_LIM_ADDR, &pp->lim,
67 69 mc, MCAMD_PROP_CSBANKMAPREG, &pp->csbnkmap_reg,
68 70 mc, MCAMD_PROP_ILEN, &pp->intlven,
69 71 mc, MCAMD_PROP_ILSEL, &pp->intlvsel,
70 72 mc, MCAMD_PROP_CSINTLVFCTR, &pp->csintlvfctr,
71 73 mc, MCAMD_PROP_BANKSWZL, &pp->bnkswzl,
72 74 mc, MCAMD_PROP_SPARECS, &pp->sparecs,
73 75 mc, MCAMD_PROP_BADCS, &pp->badcs,
74 76 NULL)) {
75 77 mcamd_dprintf(hdl, MCAMD_DBG_ERR, "%s: failed to read mc "
76 78 "props for mc 0x%p\n", caller, mc);
77 79 return (mcamd_set_errno(hdl, EMCAMD_TREEINVALID));
78 80 }
79 81
80 82 return (0);
81 83 }
82 84
83 85 static int
84 86 getcsprops(struct mcamd_hdl *hdl, mcamd_node_t *cs, const char *caller,
85 87 struct csprops *csp)
86 88 {
87 89 if (!mcamd_get_numprops(hdl,
88 90 cs, MCAMD_PROP_NUM, &csp->num,
89 91 cs, MCAMD_PROP_BASE_ADDR, &csp->base,
90 92 cs, MCAMD_PROP_MASK, &csp->mask,
91 93 cs, MCAMD_PROP_TESTFAIL, &csp->testfail,
92 94 cs, MCAMD_PROP_DIMMRANK, &csp->dimmrank,
93 95 NULL)) {
94 96 mcamd_dprintf(hdl, MCAMD_DBG_ERR, "%s: failed to read cs "
95 97 "props for cs 0x%p\n", caller, cs);
96 98 return (mcamd_set_errno(hdl, EMCAMD_TREEINVALID));
97 99 }
98 100
99 101 return (0);
100 102 }
101 103
102 104 static int
103 105 gettbls(struct mcamd_hdl *hdl, uint_t csmode, struct mcprops *mcpp,
104 106 const struct rct_bnkaddrmode **bamp, const struct rct_rcbmap **rcbmp,
105 107 const struct rct_bnkswzlinfo **swzlp, struct rct_csintlv *csid,
106 108 const char *caller)
107 109 {
108 110 uint_t rev = (uint_t)mcpp->rev;
109 111 int width = (int)mcpp->width;
110 112
111 113 if (bamp && (*bamp = rct_bnkaddrmode(rev, csmode)) == NULL) {
112 114 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "%s: no bank address mode "
113 115 "table for MC rev %d csmode %d\n", caller, rev, csmode);
114 116 return (mcamd_set_errno(hdl, EMCAMD_NOTSUP));
115 117 }
116 118
117 119 if (rcbmp && (*rcbmp = rct_rcbmap(rev, width, csmode)) == NULL) {
118 120 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "%s: no dram address map "
119 121 "table for MC rev %d csmode %d\n", caller,
120 122 rev, csmode);
121 123 return (mcamd_set_errno(hdl, EMCAMD_NOTSUP));
122 124 }
123 125
124 126 if (swzlp && (*swzlp = rct_bnkswzlinfo(rev, width)) == NULL) {
125 127 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "%s: no bank swizzling "
126 128 "table for MC rev %d width %d\n", caller, rev, width);
127 129 return (mcamd_set_errno(hdl, EMCAMD_NOTSUP));
128 130 }
129 131
130 132 if (csid) {
131 133 if (mcpp->csintlvfctr > 1) {
132 134 rct_csintlv_bits(rev, width, csmode,
133 135 mcpp->csintlvfctr, csid);
134 136 if (csid->csi_factor == 0) {
135 137 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "%s: "
136 138 "could not work out cs interleave "
137 139 "paramters for MC rev %d, width %d, "
138 140 "csmode %d, factor %d\n", caller,
139 141 rev, width, csmode,
140 142 (int)mcpp->csintlvfctr);
141 143 return (mcamd_set_errno(hdl, EMCAMD_NOTSUP));
142 144 }
143 145 } else {
144 146 csid->csi_factor = 0;
145 147 }
146 148 }
147 149
148 150 return (0);
149 151 }
150 152
151 153 static uint64_t
152 154 iaddr_add(struct mcamd_hdl *hdl, uint64_t in, uint64_t add, const char *what)
153 155 {
154 156 uint64_t new = in | add;
155 157
156 158 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "%s: 0x%llx | 0x%llx --> 0x%llx",
157 159 what, in, add, new);
158 160
159 161 return (add);
160 162 }
161 163
162 164 /*
163 165 * Where the number of row/col address bits is ambiguous (affects CG and
164 166 * earlier only) we will assign the "floating" bit to row address. If
165 167 * we adopt the same convention in address reconstruction then all should work.
166 168 */
167 169 static uint32_t
168 170 iaddr_to_row(struct mcamd_hdl *hdl, const struct rct_bnkaddrmode *bamp,
169 171 const struct rct_rcbmap *rcbm, struct rct_csintlv *csid, uint64_t iaddr)
170 172 {
171 173 uint32_t addr = 0;
172 174 int abitno, ibitno;
173 175 int nbits = bamp->bam_nrows;
174 176 int swapped = 0;
175 177
176 178 for (abitno = 0; abitno < nbits; abitno++) {
177 179 ibitno = rcbm->rcb_rowbit[abitno];
178 180 if (MC_RC_CSI_SWAPPED_BIT(csid, ibitno)) {
179 181 ibitno = MC_RC_CSI_BITSWAP(csid, ibitno);
180 182 swapped++;
181 183 }
182 184 if (BITVAL(iaddr, ibitno) != 0)
183 185 SETBIT(addr, abitno);
184 186 }
185 187
186 188 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "iaddr_to_row: iaddr 0x%llx --> "
187 189 "row 0x%x (%d bits swapped for cs intlv)\n", iaddr, addr, swapped);
188 190
189 191 return (addr);
190 192 }
191 193
192 194 /*ARGSUSED*/
193 195 static uint64_t
194 196 row_to_iaddr(struct mcamd_hdl *hdl, const struct rct_bnkaddrmode *bamp,
195 197 const struct rct_rcbmap *rcbm, struct rct_csintlv *csid, uint32_t rowaddr)
196 198 {
197 199 uint64_t iaddr = 0;
198 200 int abitno, ibitno;
199 201 int nbits = bamp->bam_nrows;
200 202
201 203 for (abitno = 0; abitno < nbits; abitno++) {
202 204 if (BIT(rowaddr, abitno) == 0)
203 205 continue;
204 206 ibitno = rcbm->rcb_rowbit[abitno];
205 207 if (MC_RC_CSI_SWAPPED_BIT(csid, ibitno)) {
206 208 ibitno = MC_RC_CSI_BITSWAP(csid, ibitno);
207 209 }
208 210 SETBIT(iaddr, ibitno);
209 211 }
210 212
211 213 return (iaddr);
212 214 }
213 215
214 216
215 217 static uint32_t
216 218 iaddr_to_col(struct mcamd_hdl *hdl, const struct rct_bnkaddrmode *bamp,
217 219 const struct rct_rcbmap *rcbm, uint64_t iaddr)
218 220 {
219 221 uint32_t addr = 0;
220 222 int abitno, ibitno, bias = 0;
221 223 int nbits = bamp->bam_ncols;
222 224
223 225 /*
224 226 * Knock off a column bit if the numbers are ambiguous
225 227 */
226 228 if (bamp->bam_ambig)
227 229 nbits--;
228 230
229 231 for (abitno = 0; abitno < nbits; abitno++) {
230 232 if (abitno == MC_PC_COLADDRBIT)
231 233 bias = 1;
232 234
233 235 ibitno = rcbm->rcb_colbit[abitno + bias];
234 236
235 237 if (BITVAL(iaddr, ibitno) != 0)
236 238 SETBIT(addr, abitno);
237 239 }
238 240
239 241 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "iaddr_to_col: iaddr 0x%llx --> "
240 242 "col 0x%x\n", iaddr, addr);
241 243
242 244 return (addr);
243 245 }
244 246
245 247 /*ARGSUSED*/
246 248 static uint64_t
247 249 col_to_iaddr(struct mcamd_hdl *hdl, const struct rct_bnkaddrmode *bamp,
248 250 const struct rct_rcbmap *rcbm, uint32_t coladdr)
249 251 {
250 252 uint64_t iaddr = 0;
251 253 int abitno, ibitno, bias = 0;
252 254 int nbits = bamp->bam_ncols;
253 255
254 256 /*
255 257 * Knock off a column bit if the numbers are ambiguous
256 258 */
257 259 if (bamp->bam_ambig)
258 260 nbits--;
259 261
260 262 for (abitno = 0; abitno < nbits; abitno++) {
261 263 if (BIT(coladdr, abitno) == 0)
262 264 continue;
263 265
264 266 if (abitno == MC_PC_COLADDRBIT)
265 267 bias = 1;
266 268
267 269 ibitno = rcbm->rcb_colbit[abitno + bias];
268 270 SETBIT(iaddr, ibitno);
269 271 }
270 272
271 273 return (iaddr);
272 274 }
273 275
274 276 /*
275 277 * Extract bank bit arguments and swizzle if requested.
276 278 */
277 279 static uint32_t
278 280 iaddr_to_bank(struct mcamd_hdl *hdl, const struct rct_rcbmap *rcbm,
279 281 const struct rct_bnkswzlinfo *swzlp, uint64_t iaddr)
280 282 {
281 283 uint32_t addr = 0;
282 284 int abitno, ibitno, i;
283 285
284 286 for (abitno = 0; abitno < rcbm->rcb_nbankbits; abitno++) {
285 287 uint32_t val;
286 288
287 289 /*
288 290 * rcb_bankbit[abitno] tells us which iaddr bit number
289 291 * will form bit abitno of the bank address
290 292 */
291 293 ibitno = rcbm->rcb_bankbit[abitno];
292 294 val = BITVAL(iaddr, ibitno);
293 295
294 296 /*
295 297 * If bank swizzling is in operation then xor the bit value
296 298 * obtained above with other iaddr bits.
297 299 */
298 300 if (swzlp) {
299 301 for (i = 0; i < MC_RC_SWZLBITS; i++) {
300 302 ibitno = swzlp->bswz_rowbits[abitno][i];
301 303 val ^= BITVAL(iaddr, ibitno);
302 304 }
303 305 }
304 306
305 307 if (val)
306 308 SETBIT(addr, abitno);
307 309 }
308 310
309 311 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "iaddr_to_bank: iaddr 0x%llx --> "
310 312 "bank 0x%x\n", iaddr, addr);
311 313
312 314 return (addr);
313 315 }
314 316
315 317 /*
316 318 * bank_to_iaddr requires the iaddr reconstructed thus far with at least the
317 319 * row bits repopulated. That's because in bank swizzle mode
318 320 * the bank bits are the result of xor'ing three original iaddr bits
319 321 * together - two of which come from the row address and the third we
320 322 * can reconstruct here. Note that a zero bankaddr bit *can* result
321 323 * in a nonzero iaddr bit (unlike in row and col reconstruction).
322 324 */
323 325 /*ARGSUSED*/
324 326 static uint64_t
325 327 bank_to_iaddr(struct mcamd_hdl *hdl, const struct rct_rcbmap *rcbm,
326 328 const struct rct_bnkswzlinfo *swzlp, uint64_t partiaddr, uint32_t bankaddr)
327 329 {
328 330 uint64_t iaddr = 0;
329 331 int abitno, pibitno, i;
330 332
331 333 for (abitno = 0; abitno < rcbm->rcb_nbankbits; abitno++) {
332 334 uint32_t val = BITVAL(bankaddr, abitno);
333 335 if (swzlp) {
334 336 for (i = 0; i < MC_RC_SWZLBITS; i++) {
335 337 pibitno = swzlp->bswz_rowbits[abitno][i];
336 338 val ^= BITVAL(partiaddr, pibitno);
337 339 }
338 340 }
339 341 if (val)
340 342 SETBIT(iaddr, rcbm->rcb_bankbit[abitno]);
341 343 }
342 344
343 345 return (iaddr);
344 346 }
345 347
346 348 static int
347 349 iaddr_to_rcb(struct mcamd_hdl *hdl, uint_t csmode, struct mcprops *mcpp,
348 350 uint64_t iaddr, uint32_t *rowp, uint32_t *colp, uint32_t *bankp)
349 351 {
350 352 const struct rct_bnkaddrmode *bamp;
351 353 const struct rct_rcbmap *rcbmp;
352 354 const struct rct_bnkswzlinfo *swzlp = NULL;
353 355 struct rct_csintlv csi;
354 356
355 357 if (gettbls(hdl, csmode, mcpp, &bamp, &rcbmp,
356 358 mcpp->bnkswzl ? &swzlp : NULL, &csi,
357 359 "iaddr_to_rcb") < 0)
358 360 return (-1); /* errno already set */
359 361
360 362 *rowp = iaddr_to_row(hdl, bamp, rcbmp, &csi, iaddr);
361 363 *colp = iaddr_to_col(hdl, bamp, rcbmp, iaddr);
362 364 *bankp = iaddr_to_bank(hdl, rcbmp, swzlp, iaddr);
363 365
364 366 return (0);
365 367 }
366 368
367 369 /*
368 370 * Take a reconstructed InputAddr and undo the normalization described in
369 371 * BKDG 3.29 3.4.4 to include the base address of the MC if no node
370 372 * interleave or to insert the node interleave selection bits.
371 373 */
372 374 static int
373 375 iaddr_unnormalize(struct mcamd_hdl *hdl, struct mcprops *mcpp, uint64_t iaddr,
374 376 uint64_t *rsltp)
375 377 {
376 378 uint64_t dramaddr;
377 379 int intlvbits;
378 380
379 381 switch (mcpp->intlven) {
380 382 case 0x0:
381 383 intlvbits = 0;
382 384 break;
383 385 case 0x1:
384 386 intlvbits = 1;
385 387 break;
386 388 case 0x3:
387 389 intlvbits = 2;
388 390 break;
389 391 case 0x7:
390 392 intlvbits = 3;
391 393 break;
392 394 default:
393 395 mcamd_dprintf(hdl, MCAMD_DBG_ERR, "iaddr_unnormalize: "
394 396 "illegal IntlvEn of %d for MC 0x%p\n",
395 397 (int)mcpp->intlven, (int)mcpp->num);
396 398 return (mcamd_set_errno(hdl, EMCAMD_TREEINVALID));
397 399 }
398 400
399 401 if (intlvbits != 0) {
400 402 /*
401 403 * For a 2/4/8 way interleave iaddr was formed by excising
402 404 * 1, 2, or 3 bits 12:12, 13:12, or 14:12 from dramaddr,
403 405 * the removed bits having done their job by selecting the
404 406 * responding node. So we must move bits 35:12 of the
405 407 * reconstructed iaddr up to make a 1, 2 or 3 bit hole and
406 408 * then fill those bits with the current IntlvSel value for
407 409 * this node. The node base address must be zero if nodes
408 410 * are interleaved.
409 411 *
410 412 * Note that the DRAM controller InputAddr is still 36 bits
411 413 * 35:0 on rev F.
412 414 */
413 415 dramaddr = (BITS(iaddr, 35, 12) << intlvbits) |
414 416 (mcpp->intlvsel << 12) | BITS(iaddr, 11, 0);
415 417 } else {
416 418 dramaddr = iaddr + mcpp->base;
417 419 }
418 420
419 421 *rsltp = dramaddr;
420 422
421 423 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "iaddr_unnormalize: iaddr 0x%llx "
422 424 "intlven 0x%x intlvsel 0x%x MC base 0x%llx --> 0x%llx\n",
423 425 iaddr, (int)mcpp->intlven, (int)mcpp->intlvsel, (int)mcpp->base,
424 426 dramaddr);
425 427
426 428 return (0);
427 429 }
428 430
429 431 int
430 432 mc_pa_to_offset(struct mcamd_hdl *hdl, mcamd_node_t *mc, mcamd_node_t *cs,
431 433 uint64_t iaddr, uint64_t *offsetp)
432 434 {
433 435 mcamd_dimm_offset_un_t offset_un;
434 436 uint_t csmode;
435 437 uint32_t bankaddr, rowaddr, coladdr;
436 438 struct mcprops mcp;
437 439 struct csprops csp;
438 440
439 441 *offsetp = MCAMD_RC_INVALID_OFFSET;
440 442
441 443 if (getmcprops(hdl, mc, "mc_dimm_offset", &mcp) < 0 ||
442 444 getcsprops(hdl, cs, "mc_dimm_offset", &csp) < 0)
443 445 return (-1); /* errno already set */
444 446
445 447 csmode = MC_CS_MODE(mcp.csbnkmap_reg, csp.num);
446 448
447 449 if (iaddr_to_rcb(hdl, csmode, &mcp, iaddr, &rowaddr,
448 450 &coladdr, &bankaddr) < 0)
449 451 return (-1); /* errno already set */
450 452
451 453 offset_un.do_offset = 0;
452 454
453 455 offset_un.do_valid = 1;
454 456 offset_un.do_version = MCAMD_OFFSET_VERSION;
455 457 offset_un.do_rank = (uint32_t)csp.dimmrank;
456 458 offset_un.do_row = rowaddr;
457 459 offset_un.do_bank = bankaddr;
458 460 offset_un.do_col = coladdr;
459 461
460 462 *offsetp = offset_un.do_offset;
461 463
462 464 return (0);
463 465 }
464 466
465 467 /*
466 468 * Given an MC, DIMM and offset (dimm rank, row, col, internal bank) we
467 469 * find the corresponding chip-select for the rank and then reconstruct
468 470 * a system address. In the absence of serial number support it is possible
469 471 * that we may be asked to perform this operation on a dimm which has been
470 472 * swapped, perhaps even for a dimm of different size and number of ranks.
471 473 * This may happen if fmadm repair has not been used. There are some
472 474 * unused bits in the offset and we could guard against this a little
473 475 * by recording in those bit some of the physical characteristic of the
474 476 * original DIMM such as size, number of ranks etc.
475 477 */
476 478 int
477 479 mc_offset_to_pa(struct mcamd_hdl *hdl, mcamd_node_t *mc, mcamd_node_t *dimm,
478 480 uint64_t offset, uint64_t *pap)
479 481 {
480 482 mcamd_node_t *cs;
481 483 mcamd_dimm_offset_un_t off_un;
482 484 uint32_t rank, rowaddr, bankaddr, coladdr;
483 485 uint64_t iaddr = 0;
484 486 const struct rct_bnkaddrmode *bamp;
485 487 const struct rct_rcbmap *rcbmp;
486 488 const struct rct_bnkswzlinfo *swzlp = NULL;
487 489 struct rct_csintlv csi;
488 490 struct mcprops mcp;
489 491 struct csprops csp;
490 492 uint64_t csmode;
491 493 int maskhi_hi, maskhi_lo, masklo_hi, masklo_lo;
492 494
493 495 off_un.do_offset = offset;
494 496 rank = off_un.do_rank;
495 497 bankaddr = off_un.do_bank;
496 498 rowaddr = off_un.do_row;
497 499 coladdr = off_un.do_col;
498 500
499 501 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mc_offset_to_pa: offset 0x%llx "
500 502 "-> rank %d bank %d row 0x%x col 0x%x\n", offset,
501 503 rank, bankaddr, rowaddr, coladdr);
502 504
503 505 if (getmcprops(hdl, mc, "mc_offset_to_pa", &mcp) < 0)
504 506 return (-1); /* errno already set */
505 507
506 508 maskhi_hi = MC_CSMASKHI_HIBIT(mcp.rev);
507 509 maskhi_lo = MC_CSMASKHI_LOBIT(mcp.rev);
508 510 masklo_hi = MC_CSMASKLO_HIBIT(mcp.rev);
509 511 masklo_lo = MC_CSMASKLO_LOBIT(mcp.rev);
510 512
511 513 /*
512 514 * Find the chip-select on this dimm using the given rank.
513 515 */
514 516 for (cs = mcamd_cs_next(hdl, dimm, NULL); cs != NULL;
515 517 cs = mcamd_cs_next(hdl, dimm, cs)) {
516 518 if (getcsprops(hdl, cs, "mc_offset_to_pa", &csp) < 0)
517 519 return (-1); /* errno already set */
518 520
519 521 if (csp.dimmrank == rank)
520 522 break;
521 523 }
522 524
523 525 if (cs == NULL) {
524 526 mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mc_offset_to_pa: Current "
525 527 "dimm in this slot does not have a cs using rank %d\n",
526 528 rank);
527 529 return (mcamd_set_errno(hdl, EMCAMD_NOADDR));
528 530 }
529 531
530 532 /*
531 533 * If the cs# has been substituted by the online spare then the
532 534 * given unum is not actually contributing to the system address
533 535 * map since all accesses to it are redirected.
534 536 *
535 537 * If the cs# failed BIOS test it is not in the address map.
536 538 *
537 539 * If the cs# is the online spare cs# then it is contributing to
538 540 * the system address map only if swapped in, and the csbase etc
539 541 * parameters to use must be those of the bad cs#.
540 542 */
541 543 if (mcp.badcs != MC_INVALNUM && csp.num == mcp.badcs) {
542 544 return (mcamd_set_errno(hdl, EMCAMD_NOADDR));
543 545 } else if (csp.testfail) {
544 546 return (mcamd_set_errno(hdl, EMCAMD_NOADDR));
545 547 } else if (mcp.sparecs != MC_INVALNUM && csp.num == mcp.sparecs &&
546 548 mcp.badcs != MC_INVALNUM) {
547 549 /*
548 550 * Iterate over all cs# of this memory controller to find
549 551 * the bad one - the bad cs# need not be on the same dimm
550 552 * as the spare.
551 553 */
552 554 for (cs = mcamd_cs_next(hdl, mc, NULL); cs != NULL;
553 555 cs = mcamd_cs_next(hdl, mc, cs)) {
554 556 mcamd_prop_t csnum;
555 557
556 558 if (!mcamd_get_numprop(hdl, cs, MCAMD_PROP_NUM,
557 559 &csnum)) {
558 560 mcamd_dprintf(hdl, MCAMD_DBG_ERR,
559 561 "mcamd_offset_to_pa: csnum lookup failed "
560 562 "while looking for bad cs#");
↓ open down ↓ |
525 lines elided |
↑ open up ↑ |
561 563 return (mcamd_set_errno(hdl,
562 564 EMCAMD_TREEINVALID));
563 565 }
564 566 if (csnum == mcp.badcs)
565 567 break;
566 568 }
567 569
568 570 if (cs == NULL) {
569 571 mcamd_dprintf(hdl, MCAMD_DBG_ERR, "mcamd_offset_to_pa: "
570 572 "failed to find cs for bad cs#%d\n", mcp.badcs);
571 - return (mcamd_set_errno(hdl,
572 - EMCAMD_TREEINVALID));
573 + return (mcamd_set_errno(hdl, EMCAMD_TREEINVALID));
573 574 }
574 575
575 576 /* found bad cs - reread properties from it instead of spare */
576 577 if (getcsprops(hdl, cs, "mc_offset_to_pa", &csp) < 0)
577 578 return (-1); /* errno already set */
578 579 }
579 580
580 581 csmode = MC_CS_MODE(mcp.csbnkmap_reg, csp.num);
581 582
582 583 if (gettbls(hdl, csmode, &mcp, &bamp, &rcbmp,
583 584 mcp.bnkswzl ? &swzlp : NULL, &csi,
584 585 "mc_offset_to_pa") < 0)
585 586 return (-1); /* errno already set */
586 587
587 588 /*
588 589 * If there are umaskable DRAM InputAddr bits the add those bits
589 590 * to iaddr from the cs base address.
590 591 */
591 592 if (MC_CSMASK_UNMASKABLE(mcp.rev) != 0) {
592 593 iaddr |= iaddr_add(hdl, iaddr,
593 594 BITS(csp.base, maskhi_hi + MC_CSMASK_UNMASKABLE(mcp.rev),
594 595 maskhi_hi + 1), "unmaskable cs basehi bits");
595 596 }
596 597
597 598 /*
598 599 * basehi bits not meing masked pass straight through to the
599 600 * iaddr.
600 601 */
601 602 iaddr |= iaddr_add(hdl, iaddr,
602 603 BITS(csp.base, maskhi_hi, maskhi_lo) &
603 604 ~BITS(csp.mask, maskhi_hi, maskhi_lo),
604 605 "cs basehi bits not being masked");
605 606
606 607 /*
607 608 * if cs interleaving is active then baselo address bit are being
608 609 * masked - pass the rest through.
609 610 */
610 611 if (mcp.csintlvfctr > 1) {
611 612 iaddr |= iaddr_add(hdl, iaddr,
612 613 BITS(csp.base, masklo_hi, masklo_lo) &
613 614 ~BITS(csp.mask, masklo_hi, masklo_lo),
614 615 "cs baselo bits not being masked");
615 616 }
616 617
617 618 /*
618 619 * Reconstruct iaddr bits from known row address
619 620 */
620 621 iaddr |= iaddr_add(hdl, iaddr,
621 622 row_to_iaddr(hdl, bamp, rcbmp, &csi, rowaddr),
622 623 "add iaddr bits from row");
623 624
624 625 /*
625 626 * Reconstruct iaddr bits from known column address
626 627 */
627 628 iaddr |= iaddr_add(hdl, iaddr,
628 629 col_to_iaddr(hdl, bamp, rcbmp, coladdr),
629 630 "add iaddr bits from col");
630 631
631 632 /*
632 633 * Reconstruct iaddr bits from known internal banksel address
633 634 */
634 635 iaddr |= iaddr_add(hdl, iaddr,
635 636 bank_to_iaddr(hdl, rcbmp, swzlp, iaddr, bankaddr),
636 637 "add iaddr bits from bank");
637 638
638 639 /*
639 640 * Move iaddr up into the range for this MC and insert any
640 641 * node interleave selection bits.
641 642 */
642 643 if (iaddr_unnormalize(hdl, &mcp, iaddr, pap) < 0)
643 644 return (-1); /* errno already set */
644 645
645 646 return (0);
646 647 }
647 648
648 649 int
649 650 mcamd_cs_size(struct mcamd_hdl *hdl, mcamd_node_t *mc, int csnum, size_t *szp)
650 651 {
651 652 uint_t csmode;
652 653 struct mcprops mcp;
653 654 const struct rct_bnkaddrmode *bamp;
654 655
655 656 if (getmcprops(hdl, mc, "mcamd_cs_size", &mcp) < 0)
656 657 return (-1); /* errno already set */
657 658
658 659 csmode = MC_CS_MODE(mcp.csbnkmap_reg, csnum);
659 660
660 661 if (gettbls(hdl, csmode, &mcp, &bamp, NULL, NULL, NULL,
661 662 "mcamd_cs_size") < 0)
662 663 return (-1); /* errno already set */
663 664
664 665 *szp = MC_CS_SIZE(bamp, mcp.width);
665 666
666 667 return (0);
667 668 }
↓ open down ↓ |
85 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX