be2net: implement EEH pci error recovery handlers
[safe/jmp/linux-2.6] / drivers / scsi / hptiop.c
index 5b7be1e..4f05565 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * HighPoint RR3xxx/4xxx controller driver for Linux
- * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved.
+ * Copyright (C) 2006-2009 HighPoint Technologies, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -25,7 +25,6 @@
 #include <linux/delay.h>
 #include <linux/timer.h>
 #include <linux/spinlock.h>
-#include <linux/hdreg.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/div64.h>
@@ -42,7 +41,7 @@ MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx/4xxx Controller Driver");
 
 static char driver_name[] = "hptiop";
 static const char driver_name_long[] = "RocketRAID 3xxx/4xxx Controller driver";
-static const char driver_ver[] = "v1.3 (071203)";
+static const char driver_ver[] = "v1.6 (090910)";
 
 static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec);
 static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,
@@ -116,9 +115,13 @@ static void hptiop_drain_outbound_queue_itl(struct hptiop_hba *hba)
 static int iop_intr_itl(struct hptiop_hba *hba)
 {
        struct hpt_iopmu_itl __iomem *iop = hba->u.itl.iop;
+       void __iomem *plx = hba->u.itl.plx;
        u32 status;
        int ret = 0;
 
+       if (plx && readl(plx + 0x11C5C) & 0xf)
+               writel(1, plx + 0x11C60);
+
        status = readl(&iop->outbound_intstatus);
 
        if (status & IOPMU_OUTBOUND_INT_MSG0) {
@@ -444,7 +447,7 @@ static void __iomem *hptiop_map_pci_bar(struct hptiop_hba *hba, int index)
        if (!(pci_resource_flags(pcidev, index) & IORESOURCE_MEM)) {
                printk(KERN_ERR "scsi%d: pci resource invalid\n",
                                hba->host->host_no);
-               return 0;
+               return NULL;
        }
 
        mem_base_phy = pci_resource_start(pcidev, index);
@@ -454,33 +457,43 @@ static void __iomem *hptiop_map_pci_bar(struct hptiop_hba *hba, int index)
        if (!mem_base_virt) {
                printk(KERN_ERR "scsi%d: Fail to ioremap memory space\n",
                                hba->host->host_no);
-               return 0;
+               return NULL;
        }
        return mem_base_virt;
 }
 
 static int hptiop_map_pci_bar_itl(struct hptiop_hba *hba)
 {
+       struct pci_dev *pcidev = hba->pcidev;
        hba->u.itl.iop = hptiop_map_pci_bar(hba, 0);
-       if (hba->u.itl.iop)
-               return 0;
-       else
+       if (hba->u.itl.iop == NULL)
                return -1;
+       if ((pcidev->device & 0xff00) == 0x4400) {
+               hba->u.itl.plx = hba->u.itl.iop;
+               hba->u.itl.iop = hptiop_map_pci_bar(hba, 2);
+               if (hba->u.itl.iop == NULL) {
+                       iounmap(hba->u.itl.plx);
+                       return -1;
+               }
+       }
+       return 0;
 }
 
 static void hptiop_unmap_pci_bar_itl(struct hptiop_hba *hba)
 {
+       if (hba->u.itl.plx)
+               iounmap(hba->u.itl.plx);
        iounmap(hba->u.itl.iop);
 }
 
 static int hptiop_map_pci_bar_mv(struct hptiop_hba *hba)
 {
        hba->u.mv.regs = hptiop_map_pci_bar(hba, 0);
-       if (hba->u.mv.regs == 0)
+       if (hba->u.mv.regs == NULL)
                return -1;
 
        hba->u.mv.mu = hptiop_map_pci_bar(hba, 2);
-       if (hba->u.mv.mu == 0) {
+       if (hba->u.mv.mu == NULL) {
                iounmap(hba->u.mv.regs);
                return -1;
        }
@@ -581,8 +594,7 @@ static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,
                break;
 
        default:
-               scp->result = ((DRIVER_INVALID|SUGGEST_ABORT)<<24) |
-                                       (DID_ABORT<<16);
+               scp->result = DRIVER_INVALID << 24 | DID_ABORT << 16;
                break;
        }
 
@@ -763,9 +775,9 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
                        scp,
                        host->host_no, scp->device->channel,
                        scp->device->id, scp->device->lun,
-                       *((u32 *)&scp->cmnd),
-                       *((u32 *)&scp->cmnd + 1),
-                       *((u32 *)&scp->cmnd + 2),
+                       ((u32 *)scp->cmnd)[0],
+                       ((u32 *)scp->cmnd)[1],
+                       ((u32 *)scp->cmnd)[2],
                        _req->index, _req->req_virt);
 
        scp->result = 0;
@@ -822,7 +834,7 @@ static int hptiop_reset_hba(struct hptiop_hba *hba)
                        atomic_read(&hba->resetting) == 0, 60 * HZ);
 
        if (atomic_read(&hba->resetting)) {
-               /* IOP is in unkown state, abort reset */
+               /* IOP is in unknown state, abort reset */
                printk(KERN_ERR "scsi%d: reset failed\n", hba->host->host_no);
                return -1;
        }
