@@ -76,7 +76,7 @@ void pm80xx_pci_mem_copy(struct pm8001_hba_info *pm8001_ha, u32 soffset,
76
76
destination1 = (u32 * )destination ;
77
77
78
78
for (index = 0 ; index < dw_count ; index += 4 , destination1 ++ ) {
79
- offset = (soffset + index / 4 );
79
+ offset = (soffset + index );
80
80
if (offset < (64 * 1024 )) {
81
81
value = pm8001_cr32 (pm8001_ha , bus_base_number , offset );
82
82
* destination1 = cpu_to_le32 (value );
@@ -93,9 +93,12 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
93
93
struct pm8001_hba_info * pm8001_ha = sha -> lldd_ha ;
94
94
void __iomem * fatal_table_address = pm8001_ha -> fatal_tbl_addr ;
95
95
u32 accum_len , reg_val , index , * temp ;
96
+ u32 status = 1 ;
96
97
unsigned long start ;
97
98
u8 * direct_data ;
98
99
char * fatal_error_data = buf ;
100
+ u32 length_to_read ;
101
+ u32 offset ;
99
102
100
103
pm8001_ha -> forensic_info .data_buf .direct_data = buf ;
101
104
if (pm8001_ha -> chip_id == chip_8001 ) {
@@ -105,16 +108,35 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
105
108
return (char * )pm8001_ha -> forensic_info .data_buf .direct_data -
106
109
(char * )buf ;
107
110
}
111
+ /* initialize variables for very first call from host application */
108
112
if (pm8001_ha -> forensic_info .data_buf .direct_offset == 0 ) {
109
113
PM8001_IO_DBG (pm8001_ha ,
110
114
pm8001_printk ("forensic_info TYPE_NON_FATAL..............\n" ));
111
115
direct_data = (u8 * )fatal_error_data ;
112
116
pm8001_ha -> forensic_info .data_type = TYPE_NON_FATAL ;
113
117
pm8001_ha -> forensic_info .data_buf .direct_len = SYSFS_OFFSET ;
118
+ pm8001_ha -> forensic_info .data_buf .direct_offset = 0 ;
114
119
pm8001_ha -> forensic_info .data_buf .read_len = 0 ;
120
+ pm8001_ha -> forensic_preserved_accumulated_transfer = 0 ;
115
121
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 );
117
125
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 ) {
118
140
/* start to get data */
119
141
/* Program the MEMBASE II Shifting Register with 0x00.*/
120
142
pm8001_cw32 (pm8001_ha , 0 , MEMBASE_II_SHIFT_REGISTER ,
@@ -127,30 +149,66 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
127
149
/* Read until accum_len is retrived */
128
150
accum_len = pm8001_mr32 (fatal_table_address ,
129
151
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.*/
132
176
if (accum_len == 0xFFFFFFFF ) {
133
177
PM8001_IO_DBG (pm8001_ha ,
134
178
pm8001_printk ("Possible PCI issue 0x%x not expected\n" ,
135
- accum_len ));
136
- return - EIO ;
179
+ accum_len ));
180
+ return status ;
137
181
}
138
- if (accum_len == 0 || accum_len >= 0x100000 ) {
182
+ /* If accumulated length is zero fail the attempt */
183
+ if (accum_len == 0 ) {
139
184
pm8001_ha -> forensic_info .data_buf .direct_data +=
140
185
sprintf (pm8001_ha -> forensic_info .data_buf .direct_data ,
141
- "%08x " , 0xFFFFFFFF );
186
+ "%08x " , 0xFFFFFFFF );
142
187
return (char * )pm8001_ha -> forensic_info .data_buf .direct_data -
143
188
(char * )buf ;
144
189
}
190
+ /* Accumulated length is good so start capturing the first data */
145
191
temp = (u32 * )pm8001_ha -> memoryMap .region [FORENSIC_MEM ].virt_ptr ;
146
192
if (pm8001_ha -> forensic_fatal_step == 0 ) {
147
193
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
+ }
148
206
if (pm8001_ha -> forensic_info .data_buf .direct_data ) {
149
207
/* 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 );
154
212
}
155
213
pm8001_ha -> fatal_bar_loc +=
156
214
pm8001_ha -> forensic_info .data_buf .direct_len ;
@@ -161,21 +219,29 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
161
219
pm8001_ha -> forensic_info .data_buf .read_len =
162
220
pm8001_ha -> forensic_info .data_buf .direct_len ;
163
221
164
- if (pm8001_ha -> forensic_last_offset >= accum_len ) {
222
+ if (pm8001_ha -> forensic_last_offset >= length_to_read ) {
165
223
pm8001_ha -> forensic_info .data_buf .direct_data +=
166
224
sprintf (pm8001_ha -> forensic_info .data_buf .direct_data ,
167
225
"%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 ++ ) {
169
229
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 ));
173
233
}
174
234
175
235
pm8001_ha -> fatal_bar_loc = 0 ;
176
236
pm8001_ha -> forensic_fatal_step = 1 ;
177
237
pm8001_ha -> fatal_forensic_shift_offset = 0 ;
178
238
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 ));
179
245
return (char * )pm8001_ha ->
180
246
forensic_info .data_buf .direct_data -
181
247
(char * )buf ;
@@ -185,12 +251,20 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
185
251
sprintf (pm8001_ha ->
186
252
forensic_info .data_buf .direct_data ,
187
253
"%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 ->
191
259
forensic_info .data_buf .direct_data ,
192
260
"%08x " , * (temp + index ));
193
261
}
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 ));
194
268
return (char * )pm8001_ha ->
195
269
forensic_info .data_buf .direct_data -
196
270
(char * )buf ;
@@ -200,63 +274,122 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
200
274
pm8001_ha -> forensic_info .data_buf .direct_data +=
201
275
sprintf (pm8001_ha -> forensic_info .data_buf .direct_data ,
202
276
"%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 ++ ) {
204
280
pm8001_ha -> forensic_info .data_buf .direct_data +=
205
281
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 ));
208
284
}
209
285
pm8001_ha -> fatal_forensic_shift_offset += 0x100 ;
210
286
pm8001_cw32 (pm8001_ha , 0 , MEMBASE_II_SHIFT_REGISTER ,
211
287
pm8001_ha -> fatal_forensic_shift_offset );
212
288
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 ));
213
295
return (char * )pm8001_ha -> forensic_info .data_buf .direct_data -
214
296
(char * )buf ;
215
297
}
216
298
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 ,
223
320
MPI_FATAL_EDUMP_HANDSHAKE_RDY );
224
321
225
- /* Poll FDDHSHK until clear */
226
- start = jiffies + (2 * HZ ); /* 2 sec */
322
+ /* Poll FDDHSHK until clear */
323
+ start = jiffies + (2 * HZ ); /* 2 sec */
227
324
228
- do {
229
- reg_val = pm8001_mr32 (fatal_table_address ,
325
+ do {
326
+ reg_val = pm8001_mr32 (fatal_table_address ,
230
327
MPI_FATAL_EDUMP_TABLE_HANDSHAKE );
231
- } while ((reg_val ) && time_before (jiffies , start ));
328
+ } while ((reg_val ) && time_before (jiffies , start ));
232
329
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
+ }
257
387
}
258
388
}
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 ));
260
393
return (char * )pm8001_ha -> forensic_info .data_buf .direct_data -
261
394
(char * )buf ;
262
395
}
0 commit comments