Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[cascardo/linux.git] / drivers / scsi / qla2xxx / qla_os.c
index 9306259..b78919a 100644 (file)
@@ -24,7 +24,7 @@ char qla2x00_version_str[40];
 /*
  * SRB allocation cache
  */
-static kmem_cache_t *srb_cachep;
+static struct kmem_cache *srb_cachep;
 
 /*
  * Ioctl related information.
@@ -39,14 +39,14 @@ MODULE_PARM_DESC(ql2xlogintimeout,
 int qlport_down_retry = 30;
 module_param(qlport_down_retry, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(qlport_down_retry,
-               "Maximum number of command retries to a port that returns"
+               "Maximum number of command retries to a port that returns "
                "a PORT-DOWN status.");
 
 int ql2xplogiabsentdevice;
 module_param(ql2xplogiabsentdevice, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(ql2xplogiabsentdevice,
                "Option to enable PLOGI to devices that are not present after "
-               "a Fabric scan.  This is needed for several broken switches."
+               "a Fabric scan.  This is needed for several broken switches. "
                "Default is 0 - no PLOGI. 1 - perfom PLOGI.");
 
 int ql2xloginretrycount = 0;
@@ -54,6 +54,19 @@ module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(ql2xloginretrycount,
                "Specify an alternate value for the NVRAM login retry count.");
 
+int ql2xallocfwdump = 1;
+module_param(ql2xallocfwdump, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xallocfwdump,
+               "Option to enable allocation of memory for a firmware dump "
+               "during HBA initialization.  Memory allocation requirements "
+               "vary by ISP type.  Default is 1 - allocate memory.");
+
+int ql2xextended_error_logging;
+module_param(ql2xextended_error_logging, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(ql2xextended_error_logging,
+               "Option to enable extended error logging, "
+               "Default is 0 - no logging. 1 - log errors.");
+
 static void qla2x00_free_device(scsi_qla_host_t *);
 
 static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha);
@@ -64,11 +77,26 @@ MODULE_PARM_DESC(ql2xfdmienable,
                "Enables FDMI registratons "
                "Default is 0 - no FDMI. 1 - perfom FDMI.");
 
+#define MAX_Q_DEPTH    32
+static int ql2xmaxqdepth = MAX_Q_DEPTH;
+module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(ql2xmaxqdepth,
+               "Maximum queue depth to report for target devices.");
+
+int ql2xqfullrampup = 120;
+module_param(ql2xqfullrampup, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(ql2xqfullrampup,
+               "Number of seconds to wait to begin to ramp-up the queue "
+               "depth for a device after a queue-full condition has been "
+               "detected.  Default is 120 seconds.");
+
 /*
  * SCSI host template entry points
  */
 static int qla2xxx_slave_configure(struct scsi_device * device);
 static int qla2xxx_slave_alloc(struct scsi_device *);
+static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time);
+static void qla2xxx_scan_start(struct Scsi_Host *);
 static void qla2xxx_slave_destroy(struct scsi_device *);
 static int qla2x00_queuecommand(struct scsi_cmnd *cmd,
                void (*fn)(struct scsi_cmnd *));
@@ -98,6 +126,8 @@ static struct scsi_host_template qla2x00_driver_template = {
 
        .slave_alloc            = qla2xxx_slave_alloc,
        .slave_destroy          = qla2xxx_slave_destroy,
+       .scan_finished          = qla2xxx_scan_finished,
+       .scan_start             = qla2xxx_scan_start,
        .change_queue_depth     = qla2x00_change_queue_depth,
        .change_queue_type      = qla2x00_change_queue_type,
        .this_id                = -1,
@@ -127,6 +157,8 @@ static struct scsi_host_template qla24xx_driver_template = {
 
        .slave_alloc            = qla2xxx_slave_alloc,
        .slave_destroy          = qla2xxx_slave_destroy,
+       .scan_finished          = qla2xxx_scan_finished,
+       .scan_start             = qla2xxx_scan_start,
        .change_queue_depth     = qla2x00_change_queue_depth,
        .change_queue_type      = qla2x00_change_queue_type,
        .this_id                = -1,
@@ -261,7 +293,7 @@ qla24xx_pci_info_str(struct scsi_qla_host *ha, char *str)
        return str;
 }
 
-char *
+static char *
 qla2x00_fw_version_str(struct scsi_qla_host *ha, char *str)
 {
        char un_str[10];
@@ -299,7 +331,7 @@ qla2x00_fw_version_str(struct scsi_qla_host *ha, char *str)
        return (str);
 }
 
-char *
+static char *
 qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str)
 {
        sprintf(str, "%d.%02d.%02d ", ha->fw_major_version,
@@ -576,6 +608,23 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha)
        return (return_status);
 }
 
