From: Christoph Hellwig <hch@lst.de>
To: Andrew Morton <akpm@osdl.org>
Cc: James Bottomley <James.Bottomley@steeleye.com>,
Christoph Hellwig <hch@lst.de>, Jens Axboe <axboe@suse.de>,
erich <erich@areca.com.tw>,
billion.wu@areca.com.tw, linux-scsi@vger.kernel.org
Subject: Re: areca RAID driver
Date: Thu, 20 Apr 2006 21:48:31 +0200 [thread overview]
Message-ID: <20060420194831.GA7923@lst.de> (raw)
In-Reply-To: <20060419155300.321c352e.akpm@osdl.org>
On Wed, Apr 19, 2006 at 03:53:00PM -0700, Andrew Morton wrote:
>
> Gents, Erich thinks that the Areca driver is pretty much ready to go.
>
> We still have the weird read-past-EOF problem if MAX_XFER_SECTORS=4096, but
> this version of the driver has it set to 512, which makes the problem go
> away. I've suggested that we can set that problem aside for now.
>
> I've put a copy of the latest diff at
> http://www.zip.com.au/~akpm/linux/patches/stuff/areca-raid-linux-scsi-driver.patch.
> Could you please take a look sometime, decide how we should proceed?
It still doesn't address lots of the month-old comments.
Serious stuff:
- doesn't follow one value per file in sysfs rule
- arcmsr_device_probe (which should really be called arcmsr_probe!)
doesn't propagate the pci_enable_device return value
- ditto for request_irq
- please do proper goto unwinding in arcmsr_device_probe instead of
calling arcmsr_pcidev_disattach in various places
- arcmsr_report_sense_info is buggy. all scsi-commands are S/G lists
now.
- pleaase don't put that odd "linux bug" workaround into
arcmsr_queue_command. If you can reproduce that bug please report it
and we'll fix it.
- the target 16 inquiry emulation is broken for the same reasons as the
report_luns one above. Care to explain why you need it at all?
- I can't see any endianess handling in the whole driver. Was this
tested on a BE platform like powerpc?
- the probe path is doing mmio access before pci_request_regions.
- scsi_remove_host is called far too late
- dma_addr_ts are casted to unsigned longs which doesn't work
with 64bit dma and 32bit plattforms
Cosmetical stuff:
- odd formated comments instead of kerneldoc / per CondingStyle
- very odd variable naming, lots of uppercase and p prefixes
- please kill all these useless forward-declarations and format
the code in the natural call flow
- the consistent_dma_mask is 32bits by default, not need to call
pci_set_consistent_dma_mask
And there's probably a lot more issues. Below is a patch that tries to
cleanup the pci driver entry points according to the above list. Due
to all this moving things around it's pretty huge.
Index: hch/areca/drivers/scsi/arcmsr/arcmsr_hba.c
===================================================================
--- hch.orig/areca/drivers/scsi/arcmsr/arcmsr_hba.c 2006-04-20 21:05:10.000000000 +0200
+++ hch/areca/drivers/scsi/arcmsr/arcmsr_hba.c 2006-04-20 21:46:49.000000000 +0200
@@ -75,7 +73,6 @@
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(ARCMSR_DRIVER_VERSION);
-static int arcmsr_initialize(struct AdapterControlBlock *pACB, struct pci_dev *pdev);
static int arcmsr_iop_message_xfer(struct AdapterControlBlock *pACB, struct scsi_cmnd *cmd);
static int arcmsr_cmd_abort(struct scsi_cmnd *);
static int arcmsr_bus_reset(struct scsi_cmnd *);
@@ -83,12 +80,6 @@
struct block_device *bdev, sector_t capacity, int *info);
static int arcmsr_queue_command(struct scsi_cmnd * cmd,
void (*done) (struct scsi_cmnd *));
-static int arcmsr_device_probe(struct pci_dev *pdev,
- const struct pci_device_id *id);
-static void arcmsr_device_remove(struct pci_dev *pdev);
-static void arcmsr_device_shutdown(struct pci_dev *pdev);
-static void arcmsr_pcidev_disattach(struct AdapterControlBlock *pACB);
-static void arcmsr_iop_init(struct AdapterControlBlock *pACB);
static void arcmsr_free_ccb_pool(struct AdapterControlBlock *pACB);
static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *pACB);
static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *pACB);
@@ -121,33 +112,6 @@
.shost_attrs = arcmsr_host_attrs,
};
-static struct pci_device_id arcmsr_device_id_table[] = {
- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)},
- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1120)},
- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1130)},
- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1160)},
- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1170)},
- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1210)},
- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1220)},
- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1230)},
- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1260)},
- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1270)},
- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1280)},
- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1380)},
- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1381)},
- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1680)},
- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1681)},
- {0, 0}, /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, arcmsr_device_id_table);
-static struct pci_driver arcmsr_pci_driver = {
- .name = "arcmsr",
- .id_table = arcmsr_device_id_table,
- .probe = arcmsr_device_probe,
- .remove = arcmsr_device_remove,
- .shutdown = arcmsr_device_shutdown
-};
-
static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
@@ -191,56 +155,218 @@
return 0;
}
-static int arcmsr_device_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
+static void arcmsr_pci_unmap_dma(struct CommandControlBlock *pCCB)
{
- struct Scsi_Host *host;
- struct AdapterControlBlock *pACB;
- uint8_t bus, dev_fun;
+ struct AdapterControlBlock *acb = pCCB->pACB;
+ struct scsi_cmnd *pcmd = pCCB->pcmd;
- if (pci_enable_device(pdev)) {
- printk(KERN_NOTICE
- "arcmsr: adapter probe pci_enable_device error \n");
- return -ENODEV;
+ if (pcmd->use_sg != 0) {
+ struct scatterlist *sl;
+
+ sl = (struct scatterlist *)pcmd->request_buffer;
+ pci_unmap_sg(acb->pdev, sl, pcmd->use_sg, pcmd->sc_data_direction);
}
- host = scsi_host_alloc(&arcmsr_scsi_host_template, sizeof (struct AdapterControlBlock));
- if (!host) {
- printk(KERN_NOTICE
- "arcmsr: adapter probe scsi_host_alloc error \n");
- pci_disable_device(pdev);
- return -ENODEV;
- }
- if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK))
- printk(KERN_INFO
- "ARECA RAID ADAPTER%d: 64BITS PCI BUS DMA ADDRESSING SUPPORTED\n"
- , host->host_no);
- else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK))
- printk(KERN_INFO
- "ARECA RAID ADAPTER%d: 32BITS PCI BUS DMA ADDRESSING SUPPORTED\n"
- , host->host_no);
- else {
+ else if (pcmd->request_bufflen != 0)
+ pci_unmap_single(acb->pdev,
+ (dma_addr_t)(unsigned long)pcmd->SCp.ptr,
+ pcmd->request_bufflen, pcmd->sc_data_direction);
+}
+
+static void arcmsr_ccb_complete(struct CommandControlBlock *pCCB, int stand_flag)
+{
+ struct AdapterControlBlock *acb = pCCB->pACB;
+ struct scsi_cmnd *pcmd = pCCB->pcmd;
+
+ arcmsr_pci_unmap_dma(pCCB);
+ if (stand_flag == 1)
+ atomic_dec(&acb->ccboutstandingcount);
+ pCCB->startdone = ARCMSR_CCB_DONE;
+ pCCB->ccb_flags = 0;
+ list_add_tail(&pCCB->list, &acb->ccb_free_list);
+ pcmd->scsi_done(pcmd);
+}
+
+static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
+{
+ struct MessageUnit __iomem *reg = acb->pmu;
+ char *acb_firm_model = acb->firm_model;
+ char *acb_firm_version = acb->firm_version;
+ char __iomem *iop_firm_model = (char __iomem *) ®->message_rwbuffer[15];
+ char __iomem *iop_firm_version = (char __iomem *) ®->message_rwbuffer[17];
+ int count;
+
+ writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0);
+ if (arcmsr_wait_msgint_ready(acb))
printk(KERN_NOTICE
- "ARECA RAID ADAPTER%d: No suitable DMA available.\n"
- , host->host_no);
- pci_disable_device(pdev);
- scsi_host_put(host);
- return -ENOMEM;
+ "arcmsr%d: wait "
+ "'get adapter firmware miscellaneous data' timeout \n",
+ acb->host->host_no);
+ count = 8;
+ while (count) {
+ *acb_firm_model = readb(iop_firm_model);
+ acb_firm_model++;
+ iop_firm_model++;
+ count--;
}
- if (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
- printk(KERN_NOTICE
- "ARECA RAID ADAPTER%d:"
- " No 32BIT coherent DMA adressing available\n"
- , host->host_no);
- pci_disable_device(pdev);
- scsi_host_put(host);
+ count = 16;
+ while (count) {
+ *acb_firm_version = readb(iop_firm_version);
+ acb_firm_version++;
+ iop_firm_version++;
+ count--;
+ }
+
+ acb->firm_request_len = readl(®->message_rwbuffer[1]);
+ acb->firm_numbers_queue = readl(®->message_rwbuffer[2]);
+ acb->firm_sdram_size = readl(®->message_rwbuffer[3]);
+ acb->firm_hd_channels = readl(®->message_rwbuffer[4]);
+}
+
+
+static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
+{
+ struct pci_dev *pdev = acb->pdev;
+ struct MessageUnit __iomem *reg = acb->pmu;
+ u32 ccb_phyaddr_hi32;
+ void *dma_coherent;
+ dma_addr_t dma_coherent_handle, dma_addr;
+ struct CommandControlBlock *pccb_tmp;
+ int i, j;
+
+ dma_coherent = dma_alloc_coherent(&pdev->dev,
+ ARCMSR_MAX_FREECCB_NUM *
+ sizeof (struct CommandControlBlock) + 0x20,
+ &dma_coherent_handle, GFP_KERNEL);
+ if (!dma_coherent)
return -ENOMEM;
+
+ acb->dma_coherent = dma_coherent;
+ acb->dma_coherent_handle = dma_coherent_handle;
+
+ if (((unsigned long)dma_coherent & 0x1F)) {
+ dma_coherent = dma_coherent +
+ (0x20 - ((unsigned long)dma_coherent & 0x1F));
+ dma_coherent_handle = dma_coherent_handle +
+ (0x20 - ((unsigned long)dma_coherent_handle & 0x1F));
+ }
+
+ dma_addr = dma_coherent_handle;
+ pccb_tmp = (struct CommandControlBlock *)dma_coherent;
+ for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
+ pccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5;
+ pccb_tmp->pACB = acb;
+ acb->pccb_pool[i] = pccb_tmp;
+ list_add_tail(&pccb_tmp->list, &acb->ccb_free_list);
+ dma_addr = dma_addr + sizeof (struct CommandControlBlock);
+ pccb_tmp++;
+ }
+
+ acb->vir2phy_offset = (unsigned long)pccb_tmp -
+ (unsigned long)dma_addr;
+ for (i = 0; i < ARCMSR_MAX_TARGETID; i++)
+ for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++)
+ acb->devstate[i][j] = ARECA_RAID_GOOD;
+
+ /*
+ * here we need to tell iop 331 our pccb_tmp.HighPart
+ * if pccb_tmp.HighPart is not zero
+ */
+ ccb_phyaddr_hi32 = (uint32_t) ((dma_coherent_handle >> 16) >> 16);
+ if (ccb_phyaddr_hi32 != 0) {
+ writel(ARCMSR_SIGNATURE_SET_CONFIG, ®->message_rwbuffer[0]);
+ writel(ccb_phyaddr_hi32, ®->message_rwbuffer[1]);
+ writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, ®->inbound_msgaddr0);
+ if (arcmsr_wait_msgint_ready(acb))
+ printk(KERN_NOTICE "arcmsr%d: "
+ "'set ccb high part physical address' timeout\n",
+ acb->host->host_no);
+ }
+
+ writel(readl(®->outbound_intmask) |
+ ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE,
+ ®->outbound_intmask);
+ return 0;
+}
+
+static void arcmsr_iop_init(struct AdapterControlBlock *acb)
+{
+ struct MessageUnit __iomem *reg = acb->pmu;
+ uint32_t intmask_org, mask, outbound_doorbell, firmware_state = 0;
+
+ do {
+ firmware_state = readl(®->outbound_msgaddr1);
+ } while (!(firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK));
+ intmask_org = readl(®->outbound_intmask)
+ | ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE;
+ arcmsr_get_firmware_spec(acb);
+
+ acb->acb_flags |= ACB_F_MSG_START_BGRB;
+ writel(ARCMSR_INBOUND_MESG0_START_BGRB, ®->inbound_msgaddr0);
+ if (arcmsr_wait_msgint_ready(acb)) {
+ printk(KERN_NOTICE "arcmsr%d: "
+ "wait 'start adapter background rebulid' timeout\n",
+ acb->host->host_no);
}
+
+ outbound_doorbell = readl(®->outbound_doorbell);
+ writel(outbound_doorbell, ®->outbound_doorbell);
+ writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell);
+ mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE
+ | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE);
+ writel(intmask_org & mask, ®->outbound_intmask);
+ acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff;
+ acb->acb_flags |= ACB_F_IOP_INITED;
+}
+
+static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
+{
+ struct MessageUnit __iomem *reg = acb->pmu;
+
+ writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0);
+ if (arcmsr_wait_msgint_ready(acb)) {
+ printk(KERN_NOTICE "arcmsr%d: "
+ "wait 'abort all outstanding command' timeout\n",
+ acb->host->host_no);
+ }
+}
+
+static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct Scsi_Host *host;
+ struct AdapterControlBlock *acb;
+ u8 bus, dev_fun;
+ int error;
+
+ error = pci_enable_device(pdev);
+ if (error)
+ goto out;
+ pci_set_master(pdev);
+
+ host = scsi_host_alloc(&arcmsr_scsi_host_template,
+ sizeof(struct AdapterControlBlock));
+ if (!host) {
+ error = -ENOMEM;
+ goto out_disable_device;
+ }
+ acb = (struct AdapterControlBlock *)host->hostdata;
+ memset(acb, 0, sizeof (struct AdapterControlBlock));
+
+ error = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+ if (error) {
+ error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (error) {
+ printk(KERN_WARNING
+ "scsi%d: No suitable DMA mask available\n",
+ host->host_no);
+ goto out_host_put;
+ }
+ }
+
bus = pdev->bus->number;
dev_fun = pdev->devfn;
- pACB = (struct AdapterControlBlock *) host->hostdata;
- memset(pACB, 0, sizeof (struct AdapterControlBlock));
- pACB->host = host;
- pACB->pdev = pdev;
+
+ acb->host = host;
+ acb->pdev = pdev;
host->max_sectors = ARCMSR_MAX_XFER_SECTORS;
host->max_lun = ARCMSR_MAX_TARGETLUN;
host->max_id = ARCMSR_MAX_TARGETID;/*16:8*/
@@ -250,70 +376,155 @@
host->cmd_per_lun = ARCMSR_MAX_CMD_PERLUN;
host->this_id = ARCMSR_SCSI_INITIATOR_ID;
host->unique_id = (bus << 8) | dev_fun;
- host->io_port = 0;
- host->n_io_port = 0;
host->irq = pdev->irq;
- pci_set_master(pdev);
- if (arcmsr_initialize(pACB, pdev)) {
- printk(KERN_NOTICE
- "arcmsr%d: initialize got error \n"
- , host->host_no);
- pci_disable_device(pdev);
- scsi_host_put(host);
- return -ENODEV;
- }
- if (pci_request_regions(pdev, "arcmsr")) {
- printk(KERN_NOTICE
- "arcmsr%d: adapter probe: pci_request_regions failed \n"
- , host->host_no);
- arcmsr_pcidev_disattach(pACB);
- return -ENODEV;
- }
- if (request_irq(pdev->irq, arcmsr_do_interrupt, SA_INTERRUPT | SA_SHIRQ,
- "arcmsr", pACB)) {
- printk(KERN_NOTICE
- "arcmsr%d: request IRQ=%d failed !\n"
- , host->host_no, pdev->irq);
- arcmsr_pcidev_disattach(pACB);
- return -ENODEV;
- }
- arcmsr_iop_init(pACB);
- if (scsi_add_host(host, &pdev->dev)) {
- printk(KERN_NOTICE
- "arcmsr%d: scsi_add_host got error \n"
- , host->host_no);
- arcmsr_pcidev_disattach(pACB);
- return -ENODEV;
+
+ error = pci_request_regions(pdev, "arcmsr");
+ if (error)
+ goto out_host_put;
+
+ acb->pmu = ioremap(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ if (!acb->pmu) {
+ printk(KERN_NOTICE "arcmsr%d: memory"
+ " mapping region fail \n", acb->host->host_no);
+ goto out_release_regions;
}
- arcmsr_alloc_sysfs_attr(pACB);
+
+ acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
+ ACB_F_MESSAGE_RQBUFFER_CLEARED |
+ ACB_F_MESSAGE_WQBUFFER_READED);
+ acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
+ INIT_LIST_HEAD(&acb->ccb_free_list);
+
+ error = arcmsr_alloc_ccb_pool(acb);
+ if (error)
+ goto out_iounmap;
+
+ error = request_irq(pdev->irq, arcmsr_do_interrupt,
+ SA_INTERRUPT | SA_SHIRQ, "arcmsr", acb);
+ if (error)
+ goto out_free_ccb_pool;
+
+ arcmsr_iop_init(acb);
pci_set_drvdata(pdev, host);
+
+ error = scsi_add_host(host, &pdev->dev);
+ if (error)
+ goto out_free_irq;
+
+ arcmsr_alloc_sysfs_attr(acb);
scsi_scan_host(host);
return 0;
+
+ out_free_irq:
+ free_irq(pdev->irq, acb);
+ out_free_ccb_pool:
+ arcmsr_free_ccb_pool(acb);
+ out_iounmap:
+ iounmap(acb->pmu);
+ out_release_regions:
+ pci_release_regions(pdev);
+ out_host_put:
+ scsi_host_put(host);
+ out_disable_device:
+ pci_disable_device(pdev);
+ out:
+ return error;
}
-static void arcmsr_device_remove(struct pci_dev *pdev)
+static void arcmsr_remove(struct pci_dev *pdev)
{
- struct Scsi_Host * host = pci_get_drvdata(pdev);
- struct AdapterControlBlock *pACB = (struct AdapterControlBlock *) host->hostdata;
+ struct Scsi_Host *host = pci_get_drvdata(pdev);
+ struct AdapterControlBlock *acb =
+ (struct AdapterControlBlock *) host->hostdata;
+ struct MessageUnit __iomem *reg = acb->pmu;
+ int poll_count = 0;
+
+ scsi_remove_host(host);
- arcmsr_pcidev_disattach(pACB);
+ arcmsr_stop_adapter_bgrb(acb);
+ arcmsr_flush_adapter_cache(acb);
+ writel(readl(®->outbound_intmask) |
+ ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE,
+ ®->outbound_intmask);
+ acb->acb_flags |= ACB_F_SCSISTOPADAPTER;
+ acb->acb_flags &= ~ACB_F_IOP_INITED;
+
+ for (poll_count = 0; poll_count < 256; poll_count++) {
+ if (!atomic_read(&acb->ccboutstandingcount))
+ break;
+ arcmsr_interrupt(acb);
+ msleep(25);
+ }
+
+ if (atomic_read(&acb->ccboutstandingcount)) {
+ int i;
+
+ arcmsr_abort_allcmd(acb);
+ for (i = 0; i < ARCMSR_MAX_OUTSTANDING_CMD; i++)
+ readl(®->outbound_queueport);
+ for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
+ struct CommandControlBlock *pCCB = acb->pccb_pool[i];
+ if (pCCB->startdone == ARCMSR_CCB_START) {
+ pCCB->startdone = ARCMSR_CCB_ABORTED;
+ pCCB->pcmd->result = DID_ABORT << 16;
+ arcmsr_ccb_complete(pCCB, 1);
+ }
+ }
+ }
+
+ free_irq(pdev->irq, acb);
+ iounmap(acb->pmu);
+ arcmsr_free_ccb_pool(acb);
+ pci_release_regions(pdev);
+
+ scsi_host_put(host);
+
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
}
static void arcmsr_device_shutdown(struct pci_dev *pdev)
{
struct Scsi_Host *host = pci_get_drvdata(pdev);
- struct AdapterControlBlock *pACB = (struct AdapterControlBlock *) host->hostdata;
+ struct AdapterControlBlock *acb =
+ (struct AdapterControlBlock *)host->hostdata;
- arcmsr_stop_adapter_bgrb(pACB);
- arcmsr_flush_adapter_cache(pACB);
+ arcmsr_stop_adapter_bgrb(acb);
+ arcmsr_flush_adapter_cache(acb);
}
+static struct pci_device_id arcmsr_device_id_table[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1120)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1130)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1160)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1170)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1210)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1220)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1230)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1260)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1270)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1280)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1380)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1381)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1680)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1681)},
+ {0, 0}, /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, arcmsr_device_id_table);
+
+static struct pci_driver arcmsr_pci_driver = {
+ .name = "arcmsr",
+ .id_table = arcmsr_device_id_table,
+ .probe = arcmsr_probe,
+ .remove = arcmsr_remove,
+ .shutdown = arcmsr_device_shutdown,
+};
+
static int arcmsr_module_init(void)
{
- int error = 0;
-
- error = pci_register_driver(&arcmsr_pci_driver);
- return error;
+ return pci_register_driver(&arcmsr_pci_driver);
}
static void arcmsr_module_exit(void)
@@ -323,23 +534,6 @@
module_init(arcmsr_module_init);
module_exit(arcmsr_module_exit);
-static void arcmsr_pci_unmap_dma(struct CommandControlBlock *pCCB)
-{
- struct AdapterControlBlock *pACB = pCCB->pACB;
- struct scsi_cmnd *pcmd = pCCB->pcmd;
-
- if (pcmd->use_sg != 0) {
- struct scatterlist *sl;
-
- sl = (struct scatterlist *)pcmd->request_buffer;
- pci_unmap_sg(pACB->pdev, sl, pcmd->use_sg, pcmd->sc_data_direction);
- }
- else if (pcmd->request_bufflen != 0)
- pci_unmap_single(pACB->pdev,
- (dma_addr_t)(unsigned long)pcmd->SCp.ptr,
- pcmd->request_bufflen, pcmd->sc_data_direction);
-}
-
static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *pACB)
{
struct MessageUnit __iomem *reg=pACB->pmu;
@@ -351,20 +545,6 @@
, pACB->host->host_no);
}
-static void arcmsr_ccb_complete(struct CommandControlBlock *pCCB, int stand_flag)
-{
- struct AdapterControlBlock *pACB = pCCB->pACB;
- struct scsi_cmnd *pcmd = pCCB->pcmd;
-
- arcmsr_pci_unmap_dma(pCCB);
- if (stand_flag == 1)
- atomic_dec(&pACB->ccboutstandingcount);
- pCCB->startdone = ARCMSR_CCB_DONE;
- pCCB->ccb_flags = 0;
- list_add_tail(&pCCB->list, &pACB->ccb_free_list);
- pcmd->scsi_done(pcmd);
-}
-
static void arcmsr_report_sense_info(struct CommandControlBlock *pCCB)
{
struct scsi_cmnd *pcmd = pCCB->pcmd;
@@ -382,17 +562,6 @@
}
}
-static void arcmsr_abort_allcmd(struct AdapterControlBlock *pACB)
-{
- struct MessageUnit __iomem *reg = pACB->pmu;
-
- writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0);
- if (arcmsr_wait_msgint_ready(pACB))
- printk(KERN_NOTICE
- "arcmsr%d: wait 'abort all outstanding command' timeout \n"
- , pACB->host->host_no);
-}
-
static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *pACB)
{
struct MessageUnit __iomem *reg = pACB->pmu;
@@ -1087,56 +1256,6 @@
return SCSI_MLQUEUE_HOST_BUSY;
}
-static void arcmsr_get_firmware_spec(struct AdapterControlBlock *pACB)
-{
- struct MessageUnit __iomem *reg = pACB->pmu;
- char *acb_firm_model = pACB->firm_model;
- char *acb_firm_version = pACB->firm_version;
- char __iomem *iop_firm_model = (char __iomem *) ®->message_rwbuffer[15];
- char __iomem *iop_firm_version = (char __iomem *) ®->message_rwbuffer[17];
- int count;
-
- writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0);
- if (arcmsr_wait_msgint_ready(pACB))
- printk(KERN_NOTICE
- "arcmsr%d: wait "
- "'get adapter firmware miscellaneous data' timeout \n"
- , pACB->host->host_no);
- count = 8;
- while (count) {
- *acb_firm_model = readb(iop_firm_model);
- acb_firm_model++;
- iop_firm_model++;
- count--;
- }
- count = 16;
- while (count) {
- *acb_firm_version = readb(iop_firm_version);
- acb_firm_version++;
- iop_firm_version++;
- count--;
- }
- printk(KERN_INFO
- "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n"
- , pACB->host->host_no
- , pACB->firm_version);
- pACB->firm_request_len = readl(®->message_rwbuffer[1]);
- pACB->firm_numbers_queue = readl(®->message_rwbuffer[2]);
- pACB->firm_sdram_size = readl(®->message_rwbuffer[3]);
- pACB->firm_hd_channels = readl(®->message_rwbuffer[4]);
-}
-
-static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *pACB)
-{
- struct MessageUnit __iomem *reg = pACB->pmu;
- pACB->acb_flags |= ACB_F_MSG_START_BGRB;
- writel(ARCMSR_INBOUND_MESG0_START_BGRB, ®->inbound_msgaddr0);
- if (arcmsr_wait_msgint_ready(pACB))
- printk(KERN_NOTICE
- "arcmsr%d: wait 'start adapter background rebulid' timeout \n"
- , pACB->host->host_no);
-}
-
static void arcmsr_polling_ccbdone(struct AdapterControlBlock *pACB, struct CommandControlBlock *poll_ccb)
{
struct MessageUnit __iomem *reg = pACB->pmu;
@@ -1230,28 +1349,6 @@
}
}
-static void arcmsr_iop_init(struct AdapterControlBlock *pACB)
-{
- struct MessageUnit __iomem *reg = pACB->pmu;
- uint32_t intmask_org, mask, outbound_doorbell, firmware_state = 0;
-
- do {
- firmware_state = readl(®->outbound_msgaddr1);
- } while (!(firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK));
- intmask_org = readl(®->outbound_intmask)
- | ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE;
- arcmsr_get_firmware_spec(pACB);
- arcmsr_start_adapter_bgrb(pACB);
- outbound_doorbell = readl(®->outbound_doorbell);
- writel(outbound_doorbell, ®->outbound_doorbell);
- writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell);
- mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE
- | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE);
- writel(intmask_org & mask, ®->outbound_intmask);
- pACB->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff;
- pACB->acb_flags |= ACB_F_IOP_INITED;
-}
-
static int arcmsr_bus_reset(struct scsi_cmnd *cmd)
{
struct AdapterControlBlock *pACB;
@@ -1404,136 +1501,3 @@
}
return buf;
}
-
-static int arcmsr_initialize(struct AdapterControlBlock *pACB, struct pci_dev *pdev)
-{
- struct MessageUnit __iomem *reg;
- uint32_t intmask_org, ccb_phyaddr_hi32;
- dma_addr_t dma_coherent_handle, dma_addr;
- uint8_t pcicmd;
- void *dma_coherent;
- void __iomem *page_remapped;
- int i, j;
- struct CommandControlBlock *pccb_tmp;
-
- pci_read_config_byte(pdev, PCI_COMMAND, &pcicmd);
- pci_write_config_byte(pdev, PCI_COMMAND,
- pcicmd | PCI_COMMAND_INVALIDATE | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
- page_remapped = ioremap(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- if ( !page_remapped ) {
- printk(KERN_NOTICE "arcmsr%d: memory"
- " mapping region fail \n", pACB->host->host_no);
- return -ENXIO;
- }
- pACB->pmu = (struct MessageUnit __iomem *)(page_remapped);
- pACB->acb_flags |=
- (ACB_F_MESSAGE_WQBUFFER_CLEARED
- | ACB_F_MESSAGE_RQBUFFER_CLEARED
- | ACB_F_MESSAGE_WQBUFFER_READED);
- pACB->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
- INIT_LIST_HEAD(&pACB->ccb_free_list);
- dma_coherent = dma_alloc_coherent(&pdev->dev
- , ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20
- , &dma_coherent_handle, GFP_KERNEL);
- if (!dma_coherent) {
- printk(KERN_NOTICE
- "arcmsr%d: dma_alloc_coherent got error \n"
- , pACB->host->host_no);
- return -ENOMEM;
- }
- pACB->dma_coherent = dma_coherent;
- pACB->dma_coherent_handle = dma_coherent_handle;
- memset(dma_coherent, 0, ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) +
- 0x20);
- if (((unsigned long)dma_coherent & 0x1F) != 0) {
- dma_coherent = dma_coherent + (0x20 - ((unsigned long)dma_coherent & 0x1F));
- dma_coherent_handle = dma_coherent_handle
- + (0x20 - ((unsigned long)dma_coherent_handle & 0x1F));
- }
- dma_addr = dma_coherent_handle;
- pccb_tmp = (struct CommandControlBlock *)dma_coherent;
- for(i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
- pccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5;
- pccb_tmp->pACB = pACB;
- pACB->pccb_pool[i] = pccb_tmp;
- list_add_tail(&pccb_tmp->list, &pACB->ccb_free_list);
- dma_addr = dma_addr + sizeof (struct CommandControlBlock);
- pccb_tmp++;
- }
- pACB->vir2phy_offset = (unsigned long)pccb_tmp - (unsigned long)dma_addr;
- for(i = 0; i < ARCMSR_MAX_TARGETID; i++) {
- for(j = 0; j < ARCMSR_MAX_TARGETLUN; j++)
- pACB->devstate[i][j] = ARECA_RAID_GOOD;
- }
- reg = pACB->pmu;
- /*
- *************************************************************
- ** here we need to tell iop 331 our pccb_tmp.HighPart
- ** if pccb_tmp.HighPart is not zero
- *************************************************************
- */
- ccb_phyaddr_hi32 = (uint32_t) ((dma_coherent_handle >> 16) >> 16);
- if (ccb_phyaddr_hi32 != 0) {
- writel(ARCMSR_SIGNATURE_SET_CONFIG, ®->message_rwbuffer[0]);
- writel(ccb_phyaddr_hi32, ®->message_rwbuffer[1]);
- writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, ®->inbound_msgaddr0);
- if (arcmsr_wait_msgint_ready(pACB))
- printk(KERN_NOTICE
- "arcmsr%d: 'set ccb high part physical address' timeout \n"
- , pACB->host->host_no);
- }
- intmask_org = readl(®->outbound_intmask);
- writel(intmask_org | ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE
- , ®->outbound_intmask);
- return 0;
-}
-
-static void arcmsr_pcidev_disattach(struct AdapterControlBlock *pACB)
-{
- struct MessageUnit __iomem *reg = pACB->pmu;
- struct pci_dev *pdev;
- struct CommandControlBlock *pCCB;
- struct Scsi_Host *host;
- uint32_t intmask_org;
- int i = 0, poll_count = 0;
-
- arcmsr_stop_adapter_bgrb(pACB);
- arcmsr_flush_adapter_cache(pACB);
- intmask_org = readl(®->outbound_intmask);
- writel(intmask_org | ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE
- , ®->outbound_intmask);
- pACB->acb_flags |= ACB_F_SCSISTOPADAPTER;
- pACB->acb_flags &= ~ACB_F_IOP_INITED;
- if (atomic_read(&pACB->ccboutstandingcount) != 0) {
- while (atomic_read(&pACB->ccboutstandingcount) != 0 && (poll_count < 256)) {
- arcmsr_interrupt(pACB);
- msleep(25);
- poll_count++;
- }
- if (atomic_read(&pACB->ccboutstandingcount) != 0) {
- arcmsr_abort_allcmd(pACB);
- for(i = 0; i < ARCMSR_MAX_OUTSTANDING_CMD; i++)
- readl(®->outbound_queueport);
- for(i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
- pCCB = pACB->pccb_pool[i];
- if (pCCB->startdone == ARCMSR_CCB_START) {
- pCCB->startdone = ARCMSR_CCB_ABORTED;
- pCCB->pcmd->result = DID_ABORT << 16;
- arcmsr_ccb_complete(pCCB, 1);
- }
- }
- }
- }
- host = pACB->host;
- pdev = pACB->pdev;
- iounmap(pACB->pmu);
- arcmsr_free_ccb_pool(pACB);
- scsi_remove_host(host);
- scsi_host_put(host);
- free_irq(pdev->irq, pACB);
- pci_release_regions(pdev);
- pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
-}
-
next prev parent reply other threads:[~2006-04-20 19:48 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-04-19 22:53 areca RAID driver Andrew Morton
2006-04-20 3:04 ` Matthew Wilcox
2006-04-20 4:39 ` erich
2006-04-20 6:44 ` Jens Axboe
2006-04-20 19:48 ` Christoph Hellwig [this message]
2006-04-20 20:07 ` Andrew Morton
2006-04-20 20:36 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20060420194831.GA7923@lst.de \
--to=hch@lst.de \
--cc=James.Bottomley@steeleye.com \
--cc=akpm@osdl.org \
--cc=axboe@suse.de \
--cc=billion.wu@areca.com.tw \
--cc=erich@areca.com.tw \
--cc=linux-scsi@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).