diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 20:34:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 20:34:15 -0400 |
commit | c70b5296e775cde46cfcb2d860ba160108a5ec7a (patch) | |
tree | 30419cb982acca44499236adcca65f2f87698c74 /drivers/scsi/qla2xxx/qla_nx.c | |
parent | 80c226fbef56576946c9655fcb2ab62e63404d12 (diff) | |
parent | 58ff4bd042adf8013c8f70fd03c2c0f8d022e387 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (84 commits)
[SCSI] be2iscsi: SGE Len == 64K
[SCSI] be2iscsi: Remove premature free of cid
[SCSI] be2iscsi: More time for FW
[SCSI] libsas: fix bug for vacant phy
[SCSI] sd: Fix overflow with big physical blocks
[SCSI] st: add MTWEOFI to write filemarks without flushing drive buffer
[SCSI] libsas: Don't issue commands to devices that have been hot-removed
[SCSI] megaraid_sas: Add Online Controller Reset to MegaRAID SAS drive
[SCSI] lpfc 8.3.17: Update lpfc driver version to 8.3.17
[SCSI] lpfc 8.3.17: Replace function reset methodology
[SCSI] lpfc 8.3.17: SCSI fixes
[SCSI] lpfc 8.3.17: BSG fixes
[SCSI] lpfc 8.3.17: SLI Additions and Fixes
[SCSI] lpfc 8.3.17: Code Cleanup and Locking fixes
[SCSI] zfcp: Remove scsi_cmnd->serial_number from debug traces
[SCSI] ipr: fix array error logging
[SCSI] aha152x: enable PCMCIA on 64bit
[SCSI] scsi_dh_alua: Handle all states correctly
[SCSI] cxgb4i: connection and ddp setting update
[SCSI] cxgb3i: fixed connection over vlan
...
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_nx.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_nx.c | 431 |
1 files changed, 238 insertions, 193 deletions
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 0a71cc71eab2..8d9edfb39803 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c | |||
@@ -403,6 +403,54 @@ qla82xx_pci_set_crbwindow(struct qla_hw_data *ha, u64 off) | |||
403 | return off; | 403 | return off; |
404 | } | 404 | } |
405 | 405 | ||
406 | static int | ||
407 | qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, ulong *off) | ||
408 | { | ||
409 | struct crb_128M_2M_sub_block_map *m; | ||
410 | |||
411 | if (*off >= QLA82XX_CRB_MAX) | ||
412 | return -1; | ||
413 | |||
414 | if (*off >= QLA82XX_PCI_CAMQM && (*off < QLA82XX_PCI_CAMQM_2M_END)) { | ||
415 | *off = (*off - QLA82XX_PCI_CAMQM) + | ||
416 | QLA82XX_PCI_CAMQM_2M_BASE + ha->nx_pcibase; | ||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | if (*off < QLA82XX_PCI_CRBSPACE) | ||
421 | return -1; | ||
422 | |||
423 | *off -= QLA82XX_PCI_CRBSPACE; | ||
424 | |||
425 | /* Try direct map */ | ||
426 | m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)]; | ||
427 | |||
428 | if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) { | ||
429 | *off = *off + m->start_2M - m->start_128M + ha->nx_pcibase; | ||
430 | return 0; | ||
431 | } | ||
432 | /* Not in direct map, use crb window */ | ||
433 | return 1; | ||
434 | } | ||
435 | |||
436 | #define CRB_WIN_LOCK_TIMEOUT 100000000 | ||
437 | static int qla82xx_crb_win_lock(struct qla_hw_data *ha) | ||
438 | { | ||
439 | int done = 0, timeout = 0; | ||
440 | |||
441 | while (!done) { | ||
442 | /* acquire semaphore3 from PCI HW block */ | ||
443 | done = qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK)); | ||
444 | if (done == 1) | ||
445 | break; | ||
446 | if (timeout >= CRB_WIN_LOCK_TIMEOUT) | ||
447 | return -1; | ||
448 | timeout++; | ||
449 | } | ||
450 | qla82xx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->portnum); | ||
451 | return 0; | ||
452 | } | ||
453 | |||
406 | int | 454 | int |
407 | qla82xx_wr_32(struct qla_hw_data *ha, ulong off, u32 data) | 455 | qla82xx_wr_32(struct qla_hw_data *ha, ulong off, u32 data) |
408 | { | 456 | { |
@@ -453,24 +501,6 @@ qla82xx_rd_32(struct qla_hw_data *ha, ulong off) | |||
453 | return data; | 501 | return data; |
454 | } | 502 | } |
455 | 503 | ||
456 | #define CRB_WIN_LOCK_TIMEOUT 100000000 | ||
457 | int qla82xx_crb_win_lock(struct qla_hw_data *ha) | ||
458 | { | ||
459 | int done = 0, timeout = 0; | ||
460 | |||
461 | while (!done) { | ||
462 | /* acquire semaphore3 from PCI HW block */ | ||
463 | done = qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK)); | ||
464 | if (done == 1) | ||
465 | break; | ||
466 | if (timeout >= CRB_WIN_LOCK_TIMEOUT) | ||
467 | return -1; | ||
468 | timeout++; | ||
469 | } | ||
470 | qla82xx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->portnum); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | #define IDC_LOCK_TIMEOUT 100000000 | 504 | #define IDC_LOCK_TIMEOUT 100000000 |
475 | int qla82xx_idc_lock(struct qla_hw_data *ha) | 505 | int qla82xx_idc_lock(struct qla_hw_data *ha) |
476 | { | 506 | { |
@@ -504,36 +534,6 @@ void qla82xx_idc_unlock(struct qla_hw_data *ha) | |||
504 | qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_UNLOCK)); | 534 | qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_UNLOCK)); |
505 | } | 535 | } |
506 | 536 | ||
507 | int | ||
508 | qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, ulong *off) | ||
509 | { | ||
510 | struct crb_128M_2M_sub_block_map *m; | ||
511 | |||
512 | if (*off >= QLA82XX_CRB_MAX) | ||
513 | return -1; | ||
514 | |||
515 | if (*off >= QLA82XX_PCI_CAMQM && (*off < QLA82XX_PCI_CAMQM_2M_END)) { | ||
516 | *off = (*off - QLA82XX_PCI_CAMQM) + | ||
517 | QLA82XX_PCI_CAMQM_2M_BASE + ha->nx_pcibase; | ||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | if (*off < QLA82XX_PCI_CRBSPACE) | ||
522 | return -1; | ||
523 | |||
524 | *off -= QLA82XX_PCI_CRBSPACE; | ||
525 | |||
526 | /* Try direct map */ | ||
527 | m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)]; | ||
528 | |||
529 | if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) { | ||
530 | *off = *off + m->start_2M - m->start_128M + ha->nx_pcibase; | ||
531 | return 0; | ||
532 | } | ||
533 | /* Not in direct map, use crb window */ | ||
534 | return 1; | ||
535 | } | ||
536 | |||
537 | /* PCI Windowing for DDR regions. */ | 537 | /* PCI Windowing for DDR regions. */ |
538 | #define QLA82XX_ADDR_IN_RANGE(addr, low, high) \ | 538 | #define QLA82XX_ADDR_IN_RANGE(addr, low, high) \ |
539 | (((addr) <= (high)) && ((addr) >= (low))) | 539 | (((addr) <= (high)) && ((addr) >= (low))) |
@@ -557,7 +557,7 @@ qla82xx_pci_mem_bound_check(struct qla_hw_data *ha, | |||
557 | 557 | ||
558 | int qla82xx_pci_set_window_warning_count; | 558 | int qla82xx_pci_set_window_warning_count; |
559 | 559 | ||
560 | unsigned long | 560 | static unsigned long |
561 | qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr) | 561 | qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr) |
562 | { | 562 | { |
563 | int window; | 563 | int window; |
@@ -798,7 +798,8 @@ qla82xx_pci_mem_write_direct(struct qla_hw_data *ha, | |||
798 | } | 798 | } |
799 | 799 | ||
800 | #define MTU_FUDGE_FACTOR 100 | 800 | #define MTU_FUDGE_FACTOR 100 |
801 | unsigned long qla82xx_decode_crb_addr(unsigned long addr) | 801 | static unsigned long |
802 | qla82xx_decode_crb_addr(unsigned long addr) | ||
802 | { | 803 | { |
803 | int i; | 804 | int i; |
804 | unsigned long base_addr, offset, pci_base; | 805 | unsigned long base_addr, offset, pci_base; |
@@ -824,7 +825,7 @@ unsigned long qla82xx_decode_crb_addr(unsigned long addr) | |||
824 | static long rom_max_timeout = 100; | 825 | static long rom_max_timeout = 100; |
825 | static long qla82xx_rom_lock_timeout = 100; | 826 | static long qla82xx_rom_lock_timeout = 100; |
826 | 827 | ||
827 | int | 828 | static int |
828 | qla82xx_rom_lock(struct qla_hw_data *ha) | 829 | qla82xx_rom_lock(struct qla_hw_data *ha) |
829 | { | 830 | { |
830 | int done = 0, timeout = 0; | 831 | int done = 0, timeout = 0; |
@@ -842,7 +843,7 @@ qla82xx_rom_lock(struct qla_hw_data *ha) | |||
842 | return 0; | 843 | return 0; |
843 | } | 844 | } |
844 | 845 | ||
845 | int | 846 | static int |
846 | qla82xx_wait_rom_busy(struct qla_hw_data *ha) | 847 | qla82xx_wait_rom_busy(struct qla_hw_data *ha) |
847 | { | 848 | { |
848 | long timeout = 0; | 849 | long timeout = 0; |
@@ -862,7 +863,7 @@ qla82xx_wait_rom_busy(struct qla_hw_data *ha) | |||
862 | return 0; | 863 | return 0; |
863 | } | 864 | } |
864 | 865 | ||
865 | int | 866 | static int |
866 | qla82xx_wait_rom_done(struct qla_hw_data *ha) | 867 | qla82xx_wait_rom_done(struct qla_hw_data *ha) |
867 | { | 868 | { |
868 | long timeout = 0; | 869 | long timeout = 0; |
@@ -882,7 +883,7 @@ qla82xx_wait_rom_done(struct qla_hw_data *ha) | |||
882 | return 0; | 883 | return 0; |
883 | } | 884 | } |
884 | 885 | ||
885 | int | 886 | static int |
886 | qla82xx_do_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp) | 887 | qla82xx_do_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp) |
887 | { | 888 | { |
888 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, addr); | 889 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, addr); |
@@ -905,7 +906,7 @@ qla82xx_do_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp) | |||
905 | return 0; | 906 | return 0; |
906 | } | 907 | } |
907 | 908 | ||
908 | int | 909 | static int |
909 | qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp) | 910 | qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp) |
910 | { | 911 | { |
911 | int ret, loops = 0; | 912 | int ret, loops = 0; |
@@ -926,7 +927,7 @@ qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp) | |||
926 | return ret; | 927 | return ret; |
927 | } | 928 | } |
928 | 929 | ||
929 | int | 930 | static int |
930 | qla82xx_read_status_reg(struct qla_hw_data *ha, uint32_t *val) | 931 | qla82xx_read_status_reg(struct qla_hw_data *ha, uint32_t *val) |
931 | { | 932 | { |
932 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_RDSR); | 933 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_RDSR); |
@@ -940,7 +941,7 @@ qla82xx_read_status_reg(struct qla_hw_data *ha, uint32_t *val) | |||
940 | return 0; | 941 | return 0; |
941 | } | 942 | } |
942 | 943 | ||
943 | int | 944 | static int |
944 | qla82xx_flash_wait_write_finish(struct qla_hw_data *ha) | 945 | qla82xx_flash_wait_write_finish(struct qla_hw_data *ha) |
945 | { | 946 | { |
946 | long timeout = 0; | 947 | long timeout = 0; |
@@ -964,7 +965,7 @@ qla82xx_flash_wait_write_finish(struct qla_hw_data *ha) | |||
964 | return ret; | 965 | return ret; |
965 | } | 966 | } |
966 | 967 | ||
967 | int | 968 | static int |
968 | qla82xx_flash_set_write_enable(struct qla_hw_data *ha) | 969 | qla82xx_flash_set_write_enable(struct qla_hw_data *ha) |
969 | { | 970 | { |
970 | uint32_t val; | 971 | uint32_t val; |
@@ -981,7 +982,7 @@ qla82xx_flash_set_write_enable(struct qla_hw_data *ha) | |||
981 | return 0; | 982 | return 0; |
982 | } | 983 | } |
983 | 984 | ||
984 | int | 985 | static int |
985 | qla82xx_write_status_reg(struct qla_hw_data *ha, uint32_t val) | 986 | qla82xx_write_status_reg(struct qla_hw_data *ha, uint32_t val) |
986 | { | 987 | { |
987 | if (qla82xx_flash_set_write_enable(ha)) | 988 | if (qla82xx_flash_set_write_enable(ha)) |
@@ -996,7 +997,7 @@ qla82xx_write_status_reg(struct qla_hw_data *ha, uint32_t val) | |||
996 | return qla82xx_flash_wait_write_finish(ha); | 997 | return qla82xx_flash_wait_write_finish(ha); |
997 | } | 998 | } |
998 | 999 | ||
999 | int | 1000 | static int |
1000 | qla82xx_write_disable_flash(struct qla_hw_data *ha) | 1001 | qla82xx_write_disable_flash(struct qla_hw_data *ha) |
1001 | { | 1002 | { |
1002 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_WRDI); | 1003 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_WRDI); |
@@ -1008,7 +1009,7 @@ qla82xx_write_disable_flash(struct qla_hw_data *ha) | |||
1008 | return 0; | 1009 | return 0; |
1009 | } | 1010 | } |
1010 | 1011 | ||
1011 | int | 1012 | static int |
1012 | ql82xx_rom_lock_d(struct qla_hw_data *ha) | 1013 | ql82xx_rom_lock_d(struct qla_hw_data *ha) |
1013 | { | 1014 | { |
1014 | int loops = 0; | 1015 | int loops = 0; |
@@ -1024,7 +1025,7 @@ ql82xx_rom_lock_d(struct qla_hw_data *ha) | |||
1024 | return 0;; | 1025 | return 0;; |
1025 | } | 1026 | } |
1026 | 1027 | ||
1027 | int | 1028 | static int |
1028 | qla82xx_write_flash_dword(struct qla_hw_data *ha, uint32_t flashaddr, | 1029 | qla82xx_write_flash_dword(struct qla_hw_data *ha, uint32_t flashaddr, |
1029 | uint32_t data) | 1030 | uint32_t data) |
1030 | { | 1031 | { |
@@ -1061,7 +1062,8 @@ done_write: | |||
1061 | /* This routine does CRB initialize sequence | 1062 | /* This routine does CRB initialize sequence |
1062 | * to put the ISP into operational state | 1063 | * to put the ISP into operational state |
1063 | */ | 1064 | */ |
1064 | int qla82xx_pinit_from_rom(scsi_qla_host_t *vha) | 1065 | static int |
1066 | qla82xx_pinit_from_rom(scsi_qla_host_t *vha) | ||
1065 | { | 1067 | { |
1066 | int addr, val; | 1068 | int addr, val; |
1067 | int i ; | 1069 | int i ; |
@@ -1207,7 +1209,8 @@ int qla82xx_pinit_from_rom(scsi_qla_host_t *vha) | |||
1207 | return 0; | 1209 | return 0; |
1208 | } | 1210 | } |
1209 | 1211 | ||
1210 | int qla82xx_check_for_bad_spd(struct qla_hw_data *ha) | 1212 | static int |
1213 | qla82xx_check_for_bad_spd(struct qla_hw_data *ha) | ||
1211 | { | 1214 | { |
1212 | u32 val = 0; | 1215 | u32 val = 0; |
1213 | val = qla82xx_rd_32(ha, BOOT_LOADER_DIMM_STATUS); | 1216 | val = qla82xx_rd_32(ha, BOOT_LOADER_DIMM_STATUS); |
@@ -1225,7 +1228,116 @@ int qla82xx_check_for_bad_spd(struct qla_hw_data *ha) | |||
1225 | return 0; | 1228 | return 0; |
1226 | } | 1229 | } |
1227 | 1230 | ||
1228 | int | 1231 | static int |
1232 | qla82xx_pci_mem_write_2M(struct qla_hw_data *ha, | ||
1233 | u64 off, void *data, int size) | ||
1234 | { | ||
1235 | int i, j, ret = 0, loop, sz[2], off0; | ||
1236 | int scale, shift_amount, startword; | ||
1237 | uint32_t temp; | ||
1238 | uint64_t off8, mem_crb, tmpw, word[2] = {0, 0}; | ||
1239 | |||
1240 | /* | ||
1241 | * If not MN, go check for MS or invalid. | ||
1242 | */ | ||
1243 | if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX) | ||
1244 | mem_crb = QLA82XX_CRB_QDR_NET; | ||
1245 | else { | ||
1246 | mem_crb = QLA82XX_CRB_DDR_NET; | ||
1247 | if (qla82xx_pci_mem_bound_check(ha, off, size) == 0) | ||
1248 | return qla82xx_pci_mem_write_direct(ha, | ||
1249 | off, data, size); | ||
1250 | } | ||
1251 | |||
1252 | off0 = off & 0x7; | ||
1253 | sz[0] = (size < (8 - off0)) ? size : (8 - off0); | ||
1254 | sz[1] = size - sz[0]; | ||
1255 | |||
1256 | off8 = off & 0xfffffff0; | ||
1257 | loop = (((off & 0xf) + size - 1) >> 4) + 1; | ||
1258 | shift_amount = 4; | ||
1259 | scale = 2; | ||
1260 | startword = (off & 0xf)/8; | ||
1261 | |||
1262 | for (i = 0; i < loop; i++) { | ||
1263 | if (qla82xx_pci_mem_read_2M(ha, off8 + | ||
1264 | (i << shift_amount), &word[i * scale], 8)) | ||
1265 | return -1; | ||
1266 | } | ||
1267 | |||
1268 | switch (size) { | ||
1269 | case 1: | ||
1270 | tmpw = *((uint8_t *)data); | ||
1271 | break; | ||
1272 | case 2: | ||
1273 | tmpw = *((uint16_t *)data); | ||
1274 | break; | ||
1275 | case 4: | ||
1276 | tmpw = *((uint32_t *)data); | ||
1277 | break; | ||
1278 | case 8: | ||
1279 | default: | ||
1280 | tmpw = *((uint64_t *)data); | ||
1281 | break; | ||
1282 | } | ||
1283 | |||
1284 | if (sz[0] == 8) { | ||
1285 | word[startword] = tmpw; | ||
1286 | } else { | ||
1287 | word[startword] &= | ||
1288 | ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); | ||
1289 | word[startword] |= tmpw << (off0 * 8); | ||
1290 | } | ||
1291 | if (sz[1] != 0) { | ||
1292 | word[startword+1] &= ~(~0ULL << (sz[1] * 8)); | ||
1293 | word[startword+1] |= tmpw >> (sz[0] * 8); | ||
1294 | } | ||
1295 | |||
1296 | /* | ||
1297 | * don't lock here - write_wx gets the lock if each time | ||
1298 | * write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1299 | * netxen_nic_pci_change_crbwindow_128M(adapter, 0); | ||
1300 | */ | ||
1301 | for (i = 0; i < loop; i++) { | ||
1302 | temp = off8 + (i << shift_amount); | ||
1303 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp); | ||
1304 | temp = 0; | ||
1305 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_HI, temp); | ||
1306 | temp = word[i * scale] & 0xffffffff; | ||
1307 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp); | ||
1308 | temp = (word[i * scale] >> 32) & 0xffffffff; | ||
1309 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp); | ||
1310 | temp = word[i*scale + 1] & 0xffffffff; | ||
1311 | qla82xx_wr_32(ha, mem_crb + | ||
1312 | MIU_TEST_AGT_WRDATA_UPPER_LO, temp); | ||
1313 | temp = (word[i*scale + 1] >> 32) & 0xffffffff; | ||
1314 | qla82xx_wr_32(ha, mem_crb + | ||
1315 | MIU_TEST_AGT_WRDATA_UPPER_HI, temp); | ||
1316 | |||
1317 | temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; | ||
1318 | qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); | ||
1319 | temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; | ||
1320 | qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); | ||
1321 | |||
1322 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1323 | temp = qla82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL); | ||
1324 | if ((temp & MIU_TA_CTL_BUSY) == 0) | ||
1325 | break; | ||
1326 | } | ||
1327 | |||
1328 | if (j >= MAX_CTL_CHECK) { | ||
1329 | if (printk_ratelimit()) | ||
1330 | dev_err(&ha->pdev->dev, | ||
1331 | "failed to write through agent\n"); | ||
1332 | ret = -1; | ||
1333 | break; | ||
1334 | } | ||
1335 | } | ||
1336 | |||
1337 | return ret; | ||
1338 | } | ||
1339 | |||
1340 | static int | ||
1229 | qla82xx_fw_load_from_flash(struct qla_hw_data *ha) | 1341 | qla82xx_fw_load_from_flash(struct qla_hw_data *ha) |
1230 | { | 1342 | { |
1231 | int i; | 1343 | int i; |
@@ -1357,114 +1469,6 @@ qla82xx_pci_mem_read_2M(struct qla_hw_data *ha, | |||
1357 | return 0; | 1469 | return 0; |
1358 | } | 1470 | } |
1359 | 1471 | ||
1360 | int | ||
1361 | qla82xx_pci_mem_write_2M(struct qla_hw_data *ha, | ||
1362 | u64 off, void *data, int size) | ||
1363 | { | ||
1364 | int i, j, ret = 0, loop, sz[2], off0; | ||
1365 | int scale, shift_amount, startword; | ||
1366 | uint32_t temp; | ||
1367 | uint64_t off8, mem_crb, tmpw, word[2] = {0, 0}; | ||
1368 | |||
1369 | /* | ||
1370 | * If not MN, go check for MS or invalid. | ||
1371 | */ | ||
1372 | if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX) | ||
1373 | mem_crb = QLA82XX_CRB_QDR_NET; | ||
1374 | else { | ||
1375 | mem_crb = QLA82XX_CRB_DDR_NET; | ||
1376 | if (qla82xx_pci_mem_bound_check(ha, off, size) == 0) | ||
1377 | return qla82xx_pci_mem_write_direct(ha, | ||
1378 | off, data, size); | ||
1379 | } | ||
1380 | |||
1381 | off0 = off & 0x7; | ||
1382 | sz[0] = (size < (8 - off0)) ? size : (8 - off0); | ||
1383 | sz[1] = size - sz[0]; | ||
1384 | |||
1385 | off8 = off & 0xfffffff0; | ||
1386 | loop = (((off & 0xf) + size - 1) >> 4) + 1; | ||
1387 | shift_amount = 4; | ||
1388 | scale = 2; | ||
1389 | startword = (off & 0xf)/8; | ||
1390 | |||
1391 | for (i = 0; i < loop; i++) { | ||
1392 | if (qla82xx_pci_mem_read_2M(ha, off8 + | ||
1393 | (i << shift_amount), &word[i * scale], 8)) | ||
1394 | return -1; | ||
1395 | } | ||
1396 | |||
1397 | switch (size) { | ||
1398 | case 1: | ||
1399 | tmpw = *((uint8_t *)data); | ||
1400 | break; | ||
1401 | case 2: | ||
1402 | tmpw = *((uint16_t *)data); | ||
1403 | break; | ||
1404 | case 4: | ||
1405 | tmpw = *((uint32_t *)data); | ||
1406 | break; | ||
1407 | case 8: | ||
1408 | default: | ||
1409 | tmpw = *((uint64_t *)data); | ||
1410 | break; | ||
1411 | } | ||
1412 | |||
1413 | if (sz[0] == 8) { | ||
1414 | word[startword] = tmpw; | ||
1415 | } else { | ||
1416 | word[startword] &= | ||
1417 | ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); | ||
1418 | word[startword] |= tmpw << (off0 * 8); | ||
1419 | } | ||
1420 | if (sz[1] != 0) { | ||
1421 | word[startword+1] &= ~(~0ULL << (sz[1] * 8)); | ||
1422 | word[startword+1] |= tmpw >> (sz[0] * 8); | ||
1423 | } | ||
1424 | |||
1425 | /* | ||
1426 | * don't lock here - write_wx gets the lock if each time | ||
1427 | * write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1428 | * netxen_nic_pci_change_crbwindow_128M(adapter, 0); | ||
1429 | */ | ||
1430 | for (i = 0; i < loop; i++) { | ||
1431 | temp = off8 + (i << shift_amount); | ||
1432 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp); | ||
1433 | temp = 0; | ||
1434 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_HI, temp); | ||
1435 | temp = word[i * scale] & 0xffffffff; | ||
1436 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp); | ||
1437 | temp = (word[i * scale] >> 32) & 0xffffffff; | ||
1438 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp); | ||
1439 | temp = word[i*scale + 1] & 0xffffffff; | ||
1440 | qla82xx_wr_32(ha, mem_crb + | ||
1441 | MIU_TEST_AGT_WRDATA_UPPER_LO, temp); | ||
1442 | temp = (word[i*scale + 1] >> 32) & 0xffffffff; | ||
1443 | qla82xx_wr_32(ha, mem_crb + | ||
1444 | MIU_TEST_AGT_WRDATA_UPPER_HI, temp); | ||
1445 | |||
1446 | temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; | ||
1447 | qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); | ||
1448 | temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; | ||
1449 | qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); | ||
1450 | |||
1451 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1452 | temp = qla82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL); | ||
1453 | if ((temp & MIU_TA_CTL_BUSY) == 0) | ||
1454 | break; | ||
1455 | } | ||
1456 | |||
1457 | if (j >= MAX_CTL_CHECK) { | ||
1458 | if (printk_ratelimit()) | ||
1459 | dev_err(&ha->pdev->dev, | ||
1460 | "failed to write through agent\n"); | ||
1461 | ret = -1; | ||
1462 | break; | ||
1463 | } | ||
1464 | } | ||
1465 | |||
1466 | return ret; | ||
1467 | } | ||
1468 | 1472 | ||
1469 | static struct qla82xx_uri_table_desc * | 1473 | static struct qla82xx_uri_table_desc * |
1470 | qla82xx_get_table_desc(const u8 *unirom, int section) | 1474 | qla82xx_get_table_desc(const u8 *unirom, int section) |
@@ -1725,7 +1729,8 @@ void qla82xx_reset_adapter(struct scsi_qla_host *vha) | |||
1725 | ha->isp_ops->disable_intrs(ha); | 1729 | ha->isp_ops->disable_intrs(ha); |
1726 | } | 1730 | } |
1727 | 1731 | ||
1728 | int qla82xx_fw_load_from_blob(struct qla_hw_data *ha) | 1732 | static int |
1733 | qla82xx_fw_load_from_blob(struct qla_hw_data *ha) | ||
1729 | { | 1734 | { |
1730 | u64 *ptr64; | 1735 | u64 *ptr64; |
1731 | u32 i, flashaddr, size; | 1736 | u32 i, flashaddr, size; |
@@ -1836,7 +1841,8 @@ qla82xx_validate_firmware_blob(scsi_qla_host_t *vha, uint8_t fw_type) | |||
1836 | return 0; | 1841 | return 0; |
1837 | } | 1842 | } |
1838 | 1843 | ||
1839 | int qla82xx_check_cmdpeg_state(struct qla_hw_data *ha) | 1844 | static int |
1845 | qla82xx_check_cmdpeg_state(struct qla_hw_data *ha) | ||
1840 | { | 1846 | { |
1841 | u32 val = 0; | 1847 | u32 val = 0; |
1842 | int retries = 60; | 1848 | int retries = 60; |
@@ -1874,7 +1880,8 @@ int qla82xx_check_cmdpeg_state(struct qla_hw_data *ha) | |||
1874 | return QLA_FUNCTION_FAILED; | 1880 | return QLA_FUNCTION_FAILED; |
1875 | } | 1881 | } |
1876 | 1882 | ||
1877 | int qla82xx_check_rcvpeg_state(struct qla_hw_data *ha) | 1883 | static int |
1884 | qla82xx_check_rcvpeg_state(struct qla_hw_data *ha) | ||
1878 | { | 1885 | { |
1879 | u32 val = 0; | 1886 | u32 val = 0; |
1880 | int retries = 60; | 1887 | int retries = 60; |
@@ -1933,7 +1940,7 @@ static struct qla82xx_legacy_intr_set legacy_intr[] = \ | |||
1933 | * @ha: SCSI driver HA context | 1940 | * @ha: SCSI driver HA context |
1934 | * @mb0: Mailbox0 register | 1941 | * @mb0: Mailbox0 register |
1935 | */ | 1942 | */ |
1936 | void | 1943 | static void |
1937 | qla82xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) | 1944 | qla82xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) |
1938 | { | 1945 | { |
1939 | uint16_t cnt; | 1946 | uint16_t cnt; |
@@ -2257,7 +2264,7 @@ void qla82xx_init_flags(struct qla_hw_data *ha) | |||
2257 | ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg; | 2264 | ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg; |
2258 | } | 2265 | } |
2259 | 2266 | ||
2260 | static inline void | 2267 | inline void |
2261 | qla82xx_set_drv_active(scsi_qla_host_t *vha) | 2268 | qla82xx_set_drv_active(scsi_qla_host_t *vha) |
2262 | { | 2269 | { |
2263 | uint32_t drv_active; | 2270 | uint32_t drv_active; |
@@ -2267,10 +2274,11 @@ qla82xx_set_drv_active(scsi_qla_host_t *vha) | |||
2267 | 2274 | ||
2268 | /* If reset value is all FF's, initialize DRV_ACTIVE */ | 2275 | /* If reset value is all FF's, initialize DRV_ACTIVE */ |
2269 | if (drv_active == 0xffffffff) { | 2276 | if (drv_active == 0xffffffff) { |
2270 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, 0); | 2277 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, |
2278 | QLA82XX_DRV_NOT_ACTIVE); | ||
2271 | drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | 2279 | drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); |
2272 | } | 2280 | } |
2273 | drv_active |= (1 << (ha->portnum * 4)); | 2281 | drv_active |= (QLA82XX_DRV_ACTIVE << (ha->portnum * 4)); |
2274 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); | 2282 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); |
2275 | } | 2283 | } |
2276 | 2284 | ||
@@ -2280,7 +2288,7 @@ qla82xx_clear_drv_active(struct qla_hw_data *ha) | |||
2280 | uint32_t drv_active; | 2288 | uint32_t drv_active; |
2281 | 2289 | ||
2282 | drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | 2290 | drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); |
2283 | drv_active &= ~(1 << (ha->portnum * 4)); | 2291 | drv_active &= ~(QLA82XX_DRV_ACTIVE << (ha->portnum * 4)); |
2284 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); | 2292 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); |
2285 | } | 2293 | } |
2286 | 2294 | ||
@@ -2291,7 +2299,7 @@ qla82xx_need_reset(struct qla_hw_data *ha) | |||
2291 | int rval; | 2299 | int rval; |
2292 | 2300 | ||
2293 | drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | 2301 | drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); |
2294 | rval = drv_state & (1 << (ha->portnum * 4)); | 2302 | rval = drv_state & (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4)); |
2295 | return rval; | 2303 | return rval; |
2296 | } | 2304 | } |
2297 | 2305 | ||
@@ -2305,7 +2313,7 @@ qla82xx_set_rst_ready(struct qla_hw_data *ha) | |||
2305 | 2313 | ||
2306 | /* If reset value is all FF's, initialize DRV_STATE */ | 2314 | /* If reset value is all FF's, initialize DRV_STATE */ |
2307 | if (drv_state == 0xffffffff) { | 2315 | if (drv_state == 0xffffffff) { |
2308 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0); | 2316 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, QLA82XX_DRVST_NOT_RDY); |
2309 | drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | 2317 | drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); |
2310 | } | 2318 | } |
2311 | drv_state |= (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4)); | 2319 | drv_state |= (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4)); |
@@ -2335,7 +2343,8 @@ qla82xx_set_qsnt_ready(struct qla_hw_data *ha) | |||
2335 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state); | 2343 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state); |
2336 | } | 2344 | } |
2337 | 2345 | ||
2338 | int qla82xx_load_fw(scsi_qla_host_t *vha) | 2346 | static int |
2347 | qla82xx_load_fw(scsi_qla_host_t *vha) | ||
2339 | { | 2348 | { |
2340 | int rst; | 2349 | int rst; |
2341 | struct fw_blob *blob; | 2350 | struct fw_blob *blob; |
@@ -2411,7 +2420,7 @@ fw_load_failed: | |||
2411 | return QLA_FUNCTION_FAILED; | 2420 | return QLA_FUNCTION_FAILED; |
2412 | } | 2421 | } |
2413 | 2422 | ||
2414 | static int | 2423 | int |
2415 | qla82xx_start_firmware(scsi_qla_host_t *vha) | 2424 | qla82xx_start_firmware(scsi_qla_host_t *vha) |
2416 | { | 2425 | { |
2417 | int pcie_cap; | 2426 | int pcie_cap; |
@@ -2419,7 +2428,7 @@ qla82xx_start_firmware(scsi_qla_host_t *vha) | |||
2419 | struct qla_hw_data *ha = vha->hw; | 2428 | struct qla_hw_data *ha = vha->hw; |
2420 | 2429 | ||
2421 | /* scrub dma mask expansion register */ | 2430 | /* scrub dma mask expansion register */ |
2422 | qla82xx_wr_32(ha, CRB_DMA_SHIFT, 0x55555555); | 2431 | qla82xx_wr_32(ha, CRB_DMA_SHIFT, QLA82XX_DMA_SHIFT_VALUE); |
2423 | 2432 | ||
2424 | /* Put both the PEG CMD and RCV PEG to default state | 2433 | /* Put both the PEG CMD and RCV PEG to default state |
2425 | * of 0 before resetting the hardware | 2434 | * of 0 before resetting the hardware |
@@ -2882,7 +2891,7 @@ queuing_error: | |||
2882 | return QLA_FUNCTION_FAILED; | 2891 | return QLA_FUNCTION_FAILED; |
2883 | } | 2892 | } |
2884 | 2893 | ||
2885 | uint32_t * | 2894 | static uint32_t * |
2886 | qla82xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, | 2895 | qla82xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, |
2887 | uint32_t length) | 2896 | uint32_t length) |
2888 | { | 2897 | { |
@@ -2903,7 +2912,7 @@ done_read: | |||
2903 | return dwptr; | 2912 | return dwptr; |
2904 | } | 2913 | } |
2905 | 2914 | ||
2906 | int | 2915 | static int |
2907 | qla82xx_unprotect_flash(struct qla_hw_data *ha) | 2916 | qla82xx_unprotect_flash(struct qla_hw_data *ha) |
2908 | { | 2917 | { |
2909 | int ret; | 2918 | int ret; |
@@ -2934,7 +2943,7 @@ done_unprotect: | |||
2934 | return ret; | 2943 | return ret; |
2935 | } | 2944 | } |
2936 | 2945 | ||
2937 | int | 2946 | static int |
2938 | qla82xx_protect_flash(struct qla_hw_data *ha) | 2947 | qla82xx_protect_flash(struct qla_hw_data *ha) |
2939 | { | 2948 | { |
2940 | int ret; | 2949 | int ret; |
@@ -2963,7 +2972,7 @@ done_protect: | |||
2963 | return ret; | 2972 | return ret; |
2964 | } | 2973 | } |
2965 | 2974 | ||
2966 | int | 2975 | static int |
2967 | qla82xx_erase_sector(struct qla_hw_data *ha, int addr) | 2976 | qla82xx_erase_sector(struct qla_hw_data *ha, int addr) |
2968 | { | 2977 | { |
2969 | int ret = 0; | 2978 | int ret = 0; |
@@ -3156,6 +3165,20 @@ qla82xx_start_iocbs(srb_t *sp) | |||
3156 | } | 3165 | } |
3157 | } | 3166 | } |
3158 | 3167 | ||
3168 | void qla82xx_rom_lock_recovery(struct qla_hw_data *ha) | ||
3169 | { | ||
3170 | if (qla82xx_rom_lock(ha)) | ||
3171 | /* Someone else is holding the lock. */ | ||
3172 | qla_printk(KERN_INFO, ha, "Resetting rom_lock\n"); | ||
3173 | |||
3174 | /* | ||
3175 | * Either we got the lock, or someone | ||
3176 | * else died while holding it. | ||
3177 | * In either case, unlock. | ||
3178 | */ | ||
3179 | qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK)); | ||
3180 | } | ||
3181 | |||
3159 | /* | 3182 | /* |
3160 | * qla82xx_device_bootstrap | 3183 | * qla82xx_device_bootstrap |
3161 | * Initialize device, set DEV_READY, start fw | 3184 | * Initialize device, set DEV_READY, start fw |
@@ -3170,12 +3193,13 @@ qla82xx_start_iocbs(srb_t *sp) | |||
3170 | static int | 3193 | static int |
3171 | qla82xx_device_bootstrap(scsi_qla_host_t *vha) | 3194 | qla82xx_device_bootstrap(scsi_qla_host_t *vha) |
3172 | { | 3195 | { |
3173 | int rval, i, timeout; | 3196 | int rval = QLA_SUCCESS; |
3197 | int i, timeout; | ||
3174 | uint32_t old_count, count; | 3198 | uint32_t old_count, count; |
3175 | struct qla_hw_data *ha = vha->hw; | 3199 | struct qla_hw_data *ha = vha->hw; |
3200 | int need_reset = 0, peg_stuck = 1; | ||
3176 | 3201 | ||
3177 | if (qla82xx_need_reset(ha)) | 3202 | need_reset = qla82xx_need_reset(ha); |
3178 | goto dev_initialize; | ||
3179 | 3203 | ||
3180 | old_count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | 3204 | old_count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); |
3181 | 3205 | ||
@@ -3189,9 +3213,27 @@ qla82xx_device_bootstrap(scsi_qla_host_t *vha) | |||
3189 | 3213 | ||
3190 | count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | 3214 | count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); |
3191 | if (count != old_count) | 3215 | if (count != old_count) |
3216 | peg_stuck = 0; | ||
3217 | } | ||
3218 | |||
3219 | if (need_reset) { | ||
3220 | /* We are trying to perform a recovery here. */ | ||
3221 | if (peg_stuck) | ||
3222 | qla82xx_rom_lock_recovery(ha); | ||
3223 | goto dev_initialize; | ||
3224 | } else { | ||
3225 | /* Start of day for this ha context. */ | ||
3226 | if (peg_stuck) { | ||
3227 | /* Either we are the first or recovery in progress. */ | ||
3228 | qla82xx_rom_lock_recovery(ha); | ||
3229 | goto dev_initialize; | ||
3230 | } else | ||
3231 | /* Firmware already running. */ | ||
3192 | goto dev_ready; | 3232 | goto dev_ready; |
3193 | } | 3233 | } |
3194 | 3234 | ||
3235 | return rval; | ||
3236 | |||
3195 | dev_initialize: | 3237 | dev_initialize: |
3196 | /* set to DEV_INITIALIZING */ | 3238 | /* set to DEV_INITIALIZING */ |
3197 | qla_printk(KERN_INFO, ha, "HW State: INITIALIZING\n"); | 3239 | qla_printk(KERN_INFO, ha, "HW State: INITIALIZING\n"); |
@@ -3304,6 +3346,9 @@ qla82xx_check_fw_alive(scsi_qla_host_t *vha) | |||
3304 | struct qla_hw_data *ha = vha->hw; | 3346 | struct qla_hw_data *ha = vha->hw; |
3305 | 3347 | ||
3306 | fw_heartbeat_counter = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | 3348 | fw_heartbeat_counter = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); |
3349 | /* all 0xff, assume AER/EEH in progress, ignore */ | ||
3350 | if (fw_heartbeat_counter == 0xffffffff) | ||
3351 | return; | ||
3307 | if (vha->fw_heartbeat_counter == fw_heartbeat_counter) { | 3352 | if (vha->fw_heartbeat_counter == fw_heartbeat_counter) { |
3308 | vha->seconds_since_last_heartbeat++; | 3353 | vha->seconds_since_last_heartbeat++; |
3309 | /* FW not alive after 2 seconds */ | 3354 | /* FW not alive after 2 seconds */ |