This source file includes following definitions.
- qla8044_rd_reg
- qla8044_wr_reg
- qla8044_rd_direct
- qla8044_wr_direct
- qla8044_set_win_base
- qla8044_rd_reg_indirect
- qla8044_wr_reg_indirect
- qla8044_read_write_crb_reg
- qla8044_poll_wait_for_ready
- qla8044_ipmdio_rd_reg
- qla8044_poll_wait_ipmdio_bus_idle
- qla8044_ipmdio_wr_reg
- qla8044_rmw_crb_reg
- qla8044_set_qsnt_ready
- qla8044_clear_qsnt_ready
- qla8044_lock_recovery
- qla8044_idc_lock
- qla8044_idc_unlock
- qla8044_flash_lock
- qla8044_flash_unlock
- qla8044_flash_lock_recovery
- qla8044_read_flash_data
- qla8044_read_optrom_data
- qla8044_need_reset
- qla8044_write_list
- qla8044_read_write_list
- qla8044_poll_reg
- qla8044_poll_list
- qla8044_poll_write_list
- qla8044_read_modify_write
- qla8044_pause
- qla8044_template_end
- qla8044_poll_read_list
- qla8044_process_reset_template
- qla8044_process_init_seq
- qla8044_process_stop_seq
- qla8044_process_start_seq
- qla8044_lockless_flash_read_u32
- qla8044_ms_mem_write_128b
- qla8044_copy_bootloader
- qla8044_restart
- qla8044_check_cmd_peg_status
- qla8044_start_firmware
- qla8044_clear_drv_active
- qla8044_device_bootstrap
- qla8044_dump_reset_seq_hdr
- qla8044_reset_seq_checksum_test
- qla8044_read_reset_template
- qla8044_set_idc_dontreset
- qla8044_set_rst_ready
- qla8044_need_reset_handler
- qla8044_set_drv_active
- qla8044_check_drv_active
- qla8044_clear_idc_dontreset
- qla8044_set_idc_ver
- qla8044_update_idc_reg
- qla8044_need_qsnt_handler
- qla8044_device_state_handler
- qla8044_check_temp
- qla8044_read_temperature
- qla8044_check_fw_alive
- qla8044_watchdog
- qla8044_minidump_process_control
- qla8044_minidump_process_rdcrb
- qla8044_minidump_process_rdmem
- qla8044_minidump_process_rdrom
- qla8044_mark_entry_skipped
- qla8044_minidump_process_l2tag
- qla8044_minidump_process_l1cache
- qla8044_minidump_process_rdocm
- qla8044_minidump_process_rdmux
- qla8044_minidump_process_queue
- qla8044_minidump_process_pollrd
- qla8044_minidump_process_rdmux2
- qla8044_minidump_process_pollrdmwr
- qla8044_check_dma_engine_state
- qla8044_start_pex_dma
- qla8044_minidump_pex_dma_read
- qla8044_minidump_process_rddfe
- qla8044_minidump_process_rdmdio
- qla8044_minidump_process_pollwr
- qla8044_collect_md_data
- qla8044_get_minidump
- qla8044_poll_flash_status_reg
- qla8044_write_flash_status_reg
- qla8044_unprotect_flash
- qla8044_protect_flash
- qla8044_erase_flash_sector
- qla8044_flash_write_u32
- qla8044_write_flash_buffer_mode
- qla8044_write_flash_dword_mode
- qla8044_write_optrom_data
- qla8044_intr_handler
- qla8044_idc_dontreset
- qla8044_clear_rst_ready
- qla8044_abort_isp
- qla8044_fw_dump
1
2
3
4
5
6
7
8 #include <linux/vmalloc.h>
9 #include <linux/delay.h>
10
11 #include "qla_def.h"
12 #include "qla_gbl.h"
13
14 #define TIMEOUT_100_MS 100
15
16 static const uint32_t qla8044_reg_tbl[] = {
17 QLA8044_PEG_HALT_STATUS1,
18 QLA8044_PEG_HALT_STATUS2,
19 QLA8044_PEG_ALIVE_COUNTER,
20 QLA8044_CRB_DRV_ACTIVE,
21 QLA8044_CRB_DEV_STATE,
22 QLA8044_CRB_DRV_STATE,
23 QLA8044_CRB_DRV_SCRATCH,
24 QLA8044_CRB_DEV_PART_INFO1,
25 QLA8044_CRB_IDC_VER_MAJOR,
26 QLA8044_FW_VER_MAJOR,
27 QLA8044_FW_VER_MINOR,
28 QLA8044_FW_VER_SUB,
29 QLA8044_CMDPEG_STATE,
30 QLA8044_ASIC_TEMP,
31 };
32
33
34 uint32_t
35 qla8044_rd_reg(struct qla_hw_data *ha, ulong addr)
36 {
37 return readl((void __iomem *) (ha->nx_pcibase + addr));
38 }
39
40 void
41 qla8044_wr_reg(struct qla_hw_data *ha, ulong addr, uint32_t val)
42 {
43 writel(val, (void __iomem *)((ha)->nx_pcibase + addr));
44 }
45
46 int
47 qla8044_rd_direct(struct scsi_qla_host *vha,
48 const uint32_t crb_reg)
49 {
50 struct qla_hw_data *ha = vha->hw;
51
52 if (crb_reg < CRB_REG_INDEX_MAX)
53 return qla8044_rd_reg(ha, qla8044_reg_tbl[crb_reg]);
54 else
55 return QLA_FUNCTION_FAILED;
56 }
57
58 void
59 qla8044_wr_direct(struct scsi_qla_host *vha,
60 const uint32_t crb_reg,
61 const uint32_t value)
62 {
63 struct qla_hw_data *ha = vha->hw;
64
65 if (crb_reg < CRB_REG_INDEX_MAX)
66 qla8044_wr_reg(ha, qla8044_reg_tbl[crb_reg], value);
67 }
68
69 static int
70 qla8044_set_win_base(scsi_qla_host_t *vha, uint32_t addr)
71 {
72 uint32_t val;
73 int ret_val = QLA_SUCCESS;
74 struct qla_hw_data *ha = vha->hw;
75
76 qla8044_wr_reg(ha, QLA8044_CRB_WIN_FUNC(ha->portnum), addr);
77 val = qla8044_rd_reg(ha, QLA8044_CRB_WIN_FUNC(ha->portnum));
78
79 if (val != addr) {
80 ql_log(ql_log_warn, vha, 0xb087,
81 "%s: Failed to set register window : "
82 "addr written 0x%x, read 0x%x!\n",
83 __func__, addr, val);
84 ret_val = QLA_FUNCTION_FAILED;
85 }
86 return ret_val;
87 }
88
89 static int
90 qla8044_rd_reg_indirect(scsi_qla_host_t *vha, uint32_t addr, uint32_t *data)
91 {
92 int ret_val = QLA_SUCCESS;
93 struct qla_hw_data *ha = vha->hw;
94
95 ret_val = qla8044_set_win_base(vha, addr);
96 if (!ret_val)
97 *data = qla8044_rd_reg(ha, QLA8044_WILDCARD);
98 else
99 ql_log(ql_log_warn, vha, 0xb088,
100 "%s: failed read of addr 0x%x!\n", __func__, addr);
101 return ret_val;
102 }
103
104 static int
105 qla8044_wr_reg_indirect(scsi_qla_host_t *vha, uint32_t addr, uint32_t data)
106 {
107 int ret_val = QLA_SUCCESS;
108 struct qla_hw_data *ha = vha->hw;
109
110 ret_val = qla8044_set_win_base(vha, addr);
111 if (!ret_val)
112 qla8044_wr_reg(ha, QLA8044_WILDCARD, data);
113 else
114 ql_log(ql_log_warn, vha, 0xb089,
115 "%s: failed wrt to addr 0x%x, data 0x%x\n",
116 __func__, addr, data);
117 return ret_val;
118 }
119
120
121
122
123
124
125
126
127
128 static void
129 qla8044_read_write_crb_reg(struct scsi_qla_host *vha,
130 uint32_t raddr, uint32_t waddr)
131 {
132 uint32_t value;
133
134 qla8044_rd_reg_indirect(vha, raddr, &value);
135 qla8044_wr_reg_indirect(vha, waddr, value);
136 }
137
138 static int
139 qla8044_poll_wait_for_ready(struct scsi_qla_host *vha, uint32_t addr1,
140 uint32_t mask)
141 {
142 unsigned long timeout;
143 uint32_t temp;
144
145
146 timeout = jiffies + msecs_to_jiffies(TIMEOUT_100_MS);
147 do {
148 qla8044_rd_reg_indirect(vha, addr1, &temp);
149 if ((temp & mask) != 0)
150 break;
151 if (time_after_eq(jiffies, timeout)) {
152 ql_log(ql_log_warn, vha, 0xb151,
153 "Error in processing rdmdio entry\n");
154 return -1;
155 }
156 } while (1);
157
158 return 0;
159 }
160
161 static uint32_t
162 qla8044_ipmdio_rd_reg(struct scsi_qla_host *vha,
163 uint32_t addr1, uint32_t addr3, uint32_t mask, uint32_t addr)
164 {
165 uint32_t temp;
166 int ret = 0;
167
168 ret = qla8044_poll_wait_for_ready(vha, addr1, mask);
169 if (ret == -1)
170 return -1;
171
172 temp = (0x40000000 | addr);
173 qla8044_wr_reg_indirect(vha, addr1, temp);
174
175 ret = qla8044_poll_wait_for_ready(vha, addr1, mask);
176 if (ret == -1)
177 return 0;
178
179 qla8044_rd_reg_indirect(vha, addr3, &ret);
180
181 return ret;
182 }
183
184
185 static int
186 qla8044_poll_wait_ipmdio_bus_idle(struct scsi_qla_host *vha,
187 uint32_t addr1, uint32_t addr2, uint32_t addr3, uint32_t mask)
188 {
189 unsigned long timeout;
190 uint32_t temp;
191
192
193 timeout = jiffies + msecs_to_jiffies(TIMEOUT_100_MS);
194 do {
195 temp = qla8044_ipmdio_rd_reg(vha, addr1, addr3, mask, addr2);
196 if ((temp & 0x1) != 1)
197 break;
198 if (time_after_eq(jiffies, timeout)) {
199 ql_log(ql_log_warn, vha, 0xb152,
200 "Error in processing mdiobus idle\n");
201 return -1;
202 }
203 } while (1);
204
205 return 0;
206 }
207
208 static int
209 qla8044_ipmdio_wr_reg(struct scsi_qla_host *vha, uint32_t addr1,
210 uint32_t addr3, uint32_t mask, uint32_t addr, uint32_t value)
211 {
212 int ret = 0;
213
214 ret = qla8044_poll_wait_for_ready(vha, addr1, mask);
215 if (ret == -1)
216 return -1;
217
218 qla8044_wr_reg_indirect(vha, addr3, value);
219 qla8044_wr_reg_indirect(vha, addr1, addr);
220
221 ret = qla8044_poll_wait_for_ready(vha, addr1, mask);
222 if (ret == -1)
223 return -1;
224
225 return 0;
226 }
227
228
229
230
231
232
233
234
235
236
237 static void
238 qla8044_rmw_crb_reg(struct scsi_qla_host *vha,
239 uint32_t raddr, uint32_t waddr, struct qla8044_rmw *p_rmw_hdr)
240 {
241 uint32_t value;
242
243 if (p_rmw_hdr->index_a)
244 value = vha->reset_tmplt.array[p_rmw_hdr->index_a];
245 else
246 qla8044_rd_reg_indirect(vha, raddr, &value);
247 value &= p_rmw_hdr->test_mask;
248 value <<= p_rmw_hdr->shl;
249 value >>= p_rmw_hdr->shr;
250 value |= p_rmw_hdr->or_value;
251 value ^= p_rmw_hdr->xor_value;
252 qla8044_wr_reg_indirect(vha, waddr, value);
253 return;
254 }
255
256 static inline void
257 qla8044_set_qsnt_ready(struct scsi_qla_host *vha)
258 {
259 uint32_t qsnt_state;
260 struct qla_hw_data *ha = vha->hw;
261
262 qsnt_state = qla8044_rd_direct(vha, QLA8044_CRB_DRV_STATE_INDEX);
263 qsnt_state |= (1 << ha->portnum);
264 qla8044_wr_direct(vha, QLA8044_CRB_DRV_STATE_INDEX, qsnt_state);
265 ql_log(ql_log_info, vha, 0xb08e, "%s(%ld): qsnt_state: 0x%08x\n",
266 __func__, vha->host_no, qsnt_state);
267 }
268
269 void
270 qla8044_clear_qsnt_ready(struct scsi_qla_host *vha)
271 {
272 uint32_t qsnt_state;
273 struct qla_hw_data *ha = vha->hw;
274
275 qsnt_state = qla8044_rd_direct(vha, QLA8044_CRB_DRV_STATE_INDEX);
276 qsnt_state &= ~(1 << ha->portnum);
277 qla8044_wr_direct(vha, QLA8044_CRB_DRV_STATE_INDEX, qsnt_state);
278 ql_log(ql_log_info, vha, 0xb08f, "%s(%ld): qsnt_state: 0x%08x\n",
279 __func__, vha->host_no, qsnt_state);
280 }
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307 static int
308 qla8044_lock_recovery(struct scsi_qla_host *vha)
309 {
310 uint32_t lock = 0, lockid;
311 struct qla_hw_data *ha = vha->hw;
312
313 lockid = qla8044_rd_reg(ha, QLA8044_DRV_LOCKRECOVERY);
314
315
316 if ((lockid & IDC_LOCK_RECOVERY_STATE_MASK) != 0)
317 return QLA_FUNCTION_FAILED;
318
319
320 qla8044_wr_reg(ha, QLA8044_DRV_LOCKRECOVERY,
321 (ha->portnum <<
322 IDC_LOCK_RECOVERY_STATE_SHIFT_BITS) | INTENT_TO_RECOVER);
323 msleep(200);
324
325
326 lockid = qla8044_rd_reg(ha, QLA8044_DRV_LOCKRECOVERY);
327 if ((lockid & IDC_LOCK_RECOVERY_OWNER_MASK) != (ha->portnum <<
328 IDC_LOCK_RECOVERY_STATE_SHIFT_BITS))
329 return QLA_FUNCTION_FAILED;
330
331 ql_dbg(ql_dbg_p3p, vha, 0xb08B, "%s:%d: IDC Lock recovery initiated\n"
332 , __func__, ha->portnum);
333
334
335 qla8044_wr_reg(ha, QLA8044_DRV_LOCKRECOVERY,
336 (ha->portnum << IDC_LOCK_RECOVERY_STATE_SHIFT_BITS) |
337 PROCEED_TO_RECOVER);
338
339
340 qla8044_wr_reg(ha, QLA8044_DRV_LOCK_ID, 0xFF);
341 qla8044_rd_reg(ha, QLA8044_DRV_UNLOCK);
342
343
344 qla8044_wr_reg(ha, QLA8044_DRV_LOCKRECOVERY, 0);
345
346
347 lock = qla8044_rd_reg(ha, QLA8044_DRV_LOCK);
348 if (lock) {
349 lockid = qla8044_rd_reg(ha, QLA8044_DRV_LOCK_ID);
350 lockid = ((lockid + (1 << 8)) & ~0xFF) | ha->portnum;
351 qla8044_wr_reg(ha, QLA8044_DRV_LOCK_ID, lockid);
352 return QLA_SUCCESS;
353 } else
354 return QLA_FUNCTION_FAILED;
355 }
356
357 int
358 qla8044_idc_lock(struct qla_hw_data *ha)
359 {
360 uint32_t ret_val = QLA_SUCCESS, timeout = 0, status = 0;
361 uint32_t lock_id, lock_cnt, func_num, tmo_owner = 0, first_owner = 0;
362 scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
363
364 while (status == 0) {
365
366 status = qla8044_rd_reg(ha, QLA8044_DRV_LOCK);
367
368 if (status) {
369
370
371 lock_id = qla8044_rd_reg(ha, QLA8044_DRV_LOCK_ID);
372 lock_id = ((lock_id + (1 << 8)) & ~0xFF) | ha->portnum;
373 qla8044_wr_reg(ha, QLA8044_DRV_LOCK_ID, lock_id);
374 break;
375 }
376
377 if (timeout == 0)
378 first_owner = qla8044_rd_reg(ha, QLA8044_DRV_LOCK_ID);
379
380 if (++timeout >=
381 (QLA8044_DRV_LOCK_TIMEOUT / QLA8044_DRV_LOCK_MSLEEP)) {
382 tmo_owner = qla8044_rd_reg(ha, QLA8044_DRV_LOCK_ID);
383 func_num = tmo_owner & 0xFF;
384 lock_cnt = tmo_owner >> 8;
385 ql_log(ql_log_warn, vha, 0xb114,
386 "%s: Lock by func %d failed after 2s, lock held "
387 "by func %d, lock count %d, first_owner %d\n",
388 __func__, ha->portnum, func_num, lock_cnt,
389 (first_owner & 0xFF));
390 if (first_owner != tmo_owner) {
391
392
393
394
395 ql_dbg(ql_dbg_p3p, vha, 0xb115,
396 "%s: %d: IDC lock failed\n",
397 __func__, ha->portnum);
398 timeout = 0;
399 } else {
400
401
402 if (qla8044_lock_recovery(vha) == QLA_SUCCESS) {
403
404 ret_val = QLA_SUCCESS;
405 ql_dbg(ql_dbg_p3p, vha, 0xb116,
406 "%s:IDC lock Recovery by %d"
407 "successful...\n", __func__,
408 ha->portnum);
409 }
410
411
412
413
414 ql_dbg(ql_dbg_p3p, vha, 0xb08a,
415 "%s: IDC lock Recovery by %d "
416 "failed, Retrying timeout\n", __func__,
417 ha->portnum);
418 timeout = 0;
419 }
420 }
421 msleep(QLA8044_DRV_LOCK_MSLEEP);
422 }
423 return ret_val;
424 }
425
426 void
427 qla8044_idc_unlock(struct qla_hw_data *ha)
428 {
429 int id;
430 scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
431
432 id = qla8044_rd_reg(ha, QLA8044_DRV_LOCK_ID);
433
434 if ((id & 0xFF) != ha->portnum) {
435 ql_log(ql_log_warn, vha, 0xb118,
436 "%s: IDC Unlock by %d failed, lock owner is %d!\n",
437 __func__, ha->portnum, (id & 0xFF));
438 return;
439 }
440
441
442 qla8044_wr_reg(ha, QLA8044_DRV_LOCK_ID, (id | 0xFF));
443 qla8044_rd_reg(ha, QLA8044_DRV_UNLOCK);
444 }
445
446
447 static int
448 qla8044_flash_lock(scsi_qla_host_t *vha)
449 {
450 int lock_owner;
451 int timeout = 0;
452 uint32_t lock_status = 0;
453 int ret_val = QLA_SUCCESS;
454 struct qla_hw_data *ha = vha->hw;
455
456 while (lock_status == 0) {
457 lock_status = qla8044_rd_reg(ha, QLA8044_FLASH_LOCK);
458 if (lock_status)
459 break;
460
461 if (++timeout >= QLA8044_FLASH_LOCK_TIMEOUT / 20) {
462 lock_owner = qla8044_rd_reg(ha,
463 QLA8044_FLASH_LOCK_ID);
464 ql_log(ql_log_warn, vha, 0xb113,
465 "%s: Simultaneous flash access by following ports, active port = %d: accessing port = %d",
466 __func__, ha->portnum, lock_owner);
467 ret_val = QLA_FUNCTION_FAILED;
468 break;
469 }
470 msleep(20);
471 }
472 qla8044_wr_reg(ha, QLA8044_FLASH_LOCK_ID, ha->portnum);
473 return ret_val;
474 }
475
476 static void
477 qla8044_flash_unlock(scsi_qla_host_t *vha)
478 {
479 struct qla_hw_data *ha = vha->hw;
480
481
482 qla8044_wr_reg(ha, QLA8044_FLASH_LOCK_ID, 0xFF);
483 qla8044_rd_reg(ha, QLA8044_FLASH_UNLOCK);
484 }
485
486
487 static
488 void qla8044_flash_lock_recovery(struct scsi_qla_host *vha)
489 {
490
491 if (qla8044_flash_lock(vha)) {
492
493 ql_log(ql_log_warn, vha, 0xb120, "Resetting flash_lock\n");
494 }
495
496
497
498
499
500
501 qla8044_flash_unlock(vha);
502 }
503
504
505
506
507 static int
508 qla8044_read_flash_data(scsi_qla_host_t *vha, uint8_t *p_data,
509 uint32_t flash_addr, int u32_word_count)
510 {
511 int i, ret_val = QLA_SUCCESS;
512 uint32_t u32_word;
513
514 if (qla8044_flash_lock(vha) != QLA_SUCCESS) {
515 ret_val = QLA_FUNCTION_FAILED;
516 goto exit_lock_error;
517 }
518
519 if (flash_addr & 0x03) {
520 ql_log(ql_log_warn, vha, 0xb117,
521 "%s: Illegal addr = 0x%x\n", __func__, flash_addr);
522 ret_val = QLA_FUNCTION_FAILED;
523 goto exit_flash_read;
524 }
525
526 for (i = 0; i < u32_word_count; i++) {
527 if (qla8044_wr_reg_indirect(vha, QLA8044_FLASH_DIRECT_WINDOW,
528 (flash_addr & 0xFFFF0000))) {
529 ql_log(ql_log_warn, vha, 0xb119,
530 "%s: failed to write addr 0x%x to "
531 "FLASH_DIRECT_WINDOW\n! ",
532 __func__, flash_addr);
533 ret_val = QLA_FUNCTION_FAILED;
534 goto exit_flash_read;
535 }
536
537 ret_val = qla8044_rd_reg_indirect(vha,
538 QLA8044_FLASH_DIRECT_DATA(flash_addr),
539 &u32_word);
540 if (ret_val != QLA_SUCCESS) {
541 ql_log(ql_log_warn, vha, 0xb08c,
542 "%s: failed to read addr 0x%x!\n",
543 __func__, flash_addr);
544 goto exit_flash_read;
545 }
546
547 *(uint32_t *)p_data = u32_word;
548 p_data = p_data + 4;
549 flash_addr = flash_addr + 4;
550 }
551
552 exit_flash_read:
553 qla8044_flash_unlock(vha);
554
555 exit_lock_error:
556 return ret_val;
557 }
558
559
560
561
562 void *
563 qla8044_read_optrom_data(struct scsi_qla_host *vha, void *buf,
564 uint32_t offset, uint32_t length)
565 {
566 scsi_block_requests(vha->host);
567 if (qla8044_read_flash_data(vha, buf, offset, length / 4)
568 != QLA_SUCCESS) {
569 ql_log(ql_log_warn, vha, 0xb08d,
570 "%s: Failed to read from flash\n",
571 __func__);
572 }
573 scsi_unblock_requests(vha->host);
574 return buf;
575 }
576
577 static inline int
578 qla8044_need_reset(struct scsi_qla_host *vha)
579 {
580 uint32_t drv_state, drv_active;
581 int rval;
582 struct qla_hw_data *ha = vha->hw;
583
584 drv_active = qla8044_rd_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX);
585 drv_state = qla8044_rd_direct(vha, QLA8044_CRB_DRV_STATE_INDEX);
586
587 rval = drv_state & (1 << ha->portnum);
588
589 if (ha->flags.eeh_busy && drv_active)
590 rval = 1;
591 return rval;
592 }
593
594
595
596
597
598
599
600
601
602
603 static void
604 qla8044_write_list(struct scsi_qla_host *vha,
605 struct qla8044_reset_entry_hdr *p_hdr)
606 {
607 struct qla8044_entry *p_entry;
608 uint32_t i;
609
610 p_entry = (struct qla8044_entry *)((char *)p_hdr +
611 sizeof(struct qla8044_reset_entry_hdr));
612
613 for (i = 0; i < p_hdr->count; i++, p_entry++) {
614 qla8044_wr_reg_indirect(vha, p_entry->arg1, p_entry->arg2);
615 if (p_hdr->delay)
616 udelay((uint32_t)(p_hdr->delay));
617 }
618 }
619
620
621
622
623
624
625
626
627
628
629 static void
630 qla8044_read_write_list(struct scsi_qla_host *vha,
631 struct qla8044_reset_entry_hdr *p_hdr)
632 {
633 struct qla8044_entry *p_entry;
634 uint32_t i;
635
636 p_entry = (struct qla8044_entry *)((char *)p_hdr +
637 sizeof(struct qla8044_reset_entry_hdr));
638
639 for (i = 0; i < p_hdr->count; i++, p_entry++) {
640 qla8044_read_write_crb_reg(vha, p_entry->arg1,
641 p_entry->arg2);
642 if (p_hdr->delay)
643 udelay((uint32_t)(p_hdr->delay));
644 }
645 }
646
647
648
649
650
651
652
653
654
655
656
657
658
659 static int
660 qla8044_poll_reg(struct scsi_qla_host *vha, uint32_t addr,
661 int duration, uint32_t test_mask, uint32_t test_result)
662 {
663 uint32_t value;
664 int timeout_error;
665 uint8_t retries;
666 int ret_val = QLA_SUCCESS;
667
668 ret_val = qla8044_rd_reg_indirect(vha, addr, &value);
669 if (ret_val == QLA_FUNCTION_FAILED) {
670 timeout_error = 1;
671 goto exit_poll_reg;
672 }
673
674
675 retries = duration/10;
676
677 do {
678 if ((value & test_mask) != test_result) {
679 timeout_error = 1;
680 msleep(duration/10);
681 ret_val = qla8044_rd_reg_indirect(vha, addr, &value);
682 if (ret_val == QLA_FUNCTION_FAILED) {
683 timeout_error = 1;
684 goto exit_poll_reg;
685 }
686 } else {
687 timeout_error = 0;
688 break;
689 }
690 } while (retries--);
691
692 exit_poll_reg:
693 if (timeout_error) {
694 vha->reset_tmplt.seq_error++;
695 ql_log(ql_log_fatal, vha, 0xb090,
696 "%s: Poll Failed: 0x%08x 0x%08x 0x%08x\n",
697 __func__, value, test_mask, test_result);
698 }
699
700 return timeout_error;
701 }
702
703
704
705
706
707
708
709
710
711
712 static void
713 qla8044_poll_list(struct scsi_qla_host *vha,
714 struct qla8044_reset_entry_hdr *p_hdr)
715 {
716 long delay;
717 struct qla8044_entry *p_entry;
718 struct qla8044_poll *p_poll;
719 uint32_t i;
720 uint32_t value;
721
722 p_poll = (struct qla8044_poll *)
723 ((char *)p_hdr + sizeof(struct qla8044_reset_entry_hdr));
724
725
726
727
728 p_entry = (struct qla8044_entry *)((char *)p_poll +
729 sizeof(struct qla8044_poll));
730
731 delay = (long)p_hdr->delay;
732
733 if (!delay) {
734 for (i = 0; i < p_hdr->count; i++, p_entry++)
735 qla8044_poll_reg(vha, p_entry->arg1,
736 delay, p_poll->test_mask, p_poll->test_value);
737 } else {
738 for (i = 0; i < p_hdr->count; i++, p_entry++) {
739 if (delay) {
740 if (qla8044_poll_reg(vha,
741 p_entry->arg1, delay,
742 p_poll->test_mask,
743 p_poll->test_value)) {
744
745
746
747
748
749 qla8044_rd_reg_indirect(vha,
750 p_entry->arg1, &value);
751 qla8044_rd_reg_indirect(vha,
752 p_entry->arg2, &value);
753 }
754 }
755 }
756 }
757 }
758
759
760
761
762
763
764
765
766
767
768 static void
769 qla8044_poll_write_list(struct scsi_qla_host *vha,
770 struct qla8044_reset_entry_hdr *p_hdr)
771 {
772 long delay;
773 struct qla8044_quad_entry *p_entry;
774 struct qla8044_poll *p_poll;
775 uint32_t i;
776
777 p_poll = (struct qla8044_poll *)((char *)p_hdr +
778 sizeof(struct qla8044_reset_entry_hdr));
779
780 p_entry = (struct qla8044_quad_entry *)((char *)p_poll +
781 sizeof(struct qla8044_poll));
782
783 delay = (long)p_hdr->delay;
784
785 for (i = 0; i < p_hdr->count; i++, p_entry++) {
786 qla8044_wr_reg_indirect(vha,
787 p_entry->dr_addr, p_entry->dr_value);
788 qla8044_wr_reg_indirect(vha,
789 p_entry->ar_addr, p_entry->ar_value);
790 if (delay) {
791 if (qla8044_poll_reg(vha,
792 p_entry->ar_addr, delay,
793 p_poll->test_mask,
794 p_poll->test_value)) {
795 ql_dbg(ql_dbg_p3p, vha, 0xb091,
796 "%s: Timeout Error: poll list, ",
797 __func__);
798 ql_dbg(ql_dbg_p3p, vha, 0xb092,
799 "item_num %d, entry_num %d\n", i,
800 vha->reset_tmplt.seq_index);
801 }
802 }
803 }
804 }
805
806
807
808
809
810
811
812
813
814
815 static void
816 qla8044_read_modify_write(struct scsi_qla_host *vha,
817 struct qla8044_reset_entry_hdr *p_hdr)
818 {
819 struct qla8044_entry *p_entry;
820 struct qla8044_rmw *p_rmw_hdr;
821 uint32_t i;
822
823 p_rmw_hdr = (struct qla8044_rmw *)((char *)p_hdr +
824 sizeof(struct qla8044_reset_entry_hdr));
825
826 p_entry = (struct qla8044_entry *)((char *)p_rmw_hdr +
827 sizeof(struct qla8044_rmw));
828
829 for (i = 0; i < p_hdr->count; i++, p_entry++) {
830 qla8044_rmw_crb_reg(vha, p_entry->arg1,
831 p_entry->arg2, p_rmw_hdr);
832 if (p_hdr->delay)
833 udelay((uint32_t)(p_hdr->delay));
834 }
835 }
836
837
838
839
840
841
842
843
844
845 static
846 void qla8044_pause(struct scsi_qla_host *vha,
847 struct qla8044_reset_entry_hdr *p_hdr)
848 {
849 if (p_hdr->delay)
850 mdelay((uint32_t)((long)p_hdr->delay));
851 }
852
853
854
855
856
857
858
859
860 static void
861 qla8044_template_end(struct scsi_qla_host *vha,
862 struct qla8044_reset_entry_hdr *p_hdr)
863 {
864 vha->reset_tmplt.template_end = 1;
865
866 if (vha->reset_tmplt.seq_error == 0) {
867 ql_dbg(ql_dbg_p3p, vha, 0xb093,
868 "%s: Reset sequence completed SUCCESSFULLY.\n", __func__);
869 } else {
870 ql_log(ql_log_fatal, vha, 0xb094,
871 "%s: Reset sequence completed with some timeout "
872 "errors.\n", __func__);
873 }
874 }
875
876
877
878
879
880
881
882
883
884
885 static void
886 qla8044_poll_read_list(struct scsi_qla_host *vha,
887 struct qla8044_reset_entry_hdr *p_hdr)
888 {
889 long delay;
890 int index;
891 struct qla8044_quad_entry *p_entry;
892 struct qla8044_poll *p_poll;
893 uint32_t i;
894 uint32_t value;
895
896 p_poll = (struct qla8044_poll *)
897 ((char *)p_hdr + sizeof(struct qla8044_reset_entry_hdr));
898
899 p_entry = (struct qla8044_quad_entry *)
900 ((char *)p_poll + sizeof(struct qla8044_poll));
901
902 delay = (long)p_hdr->delay;
903
904 for (i = 0; i < p_hdr->count; i++, p_entry++) {
905 qla8044_wr_reg_indirect(vha, p_entry->ar_addr,
906 p_entry->ar_value);
907 if (delay) {
908 if (qla8044_poll_reg(vha, p_entry->ar_addr, delay,
909 p_poll->test_mask, p_poll->test_value)) {
910 ql_dbg(ql_dbg_p3p, vha, 0xb095,
911 "%s: Timeout Error: poll "
912 "list, ", __func__);
913 ql_dbg(ql_dbg_p3p, vha, 0xb096,
914 "Item_num %d, "
915 "entry_num %d\n", i,
916 vha->reset_tmplt.seq_index);
917 } else {
918 index = vha->reset_tmplt.array_index;
919 qla8044_rd_reg_indirect(vha,
920 p_entry->dr_addr, &value);
921 vha->reset_tmplt.array[index++] = value;
922 if (index == QLA8044_MAX_RESET_SEQ_ENTRIES)
923 vha->reset_tmplt.array_index = 1;
924 }
925 }
926 }
927 }
928
929
930
931
932
933
934
935
936
937
938
939
940 static void
941 qla8044_process_reset_template(struct scsi_qla_host *vha,
942 char *p_buff)
943 {
944 int index, entries;
945 struct qla8044_reset_entry_hdr *p_hdr;
946 char *p_entry = p_buff;
947
948 vha->reset_tmplt.seq_end = 0;
949 vha->reset_tmplt.template_end = 0;
950 entries = vha->reset_tmplt.hdr->entries;
951 index = vha->reset_tmplt.seq_index;
952
953 for (; (!vha->reset_tmplt.seq_end) && (index < entries); index++) {
954 p_hdr = (struct qla8044_reset_entry_hdr *)p_entry;
955 switch (p_hdr->cmd) {
956 case OPCODE_NOP:
957 break;
958 case OPCODE_WRITE_LIST:
959 qla8044_write_list(vha, p_hdr);
960 break;
961 case OPCODE_READ_WRITE_LIST:
962 qla8044_read_write_list(vha, p_hdr);
963 break;
964 case OPCODE_POLL_LIST:
965 qla8044_poll_list(vha, p_hdr);
966 break;
967 case OPCODE_POLL_WRITE_LIST:
968 qla8044_poll_write_list(vha, p_hdr);
969 break;
970 case OPCODE_READ_MODIFY_WRITE:
971 qla8044_read_modify_write(vha, p_hdr);
972 break;
973 case OPCODE_SEQ_PAUSE:
974 qla8044_pause(vha, p_hdr);
975 break;
976 case OPCODE_SEQ_END:
977 vha->reset_tmplt.seq_end = 1;
978 break;
979 case OPCODE_TMPL_END:
980 qla8044_template_end(vha, p_hdr);
981 break;
982 case OPCODE_POLL_READ_LIST:
983 qla8044_poll_read_list(vha, p_hdr);
984 break;
985 default:
986 ql_log(ql_log_fatal, vha, 0xb097,
987 "%s: Unknown command ==> 0x%04x on "
988 "entry = %d\n", __func__, p_hdr->cmd, index);
989 break;
990 }
991
992
993
994 p_entry += p_hdr->size;
995 }
996 vha->reset_tmplt.seq_index = index;
997 }
998
999 static void
1000 qla8044_process_init_seq(struct scsi_qla_host *vha)
1001 {
1002 qla8044_process_reset_template(vha,
1003 vha->reset_tmplt.init_offset);
1004 if (vha->reset_tmplt.seq_end != 1)
1005 ql_log(ql_log_fatal, vha, 0xb098,
1006 "%s: Abrupt INIT Sub-Sequence end.\n",
1007 __func__);
1008 }
1009
1010 static void
1011 qla8044_process_stop_seq(struct scsi_qla_host *vha)
1012 {
1013 vha->reset_tmplt.seq_index = 0;
1014 qla8044_process_reset_template(vha, vha->reset_tmplt.stop_offset);
1015 if (vha->reset_tmplt.seq_end != 1)
1016 ql_log(ql_log_fatal, vha, 0xb099,
1017 "%s: Abrupt STOP Sub-Sequence end.\n", __func__);
1018 }
1019
1020 static void
1021 qla8044_process_start_seq(struct scsi_qla_host *vha)
1022 {
1023 qla8044_process_reset_template(vha, vha->reset_tmplt.start_offset);
1024 if (vha->reset_tmplt.template_end != 1)
1025 ql_log(ql_log_fatal, vha, 0xb09a,
1026 "%s: Abrupt START Sub-Sequence end.\n",
1027 __func__);
1028 }
1029
1030 static int
1031 qla8044_lockless_flash_read_u32(struct scsi_qla_host *vha,
1032 uint32_t flash_addr, uint8_t *p_data, int u32_word_count)
1033 {
1034 uint32_t i;
1035 uint32_t u32_word;
1036 uint32_t flash_offset;
1037 uint32_t addr = flash_addr;
1038 int ret_val = QLA_SUCCESS;
1039
1040 flash_offset = addr & (QLA8044_FLASH_SECTOR_SIZE - 1);
1041
1042 if (addr & 0x3) {
1043 ql_log(ql_log_fatal, vha, 0xb09b, "%s: Illegal addr = 0x%x\n",
1044 __func__, addr);
1045 ret_val = QLA_FUNCTION_FAILED;
1046 goto exit_lockless_read;
1047 }
1048
1049 ret_val = qla8044_wr_reg_indirect(vha,
1050 QLA8044_FLASH_DIRECT_WINDOW, (addr));
1051
1052 if (ret_val != QLA_SUCCESS) {
1053 ql_log(ql_log_fatal, vha, 0xb09c,
1054 "%s: failed to write addr 0x%x to FLASH_DIRECT_WINDOW!\n",
1055 __func__, addr);
1056 goto exit_lockless_read;
1057 }
1058
1059
1060 if ((flash_offset + (u32_word_count * sizeof(uint32_t))) >
1061 (QLA8044_FLASH_SECTOR_SIZE - 1)) {
1062
1063 for (i = 0; i < u32_word_count; i++) {
1064 ret_val = qla8044_rd_reg_indirect(vha,
1065 QLA8044_FLASH_DIRECT_DATA(addr), &u32_word);
1066 if (ret_val != QLA_SUCCESS) {
1067 ql_log(ql_log_fatal, vha, 0xb09d,
1068 "%s: failed to read addr 0x%x!\n",
1069 __func__, addr);
1070 goto exit_lockless_read;
1071 }
1072 *(uint32_t *)p_data = u32_word;
1073 p_data = p_data + 4;
1074 addr = addr + 4;
1075 flash_offset = flash_offset + 4;
1076 if (flash_offset > (QLA8044_FLASH_SECTOR_SIZE - 1)) {
1077
1078 ret_val = qla8044_wr_reg_indirect(vha,
1079 QLA8044_FLASH_DIRECT_WINDOW, (addr));
1080 if (ret_val != QLA_SUCCESS) {
1081 ql_log(ql_log_fatal, vha, 0xb09f,
1082 "%s: failed to write addr "
1083 "0x%x to FLASH_DIRECT_WINDOW!\n",
1084 __func__, addr);
1085 goto exit_lockless_read;
1086 }
1087 flash_offset = 0;
1088 }
1089 }
1090 } else {
1091
1092 for (i = 0; i < u32_word_count; i++) {
1093 ret_val = qla8044_rd_reg_indirect(vha,
1094 QLA8044_FLASH_DIRECT_DATA(addr), &u32_word);
1095 if (ret_val != QLA_SUCCESS) {
1096 ql_log(ql_log_fatal, vha, 0xb0a0,
1097 "%s: failed to read addr 0x%x!\n",
1098 __func__, addr);
1099 goto exit_lockless_read;
1100 }
1101 *(uint32_t *)p_data = u32_word;
1102 p_data = p_data + 4;
1103 addr = addr + 4;
1104 }
1105 }
1106
1107 exit_lockless_read:
1108 return ret_val;
1109 }
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121 static int
1122 qla8044_ms_mem_write_128b(struct scsi_qla_host *vha,
1123 uint64_t addr, uint32_t *data, uint32_t count)
1124 {
1125 int i, j, ret_val = QLA_SUCCESS;
1126 uint32_t agt_ctrl;
1127 unsigned long flags;
1128 struct qla_hw_data *ha = vha->hw;
1129
1130
1131 if (addr & 0xF) {
1132 ret_val = QLA_FUNCTION_FAILED;
1133 goto exit_ms_mem_write;
1134 }
1135 write_lock_irqsave(&ha->hw_lock, flags);
1136
1137
1138 ret_val = qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_ADDR_HI, 0);
1139 if (ret_val == QLA_FUNCTION_FAILED) {
1140 ql_log(ql_log_fatal, vha, 0xb0a1,
1141 "%s: write to AGT_ADDR_HI failed!\n", __func__);
1142 goto exit_ms_mem_write_unlock;
1143 }
1144
1145 for (i = 0; i < count; i++, addr += 16) {
1146 if (!((addr_in_range(addr, QLA8044_ADDR_QDR_NET,
1147 QLA8044_ADDR_QDR_NET_MAX)) ||
1148 (addr_in_range(addr, QLA8044_ADDR_DDR_NET,
1149 QLA8044_ADDR_DDR_NET_MAX)))) {
1150 ret_val = QLA_FUNCTION_FAILED;
1151 goto exit_ms_mem_write_unlock;
1152 }
1153
1154 ret_val = qla8044_wr_reg_indirect(vha,
1155 MD_MIU_TEST_AGT_ADDR_LO, addr);
1156
1157
1158 ret_val += qla8044_wr_reg_indirect(vha,
1159 MD_MIU_TEST_AGT_WRDATA_LO, *data++);
1160 ret_val += qla8044_wr_reg_indirect(vha,
1161 MD_MIU_TEST_AGT_WRDATA_HI, *data++);
1162 ret_val += qla8044_wr_reg_indirect(vha,
1163 MD_MIU_TEST_AGT_WRDATA_ULO, *data++);
1164 ret_val += qla8044_wr_reg_indirect(vha,
1165 MD_MIU_TEST_AGT_WRDATA_UHI, *data++);
1166 if (ret_val == QLA_FUNCTION_FAILED) {
1167 ql_log(ql_log_fatal, vha, 0xb0a2,
1168 "%s: write to AGT_WRDATA failed!\n",
1169 __func__);
1170 goto exit_ms_mem_write_unlock;
1171 }
1172
1173
1174 ret_val = qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_CTRL,
1175 MIU_TA_CTL_WRITE_ENABLE);
1176 ret_val += qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_CTRL,
1177 MIU_TA_CTL_WRITE_START);
1178 if (ret_val == QLA_FUNCTION_FAILED) {
1179 ql_log(ql_log_fatal, vha, 0xb0a3,
1180 "%s: write to AGT_CTRL failed!\n", __func__);
1181 goto exit_ms_mem_write_unlock;
1182 }
1183
1184 for (j = 0; j < MAX_CTL_CHECK; j++) {
1185 ret_val = qla8044_rd_reg_indirect(vha,
1186 MD_MIU_TEST_AGT_CTRL, &agt_ctrl);
1187 if (ret_val == QLA_FUNCTION_FAILED) {
1188 ql_log(ql_log_fatal, vha, 0xb0a4,
1189 "%s: failed to read "
1190 "MD_MIU_TEST_AGT_CTRL!\n", __func__);
1191 goto exit_ms_mem_write_unlock;
1192 }
1193 if ((agt_ctrl & MIU_TA_CTL_BUSY) == 0)
1194 break;
1195 }
1196
1197
1198 if (j >= MAX_CTL_CHECK) {
1199 ql_log(ql_log_fatal, vha, 0xb0a5,
1200 "%s: MS memory write failed!\n",
1201 __func__);
1202 ret_val = QLA_FUNCTION_FAILED;
1203 goto exit_ms_mem_write_unlock;
1204 }
1205 }
1206
1207 exit_ms_mem_write_unlock:
1208 write_unlock_irqrestore(&ha->hw_lock, flags);
1209
1210 exit_ms_mem_write:
1211 return ret_val;
1212 }
1213
1214 static int
1215 qla8044_copy_bootloader(struct scsi_qla_host *vha)
1216 {
1217 uint8_t *p_cache;
1218 uint32_t src, count, size;
1219 uint64_t dest;
1220 int ret_val = QLA_SUCCESS;
1221 struct qla_hw_data *ha = vha->hw;
1222
1223 src = QLA8044_BOOTLOADER_FLASH_ADDR;
1224 dest = qla8044_rd_reg(ha, QLA8044_BOOTLOADER_ADDR);
1225 size = qla8044_rd_reg(ha, QLA8044_BOOTLOADER_SIZE);
1226
1227
1228 if (size & 0xF)
1229 size = (size + 16) & ~0xF;
1230
1231
1232 count = size/16;
1233
1234 p_cache = vmalloc(size);
1235 if (p_cache == NULL) {
1236 ql_log(ql_log_fatal, vha, 0xb0a6,
1237 "%s: Failed to allocate memory for "
1238 "boot loader cache\n", __func__);
1239 ret_val = QLA_FUNCTION_FAILED;
1240 goto exit_copy_bootloader;
1241 }
1242
1243 ret_val = qla8044_lockless_flash_read_u32(vha, src,
1244 p_cache, size/sizeof(uint32_t));
1245 if (ret_val == QLA_FUNCTION_FAILED) {
1246 ql_log(ql_log_fatal, vha, 0xb0a7,
1247 "%s: Error reading F/W from flash!!!\n", __func__);
1248 goto exit_copy_error;
1249 }
1250 ql_dbg(ql_dbg_p3p, vha, 0xb0a8, "%s: Read F/W from flash!\n",
1251 __func__);
1252
1253
1254 ret_val = qla8044_ms_mem_write_128b(vha, dest,
1255 (uint32_t *)p_cache, count);
1256 if (ret_val == QLA_FUNCTION_FAILED) {
1257 ql_log(ql_log_fatal, vha, 0xb0a9,
1258 "%s: Error writing F/W to MS !!!\n", __func__);
1259 goto exit_copy_error;
1260 }
1261 ql_dbg(ql_dbg_p3p, vha, 0xb0aa,
1262 "%s: Wrote F/W (size %d) to MS !!!\n",
1263 __func__, size);
1264
1265 exit_copy_error:
1266 vfree(p_cache);
1267
1268 exit_copy_bootloader:
1269 return ret_val;
1270 }
1271
1272 static int
1273 qla8044_restart(struct scsi_qla_host *vha)
1274 {
1275 int ret_val = QLA_SUCCESS;
1276 struct qla_hw_data *ha = vha->hw;
1277
1278 qla8044_process_stop_seq(vha);
1279
1280
1281 if (ql2xmdenable)
1282 qla8044_get_minidump(vha);
1283 else
1284 ql_log(ql_log_fatal, vha, 0xb14c,
1285 "Minidump disabled.\n");
1286
1287 qla8044_process_init_seq(vha);
1288
1289 if (qla8044_copy_bootloader(vha)) {
1290 ql_log(ql_log_fatal, vha, 0xb0ab,
1291 "%s: Copy bootloader, firmware restart failed!\n",
1292 __func__);
1293 ret_val = QLA_FUNCTION_FAILED;
1294 goto exit_restart;
1295 }
1296
1297
1298
1299
1300 qla8044_wr_reg(ha, QLA8044_FW_IMAGE_VALID, QLA8044_BOOT_FROM_FLASH);
1301
1302 qla8044_process_start_seq(vha);
1303
1304 exit_restart:
1305 return ret_val;
1306 }
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316 static int
1317 qla8044_check_cmd_peg_status(struct scsi_qla_host *vha)
1318 {
1319 uint32_t val, ret_val = QLA_FUNCTION_FAILED;
1320 int retries = CRB_CMDPEG_CHECK_RETRY_COUNT;
1321 struct qla_hw_data *ha = vha->hw;
1322
1323 do {
1324 val = qla8044_rd_reg(ha, QLA8044_CMDPEG_STATE);
1325 if (val == PHAN_INITIALIZE_COMPLETE) {
1326 ql_dbg(ql_dbg_p3p, vha, 0xb0ac,
1327 "%s: Command Peg initialization "
1328 "complete! state=0x%x\n", __func__, val);
1329 ret_val = QLA_SUCCESS;
1330 break;
1331 }
1332 msleep(CRB_CMDPEG_CHECK_DELAY);
1333 } while (--retries);
1334
1335 return ret_val;
1336 }
1337
1338 static int
1339 qla8044_start_firmware(struct scsi_qla_host *vha)
1340 {
1341 int ret_val = QLA_SUCCESS;
1342
1343 if (qla8044_restart(vha)) {
1344 ql_log(ql_log_fatal, vha, 0xb0ad,
1345 "%s: Restart Error!!!, Need Reset!!!\n",
1346 __func__);
1347 ret_val = QLA_FUNCTION_FAILED;
1348 goto exit_start_fw;
1349 } else
1350 ql_dbg(ql_dbg_p3p, vha, 0xb0af,
1351 "%s: Restart done!\n", __func__);
1352
1353 ret_val = qla8044_check_cmd_peg_status(vha);
1354 if (ret_val) {
1355 ql_log(ql_log_fatal, vha, 0xb0b0,
1356 "%s: Peg not initialized!\n", __func__);
1357 ret_val = QLA_FUNCTION_FAILED;
1358 }
1359
1360 exit_start_fw:
1361 return ret_val;
1362 }
1363
1364 void
1365 qla8044_clear_drv_active(struct qla_hw_data *ha)
1366 {
1367 uint32_t drv_active;
1368 struct scsi_qla_host *vha = pci_get_drvdata(ha->pdev);
1369
1370 drv_active = qla8044_rd_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX);
1371 drv_active &= ~(1 << (ha->portnum));
1372
1373 ql_log(ql_log_info, vha, 0xb0b1,
1374 "%s(%ld): drv_active: 0x%08x\n",
1375 __func__, vha->host_no, drv_active);
1376
1377 qla8044_wr_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX, drv_active);
1378 }
1379
1380
1381
1382
1383
1384
1385
1386 static int
1387 qla8044_device_bootstrap(struct scsi_qla_host *vha)
1388 {
1389 int rval = QLA_FUNCTION_FAILED;
1390 int i;
1391 uint32_t old_count = 0, count = 0;
1392 int need_reset = 0;
1393 uint32_t idc_ctrl;
1394 struct qla_hw_data *ha = vha->hw;
1395
1396 need_reset = qla8044_need_reset(vha);
1397
1398 if (!need_reset) {
1399 old_count = qla8044_rd_direct(vha,
1400 QLA8044_PEG_ALIVE_COUNTER_INDEX);
1401
1402 for (i = 0; i < 10; i++) {
1403 msleep(200);
1404
1405 count = qla8044_rd_direct(vha,
1406 QLA8044_PEG_ALIVE_COUNTER_INDEX);
1407 if (count != old_count) {
1408 rval = QLA_SUCCESS;
1409 goto dev_ready;
1410 }
1411 }
1412 qla8044_flash_lock_recovery(vha);
1413 } else {
1414
1415 if (ha->flags.isp82xx_fw_hung)
1416 qla8044_flash_lock_recovery(vha);
1417 }
1418
1419
1420 ql_log(ql_log_info, vha, 0xb0b2,
1421 "%s: HW State: INITIALIZING\n", __func__);
1422 qla8044_wr_direct(vha, QLA8044_CRB_DEV_STATE_INDEX,
1423 QLA8XXX_DEV_INITIALIZING);
1424
1425 qla8044_idc_unlock(ha);
1426 rval = qla8044_start_firmware(vha);
1427 qla8044_idc_lock(ha);
1428
1429 if (rval != QLA_SUCCESS) {
1430 ql_log(ql_log_info, vha, 0xb0b3,
1431 "%s: HW State: FAILED\n", __func__);
1432 qla8044_clear_drv_active(ha);
1433 qla8044_wr_direct(vha, QLA8044_CRB_DEV_STATE_INDEX,
1434 QLA8XXX_DEV_FAILED);
1435 return rval;
1436 }
1437
1438
1439
1440 idc_ctrl = qla8044_rd_reg(ha, QLA8044_IDC_DRV_CTRL);
1441 if (idc_ctrl & GRACEFUL_RESET_BIT1) {
1442 qla8044_wr_reg(ha, QLA8044_IDC_DRV_CTRL,
1443 (idc_ctrl & ~GRACEFUL_RESET_BIT1));
1444 ha->fw_dumped = 0;
1445 }
1446
1447 dev_ready:
1448 ql_log(ql_log_info, vha, 0xb0b4,
1449 "%s: HW State: READY\n", __func__);
1450 qla8044_wr_direct(vha, QLA8044_CRB_DEV_STATE_INDEX, QLA8XXX_DEV_READY);
1451
1452 return rval;
1453 }
1454
1455
1456 static void
1457 qla8044_dump_reset_seq_hdr(struct scsi_qla_host *vha)
1458 {
1459 u8 *phdr;
1460
1461 if (!vha->reset_tmplt.buff) {
1462 ql_log(ql_log_fatal, vha, 0xb0b5,
1463 "%s: Error Invalid reset_seq_template\n", __func__);
1464 return;
1465 }
1466
1467 phdr = vha->reset_tmplt.buff;
1468 ql_dbg(ql_dbg_p3p, vha, 0xb0b6,
1469 "Reset Template :\n\t0x%X 0x%X 0x%X 0x%X"
1470 "0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n"
1471 "\t0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n\n",
1472 *phdr, *(phdr+1), *(phdr+2), *(phdr+3), *(phdr+4),
1473 *(phdr+5), *(phdr+6), *(phdr+7), *(phdr + 8),
1474 *(phdr+9), *(phdr+10), *(phdr+11), *(phdr+12),
1475 *(phdr+13), *(phdr+14), *(phdr+15));
1476 }
1477
1478
1479
1480
1481
1482
1483
1484
1485 static int
1486 qla8044_reset_seq_checksum_test(struct scsi_qla_host *vha)
1487 {
1488 uint32_t sum = 0;
1489 uint16_t *buff = (uint16_t *)vha->reset_tmplt.buff;
1490 int u16_count = vha->reset_tmplt.hdr->size / sizeof(uint16_t);
1491
1492 while (u16_count-- > 0)
1493 sum += *buff++;
1494
1495 while (sum >> 16)
1496 sum = (sum & 0xFFFF) + (sum >> 16);
1497
1498
1499 if (~sum) {
1500 return QLA_SUCCESS;
1501 } else {
1502 ql_log(ql_log_fatal, vha, 0xb0b7,
1503 "%s: Reset seq checksum failed\n", __func__);
1504 return QLA_FUNCTION_FAILED;
1505 }
1506 }
1507
1508
1509
1510
1511
1512
1513
1514 void
1515 qla8044_read_reset_template(struct scsi_qla_host *vha)
1516 {
1517 uint8_t *p_buff;
1518 uint32_t addr, tmplt_hdr_def_size, tmplt_hdr_size;
1519
1520 vha->reset_tmplt.seq_error = 0;
1521 vha->reset_tmplt.buff = vmalloc(QLA8044_RESTART_TEMPLATE_SIZE);
1522 if (vha->reset_tmplt.buff == NULL) {
1523 ql_log(ql_log_fatal, vha, 0xb0b8,
1524 "%s: Failed to allocate reset template resources\n",
1525 __func__);
1526 goto exit_read_reset_template;
1527 }
1528
1529 p_buff = vha->reset_tmplt.buff;
1530 addr = QLA8044_RESET_TEMPLATE_ADDR;
1531
1532 tmplt_hdr_def_size =
1533 sizeof(struct qla8044_reset_template_hdr) / sizeof(uint32_t);
1534
1535 ql_dbg(ql_dbg_p3p, vha, 0xb0b9,
1536 "%s: Read template hdr size %d from Flash\n",
1537 __func__, tmplt_hdr_def_size);
1538
1539
1540 if (qla8044_read_flash_data(vha, p_buff, addr, tmplt_hdr_def_size)) {
1541 ql_log(ql_log_fatal, vha, 0xb0ba,
1542 "%s: Failed to read reset template\n", __func__);
1543 goto exit_read_template_error;
1544 }
1545
1546 vha->reset_tmplt.hdr =
1547 (struct qla8044_reset_template_hdr *) vha->reset_tmplt.buff;
1548
1549
1550 tmplt_hdr_size = vha->reset_tmplt.hdr->hdr_size/sizeof(uint32_t);
1551 if ((tmplt_hdr_size != tmplt_hdr_def_size) ||
1552 (vha->reset_tmplt.hdr->signature != RESET_TMPLT_HDR_SIGNATURE)) {
1553 ql_log(ql_log_fatal, vha, 0xb0bb,
1554 "%s: Template Header size invalid %d "
1555 "tmplt_hdr_def_size %d!!!\n", __func__,
1556 tmplt_hdr_size, tmplt_hdr_def_size);
1557 goto exit_read_template_error;
1558 }
1559
1560 addr = QLA8044_RESET_TEMPLATE_ADDR + vha->reset_tmplt.hdr->hdr_size;
1561 p_buff = vha->reset_tmplt.buff + vha->reset_tmplt.hdr->hdr_size;
1562 tmplt_hdr_def_size = (vha->reset_tmplt.hdr->size -
1563 vha->reset_tmplt.hdr->hdr_size)/sizeof(uint32_t);
1564
1565 ql_dbg(ql_dbg_p3p, vha, 0xb0bc,
1566 "%s: Read rest of the template size %d\n",
1567 __func__, vha->reset_tmplt.hdr->size);
1568
1569
1570 if (qla8044_read_flash_data(vha, p_buff, addr, tmplt_hdr_def_size)) {
1571 ql_log(ql_log_fatal, vha, 0xb0bd,
1572 "%s: Failed to read reset template\n", __func__);
1573 goto exit_read_template_error;
1574 }
1575
1576
1577 if (qla8044_reset_seq_checksum_test(vha)) {
1578 ql_log(ql_log_fatal, vha, 0xb0be,
1579 "%s: Reset Seq checksum failed!\n", __func__);
1580 goto exit_read_template_error;
1581 }
1582
1583 ql_dbg(ql_dbg_p3p, vha, 0xb0bf,
1584 "%s: Reset Seq checksum passed! Get stop, "
1585 "start and init seq offsets\n", __func__);
1586
1587
1588 vha->reset_tmplt.init_offset = vha->reset_tmplt.buff +
1589 vha->reset_tmplt.hdr->init_seq_offset;
1590
1591 vha->reset_tmplt.start_offset = vha->reset_tmplt.buff +
1592 vha->reset_tmplt.hdr->start_seq_offset;
1593
1594 vha->reset_tmplt.stop_offset = vha->reset_tmplt.buff +
1595 vha->reset_tmplt.hdr->hdr_size;
1596
1597 qla8044_dump_reset_seq_hdr(vha);
1598
1599 goto exit_read_reset_template;
1600
1601 exit_read_template_error:
1602 vfree(vha->reset_tmplt.buff);
1603
1604 exit_read_reset_template:
1605 return;
1606 }
1607
1608 void
1609 qla8044_set_idc_dontreset(struct scsi_qla_host *vha)
1610 {
1611 uint32_t idc_ctrl;
1612 struct qla_hw_data *ha = vha->hw;
1613
1614 idc_ctrl = qla8044_rd_reg(ha, QLA8044_IDC_DRV_CTRL);
1615 idc_ctrl |= DONTRESET_BIT0;
1616 ql_dbg(ql_dbg_p3p, vha, 0xb0c0,
1617 "%s: idc_ctrl = %d\n", __func__, idc_ctrl);
1618 qla8044_wr_reg(ha, QLA8044_IDC_DRV_CTRL, idc_ctrl);
1619 }
1620
1621 static inline void
1622 qla8044_set_rst_ready(struct scsi_qla_host *vha)
1623 {
1624 uint32_t drv_state;
1625 struct qla_hw_data *ha = vha->hw;
1626
1627 drv_state = qla8044_rd_direct(vha, QLA8044_CRB_DRV_STATE_INDEX);
1628
1629
1630
1631 drv_state |= (1 << ha->portnum);
1632
1633 ql_log(ql_log_info, vha, 0xb0c1,
1634 "%s(%ld): drv_state: 0x%08x\n",
1635 __func__, vha->host_no, drv_state);
1636 qla8044_wr_direct(vha, QLA8044_CRB_DRV_STATE_INDEX, drv_state);
1637 }
1638
1639
1640
1641
1642
1643
1644
1645 static void
1646 qla8044_need_reset_handler(struct scsi_qla_host *vha)
1647 {
1648 uint32_t dev_state = 0, drv_state, drv_active;
1649 unsigned long reset_timeout;
1650 struct qla_hw_data *ha = vha->hw;
1651
1652 ql_log(ql_log_fatal, vha, 0xb0c2,
1653 "%s: Performing ISP error recovery\n", __func__);
1654
1655 if (vha->flags.online) {
1656 qla8044_idc_unlock(ha);
1657 qla2x00_abort_isp_cleanup(vha);
1658 ha->isp_ops->get_flash_version(vha, vha->req->ring);
1659 ha->isp_ops->nvram_config(vha);
1660 qla8044_idc_lock(ha);
1661 }
1662
1663 dev_state = qla8044_rd_direct(vha,
1664 QLA8044_CRB_DEV_STATE_INDEX);
1665 drv_state = qla8044_rd_direct(vha,
1666 QLA8044_CRB_DRV_STATE_INDEX);
1667 drv_active = qla8044_rd_direct(vha,
1668 QLA8044_CRB_DRV_ACTIVE_INDEX);
1669
1670 ql_log(ql_log_info, vha, 0xb0c5,
1671 "%s(%ld): drv_state = 0x%x, drv_active = 0x%x dev_state = 0x%x\n",
1672 __func__, vha->host_no, drv_state, drv_active, dev_state);
1673
1674 qla8044_set_rst_ready(vha);
1675
1676
1677 reset_timeout = jiffies + (ha->fcoe_reset_timeout * HZ);
1678
1679 do {
1680 if (time_after_eq(jiffies, reset_timeout)) {
1681 ql_log(ql_log_info, vha, 0xb0c4,
1682 "%s: Function %d: Reset Ack Timeout!, drv_state: 0x%08x, drv_active: 0x%08x\n",
1683 __func__, ha->portnum, drv_state, drv_active);
1684 break;
1685 }
1686
1687 qla8044_idc_unlock(ha);
1688 msleep(1000);
1689 qla8044_idc_lock(ha);
1690
1691 dev_state = qla8044_rd_direct(vha,
1692 QLA8044_CRB_DEV_STATE_INDEX);
1693 drv_state = qla8044_rd_direct(vha,
1694 QLA8044_CRB_DRV_STATE_INDEX);
1695 drv_active = qla8044_rd_direct(vha,
1696 QLA8044_CRB_DRV_ACTIVE_INDEX);
1697 } while (((drv_state & drv_active) != drv_active) &&
1698 (dev_state == QLA8XXX_DEV_NEED_RESET));
1699
1700
1701 if (drv_state != drv_active) {
1702 ql_log(ql_log_info, vha, 0xb0c7,
1703 "%s(%ld): Function %d turning off drv_active of non-acking function 0x%x\n",
1704 __func__, vha->host_no, ha->portnum,
1705 (drv_active ^ drv_state));
1706 drv_active = drv_active & drv_state;
1707 qla8044_wr_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX,
1708 drv_active);
1709 } else {
1710
1711
1712
1713
1714 if ((ha->flags.nic_core_reset_owner) &&
1715 (dev_state == QLA8XXX_DEV_NEED_RESET)) {
1716 ha->flags.nic_core_reset_owner = 0;
1717 qla8044_device_bootstrap(vha);
1718 return;
1719 }
1720 }
1721
1722
1723 if (!(drv_active & (1 << ha->portnum))) {
1724 ha->flags.nic_core_reset_owner = 0;
1725 return;
1726 }
1727
1728
1729
1730
1731
1732 if (ha->flags.nic_core_reset_owner ||
1733 ((drv_state & drv_active) == QLA8044_FUN7_ACTIVE_INDEX)) {
1734 ha->flags.nic_core_reset_owner = 0;
1735 qla8044_device_bootstrap(vha);
1736 }
1737 }
1738
1739 static void
1740 qla8044_set_drv_active(struct scsi_qla_host *vha)
1741 {
1742 uint32_t drv_active;
1743 struct qla_hw_data *ha = vha->hw;
1744
1745 drv_active = qla8044_rd_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX);
1746
1747
1748
1749 drv_active |= (1 << ha->portnum);
1750
1751 ql_log(ql_log_info, vha, 0xb0c8,
1752 "%s(%ld): drv_active: 0x%08x\n",
1753 __func__, vha->host_no, drv_active);
1754 qla8044_wr_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX, drv_active);
1755 }
1756
1757 static int
1758 qla8044_check_drv_active(struct scsi_qla_host *vha)
1759 {
1760 uint32_t drv_active;
1761 struct qla_hw_data *ha = vha->hw;
1762
1763 drv_active = qla8044_rd_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX);
1764 if (drv_active & (1 << ha->portnum))
1765 return QLA_SUCCESS;
1766 else
1767 return QLA_TEST_FAILED;
1768 }
1769
1770 static void
1771 qla8044_clear_idc_dontreset(struct scsi_qla_host *vha)
1772 {
1773 uint32_t idc_ctrl;
1774 struct qla_hw_data *ha = vha->hw;
1775
1776 idc_ctrl = qla8044_rd_reg(ha, QLA8044_IDC_DRV_CTRL);
1777 idc_ctrl &= ~DONTRESET_BIT0;
1778 ql_log(ql_log_info, vha, 0xb0c9,
1779 "%s: idc_ctrl = %d\n", __func__,
1780 idc_ctrl);
1781 qla8044_wr_reg(ha, QLA8044_IDC_DRV_CTRL, idc_ctrl);
1782 }
1783
1784 static int
1785 qla8044_set_idc_ver(struct scsi_qla_host *vha)
1786 {
1787 int idc_ver;
1788 uint32_t drv_active;
1789 int rval = QLA_SUCCESS;
1790 struct qla_hw_data *ha = vha->hw;
1791
1792 drv_active = qla8044_rd_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX);
1793 if (drv_active == (1 << ha->portnum)) {
1794 idc_ver = qla8044_rd_direct(vha,
1795 QLA8044_CRB_DRV_IDC_VERSION_INDEX);
1796 idc_ver &= (~0xFF);
1797 idc_ver |= QLA8044_IDC_VER_MAJ_VALUE;
1798 qla8044_wr_direct(vha, QLA8044_CRB_DRV_IDC_VERSION_INDEX,
1799 idc_ver);
1800 ql_log(ql_log_info, vha, 0xb0ca,
1801 "%s: IDC version updated to %d\n",
1802 __func__, idc_ver);
1803 } else {
1804 idc_ver = qla8044_rd_direct(vha,
1805 QLA8044_CRB_DRV_IDC_VERSION_INDEX);
1806 idc_ver &= 0xFF;
1807 if (QLA8044_IDC_VER_MAJ_VALUE != idc_ver) {
1808 ql_log(ql_log_info, vha, 0xb0cb,
1809 "%s: qla4xxx driver IDC version %d "
1810 "is not compatible with IDC version %d "
1811 "of other drivers!\n",
1812 __func__, QLA8044_IDC_VER_MAJ_VALUE,
1813 idc_ver);
1814 rval = QLA_FUNCTION_FAILED;
1815 goto exit_set_idc_ver;
1816 }
1817 }
1818
1819
1820 idc_ver = qla8044_rd_reg(ha, QLA8044_CRB_IDC_VER_MINOR);
1821 idc_ver &= ~(0x03 << (ha->portnum * 2));
1822 idc_ver |= (QLA8044_IDC_VER_MIN_VALUE << (ha->portnum * 2));
1823 qla8044_wr_reg(ha, QLA8044_CRB_IDC_VER_MINOR, idc_ver);
1824
1825 exit_set_idc_ver:
1826 return rval;
1827 }
1828
1829 static int
1830 qla8044_update_idc_reg(struct scsi_qla_host *vha)
1831 {
1832 uint32_t drv_active;
1833 int rval = QLA_SUCCESS;
1834 struct qla_hw_data *ha = vha->hw;
1835
1836 if (vha->flags.init_done)
1837 goto exit_update_idc_reg;
1838
1839 qla8044_idc_lock(ha);
1840 qla8044_set_drv_active(vha);
1841
1842 drv_active = qla8044_rd_direct(vha,
1843 QLA8044_CRB_DRV_ACTIVE_INDEX);
1844
1845
1846
1847 if ((drv_active == (1 << ha->portnum)) && !ql2xdontresethba)
1848 qla8044_clear_idc_dontreset(vha);
1849
1850 rval = qla8044_set_idc_ver(vha);
1851 if (rval == QLA_FUNCTION_FAILED)
1852 qla8044_clear_drv_active(ha);
1853 qla8044_idc_unlock(ha);
1854
1855 exit_update_idc_reg:
1856 return rval;
1857 }
1858
1859
1860
1861
1862
1863 static void
1864 qla8044_need_qsnt_handler(struct scsi_qla_host *vha)
1865 {
1866 unsigned long qsnt_timeout;
1867 uint32_t drv_state, drv_active, dev_state;
1868 struct qla_hw_data *ha = vha->hw;
1869
1870 if (vha->flags.online)
1871 qla2x00_quiesce_io(vha);
1872 else
1873 return;
1874
1875 qla8044_set_qsnt_ready(vha);
1876
1877
1878 qsnt_timeout = jiffies + (QSNT_ACK_TOV * HZ);
1879 drv_state = qla8044_rd_direct(vha, QLA8044_CRB_DRV_STATE_INDEX);
1880 drv_active = qla8044_rd_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX);
1881
1882
1883
1884 drv_active = drv_active << 1;
1885
1886 while (drv_state != drv_active) {
1887 if (time_after_eq(jiffies, qsnt_timeout)) {
1888
1889
1890
1891 clear_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
1892 qla8044_wr_direct(vha, QLA8044_CRB_DEV_STATE_INDEX,
1893 QLA8XXX_DEV_READY);
1894 qla8044_clear_qsnt_ready(vha);
1895 ql_log(ql_log_info, vha, 0xb0cc,
1896 "Timeout waiting for quiescent ack!!!\n");
1897 return;
1898 }
1899 qla8044_idc_unlock(ha);
1900 msleep(1000);
1901 qla8044_idc_lock(ha);
1902
1903 drv_state = qla8044_rd_direct(vha,
1904 QLA8044_CRB_DRV_STATE_INDEX);
1905 drv_active = qla8044_rd_direct(vha,
1906 QLA8044_CRB_DRV_ACTIVE_INDEX);
1907 drv_active = drv_active << 1;
1908 }
1909
1910
1911 dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX);
1912
1913 if (dev_state == QLA8XXX_DEV_NEED_QUIESCENT) {
1914 qla8044_wr_direct(vha, QLA8044_CRB_DEV_STATE_INDEX,
1915 QLA8XXX_DEV_QUIESCENT);
1916 ql_log(ql_log_info, vha, 0xb0cd,
1917 "%s: HW State: QUIESCENT\n", __func__);
1918 }
1919 }
1920
1921
1922
1923
1924
1925
1926
1927 int
1928 qla8044_device_state_handler(struct scsi_qla_host *vha)
1929 {
1930 uint32_t dev_state;
1931 int rval = QLA_SUCCESS;
1932 unsigned long dev_init_timeout;
1933 struct qla_hw_data *ha = vha->hw;
1934
1935 rval = qla8044_update_idc_reg(vha);
1936 if (rval == QLA_FUNCTION_FAILED)
1937 goto exit_error;
1938
1939 dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX);
1940 ql_dbg(ql_dbg_p3p, vha, 0xb0ce,
1941 "Device state is 0x%x = %s\n",
1942 dev_state, dev_state < MAX_STATES ?
1943 qdev_state(dev_state) : "Unknown");
1944
1945
1946 dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout * HZ);
1947
1948 qla8044_idc_lock(ha);
1949
1950 while (1) {
1951 if (time_after_eq(jiffies, dev_init_timeout)) {
1952 if (qla8044_check_drv_active(vha) == QLA_SUCCESS) {
1953 ql_log(ql_log_warn, vha, 0xb0cf,
1954 "%s: Device Init Failed 0x%x = %s\n",
1955 QLA2XXX_DRIVER_NAME, dev_state,
1956 dev_state < MAX_STATES ?
1957 qdev_state(dev_state) : "Unknown");
1958 qla8044_wr_direct(vha,
1959 QLA8044_CRB_DEV_STATE_INDEX,
1960 QLA8XXX_DEV_FAILED);
1961 }
1962 }
1963
1964 dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX);
1965 ql_log(ql_log_info, vha, 0xb0d0,
1966 "Device state is 0x%x = %s\n",
1967 dev_state, dev_state < MAX_STATES ?
1968 qdev_state(dev_state) : "Unknown");
1969
1970
1971 switch (dev_state) {
1972 case QLA8XXX_DEV_READY:
1973 ha->flags.nic_core_reset_owner = 0;
1974 goto exit;
1975 case QLA8XXX_DEV_COLD:
1976 rval = qla8044_device_bootstrap(vha);
1977 break;
1978 case QLA8XXX_DEV_INITIALIZING:
1979 qla8044_idc_unlock(ha);
1980 msleep(1000);
1981 qla8044_idc_lock(ha);
1982 break;
1983 case QLA8XXX_DEV_NEED_RESET:
1984
1985
1986
1987 qla8044_need_reset_handler(vha);
1988 break;
1989 case QLA8XXX_DEV_NEED_QUIESCENT:
1990
1991 qla8044_need_qsnt_handler(vha);
1992
1993
1994 dev_init_timeout = jiffies +
1995 (ha->fcoe_reset_timeout * HZ);
1996 break;
1997 case QLA8XXX_DEV_QUIESCENT:
1998 ql_log(ql_log_info, vha, 0xb0d1,
1999 "HW State: QUIESCENT\n");
2000
2001 qla8044_idc_unlock(ha);
2002 msleep(1000);
2003 qla8044_idc_lock(ha);
2004
2005
2006 dev_init_timeout = jiffies +
2007 (ha->fcoe_reset_timeout * HZ);
2008 break;
2009 case QLA8XXX_DEV_FAILED:
2010 ha->flags.nic_core_reset_owner = 0;
2011 qla8044_idc_unlock(ha);
2012 qla8xxx_dev_failed_handler(vha);
2013 rval = QLA_FUNCTION_FAILED;
2014 qla8044_idc_lock(ha);
2015 goto exit;
2016 default:
2017 qla8044_idc_unlock(ha);
2018 qla8xxx_dev_failed_handler(vha);
2019 rval = QLA_FUNCTION_FAILED;
2020 qla8044_idc_lock(ha);
2021 goto exit;
2022 }
2023 }
2024 exit:
2025 qla8044_idc_unlock(ha);
2026
2027 exit_error:
2028 return rval;
2029 }
2030
2031
2032
2033
2034
2035
2036
2037 static int
2038 qla8044_check_temp(struct scsi_qla_host *vha)
2039 {
2040 uint32_t temp, temp_state, temp_val;
2041 int status = QLA_SUCCESS;
2042
2043 temp = qla8044_rd_direct(vha, QLA8044_CRB_TEMP_STATE_INDEX);
2044 temp_state = qla82xx_get_temp_state(temp);
2045 temp_val = qla82xx_get_temp_val(temp);
2046
2047 if (temp_state == QLA82XX_TEMP_PANIC) {
2048 ql_log(ql_log_warn, vha, 0xb0d2,
2049 "Device temperature %d degrees C"
2050 " exceeds maximum allowed. Hardware has been shut"
2051 " down\n", temp_val);
2052 status = QLA_FUNCTION_FAILED;
2053 return status;
2054 } else if (temp_state == QLA82XX_TEMP_WARN) {
2055 ql_log(ql_log_warn, vha, 0xb0d3,
2056 "Device temperature %d"
2057 " degrees C exceeds operating range."
2058 " Immediate action needed.\n", temp_val);
2059 }
2060 return 0;
2061 }
2062
2063 int qla8044_read_temperature(scsi_qla_host_t *vha)
2064 {
2065 uint32_t temp;
2066
2067 temp = qla8044_rd_direct(vha, QLA8044_CRB_TEMP_STATE_INDEX);
2068 return qla82xx_get_temp_val(temp);
2069 }
2070
2071
2072
2073
2074
2075
2076
2077 int
2078 qla8044_check_fw_alive(struct scsi_qla_host *vha)
2079 {
2080 uint32_t fw_heartbeat_counter;
2081 uint32_t halt_status1, halt_status2;
2082 int status = QLA_SUCCESS;
2083
2084 fw_heartbeat_counter = qla8044_rd_direct(vha,
2085 QLA8044_PEG_ALIVE_COUNTER_INDEX);
2086
2087
2088 if (fw_heartbeat_counter == 0xffffffff) {
2089 ql_dbg(ql_dbg_p3p, vha, 0xb0d4,
2090 "scsi%ld: %s: Device in frozen "
2091 "state, QLA82XX_PEG_ALIVE_COUNTER is 0xffffffff\n",
2092 vha->host_no, __func__);
2093 return status;
2094 }
2095
2096 if (vha->fw_heartbeat_counter == fw_heartbeat_counter) {
2097 vha->seconds_since_last_heartbeat++;
2098
2099 if (vha->seconds_since_last_heartbeat == 2) {
2100 vha->seconds_since_last_heartbeat = 0;
2101 halt_status1 = qla8044_rd_direct(vha,
2102 QLA8044_PEG_HALT_STATUS1_INDEX);
2103 halt_status2 = qla8044_rd_direct(vha,
2104 QLA8044_PEG_HALT_STATUS2_INDEX);
2105
2106 ql_log(ql_log_info, vha, 0xb0d5,
2107 "scsi(%ld): %s, ISP8044 "
2108 "Dumping hw/fw registers:\n"
2109 " PEG_HALT_STATUS1: 0x%x, "
2110 "PEG_HALT_STATUS2: 0x%x,\n",
2111 vha->host_no, __func__, halt_status1,
2112 halt_status2);
2113 status = QLA_FUNCTION_FAILED;
2114 }
2115 } else
2116 vha->seconds_since_last_heartbeat = 0;
2117
2118 vha->fw_heartbeat_counter = fw_heartbeat_counter;
2119 return status;
2120 }
2121
2122 void
2123 qla8044_watchdog(struct scsi_qla_host *vha)
2124 {
2125 uint32_t dev_state, halt_status;
2126 int halt_status_unrecoverable = 0;
2127 struct qla_hw_data *ha = vha->hw;
2128
2129
2130 if (!(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
2131 test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags))) {
2132 dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX);
2133
2134 if (qla8044_check_fw_alive(vha)) {
2135 ha->flags.isp82xx_fw_hung = 1;
2136 ql_log(ql_log_warn, vha, 0xb10a,
2137 "Firmware hung.\n");
2138 qla82xx_clear_pending_mbx(vha);
2139 }
2140
2141 if (qla8044_check_temp(vha)) {
2142 set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags);
2143 ha->flags.isp82xx_fw_hung = 1;
2144 qla2xxx_wake_dpc(vha);
2145 } else if (dev_state == QLA8XXX_DEV_NEED_RESET &&
2146 !test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) {
2147 ql_log(ql_log_info, vha, 0xb0d6,
2148 "%s: HW State: NEED RESET!\n",
2149 __func__);
2150 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
2151 qla2xxx_wake_dpc(vha);
2152 } else if (dev_state == QLA8XXX_DEV_NEED_QUIESCENT &&
2153 !test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) {
2154 ql_log(ql_log_info, vha, 0xb0d7,
2155 "%s: HW State: NEED QUIES detected!\n",
2156 __func__);
2157 set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
2158 qla2xxx_wake_dpc(vha);
2159 } else {
2160
2161 if (ha->flags.isp82xx_fw_hung) {
2162 halt_status = qla8044_rd_direct(vha,
2163 QLA8044_PEG_HALT_STATUS1_INDEX);
2164 if (halt_status &
2165 QLA8044_HALT_STATUS_FW_RESET) {
2166 ql_log(ql_log_fatal, vha,
2167 0xb0d8, "%s: Firmware "
2168 "error detected device "
2169 "is being reset\n",
2170 __func__);
2171 } else if (halt_status &
2172 QLA8044_HALT_STATUS_UNRECOVERABLE) {
2173 halt_status_unrecoverable = 1;
2174 }
2175
2176
2177
2178
2179 if (halt_status_unrecoverable) {
2180 set_bit(ISP_UNRECOVERABLE,
2181 &vha->dpc_flags);
2182 } else {
2183 if (dev_state ==
2184 QLA8XXX_DEV_QUIESCENT) {
2185 set_bit(FCOE_CTX_RESET_NEEDED,
2186 &vha->dpc_flags);
2187 ql_log(ql_log_info, vha, 0xb0d9,
2188 "%s: FW CONTEXT Reset "
2189 "needed!\n", __func__);
2190 } else {
2191 ql_log(ql_log_info, vha,
2192 0xb0da, "%s: "
2193 "detect abort needed\n",
2194 __func__);
2195 set_bit(ISP_ABORT_NEEDED,
2196 &vha->dpc_flags);
2197 }
2198 }
2199 qla2xxx_wake_dpc(vha);
2200 }
2201 }
2202
2203 }
2204 }
2205
2206 static int
2207 qla8044_minidump_process_control(struct scsi_qla_host *vha,
2208 struct qla8044_minidump_entry_hdr *entry_hdr)
2209 {
2210 struct qla8044_minidump_entry_crb *crb_entry;
2211 uint32_t read_value, opcode, poll_time, addr, index;
2212 uint32_t crb_addr, rval = QLA_SUCCESS;
2213 unsigned long wtime;
2214 struct qla8044_minidump_template_hdr *tmplt_hdr;
2215 int i;
2216 struct qla_hw_data *ha = vha->hw;
2217
2218 ql_dbg(ql_dbg_p3p, vha, 0xb0dd, "Entering fn: %s\n", __func__);
2219 tmplt_hdr = (struct qla8044_minidump_template_hdr *)
2220 ha->md_tmplt_hdr;
2221 crb_entry = (struct qla8044_minidump_entry_crb *)entry_hdr;
2222
2223 crb_addr = crb_entry->addr;
2224 for (i = 0; i < crb_entry->op_count; i++) {
2225 opcode = crb_entry->crb_ctrl.opcode;
2226
2227 if (opcode & QLA82XX_DBG_OPCODE_WR) {
2228 qla8044_wr_reg_indirect(vha, crb_addr,
2229 crb_entry->value_1);
2230 opcode &= ~QLA82XX_DBG_OPCODE_WR;
2231 }
2232
2233 if (opcode & QLA82XX_DBG_OPCODE_RW) {
2234 qla8044_rd_reg_indirect(vha, crb_addr, &read_value);
2235 qla8044_wr_reg_indirect(vha, crb_addr, read_value);
2236 opcode &= ~QLA82XX_DBG_OPCODE_RW;
2237 }
2238
2239 if (opcode & QLA82XX_DBG_OPCODE_AND) {
2240 qla8044_rd_reg_indirect(vha, crb_addr, &read_value);
2241 read_value &= crb_entry->value_2;
2242 opcode &= ~QLA82XX_DBG_OPCODE_AND;
2243 if (opcode & QLA82XX_DBG_OPCODE_OR) {
2244 read_value |= crb_entry->value_3;
2245 opcode &= ~QLA82XX_DBG_OPCODE_OR;
2246 }
2247 qla8044_wr_reg_indirect(vha, crb_addr, read_value);
2248 }
2249 if (opcode & QLA82XX_DBG_OPCODE_OR) {
2250 qla8044_rd_reg_indirect(vha, crb_addr, &read_value);
2251 read_value |= crb_entry->value_3;
2252 qla8044_wr_reg_indirect(vha, crb_addr, read_value);
2253 opcode &= ~QLA82XX_DBG_OPCODE_OR;
2254 }
2255 if (opcode & QLA82XX_DBG_OPCODE_POLL) {
2256 poll_time = crb_entry->crb_strd.poll_timeout;
2257 wtime = jiffies + poll_time;
2258 qla8044_rd_reg_indirect(vha, crb_addr, &read_value);
2259
2260 do {
2261 if ((read_value & crb_entry->value_2) ==
2262 crb_entry->value_1) {
2263 break;
2264 } else if (time_after_eq(jiffies, wtime)) {
2265
2266 rval = QLA_FUNCTION_FAILED;
2267 break;
2268 } else {
2269 qla8044_rd_reg_indirect(vha,
2270 crb_addr, &read_value);
2271 }
2272 } while (1);
2273 opcode &= ~QLA82XX_DBG_OPCODE_POLL;
2274 }
2275
2276 if (opcode & QLA82XX_DBG_OPCODE_RDSTATE) {
2277 if (crb_entry->crb_strd.state_index_a) {
2278 index = crb_entry->crb_strd.state_index_a;
2279 addr = tmplt_hdr->saved_state_array[index];
2280 } else {
2281 addr = crb_addr;
2282 }
2283
2284 qla8044_rd_reg_indirect(vha, addr, &read_value);
2285 index = crb_entry->crb_ctrl.state_index_v;
2286 tmplt_hdr->saved_state_array[index] = read_value;
2287 opcode &= ~QLA82XX_DBG_OPCODE_RDSTATE;
2288 }
2289
2290 if (opcode & QLA82XX_DBG_OPCODE_WRSTATE) {
2291 if (crb_entry->crb_strd.state_index_a) {
2292 index = crb_entry->crb_strd.state_index_a;
2293 addr = tmplt_hdr->saved_state_array[index];
2294 } else {
2295 addr = crb_addr;
2296 }
2297
2298 if (crb_entry->crb_ctrl.state_index_v) {
2299 index = crb_entry->crb_ctrl.state_index_v;
2300 read_value =
2301 tmplt_hdr->saved_state_array[index];
2302 } else {
2303 read_value = crb_entry->value_1;
2304 }
2305
2306 qla8044_wr_reg_indirect(vha, addr, read_value);
2307 opcode &= ~QLA82XX_DBG_OPCODE_WRSTATE;
2308 }
2309
2310 if (opcode & QLA82XX_DBG_OPCODE_MDSTATE) {
2311 index = crb_entry->crb_ctrl.state_index_v;
2312 read_value = tmplt_hdr->saved_state_array[index];
2313 read_value <<= crb_entry->crb_ctrl.shl;
2314 read_value >>= crb_entry->crb_ctrl.shr;
2315 if (crb_entry->value_2)
2316 read_value &= crb_entry->value_2;
2317 read_value |= crb_entry->value_3;
2318 read_value += crb_entry->value_1;
2319 tmplt_hdr->saved_state_array[index] = read_value;
2320 opcode &= ~QLA82XX_DBG_OPCODE_MDSTATE;
2321 }
2322 crb_addr += crb_entry->crb_strd.addr_stride;
2323 }
2324 return rval;
2325 }
2326
2327 static void
2328 qla8044_minidump_process_rdcrb(struct scsi_qla_host *vha,
2329 struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2330 {
2331 uint32_t r_addr, r_stride, loop_cnt, i, r_value;
2332 struct qla8044_minidump_entry_crb *crb_hdr;
2333 uint32_t *data_ptr = *d_ptr;
2334
2335 ql_dbg(ql_dbg_p3p, vha, 0xb0de, "Entering fn: %s\n", __func__);
2336 crb_hdr = (struct qla8044_minidump_entry_crb *)entry_hdr;
2337 r_addr = crb_hdr->addr;
2338 r_stride = crb_hdr->crb_strd.addr_stride;
2339 loop_cnt = crb_hdr->op_count;
2340
2341 for (i = 0; i < loop_cnt; i++) {
2342 qla8044_rd_reg_indirect(vha, r_addr, &r_value);
2343 *data_ptr++ = r_addr;
2344 *data_ptr++ = r_value;
2345 r_addr += r_stride;
2346 }
2347 *d_ptr = data_ptr;
2348 }
2349
2350 static int
2351 qla8044_minidump_process_rdmem(struct scsi_qla_host *vha,
2352 struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2353 {
2354 uint32_t r_addr, r_value, r_data;
2355 uint32_t i, j, loop_cnt;
2356 struct qla8044_minidump_entry_rdmem *m_hdr;
2357 unsigned long flags;
2358 uint32_t *data_ptr = *d_ptr;
2359 struct qla_hw_data *ha = vha->hw;
2360
2361 ql_dbg(ql_dbg_p3p, vha, 0xb0df, "Entering fn: %s\n", __func__);
2362 m_hdr = (struct qla8044_minidump_entry_rdmem *)entry_hdr;
2363 r_addr = m_hdr->read_addr;
2364 loop_cnt = m_hdr->read_data_size/16;
2365
2366 ql_dbg(ql_dbg_p3p, vha, 0xb0f0,
2367 "[%s]: Read addr: 0x%x, read_data_size: 0x%x\n",
2368 __func__, r_addr, m_hdr->read_data_size);
2369
2370 if (r_addr & 0xf) {
2371 ql_dbg(ql_dbg_p3p, vha, 0xb0f1,
2372 "[%s]: Read addr 0x%x not 16 bytes aligned\n",
2373 __func__, r_addr);
2374 return QLA_FUNCTION_FAILED;
2375 }
2376
2377 if (m_hdr->read_data_size % 16) {
2378 ql_dbg(ql_dbg_p3p, vha, 0xb0f2,
2379 "[%s]: Read data[0x%x] not multiple of 16 bytes\n",
2380 __func__, m_hdr->read_data_size);
2381 return QLA_FUNCTION_FAILED;
2382 }
2383
2384 ql_dbg(ql_dbg_p3p, vha, 0xb0f3,
2385 "[%s]: rdmem_addr: 0x%x, read_data_size: 0x%x, loop_cnt: 0x%x\n",
2386 __func__, r_addr, m_hdr->read_data_size, loop_cnt);
2387
2388 write_lock_irqsave(&ha->hw_lock, flags);
2389 for (i = 0; i < loop_cnt; i++) {
2390 qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_ADDR_LO, r_addr);
2391 r_value = 0;
2392 qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_ADDR_HI, r_value);
2393 r_value = MIU_TA_CTL_ENABLE;
2394 qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_CTRL, r_value);
2395 r_value = MIU_TA_CTL_START_ENABLE;
2396 qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_CTRL, r_value);
2397
2398 for (j = 0; j < MAX_CTL_CHECK; j++) {
2399 qla8044_rd_reg_indirect(vha, MD_MIU_TEST_AGT_CTRL,
2400 &r_value);
2401 if ((r_value & MIU_TA_CTL_BUSY) == 0)
2402 break;
2403 }
2404
2405 if (j >= MAX_CTL_CHECK) {
2406 write_unlock_irqrestore(&ha->hw_lock, flags);
2407 return QLA_SUCCESS;
2408 }
2409
2410 for (j = 0; j < 4; j++) {
2411 qla8044_rd_reg_indirect(vha, MD_MIU_TEST_AGT_RDDATA[j],
2412 &r_data);
2413 *data_ptr++ = r_data;
2414 }
2415
2416 r_addr += 16;
2417 }
2418 write_unlock_irqrestore(&ha->hw_lock, flags);
2419
2420 ql_dbg(ql_dbg_p3p, vha, 0xb0f4,
2421 "Leaving fn: %s datacount: 0x%x\n",
2422 __func__, (loop_cnt * 16));
2423
2424 *d_ptr = data_ptr;
2425 return QLA_SUCCESS;
2426 }
2427
2428
2429 static uint32_t
2430 qla8044_minidump_process_rdrom(struct scsi_qla_host *vha,
2431 struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2432 {
2433 uint32_t fl_addr, u32_count, rval;
2434 struct qla8044_minidump_entry_rdrom *rom_hdr;
2435 uint32_t *data_ptr = *d_ptr;
2436
2437 rom_hdr = (struct qla8044_minidump_entry_rdrom *)entry_hdr;
2438 fl_addr = rom_hdr->read_addr;
2439 u32_count = (rom_hdr->read_data_size)/sizeof(uint32_t);
2440
2441 ql_dbg(ql_dbg_p3p, vha, 0xb0f5, "[%s]: fl_addr: 0x%x, count: 0x%x\n",
2442 __func__, fl_addr, u32_count);
2443
2444 rval = qla8044_lockless_flash_read_u32(vha, fl_addr,
2445 (u8 *)(data_ptr), u32_count);
2446
2447 if (rval != QLA_SUCCESS) {
2448 ql_log(ql_log_fatal, vha, 0xb0f6,
2449 "%s: Flash Read Error,Count=%d\n", __func__, u32_count);
2450 return QLA_FUNCTION_FAILED;
2451 } else {
2452 data_ptr += u32_count;
2453 *d_ptr = data_ptr;
2454 return QLA_SUCCESS;
2455 }
2456 }
2457
2458 static void
2459 qla8044_mark_entry_skipped(struct scsi_qla_host *vha,
2460 struct qla8044_minidump_entry_hdr *entry_hdr, int index)
2461 {
2462 entry_hdr->d_ctrl.driver_flags |= QLA82XX_DBG_SKIPPED_FLAG;
2463
2464 ql_log(ql_log_info, vha, 0xb0f7,
2465 "scsi(%ld): Skipping entry[%d]: ETYPE[0x%x]-ELEVEL[0x%x]\n",
2466 vha->host_no, index, entry_hdr->entry_type,
2467 entry_hdr->d_ctrl.entry_capture_mask);
2468 }
2469
2470 static int
2471 qla8044_minidump_process_l2tag(struct scsi_qla_host *vha,
2472 struct qla8044_minidump_entry_hdr *entry_hdr,
2473 uint32_t **d_ptr)
2474 {
2475 uint32_t addr, r_addr, c_addr, t_r_addr;
2476 uint32_t i, k, loop_count, t_value, r_cnt, r_value;
2477 unsigned long p_wait, w_time, p_mask;
2478 uint32_t c_value_w, c_value_r;
2479 struct qla8044_minidump_entry_cache *cache_hdr;
2480 int rval = QLA_FUNCTION_FAILED;
2481 uint32_t *data_ptr = *d_ptr;
2482
2483 ql_dbg(ql_dbg_p3p, vha, 0xb0f8, "Entering fn: %s\n", __func__);
2484 cache_hdr = (struct qla8044_minidump_entry_cache *)entry_hdr;
2485
2486 loop_count = cache_hdr->op_count;
2487 r_addr = cache_hdr->read_addr;
2488 c_addr = cache_hdr->control_addr;
2489 c_value_w = cache_hdr->cache_ctrl.write_value;
2490
2491 t_r_addr = cache_hdr->tag_reg_addr;
2492 t_value = cache_hdr->addr_ctrl.init_tag_value;
2493 r_cnt = cache_hdr->read_ctrl.read_addr_cnt;
2494 p_wait = cache_hdr->cache_ctrl.poll_wait;
2495 p_mask = cache_hdr->cache_ctrl.poll_mask;
2496
2497 for (i = 0; i < loop_count; i++) {
2498 qla8044_wr_reg_indirect(vha, t_r_addr, t_value);
2499 if (c_value_w)
2500 qla8044_wr_reg_indirect(vha, c_addr, c_value_w);
2501
2502 if (p_mask) {
2503 w_time = jiffies + p_wait;
2504 do {
2505 qla8044_rd_reg_indirect(vha, c_addr,
2506 &c_value_r);
2507 if ((c_value_r & p_mask) == 0) {
2508 break;
2509 } else if (time_after_eq(jiffies, w_time)) {
2510
2511 return rval;
2512 }
2513 } while (1);
2514 }
2515
2516 addr = r_addr;
2517 for (k = 0; k < r_cnt; k++) {
2518 qla8044_rd_reg_indirect(vha, addr, &r_value);
2519 *data_ptr++ = r_value;
2520 addr += cache_hdr->read_ctrl.read_addr_stride;
2521 }
2522 t_value += cache_hdr->addr_ctrl.tag_value_stride;
2523 }
2524 *d_ptr = data_ptr;
2525 return QLA_SUCCESS;
2526 }
2527
2528 static void
2529 qla8044_minidump_process_l1cache(struct scsi_qla_host *vha,
2530 struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2531 {
2532 uint32_t addr, r_addr, c_addr, t_r_addr;
2533 uint32_t i, k, loop_count, t_value, r_cnt, r_value;
2534 uint32_t c_value_w;
2535 struct qla8044_minidump_entry_cache *cache_hdr;
2536 uint32_t *data_ptr = *d_ptr;
2537
2538 cache_hdr = (struct qla8044_minidump_entry_cache *)entry_hdr;
2539 loop_count = cache_hdr->op_count;
2540 r_addr = cache_hdr->read_addr;
2541 c_addr = cache_hdr->control_addr;
2542 c_value_w = cache_hdr->cache_ctrl.write_value;
2543
2544 t_r_addr = cache_hdr->tag_reg_addr;
2545 t_value = cache_hdr->addr_ctrl.init_tag_value;
2546 r_cnt = cache_hdr->read_ctrl.read_addr_cnt;
2547
2548 for (i = 0; i < loop_count; i++) {
2549 qla8044_wr_reg_indirect(vha, t_r_addr, t_value);
2550 qla8044_wr_reg_indirect(vha, c_addr, c_value_w);
2551 addr = r_addr;
2552 for (k = 0; k < r_cnt; k++) {
2553 qla8044_rd_reg_indirect(vha, addr, &r_value);
2554 *data_ptr++ = r_value;
2555 addr += cache_hdr->read_ctrl.read_addr_stride;
2556 }
2557 t_value += cache_hdr->addr_ctrl.tag_value_stride;
2558 }
2559 *d_ptr = data_ptr;
2560 }
2561
2562 static void
2563 qla8044_minidump_process_rdocm(struct scsi_qla_host *vha,
2564 struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2565 {
2566 uint32_t r_addr, r_stride, loop_cnt, i, r_value;
2567 struct qla8044_minidump_entry_rdocm *ocm_hdr;
2568 uint32_t *data_ptr = *d_ptr;
2569 struct qla_hw_data *ha = vha->hw;
2570
2571 ql_dbg(ql_dbg_p3p, vha, 0xb0f9, "Entering fn: %s\n", __func__);
2572
2573 ocm_hdr = (struct qla8044_minidump_entry_rdocm *)entry_hdr;
2574 r_addr = ocm_hdr->read_addr;
2575 r_stride = ocm_hdr->read_addr_stride;
2576 loop_cnt = ocm_hdr->op_count;
2577
2578 ql_dbg(ql_dbg_p3p, vha, 0xb0fa,
2579 "[%s]: r_addr: 0x%x, r_stride: 0x%x, loop_cnt: 0x%x\n",
2580 __func__, r_addr, r_stride, loop_cnt);
2581
2582 for (i = 0; i < loop_cnt; i++) {
2583 r_value = readl((void __iomem *)(r_addr + ha->nx_pcibase));
2584 *data_ptr++ = r_value;
2585 r_addr += r_stride;
2586 }
2587 ql_dbg(ql_dbg_p3p, vha, 0xb0fb, "Leaving fn: %s datacount: 0x%lx\n",
2588 __func__, (long unsigned int) (loop_cnt * sizeof(uint32_t)));
2589
2590 *d_ptr = data_ptr;
2591 }
2592
2593 static void
2594 qla8044_minidump_process_rdmux(struct scsi_qla_host *vha,
2595 struct qla8044_minidump_entry_hdr *entry_hdr,
2596 uint32_t **d_ptr)
2597 {
2598 uint32_t r_addr, s_stride, s_addr, s_value, loop_cnt, i, r_value;
2599 struct qla8044_minidump_entry_mux *mux_hdr;
2600 uint32_t *data_ptr = *d_ptr;
2601
2602 ql_dbg(ql_dbg_p3p, vha, 0xb0fc, "Entering fn: %s\n", __func__);
2603
2604 mux_hdr = (struct qla8044_minidump_entry_mux *)entry_hdr;
2605 r_addr = mux_hdr->read_addr;
2606 s_addr = mux_hdr->select_addr;
2607 s_stride = mux_hdr->select_value_stride;
2608 s_value = mux_hdr->select_value;
2609 loop_cnt = mux_hdr->op_count;
2610
2611 for (i = 0; i < loop_cnt; i++) {
2612 qla8044_wr_reg_indirect(vha, s_addr, s_value);
2613 qla8044_rd_reg_indirect(vha, r_addr, &r_value);
2614 *data_ptr++ = s_value;
2615 *data_ptr++ = r_value;
2616 s_value += s_stride;
2617 }
2618 *d_ptr = data_ptr;
2619 }
2620
2621 static void
2622 qla8044_minidump_process_queue(struct scsi_qla_host *vha,
2623 struct qla8044_minidump_entry_hdr *entry_hdr,
2624 uint32_t **d_ptr)
2625 {
2626 uint32_t s_addr, r_addr;
2627 uint32_t r_stride, r_value, r_cnt, qid = 0;
2628 uint32_t i, k, loop_cnt;
2629 struct qla8044_minidump_entry_queue *q_hdr;
2630 uint32_t *data_ptr = *d_ptr;
2631
2632 ql_dbg(ql_dbg_p3p, vha, 0xb0fd, "Entering fn: %s\n", __func__);
2633 q_hdr = (struct qla8044_minidump_entry_queue *)entry_hdr;
2634 s_addr = q_hdr->select_addr;
2635 r_cnt = q_hdr->rd_strd.read_addr_cnt;
2636 r_stride = q_hdr->rd_strd.read_addr_stride;
2637 loop_cnt = q_hdr->op_count;
2638
2639 for (i = 0; i < loop_cnt; i++) {
2640 qla8044_wr_reg_indirect(vha, s_addr, qid);
2641 r_addr = q_hdr->read_addr;
2642 for (k = 0; k < r_cnt; k++) {
2643 qla8044_rd_reg_indirect(vha, r_addr, &r_value);
2644 *data_ptr++ = r_value;
2645 r_addr += r_stride;
2646 }
2647 qid += q_hdr->q_strd.queue_id_stride;
2648 }
2649 *d_ptr = data_ptr;
2650 }
2651
2652
2653 static uint32_t
2654 qla8044_minidump_process_pollrd(struct scsi_qla_host *vha,
2655 struct qla8044_minidump_entry_hdr *entry_hdr,
2656 uint32_t **d_ptr)
2657 {
2658 uint32_t r_addr, s_addr, s_value, r_value, poll_wait, poll_mask;
2659 uint16_t s_stride, i;
2660 struct qla8044_minidump_entry_pollrd *pollrd_hdr;
2661 uint32_t *data_ptr = *d_ptr;
2662
2663 pollrd_hdr = (struct qla8044_minidump_entry_pollrd *) entry_hdr;
2664 s_addr = pollrd_hdr->select_addr;
2665 r_addr = pollrd_hdr->read_addr;
2666 s_value = pollrd_hdr->select_value;
2667 s_stride = pollrd_hdr->select_value_stride;
2668
2669 poll_wait = pollrd_hdr->poll_wait;
2670 poll_mask = pollrd_hdr->poll_mask;
2671
2672 for (i = 0; i < pollrd_hdr->op_count; i++) {
2673 qla8044_wr_reg_indirect(vha, s_addr, s_value);
2674 poll_wait = pollrd_hdr->poll_wait;
2675 while (1) {
2676 qla8044_rd_reg_indirect(vha, s_addr, &r_value);
2677 if ((r_value & poll_mask) != 0) {
2678 break;
2679 } else {
2680 usleep_range(1000, 1100);
2681 if (--poll_wait == 0) {
2682 ql_log(ql_log_fatal, vha, 0xb0fe,
2683 "%s: TIMEOUT\n", __func__);
2684 goto error;
2685 }
2686 }
2687 }
2688 qla8044_rd_reg_indirect(vha, r_addr, &r_value);
2689 *data_ptr++ = s_value;
2690 *data_ptr++ = r_value;
2691
2692 s_value += s_stride;
2693 }
2694 *d_ptr = data_ptr;
2695 return QLA_SUCCESS;
2696
2697 error:
2698 return QLA_FUNCTION_FAILED;
2699 }
2700
2701 static void
2702 qla8044_minidump_process_rdmux2(struct scsi_qla_host *vha,
2703 struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2704 {
2705 uint32_t sel_val1, sel_val2, t_sel_val, data, i;
2706 uint32_t sel_addr1, sel_addr2, sel_val_mask, read_addr;
2707 struct qla8044_minidump_entry_rdmux2 *rdmux2_hdr;
2708 uint32_t *data_ptr = *d_ptr;
2709
2710 rdmux2_hdr = (struct qla8044_minidump_entry_rdmux2 *) entry_hdr;
2711 sel_val1 = rdmux2_hdr->select_value_1;
2712 sel_val2 = rdmux2_hdr->select_value_2;
2713 sel_addr1 = rdmux2_hdr->select_addr_1;
2714 sel_addr2 = rdmux2_hdr->select_addr_2;
2715 sel_val_mask = rdmux2_hdr->select_value_mask;
2716 read_addr = rdmux2_hdr->read_addr;
2717
2718 for (i = 0; i < rdmux2_hdr->op_count; i++) {
2719 qla8044_wr_reg_indirect(vha, sel_addr1, sel_val1);
2720 t_sel_val = sel_val1 & sel_val_mask;
2721 *data_ptr++ = t_sel_val;
2722
2723 qla8044_wr_reg_indirect(vha, sel_addr2, t_sel_val);
2724 qla8044_rd_reg_indirect(vha, read_addr, &data);
2725
2726 *data_ptr++ = data;
2727
2728 qla8044_wr_reg_indirect(vha, sel_addr1, sel_val2);
2729 t_sel_val = sel_val2 & sel_val_mask;
2730 *data_ptr++ = t_sel_val;
2731
2732 qla8044_wr_reg_indirect(vha, sel_addr2, t_sel_val);
2733 qla8044_rd_reg_indirect(vha, read_addr, &data);
2734
2735 *data_ptr++ = data;
2736
2737 sel_val1 += rdmux2_hdr->select_value_stride;
2738 sel_val2 += rdmux2_hdr->select_value_stride;
2739 }
2740
2741 *d_ptr = data_ptr;
2742 }
2743
2744 static uint32_t
2745 qla8044_minidump_process_pollrdmwr(struct scsi_qla_host *vha,
2746 struct qla8044_minidump_entry_hdr *entry_hdr,
2747 uint32_t **d_ptr)
2748 {
2749 uint32_t poll_wait, poll_mask, r_value, data;
2750 uint32_t addr_1, addr_2, value_1, value_2;
2751 struct qla8044_minidump_entry_pollrdmwr *poll_hdr;
2752 uint32_t *data_ptr = *d_ptr;
2753
2754 poll_hdr = (struct qla8044_minidump_entry_pollrdmwr *) entry_hdr;
2755 addr_1 = poll_hdr->addr_1;
2756 addr_2 = poll_hdr->addr_2;
2757 value_1 = poll_hdr->value_1;
2758 value_2 = poll_hdr->value_2;
2759 poll_mask = poll_hdr->poll_mask;
2760
2761 qla8044_wr_reg_indirect(vha, addr_1, value_1);
2762
2763 poll_wait = poll_hdr->poll_wait;
2764 while (1) {
2765 qla8044_rd_reg_indirect(vha, addr_1, &r_value);
2766
2767 if ((r_value & poll_mask) != 0) {
2768 break;
2769 } else {
2770 usleep_range(1000, 1100);
2771 if (--poll_wait == 0) {
2772 ql_log(ql_log_fatal, vha, 0xb0ff,
2773 "%s: TIMEOUT\n", __func__);
2774 goto error;
2775 }
2776 }
2777 }
2778
2779 qla8044_rd_reg_indirect(vha, addr_2, &data);
2780 data &= poll_hdr->modify_mask;
2781 qla8044_wr_reg_indirect(vha, addr_2, data);
2782 qla8044_wr_reg_indirect(vha, addr_1, value_2);
2783
2784 poll_wait = poll_hdr->poll_wait;
2785 while (1) {
2786 qla8044_rd_reg_indirect(vha, addr_1, &r_value);
2787
2788 if ((r_value & poll_mask) != 0) {
2789 break;
2790 } else {
2791 usleep_range(1000, 1100);
2792 if (--poll_wait == 0) {
2793 ql_log(ql_log_fatal, vha, 0xb100,
2794 "%s: TIMEOUT2\n", __func__);
2795 goto error;
2796 }
2797 }
2798 }
2799
2800 *data_ptr++ = addr_2;
2801 *data_ptr++ = data;
2802
2803 *d_ptr = data_ptr;
2804
2805 return QLA_SUCCESS;
2806
2807 error:
2808 return QLA_FUNCTION_FAILED;
2809 }
2810
2811 #define ISP8044_PEX_DMA_ENGINE_INDEX 8
2812 #define ISP8044_PEX_DMA_BASE_ADDRESS 0x77320000
2813 #define ISP8044_PEX_DMA_NUM_OFFSET 0x10000UL
2814 #define ISP8044_PEX_DMA_CMD_ADDR_LOW 0x0
2815 #define ISP8044_PEX_DMA_CMD_ADDR_HIGH 0x04
2816 #define ISP8044_PEX_DMA_CMD_STS_AND_CNTRL 0x08
2817
2818 #define ISP8044_PEX_DMA_READ_SIZE (16 * 1024)
2819 #define ISP8044_PEX_DMA_MAX_WAIT (100 * 100)
2820
2821 static int
2822 qla8044_check_dma_engine_state(struct scsi_qla_host *vha)
2823 {
2824 struct qla_hw_data *ha = vha->hw;
2825 int rval = QLA_SUCCESS;
2826 uint32_t dma_eng_num = 0, cmd_sts_and_cntrl = 0;
2827 uint64_t dma_base_addr = 0;
2828 struct qla8044_minidump_template_hdr *tmplt_hdr = NULL;
2829
2830 tmplt_hdr = ha->md_tmplt_hdr;
2831 dma_eng_num =
2832 tmplt_hdr->saved_state_array[ISP8044_PEX_DMA_ENGINE_INDEX];
2833 dma_base_addr = ISP8044_PEX_DMA_BASE_ADDRESS +
2834 (dma_eng_num * ISP8044_PEX_DMA_NUM_OFFSET);
2835
2836
2837 rval = qla8044_rd_reg_indirect(vha,
2838 (dma_base_addr + ISP8044_PEX_DMA_CMD_STS_AND_CNTRL),
2839 &cmd_sts_and_cntrl);
2840 if (rval)
2841 return QLA_FUNCTION_FAILED;
2842
2843
2844 if (cmd_sts_and_cntrl & BIT_31)
2845 return QLA_SUCCESS;
2846
2847 return QLA_FUNCTION_FAILED;
2848 }
2849
2850 static int
2851 qla8044_start_pex_dma(struct scsi_qla_host *vha,
2852 struct qla8044_minidump_entry_rdmem_pex_dma *m_hdr)
2853 {
2854 struct qla_hw_data *ha = vha->hw;
2855 int rval = QLA_SUCCESS, wait = 0;
2856 uint32_t dma_eng_num = 0, cmd_sts_and_cntrl = 0;
2857 uint64_t dma_base_addr = 0;
2858 struct qla8044_minidump_template_hdr *tmplt_hdr = NULL;
2859
2860 tmplt_hdr = ha->md_tmplt_hdr;
2861 dma_eng_num =
2862 tmplt_hdr->saved_state_array[ISP8044_PEX_DMA_ENGINE_INDEX];
2863 dma_base_addr = ISP8044_PEX_DMA_BASE_ADDRESS +
2864 (dma_eng_num * ISP8044_PEX_DMA_NUM_OFFSET);
2865
2866 rval = qla8044_wr_reg_indirect(vha,
2867 dma_base_addr + ISP8044_PEX_DMA_CMD_ADDR_LOW,
2868 m_hdr->desc_card_addr);
2869 if (rval)
2870 goto error_exit;
2871
2872 rval = qla8044_wr_reg_indirect(vha,
2873 dma_base_addr + ISP8044_PEX_DMA_CMD_ADDR_HIGH, 0);
2874 if (rval)
2875 goto error_exit;
2876
2877 rval = qla8044_wr_reg_indirect(vha,
2878 dma_base_addr + ISP8044_PEX_DMA_CMD_STS_AND_CNTRL,
2879 m_hdr->start_dma_cmd);
2880 if (rval)
2881 goto error_exit;
2882
2883
2884 for (wait = 0; wait < ISP8044_PEX_DMA_MAX_WAIT; wait++) {
2885 rval = qla8044_rd_reg_indirect(vha,
2886 (dma_base_addr + ISP8044_PEX_DMA_CMD_STS_AND_CNTRL),
2887 &cmd_sts_and_cntrl);
2888 if (rval)
2889 goto error_exit;
2890
2891 if ((cmd_sts_and_cntrl & BIT_1) == 0)
2892 break;
2893
2894 udelay(10);
2895 }
2896
2897
2898 if (wait >= ISP8044_PEX_DMA_MAX_WAIT) {
2899 rval = QLA_FUNCTION_FAILED;
2900 goto error_exit;
2901 }
2902
2903 error_exit:
2904 return rval;
2905 }
2906
2907 static int
2908 qla8044_minidump_pex_dma_read(struct scsi_qla_host *vha,
2909 struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2910 {
2911 struct qla_hw_data *ha = vha->hw;
2912 int rval = QLA_SUCCESS;
2913 struct qla8044_minidump_entry_rdmem_pex_dma *m_hdr = NULL;
2914 uint32_t chunk_size, read_size;
2915 uint8_t *data_ptr = (uint8_t *)*d_ptr;
2916 void *rdmem_buffer = NULL;
2917 dma_addr_t rdmem_dma;
2918 struct qla8044_pex_dma_descriptor dma_desc;
2919
2920 rval = qla8044_check_dma_engine_state(vha);
2921 if (rval != QLA_SUCCESS) {
2922 ql_dbg(ql_dbg_p3p, vha, 0xb147,
2923 "DMA engine not available. Fallback to rdmem-read.\n");
2924 return QLA_FUNCTION_FAILED;
2925 }
2926
2927 m_hdr = (void *)entry_hdr;
2928
2929 rdmem_buffer = dma_alloc_coherent(&ha->pdev->dev,
2930 ISP8044_PEX_DMA_READ_SIZE, &rdmem_dma, GFP_KERNEL);
2931 if (!rdmem_buffer) {
2932 ql_dbg(ql_dbg_p3p, vha, 0xb148,
2933 "Unable to allocate rdmem dma buffer\n");
2934 return QLA_FUNCTION_FAILED;
2935 }
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945 dma_desc.cmd.dma_desc_cmd = (m_hdr->dma_desc_cmd & 0xff0f);
2946 dma_desc.cmd.dma_desc_cmd |=
2947 ((PCI_FUNC(ha->pdev->devfn) & 0xf) << 0x4);
2948
2949 dma_desc.dma_bus_addr = rdmem_dma;
2950 dma_desc.cmd.read_data_size = chunk_size = ISP8044_PEX_DMA_READ_SIZE;
2951 read_size = 0;
2952
2953
2954
2955
2956
2957 while (read_size < m_hdr->read_data_size) {
2958 if (m_hdr->read_data_size - read_size <
2959 ISP8044_PEX_DMA_READ_SIZE) {
2960 chunk_size = (m_hdr->read_data_size - read_size);
2961 dma_desc.cmd.read_data_size = chunk_size;
2962 }
2963
2964 dma_desc.src_addr = m_hdr->read_addr + read_size;
2965
2966
2967 rval = qla8044_ms_mem_write_128b(vha,
2968 m_hdr->desc_card_addr, (void *)&dma_desc,
2969 (sizeof(struct qla8044_pex_dma_descriptor)/16));
2970 if (rval) {
2971 ql_log(ql_log_warn, vha, 0xb14a,
2972 "%s: Error writing rdmem-dma-init to MS !!!\n",
2973 __func__);
2974 goto error_exit;
2975 }
2976 ql_dbg(ql_dbg_p3p, vha, 0xb14b,
2977 "%s: Dma-descriptor: Instruct for rdmem dma "
2978 "(chunk_size 0x%x).\n", __func__, chunk_size);
2979
2980
2981 rval = qla8044_start_pex_dma(vha, m_hdr);
2982 if (rval)
2983 goto error_exit;
2984
2985 memcpy(data_ptr, rdmem_buffer, chunk_size);
2986 data_ptr += chunk_size;
2987 read_size += chunk_size;
2988 }
2989
2990 *d_ptr = (void *)data_ptr;
2991
2992 error_exit:
2993 if (rdmem_buffer)
2994 dma_free_coherent(&ha->pdev->dev, ISP8044_PEX_DMA_READ_SIZE,
2995 rdmem_buffer, rdmem_dma);
2996
2997 return rval;
2998 }
2999
3000 static uint32_t
3001 qla8044_minidump_process_rddfe(struct scsi_qla_host *vha,
3002 struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
3003 {
3004 int loop_cnt;
3005 uint32_t addr1, addr2, value, data, temp, wrVal;
3006 uint8_t stride, stride2;
3007 uint16_t count;
3008 uint32_t poll, mask, modify_mask;
3009 uint32_t wait_count = 0;
3010 uint32_t *data_ptr = *d_ptr;
3011 struct qla8044_minidump_entry_rddfe *rddfe;
3012
3013 rddfe = (struct qla8044_minidump_entry_rddfe *) entry_hdr;
3014
3015 addr1 = rddfe->addr_1;
3016 value = rddfe->value;
3017 stride = rddfe->stride;
3018 stride2 = rddfe->stride2;
3019 count = rddfe->count;
3020
3021 poll = rddfe->poll;
3022 mask = rddfe->mask;
3023 modify_mask = rddfe->modify_mask;
3024
3025 addr2 = addr1 + stride;
3026
3027 for (loop_cnt = 0x0; loop_cnt < count; loop_cnt++) {
3028 qla8044_wr_reg_indirect(vha, addr1, (0x40000000 | value));
3029
3030 wait_count = 0;
3031 while (wait_count < poll) {
3032 qla8044_rd_reg_indirect(vha, addr1, &temp);
3033 if ((temp & mask) != 0)
3034 break;
3035 wait_count++;
3036 }
3037
3038 if (wait_count == poll) {
3039 ql_log(ql_log_warn, vha, 0xb153,
3040 "%s: TIMEOUT\n", __func__);
3041 goto error;
3042 } else {
3043 qla8044_rd_reg_indirect(vha, addr2, &temp);
3044 temp = temp & modify_mask;
3045 temp = (temp | ((loop_cnt << 16) | loop_cnt));
3046 wrVal = ((temp << 16) | temp);
3047
3048 qla8044_wr_reg_indirect(vha, addr2, wrVal);
3049 qla8044_wr_reg_indirect(vha, addr1, value);
3050
3051 wait_count = 0;
3052 while (wait_count < poll) {
3053 qla8044_rd_reg_indirect(vha, addr1, &temp);
3054 if ((temp & mask) != 0)
3055 break;
3056 wait_count++;
3057 }
3058 if (wait_count == poll) {
3059 ql_log(ql_log_warn, vha, 0xb154,
3060 "%s: TIMEOUT\n", __func__);
3061 goto error;
3062 }
3063
3064 qla8044_wr_reg_indirect(vha, addr1,
3065 ((0x40000000 | value) + stride2));
3066 wait_count = 0;
3067 while (wait_count < poll) {
3068 qla8044_rd_reg_indirect(vha, addr1, &temp);
3069 if ((temp & mask) != 0)
3070 break;
3071 wait_count++;
3072 }
3073
3074 if (wait_count == poll) {
3075 ql_log(ql_log_warn, vha, 0xb155,
3076 "%s: TIMEOUT\n", __func__);
3077 goto error;
3078 }
3079
3080 qla8044_rd_reg_indirect(vha, addr2, &data);
3081
3082 *data_ptr++ = wrVal;
3083 *data_ptr++ = data;
3084 }
3085
3086 }
3087
3088 *d_ptr = data_ptr;
3089 return QLA_SUCCESS;
3090
3091 error:
3092 return -1;
3093
3094 }
3095
3096 static uint32_t
3097 qla8044_minidump_process_rdmdio(struct scsi_qla_host *vha,
3098 struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
3099 {
3100 int ret = 0;
3101 uint32_t addr1, addr2, value1, value2, data, selVal;
3102 uint8_t stride1, stride2;
3103 uint32_t addr3, addr4, addr5, addr6, addr7;
3104 uint16_t count, loop_cnt;
3105 uint32_t mask;
3106 uint32_t *data_ptr = *d_ptr;
3107
3108 struct qla8044_minidump_entry_rdmdio *rdmdio;
3109
3110 rdmdio = (struct qla8044_minidump_entry_rdmdio *) entry_hdr;
3111
3112 addr1 = rdmdio->addr_1;
3113 addr2 = rdmdio->addr_2;
3114 value1 = rdmdio->value_1;
3115 stride1 = rdmdio->stride_1;
3116 stride2 = rdmdio->stride_2;
3117 count = rdmdio->count;
3118
3119 mask = rdmdio->mask;
3120 value2 = rdmdio->value_2;
3121
3122 addr3 = addr1 + stride1;
3123
3124 for (loop_cnt = 0; loop_cnt < count; loop_cnt++) {
3125 ret = qla8044_poll_wait_ipmdio_bus_idle(vha, addr1, addr2,
3126 addr3, mask);
3127 if (ret == -1)
3128 goto error;
3129
3130 addr4 = addr2 - stride1;
3131 ret = qla8044_ipmdio_wr_reg(vha, addr1, addr3, mask, addr4,
3132 value2);
3133 if (ret == -1)
3134 goto error;
3135
3136 addr5 = addr2 - (2 * stride1);
3137 ret = qla8044_ipmdio_wr_reg(vha, addr1, addr3, mask, addr5,
3138 value1);
3139 if (ret == -1)
3140 goto error;
3141
3142 addr6 = addr2 - (3 * stride1);
3143 ret = qla8044_ipmdio_wr_reg(vha, addr1, addr3, mask,
3144 addr6, 0x2);
3145 if (ret == -1)
3146 goto error;
3147
3148 ret = qla8044_poll_wait_ipmdio_bus_idle(vha, addr1, addr2,
3149 addr3, mask);
3150 if (ret == -1)
3151 goto error;
3152
3153 addr7 = addr2 - (4 * stride1);
3154 data = qla8044_ipmdio_rd_reg(vha, addr1, addr3, mask, addr7);
3155 if (data == -1)
3156 goto error;
3157
3158 selVal = (value2 << 18) | (value1 << 2) | 2;
3159
3160 stride2 = rdmdio->stride_2;
3161 *data_ptr++ = selVal;
3162 *data_ptr++ = data;
3163
3164 value1 = value1 + stride2;
3165 *d_ptr = data_ptr;
3166 }
3167
3168 return 0;
3169
3170 error:
3171 return -1;
3172 }
3173
3174 static uint32_t qla8044_minidump_process_pollwr(struct scsi_qla_host *vha,
3175 struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
3176 {
3177 uint32_t addr1, addr2, value1, value2, poll, r_value;
3178 uint32_t wait_count = 0;
3179 struct qla8044_minidump_entry_pollwr *pollwr_hdr;
3180
3181 pollwr_hdr = (struct qla8044_minidump_entry_pollwr *)entry_hdr;
3182 addr1 = pollwr_hdr->addr_1;
3183 addr2 = pollwr_hdr->addr_2;
3184 value1 = pollwr_hdr->value_1;
3185 value2 = pollwr_hdr->value_2;
3186
3187 poll = pollwr_hdr->poll;
3188
3189 while (wait_count < poll) {
3190 qla8044_rd_reg_indirect(vha, addr1, &r_value);
3191
3192 if ((r_value & poll) != 0)
3193 break;
3194 wait_count++;
3195 }
3196
3197 if (wait_count == poll) {
3198 ql_log(ql_log_warn, vha, 0xb156, "%s: TIMEOUT\n", __func__);
3199 goto error;
3200 }
3201
3202 qla8044_wr_reg_indirect(vha, addr2, value2);
3203 qla8044_wr_reg_indirect(vha, addr1, value1);
3204
3205 wait_count = 0;
3206 while (wait_count < poll) {
3207 qla8044_rd_reg_indirect(vha, addr1, &r_value);
3208
3209 if ((r_value & poll) != 0)
3210 break;
3211 wait_count++;
3212 }
3213
3214 return QLA_SUCCESS;
3215
3216 error:
3217 return -1;
3218 }
3219
3220
3221
3222
3223
3224
3225 int
3226 qla8044_collect_md_data(struct scsi_qla_host *vha)
3227 {
3228 int num_entry_hdr = 0;
3229 struct qla8044_minidump_entry_hdr *entry_hdr;
3230 struct qla8044_minidump_template_hdr *tmplt_hdr;
3231 uint32_t *data_ptr;
3232 uint32_t data_collected = 0, f_capture_mask;
3233 int i, rval = QLA_FUNCTION_FAILED;
3234 uint64_t now;
3235 uint32_t timestamp, idc_control;
3236 struct qla_hw_data *ha = vha->hw;
3237
3238 if (!ha->md_dump) {
3239 ql_log(ql_log_info, vha, 0xb101,
3240 "%s(%ld) No buffer to dump\n",
3241 __func__, vha->host_no);
3242 return rval;
3243 }
3244
3245 if (ha->fw_dumped) {
3246 ql_log(ql_log_warn, vha, 0xb10d,
3247 "Firmware has been previously dumped (%p) "
3248 "-- ignoring request.\n", ha->fw_dump);
3249 goto md_failed;
3250 }
3251
3252 ha->fw_dumped = 0;
3253
3254 if (!ha->md_tmplt_hdr || !ha->md_dump) {
3255 ql_log(ql_log_warn, vha, 0xb10e,
3256 "Memory not allocated for minidump capture\n");
3257 goto md_failed;
3258 }
3259
3260 qla8044_idc_lock(ha);
3261 idc_control = qla8044_rd_reg(ha, QLA8044_IDC_DRV_CTRL);
3262 if (idc_control & GRACEFUL_RESET_BIT1) {
3263 ql_log(ql_log_warn, vha, 0xb112,
3264 "Forced reset from application, "
3265 "ignore minidump capture\n");
3266 qla8044_wr_reg(ha, QLA8044_IDC_DRV_CTRL,
3267 (idc_control & ~GRACEFUL_RESET_BIT1));
3268 qla8044_idc_unlock(ha);
3269
3270 goto md_failed;
3271 }
3272 qla8044_idc_unlock(ha);
3273
3274 if (qla82xx_validate_template_chksum(vha)) {
3275 ql_log(ql_log_info, vha, 0xb109,
3276 "Template checksum validation error\n");
3277 goto md_failed;
3278 }
3279
3280 tmplt_hdr = (struct qla8044_minidump_template_hdr *)
3281 ha->md_tmplt_hdr;
3282 data_ptr = (uint32_t *)((uint8_t *)ha->md_dump);
3283 num_entry_hdr = tmplt_hdr->num_of_entries;
3284
3285 ql_dbg(ql_dbg_p3p, vha, 0xb11a,
3286 "Capture Mask obtained: 0x%x\n", tmplt_hdr->capture_debug_level);
3287
3288 f_capture_mask = tmplt_hdr->capture_debug_level & 0xFF;
3289
3290
3291 if ((f_capture_mask & 0x3) != 0x3) {
3292 ql_log(ql_log_warn, vha, 0xb10f,
3293 "Minimum required capture mask[0x%x] level not set\n",
3294 f_capture_mask);
3295
3296 }
3297 tmplt_hdr->driver_capture_mask = ql2xmdcapmask;
3298 ql_log(ql_log_info, vha, 0xb102,
3299 "[%s]: starting data ptr: %p\n",
3300 __func__, data_ptr);
3301 ql_log(ql_log_info, vha, 0xb10b,
3302 "[%s]: no of entry headers in Template: 0x%x\n",
3303 __func__, num_entry_hdr);
3304 ql_log(ql_log_info, vha, 0xb10c,
3305 "[%s]: Total_data_size 0x%x, %d obtained\n",
3306 __func__, ha->md_dump_size, ha->md_dump_size);
3307
3308
3309 now = get_jiffies_64();
3310 timestamp = (u32)(jiffies_to_msecs(now) / 1000);
3311 tmplt_hdr->driver_timestamp = timestamp;
3312
3313 entry_hdr = (struct qla8044_minidump_entry_hdr *)
3314 (((uint8_t *)ha->md_tmplt_hdr) + tmplt_hdr->first_entry_offset);
3315 tmplt_hdr->saved_state_array[QLA8044_SS_OCM_WNDREG_INDEX] =
3316 tmplt_hdr->ocm_window_reg[ha->portnum];
3317
3318
3319 for (i = 0; i < num_entry_hdr; i++) {
3320 if (data_collected > ha->md_dump_size) {
3321 ql_log(ql_log_info, vha, 0xb103,
3322 "Data collected: [0x%x], "
3323 "Total Dump size: [0x%x]\n",
3324 data_collected, ha->md_dump_size);
3325 return rval;
3326 }
3327
3328 if (!(entry_hdr->d_ctrl.entry_capture_mask &
3329 ql2xmdcapmask)) {
3330 entry_hdr->d_ctrl.driver_flags |=
3331 QLA82XX_DBG_SKIPPED_FLAG;
3332 goto skip_nxt_entry;
3333 }
3334
3335 ql_dbg(ql_dbg_p3p, vha, 0xb104,
3336 "Data collected: [0x%x], Dump size left:[0x%x]\n",
3337 data_collected,
3338 (ha->md_dump_size - data_collected));
3339
3340
3341
3342
3343 switch (entry_hdr->entry_type) {
3344 case QLA82XX_RDEND:
3345 qla8044_mark_entry_skipped(vha, entry_hdr, i);
3346 break;
3347 case QLA82XX_CNTRL:
3348 rval = qla8044_minidump_process_control(vha,
3349 entry_hdr);
3350 if (rval != QLA_SUCCESS) {
3351 qla8044_mark_entry_skipped(vha, entry_hdr, i);
3352 goto md_failed;
3353 }
3354 break;
3355 case QLA82XX_RDCRB:
3356 qla8044_minidump_process_rdcrb(vha,
3357 entry_hdr, &data_ptr);
3358 break;
3359 case QLA82XX_RDMEM:
3360 rval = qla8044_minidump_pex_dma_read(vha,
3361 entry_hdr, &data_ptr);
3362 if (rval != QLA_SUCCESS) {
3363 rval = qla8044_minidump_process_rdmem(vha,
3364 entry_hdr, &data_ptr);
3365 if (rval != QLA_SUCCESS) {
3366 qla8044_mark_entry_skipped(vha,
3367 entry_hdr, i);
3368 goto md_failed;
3369 }
3370 }
3371 break;
3372 case QLA82XX_BOARD:
3373 case QLA82XX_RDROM:
3374 rval = qla8044_minidump_process_rdrom(vha,
3375 entry_hdr, &data_ptr);
3376 if (rval != QLA_SUCCESS) {
3377 qla8044_mark_entry_skipped(vha,
3378 entry_hdr, i);
3379 }
3380 break;
3381 case QLA82XX_L2DTG:
3382 case QLA82XX_L2ITG:
3383 case QLA82XX_L2DAT:
3384 case QLA82XX_L2INS:
3385 rval = qla8044_minidump_process_l2tag(vha,
3386 entry_hdr, &data_ptr);
3387 if (rval != QLA_SUCCESS) {
3388 qla8044_mark_entry_skipped(vha, entry_hdr, i);
3389 goto md_failed;
3390 }
3391 break;
3392 case QLA8044_L1DTG:
3393 case QLA8044_L1ITG:
3394 case QLA82XX_L1DAT:
3395 case QLA82XX_L1INS:
3396 qla8044_minidump_process_l1cache(vha,
3397 entry_hdr, &data_ptr);
3398 break;
3399 case QLA82XX_RDOCM:
3400 qla8044_minidump_process_rdocm(vha,
3401 entry_hdr, &data_ptr);
3402 break;
3403 case QLA82XX_RDMUX:
3404 qla8044_minidump_process_rdmux(vha,
3405 entry_hdr, &data_ptr);
3406 break;
3407 case QLA82XX_QUEUE:
3408 qla8044_minidump_process_queue(vha,
3409 entry_hdr, &data_ptr);
3410 break;
3411 case QLA8044_POLLRD:
3412 rval = qla8044_minidump_process_pollrd(vha,
3413 entry_hdr, &data_ptr);
3414 if (rval != QLA_SUCCESS)
3415 qla8044_mark_entry_skipped(vha, entry_hdr, i);
3416 break;
3417 case QLA8044_RDMUX2:
3418 qla8044_minidump_process_rdmux2(vha,
3419 entry_hdr, &data_ptr);
3420 break;
3421 case QLA8044_POLLRDMWR:
3422 rval = qla8044_minidump_process_pollrdmwr(vha,
3423 entry_hdr, &data_ptr);
3424 if (rval != QLA_SUCCESS)
3425 qla8044_mark_entry_skipped(vha, entry_hdr, i);
3426 break;
3427 case QLA8044_RDDFE:
3428 rval = qla8044_minidump_process_rddfe(vha, entry_hdr,
3429 &data_ptr);
3430 if (rval != QLA_SUCCESS)
3431 qla8044_mark_entry_skipped(vha, entry_hdr, i);
3432 break;
3433 case QLA8044_RDMDIO:
3434 rval = qla8044_minidump_process_rdmdio(vha, entry_hdr,
3435 &data_ptr);
3436 if (rval != QLA_SUCCESS)
3437 qla8044_mark_entry_skipped(vha, entry_hdr, i);
3438 break;
3439 case QLA8044_POLLWR:
3440 rval = qla8044_minidump_process_pollwr(vha, entry_hdr,
3441 &data_ptr);
3442 if (rval != QLA_SUCCESS)
3443 qla8044_mark_entry_skipped(vha, entry_hdr, i);
3444 break;
3445 case QLA82XX_RDNOP:
3446 default:
3447 qla8044_mark_entry_skipped(vha, entry_hdr, i);
3448 break;
3449 }
3450
3451 data_collected = (uint8_t *)data_ptr -
3452 (uint8_t *)((uint8_t *)ha->md_dump);
3453 skip_nxt_entry:
3454
3455
3456
3457 entry_hdr = (struct qla8044_minidump_entry_hdr *)
3458 (((uint8_t *)entry_hdr) + entry_hdr->entry_size);
3459 }
3460
3461 if (data_collected != ha->md_dump_size) {
3462 ql_log(ql_log_info, vha, 0xb105,
3463 "Dump data mismatch: Data collected: "
3464 "[0x%x], total_data_size:[0x%x]\n",
3465 data_collected, ha->md_dump_size);
3466 rval = QLA_FUNCTION_FAILED;
3467 goto md_failed;
3468 }
3469
3470 ql_log(ql_log_info, vha, 0xb110,
3471 "Firmware dump saved to temp buffer (%ld/%p %ld/%p).\n",
3472 vha->host_no, ha->md_tmplt_hdr, vha->host_no, ha->md_dump);
3473 ha->fw_dumped = 1;
3474 qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP);
3475
3476
3477 ql_log(ql_log_info, vha, 0xb106,
3478 "Leaving fn: %s Last entry: 0x%x\n",
3479 __func__, i);
3480 md_failed:
3481 return rval;
3482 }
3483
3484 void
3485 qla8044_get_minidump(struct scsi_qla_host *vha)
3486 {
3487 struct qla_hw_data *ha = vha->hw;
3488
3489 if (!qla8044_collect_md_data(vha)) {
3490 ha->fw_dumped = 1;
3491 ha->prev_minidump_failed = 0;
3492 } else {
3493 ql_log(ql_log_fatal, vha, 0xb0db,
3494 "%s: Unable to collect minidump\n",
3495 __func__);
3496 ha->prev_minidump_failed = 1;
3497 }
3498 }
3499
3500 static int
3501 qla8044_poll_flash_status_reg(struct scsi_qla_host *vha)
3502 {
3503 uint32_t flash_status;
3504 int retries = QLA8044_FLASH_READ_RETRY_COUNT;
3505 int ret_val = QLA_SUCCESS;
3506
3507 while (retries--) {
3508 ret_val = qla8044_rd_reg_indirect(vha, QLA8044_FLASH_STATUS,
3509 &flash_status);
3510 if (ret_val) {
3511 ql_log(ql_log_warn, vha, 0xb13c,
3512 "%s: Failed to read FLASH_STATUS reg.\n",
3513 __func__);
3514 break;
3515 }
3516 if ((flash_status & QLA8044_FLASH_STATUS_READY) ==
3517 QLA8044_FLASH_STATUS_READY)
3518 break;
3519 msleep(QLA8044_FLASH_STATUS_REG_POLL_DELAY);
3520 }
3521
3522 if (!retries)
3523 ret_val = QLA_FUNCTION_FAILED;
3524
3525 return ret_val;
3526 }
3527
3528 static int
3529 qla8044_write_flash_status_reg(struct scsi_qla_host *vha,
3530 uint32_t data)
3531 {
3532 int ret_val = QLA_SUCCESS;
3533 uint32_t cmd;
3534
3535 cmd = vha->hw->fdt_wrt_sts_reg_cmd;
3536
3537 ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3538 QLA8044_FLASH_STATUS_WRITE_DEF_SIG | cmd);
3539 if (ret_val) {
3540 ql_log(ql_log_warn, vha, 0xb125,
3541 "%s: Failed to write to FLASH_ADDR.\n", __func__);
3542 goto exit_func;
3543 }
3544
3545 ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_WRDATA, data);
3546 if (ret_val) {
3547 ql_log(ql_log_warn, vha, 0xb126,
3548 "%s: Failed to write to FLASH_WRDATA.\n", __func__);
3549 goto exit_func;
3550 }
3551
3552 ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL,
3553 QLA8044_FLASH_SECOND_ERASE_MS_VAL);
3554 if (ret_val) {
3555 ql_log(ql_log_warn, vha, 0xb127,
3556 "%s: Failed to write to FLASH_CONTROL.\n", __func__);
3557 goto exit_func;
3558 }
3559
3560 ret_val = qla8044_poll_flash_status_reg(vha);
3561 if (ret_val)
3562 ql_log(ql_log_warn, vha, 0xb128,
3563 "%s: Error polling flash status reg.\n", __func__);
3564
3565 exit_func:
3566 return ret_val;
3567 }
3568
3569
3570
3571
3572 static int
3573 qla8044_unprotect_flash(scsi_qla_host_t *vha)
3574 {
3575 int ret_val;
3576 struct qla_hw_data *ha = vha->hw;
3577
3578 ret_val = qla8044_write_flash_status_reg(vha, ha->fdt_wrt_enable);
3579 if (ret_val)
3580 ql_log(ql_log_warn, vha, 0xb139,
3581 "%s: Write flash status failed.\n", __func__);
3582
3583 return ret_val;
3584 }
3585
3586
3587
3588
3589 static int
3590 qla8044_protect_flash(scsi_qla_host_t *vha)
3591 {
3592 int ret_val;
3593 struct qla_hw_data *ha = vha->hw;
3594
3595 ret_val = qla8044_write_flash_status_reg(vha, ha->fdt_wrt_disable);
3596 if (ret_val)
3597 ql_log(ql_log_warn, vha, 0xb13b,
3598 "%s: Write flash status failed.\n", __func__);
3599
3600 return ret_val;
3601 }
3602
3603
3604 static int
3605 qla8044_erase_flash_sector(struct scsi_qla_host *vha,
3606 uint32_t sector_start_addr)
3607 {
3608 uint32_t reversed_addr;
3609 int ret_val = QLA_SUCCESS;
3610
3611 ret_val = qla8044_poll_flash_status_reg(vha);
3612 if (ret_val) {
3613 ql_log(ql_log_warn, vha, 0xb12e,
3614 "%s: Poll flash status after erase failed..\n", __func__);
3615 }
3616
3617 reversed_addr = (((sector_start_addr & 0xFF) << 16) |
3618 (sector_start_addr & 0xFF00) |
3619 ((sector_start_addr & 0xFF0000) >> 16));
3620
3621 ret_val = qla8044_wr_reg_indirect(vha,
3622 QLA8044_FLASH_WRDATA, reversed_addr);
3623 if (ret_val) {
3624 ql_log(ql_log_warn, vha, 0xb12f,
3625 "%s: Failed to write to FLASH_WRDATA.\n", __func__);
3626 }
3627 ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3628 QLA8044_FLASH_ERASE_SIG | vha->hw->fdt_erase_cmd);
3629 if (ret_val) {
3630 ql_log(ql_log_warn, vha, 0xb130,
3631 "%s: Failed to write to FLASH_ADDR.\n", __func__);
3632 }
3633 ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL,
3634 QLA8044_FLASH_LAST_ERASE_MS_VAL);
3635 if (ret_val) {
3636 ql_log(ql_log_warn, vha, 0xb131,
3637 "%s: Failed write to FLASH_CONTROL.\n", __func__);
3638 }
3639 ret_val = qla8044_poll_flash_status_reg(vha);
3640 if (ret_val) {
3641 ql_log(ql_log_warn, vha, 0xb132,
3642 "%s: Poll flash status failed.\n", __func__);
3643 }
3644
3645
3646 return ret_val;
3647 }
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660 static int
3661 qla8044_flash_write_u32(struct scsi_qla_host *vha, uint32_t addr,
3662 uint32_t *p_data)
3663 {
3664 int ret_val = QLA_SUCCESS;
3665
3666 ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3667 0x00800000 | (addr >> 2));
3668 if (ret_val) {
3669 ql_log(ql_log_warn, vha, 0xb134,
3670 "%s: Failed write to FLASH_ADDR.\n", __func__);
3671 goto exit_func;
3672 }
3673 ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_WRDATA, *p_data);
3674 if (ret_val) {
3675 ql_log(ql_log_warn, vha, 0xb135,
3676 "%s: Failed write to FLASH_WRDATA.\n", __func__);
3677 goto exit_func;
3678 }
3679 ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL, 0x3D);
3680 if (ret_val) {
3681 ql_log(ql_log_warn, vha, 0xb136,
3682 "%s: Failed write to FLASH_CONTROL.\n", __func__);
3683 goto exit_func;
3684 }
3685 ret_val = qla8044_poll_flash_status_reg(vha);
3686 if (ret_val) {
3687 ql_log(ql_log_warn, vha, 0xb137,
3688 "%s: Poll flash status failed.\n", __func__);
3689 }
3690
3691 exit_func:
3692 return ret_val;
3693 }
3694
3695 static int
3696 qla8044_write_flash_buffer_mode(scsi_qla_host_t *vha, uint32_t *dwptr,
3697 uint32_t faddr, uint32_t dwords)
3698 {
3699 int ret = QLA_FUNCTION_FAILED;
3700 uint32_t spi_val;
3701
3702 if (dwords < QLA8044_MIN_OPTROM_BURST_DWORDS ||
3703 dwords > QLA8044_MAX_OPTROM_BURST_DWORDS) {
3704 ql_dbg(ql_dbg_user, vha, 0xb123,
3705 "Got unsupported dwords = 0x%x.\n",
3706 dwords);
3707 return QLA_FUNCTION_FAILED;
3708 }
3709
3710 qla8044_rd_reg_indirect(vha, QLA8044_FLASH_SPI_CONTROL, &spi_val);
3711 qla8044_wr_reg_indirect(vha, QLA8044_FLASH_SPI_CONTROL,
3712 spi_val | QLA8044_FLASH_SPI_CTL);
3713 qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3714 QLA8044_FLASH_FIRST_TEMP_VAL);
3715
3716
3717 ret = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_WRDATA,
3718 *dwptr++);
3719 qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL,
3720 QLA8044_FLASH_FIRST_MS_PATTERN);
3721
3722 ret = qla8044_poll_flash_status_reg(vha);
3723 if (ret) {
3724 ql_log(ql_log_warn, vha, 0xb124,
3725 "%s: Failed.\n", __func__);
3726 goto exit_func;
3727 }
3728
3729 dwords--;
3730
3731 qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3732 QLA8044_FLASH_SECOND_TEMP_VAL);
3733
3734
3735
3736 while (dwords != 1) {
3737 qla8044_wr_reg_indirect(vha, QLA8044_FLASH_WRDATA, *dwptr++);
3738 qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL,
3739 QLA8044_FLASH_SECOND_MS_PATTERN);
3740 ret = qla8044_poll_flash_status_reg(vha);
3741 if (ret) {
3742 ql_log(ql_log_warn, vha, 0xb129,
3743 "%s: Failed.\n", __func__);
3744 goto exit_func;
3745 }
3746 dwords--;
3747 }
3748
3749 qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3750 QLA8044_FLASH_FIRST_TEMP_VAL | (faddr >> 2));
3751
3752
3753 qla8044_wr_reg_indirect(vha, QLA8044_FLASH_WRDATA, *dwptr++);
3754 qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL,
3755 QLA8044_FLASH_LAST_MS_PATTERN);
3756 ret = qla8044_poll_flash_status_reg(vha);
3757 if (ret) {
3758 ql_log(ql_log_warn, vha, 0xb12a,
3759 "%s: Failed.\n", __func__);
3760 goto exit_func;
3761 }
3762 qla8044_rd_reg_indirect(vha, QLA8044_FLASH_SPI_STATUS, &spi_val);
3763
3764 if ((spi_val & QLA8044_FLASH_SPI_CTL) == QLA8044_FLASH_SPI_CTL) {
3765 ql_log(ql_log_warn, vha, 0xb12b,
3766 "%s: Failed.\n", __func__);
3767 spi_val = 0;
3768
3769 qla8044_rd_reg_indirect(vha, QLA8044_FLASH_SPI_CONTROL,
3770 &spi_val);
3771 qla8044_wr_reg_indirect(vha, QLA8044_FLASH_SPI_CONTROL,
3772 spi_val | QLA8044_FLASH_SPI_CTL);
3773 }
3774 exit_func:
3775 return ret;
3776 }
3777
3778 static int
3779 qla8044_write_flash_dword_mode(scsi_qla_host_t *vha, uint32_t *dwptr,
3780 uint32_t faddr, uint32_t dwords)
3781 {
3782 int ret = QLA_FUNCTION_FAILED;
3783 uint32_t liter;
3784
3785 for (liter = 0; liter < dwords; liter++, faddr += 4, dwptr++) {
3786 ret = qla8044_flash_write_u32(vha, faddr, dwptr);
3787 if (ret) {
3788 ql_dbg(ql_dbg_p3p, vha, 0xb141,
3789 "%s: flash address=%x data=%x.\n", __func__,
3790 faddr, *dwptr);
3791 break;
3792 }
3793 }
3794
3795 return ret;
3796 }
3797
3798 int
3799 qla8044_write_optrom_data(struct scsi_qla_host *vha, void *buf,
3800 uint32_t offset, uint32_t length)
3801 {
3802 int rval = QLA_FUNCTION_FAILED, i, burst_iter_count;
3803 int dword_count, erase_sec_count;
3804 uint32_t erase_offset;
3805 uint8_t *p_cache, *p_src;
3806
3807 erase_offset = offset;
3808
3809 p_cache = kcalloc(length, sizeof(uint8_t), GFP_KERNEL);
3810 if (!p_cache)
3811 return QLA_FUNCTION_FAILED;
3812
3813 memcpy(p_cache, buf, length);
3814 p_src = p_cache;
3815 dword_count = length / sizeof(uint32_t);
3816
3817
3818
3819 burst_iter_count = dword_count / QLA8044_MAX_OPTROM_BURST_DWORDS;
3820 erase_sec_count = length / QLA8044_SECTOR_SIZE;
3821
3822
3823 scsi_block_requests(vha->host);
3824
3825 qla8044_flash_lock(vha);
3826 qla8044_unprotect_flash(vha);
3827
3828
3829 for (i = 0; i < erase_sec_count; i++) {
3830 rval = qla8044_erase_flash_sector(vha, erase_offset);
3831 ql_dbg(ql_dbg_user, vha, 0xb138,
3832 "Done erase of sector=0x%x.\n",
3833 erase_offset);
3834 if (rval) {
3835 ql_log(ql_log_warn, vha, 0xb121,
3836 "Failed to erase the sector having address: "
3837 "0x%x.\n", erase_offset);
3838 goto out;
3839 }
3840 erase_offset += QLA8044_SECTOR_SIZE;
3841 }
3842 ql_dbg(ql_dbg_user, vha, 0xb13f,
3843 "Got write for addr = 0x%x length=0x%x.\n",
3844 offset, length);
3845
3846 for (i = 0; i < burst_iter_count; i++) {
3847
3848
3849 rval = qla8044_write_flash_buffer_mode(vha, (uint32_t *)p_src,
3850 offset, QLA8044_MAX_OPTROM_BURST_DWORDS);
3851 if (rval) {
3852
3853 ql_log(ql_log_warn, vha, 0xb122,
3854 "Failed to write flash in buffer mode, "
3855 "Reverting to slow-write.\n");
3856 rval = qla8044_write_flash_dword_mode(vha,
3857 (uint32_t *)p_src, offset,
3858 QLA8044_MAX_OPTROM_BURST_DWORDS);
3859 }
3860 p_src += sizeof(uint32_t) * QLA8044_MAX_OPTROM_BURST_DWORDS;
3861 offset += sizeof(uint32_t) * QLA8044_MAX_OPTROM_BURST_DWORDS;
3862 }
3863 ql_dbg(ql_dbg_user, vha, 0xb133,
3864 "Done writing.\n");
3865
3866 out:
3867 qla8044_protect_flash(vha);
3868 qla8044_flash_unlock(vha);
3869 scsi_unblock_requests(vha->host);
3870 kfree(p_cache);
3871
3872 return rval;
3873 }
3874
3875 #define LEG_INT_PTR_B31 (1 << 31)
3876 #define LEG_INT_PTR_B30 (1 << 30)
3877 #define PF_BITS_MASK (0xF << 16)
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887 irqreturn_t
3888 qla8044_intr_handler(int irq, void *dev_id)
3889 {
3890 scsi_qla_host_t *vha;
3891 struct qla_hw_data *ha;
3892 struct rsp_que *rsp;
3893 struct device_reg_82xx __iomem *reg;
3894 int status = 0;
3895 unsigned long flags;
3896 unsigned long iter;
3897 uint32_t stat;
3898 uint16_t mb[8];
3899 uint32_t leg_int_ptr = 0, pf_bit;
3900
3901 rsp = (struct rsp_que *) dev_id;
3902 if (!rsp) {
3903 ql_log(ql_log_info, NULL, 0xb143,
3904 "%s(): NULL response queue pointer\n", __func__);
3905 return IRQ_NONE;
3906 }
3907 ha = rsp->hw;
3908 vha = pci_get_drvdata(ha->pdev);
3909
3910 if (unlikely(pci_channel_offline(ha->pdev)))
3911 return IRQ_HANDLED;
3912
3913 leg_int_ptr = qla8044_rd_reg(ha, LEG_INTR_PTR_OFFSET);
3914
3915
3916 if (!(leg_int_ptr & (LEG_INT_PTR_B31))) {
3917 ql_dbg(ql_dbg_p3p, vha, 0xb144,
3918 "%s: Legacy Interrupt Bit 31 not set, "
3919 "spurious interrupt!\n", __func__);
3920 return IRQ_NONE;
3921 }
3922
3923 pf_bit = ha->portnum << 16;
3924
3925 if ((leg_int_ptr & (PF_BITS_MASK)) != pf_bit) {
3926 ql_dbg(ql_dbg_p3p, vha, 0xb145,
3927 "%s: Incorrect function ID 0x%x in "
3928 "legacy interrupt register, "
3929 "ha->pf_bit = 0x%x\n", __func__,
3930 (leg_int_ptr & (PF_BITS_MASK)), pf_bit);
3931 return IRQ_NONE;
3932 }
3933
3934
3935
3936
3937
3938 qla8044_wr_reg(ha, LEG_INTR_TRIG_OFFSET, 0);
3939 do {
3940 leg_int_ptr = qla8044_rd_reg(ha, LEG_INTR_PTR_OFFSET);
3941 if ((leg_int_ptr & (PF_BITS_MASK)) != pf_bit)
3942 break;
3943 } while (leg_int_ptr & (LEG_INT_PTR_B30));
3944
3945 reg = &ha->iobase->isp82;
3946 spin_lock_irqsave(&ha->hardware_lock, flags);
3947 for (iter = 1; iter--; ) {
3948
3949 if (RD_REG_DWORD(®->host_int)) {
3950 stat = RD_REG_DWORD(®->host_status);
3951 if ((stat & HSRX_RISC_INT) == 0)
3952 break;
3953
3954 switch (stat & 0xff) {
3955 case 0x1:
3956 case 0x2:
3957 case 0x10:
3958 case 0x11:
3959 qla82xx_mbx_completion(vha, MSW(stat));
3960 status |= MBX_INTERRUPT;
3961 break;
3962 case 0x12:
3963 mb[0] = MSW(stat);
3964 mb[1] = RD_REG_WORD(®->mailbox_out[1]);
3965 mb[2] = RD_REG_WORD(®->mailbox_out[2]);
3966 mb[3] = RD_REG_WORD(®->mailbox_out[3]);
3967 qla2x00_async_event(vha, rsp, mb);
3968 break;
3969 case 0x13:
3970 qla24xx_process_response_queue(vha, rsp);
3971 break;
3972 default:
3973 ql_dbg(ql_dbg_p3p, vha, 0xb146,
3974 "Unrecognized interrupt type "
3975 "(%d).\n", stat & 0xff);
3976 break;
3977 }
3978 }
3979 WRT_REG_DWORD(®->host_int, 0);
3980 }
3981
3982 qla2x00_handle_mbx_completion(ha, status);
3983 spin_unlock_irqrestore(&ha->hardware_lock, flags);
3984
3985 return IRQ_HANDLED;
3986 }
3987
3988 static int
3989 qla8044_idc_dontreset(struct qla_hw_data *ha)
3990 {
3991 uint32_t idc_ctrl;
3992
3993 idc_ctrl = qla8044_rd_reg(ha, QLA8044_IDC_DRV_CTRL);
3994 return idc_ctrl & DONTRESET_BIT0;
3995 }
3996
3997 static void
3998 qla8044_clear_rst_ready(scsi_qla_host_t *vha)
3999 {
4000 uint32_t drv_state;
4001
4002 drv_state = qla8044_rd_direct(vha, QLA8044_CRB_DRV_STATE_INDEX);
4003
4004
4005
4006
4007
4008
4009 drv_state &= ~(1 << vha->hw->portnum);
4010
4011 ql_dbg(ql_dbg_p3p, vha, 0xb13d,
4012 "drv_state: 0x%08x\n", drv_state);
4013 qla8044_wr_direct(vha, QLA8044_CRB_DRV_STATE_INDEX, drv_state);
4014 }
4015
4016 int
4017 qla8044_abort_isp(scsi_qla_host_t *vha)
4018 {
4019 int rval;
4020 uint32_t dev_state;
4021 struct qla_hw_data *ha = vha->hw;
4022
4023 qla8044_idc_lock(ha);
4024 dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX);
4025
4026 if (ql2xdontresethba)
4027 qla8044_set_idc_dontreset(vha);
4028
4029
4030
4031
4032
4033
4034
4035 if (dev_state == QLA8XXX_DEV_READY) {
4036
4037
4038 if (qla8044_idc_dontreset(ha) == DONTRESET_BIT0) {
4039 ql_dbg(ql_dbg_p3p, vha, 0xb13e,
4040 "Reset recovery disabled\n");
4041 rval = QLA_FUNCTION_FAILED;
4042 goto exit_isp_reset;
4043 }
4044
4045 ql_dbg(ql_dbg_p3p, vha, 0xb140,
4046 "HW State: NEED RESET\n");
4047 qla8044_wr_direct(vha, QLA8044_CRB_DEV_STATE_INDEX,
4048 QLA8XXX_DEV_NEED_RESET);
4049 }
4050
4051
4052
4053
4054 qla83xx_reset_ownership(vha);
4055
4056 qla8044_idc_unlock(ha);
4057 rval = qla8044_device_state_handler(vha);
4058 qla8044_idc_lock(ha);
4059 qla8044_clear_rst_ready(vha);
4060
4061 exit_isp_reset:
4062 qla8044_idc_unlock(ha);
4063 if (rval == QLA_SUCCESS) {
4064 ha->flags.isp82xx_fw_hung = 0;
4065 ha->flags.nic_core_reset_hdlr_active = 0;
4066 rval = qla82xx_restart_isp(vha);
4067 }
4068
4069 return rval;
4070 }
4071
4072 void
4073 qla8044_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
4074 {
4075 struct qla_hw_data *ha = vha->hw;
4076
4077 if (!ha->allow_cna_fw_dump)
4078 return;
4079
4080 scsi_block_requests(vha->host);
4081 ha->flags.isp82xx_no_md_cap = 1;
4082 qla8044_idc_lock(ha);
4083 qla82xx_set_reset_owner(vha);
4084 qla8044_idc_unlock(ha);
4085 qla2x00_wait_for_chip_reset(vha);
4086 scsi_unblock_requests(vha->host);
4087 }