linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / scsi / qla2xxx / qla_init.c
index 8596491..634ee17 100644 (file)
@@ -39,8 +39,6 @@ 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.                */
 /****************************************************************************/
@@ -91,17 +89,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
 
        ha->isp_ops.nvram_config(ha);
 
-       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;
-       }
-
        qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n");
 
        retry = 10;
@@ -207,6 +194,7 @@ 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);
@@ -244,6 +232,7 @@ 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);
@@ -331,6 +320,7 @@ 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);
@@ -396,7 +386,9 @@ 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, ha->fw_srisc_address);
+               rval = qla2x00_verify_checksum(ha,
+                   IS_QLA24XX(ha) || IS_QLA25XX(ha) ? RISC_SADDRESS :
+                   *ha->brd_info->fw_info[0].fwstart);
        }
 
        if (rval) {
@@ -419,6 +411,7 @@ 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);
@@ -526,8 +519,20 @@ 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 (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY)
+                       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);
                                break;
+                       }
+
+                       if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)))
+                               spin_unlock_irqrestore(&ha->mbx_reg_lock,
+                                   mbx_flags);
 
                        udelay(100);
                }
@@ -722,7 +727,6 @@ 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;
        }
 
@@ -783,104 +787,19 @@ qla24xx_chip_diag(scsi_qla_host_t *ha)
        return rval;
 }
 
-void
+static 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;
-       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) {
+       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
                qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for "
-                   "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));
+                   "firmware dump!!!\n", ha->fw_dump24_len / 1024);
 }
 
 /**
@@ -902,6 +821,9 @@ 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)
@@ -969,9 +891,6 @@ 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
@@ -1083,10 +1002,6 @@ 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);
 }
@@ -1275,7 +1190,8 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
                        rval = QLA_FUNCTION_FAILED;
 
                        if (atomic_read(&ha->loop_down_timer) &&
-                           fw_state != FSTATE_READY) {
+                           (fw_state >= FSTATE_LOSS_OF_SYNC ||
+                               fw_state == FSTATE_WAIT_AL_PA)) {
                                /* Loop down. Timeout on min_wait for states
                                 * other than Wait for Login.
                                 */
@@ -1584,9 +1500,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 * 2]);
+                                           qla2x00_model_name[index]);
                                        ha->model_desc =
-                                           qla2x00_model_name[index * 2 + 1];
+                                           qla2x00_model_desc[index];
                                } else {
                                        strcpy(ha->model_number, "QLA23xx");
                                }
@@ -1624,12 +1540,6 @@ 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) {
                /*
@@ -1643,8 +1553,6 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
        /*
         * Set host adapter parameters.
         */
-       if (nv->host_p[0] & BIT_7)
-               extended_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))
@@ -1653,7 +1561,6 @@ 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;
@@ -1747,8 +1654,6 @@ 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));
@@ -1769,6 +1674,14 @@ 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)
 {
@@ -1792,7 +1705,7 @@ qla2x00_rport_del(void *data)
  *
  * Returns a pointer to the allocated fcport, or NULL, if none available.
  */
-static fc_port_t *
+fc_port_t *
 qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
 {
        fc_port_t *fcport;
@@ -1806,10 +1719,13 @@ 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);
 }
@@ -1869,9 +1785,6 @@ 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))) {
 
@@ -2135,6 +2048,10 @@ qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
            PORT_RETRY_TIME);
        fcport->flags &= ~FCF_LOGIN_NEEDED;
 
+       if (fcport->port_type == FCT_INITIATOR ||
+           fcport->port_type == FCT_BROADCAST)
+               fcport->device_type = TYPE_PROCESSOR;
+
        atomic_set(&fcport->state, FCS_ONLINE);
 
        if (ha->flags.init_done)
@@ -2205,7 +2122,7 @@ 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_QLA54XX(ha))
+       if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
                loop_id = NPH_F_PORT;
        else
                loop_id = SNS_FL_PORT;
@@ -2231,7 +2148,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_QLA54XX(ha))
+               if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
                        loop_id = NPH_SNS;
                else
                        loop_id = SIMPLE_NAME_SERVER;
@@ -2349,7 +2266,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
                        }
 
                        /* Remove device from the new list and add it to DB */