@@ -849,10 +861,13 @@ static int hptiop_reset(struct scsi_cmnd *scp)
 }
 
 static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev,
-                                               int queue_depth)
+                                         int queue_depth, int reason)
 {
        struct hptiop_hba *hba = (struct hptiop_hba *)sdev->host->hostdata;
 
+       if (reason != SCSI_QDEPTH_DEFAULT)
+               return -EOPNOTSUPP;
+
        if (queue_depth > hba->max_requests)
                queue_depth = hba->max_requests;
        scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
@@ -960,8 +975,8 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
        pci_set_master(pcidev);
 
        /* Enable 64bit DMA if possible */
-       if (pci_set_dma_mask(pcidev, DMA_64BIT_MASK)) {
-               if (pci_set_dma_mask(pcidev, DMA_32BIT_MASK)) {
+       if (pci_set_dma_mask(pcidev, DMA_BIT_MASK(64))) {
+               if (pci_set_dma_mask(pcidev, DMA_BIT_MASK(32))) {
                        printk(KERN_ERR "hptiop: fail to set dma_mask\n");
                        goto disable_pci_device;
                }
@@ -1210,8 +1225,8 @@ static void hptiop_remove(struct pci_dev *pcidev)
 
 static struct hptiop_adapter_ops hptiop_itl_ops = {
        .iop_wait_ready    = iop_wait_ready_itl,
-       .internal_memalloc = 0,
-       .internal_memfree  = 0,
+       .internal_memalloc = NULL,
+       .internal_memfree  = NULL,
        .map_pci_bar       = hptiop_map_pci_bar_itl,
        .unmap_pci_bar     = hptiop_unmap_pci_bar_itl,
        .enable_intr       = hptiop_enable_intr_itl,
@@ -1241,14 +1256,23 @@ static struct hptiop_adapter_ops hptiop_mv_ops = {
 static struct pci_device_id hptiop_id_table[] = {
        { PCI_VDEVICE(TTI, 0x3220), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3320), (kernel_ulong_t)&hptiop_itl_ops },
-       { PCI_VDEVICE(TTI, 0x3520), (kernel_ulong_t)&hptiop_itl_ops },
-       { PCI_VDEVICE(TTI, 0x4320), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x3410), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3510), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3511), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x3520), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3521), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3522), (kernel_ulong_t)&hptiop_itl_ops },
-       { PCI_VDEVICE(TTI, 0x3410), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3540), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x4311), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x4320), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x4321), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x4400), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3120), (kernel_ulong_t)&hptiop_mv_ops },
        { PCI_VDEVICE(TTI, 0x3122), (kernel_ulong_t)&hptiop_mv_ops },
        { PCI_VDEVICE(TTI, 0x3020), (kernel_ulong_t)&hptiop_mv_ops },