Merge branch 'linus'
[powerpc.git] / drivers / scsi / qla2xxx / qla_os.c
index 3f20d76..68f5d24 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.
@@ -61,9 +61,9 @@ MODULE_PARM_DESC(ql2xallocfwdump,
                "during HBA initialization.  Memory allocation requirements "
                "vary by ISP type.  Default is 1 - allocate memory.");
 
-int qla2_extended_error_logging;
-module_param(qla2_extended_error_logging, int, S_IRUGO|S_IRUSR);
-MODULE_PARM_DESC(qla2_extended_error_logging,
+int ql2xextended_error_logging;
+module_param(ql2xextended_error_logging, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xextended_error_logging,
                "Option to enable extended error logging, "
                "Default is 0 - no logging. 1 - log errors.");
 
@@ -77,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 *));
@@ -111,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,
@@ -274,7 +291,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];
@@ -312,7 +329,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,
@@ -621,7 +638,7 @@ qla2x00_block_error_handler(struct scsi_cmnd *cmnd)
 * 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);
@@ -758,7 +775,7 @@ 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);
@@ -889,7 +906,7 @@ 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);
@@ -950,7 +967,7 @@ 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);
@@ -1020,48 +1037,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;
 }
 
 /*
@@ -1104,9 +1122,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;
 
@@ -1353,6 +1371,29 @@ 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
  */
@@ -1364,10 +1405,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        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))
@@ -1375,7 +1414,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
        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) {
@@ -1413,6 +1454,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        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;
@@ -1440,6 +1485,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        ha->isp_ops.fw_dump             = qla2100_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;
@@ -1505,6 +1551,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                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;
        }
@@ -1519,14 +1566,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        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,
@@ -1570,15 +1609,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        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);
@@ -1614,30 +1647,19 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
        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);
@@ -1652,10 +1674,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
            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:
@@ -1712,8 +1730,10 @@ qla2x00_free_device(scsi_qla_host_t *ha)
        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)
@@ -1721,11 +1741,7 @@ 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)
@@ -2697,7 +2713,7 @@ qla2x00_module_init(void)
 
        /* Derive version string. */
        strcpy(qla2x00_version_str, QLA2XXX_VERSION);
-       if (qla2_extended_error_logging)
+       if (ql2xextended_error_logging)
                strcat(qla2x00_version_str, "-debug");
 
        qla2xxx_transport_template =