diff options
author | Giridhar Malavali <giridhar.malavali@qlogic.com> | 2010-05-04 18:01:34 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-05-16 18:22:11 -0400 |
commit | f1af6208c8cef81e313ec2e64b44e783c3a11c13 (patch) | |
tree | 73a61ecfb3975df4a5fde3893662ff72b1a4ef4c /drivers/scsi/qla2xxx/qla_nx.c | |
parent | f4c496c1fbaa59dbb3820c18453df661079b1d4a (diff) |
[SCSI] qla2xxx: Updates to ISP82xx support.
1) Allow transition to NEED RESET state only from READY state for ISP82xx.
2) Avoid infinite ISP aborts when chip reset fails.
3) Code cleanup to remove some of the unused debug code.
Signed-off-by: Lalit Chandivade <lalit.chandivade@qlogic.com>
Signed-off-by: Santosh Vernekar <santosh.vernekar@qlogic.com>
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_nx.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_nx.c | 205 |
1 files changed, 103 insertions, 102 deletions
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 495ff1ade36e..ff562de0e8e7 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c | |||
@@ -30,16 +30,6 @@ | |||
30 | #define QLA82XX_PCI_CAMQM_2M_BASE (0x000ff800UL) | 30 | #define QLA82XX_PCI_CAMQM_2M_BASE (0x000ff800UL) |
31 | #define CRB_INDIRECT_2M (0x1e0000UL) | 31 | #define CRB_INDIRECT_2M (0x1e0000UL) |
32 | 32 | ||
33 | static inline void *qla82xx_pci_base_offsetfset(struct qla_hw_data *ha, | ||
34 | unsigned long off) | ||
35 | { | ||
36 | if ((off < ha->first_page_group_end) && | ||
37 | (off >= ha->first_page_group_start)) | ||
38 | return (void *)(ha->nx_pcibase + off); | ||
39 | |||
40 | return NULL; | ||
41 | } | ||
42 | |||
43 | #define MAX_CRB_XFORM 60 | 33 | #define MAX_CRB_XFORM 60 |
44 | static unsigned long crb_addr_xform[MAX_CRB_XFORM]; | 34 | static unsigned long crb_addr_xform[MAX_CRB_XFORM]; |
45 | int qla82xx_crb_table_initialized; | 35 | int qla82xx_crb_table_initialized; |
@@ -335,6 +325,18 @@ unsigned qla82xx_crb_hub_agt[64] = { | |||
335 | 0, | 325 | 0, |
336 | }; | 326 | }; |
337 | 327 | ||
328 | /* Device states */ | ||
329 | char *qdev_state[] = { | ||
330 | "Unknown", | ||
331 | "Cold", | ||
332 | "Initializing", | ||
333 | "Ready", | ||
334 | "Need Reset", | ||
335 | "Need Quiescent", | ||
336 | "Failed", | ||
337 | "Quiescent", | ||
338 | }; | ||
339 | |||
338 | /* | 340 | /* |
339 | * In: 'off' is offset from CRB space in 128M pci map | 341 | * In: 'off' is offset from CRB space in 128M pci map |
340 | * Out: 'off' is 2M pci map addr | 342 | * Out: 'off' is 2M pci map addr |
@@ -661,7 +663,7 @@ static int qla82xx_pci_mem_read_direct(struct qla_hw_data *ha, | |||
661 | u64 off, void *data, int size) | 663 | u64 off, void *data, int size) |
662 | { | 664 | { |
663 | unsigned long flags; | 665 | unsigned long flags; |
664 | void *addr; | 666 | void *addr = NULL; |
665 | int ret = 0; | 667 | int ret = 0; |
666 | u64 start; | 668 | u64 start; |
667 | uint8_t *mem_ptr = NULL; | 669 | uint8_t *mem_ptr = NULL; |
@@ -684,26 +686,23 @@ static int qla82xx_pci_mem_read_direct(struct qla_hw_data *ha, | |||
684 | return -1; | 686 | return -1; |
685 | } | 687 | } |
686 | 688 | ||
687 | addr = qla82xx_pci_base_offsetfset(ha, start); | 689 | write_unlock_irqrestore(&ha->hw_lock, flags); |
688 | if (!addr) { | 690 | mem_base = pci_resource_start(ha->pdev, 0); |
689 | write_unlock_irqrestore(&ha->hw_lock, flags); | 691 | mem_page = start & PAGE_MASK; |
690 | mem_base = pci_resource_start(ha->pdev, 0); | 692 | /* Map two pages whenever user tries to access addresses in two |
691 | mem_page = start & PAGE_MASK; | 693 | * consecutive pages. |
692 | /* Map two pages whenever user tries to access addresses in two | 694 | */ |
693 | * consecutive pages. | 695 | if (mem_page != ((start + size - 1) & PAGE_MASK)) |
694 | */ | 696 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2); |
695 | if (mem_page != ((start + size - 1) & PAGE_MASK)) | 697 | else |
696 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2); | 698 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); |
697 | else | 699 | if (mem_ptr == 0UL) { |
698 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); | 700 | *(u8 *)data = 0; |
699 | if (mem_ptr == 0UL) { | 701 | return -1; |
700 | *(u8 *)data = 0; | ||
701 | return -1; | ||
702 | } | ||
703 | addr = mem_ptr; | ||
704 | addr += start & (PAGE_SIZE - 1); | ||
705 | write_lock_irqsave(&ha->hw_lock, flags); | ||
706 | } | 702 | } |
703 | addr = mem_ptr; | ||
704 | addr += start & (PAGE_SIZE - 1); | ||
705 | write_lock_irqsave(&ha->hw_lock, flags); | ||
707 | 706 | ||
708 | switch (size) { | 707 | switch (size) { |
709 | case 1: | 708 | case 1: |
@@ -734,7 +733,7 @@ qla82xx_pci_mem_write_direct(struct qla_hw_data *ha, | |||
734 | u64 off, void *data, int size) | 733 | u64 off, void *data, int size) |
735 | { | 734 | { |
736 | unsigned long flags; | 735 | unsigned long flags; |
737 | void *addr; | 736 | void *addr = NULL; |
738 | int ret = 0; | 737 | int ret = 0; |
739 | u64 start; | 738 | u64 start; |
740 | uint8_t *mem_ptr = NULL; | 739 | uint8_t *mem_ptr = NULL; |
@@ -757,25 +756,22 @@ qla82xx_pci_mem_write_direct(struct qla_hw_data *ha, | |||
757 | return -1; | 756 | return -1; |
758 | } | 757 | } |
759 | 758 | ||
760 | addr = qla82xx_pci_base_offsetfset(ha, start); | 759 | write_unlock_irqrestore(&ha->hw_lock, flags); |
761 | if (!addr) { | 760 | mem_base = pci_resource_start(ha->pdev, 0); |
762 | write_unlock_irqrestore(&ha->hw_lock, flags); | 761 | mem_page = start & PAGE_MASK; |
763 | mem_base = pci_resource_start(ha->pdev, 0); | 762 | /* Map two pages whenever user tries to access addresses in two |
764 | mem_page = start & PAGE_MASK; | 763 | * consecutive pages. |
765 | /* Map two pages whenever user tries to access addresses in two | 764 | */ |
766 | * consecutive pages. | 765 | if (mem_page != ((start + size - 1) & PAGE_MASK)) |
767 | */ | 766 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2); |
768 | if (mem_page != ((start + size - 1) & PAGE_MASK)) | 767 | else |
769 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2); | 768 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); |
770 | else | 769 | if (mem_ptr == 0UL) |
771 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); | 770 | return -1; |
772 | if (mem_ptr == 0UL) | ||
773 | return -1; | ||
774 | 771 | ||
775 | addr = mem_ptr; | 772 | addr = mem_ptr; |
776 | addr += start & (PAGE_SIZE - 1); | 773 | addr += start & (PAGE_SIZE - 1); |
777 | write_lock_irqsave(&ha->hw_lock, flags); | 774 | write_lock_irqsave(&ha->hw_lock, flags); |
778 | } | ||
779 | 775 | ||
780 | switch (size) { | 776 | switch (size) { |
781 | case 1: | 777 | case 1: |
@@ -1866,6 +1862,14 @@ void qla82xx_config_rings(struct scsi_qla_host *vha) | |||
1866 | WRT_REG_DWORD((unsigned long __iomem *)®->rsp_q_out[0], 0); | 1862 | WRT_REG_DWORD((unsigned long __iomem *)®->rsp_q_out[0], 0); |
1867 | } | 1863 | } |
1868 | 1864 | ||
1865 | void qla82xx_reset_adapter(struct scsi_qla_host *vha) | ||
1866 | { | ||
1867 | struct qla_hw_data *ha = vha->hw; | ||
1868 | vha->flags.online = 0; | ||
1869 | qla2x00_try_to_stop_firmware(vha); | ||
1870 | ha->isp_ops->disable_intrs(ha); | ||
1871 | } | ||
1872 | |||
1869 | int qla82xx_fw_load_from_blob(struct qla_hw_data *ha) | 1873 | int qla82xx_fw_load_from_blob(struct qla_hw_data *ha) |
1870 | { | 1874 | { |
1871 | u64 *ptr64; | 1875 | u64 *ptr64; |
@@ -2093,15 +2097,7 @@ qla82xx_intr_handler(int irq, void *dev_id) | |||
2093 | 2097 | ||
2094 | if (RD_REG_DWORD(®->host_int)) { | 2098 | if (RD_REG_DWORD(®->host_int)) { |
2095 | stat = RD_REG_DWORD(®->host_status); | 2099 | stat = RD_REG_DWORD(®->host_status); |
2096 | if (stat & HSRX_RISC_PAUSED) { | 2100 | if ((stat & HSRX_RISC_INT) == 0) |
2097 | if (pci_channel_offline(ha->pdev)) | ||
2098 | break; | ||
2099 | |||
2100 | qla_printk(KERN_INFO, ha, "RISC paused\n"); | ||
2101 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
2102 | qla2xxx_wake_dpc(vha); | ||
2103 | break; | ||
2104 | } else if ((stat & HSRX_RISC_INT) == 0) | ||
2105 | break; | 2101 | break; |
2106 | 2102 | ||
2107 | switch (stat & 0xff) { | 2103 | switch (stat & 0xff) { |
@@ -2177,15 +2173,7 @@ qla82xx_msix_default(int irq, void *dev_id) | |||
2177 | do { | 2173 | do { |
2178 | if (RD_REG_DWORD(®->host_int)) { | 2174 | if (RD_REG_DWORD(®->host_int)) { |
2179 | stat = RD_REG_DWORD(®->host_status); | 2175 | stat = RD_REG_DWORD(®->host_status); |
2180 | if (stat & HSRX_RISC_PAUSED) { | 2176 | if ((stat & HSRX_RISC_INT) == 0) |
2181 | if (pci_channel_offline(ha->pdev)) | ||
2182 | break; | ||
2183 | |||
2184 | qla_printk(KERN_INFO, ha, "RISC paused\n"); | ||
2185 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
2186 | qla2xxx_wake_dpc(vha); | ||
2187 | break; | ||
2188 | } else if ((stat & HSRX_RISC_INT) == 0) | ||
2189 | break; | 2177 | break; |
2190 | 2178 | ||
2191 | switch (stat & 0xff) { | 2179 | switch (stat & 0xff) { |
@@ -3348,6 +3336,9 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha) | |||
3348 | } | 3336 | } |
3349 | 3337 | ||
3350 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | 3338 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); |
3339 | qla_printk(KERN_INFO, ha, "3:Device state is 0x%x = %s\n", dev_state, | ||
3340 | dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); | ||
3341 | |||
3351 | /* Force to DEV_COLD unless someone else is starting a reset */ | 3342 | /* Force to DEV_COLD unless someone else is starting a reset */ |
3352 | if (dev_state != QLA82XX_DEV_INITIALIZING) { | 3343 | if (dev_state != QLA82XX_DEV_INITIALIZING) { |
3353 | qla_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n"); | 3344 | qla_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n"); |
@@ -3398,7 +3389,6 @@ int | |||
3398 | qla82xx_device_state_handler(scsi_qla_host_t *vha) | 3389 | qla82xx_device_state_handler(scsi_qla_host_t *vha) |
3399 | { | 3390 | { |
3400 | uint32_t dev_state; | 3391 | uint32_t dev_state; |
3401 | uint32_t drv_active; | ||
3402 | int rval = QLA_SUCCESS; | 3392 | int rval = QLA_SUCCESS; |
3403 | unsigned long dev_init_timeout; | 3393 | unsigned long dev_init_timeout; |
3404 | struct qla_hw_data *ha = vha->hw; | 3394 | struct qla_hw_data *ha = vha->hw; |
@@ -3407,38 +3397,9 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha) | |||
3407 | if (!vha->flags.init_done) | 3397 | if (!vha->flags.init_done) |
3408 | qla82xx_set_drv_active(vha); | 3398 | qla82xx_set_drv_active(vha); |
3409 | 3399 | ||
3410 | /* Set cold state*/ | 3400 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); |
3411 | if (!PCI_FUNC(ha->pdev->devfn & 1)) { | 3401 | qla_printk(KERN_INFO, ha, "1:Device state is 0x%x = %s\n", dev_state, |
3412 | 3402 | dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); | |
3413 | /* Check if other functions alive, else set dev state | ||
3414 | * to cold | ||
3415 | */ | ||
3416 | drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | ||
3417 | drv_active &= ~(1 << (ha->portnum * 4)); | ||
3418 | drv_active &= ~(1 << ((ha->portnum + 1) * 4)); | ||
3419 | |||
3420 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
3421 | if (!drv_active) { | ||
3422 | |||
3423 | switch (dev_state) { | ||
3424 | case QLA82XX_DEV_COLD: | ||
3425 | case QLA82XX_DEV_READY: | ||
3426 | case QLA82XX_DEV_INITIALIZING: | ||
3427 | case QLA82XX_DEV_NEED_RESET: | ||
3428 | case QLA82XX_DEV_NEED_QUIESCENT: | ||
3429 | case QLA82XX_DEV_QUIESCENT: | ||
3430 | case QLA82XX_DEV_FAILED: | ||
3431 | break; | ||
3432 | default: | ||
3433 | qla_printk(KERN_INFO, ha, | ||
3434 | "No other function exist," | ||
3435 | " resetting dev state to COLD\n"); | ||
3436 | qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
3437 | QLA82XX_DEV_COLD); | ||
3438 | break; | ||
3439 | } | ||
3440 | } | ||
3441 | } | ||
3442 | 3403 | ||
3443 | /* wait for 30 seconds for device to go ready */ | 3404 | /* wait for 30 seconds for device to go ready */ |
3444 | dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); | 3405 | dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); |
@@ -3453,6 +3414,11 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha) | |||
3453 | break; | 3414 | break; |
3454 | } | 3415 | } |
3455 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | 3416 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); |
3417 | qla_printk(KERN_INFO, ha, | ||
3418 | "2:Device state is 0x%x = %s\n", dev_state, | ||
3419 | dev_state < MAX_STATES ? | ||
3420 | qdev_state[dev_state] : "Unknown"); | ||
3421 | |||
3456 | switch (dev_state) { | 3422 | switch (dev_state) { |
3457 | case QLA82XX_DEV_READY: | 3423 | case QLA82XX_DEV_READY: |
3458 | goto exit; | 3424 | goto exit; |
@@ -3545,12 +3511,14 @@ qla82xx_abort_isp(scsi_qla_host_t *vha) | |||
3545 | 3511 | ||
3546 | qla82xx_idc_lock(ha); | 3512 | qla82xx_idc_lock(ha); |
3547 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | 3513 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); |
3548 | if (dev_state != QLA82XX_DEV_INITIALIZING) { | 3514 | if (dev_state == QLA82XX_DEV_READY) { |
3549 | qla_printk(KERN_INFO, ha, "HW State: NEED RESET\n"); | 3515 | qla_printk(KERN_INFO, ha, "HW State: NEED RESET\n"); |
3550 | qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | 3516 | qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, |
3551 | QLA82XX_DEV_NEED_RESET); | 3517 | QLA82XX_DEV_NEED_RESET); |
3552 | } else | 3518 | } else |
3553 | qla_printk(KERN_INFO, ha, "HW State: DEVICE INITIALIZING\n"); | 3519 | qla_printk(KERN_INFO, ha, "HW State: %s\n", |
3520 | dev_state < MAX_STATES ? | ||
3521 | qdev_state[dev_state] : "Unknown"); | ||
3554 | qla82xx_idc_unlock(ha); | 3522 | qla82xx_idc_unlock(ha); |
3555 | 3523 | ||
3556 | rval = qla82xx_device_state_handler(vha); | 3524 | rval = qla82xx_device_state_handler(vha); |
@@ -3561,6 +3529,39 @@ qla82xx_abort_isp(scsi_qla_host_t *vha) | |||
3561 | 3529 | ||
3562 | if (rval == QLA_SUCCESS) | 3530 | if (rval == QLA_SUCCESS) |
3563 | qla82xx_restart_isp(vha); | 3531 | qla82xx_restart_isp(vha); |
3532 | |||
3533 | if (rval) { | ||
3534 | vha->flags.online = 1; | ||
3535 | if (test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { | ||
3536 | if (ha->isp_abort_cnt == 0) { | ||
3537 | qla_printk(KERN_WARNING, ha, | ||
3538 | "ISP error recovery failed - " | ||
3539 | "board disabled\n"); | ||
3540 | /* | ||
3541 | * The next call disables the board | ||
3542 | * completely. | ||
3543 | */ | ||
3544 | ha->isp_ops->reset_adapter(vha); | ||
3545 | vha->flags.online = 0; | ||
3546 | clear_bit(ISP_ABORT_RETRY, | ||
3547 | &vha->dpc_flags); | ||
3548 | rval = QLA_SUCCESS; | ||
3549 | } else { /* schedule another ISP abort */ | ||
3550 | ha->isp_abort_cnt--; | ||
3551 | DEBUG(qla_printk(KERN_INFO, ha, | ||
3552 | "qla%ld: ISP abort - retry remaining %d\n", | ||
3553 | vha->host_no, ha->isp_abort_cnt)); | ||
3554 | rval = QLA_FUNCTION_FAILED; | ||
3555 | } | ||
3556 | } else { | ||
3557 | ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT; | ||
3558 | DEBUG(qla_printk(KERN_INFO, ha, | ||
3559 | "(%ld): ISP error recovery - retrying (%d) " | ||
3560 | "more times\n", vha->host_no, ha->isp_abort_cnt)); | ||
3561 | set_bit(ISP_ABORT_RETRY, &vha->dpc_flags); | ||
3562 | rval = QLA_FUNCTION_FAILED; | ||
3563 | } | ||
3564 | } | ||
3564 | return rval; | 3565 | return rval; |
3565 | } | 3566 | } |
3566 | 3567 | ||