hptiop: Support HighPoint RR36xx HBAs and Support SAS tape and SAS media changer
authorlinux <linux@highpoint-tech.com>
Fri, 31 Jul 2015 03:25:55 +0000 (11:25 +0800)
committerJames Bottomley <JBottomley@Odin.com>
Wed, 12 Aug 2015 20:14:57 +0000 (13:14 -0700)
Support HighPoint RR36xx HBAs which are based on Marvell Frey.
Support SAS tape and SAS media changer.

[jejb: remove now unused label]
Signed-off-by: HighPoint Linux Team <linux@highpoint-tech.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: James Bottomley <JBottomley@Odin.com>
drivers/scsi/hptiop.c
drivers/scsi/hptiop.h

index e995218476edd6677afa2979f4e7dec73bf05c8d..a83f705ed8a54172f21e8655e52c6c618edbcb9a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * HighPoint RR3xxx/4xxx controller driver for Linux
- * Copyright (C) 2006-2012 HighPoint Technologies, Inc. All Rights Reserved.
+ * Copyright (C) 2006-2015 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
@@ -42,7 +42,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.8";
+static const char driver_ver[] = "v1.10.0";
 
 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,
@@ -764,9 +764,7 @@ static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,
                scsi_set_resid(scp,
                        scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length));
                scp->result = SAM_STAT_CHECK_CONDITION;
-               memcpy(scp->sense_buffer, &req->sg_list,
-                               min_t(size_t, SCSI_SENSE_BUFFERSIZE,
-                                       le32_to_cpu(req->dataxfer_length)));
+               memcpy(scp->sense_buffer, &req->sg_list, SCSI_SENSE_BUFFERSIZE);
                goto skip_resid;
                break;
 
