From aa6f5ffbdba45aa8e19e5048648fc6c7b25376d3 Mon Sep 17 00:00:00 2001 From: merge Date: Thu, 22 Jan 2009 13:55:32 +0000 Subject: MERGE-via-pending-tracking-hist-MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040-1232632141 pending-tracking-hist top was MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040-1232632141 / fdf777a63bcb59e0dfd78bfe2c6242e01f6d4eb9 ... parent commitmessage: From: merge MERGE-via-stable-tracking-hist-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040 stable-tracking-hist top was MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040 / 90463bfd2d5a3c8b52f6e6d71024a00e052b0ced ... parent commitmessage: From: merge MERGE-via-mokopatches-tracking-hist-fix-stray-endmenu-patch mokopatches-tracking-hist top was fix-stray-endmenu-patch / 3630e0be570de8057e7f8d2fe501ed353cdf34e6 ... parent commitmessage: From: Andy Green fix-stray-endmenu.patch Signed-off-by: Andy Green --- drivers/scsi/qla2xxx/qla_init.c | 1584 ++++++++++++++++++++++++--------------- 1 file changed, 977 insertions(+), 607 deletions(-) (limited to 'drivers/scsi/qla2xxx/qla_init.c') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index a470f2d3270..9ad4d0968e5 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5,6 +5,7 @@ * See LICENSE.qla2xxx for copyright and licensing details. */ #include "qla_def.h" +#include "qla_gbl.h" #include #include @@ -21,7 +22,6 @@ static int qla2x00_isp_firmware(scsi_qla_host_t *); static void qla2x00_resize_request_q(scsi_qla_host_t *); static int qla2x00_setup_chip(scsi_qla_host_t *); -static void qla2x00_init_response_q_entries(scsi_qla_host_t *); static int qla2x00_init_rings(scsi_qla_host_t *); static int qla2x00_fw_ready(scsi_qla_host_t *); static int qla2x00_configure_hba(scsi_qla_host_t *); @@ -35,10 +35,11 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *, static int qla2x00_restart_isp(scsi_qla_host_t *); -static int qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev); +static int qla2x00_find_new_loop_id(scsi_qla_host_t *, fc_port_t *); static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *); static int qla84xx_init_chip(scsi_qla_host_t *); +static int qla25xx_init_queues(struct qla_hw_data *); /****************************************************************************/ /* QLogic ISP2x00 Hardware Support Functions. */ @@ -55,77 +56,81 @@ static int qla84xx_init_chip(scsi_qla_host_t *); * 0 = success */ int -qla2x00_initialize_adapter(scsi_qla_host_t *ha) +qla2x00_initialize_adapter(scsi_qla_host_t *vha) { int rval; - + struct qla_hw_data *ha = vha->hw; + struct req_que *req = ha->req_q_map[0]; /* Clear adapter flags. */ - ha->flags.online = 0; - ha->flags.reset_active = 0; - atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); - atomic_set(&ha->loop_state, LOOP_DOWN); - ha->device_flags = DFLG_NO_CABLE; - ha->dpc_flags = 0; - ha->flags.management_server_logged_in = 0; - ha->marker_needed = 0; + vha->flags.online = 0; + vha->flags.reset_active = 0; + atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); + atomic_set(&vha->loop_state, LOOP_DOWN); + vha->device_flags = DFLG_NO_CABLE; + vha->dpc_flags = 0; + vha->flags.management_server_logged_in = 0; + vha->marker_needed = 0; ha->mbx_flags = 0; ha->isp_abort_cnt = 0; ha->beacon_blink_led = 0; - set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); + set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); + + set_bit(0, ha->req_qid_map); + set_bit(0, ha->rsp_qid_map); qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); - rval = ha->isp_ops->pci_config(ha); + rval = ha->isp_ops->pci_config(vha); if (rval) { DEBUG2(printk("scsi(%ld): Unable to configure PCI space.\n", - ha->host_no)); + vha->host_no)); return (rval); } - ha->isp_ops->reset_chip(ha); + ha->isp_ops->reset_chip(vha); - rval = qla2xxx_get_flash_info(ha); + rval = qla2xxx_get_flash_info(vha); if (rval) { DEBUG2(printk("scsi(%ld): Unable to validate FLASH data.\n", - ha->host_no)); + vha->host_no)); return (rval); } - ha->isp_ops->get_flash_version(ha, ha->request_ring); + ha->isp_ops->get_flash_version(vha, req->ring); qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); - ha->isp_ops->nvram_config(ha); + ha->isp_ops->nvram_config(vha); if (ha->flags.disable_serdes) { /* Mask HBA via NVRAM settings? */ qla_printk(KERN_INFO, ha, "Masking HBA WWPN " "%02x%02x%02x%02x%02x%02x%02x%02x (via NVRAM).\n", - ha->port_name[0], ha->port_name[1], - ha->port_name[2], ha->port_name[3], - ha->port_name[4], ha->port_name[5], - ha->port_name[6], ha->port_name[7]); + vha->port_name[0], vha->port_name[1], + vha->port_name[2], vha->port_name[3], + vha->port_name[4], vha->port_name[5], + vha->port_name[6], vha->port_name[7]); return QLA_FUNCTION_FAILED; } qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); - if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { - rval = ha->isp_ops->chip_diag(ha); + if (qla2x00_isp_firmware(vha) != QLA_SUCCESS) { + rval = ha->isp_ops->chip_diag(vha); if (rval) return (rval); - rval = qla2x00_setup_chip(ha); + rval = qla2x00_setup_chip(vha); if (rval) return (rval); } if (IS_QLA84XX(ha)) { - ha->cs84xx = qla84xx_get_chip(ha); + ha->cs84xx = qla84xx_get_chip(vha); if (!ha->cs84xx) { qla_printk(KERN_ERR, ha, "Unable to configure ISP84XX.\n"); return QLA_FUNCTION_FAILED; } } - rval = qla2x00_init_rings(ha); + rval = qla2x00_init_rings(vha); return (rval); } @@ -137,11 +142,11 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) * Returns 0 on success. */ int -qla2100_pci_config(scsi_qla_host_t *ha) +qla2100_pci_config(scsi_qla_host_t *vha) { uint16_t w; - uint32_t d; unsigned long flags; + struct qla_hw_data *ha = vha->hw; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; pci_set_master(ha->pdev); @@ -151,10 +156,7 @@ qla2100_pci_config(scsi_qla_host_t *ha) w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); pci_write_config_word(ha->pdev, PCI_COMMAND, w); - /* Reset expansion ROM address decode enable */ - pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); - d &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); + pci_disable_rom(ha->pdev); /* Get PCI bus information. */ spin_lock_irqsave(&ha->hardware_lock, flags); @@ -171,12 +173,12 @@ qla2100_pci_config(scsi_qla_host_t *ha) * Returns 0 on success. */ int -qla2300_pci_config(scsi_qla_host_t *ha) +qla2300_pci_config(scsi_qla_host_t *vha) { uint16_t w; - uint32_t d; unsigned long flags = 0; uint32_t cnt; + struct qla_hw_data *ha = vha->hw; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; pci_set_master(ha->pdev); @@ -236,10 +238,7 @@ qla2300_pci_config(scsi_qla_host_t *ha) pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); - /* Reset expansion ROM address decode enable */ - pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); - d &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); + pci_disable_rom(ha->pdev); /* Get PCI bus information. */ spin_lock_irqsave(&ha->hardware_lock, flags); @@ -256,11 +255,11 @@ qla2300_pci_config(scsi_qla_host_t *ha) * Returns 0 on success. */ int -qla24xx_pci_config(scsi_qla_host_t *ha) +qla24xx_pci_config(scsi_qla_host_t *vha) { uint16_t w; - uint32_t d; unsigned long flags = 0; + struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; pci_set_master(ha->pdev); @@ -281,10 +280,7 @@ qla24xx_pci_config(scsi_qla_host_t *ha) if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP)) pcie_set_readrq(ha->pdev, 2048); - /* Reset expansion ROM address decode enable */ - pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); - d &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); + pci_disable_rom(ha->pdev); ha->chip_revision = ha->pdev->revision; @@ -303,10 +299,10 @@ qla24xx_pci_config(scsi_qla_host_t *ha) * Returns 0 on success. */ int -qla25xx_pci_config(scsi_qla_host_t *ha) +qla25xx_pci_config(scsi_qla_host_t *vha) { uint16_t w; - uint32_t d; + struct qla_hw_data *ha = vha->hw; pci_set_master(ha->pdev); pci_try_set_mwi(ha->pdev); @@ -320,10 +316,7 @@ qla25xx_pci_config(scsi_qla_host_t *ha) if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP)) pcie_set_readrq(ha->pdev, 2048); - /* Reset expansion ROM address decode enable */ - pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); - d &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); + pci_disable_rom(ha->pdev); ha->chip_revision = ha->pdev->revision; @@ -337,32 +330,33 @@ qla25xx_pci_config(scsi_qla_host_t *ha) * Returns 0 on success. */ static int -qla2x00_isp_firmware(scsi_qla_host_t *ha) +qla2x00_isp_firmware(scsi_qla_host_t *vha) { int rval; uint16_t loop_id, topo, sw_cap; uint8_t domain, area, al_pa; + struct qla_hw_data *ha = vha->hw; /* Assume loading risc code */ rval = QLA_FUNCTION_FAILED; if (ha->flags.disable_risc_code_load) { DEBUG2(printk("scsi(%ld): RISC CODE NOT loaded\n", - ha->host_no)); + vha->host_no)); qla_printk(KERN_INFO, ha, "RISC CODE NOT loaded\n"); /* Verify checksum of loaded RISC code. */ - rval = qla2x00_verify_checksum(ha, ha->fw_srisc_address); + rval = qla2x00_verify_checksum(vha, ha->fw_srisc_address); if (rval == QLA_SUCCESS) { /* And, verify we are not in ROM code. */ - rval = qla2x00_get_adapter_id(ha, &loop_id, &al_pa, + rval = qla2x00_get_adapter_id(vha, &loop_id, &al_pa, &area, &domain, &topo, &sw_cap); } } if (rval) { DEBUG2_3(printk("scsi(%ld): **** Load RISC code ****\n", - ha->host_no)); + vha->host_no)); } return (rval); @@ -375,9 +369,10 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha) * Returns 0 on success. */ void -qla2x00_reset_chip(scsi_qla_host_t *ha) +qla2x00_reset_chip(scsi_qla_host_t *vha) { unsigned long flags = 0; + struct qla_hw_data *ha = vha->hw; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; uint32_t cnt; uint16_t cmd; @@ -515,10 +510,11 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) * Returns 0 on success. */ static inline void -qla24xx_reset_risc(scsi_qla_host_t *ha) +qla24xx_reset_risc(scsi_qla_host_t *vha) { int hw_evt = 0; unsigned long flags = 0; + struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; uint32_t cnt, d2; uint16_t wd; @@ -556,10 +552,6 @@ qla24xx_reset_risc(scsi_qla_host_t *ha) d2 = RD_REG_DWORD(®->ctrl_status); barrier(); } - if (cnt == 0 || hw_evt) - qla2xxx_hw_event_log(ha, HW_EVENT_RESET_ERR, - RD_REG_WORD(®->mailbox1), RD_REG_WORD(®->mailbox2), - RD_REG_WORD(®->mailbox3)); WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET); RD_REG_DWORD(®->hccr); @@ -578,6 +570,9 @@ qla24xx_reset_risc(scsi_qla_host_t *ha) } spin_unlock_irqrestore(&ha->hardware_lock, flags); + + if (IS_NOPOLLING_TYPE(ha)) + ha->isp_ops->enable_intrs(ha); } /** @@ -587,12 +582,13 @@ qla24xx_reset_risc(scsi_qla_host_t *ha) * Returns 0 on success. */ void -qla24xx_reset_chip(scsi_qla_host_t *ha) +qla24xx_reset_chip(scsi_qla_host_t *vha) { + struct qla_hw_data *ha = vha->hw; ha->isp_ops->disable_intrs(ha); /* Perform RISC reset. */ - qla24xx_reset_risc(ha); + qla24xx_reset_risc(vha); } /** @@ -602,20 +598,22 @@ qla24xx_reset_chip(scsi_qla_host_t *ha) * Returns 0 on success. */ int -qla2x00_chip_diag(scsi_qla_host_t *ha) +qla2x00_chip_diag(scsi_qla_host_t *vha) { int rval; + struct qla_hw_data *ha = vha->hw; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; unsigned long flags = 0; uint16_t data; uint32_t cnt; uint16_t mb[5]; + struct req_que *req = ha->req_q_map[0]; /* Assume a failed state */ rval = QLA_FUNCTION_FAILED; DEBUG3(printk("scsi(%ld): Testing device at %lx.\n", - ha->host_no, (u_long)®->flash_address)); + vha->host_no, (u_long)®->flash_address)); spin_lock_irqsave(&ha->hardware_lock, flags); @@ -678,17 +676,17 @@ qla2x00_chip_diag(scsi_qla_host_t *ha) ha->product_id[3] = mb[4]; /* Adjust fw RISC transfer size */ - if (ha->request_q_length > 1024) + if (req->length > 1024) ha->fw_transfer_size = REQUEST_ENTRY_SIZE * 1024; else ha->fw_transfer_size = REQUEST_ENTRY_SIZE * - ha->request_q_length; + req->length; if (IS_QLA2200(ha) && RD_MAILBOX_REG(ha, reg, 7) == QLA2200A_RISC_ROM_VER) { /* Limit firmware transfer size with a 2200A */ DEBUG3(printk("scsi(%ld): Found QLA2200A chip.\n", - ha->host_no)); + vha->host_no)); ha->device_type |= DT_ISP2200A; ha->fw_transfer_size = 128; @@ -697,11 +695,11 @@ qla2x00_chip_diag(scsi_qla_host_t *ha) /* Wrap Incoming Mailboxes Test. */ spin_unlock_irqrestore(&ha->hardware_lock, flags); - DEBUG3(printk("scsi(%ld): Checking mailboxes.\n", ha->host_no)); - rval = qla2x00_mbx_reg_test(ha); + DEBUG3(printk("scsi(%ld): Checking mailboxes.\n", vha->host_no)); + rval = qla2x00_mbx_reg_test(vha); if (rval) { DEBUG(printk("scsi(%ld): Failed mailbox send register test\n", - ha->host_no)); + vha->host_no)); qla_printk(KERN_WARNING, ha, "Failed mailbox send register test\n"); } @@ -714,7 +712,7 @@ qla2x00_chip_diag(scsi_qla_host_t *ha) chip_diag_failed: if (rval) DEBUG2_3(printk("scsi(%ld): Chip diagnostics **** FAILED " - "****\n", ha->host_no)); + "****\n", vha->host_no)); spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -728,19 +726,21 @@ chip_diag_failed: * Returns 0 on success. */ int -qla24xx_chip_diag(scsi_qla_host_t *ha) +qla24xx_chip_diag(scsi_qla_host_t *vha) { int rval; + struct qla_hw_data *ha = vha->hw; + struct req_que *req = ha->req_q_map[0]; /* Perform RISC reset. */ - qla24xx_reset_risc(ha); + qla24xx_reset_risc(vha); - ha->fw_transfer_size = REQUEST_ENTRY_SIZE * ha->request_q_length; + ha->fw_transfer_size = REQUEST_ENTRY_SIZE * req->length; - rval = qla2x00_mbx_reg_test(ha); + rval = qla2x00_mbx_reg_test(vha); if (rval) { DEBUG(printk("scsi(%ld): Failed mailbox send register test\n", - ha->host_no)); + vha->host_no)); qla_printk(KERN_WARNING, ha, "Failed mailbox send register test\n"); } else { @@ -752,13 +752,16 @@ qla24xx_chip_diag(scsi_qla_host_t *ha) } void -qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) +qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) { int rval; uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size, - eft_size, fce_size; + eft_size, fce_size, mq_size; dma_addr_t tc_dma; void *tc; + struct qla_hw_data *ha = vha->hw; + struct req_que *req = ha->req_q_map[0]; + struct rsp_que *rsp = ha->rsp_q_map[0]; if (ha->fw_dump) { qla_printk(KERN_WARNING, ha, @@ -767,7 +770,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) } ha->fw_dumped = 0; - fixed_size = mem_size = eft_size = fce_size = 0; + fixed_size = mem_size = eft_size = fce_size = mq_size = 0; if (IS_QLA2100(ha) || IS_QLA2200(ha)) { fixed_size = sizeof(struct qla2100_fw_dump); } else if (IS_QLA23XX(ha)) { @@ -775,14 +778,19 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) mem_size = (ha->fw_memory_size - 0x11000 + 1) * sizeof(uint16_t); } else if (IS_FWI2_CAPABLE(ha)) { - fixed_size = IS_QLA25XX(ha) ? - offsetof(struct qla25xx_fw_dump, ext_mem): - offsetof(struct qla24xx_fw_dump, ext_mem); + if (IS_QLA81XX(ha)) + fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem); + else if (IS_QLA25XX(ha)) + fixed_size = offsetof(struct qla25xx_fw_dump, ext_mem); + else + fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem); mem_size = (ha->fw_memory_size - 0x100000 + 1) * sizeof(uint32_t); + if (ha->mqenable) + mq_size = sizeof(struct qla2xxx_mq_chain); /* Allocate memory for Fibre Channel Event Buffer. */ - if (!IS_QLA25XX(ha)) + if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha)) goto try_eft; tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, @@ -794,7 +802,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) } memset(tc, 0, FCE_SIZE); - rval = qla2x00_enable_fce_trace(ha, tc_dma, FCE_NUM_BUFFERS, + rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS, ha->fce_mb, &ha->fce_bufs); if (rval) { qla_printk(KERN_WARNING, ha, "Unable to initialize " @@ -823,7 +831,7 @@ try_eft: } memset(tc, 0, EFT_SIZE); - rval = qla2x00_enable_eft_trace(ha, tc_dma, EFT_NUM_BUFFERS); + rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS); if (rval) { qla_printk(KERN_WARNING, ha, "Unable to initialize " "EFT (%d).\n", rval); @@ -840,12 +848,14 @@ try_eft: ha->eft = tc; } cont_alloc: - req_q_size = ha->request_q_length * sizeof(request_t); - rsp_q_size = ha->response_q_length * sizeof(response_t); + req_q_size = req->length * sizeof(request_t); + rsp_q_size = rsp->length * sizeof(response_t); dump_size = offsetof(struct qla2xxx_fw_dump, isp); dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + - eft_size + fce_size; + eft_size; + ha->chain_offset = dump_size; + dump_size += mq_size + fce_size; ha->fw_dump = vmalloc(dump_size); if (!ha->fw_dump) { @@ -860,7 +870,6 @@ cont_alloc: } return; } - qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware dump...\n", dump_size / 1024); @@ -891,27 +900,29 @@ cont_alloc: * Returns 0 on success. */ static void -qla2x00_resize_request_q(scsi_qla_host_t *ha) +qla2x00_resize_request_q(scsi_qla_host_t *vha) { int rval; uint16_t fw_iocb_cnt = 0; uint16_t request_q_length = REQUEST_ENTRY_CNT_2XXX_EXT_MEM; dma_addr_t request_dma; request_t *request_ring; + struct qla_hw_data *ha = vha->hw; + struct req_que *req = ha->req_q_map[0]; /* Valid only on recent ISPs. */ if (IS_QLA2100(ha) || IS_QLA2200(ha)) return; /* Retrieve IOCB counts available to the firmware. */ - rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt, - &ha->max_npiv_vports); + rval = qla2x00_get_resource_cnts(vha, NULL, NULL, NULL, &fw_iocb_cnt, + &ha->max_npiv_vports); if (rval) return; /* No point in continuing if current settings are sufficient. */ if (fw_iocb_cnt < 1024) return; - if (ha->request_q_length >= request_q_length) + if (req->length >= request_q_length) return; /* Attempt to claim larger area for request queue. */ @@ -925,17 +936,17 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha) qla_printk(KERN_INFO, ha, "Extended memory detected (%d KB)...\n", (ha->fw_memory_size + 1) / 1024); qla_printk(KERN_INFO, ha, "Resizing request queue depth " - "(%d -> %d)...\n", ha->request_q_length, request_q_length); + "(%d -> %d)...\n", req->length, request_q_length); /* Clear old allocations. */ dma_free_coherent(&ha->pdev->dev, - (ha->request_q_length + 1) * sizeof(request_t), ha->request_ring, - ha->request_dma); + (req->length + 1) * sizeof(request_t), req->ring, + req->dma); /* Begin using larger queue. */ - ha->request_q_length = request_q_length; - ha->request_ring = request_ring; - ha->request_dma = request_dma; + req->length = request_q_length; + req->ring = request_ring; + req->dma = request_dma; } /** @@ -945,10 +956,11 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha) * Returns 0 on success. */ static int -qla2x00_setup_chip(scsi_qla_host_t *ha) +qla2x00_setup_chip(scsi_qla_host_t *vha) { int rval; uint32_t srisc_address = 0; + struct qla_hw_data *ha = vha->hw; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; unsigned long flags; @@ -961,29 +973,28 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) } /* Load firmware sequences */ - rval = ha->isp_ops->load_risc(ha, &srisc_address); + rval = ha->isp_ops->load_risc(vha, &srisc_address); if (rval == QLA_SUCCESS) { DEBUG(printk("scsi(%ld): Verifying Checksum of loaded RISC " - "code.\n", ha->host_no)); + "code.\n", vha->host_no)); - rval = qla2x00_verify_checksum(ha, srisc_address); + rval = qla2x00_verify_checksum(vha, srisc_address); if (rval == QLA_SUCCESS) { /* Start firmware execution. */ DEBUG(printk("scsi(%ld): Checksum OK, start " - "firmware.\n", ha->host_no)); + "firmware.\n", vha->host_no)); - rval = qla2x00_execute_fw(ha, srisc_address); + rval = qla2x00_execute_fw(vha, srisc_address); /* Retrieve firmware information. */ if (rval == QLA_SUCCESS && ha->fw_major_version == 0) { - qla2x00_get_fw_version(ha, + qla2x00_get_fw_version(vha, &ha->fw_major_version, &ha->fw_minor_version, &ha->fw_subminor_version, - &ha->fw_attributes, &ha->fw_memory_size); - qla2x00_resize_request_q(ha); + &ha->fw_attributes, &ha->fw_memory_size, + ha->mpi_version, &ha->mpi_capabilities); ha->flags.npiv_supported = 0; - if ((IS_QLA24XX(ha) || IS_QLA25XX(ha) || - IS_QLA84XX(ha)) && + if (IS_QLA2XXX_MIDTYPE(ha) && (ha->fw_attributes & BIT_2)) { ha->flags.npiv_supported = 1; if ((!ha->max_npiv_vports) || @@ -992,14 +1003,15 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) ha->max_npiv_vports = MIN_MULTI_ID_FABRIC - 1; } + qla2x00_resize_request_q(vha); if (ql2xallocfwdump) - qla2x00_alloc_fw_dump(ha); + qla2x00_alloc_fw_dump(vha); } } else { DEBUG2(printk(KERN_INFO "scsi(%ld): ISP Firmware failed checksum.\n", - ha->host_no)); + vha->host_no)); } } @@ -1018,7 +1030,7 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) if (rval) { DEBUG2_3(printk("scsi(%ld): Setup chip **** FAILED ****.\n", - ha->host_no)); + vha->host_no)); } return (rval); @@ -1033,14 +1045,14 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) * * Returns 0 on success. */ -static void -qla2x00_init_response_q_entries(scsi_qla_host_t *ha) +void +qla2x00_init_response_q_entries(struct rsp_que *rsp) { uint16_t cnt; response_t *pkt; - pkt = ha->response_ring_ptr; - for (cnt = 0; cnt < ha->response_q_length; cnt++) { + pkt = rsp->ring_ptr; + for (cnt = 0; cnt < rsp->length; cnt++) { pkt->signature = RESPONSE_PROCESSED; pkt++; } @@ -1054,19 +1066,20 @@ qla2x00_init_response_q_entries(scsi_qla_host_t *ha) * Returns 0 on success. */ void -qla2x00_update_fw_options(scsi_qla_host_t *ha) +qla2x00_update_fw_options(scsi_qla_host_t *vha) { uint16_t swing, emphasis, tx_sens, rx_sens; + struct qla_hw_data *ha = vha->hw; memset(ha->fw_options, 0, sizeof(ha->fw_options)); - qla2x00_get_fw_options(ha, ha->fw_options); + qla2x00_get_fw_options(vha, ha->fw_options); if (IS_QLA2100(ha) || IS_QLA2200(ha)) return; /* Serial Link options. */ DEBUG3(printk("scsi(%ld): Serial link options:\n", - ha->host_no)); + vha->host_no)); DEBUG3(qla2x00_dump_buffer((uint8_t *)&ha->fw_seriallink_options, sizeof(ha->fw_seriallink_options))); @@ -1124,19 +1137,20 @@ qla2x00_update_fw_options(scsi_qla_host_t *ha) ha->fw_options[2] |= BIT_13; /* Update firmware options. */ - qla2x00_set_fw_options(ha, ha->fw_options); + qla2x00_set_fw_options(vha, ha->fw_options); } void -qla24xx_update_fw_options(scsi_qla_host_t *ha) +qla24xx_update_fw_options(scsi_qla_host_t *vha) { int rval; + struct qla_hw_data *ha = vha->hw; /* Update Serial Link options. */ if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) return; - rval = qla2x00_set_serdes_params(ha, + rval = qla2x00_set_serdes_params(vha, le16_to_cpu(ha->fw_seriallink_options24[1]), le16_to_cpu(ha->fw_seriallink_options24[2]), le16_to_cpu(ha->fw_seriallink_options24[3])); @@ -1147,19 +1161,22 @@ qla24xx_update_fw_options(scsi_qla_host_t *ha) } void -qla2x00_config_rings(struct scsi_qla_host *ha) +qla2x00_config_rings(struct scsi_qla_host *vha) { + struct qla_hw_data *ha = vha->hw; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + struct req_que *req = ha->req_q_map[0]; + struct rsp_que *rsp = ha->rsp_q_map[0]; /* Setup ring parameters in initialization control block. */ ha->init_cb->request_q_outpointer = __constant_cpu_to_le16(0); ha->init_cb->response_q_inpointer = __constant_cpu_to_le16(0); - ha->init_cb->request_q_length = cpu_to_le16(ha->request_q_length); - ha->init_cb->response_q_length = cpu_to_le16(ha->response_q_length); - ha->init_cb->request_q_address[0] = cpu_to_le32(LSD(ha->request_dma)); - ha->init_cb->request_q_address[1] = cpu_to_le32(MSD(ha->request_dma)); - ha->init_cb->response_q_address[0] = cpu_to_le32(LSD(ha->response_dma)); - ha->init_cb->response_q_address[1] = cpu_to_le32(MSD(ha->response_dma)); + ha->init_cb->request_q_length = cpu_to_le16(req->length); + ha->init_cb->response_q_length = cpu_to_le16(rsp->length); + ha->init_cb->request_q_address[0] = cpu_to_le32(LSD(req->dma)); + ha->init_cb->request_q_address[1] = cpu_to_le32(MSD(req->dma)); + ha->init_cb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma)); + ha->init_cb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma)); WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), 0); WRT_REG_WORD(ISP_REQ_Q_OUT(ha, reg), 0); @@ -1169,27 +1186,62 @@ qla2x00_config_rings(struct scsi_qla_host *ha) } void -qla24xx_config_rings(struct scsi_qla_host *ha) +qla24xx_config_rings(struct scsi_qla_host *vha) { - struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + struct qla_hw_data *ha = vha->hw; + device_reg_t __iomem *reg = ISP_QUE_REG(ha, 0); + struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp; + struct qla_msix_entry *msix; struct init_cb_24xx *icb; + uint16_t rid = 0; + struct req_que *req = ha->req_q_map[0]; + struct rsp_que *rsp = ha->rsp_q_map[0]; - /* Setup ring parameters in initialization control block. */ +/* Setup ring parameters in initialization control block. */ icb = (struct init_cb_24xx *)ha->init_cb; icb->request_q_outpointer = __constant_cpu_to_le16(0); icb->response_q_inpointer = __constant_cpu_to_le16(0); - icb->request_q_length = cpu_to_le16(ha->request_q_length); - icb->response_q_length = cpu_to_le16(ha->response_q_length); - icb->request_q_address[0] = cpu_to_le32(LSD(ha->request_dma)); - icb->request_q_address[1] = cpu_to_le32(MSD(ha->request_dma)); - icb->response_q_address[0] = cpu_to_le32(LSD(ha->response_dma)); - icb->response_q_address[1] = cpu_to_le32(MSD(ha->response_dma)); - - WRT_REG_DWORD(®->req_q_in, 0); - WRT_REG_DWORD(®->req_q_out, 0); - WRT_REG_DWORD(®->rsp_q_in, 0); - WRT_REG_DWORD(®->rsp_q_out, 0); - RD_REG_DWORD(®->rsp_q_out); + icb->request_q_length = cpu_to_le16(req->length); + icb->response_q_length = cpu_to_le16(rsp->length); + icb->request_q_address[0] = cpu_to_le32(LSD(req->dma)); + icb->request_q_address[1] = cpu_to_le32(MSD(req->dma)); + icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma)); + icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma)); + + if (ha->mqenable) { + icb->qos = __constant_cpu_to_le16(QLA_DEFAULT_QUE_QOS); + icb->rid = __constant_cpu_to_le16(rid); + if (ha->flags.msix_enabled) { + msix = &ha->msix_entries[1]; + DEBUG2_17(printk(KERN_INFO + "Reistering vector 0x%x for base que\n", msix->entry)); + icb->msix = cpu_to_le16(msix->entry); + } + /* Use alternate PCI bus number */ + if (MSB(rid)) + icb->firmware_options_2 |= + __constant_cpu_to_le32(BIT_19); + /* Use alternate PCI devfn */ + if (LSB(rid)) + icb->firmware_options_2 |= + __constant_cpu_to_le32(BIT_18); + + icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_22); + icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_23); + ha->rsp_q_map[0]->options = icb->firmware_options_2; + + WRT_REG_DWORD(®->isp25mq.req_q_in, 0); + WRT_REG_DWORD(®->isp25mq.req_q_out, 0); + WRT_REG_DWORD(®->isp25mq.rsp_q_in, 0); + WRT_REG_DWORD(®->isp25mq.rsp_q_out, 0); + } else { + WRT_REG_DWORD(®->isp24.req_q_in, 0); + WRT_REG_DWORD(®->isp24.req_q_out, 0); + WRT_REG_DWORD(®->isp24.rsp_q_in, 0); + WRT_REG_DWORD(®->isp24.rsp_q_out, 0); + } + /* PCI posting */ + RD_REG_DWORD(&ioreg->hccr); } /** @@ -1202,57 +1254,73 @@ qla24xx_config_rings(struct scsi_qla_host *ha) * Returns 0 on success. */ static int -qla2x00_init_rings(scsi_qla_host_t *ha) +qla2x00_init_rings(scsi_qla_host_t *vha) { int rval; unsigned long flags = 0; - int cnt; + int cnt, que; + struct qla_hw_data *ha = vha->hw; + struct req_que *req; + struct rsp_que *rsp; + struct scsi_qla_host *vp; struct mid_init_cb_24xx *mid_init_cb = (struct mid_init_cb_24xx *) ha->init_cb; spin_lock_irqsave(&ha->hardware_lock, flags); /* Clear outstanding commands array. */ - for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) - ha->outstanding_cmds[cnt] = NULL; + for (que = 0; que < ha->max_queues; que++) { + req = ha->req_q_map[que]; + if (!req) + continue; + for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) + req->outstanding_cmds[cnt] = NULL; - ha->current_outstanding_cmd = 0; + req->current_outstanding_cmd = 0; - /* Clear RSCN queue. */ - ha->rscn_in_ptr = 0; - ha->rscn_out_ptr = 0; + /* Initialize firmware. */ + req->ring_ptr = req->ring; + req->ring_index = 0; + req->cnt = req->length; + } - /* Initialize firmware. */ - ha->request_ring_ptr = ha->request_ring; - ha->req_ring_index = 0; - ha->req_q_cnt = ha->request_q_length; - ha->response_ring_ptr = ha->response_ring; - ha->rsp_ring_index = 0; + for (que = 0; que < ha->max_queues; que++) { + rsp = ha->rsp_q_map[que]; + if (!rsp) + continue; + rsp->ring_ptr = rsp->ring; + rsp->ring_index = 0; - /* Initialize response queue entries */ - qla2x00_init_response_q_entries(ha); + /* Initialize response queue entries */ + qla2x00_init_response_q_entries(rsp); + } - ha->isp_ops->config_rings(ha); + /* Clear RSCN queue. */ + list_for_each_entry(vp, &ha->vp_list, list) { + vp->rscn_in_ptr = 0; + vp->rscn_out_ptr = 0; + } + ha->isp_ops->config_rings(vha); spin_unlock_irqrestore(&ha->hardware_lock, flags); /* Update any ISP specific firmware options before initialization. */ - ha->isp_ops->update_fw_options(ha); + ha->isp_ops->update_fw_options(vha); - DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); + DEBUG(printk("scsi(%ld): Issue init firmware.\n", vha->host_no)); if (ha->flags.npiv_supported) mid_init_cb->count = cpu_to_le16(ha->max_npiv_vports); mid_init_cb->options = __constant_cpu_to_le16(BIT_1); - rval = qla2x00_init_firmware(ha, ha->init_cb_size); + rval = qla2x00_init_firmware(vha, ha->init_cb_size); if (rval) { DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n", - ha->host_no)); + vha->host_no)); } else { DEBUG3(printk("scsi(%ld): Init firmware -- success.\n", - ha->host_no)); + vha->host_no)); } return (rval); @@ -1265,13 +1333,14 @@ qla2x00_init_rings(scsi_qla_host_t *ha) * Returns 0 on success. */ static int -qla2x00_fw_ready(scsi_qla_host_t *ha) +qla2x00_fw_ready(scsi_qla_host_t *vha) { int rval; unsigned long wtime, mtime, cs84xx_time; uint16_t min_wait; /* Minimum wait time if loop is down */ uint16_t wait_time; /* Wait time if loop is coming ready */ uint16_t state[3]; + struct qla_hw_data *ha = vha->hw; rval = QLA_SUCCESS; @@ -1293,29 +1362,29 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) wtime = jiffies + (wait_time * HZ); /* Wait for ISP to finish LIP */ - if (!ha->flags.init_done) + if (!vha->flags.init_done) qla_printk(KERN_INFO, ha, "Waiting for LIP to complete...\n"); DEBUG3(printk("scsi(%ld): Waiting for LIP to complete...\n", - ha->host_no)); + vha->host_no)); do { - rval = qla2x00_get_firmware_state(ha, state); + rval = qla2x00_get_firmware_state(vha, state); if (rval == QLA_SUCCESS) { if (state[0] < FSTATE_LOSS_OF_SYNC) { - ha->device_flags &= ~DFLG_NO_CABLE; + vha->device_flags &= ~DFLG_NO_CABLE; } if (IS_QLA84XX(ha) && state[0] != FSTATE_READY) { DEBUG16(printk("scsi(%ld): fw_state=%x " - "84xx=%x.\n", ha->host_no, state[0], + "84xx=%x.\n", vha->host_no, state[0], state[2])); if ((state[2] & FSTATE_LOGGED_IN) && (state[2] & FSTATE_WAITING_FOR_VERIFY)) { DEBUG16(printk("scsi(%ld): Sending " - "verify iocb.\n", ha->host_no)); + "verify iocb.\n", vha->host_no)); cs84xx_time = jiffies; - rval = qla84xx_init_chip(ha); + rval = qla84xx_init_chip(vha); if (rval != QLA_SUCCESS) break; @@ -1325,13 +1394,13 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) mtime += cs84xx_time; DEBUG16(printk("scsi(%ld): Increasing " "wait time by %ld. New time %ld\n", - ha->host_no, cs84xx_time, wtime)); + vha->host_no, cs84xx_time, wtime)); } } else if (state[0] == FSTATE_READY) { DEBUG(printk("scsi(%ld): F/W Ready - OK \n", - ha->host_no)); + vha->host_no)); - qla2x00_get_retry_cnt(ha, &ha->retry_count, + qla2x00_get_retry_cnt(vha, &ha->retry_count, &ha->login_timeout, &ha->r_a_tov); rval = QLA_SUCCESS; @@ -1340,7 +1409,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) rval = QLA_FUNCTION_FAILED; - if (atomic_read(&ha->loop_down_timer) && + if (atomic_read(&vha->loop_down_timer) && state[0] != FSTATE_READY) { /* Loop down. Timeout on min_wait for states * other than Wait for Login. @@ -1349,7 +1418,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) qla_printk(KERN_INFO, ha, "Cable is unplugged...\n"); - ha->device_flags |= DFLG_NO_CABLE; + vha->device_flags |= DFLG_NO_CABLE; break; } } @@ -1366,15 +1435,15 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) msleep(500); DEBUG3(printk("scsi(%ld): fw_state=%x curr time=%lx.\n", - ha->host_no, state[0], jiffies)); + vha->host_no, state[0], jiffies)); } while (1); DEBUG(printk("scsi(%ld): fw_state=%x curr time=%lx.\n", - ha->host_no, state[0], jiffies)); + vha->host_no, state[0], jiffies)); if (rval) { DEBUG2_3(printk("scsi(%ld): Firmware ready **** FAILED ****.\n", - ha->host_no)); + vha->host_no)); } return (rval); @@ -1394,7 +1463,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) * Kernel context. */ static int -qla2x00_configure_hba(scsi_qla_host_t *ha) +qla2x00_configure_hba(scsi_qla_host_t *vha) { int rval; uint16_t loop_id; @@ -1404,19 +1473,20 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) uint8_t area; uint8_t domain; char connect_type[22]; + struct qla_hw_data *ha = vha->hw; /* Get host addresses. */ - rval = qla2x00_get_adapter_id(ha, + rval = qla2x00_get_adapter_id(vha, &loop_id, &al_pa, &area, &domain, &topo, &sw_cap); if (rval != QLA_SUCCESS) { - if (LOOP_TRANSITION(ha) || atomic_read(&ha->loop_down_timer) || + if (LOOP_TRANSITION(vha) || atomic_read(&ha->loop_down_timer) || (rval == QLA_COMMAND_ERROR && loop_id == 0x7)) { DEBUG2(printk("%s(%ld) Loop is in a transition state\n", - __func__, ha->host_no)); + __func__, vha->host_no)); } else { qla_printk(KERN_WARNING, ha, "ERROR -- Unable to get host loop ID.\n"); - set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); } return (rval); } @@ -1427,7 +1497,7 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) return (QLA_FUNCTION_FAILED); } - ha->loop_id = loop_id; + vha->loop_id = loop_id; /* initialize */ ha->min_external_loopid = SNS_FIRST_LOOP_ID; @@ -1437,14 +1507,14 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) switch (topo) { case 0: DEBUG3(printk("scsi(%ld): HBA in NL topology.\n", - ha->host_no)); + vha->host_no)); ha->current_topology = ISP_CFG_NL; strcpy(connect_type, "(Loop)"); break; case 1: DEBUG3(printk("scsi(%ld): HBA in FL topology.\n", - ha->host_no)); + vha->host_no)); ha->switch_cap = sw_cap; ha->current_topology = ISP_CFG_FL; strcpy(connect_type, "(FL_Port)"); @@ -1452,7 +1522,7 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) case 2: DEBUG3(printk("scsi(%ld): HBA in N P2P topology.\n", - ha->host_no)); + vha->host_no)); ha->operating_mode = P2P; ha->current_topology = ISP_CFG_N; strcpy(connect_type, "(N_Port-to-N_Port)"); @@ -1460,7 +1530,7 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) case 3: DEBUG3(printk("scsi(%ld): HBA in F P2P topology.\n", - ha->host_no)); + vha->host_no)); ha->switch_cap = sw_cap; ha->operating_mode = P2P; ha->current_topology = ISP_CFG_F; @@ -1470,7 +1540,7 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) default: DEBUG3(printk("scsi(%ld): HBA in unknown topology %x. " "Using NL.\n", - ha->host_no, topo)); + vha->host_no, topo)); ha->current_topology = ISP_CFG_NL; strcpy(connect_type, "(Loop)"); break; @@ -1478,29 +1548,31 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) /* Save Host port and loop ID. */ /* byte order - Big Endian */ - ha->d_id.b.domain = domain; - ha->d_id.b.area = area; - ha->d_id.b.al_pa = al_pa; + vha->d_id.b.domain = domain; + vha->d_id.b.area = area; + vha->d_id.b.al_pa = al_pa; - if (!ha->flags.init_done) + if (!vha->flags.init_done) qla_printk(KERN_INFO, ha, "Topology - %s, Host Loop address 0x%x\n", - connect_type, ha->loop_id); + connect_type, vha->loop_id); if (rval) { - DEBUG2_3(printk("scsi(%ld): FAILED.\n", ha->host_no)); + DEBUG2_3(printk("scsi(%ld): FAILED.\n", vha->host_no)); } else { - DEBUG3(printk("scsi(%ld): exiting normally.\n", ha->host_no)); + DEBUG3(printk("scsi(%ld): exiting normally.\n", vha->host_no)); } return(rval); } static inline void -qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *def) +qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, + char *def) { char *st, *en; uint16_t index; + struct qla_hw_data *ha = vha->hw; if (memcmp(model, BINZERO, len) != 0) { strncpy(ha->model_number, model, len); @@ -1532,16 +1604,17 @@ qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *de } } if (IS_FWI2_CAPABLE(ha)) - qla2xxx_get_vpd_field(ha, "\x82", ha->model_desc, + qla2xxx_get_vpd_field(vha, "\x82", ha->model_desc, sizeof(ha->model_desc)); } /* On sparc systems, obtain port and node WWN from firmware * properties. */ -static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, nvram_t *nv) +static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv) { #ifdef CONFIG_SPARC + struct qla_hw_data *ha = vha->hw; struct pci_dev *pdev = ha->pdev; struct device_node *dp = pci_device_to_OF_node(pdev); const u8 *val; @@ -1571,12 +1644,13 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, nvram_t *nv) * 0 = success. */ int -qla2x00_nvram_config(scsi_qla_host_t *ha) +qla2x00_nvram_config(scsi_qla_host_t *vha) { int rval; uint8_t chksum = 0; uint16_t cnt; uint8_t *dptr1, *dptr2; + struct qla_hw_data *ha = vha->hw; init_cb_t *icb = ha->init_cb; nvram_t *nv = ha->nvram; uint8_t *ptr = ha->nvram; @@ -1592,11 +1666,11 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) ha->nvram_base = 0x80; /* Get NVRAM data and calculate checksum. */ - ha->isp_ops->read_nvram(ha, ptr, ha->nvram_base, ha->nvram_size); + ha->isp_ops->read_nvram(vha, ptr, ha->nvram_base, ha->nvram_size); for (cnt = 0, chksum = 0; cnt < ha->nvram_size; cnt++) chksum += *ptr++; - DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); + DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", vha->host_no)); DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size)); /* Bad NVRAM data, set defaults parameters. */ @@ -1609,10 +1683,6 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet " "invalid -- WWPN) defaults.\n"); - if (chksum) - qla2xxx_hw_event_log(ha, HW_EVENT_NVRAM_CHKSUM_ERR, 0, - MSW(chksum), LSW(chksum)); - /* * Set default initialization control block. */ @@ -1647,7 +1717,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) nv->port_name[3] = 224; nv->port_name[4] = 139; - qla2xxx_nvram_wwn_from_ofw(ha, nv); + qla2xxx_nvram_wwn_from_ofw(vha, nv); nv->login_timeout = 4; @@ -1700,7 +1770,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) strcpy(ha->model_number, "QLA2300"); } } else { - qla2x00_set_model_info(ha, nv->model_number, + qla2x00_set_model_info(vha, nv->model_number, sizeof(nv->model_number), "QLA23xx"); } } else if (IS_QLA2200(ha)) { @@ -1776,8 +1846,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) ha->serial0 = icb->port_name[5]; ha->serial1 = icb->port_name[6]; ha->serial2 = icb->port_name[7]; - ha->node_name = icb->node_name; - ha->port_name = icb->port_name; + memcpy(vha->node_name, icb->node_name, WWN_SIZE); + memcpy(vha->port_name, icb->port_name, WWN_SIZE); icb->execution_throttle = __constant_cpu_to_le16(0xFFFF); @@ -1845,10 +1915,10 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) icb->response_accumulation_timer = 3; icb->interrupt_delay_timer = 5; - ha->flags.process_response_queue = 1; + vha->flags.process_response_queue = 1; } else { /* Enable ZIO. */ - if (!ha->flags.init_done) { + if (!vha->flags.init_done) { ha->zio_mode = icb->add_firmware_options[0] & (BIT_3 | BIT_2 | BIT_1 | BIT_0); ha->zio_timer = icb->interrupt_delay_timer ? @@ -1856,12 +1926,12 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) } icb->add_firmware_options[0] &= ~(BIT_3 | BIT_2 | BIT_1 | BIT_0); - ha->flags.process_response_queue = 0; + vha->flags.process_response_queue = 0; if (ha->zio_mode != QLA_ZIO_DISABLED) { ha->zio_mode = QLA_ZIO_MODE_6; DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer " - "delay (%d us).\n", ha->host_no, ha->zio_mode, + "delay (%d us).\n", vha->host_no, ha->zio_mode, ha->zio_timer * 100)); qla_printk(KERN_INFO, ha, "ZIO mode %d enabled; timer delay (%d us).\n", @@ -1869,13 +1939,13 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) icb->add_firmware_options[0] |= (uint8_t)ha->zio_mode; icb->interrupt_delay_timer = (uint8_t)ha->zio_timer; - ha->flags.process_response_queue = 1; + vha->flags.process_response_queue = 1; } } if (rval) { DEBUG2_3(printk(KERN_WARNING - "scsi(%ld): NVRAM configuration failed!\n", ha->host_no)); + "scsi(%ld): NVRAM configuration failed!\n", vha->host_no)); } return (rval); } @@ -1886,10 +1956,10 @@ qla2x00_rport_del(void *data) fc_port_t *fcport = data; struct fc_rport *rport; - spin_lock_irq(fcport->ha->host->host_lock); + spin_lock_irq(fcport->vha->host->host_lock); rport = fcport->drport; fcport->drport = NULL; - spin_unlock_irq(fcport->ha->host->host_lock); + spin_unlock_irq(fcport->vha->host->host_lock); if (rport) fc_remote_port_delete(rport); } @@ -1902,7 +1972,7 @@ qla2x00_rport_del(void *data) * Returns a pointer to the allocated fcport, or NULL, if none available. */ static fc_port_t * -qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) +qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) { fc_port_t *fcport; @@ -1911,8 +1981,8 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) return NULL; /* Setup fcport template structure. */ - fcport->ha = ha; - fcport->vp_idx = ha->vp_idx; + fcport->vha = vha; + fcport->vp_idx = vha->vp_idx; fcport->port_type = FCT_UNKNOWN; fcport->loop_id = FC_NO_LOOP_ID; atomic_set(&fcport->state, FCS_UNCONFIGURED); @@ -1935,101 +2005,97 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) * 2 = database was full and device was not configured. */ static int -qla2x00_configure_loop(scsi_qla_host_t *ha) +qla2x00_configure_loop(scsi_qla_host_t *vha) { int rval; unsigned long flags, save_flags; - + struct qla_hw_data *ha = vha->hw; rval = QLA_SUCCESS; /* Get Initiator ID */ - if (test_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags)) { - rval = qla2x00_configure_hba(ha); + if (test_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags)) { + rval = qla2x00_configure_hba(vha); if (rval != QLA_SUCCESS) { DEBUG(printk("scsi(%ld): Unable to configure HBA.\n", - ha->host_no)); + vha->host_no)); return (rval); } } - save_flags = flags = ha->dpc_flags; + save_flags = flags = vha->dpc_flags; DEBUG(printk("scsi(%ld): Configure loop -- dpc flags =0x%lx\n", - ha->host_no, flags)); + vha->host_no, flags)); /* * If we have both an RSCN and PORT UPDATE pending then handle them * both at the same time. */ - clear_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); - clear_bit(RSCN_UPDATE, &ha->dpc_flags); + clear_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); + clear_bit(RSCN_UPDATE, &vha->dpc_flags); /* Determine what we need to do */ if (ha->current_topology == ISP_CFG_FL && (test_bit(LOCAL_LOOP_UPDATE, &flags))) { - ha->flags.rscn_queue_overflow = 1; + vha->flags.rscn_queue_overflow = 1; set_bit(RSCN_UPDATE, &flags); } else if (ha->current_topology == ISP_CFG_F && (test_bit(LOCAL_LOOP_UPDATE, &flags))) { - ha->flags.rscn_queue_overflow = 1; + vha->flags.rscn_queue_overflow = 1; set_bit(RSCN_UPDATE, &flags); clear_bit(LOCAL_LOOP_UPDATE, &flags); } else if (ha->current_topology == ISP_CFG_N) { clear_bit(RSCN_UPDATE, &flags); - } else if (!ha->flags.online || + } else if (!vha->flags.online || (test_bit(ABORT_ISP_ACTIVE, &flags))) { - ha->flags.rscn_queue_overflow = 1; + vha->flags.rscn_queue_overflow = 1; set_bit(RSCN_UPDATE, &flags); set_bit(LOCAL_LOOP_UPDATE, &flags); } if (test_bit(LOCAL_LOOP_UPDATE, &flags)) { - if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { + if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) rval = QLA_FUNCTION_FAILED; - } else { - rval = qla2x00_configure_local_loop(ha); - } + else + rval = qla2x00_configure_local_loop(vha); } if (rval == QLA_SUCCESS && test_bit(RSCN_UPDATE, &flags)) { - if (LOOP_TRANSITION(ha)) { + if (LOOP_TRANSITION(vha)) rval = QLA_FUNCTION_FAILED; - } else { - rval = qla2x00_configure_fabric(ha); - } + else + rval = qla2x00_configure_fabric(vha); } if (rval == QLA_SUCCESS) { - if (atomic_read(&ha->loop_down_timer) || - test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { + if (atomic_read(&vha->loop_down_timer) || + test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) { rval = QLA_FUNCTION_FAILED; } else { - atomic_set(&ha->loop_state, LOOP_READY); + atomic_set(&vha->loop_state, LOOP_READY); - DEBUG(printk("scsi(%ld): LOOP READY\n", ha->host_no)); + DEBUG(printk("scsi(%ld): LOOP READY\n", vha->host_no)); } } if (rval) { DEBUG2_3(printk("%s(%ld): *** FAILED ***\n", - __func__, ha->host_no)); + __func__, vha->host_no)); } else { DEBUG3(printk("%s: exiting normally\n", __func__)); } /* Restore state if a resync event occurred during processing */ - if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { + if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) { if (test_bit(LOCAL_LOOP_UPDATE, &save_flags)) - set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); - if (test_bit(RSCN_UPDATE, &save_flags)) { - ha->flags.rscn_queue_overflow = 1; - set_bit(RSCN_UPDATE, &ha->dpc_flags); - } + set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); + if (test_bit(RSCN_UPDATE, &save_flags)) + set_bit(RSCN_UPDATE, &vha->dpc_flags); } return (rval); @@ -2048,7 +2114,7 @@ qla2x00_configure_loop(scsi_qla_host_t *ha) * 0 = success. */ static int -qla2x00_configure_local_loop(scsi_qla_host_t *ha) +qla2x00_configure_local_loop(scsi_qla_host_t *vha) { int rval, rval2; int found_devs; @@ -2060,18 +2126,18 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) char *id_iter; uint16_t loop_id; uint8_t domain, area, al_pa; - scsi_qla_host_t *pha = to_qla_parent(ha); + struct qla_hw_data *ha = vha->hw; found_devs = 0; new_fcport = NULL; entries = MAX_FIBRE_DEVICES; - DEBUG3(printk("scsi(%ld): Getting FCAL position map\n", ha->host_no)); - DEBUG3(qla2x00_get_fcal_position_map(ha, NULL)); + DEBUG3(printk("scsi(%ld): Getting FCAL position map\n", vha->host_no)); + DEBUG3(qla2x00_get_fcal_position_map(vha, NULL)); /* Get list of logged in devices. */ memset(ha->gid_list, 0, GID_LIST_SIZE); - rval = qla2x00_get_id_list(ha, ha->gid_list, ha->gid_list_dma, + rval = qla2x00_get_id_list(vha, ha->gid_list, ha->gid_list_dma, &entries); if (rval != QLA_SUCCESS) goto cleanup_allocation; @@ -2082,7 +2148,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) entries * sizeof(struct gid_list_info))); /* Allocate temporary fcport for any new fcports discovered. */ - new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL); + new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); if (new_fcport == NULL) { rval = QLA_MEMORY_ALLOC_FAILED; goto cleanup_allocation; @@ -2092,17 +2158,14 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) /* * Mark local devices that were present with FCF_DEVICE_LOST for now. */ - list_for_each_entry(fcport, &pha->fcports, list) { - if (fcport->vp_idx != ha->vp_idx) - continue; - + list_for_each_entry(fcport, &vha->vp_fcports, list) { if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->port_type != FCT_BROADCAST && (fcport->flags & FCF_FABRIC_DEVICE) == 0) { DEBUG(printk("scsi(%ld): Marking port lost, " "loop_id=0x%04x\n", - ha->host_no, fcport->loop_id)); + vha->host_no, fcport->loop_id)); atomic_set(&fcport->state, FCS_DEVICE_LOST); fcport->flags &= ~FCF_FARP_DONE; @@ -2129,7 +2192,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) /* Bypass if not same domain and area of adapter. */ if (area && domain && - (area != ha->d_id.b.area || domain != ha->d_id.b.domain)) + (area != vha->d_id.b.area || domain != vha->d_id.b.domain)) continue; /* Bypass invalid local loop ID. */ @@ -2141,26 +2204,23 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) new_fcport->d_id.b.area = area; new_fcport->d_id.b.al_pa = al_pa; new_fcport->loop_id = loop_id; - new_fcport->vp_idx = ha->vp_idx; - rval2 = qla2x00_get_port_database(ha, new_fcport, 0); + new_fcport->vp_idx = vha->vp_idx; + rval2 = qla2x00_get_port_database(vha, new_fcport, 0); if (rval2 != QLA_SUCCESS) { DEBUG2(printk("scsi(%ld): Failed to retrieve fcport " "information -- get_port_database=%x, " "loop_id=0x%04x\n", - ha->host_no, rval2, new_fcport->loop_id)); + vha->host_no, rval2, new_fcport->loop_id)); DEBUG2(printk("scsi(%ld): Scheduling resync...\n", - ha->host_no)); - set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + vha->host_no)); + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); continue; } /* Check for matching device in port list. */ found = 0; fcport = NULL; - list_for_each_entry(fcport, &pha->fcports, list) { - if (fcport->vp_idx != ha->vp_idx) - continue; - + list_for_each_entry(fcport, &vha->vp_fcports, list) { if (memcmp(new_fcport->port_name, fcport->port_name, WWN_SIZE)) continue; @@ -2180,17 +2240,15 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) if (!found) { /* New device, add to fcports list. */ new_fcport->flags &= ~FCF_PERSISTENT_BOUND; - if (ha->parent) { - new_fcport->ha = ha; - new_fcport->vp_idx = ha->vp_idx; - list_add_tail(&new_fcport->vp_fcport, - &ha->vp_fcports); + if (vha->vp_idx) { + new_fcport->vha = vha; + new_fcport->vp_idx = vha->vp_idx; } - list_add_tail(&new_fcport->list, &pha->fcports); + list_add_tail(&new_fcport->list, &vha->vp_fcports); /* Allocate a new replacement fcport. */ fcport = new_fcport; - new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL); + new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); if (new_fcport == NULL) { rval = QLA_MEMORY_ALLOC_FAILED; goto cleanup_allocation; @@ -2201,7 +2259,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) /* Base iIDMA settings on HBA port speed. */ fcport->fp_speed = ha->link_data_rate; - qla2x00_update_fcport(ha, fcport); + qla2x00_update_fcport(vha, fcport); found_devs++; } @@ -2211,24 +2269,25 @@ cleanup_allocation: if (rval != QLA_SUCCESS) { DEBUG2(printk("scsi(%ld): Configure local loop error exit: " - "rval=%x\n", ha->host_no, rval)); + "rval=%x\n", vha->host_no, rval)); } if (found_devs) { - ha->device_flags |= DFLG_LOCAL_DEVICES; - ha->device_flags &= ~DFLG_RETRY_LOCAL_DEVICES; + vha->device_flags |= DFLG_LOCAL_DEVICES; + vha->device_flags &= ~DFLG_RETRY_LOCAL_DEVICES; } return (rval); } static void -qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) +qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) { #define LS_UNKNOWN 2 static char *link_speeds[5] = { "1", "2", "?", "4", "8" }; int rval; uint16_t mb[6]; + struct qla_hw_data *ha = vha->hw; if (!IS_IIDMA_CAPABLE(ha)) return; @@ -2237,12 +2296,12 @@ qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) fcport->fp_speed > ha->link_data_rate) return; - rval = qla2x00_set_idma_speed(ha, fcport->loop_id, fcport->fp_speed, + rval = qla2x00_set_idma_speed(vha, fcport->loop_id, fcport->fp_speed, mb); if (rval != QLA_SUCCESS) { DEBUG2(printk("scsi(%ld): Unable to adjust iIDMA " "%02x%02x%02x%02x%02x%02x%02x%02x -- %04x %x %04x %04x.\n", - ha->host_no, fcport->port_name[0], fcport->port_name[1], + vha->host_no, fcport->port_name[0], fcport->port_name[1], fcport->port_name[2], fcport->port_name[3], fcport->port_name[4], fcport->port_name[5], fcport->port_name[6], fcport->port_name[7], rval, @@ -2260,10 +2319,11 @@ qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) } static void -qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport) +qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport) { struct fc_rport_identifiers rport_ids; struct fc_rport *rport; + struct qla_hw_data *ha = vha->hw; if (fcport->drport) qla2x00_rport_del(fcport); @@ -2273,15 +2333,15 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport) rport_ids.port_id = fcport->d_id.b.domain << 16 | fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa; rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; - fcport->rport = rport = fc_remote_port_add(ha->host, 0, &rport_ids); + fcport->rport = rport = fc_remote_port_add(vha->host, 0, &rport_ids); if (!rport) { qla_printk(KERN_WARNING, ha, "Unable to allocate fc remote port!\n"); return; } - spin_lock_irq(fcport->ha->host->host_lock); + spin_lock_irq(fcport->vha->host->host_lock); *((fc_port_t **)rport->dd_data) = fcport; - spin_unlock_irq(fcport->ha->host->host_lock); + spin_unlock_irq(fcport->vha->host->host_lock); rport->supported_classes = fcport->supported_classes; @@ -2309,23 +2369,23 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport) * Kernel context. */ void -qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) +qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) { - scsi_qla_host_t *pha = to_qla_parent(ha); + struct qla_hw_data *ha = vha->hw; - fcport->ha = ha; + fcport->vha = vha; fcport->login_retry = 0; - fcport->port_login_retry_count = pha->port_down_retry_count * + fcport->port_login_retry_count = ha->port_down_retry_count * PORT_RETRY_TIME; - atomic_set(&fcport->port_down_timer, pha->port_down_retry_count * + atomic_set(&fcport->port_down_timer, ha->port_down_retry_count * PORT_RETRY_TIME); fcport->flags &= ~FCF_LOGIN_NEEDED; - qla2x00_iidma_fcport(ha, fcport); + qla2x00_iidma_fcport(vha, fcport); atomic_set(&fcport->state, FCS_ONLINE); - qla2x00_reg_remote_port(ha, fcport); + qla2x00_reg_remote_port(vha, fcport); } /* @@ -2340,7 +2400,7 @@ qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) * BIT_0 = error */ static int -qla2x00_configure_fabric(scsi_qla_host_t *ha) +qla2x00_configure_fabric(scsi_qla_host_t *vha) { int rval, rval2; fc_port_t *fcport, *fcptemp; @@ -2348,25 +2408,26 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) uint16_t mb[MAILBOX_REGISTER_COUNT]; uint16_t loop_id; LIST_HEAD(new_fcports); - scsi_qla_host_t *pha = to_qla_parent(ha); + struct qla_hw_data *ha = vha->hw; + struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); /* If FL port exists, then SNS is present */ if (IS_FWI2_CAPABLE(ha)) loop_id = NPH_F_PORT; else loop_id = SNS_FL_PORT; - rval = qla2x00_get_port_name(ha, loop_id, ha->fabric_node_name, 1); + rval = qla2x00_get_port_name(vha, loop_id, vha->fabric_node_name, 1); if (rval != QLA_SUCCESS) { DEBUG2(printk("scsi(%ld): MBC_GET_PORT_NAME Failed, No FL " - "Port\n", ha->host_no)); + "Port\n", vha->host_no)); - ha->device_flags &= ~SWITCH_FOUND; + vha->device_flags &= ~SWITCH_FOUND; return (QLA_SUCCESS); } - ha->device_flags |= SWITCH_FOUND; + vha->device_flags |= SWITCH_FOUND; /* Mark devices that need re-synchronization. */ - rval2 = qla2x00_device_resync(ha); + rval2 = qla2x00_device_resync(vha); if (rval2 == QLA_RSCNS_HANDLED) { /* No point doing the scan, just continue. */ return (QLA_SUCCESS); @@ -2374,15 +2435,15 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) do { /* FDMI support. */ if (ql2xfdmienable && - test_and_clear_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags)) - qla2x00_fdmi_register(ha); + test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags)) + qla2x00_fdmi_register(vha); /* Ensure we are logged into the SNS. */ if (IS_FWI2_CAPABLE(ha)) loop_id = NPH_SNS; else loop_id = SIMPLE_NAME_SERVER; - ha->isp_ops->fabric_login(ha, loop_id, 0xff, 0xff, + ha->isp_ops->fabric_login(vha, loop_id, 0xff, 0xff, 0xfc, mb, BIT_1 | BIT_0); if (mb[0] != MBS_COMMAND_COMPLETE) { DEBUG2(qla_printk(KERN_INFO, ha, @@ -2392,29 +2453,29 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) return (QLA_SUCCESS); } - if (test_and_clear_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags)) { - if (qla2x00_rft_id(ha)) { + if (test_and_clear_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags)) { + if (qla2x00_rft_id(vha)) { /* EMPTY */ DEBUG2(printk("scsi(%ld): Register FC-4 " - "TYPE failed.\n", ha->host_no)); + "TYPE failed.\n", vha->host_no)); } - if (qla2x00_rff_id(ha)) { + if (qla2x00_rff_id(vha)) { /* EMPTY */ DEBUG2(printk("scsi(%ld): Register FC-4 " - "Features failed.\n", ha->host_no)); + "Features failed.\n", vha->host_no)); } - if (qla2x00_rnn_id(ha)) { + if (qla2x00_rnn_id(vha)) { /* EMPTY */ DEBUG2(printk("scsi(%ld): Register Node Name " - "failed.\n", ha->host_no)); - } else if (qla2x00_rsnn_nn(ha)) { + "failed.\n", vha->host_no)); + } else if (qla2x00_rsnn_nn(vha)) { /* EMPTY */ DEBUG2(printk("scsi(%ld): Register Symbolic " - "Node Name failed.\n", ha->host_no)); + "Node Name failed.\n", vha->host_no)); } } - rval = qla2x00_find_all_fabric_devs(ha, &new_fcports); + rval = qla2x00_find_all_fabric_devs(vha, &new_fcports); if (rval != QLA_SUCCESS) break; @@ -2422,24 +2483,21 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) * Logout all previous fabric devices marked lost, except * tape devices. */ - list_for_each_entry(fcport, &pha->fcports, list) { - if (fcport->vp_idx !=ha->vp_idx) - continue; - - if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) + list_for_each_entry(fcport, &vha->vp_fcports, list) { + if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) break; if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) continue; if (atomic_read(&fcport->state) == FCS_DEVICE_LOST) { - qla2x00_mark_device_lost(ha, fcport, + qla2x00_mark_device_lost(vha, fcport, ql2xplogiabsentdevice, 0); if (fcport->loop_id != FC_NO_LOOP_ID && (fcport->flags & FCF_TAPE_PRESENT) == 0 && fcport->port_type != FCT_INITIATOR && fcport->port_type != FCT_BROADCAST) { - ha->isp_ops->fabric_logout(ha, + ha->isp_ops->fabric_logout(vha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, @@ -2450,18 +2508,15 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) } /* Starting free loop ID. */ - next_loopid = pha->min_external_loopid; + next_loopid = ha->min_external_loopid; /* * Scan through our port list and login entries that need to be * logged in. */ - list_for_each_entry(fcport, &pha->fcports, list) { - if (fcport->vp_idx != ha->vp_idx) - continue; - - if (atomic_read(&ha->loop_down_timer) || - test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) + list_for_each_entry(fcport, &vha->vp_fcports, list) { + if (atomic_read(&vha->loop_down_timer) || + test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) break; if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || @@ -2471,14 +2526,14 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) if (fcport->loop_id == FC_NO_LOOP_ID) { fcport->loop_id = next_loopid; rval = qla2x00_find_new_loop_id( - to_qla_parent(ha), fcport); + base_vha, fcport); if (rval != QLA_SUCCESS) { /* Ran out of IDs to use */ break; } } /* Login and update database */ - qla2x00_fabric_dev_login(ha, fcport, &next_loopid); + qla2x00_fabric_dev_login(vha, fcport, &next_loopid); } /* Exit if out of loop IDs. */ @@ -2490,31 +2545,26 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) * Login and add the new devices to our port list. */ list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) { - if (atomic_read(&ha->loop_down_timer) || - test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) + if (atomic_read(&vha->loop_down_timer) || + test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) break; /* Find a new loop ID to use. */ fcport->loop_id = next_loopid; - rval = qla2x00_find_new_loop_id(to_qla_parent(ha), - fcport); + rval = qla2x00_find_new_loop_id(base_vha, fcport); if (rval != QLA_SUCCESS) { /* Ran out of IDs to use */ break; } /* Login and update database */ - qla2x00_fabric_dev_login(ha, fcport, &next_loopid); - - if (ha->parent) { - fcport->ha = ha; - fcport->vp_idx = ha->vp_idx; - list_add_tail(&fcport->vp_fcport, - &ha->vp_fcports); - list_move_tail(&fcport->list, - &ha->parent->fcports); - } else - list_move_tail(&fcport->list, &ha->fcports); + qla2x00_fabric_dev_login(vha, fcport, &next_loopid); + + if (vha->vp_idx) { + fcport->vha = vha; + fcport->vp_idx = vha->vp_idx; + } + list_move_tail(&fcport->list, &vha->vp_fcports); } } while (0); @@ -2526,7 +2576,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) if (rval) { DEBUG2(printk("scsi(%ld): Configure fabric error exit: " - "rval=%d\n", ha->host_no, rval)); + "rval=%d\n", vha->host_no, rval)); } return (rval); @@ -2547,7 +2597,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) * Kernel context. */ static int -qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) +qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, + struct list_head *new_fcports) { int rval; uint16_t loop_id; @@ -2558,11 +2609,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) int swl_idx; int first_dev, last_dev; port_id_t wrap, nxt_d_id; - int vp_index; - int empty_vp_index; - int found_vp; - scsi_qla_host_t *vha; - scsi_qla_host_t *pha = to_qla_parent(ha); + struct qla_hw_data *ha = vha->hw; + struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); rval = QLA_SUCCESS; @@ -2571,43 +2619,42 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) if (!swl) { /*EMPTY*/ DEBUG2(printk("scsi(%ld): GID_PT allocations failed, fallback " - "on GA_NXT\n", ha->host_no)); + "on GA_NXT\n", vha->host_no)); } else { - if (qla2x00_gid_pt(ha, swl) != QLA_SUCCESS) { + if (qla2x00_gid_pt(vha, swl) != QLA_SUCCESS) { kfree(swl); swl = NULL; - } else if (qla2x00_gpn_id(ha, swl) != QLA_SUCCESS) { + } else if (qla2x00_gpn_id(vha, swl) != QLA_SUCCESS) { kfree(swl); swl = NULL; - } else if (qla2x00_gnn_id(ha, swl) != QLA_SUCCESS) { + } else if (qla2x00_gnn_id(vha, swl) != QLA_SUCCESS) { kfree(swl); swl = NULL; } else if (ql2xiidmaenable && - qla2x00_gfpn_id(ha, swl) == QLA_SUCCESS) { - qla2x00_gpsc(ha, swl); + qla2x00_gfpn_id(vha, swl) == QLA_SUCCESS) { + qla2x00_gpsc(vha, swl); } } swl_idx = 0; /* Allocate temporary fcport for any new fcports discovered. */ - new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL); + new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); if (new_fcport == NULL) { kfree(swl); return (QLA_MEMORY_ALLOC_FAILED); } new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED); - new_fcport->vp_idx = ha->vp_idx; /* Set start port ID scan at adapter ID. */ first_dev = 1; last_dev = 0; /* Starting free loop ID. */ - loop_id = pha->min_external_loopid; - for (; loop_id <= ha->last_loop_id; loop_id++) { - if (qla2x00_is_reserved_id(ha, loop_id)) + loop_id = ha->min_external_loopid; + for (; loop_id <= ha->max_loop_id; loop_id++) { + if (qla2x00_is_reserved_id(vha, loop_id)) continue; - if (atomic_read(&ha->loop_down_timer) || LOOP_TRANSITION(ha)) + if (atomic_read(&vha->loop_down_timer) || LOOP_TRANSITION(vha)) break; if (swl != NULL) { @@ -2630,7 +2677,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) } } else { /* Send GA_NXT to the switch */ - rval = qla2x00_ga_nxt(ha, new_fcport); + rval = qla2x00_ga_nxt(vha, new_fcport); if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "SNS scan failed -- assuming zero-entry " @@ -2651,44 +2698,31 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) first_dev = 0; } else if (new_fcport->d_id.b24 == wrap.b24) { DEBUG2(printk("scsi(%ld): device wrap (%02x%02x%02x)\n", - ha->host_no, new_fcport->d_id.b.domain, + vha->host_no, new_fcport->d_id.b.domain, new_fcport->d_id.b.area, new_fcport->d_id.b.al_pa)); break; } /* Bypass if same physical adapter. */ - if (new_fcport->d_id.b24 == pha->d_id.b24) + if (new_fcport->d_id.b24 == base_vha->d_id.b24) continue; /* Bypass virtual ports of the same host. */ - if (pha->num_vhosts) { - for_each_mapped_vp_idx(pha, vp_index) { - empty_vp_index = 1; - found_vp = 0; - list_for_each_entry(vha, &pha->vp_list, - vp_list) { - if (vp_index == vha->vp_idx) { - empty_vp_index = 0; - found_vp = 1; - break; - } - } - - if (empty_vp_index) - continue; - - if (found_vp && - new_fcport->d_id.b24 == vha->d_id.b24) + found = 0; + if (ha->num_vhosts) { + list_for_each_entry(vp, &ha->vp_list, list) { + if (new_fcport->d_id.b24 == vp->d_id.b24) { + found = 1; break; + } } - - if (vp_index <= pha->max_npiv_vports) + if (found) continue; } /* Bypass if same domain and area of adapter. */ if (((new_fcport->d_id.b24 & 0xffff00) == - (ha->d_id.b24 & 0xffff00)) && ha->current_topology == + (vha->d_id.b24 & 0xffff00)) && ha->current_topology == ISP_CFG_FL) continue; @@ -2698,9 +2732,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) /* Locate matching device in database. */ found = 0; - list_for_each_entry(fcport, &pha->fcports, list) { - if (new_fcport->vp_idx != fcport->vp_idx) - continue; + list_for_each_entry(fcport, &vha->vp_fcports, list) { if (memcmp(new_fcport->port_name, fcport->port_name, WWN_SIZE)) continue; @@ -2744,7 +2776,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) (fcport->flags & FCF_TAPE_PRESENT) == 0 && fcport->port_type != FCT_INITIATOR && fcport->port_type != FCT_BROADCAST) { - ha->isp_ops->fabric_logout(ha, fcport->loop_id, + ha->isp_ops->fabric_logout(vha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); fcport->loop_id = FC_NO_LOOP_ID; @@ -2755,27 +2787,25 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) if (found) continue; - /* If device was not in our fcports list, then add it. */ list_add_tail(&new_fcport->list, new_fcports); /* Allocate a new replacement fcport. */ nxt_d_id.b24 = new_fcport->d_id.b24; - new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL); + new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); if (new_fcport == NULL) { kfree(swl); return (QLA_MEMORY_ALLOC_FAILED); } new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED); new_fcport->d_id.b24 = nxt_d_id.b24; - new_fcport->vp_idx = ha->vp_idx; } kfree(swl); kfree(new_fcport); if (!list_empty(new_fcports)) - ha->device_flags |= DFLG_FABRIC_DEVICES; + vha->device_flags |= DFLG_FABRIC_DEVICES; return (rval); } @@ -2795,13 +2825,14 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) * Kernel context. */ static int -qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev) +qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) { int rval; int found; fc_port_t *fcport; uint16_t first_loop_id; - scsi_qla_host_t *pha = to_qla_parent(ha); + struct qla_hw_data *ha = vha->hw; + struct scsi_qla_host *vp; rval = QLA_SUCCESS; @@ -2810,17 +2841,15 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev) for (;;) { /* Skip loop ID if already used by adapter. */ - if (dev->loop_id == ha->loop_id) { + if (dev->loop_id == vha->loop_id) dev->loop_id++; - } /* Skip reserved loop IDs. */ - while (qla2x00_is_reserved_id(ha, dev->loop_id)) { + while (qla2x00_is_reserved_id(vha, dev->loop_id)) dev->loop_id++; - } /* Reset loop ID if passed the end. */ - if (dev->loop_id > ha->last_loop_id) { + if (dev->loop_id > ha->max_loop_id) { /* first loop ID. */ dev->loop_id = ha->min_external_loopid; } @@ -2828,12 +2857,17 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev) /* Check for loop ID being already in use. */ found = 0; fcport = NULL; - list_for_each_entry(fcport, &pha->fcports, list) { - if (fcport->loop_id == dev->loop_id && fcport != dev) { - /* ID possibly in use */ - found++; - break; + list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry(fcport, &vp->vp_fcports, list) { + if (fcport->loop_id == dev->loop_id && + fcport != dev) { + /* ID possibly in use */ + found++; + break; + } } + if (found) + break; } /* If not in use then it is free to use. */ @@ -2866,7 +2900,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev) * Kernel context. */ static int -qla2x00_device_resync(scsi_qla_host_t *ha) +qla2x00_device_resync(scsi_qla_host_t *vha) { int rval; uint32_t mask; @@ -2875,14 +2909,13 @@ qla2x00_device_resync(scsi_qla_host_t *ha) uint8_t rscn_out_iter; uint8_t format; port_id_t d_id; - scsi_qla_host_t *pha = to_qla_parent(ha); rval = QLA_RSCNS_HANDLED; - while (ha->rscn_out_ptr != ha->rscn_in_ptr || - ha->flags.rscn_queue_overflow) { + while (vha->rscn_out_ptr != vha->rscn_in_ptr || + vha->flags.rscn_queue_overflow) { - rscn_entry = ha->rscn_queue[ha->rscn_out_ptr]; + rscn_entry = vha->rscn_queue[vha->rscn_out_ptr]; format = MSB(MSW(rscn_entry)); d_id.b.domain = LSB(MSW(rscn_entry)); d_id.b.area = MSB(LSW(rscn_entry)); @@ -2890,37 +2923,37 @@ qla2x00_device_resync(scsi_qla_host_t *ha) DEBUG(printk("scsi(%ld): RSCN queue entry[%d] = " "[%02x/%02x%02x%02x].\n", - ha->host_no, ha->rscn_out_ptr, format, d_id.b.domain, + vha->host_no, vha->rscn_out_ptr, format, d_id.b.domain, d_id.b.area, d_id.b.al_pa)); - ha->rscn_out_ptr++; - if (ha->rscn_out_ptr == MAX_RSCN_COUNT) - ha->rscn_out_ptr = 0; + vha->rscn_out_ptr++; + if (vha->rscn_out_ptr == MAX_RSCN_COUNT) + vha->rscn_out_ptr = 0; /* Skip duplicate entries. */ - for (rscn_out_iter = ha->rscn_out_ptr; - !ha->flags.rscn_queue_overflow && - rscn_out_iter != ha->rscn_in_ptr; + for (rscn_out_iter = vha->rscn_out_ptr; + !vha->flags.rscn_queue_overflow && + rscn_out_iter != vha->rscn_in_ptr; rscn_out_iter = (rscn_out_iter == (MAX_RSCN_COUNT - 1)) ? 0: rscn_out_iter + 1) { - if (rscn_entry != ha->rscn_queue[rscn_out_iter]) + if (rscn_entry != vha->rscn_queue[rscn_out_iter]) break; DEBUG(printk("scsi(%ld): Skipping duplicate RSCN queue " - "entry found at [%d].\n", ha->host_no, + "entry found at [%d].\n", vha->host_no, rscn_out_iter)); - ha->rscn_out_ptr = rscn_out_iter; + vha->rscn_out_ptr = rscn_out_iter; } /* Queue overflow, set switch default case. */ - if (ha->flags.rscn_queue_overflow) { + if (vha->flags.rscn_queue_overflow) { DEBUG(printk("scsi(%ld): device_resync: rscn " - "overflow.\n", ha->host_no)); + "overflow.\n", vha->host_no)); format = 3; - ha->flags.rscn_queue_overflow = 0; + vha->flags.rscn_queue_overflow = 0; } switch (format) { @@ -2936,16 +2969,13 @@ qla2x00_device_resync(scsi_qla_host_t *ha) default: mask = 0x0; d_id.b24 = 0; - ha->rscn_out_ptr = ha->rscn_in_ptr; + vha->rscn_out_ptr = vha->rscn_in_ptr; break; } rval = QLA_SUCCESS; - list_for_each_entry(fcport, &pha->fcports, list) { - if (fcport->vp_idx != ha->vp_idx) - continue; - + list_for_each_entry(fcport, &vha->vp_fcports, list) { if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || (fcport->d_id.b24 & mask) != d_id.b24 || fcport->port_type == FCT_BROADCAST) @@ -2954,7 +2984,7 @@ qla2x00_device_resync(scsi_qla_host_t *ha) if (atomic_read(&fcport->state) == FCS_ONLINE) { if (format != 3 || fcport->port_type != FCT_INITIATOR) { - qla2x00_mark_device_lost(ha, fcport, + qla2x00_mark_device_lost(vha, fcport, 0, 0); } } @@ -2981,30 +3011,31 @@ qla2x00_device_resync(scsi_qla_host_t *ha) * Kernel context. */ static int -qla2x00_fabric_dev_login(scsi_qla_host_t *ha, fc_port_t *fcport, +qla2x00_fabric_dev_login(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t *next_loopid) { int rval; int retry; uint8_t opts; + struct qla_hw_data *ha = vha->hw; rval = QLA_SUCCESS; retry = 0; - rval = qla2x00_fabric_login(ha, fcport, next_loopid); + rval = qla2x00_fabric_login(vha, fcport, next_loopid); if (rval == QLA_SUCCESS) { /* Send an ADISC to tape devices.*/ opts = 0; if (fcport->flags & FCF_TAPE_PRESENT) opts |= BIT_1; - rval = qla2x00_get_port_database(ha, fcport, opts); + rval = qla2x00_get_port_database(vha, fcport, opts); if (rval != QLA_SUCCESS) { - ha->isp_ops->fabric_logout(ha, fcport->loop_id, + ha->isp_ops->fabric_logout(vha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); - qla2x00_mark_device_lost(ha, fcport, 1, 0); + qla2x00_mark_device_lost(vha, fcport, 1, 0); } else { - qla2x00_update_fcport(ha, fcport); + qla2x00_update_fcport(vha, fcport); } } @@ -3026,13 +3057,14 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *ha, fc_port_t *fcport, * 3 - Fatal error */ int -qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, +qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t *next_loopid) { int rval; int retry; uint16_t tmp_loopid; uint16_t mb[MAILBOX_REGISTER_COUNT]; + struct qla_hw_data *ha = vha->hw; retry = 0; tmp_loopid = 0; @@ -3040,11 +3072,11 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, for (;;) { DEBUG(printk("scsi(%ld): Trying Fabric Login w/loop id 0x%04x " "for port %02x%02x%02x.\n", - ha->host_no, fcport->loop_id, fcport->d_id.b.domain, + vha->host_no, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa)); /* Login fcport on switch. */ - ha->isp_ops->fabric_login(ha, fcport->loop_id, + ha->isp_ops->fabric_login(vha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa, mb, BIT_0); if (mb[0] == MBS_PORT_ID_USED) { @@ -3100,7 +3132,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, * Loop ID already used, try next loop ID. */ fcport->loop_id++; - rval = qla2x00_find_new_loop_id(ha, fcport); + rval = qla2x00_find_new_loop_id(vha, fcport); if (rval != QLA_SUCCESS) { /* Ran out of loop IDs to use */ break; @@ -3112,10 +3144,10 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, * dead. */ *next_loopid = fcport->loop_id; - ha->isp_ops->fabric_logout(ha, fcport->loop_id, + ha->isp_ops->fabric_logout(vha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); - qla2x00_mark_device_lost(ha, fcport, 1, 0); + qla2x00_mark_device_lost(vha, fcport, 1, 0); rval = 1; break; @@ -3125,12 +3157,12 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, */ DEBUG2(printk("%s(%ld): failed=%x port_id=%02x%02x%02x " "loop_id=%x jiffies=%lx.\n", - __func__, ha->host_no, mb[0], + __func__, vha->host_no, mb[0], fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa, fcport->loop_id, jiffies)); *next_loopid = fcport->loop_id; - ha->isp_ops->fabric_logout(ha, fcport->loop_id, + ha->isp_ops->fabric_logout(vha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); fcport->loop_id = FC_NO_LOOP_ID; @@ -3158,13 +3190,13 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, * 3 - Fatal error */ int -qla2x00_local_device_login(scsi_qla_host_t *ha, fc_port_t *fcport) +qla2x00_local_device_login(scsi_qla_host_t *vha, fc_port_t *fcport) { int rval; uint16_t mb[MAILBOX_REGISTER_COUNT]; memset(mb, 0, sizeof(mb)); - rval = qla2x00_login_local_device(ha, fcport, mb, BIT_0); + rval = qla2x00_login_local_device(vha, fcport, mb, BIT_0); if (rval == QLA_SUCCESS) { /* Interrogate mailbox registers for any errors */ if (mb[0] == MBS_COMMAND_ERROR) @@ -3188,57 +3220,57 @@ qla2x00_local_device_login(scsi_qla_host_t *ha, fc_port_t *fcport) * 0 = success */ int -qla2x00_loop_resync(scsi_qla_host_t *ha) +qla2x00_loop_resync(scsi_qla_host_t *vha) { - int rval; + int rval = QLA_SUCCESS; uint32_t wait_time; - - rval = QLA_SUCCESS; - - atomic_set(&ha->loop_state, LOOP_UPDATE); - clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); - if (ha->flags.online) { - if (!(rval = qla2x00_fw_ready(ha))) { + struct qla_hw_data *ha = vha->hw; + struct req_que *req = ha->req_q_map[vha->req_ques[0]]; + struct rsp_que *rsp = req->rsp; + + atomic_set(&vha->loop_state, LOOP_UPDATE); + clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags); + if (vha->flags.online) { + if (!(rval = qla2x00_fw_ready(vha))) { /* Wait at most MAX_TARGET RSCNs for a stable link. */ wait_time = 256; do { - atomic_set(&ha->loop_state, LOOP_UPDATE); + atomic_set(&vha->loop_state, LOOP_UPDATE); /* Issue a marker after FW becomes ready. */ - qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); - ha->marker_needed = 0; + qla2x00_marker(vha, req, rsp, 0, 0, + MK_SYNC_ALL); + vha->marker_needed = 0; /* Remap devices on Loop. */ - clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); - qla2x00_configure_loop(ha); + qla2x00_configure_loop(vha); wait_time--; - } while (!atomic_read(&ha->loop_down_timer) && - !(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) && - wait_time && - (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))); + } while (!atomic_read(&vha->loop_down_timer) && + !(test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) + && wait_time && (test_bit(LOOP_RESYNC_NEEDED, + &vha->dpc_flags))); } } - if (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) { + if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) return (QLA_FUNCTION_FAILED); - } - if (rval) { + if (rval) DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__)); - } return (rval); } void -qla2x00_update_fcports(scsi_qla_host_t *ha) +qla2x00_update_fcports(scsi_qla_host_t *vha) { fc_port_t *fcport; /* Go with deferred removal of rport references. */ - list_for_each_entry(fcport, &ha->fcports, list) - if (fcport->drport && + list_for_each_entry(fcport, &vha->vp_fcports, list) + if (fcport && fcport->drport && atomic_read(&fcport->state) != FCS_UNCONFIGURED) qla2x00_rport_del(fcport); } @@ -3254,63 +3286,65 @@ qla2x00_update_fcports(scsi_qla_host_t *ha) * 0 = success */ int -qla2x00_abort_isp(scsi_qla_host_t *ha) +qla2x00_abort_isp(scsi_qla_host_t *vha) { int rval; uint8_t status = 0; - scsi_qla_host_t *vha; + struct qla_hw_data *ha = vha->hw; + struct scsi_qla_host *vp; + struct req_que *req = ha->req_q_map[0]; - if (ha->flags.online) { - ha->flags.online = 0; - clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + if (vha->flags.online) { + vha->flags.online = 0; + clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); ha->qla_stats.total_isp_aborts++; qla_printk(KERN_INFO, ha, "Performing ISP error recovery - ha= %p.\n", ha); - ha->isp_ops->reset_chip(ha); - - atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); - if (atomic_read(&ha->loop_state) != LOOP_DOWN) { - atomic_set(&ha->loop_state, LOOP_DOWN); - qla2x00_mark_all_devices_lost(ha, 0); - list_for_each_entry(vha, &ha->vp_list, vp_list) - qla2x00_mark_all_devices_lost(vha, 0); + ha->isp_ops->reset_chip(vha); + + atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); + if (atomic_read(&vha->loop_state) != LOOP_DOWN) { + atomic_set(&vha->loop_state, LOOP_DOWN); + qla2x00_mark_all_devices_lost(vha, 0); + list_for_each_entry(vp, &ha->vp_list, list) + qla2x00_mark_all_devices_lost(vp, 0); } else { - if (!atomic_read(&ha->loop_down_timer)) - atomic_set(&ha->loop_down_timer, + if (!atomic_read(&vha->loop_down_timer)) + atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); } /* Requeue all commands in outstanding command list. */ - qla2x00_abort_all_cmds(ha, DID_RESET << 16); + qla2x00_abort_all_cmds(vha, DID_RESET << 16); - ha->isp_ops->get_flash_version(ha, ha->request_ring); + ha->isp_ops->get_flash_version(vha, req->ring); - ha->isp_ops->nvram_config(ha); + ha->isp_ops->nvram_config(vha); - if (!qla2x00_restart_isp(ha)) { - clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); + if (!qla2x00_restart_isp(vha)) { + clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags); - if (!atomic_read(&ha->loop_down_timer)) { + if (!atomic_read(&vha->loop_down_timer)) { /* * Issue marker command only when we are going * to start the I/O . */ - ha->marker_needed = 1; + vha->marker_needed = 1; } - ha->flags.online = 1; + vha->flags.online = 1; ha->isp_ops->enable_intrs(ha); ha->isp_abort_cnt = 0; - clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); + clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags); if (ha->fce) { ha->flags.fce_enabled = 1; memset(ha->fce, 0, fce_calc_size(ha->fce_bufs)); - rval = qla2x00_enable_fce_trace(ha, + rval = qla2x00_enable_fce_trace(vha, ha->fce_dma, ha->fce_bufs, ha->fce_mb, &ha->fce_bufs); if (rval) { @@ -3323,7 +3357,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) if (ha->eft) { memset(ha->eft, 0, EFT_SIZE); - rval = qla2x00_enable_eft_trace(ha, + rval = qla2x00_enable_eft_trace(vha, ha->eft_dma, EFT_NUM_BUFFERS); if (rval) { qla_printk(KERN_WARNING, ha, @@ -3332,8 +3366,8 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) } } } else { /* failed the ISP abort */ - ha->flags.online = 1; - if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) { + vha->flags.online = 1; + if (test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { if (ha->isp_abort_cnt == 0) { qla_printk(KERN_WARNING, ha, "ISP error recovery failed - " @@ -3342,37 +3376,41 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) * The next call disables the board * completely. */ - ha->isp_ops->reset_adapter(ha); - ha->flags.online = 0; + ha->isp_ops->reset_adapter(vha); + vha->flags.online = 0; clear_bit(ISP_ABORT_RETRY, - &ha->dpc_flags); + &vha->dpc_flags); status = 0; } else { /* schedule another ISP abort */ ha->isp_abort_cnt--; DEBUG(printk("qla%ld: ISP abort - " "retry remaining %d\n", - ha->host_no, ha->isp_abort_cnt)); + vha->host_no, ha->isp_abort_cnt)); status = 1; } } else { ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT; DEBUG(printk("qla2x00(%ld): ISP error recovery " "- retrying (%d) more times\n", - ha->host_no, ha->isp_abort_cnt)); - set_bit(ISP_ABORT_RETRY, &ha->dpc_flags); + vha->host_no, ha->isp_abort_cnt)); + set_bit(ISP_ABORT_RETRY, &vha->dpc_flags); status = 1; } } } - if (status) { + if (!status) { + DEBUG(printk(KERN_INFO + "qla2x00_abort_isp(%ld): succeeded.\n", + vha->host_no)); + list_for_each_entry(vp, &ha->vp_list, list) { + if (vp->vp_idx) + qla2x00_vp_abort_isp(vp); + } + } else { qla_printk(KERN_INFO, ha, "qla2x00_abort_isp: **** FAILED ****\n"); - } else { - DEBUG(printk(KERN_INFO - "qla2x00_abort_isp(%ld): exiting.\n", - ha->host_no)); } return(status); @@ -3389,42 +3427,50 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) * 0 = success */ static int -qla2x00_restart_isp(scsi_qla_host_t *ha) +qla2x00_restart_isp(scsi_qla_host_t *vha) { uint8_t status = 0; uint32_t wait_time; + struct qla_hw_data *ha = vha->hw; + struct req_que *req = ha->req_q_map[0]; + struct rsp_que *rsp = ha->rsp_q_map[0]; /* If firmware needs to be loaded */ - if (qla2x00_isp_firmware(ha)) { - ha->flags.online = 0; - if (!(status = ha->isp_ops->chip_diag(ha))) - status = qla2x00_setup_chip(ha); + if (qla2x00_isp_firmware(vha)) { + vha->flags.online = 0; + status = ha->isp_ops->chip_diag(vha); + if (!status) + status = qla2x00_setup_chip(vha); } - if (!status && !(status = qla2x00_init_rings(ha))) { - clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); - if (!(status = qla2x00_fw_ready(ha))) { + if (!status && !(status = qla2x00_init_rings(vha))) { + clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags); + /* Initialize the queues in use */ + qla25xx_init_queues(ha); + + status = qla2x00_fw_ready(vha); + if (!status) { DEBUG(printk("%s(): Start configure loop, " "status = %d\n", __func__, status)); /* Issue a marker after FW becomes ready. */ - qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); + qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL); - ha->flags.online = 1; + vha->flags.online = 1; /* Wait at most MAX_TARGET RSCNs for a stable link. */ wait_time = 256; do { - clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); - qla2x00_configure_loop(ha); + clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + qla2x00_configure_loop(vha); wait_time--; - } while (!atomic_read(&ha->loop_down_timer) && - !(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) && - wait_time && - (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))); + } while (!atomic_read(&vha->loop_down_timer) && + !(test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) + && wait_time && (test_bit(LOOP_RESYNC_NEEDED, + &vha->dpc_flags))); } /* if no cable then assume it's good */ - if ((ha->device_flags & DFLG_NO_CABLE)) + if ((vha->device_flags & DFLG_NO_CABLE)) status = 0; DEBUG(printk("%s(): Configure loop done, status = 0x%x\n", @@ -3434,6 +3480,47 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) return (status); } +static int +qla25xx_init_queues(struct qla_hw_data *ha) +{ + struct rsp_que *rsp = NULL; + struct req_que *req = NULL; + struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); + int ret = -1; + int i; + + for (i = 1; i < ha->max_queues; i++) { + rsp = ha->rsp_q_map[i]; + if (rsp) { + rsp->options &= ~BIT_0; + ret = qla25xx_init_rsp_que(base_vha, rsp, rsp->options); + if (ret != QLA_SUCCESS) + DEBUG2_17(printk(KERN_WARNING + "%s Rsp que:%d init failed\n", __func__, + rsp->id)); + else + DEBUG2_17(printk(KERN_INFO + "%s Rsp que:%d inited\n", __func__, + rsp->id)); + } + req = ha->req_q_map[i]; + if (req) { + /* Clear outstanding commands array. */ + req->options &= ~BIT_0; + ret = qla25xx_init_req_que(base_vha, req, req->options); + if (ret != QLA_SUCCESS) + DEBUG2_17(printk(KERN_WARNING + "%s Req que:%d init failed\n", __func__, + req->id)); + else + DEBUG2_17(printk(KERN_WARNING + "%s Req que:%d inited\n", __func__, + req->id)); + } + } + return ret; +} + /* * qla2x00_reset_adapter * Reset adapter. @@ -3442,12 +3529,13 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) * ha = adapter block pointer. */ void -qla2x00_reset_adapter(scsi_qla_host_t *ha) +qla2x00_reset_adapter(scsi_qla_host_t *vha) { unsigned long flags = 0; + struct qla_hw_data *ha = vha->hw; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; - ha->flags.online = 0; + vha->flags.online = 0; ha->isp_ops->disable_intrs(ha); spin_lock_irqsave(&ha->hardware_lock, flags); @@ -3459,12 +3547,13 @@ qla2x00_reset_adapter(scsi_qla_host_t *ha) } void -qla24xx_reset_adapter(scsi_qla_host_t *ha) +qla24xx_reset_adapter(scsi_qla_host_t *vha) { unsigned long flags = 0; + struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; - ha->flags.online = 0; + vha->flags.online = 0; ha->isp_ops->disable_intrs(ha); spin_lock_irqsave(&ha->hardware_lock, flags); @@ -3478,9 +3567,11 @@ qla24xx_reset_adapter(scsi_qla_host_t *ha) /* On sparc systems, obtain port and node WWN from firmware * properties. */ -static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, struct nvram_24xx *nv) +static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, + struct nvram_24xx *nv) { #ifdef CONFIG_SPARC + struct qla_hw_data *ha = vha->hw; struct pci_dev *pdev = ha->pdev; struct device_node *dp = pci_device_to_OF_node(pdev); const u8 *val; @@ -3497,7 +3588,7 @@ static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, struct nvram_24xx *n } int -qla24xx_nvram_config(scsi_qla_host_t *ha) +qla24xx_nvram_config(scsi_qla_host_t *vha) { int rval; struct init_cb_24xx *icb; @@ -3506,6 +3597,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) uint8_t *dptr1, *dptr2; uint32_t chksum; uint16_t cnt; + struct qla_hw_data *ha = vha->hw; rval = QLA_SUCCESS; icb = (struct init_cb_24xx *)ha->init_cb; @@ -3523,12 +3615,12 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) /* Get VPD data into cache */ ha->vpd = ha->nvram + VPD_OFFSET; - ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, + ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd, ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4); /* Get NVRAM data into cache and calculate checksum. */ dptr = (uint32_t *)nv; - ha->isp_ops->read_nvram(ha, (uint8_t *)dptr, ha->nvram_base, + ha->isp_ops->read_nvram(vha, (uint8_t *)dptr, ha->nvram_base, ha->nvram_size); for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++) chksum += le32_to_cpu(*dptr++); @@ -3573,7 +3665,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) nv->node_name[5] = 0x1c; nv->node_name[6] = 0x55; nv->node_name[7] = 0x86; - qla24xx_nvram_wwn_from_ofw(ha, nv); + qla24xx_nvram_wwn_from_ofw(vha, nv); nv->login_retry_count = __constant_cpu_to_le16(8); nv->interrupt_delay_timer = __constant_cpu_to_le16(0); nv->login_timeout = __constant_cpu_to_le16(0); @@ -3593,7 +3685,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) } /* Reset Initialization control block */ - memset(icb, 0, sizeof(struct init_cb_24xx)); + memset(icb, 0, ha->init_cb_size); /* Copy 1st segment. */ dptr1 = (uint8_t *)icb; @@ -3616,7 +3708,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) /* * Setup driver NVRAM options. */ - qla2x00_set_model_info(ha, nv->model_name, sizeof(nv->model_name), + qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name), "QLA2462"); /* Use alternate WWN? */ @@ -3655,8 +3747,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) ha->serial0 = icb->port_name[5]; ha->serial1 = icb->port_name[6]; ha->serial2 = icb->port_name[7]; - ha->node_name = icb->node_name; - ha->port_name = icb->port_name; + memcpy(vha->node_name, icb->node_name, WWN_SIZE); + memcpy(vha->port_name, icb->port_name, WWN_SIZE); icb->execution_throttle = __constant_cpu_to_le16(0xFFFF); @@ -3711,7 +3803,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) ha->login_retry_count = ql2xloginretrycount; /* Enable ZIO. */ - if (!ha->flags.init_done) { + if (!vha->flags.init_done) { ha->zio_mode = le32_to_cpu(icb->firmware_options_2) & (BIT_3 | BIT_2 | BIT_1 | BIT_0); ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ? @@ -3719,12 +3811,12 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) } icb->firmware_options_2 &= __constant_cpu_to_le32( ~(BIT_3 | BIT_2 | BIT_1 | BIT_0)); - ha->flags.process_response_queue = 0; + vha->flags.process_response_queue = 0; if (ha->zio_mode != QLA_ZIO_DISABLED) { ha->zio_mode = QLA_ZIO_MODE_6; DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay " - "(%d us).\n", ha->host_no, ha->zio_mode, + "(%d us).\n", vha->host_no, ha->zio_mode, ha->zio_timer * 100)); qla_printk(KERN_INFO, ha, "ZIO mode %d enabled; timer delay (%d us).\n", @@ -3733,36 +3825,37 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) icb->firmware_options_2 |= cpu_to_le32( (uint32_t)ha->zio_mode); icb->interrupt_delay_timer = cpu_to_le16(ha->zio_timer); - ha->flags.process_response_queue = 1; + vha->flags.process_response_queue = 1; } if (rval) { DEBUG2_3(printk(KERN_WARNING - "scsi(%ld): NVRAM configuration failed!\n", ha->host_no)); + "scsi(%ld): NVRAM configuration failed!\n", vha->host_no)); } return (rval); } static int -qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) +qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr) { - int rval; + int rval = QLA_SUCCESS; int segments, fragment; uint32_t faddr; uint32_t *dcode, dlen; uint32_t risc_addr; uint32_t risc_size; uint32_t i; - + struct qla_hw_data *ha = vha->hw; + struct req_que *req = ha->req_q_map[0]; rval = QLA_SUCCESS; segments = FA_RISC_CODE_SEGMENTS; faddr = ha->flt_region_fw; - dcode = (uint32_t *)ha->request_ring; + dcode = (uint32_t *)req->ring; *srisc_addr = 0; /* Validate firmware image by checking version. */ - qla24xx_read_flash_data(ha, dcode, faddr + 4, 4); + qla24xx_read_flash_data(vha, dcode, faddr + 4, 4); for (i = 0; i < 4; i++) dcode[i] = be32_to_cpu(dcode[i]); if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && @@ -3780,7 +3873,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) while (segments && rval == QLA_SUCCESS) { /* Read segment's load information. */ - qla24xx_read_flash_data(ha, dcode, faddr, 4); + qla24xx_read_flash_data(vha, dcode, faddr, 4); risc_addr = be32_to_cpu(dcode[2]); *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr; @@ -3794,17 +3887,17 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) DEBUG7(printk("scsi(%ld): Loading risc segment@ risc " "addr %x, number of dwords 0x%x, offset 0x%x.\n", - ha->host_no, risc_addr, dlen, faddr)); + vha->host_no, risc_addr, dlen, faddr)); - qla24xx_read_flash_data(ha, dcode, faddr, dlen); + qla24xx_read_flash_data(vha, dcode, faddr, dlen); for (i = 0; i < dlen; i++) dcode[i] = swab32(dcode[i]); - rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, + rval = qla2x00_load_ram(vha, req->dma, risc_addr, dlen); if (rval) { DEBUG(printk("scsi(%ld):[ERROR] Failed to load " - "segment %d of firmware\n", ha->host_no, + "segment %d of firmware\n", vha->host_no, fragment)); qla_printk(KERN_WARNING, ha, "[ERROR] Failed to load segment %d of " @@ -3828,16 +3921,18 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) #define QLA_FW_URL "ftp://ftp.qlogic.com/outgoing/linux/firmware/" int -qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) +qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) { int rval; int i, fragment; uint16_t *wcode, *fwcode; uint32_t risc_addr, risc_size, fwclen, wlen, *seg; struct fw_blob *blob; + struct qla_hw_data *ha = vha->hw; + struct req_que *req = ha->req_q_map[0]; /* Load firmware blob. */ - blob = qla2x00_request_firmware(ha); + blob = qla2x00_request_firmware(vha); if (!blob) { qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); qla_printk(KERN_ERR, ha, "Firmware images can be retrieved " @@ -3847,7 +3942,7 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) rval = QLA_SUCCESS; - wcode = (uint16_t *)ha->request_ring; + wcode = (uint16_t *)req->ring; *srisc_addr = 0; fwcode = (uint16_t *)blob->fw->data; fwclen = 0; @@ -3894,17 +3989,17 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) wlen = risc_size; DEBUG7(printk("scsi(%ld): Loading risc segment@ risc " - "addr %x, number of words 0x%x.\n", ha->host_no, + "addr %x, number of words 0x%x.\n", vha->host_no, risc_addr, wlen)); for (i = 0; i < wlen; i++) wcode[i] = swab16(fwcode[i]); - rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, + rval = qla2x00_load_ram(vha, req->dma, risc_addr, wlen); if (rval) { DEBUG(printk("scsi(%ld):[ERROR] Failed to load " - "segment %d of firmware\n", ha->host_no, + "segment %d of firmware\n", vha->host_no, fragment)); qla_printk(KERN_WARNING, ha, "[ERROR] Failed to load segment %d of " @@ -3928,7 +4023,7 @@ fail_fw_integrity: } int -qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) +qla24xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) { int rval; int segments, fragment; @@ -3938,9 +4033,11 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) uint32_t i; struct fw_blob *blob; uint32_t *fwcode, fwclen; + struct qla_hw_data *ha = vha->hw; + struct req_que *req = ha->req_q_map[0]; /* Load firmware blob. */ - blob = qla2x00_request_firmware(ha); + blob = qla2x00_request_firmware(vha); if (!blob) { qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); qla_printk(KERN_ERR, ha, "Firmware images can be retrieved " @@ -3949,13 +4046,13 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) /* Try to load RISC code from flash. */ qla_printk(KERN_ERR, ha, "Attempting to load (potentially " "outdated) firmware from flash.\n"); - return qla24xx_load_risc_flash(ha, srisc_addr); + return qla24xx_load_risc_flash(vha, srisc_addr); } rval = QLA_SUCCESS; segments = FA_RISC_CODE_SEGMENTS; - dcode = (uint32_t *)ha->request_ring; + dcode = (uint32_t *)req->ring; *srisc_addr = 0; fwcode = (uint32_t *)blob->fw->data; fwclen = 0; @@ -4003,17 +4100,17 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) dlen = risc_size; DEBUG7(printk("scsi(%ld): Loading risc segment@ risc " - "addr %x, number of dwords 0x%x.\n", ha->host_no, + "addr %x, number of dwords 0x%x.\n", vha->host_no, risc_addr, dlen)); for (i = 0; i < dlen; i++) dcode[i] = swab32(fwcode[i]); - rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, + rval = qla2x00_load_ram(vha, req->dma, risc_addr, dlen); if (rval) { DEBUG(printk("scsi(%ld):[ERROR] Failed to load " - "segment %d of firmware\n", ha->host_no, + "segment %d of firmware\n", vha->host_no, fragment)); qla_printk(KERN_WARNING, ha, "[ERROR] Failed to load segment %d of " @@ -4037,49 +4134,53 @@ fail_fw_integrity: } void -qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha) +qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha) { int ret, retries; + struct qla_hw_data *ha = vha->hw; if (!IS_FWI2_CAPABLE(ha)) return; if (!ha->fw_major_version) return; - ret = qla2x00_stop_firmware(ha); + ret = qla2x00_stop_firmware(vha); for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT && retries ; retries--) { - ha->isp_ops->reset_chip(ha); - if (ha->isp_ops->chip_diag(ha) != QLA_SUCCESS) + ha->isp_ops->reset_chip(vha); + if (ha->isp_ops->chip_diag(vha) != QLA_SUCCESS) continue; - if (qla2x00_setup_chip(ha) != QLA_SUCCESS) + if (qla2x00_setup_chip(vha) != QLA_SUCCESS) continue; qla_printk(KERN_INFO, ha, "Attempting retry of stop-firmware command...\n"); - ret = qla2x00_stop_firmware(ha); + ret = qla2x00_stop_firmware(vha); } } int -qla24xx_configure_vhba(scsi_qla_host_t *ha) +qla24xx_configure_vhba(scsi_qla_host_t *vha) { int rval = QLA_SUCCESS; uint16_t mb[MAILBOX_REGISTER_COUNT]; + struct qla_hw_data *ha = vha->hw; + struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); + struct req_que *req = ha->req_q_map[vha->req_ques[0]]; + struct rsp_que *rsp = req->rsp; - if (!ha->parent) + if (!vha->vp_idx) return -EINVAL; - rval = qla2x00_fw_ready(ha->parent); + rval = qla2x00_fw_ready(base_vha); if (rval == QLA_SUCCESS) { - clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); - qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); + clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags); + qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL); } - ha->flags.management_server_logged_in = 0; + vha->flags.management_server_logged_in = 0; /* Login to SNS first */ - qla24xx_login_fabric(ha->parent, NPH_SNS, 0xff, 0xff, 0xfc, - mb, BIT_1); + ha->isp_ops->fabric_login(vha, NPH_SNS, 0xff, 0xff, 0xfc, mb, BIT_1); if (mb[0] != MBS_COMMAND_COMPLETE) { DEBUG15(qla_printk(KERN_INFO, ha, "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x " @@ -4088,11 +4189,11 @@ qla24xx_configure_vhba(scsi_qla_host_t *ha) return (QLA_FUNCTION_FAILED); } - atomic_set(&ha->loop_down_timer, 0); - atomic_set(&ha->loop_state, LOOP_UP); - set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); - set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); - rval = qla2x00_loop_resync(ha->parent); + atomic_set(&vha->loop_down_timer, 0); + atomic_set(&vha->loop_state, LOOP_UP); + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); + rval = qla2x00_loop_resync(base_vha); return rval; } @@ -4103,9 +4204,10 @@ static LIST_HEAD(qla_cs84xx_list); static DEFINE_MUTEX(qla_cs84xx_mutex); static struct qla_chip_state_84xx * -qla84xx_get_chip(struct scsi_qla_host *ha) +qla84xx_get_chip(struct scsi_qla_host *vha) { struct qla_chip_state_84xx *cs84xx; + struct qla_hw_data *ha = vha->hw; mutex_lock(&qla_cs84xx_mutex); @@ -4145,24 +4247,292 @@ __qla84xx_chip_release(struct kref *kref) } void -qla84xx_put_chip(struct scsi_qla_host *ha) +qla84xx_put_chip(struct scsi_qla_host *vha) { + struct qla_hw_data *ha = vha->hw; if (ha->cs84xx) kref_put(&ha->cs84xx->kref, __qla84xx_chip_release); } static int -qla84xx_init_chip(scsi_qla_host_t *ha) +qla84xx_init_chip(scsi_qla_host_t *vha) { int rval; uint16_t status[2]; + struct qla_hw_data *ha = vha->hw; mutex_lock(&ha->cs84xx->fw_update_mutex); - rval = qla84xx_verify_chip(ha, status); + rval = qla84xx_verify_chip(vha, status); mutex_unlock(&ha->cs84xx->fw_update_mutex); return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED: QLA_SUCCESS; } + +/* 81XX Support **************************************************************/ + +int +qla81xx_nvram_config(scsi_qla_host_t *vha) +{ + int rval; + struct init_cb_81xx *icb; + struct nvram_81xx *nv; + uint32_t *dptr; + uint8_t *dptr1, *dptr2; + uint32_t chksum; + uint16_t cnt; + struct qla_hw_data *ha = vha->hw; + + rval = QLA_SUCCESS; + icb = (struct init_cb_81xx *)ha->init_cb; + nv = ha->nvram; + + /* Determine NVRAM starting address. */ + ha->nvram_size = sizeof(struct nvram_81xx); + ha->nvram_base = FA_NVRAM_FUNC0_ADDR; + ha->vpd_size = FA_NVRAM_VPD_SIZE; + ha->vpd_base = FA_NVRAM_VPD0_ADDR; + if (PCI_FUNC(ha->pdev->devfn) & 1) { + ha->nvram_base = FA_NVRAM_FUNC1_ADDR; + ha->vpd_base = FA_NVRAM_VPD1_ADDR; + } + + /* Get VPD data into cache */ + ha->vpd = ha->nvram + VPD_OFFSET; + ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd, + ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4); + + /* Get NVRAM data into cache and calculate checksum. */ + dptr = (uint32_t *)nv; + ha->isp_ops->read_nvram(vha, (uint8_t *)dptr, ha->nvram_base, + ha->nvram_size); + for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++) + chksum += le32_to_cpu(*dptr++); + + DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); + DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size)); + + /* Bad NVRAM data, set defaults parameters. */ + if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' + || nv->id[3] != ' ' || + nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) { + /* Reset NVRAM data. */ + qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: " + "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], + le16_to_cpu(nv->nvram_version)); + qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet " + "invalid -- WWPN) defaults.\n"); + + /* + * Set default initialization control block. + */ + memset(nv, 0, ha->nvram_size); + nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION); + nv->version = __constant_cpu_to_le16(ICB_VERSION); + nv->frame_payload_size = __constant_cpu_to_le16(2048); + nv->execution_throttle = __constant_cpu_to_le16(0xFFFF); + nv->exchange_count = __constant_cpu_to_le16(0); + nv->port_name[0] = 0x21; + nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn); + nv->port_name[2] = 0x00; + nv->port_name[3] = 0xe0; + nv->port_name[4] = 0x8b; + nv->port_name[5] = 0x1c; + nv->port_name[6] = 0x55; + nv->port_name[7] = 0x86; + nv->node_name[0] = 0x20; + nv->node_name[1] = 0x00; + nv->node_name[2] = 0x00; + nv->node_name[3] = 0xe0; + nv->node_name[4] = 0x8b; + nv->node_name[5] = 0x1c; + nv->node_name[6] = 0x55; + nv->node_name[7] = 0x86; + nv->login_retry_count = __constant_cpu_to_le16(8); + nv->interrupt_delay_timer = __constant_cpu_to_le16(0); + nv->login_timeout = __constant_cpu_to_le16(0); + nv->firmware_options_1 = + __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1); + nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4); + nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12); + nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13); + nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10); + nv->efi_parameters = __constant_cpu_to_le32(0); + nv->reset_delay = 5; + nv->max_luns_per_target = __constant_cpu_to_le16(128); + nv->port_down_retry_count = __constant_cpu_to_le16(30); + nv->link_down_timeout = __constant_cpu_to_le16(30); + nv->enode_mac[0] = 0x01; + nv->enode_mac[1] = 0x02; + nv->enode_mac[2] = 0x03; + nv->enode_mac[3] = 0x04; + nv->enode_mac[4] = 0x05; + nv->enode_mac[5] = 0x06 + PCI_FUNC(ha->pdev->devfn); + + rval = 1; + } + + /* Reset Initialization control block */ + memset(icb, 0, sizeof(struct init_cb_81xx)); + + /* Copy 1st segment. */ + dptr1 = (uint8_t *)icb; + dptr2 = (uint8_t *)&nv->version; + cnt = (uint8_t *)&icb->response_q_inpointer - (uint8_t *)&icb->version; + while (cnt--) + *dptr1++ = *dptr2++; + + icb->login_retry_count = nv->login_retry_count; + + /* Copy 2nd segment. */ + dptr1 = (uint8_t *)&icb->interrupt_delay_timer; + dptr2 = (uint8_t *)&nv->interrupt_delay_timer; + cnt = (uint8_t *)&icb->reserved_5 - + (uint8_t *)&icb->interrupt_delay_timer; + while (cnt--) + *dptr1++ = *dptr2++; + + memcpy(icb->enode_mac, nv->enode_mac, sizeof(icb->enode_mac)); + /* Some boards (with valid NVRAMs) still have NULL enode_mac!! */ + if (!memcmp(icb->enode_mac, "\0\0\0\0\0\0", sizeof(icb->enode_mac))) { + icb->enode_mac[0] = 0x01; + icb->enode_mac[1] = 0x02; + icb->enode_mac[2] = 0x03; + icb->enode_mac[3] = 0x04; + icb->enode_mac[4] = 0x05; + icb->enode_mac[5] = 0x06 + PCI_FUNC(ha->pdev->devfn); + } + + /* + * Setup driver NVRAM options. + */ + qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name), + "QLE81XX"); + + /* Use alternate WWN? */ + if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { + memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE); + memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE); + } + + /* Prepare nodename */ + if ((icb->firmware_options_1 & __constant_cpu_to_le32(BIT_14)) == 0) { + /* + * Firmware will apply the following mask if the nodename was + * not provided. + */ + memcpy(icb->node_name, icb->port_name, WWN_SIZE); + icb->node_name[0] &= 0xF0; + } + + /* Set host adapter parameters. */ + ha->flags.disable_risc_code_load = 0; + ha->flags.enable_lip_reset = 0; + ha->flags.enable_lip_full_login = + le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0; + ha->flags.enable_target_reset = + le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0; + ha->flags.enable_led_scheme = 0; + ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0; + + ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) & + (BIT_6 | BIT_5 | BIT_4)) >> 4; + + /* save HBA serial number */ + ha->serial0 = icb->port_name[5]; + ha->serial1 = icb->port_name[6]; + ha->serial2 = icb->port_name[7]; + memcpy(vha->node_name, icb->node_name, WWN_SIZE); + memcpy(vha->port_name, icb->port_name, WWN_SIZE); + + icb->execution_throttle = __constant_cpu_to_le16(0xFFFF); + + ha->retry_count = le16_to_cpu(nv->login_retry_count); + + /* Set minimum login_timeout to 4 seconds. */ + if (le16_to_cpu(nv->login_timeout) < ql2xlogintimeout) + nv->login_timeout = cpu_to_le16(ql2xlogintimeout); + if (le16_to_cpu(nv->login_timeout) < 4) + nv->login_timeout = __constant_cpu_to_le16(4); + ha->login_timeout = le16_to_cpu(nv->login_timeout); + icb->login_timeout = nv->login_timeout; + + /* Set minimum RATOV to 100 tenths of a second. */ + ha->r_a_tov = 100; + + ha->loop_reset_delay = nv->reset_delay; + + /* Link Down Timeout = 0: + * + * When Port Down timer expires we will start returning + * I/O's to OS with "DID_NO_CONNECT". + * + * Link Down Timeout != 0: + * + * The driver waits for the link to come up after link down + * before returning I/Os to OS with "DID_NO_CONNECT". + */ + if (le16_to_cpu(nv->link_down_timeout) == 0) { + ha->loop_down_abort_time = + (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT); + } else { + ha->link_down_timeout = le16_to_cpu(nv->link_down_timeout); + ha->loop_down_abort_time = + (LOOP_DOWN_TIME - ha->link_down_timeout); + } + + /* Need enough time to try and get the port back. */ + ha->port_down_retry_count = le16_to_cpu(nv->port_down_retry_count); + if (qlport_down_retry) + ha->port_down_retry_count = qlport_down_retry; + + /* Set login_retry_count */ + ha->login_retry_count = le16_to_cpu(nv->login_retry_count); + if (ha->port_down_retry_count == + le16_to_cpu(nv->port_down_retry_count) && + ha->port_down_retry_count > 3) + ha->login_retry_count = ha->port_down_retry_count; + else if (ha->port_down_retry_count > (int)ha->login_retry_count) + ha->login_retry_count = ha->port_down_retry_count; + if (ql2xloginretrycount) + ha->login_retry_count = ql2xloginretrycount; + + /* Enable ZIO. */ + if (!vha->flags.init_done) { + ha->zio_mode = le32_to_cpu(icb->firmware_options_2) & + (BIT_3 | BIT_2 | BIT_1 | BIT_0); + ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ? + le16_to_cpu(icb->interrupt_delay_timer): 2; + } + icb->firmware_options_2 &= __constant_cpu_to_le32( + ~(BIT_3 | BIT_2 | BIT_1 | BIT_0)); + vha->flags.process_response_queue = 0; + if (ha->zio_mode != QLA_ZIO_DISABLED) { + ha->zio_mode = QLA_ZIO_MODE_6; + + DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay " + "(%d us).\n", vha->host_no, ha->zio_mode, + ha->zio_timer * 100)); + qla_printk(KERN_INFO, ha, + "ZIO mode %d enabled; timer delay (%d us).\n", + ha->zio_mode, ha->zio_timer * 100); + + icb->firmware_options_2 |= cpu_to_le32( + (uint32_t)ha->zio_mode); + icb->interrupt_delay_timer = cpu_to_le16(ha->zio_timer); + vha->flags.process_response_queue = 1; + } + + if (rval) { + DEBUG2_3(printk(KERN_WARNING + "scsi(%ld): NVRAM configuration failed!\n", vha->host_no)); + } + return (rval); +} + +void +qla81xx_update_fw_options(scsi_qla_host_t *ha) +{ +} -- cgit v1.2.3