+static void
+qla2x00_block_error_handler(struct scsi_cmnd *cmnd)
+{
+       struct Scsi_Host *shost = cmnd->device->host;
+       struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
+       unsigned long flags;
+
+       spin_lock_irqsave(shost->host_lock, flags);
+       while (rport->port_state == FC_PORTSTATE_BLOCKED) {
+               spin_unlock_irqrestore(shost->host_lock, flags);
+               msleep(1000);
+               spin_lock_irqsave(shost->host_lock, flags);
+       }
+       spin_unlock_irqrestore(shost->host_lock, flags);
+       return;
+}
+
 /**************************************************************************
 * qla2xxx_eh_abort
 *
@@ -591,7 +640,7 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha)
 * Note:
 *    Only return FAILED if command not returned by firmware.
 **************************************************************************/
-int
+static int
 qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 {
        scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
@@ -602,6 +651,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
        unsigned long flags;
        int wait = 0;
 
+       qla2x00_block_error_handler(cmd);
+
        if (!CMD_SP(cmd))
                return SUCCESS;
 
@@ -624,7 +675,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 
                DEBUG2(printk("%s(%ld): aborting sp %p from RISC. pid=%ld.\n",
                    __func__, ha->host_no, sp, serial));
-               DEBUG3(qla2x00_print_scsi_cmd(cmd);)
+               DEBUG3(qla2x00_print_scsi_cmd(cmd));
 
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
                if (ha->isp_ops.abort_command(ha, sp)) {
@@ -726,24 +777,24 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
 *    SUCCESS/FAILURE (defined as macro in scsi.h).
 *
 **************************************************************************/
-int
+static int
 qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
 {
        scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
        fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
-       srb_t *sp;
        int ret;
        unsigned int id, lun;
        unsigned long serial;
 
+       qla2x00_block_error_handler(cmd);
+
        ret = FAILED;
 
        id = cmd->device->id;
        lun = cmd->device->lun;
        serial = cmd->serial_number;
 
-       sp = (srb_t *) CMD_SP(cmd);
-       if (!sp || !fcport)
+       if (!fcport)
                return ret;
 
        qla_printk(KERN_INFO, ha,
@@ -766,7 +817,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
 #endif
        } else {
                DEBUG2(printk(KERN_INFO
-                   "%s failed: loop not ready\n",__func__);)
+                   "%s failed: loop not ready\n",__func__));
        }
 
        if (ret == FAILED) {
@@ -857,24 +908,24 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
 *    SUCCESS/FAILURE (defined as macro in scsi.h).
 *
 **************************************************************************/
-int
+static int
 qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
 {
        scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
        fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
-       srb_t *sp;
        int ret;
        unsigned int id, lun;
        unsigned long serial;
 
+       qla2x00_block_error_handler(cmd);
+
        ret = FAILED;
 
        id = cmd->device->id;
        lun = cmd->device->lun;
        serial = cmd->serial_number;
 
-       sp = (srb_t *) CMD_SP(cmd);
-       if (!sp || !fcport)
+       if (!fcport)
                return ret;
 
        qla_printk(KERN_INFO, ha,
@@ -918,24 +969,24 @@ eh_bus_reset_done:
 *
 * Note:
 **************************************************************************/
-int
+static int
 qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
 {
        scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
        fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
-       srb_t *sp;
        int ret;
        unsigned int id, lun;
        unsigned long serial;
 
+       qla2x00_block_error_handler(cmd);
+
        ret = FAILED;
 
        id = cmd->device->id;
        lun = cmd->device->lun;
        serial = cmd->serial_number;
 
-       sp = (srb_t *) CMD_SP(cmd);
-       if (!sp || !fcport)
+       if (!fcport)
                return ret;
 
        qla_printk(KERN_INFO, ha,
@@ -988,48 +1039,49 @@ eh_host_reset_lock:
 static int
 qla2x00_loop_reset(scsi_qla_host_t *ha)
 {
-       int status = QLA_SUCCESS;
+       int ret;
        struct fc_port *fcport;
 
+       if (ha->flags.enable_lip_full_login) {
+               ret = qla2x00_full_login_lip(ha);
+               if (ret != QLA_SUCCESS) {
+                       DEBUG2_3(printk("%s(%ld): bus_reset failed: "
+                           "full_login_lip=%d.\n", __func__, ha->host_no,
+                           ret));
+               }
+               atomic_set(&ha->loop_state, LOOP_DOWN);
+               atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
+               qla2x00_mark_all_devices_lost(ha, 0);
+               qla2x00_wait_for_loop_ready(ha);
+       }
+
        if (ha->flags.enable_lip_reset) {
-               status = qla2x00_lip_reset(ha);
+               ret = qla2x00_lip_reset(ha);
+               if (ret != QLA_SUCCESS) {
+                       DEBUG2_3(printk("%s(%ld): bus_reset failed: "
+                           "lip_reset=%d.\n", __func__, ha->host_no, ret));
+               }
+               qla2x00_wait_for_loop_ready(ha);
        }
 
-       if (status == QLA_SUCCESS && ha->flags.enable_target_reset) {
+       if (ha->flags.enable_target_reset) {
                list_for_each_entry(fcport, &ha->fcports, list) {
                        if (fcport->port_type != FCT_TARGET)
                                continue;
 
-                       status = qla2x00_device_reset(ha, fcport);
-                       if (status != QLA_SUCCESS)
-                               break;
+                       ret = qla2x00_device_reset(ha, fcport);
+                       if (ret != QLA_SUCCESS) {
+                               DEBUG2_3(printk("%s(%ld): bus_reset failed: "
+                                   "target_reset=%d d_id=%x.\n", __func__,
+                                   ha->host_no, ret, fcport->d_id.b24));
+                       }
                }
        }
 
-       if (status == QLA_SUCCESS &&
-               ((!ha->flags.enable_target_reset &&
-                 !ha->flags.enable_lip_reset) ||
-               ha->flags.enable_lip_full_login)) {
-
-               status = qla2x00_full_login_lip(ha);
-       }
-
        /* Issue marker command only when we are going to start the I/O */
        ha->marker_needed = 1;
 
-       if (status) {
-               /* Empty */
-               DEBUG2_3(printk("%s(%ld): **** FAILED ****\n",
-                               __func__,
-                               ha->host_no);)
-       } else {
-               /* Empty */
-               DEBUG3(printk("%s(%ld): exiting normally.\n",
-                               __func__,
-                               ha->host_no);)
-       }
-
-       return(status);
+       return QLA_SUCCESS;
 }
 
 /*
@@ -1072,9 +1124,9 @@ qla2xxx_slave_configure(struct scsi_device *sdev)
        struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
 
        if (sdev->tagged_supported)
-               scsi_activate_tcq(sdev, 32);
+               scsi_activate_tcq(sdev, ha->max_q_depth);
        else
-               scsi_deactivate_tcq(sdev, 32);
+               scsi_deactivate_tcq(sdev, ha->max_q_depth);
 
        rport->dev_loss_tmo = ha->port_down_retry_count + 5;
 
@@ -1321,20 +1373,42 @@ qla24xx_disable_intrs(scsi_qla_host_t *ha)
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 }
 
+static void
+qla2xxx_scan_start(struct Scsi_Host *shost)
+{
+       scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata;
+
+       set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
+       set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
+       set_bit(RSCN_UPDATE, &ha->dpc_flags);
+}
+
+static int
+qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+       scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata;
+
+       if (!ha->host)
+               return 1;
+       if (time > ha->loop_reset_delay * HZ)
+               return 1;
+
+       return atomic_read(&ha->loop_state) == LOOP_READY;
+}
+
 /*
  * PCI driver interface
  */
-static int qla2x00_probe_one(struct pci_dev *pdev)
+static int __devinit
+qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int     ret = -ENODEV;
        device_reg_t __iomem *reg;
        struct Scsi_Host *host;
        scsi_qla_host_t *ha;
        unsigned long   flags = 0;
-       unsigned long   wait_switch = 0;
        char pci_info[20];
        char fw_str[30];
-       fc_port_t *fcport;
        struct scsi_host_template *sht;
 
        if (pci_enable_device(pdev))
@@ -1342,7 +1416,9 @@ static int qla2x00_probe_one(struct pci_dev *pdev)
 
        sht = &qla2x00_driver_template;
        if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
-           pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432)
+           pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
+           pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||
+           pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432)
                sht = &qla24xx_driver_template;
        host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
        if (host == NULL) {
@@ -1377,9 +1453,13 @@ static int qla2x00_probe_one(struct pci_dev *pdev)
        ha->prev_topology = 0;
        ha->init_cb_size = sizeof(init_cb_t);
        ha->mgmt_svr_loop_id = MANAGEMENT_SERVER;
-       ha->link_data_rate = LDR_UNKNOWN;
+       ha->link_data_rate = PORT_SPEED_UNKNOWN;
        ha->optrom_size = OPTROM_SIZE_2300;
 
+       ha->max_q_depth = MAX_Q_DEPTH;
+       if (ql2xmaxqdepth != 0 && ql2xmaxqdepth <= 0xffffU)
+               ha->max_q_depth = ql2xmaxqdepth;
+
        /* Assign ISP specific operations. */
        ha->isp_ops.pci_config          = qla2100_pci_config;
        ha->isp_ops.reset_chip          = qla2x00_reset_chip;
@@ -1405,9 +1485,9 @@ static int qla2x00_probe_one(struct pci_dev *pdev)
        ha->isp_ops.read_nvram          = qla2x00_read_nvram_data;
        ha->isp_ops.write_nvram         = qla2x00_write_nvram_data;
        ha->isp_ops.fw_dump             = qla2100_fw_dump;
-       ha->isp_ops.ascii_fw_dump       = qla2100_ascii_fw_dump;
        ha->isp_ops.read_optrom         = qla2x00_read_optrom_data;
        ha->isp_ops.write_optrom        = qla2x00_write_optrom_data;
+       ha->isp_ops.get_flash_version   = qla2x00_get_flash_version;
        if (IS_QLA2100(ha)) {
                host->max_id = MAX_TARGETS_2100;
                ha->mbx_count = MAILBOX_REGISTER_COUNT_2100;
@@ -1432,7 +1512,6 @@ static int qla2x00_probe_one(struct pci_dev *pdev)
                ha->isp_ops.pci_config = qla2300_pci_config;
                ha->isp_ops.intr_handler = qla2300_intr_handler;
                ha->isp_ops.fw_dump = qla2300_fw_dump;
-               ha->isp_ops.ascii_fw_dump = qla2300_ascii_fw_dump;
                ha->isp_ops.beacon_on = qla2x00_beacon_on;
                ha->isp_ops.beacon_off = qla2x00_beacon_off;
                ha->isp_ops.beacon_blink = qla2x00_beacon_blink;
@@ -1469,12 +1548,12 @@ static int qla2x00_probe_one(struct pci_dev *pdev)
                ha->isp_ops.read_nvram = qla24xx_read_nvram_data;
                ha->isp_ops.write_nvram = qla24xx_write_nvram_data;
                ha->isp_ops.fw_dump = qla24xx_fw_dump;
-               ha->isp_ops.ascii_fw_dump = qla24xx_ascii_fw_dump;
                ha->isp_ops.read_optrom = qla24xx_read_optrom_data;
                ha->isp_ops.write_optrom = qla24xx_write_optrom_data;
                ha->isp_ops.beacon_on = qla24xx_beacon_on;
                ha->isp_ops.beacon_off = qla24xx_beacon_off;
                ha->isp_ops.beacon_blink = qla24xx_beacon_blink;
+               ha->isp_ops.get_flash_version = qla24xx_get_flash_version;
                ha->gid_list_info_size = 8;
                ha->optrom_size = OPTROM_SIZE_24XX;
        }
@@ -1489,14 +1568,6 @@ static int qla2x00_probe_one(struct pci_dev *pdev)
        INIT_LIST_HEAD(&ha->list);
        INIT_LIST_HEAD(&ha->fcports);
 
-       /*
-        * These locks are used to prevent more than one CPU
-        * from modifying the queue at the same time. The
-        * higher level "host_lock" will reduce most
-        * contention for these locks.
-        */
-       spin_lock_init(&ha->mbx_reg_lock);
-
        qla2x00_config_dma_addressing(ha);
        if (qla2x00_mem_alloc(ha)) {
                qla_printk(KERN_WARNING, ha,
@@ -1540,15 +1611,9 @@ static int qla2x00_probe_one(struct pci_dev *pdev)
        host->max_lun = MAX_LUNS;
        host->transportt = qla2xxx_transport_template;
 
-       ret = request_irq(pdev->irq, ha->isp_ops.intr_handler,
-           IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha);
-       if (ret) {
-               qla_printk(KERN_WARNING, ha,
-                   "Failed to reserve interrupt %d already in use.\n",
-                   pdev->irq);
+       ret = qla2x00_request_irqs(ha);
+       if (ret)
                goto probe_failed;
-       }
-       host->irq = pdev->irq;
 
        /* Initialized the timer */
        qla2x00_start_timer(ha, qla2x00_timer, WATCH_INTERVAL);
@@ -1584,30 +1649,19 @@ static int qla2x00_probe_one(struct pci_dev *pdev)
 
        ha->isp_ops.enable_intrs(ha);
 
-       /* v2.19.5b6 */
-       /*
-        * Wait around max loop_reset_delay secs for the devices to come
-        * on-line. We don't want Linux scanning before we are ready.
-        *
-        */
-       for (wait_switch = jiffies + (ha->loop_reset_delay * HZ);
-           time_before(jiffies,wait_switch) &&
-            !(ha->device_flags & (DFLG_NO_CABLE | DFLG_FABRIC_DEVICES))
-            && (ha->device_flags & SWITCH_FOUND) ;) {
-
-               qla2x00_check_fabric_devices(ha);
-
-               msleep(10);
-       }
-
        pci_set_drvdata(pdev, ha);
+
        ha->flags.init_done = 1;
+       ha->flags.online = 1;
+
        num_hosts++;
 
        ret = scsi_add_host(host, &pdev->dev);
        if (ret)
                goto probe_failed;
 
+       scsi_scan_host(host);
+
        qla2x00_alloc_sysfs_attr(ha);
 
        qla2x00_init_host_attr(ha);
@@ -1622,10 +1676,6 @@ static int qla2x00_probe_one(struct pci_dev *pdev)
            ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no,
            ha->isp_ops.fw_version_str(ha, fw_str));
 
-       /* Go with fc_rport registration. */
-       list_for_each_entry(fcport, &ha->fcports, list)
-               qla2x00_reg_remote_port(ha, fcport);
-
        return 0;
 
 probe_failed:
@@ -1640,7 +1690,8 @@ probe_out:
        return ret;
 }
 
-static void qla2x00_remove_one(struct pci_dev *pdev)
+static void __devexit
+qla2x00_remove_one(struct pci_dev *pdev)
 {
        scsi_qla_host_t *ha;
 
@@ -1656,6 +1707,7 @@ static void qla2x00_remove_one(struct pci_dev *pdev)
 
        scsi_host_put(ha->host);
 
+       pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);
 }
 
@@ -1678,8 +1730,13 @@ qla2x00_free_device(scsi_qla_host_t *ha)
                kthread_stop(t);
        }
 
+       if (ha->eft)
+               qla2x00_trace_control(ha, TC_DISABLE, 0, 0);
+
+       ha->flags.online = 0;
+
        /* Stop currently executing firmware. */
-       qla2x00_stop_firmware(ha);
+       qla2x00_try_to_stop_firmware(ha);
 
        /* turn-off interrupts on the card */
        if (ha->interrupts_on)
@@ -1687,18 +1744,12 @@ qla2x00_free_device(scsi_qla_host_t *ha)
 
        qla2x00_mem_free(ha);
 
-       ha->flags.online = 0;
-
-       /* Detach interrupts */
-       if (ha->host->irq)
-               free_irq(ha->host->irq, ha);
+       qla2x00_free_irqs(ha);
 
        /* release io space registers  */
        if (ha->iobase)
                iounmap(ha->iobase);
        pci_release_regions(ha->pdev);
-
-       pci_disable_device(ha->pdev);
 }
 
 static inline void
@@ -1899,17 +1950,6 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
                }
                memset(ha->init_cb, 0, ha->init_cb_size);
 
-               /* Allocate ioctl related memory. */
-               if (qla2x00_alloc_ioctl_mem(ha)) {
-                       qla_printk(KERN_WARNING, ha,
-                           "Memory Allocation failed - ioctl_mem\n");
-
-                       qla2x00_mem_free(ha);
-                       msleep(100);
-
-                       continue;
-               }
-
                if (qla2x00_allocate_sp_pool(ha)) {
                        qla_printk(KERN_WARNING, ha,
                            "Memory Allocation failed - "
@@ -1972,6 +2012,26 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
                                continue;
                        }
                        memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt));
+
+                       if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+                               /*
+                                * Get consistent memory allocated for SFP
+                                * block.
+                                */
+                               ha->sfp_data = dma_pool_alloc(ha->s_dma_pool,
+                                   GFP_KERNEL, &ha->sfp_data_dma);
+                               if (ha->sfp_data == NULL) {
+                                       qla_printk(KERN_WARNING, ha,
+                                           "Memory Allocation failed - "
+                                           "sfp_data\n");
+
+                                       qla2x00_mem_free(ha);
+                                       msleep(100);
+
+                                       continue;
+                               }
+                               memset(ha->sfp_data, 0, SFP_BLOCK_SIZE);
+                       }
                }
 
                /* Done all allocations without any error. */