-                       list_move_tail(&fcport->list, &ha->fcports);
+                       list_del(&fcport->list);
+                       list_add_tail(&fcport->list, &ha->fcports);
 
                        /* Login and update database */
                        qla2x00_fabric_dev_login(ha, fcport, &next_loopid);
@@ -2588,7 +2506,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
  * Context:
  *     Kernel context.
  */
-static int
+int
 qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev)
 {
        int     rval;
@@ -2662,6 +2580,7 @@ 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;
@@ -2717,6 +2636,17 @@ 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:
@@ -2734,6 +2664,10 @@ 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 ||
@@ -2947,13 +2881,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 *ha, uint16_t loop_id)
 {
        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(ha, loop_id, mb, BIT_0);
        if (rval == QLA_SUCCESS) {
                /* Interrogate mailbox registers for any errors */
                if (mb[0] == MBS_COMMAND_ERROR)
@@ -3063,7 +2997,6 @@ 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;
@@ -3120,16 +3053,6 @@ 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)) {
@@ -3150,14 +3073,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;
                        }
@@ -3171,7 +3094,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);
@@ -3206,7 +3129,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
 
                        spin_lock_irqsave(&ha->hardware_lock, flags);
 
-                       if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) {
+                       if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) {
                                /*
                                 * Disable SRAM, Instruction RAM and GP RAM
                                 * parity.
@@ -3222,7 +3145,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
 
                        spin_lock_irqsave(&ha->hardware_lock, flags);
 
-                       if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) {
+                       if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) {
                                /* Enable proper parity */
                                if (IS_QLA2300(ha))
                                        /* SRAM parity */
@@ -3247,7 +3170,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);
@@ -3271,7 +3194,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
 
                DEBUG(printk("%s(): Configure loop done, status = 0x%x\n",
                                __func__,
-                               status));
+                               status);)
        }
        return (status);
 }
@@ -3335,12 +3258,8 @@ 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;
-       ha->vpd_size = FA_NVRAM_VPD_SIZE;
-       ha->vpd_base = FA_NVRAM_VPD0_ADDR;
-       if (PCI_FUNC(ha->pdev->devfn)) {
+       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;
@@ -3391,6 +3310,7 @@ 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 =
@@ -3419,7 +3339,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
                *dptr1++ = *dptr2++;
 
        icb->login_retry_count = nv->login_retry_count;
-       icb->link_down_on_nos = nv->link_down_on_nos;
+       icb->link_down_timeout = nv->link_down_timeout;
 
        /* Copy 2nd segment. */
        dptr1 = (uint8_t *)&icb->interrupt_delay_timer;
@@ -3448,18 +3368,12 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
 
                index = (ha->pdev->subsystem_device & 0xff);
                if (index < QLA_MODEL_NAMES)
-                       ha->model_desc = qla2x00_model_name[index * 2 + 1];
+                       ha->model_desc = qla2x00_model_desc[index];
        } 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 & __constant_cpu_to_le32(BIT_14)) == 0) {
+       if ((icb->firmware_options_1 & BIT_14) == 0) {
                /*
                 * Firmware will apply the following mask if the nodename was
                 * not provided.
@@ -3474,10 +3388,9 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
        ha->flags.enable_lip_full_login = 1;
        ha->flags.enable_target_reset = 1;
        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;
+       ha->operating_mode =
+           (icb->firmware_options_2 & (BIT_6 | BIT_5 | BIT_4)) >> 4;
 
        memcpy(ha->fw_seriallink_options24, nv->seriallink_options,
            sizeof(ha->fw_seriallink_options24));
@@ -3552,8 +3465,6 @@ 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));
@@ -3574,7 +3485,134 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
        return (rval);
 }
 
-static int
+#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
 qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
 {
        int     rval;
@@ -3656,7 +3694,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
        return rval;
 }
 
-#define QLA_FW_URL "ftp://ftp.qlogic.com/outgoing/linux/firmware/"
+#else  /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
 
 int
 qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
@@ -3671,8 +3709,6 @@ 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;
        }
 
@@ -3774,13 +3810,7 @@ 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");
-               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);
+               return QLA_FUNCTION_FAILED;
        }
 
        rval = QLA_SUCCESS;
@@ -3866,3 +3896,4 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
 fail_fw_integrity:
        return QLA_FUNCTION_FAILED;
 }
+#endif