Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / scsi / qla2xxx / qla_os.c
index 0351d380c2d7b1790c93d5655ff856b66d59cb74..aba1e6d480669ff6e9f932e55e6364f397d050df 100644 (file)
@@ -105,13 +105,12 @@ static int qla2xxx_eh_abort(struct scsi_cmnd *);
 static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
 static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
 static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
-static int qla2x00_loop_reset(scsi_qla_host_t *ha);
 static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *);
 
 static int qla2x00_change_queue_depth(struct scsi_device *, int);
 static int qla2x00_change_queue_type(struct scsi_device *, int);
 
-struct scsi_host_template qla2x00_driver_template = {
+static struct scsi_host_template qla2x00_driver_template = {
        .module                 = THIS_MODULE,
        .name                   = QLA2XXX_DRIVER_NAME,
        .queuecommand           = qla2x00_queuecommand,
@@ -179,13 +178,6 @@ struct scsi_transport_template *qla2xxx_transport_vport_template = NULL;
  * Timer routines
  */
 
-void qla2x00_timer(scsi_qla_host_t *);
-
-__inline__ void qla2x00_start_timer(scsi_qla_host_t *,
-    void *, unsigned long);
-static __inline__ void qla2x00_restart_timer(scsi_qla_host_t *, unsigned long);
-__inline__ void qla2x00_stop_timer(scsi_qla_host_t *);
-
 __inline__ void
 qla2x00_start_timer(scsi_qla_host_t *ha, void *func, unsigned long interval)
 {
@@ -203,7 +195,7 @@ qla2x00_restart_timer(scsi_qla_host_t *ha, unsigned long interval)
        mod_timer(&ha->timer, jiffies + interval * HZ);
 }
 
-__inline__ void
+static __inline__ void
 qla2x00_stop_timer(scsi_qla_host_t *ha)
 {
        del_timer_sync(&ha->timer);
@@ -214,12 +206,11 @@ static int qla2x00_do_dpc(void *data);
 
 static void qla2x00_rst_aen(scsi_qla_host_t *);
 
-uint8_t qla2x00_mem_alloc(scsi_qla_host_t *);
-void qla2x00_mem_free(scsi_qla_host_t *ha);
+static uint8_t qla2x00_mem_alloc(scsi_qla_host_t *);
+static void qla2x00_mem_free(scsi_qla_host_t *ha);
 static int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha);
 static void qla2x00_free_sp_pool(scsi_qla_host_t *ha);
 static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *);
-void qla2x00_sp_compl(scsi_qla_host_t *ha, srb_t *);
 
 /* -------------------------------------------------------------------------- */
 
@@ -1060,7 +1051,7 @@ eh_host_reset_lock:
 * Returns:
 *      0 = success
 */
-static int
+int
 qla2x00_loop_reset(scsi_qla_host_t *ha)
 {
        int ret;
@@ -1479,15 +1470,23 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha)
 static int
 qla2x00_iospace_config(scsi_qla_host_t *ha)
 {
-       unsigned long   pio, pio_len, pio_flags;
-       unsigned long   mmio, mmio_len, mmio_flags;
+       resource_size_t pio;
+
+       if (pci_request_selected_regions(ha->pdev, ha->bars,
+           QLA2XXX_DRIVER_NAME)) {
+               qla_printk(KERN_WARNING, ha,
+                   "Failed to reserve PIO/MMIO regions (%s)\n",
+                   pci_name(ha->pdev));
+
+               goto iospace_error_exit;
+       }
+       if (!(ha->bars & 1))
+               goto skip_pio;
 
        /* We only need PIO for Flash operations on ISP2312 v2 chips. */
        pio = pci_resource_start(ha->pdev, 0);
-       pio_len = pci_resource_len(ha->pdev, 0);
-       pio_flags = pci_resource_flags(ha->pdev, 0);
-       if (pio_flags & IORESOURCE_IO) {
-               if (pio_len < MIN_IOBASE_LEN) {
+       if (pci_resource_flags(ha->pdev, 0) & IORESOURCE_IO) {
+               if (pci_resource_len(ha->pdev, 0) < MIN_IOBASE_LEN) {
                        qla_printk(KERN_WARNING, ha,
                            "Invalid PCI I/O region size (%s)...\n",
                                pci_name(ha->pdev));
@@ -1499,36 +1498,24 @@ qla2x00_iospace_config(scsi_qla_host_t *ha)
                    pci_name(ha->pdev));
                pio = 0;
        }
+       ha->pio_address = pio;
 
+skip_pio:
        /* Use MMIO operations for all accesses. */
-       mmio = pci_resource_start(ha->pdev, 1);
-       mmio_len = pci_resource_len(ha->pdev, 1);
-       mmio_flags = pci_resource_flags(ha->pdev, 1);
-
-       if (!(mmio_flags & IORESOURCE_MEM)) {
+       if (!(pci_resource_flags(ha->pdev, 1) & IORESOURCE_MEM)) {
                qla_printk(KERN_ERR, ha,
-                   "region #0 not an MMIO resource (%s), aborting\n",
+                   "region #1 not an MMIO resource (%s), aborting\n",
                    pci_name(ha->pdev));
                goto iospace_error_exit;
        }
-       if (mmio_len < MIN_IOBASE_LEN) {
+       if (pci_resource_len(ha->pdev, 1) < MIN_IOBASE_LEN) {
                qla_printk(KERN_ERR, ha,
                    "Invalid PCI mem region size (%s), aborting\n",
                        pci_name(ha->pdev));
                goto iospace_error_exit;
        }
 
-       if (pci_request_regions(ha->pdev, QLA2XXX_DRIVER_NAME)) {
-               qla_printk(KERN_WARNING, ha,
-                   "Failed to reserve PIO/MMIO regions (%s)\n",
-                   pci_name(ha->pdev));
-
-               goto iospace_error_exit;
-       }
-
-       ha->pio_address = pio;
-       ha->pio_length = pio_len;
-       ha->iobase = ioremap(mmio, MIN_IOBASE_LEN);
+       ha->iobase = ioremap(pci_resource_start(ha->pdev, 1), MIN_IOBASE_LEN);
        if (!ha->iobase) {
                qla_printk(KERN_ERR, ha,
                    "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));
@@ -1579,21 +1566,26 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        char pci_info[30];
        char fw_str[30];
        struct scsi_host_template *sht;
+       int bars;
 
-       if (pci_enable_device(pdev))
-               goto probe_out;
-
-       if (pci_find_aer_capability(pdev))
-               if (pci_enable_pcie_error_reporting(pdev))
-                       goto probe_out;
-
+       bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
        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_ISP5422 ||
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 ||
-           pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532)
+           pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) {
+               bars = pci_select_bars(pdev, IORESOURCE_MEM);
                sht = &qla24xx_driver_template;
+       }
+
+       if (pci_enable_device_bars(pdev, bars))
+               goto probe_out;
+
+       if (pci_find_aer_capability(pdev))
+               if (pci_enable_pcie_error_reporting(pdev))
+                       goto probe_out;
+
        host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
        if (host == NULL) {
                printk(KERN_WARNING
@@ -1610,6 +1602,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        ha->host_no = host->host_no;
        sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no);
        ha->parent = NULL;
+       ha->bars = bars;
 
        /* Set ISP-type information. */
        qla2x00_set_isp_flags(ha);
@@ -1691,9 +1684,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        /* load the F/W, read paramaters, and init the H/W */
        ha->instance = num_hosts;
 
-       init_MUTEX(&ha->mbx_cmd_sem);
        init_MUTEX(&ha->vport_sem);
-       init_MUTEX_LOCKED(&ha->mbx_intr_sem);
+       init_completion(&ha->mbx_cmd_comp);
+       complete(&ha->mbx_cmd_comp);
+       init_completion(&ha->mbx_intr_comp);
 
        INIT_LIST_HEAD(&ha->list);
        INIT_LIST_HEAD(&ha->fcports);
@@ -1797,6 +1791,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
        qla2x00_init_host_attr(ha);
 
+       qla2x00_dfs_setup(ha);
+
        qla_printk(KERN_INFO, ha, "\n"
            " QLogic Fibre Channel HBA Driver: %s\n"
            "  QLogic %s - %s\n"
@@ -1821,13 +1817,15 @@ probe_out:
        return ret;
 }
 
-static void __devexit
+static void
 qla2x00_remove_one(struct pci_dev *pdev)
 {
        scsi_qla_host_t *ha;
 
        ha = pci_get_drvdata(pdev);
 
+       qla2x00_dfs_remove(ha);
+
        qla2x00_free_sysfs_attr(ha);
 
        fc_remove_host(ha->host);
@@ -1861,8 +1859,11 @@ qla2x00_free_device(scsi_qla_host_t *ha)
                kthread_stop(t);
        }
 
+       if (ha->flags.fce_enabled)
+               qla2x00_disable_fce_trace(ha, NULL, NULL);
+
        if (ha->eft)
-               qla2x00_trace_control(ha, TC_DISABLE, 0, 0);
+               qla2x00_disable_eft_trace(ha);
 
        ha->flags.online = 0;
 
@@ -1880,7 +1881,7 @@ qla2x00_free_device(scsi_qla_host_t *ha)
        /* release io space registers  */
        if (ha->iobase)
                iounmap(ha->iobase);
-       pci_release_regions(ha->pdev);
+       pci_release_selected_regions(ha->pdev, ha->bars);
 }
 
 static inline void
@@ -2006,7 +2007,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer)
 *      0  = success.
 *      1  = failure.
 */
-uint8_t
+static uint8_t
 qla2x00_mem_alloc(scsi_qla_host_t *ha)
 {
        char    name[16];
@@ -2203,7 +2204,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
 * Input:
 *      ha = adapter block pointer.
 */
-void
+static void
 qla2x00_mem_free(scsi_qla_host_t *ha)
 {
        struct list_head        *fcpl, *fcptemp;
@@ -2218,6 +2219,10 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
        /* free sp pool */
        qla2x00_free_sp_pool(ha);
 
+       if (ha->fce)
+               dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
+                   ha->fce_dma);
+
        if (ha->fw_dump) {
                if (ha->eft)
                        dma_free_coherent(&ha->pdev->dev,
@@ -2738,23 +2743,6 @@ qla2x00_timer(scsi_qla_host_t *ha)
        qla2x00_restart_timer(ha, WATCH_INTERVAL);
 }
 
-/* XXX(hch): crude hack to emulate a down_timeout() */
-int
-qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout)
-{
-       const unsigned int step = 100; /* msecs */
-       unsigned int iterations = jiffies_to_msecs(timeout)/100;
-
-       do {
-               if (!down_trylock(sema))
-                       return 0;
-               if (msleep_interruptible(step))
-                       break;
-       } while (--iterations > 0);
-
-       return -ETIMEDOUT;
-}
-
 /* Firmware interface routines. */
 
 #define FW_BLOBS       6
@@ -2890,7 +2878,7 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
        pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT;
        scsi_qla_host_t *ha = pci_get_drvdata(pdev);
 
-       if (pci_enable_device(pdev)) {
+       if (pci_enable_device_bars(pdev, ha->bars)) {
                qla_printk(KERN_WARNING, ha,
                    "Can't re-enable PCI device after reset.\n");
 
@@ -2955,7 +2943,7 @@ static struct pci_driver qla2xxx_pci_driver = {
        },
        .id_table       = qla2xxx_pci_tbl,
        .probe          = qla2x00_probe_one,
-       .remove         = __devexit_p(qla2x00_remove_one),
+       .remove         = qla2x00_remove_one,
        .err_handler    = &qla2xxx_err_handler,
 };