X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Fqla2xxx%2Fqla_init.c;h=b3dac26ddba3e50767c852aecaf07921bf4f363a;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=634ee174bff2a315e95fc29dd6fc41a72145480f;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 634ee174b..b3dac26dd 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -39,6 +39,8 @@ 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); + /****************************************************************************/ /* QLogic ISP2x00 Hardware Support Functions. */ /****************************************************************************/ @@ -57,9 +59,6 @@ int qla2x00_initialize_adapter(scsi_qla_host_t *ha) { int rval; - uint8_t restart_risc = 0; - uint8_t retry; - uint32_t wait_time; /* Clear adapter flags. */ ha->flags.online = 0; @@ -89,89 +88,28 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) ha->isp_ops.nvram_config(ha); - qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); - - retry = 10; - /* - * Try to configure the loop. - */ - do { - restart_risc = 0; - - /* If firmware needs to be loaded */ - if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { - if ((rval = ha->isp_ops.chip_diag(ha)) == QLA_SUCCESS) { - rval = qla2x00_setup_chip(ha); - } - } - - if (rval == QLA_SUCCESS && - (rval = qla2x00_init_rings(ha)) == QLA_SUCCESS) { -check_fw_ready_again: - /* - * Wait for a successful LIP up to a maximum - * of (in seconds): RISC login timeout value, - * RISC retry count value, and port down retry - * value OR a minimum of 4 seconds OR If no - * cable, only 5 seconds. - */ - rval = qla2x00_fw_ready(ha); - if (rval == QLA_SUCCESS) { - clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); - - /* Issue a marker after FW becomes ready. */ - qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); - - /* - * Wait at most MAX_TARGET RSCNs for a stable - * link. - */ - wait_time = 256; - do { - clear_bit(LOOP_RESYNC_NEEDED, - &ha->dpc_flags); - rval = qla2x00_configure_loop(ha); - - if (test_and_clear_bit(ISP_ABORT_NEEDED, - &ha->dpc_flags)) { - restart_risc = 1; - break; - } - - /* - * If loop state change while we were - * discoverying devices then wait for - * LIP to complete - */ - - if (atomic_read(&ha->loop_state) != - LOOP_READY && retry--) { - goto check_fw_ready_again; - } - wait_time--; - } while (!atomic_read(&ha->loop_down_timer) && - retry && - wait_time && - (test_bit(LOOP_RESYNC_NEEDED, - &ha->dpc_flags))); - - if (wait_time == 0) - rval = QLA_FUNCTION_FAILED; - } else if (ha->device_flags & DFLG_NO_CABLE) - /* If no cable, then all is good. */ - rval = QLA_SUCCESS; - } - } while (restart_risc && retry--); + 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]); + return QLA_FUNCTION_FAILED; + } - if (rval == QLA_SUCCESS) { - clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); - qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); - ha->marker_needed = 0; + qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); - ha->flags.online = 1; - } else { - DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__)); + if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { + rval = ha->isp_ops.chip_diag(ha); + if (rval) + return (rval); + rval = qla2x00_setup_chip(ha); + if (rval) + return (rval); } + rval = qla2x00_init_rings(ha); return (rval); } @@ -194,7 +132,6 @@ qla2100_pci_config(scsi_qla_host_t *ha) mwi = 0; if (pci_set_mwi(ha->pdev)) mwi = PCI_COMMAND_INVALIDATE; - pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); @@ -232,7 +169,6 @@ qla2300_pci_config(scsi_qla_host_t *ha) mwi = 0; if (pci_set_mwi(ha->pdev)) mwi = PCI_COMMAND_INVALIDATE; - pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); @@ -320,7 +256,6 @@ qla24xx_pci_config(scsi_qla_host_t *ha) mwi = 0; if (pci_set_mwi(ha->pdev)) mwi = PCI_COMMAND_INVALIDATE; - pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); @@ -386,9 +321,7 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha) qla_printk(KERN_INFO, ha, "RISC CODE NOT loaded\n"); /* Verify checksum of loaded RISC code. */ - rval = qla2x00_verify_checksum(ha, - IS_QLA24XX(ha) || IS_QLA25XX(ha) ? RISC_SADDRESS : - *ha->brd_info->fw_info[0].fwstart); + rval = qla2x00_verify_checksum(ha, ha->fw_srisc_address); } if (rval) { @@ -411,7 +344,6 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) unsigned long flags = 0; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; uint32_t cnt; - unsigned long mbx_flags = 0; uint16_t cmd; ha->isp_ops.disable_intrs(ha); @@ -519,20 +451,8 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) { for (cnt = 0; cnt < 30000; cnt++) { - if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) - spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags); - - if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY) { - if (!(test_bit(ABORT_ISP_ACTIVE, - &ha->dpc_flags))) - spin_unlock_irqrestore( - &ha->mbx_reg_lock, mbx_flags); + if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY) break; - } - - if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) - spin_unlock_irqrestore(&ha->mbx_reg_lock, - mbx_flags); udelay(100); } @@ -727,6 +647,7 @@ qla2x00_chip_diag(scsi_qla_host_t *ha) DEBUG3(printk("scsi(%ld): Found QLA2200A chip.\n", ha->host_no)); + ha->device_type |= DT_ISP2200A; ha->fw_transfer_size = 128; } @@ -787,19 +708,104 @@ qla24xx_chip_diag(scsi_qla_host_t *ha) return rval; } -static void +void qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) { + int rval; + uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size, + eft_size; + dma_addr_t eft_dma; + void *eft; + + if (ha->fw_dump) { + qla_printk(KERN_WARNING, ha, + "Firmware dump previously allocated.\n"); + return; + } + ha->fw_dumped = 0; - ha->fw_dump24_len = sizeof(struct qla24xx_fw_dump); - ha->fw_dump24_len += (ha->fw_memory_size - 0x100000) * sizeof(uint32_t); - ha->fw_dump24 = vmalloc(ha->fw_dump24_len); - if (ha->fw_dump24) - qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware " - "dump...\n", ha->fw_dump24_len / 1024); - else + fixed_size = mem_size = eft_size = 0; + if (IS_QLA2100(ha) || IS_QLA2200(ha)) { + fixed_size = sizeof(struct qla2100_fw_dump); + } else if (IS_QLA23XX(ha)) { + fixed_size = offsetof(struct qla2300_fw_dump, data_ram); + mem_size = (ha->fw_memory_size - 0x11000 + 1) * + sizeof(uint16_t); + } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem); + mem_size = (ha->fw_memory_size - 0x100000 + 1) * + sizeof(uint32_t); + + /* Allocate memory for Extended Trace Buffer. */ + eft = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &eft_dma, + GFP_KERNEL); + if (!eft) { + qla_printk(KERN_WARNING, ha, "Unable to allocate " + "(%d KB) for EFT.\n", EFT_SIZE / 1024); + goto cont_alloc; + } + + rval = qla2x00_trace_control(ha, TC_ENABLE, eft_dma, + EFT_NUM_BUFFERS); + if (rval) { + qla_printk(KERN_WARNING, ha, "Unable to initialize " + "EFT (%d).\n", rval); + dma_free_coherent(&ha->pdev->dev, EFT_SIZE, eft, + eft_dma); + goto cont_alloc; + } + + qla_printk(KERN_INFO, ha, "Allocated (%d KB) for EFT...\n", + EFT_SIZE / 1024); + + eft_size = EFT_SIZE; + memset(eft, 0, eft_size); + ha->eft_dma = eft_dma; + ha->eft = eft; + } +cont_alloc: + req_q_size = ha->request_q_length * sizeof(request_t); + rsp_q_size = ha->response_q_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; + + ha->fw_dump = vmalloc(dump_size); + if (!ha->fw_dump) { qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for " - "firmware dump!!!\n", ha->fw_dump24_len / 1024); + "firmware dump!!!\n", dump_size / 1024); + + if (ha->eft) { + dma_free_coherent(&ha->pdev->dev, eft_size, ha->eft, + ha->eft_dma); + ha->eft = NULL; + ha->eft_dma = 0; + } + return; + } + + qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware dump...\n", + dump_size / 1024); + + ha->fw_dump_len = dump_size; + ha->fw_dump->signature[0] = 'Q'; + ha->fw_dump->signature[1] = 'L'; + ha->fw_dump->signature[2] = 'G'; + ha->fw_dump->signature[3] = 'C'; + ha->fw_dump->version = __constant_htonl(1); + + ha->fw_dump->fixed_size = htonl(fixed_size); + ha->fw_dump->mem_size = htonl(mem_size); + ha->fw_dump->req_q_size = htonl(req_q_size); + ha->fw_dump->rsp_q_size = htonl(rsp_q_size); + + ha->fw_dump->eft_size = htonl(eft_size); + ha->fw_dump->eft_addr_l = htonl(LSD(ha->eft_dma)); + ha->fw_dump->eft_addr_h = htonl(MSD(ha->eft_dma)); + + ha->fw_dump->header_size = + htonl(offsetof(struct qla2xxx_fw_dump, isp)); } /** @@ -821,9 +827,6 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha) if (IS_QLA2100(ha) || IS_QLA2200(ha)) return; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) - qla2x00_alloc_fw_dump(ha); - /* Retrieve IOCB counts available to the firmware. */ rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt); if (rval) @@ -891,6 +894,9 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) &ha->fw_subminor_version, &ha->fw_attributes, &ha->fw_memory_size); qla2x00_resize_request_q(ha); + + if (ql2xallocfwdump) + qla2x00_alloc_fw_dump(ha); } } else { DEBUG2(printk(KERN_INFO @@ -1002,6 +1008,10 @@ qla2x00_update_fw_options(scsi_qla_host_t *ha) if (ha->flags.enable_led_scheme) ha->fw_options[2] |= BIT_12; + /* Detect ISP6312. */ + if (IS_QLA6312(ha)) + ha->fw_options[2] |= BIT_13; + /* Update firmware options. */ qla2x00_set_fw_options(ha, ha->fw_options); } @@ -1190,8 +1200,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) rval = QLA_FUNCTION_FAILED; if (atomic_read(&ha->loop_down_timer) && - (fw_state >= FSTATE_LOSS_OF_SYNC || - fw_state == FSTATE_WAIT_AL_PA)) { + fw_state != FSTATE_READY) { /* Loop down. Timeout on min_wait for states * other than Wait for Login. */ @@ -1500,9 +1509,9 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) index = (ha->pdev->subsystem_device & 0xff); if (index < QLA_MODEL_NAMES) { strcpy(ha->model_number, - qla2x00_model_name[index]); + qla2x00_model_name[index * 2]); ha->model_desc = - qla2x00_model_desc[index]; + qla2x00_model_name[index * 2 + 1]; } else { strcpy(ha->model_number, "QLA23xx"); } @@ -1540,6 +1549,12 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) while (cnt--) *dptr1++ = *dptr2++; + /* Use alternate WWN? */ + if (nv->host_p[1] & BIT_7) { + 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] & BIT_6) == 0) { /* @@ -1553,6 +1568,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) /* * Set host adapter parameters. */ + if (nv->host_p[0] & BIT_7) + ql2xextended_error_logging = 1; ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0); /* Always load RISC code on non ISP2[12]00 chips. */ if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) @@ -1561,6 +1578,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0); ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0); ha->flags.enable_led_scheme = (nv->special_options[1] & BIT_4) ? 1 : 0; + ha->flags.disable_serdes = 0; ha->operating_mode = (icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4; @@ -1654,6 +1672,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) ~(BIT_3 | BIT_2 | BIT_1 | BIT_0); ha->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, ha->zio_timer * 100)); @@ -1674,14 +1694,6 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) return (rval); } -static void -qla2x00_rport_add(void *data) -{ - fc_port_t *fcport = data; - - qla2x00_reg_remote_port(fcport->ha, fcport); -} - static void qla2x00_rport_del(void *data) { @@ -1705,7 +1717,7 @@ qla2x00_rport_del(void *data) * * Returns a pointer to the allocated fcport, or NULL, if none available. */ -fc_port_t * +static fc_port_t * qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) { fc_port_t *fcport; @@ -1719,13 +1731,10 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) fcport->ha = ha; fcport->port_type = FCT_UNKNOWN; fcport->loop_id = FC_NO_LOOP_ID; - fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; atomic_set(&fcport->state, FCS_UNCONFIGURED); fcport->flags = FCF_RLC_SUPPORT; fcport->supported_classes = FC_COS_UNSPECIFIED; spin_lock_init(&fcport->rport_lock); - INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport); - INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport); return (fcport); } @@ -1785,6 +1794,9 @@ qla2x00_configure_loop(scsi_qla_host_t *ha) 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 || (test_bit(ABORT_ISP_ACTIVE, &flags))) { @@ -1987,6 +1999,19 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) new_fcport->flags &= ~FCF_FABRIC_DEVICE; } + /* Base iIDMA settings on HBA port speed. */ + switch (ha->link_data_rate) { + case PORT_SPEED_1GB: + fcport->fp_speed = cpu_to_be16(BIT_15); + break; + case PORT_SPEED_2GB: + fcport->fp_speed = cpu_to_be16(BIT_14); + break; + case PORT_SPEED_4GB: + fcport->fp_speed = cpu_to_be16(BIT_13); + break; + } + qla2x00_update_fcport(ha, fcport); found_devs++; @@ -2022,43 +2047,63 @@ qla2x00_probe_for_all_luns(scsi_qla_host_t *ha) } } -/* - * qla2x00_update_fcport - * Updates device on list. - * - * Input: - * ha = adapter block pointer. - * fcport = port structure pointer. - * - * Return: - * 0 - Success - * BIT_0 - error - * - * Context: - * Kernel context. - */ -void -qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) +static void +qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) { - fcport->ha = ha; - fcport->login_retry = 0; - fcport->port_login_retry_count = ha->port_down_retry_count * - PORT_RETRY_TIME; - atomic_set(&fcport->port_down_timer, ha->port_down_retry_count * - PORT_RETRY_TIME); - fcport->flags &= ~FCF_LOGIN_NEEDED; +#define LS_UNKNOWN 2 + static char *link_speeds[5] = { "1", "2", "?", "4" }; + int rval; + uint16_t port_speed, mb[6]; - if (fcport->port_type == FCT_INITIATOR || - fcport->port_type == FCT_BROADCAST) - fcport->device_type = TYPE_PROCESSOR; + if (!IS_QLA24XX(ha)) + return; - atomic_set(&fcport->state, FCS_ONLINE); + switch (be16_to_cpu(fcport->fp_speed)) { + case BIT_15: + port_speed = PORT_SPEED_1GB; + break; + case BIT_14: + port_speed = PORT_SPEED_2GB; + break; + case BIT_13: + port_speed = PORT_SPEED_4GB; + break; + default: + DEBUG2(printk("scsi(%ld): %02x%02x%02x%02x%02x%02x%02x%02x -- " + "unsupported FM port operating speed (%04x).\n", + ha->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], + be16_to_cpu(fcport->fp_speed))); + port_speed = PORT_SPEED_UNKNOWN; + break; + } + if (port_speed == PORT_SPEED_UNKNOWN) + return; - if (ha->flags.init_done) - qla2x00_reg_remote_port(ha, fcport); + rval = qla2x00_set_idma_speed(ha, fcport->loop_id, port_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], + 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, + port_speed, mb[0], mb[1])); + } else { + DEBUG2(qla_printk(KERN_INFO, ha, + "iIDMA adjusted to %s GB/s on " + "%02x%02x%02x%02x%02x%02x%02x%02x.\n", + link_speeds[port_speed], 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])); + } } -void +static void qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport) { struct fc_rport_identifiers rport_ids; @@ -2100,6 +2145,39 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport) fcport->os_target_id = rport->scsi_target_id; } +/* + * qla2x00_update_fcport + * Updates device on list. + * + * Input: + * ha = adapter block pointer. + * fcport = port structure pointer. + * + * Return: + * 0 - Success + * BIT_0 - error + * + * Context: + * Kernel context. + */ +void +qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) +{ + fcport->ha = ha; + fcport->login_retry = 0; + fcport->port_login_retry_count = ha->port_down_retry_count * + PORT_RETRY_TIME; + atomic_set(&fcport->port_down_timer, ha->port_down_retry_count * + PORT_RETRY_TIME); + fcport->flags &= ~FCF_LOGIN_NEEDED; + + qla2x00_iidma_fcport(ha, fcport); + + atomic_set(&fcport->state, FCS_ONLINE); + + qla2x00_reg_remote_port(ha, fcport); +} + /* * qla2x00_configure_fabric * Setup SNS devices with loop ID's. @@ -2122,11 +2200,11 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) LIST_HEAD(new_fcports); /* If FL port exists, then SNS is present */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) loop_id = NPH_F_PORT; else loop_id = SNS_FL_PORT; - rval = qla2x00_get_port_name(ha, loop_id, NULL, 0); + rval = qla2x00_get_port_name(ha, loop_id, ha->fabric_node_name, 1); if (rval != QLA_SUCCESS) { DEBUG2(printk("scsi(%ld): MBC_GET_PORT_NAME Failed, No FL " "Port\n", ha->host_no)); @@ -2134,6 +2212,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) ha->device_flags &= ~SWITCH_FOUND; return (QLA_SUCCESS); } + ha->device_flags |= SWITCH_FOUND; /* Mark devices that need re-synchronization. */ rval2 = qla2x00_device_resync(ha); @@ -2148,7 +2227,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) qla2x00_fdmi_register(ha); /* Ensure we are logged into the SNS. */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) loop_id = NPH_SNS; else loop_id = SIMPLE_NAME_SERVER; @@ -2266,8 +2345,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) } /* Remove device from the new list and add it to DB */ - list_del(&fcport->list); - list_add_tail(&fcport->list, &ha->fcports); + list_move_tail(&fcport->list, &ha->fcports); /* Login and update database */ qla2x00_fabric_dev_login(ha, fcport, &next_loopid); @@ -2334,6 +2412,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) } else if (qla2x00_gnn_id(ha, swl) != QLA_SUCCESS) { kfree(swl); swl = NULL; + } else if (qla2x00_gfpn_id(ha, swl) == QLA_SUCCESS) { + qla2x00_gpsc(ha, swl); } } swl_idx = 0; @@ -2368,6 +2448,9 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) swl[swl_idx].node_name, WWN_SIZE); memcpy(new_fcport->port_name, swl[swl_idx].port_name, WWN_SIZE); + memcpy(new_fcport->fabric_port_name, + swl[swl_idx].fabric_port_name, WWN_SIZE); + new_fcport->fp_speed = swl[swl_idx].fp_speed; if (swl[swl_idx].d_id.b.rsvd_1 != 0) { last_dev = 1; @@ -2425,6 +2508,11 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) found++; + /* Update port state. */ + memcpy(fcport->fabric_port_name, + new_fcport->fabric_port_name, WWN_SIZE); + fcport->fp_speed = new_fcport->fp_speed; + /* * If address the same and state FCS_ONLINE, nothing * changed. @@ -2506,7 +2594,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) * Context: * Kernel context. */ -int +static int qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev) { int rval; @@ -2580,7 +2668,6 @@ static int qla2x00_device_resync(scsi_qla_host_t *ha) { int rval; - int rval2; uint32_t mask; fc_port_t *fcport; uint32_t rscn_entry; @@ -2636,17 +2723,6 @@ qla2x00_device_resync(scsi_qla_host_t *ha) switch (format) { case 0: - if (ql2xprocessrscn && - !IS_QLA2100(ha) && !IS_QLA2200(ha) && - !IS_QLA6312(ha) && !IS_QLA6322(ha) && - !IS_QLA24XX(ha) && !IS_QLA25XX(ha) && - ha->flags.init_done) { - /* Handle port RSCN via asyncronous IOCBs */ - rval2 = qla2x00_handle_port_rscn(ha, rscn_entry, - NULL, 0); - if (rval2 == QLA_SUCCESS) - continue; - } mask = 0xffffff; break; case 1: @@ -2664,10 +2740,6 @@ qla2x00_device_resync(scsi_qla_host_t *ha) rval = QLA_SUCCESS; - /* Abort any outstanding IO descriptors. */ - if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) - qla2x00_cancel_io_descriptors(ha); - list_for_each_entry(fcport, &ha->fcports, list) { if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || (fcport->d_id.b24 & mask) != d_id.b24 || @@ -2881,13 +2953,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, uint16_t loop_id) +qla2x00_local_device_login(scsi_qla_host_t *ha, fc_port_t *fcport) { int rval; uint16_t mb[MAILBOX_REGISTER_COUNT]; memset(mb, 0, sizeof(mb)); - rval = qla2x00_login_local_device(ha, loop_id, mb, BIT_0); + rval = qla2x00_login_local_device(ha, fcport, mb, BIT_0); if (rval == QLA_SUCCESS) { /* Interrogate mailbox registers for any errors */ if (mb[0] == MBS_COMMAND_ERROR) @@ -2997,6 +3069,7 @@ qla2x00_update_fcports(scsi_qla_host_t *ha) int qla2x00_abort_isp(scsi_qla_host_t *ha) { + int rval; unsigned long flags = 0; uint16_t cnt; srb_t *sp; @@ -3053,6 +3126,16 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) ha->isp_abort_cnt = 0; clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); + + if (ha->eft) { + rval = qla2x00_trace_control(ha, TC_ENABLE, + ha->eft_dma, EFT_NUM_BUFFERS); + if (rval) { + qla_printk(KERN_WARNING, ha, + "Unable to reinitialize EFT " + "(%d).\n", rval); + } + } } else { /* failed the ISP abort */ ha->flags.online = 1; if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) { @@ -3073,14 +3156,14 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) ha->isp_abort_cnt--; DEBUG(printk("qla%ld: ISP abort - " "retry remaining %d\n", - ha->host_no, ha->isp_abort_cnt);) + ha->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);) + ha->host_no, ha->isp_abort_cnt)); set_bit(ISP_ABORT_RETRY, &ha->dpc_flags); status = 1; } @@ -3094,7 +3177,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) } else { DEBUG(printk(KERN_INFO "qla2x00_abort_isp(%ld): exiting.\n", - ha->host_no);) + ha->host_no)); } return(status); @@ -3129,7 +3212,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) spin_lock_irqsave(&ha->hardware_lock, flags); - if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) { + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) { /* * Disable SRAM, Instruction RAM and GP RAM * parity. @@ -3145,7 +3228,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) spin_lock_irqsave(&ha->hardware_lock, flags); - if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) { + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) { /* Enable proper parity */ if (IS_QLA2300(ha)) /* SRAM parity */ @@ -3170,7 +3253,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); if (!(status = qla2x00_fw_ready(ha))) { DEBUG(printk("%s(): Start configure loop, " - "status = %d\n", __func__, status);) + "status = %d\n", __func__, status)); /* Issue a marker after FW becomes ready. */ qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); @@ -3194,7 +3277,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) DEBUG(printk("%s(): Configure loop done, status = 0x%x\n", __func__, - status);) + status)); } return (status); } @@ -3258,8 +3341,12 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) /* Determine NVRAM starting address. */ ha->nvram_size = sizeof(struct nvram_24xx); ha->nvram_base = FA_NVRAM_FUNC0_ADDR; - if (PCI_FUNC(ha->pdev->devfn)) + ha->vpd_size = FA_NVRAM_VPD_SIZE; + ha->vpd_base = FA_NVRAM_VPD0_ADDR; + if (PCI_FUNC(ha->pdev->devfn)) { ha->nvram_base = FA_NVRAM_FUNC1_ADDR; + ha->vpd_base = FA_NVRAM_VPD1_ADDR; + } /* Get NVRAM data and calculate checksum. */ dptr = (uint32_t *)nv; @@ -3310,7 +3397,6 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) nv->node_name[6] = 0x55; nv->node_name[7] = 0x86; nv->login_retry_count = __constant_cpu_to_le16(8); - nv->link_down_timeout = __constant_cpu_to_le16(200); nv->interrupt_delay_timer = __constant_cpu_to_le16(0); nv->login_timeout = __constant_cpu_to_le16(0); nv->firmware_options_1 = @@ -3339,7 +3425,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) *dptr1++ = *dptr2++; icb->login_retry_count = nv->login_retry_count; - icb->link_down_timeout = nv->link_down_timeout; + icb->link_down_on_nos = nv->link_down_on_nos; /* Copy 2nd segment. */ dptr1 = (uint8_t *)&icb->interrupt_delay_timer; @@ -3368,12 +3454,18 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) index = (ha->pdev->subsystem_device & 0xff); if (index < QLA_MODEL_NAMES) - ha->model_desc = qla2x00_model_desc[index]; + ha->model_desc = qla2x00_model_name[index * 2 + 1]; } else strcpy(ha->model_number, "QLA2462"); + /* 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 & BIT_14) == 0) { + if ((icb->firmware_options_1 & __constant_cpu_to_le32(BIT_14)) == 0) { /* * Firmware will apply the following mask if the nodename was * not provided. @@ -3384,13 +3476,16 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) /* Set host adapter parameters. */ ha->flags.disable_risc_code_load = 0; - ha->flags.enable_lip_reset = 1; - ha->flags.enable_lip_full_login = 1; - ha->flags.enable_target_reset = 1; + 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 = - (icb->firmware_options_2 & (BIT_6 | BIT_5 | BIT_4)) >> 4; + ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) & + (BIT_6 | BIT_5 | BIT_4)) >> 4; memcpy(ha->fw_seriallink_options24, nv->seriallink_options, sizeof(ha->fw_seriallink_options24)); @@ -3465,6 +3560,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) ~(BIT_3 | BIT_2 | BIT_1 | BIT_0)); ha->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, ha->zio_timer * 100)); @@ -3485,134 +3582,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) return (rval); } -#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) - -int -qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) -{ - int rval, num, i; - uint32_t cnt; - uint16_t *risc_code; - uint32_t risc_addr, risc_size; - uint16_t *req_ring; - struct qla_fw_info *fw_iter; - - rval = QLA_SUCCESS; - - /* Load firmware sequences */ - fw_iter = ha->brd_info->fw_info; - *srisc_addr = *ha->brd_info->fw_info->fwstart; - while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) { - risc_code = fw_iter->fwcode; - risc_size = *fw_iter->fwlen; - if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) - risc_addr = *fw_iter->fwstart; - else - risc_addr = *fw_iter->lfwstart; - - num = 0; - rval = 0; - while (risc_size > 0 && !rval) { - cnt = (uint16_t)(ha->fw_transfer_size >> 1); - if (cnt > risc_size) - cnt = risc_size; - - DEBUG7(printk("scsi(%ld): Loading risc segment@ " - "addr %p, number of bytes 0x%x, offset 0x%lx.\n", - ha->host_no, risc_code, cnt, risc_addr)); - - req_ring = (uint16_t *)ha->request_ring; - for (i = 0; i < cnt; i++) - req_ring[i] = cpu_to_le16(risc_code[i]); - - rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, - cnt); - if (rval) { - DEBUG(printk("scsi(%ld): [ERROR] Failed to " - "load segment %d of firmware\n", - ha->host_no, num)); - qla_printk(KERN_WARNING, ha, - "[ERROR] Failed to load segment %d of " - "firmware\n", num); - - qla2x00_dump_regs(ha); - break; - } - - risc_code += cnt; - risc_addr += cnt; - risc_size -= cnt; - num++; - } - - /* Next firmware sequence */ - fw_iter++; - } - return rval; -} - -int -qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) -{ - int rval, num, i; - uint32_t cnt; - uint32_t *risc_code; - uint32_t risc_addr, risc_size; - uint32_t *req_ring; - struct qla_fw_info *fw_iter; - - rval = QLA_SUCCESS; - - /* Load firmware sequences */ - fw_iter = ha->brd_info->fw_info; - *srisc_addr = *((uint32_t *)fw_iter->lfwstart); - while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) { - risc_code = (uint32_t *)fw_iter->fwcode; - risc_size = *((uint32_t *)fw_iter->fwlen); - risc_addr = *((uint32_t *)fw_iter->lfwstart); - - num = 0; - rval = 0; - while (risc_size > 0 && !rval) { - cnt = (uint32_t)(ha->fw_transfer_size >> 2); - if (cnt > risc_size) - cnt = risc_size; - - DEBUG7(printk("scsi(%ld): Loading risc segment@ " - "addr %p, number of bytes 0x%x, offset 0x%lx.\n", - ha->host_no, risc_code, cnt, risc_addr)); - - req_ring = (uint32_t *)ha->request_ring; - for (i = 0; i < cnt; i++) - req_ring[i] = cpu_to_le32(risc_code[i]); - - rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, - cnt); - if (rval) { - DEBUG(printk("scsi(%ld): [ERROR] Failed to " - "load segment %d of firmware\n", - ha->host_no, num)); - qla_printk(KERN_WARNING, ha, - "[ERROR] Failed to load segment %d of " - "firmware\n", num); - - qla2x00_dump_regs(ha); - break; - } - - risc_code += cnt; - risc_addr += cnt; - risc_size -= cnt; - num++; - } - - /* Next firmware sequence */ - fw_iter++; - } - return rval; -} - -int +static int qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) { int rval; @@ -3694,7 +3664,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) return rval; } -#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */ +#define QLA_FW_URL "ftp://ftp.qlogic.com/outgoing/linux/firmware/" int qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) @@ -3709,6 +3679,8 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) blob = qla2x00_request_firmware(ha); if (!blob) { qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); + qla_printk(KERN_ERR, ha, "Firmware images can be retrieved " + "from: " QLA_FW_URL ".\n"); return QLA_FUNCTION_FAILED; } @@ -3810,7 +3782,13 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) blob = qla2x00_request_firmware(ha); if (!blob) { qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); - return QLA_FUNCTION_FAILED; + qla_printk(KERN_ERR, ha, "Firmware images can be retrieved " + "from: " QLA_FW_URL ".\n"); + + /* 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); } rval = QLA_SUCCESS; @@ -3896,4 +3874,24 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) fail_fw_integrity: return QLA_FUNCTION_FAILED; } -#endif + +void +qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha) +{ + int ret, retries; + + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) + return; + + ret = qla2x00_stop_firmware(ha); + for (retries = 5; ret != QLA_SUCCESS && retries ; retries--) { + qla2x00_reset_chip(ha); + if (qla2x00_chip_diag(ha) != QLA_SUCCESS) + continue; + if (qla2x00_setup_chip(ha) != QLA_SUCCESS) + continue; + qla_printk(KERN_INFO, ha, + "Attempting retry of stop-firmware command...\n"); + ret = qla2x00_stop_firmware(ha); + } +}