@@ -2006,12 +2066,16 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
                return;
        }
 
-       /* free ioctl memory */
-       qla2x00_free_ioctl_mem(ha);
-
        /* free sp pool */
        qla2x00_free_sp_pool(ha);
 
+       if (ha->fw_dump) {
+               if (ha->eft)
+                       dma_free_coherent(&ha->pdev->dev,
+                           ntohl(ha->fw_dump->eft_size), ha->eft, ha->eft_dma);
+               vfree(ha->fw_dump);
+       }
+
        if (ha->sns_cmd)
                dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt),
                    ha->sns_cmd, ha->sns_cmd_dma);
@@ -2020,6 +2084,9 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
                dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt),
                    ha->ct_sns, ha->ct_sns_dma);
 
+       if (ha->sfp_data)
+               dma_pool_free(ha->s_dma_pool, ha->sfp_data, ha->sfp_data_dma);
+
        if (ha->ms_iocb)
                dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
 
@@ -2043,6 +2110,8 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
                    (ha->request_q_length + 1) * sizeof(request_t),
                    ha->request_ring, ha->request_dma);
 
+       ha->eft = NULL;
+       ha->eft_dma = 0;
        ha->sns_cmd = NULL;
        ha->sns_cmd_dma = 0;
        ha->ct_sns = NULL;
