diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_nx.c')
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_nx.c | 490 |
1 files changed, 274 insertions, 216 deletions
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index caf627ba7fa..58f3c912d96 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2011 QLogic Corporation + * Copyright (c) 2003-2014 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ @@ -36,7 +36,7 @@ #define MAX_CRB_XFORM 60 static unsigned long crb_addr_xform[MAX_CRB_XFORM]; -int qla82xx_crb_table_initialized; +static int qla82xx_crb_table_initialized; #define qla82xx_crb_addr_transform(name) \ (crb_addr_xform[QLA82XX_HW_PX_MAP_CRB_##name] = \ @@ -102,7 +102,7 @@ static void qla82xx_crb_addr_transform_setup(void) qla82xx_crb_table_initialized = 1; } -struct crb_128M_2M_block_map crb_128M_2M_map[64] = { +static struct crb_128M_2M_block_map crb_128M_2M_map[64] = { {{{0, 0, 0, 0} } }, {{{1, 0x0100000, 0x0102000, 0x120000}, {1, 0x0110000, 0x0120000, 0x130000}, @@ -262,7 +262,7 @@ struct crb_128M_2M_block_map crb_128M_2M_map[64] = { /* * top 12 bits of crb internal address (hub, agent) */ -unsigned qla82xx_crb_hub_agt[64] = { +static unsigned qla82xx_crb_hub_agt[64] = { 0, QLA82XX_HW_CRB_HUB_AGT_ADR_PS, QLA82XX_HW_CRB_HUB_AGT_ADR_MN, @@ -330,7 +330,7 @@ unsigned qla82xx_crb_hub_agt[64] = { }; /* Device states */ -char *q_dev_state[] = { +static char *q_dev_state[] = { "Unknown", "Cold", "Initializing", @@ -359,12 +359,13 @@ qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong *off) ha->crb_win = CRB_HI(*off); writel(ha->crb_win, - (void *)(CRB_WINDOW_2M + ha->nx_pcibase)); + (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); /* Read back value to make sure write has gone through before trying * to use it. */ - win_read = RD_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase)); + win_read = RD_REG_DWORD((void __iomem *) + (CRB_WINDOW_2M + ha->nx_pcibase)); if (win_read != ha->crb_win) { ql_dbg(ql_dbg_p3p, vha, 0xb000, "%s: Written crbwin (0x%x) " @@ -567,7 +568,7 @@ qla82xx_pci_mem_bound_check(struct qla_hw_data *ha, return 1; } -int qla82xx_pci_set_window_warning_count; +static int qla82xx_pci_set_window_warning_count; static unsigned long qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr) @@ -677,10 +678,10 @@ static int qla82xx_pci_mem_read_direct(struct qla_hw_data *ha, u64 off, void *data, int size) { unsigned long flags; - void *addr = NULL; + void __iomem *addr = NULL; int ret = 0; u64 start; - uint8_t *mem_ptr = NULL; + uint8_t __iomem *mem_ptr = NULL; unsigned long mem_base; unsigned long mem_page; scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); @@ -712,7 +713,7 @@ static int qla82xx_pci_mem_read_direct(struct qla_hw_data *ha, mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2); else mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); - if (mem_ptr == 0UL) { + if (mem_ptr == NULL) { *(u8 *)data = 0; return -1; } @@ -749,10 +750,10 @@ qla82xx_pci_mem_write_direct(struct qla_hw_data *ha, u64 off, void *data, int size) { unsigned long flags; - void *addr = NULL; + void __iomem *addr = NULL; int ret = 0; u64 start; - uint8_t *mem_ptr = NULL; + uint8_t __iomem *mem_ptr = NULL; unsigned long mem_base; unsigned long mem_page; scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); @@ -784,7 +785,7 @@ qla82xx_pci_mem_write_direct(struct qla_hw_data *ha, mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2); else mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); - if (mem_ptr == 0UL) + if (mem_ptr == NULL) return -1; addr = mem_ptr; @@ -846,23 +847,31 @@ static int qla82xx_rom_lock(struct qla_hw_data *ha) { int done = 0, timeout = 0; + uint32_t lock_owner = 0; + scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); while (!done) { /* acquire semaphore2 from PCI HW block */ done = qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_LOCK)); if (done == 1) break; - if (timeout >= qla82xx_rom_lock_timeout) + if (timeout >= qla82xx_rom_lock_timeout) { + lock_owner = qla82xx_rd_32(ha, QLA82XX_ROM_LOCK_ID); + ql_log(ql_log_warn, vha, 0xb157, + "%s: Simultaneous flash access by following ports, active port = %d: accessing port = %d", + __func__, ha->portnum, lock_owner); return -1; + } timeout++; } - qla82xx_wr_32(ha, QLA82XX_ROM_LOCK_ID, ROM_LOCK_DRIVER); + qla82xx_wr_32(ha, QLA82XX_ROM_LOCK_ID, ha->portnum); return 0; } static void qla82xx_rom_unlock(struct qla_hw_data *ha) { + qla82xx_wr_32(ha, QLA82XX_ROM_LOCK_ID, 0xffffffff); qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK)); } @@ -908,24 +917,24 @@ qla82xx_wait_rom_done(struct qla_hw_data *ha) return 0; } -int +static int qla82xx_md_rw_32(struct qla_hw_data *ha, uint32_t off, u32 data, uint8_t flag) { uint32_t off_value, rval = 0; - WRT_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase), + WRT_REG_DWORD((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase), (off & 0xFFFF0000)); /* Read back value to make sure write has gone through */ - RD_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase)); + RD_REG_DWORD((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); off_value = (off & 0x0000FFFF); if (flag) - WRT_REG_DWORD((void *) + WRT_REG_DWORD((void __iomem *) (off_value + CRB_INDIRECT_2M + ha->nx_pcibase), data); else - rval = RD_REG_DWORD((void *) + rval = RD_REG_DWORD((void __iomem *) (off_value + CRB_INDIRECT_2M + ha->nx_pcibase)); return rval; @@ -946,6 +955,7 @@ static int qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp) { int ret, loops = 0; + uint32_t lock_owner = 0; scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); while ((qla82xx_rom_lock(ha) != 0) && (loops < 50000)) { @@ -954,8 +964,10 @@ qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp) loops++; } if (loops >= 50000) { + lock_owner = qla82xx_rd_32(ha, QLA82XX_ROM_LOCK_ID); ql_log(ql_log_fatal, vha, 0x00b9, - "Failed to aquire SEM2 lock.\n"); + "Failed to acquire SEM2 lock, Lock Owner %u.\n", + lock_owner); return -1; } ret = qla82xx_do_rom_fast_read(ha, addr, valp); @@ -1053,6 +1065,7 @@ static int ql82xx_rom_lock_d(struct qla_hw_data *ha) { int loops = 0; + uint32_t lock_owner = 0; scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); while ((qla82xx_rom_lock(ha) != 0) && (loops < 50000)) { @@ -1061,8 +1074,9 @@ ql82xx_rom_lock_d(struct qla_hw_data *ha) loops++; } if (loops >= 50000) { + lock_owner = qla82xx_rd_32(ha, QLA82XX_ROM_LOCK_ID); ql_log(ql_log_warn, vha, 0xb010, - "ROM lock failed.\n"); + "ROM lock failed, Lock Owner %u.\n", lock_owner); return -1; } return 0; @@ -1122,7 +1136,7 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha) long data; }; - /* Halt all the indiviual PEGs and other blocks of the ISP */ + /* Halt all the individual PEGs and other blocks of the ISP */ qla82xx_rom_lock(ha); /* disable all I2Q */ @@ -1612,25 +1626,6 @@ qla82xx_get_fw_offs(struct qla_hw_data *ha) } /* PCI related functions */ -char * -qla82xx_pci_info_str(struct scsi_qla_host *vha, char *str) -{ - int pcie_reg; - struct qla_hw_data *ha = vha->hw; - char lwstr[6]; - uint16_t lnk; - - pcie_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP); - pci_read_config_word(ha->pdev, pcie_reg + PCI_EXP_LNKSTA, &lnk); - ha->link_width = (lnk >> 4) & 0x3f; - - strcpy(str, "PCIe ("); - strcat(str, "2.5Gb/s "); - snprintf(lwstr, sizeof(lwstr), "x%d)", ha->link_width); - strcat(str, lwstr); - return str; -} - int qla82xx_pci_region_offset(struct pci_dev *pdev, int region) { unsigned long val = 0; @@ -1673,13 +1668,18 @@ qla82xx_iospace_config(struct qla_hw_data *ha) if (!ha->nx_pcibase) { ql_log_pci(ql_log_fatal, ha->pdev, 0x000e, "Cannot remap pcibase MMIO, aborting.\n"); - pci_release_regions(ha->pdev); goto iospace_error_exit; } /* Mapping of IO base pointer */ - ha->iobase = (device_reg_t __iomem *)((uint8_t *)ha->nx_pcibase + - 0xbc000 + (ha->pdev->devfn << 11)); + if (IS_QLA8044(ha)) { + ha->iobase = + (device_reg_t *)((uint8_t *)ha->nx_pcibase); + } else if (IS_QLA82XX(ha)) { + ha->iobase = + (device_reg_t *)((uint8_t *)ha->nx_pcibase + + 0xbc000 + (ha->pdev->devfn << 11)); + } if (!ql2xdbwr) { ha->nxdb_wr_ptr = @@ -1688,7 +1688,6 @@ qla82xx_iospace_config(struct qla_hw_data *ha) if (!ha->nxdb_wr_ptr) { ql_log_pci(ql_log_fatal, ha->pdev, 0x000f, "Cannot remap MMIO, aborting.\n"); - pci_release_regions(ha->pdev); goto iospace_error_exit; } @@ -1783,14 +1782,6 @@ void qla82xx_config_rings(struct scsi_qla_host *vha) WRT_REG_DWORD((unsigned long __iomem *)®->rsp_q_out[0], 0); } -void qla82xx_reset_adapter(struct scsi_qla_host *vha) -{ - struct qla_hw_data *ha = vha->hw; - vha->flags.online = 0; - qla2x00_try_to_stop_firmware(vha); - ha->isp_ops->disable_intrs(ha); -} - static int qla82xx_fw_load_from_blob(struct qla_hw_data *ha) { @@ -1875,7 +1866,7 @@ qla82xx_set_product_offset(struct qla_hw_data *ha) return -1; } -int +static int qla82xx_validate_firmware_blob(scsi_qla_host_t *vha, uint8_t fw_type) { __le32 val; @@ -1980,20 +1971,6 @@ qla82xx_check_rcvpeg_state(struct qla_hw_data *ha) } /* ISR related functions */ -uint32_t qla82xx_isr_int_target_mask_enable[8] = { - ISR_INT_TARGET_MASK, ISR_INT_TARGET_MASK_F1, - ISR_INT_TARGET_MASK_F2, ISR_INT_TARGET_MASK_F3, - ISR_INT_TARGET_MASK_F4, ISR_INT_TARGET_MASK_F5, - ISR_INT_TARGET_MASK_F7, ISR_INT_TARGET_MASK_F7 -}; - -uint32_t qla82xx_isr_int_target_status[8] = { - ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1, - ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3, - ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5, - ISR_INT_TARGET_STATUS_F7, ISR_INT_TARGET_STATUS_F7 -}; - static struct qla82xx_legacy_intr_set legacy_intr[] = \ QLA82XX_LEGACY_INTR_CONFIG; @@ -2002,7 +1979,7 @@ static struct qla82xx_legacy_intr_set legacy_intr[] = \ * @ha: SCSI driver HA context * @mb0: Mailbox0 register */ -static void +void qla82xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) { uint16_t cnt; @@ -2109,22 +2086,13 @@ qla82xx_intr_handler(int irq, void *dev_id) } WRT_REG_DWORD(®->host_int, 0); } + + qla2x00_handle_mbx_completion(ha, status); spin_unlock_irqrestore(&ha->hardware_lock, flags); + if (!ha->flags.msi_enabled) qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); -#ifdef QL_DEBUG_LEVEL_17 - if (!irq && ha->flags.eeh_busy) - ql_log(ql_log_warn, vha, 0x503d, - "isr:status %x, cmd_flags %lx, mbox_int %x, stat %x.\n", - status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat); -#endif - - if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && - (status & MBX_INTERRUPT) && ha->flags.mbox_int) { - set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); - complete(&ha->mbx_intr_comp); - } return IRQ_HANDLED; } @@ -2138,6 +2106,7 @@ qla82xx_msix_default(int irq, void *dev_id) int status = 0; unsigned long flags; uint32_t stat = 0; + uint32_t host_int = 0; uint16_t mb[4]; rsp = (struct rsp_que *) dev_id; @@ -2153,7 +2122,10 @@ qla82xx_msix_default(int irq, void *dev_id) spin_lock_irqsave(&ha->hardware_lock, flags); vha = pci_get_drvdata(ha->pdev); do { - if (RD_REG_DWORD(®->host_int)) { + host_int = RD_REG_DWORD(®->host_int); + if (qla2x00_check_reg_for_disconnect(vha, host_int)) + break; + if (host_int) { stat = RD_REG_DWORD(®->host_status); switch (stat & 0xff) { @@ -2184,20 +2156,9 @@ qla82xx_msix_default(int irq, void *dev_id) WRT_REG_DWORD(®->host_int, 0); } while (0); + qla2x00_handle_mbx_completion(ha, status); spin_unlock_irqrestore(&ha->hardware_lock, flags); -#ifdef QL_DEBUG_LEVEL_17 - if (!irq && ha->flags.eeh_busy) - ql_log(ql_log_warn, vha, 0x5044, - "isr:status %x, cmd_flags %lx, mbox_int %x, stat %x.\n", - status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat); -#endif - - if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && - (status & MBX_INTERRUPT) && ha->flags.mbox_int) { - set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); - complete(&ha->mbx_intr_comp); - } return IRQ_HANDLED; } @@ -2209,6 +2170,7 @@ qla82xx_msix_rsp_q(int irq, void *dev_id) struct rsp_que *rsp; struct device_reg_82xx __iomem *reg; unsigned long flags; + uint32_t host_int = 0; rsp = (struct rsp_que *) dev_id; if (!rsp) { @@ -2221,8 +2183,12 @@ qla82xx_msix_rsp_q(int irq, void *dev_id) reg = &ha->iobase->isp82; spin_lock_irqsave(&ha->hardware_lock, flags); vha = pci_get_drvdata(ha->pdev); + host_int = RD_REG_DWORD(®->host_int); + if (qla2x00_check_reg_for_disconnect(vha, host_int)) + goto out; qla24xx_process_response_queue(vha, rsp); WRT_REG_DWORD(®->host_int, 0); +out: spin_unlock_irqrestore(&ha->hardware_lock, flags); return IRQ_HANDLED; } @@ -2236,6 +2202,7 @@ qla82xx_poll(int irq, void *dev_id) struct device_reg_82xx __iomem *reg; int status = 0; uint32_t stat; + uint32_t host_int = 0; uint16_t mb[4]; unsigned long flags; @@ -2251,7 +2218,10 @@ qla82xx_poll(int irq, void *dev_id) spin_lock_irqsave(&ha->hardware_lock, flags); vha = pci_get_drvdata(ha->pdev); - if (RD_REG_DWORD(®->host_int)) { + host_int = RD_REG_DWORD(®->host_int); + if (qla2x00_check_reg_for_disconnect(vha, host_int)) + goto out; + if (host_int) { stat = RD_REG_DWORD(®->host_status); switch (stat & 0xff) { case 0x1: @@ -2277,8 +2247,9 @@ qla82xx_poll(int irq, void *dev_id) stat * 0xff); break; } + WRT_REG_DWORD(®->host_int, 0); } - WRT_REG_DWORD(®->host_int, 0); +out: spin_unlock_irqrestore(&ha->hardware_lock, flags); } @@ -2288,7 +2259,10 @@ qla82xx_enable_intrs(struct qla_hw_data *ha) scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); qla82xx_mbx_intr_enable(vha); spin_lock_irq(&ha->hardware_lock); - qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); + if (IS_QLA8044(ha)) + qla8044_wr_reg(ha, LEG_INTR_MASK_OFFSET, 0); + else + qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); spin_unlock_irq(&ha->hardware_lock); ha->interrupts_on = 1; } @@ -2299,7 +2273,10 @@ qla82xx_disable_intrs(struct qla_hw_data *ha) scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); qla82xx_mbx_intr_disable(vha); spin_lock_irq(&ha->hardware_lock); - qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400); + if (IS_QLA8044(ha)) + qla8044_wr_reg(ha, LEG_INTR_MASK_OFFSET, 1); + else + qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400); spin_unlock_irq(&ha->hardware_lock); ha->interrupts_on = 0; } @@ -2322,6 +2299,29 @@ void qla82xx_init_flags(struct qla_hw_data *ha) } inline void +qla82xx_set_idc_version(scsi_qla_host_t *vha) +{ + int idc_ver; + uint32_t drv_active; + struct qla_hw_data *ha = vha->hw; + + drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); + if (drv_active == (QLA82XX_DRV_ACTIVE << (ha->portnum * 4))) { + qla82xx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, + QLA82XX_IDC_VERSION); + ql_log(ql_log_info, vha, 0xb082, + "IDC version updated to %d\n", QLA82XX_IDC_VERSION); + } else { + idc_ver = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_IDC_VERSION); + if (idc_ver != QLA82XX_IDC_VERSION) + ql_log(ql_log_info, vha, 0xb083, + "qla2xxx driver IDC version %d is not compatible " + "with IDC version %d of the other drivers\n", + QLA82XX_IDC_VERSION, idc_ver); + } +} + +inline void qla82xx_set_drv_active(scsi_qla_host_t *vha) { uint32_t drv_active; @@ -2355,7 +2355,7 @@ qla82xx_need_reset(struct qla_hw_data *ha) uint32_t drv_state; int rval; - if (ha->flags.isp82xx_reset_owner) + if (ha->flags.nic_core_reset_owner) return 1; else { drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); @@ -2497,7 +2497,6 @@ fw_load_failed: int qla82xx_start_firmware(scsi_qla_host_t *vha) { - int pcie_cap; uint16_t lnk; struct qla_hw_data *ha = vha->hw; @@ -2528,8 +2527,7 @@ qla82xx_start_firmware(scsi_qla_host_t *vha) } /* Negotiated Link width */ - pcie_cap = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP); - pci_read_config_word(ha->pdev, pcie_cap + PCI_EXP_LNKSTA, &lnk); + pcie_capability_read_word(ha->pdev, PCI_EXP_LNKSTA, &lnk); ha->link_width = (lnk >> 4) & 0x3f; /* Synchronize with Receive peg */ @@ -2811,7 +2809,7 @@ qla82xx_start_iocbs(scsi_qla_host_t *vha) else { WRT_REG_DWORD((unsigned long __iomem *)ha->nxdb_wr_ptr, dbval); wmb(); - while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) { + while (RD_REG_DWORD((void __iomem *)ha->nxdb_rd_ptr) != dbval) { WRT_REG_DWORD((unsigned long __iomem *)ha->nxdb_wr_ptr, dbval); wmb(); @@ -2819,15 +2817,18 @@ qla82xx_start_iocbs(scsi_qla_host_t *vha) } } -void qla82xx_rom_lock_recovery(struct qla_hw_data *ha) +static void +qla82xx_rom_lock_recovery(struct qla_hw_data *ha) { scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); + uint32_t lock_owner = 0; - if (qla82xx_rom_lock(ha)) + if (qla82xx_rom_lock(ha)) { + lock_owner = qla82xx_rd_32(ha, QLA82XX_ROM_LOCK_ID); /* Someone else is holding the lock. */ ql_log(ql_log_info, vha, 0xb022, - "Resetting rom_lock.\n"); - + "Resetting rom_lock, Lock Owner %u.\n", lock_owner); + } /* * Either we got the lock, or someone * else died while holding it. @@ -2851,54 +2852,34 @@ static int qla82xx_device_bootstrap(scsi_qla_host_t *vha) { int rval = QLA_SUCCESS; - int i, timeout; + int i; uint32_t old_count, count; struct qla_hw_data *ha = vha->hw; - int need_reset = 0, peg_stuck = 1; + int need_reset = 0; need_reset = qla82xx_need_reset(ha); - old_count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); - - for (i = 0; i < 10; i++) { - timeout = msleep_interruptible(200); - if (timeout) { - qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, - QLA82XX_DEV_FAILED); - return QLA_FUNCTION_FAILED; - } - - count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); - if (count != old_count) - peg_stuck = 0; - } - if (need_reset) { /* We are trying to perform a recovery here. */ - if (peg_stuck) + if (ha->flags.isp82xx_fw_hung) qla82xx_rom_lock_recovery(ha); - goto dev_initialize; } else { - /* Start of day for this ha context. */ - if (peg_stuck) { - /* Either we are the first or recovery in progress. */ - qla82xx_rom_lock_recovery(ha); - goto dev_initialize; - } else - /* Firmware already running. */ - goto dev_ready; + old_count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); + for (i = 0; i < 10; i++) { + msleep(200); + count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); + if (count != old_count) { + rval = QLA_SUCCESS; + goto dev_ready; + } + } + qla82xx_rom_lock_recovery(ha); } - return rval; - -dev_initialize: /* set to DEV_INITIALIZING */ ql_log(ql_log_info, vha, 0x009e, "HW State: INITIALIZING.\n"); - qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_INITIALIZING); - - /* Driver that sets device state to initializating sets IDC version */ - qla82xx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, QLA82XX_IDC_VERSION); + qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA8XXX_DEV_INITIALIZING); qla82xx_idc_unlock(ha); rval = qla82xx_start_firmware(vha); @@ -2908,14 +2889,14 @@ dev_initialize: ql_log(ql_log_fatal, vha, 0x00ad, "HW State: FAILED.\n"); qla82xx_clear_drv_active(ha); - qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_FAILED); + qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA8XXX_DEV_FAILED); return rval; } dev_ready: ql_log(ql_log_info, vha, 0x00ae, "HW State: READY.\n"); - qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_READY); + qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA8XXX_DEV_READY); return QLA_SUCCESS; } @@ -2939,7 +2920,7 @@ qla82xx_need_qsnt_handler(scsi_qla_host_t *vha) if (vha->flags.online) { /*Block any further I/O and wait for pending cmnds to complete*/ - qla82xx_quiescent_state_cleanup(vha); + qla2x00_quiesce_io(vha); } /* Set the quiescence ready bit */ @@ -2964,7 +2945,7 @@ qla82xx_need_qsnt_handler(scsi_qla_host_t *vha) "DRV_STATE:%d.\n", QLA2XXX_DRIVER_NAME, drv_active, drv_state); qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, - QLA82XX_DEV_READY); + QLA8XXX_DEV_READY); ql_log(ql_log_info, vha, 0xb025, "HW State: DEV_READY.\n"); qla82xx_idc_unlock(ha); @@ -2985,10 +2966,10 @@ qla82xx_need_qsnt_handler(scsi_qla_host_t *vha) } dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); /* everyone acked so set the state to DEV_QUIESCENCE */ - if (dev_state == QLA82XX_DEV_NEED_QUIESCENT) { + if (dev_state == QLA8XXX_DEV_NEED_QUIESCENT) { ql_log(ql_log_info, vha, 0xb026, "HW State: DEV_QUIESCENT.\n"); - qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_QUIESCENT); + qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA8XXX_DEV_QUIESCENT); } } @@ -3018,8 +2999,8 @@ qla82xx_wait_for_state_change(scsi_qla_host_t *vha, uint32_t curr_state) return dev_state; } -static void -qla82xx_dev_failed_handler(scsi_qla_host_t *vha) +void +qla8xxx_dev_failed_handler(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; @@ -3027,9 +3008,13 @@ qla82xx_dev_failed_handler(scsi_qla_host_t *vha) ql_log(ql_log_fatal, vha, 0x00b8, "Disabling the board.\n"); - qla82xx_idc_lock(ha); - qla82xx_clear_drv_active(ha); - qla82xx_idc_unlock(ha); + if (IS_QLA82XX(ha)) { + qla82xx_clear_drv_active(ha); + qla82xx_idc_unlock(ha); + } else if (IS_QLA8044(ha)) { + qla8044_clear_drv_active(ha); + qla8044_idc_unlock(ha); + } /* Set DEV_FAILED flag to disable timer */ vha->device_flags |= DFLG_DEV_FAILED; @@ -3068,7 +3053,7 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha) } drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); - if (!ha->flags.isp82xx_reset_owner) { + if (!ha->flags.nic_core_reset_owner) { ql_dbg(ql_dbg_p3p, vha, 0xb028, "reset_acknowledged by 0x%x\n", ha->portnum); qla82xx_set_rst_ready(ha); @@ -3080,7 +3065,7 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha) } /* wait for 10 seconds for reset ack from all functions */ - reset_timeout = jiffies + (ha->nx_reset_timeout * HZ); + reset_timeout = jiffies + (ha->fcoe_reset_timeout * HZ); drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); @@ -3092,7 +3077,7 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha) drv_state, drv_active, dev_state, active_mask); while (drv_state != drv_active && - dev_state != QLA82XX_DEV_INITIALIZING) { + dev_state != QLA8XXX_DEV_INITIALIZING) { if (time_after_eq(jiffies, reset_timeout)) { ql_log(ql_log_warn, vha, 0x00b5, "Reset timeout.\n"); @@ -3103,7 +3088,7 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha) qla82xx_idc_lock(ha); drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); - if (ha->flags.isp82xx_reset_owner) + if (ha->flags.nic_core_reset_owner) drv_active &= active_mask; dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); } @@ -3119,11 +3104,11 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha) dev_state < MAX_STATES ? qdev_state(dev_state) : "Unknown"); /* Force to DEV_COLD unless someone else is starting a reset */ - if (dev_state != QLA82XX_DEV_INITIALIZING && - dev_state != QLA82XX_DEV_COLD) { + if (dev_state != QLA8XXX_DEV_INITIALIZING && + dev_state != QLA8XXX_DEV_COLD) { ql_log(ql_log_info, vha, 0x00b7, "HW State: COLD/RE-INIT.\n"); - qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD); + qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA8XXX_DEV_COLD); qla82xx_set_rst_ready(ha); if (ql2xmdenable) { if (qla82xx_md_collect(vha)) @@ -3152,18 +3137,18 @@ qla82xx_check_md_needed(scsi_qla_host_t *vha) if (ql2xmdenable) { if (!ha->fw_dumped) { - if (fw_major_version != ha->fw_major_version || + if ((fw_major_version != ha->fw_major_version || fw_minor_version != ha->fw_minor_version || - fw_subminor_version != ha->fw_subminor_version) { - ql_log(ql_log_info, vha, 0xb02d, - "Firmware version differs " - "Previous version: %d:%d:%d - " - "New version: %d:%d:%d\n", + fw_subminor_version != ha->fw_subminor_version) || + (ha->prev_minidump_failed)) { + ql_dbg(ql_dbg_p3p, vha, 0xb02d, + "Firmware version differs Previous version: %d:%d:%d - New version: %d:%d:%d, prev_minidump_failed: %d.\n", fw_major_version, fw_minor_version, fw_subminor_version, ha->fw_major_version, ha->fw_minor_version, - ha->fw_subminor_version); + ha->fw_subminor_version, + ha->prev_minidump_failed); /* Release MiniDump resources */ qla82xx_md_free(vha); /* ALlocate MiniDump resources */ @@ -3177,7 +3162,7 @@ qla82xx_check_md_needed(scsi_qla_host_t *vha) } -int +static int qla82xx_check_fw_alive(scsi_qla_host_t *vha) { uint32_t fw_heartbeat_counter; @@ -3230,8 +3215,10 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha) int loopcount = 0; qla82xx_idc_lock(ha); - if (!vha->flags.init_done) + if (!vha->flags.init_done) { qla82xx_set_drv_active(vha); + qla82xx_set_idc_version(vha); + } dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); old_dev_state = dev_state; @@ -3241,7 +3228,7 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha) dev_state < MAX_STATES ? qdev_state(dev_state) : "Unknown"); /* wait for 30 seconds for device to go ready */ - dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); + dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout * HZ); while (1) { @@ -3265,18 +3252,18 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha) } switch (dev_state) { - case QLA82XX_DEV_READY: - ha->flags.isp82xx_reset_owner = 0; - goto exit; - case QLA82XX_DEV_COLD: + case QLA8XXX_DEV_READY: + ha->flags.nic_core_reset_owner = 0; + goto rel_lock; + case QLA8XXX_DEV_COLD: rval = qla82xx_device_bootstrap(vha); break; - case QLA82XX_DEV_INITIALIZING: + case QLA8XXX_DEV_INITIALIZING: qla82xx_idc_unlock(ha); msleep(1000); qla82xx_idc_lock(ha); break; - case QLA82XX_DEV_NEED_RESET: + case QLA8XXX_DEV_NEED_RESET: if (!ql2xdontresethba) qla82xx_need_reset_handler(vha); else { @@ -3285,31 +3272,31 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha) qla82xx_idc_lock(ha); } dev_init_timeout = jiffies + - (ha->nx_dev_init_timeout * HZ); + (ha->fcoe_dev_init_timeout * HZ); break; - case QLA82XX_DEV_NEED_QUIESCENT: + case QLA8XXX_DEV_NEED_QUIESCENT: qla82xx_need_qsnt_handler(vha); /* Reset timeout value after quiescence handler */ - dev_init_timeout = jiffies + (ha->nx_dev_init_timeout\ + dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout\ * HZ); break; - case QLA82XX_DEV_QUIESCENT: + case QLA8XXX_DEV_QUIESCENT: /* Owner will exit and other will wait for the state * to get changed */ if (ha->flags.quiesce_owner) - goto exit; + goto rel_lock; qla82xx_idc_unlock(ha); msleep(1000); qla82xx_idc_lock(ha); /* Reset timeout value after quiescence handler */ - dev_init_timeout = jiffies + (ha->nx_dev_init_timeout\ + dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout\ * HZ); break; - case QLA82XX_DEV_FAILED: - qla82xx_dev_failed_handler(vha); + case QLA8XXX_DEV_FAILED: + qla8xxx_dev_failed_handler(vha); rval = QLA_FUNCTION_FAILED; goto exit; default: @@ -3319,8 +3306,9 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha) } loopcount++; } -exit: +rel_lock: qla82xx_idc_unlock(ha); +exit: return rval; } @@ -3348,6 +3336,14 @@ static int qla82xx_check_temp(scsi_qla_host_t *vha) return 0; } +int qla82xx_read_temperature(scsi_qla_host_t *vha) +{ + uint32_t temp; + + temp = qla82xx_rd_32(vha->hw, CRB_TEMP_STATE); + return qla82xx_get_temp_val(temp); +} + void qla82xx_clear_pending_mbx(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; @@ -3357,7 +3353,7 @@ void qla82xx_clear_pending_mbx(scsi_qla_host_t *vha) ha->flags.mbox_busy = 0; ql_log(ql_log_warn, vha, 0x6010, "Doing premature completion of mbx command.\n"); - if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) + if (test_and_clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) complete(&ha->mbx_intr_comp); } } @@ -3368,22 +3364,30 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) struct qla_hw_data *ha = vha->hw; /* don't poll if reset is going on */ - if (!ha->flags.isp82xx_reset_hdlr_active) { + if (!ha->flags.nic_core_reset_hdlr_active) { dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); if (qla82xx_check_temp(vha)) { set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags); ha->flags.isp82xx_fw_hung = 1; qla82xx_clear_pending_mbx(vha); - } else if (dev_state == QLA82XX_DEV_NEED_RESET && + } else if (dev_state == QLA8XXX_DEV_NEED_RESET && !test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) { ql_log(ql_log_warn, vha, 0x6001, "Adapter reset needed.\n"); set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); - } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && + } else if (dev_state == QLA8XXX_DEV_NEED_QUIESCENT && !test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) { ql_log(ql_log_warn, vha, 0x6002, "Quiescent needed.\n"); set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags); + } else if (dev_state == QLA8XXX_DEV_FAILED && + !test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) && + vha->flags.online == 1) { + ql_log(ql_log_warn, vha, 0xb055, + "Adapter state is failed. Offlining.\n"); + set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags); + ha->flags.isp82xx_fw_hung = 1; + qla82xx_clear_pending_mbx(vha); } else { if (qla82xx_check_fw_alive(vha)) { ql_dbg(ql_dbg_timer, vha, 0x6011, @@ -3433,8 +3437,18 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) int qla82xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) { - int rval; - rval = qla82xx_device_state_handler(vha); + int rval = -1; + struct qla_hw_data *ha = vha->hw; + + if (IS_QLA82XX(ha)) + rval = qla82xx_device_state_handler(vha); + else if (IS_QLA8044(ha)) { + qla8044_idc_lock(ha); + /* Decide the reset ownership */ + qla83xx_reset_ownership(vha); + qla8044_idc_unlock(ha); + rval = qla8044_device_state_handler(vha); + } return rval; } @@ -3442,17 +3456,25 @@ void qla82xx_set_reset_owner(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; - uint32_t dev_state; + uint32_t dev_state = 0; - dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); - if (dev_state == QLA82XX_DEV_READY) { + if (IS_QLA82XX(ha)) + dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); + else if (IS_QLA8044(ha)) + dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX); + + if (dev_state == QLA8XXX_DEV_READY) { ql_log(ql_log_info, vha, 0xb02f, "HW State: NEED RESET\n"); - qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, - QLA82XX_DEV_NEED_RESET); - ha->flags.isp82xx_reset_owner = 1; - ql_dbg(ql_dbg_p3p, vha, 0xb030, - "reset_owner is 0x%x\n", ha->portnum); + if (IS_QLA82XX(ha)) { + qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, + QLA8XXX_DEV_NEED_RESET); + ha->flags.nic_core_reset_owner = 1; + ql_dbg(ql_dbg_p3p, vha, 0xb030, + "reset_owner is 0x%x\n", ha->portnum); + } else if (IS_QLA8044(ha)) + qla8044_wr_direct(vha, QLA8044_CRB_DEV_STATE_INDEX, + QLA8XXX_DEV_NEED_RESET); } else ql_log(ql_log_info, vha, 0xb031, "Device state is 0x%x = %s.\n", @@ -3473,7 +3495,7 @@ qla82xx_set_reset_owner(scsi_qla_host_t *vha) int qla82xx_abort_isp(scsi_qla_host_t *vha) { - int rval; + int rval = -1; struct qla_hw_data *ha = vha->hw; if (vha->device_flags & DFLG_DEV_FAILED) { @@ -3481,13 +3503,21 @@ qla82xx_abort_isp(scsi_qla_host_t *vha) "Device in failed state, exiting.\n"); return QLA_SUCCESS; } - ha->flags.isp82xx_reset_hdlr_active = 1; + ha->flags.nic_core_reset_hdlr_active = 1; qla82xx_idc_lock(ha); qla82xx_set_reset_owner(vha); qla82xx_idc_unlock(ha); - rval = qla82xx_device_state_handler(vha); + if (IS_QLA82XX(ha)) + rval = qla82xx_device_state_handler(vha); + else if (IS_QLA8044(ha)) { + qla8044_idc_lock(ha); + /* Decide the reset ownership */ + qla83xx_reset_ownership(vha); + qla8044_idc_unlock(ha); + rval = qla8044_device_state_handler(vha); + } qla82xx_idc_lock(ha); qla82xx_clear_rst_ready(ha); @@ -3495,7 +3525,7 @@ qla82xx_abort_isp(scsi_qla_host_t *vha) if (rval == QLA_SUCCESS) { ha->flags.isp82xx_fw_hung = 0; - ha->flags.isp82xx_reset_hdlr_active = 0; + ha->flags.nic_core_reset_hdlr_active = 0; qla82xx_restart_isp(vha); } @@ -3607,7 +3637,7 @@ int qla2x00_wait_for_fcoe_ctx_reset(scsi_qla_host_t *vha) void qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha) { - int i; + int i, fw_state = 0; unsigned long flags; struct qla_hw_data *ha = vha->hw; @@ -3618,7 +3648,11 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha) if (!ha->flags.isp82xx_fw_hung) { for (i = 0; i < 2; i++) { msleep(1000); - if (qla82xx_check_fw_alive(vha)) { + if (IS_QLA82XX(ha)) + fw_state = qla82xx_check_fw_alive(vha); + else if (IS_QLA8044(ha)) + fw_state = qla8044_check_fw_alive(vha); + if (fw_state) { ha->flags.isp82xx_fw_hung = 1; qla82xx_clear_pending_mbx(vha); break; @@ -3640,11 +3674,13 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha) req = ha->req_q_map[que]; if (!req) continue; - for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { + for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) { sp = req->outstanding_cmds[cnt]; if (sp) { - if (!sp->u.scmd.ctx || - (sp->flags & SRB_FCP_CMND_DMA_VALID)) { + if ((!sp->u.scmd.ctx || + (sp->flags & + SRB_FCP_CMND_DMA_VALID)) && + !ha->flags.isp82xx_fw_hung) { spin_unlock_irqrestore( &ha->hardware_lock, flags); if (ha->isp_ops->abort_command(sp)) { @@ -3806,7 +3842,8 @@ qla82xx_minidump_process_rdocm(scsi_qla_host_t *vha, loop_cnt = ocm_hdr->op_count; for (i = 0; i < loop_cnt; i++) { - r_value = RD_REG_DWORD((void *)(r_addr + ha->nx_pcibase)); + r_value = RD_REG_DWORD((void __iomem *) + (r_addr + ha->nx_pcibase)); *data_ptr++ = cpu_to_le32(r_value); r_addr += r_stride; } @@ -4030,7 +4067,7 @@ qla82xx_minidump_process_rdmem(scsi_qla_host_t *vha, if (r_addr & 0xf) { ql_log(ql_log_warn, vha, 0xb033, - "Read addr 0x%x not 16 bytes alligned\n", r_addr); + "Read addr 0x%x not 16 bytes aligned\n", r_addr); return rval; } @@ -4081,7 +4118,7 @@ qla82xx_minidump_process_rdmem(scsi_qla_host_t *vha, return QLA_SUCCESS; } -static int +int qla82xx_validate_template_chksum(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; @@ -4365,7 +4402,7 @@ qla82xx_md_free(scsi_qla_host_t *vha) ha->md_tmplt_hdr, ha->md_template_size / 1024); dma_free_coherent(&ha->pdev->dev, ha->md_template_size, ha->md_tmplt_hdr, ha->md_tmplt_hdr_dma); - ha->md_tmplt_hdr = 0; + ha->md_tmplt_hdr = NULL; } /* Release the template data buffer allocated */ @@ -4375,7 +4412,7 @@ qla82xx_md_free(scsi_qla_host_t *vha) ha->md_dump, ha->md_dump_size / 1024); vfree(ha->md_dump); ha->md_dump_size = 0; - ha->md_dump = 0; + ha->md_dump = NULL; } } @@ -4393,7 +4430,11 @@ qla82xx_md_prep(scsi_qla_host_t *vha) ha->md_template_size / 1024); /* Get Minidump template */ - rval = qla82xx_md_get_template(vha); + if (IS_QLA8044(ha)) + rval = qla8044_md_get_template(vha); + else + rval = qla82xx_md_get_template(vha); + if (rval == QLA_SUCCESS) { ql_dbg(ql_dbg_p3p, vha, 0xb04b, "MiniDump Template obtained\n"); @@ -4412,7 +4453,7 @@ qla82xx_md_prep(scsi_qla_host_t *vha) dma_free_coherent(&ha->pdev->dev, ha->md_template_size, ha->md_tmplt_hdr, ha->md_tmplt_hdr_dma); - ha->md_tmplt_hdr = 0; + ha->md_tmplt_hdr = NULL; } } @@ -4458,3 +4499,20 @@ exit: qla82xx_idc_unlock(ha); return rval; } + +void +qla82xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) +{ + struct qla_hw_data *ha = vha->hw; + + if (!ha->allow_cna_fw_dump) + return; + + scsi_block_requests(vha->host); + ha->flags.isp82xx_no_md_cap = 1; + qla82xx_idc_lock(ha); + qla82xx_set_reset_owner(vha); + qla82xx_idc_unlock(ha); + qla2x00_wait_for_chip_reset(vha); + scsi_unblock_requests(vha->host); +} |
