Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] bfa: IOC bug fixes.

- Add logic to handle the case where PCI mapping goes away when
IOCPF state machine is waiting for semaphore.
- Added logic to unlock hw semaphore if the previos FW boot was
from flash based and the current FW initialization attempt is from OS.
- Added fix to update hbfails and hb_count stats during hwerror event.

Signed-off-by: Krishna Gudipati <kgudipat@brocade.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

authored by

Krishna Gudipati and committed by
James Bottomley
5a0adaed 1a4d8e1b

+125 -34
+2
drivers/scsi/bfa/bfa_defs.h
··· 274 274 BFA_IOC_DISABLED = 10, /* IOC is disabled */ 275 275 BFA_IOC_FWMISMATCH = 11, /* IOC f/w different from drivers */ 276 276 BFA_IOC_ENABLING = 12, /* IOC is being enabled */ 277 + BFA_IOC_HWFAIL = 13, /* PCI mapping doesn't exist */ 277 278 }; 278 279 279 280 /* ··· 304 303 u32 enable_reqs; 305 304 u32 disable_replies; 306 305 u32 enable_replies; 306 + u32 rsvd; 307 307 }; 308 308 309 309 /*
+111 -5
drivers/scsi/bfa/bfa_ioc.c
··· 112 112 IOC_E_HBFAIL = 9, /* heartbeat failure */ 113 113 IOC_E_HWERROR = 10, /* hardware error interrupt */ 114 114 IOC_E_TIMEOUT = 11, /* timeout */ 115 + IOC_E_HWFAILED = 12, /* PCI mapping failure notice */ 115 116 }; 116 117 117 118 bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event); ··· 124 123 bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event); 125 124 bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event); 126 125 bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event); 126 + bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc_s, enum ioc_event); 127 127 128 128 static struct bfa_sm_table_s ioc_sm_table[] = { 129 129 {BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT}, ··· 136 134 {BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL}, 137 135 {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING}, 138 136 {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED}, 137 + {BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL}, 139 138 }; 140 139 141 140 /* ··· 179 176 IOCPF_E_GETATTRFAIL = 9, /* init fail notice by ioc sm */ 180 177 IOCPF_E_SEMLOCKED = 10, /* h/w semaphore is locked */ 181 178 IOCPF_E_TIMEOUT = 11, /* f/w response timeout */ 179 + IOCPF_E_SEM_ERROR = 12, /* h/w sem mapping error */ 182 180 }; 183 181 184 182 /* ··· 326 322 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); 327 323 break; 328 324 325 + case IOC_E_HWFAILED: 326 + ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); 327 + bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail); 328 + break; 329 + 329 330 case IOC_E_DISABLE: 330 331 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); 331 332 break; ··· 474 465 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL); 475 466 break; 476 467 468 + case IOC_E_HWFAILED: 469 + bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail); 470 + bfa_ioc_disable_comp(ioc); 471 + break; 472 + 477 473 default: 478 474 bfa_sm_fault(ioc, event); 479 475 } ··· 548 534 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); 549 535 break; 550 536 537 + case IOC_E_HWFAILED: 538 + ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); 539 + bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail); 540 + break; 541 + 551 542 case IOC_E_ENABLE: 552 543 break; 553 544 ··· 610 591 } 611 592 } 612 593 594 + static void 595 + bfa_ioc_sm_hwfail_entry(struct bfa_ioc_s *ioc) 596 + { 597 + bfa_trc(ioc, 0); 598 + } 599 + 600 + static void 601 + bfa_ioc_sm_hwfail(struct bfa_ioc_s *ioc, enum ioc_event event) 602 + { 603 + bfa_trc(ioc, event); 604 + 605 + switch (event) { 606 + case IOC_E_ENABLE: 607 + ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); 608 + break; 609 + 610 + case IOC_E_DISABLE: 611 + ioc->cbfn->disable_cbfn(ioc->bfa); 612 + break; 613 + 614 + case IOC_E_DETACH: 615 + bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit); 616 + break; 617 + 618 + default: 619 + bfa_sm_fault(ioc, event); 620 + } 621 + } 622 + 613 623 /* 614 624 * IOCPF State Machine 615 625 */ ··· 682 634 static void 683 635 bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf) 684 636 { 637 + struct bfi_ioc_image_hdr_s fwhdr; 638 + u32 fwstate = readl(iocpf->ioc->ioc_regs.ioc_fwstate); 639 + 640 + /* h/w sem init */ 641 + if (fwstate == BFI_IOC_UNINIT) 642 + goto sem_get; 643 + 644 + bfa_ioc_fwver_get(iocpf->ioc, &fwhdr); 645 + 646 + if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL) 647 + goto sem_get; 648 + 649 + bfa_trc(iocpf->ioc, fwstate); 650 + bfa_trc(iocpf->ioc, fwhdr.exec); 651 + writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.ioc_fwstate); 652 + 653 + /* 654 + * Try to lock and then unlock the semaphore. 655 + */ 656 + readl(iocpf->ioc->ioc_regs.ioc_sem_reg); 657 + writel(1, iocpf->ioc->ioc_regs.ioc_sem_reg); 658 + sem_get: 685 659 bfa_ioc_hw_sem_get(iocpf->ioc); 686 660 } 687 661 ··· 732 662 writel(1, ioc->ioc_regs.ioc_sem_reg); 733 663 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch); 734 664 } 665 + break; 666 + 667 + case IOCPF_E_SEM_ERROR: 668 + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); 669 + bfa_fsm_send_event(ioc, IOC_E_HWFAILED); 735 670 break; 736 671 737 672 case IOCPF_E_DISABLE: ··· 830 755 writel(1, ioc->ioc_regs.ioc_sem_reg); 831 756 bfa_sem_timer_start(ioc); 832 757 } 758 + break; 759 + 760 + case IOCPF_E_SEM_ERROR: 761 + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); 762 + bfa_fsm_send_event(ioc, IOC_E_HWFAILED); 833 763 break; 834 764 835 765 case IOCPF_E_DISABLE: ··· 1037 957 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); 1038 958 break; 1039 959 960 + case IOCPF_E_SEM_ERROR: 961 + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); 962 + bfa_fsm_send_event(ioc, IOC_E_HWFAILED); 963 + break; 964 + 1040 965 case IOCPF_E_FAIL: 1041 966 break; 1042 967 ··· 1085 1000 static void 1086 1001 bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf_s *iocpf) 1087 1002 { 1003 + bfa_ioc_debug_save_ftrc(iocpf->ioc); 1088 1004 bfa_ioc_hw_sem_get(iocpf->ioc); 1089 1005 } 1090 1006 ··· 1106 1020 writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); 1107 1021 writel(1, ioc->ioc_regs.ioc_sem_reg); 1108 1022 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); 1023 + break; 1024 + 1025 + case IOCPF_E_SEM_ERROR: 1026 + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); 1027 + bfa_fsm_send_event(ioc, IOC_E_HWFAILED); 1109 1028 break; 1110 1029 1111 1030 case IOCPF_E_DISABLE: ··· 1135 1044 static void 1136 1045 bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf) 1137 1046 { 1047 + bfa_trc(iocpf->ioc, 0); 1138 1048 } 1139 1049 1140 1050 /* ··· 1205 1113 } 1206 1114 break; 1207 1115 1116 + case IOCPF_E_SEM_ERROR: 1117 + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); 1118 + bfa_fsm_send_event(ioc, IOC_E_HWFAILED); 1119 + break; 1120 + 1208 1121 case IOCPF_E_DISABLE: 1209 1122 bfa_sem_timer_stop(ioc); 1210 1123 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); ··· 1226 1129 static void 1227 1130 bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf) 1228 1131 { 1132 + bfa_trc(iocpf->ioc, 0); 1229 1133 } 1230 1134 1231 1135 /* ··· 1293 1195 if (!(r32 & 1)) 1294 1196 return BFA_TRUE; 1295 1197 1296 - WARN_ON(cnt >= BFA_SEM_SPINCNT); 1297 1198 return BFA_FALSE; 1298 1199 } 1299 1200 ··· 1306 1209 * will return 1. Semaphore is released by writing 1 to the register 1307 1210 */ 1308 1211 r32 = readl(ioc->ioc_regs.ioc_sem_reg); 1212 + if (r32 == ~0) { 1213 + WARN_ON(r32 == ~0); 1214 + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEM_ERROR); 1215 + return; 1216 + } 1309 1217 if (!(r32 & 1)) { 1310 1218 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED); 1311 1219 return; ··· 1719 1617 attr->adapter_prop = be32_to_cpu(attr->adapter_prop); 1720 1618 attr->card_type = be32_to_cpu(attr->card_type); 1721 1619 attr->maxfrsize = be16_to_cpu(attr->maxfrsize); 1620 + ioc->fcmode = (attr->port_mode == BFI_PORT_MODE_FC); 1722 1621 1723 1622 bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR); 1724 1623 } ··· 1836 1733 /* 1837 1734 * release semaphore. 1838 1735 */ 1736 + readl(ioc->ioc_regs.ioc_init_sem_reg); 1839 1737 writel(1, ioc->ioc_regs.ioc_init_sem_reg); 1840 1738 1841 1739 bfa_trc(ioc, pgnum); ··· 1893 1789 /* 1894 1790 * release semaphore. 1895 1791 */ 1792 + readl(ioc->ioc_regs.ioc_init_sem_reg); 1896 1793 writel(1, ioc->ioc_regs.ioc_init_sem_reg); 1897 1794 bfa_trc(ioc, pgnum); 1898 1795 return BFA_STATUS_OK; ··· 1945 1840 /* 1946 1841 * release semaphore. 1947 1842 */ 1843 + readl(ioc->ioc_regs.ioc_init_sem_reg); 1948 1844 writel(1, ioc->ioc_regs.ioc_init_sem_reg); 1949 1845 1950 1846 return BFA_STATUS_OK; ··· 2338 2232 void 2339 2233 bfa_ioc_error_isr(struct bfa_ioc_s *ioc) 2340 2234 { 2235 + bfa_ioc_stats(ioc, ioc_hbfails); 2236 + ioc->stats.hb_count = ioc->hb_count; 2341 2237 bfa_fsm_send_event(ioc, IOC_E_HWERROR); 2342 2238 } 2343 2239 ··· 2462 2354 enum bfa_ioc_type_e 2463 2355 bfa_ioc_get_type(struct bfa_ioc_s *ioc) 2464 2356 { 2465 - enum bfi_port_mode mode; 2466 - 2467 2357 if (ioc->clscode == BFI_PCIFN_CLASS_ETH) 2468 2358 return BFA_IOC_TYPE_LL; 2469 2359 2470 2360 WARN_ON(ioc->clscode != BFI_PCIFN_CLASS_FC); 2471 2361 2472 - mode = (ioc->port_id == 0) ? ioc->port0_mode : ioc->port1_mode; 2473 - return (mode == BFI_PORT_MODE_FC) 2362 + return (ioc->attr->port_mode == BFI_PORT_MODE_FC) 2474 2363 ? BFA_IOC_TYPE_FC : BFA_IOC_TYPE_FCoE; 2475 2364 } 2476 2365 ··· 2844 2739 bfa_ioc_recover(struct bfa_ioc_s *ioc) 2845 2740 { 2846 2741 bfa_ioc_stats(ioc, ioc_hbfails); 2742 + ioc->stats.hb_count = ioc->hb_count; 2847 2743 bfa_fsm_send_event(ioc, IOC_E_HBFAIL); 2848 2744 } 2849 2745
-15
drivers/scsi/bfa/bfa_ioc_cb.c
··· 69 69 static bfa_boolean_t 70 70 bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc) 71 71 { 72 - struct bfi_ioc_image_hdr_s fwhdr; 73 - uint32_t fwstate = readl(ioc->ioc_regs.ioc_fwstate); 74 - 75 - if (fwstate == BFI_IOC_UNINIT) 76 - return BFA_TRUE; 77 - 78 - bfa_ioc_fwver_get(ioc, &fwhdr); 79 - 80 - if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL) 81 - return BFA_TRUE; 82 - 83 - bfa_trc(ioc, fwstate); 84 - bfa_trc(ioc, fwhdr.exec); 85 - writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); 86 - 87 72 return BFA_TRUE; 88 73 } 89 74
+10 -13
drivers/scsi/bfa/bfa_ioc_ct.c
··· 58 58 struct bfi_ioc_image_hdr_s fwhdr; 59 59 60 60 /* 61 - * Firmware match check is relevant only for CNA. 62 - */ 63 - if (!bfa_ioc_is_cna(ioc)) 64 - return BFA_TRUE; 65 - 66 - /* 67 61 * If bios boot (flash based) -- do not increment usage count 68 62 */ 69 63 if (bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)) < ··· 72 78 */ 73 79 if (usecnt == 0) { 74 80 writel(1, ioc->ioc_regs.ioc_usage_reg); 81 + readl(ioc->ioc_regs.ioc_usage_sem_reg); 75 82 writel(1, ioc->ioc_regs.ioc_usage_sem_reg); 76 83 writel(0, ioc->ioc_regs.ioc_fail_sync); 77 84 bfa_trc(ioc, usecnt); ··· 92 97 */ 93 98 bfa_ioc_fwver_get(ioc, &fwhdr); 94 99 if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) { 100 + readl(ioc->ioc_regs.ioc_usage_sem_reg); 95 101 writel(1, ioc->ioc_regs.ioc_usage_sem_reg); 96 102 bfa_trc(ioc, usecnt); 97 103 return BFA_FALSE; ··· 103 107 */ 104 108 usecnt++; 105 109 writel(usecnt, ioc->ioc_regs.ioc_usage_reg); 110 + readl(ioc->ioc_regs.ioc_usage_sem_reg); 106 111 writel(1, ioc->ioc_regs.ioc_usage_sem_reg); 107 112 bfa_trc(ioc, usecnt); 108 113 return BFA_TRUE; ··· 113 116 bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc) 114 117 { 115 118 u32 usecnt; 116 - 117 - /* 118 - * Firmware lock is relevant only for CNA. 119 - */ 120 - if (!bfa_ioc_is_cna(ioc)) 121 - return; 122 119 123 120 /* 124 121 * If bios boot (flash based) -- do not decrement usage count ··· 132 141 writel(usecnt, ioc->ioc_regs.ioc_usage_reg); 133 142 bfa_trc(ioc, usecnt); 134 143 144 + readl(ioc->ioc_regs.ioc_usage_sem_reg); 135 145 writel(1, ioc->ioc_regs.ioc_usage_sem_reg); 136 146 } 137 147 ··· 336 344 static void 337 345 bfa_ioc_ct2_map_port(struct bfa_ioc_s *ioc) 338 346 { 339 - ioc->port_id = bfa_ioc_pcifn(ioc) % 2; 347 + void __iomem *rb = ioc->pcidev.pci_bar_kva; 348 + u32 r32; 349 + 350 + r32 = readl(rb + CT2_HOSTFN_PERSONALITY0); 351 + ioc->port_id = ((r32 & __FC_LL_PORT_MAP__MK) >> __FC_LL_PORT_MAP__SH); 340 352 341 353 bfa_trc(ioc, bfa_ioc_pcifn(ioc)); 342 354 bfa_trc(ioc, ioc->port_id); ··· 403 407 if (bfa_ioc_is_cna(ioc)) { 404 408 bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); 405 409 writel(0, ioc->ioc_regs.ioc_usage_reg); 410 + readl(ioc->ioc_regs.ioc_usage_sem_reg); 406 411 writel(1, ioc->ioc_regs.ioc_usage_sem_reg); 407 412 } 408 413
+2 -1
drivers/scsi/bfa/bfi.h
··· 236 236 wwn_t mfg_pwwn; /* Mfg port wwn */ 237 237 wwn_t mfg_nwwn; /* Mfg node wwn */ 238 238 mac_t mfg_mac; /* Mfg mac */ 239 - u16 rsvd_a; 239 + u8 port_mode; /* bfi_port_mode */ 240 + u8 rsvd_a; 240 241 wwn_t pwwn; 241 242 wwn_t nwwn; 242 243 mac_t mac; /* PBC or Mfg mac */