Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a93429c3 authored by linux's avatar linux Committed by James Bottomley
Browse files

hptiop: Support HighPoint RR36xx HBAs and Support SAS tape and SAS media changer



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: default avatarHighPoint Linux Team <linux@highpoint-tech.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarJames Bottomley <JBottomley@Odin.com>
parent 442d7562
Loading
Loading
Loading
Loading
+62 −35
Original line number Diff line number Diff line
/*
 * 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,18 +1437,21 @@ 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;
	hba->req_list = NULL;

	for (i = 0; i < hba->max_requests; i++) {
		start_virt = dma_alloc_coherent(&pcidev->dev,
				hba->req_size*hba->max_requests + 0x20,
					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_irq;
			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;
@@ -1447,15 +1459,11 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
			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:
	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 * hba->max_requests + 0x20,
			hba->dma_coherent, hba->dma_coherent_handle);
					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);

	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 * hba->max_requests + 0x20,
			hba->dma_coherent,
			hba->dma_coherent_handle);
					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 },
	{},
};

+3 −3
Original line number Diff line number Diff line
/*
 * 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;