@@ -2071,13 +2140,9 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
        }
        INIT_LIST_HEAD(&ha->fcports);
 
-       vfree(ha->fw_dump);
-       vfree(ha->fw_dump_buffer);
-
        ha->fw_dump = NULL;
        ha->fw_dumped = 0;
        ha->fw_dump_reading = 0;
-       ha->fw_dump_buffer = NULL;
 
        vfree(ha->optrom_buffer);
 }
@@ -2215,9 +2280,6 @@ qla2x00_do_dpc(void *data)
 
                        next_loopid = 0;
                        list_for_each_entry(fcport, &ha->fcports, list) {
-                               if (fcport->port_type != FCT_TARGET)
-                                       continue;
-
                                /*
                                 * If the port is not ONLINE then try to login
                                 * to it if we haven't run out of retries.
@@ -2544,14 +2606,20 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout)
 #define FW_ISP2322     3
 #define FW_ISP24XX     4
 
+#define FW_FILE_ISP21XX        "ql2100_fw.bin"
+#define FW_FILE_ISP22XX        "ql2200_fw.bin"
+#define FW_FILE_ISP2300        "ql2300_fw.bin"
+#define FW_FILE_ISP2322        "ql2322_fw.bin"
+#define FW_FILE_ISP24XX        "ql2400_fw.bin"
+
 static DECLARE_MUTEX(qla_fw_lock);
 
 static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
-       { .name = "ql2100_fw.bin", .segs = { 0x1000, 0 }, },
-       { .name = "ql2200_fw.bin", .segs = { 0x1000, 0 }, },
-       { .name = "ql2300_fw.bin", .segs = { 0x800, 0 }, },
-       { .name = "ql2322_fw.bin", .segs = { 0x800, 0x1c000, 0x1e000, 0 }, },
-       { .name = "ql2400_fw.bin", },
+       { .name = FW_FILE_ISP21XX, .segs = { 0x1000, 0 }, },
+       { .name = FW_FILE_ISP22XX, .segs = { 0x1000, 0 }, },
+       { .name = FW_FILE_ISP2300, .segs = { 0x800, 0 }, },
+       { .name = FW_FILE_ISP2322, .segs = { 0x800, 0x1c000, 0x1e000, 0 }, },
+       { .name = FW_FILE_ISP24XX, },
 };
 
 struct fw_blob *
@@ -2617,40 +2685,16 @@ static struct pci_device_id qla2xxx_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
 
-static int __devinit
-qla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-       return qla2x00_probe_one(pdev);
-}
-
-static void __devexit
-qla2xxx_remove_one(struct pci_dev *pdev)
-{
-       qla2x00_remove_one(pdev);
-}
-
 static struct pci_driver qla2xxx_pci_driver = {
        .name           = QLA2XXX_DRIVER_NAME,
        .driver         = {
                .owner          = THIS_MODULE,
        },
        .id_table       = qla2xxx_pci_tbl,
-       .probe          = qla2xxx_probe_one,
-       .remove         = __devexit_p(qla2xxx_remove_one),
+       .probe          = qla2x00_probe_one,
+       .remove         = __devexit_p(qla2x00_remove_one),
 };
 
-static inline int
-qla2x00_pci_module_init(void)
-{
-       return pci_module_init(&qla2xxx_pci_driver);
-}
-
-static inline void
-qla2x00_pci_module_exit(void)
-{
-       pci_unregister_driver(&qla2xxx_pci_driver);
-}
-
 /**
  * qla2x00_module_init - Module initialization.
  **/
@@ -2670,16 +2714,16 @@ qla2x00_module_init(void)
 
        /* Derive version string. */
        strcpy(qla2x00_version_str, QLA2XXX_VERSION);
-#if DEBUG_QLA2100
-       strcat(qla2x00_version_str, "-debug");
-#endif
+       if (ql2xextended_error_logging)
+               strcat(qla2x00_version_str, "-debug");
+
        qla2xxx_transport_template =
            fc_attach_transport(&qla2xxx_transport_functions);
        if (!qla2xxx_transport_template)
                return -ENODEV;
 
        printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n");
-       ret = qla2x00_pci_module_init();
+       ret = pci_register_driver(&qla2xxx_pci_driver);
        if (ret) {
                kmem_cache_destroy(srb_cachep);
                fc_release_transport(qla2xxx_transport_template);
@@ -2693,7 +2737,7 @@ qla2x00_module_init(void)
 static void __exit
 qla2x00_module_exit(void)
 {
-       qla2x00_pci_module_exit();
+       pci_unregister_driver(&qla2xxx_pci_driver);
        qla2x00_release_firmware();
        kmem_cache_destroy(srb_cachep);
        fc_release_transport(qla2xxx_transport_template);
@@ -2706,3 +2750,8 @@ MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic Fibre Channel HBA Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(QLA2XXX_VERSION);
+MODULE_FIRMWARE(FW_FILE_ISP21XX);
+MODULE_FIRMWARE(FW_FILE_ISP22XX);
+MODULE_FIRMWARE(FW_FILE_ISP2300);
+MODULE_FIRMWARE(FW_FILE_ISP2322);
+MODULE_FIRMWARE(FW_FILE_ISP24XX);