1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * This file contains firmware log routines.
27 */
28
29 #include <sys/scsi/adapters/pmcs/pmcs.h>
30 #include <sys/scsi/adapters/pmcs/pmcs_fwlog.h>
31
32 static int pmcs_dump_ioqs(pmcs_hw_t *, caddr_t, uint32_t);
33 static int pmcs_dump_spc_ver(pmcs_hw_t *, caddr_t, uint32_t);
34 static int pmcs_dump_mpi_table(pmcs_hw_t *, caddr_t, uint32_t);
35 static int pmcs_dump_gsm_conf(pmcs_hw_t *, caddr_t, uint32_t);
36 static int pmcs_dump_pcie_conf(pmcs_hw_t *, caddr_t, uint32_t);
37 static uint32_t pmcs_get_axil(pmcs_hw_t *);
38 static boolean_t pmcs_shift_axil(pmcs_hw_t *, uint32_t);
39 static void pmcs_restore_axil(pmcs_hw_t *, uint32_t);
40 static int pmcs_dump_gsm(pmcs_hw_t *, caddr_t, uint32_t);
41 static int pmcs_dump_gsm_addiregs(pmcs_hw_t *, caddr_t, uint32_t);
42 static int pmcs_dump_hsst_sregs(pmcs_hw_t *, caddr_t, uint32_t);
43 static int pmcs_dump_sspa_sregs(pmcs_hw_t *, caddr_t, uint32_t);
44 static int pmcs_dump_fwlog(pmcs_hw_t *, caddr_t, uint32_t);
45 static void pmcs_write_fwlog(pmcs_hw_t *, pmcs_fw_event_hdr_t *);
46
47 /*
48 * Dump internal registers. Used after a firmware crash.
49 * Here dump various registers for firmware forensics,
50 * including MPI, GSM configuration, firmware log, IO Queues etc.
51 */
52 void
pmcs_register_dump_int(pmcs_hw_t * pwp)53 pmcs_register_dump_int(pmcs_hw_t *pwp)
54 {
55 int n = 0;
56 uint32_t size_left = 0;
57 uint32_t scratch = 0;
58 uint8_t slice = 0;
59 caddr_t buf = NULL;
60
61 ASSERT(mutex_owned(&pwp->lock));
62
63 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
64 "pmcs%d: Internal register dump", ddi_get_instance(pwp->dip));
65
66 if (pwp->regdumpp == NULL) {
67 pwp->regdumpp =
68 kmem_zalloc(PMCS_REG_DUMP_SIZE, KM_NOSLEEP);
69 if (pwp->regdumpp == NULL) {
70 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
71 "%s: register dump memory not allocated", __func__);
72 return;
73 }
74 }
75 buf = pwp->regdumpp;
76 size_left = PMCS_REG_DUMP_SIZE - 1;
77
78 n = pmcs_dump_spc_ver(pwp, buf, size_left);
79 ASSERT(size_left >= n);
80 buf += n; size_left -= n;
81 n = pmcs_dump_gsm_conf(pwp, buf, size_left);
82 ASSERT(size_left >= n);
83 buf += n; size_left -= n;
84 n = pmcs_dump_pcie_conf(pwp, buf, size_left);
85 ASSERT(size_left >= n);
86 buf += n; size_left -= n;
87 n = pmcs_dump_mpi_table(pwp, buf, size_left);
88 ASSERT(size_left >= n);
89 buf += n; size_left -= n;
90 n = pmcs_dump_ioqs(pwp, buf, size_left);
91 ASSERT(size_left >= n);
92 buf += n; size_left -= n;
93
94 if (pwp->state == STATE_DEAD) {
95 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
96 "%s: HBA dead, skipping AAP1/IOP registers and event logs",
97 __func__);
98 goto skip_logs;
99 }
100
101 scratch = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1);
102 if ((scratch & PMCS_MSGU_AAP_STATE_MASK) == PMCS_MSGU_AAP_STATE_ERROR) {
103 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
104 "%s: MSGU in error state, skipping AAP1/IOP registers and "
105 "event logs", __func__);
106 goto skip_logs;
107 }
108
109 mutex_exit(&pwp->lock);
110 slice = (PMCS_REGISTER_DUMP_FLASH_SIZE / PMCS_FLASH_CHUNK_SIZE);
111 n = snprintf(buf, size_left, "\nDump AAP1 register: \n"
112 "-----------------\n");
113 ASSERT(size_left >= n);
114 buf += n; size_left -= n;
115 for (uint8_t j = 0; j < slice; j++) {
116 n = pmcs_get_nvmd(pwp, PMCS_NVMD_REG_DUMP,
117 PMCIN_NVMD_AAP1, (j * PMCS_FLASH_CHUNK_SIZE),
118 buf, size_left);
119 if (n == PMCS_FLASH_CHUNK_SIZE) {
120 ASSERT(size_left >= n);
121 buf += n; size_left -= n;
122 } else if ((n < PMCS_FLASH_CHUNK_SIZE) && (n > 0)) {
123 ASSERT(size_left >= n);
124 buf += n; size_left -= n;
125 break;
126 } else if (n == 0) {
127 n = snprintf(buf, size_left, "AAP1: Content of "
128 "register dump on flash is NULL\n");
129 ASSERT(size_left >= n);
130 buf += n; size_left -= n;
131 break;
132 } else {
133 n = snprintf(buf, size_left,
134 "AAP1: Unable to obtain internal register dump\n");
135 ASSERT(size_left >= n);
136 buf += n; size_left -= n;
137 break;
138 }
139
140 }
141
142 n = snprintf(buf, size_left, "\nDump IOP register: \n"
143 "-----------------\n");
144 ASSERT(size_left >= n);
145 buf += n; size_left -= n;
146 for (uint8_t j = 0; j < slice; j++) {
147 n = pmcs_get_nvmd(pwp, PMCS_NVMD_REG_DUMP,
148 PMCIN_NVMD_IOP, (j * PMCS_FLASH_CHUNK_SIZE),
149 buf, size_left);
150 if (n == PMCS_FLASH_CHUNK_SIZE) {
151 ASSERT(size_left >= n);
152 buf += n; size_left -= n;
153 } else if ((n < PMCS_FLASH_CHUNK_SIZE) && (n > 0)) {
154 ASSERT(size_left >= n);
155 buf += n; size_left -= n;
156 break;
157 } else if (n == 0) {
158 n = snprintf(buf, size_left,
159 "IOP: Content of internal register dump is NULL\n");
160 ASSERT(size_left >= n);
161 buf += n; size_left -= n;
162 break;
163 } else {
164 n = snprintf(buf, size_left,
165 "IOP: Unable to obtain internal register dump\n");
166 ASSERT(size_left >= n);
167 buf += n; size_left -= n;
168 break;
169 }
170
171 }
172
173 n = snprintf(buf, size_left, "\nDump AAP1 event log: \n"
174 "-----------------\n");
175 ASSERT(size_left >= n);
176 buf += n; size_left -= n;
177 for (uint8_t j = 0; j < slice; j++) {
178 n = pmcs_get_nvmd(pwp, PMCS_NVMD_EVENT_LOG,
179 PMCIN_NVMD_AAP1, (j * PMCS_FLASH_CHUNK_SIZE),
180 buf, size_left);
181 if (n > 0) {
182 ASSERT(size_left >= n);
183 buf += n; size_left -= n;
184 } else {
185 n = snprintf(buf, size_left,
186 "AAP1: Unable to obtain event log on flash\n");
187 ASSERT(size_left >= n);
188 buf += n; size_left -= n;
189 break;
190 }
191 }
192
193 n = snprintf(buf, size_left, "\nDump IOP event log: \n"
194 "-----------------\n");
195 ASSERT(size_left >= n);
196 buf += n; size_left -= n;
197 for (uint8_t j = 0; j < slice; j++) {
198 n = pmcs_get_nvmd(pwp, PMCS_NVMD_EVENT_LOG,
199 PMCIN_NVMD_IOP, (j * PMCS_FLASH_CHUNK_SIZE),
200 buf, size_left);
201 if (n > 0) {
202 ASSERT(size_left >= n);
203 buf += n; size_left -= n;
204 } else {
205 n = snprintf(buf, size_left,
206 "IOP: Unable to obtain event log dump\n");
207 ASSERT(size_left >= n);
208 buf += n; size_left -= n;
209 break;
210 }
211 }
212 mutex_enter(&pwp->lock);
213
214 skip_logs:
215 n = pmcs_dump_gsm_addiregs(pwp, buf, size_left);
216 ASSERT(size_left >= n);
217 buf += n; size_left -= n;
218
219 n = pmcs_dump_hsst_sregs(pwp, buf, size_left);
220 ASSERT(size_left >= n);
221 buf += n; size_left -= n;
222
223 n = pmcs_dump_sspa_sregs(pwp, buf, size_left);
224 ASSERT(size_left >= n);
225 buf += n; size_left -= n;
226 n = snprintf(buf, size_left, "\nDump firmware log: \n"
227 "-----------------\n");
228 ASSERT(size_left >= n);
229 buf += n; size_left -= n;
230
231 n = pmcs_dump_fwlog(pwp, buf, size_left);
232 ASSERT(size_left >= n);
233 buf += n; size_left -= n;
234
235 n = pmcs_dump_gsm(pwp, buf, size_left);
236 ASSERT(size_left >= n);
237 buf += n; size_left -= n;
238
239 n = snprintf(buf, size_left, "-----------------\n"
240 "\n------------ Dump internal registers end -------------\n");
241 ASSERT(size_left >= n);
242 buf += n; size_left -= n;
243 }
244
245 static int
pmcs_dump_fwlog(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)246 pmcs_dump_fwlog(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
247 {
248 pmcs_fw_event_hdr_t *evl_hdr;
249 int n = 0, retries = 0;
250 uint32_t evlog_latest_idx;
251 boolean_t log_is_current = B_FALSE;
252
253 if (pwp->fwlogp == NULL) {
254 n = snprintf(buf, size_left, "\nFirmware logging "
255 "not enabled\n");
256 return (n);
257 }
258
259 /*
260 * First, check to make sure all entries have been DMAed to the
261 * log buffer.
262 *
263 * We'll wait the required 50ms, but if the latest entry keeps
264 * changing, we'll only retry twice
265 */
266 evl_hdr = (pmcs_fw_event_hdr_t *)pwp->fwlogp;
267 evlog_latest_idx = evl_hdr->fw_el_latest_idx;
268
269 while ((log_is_current == B_FALSE) && (retries < 3)) {
270 drv_usecwait(50 * 1000);
271 if (evl_hdr->fw_el_latest_idx == evlog_latest_idx) {
272 log_is_current = B_TRUE;
273 } else {
274 ++retries;
275 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
276 "%s: event log is still being updated... waiting",
277 __func__);
278 evlog_latest_idx = evl_hdr->fw_el_latest_idx;
279 }
280 }
281
282 n = pmcs_dump_binary(pwp, pwp->fwlogp, 0, (PMCS_FWLOG_SIZE >> 2),
283 buf, size_left);
284
285 return (n);
286 }
287
288 /*
289 * Dump Inbound and Outbound Queues.
290 */
291 static int
pmcs_dump_ioqs(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)292 pmcs_dump_ioqs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
293 {
294 uint8_t i = 0, k = 0;
295 uint32_t j = 0, depth = 0;
296 int n = 0;
297 uint32_t *ptr = NULL;
298
299 n += snprintf(&buf[n], (size_left - n), "\nDump I/O queues: \n"
300 "-----------------\n");
301 for (i = 0; i < PMCS_NIQ; i++) {
302 depth = PMCS_IQDX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i)));
303 n += snprintf(&buf[n], (size_left - n),
304 "IQ[%d] Details:\n-----------------\n", i);
305 n += snprintf(&buf[n], (size_left - n),
306 " depth = 0x%04x\n", depth);
307 n += snprintf(&buf[n], (size_left - n),
308 " latest ci = 0x%02x\n", pmcs_rd_iqci(pwp, i));
309 n += snprintf(&buf[n], (size_left - n),
310 " latest pi = 0x%02x\n", pmcs_rd_iqpi(pwp, i));
311 for (j = 0; j < depth; j++) {
312 n += snprintf(&buf[n], (size_left - n),
313 "IOMB[%d]:\n", j);
314 ptr = &pwp->iqp[i][(j * PMCS_QENTRY_SIZE) >> 2];
315 for (k = 0; k < (PMCS_QENTRY_SIZE / sizeof (uint32_t));
316 k += 8) {
317 n += snprintf(&buf[n], (size_left - n),
318 "0x%08x 0x%08x 0x%08x 0x%08x "
319 "0x%08x 0x%08x 0x%08x 0x%08x\n",
320 LE_32(ptr[k]), LE_32(ptr[k+1]),
321 LE_32(ptr[k+2]), LE_32(ptr[k+3]),
322 LE_32(ptr[k+4]), LE_32(ptr[k+5]),
323 LE_32(ptr[k+6]), LE_32(ptr[k+7]));
324 }
325 }
326 }
327 for (i = 0; i < PMCS_NOQ; i++) {
328 depth = PMCS_OQDX(pmcs_rd_oqc_tbl(pwp, PMCS_OQC_PARMX(i)));
329 n += snprintf(&buf[n], (size_left - n),
330 "OQ[%d] Details:\n", i);
331 n += snprintf(&buf[n], (size_left - n),
332 " depth = 0x%04x\n", depth);
333 n += snprintf(&buf[n], (size_left - n),
334 " latest ci = 0x%02x\n", pmcs_rd_oqci(pwp, i));
335 n += snprintf(&buf[n], (size_left - n),
336 " latest pi = 0x%02x\n", pmcs_rd_oqpi(pwp, i));
337 for (j = 0; j < depth; j++) {
338 n += snprintf(&buf[n], (size_left - n),
339 "IOMB[%d]:\n", j);
340 ptr = &pwp->oqp[i][(j * PMCS_QENTRY_SIZE) >> 2];
341 for (k = 0; k < (PMCS_QENTRY_SIZE / sizeof (uint32_t));
342 k += 8) {
343 n += snprintf(&buf[n], (size_left - n),
344 "0x%08x 0x%08x 0x%08x 0x%08x "
345 "0x%08x 0x%08x 0x%08x 0x%08x\n",
346 LE_32(ptr[k]), LE_32(ptr[k+1]),
347 LE_32(ptr[k+2]), LE_32(ptr[k+3]),
348 LE_32(ptr[k+4]), LE_32(ptr[k+5]),
349 LE_32(ptr[k+6]), LE_32(ptr[k+7]));
350 }
351 }
352
353 }
354 n += snprintf(&buf[n], (size_left - n), "-----------------\n"
355 "Dump I/O queues end \n");
356 return (n);
357 }
358
359 /*
360 * Dump SPC Version.
361 */
362 static int
pmcs_dump_spc_ver(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)363 pmcs_dump_spc_ver(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
364 {
365 int n = 0;
366
367 n += snprintf(&buf[n], (size_left - n), "\nDump SPC version: \n"
368 "-----------------\n");
369 n += snprintf(&buf[n], (size_left - n), "Firmware Release Type = "
370 "0x%02x\n", PMCS_FW_TYPE(pwp));
371 n += snprintf(&buf[n], (size_left - n), " Sub-Minor Release "
372 "Number = 0x%02x\n", PMCS_FW_MICRO(pwp));
373 n += snprintf(&buf[n], (size_left - n), " Minor Release "
374 "Number = 0x%02x\n", PMCS_FW_MINOR(pwp));
375 n += snprintf(&buf[n], (size_left - n), " Major Release "
376 "Number = 0x%02x\n", PMCS_FW_MAJOR(pwp));
377 n += snprintf(&buf[n], (size_left - n), "SPC DeviceID = 0x%04x\n",
378 pmcs_rd_topunit(pwp, PMCS_SPC_DEVICE_ID));
379 n += snprintf(&buf[n], (size_left - n), "SPC Device Revision = "
380 "0x%08x\n", pmcs_rd_topunit(pwp, PMCS_DEVICE_REVISION));
381 n += snprintf(&buf[n], (size_left - n), "SPC BootStrap Register = "
382 "0x%08x\n", pmcs_rd_topunit(pwp, PMCS_SPC_BOOT_STRAP));
383 n += snprintf(&buf[n], (size_left - n), "SPC Reset Register = 0x%08x\n",
384 pmcs_rd_topunit(pwp, PMCS_SPC_RESET));
385 n += snprintf(&buf[n], (size_left - n), "-----------------\n"
386 "Dump SPC version end \n");
387 return (n);
388 }
389
390 /*
391 * Dump MPI Table.
392 */
393 static int
pmcs_dump_mpi_table(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)394 pmcs_dump_mpi_table(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
395 {
396 int n = 0;
397
398 n += snprintf(&buf[n], (size_left - n), "\nDump MSGU registers: \n"
399 "-----------------\n");
400 n += snprintf(&buf[n], (size_left - n), "inb_doorbell = 0x%08x\n",
401 pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB));
402 n += snprintf(&buf[n], (size_left - n), "inb_doorbell_clear = 0x%08x"
403 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB_CLEAR));
404 n += snprintf(&buf[n], (size_left - n), "outb_doorbell = 0x%08x"
405 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB));
406 n += snprintf(&buf[n], (size_left - n), "outb_doorbell_clear = 0x%08x"
407 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR));
408 n += snprintf(&buf[n], (size_left - n), "scratch_pad0 = 0x%08x"
409 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH0));
410 n += snprintf(&buf[n], (size_left - n), "scratch_pad1 = 0x%08x"
411 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1));
412 n += snprintf(&buf[n], (size_left - n), "scratch_pad2 = 0x%08x"
413 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2));
414 n += snprintf(&buf[n], (size_left - n), "scratch_pad3 = 0x%08x"
415 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH3));
416 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad0 = 0x%08x"
417 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH0));
418 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad1 = 0x%08x"
419 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH1));
420 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad2 = 0x%08x"
421 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH2));
422 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad3 = 0x%08x"
423 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH3));
424 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad4 = 0x%08x"
425 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH4));
426 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad5 = 0x%08x"
427 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH5));
428 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad6 = 0x%08x"
429 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH6));
430 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad7 = 0x%08x"
431 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH7));
432 n += snprintf(&buf[n], (size_left - n), "outb_doorbell_mask = 0x%08x"
433 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_MASK));
434
435 n += snprintf(&buf[n], (size_left - n), "MPI Configuration Table: \n"
436 "-----------------\n");
437 n += snprintf(&buf[n], (size_left - n), "ASCII Signature = 0x%08x\n",
438 pmcs_rd_mpi_tbl(pwp, PMCS_MPI_AS));
439 n += snprintf(&buf[n], (size_left - n), "Firmware Release Type = "
440 "0x%08x\n", PMCS_FW_TYPE(pwp));
441 n += snprintf(&buf[n], (size_left - n), "Firmware Release Variant = "
442 "0x%08x\n", PMCS_FW_VARIANT(pwp));
443 n += snprintf(&buf[n], (size_left - n), "Firmware Sub-Minor Release "
444 "Number = 0x%08x\n", PMCS_FW_MICRO(pwp));
445 n += snprintf(&buf[n], (size_left - n), "Firmware Minor Release "
446 "Number = 0x%08x\n", PMCS_FW_MINOR(pwp));
447 n += snprintf(&buf[n], (size_left - n), "Firmware Major Release "
448 "Number = 0x%08x\n", PMCS_FW_MAJOR(pwp));
449 n += snprintf(&buf[n], (size_left - n), "Maximum Outstanding I/Os "
450 "supported = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MOIO));
451 n += snprintf(&buf[n], (size_left - n), "Maximum Scatter-Gather List "
452 "Elements = 0x%08x\n",
453 PMCS_MSGL(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO0)));
454 n += snprintf(&buf[n], (size_left - n), "Maximum number of devices "
455 "connected to the SPC = 0x%08x\n",
456 PMCS_MD(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO0)));
457 n += snprintf(&buf[n], (size_left - n), "Maximum Number of IQs "
458 "supported = 0x%08x\n",
459 PMCS_MNIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
460 n += snprintf(&buf[n], (size_left - n), "Maximum Number of OQs "
461 "supported = 0x%08x\n",
462 PMCS_MNOQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
463 n += snprintf(&buf[n], (size_left - n), "High Priority Queue supported"
464 " = 0x%08x\n", PMCS_HPIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
465 n += snprintf(&buf[n], (size_left - n), "Interrupt Coalescing supported"
466 " = 0x%08x\n", PMCS_ICS(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
467 n += snprintf(&buf[n], (size_left - n), "Number of Phys = "
468 "0x%08x\n", PMCS_NPHY(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
469 n += snprintf(&buf[n], (size_left - n), "SAS Revision Specification = "
470 "0x%08x\n", PMCS_SASREV(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
471 n += snprintf(&buf[n], (size_left - n), "General Status Table Offset = "
472 "0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_GSTO));
473 n += snprintf(&buf[n], (size_left - n), "Inbound Queue Configuration "
474 "Table Offset = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IQCTO));
475 n += snprintf(&buf[n], (size_left - n), "Outbound Queue Configuration "
476 "Table Offset = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_OQCTO));
477 n += snprintf(&buf[n], (size_left - n), "Inbound Queue Normal/High "
478 "Priority Processing Depth = 0x%02x 0x%02x\n",
479 (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) & IQ_NORMAL_PRI_DEPTH_MASK),
480 ((pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) &
481 IQ_HIPRI_PRI_DEPTH_MASK) >> IQ_HIPRI_PRI_DEPTH_SHIFT));
482 n += snprintf(&buf[n], (size_left - n), "General Event Notification "
483 "Queue = 0x%02x\n", (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) &
484 GENERAL_EVENT_OQ_MASK) >> GENERAL_EVENT_OQ_SHIFT);
485 n += snprintf(&buf[n], (size_left - n), "Device Handle Removed "
486 "Notification Queue = 0x%02x\n",
487 (uint32_t)(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) &
488 DEVICE_HANDLE_REMOVED_MASK) >> DEVICE_HANDLE_REMOVED_SHIFT);
489 for (uint8_t i = 0; i < pwp->nphy; i++) {
490 uint32_t woff = i / 4;
491 uint32_t shf = (i % 4) * 8;
492 n += snprintf(&buf[n], (size_left - n), "SAS HW Event "
493 "Notification Queue - PHY ID %d = 0x%02x\n", i,
494 (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_EVQS + (woff << 2)) >> shf)
495 & 0xff);
496 }
497 for (uint8_t i = 0; i < pwp->nphy; i++) {
498 uint32_t woff = i / 4;
499 uint32_t shf = (i % 4) * 8;
500 n += snprintf(&buf[n], (size_left - n), "SATA NCQ Error "
501 "Event Notification Queue - PHY ID %d = 0x%02x\n", i,
502 (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_SNCQ + (woff << 2)) >> shf)
503 & 0xff);
504 }
505 for (uint8_t i = 0; i < pwp->nphy; i++) {
506 uint32_t woff = i / 4;
507 uint32_t shf = (i % 4) * 8;
508 n += snprintf(&buf[n], (size_left - n), "I_T Nexus Target "
509 "Event Notification Queue - PHY ID %d = 0x%02x\n", i,
510 (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IT_NTENQ +
511 (woff << 2)) >> shf) & 0xff);
512 }
513 for (uint8_t i = 0; i < pwp->nphy; i++) {
514 uint32_t woff = i / 4;
515 uint32_t shf = (i % 4) * 8;
516 n += snprintf(&buf[n], (size_left - n), "SSP Target "
517 "Event Notification Queue - PHY ID %d = 0x%02x\n", i,
518 (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_SSP_TENQ +
519 (woff << 2)) >> shf) & 0xff);
520 }
521
522 n += snprintf(&buf[n], (size_left - n), "I/O Abort Delay = 0x%04x\n",
523 pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IOABTDLY) & 0xffff);
524 n += snprintf(&buf[n], (size_left - n),
525 "Customization Setting = 0x%08x\n",
526 pmcs_rd_mpi_tbl(pwp, PMCS_MPI_CUSTSET));
527 n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Address "
528 "Higher = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBAH));
529 n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Address "
530 "Lower = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBAL));
531 n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Size "
532 "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBS));
533 n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Severity "
534 "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELSEV));
535 n += snprintf(&buf[n], (size_left - n), "IOP Event Log Buffer Address "
536 "Higher = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELBAH));
537 n += snprintf(&buf[n], (size_left - n), "IOP Event Log Buffer Address "
538 "Lower = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELBAL));
539 n += snprintf(&buf[n], (size_left - n), "IOP Event Log Buffer Size "
540 "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELBS));
541 n += snprintf(&buf[n], (size_left - n), "IOP Event Log Severity "
542 "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELSEV));
543 n += snprintf(&buf[n], (size_left - n), "Fatal Error Interrupt "
544 "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_FERR));
545 n += snprintf(&buf[n], (size_left - n),
546 "Fatal Error Register Dump Offset "
547 "For MSGU = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDOMSGU));
548 n += snprintf(&buf[n], (size_left - n),
549 "Fatal Error Register Dump Length "
550 "For MSGU = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDLMSGU));
551 n += snprintf(&buf[n], (size_left - n),
552 "Fatal Error Register Dump Offset "
553 "For IOP = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDOIOP));
554 n += snprintf(&buf[n], (size_left - n),
555 "Fatal Error Register Dump Length "
556 "For IOP = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDLIOP));
557
558 n += snprintf(&buf[n], (size_left - n), "Dump GS Table: \n"
559 "-----------------\n");
560 n += snprintf(&buf[n], (size_left - n), "GST MPI State: 0x%08x\n",
561 pmcs_rd_gst_tbl(pwp, PMCS_GST_BASE));
562 n += snprintf(&buf[n], (size_left - n), "Inbound Queue Freeze State 0 "
563 "= 0x%08x\n", pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ0));
564 n += snprintf(&buf[n], (size_left - n), "Inbound Queue Freeze State 1 "
565 "= 0x%08x\n", pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ1));
566 n += snprintf(&buf[n], (size_left - n), "MSGU Tick Count = 0x%08x \n",
567 pmcs_rd_gst_tbl(pwp, PMCS_GST_MSGU_TICK));
568 n += snprintf(&buf[n], (size_left - n), "IOP Tick Count = 0x%08x\n",
569 pmcs_rd_gst_tbl(pwp, PMCS_GST_IOP_TICK));
570 for (uint8_t i = 0; i < pwp->nphy; i++) {
571 n += snprintf(&buf[n], (size_left - n), " Phy %d state = "
572 "0x%08x\n", i, pmcs_rd_gst_tbl(pwp, PMCS_GST_PHY_INFO(i)));
573 }
574 for (uint8_t i = 0; i < pwp->nphy; i++) {
575 n += snprintf(&buf[n], (size_left - n), " Recoverable Error "
576 "Information %d = 0x%08x\n", i,
577 pmcs_rd_gst_tbl(pwp, PMCS_GST_RERR_INFO(i)));
578 }
579
580 n += snprintf(&buf[n], (size_left - n), "Dump IQCT Table\n"
581 "-----------------\n");
582 for (uint8_t i = 0; i < PMCS_NIQ; i++) {
583 n += snprintf(&buf[n], (size_left - n), "Inbound Queue "
584 "Configuration Table - [%d]:\n", i);
585 n += snprintf(&buf[n], (size_left - n), " Inbound Queue "
586 "Depth = 0x%08x\n",
587 PMCS_IQDX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i))));
588 n += snprintf(&buf[n], (size_left - n), " Inbound Queue "
589 "Element Size and Priority = 0x%08x 0x%08x\n",
590 PMCS_IQESX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i))),
591 PMCS_IQPX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i))));
592 n += snprintf(&buf[n], (size_left - n), " Inbound Queue "
593 "Base Address High = 0x%08x\n",
594 pmcs_rd_iqc_tbl(pwp, PMCS_IQBAHX(i)));
595 n += snprintf(&buf[n], (size_left - n), " Inbound Queue "
596 "Base Address Low = 0x%08x\n",
597 pmcs_rd_iqc_tbl(pwp, PMCS_IQBALX(i)));
598 n += snprintf(&buf[n], (size_left - n), " Inbound Queue "
599 "Consumer Index Base Address High = 0x%08x\n",
600 pmcs_rd_iqc_tbl(pwp, PMCS_IQCIBAHX(i)));
601 n += snprintf(&buf[n], (size_left - n), " Inbound Queue "
602 "Consumer Index Base Address Low = 0x%08x\n",
603 pmcs_rd_iqc_tbl(pwp, PMCS_IQCIBALX(i)));
604 n += snprintf(&buf[n], (size_left - n), " Inbound Queue "
605 "Producer Index PCI BAR = 0x%08x\n",
606 pmcs_rd_iqc_tbl(pwp, PMCS_IQPIBARX(i)));
607 n += snprintf(&buf[n], (size_left - n), " Inbound Queue "
608 "Producer Index PCI BAR offset = 0x%08x\n",
609 pmcs_rd_iqc_tbl(pwp, PMCS_IQPIOFFX(i)));
610 }
611
612 n += snprintf(&buf[n], (size_left - n), "Dump OQCT Table: \n"
613 "-----------------\n");
614 for (uint8_t i = 0; i < PMCS_NOQ; i++) {
615 n += snprintf(&buf[n], (size_left - n), "Outbound Queue "
616 "Configuration Table - [%d]:\n", i);
617 n += snprintf(&buf[n], (size_left - n), " Outbound Queue "
618 "Depth = 0x%08x\n",
619 PMCS_OQDX(pmcs_rd_oqc_tbl(pwp, PMCS_OQC_PARMX(i))));
620 n += snprintf(&buf[n], (size_left - n), " Outbound Queue "
621 "Element Size = 0x%08x\n",
622 PMCS_OQESX(pmcs_rd_oqc_tbl(pwp, PMCS_OQC_PARMX(i))));
623 n += snprintf(&buf[n], (size_left - n), " Outbound Queue "
624 "Base Address High = 0x%08x\n",
625 pmcs_rd_oqc_tbl(pwp, PMCS_OQBAHX(i)));
626 n += snprintf(&buf[n], (size_left - n), " Outbound Queue "
627 "Base Address Low = 0x%08x\n",
628 pmcs_rd_oqc_tbl(pwp, PMCS_OQBALX(i)));
629 n += snprintf(&buf[n], (size_left - n), " Outbound Queue "
630 "Producer Index Base Address High = 0x%08x\n",
631 pmcs_rd_oqc_tbl(pwp, PMCS_OQPIBAHX(i)));
632 n += snprintf(&buf[n], (size_left - n), " Outbound Queue "
633 "Producer Index Base Address Low = 0x%08x\n",
634 pmcs_rd_oqc_tbl(pwp, PMCS_OQPIBALX(i)));
635 n += snprintf(&buf[n], (size_left - n), " Outbound Queue "
636 "Consumer Index PCI BAR = 0x%08x\n",
637 pmcs_rd_oqc_tbl(pwp, PMCS_OQCIBARX(i)));
638 n += snprintf(&buf[n], (size_left - n), " Outbound Queue "
639 "Consumer Index PCI BAR offset = 0x%08x\n",
640 pmcs_rd_oqc_tbl(pwp, PMCS_OQCIOFFX(i)));
641
642 n += snprintf(&buf[n], (size_left - n), " Outbound Queue "
643 "Interrupt Coalescing Timeout = 0x%08x\n",
644 PMCS_OQICT(pmcs_rd_oqc_tbl(pwp, PMCS_OQIPARM(i))));
645 n += snprintf(&buf[n], (size_left - n), " Outbound Queue "
646 "Interrupt Coalescing Count = 0x%08x\n",
647 PMCS_OQICC(pmcs_rd_oqc_tbl(pwp, PMCS_OQIPARM(i))));
648 n += snprintf(&buf[n], (size_left - n), " Outbound Queue "
649 "Interrupt Vector = 0x%08x\n",
650 PMCS_OQIV(pmcs_rd_oqc_tbl(pwp, PMCS_OQIPARM(i))));
651 n += snprintf(&buf[n], (size_left - n), " Outbound Queue "
652 "Dynamic Interrupt Coalescing Timeout = 0x%08x\n",
653 pmcs_rd_oqc_tbl(pwp, PMCS_OQDICX(i)));
654
655 }
656 n += snprintf(&buf[n], (size_left - n), "-----------------\n"
657 "Dump MPI Table end\n");
658 return (n);
659 }
660
661 /*ARGSUSED*/
662 int
pmcs_dump_binary(pmcs_hw_t * pwp,uint32_t * addr,uint32_t off,uint32_t words_to_read,caddr_t buf,uint32_t size_left)663 pmcs_dump_binary(pmcs_hw_t *pwp, uint32_t *addr, uint32_t off,
664 uint32_t words_to_read, caddr_t buf, uint32_t size_left)
665 {
666 uint32_t i;
667 int n = 0;
668 char c = ' ';
669
670 for (i = 0, n = 0; i < words_to_read; i++) {
671 if ((i & 7) == 0) {
672 n += snprintf(&buf[n], (size_left - n),
673 "%08x: ", (i << 2) + off);
674 }
675 if ((i + 1) & 7) {
676 c = ' ';
677 } else {
678 c = '\n';
679 }
680 n += snprintf(&buf[n], (size_left - n), "%08x%c", addr[i], c);
681 }
682 return (n);
683 }
684
685 /*
686 * Dump Global Shared Memory Configuration Registers
687 */
688 static int
pmcs_dump_gsm_conf(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)689 pmcs_dump_gsm_conf(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
690 {
691 int n = 0;
692
693 n += snprintf(&buf[n], (size_left - n), "\nDump GSM configuration "
694 "registers: \n -----------------\n");
695 n += snprintf(&buf[n], (size_left - n), "RB6 Access Register = "
696 "0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, RB6_ACCESS));
697 n += snprintf(&buf[n], (size_left - n), "CFG and RST = 0x%08x\n",
698 pmcs_rd_gsm_reg(pwp, 0, GSM_CFG_AND_RESET));
699 n += snprintf(&buf[n], (size_left - n), "RAM ECC ERR INDICATOR= "
700 "0x%08x\n", pmcs_rd_gsm_reg(pwp, 0,
701 RAM_ECC_DOUBLE_ERROR_INDICATOR));
702 n += snprintf(&buf[n], (size_left - n), "READ ADR PARITY CHK EN = "
703 "0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, READ_ADR_PARITY_CHK_EN));
704 n += snprintf(&buf[n], (size_left - n), "WRITE ADR PARITY CHK EN = "
705 "0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, WRITE_ADR_PARITY_CHK_EN));
706 n += snprintf(&buf[n], (size_left - n), "WRITE DATA PARITY CHK EN= "
707 "0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, WRITE_DATA_PARITY_CHK_EN));
708 n += snprintf(&buf[n], (size_left - n),
709 "READ ADR PARITY ERROR INDICATOR = 0x%08x\n",
710 pmcs_rd_gsm_reg(pwp, 0, READ_ADR_PARITY_ERROR_INDICATOR));
711 n += snprintf(&buf[n], (size_left - n),
712 "WRITE ADR PARITY ERROR INDICATOR = 0x%08x\n",
713 pmcs_rd_gsm_reg(pwp, 0, WRITE_ADR_PARITY_ERROR_INDICATOR));
714 n += snprintf(&buf[n], (size_left - n),
715 "WRITE DATA PARITY ERROR INDICATOR = 0x%08x\n",
716 pmcs_rd_gsm_reg(pwp, 0, WRITE_DATA_PARITY_ERROR_INDICATOR));
717 n += snprintf(&buf[n], (size_left - n), "NMI Enable VPE0 IOP Register"
718 " = 0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, NMI_EN_VPE0_IOP));
719 n += snprintf(&buf[n], (size_left - n), "NMI Enable VPE0 AAP1 Register"
720 " = 0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, NMI_EN_VPE0_AAP1));
721 n += snprintf(&buf[n], (size_left - n), "-----------------\n"
722 "Dump GSM configuration registers end \n");
723 return (n);
724 }
725
726 /*
727 * Dump PCIe Configuration Registers.
728 */
729 static int
pmcs_dump_pcie_conf(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)730 pmcs_dump_pcie_conf(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
731 {
732 int n = 0;
733 uint32_t i = 0;
734
735 n += snprintf(&buf[n], (size_left - n), "\nDump PCIe configuration "
736 "registers: \n -----------------\n");
737 n += snprintf(&buf[n], (size_left - n), "VENID = 0x%04x\n",
738 pci_config_get16(pwp->pci_acc_handle, PCI_CONF_VENID));
739 n += snprintf(&buf[n], (size_left - n), "DEVICE_ID = 0x%04x\n",
740 pci_config_get16(pwp->pci_acc_handle, PCI_CONF_DEVID));
741 n += snprintf(&buf[n], (size_left - n), "CFGCMD = 0x%04x\n",
742 pci_config_get16(pwp->pci_acc_handle, PCI_CONF_COMM));
743 n += snprintf(&buf[n], (size_left - n), "CFGSTAT = 0x%04x\n",
744 pci_config_get16(pwp->pci_acc_handle, PCI_CONF_STAT));
745 n += snprintf(&buf[n], (size_left - n), "CLSCODE and REVID = 0x%08x\n",
746 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_REVID));
747 n += snprintf(&buf[n], (size_left - n), "BIST HDRTYPE LATTIM CLSIZE = "
748 "0x%08x\n",
749 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_CACHE_LINESZ));
750 n += snprintf(&buf[n], (size_left - n), "MEMBASE-I LOWER = 0x%08x\n",
751 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE0));
752 n += snprintf(&buf[n], (size_left - n), "MEMBASE-I UPPER = 0x%08x\n",
753 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE1));
754 n += snprintf(&buf[n], (size_left - n), "MEMBASE-II LOWER = 0x%08x\n",
755 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE2));
756 n += snprintf(&buf[n], (size_left - n), "MEMBASE-II UPPER = 0x%08x\n",
757 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE3));
758 n += snprintf(&buf[n], (size_left - n), "MEMBASE-III = 0x%08x\n",
759 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE4));
760 n += snprintf(&buf[n], (size_left - n), "MEMBASE-IV = 0x%08x\n",
761 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE5));
762 n += snprintf(&buf[n], (size_left - n), "SVID = 0x%08x\n",
763 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_SUBVENID));
764 n += snprintf(&buf[n], (size_left - n), "ROMBASE = 0x%08x\n",
765 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_ROM));
766 n += snprintf(&buf[n], (size_left - n), "CAP_PTR = 0x%02x\n",
767 pci_config_get8(pwp->pci_acc_handle, PCI_CONF_CAP_PTR));
768 n += snprintf(&buf[n], (size_left - n), "MAXLAT MINGNT INTPIN "
769 "INTLINE = 0x%08x\n",
770 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_ILINE));
771 n += snprintf(&buf[n], (size_left - n), "PMC PM_NEXT_CAP PM_CAP_ID = "
772 "0x%08x\n", pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PMC));
773 n += snprintf(&buf[n], (size_left - n), "PMCSR = 0x%08x\n",
774 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PMCSR));
775 n += snprintf(&buf[n], (size_left - n),
776 "MC MSI_NEXT_CAP MSI_CAP_ID = 0x%08x\n",
777 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MSI));
778 n += snprintf(&buf[n], (size_left - n), "MAL = 0x%08x\n",
779 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MAL));
780 n += snprintf(&buf[n], (size_left - n), "MAU = 0x%08x\n",
781 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MAU));
782 n += snprintf(&buf[n], (size_left - n), "MD = 0x%04x\n",
783 pci_config_get16(pwp->pci_acc_handle, PMCS_PCI_MD));
784 n += snprintf(&buf[n], (size_left - n),
785 "PCIE_CAP PCIE_NEXT_CAP PCIE_CAP_ID = 0x%08x\n",
786 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PCIE));
787 n += snprintf(&buf[n], (size_left - n), "DEVICE_CAP = 0x%08x\n",
788 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_DEV_CAP));
789 n += snprintf(&buf[n], (size_left - n),
790 "DEVICE_STAT DEVICE_CTRL = 0x%08x\n",
791 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_DEV_CTRL));
792 n += snprintf(&buf[n], (size_left - n), "LINK_CAP = 0x%08x\n",
793 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_LINK_CAP));
794 n += snprintf(&buf[n], (size_left - n),
795 "LINK_STAT LINK_CTRL = 0x%08x\n",
796 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_LINK_CTRL));
797 n += snprintf(&buf[n], (size_left - n), "MSIX_CAP = 0x%08x\n",
798 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MSIX_CAP));
799 n += snprintf(&buf[n], (size_left - n), "TBL_OFFSET = 0x%08x\n",
800 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_TBL_OFFSET));
801 n += snprintf(&buf[n], (size_left - n), "PBA_OFFSET = 0x%08x\n",
802 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PBA_OFFSET));
803 n += snprintf(&buf[n], (size_left - n), "PCIE_CAP_HD = 0x%08x\n",
804 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PCIE_CAP_HD));
805 n += snprintf(&buf[n], (size_left - n), "UE_STAT = 0x%08x\n",
806 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_UE_STAT));
807 n += snprintf(&buf[n], (size_left - n), "UE_MASK = 0x%08x\n",
808 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_UE_MASK));
809 n += snprintf(&buf[n], (size_left - n), "UE_SEV = 0x%08x\n",
810 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_UE_SEV));
811 n += snprintf(&buf[n], (size_left - n), "CE_STAT = 0x%08x\n",
812 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_CE_STAT));
813 n += snprintf(&buf[n], (size_left - n), "CE_MASK = 0x%08x\n",
814 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_CE_MASK));
815 n += snprintf(&buf[n], (size_left - n), "ADV_ERR_CTRL = 0x%08x\n",
816 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_ADV_ERR_CTRL));
817 for (i = 0; i < 4; i++) {
818 n += snprintf(&buf[n], (size_left - n), "HD_LOG_DW%d = "
819 "0x%08x\n", i, pci_config_get32(pwp->pci_acc_handle,
820 (PMCS_PCI_HD_LOG_DW + i * 4)));
821 }
822 n += snprintf(&buf[n], (size_left - n), "-----------------\n"
823 "Dump PCIe configuration registers end \n");
824 return (n);
825 }
826 /*
827 * Called with axil_lock held
828 */
829 static boolean_t
pmcs_shift_axil(pmcs_hw_t * pwp,uint32_t offset)830 pmcs_shift_axil(pmcs_hw_t *pwp, uint32_t offset)
831 {
832 uint32_t newaxil = offset & ~GSM_BASE_MASK;
833
834 ASSERT(mutex_owned(&pwp->axil_lock));
835 ddi_put32(pwp->top_acc_handle,
836 &pwp->top_regs[PMCS_AXI_TRANS >> 2], newaxil);
837 drv_usecwait(10);
838
839 if (ddi_get32(pwp->top_acc_handle,
840 &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != newaxil) {
841 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
842 "AXIL register update failed");
843 return (B_FALSE);
844 }
845 return (B_TRUE);
846 }
847
848 static uint32_t
pmcs_get_axil(pmcs_hw_t * pwp)849 pmcs_get_axil(pmcs_hw_t *pwp)
850 {
851 uint32_t regval = 0;
852 mutex_enter(&pwp->axil_lock);
853 regval = ddi_get32(pwp->top_acc_handle,
854 &pwp->top_regs[PMCS_AXI_TRANS >> 2]);
855 mutex_exit(&pwp->axil_lock);
856 return (regval);
857 }
858
859 static void
pmcs_restore_axil(pmcs_hw_t * pwp,uint32_t oldaxil)860 pmcs_restore_axil(pmcs_hw_t *pwp, uint32_t oldaxil)
861 {
862 mutex_enter(&pwp->axil_lock);
863 ddi_put32(pwp->top_acc_handle,
864 &pwp->top_regs[PMCS_AXI_TRANS >> 2], oldaxil);
865 drv_usecwait(10);
866
867 if (ddi_get32(pwp->top_acc_handle,
868 &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != oldaxil) {
869 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
870 "AXIL register restore failed");
871 }
872 mutex_exit(&pwp->axil_lock);
873 }
874
875 /*
876 * Dump Additional GSM Registers.
877 */
878 static int
pmcs_dump_gsm_addiregs(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)879 pmcs_dump_gsm_addiregs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
880 {
881 uint32_t i = 0;
882 int n = 0, j = 0, nums = 0;
883 uint32_t gsm_addr = 0, addr = 0;
884
885 n += snprintf(&buf[n], (size_left - n), "\nDump GSM Sparse Registers:"
886 "\n-----------------\n");
887 for (i = 0; i < sizeof (gsm_spregs) / sizeof (pmcs_sparse_regs_t);
888 i++) {
889 gsm_addr =
890 gsm_spregs[i].shift_addr + gsm_spregs[i].offset_start;
891 nums = gsm_spregs[i].offset_end - gsm_spregs[i].offset_start;
892 if (gsm_spregs[i].flag & PMCS_SPREGS_BLOCK_START) {
893 n += snprintf(&buf[n], (size_left - n), "\n%s - 0x%08X"
894 "[MEMBASE-III SHIFT = 0x%08X]\nOffset:\n",
895 gsm_spregs[i].desc ? gsm_spregs[i].desc : "NULL",
896 gsm_spregs[i].base_addr, gsm_spregs[i].shift_addr);
897 }
898
899 if (nums == 0) {
900 n += snprintf(&buf[n], (size_left - n),
901 "[%04X]: %08X\n", gsm_spregs[i].offset_start,
902 pmcs_rd_gsm_reg(pwp, 0, gsm_addr));
903 } else if (nums > 0) {
904 n += snprintf(&buf[n], (size_left - n),
905 "\n[%04X] - [%04X]: \n", gsm_spregs[i].offset_start,
906 gsm_spregs[i].offset_end);
907
908 j = 0;
909 while (nums > 0) {
910 addr = gsm_addr + j * 4;
911 n += snprintf(&buf[n], (size_left - n),
912 "[%04X]: %08X\n", addr & GSM_BASE_MASK,
913 pmcs_rd_gsm_reg(pwp, 0, addr));
914 j++;
915 nums -= 4;
916 }
917 }
918
919 }
920
921 n += snprintf(&buf[n], (size_left - n), "-----------------\n"
922 "------------ Dump GSM Sparse Registers end ------------\n");
923 return (n);
924
925 }
926
927 /*
928 * Dump GSM Memory Regions.
929 */
930 static int
pmcs_dump_gsm(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)931 pmcs_dump_gsm(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
932 {
933 int n = 0;
934 uint32_t i = 0;
935 uint32_t oldaxil = 0;
936 uint32_t gsm_addr = 0;
937 uint32_t *local_buf = NULL;
938
939 local_buf = kmem_zalloc(GSM_SM_BLKSZ, KM_NOSLEEP);
940 if (local_buf == NULL) {
941 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
942 "%s: local_buf memory not allocated", __func__);
943 return (0);
944 }
945
946 oldaxil = pmcs_get_axil(pwp);
947 mutex_enter(&pwp->axil_lock);
948 n += snprintf(&buf[n], (size_left - n), "\nDump GSM IO Status Table: \n"
949 " -----------------\n");
950 for (i = 0; i < 4; i++) {
951 gsm_addr = IO_STATUS_TABLE_BASE + GSM_SM_BLKSZ * i;
952 if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
953 gsm_addr &= GSM_BASE_MASK;
954 ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
955 &pwp->gsm_regs[gsm_addr >> 2], GSM_SM_BLKSZ >> 2,
956 DDI_DEV_AUTOINCR);
957 n += pmcs_dump_binary(pwp, local_buf, i * GSM_SM_BLKSZ,
958 GSM_SM_BLKSZ >> 2, &buf[n], size_left - n);
959 }
960 }
961 n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
962 "Dump GSM IO Status Table end \n");
963 n += snprintf(&buf[n], (size_left - n), "\nDump Ring Buffer Storage: \n"
964 " -----------------\n");
965 for (i = 0; i < 2; i++) {
966 gsm_addr = RING_BUF_STORAGE_0 + GSM_SM_BLKSZ * i;
967 if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
968 gsm_addr &= GSM_BASE_MASK;
969 ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
970 &pwp->gsm_regs[gsm_addr >> 2], GSM_SM_BLKSZ >> 2,
971 DDI_DEV_AUTOINCR);
972 n += pmcs_dump_binary(pwp, local_buf, i * GSM_SM_BLKSZ,
973 GSM_SM_BLKSZ >> 2, &buf[n], size_left - n);
974 }
975 }
976 n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
977 "Dump Ring Buffer Storage end \n");
978
979 n += snprintf(&buf[n], (size_left - n), "\nDump Ring Buffer Pointers:\n"
980 " -----------------\n");
981 gsm_addr = RING_BUF_PTR_ACC_BASE + RING_BUF_PTR_OFF;
982 if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
983 gsm_addr &= GSM_BASE_MASK;
984 ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
985 &pwp->gsm_regs[gsm_addr >> 2],
986 RING_BUF_PTR_SIZE >> 2, DDI_DEV_AUTOINCR);
987 n += pmcs_dump_binary(pwp, local_buf, 0,
988 RING_BUF_PTR_SIZE >> 2, &buf[n], size_left - n);
989 }
990 n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
991 "Dump Ring Buffer Pointers end \n");
992
993 n += snprintf(&buf[n], (size_left - n), "\nDump Ring Buffer Access: \n"
994 " -----------------\n");
995 gsm_addr = RING_BUF_PTR_ACC_BASE + RING_BUF_ACC_OFF;
996 if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
997 gsm_addr &= GSM_BASE_MASK;
998 ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
999 &pwp->gsm_regs[gsm_addr >> 2],
1000 RING_BUF_ACC_SIZE >> 2, DDI_DEV_AUTOINCR);
1001 n += pmcs_dump_binary(pwp, local_buf, 0,
1002 RING_BUF_ACC_SIZE >> 2, &buf[n], size_left - n);
1003 }
1004 n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
1005 "Dump Ring Buffer Access end \n");
1006
1007 n += snprintf(&buf[n], (size_left - n), "\nDump GSM SM: \n"
1008 " -----------------\n");
1009 for (i = 0; i < 16; i++) {
1010 gsm_addr = GSM_SM_BASE + GSM_SM_BLKSZ * i;
1011 if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
1012 gsm_addr &= GSM_BASE_MASK;
1013 ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
1014 &pwp->gsm_regs[gsm_addr >> 2],
1015 GSM_SM_BLKSZ >> 2, DDI_DEV_AUTOINCR);
1016 n += pmcs_dump_binary(pwp, local_buf, i * GSM_SM_BLKSZ,
1017 GSM_SM_BLKSZ >> 2, &buf[n], size_left - n);
1018 }
1019 }
1020 mutex_exit(&pwp->axil_lock);
1021 pmcs_restore_axil(pwp, oldaxil);
1022
1023 n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
1024 "Dump GSM SM end \n");
1025 n += snprintf(&buf[n], (size_left - n), "-----------------\n"
1026 "\n------------ Dump GSM Memory Regions end -------------\n");
1027 if (local_buf) {
1028 kmem_free(local_buf, GSM_SM_BLKSZ);
1029 }
1030 return (n);
1031 }
1032
1033 /*
1034 * Trace current Inbound Message host sent to SPC.
1035 */
1036 void
pmcs_iqp_trace(pmcs_hw_t * pwp,uint32_t qnum)1037 pmcs_iqp_trace(pmcs_hw_t *pwp, uint32_t qnum)
1038 {
1039 uint32_t k = 0;
1040 int n = 0;
1041 uint32_t *ptr = NULL;
1042 char *tbuf = pwp->iqpt->curpos;
1043 uint32_t size_left = pwp->iqpt->size_left;
1044
1045 if (tbuf == NULL) {
1046 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1047 "%s: trace buffer is not ready,"
1048 " Inbound Message from host to SPC is not traced",
1049 __func__);
1050 return;
1051 } else if (size_left < PMCS_QENTRY_SIZE * PMCS_QENTRY_SIZE) {
1052 tbuf = pwp->iqpt->curpos = pwp->iqpt->head;
1053 size_left = pwp->iqpt->size_left = PMCS_IQP_TRACE_BUFFER_SIZE;
1054 }
1055
1056 ptr = &pwp->iqp[qnum][pwp->shadow_iqpi[qnum] *
1057 (PMCS_QENTRY_SIZE >> 2)];
1058 for (k = 0; k < (PMCS_QENTRY_SIZE / sizeof (uint32_t));
1059 k += 8) {
1060 n += snprintf(&tbuf[n], (size_left - n),
1061 "0x%08x 0x%08x 0x%08x 0x%08x "
1062 "0x%08x 0x%08x 0x%08x 0x%08x\n",
1063 LE_32(ptr[k]), LE_32(ptr[k+1]),
1064 LE_32(ptr[k+2]), LE_32(ptr[k+3]),
1065 LE_32(ptr[k+4]), LE_32(ptr[k+5]),
1066 LE_32(ptr[k+6]), LE_32(ptr[k+7]));
1067 }
1068 pwp->iqpt->size_left -= n;
1069 if (pwp->iqpt->size_left > 0) {
1070 pwp->iqpt->curpos += n;
1071 } else {
1072 pwp->iqpt->curpos =
1073 pwp->iqpt->head + PMCS_IQP_TRACE_BUFFER_SIZE - 1;
1074 }
1075 }
1076
1077 /*
1078 * Capture HSST State Registers.
1079 */
1080 static int
pmcs_dump_hsst_sregs(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)1081 pmcs_dump_hsst_sregs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
1082 {
1083 uint32_t i = 0, j = 0, addr = 0;
1084 int n = 0;
1085
1086 n += snprintf(&buf[n], (size_left - n), "\nHSST State Capture : \n"
1087 "-----------------\n");
1088 n += snprintf(&buf[n], (size_left - n), "%s \t %s \n",
1089 hsst_state[8].desc ? hsst_state[8].desc : "NULL",
1090 hsst_state[16].desc ? hsst_state[16].desc : "NULL");
1091
1092 for (i = 0; i < 8; i++) {
1093 addr = hsst_state[i].offset_start +
1094 hsst_state[i].shift_addr;
1095 n += snprintf(&buf[n], (size_left - n), "Phy[%1d]\n", i);
1096 for (j = 0; j < 6; j++) {
1097 pmcs_wr_gsm_reg(pwp, addr, j);
1098 pmcs_wr_gsm_reg(pwp, addr, (0x0100 + j));
1099 addr = hsst_state[i+8].offset_start +
1100 hsst_state[i+8].shift_addr;
1101 n += snprintf(&buf[n], (size_left - n),
1102 "[%08X]: %08X\t", addr, pmcs_rd_gsm_reg(pwp, 0,
1103 addr));
1104 addr = hsst_state[i+16].offset_start +
1105 hsst_state[i+16].shift_addr;
1106 n += snprintf(&buf[n], (size_left - n),
1107 "[%08X]: %08X\n", addr, pmcs_rd_gsm_reg(pwp, 0,
1108 addr));
1109 }
1110
1111 }
1112 return (n);
1113
1114 }
1115
1116 /*
1117 * Capture SSPA State Registers.
1118 */
1119 static int
pmcs_dump_sspa_sregs(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)1120 pmcs_dump_sspa_sregs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
1121 {
1122 uint32_t i = 0, rv = 0, addr = 0;
1123 int n = 0;
1124
1125 n += snprintf(&buf[n], (size_left - n), "\nSSPA State Capture : \n"
1126 "-----------------\n");
1127 for (i = 0; i < 8; i++) {
1128 if (sspa_state[i].flag & PMCS_SPREGS_BLOCK_START) {
1129 n += snprintf(&buf[n], (size_left - n), "%s \n",
1130 sspa_state[i].desc ? sspa_state[i].desc : "NULL");
1131 }
1132 addr = sspa_state[i].offset_start + sspa_state[i].shift_addr;
1133 rv = pmcs_rd_gsm_reg(pwp, 0, addr);
1134 rv |= PMCS_SSPA_CONTROL_REGISTER_BIT27;
1135 pmcs_wr_gsm_reg(pwp, addr, rv);
1136 n += snprintf(&buf[n], (size_left - n), "[%08X]: %08X \n",
1137 addr, pmcs_rd_gsm_reg(pwp, 0, addr));
1138
1139 }
1140 return (n);
1141 }
1142
1143 /*
1144 * Dump fatal error register content from GSM.
1145 */
1146 int
pmcs_dump_feregs(pmcs_hw_t * pwp,uint32_t * addr,uint8_t nvmd,caddr_t buf,uint32_t size_left)1147 pmcs_dump_feregs(pmcs_hw_t *pwp, uint32_t *addr, uint8_t nvmd,
1148 caddr_t buf, uint32_t size_left)
1149 {
1150 uint32_t offset = 0, length = 0;
1151 int i = 0;
1152 uint8_t *ptr = (uint8_t *)addr;
1153
1154 if ((addr == NULL) || (buf == NULL)) {
1155 return (0);
1156 }
1157 switch (nvmd) {
1158 case PMCIN_NVMD_AAP1:
1159 offset = pmcs_rd_mpi_tbl(pwp, PMCS_FERDOMSGU);
1160 length = pmcs_rd_mpi_tbl(pwp, PMCS_FERDLMSGU);
1161 break;
1162 case PMCIN_NVMD_IOP:
1163 offset = pmcs_rd_mpi_tbl(pwp, PMCS_FERDOIOP);
1164 length = pmcs_rd_mpi_tbl(pwp, PMCS_FERDLIOP);
1165 break;
1166 default:
1167 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1168 "UNKNOWN NVMD DEVICE %s():%d", __func__, __LINE__);
1169 return (0);
1170 }
1171
1172 while ((i < length) && (ptr[i + offset] != 0xff) &&
1173 (ptr[i + offset] != '\0')) {
1174 i += snprintf(&buf[i], (size_left - i),
1175 "%c", ptr[i + offset]);
1176 }
1177 return (i);
1178 }
1179
1180 /*
1181 * Write out either the AAP1 or IOP event log
1182 */
1183 static void
pmcs_write_fwlog(pmcs_hw_t * pwp,pmcs_fw_event_hdr_t * fwlogp)1184 pmcs_write_fwlog(pmcs_hw_t *pwp, pmcs_fw_event_hdr_t *fwlogp)
1185 {
1186 struct vnode *vnp;
1187 caddr_t fwlogfile, bufp;
1188 rlim64_t rlimit;
1189 ssize_t resid;
1190 offset_t offset = 0;
1191 int error;
1192 uint32_t data_len;
1193
1194 if (fwlogp == pwp->fwlogp_aap1) {
1195 fwlogfile = pwp->fwlogfile_aap1;
1196 } else {
1197 fwlogfile = pwp->fwlogfile_iop;
1198 }
1199
1200 if ((error = vn_open(fwlogfile, UIO_SYSSPACE, FCREAT|FWRITE, 0644,
1201 &vnp, CRCREAT, 0)) != 0) {
1202 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1203 "%s: Could not create '%s', error %d", __func__,
1204 fwlogfile, error);
1205 return;
1206 }
1207
1208 bufp = (caddr_t)fwlogp;
1209 data_len = PMCS_FWLOG_SIZE / 2;
1210 rlimit = data_len + 1;
1211 for (;;) {
1212 error = vn_rdwr(UIO_WRITE, vnp, bufp, data_len, offset,
1213 UIO_SYSSPACE, FSYNC, rlimit, CRED(), &resid);
1214 if (error) {
1215 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1216 "%s: could not write %s, error %d", __func__,
1217 fwlogfile, error);
1218 break;
1219 }
1220 if (resid == data_len) {
1221 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1222 "%s: Out of space in %s, error %d", __func__,
1223 fwlogfile, error);
1224 error = ENOSPC;
1225 break;
1226 }
1227 if (resid == 0)
1228 break;
1229 offset += (data_len - resid);
1230 data_len = (ssize_t)resid;
1231 }
1232
1233 if (error = VOP_CLOSE(vnp, FWRITE, 1, (offset_t)0, kcred, NULL)) {
1234 if (!error) {
1235 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1236 "%s: Error on close %s, error %d", __func__,
1237 fwlogfile, error);
1238 }
1239 }
1240
1241 VN_RELE(vnp);
1242 }
1243
1244 /*
1245 * Check the in-memory event log. If it's filled up to or beyond the
1246 * threshold, write it out to the configured filename.
1247 */
1248 void
pmcs_gather_fwlog(pmcs_hw_t * pwp)1249 pmcs_gather_fwlog(pmcs_hw_t *pwp)
1250 {
1251 uint32_t num_entries_aap1, num_entries_iop, fname_suffix;
1252
1253 ASSERT(!mutex_owned(&pwp->lock));
1254
1255 /*
1256 * Get our copies of the latest indices
1257 */
1258 pwp->fwlog_latest_idx_aap1 = pwp->fwlogp_aap1->fw_el_latest_idx;
1259 pwp->fwlog_latest_idx_iop = pwp->fwlogp_iop->fw_el_latest_idx;
1260
1261 /*
1262 * We need entries in the log before we can know how big they are
1263 */
1264 if ((pwp->fwlog_max_entries_aap1 == 0) &&
1265 (pwp->fwlogp_aap1->fw_el_latest_idx != 0)) {
1266 pwp->fwlog_max_entries_aap1 =
1267 (PMCS_FWLOG_SIZE / 2) / pwp->fwlogp_aap1->fw_el_entry_size;
1268 pwp->fwlog_threshold_aap1 =
1269 (pwp->fwlog_max_entries_aap1 * PMCS_FWLOG_THRESH) / 100;
1270 }
1271
1272 if ((pwp->fwlog_max_entries_iop == 0) &&
1273 (pwp->fwlogp_iop->fw_el_latest_idx != 0)) {
1274 pwp->fwlog_max_entries_iop =
1275 (PMCS_FWLOG_SIZE / 2) / pwp->fwlogp_iop->fw_el_entry_size;
1276 pwp->fwlog_threshold_iop =
1277 (pwp->fwlog_max_entries_iop * PMCS_FWLOG_THRESH) / 100;
1278 }
1279
1280 /*
1281 * Check if we've reached the threshold in the AAP1 log. We do this
1282 * by comparing the latest index with our copy of the oldest index
1283 * (not the chip's).
1284 */
1285 if (pwp->fwlog_latest_idx_aap1 >= pwp->fwlog_oldest_idx_aap1) {
1286 /* Log has not wrapped */
1287 num_entries_aap1 =
1288 pwp->fwlog_latest_idx_aap1 - pwp->fwlog_oldest_idx_aap1;
1289 } else {
1290 /* Log has wrapped */
1291 num_entries_aap1 = pwp->fwlog_max_entries_aap1 -
1292 (pwp->fwlog_oldest_idx_aap1 - pwp->fwlog_latest_idx_aap1);
1293 }
1294
1295 /*
1296 * Now check the IOP log
1297 */
1298 if (pwp->fwlog_latest_idx_iop >= pwp->fwlog_oldest_idx_iop) {
1299 /* Log has not wrapped */
1300 num_entries_iop = pwp->fwlog_latest_idx_iop -
1301 pwp->fwlog_oldest_idx_iop;
1302 } else {
1303 /* Log has wrapped */
1304 num_entries_iop = pwp->fwlog_max_entries_iop -
1305 (pwp->fwlog_oldest_idx_iop - pwp->fwlog_latest_idx_iop);
1306 }
1307
1308 if ((num_entries_aap1 < pwp->fwlog_threshold_aap1) &&
1309 (num_entries_iop < pwp->fwlog_threshold_iop)) {
1310 return;
1311 }
1312
1313 /*
1314 * We also can't write the event log out if it's too early in boot
1315 * (i.e. the root fs isn't mounted yet).
1316 */
1317 if (!modrootloaded) {
1318 return;
1319 }
1320
1321 /*
1322 * Write out the necessary log file(s), update the "oldest" pointers
1323 * and the suffix to the written filenames.
1324 */
1325 if (num_entries_aap1 >= pwp->fwlog_threshold_aap1) {
1326 pmcs_write_fwlog(pwp, pwp->fwlogp_aap1);
1327 pwp->fwlog_oldest_idx_aap1 = pwp->fwlog_latest_idx_aap1;
1328
1329 fname_suffix = strlen(pwp->fwlogfile_aap1) - 1;
1330 if (pwp->fwlogfile_aap1[fname_suffix] == '4') {
1331 pwp->fwlogfile_aap1[fname_suffix] = '0';
1332 } else {
1333 ++pwp->fwlogfile_aap1[fname_suffix];
1334 }
1335 }
1336
1337 if (num_entries_iop >= pwp->fwlog_threshold_iop) {
1338 pmcs_write_fwlog(pwp, pwp->fwlogp_iop);
1339 pwp->fwlog_oldest_idx_iop = pwp->fwlog_latest_idx_iop;
1340
1341 fname_suffix = strlen(pwp->fwlogfile_iop) - 1;
1342 if (pwp->fwlogfile_iop[fname_suffix] == '4') {
1343 pwp->fwlogfile_iop[fname_suffix] = '0';
1344 } else {
1345 ++pwp->fwlogfile_iop[fname_suffix];
1346 }
1347 }
1348 }
1349