Skip to content

Commit 044f59d

Browse files
Deepak Ukeymartinkpetersen
authored andcommitted
scsi: pm80xx: Modified the logic to collect fatal dump
Added the correct method to collect the fatal dump. Link: https://lore.kernel.org/r/[email protected] Reported-by: kbuild test robot <[email protected]> Acked-by: Jack Wang <[email protected]> Signed-off-by: Deepak Ukey <[email protected]> Signed-off-by: Viswas G <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 7295493 commit 044f59d

File tree

2 files changed

+195
-59
lines changed

2 files changed

+195
-59
lines changed

drivers/scsi/pm8001/pm8001_sas.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ struct pm8001_ioctl_payload {
152152
#define MPI_FATAL_EDUMP_TABLE_HANDSHAKE 0x0C /* FDDHSHK */
153153
#define MPI_FATAL_EDUMP_TABLE_STATUS 0x10 /* FDDTSTAT */
154154
#define MPI_FATAL_EDUMP_TABLE_ACCUM_LEN 0x14 /* ACCDDLEN */
155+
#define MPI_FATAL_EDUMP_TABLE_TOTAL_LEN 0x18 /* TOTALLEN */
156+
#define MPI_FATAL_EDUMP_TABLE_SIGNATURE 0x1C /* SIGNITURE */
155157
#define MPI_FATAL_EDUMP_HANDSHAKE_RDY 0x1
156158
#define MPI_FATAL_EDUMP_HANDSHAKE_BUSY 0x0
157159
#define MPI_FATAL_EDUMP_TABLE_STAT_RSVD 0x0
@@ -507,6 +509,7 @@ struct pm8001_hba_info {
507509
u32 forensic_last_offset;
508510
u32 fatal_forensic_shift_offset;
509511
u32 forensic_fatal_step;
512+
u32 forensic_preserved_accumulated_transfer;
510513
u32 evtlog_ib_offset;
511514
u32 evtlog_ob_offset;
512515
void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/

drivers/scsi/pm8001/pm80xx_hwi.c

Lines changed: 192 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ void pm80xx_pci_mem_copy(struct pm8001_hba_info *pm8001_ha, u32 soffset,
7676
destination1 = (u32 *)destination;
7777

7878
for (index = 0; index < dw_count; index += 4, destination1++) {
79-
offset = (soffset + index / 4);
79+
offset = (soffset + index);
8080
if (offset < (64 * 1024)) {
8181
value = pm8001_cr32(pm8001_ha, bus_base_number, offset);
8282
*destination1 = cpu_to_le32(value);
@@ -93,9 +93,12 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
9393
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
9494
void __iomem *fatal_table_address = pm8001_ha->fatal_tbl_addr;
9595
u32 accum_len , reg_val, index, *temp;
96+
u32 status = 1;
9697
unsigned long start;
9798
u8 *direct_data;
9899
char *fatal_error_data = buf;
100+
u32 length_to_read;
101+
u32 offset;
99102

100103
pm8001_ha->forensic_info.data_buf.direct_data = buf;
101104
if (pm8001_ha->chip_id == chip_8001) {
@@ -105,16 +108,35 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
105108
return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
106109
(char *)buf;
107110
}
111+
/* initialize variables for very first call from host application */
108112
if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {
109113
PM8001_IO_DBG(pm8001_ha,
110114
pm8001_printk("forensic_info TYPE_NON_FATAL..............\n"));
111115
direct_data = (u8 *)fatal_error_data;
112116
pm8001_ha->forensic_info.data_type = TYPE_NON_FATAL;
113117
pm8001_ha->forensic_info.data_buf.direct_len = SYSFS_OFFSET;
118+
pm8001_ha->forensic_info.data_buf.direct_offset = 0;
114119
pm8001_ha->forensic_info.data_buf.read_len = 0;
120+
pm8001_ha->forensic_preserved_accumulated_transfer = 0;
115121

116-
pm8001_ha->forensic_info.data_buf.direct_data = direct_data;
122+
/* Write signature to fatal dump table */
123+
pm8001_mw32(fatal_table_address,
124+
MPI_FATAL_EDUMP_TABLE_SIGNATURE, 0x1234abcd);
117125

126+
pm8001_ha->forensic_info.data_buf.direct_data = direct_data;
127+
PM8001_IO_DBG(pm8001_ha,
128+
pm8001_printk("ossaHwCB: status1 %d\n", status));
129+
PM8001_IO_DBG(pm8001_ha,
130+
pm8001_printk("ossaHwCB: read_len 0x%x\n",
131+
pm8001_ha->forensic_info.data_buf.read_len));
132+
PM8001_IO_DBG(pm8001_ha,
133+
pm8001_printk("ossaHwCB: direct_len 0x%x\n",
134+
pm8001_ha->forensic_info.data_buf.direct_len));
135+
PM8001_IO_DBG(pm8001_ha,
136+
pm8001_printk("ossaHwCB: direct_offset 0x%x\n",
137+
pm8001_ha->forensic_info.data_buf.direct_offset));
138+
}
139+
if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {
118140
/* start to get data */
119141
/* Program the MEMBASE II Shifting Register with 0x00.*/
120142
pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
@@ -127,30 +149,66 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
127149
/* Read until accum_len is retrived */
128150
accum_len = pm8001_mr32(fatal_table_address,
129151
MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
130-
PM8001_IO_DBG(pm8001_ha, pm8001_printk("accum_len 0x%x\n",
131-
accum_len));
152+
/* Determine length of data between previously stored transfer length
153+
* and current accumulated transfer length
154+
*/
155+
length_to_read =
156+
accum_len - pm8001_ha->forensic_preserved_accumulated_transfer;
157+
PM8001_IO_DBG(pm8001_ha,
158+
pm8001_printk("get_fatal_spcv: accum_len 0x%x\n", accum_len));
159+
PM8001_IO_DBG(pm8001_ha,
160+
pm8001_printk("get_fatal_spcv: length_to_read 0x%x\n",
161+
length_to_read));
162+
PM8001_IO_DBG(pm8001_ha,
163+
pm8001_printk("get_fatal_spcv: last_offset 0x%x\n",
164+
pm8001_ha->forensic_last_offset));
165+
PM8001_IO_DBG(pm8001_ha,
166+
pm8001_printk("get_fatal_spcv: read_len 0x%x\n",
167+
pm8001_ha->forensic_info.data_buf.read_len));
168+
PM8001_IO_DBG(pm8001_ha,
169+
pm8001_printk("get_fatal_spcv:: direct_len 0x%x\n",
170+
pm8001_ha->forensic_info.data_buf.direct_len));
171+
PM8001_IO_DBG(pm8001_ha,
172+
pm8001_printk("get_fatal_spcv:: direct_offset 0x%x\n",
173+
pm8001_ha->forensic_info.data_buf.direct_offset));
174+
175+
/* If accumulated length failed to read correctly fail the attempt.*/
132176
if (accum_len == 0xFFFFFFFF) {
133177
PM8001_IO_DBG(pm8001_ha,
134178
pm8001_printk("Possible PCI issue 0x%x not expected\n",
135-
accum_len));
136-
return -EIO;
179+
accum_len));
180+
return status;
137181
}
138-
if (accum_len == 0 || accum_len >= 0x100000) {
182+
/* If accumulated length is zero fail the attempt */
183+
if (accum_len == 0) {
139184
pm8001_ha->forensic_info.data_buf.direct_data +=
140185
sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
141-
"%08x ", 0xFFFFFFFF);
186+
"%08x ", 0xFFFFFFFF);
142187
return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
143188
(char *)buf;
144189
}
190+
/* Accumulated length is good so start capturing the first data */
145191
temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr;
146192
if (pm8001_ha->forensic_fatal_step == 0) {
147193
moreData:
194+
/* If data to read is less than SYSFS_OFFSET then reduce the
195+
* length of dataLen
196+
*/
197+
if (pm8001_ha->forensic_last_offset + SYSFS_OFFSET
198+
> length_to_read) {
199+
pm8001_ha->forensic_info.data_buf.direct_len =
200+
length_to_read -
201+
pm8001_ha->forensic_last_offset;
202+
} else {
203+
pm8001_ha->forensic_info.data_buf.direct_len =
204+
SYSFS_OFFSET;
205+
}
148206
if (pm8001_ha->forensic_info.data_buf.direct_data) {
149207
/* Data is in bar, copy to host memory */
150-
pm80xx_pci_mem_copy(pm8001_ha, pm8001_ha->fatal_bar_loc,
151-
pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr,
152-
pm8001_ha->forensic_info.data_buf.direct_len ,
153-
1);
208+
pm80xx_pci_mem_copy(pm8001_ha,
209+
pm8001_ha->fatal_bar_loc,
210+
pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr,
211+
pm8001_ha->forensic_info.data_buf.direct_len, 1);
154212
}
155213
pm8001_ha->fatal_bar_loc +=
156214
pm8001_ha->forensic_info.data_buf.direct_len;
@@ -161,21 +219,29 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
161219
pm8001_ha->forensic_info.data_buf.read_len =
162220
pm8001_ha->forensic_info.data_buf.direct_len;
163221

164-
if (pm8001_ha->forensic_last_offset >= accum_len) {
222+
if (pm8001_ha->forensic_last_offset >= length_to_read) {
165223
pm8001_ha->forensic_info.data_buf.direct_data +=
166224
sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
167225
"%08x ", 3);
168-
for (index = 0; index < (SYSFS_OFFSET / 4); index++) {
226+
for (index = 0; index <
227+
(pm8001_ha->forensic_info.data_buf.direct_len
228+
/ 4); index++) {
169229
pm8001_ha->forensic_info.data_buf.direct_data +=
170-
sprintf(pm8001_ha->
171-
forensic_info.data_buf.direct_data,
172-
"%08x ", *(temp + index));
230+
sprintf(
231+
pm8001_ha->forensic_info.data_buf.direct_data,
232+
"%08x ", *(temp + index));
173233
}
174234

175235
pm8001_ha->fatal_bar_loc = 0;
176236
pm8001_ha->forensic_fatal_step = 1;
177237
pm8001_ha->fatal_forensic_shift_offset = 0;
178238
pm8001_ha->forensic_last_offset = 0;
239+
status = 0;
240+
offset = (int)
241+
((char *)pm8001_ha->forensic_info.data_buf.direct_data
242+
- (char *)buf);
243+
PM8001_IO_DBG(pm8001_ha,
244+
pm8001_printk("get_fatal_spcv:return1 0x%x\n", offset));
179245
return (char *)pm8001_ha->
180246
forensic_info.data_buf.direct_data -
181247
(char *)buf;
@@ -185,12 +251,20 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
185251
sprintf(pm8001_ha->
186252
forensic_info.data_buf.direct_data,
187253
"%08x ", 2);
188-
for (index = 0; index < (SYSFS_OFFSET / 4); index++) {
189-
pm8001_ha->forensic_info.data_buf.direct_data +=
190-
sprintf(pm8001_ha->
254+
for (index = 0; index <
255+
(pm8001_ha->forensic_info.data_buf.direct_len
256+
/ 4); index++) {
257+
pm8001_ha->forensic_info.data_buf.direct_data
258+
+= sprintf(pm8001_ha->
191259
forensic_info.data_buf.direct_data,
192260
"%08x ", *(temp + index));
193261
}
262+
status = 0;
263+
offset = (int)
264+
((char *)pm8001_ha->forensic_info.data_buf.direct_data
265+
- (char *)buf);
266+
PM8001_IO_DBG(pm8001_ha,
267+
pm8001_printk("get_fatal_spcv:return2 0x%x\n", offset));
194268
return (char *)pm8001_ha->
195269
forensic_info.data_buf.direct_data -
196270
(char *)buf;
@@ -200,63 +274,122 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
200274
pm8001_ha->forensic_info.data_buf.direct_data +=
201275
sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
202276
"%08x ", 2);
203-
for (index = 0; index < 256; index++) {
277+
for (index = 0; index <
278+
(pm8001_ha->forensic_info.data_buf.direct_len
279+
/ 4) ; index++) {
204280
pm8001_ha->forensic_info.data_buf.direct_data +=
205281
sprintf(pm8001_ha->
206-
forensic_info.data_buf.direct_data,
207-
"%08x ", *(temp + index));
282+
forensic_info.data_buf.direct_data,
283+
"%08x ", *(temp + index));
208284
}
209285
pm8001_ha->fatal_forensic_shift_offset += 0x100;
210286
pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
211287
pm8001_ha->fatal_forensic_shift_offset);
212288
pm8001_ha->fatal_bar_loc = 0;
289+
status = 0;
290+
offset = (int)
291+
((char *)pm8001_ha->forensic_info.data_buf.direct_data
292+
- (char *)buf);
293+
PM8001_IO_DBG(pm8001_ha,
294+
pm8001_printk("get_fatal_spcv: return3 0x%x\n", offset));
213295
return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
214296
(char *)buf;
215297
}
216298
if (pm8001_ha->forensic_fatal_step == 1) {
217-
pm8001_ha->fatal_forensic_shift_offset = 0;
218-
/* Read 64K of the debug data. */
219-
pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
220-
pm8001_ha->fatal_forensic_shift_offset);
221-
pm8001_mw32(fatal_table_address,
222-
MPI_FATAL_EDUMP_TABLE_HANDSHAKE,
299+
/* store previous accumulated length before triggering next
300+
* accumulated length update
301+
*/
302+
pm8001_ha->forensic_preserved_accumulated_transfer =
303+
pm8001_mr32(fatal_table_address,
304+
MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
305+
306+
/* continue capturing the fatal log until Dump status is 0x3 */
307+
if (pm8001_mr32(fatal_table_address,
308+
MPI_FATAL_EDUMP_TABLE_STATUS) <
309+
MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) {
310+
311+
/* reset fddstat bit by writing to zero*/
312+
pm8001_mw32(fatal_table_address,
313+
MPI_FATAL_EDUMP_TABLE_STATUS, 0x0);
314+
315+
/* set dump control value to '1' so that new data will
316+
* be transferred to shared memory
317+
*/
318+
pm8001_mw32(fatal_table_address,
319+
MPI_FATAL_EDUMP_TABLE_HANDSHAKE,
223320
MPI_FATAL_EDUMP_HANDSHAKE_RDY);
224321

225-
/* Poll FDDHSHK until clear */
226-
start = jiffies + (2 * HZ); /* 2 sec */
322+
/*Poll FDDHSHK until clear */
323+
start = jiffies + (2 * HZ); /* 2 sec */
227324

228-
do {
229-
reg_val = pm8001_mr32(fatal_table_address,
325+
do {
326+
reg_val = pm8001_mr32(fatal_table_address,
230327
MPI_FATAL_EDUMP_TABLE_HANDSHAKE);
231-
} while ((reg_val) && time_before(jiffies, start));
328+
} while ((reg_val) && time_before(jiffies, start));
232329

233-
if (reg_val != 0) {
234-
PM8001_FAIL_DBG(pm8001_ha,
235-
pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER"
236-
" = 0x%x\n", reg_val));
237-
return -EIO;
238-
}
239-
240-
/* Read the next 64K of the debug data. */
241-
pm8001_ha->forensic_fatal_step = 0;
242-
if (pm8001_mr32(fatal_table_address,
243-
MPI_FATAL_EDUMP_TABLE_STATUS) !=
244-
MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) {
245-
pm8001_mw32(fatal_table_address,
246-
MPI_FATAL_EDUMP_TABLE_HANDSHAKE, 0);
247-
goto moreData;
248-
} else {
249-
pm8001_ha->forensic_info.data_buf.direct_data +=
250-
sprintf(pm8001_ha->
251-
forensic_info.data_buf.direct_data,
252-
"%08x ", 4);
253-
pm8001_ha->forensic_info.data_buf.read_len = 0xFFFFFFFF;
254-
pm8001_ha->forensic_info.data_buf.direct_len = 0;
255-
pm8001_ha->forensic_info.data_buf.direct_offset = 0;
256-
pm8001_ha->forensic_info.data_buf.read_len = 0;
330+
if (reg_val != 0) {
331+
PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
332+
"TIMEOUT:MPI_FATAL_EDUMP_TABLE_HDSHAKE 0x%x\n",
333+
reg_val));
334+
/* Fail the dump if a timeout occurs */
335+
pm8001_ha->forensic_info.data_buf.direct_data +=
336+
sprintf(
337+
pm8001_ha->forensic_info.data_buf.direct_data,
338+
"%08x ", 0xFFFFFFFF);
339+
return((char *)
340+
pm8001_ha->forensic_info.data_buf.direct_data
341+
- (char *)buf);
342+
}
343+
/* Poll status register until set to 2 or
344+
* 3 for up to 2 seconds
345+
*/
346+
start = jiffies + (2 * HZ); /* 2 sec */
347+
348+
do {
349+
reg_val = pm8001_mr32(fatal_table_address,
350+
MPI_FATAL_EDUMP_TABLE_STATUS);
351+
} while (((reg_val != 2) || (reg_val != 3)) &&
352+
time_before(jiffies, start));
353+
354+
if (reg_val < 2) {
355+
PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
356+
"TIMEOUT:MPI_FATAL_EDUMP_TABLE_STATUS = 0x%x\n",
357+
reg_val));
358+
/* Fail the dump if a timeout occurs */
359+
pm8001_ha->forensic_info.data_buf.direct_data +=
360+
sprintf(
361+
pm8001_ha->forensic_info.data_buf.direct_data,
362+
"%08x ", 0xFFFFFFFF);
363+
pm8001_cw32(pm8001_ha, 0,
364+
MEMBASE_II_SHIFT_REGISTER,
365+
pm8001_ha->fatal_forensic_shift_offset);
366+
}
367+
/* Read the next block of the debug data.*/
368+
length_to_read = pm8001_mr32(fatal_table_address,
369+
MPI_FATAL_EDUMP_TABLE_ACCUM_LEN) -
370+
pm8001_ha->forensic_preserved_accumulated_transfer;
371+
if (length_to_read != 0x0) {
372+
pm8001_ha->forensic_fatal_step = 0;
373+
goto moreData;
374+
} else {
375+
pm8001_ha->forensic_info.data_buf.direct_data +=
376+
sprintf(
377+
pm8001_ha->forensic_info.data_buf.direct_data,
378+
"%08x ", 4);
379+
pm8001_ha->forensic_info.data_buf.read_len
380+
= 0xFFFFFFFF;
381+
pm8001_ha->forensic_info.data_buf.direct_len
382+
= 0;
383+
pm8001_ha->forensic_info.data_buf.direct_offset
384+
= 0;
385+
pm8001_ha->forensic_info.data_buf.read_len = 0;
386+
}
257387
}
258388
}
259-
389+
offset = (int)((char *)pm8001_ha->forensic_info.data_buf.direct_data
390+
- (char *)buf);
391+
PM8001_IO_DBG(pm8001_ha,
392+
pm8001_printk("get_fatal_spcv: return4 0x%x\n", offset));
260393
return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
261394
(char *)buf;
262395
}

0 commit comments

Comments
 (0)