@@ -1037,8 +1035,9 @@ static int hptiop_queuecommand_lck(struct scsi_cmnd *scp,
 
        scp->result = 0;
 
-       if (scp->device->channel || scp->device->lun ||
-                       scp->device->id > hba->max_devices) {
+       if (scp->device->channel ||
+                       (scp->device->id > hba->max_devices) ||
+                       ((scp->device->id == (hba->max_devices-1)) && scp->device->lun)) {
                scp->result = DID_BAD_TARGET << 16;
                free_req(hba, _req);
                goto cmd_done;
@@ -1168,6 +1167,14 @@ static struct device_attribute *hptiop_attrs[] = {
        NULL
 };
 
+static int hptiop_slave_config(struct scsi_device *sdev)
+{
+       if (sdev->type == TYPE_TAPE)
+               blk_queue_max_hw_sectors(sdev->request_queue, 8192);
+
+       return 0;
+}
+
 static struct scsi_host_template driver_template = {
        .module                     = THIS_MODULE,
        .name                       = driver_name,
@@ -1179,6 +1186,7 @@ static struct scsi_host_template driver_template = {
        .use_clustering             = ENABLE_CLUSTERING,
        .proc_name                  = driver_name,
        .shost_attrs                = hptiop_attrs,
+       .slave_configure            = hptiop_slave_config,
        .this_id                    = -1,
        .change_queue_depth         = hptiop_adjust_disk_queue_depth,
 };
@@ -1323,6 +1331,7 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
        }
 
        hba = (struct hptiop_hba *)host->hostdata;
+       memset(hba, 0, sizeof(struct hptiop_hba));
 
        hba->ops = iop_ops;
        hba->pcidev = pcidev;
@@ -1336,7 +1345,7 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
        init_waitqueue_head(&hba->reset_wq);
        init_waitqueue_head(&hba->ioctl_wq);
 
-       host->max_lun = 1;
+       host->max_lun = 128;
        host->max_channel = 0;
        host->io_port = 0;
        host->n_io_port = 0;
@@ -1428,34 +1437,33 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
        dprintk("req_size=%d, max_requests=%d\n", req_size, hba->max_requests);
 
        hba->req_size = req_size;
-       start_virt = dma_alloc_coherent(&pcidev->dev,
-                               hba->req_size*hba->max_requests + 0x20,
-                               &start_phy, GFP_KERNEL);
+       hba->req_list = NULL;
 
-       if (!start_virt) {
-               printk(KERN_ERR "scsi%d: fail to alloc request mem\n",
-                                       hba->host->host_no);
-               goto free_request_irq;
-       }
+       for (i = 0; i < hba->max_requests; i++) {
+               start_virt = dma_alloc_coherent(&pcidev->dev,
+                                       hba->req_size + 0x20,
+                                       &start_phy, GFP_KERNEL);
+
+               if (!start_virt) {
+                       printk(KERN_ERR "scsi%d: fail to alloc request mem\n",
+                                               hba->host->host_no);
+                       goto free_request_mem;
+               }
 
-       hba->dma_coherent = start_virt;
-       hba->dma_coherent_handle = start_phy;
+               hba->dma_coherent[i] = start_virt;
+               hba->dma_coherent_handle[i] = start_phy;
 
-       if ((start_phy & 0x1f) != 0) {
-               offset = ((start_phy + 0x1f) & ~0x1f) - start_phy;
-               start_phy += offset;
-               start_virt += offset;
-       }
+               if ((start_phy & 0x1f) != 0) {
+                       offset = ((start_phy + 0x1f) & ~0x1f) - start_phy;
+                       start_phy += offset;
+                       start_virt += offset;
+               }
 
-       hba->req_list = NULL;
-       for (i = 0; i < hba->max_requests; i++) {
                hba->reqs[i].next = NULL;
                hba->reqs[i].req_virt = start_virt;
                hba->reqs[i].req_shifted_phy = start_phy >> 5;
                hba->reqs[i].index = i;
                free_req(hba, &hba->reqs[i]);
-               start_virt = (char *)start_virt + hba->req_size;
-               start_phy = start_phy + hba->req_size;
        }
 
        /* Enable Interrupt and start background task */
@@ -1474,11 +1482,16 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
        return 0;
 
 free_request_mem:
-       dma_free_coherent(&hba->pcidev->dev,
-                       hba->req_size * hba->max_requests + 0x20,
-                       hba->dma_coherent, hba->dma_coherent_handle);
+       for (i = 0; i < hba->max_requests; i++) {
+               if (hba->dma_coherent[i] && hba->dma_coherent_handle[i])
+                       dma_free_coherent(&hba->pcidev->dev,
+                                       hba->req_size + 0x20,
+                                       hba->dma_coherent[i],
+                                       hba->dma_coherent_handle[i]);
+               else
+                       break;
+       }
 
-free_request_irq:
        free_irq(hba->pcidev->irq, hba);
 
 unmap_pci_bar:
@@ -1546,6 +1559,7 @@ static void hptiop_remove(struct pci_dev *pcidev)
 {
        struct Scsi_Host *host = pci_get_drvdata(pcidev);
        struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
+       u32 i;
 
        dprintk("scsi%d: hptiop_remove\n", hba->host->host_no);
 
@@ -1555,10 +1569,15 @@ static void hptiop_remove(struct pci_dev *pcidev)
 
        free_irq(hba->pcidev->irq, hba);
 
-       dma_free_coherent(&hba->pcidev->dev,
-                       hba->req_size * hba->max_requests + 0x20,
-                       hba->dma_coherent,
-                       hba->dma_coherent_handle);
+       for (i = 0; i < hba->max_requests; i++) {
+               if (hba->dma_coherent[i] && hba->dma_coherent_handle[i])
+                       dma_free_coherent(&hba->pcidev->dev,
+                                       hba->req_size + 0x20,
+                                       hba->dma_coherent[i],
+                                       hba->dma_coherent_handle[i]);
+               else
+                       break;
+       }
 
        hba->ops->internal_memfree(hba);
 
@@ -1653,6 +1672,14 @@ static struct pci_device_id hptiop_id_table[] = {
        { PCI_VDEVICE(TTI, 0x3020), (kernel_ulong_t)&hptiop_mv_ops },
        { PCI_VDEVICE(TTI, 0x4520), (kernel_ulong_t)&hptiop_mvfrey_ops },
        { PCI_VDEVICE(TTI, 0x4522), (kernel_ulong_t)&hptiop_mvfrey_ops },
+       { PCI_VDEVICE(TTI, 0x3610), (kernel_ulong_t)&hptiop_mvfrey_ops },
+       { PCI_VDEVICE(TTI, 0x3611), (kernel_ulong_t)&hptiop_mvfrey_ops },
+       { PCI_VDEVICE(TTI, 0x3620), (kernel_ulong_t)&hptiop_mvfrey_ops },
+       { PCI_VDEVICE(TTI, 0x3622), (kernel_ulong_t)&hptiop_mvfrey_ops },
+       { PCI_VDEVICE(TTI, 0x3640), (kernel_ulong_t)&hptiop_mvfrey_ops },
+       { PCI_VDEVICE(TTI, 0x3660), (kernel_ulong_t)&hptiop_mvfrey_ops },
+       { PCI_VDEVICE(TTI, 0x3680), (kernel_ulong_t)&hptiop_mvfrey_ops },
+       { PCI_VDEVICE(TTI, 0x3690), (kernel_ulong_t)&hptiop_mvfrey_ops },
        {},
 };
 
index 020619d60b081d4d393f9ed10565c96e844f96ce..4d1c51153b70334e152262875f8ba7a6148dd53b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * HighPoint RR3xxx/4xxx controller driver for Linux
- * Copyright (C) 2006-2012 HighPoint Technologies, Inc. All Rights Reserved.
+ * Copyright (C) 2006-2015 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
@@ -327,8 +327,8 @@ struct hptiop_hba {
        struct hptiop_request reqs[HPTIOP_MAX_REQUESTS];
 
        /* used to free allocated dma area */
-       void        *dma_coherent;
-       dma_addr_t  dma_coherent_handle;
+       void        *dma_coherent[HPTIOP_MAX_REQUESTS];
+       dma_addr_t  dma_coherent_handle[HPTIOP_MAX_REQUESTS];
 
        atomic_t    reset_count;
        atomic_t    resetting;