diff --git a/debian/changelog b/debian/changelog index eb2ad8227..1696d1b4d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -181,6 +181,7 @@ linux (3.16.7-ckt7-1) UNRELEASED; urgency=medium * [x86] ALSA: Enable SND_SOC, SND_SOC_INTEL_SST, SND_SOC_INTEL_HASWELL_MACH, SND_SOC_INTEL_BYT_RT5640_MACH, SND_SOC_INTEL_BYT_MAX98090_MACH as modules (Closes: #773835) + * arcmsr: Backport changes up to Linux 3.18 (Closes: #698821) [ Helge Deller ] * [alpha] build debian-installer udeb packages diff --git a/debian/patches/features/all/arcmsr/0001-arcmsr-fix-command-timeout-under-heavy-load.patch b/debian/patches/features/all/arcmsr/0001-arcmsr-fix-command-timeout-under-heavy-load.patch new file mode 100644 index 000000000..0a3cd497d --- /dev/null +++ b/debian/patches/features/all/arcmsr/0001-arcmsr-fix-command-timeout-under-heavy-load.patch @@ -0,0 +1,281 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 14:18:24 +0800 +Subject: [01/19] arcmsr: fix command timeout under heavy load +Origin: https://git.kernel.org/linus/6b3937227479e50032112faf74bd913f36dba2c6 +Bug-Debian: https://bugs.debian.org/698821 + +This patch rewrites the interrupt service routine relate function to fix +a command timeout under heavy controller load. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr.h | 2 +- + drivers/scsi/arcmsr/arcmsr_hba.c | 198 +++++++++++++++++++-------------------- + 2 files changed, 98 insertions(+), 102 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h +index 77b26f5..8f35793 100644 +--- a/drivers/scsi/arcmsr/arcmsr.h ++++ b/drivers/scsi/arcmsr/arcmsr.h +@@ -51,7 +51,7 @@ struct device_attribute; + #else + #define ARCMSR_MAX_FREECCB_NUM 320 + #endif +-#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2010/08/05" ++#define ARCMSR_DRIVER_VERSION "v1.30.00.04-20140428" + #define ARCMSR_SCSI_INITIATOR_ID 255 + #define ARCMSR_MAX_XFER_SECTORS 512 + #define ARCMSR_MAX_XFER_SECTORS_B 4096 +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index b13764c..506fe7b 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -1441,14 +1441,15 @@ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) + uint32_t outbound_doorbell; + struct MessageUnit_A __iomem *reg = acb->pmuA; + outbound_doorbell = readl(®->outbound_doorbell); +- writel(outbound_doorbell, ®->outbound_doorbell); +- if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { +- arcmsr_iop2drv_data_wrote_handle(acb); +- } +- +- if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { +- arcmsr_iop2drv_data_read_handle(acb); +- } ++ do { ++ writel(outbound_doorbell, ®->outbound_doorbell); ++ if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) ++ arcmsr_iop2drv_data_wrote_handle(acb); ++ if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) ++ arcmsr_iop2drv_data_read_handle(acb); ++ outbound_doorbell = readl(®->outbound_doorbell); ++ } while (outbound_doorbell & (ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK ++ | ARCMSR_OUTBOUND_IOP331_DATA_READ_OK)); + } + static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *pACB) + { +@@ -1462,17 +1463,19 @@ static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *pACB) + ******************************************************************* + */ + outbound_doorbell = readl(®->outbound_doorbell); +- writel(outbound_doorbell, ®->outbound_doorbell_clear);/*clear interrupt*/ +- if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { +- arcmsr_iop2drv_data_wrote_handle(pACB); +- } +- if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { +- arcmsr_iop2drv_data_read_handle(pACB); +- } +- if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { +- arcmsr_hbc_message_isr(pACB); /* messenger of "driver to iop commands" */ +- } +- return; ++ do { ++ writel(outbound_doorbell, ®->outbound_doorbell_clear); ++ readl(®->outbound_doorbell_clear); ++ if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) ++ arcmsr_iop2drv_data_wrote_handle(pACB); ++ if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) ++ arcmsr_iop2drv_data_read_handle(pACB); ++ if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) ++ arcmsr_hbc_message_isr(pACB); ++ outbound_doorbell = readl(®->outbound_doorbell); ++ } while (outbound_doorbell & (ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK ++ | ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK ++ | ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE)); + } + static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) + { +@@ -1521,21 +1524,23 @@ static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) + /* areca cdb command done */ + /* Use correct offset and size for syncing */ + +- while (readl(&phbcmu->host_int_status) & +- ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR){ +- /* check if command done with no error*/ +- flag_ccb = readl(&phbcmu->outbound_queueport_low); +- ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0);/*frame must be 32 bytes aligned*/ +- arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + ccb_cdb_phy); +- ccb = container_of(arcmsr_cdb, struct CommandControlBlock, arcmsr_cdb); +- error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? true : false; +- /* check if command done with no error */ +- arcmsr_drain_donequeue(acb, ccb, error); +- if (throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) { +- writel(ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING, &phbcmu->inbound_doorbell); +- break; +- } +- throttling++; ++ while ((flag_ccb = readl(&phbcmu->outbound_queueport_low)) != ++ 0xFFFFFFFF) { ++ ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0); ++ arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset ++ + ccb_cdb_phy); ++ ccb = container_of(arcmsr_cdb, struct CommandControlBlock, ++ arcmsr_cdb); ++ error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ++ ? true : false; ++ /* check if command done with no error */ ++ arcmsr_drain_donequeue(acb, ccb, error); ++ throttling++; ++ if (throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) { ++ writel(ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING, ++ &phbcmu->inbound_doorbell); ++ throttling = 0; ++ } + } + } + /* +@@ -1584,21 +1589,22 @@ static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) + struct MessageUnit_A __iomem *reg = acb->pmuA; + outbound_intstatus = readl(®->outbound_intstatus) & + acb->outbound_int_enable; +- if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) { +- return 1; +- } +- writel(outbound_intstatus, ®->outbound_intstatus); +- if (outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { +- arcmsr_hba_doorbell_isr(acb); +- } +- if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { +- arcmsr_hba_postqueue_isr(acb); +- } +- if(outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { +- /* messenger of "driver to iop commands" */ +- arcmsr_hba_message_isr(acb); +- } +- return 0; ++ if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) ++ return IRQ_NONE; ++ do { ++ writel(outbound_intstatus, ®->outbound_intstatus); ++ if (outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) ++ arcmsr_hba_doorbell_isr(acb); ++ if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) ++ arcmsr_hba_postqueue_isr(acb); ++ if (outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) ++ arcmsr_hba_message_isr(acb); ++ outbound_intstatus = readl(®->outbound_intstatus) & ++ acb->outbound_int_enable; ++ } while (outbound_intstatus & (ARCMSR_MU_OUTBOUND_DOORBELL_INT ++ | ARCMSR_MU_OUTBOUND_POSTQUEUE_INT ++ | ARCMSR_MU_OUTBOUND_MESSAGE0_INT)); ++ return IRQ_HANDLED; + } + + static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) +@@ -1608,27 +1614,25 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) + outbound_doorbell = readl(reg->iop2drv_doorbell) & + acb->outbound_int_enable; + if (!outbound_doorbell) +- return 1; +- +- writel(~outbound_doorbell, reg->iop2drv_doorbell); +- /*in case the last action of doorbell interrupt clearance is cached, +- this action can push HW to write down the clear bit*/ +- readl(reg->iop2drv_doorbell); +- writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell); +- if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { +- arcmsr_iop2drv_data_wrote_handle(acb); +- } +- if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { +- arcmsr_iop2drv_data_read_handle(acb); +- } +- if (outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { +- arcmsr_hbb_postqueue_isr(acb); +- } +- if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { +- /* messenger of "driver to iop commands" */ +- arcmsr_hbb_message_isr(acb); +- } +- return 0; ++ return IRQ_NONE; ++ do { ++ writel(~outbound_doorbell, reg->iop2drv_doorbell); ++ writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell); ++ if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) ++ arcmsr_iop2drv_data_wrote_handle(acb); ++ if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) ++ arcmsr_iop2drv_data_read_handle(acb); ++ if (outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) ++ arcmsr_hbb_postqueue_isr(acb); ++ if (outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) ++ arcmsr_hbb_message_isr(acb); ++ outbound_doorbell = readl(reg->iop2drv_doorbell) & ++ acb->outbound_int_enable; ++ } while (outbound_doorbell & (ARCMSR_IOP2DRV_DATA_WRITE_OK ++ | ARCMSR_IOP2DRV_DATA_READ_OK ++ | ARCMSR_IOP2DRV_CDB_DONE ++ | ARCMSR_IOP2DRV_MESSAGE_CMD_DONE)); ++ return IRQ_HANDLED; + } + + static int arcmsr_handle_hbc_isr(struct AdapterControlBlock *pACB) +@@ -1640,44 +1644,36 @@ static int arcmsr_handle_hbc_isr(struct AdapterControlBlock *pACB) + ** check outbound intstatus + ********************************************* + */ +- host_interrupt_status = readl(&phbcmu->host_int_status); +- if (!host_interrupt_status) { +- /*it must be share irq*/ +- return 1; +- } +- /* MU ioctl transfer doorbell interrupts*/ +- if (host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { +- arcmsr_hbc_doorbell_isr(pACB); /* messenger of "ioctl message read write" */ +- } +- /* MU post queue interrupts*/ +- if (host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { +- arcmsr_hbc_postqueue_isr(pACB); /* messenger of "scsi commands" */ +- } +- return 0; ++ host_interrupt_status = readl(&phbcmu->host_int_status) & ++ (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | ++ ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR); ++ if (!host_interrupt_status) ++ return IRQ_NONE; ++ do { ++ if (host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) ++ arcmsr_hbc_doorbell_isr(pACB); ++ /* MU post queue interrupts*/ ++ if (host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) ++ arcmsr_hbc_postqueue_isr(pACB); ++ host_interrupt_status = readl(&phbcmu->host_int_status); ++ } while (host_interrupt_status & (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | ++ ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR)); ++ return IRQ_HANDLED; + } + static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) + { + switch (acb->adapter_type) { +- case ACB_ADAPTER_TYPE_A: { +- if (arcmsr_handle_hba_isr(acb)) { +- return IRQ_NONE; +- } +- } ++ case ACB_ADAPTER_TYPE_A: ++ return arcmsr_handle_hba_isr(acb); + break; +- +- case ACB_ADAPTER_TYPE_B: { +- if (arcmsr_handle_hbb_isr(acb)) { +- return IRQ_NONE; +- } +- } ++ case ACB_ADAPTER_TYPE_B: ++ return arcmsr_handle_hbb_isr(acb); + break; +- case ACB_ADAPTER_TYPE_C: { +- if (arcmsr_handle_hbc_isr(acb)) { +- return IRQ_NONE; +- } +- } ++ case ACB_ADAPTER_TYPE_C: ++ return arcmsr_handle_hbc_isr(acb); ++ default: ++ return IRQ_NONE; + } +- return IRQ_HANDLED; + } + + static void arcmsr_iop_parking(struct AdapterControlBlock *acb) diff --git a/debian/patches/features/all/arcmsr/0002-arcmsr-add-code-to-support-msi-x-and-msi-interrupt.patch b/debian/patches/features/all/arcmsr/0002-arcmsr-add-code-to-support-msi-x-and-msi-interrupt.patch new file mode 100644 index 000000000..ffcebf157 --- /dev/null +++ b/debian/patches/features/all/arcmsr/0002-arcmsr-add-code-to-support-msi-x-and-msi-interrupt.patch @@ -0,0 +1,215 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 14:23:31 +0800 +Subject: [02/19] arcmsr: add code to support MSI-X and MSI interrupt +Origin: https://git.kernel.org/linus/1d1166ea16ac7047a1b01f20dcbcc6f7754c3c23 +Bug-Debian: https://bugs.debian.org/698821 + +This patch adds code to support MSI and MSI-X interrupt. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr.h | 5 +++ + drivers/scsi/arcmsr/arcmsr_hba.c | 83 ++++++++++++++++++++++++++++++++++------ + 2 files changed, 76 insertions(+), 12 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h +index 8f35793..1c64b60 100644 +--- a/drivers/scsi/arcmsr/arcmsr.h ++++ b/drivers/scsi/arcmsr/arcmsr.h +@@ -64,6 +64,7 @@ struct device_attribute; + #define ARCMSR_MAX_HBB_POSTQUEUE 264 + #define ARCMSR_MAX_XFER_LEN 0x26000 /* 152K */ + #define ARCMSR_CDB_SG_PAGE_LENGTH 256 ++#define ARCMST_NUM_MSIX_VECTORS 4 + #ifndef PCI_DEVICE_ID_ARECA_1880 + #define PCI_DEVICE_ID_ARECA_1880 0x1880 + #endif +@@ -508,6 +509,7 @@ struct AdapterControlBlock + struct pci_dev * pdev; + struct Scsi_Host * host; + unsigned long vir2phy_offset; ++ struct msix_entry entries[ARCMST_NUM_MSIX_VECTORS]; + /* Offset is used in making arc cdb physical to virtual calculations */ + uint32_t outbound_int_enable; + uint32_t cdb_phyaddr_hi32; +@@ -544,6 +546,8 @@ struct AdapterControlBlock + /* iop init */ + #define ACB_F_ABORT 0x0200 + #define ACB_F_FIRMWARE_TRAP 0x0400 ++ #define ACB_F_MSI_ENABLED 0x1000 ++ #define ACB_F_MSIX_ENABLED 0x2000 + struct CommandControlBlock * pccb_pool[ARCMSR_MAX_FREECCB_NUM]; + /* used for memory free */ + struct list_head ccb_free_list; +@@ -594,6 +598,7 @@ struct AdapterControlBlock + #define FW_DEADLOCK 0x0010 + atomic_t rq_map_token; + atomic_t ante_token_value; ++ int msix_vector_count; + };/* HW_DEVICE_EXTENSION */ + /* + ******************************************************************************* +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index 506fe7b..60227d56 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -603,6 +603,56 @@ static void arcmsr_message_isr_bh_fn(struct work_struct *work) + } + } + ++static int ++arcmsr_request_irq(struct pci_dev *pdev, struct AdapterControlBlock *acb) ++{ ++ int i, j, r; ++ struct msix_entry entries[ARCMST_NUM_MSIX_VECTORS]; ++ ++ for (i = 0; i < ARCMST_NUM_MSIX_VECTORS; i++) ++ entries[i].entry = i; ++ r = pci_enable_msix_range(pdev, entries, 1, ARCMST_NUM_MSIX_VECTORS); ++ if (r < 0) ++ goto msi_int; ++ acb->msix_vector_count = r; ++ for (i = 0; i < r; i++) { ++ if (request_irq(entries[i].vector, ++ arcmsr_do_interrupt, 0, "arcmsr", acb)) { ++ pr_warn("arcmsr%d: request_irq =%d failed!\n", ++ acb->host->host_no, entries[i].vector); ++ for (j = 0 ; j < i ; j++) ++ free_irq(entries[j].vector, acb); ++ pci_disable_msix(pdev); ++ goto msi_int; ++ } ++ acb->entries[i] = entries[i]; ++ } ++ acb->acb_flags |= ACB_F_MSIX_ENABLED; ++ pr_info("arcmsr%d: msi-x enabled\n", acb->host->host_no); ++ return SUCCESS; ++msi_int: ++ if (pci_enable_msi_exact(pdev, 1) < 0) ++ goto legacy_int; ++ if (request_irq(pdev->irq, arcmsr_do_interrupt, ++ IRQF_SHARED, "arcmsr", acb)) { ++ pr_warn("arcmsr%d: request_irq =%d failed!\n", ++ acb->host->host_no, pdev->irq); ++ pci_disable_msi(pdev); ++ goto legacy_int; ++ } ++ acb->acb_flags |= ACB_F_MSI_ENABLED; ++ pr_info("arcmsr%d: msi enabled\n", acb->host->host_no); ++ return SUCCESS; ++legacy_int: ++ if (request_irq(pdev->irq, arcmsr_do_interrupt, ++ IRQF_SHARED, "arcmsr", acb)) { ++ pr_warn("arcmsr%d: request_irq = %d failed!\n", ++ acb->host->host_no, pdev->irq); ++ return FAILED; ++ } ++ return SUCCESS; ++} ++ + static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) + { + struct Scsi_Host *host; +@@ -667,16 +717,13 @@ static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) + if(error){ + goto free_hbb_mu; + } +- arcmsr_iop_init(acb); + error = scsi_add_host(host, &pdev->dev); + if(error){ + goto RAID_controller_stop; + } +- error = request_irq(pdev->irq, arcmsr_do_interrupt, IRQF_SHARED, "arcmsr", acb); +- if(error){ ++ if (arcmsr_request_irq(pdev, acb) == FAILED) + goto scsi_host_remove; +- } +- host->irq = pdev->irq; ++ arcmsr_iop_init(acb); + scsi_scan_host(host); + INIT_WORK(&acb->arcmsr_do_message_isr_bh, arcmsr_message_isr_bh_fn); + atomic_set(&acb->rq_map_token, 16); +@@ -710,6 +757,22 @@ pci_disable_dev: + return -ENODEV; + } + ++static void arcmsr_free_irq(struct pci_dev *pdev, ++ struct AdapterControlBlock *acb) ++{ ++ int i; ++ ++ if (acb->acb_flags & ACB_F_MSI_ENABLED) { ++ free_irq(pdev->irq, acb); ++ pci_disable_msi(pdev); ++ } else if (acb->acb_flags & ACB_F_MSIX_ENABLED) { ++ for (i = 0; i < acb->msix_vector_count; i++) ++ free_irq(acb->entries[i].vector, acb); ++ pci_disable_msix(pdev); ++ } else ++ free_irq(pdev->irq, acb); ++} ++ + static uint8_t arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) + { + struct MessageUnit_A __iomem *reg = acb->pmuA; +@@ -992,6 +1055,7 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) + } + } + } ++ + static void arcmsr_remove(struct pci_dev *pdev) + { + struct Scsi_Host *host = pci_get_drvdata(pdev); +@@ -1029,7 +1093,7 @@ static void arcmsr_remove(struct pci_dev *pdev) + } + } + } +- free_irq(pdev->irq, acb); ++ arcmsr_free_irq(pdev, acb); + arcmsr_free_ccb_pool(acb); + arcmsr_free_hbb_mu(acb); + arcmsr_unmap_pciregion(acb); +@@ -1045,6 +1109,7 @@ static void arcmsr_shutdown(struct pci_dev *pdev) + (struct AdapterControlBlock *)host->hostdata; + del_timer_sync(&acb->eternal_timer); + arcmsr_disable_outbound_ints(acb); ++ arcmsr_free_irq(pdev, acb); + flush_work(&acb->arcmsr_do_message_isr_bh); + arcmsr_stop_adapter_bgrb(acb); + arcmsr_flush_adapter_cache(acb); +@@ -2516,8 +2581,6 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + case ACB_ADAPTER_TYPE_A: { + if (cdb_phyaddr_hi32 != 0) { + struct MessageUnit_A __iomem *reg = acb->pmuA; +- uint32_t intmask_org; +- intmask_org = arcmsr_disable_outbound_ints(acb); + writel(ARCMSR_SIGNATURE_SET_CONFIG, \ + ®->message_rwbuffer[0]); + writel(cdb_phyaddr_hi32, ®->message_rwbuffer[1]); +@@ -2529,7 +2592,6 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + acb->host->host_no); + return 1; + } +- arcmsr_enable_outbound_ints(acb, intmask_org); + } + } + break; +@@ -2539,8 +2601,6 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + uint32_t __iomem *rwbuffer; + + struct MessageUnit_B *reg = acb->pmuB; +- uint32_t intmask_org; +- intmask_org = arcmsr_disable_outbound_ints(acb); + reg->postq_index = 0; + reg->doneq_index = 0; + writel(ARCMSR_MESSAGE_SET_POST_WINDOW, reg->drv2iop_doorbell); +@@ -2569,7 +2629,6 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + return 1; + } + arcmsr_hbb_enable_driver_mode(acb); +- arcmsr_enable_outbound_ints(acb, intmask_org); + } + break; + case ACB_ADAPTER_TYPE_C: { diff --git a/debian/patches/features/all/arcmsr/0003-arcmsr-add-code-to-support-hibernation.patch b/debian/patches/features/all/arcmsr/0003-arcmsr-add-code-to-support-hibernation.patch new file mode 100644 index 000000000..bb54dcc47 --- /dev/null +++ b/debian/patches/features/all/arcmsr/0003-arcmsr-add-code-to-support-hibernation.patch @@ -0,0 +1,121 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 14:26:09 +0800 +Subject: [03/19] arcmsr: add code to support hibernation +Origin: https://git.kernel.org/linus/61cda87f33be22828c3b52863da1c456ba108d37 +Bug-Debian: https://bugs.debian.org/698821 + +This patch adds code to support system hibernation. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr_hba.c | 76 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 76 insertions(+) + +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index 60227d56..b338a3b 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -89,11 +89,15 @@ static int arcmsr_bios_param(struct scsi_device *sdev, + static int arcmsr_queue_command(struct Scsi_Host *h, struct scsi_cmnd *cmd); + static int arcmsr_probe(struct pci_dev *pdev, + const struct pci_device_id *id); ++static int arcmsr_suspend(struct pci_dev *pdev, pm_message_t state); ++static int arcmsr_resume(struct pci_dev *pdev); + static void arcmsr_remove(struct pci_dev *pdev); + static void arcmsr_shutdown(struct pci_dev *pdev); + static void arcmsr_iop_init(struct AdapterControlBlock *acb); + static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb); + static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); ++static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, ++ u32 intmask_org); + static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); + static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb); + static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb); +@@ -167,6 +171,8 @@ static struct pci_driver arcmsr_pci_driver = { + .id_table = arcmsr_device_id_table, + .probe = arcmsr_probe, + .remove = arcmsr_remove, ++ .suspend = arcmsr_suspend, ++ .resume = arcmsr_resume, + .shutdown = arcmsr_shutdown, + }; + /* +@@ -773,6 +779,76 @@ static void arcmsr_free_irq(struct pci_dev *pdev, + free_irq(pdev->irq, acb); + } + ++static int arcmsr_suspend(struct pci_dev *pdev, pm_message_t state) ++{ ++ uint32_t intmask_org; ++ struct Scsi_Host *host = pci_get_drvdata(pdev); ++ struct AdapterControlBlock *acb = ++ (struct AdapterControlBlock *)host->hostdata; ++ ++ intmask_org = arcmsr_disable_outbound_ints(acb); ++ arcmsr_free_irq(pdev, acb); ++ del_timer_sync(&acb->eternal_timer); ++ flush_work(&acb->arcmsr_do_message_isr_bh); ++ arcmsr_stop_adapter_bgrb(acb); ++ arcmsr_flush_adapter_cache(acb); ++ pci_set_drvdata(pdev, host); ++ pci_save_state(pdev); ++ pci_disable_device(pdev); ++ pci_set_power_state(pdev, pci_choose_state(pdev, state)); ++ return 0; ++} ++ ++static int arcmsr_resume(struct pci_dev *pdev) ++{ ++ int error; ++ struct Scsi_Host *host = pci_get_drvdata(pdev); ++ struct AdapterControlBlock *acb = ++ (struct AdapterControlBlock *)host->hostdata; ++ ++ pci_set_power_state(pdev, PCI_D0); ++ pci_enable_wake(pdev, PCI_D0, 0); ++ pci_restore_state(pdev); ++ if (pci_enable_device(pdev)) { ++ pr_warn("%s: pci_enable_device error\n", __func__); ++ return -ENODEV; ++ } ++ error = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); ++ if (error) { ++ error = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); ++ if (error) { ++ pr_warn("scsi%d: No suitable DMA mask available\n", ++ host->host_no); ++ goto controller_unregister; ++ } ++ } ++ pci_set_master(pdev); ++ if (arcmsr_request_irq(pdev, acb) == FAILED) ++ goto controller_stop; ++ arcmsr_iop_init(acb); ++ INIT_WORK(&acb->arcmsr_do_message_isr_bh, arcmsr_message_isr_bh_fn); ++ atomic_set(&acb->rq_map_token, 16); ++ atomic_set(&acb->ante_token_value, 16); ++ acb->fw_flag = FW_NORMAL; ++ init_timer(&acb->eternal_timer); ++ acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6 * HZ); ++ acb->eternal_timer.data = (unsigned long) acb; ++ acb->eternal_timer.function = &arcmsr_request_device_map; ++ add_timer(&acb->eternal_timer); ++ return 0; ++controller_stop: ++ arcmsr_stop_adapter_bgrb(acb); ++ arcmsr_flush_adapter_cache(acb); ++controller_unregister: ++ scsi_remove_host(host); ++ arcmsr_free_ccb_pool(acb); ++ arcmsr_unmap_pciregion(acb); ++ pci_release_regions(pdev); ++ scsi_host_put(host); ++ pci_disable_device(pdev); ++ return -ENODEV; ++} ++ + static uint8_t arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) + { + struct MessageUnit_A __iomem *reg = acb->pmuA; diff --git a/debian/patches/features/all/arcmsr/0004-arcmsr-limit-max.-number-of-scsi-command-request.patch b/debian/patches/features/all/arcmsr/0004-arcmsr-limit-max.-number-of-scsi-command-request.patch new file mode 100644 index 000000000..88a925134 --- /dev/null +++ b/debian/patches/features/all/arcmsr/0004-arcmsr-limit-max.-number-of-scsi-command-request.patch @@ -0,0 +1,108 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 14:29:41 +0800 +Subject: [04/19] arcmsr: limit max. number of SCSI command request +Origin: https://git.kernel.org/linus/3df824aff935444601101cc329ebe3f52e126a4e +Bug-Debian: https://bugs.debian.org/698821 + +This patch limits the max. number of SCSI commmand request to avoid command +overflow. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr.h | 4 +++- + drivers/scsi/arcmsr/arcmsr_hba.c | 32 ++++++++++++++++++++++---------- + 2 files changed, 25 insertions(+), 11 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h +index 1c64b60..0ae0ce3 100644 +--- a/drivers/scsi/arcmsr/arcmsr.h ++++ b/drivers/scsi/arcmsr/arcmsr.h +@@ -45,11 +45,12 @@ + #include + struct device_attribute; + /*The limit of outstanding scsi command that firmware can handle*/ +-#define ARCMSR_MAX_OUTSTANDING_CMD 256 + #ifdef CONFIG_XEN + #define ARCMSR_MAX_FREECCB_NUM 160 ++#define ARCMSR_MAX_OUTSTANDING_CMD 155 + #else + #define ARCMSR_MAX_FREECCB_NUM 320 ++#define ARCMSR_MAX_OUTSTANDING_CMD 255 + #endif + #define ARCMSR_DRIVER_VERSION "v1.30.00.04-20140428" + #define ARCMSR_SCSI_INITIATOR_ID 255 +@@ -598,6 +599,7 @@ struct AdapterControlBlock + #define FW_DEADLOCK 0x0010 + atomic_t rq_map_token; + atomic_t ante_token_value; ++ uint32_t maxOutstanding; + int msix_vector_count; + };/* HW_DEVICE_EXTENSION */ + /* +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index b338a3b..ed61ee2 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -134,7 +134,7 @@ static struct scsi_host_template arcmsr_scsi_host_template = { + .eh_bus_reset_handler = arcmsr_bus_reset, + .bios_param = arcmsr_bios_param, + .change_queue_depth = arcmsr_adjust_disk_queue_depth, +- .can_queue = ARCMSR_MAX_FREECCB_NUM, ++ .can_queue = ARCMSR_MAX_OUTSTANDING_CMD, + .this_id = ARCMSR_SCSI_INITIATOR_ID, + .sg_tablesize = ARCMSR_DEFAULT_SG_ENTRIES, + .max_sectors = ARCMSR_MAX_XFER_SECTORS_C, +@@ -693,7 +693,7 @@ static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) + host->max_lun = ARCMSR_MAX_TARGETLUN; + host->max_id = ARCMSR_MAX_TARGETID; /*16:8*/ + host->max_cmd_len = 16; /*this is issue of 64bit LBA ,over 2T byte*/ +- host->can_queue = ARCMSR_MAX_FREECCB_NUM; /* max simultaneous cmds */ ++ host->can_queue = ARCMSR_MAX_OUTSTANDING_CMD; + host->cmd_per_lun = ARCMSR_MAX_CMD_PERLUN; + host->this_id = ARCMSR_SCSI_INITIATOR_ID; + host->unique_id = (bus << 8) | dev_fun; +@@ -2216,9 +2216,6 @@ static int arcmsr_queue_command_lck(struct scsi_cmnd *cmd, + arcmsr_handle_virtual_command(acb, cmd); + return 0; + } +- if (atomic_read(&acb->ccboutstandingcount) >= +- ARCMSR_MAX_OUTSTANDING_CMD) +- return SCSI_MLQUEUE_HOST_BUSY; + ccb = arcmsr_get_freeccb(acb); + if (!ccb) + return SCSI_MLQUEUE_HOST_BUSY; +@@ -2428,12 +2425,27 @@ static bool arcmsr_get_hbc_config(struct AdapterControlBlock *pACB) + } + static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) + { +- if (acb->adapter_type == ACB_ADAPTER_TYPE_A) +- return arcmsr_get_hba_config(acb); +- else if (acb->adapter_type == ACB_ADAPTER_TYPE_B) +- return arcmsr_get_hbb_config(acb); ++ bool rtn = false; ++ ++ switch (acb->adapter_type) { ++ case ACB_ADAPTER_TYPE_A: ++ rtn = arcmsr_get_hba_config(acb); ++ break; ++ case ACB_ADAPTER_TYPE_B: ++ rtn = arcmsr_get_hbb_config(acb); ++ break; ++ case ACB_ADAPTER_TYPE_C: ++ rtn = arcmsr_get_hbc_config(acb); ++ break; ++ default: ++ break; ++ } ++ if (acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) ++ acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD; + else +- return arcmsr_get_hbc_config(acb); ++ acb->maxOutstanding = acb->firm_numbers_queue - 1; ++ acb->host->can_queue = acb->maxOutstanding; ++ return rtn; + } + + static int arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, diff --git a/debian/patches/features/all/arcmsr/0005-arcmsr-return-status-of-abort-command.patch b/debian/patches/features/all/arcmsr/0005-arcmsr-return-status-of-abort-command.patch new file mode 100644 index 000000000..c21b19034 --- /dev/null +++ b/debian/patches/features/all/arcmsr/0005-arcmsr-return-status-of-abort-command.patch @@ -0,0 +1,79 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 14:47:16 +0800 +Subject: [05/19] arcmsr: return status of abort command +Origin: https://git.kernel.org/linus/cab5aecee60a7930ca208ee723c18be7b400cfaf +Bug-Debian: https://bugs.debian.org/698821 + +This patch fixes the wrong return status of abort command. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +[bwh: Backported to 3.16: adjust context] +--- + drivers/scsi/arcmsr/arcmsr_hba.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -2477,7 +2477,7 @@ static int arcmsr_polling_hba_ccbdone(st + } + arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + (flag_ccb << 5)); + ccb = container_of(arcmsr_cdb, struct CommandControlBlock, arcmsr_cdb); +- poll_ccb_done = (ccb == poll_ccb) ? 1:0; ++ poll_ccb_done |= (ccb == poll_ccb) ? 1 : 0; + if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { + if ((ccb->startdone == ARCMSR_CCB_ABORTED) || (ccb == poll_ccb)) { + printk(KERN_NOTICE "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'" +@@ -2541,7 +2541,7 @@ static int arcmsr_polling_hbb_ccbdone(st + /* check if command done with no error*/ + arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + (flag_ccb << 5)); + ccb = container_of(arcmsr_cdb, struct CommandControlBlock, arcmsr_cdb); +- poll_ccb_done = (ccb == poll_ccb) ? 1:0; ++ poll_ccb_done |= (ccb == poll_ccb) ? 1 : 0; + if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { + if ((ccb->startdone == ARCMSR_CCB_ABORTED) || (ccb == poll_ccb)) { + printk(KERN_NOTICE "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'" +@@ -2597,7 +2597,7 @@ polling_hbc_ccb_retry: + ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0); + arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + ccb_cdb_phy);/*frame must be 32 bytes aligned*/ + pCCB = container_of(arcmsr_cdb, struct CommandControlBlock, arcmsr_cdb); +- poll_ccb_done = (pCCB == poll_ccb) ? 1 : 0; ++ poll_ccb_done |= (pCCB == poll_ccb) ? 1 : 0; + /* check ifcommand done with no error*/ + if ((pCCB->acb != acb) || (pCCB->startdone != ARCMSR_CCB_START)) { + if (pCCB->startdone == ARCMSR_CCB_ABORTED) { +@@ -3199,8 +3199,10 @@ static int arcmsr_abort(struct scsi_cmnd + (struct AdapterControlBlock *)cmd->device->host->hostdata; + int i = 0; + int rtn = FAILED; ++ uint32_t intmask_org; ++ + printk(KERN_NOTICE +- "arcmsr%d: abort device command of scsi id = %d lun = %d \n", ++ "arcmsr%d: abort device command of scsi id = %d lun = %d\n", + acb->host->host_no, cmd->device->id, cmd->device->lun); + acb->acb_flags |= ACB_F_ABORT; + acb->num_aborts++; +@@ -3210,9 +3212,12 @@ static int arcmsr_abort(struct scsi_cmnd + ** we need to handle it as soon as possible and exit + ************************************************ + */ +- if (!atomic_read(&acb->ccboutstandingcount)) ++ if (!atomic_read(&acb->ccboutstandingcount)) { ++ acb->acb_flags &= ~ACB_F_ABORT; + return rtn; ++ } + ++ intmask_org = arcmsr_disable_outbound_ints(acb); + for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { + struct CommandControlBlock *ccb = acb->pccb_pool[i]; + if (ccb->startdone == ARCMSR_CCB_START && ccb->pcmd == cmd) { +@@ -3222,6 +3227,7 @@ static int arcmsr_abort(struct scsi_cmnd + } + } + acb->acb_flags &= ~ACB_F_ABORT; ++ arcmsr_enable_outbound_ints(acb, intmask_org); + return rtn; + } + diff --git a/debian/patches/features/all/arcmsr/0006-arcmsr-store-adapter-type-in-pci-id-table.patch b/debian/patches/features/all/arcmsr/0006-arcmsr-store-adapter-type-in-pci-id-table.patch new file mode 100644 index 000000000..402de8bd7 --- /dev/null +++ b/debian/patches/features/all/arcmsr/0006-arcmsr-store-adapter-type-in-pci-id-table.patch @@ -0,0 +1,123 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 14:55:57 +0800 +Subject: [06/19] arcmsr: store adapter type in PCI id table +Origin: https://git.kernel.org/linus/8b7c994298d7a18f45a9cec2e9b496d9784b1135 +Bug-Debian: https://bugs.debian.org/698821 + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr_hba.c | 81 ++++++++++++++++++++-------------------- + 1 file changed, 41 insertions(+), 40 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index 87f3882..30b378c 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -143,29 +143,50 @@ static struct scsi_host_template arcmsr_scsi_host_template = { + .shost_attrs = arcmsr_host_attrs, + .no_write_same = 1, + }; ++ + 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_1200)}, +- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1201)}, +- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1202)}, +- {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)}, +- {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1880)}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110), ++ .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1120), ++ .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1130), ++ .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1160), ++ .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1170), ++ .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1200), ++ .driver_data = ACB_ADAPTER_TYPE_B}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1201), ++ .driver_data = ACB_ADAPTER_TYPE_B}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1202), ++ .driver_data = ACB_ADAPTER_TYPE_B}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1210), ++ .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1220), ++ .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1230), ++ .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1260), ++ .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1270), ++ .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1280), ++ .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1380), ++ .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1381), ++ .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1680), ++ .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1681), ++ .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1880), ++ .driver_data = ACB_ADAPTER_TYPE_C}, + {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, +@@ -295,26 +316,6 @@ static int arcmsr_bios_param(struct scsi_device *sdev, + return 0; + } + +-static void arcmsr_define_adapter_type(struct AdapterControlBlock *acb) +-{ +- struct pci_dev *pdev = acb->pdev; +- u16 dev_id; +- pci_read_config_word(pdev, PCI_DEVICE_ID, &dev_id); +- acb->dev_id = dev_id; +- switch (dev_id) { +- case 0x1880: { +- acb->adapter_type = ACB_ADAPTER_TYPE_C; +- } +- break; +- case 0x1201: { +- acb->adapter_type = ACB_ADAPTER_TYPE_B; +- } +- break; +- +- default: acb->adapter_type = ACB_ADAPTER_TYPE_A; +- } +-} +- + static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) + { + struct MessageUnit_A __iomem *reg = acb->pmuA; +@@ -710,7 +711,7 @@ static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) + ACB_F_MESSAGE_WQBUFFER_READED); + acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; + INIT_LIST_HEAD(&acb->ccb_free_list); +- arcmsr_define_adapter_type(acb); ++ acb->adapter_type = id->driver_data; + error = arcmsr_remap_pciregion(acb); + if(!error){ + goto pci_release_regs; diff --git a/debian/patches/features/all/arcmsr/0007-arcmsr-revise-message_isr_bh_fn-to-remove-duplicate-.patch b/debian/patches/features/all/arcmsr/0007-arcmsr-revise-message_isr_bh_fn-to-remove-duplicate-.patch new file mode 100644 index 000000000..f42c9bdd8 --- /dev/null +++ b/debian/patches/features/all/arcmsr/0007-arcmsr-revise-message_isr_bh_fn-to-remove-duplicate-.patch @@ -0,0 +1,194 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 14:59:00 +0800 +Subject: [07/19] arcmsr: revise message_isr_bh_fn to remove duplicate code +Origin: https://git.kernel.org/linus/12aad94792718c6a79bbd395a650caff85f76ae4 +Bug-Debian: https://bugs.debian.org/698821 + +Revise message_isr_bh_fn to remove the duplicate code for each adapter type. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr_hba.c | 160 +++++++++++++-------------------------- + 1 file changed, 54 insertions(+), 106 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index 30b378c..bfe2ac4 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -493,120 +493,68 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) + + static void arcmsr_message_isr_bh_fn(struct work_struct *work) + { +- struct AdapterControlBlock *acb = container_of(work,struct AdapterControlBlock, arcmsr_do_message_isr_bh); ++ struct AdapterControlBlock *acb = container_of(work, ++ struct AdapterControlBlock, arcmsr_do_message_isr_bh); ++ char *acb_dev_map = (char *)acb->device_map; ++ uint32_t __iomem *signature = NULL; ++ char __iomem *devicemap = NULL; ++ int target, lun; ++ struct scsi_device *psdev; ++ char diff, temp; ++ + switch (acb->adapter_type) { +- case ACB_ADAPTER_TYPE_A: { ++ case ACB_ADAPTER_TYPE_A: { ++ struct MessageUnit_A __iomem *reg = acb->pmuA; + +- struct MessageUnit_A __iomem *reg = acb->pmuA; +- char *acb_dev_map = (char *)acb->device_map; +- uint32_t __iomem *signature = (uint32_t __iomem*) (®->message_rwbuffer[0]); +- char __iomem *devicemap = (char __iomem*) (®->message_rwbuffer[21]); +- int target, lun; +- struct scsi_device *psdev; +- char diff; +- +- atomic_inc(&acb->rq_map_token); +- if (readl(signature) == ARCMSR_SIGNATURE_GET_CONFIG) { +- for(target = 0; target < ARCMSR_MAX_TARGETID -1; target++) { +- diff = (*acb_dev_map)^readb(devicemap); +- if (diff != 0) { +- char temp; +- *acb_dev_map = readb(devicemap); +- temp =*acb_dev_map; +- for(lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) { +- if((temp & 0x01)==1 && (diff & 0x01) == 1) { +- scsi_add_device(acb->host, 0, target, lun); +- }else if((temp & 0x01) == 0 && (diff & 0x01) == 1) { +- psdev = scsi_device_lookup(acb->host, 0, target, lun); +- if (psdev != NULL ) { +- scsi_remove_device(psdev); +- scsi_device_put(psdev); +- } +- } +- temp >>= 1; +- diff >>= 1; +- } +- } +- devicemap++; +- acb_dev_map++; +- } +- } +- break; +- } ++ signature = (uint32_t __iomem *)(®->message_rwbuffer[0]); ++ devicemap = (char __iomem *)(®->message_rwbuffer[21]); ++ break; ++ } ++ case ACB_ADAPTER_TYPE_B: { ++ struct MessageUnit_B *reg = acb->pmuB; + +- case ACB_ADAPTER_TYPE_B: { +- struct MessageUnit_B *reg = acb->pmuB; +- char *acb_dev_map = (char *)acb->device_map; +- uint32_t __iomem *signature = (uint32_t __iomem*)(®->message_rwbuffer[0]); +- char __iomem *devicemap = (char __iomem*)(®->message_rwbuffer[21]); +- int target, lun; +- struct scsi_device *psdev; +- char diff; +- +- atomic_inc(&acb->rq_map_token); +- if (readl(signature) == ARCMSR_SIGNATURE_GET_CONFIG) { +- for(target = 0; target < ARCMSR_MAX_TARGETID -1; target++) { +- diff = (*acb_dev_map)^readb(devicemap); +- if (diff != 0) { +- char temp; +- *acb_dev_map = readb(devicemap); +- temp =*acb_dev_map; +- for(lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) { +- if((temp & 0x01)==1 && (diff & 0x01) == 1) { +- scsi_add_device(acb->host, 0, target, lun); +- }else if((temp & 0x01) == 0 && (diff & 0x01) == 1) { +- psdev = scsi_device_lookup(acb->host, 0, target, lun); +- if (psdev != NULL ) { +- scsi_remove_device(psdev); +- scsi_device_put(psdev); +- } +- } +- temp >>= 1; +- diff >>= 1; +- } +- } +- devicemap++; +- acb_dev_map++; +- } +- } +- } ++ signature = (uint32_t __iomem *)(®->message_rwbuffer[0]); ++ devicemap = (char __iomem *)(®->message_rwbuffer[21]); + break; +- case ACB_ADAPTER_TYPE_C: { +- struct MessageUnit_C *reg = acb->pmuC; +- char *acb_dev_map = (char *)acb->device_map; +- uint32_t __iomem *signature = (uint32_t __iomem *)(®->msgcode_rwbuffer[0]); +- char __iomem *devicemap = (char __iomem *)(®->msgcode_rwbuffer[21]); +- int target, lun; +- struct scsi_device *psdev; +- char diff; +- +- atomic_inc(&acb->rq_map_token); +- if (readl(signature) == ARCMSR_SIGNATURE_GET_CONFIG) { +- for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) { +- diff = (*acb_dev_map)^readb(devicemap); +- if (diff != 0) { +- char temp; +- *acb_dev_map = readb(devicemap); +- temp = *acb_dev_map; +- for (lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) { +- if ((temp & 0x01) == 1 && (diff & 0x01) == 1) { +- scsi_add_device(acb->host, 0, target, lun); +- } else if ((temp & 0x01) == 0 && (diff & 0x01) == 1) { +- psdev = scsi_device_lookup(acb->host, 0, target, lun); +- if (psdev != NULL) { +- scsi_remove_device(psdev); +- scsi_device_put(psdev); +- } +- } +- temp >>= 1; +- diff >>= 1; +- } ++ } ++ case ACB_ADAPTER_TYPE_C: { ++ struct MessageUnit_C __iomem *reg = acb->pmuC; ++ ++ signature = (uint32_t __iomem *)(®->msgcode_rwbuffer[0]); ++ devicemap = (char __iomem *)(®->msgcode_rwbuffer[21]); ++ break; ++ } ++ } ++ atomic_inc(&acb->rq_map_token); ++ if (readl(signature) != ARCMSR_SIGNATURE_GET_CONFIG) ++ return; ++ for (target = 0; target < ARCMSR_MAX_TARGETID - 1; ++ target++) { ++ temp = readb(devicemap); ++ diff = (*acb_dev_map) ^ temp; ++ if (diff != 0) { ++ *acb_dev_map = temp; ++ for (lun = 0; lun < ARCMSR_MAX_TARGETLUN; ++ lun++) { ++ if ((diff & 0x01) == 1 && ++ (temp & 0x01) == 1) { ++ scsi_add_device(acb->host, ++ 0, target, lun); ++ } else if ((diff & 0x01) == 1 ++ && (temp & 0x01) == 0) { ++ psdev = scsi_device_lookup(acb->host, ++ 0, target, lun); ++ if (psdev != NULL) { ++ scsi_remove_device(psdev); ++ scsi_device_put(psdev); + } +- devicemap++; +- acb_dev_map++; + } ++ temp >>= 1; ++ diff >>= 1; + } + } ++ devicemap++; ++ acb_dev_map++; + } + } + diff --git a/debian/patches/features/all/arcmsr/0008-arcmsr-remove-calling-arcmsr_hbb_enable_driver_mode.patch b/debian/patches/features/all/arcmsr/0008-arcmsr-remove-calling-arcmsr_hbb_enable_driver_mode.patch new file mode 100644 index 000000000..10aa0e8f7 --- /dev/null +++ b/debian/patches/features/all/arcmsr/0008-arcmsr-remove-calling-arcmsr_hbb_enable_driver_mode.patch @@ -0,0 +1,52 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 15:01:28 +0800 +Subject: [08/19] arcmsr: remove calling arcmsr_hbb_enable_driver_mode +Origin: https://git.kernel.org/linus/a5849726bc88506e84e5754d6bfde81ba091f24d +Bug-Debian: https://bugs.debian.org/698821 + +Remove calling arcmsr_hbb_enable_driver_mode by in-lining the code into +the caller. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr_hba.c | 18 ++++++------------ + 1 file changed, 6 insertions(+), 12 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index bfe2ac4..5dd520b 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -858,17 +858,6 @@ static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb) + return rtnval; + } + +-static bool arcmsr_hbb_enable_driver_mode(struct AdapterControlBlock *pacb) +-{ +- struct MessageUnit_B *reg = pacb->pmuB; +- writel(ARCMSR_MESSAGE_START_DRIVER_MODE, reg->drv2iop_doorbell); +- if (!arcmsr_hbb_wait_msgint_ready(pacb)) { +- printk(KERN_ERR "arcmsr%d: can't set driver mode. \n", pacb->host->host_no); +- return false; +- } +- return true; +-} +- + static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) + { + struct scsi_cmnd *pcmd = ccb->pcmd; +@@ -2665,7 +2654,12 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + timeout \n",acb->host->host_no); + return 1; + } +- arcmsr_hbb_enable_driver_mode(acb); ++ writel(ARCMSR_MESSAGE_START_DRIVER_MODE, reg->drv2iop_doorbell); ++ if (!arcmsr_hbb_wait_msgint_ready(acb)) { ++ pr_err("arcmsr%d: can't set driver mode.\n", ++ acb->host->host_no); ++ return 1; ++ } + } + break; + case ACB_ADAPTER_TYPE_C: { diff --git a/debian/patches/features/all/arcmsr/0009-arcmsr-modify-printing-adapter-model-number-and-f-w-.patch b/debian/patches/features/all/arcmsr/0009-arcmsr-modify-printing-adapter-model-number-and-f-w-.patch new file mode 100644 index 000000000..570296445 --- /dev/null +++ b/debian/patches/features/all/arcmsr/0009-arcmsr-modify-printing-adapter-model-number-and-f-w-.patch @@ -0,0 +1,61 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 15:03:55 +0800 +Subject: [09/19] arcmsr: modify printing adapter model number and F/W messages +Origin: https://git.kernel.org/linus/a2c89bbccac476d42a8526c0c59d081d9e56d0a8 +Bug-Debian: https://bugs.debian.org/698821 + +Adjust printing order of adapter model name and firmware version. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr_hba.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index 5dd520b..0707677 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -2207,10 +2207,10 @@ static bool arcmsr_get_hba_config(struct AdapterControlBlock *acb) + iop_device_map++; + count--; + } +- printk(KERN_NOTICE "Areca RAID Controller%d: F/W %s & Model %s\n", ++ pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n", + acb->host->host_no, +- acb->firm_version, +- acb->firm_model); ++ acb->firm_model, ++ acb->firm_version); + acb->signature = readl(®->message_rwbuffer[0]); + acb->firm_request_len = readl(®->message_rwbuffer[1]); + acb->firm_numbers_queue = readl(®->message_rwbuffer[2]); +@@ -2283,10 +2283,10 @@ static bool arcmsr_get_hbb_config(struct AdapterControlBlock *acb) + count--; + } + +- printk(KERN_NOTICE "Areca RAID Controller%d: F/W %s & Model %s\n", ++ pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n", + acb->host->host_no, +- acb->firm_version, +- acb->firm_model); ++ acb->firm_model, ++ acb->firm_version); + + acb->signature = readl(®->message_rwbuffer[1]); + /*firm_signature,1,00-03*/ +@@ -2349,10 +2349,10 @@ static bool arcmsr_get_hbc_config(struct AdapterControlBlock *pACB) + iop_firm_version++; + count--; + } +- printk(KERN_NOTICE "Areca RAID Controller%d: F/W %s & Model %s\n", ++ pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n", + pACB->host->host_no, +- pACB->firm_version, +- pACB->firm_model); ++ pACB->firm_model, ++ pACB->firm_version); + pACB->firm_request_len = readl(®->msgcode_rwbuffer[1]); /*firm_request_len,1,04-07*/ + pACB->firm_numbers_queue = readl(®->msgcode_rwbuffer[2]); /*firm_numbers_queue,2,08-11*/ + pACB->firm_sdram_size = readl(®->msgcode_rwbuffer[3]); /*firm_sdram_size,3,12-15*/ diff --git a/debian/patches/features/all/arcmsr/0010-arcmsr-clear-outbound-doorbell-buffer-completely.patch b/debian/patches/features/all/arcmsr/0010-arcmsr-clear-outbound-doorbell-buffer-completely.patch new file mode 100644 index 000000000..18c6b341b --- /dev/null +++ b/debian/patches/features/all/arcmsr/0010-arcmsr-clear-outbound-doorbell-buffer-completely.patch @@ -0,0 +1,57 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 15:07:35 +0800 +Subject: [10/19] arcmsr: clear outbound doorbell buffer completely +Origin: https://git.kernel.org/linus/5eb6bfa02a9dfecbb1f644a0b13b16cd3d23770b +Bug-Debian: https://bugs.debian.org/698821 + +Clear outbound doorbell buffer completely for adapter type C. This is to +prevent getting bad data input from IOP before ioctl command processing +starts. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr_hba.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index 0707677..3363c31 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -2870,11 +2870,23 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb) + break; + case ACB_ADAPTER_TYPE_C: { + struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC; +- uint32_t outbound_doorbell; ++ uint32_t outbound_doorbell, i; + /* empty doorbell Qbuffer if door bell ringed */ + outbound_doorbell = readl(®->outbound_doorbell); + writel(outbound_doorbell, ®->outbound_doorbell_clear); + writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, ®->inbound_doorbell); ++ for (i = 0; i < 200; i++) { ++ msleep(20); ++ outbound_doorbell = readl(®->outbound_doorbell); ++ if (outbound_doorbell & ++ ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { ++ writel(outbound_doorbell, ++ ®->outbound_doorbell_clear); ++ writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, ++ ®->inbound_doorbell); ++ } else ++ break; ++ } + } + } + } +@@ -3102,9 +3114,7 @@ sleep: + arcmsr_get_firmware_spec(acb); + arcmsr_start_adapter_bgrb(acb); + /* clear Qbuffer if door bell ringed */ +- outbound_doorbell = readl(®->outbound_doorbell); +- writel(outbound_doorbell, ®->outbound_doorbell_clear); /*clear interrupt */ +- writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, ®->inbound_doorbell); ++ arcmsr_clear_doorbell_queue_buffer(acb); + /* enable outbound Post Queue,outbound doorbell Interrupt */ + arcmsr_enable_outbound_ints(acb, intmask_org); + atomic_set(&acb->rq_map_token, 16); diff --git a/debian/patches/features/all/arcmsr/0011-arcmsr-rename-functions-and-variables.patch b/debian/patches/features/all/arcmsr/0011-arcmsr-rename-functions-and-variables.patch new file mode 100644 index 000000000..c2b18f418 --- /dev/null +++ b/debian/patches/features/all/arcmsr/0011-arcmsr-rename-functions-and-variables.patch @@ -0,0 +1,857 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 15:10:12 +0800 +Subject: [11/19] arcmsr: rename functions and variables +Origin: https://git.kernel.org/linus/626fa32c801ed583594831051ff9fd56f2e6d261 +Bug-Debian: https://bugs.debian.org/698821 + +Rename some variable and function names for readability and consistency. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr.h | 6 +- + drivers/scsi/arcmsr/arcmsr_hba.c | 234 ++++++++++++++++++++------------------- + 2 files changed, 121 insertions(+), 119 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h +index 0ae0ce3..6d616be 100644 +--- a/drivers/scsi/arcmsr/arcmsr.h ++++ b/drivers/scsi/arcmsr/arcmsr.h +@@ -359,7 +359,7 @@ struct ARCMSR_CDB + #define ARCMSR_CDB_FLAG_ORDEREDQ 0x10 + + uint8_t msgPages; +- uint32_t Context; ++ uint32_t msgContext; + uint32_t DataLength; + uint8_t Cdb[16]; + uint8_t DeviceStatus; +@@ -562,7 +562,7 @@ struct AdapterControlBlock + /* dma_coherent used for memory free */ + dma_addr_t dma_coherent_handle; + /* dma_coherent_handle used for memory free */ +- dma_addr_t dma_coherent_handle_hbb_mu; ++ dma_addr_t dma_coherent_handle2; + unsigned int uncache_size; + uint8_t rqbuffer[ARCMSR_MAX_QBUFFER]; + /* data collection buffer for read from 80331 */ +@@ -613,7 +613,7 @@ struct CommandControlBlock{ + struct list_head list; /*x32: 8byte, x64: 16byte*/ + struct scsi_cmnd *pcmd; /*8 bytes pointer of linux scsi command */ + struct AdapterControlBlock *acb; /*x32: 4byte, x64: 8byte*/ +- uint32_t cdb_phyaddr_pattern; /*x32: 4byte, x64: 4byte*/ ++ uint32_t cdb_phyaddr; /*x32: 4byte, x64: 4byte*/ + uint32_t arc_cdb_size; /*x32:4byte,x64:4byte*/ + uint16_t ccb_flags; /*x32: 2byte, x64: 2byte*/ + #define CCB_FLAG_READ 0x0000 +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index 3363c31..7253323 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -99,16 +99,16 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); + static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, + u32 intmask_org); + static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); +-static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb); +-static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb); ++static void arcmsr_hbaA_flush_cache(struct AdapterControlBlock *acb); ++static void arcmsr_hbaB_flush_cache(struct AdapterControlBlock *acb); + static void arcmsr_request_device_map(unsigned long pacb); +-static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb); +-static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb); +-static void arcmsr_request_hbc_device_map(struct AdapterControlBlock *acb); ++static void arcmsr_hbaA_request_device_map(struct AdapterControlBlock *acb); ++static void arcmsr_hbaB_request_device_map(struct AdapterControlBlock *acb); ++static void arcmsr_hbaC_request_device_map(struct AdapterControlBlock *acb); + static void arcmsr_message_isr_bh_fn(struct work_struct *work); + static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb); + static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); +-static void arcmsr_hbc_message_isr(struct AdapterControlBlock *pACB); ++static void arcmsr_hbaC_message_isr(struct AdapterControlBlock *pACB); + static void arcmsr_hardware_reset(struct AdapterControlBlock *acb); + static const char *arcmsr_info(struct Scsi_Host *); + static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); +@@ -201,7 +201,7 @@ static struct pci_driver arcmsr_pci_driver = { + **************************************************************************** + */ + +-static void arcmsr_free_hbb_mu(struct AdapterControlBlock *acb) ++static void arcmsr_free_mu(struct AdapterControlBlock *acb) + { + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: +@@ -210,7 +210,7 @@ static void arcmsr_free_hbb_mu(struct AdapterControlBlock *acb) + case ACB_ADAPTER_TYPE_B:{ + dma_free_coherent(&acb->pdev->dev, + sizeof(struct MessageUnit_B), +- acb->pmuB, acb->dma_coherent_handle_hbb_mu); ++ acb->pmuB, acb->dma_coherent_handle2); + } + } + } +@@ -316,7 +316,7 @@ static int arcmsr_bios_param(struct scsi_device *sdev, + return 0; + } + +-static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) ++static uint8_t arcmsr_hbaA_wait_msgint_ready(struct AdapterControlBlock *acb) + { + struct MessageUnit_A __iomem *reg = acb->pmuA; + int i; +@@ -334,7 +334,7 @@ static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) + return false; + } + +-static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) ++static uint8_t arcmsr_hbaB_wait_msgint_ready(struct AdapterControlBlock *acb) + { + struct MessageUnit_B *reg = acb->pmuB; + int i; +@@ -354,7 +354,7 @@ static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) + return false; + } + +-static uint8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *pACB) ++static uint8_t arcmsr_hbaC_wait_msgint_ready(struct AdapterControlBlock *pACB) + { + struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)pACB->pmuC; + int i; +@@ -372,13 +372,13 @@ static uint8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *pACB) + return false; + } + +-static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) ++static void arcmsr_hbaA_flush_cache(struct AdapterControlBlock *acb) + { + struct MessageUnit_A __iomem *reg = acb->pmuA; + int retry_count = 30; + writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); + do { +- if (arcmsr_hba_wait_msgint_ready(acb)) ++ if (arcmsr_hbaA_wait_msgint_ready(acb)) + break; + else { + retry_count--; +@@ -388,13 +388,13 @@ static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) + } while (retry_count != 0); + } + +-static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) ++static void arcmsr_hbaB_flush_cache(struct AdapterControlBlock *acb) + { + struct MessageUnit_B *reg = acb->pmuB; + int retry_count = 30; + writel(ARCMSR_MESSAGE_FLUSH_CACHE, reg->drv2iop_doorbell); + do { +- if (arcmsr_hbb_wait_msgint_ready(acb)) ++ if (arcmsr_hbaB_wait_msgint_ready(acb)) + break; + else { + retry_count--; +@@ -404,14 +404,14 @@ static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) + } while (retry_count != 0); + } + +-static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *pACB) ++static void arcmsr_hbaC_flush_cache(struct AdapterControlBlock *pACB) + { + struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC; + int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ + writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell); + do { +- if (arcmsr_hbc_wait_msgint_ready(pACB)) { ++ if (arcmsr_hbaC_wait_msgint_ready(pACB)) { + break; + } else { + retry_count--; +@@ -426,16 +426,16 @@ static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { +- arcmsr_flush_hba_cache(acb); ++ arcmsr_hbaA_flush_cache(acb); + } + break; + + case ACB_ADAPTER_TYPE_B: { +- arcmsr_flush_hbb_cache(acb); ++ arcmsr_hbaB_flush_cache(acb); + } + break; + case ACB_ADAPTER_TYPE_C: { +- arcmsr_flush_hbc_cache(acb); ++ arcmsr_hbaC_flush_cache(acb); + } + } + } +@@ -480,7 +480,9 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) + acb->vir2phy_offset = (unsigned long)dma_coherent - (unsigned long)dma_coherent_handle; + for(i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++){ + cdb_phyaddr = dma_coherent_handle + offsetof(struct CommandControlBlock, arcmsr_cdb); +- ccb_tmp->cdb_phyaddr_pattern = ((acb->adapter_type == ACB_ADAPTER_TYPE_C) ? cdb_phyaddr : (cdb_phyaddr >> 5)); ++ ccb_tmp->cdb_phyaddr = ++ ((acb->adapter_type == ACB_ADAPTER_TYPE_C) ? ++ cdb_phyaddr : (cdb_phyaddr >> 5)); + acb->pccb_pool[i] = ccb_tmp; + ccb_tmp->acb = acb; + INIT_LIST_HEAD(&ccb_tmp->list); +@@ -700,7 +702,7 @@ RAID_controller_stop: + arcmsr_flush_adapter_cache(acb); + arcmsr_free_ccb_pool(acb); + free_hbb_mu: +- arcmsr_free_hbb_mu(acb); ++ arcmsr_free_mu(acb); + unmap_pci_region: + arcmsr_unmap_pciregion(acb); + pci_release_regs: +@@ -798,40 +800,40 @@ controller_unregister: + return -ENODEV; + } + +-static uint8_t arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) ++static uint8_t arcmsr_hbaA_abort_allcmd(struct AdapterControlBlock *acb) + { + struct MessageUnit_A __iomem *reg = acb->pmuA; + writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); +- if (!arcmsr_hba_wait_msgint_ready(acb)) { ++ if (!arcmsr_hbaA_wait_msgint_ready(acb)) { + printk(KERN_NOTICE +- "arcmsr%d: wait 'abort all outstanding command' timeout \n" ++ "arcmsr%d: wait 'abort all outstanding command' timeout\n" + , acb->host->host_no); + return false; + } + return true; + } + +-static uint8_t arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) ++static uint8_t arcmsr_hbaB_abort_allcmd(struct AdapterControlBlock *acb) + { + struct MessageUnit_B *reg = acb->pmuB; + + writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell); +- if (!arcmsr_hbb_wait_msgint_ready(acb)) { ++ if (!arcmsr_hbaB_wait_msgint_ready(acb)) { + printk(KERN_NOTICE +- "arcmsr%d: wait 'abort all outstanding command' timeout \n" ++ "arcmsr%d: wait 'abort all outstanding command' timeout\n" + , acb->host->host_no); + return false; + } + return true; + } +-static uint8_t arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *pACB) ++static uint8_t arcmsr_hbaC_abort_allcmd(struct AdapterControlBlock *pACB) + { + struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC; + writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell); +- if (!arcmsr_hbc_wait_msgint_ready(pACB)) { ++ if (!arcmsr_hbaC_wait_msgint_ready(pACB)) { + printk(KERN_NOTICE +- "arcmsr%d: wait 'abort all outstanding command' timeout \n" ++ "arcmsr%d: wait 'abort all outstanding command' timeout\n" + , pACB->host->host_no); + return false; + } +@@ -842,17 +844,17 @@ static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb) + uint8_t rtnval = 0; + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { +- rtnval = arcmsr_abort_hba_allcmd(acb); ++ rtnval = arcmsr_hbaA_abort_allcmd(acb); + } + break; + + case ACB_ADAPTER_TYPE_B: { +- rtnval = arcmsr_abort_hbb_allcmd(acb); ++ rtnval = arcmsr_hbaB_abort_allcmd(acb); + } + break; + + case ACB_ADAPTER_TYPE_C: { +- rtnval = arcmsr_abort_hbc_allcmd(acb); ++ rtnval = arcmsr_hbaC_abort_allcmd(acb); + } + } + return rtnval; +@@ -1109,7 +1111,7 @@ static void arcmsr_remove(struct pci_dev *pdev) + } + arcmsr_free_irq(pdev, acb); + arcmsr_free_ccb_pool(acb); +- arcmsr_free_hbb_mu(acb); ++ arcmsr_free_mu(acb); + arcmsr_unmap_pciregion(acb); + pci_release_regions(pdev); + scsi_host_put(host); +@@ -1194,7 +1196,7 @@ static int arcmsr_build_ccb(struct AdapterControlBlock *acb, + arcmsr_cdb->TargetID = pcmd->device->id; + arcmsr_cdb->LUN = pcmd->device->lun; + arcmsr_cdb->Function = 1; +- arcmsr_cdb->Context = 0; ++ arcmsr_cdb->msgContext = 0; + memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len); + + nseg = scsi_dma_map(pcmd); +@@ -1235,7 +1237,7 @@ static int arcmsr_build_ccb(struct AdapterControlBlock *acb, + + static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb) + { +- uint32_t cdb_phyaddr_pattern = ccb->cdb_phyaddr_pattern; ++ uint32_t cdb_phyaddr = ccb->cdb_phyaddr; + struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; + atomic_inc(&acb->ccboutstandingcount); + ccb->startdone = ARCMSR_CCB_START; +@@ -1244,13 +1246,12 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr + struct MessageUnit_A __iomem *reg = acb->pmuA; + + if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) +- writel(cdb_phyaddr_pattern | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, ++ writel(cdb_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, + ®->inbound_queueport); +- else { +- writel(cdb_phyaddr_pattern, ®->inbound_queueport); +- } +- } ++ else ++ writel(cdb_phyaddr, ®->inbound_queueport); + break; ++ } + + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = acb->pmuB; +@@ -1259,10 +1260,10 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr + ending_index = ((index + 1) % ARCMSR_MAX_HBB_POSTQUEUE); + writel(0, ®->post_qbuffer[ending_index]); + if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { +- writel(cdb_phyaddr_pattern | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,\ ++ writel(cdb_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, + ®->post_qbuffer[index]); + } else { +- writel(cdb_phyaddr_pattern, ®->post_qbuffer[index]); ++ writel(cdb_phyaddr, ®->post_qbuffer[index]); + } + index++; + index %= ARCMSR_MAX_HBB_POSTQUEUE;/*if last index number set it to 0 */ +@@ -1275,7 +1276,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr + uint32_t ccb_post_stamp, arc_cdb_size; + + arc_cdb_size = (ccb->arc_cdb_size > 0x300) ? 0x300 : ccb->arc_cdb_size; +- ccb_post_stamp = (cdb_phyaddr_pattern | ((arc_cdb_size - 1) >> 6) | 1); ++ ccb_post_stamp = (cdb_phyaddr | ((arc_cdb_size - 1) >> 6) | 1); + if (acb->cdb_phyaddr_hi32) { + writel(acb->cdb_phyaddr_hi32, &phbcmu->inbound_queueport_high); + writel(ccb_post_stamp, &phbcmu->inbound_queueport_low); +@@ -1286,40 +1287,40 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr + } + } + +-static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) ++static void arcmsr_hbaA_stop_bgrb(struct AdapterControlBlock *acb) + { + struct MessageUnit_A __iomem *reg = acb->pmuA; + acb->acb_flags &= ~ACB_F_MSG_START_BGRB; + writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0); +- if (!arcmsr_hba_wait_msgint_ready(acb)) { ++ if (!arcmsr_hbaA_wait_msgint_ready(acb)) { + printk(KERN_NOTICE +- "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" ++ "arcmsr%d: wait 'stop adapter background rebulid' timeout\n" + , acb->host->host_no); + } + } + +-static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) ++static void arcmsr_hbaB_stop_bgrb(struct AdapterControlBlock *acb) + { + struct MessageUnit_B *reg = acb->pmuB; + acb->acb_flags &= ~ACB_F_MSG_START_BGRB; + writel(ARCMSR_MESSAGE_STOP_BGRB, reg->drv2iop_doorbell); + +- if (!arcmsr_hbb_wait_msgint_ready(acb)) { ++ if (!arcmsr_hbaB_wait_msgint_ready(acb)) { + printk(KERN_NOTICE +- "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" ++ "arcmsr%d: wait 'stop adapter background rebulid' timeout\n" + , acb->host->host_no); + } + } + +-static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *pACB) ++static void arcmsr_hbaC_stop_bgrb(struct AdapterControlBlock *pACB) + { + struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC; + pACB->acb_flags &= ~ACB_F_MSG_START_BGRB; + writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell); +- if (!arcmsr_hbc_wait_msgint_ready(pACB)) { ++ if (!arcmsr_hbaC_wait_msgint_ready(pACB)) { + printk(KERN_NOTICE +- "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" ++ "arcmsr%d: wait 'stop adapter background rebulid' timeout\n" + , pACB->host->host_no); + } + return; +@@ -1328,16 +1329,16 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) + { + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { +- arcmsr_stop_hba_bgrb(acb); ++ arcmsr_hbaA_stop_bgrb(acb); + } + break; + + case ACB_ADAPTER_TYPE_B: { +- arcmsr_stop_hbb_bgrb(acb); ++ arcmsr_hbaB_stop_bgrb(acb); + } + break; + case ACB_ADAPTER_TYPE_C: { +- arcmsr_stop_hbc_bgrb(acb); ++ arcmsr_hbaC_stop_bgrb(acb); + } + } + } +@@ -1515,7 +1516,7 @@ static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) + } + } + +-static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) ++static void arcmsr_hbaA_doorbell_isr(struct AdapterControlBlock *acb) + { + uint32_t outbound_doorbell; + struct MessageUnit_A __iomem *reg = acb->pmuA; +@@ -1530,7 +1531,7 @@ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) + } while (outbound_doorbell & (ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK + | ARCMSR_OUTBOUND_IOP331_DATA_READ_OK)); + } +-static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *pACB) ++static void arcmsr_hbaC_doorbell_isr(struct AdapterControlBlock *pACB) + { + uint32_t outbound_doorbell; + struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC; +@@ -1550,13 +1551,13 @@ static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *pACB) + if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) + arcmsr_iop2drv_data_read_handle(pACB); + if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) +- arcmsr_hbc_message_isr(pACB); ++ arcmsr_hbaC_message_isr(pACB); + outbound_doorbell = readl(®->outbound_doorbell); + } while (outbound_doorbell & (ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK + | ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK + | ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE)); + } +-static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) ++static void arcmsr_hbaA_postqueue_isr(struct AdapterControlBlock *acb) + { + uint32_t flag_ccb; + struct MessageUnit_A __iomem *reg = acb->pmuA; +@@ -1570,7 +1571,7 @@ static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) + arcmsr_drain_donequeue(acb, pCCB, error); + } + } +-static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) ++static void arcmsr_hbaB_postqueue_isr(struct AdapterControlBlock *acb) + { + uint32_t index; + uint32_t flag_ccb; +@@ -1591,7 +1592,7 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) + } + } + +-static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) ++static void arcmsr_hbaC_postqueue_isr(struct AdapterControlBlock *acb) + { + struct MessageUnit_C *phbcmu; + struct ARCMSR_CDB *arcmsr_cdb; +@@ -1630,14 +1631,14 @@ static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) + ** We want this in order to compare the drivemap so that we can detect newly-attached drives. + ********************************************************************************** + */ +-static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) ++static void arcmsr_hbaA_message_isr(struct AdapterControlBlock *acb) + { + struct MessageUnit_A *reg = acb->pmuA; + /*clear interrupt and message state*/ + writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT, ®->outbound_intstatus); + schedule_work(&acb->arcmsr_do_message_isr_bh); + } +-static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) ++static void arcmsr_hbaB_message_isr(struct AdapterControlBlock *acb) + { + struct MessageUnit_B *reg = acb->pmuB; + +@@ -1654,7 +1655,7 @@ static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) + ** We want this in order to compare the drivemap so that we can detect newly-attached drives. + ********************************************************************************** + */ +-static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) ++static void arcmsr_hbaC_message_isr(struct AdapterControlBlock *acb) + { + struct MessageUnit_C *reg = acb->pmuC; + /*clear interrupt and message state*/ +@@ -1662,7 +1663,7 @@ static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) + schedule_work(&acb->arcmsr_do_message_isr_bh); + } + +-static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) ++static int arcmsr_hbaA_handle_isr(struct AdapterControlBlock *acb) + { + uint32_t outbound_intstatus; + struct MessageUnit_A __iomem *reg = acb->pmuA; +@@ -1673,11 +1674,11 @@ static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) + do { + writel(outbound_intstatus, ®->outbound_intstatus); + if (outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) +- arcmsr_hba_doorbell_isr(acb); ++ arcmsr_hbaA_doorbell_isr(acb); + if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) +- arcmsr_hba_postqueue_isr(acb); ++ arcmsr_hbaA_postqueue_isr(acb); + if (outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) +- arcmsr_hba_message_isr(acb); ++ arcmsr_hbaA_message_isr(acb); + outbound_intstatus = readl(®->outbound_intstatus) & + acb->outbound_int_enable; + } while (outbound_intstatus & (ARCMSR_MU_OUTBOUND_DOORBELL_INT +@@ -1686,7 +1687,7 @@ static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) + return IRQ_HANDLED; + } + +-static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) ++static int arcmsr_hbaB_handle_isr(struct AdapterControlBlock *acb) + { + uint32_t outbound_doorbell; + struct MessageUnit_B *reg = acb->pmuB; +@@ -1702,9 +1703,9 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) + if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) + arcmsr_iop2drv_data_read_handle(acb); + if (outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) +- arcmsr_hbb_postqueue_isr(acb); ++ arcmsr_hbaB_postqueue_isr(acb); + if (outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) +- arcmsr_hbb_message_isr(acb); ++ arcmsr_hbaB_message_isr(acb); + outbound_doorbell = readl(reg->iop2drv_doorbell) & + acb->outbound_int_enable; + } while (outbound_doorbell & (ARCMSR_IOP2DRV_DATA_WRITE_OK +@@ -1714,7 +1715,7 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) + return IRQ_HANDLED; + } + +-static int arcmsr_handle_hbc_isr(struct AdapterControlBlock *pACB) ++static int arcmsr_hbaC_handle_isr(struct AdapterControlBlock *pACB) + { + uint32_t host_interrupt_status; + struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)pACB->pmuC; +@@ -1730,10 +1731,10 @@ static int arcmsr_handle_hbc_isr(struct AdapterControlBlock *pACB) + return IRQ_NONE; + do { + if (host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) +- arcmsr_hbc_doorbell_isr(pACB); ++ arcmsr_hbaC_doorbell_isr(pACB); + /* MU post queue interrupts*/ + if (host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) +- arcmsr_hbc_postqueue_isr(pACB); ++ arcmsr_hbaC_postqueue_isr(pACB); + host_interrupt_status = readl(&phbcmu->host_int_status); + } while (host_interrupt_status & (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | + ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR)); +@@ -1743,13 +1744,13 @@ static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) + { + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: +- return arcmsr_handle_hba_isr(acb); ++ return arcmsr_hbaA_handle_isr(acb); + break; + case ACB_ADAPTER_TYPE_B: +- return arcmsr_handle_hbb_isr(acb); ++ return arcmsr_hbaB_handle_isr(acb); + break; + case ACB_ADAPTER_TYPE_C: +- return arcmsr_handle_hbc_isr(acb); ++ return arcmsr_hbaC_handle_isr(acb); + default: + return IRQ_NONE; + } +@@ -2168,7 +2169,7 @@ static int arcmsr_queue_command_lck(struct scsi_cmnd *cmd, + + static DEF_SCSI_QCMD(arcmsr_queue_command) + +-static bool arcmsr_get_hba_config(struct AdapterControlBlock *acb) ++static bool arcmsr_hbaA_get_config(struct AdapterControlBlock *acb) + { + struct MessageUnit_A __iomem *reg = acb->pmuA; + char *acb_firm_model = acb->firm_model; +@@ -2179,7 +2180,7 @@ static bool arcmsr_get_hba_config(struct AdapterControlBlock *acb) + char __iomem *iop_device_map = (char __iomem *)(®->message_rwbuffer[21]); + int count; + writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); +- if (!arcmsr_hba_wait_msgint_ready(acb)) { ++ if (!arcmsr_hbaA_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ + miscellaneous data' timeout \n", acb->host->host_no); + return false; +@@ -2219,7 +2220,7 @@ static bool arcmsr_get_hba_config(struct AdapterControlBlock *acb) + acb->firm_cfg_version = readl(®->message_rwbuffer[25]); /*firm_cfg_version,25,100-103*/ + return true; + } +-static bool arcmsr_get_hbb_config(struct AdapterControlBlock *acb) ++static bool arcmsr_hbaB_get_config(struct AdapterControlBlock *acb) + { + struct MessageUnit_B *reg = acb->pmuB; + struct pci_dev *pdev = acb->pdev; +@@ -2240,7 +2241,7 @@ static bool arcmsr_get_hbb_config(struct AdapterControlBlock *acb) + printk(KERN_NOTICE "arcmsr%d: dma_alloc_coherent got error for hbb mu\n", acb->host->host_no); + return false; + } +- acb->dma_coherent_handle_hbb_mu = dma_coherent_handle; ++ acb->dma_coherent_handle2 = dma_coherent_handle; + reg = (struct MessageUnit_B *)dma_coherent; + acb->pmuB = reg; + reg->drv2iop_doorbell= (uint32_t __iomem *)((unsigned long)acb->mem_base0 + ARCMSR_DRV2IOP_DOORBELL); +@@ -2255,7 +2256,7 @@ static bool arcmsr_get_hbb_config(struct AdapterControlBlock *acb) + iop_device_map = (char __iomem *)(®->message_rwbuffer[21]); /*firm_version,21,84-99*/ + + writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell); +- if (!arcmsr_hbb_wait_msgint_ready(acb)) { ++ if (!arcmsr_hbaB_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ + miscellaneous data' timeout \n", acb->host->host_no); + return false; +@@ -2303,7 +2304,7 @@ static bool arcmsr_get_hbb_config(struct AdapterControlBlock *acb) + return true; + } + +-static bool arcmsr_get_hbc_config(struct AdapterControlBlock *pACB) ++static bool arcmsr_hbaC_get_config(struct AdapterControlBlock *pACB) + { + uint32_t intmask_org, Index, firmware_state = 0; + struct MessageUnit_C *reg = pACB->pmuC; +@@ -2367,13 +2368,13 @@ static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) + + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: +- rtn = arcmsr_get_hba_config(acb); ++ rtn = arcmsr_hbaA_get_config(acb); + break; + case ACB_ADAPTER_TYPE_B: +- rtn = arcmsr_get_hbb_config(acb); ++ rtn = arcmsr_hbaB_get_config(acb); + break; + case ACB_ADAPTER_TYPE_C: +- rtn = arcmsr_get_hbc_config(acb); ++ rtn = arcmsr_hbaC_get_config(acb); + break; + default: + break; +@@ -2386,7 +2387,7 @@ static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) + return rtn; + } + +-static int arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, ++static int arcmsr_hbaA_polling_ccbdone(struct AdapterControlBlock *acb, + struct CommandControlBlock *poll_ccb) + { + struct MessageUnit_A __iomem *reg = acb->pmuA; +@@ -2442,7 +2443,7 @@ static int arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, + return rtn; + } + +-static int arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, ++static int arcmsr_hbaB_polling_ccbdone(struct AdapterControlBlock *acb, + struct CommandControlBlock *poll_ccb) + { + struct MessageUnit_B *reg = acb->pmuB; +@@ -2506,7 +2507,8 @@ static int arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, + return rtn; + } + +-static int arcmsr_polling_hbc_ccbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_ccb) ++static int arcmsr_hbaC_polling_ccbdone(struct AdapterControlBlock *acb, ++ struct CommandControlBlock *poll_ccb) + { + struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC; + uint32_t flag_ccb, ccb_cdb_phy; +@@ -2569,16 +2571,16 @@ static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { +- rtn = arcmsr_polling_hba_ccbdone(acb, poll_ccb); ++ rtn = arcmsr_hbaA_polling_ccbdone(acb, poll_ccb); + } + break; + + case ACB_ADAPTER_TYPE_B: { +- rtn = arcmsr_polling_hbb_ccbdone(acb, poll_ccb); ++ rtn = arcmsr_hbaB_polling_ccbdone(acb, poll_ccb); + } + break; + case ACB_ADAPTER_TYPE_C: { +- rtn = arcmsr_polling_hbc_ccbdone(acb, poll_ccb); ++ rtn = arcmsr_hbaC_polling_ccbdone(acb, poll_ccb); + } + } + return rtn; +@@ -2612,7 +2614,7 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + writel(cdb_phyaddr_hi32, ®->message_rwbuffer[1]); + writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, \ + ®->inbound_msgaddr0); +- if (!arcmsr_hba_wait_msgint_ready(acb)) { ++ if (!arcmsr_hbaA_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: ""set ccb high \ + part physical address timeout\n", + acb->host->host_no); +@@ -2630,12 +2632,12 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + reg->postq_index = 0; + reg->doneq_index = 0; + writel(ARCMSR_MESSAGE_SET_POST_WINDOW, reg->drv2iop_doorbell); +- if (!arcmsr_hbb_wait_msgint_ready(acb)) { ++ if (!arcmsr_hbaB_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d:can not set diver mode\n", \ + acb->host->host_no); + return 1; + } +- post_queue_phyaddr = acb->dma_coherent_handle_hbb_mu; ++ post_queue_phyaddr = acb->dma_coherent_handle2; + rwbuffer = reg->message_rwbuffer; + /* driver "set config" signature */ + writel(ARCMSR_SIGNATURE_SET_CONFIG, rwbuffer++); +@@ -2649,13 +2651,13 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + writel(1056, rwbuffer); + + writel(ARCMSR_MESSAGE_SET_CONFIG, reg->drv2iop_doorbell); +- if (!arcmsr_hbb_wait_msgint_ready(acb)) { ++ if (!arcmsr_hbaB_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: 'set command Q window' \ + timeout \n",acb->host->host_no); + return 1; + } + writel(ARCMSR_MESSAGE_START_DRIVER_MODE, reg->drv2iop_doorbell); +- if (!arcmsr_hbb_wait_msgint_ready(acb)) { ++ if (!arcmsr_hbaB_wait_msgint_ready(acb)) { + pr_err("arcmsr%d: can't set driver mode.\n", + acb->host->host_no); + return 1; +@@ -2672,7 +2674,7 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + writel(cdb_phyaddr_hi32, ®->msgcode_rwbuffer[1]); + writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, ®->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell); +- if (!arcmsr_hbc_wait_msgint_ready(acb)) { ++ if (!arcmsr_hbaC_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: 'set command Q window' \ + timeout \n", acb->host->host_no); + return 1; +@@ -2713,7 +2715,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) + } + } + +-static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb) ++static void arcmsr_hbaA_request_device_map(struct AdapterControlBlock *acb) + { + struct MessageUnit_A __iomem *reg = acb->pmuA; + if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0 ) || ((acb->acb_flags & ACB_F_ABORT) != 0 )){ +@@ -2735,7 +2737,7 @@ static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb) + return; + } + +-static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb) ++static void arcmsr_hbaB_request_device_map(struct AdapterControlBlock *acb) + { + struct MessageUnit_B __iomem *reg = acb->pmuB; + if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0 ) || ((acb->acb_flags & ACB_F_ABORT) != 0 )){ +@@ -2757,7 +2759,7 @@ static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb) + return; + } + +-static void arcmsr_request_hbc_device_map(struct AdapterControlBlock *acb) ++static void arcmsr_hbaC_request_device_map(struct AdapterControlBlock *acb) + { + struct MessageUnit_C __iomem *reg = acb->pmuC; + if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0) || ((acb->acb_flags & ACB_F_ABORT) != 0)) { +@@ -2785,48 +2787,48 @@ static void arcmsr_request_device_map(unsigned long pacb) + struct AdapterControlBlock *acb = (struct AdapterControlBlock *)pacb; + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { +- arcmsr_request_hba_device_map(acb); ++ arcmsr_hbaA_request_device_map(acb); + } + break; + case ACB_ADAPTER_TYPE_B: { +- arcmsr_request_hbb_device_map(acb); ++ arcmsr_hbaB_request_device_map(acb); + } + break; + case ACB_ADAPTER_TYPE_C: { +- arcmsr_request_hbc_device_map(acb); ++ arcmsr_hbaC_request_device_map(acb); + } + } + } + +-static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) ++static void arcmsr_hbaA_start_bgrb(struct AdapterControlBlock *acb) + { + struct MessageUnit_A __iomem *reg = acb->pmuA; + acb->acb_flags |= ACB_F_MSG_START_BGRB; + writel(ARCMSR_INBOUND_MESG0_START_BGRB, ®->inbound_msgaddr0); +- if (!arcmsr_hba_wait_msgint_ready(acb)) { ++ if (!arcmsr_hbaA_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \ + rebulid' timeout \n", acb->host->host_no); + } + } + +-static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) ++static void arcmsr_hbaB_start_bgrb(struct AdapterControlBlock *acb) + { + struct MessageUnit_B *reg = acb->pmuB; + acb->acb_flags |= ACB_F_MSG_START_BGRB; + writel(ARCMSR_MESSAGE_START_BGRB, reg->drv2iop_doorbell); +- if (!arcmsr_hbb_wait_msgint_ready(acb)) { ++ if (!arcmsr_hbaB_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \ + rebulid' timeout \n",acb->host->host_no); + } + } + +-static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *pACB) ++static void arcmsr_hbaC_start_bgrb(struct AdapterControlBlock *pACB) + { + struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)pACB->pmuC; + pACB->acb_flags |= ACB_F_MSG_START_BGRB; + writel(ARCMSR_INBOUND_MESG0_START_BGRB, &phbcmu->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, &phbcmu->inbound_doorbell); +- if (!arcmsr_hbc_wait_msgint_ready(pACB)) { ++ if (!arcmsr_hbaC_wait_msgint_ready(pACB)) { + printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \ + rebulid' timeout \n", pACB->host->host_no); + } +@@ -2836,13 +2838,13 @@ static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) + { + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: +- arcmsr_start_hba_bgrb(acb); ++ arcmsr_hbaA_start_bgrb(acb); + break; + case ACB_ADAPTER_TYPE_B: +- arcmsr_start_hbb_bgrb(acb); ++ arcmsr_hbaB_start_bgrb(acb); + break; + case ACB_ADAPTER_TYPE_C: +- arcmsr_start_hbc_bgrb(acb); ++ arcmsr_hbaC_start_bgrb(acb); + } + } + +@@ -2900,7 +2902,7 @@ static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) + { + struct MessageUnit_B *reg = acb->pmuB; + writel(ARCMSR_MESSAGE_ACTIVE_EOI_MODE, reg->drv2iop_doorbell); +- if (!arcmsr_hbb_wait_msgint_ready(acb)) { ++ if (!arcmsr_hbaB_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "ARCMSR IOP enables EOI_MODE TIMEOUT"); + return; + } diff --git a/debian/patches/features/all/arcmsr/0012-arcmsr-revise-allocation-of-second-dma_coherent_hand.patch b/debian/patches/features/all/arcmsr/0012-arcmsr-revise-allocation-of-second-dma_coherent_hand.patch new file mode 100644 index 000000000..b5aeee9eb --- /dev/null +++ b/debian/patches/features/all/arcmsr/0012-arcmsr-revise-allocation-of-second-dma_coherent_hand.patch @@ -0,0 +1,134 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 15:14:14 +0800 +Subject: [12/19] arcmsr: revise allocation of second dma_coherent_handle for + type B +Origin: https://git.kernel.org/linus/6e38adfc58406e7ea6f6701c49abaf046ce076a8 +Bug-Debian: https://bugs.debian.org/698821 + +This modification is for consistency with upcoming adapter type D. +Both adapter type B and D have similar H/W and S/W structure. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr.h | 2 ++ + drivers/scsi/arcmsr/arcmsr_hba.c | 38 ++++++++++++++++++++++++-------------- + 2 files changed, 26 insertions(+), 14 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h +index 6d616be..83c0a7d 100644 +--- a/drivers/scsi/arcmsr/arcmsr.h ++++ b/drivers/scsi/arcmsr/arcmsr.h +@@ -507,6 +507,7 @@ struct AdapterControlBlock + #define ACB_ADAPTER_TYPE_B 0x00000002 /* hbb M IOP */ + #define ACB_ADAPTER_TYPE_C 0x00000004 /* hbc P IOP */ + #define ACB_ADAPTER_TYPE_D 0x00000008 /* hbd A IOP */ ++ u32 roundup_ccbsize; + struct pci_dev * pdev; + struct Scsi_Host * host; + unsigned long vir2phy_offset; +@@ -563,6 +564,7 @@ struct AdapterControlBlock + dma_addr_t dma_coherent_handle; + /* dma_coherent_handle used for memory free */ + dma_addr_t dma_coherent_handle2; ++ void *dma_coherent2; + unsigned int uncache_size; + uint8_t rqbuffer[ARCMSR_MAX_QBUFFER]; + /* data collection buffer for read from 80331 */ +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index 7253323..fc0dfbc 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -204,13 +204,10 @@ static struct pci_driver arcmsr_pci_driver = { + static void arcmsr_free_mu(struct AdapterControlBlock *acb) + { + switch (acb->adapter_type) { +- case ACB_ADAPTER_TYPE_A: +- case ACB_ADAPTER_TYPE_C: +- break; + case ACB_ADAPTER_TYPE_B:{ +- dma_free_coherent(&acb->pdev->dev, +- sizeof(struct MessageUnit_B), +- acb->pmuB, acb->dma_coherent_handle2); ++ dma_free_coherent(&acb->pdev->dev, acb->roundup_ccbsize, ++ acb->dma_coherent2, acb->dma_coherent_handle2); ++ break; + } + } + } +@@ -2236,12 +2233,18 @@ static bool arcmsr_hbaB_get_config(struct AdapterControlBlock *acb) + char __iomem *iop_device_map; + /*firm_version,21,84-99*/ + int count; +- dma_coherent = dma_alloc_coherent(&pdev->dev, sizeof(struct MessageUnit_B), &dma_coherent_handle, GFP_KERNEL); ++ ++ acb->roundup_ccbsize = roundup(sizeof(struct MessageUnit_B), 32); ++ dma_coherent = dma_alloc_coherent(&pdev->dev, acb->roundup_ccbsize, ++ &dma_coherent_handle, GFP_KERNEL); + if (!dma_coherent){ +- printk(KERN_NOTICE "arcmsr%d: dma_alloc_coherent got error for hbb mu\n", acb->host->host_no); ++ printk(KERN_NOTICE ++ "arcmsr%d: dma_alloc_coherent got error for hbb mu\n", ++ acb->host->host_no); + return false; + } + acb->dma_coherent_handle2 = dma_coherent_handle; ++ acb->dma_coherent2 = dma_coherent; + reg = (struct MessageUnit_B *)dma_coherent; + acb->pmuB = reg; + reg->drv2iop_doorbell= (uint32_t __iomem *)((unsigned long)acb->mem_base0 + ARCMSR_DRV2IOP_DOORBELL); +@@ -2589,6 +2592,7 @@ static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, + static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + { + uint32_t cdb_phyaddr, cdb_phyaddr_hi32; ++ dma_addr_t dma_coherent_handle; + + /* + ******************************************************************** +@@ -2596,8 +2600,16 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + ** if freeccb.HighPart is not zero + ******************************************************************** + */ +- cdb_phyaddr = lower_32_bits(acb->dma_coherent_handle); +- cdb_phyaddr_hi32 = upper_32_bits(acb->dma_coherent_handle); ++ switch (acb->adapter_type) { ++ case ACB_ADAPTER_TYPE_B: ++ dma_coherent_handle = acb->dma_coherent_handle2; ++ break; ++ default: ++ dma_coherent_handle = acb->dma_coherent_handle; ++ break; ++ } ++ cdb_phyaddr = lower_32_bits(dma_coherent_handle); ++ cdb_phyaddr_hi32 = upper_32_bits(dma_coherent_handle); + acb->cdb_phyaddr_hi32 = cdb_phyaddr_hi32; + /* + *********************************************************************** +@@ -2625,7 +2637,6 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + break; + + case ACB_ADAPTER_TYPE_B: { +- unsigned long post_queue_phyaddr; + uint32_t __iomem *rwbuffer; + + struct MessageUnit_B *reg = acb->pmuB; +@@ -2637,16 +2648,15 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + acb->host->host_no); + return 1; + } +- post_queue_phyaddr = acb->dma_coherent_handle2; + rwbuffer = reg->message_rwbuffer; + /* driver "set config" signature */ + writel(ARCMSR_SIGNATURE_SET_CONFIG, rwbuffer++); + /* normal should be zero */ + writel(cdb_phyaddr_hi32, rwbuffer++); + /* postQ size (256 + 8)*4 */ +- writel(post_queue_phyaddr, rwbuffer++); ++ writel(cdb_phyaddr, rwbuffer++); + /* doneQ size (256 + 8)*4 */ +- writel(post_queue_phyaddr + 1056, rwbuffer++); ++ writel(cdb_phyaddr + 1056, rwbuffer++); + /* ccb maxQ size must be --> [(256 + 8)*4]*/ + writel(1056, rwbuffer); + diff --git a/debian/patches/features/all/arcmsr/0013-arcmsr-fix-ioctl-data-read-write-error-for-adapter-t.patch b/debian/patches/features/all/arcmsr/0013-arcmsr-fix-ioctl-data-read-write-error-for-adapter-t.patch new file mode 100644 index 000000000..426a6ff16 --- /dev/null +++ b/debian/patches/features/all/arcmsr/0013-arcmsr-fix-ioctl-data-read-write-error-for-adapter-t.patch @@ -0,0 +1,962 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 15:17:45 +0800 +Subject: [13/19] arcmsr: fix ioctl data read/write error for adapter type C +Origin: https://git.kernel.org/linus/bb263c4ecbb186fe394c6c9acc32d8c59b6a7bdd +Bug-Debian: https://bugs.debian.org/698821 + +Rewrite ioctl entry and its relate function. This patch fix ioctl data +read/write error and change data I/O access from byte to Dword. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr.h | 8 +- + drivers/scsi/arcmsr/arcmsr_attr.c | 101 +++++-- + drivers/scsi/arcmsr/arcmsr_hba.c | 572 ++++++++++++++++++++++++-------------- + 3 files changed, 442 insertions(+), 239 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h +index 83c0a7d..799393e 100644 +--- a/drivers/scsi/arcmsr/arcmsr.h ++++ b/drivers/scsi/arcmsr/arcmsr.h +@@ -518,6 +518,8 @@ struct AdapterControlBlock + uint32_t reg_mu_acc_handle0; + spinlock_t eh_lock; + spinlock_t ccblist_lock; ++ spinlock_t rqbuffer_lock; ++ spinlock_t wqbuffer_lock; + union { + struct MessageUnit_A __iomem *pmuA; + struct MessageUnit_B *pmuB; +@@ -693,8 +695,10 @@ struct SENSE_DATA + #define ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE 0x01 + #define ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE 0x1F + +-extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *); +-extern void arcmsr_iop_message_read(struct AdapterControlBlock *); ++extern void arcmsr_write_ioctldata2iop(struct AdapterControlBlock *); ++extern uint32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *, ++ struct QBUFFER __iomem *); ++extern void arcmsr_clear_iop2drv_rqueue_buffer(struct AdapterControlBlock *); + extern struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *); + extern struct device_attribute *arcmsr_host_attrs[]; + extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *); +diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c +index acdae33..16422ad 100644 +--- a/drivers/scsi/arcmsr/arcmsr_attr.c ++++ b/drivers/scsi/arcmsr/arcmsr_attr.c +@@ -70,40 +70,75 @@ static ssize_t arcmsr_sysfs_iop_message_read(struct file *filp, + struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; + uint8_t *pQbuffer,*ptmpQbuffer; + int32_t allxfer_len = 0; ++ unsigned long flags; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + /* do message unit read. */ + ptmpQbuffer = (uint8_t *)buf; +- while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) +- && (allxfer_len < 1031)) { ++ spin_lock_irqsave(&acb->rqbuffer_lock, flags); ++ if (acb->rqbuf_firstindex != acb->rqbuf_lastindex) { + pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; +- memcpy(ptmpQbuffer, pQbuffer, 1); +- acb->rqbuf_firstindex++; +- acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; +- ptmpQbuffer++; +- allxfer_len++; ++ if (acb->rqbuf_firstindex > acb->rqbuf_lastindex) { ++ if ((ARCMSR_MAX_QBUFFER - acb->rqbuf_firstindex) >= 1032) { ++ memcpy(ptmpQbuffer, pQbuffer, 1032); ++ acb->rqbuf_firstindex += 1032; ++ acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; ++ allxfer_len = 1032; ++ } else { ++ if (((ARCMSR_MAX_QBUFFER - acb->rqbuf_firstindex) ++ + acb->rqbuf_lastindex) > 1032) { ++ memcpy(ptmpQbuffer, pQbuffer, ++ ARCMSR_MAX_QBUFFER ++ - acb->rqbuf_firstindex); ++ ptmpQbuffer += ARCMSR_MAX_QBUFFER ++ - acb->rqbuf_firstindex; ++ memcpy(ptmpQbuffer, acb->rqbuffer, 1032 ++ - (ARCMSR_MAX_QBUFFER - ++ acb->rqbuf_firstindex)); ++ acb->rqbuf_firstindex = 1032 - ++ (ARCMSR_MAX_QBUFFER - ++ acb->rqbuf_firstindex); ++ allxfer_len = 1032; ++ } else { ++ memcpy(ptmpQbuffer, pQbuffer, ++ ARCMSR_MAX_QBUFFER - ++ acb->rqbuf_firstindex); ++ ptmpQbuffer += ARCMSR_MAX_QBUFFER - ++ acb->rqbuf_firstindex; ++ memcpy(ptmpQbuffer, acb->rqbuffer, ++ acb->rqbuf_lastindex); ++ allxfer_len = ARCMSR_MAX_QBUFFER - ++ acb->rqbuf_firstindex + ++ acb->rqbuf_lastindex; ++ acb->rqbuf_firstindex = ++ acb->rqbuf_lastindex; ++ } ++ } ++ } else { ++ if ((acb->rqbuf_lastindex - acb->rqbuf_firstindex) > 1032) { ++ memcpy(ptmpQbuffer, pQbuffer, 1032); ++ acb->rqbuf_firstindex += 1032; ++ allxfer_len = 1032; ++ } else { ++ memcpy(ptmpQbuffer, pQbuffer, acb->rqbuf_lastindex ++ - acb->rqbuf_firstindex); ++ allxfer_len = acb->rqbuf_lastindex - ++ acb->rqbuf_firstindex; ++ acb->rqbuf_firstindex = acb->rqbuf_lastindex; ++ } ++ } + } + if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { + struct QBUFFER __iomem *prbuffer; +- uint8_t __iomem *iop_data; +- int32_t iop_len; +- + acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + prbuffer = arcmsr_get_iop_rqbuffer(acb); +- iop_data = prbuffer->data; +- iop_len = readl(&prbuffer->data_len); +- while (iop_len > 0) { +- acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); +- acb->rqbuf_lastindex++; +- acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; +- iop_data++; +- iop_len--; +- } +- arcmsr_iop_message_read(acb); ++ if (arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) ++ acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; + } +- return (allxfer_len); ++ spin_unlock_irqrestore(&acb->rqbuffer_lock, flags); ++ return allxfer_len; + } + + static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp, +@@ -117,6 +152,7 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp, + struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; + int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; + uint8_t *pQbuffer, *ptmpuserbuffer; ++ unsigned long flags; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; +@@ -125,18 +161,19 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp, + /* do message unit write. */ + ptmpuserbuffer = (uint8_t *)buf; + user_len = (int32_t)count; ++ spin_lock_irqsave(&acb->wqbuffer_lock, flags); + wqbuf_lastindex = acb->wqbuf_lastindex; + wqbuf_firstindex = acb->wqbuf_firstindex; + if (wqbuf_lastindex != wqbuf_firstindex) { +- arcmsr_post_ioctldata2iop(acb); ++ arcmsr_write_ioctldata2iop(acb); ++ spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); + return 0; /*need retry*/ + } else { + my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) +- &(ARCMSR_MAX_QBUFFER - 1); ++ &(ARCMSR_MAX_QBUFFER - 1); + if (my_empty_len >= user_len) { + while (user_len > 0) { +- pQbuffer = +- &acb->wqbuffer[acb->wqbuf_lastindex]; ++ pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; + memcpy(pQbuffer, ptmpuserbuffer, 1); + acb->wqbuf_lastindex++; + acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; +@@ -146,10 +183,12 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp, + if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { + acb->acb_flags &= + ~ACB_F_MESSAGE_WQBUFFER_CLEARED; +- arcmsr_post_ioctldata2iop(acb); ++ arcmsr_write_ioctldata2iop(acb); + } ++ spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); + return count; + } else { ++ spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); + return 0; /*need retry*/ + } + } +@@ -165,22 +204,24 @@ static ssize_t arcmsr_sysfs_iop_message_clear(struct file *filp, + struct Scsi_Host *host = class_to_shost(dev); + struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; + uint8_t *pQbuffer; ++ unsigned long flags; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + +- if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { +- acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; +- arcmsr_iop_message_read(acb); +- } ++ arcmsr_clear_iop2drv_rqueue_buffer(acb); + acb->acb_flags |= + (ACB_F_MESSAGE_WQBUFFER_CLEARED + | ACB_F_MESSAGE_RQBUFFER_CLEARED + | ACB_F_MESSAGE_WQBUFFER_READED); ++ spin_lock_irqsave(&acb->rqbuffer_lock, flags); + acb->rqbuf_firstindex = 0; + acb->rqbuf_lastindex = 0; ++ spin_unlock_irqrestore(&acb->rqbuffer_lock, flags); ++ spin_lock_irqsave(&acb->wqbuffer_lock, flags); + acb->wqbuf_firstindex = 0; + acb->wqbuf_lastindex = 0; ++ spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); + pQbuffer = acb->rqbuffer; + memset(pQbuffer, 0, sizeof (struct QBUFFER)); + pQbuffer = acb->wqbuffer; +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index fc0dfbc..1576805 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -653,6 +653,8 @@ static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) + } + spin_lock_init(&acb->eh_lock); + spin_lock_init(&acb->ccblist_lock); ++ spin_lock_init(&acb->rqbuffer_lock); ++ spin_lock_init(&acb->wqbuffer_lock); + acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | + ACB_F_MESSAGE_RQBUFFER_CLEARED | + ACB_F_MESSAGE_WQBUFFER_READED); +@@ -1449,68 +1451,175 @@ static struct QBUFFER __iomem *arcmsr_get_iop_wqbuffer(struct AdapterControlBloc + return pqbuffer; + } + +-static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) ++static uint32_t ++arcmsr_Read_iop_rqbuffer_in_DWORD(struct AdapterControlBlock *acb, ++ struct QBUFFER __iomem *prbuffer) + { +- struct QBUFFER __iomem *prbuffer; +- struct QBUFFER *pQbuffer; +- uint8_t __iomem *iop_data; +- int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; +- rqbuf_lastindex = acb->rqbuf_lastindex; +- rqbuf_firstindex = acb->rqbuf_firstindex; +- prbuffer = arcmsr_get_iop_rqbuffer(acb); +- iop_data = (uint8_t __iomem *)prbuffer->data; +- iop_len = prbuffer->data_len; +- my_empty_len = (rqbuf_firstindex - rqbuf_lastindex - 1) & (ARCMSR_MAX_QBUFFER - 1); +- +- if (my_empty_len >= iop_len) +- { +- while (iop_len > 0) { +- pQbuffer = (struct QBUFFER *)&acb->rqbuffer[rqbuf_lastindex]; +- memcpy(pQbuffer, iop_data, 1); +- rqbuf_lastindex++; +- rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; ++ uint8_t *pQbuffer; ++ uint8_t *buf1 = NULL; ++ uint32_t __iomem *iop_data; ++ uint32_t iop_len, data_len, *buf2 = NULL; ++ ++ iop_data = (uint32_t __iomem *)prbuffer->data; ++ iop_len = readl(&prbuffer->data_len); ++ if (iop_len > 0) { ++ buf1 = kmalloc(128, GFP_ATOMIC); ++ buf2 = (uint32_t *)buf1; ++ if (buf1 == NULL) ++ return 0; ++ data_len = iop_len; ++ while (data_len >= 4) { ++ *buf2++ = readl(iop_data); + iop_data++; +- iop_len--; ++ data_len -= 4; + } +- acb->rqbuf_lastindex = rqbuf_lastindex; +- arcmsr_iop_message_read(acb); ++ if (data_len) ++ *buf2 = readl(iop_data); ++ buf2 = (uint32_t *)buf1; ++ } ++ while (iop_len > 0) { ++ pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; ++ *pQbuffer = *buf1; ++ acb->rqbuf_lastindex++; ++ /* if last, index number set it to 0 */ ++ acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; ++ buf1++; ++ iop_len--; ++ } ++ if (buf2) ++ kfree(buf2); ++ /* let IOP know data has been read */ ++ arcmsr_iop_message_read(acb); ++ return 1; ++} ++ ++uint32_t ++arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, ++ struct QBUFFER __iomem *prbuffer) { ++ ++ uint8_t *pQbuffer; ++ uint8_t __iomem *iop_data; ++ uint32_t iop_len; ++ ++ if (acb->adapter_type & ACB_ADAPTER_TYPE_C) ++ return arcmsr_Read_iop_rqbuffer_in_DWORD(acb, prbuffer); ++ iop_data = (uint8_t __iomem *)prbuffer->data; ++ iop_len = readl(&prbuffer->data_len); ++ while (iop_len > 0) { ++ pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; ++ *pQbuffer = readb(iop_data); ++ acb->rqbuf_lastindex++; ++ acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; ++ iop_data++; ++ iop_len--; + } ++ arcmsr_iop_message_read(acb); ++ return 1; ++} + +- else { ++static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) ++{ ++ unsigned long flags; ++ struct QBUFFER __iomem *prbuffer; ++ int32_t buf_empty_len; ++ ++ spin_lock_irqsave(&acb->rqbuffer_lock, flags); ++ prbuffer = arcmsr_get_iop_rqbuffer(acb); ++ buf_empty_len = (acb->rqbuf_lastindex - acb->rqbuf_firstindex - 1) & ++ (ARCMSR_MAX_QBUFFER - 1); ++ if (buf_empty_len >= readl(&prbuffer->data_len)) { ++ if (arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) ++ acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; ++ } else + acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; ++ spin_unlock_irqrestore(&acb->rqbuffer_lock, flags); ++} ++ ++static void arcmsr_write_ioctldata2iop_in_DWORD(struct AdapterControlBlock *acb) ++{ ++ uint8_t *pQbuffer; ++ struct QBUFFER __iomem *pwbuffer; ++ uint8_t *buf1 = NULL; ++ uint32_t __iomem *iop_data; ++ uint32_t allxfer_len = 0, data_len, *buf2 = NULL, data; ++ ++ if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { ++ buf1 = kmalloc(128, GFP_ATOMIC); ++ buf2 = (uint32_t *)buf1; ++ if (buf1 == NULL) ++ return; ++ ++ acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); ++ pwbuffer = arcmsr_get_iop_wqbuffer(acb); ++ iop_data = (uint32_t __iomem *)pwbuffer->data; ++ while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) ++ && (allxfer_len < 124)) { ++ pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; ++ *buf1 = *pQbuffer; ++ acb->wqbuf_firstindex++; ++ acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; ++ buf1++; ++ allxfer_len++; ++ } ++ data_len = allxfer_len; ++ buf1 = (uint8_t *)buf2; ++ while (data_len >= 4) { ++ data = *buf2++; ++ writel(data, iop_data); ++ iop_data++; ++ data_len -= 4; ++ } ++ if (data_len) { ++ data = *buf2; ++ writel(data, iop_data); ++ } ++ writel(allxfer_len, &pwbuffer->data_len); ++ kfree(buf1); ++ arcmsr_iop_message_wrote(acb); + } + } + +-static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) ++void ++arcmsr_write_ioctldata2iop(struct AdapterControlBlock *acb) + { +- acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; +- if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) { +- uint8_t *pQbuffer; +- struct QBUFFER __iomem *pwbuffer; +- uint8_t __iomem *iop_data; +- int32_t allxfer_len = 0; ++ uint8_t *pQbuffer; ++ struct QBUFFER __iomem *pwbuffer; ++ uint8_t __iomem *iop_data; ++ int32_t allxfer_len = 0; + ++ if (acb->adapter_type & ACB_ADAPTER_TYPE_C) { ++ arcmsr_write_ioctldata2iop_in_DWORD(acb); ++ return; ++ } ++ if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { + acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); + pwbuffer = arcmsr_get_iop_wqbuffer(acb); + iop_data = (uint8_t __iomem *)pwbuffer->data; +- +- while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) && \ +- (allxfer_len < 124)) { ++ while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) ++ && (allxfer_len < 124)) { + pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; +- memcpy(iop_data, pQbuffer, 1); ++ writeb(*pQbuffer, iop_data); + acb->wqbuf_firstindex++; + acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; + iop_data++; + allxfer_len++; + } +- pwbuffer->data_len = allxfer_len; +- ++ writel(allxfer_len, &pwbuffer->data_len); + arcmsr_iop_message_wrote(acb); + } ++} ++ ++static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) ++{ ++ unsigned long flags; + +- if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) { ++ spin_lock_irqsave(&acb->wqbuffer_lock, flags); ++ acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; ++ if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) ++ arcmsr_write_ioctldata2iop(acb); ++ if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) + acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; +- } ++ spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); + } + + static void arcmsr_hbaA_doorbell_isr(struct AdapterControlBlock *acb) +@@ -1768,296 +1877,345 @@ static void arcmsr_iop_parking(struct AdapterControlBlock *acb) + } + } + +-void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) ++ ++void arcmsr_clear_iop2drv_rqueue_buffer(struct AdapterControlBlock *acb) + { +- int32_t wqbuf_firstindex, wqbuf_lastindex; +- uint8_t *pQbuffer; +- struct QBUFFER __iomem *pwbuffer; +- uint8_t __iomem *iop_data; +- int32_t allxfer_len = 0; +- pwbuffer = arcmsr_get_iop_wqbuffer(acb); +- iop_data = (uint8_t __iomem *)pwbuffer->data; +- if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { +- acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); +- wqbuf_firstindex = acb->wqbuf_firstindex; +- wqbuf_lastindex = acb->wqbuf_lastindex; +- while ((wqbuf_firstindex != wqbuf_lastindex) && (allxfer_len < 124)) { +- pQbuffer = &acb->wqbuffer[wqbuf_firstindex]; +- memcpy(iop_data, pQbuffer, 1); +- wqbuf_firstindex++; +- wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; +- iop_data++; +- allxfer_len++; ++ uint32_t i; ++ ++ if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { ++ for (i = 0; i < 15; i++) { ++ if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { ++ acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; ++ acb->rqbuf_firstindex = 0; ++ acb->rqbuf_lastindex = 0; ++ arcmsr_iop_message_read(acb); ++ mdelay(30); ++ } else if (acb->rqbuf_firstindex != ++ acb->rqbuf_lastindex) { ++ acb->rqbuf_firstindex = 0; ++ acb->rqbuf_lastindex = 0; ++ mdelay(30); ++ } else ++ break; + } +- acb->wqbuf_firstindex = wqbuf_firstindex; +- pwbuffer->data_len = allxfer_len; +- arcmsr_iop_message_wrote(acb); + } + } + + static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, +- struct scsi_cmnd *cmd) ++ struct scsi_cmnd *cmd) + { +- struct CMD_MESSAGE_FIELD *pcmdmessagefld; +- int retvalue = 0, transfer_len = 0; + char *buffer; ++ unsigned short use_sg; ++ int retvalue = 0, transfer_len = 0; ++ unsigned long flags; ++ struct CMD_MESSAGE_FIELD *pcmdmessagefld; ++ uint32_t controlcode = (uint32_t)cmd->cmnd[5] << 24 | ++ (uint32_t)cmd->cmnd[6] << 16 | ++ (uint32_t)cmd->cmnd[7] << 8 | ++ (uint32_t)cmd->cmnd[8]; + struct scatterlist *sg; +- uint32_t controlcode = (uint32_t ) cmd->cmnd[5] << 24 | +- (uint32_t ) cmd->cmnd[6] << 16 | +- (uint32_t ) cmd->cmnd[7] << 8 | +- (uint32_t ) cmd->cmnd[8]; +- /* 4 bytes: Areca io control code */ ++ ++ use_sg = scsi_sg_count(cmd); + sg = scsi_sglist(cmd); + buffer = kmap_atomic(sg_page(sg)) + sg->offset; +- if (scsi_sg_count(cmd) > 1) { ++ if (use_sg > 1) { + retvalue = ARCMSR_MESSAGE_FAIL; + goto message_out; + } + transfer_len += sg->length; +- + if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { + retvalue = ARCMSR_MESSAGE_FAIL; ++ pr_info("%s: ARCMSR_MESSAGE_FAIL!\n", __func__); + goto message_out; + } +- pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; +- switch(controlcode) { +- ++ pcmdmessagefld = (struct CMD_MESSAGE_FIELD *)buffer; ++ switch (controlcode) { + case ARCMSR_MESSAGE_READ_RQBUFFER: { + unsigned char *ver_addr; + uint8_t *pQbuffer, *ptmpQbuffer; +- int32_t allxfer_len = 0; +- ++ uint32_t allxfer_len = 0; + ver_addr = kmalloc(1032, GFP_ATOMIC); + if (!ver_addr) { + retvalue = ARCMSR_MESSAGE_FAIL; ++ pr_info("%s: memory not enough!\n", __func__); + goto message_out; + } +- + ptmpQbuffer = ver_addr; +- while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) +- && (allxfer_len < 1031)) { ++ spin_lock_irqsave(&acb->rqbuffer_lock, flags); ++ if (acb->rqbuf_firstindex != acb->rqbuf_lastindex) { + pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; +- memcpy(ptmpQbuffer, pQbuffer, 1); +- acb->rqbuf_firstindex++; +- acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; +- ptmpQbuffer++; +- allxfer_len++; ++ if (acb->rqbuf_firstindex > acb->rqbuf_lastindex) { ++ if ((ARCMSR_MAX_QBUFFER - ++ acb->rqbuf_firstindex) >= 1032) { ++ memcpy(ptmpQbuffer, pQbuffer, 1032); ++ acb->rqbuf_firstindex += 1032; ++ acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; ++ allxfer_len = 1032; ++ } else { ++ if (((ARCMSR_MAX_QBUFFER - ++ acb->rqbuf_firstindex) + ++ acb->rqbuf_lastindex) > 1032) { ++ memcpy(ptmpQbuffer, ++ pQbuffer, ARCMSR_MAX_QBUFFER ++ - acb->rqbuf_firstindex); ++ ptmpQbuffer += ++ ARCMSR_MAX_QBUFFER - ++ acb->rqbuf_firstindex; ++ memcpy(ptmpQbuffer, ++ acb->rqbuffer, 1032 - ++ (ARCMSR_MAX_QBUFFER ++ - acb->rqbuf_firstindex)); ++ acb->rqbuf_firstindex = ++ 1032 - (ARCMSR_MAX_QBUFFER ++ - acb->rqbuf_firstindex); ++ allxfer_len = 1032; ++ } else { ++ memcpy(ptmpQbuffer, ++ pQbuffer, ARCMSR_MAX_QBUFFER ++ - acb->rqbuf_firstindex); ++ ptmpQbuffer += ++ ARCMSR_MAX_QBUFFER - ++ acb->rqbuf_firstindex; ++ memcpy(ptmpQbuffer, ++ acb->rqbuffer, ++ acb->rqbuf_lastindex); ++ allxfer_len = ARCMSR_MAX_QBUFFER ++ - acb->rqbuf_firstindex + ++ acb->rqbuf_lastindex; ++ acb->rqbuf_firstindex = ++ acb->rqbuf_lastindex; ++ } ++ } ++ } else { ++ if ((acb->rqbuf_lastindex - ++ acb->rqbuf_firstindex) > 1032) { ++ memcpy(ptmpQbuffer, pQbuffer, 1032); ++ acb->rqbuf_firstindex += 1032; ++ allxfer_len = 1032; ++ } else { ++ memcpy(ptmpQbuffer, pQbuffer, ++ acb->rqbuf_lastindex - ++ acb->rqbuf_firstindex); ++ allxfer_len = acb->rqbuf_lastindex ++ - acb->rqbuf_firstindex; ++ acb->rqbuf_firstindex = ++ acb->rqbuf_lastindex; ++ } ++ } + } ++ memcpy(pcmdmessagefld->messagedatabuffer, ver_addr, ++ allxfer_len); + if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { +- + struct QBUFFER __iomem *prbuffer; +- uint8_t __iomem *iop_data; +- int32_t iop_len; +- + acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + prbuffer = arcmsr_get_iop_rqbuffer(acb); +- iop_data = prbuffer->data; +- iop_len = readl(&prbuffer->data_len); +- while (iop_len > 0) { +- acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); +- acb->rqbuf_lastindex++; +- acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; +- iop_data++; +- iop_len--; +- } +- arcmsr_iop_message_read(acb); +- } +- memcpy(pcmdmessagefld->messagedatabuffer, ver_addr, allxfer_len); +- pcmdmessagefld->cmdmessage.Length = allxfer_len; +- if(acb->fw_flag == FW_DEADLOCK) { +- pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; +- }else{ +- pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; ++ if (arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) ++ acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; + } ++ spin_unlock_irqrestore(&acb->rqbuffer_lock, flags); + kfree(ver_addr); +- } ++ pcmdmessagefld->cmdmessage.Length = allxfer_len; ++ if (acb->fw_flag == FW_DEADLOCK) ++ pcmdmessagefld->cmdmessage.ReturnCode = ++ ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; ++ else ++ pcmdmessagefld->cmdmessage.ReturnCode = ++ ARCMSR_MESSAGE_RETURNCODE_OK; + break; +- ++ } + case ARCMSR_MESSAGE_WRITE_WQBUFFER: { + unsigned char *ver_addr; + int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; + uint8_t *pQbuffer, *ptmpuserbuffer; +- + ver_addr = kmalloc(1032, GFP_ATOMIC); + if (!ver_addr) { + retvalue = ARCMSR_MESSAGE_FAIL; + goto message_out; + } +- if(acb->fw_flag == FW_DEADLOCK) { +- pcmdmessagefld->cmdmessage.ReturnCode = +- ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; +- }else{ +- pcmdmessagefld->cmdmessage.ReturnCode = +- ARCMSR_MESSAGE_RETURNCODE_OK; +- } + ptmpuserbuffer = ver_addr; + user_len = pcmdmessagefld->cmdmessage.Length; +- memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); ++ memcpy(ptmpuserbuffer, ++ pcmdmessagefld->messagedatabuffer, user_len); ++ spin_lock_irqsave(&acb->wqbuffer_lock, flags); + wqbuf_lastindex = acb->wqbuf_lastindex; + wqbuf_firstindex = acb->wqbuf_firstindex; + if (wqbuf_lastindex != wqbuf_firstindex) { + struct SENSE_DATA *sensebuffer = + (struct SENSE_DATA *)cmd->sense_buffer; +- arcmsr_post_ioctldata2iop(acb); ++ arcmsr_write_ioctldata2iop(acb); + /* has error report sensedata */ +- sensebuffer->ErrorCode = 0x70; ++ sensebuffer->ErrorCode = SCSI_SENSE_CURRENT_ERRORS; + sensebuffer->SenseKey = ILLEGAL_REQUEST; + sensebuffer->AdditionalSenseLength = 0x0A; + sensebuffer->AdditionalSenseCode = 0x20; + sensebuffer->Valid = 1; + retvalue = ARCMSR_MESSAGE_FAIL; + } else { +- my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) +- &(ARCMSR_MAX_QBUFFER - 1); ++ my_empty_len = (wqbuf_firstindex - wqbuf_lastindex - 1) ++ & (ARCMSR_MAX_QBUFFER - 1); + if (my_empty_len >= user_len) { + while (user_len > 0) { +- pQbuffer = +- &acb->wqbuffer[acb->wqbuf_lastindex]; +- memcpy(pQbuffer, ptmpuserbuffer, 1); +- acb->wqbuf_lastindex++; +- acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; +- ptmpuserbuffer++; +- user_len--; ++ pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; ++ if ((acb->wqbuf_lastindex + user_len) ++ > ARCMSR_MAX_QBUFFER) { ++ memcpy(pQbuffer, ptmpuserbuffer, ++ ARCMSR_MAX_QBUFFER - ++ acb->wqbuf_lastindex); ++ ptmpuserbuffer += ++ (ARCMSR_MAX_QBUFFER ++ - acb->wqbuf_lastindex); ++ user_len -= (ARCMSR_MAX_QBUFFER ++ - acb->wqbuf_lastindex); ++ acb->wqbuf_lastindex = 0; ++ } else { ++ memcpy(pQbuffer, ptmpuserbuffer, ++ user_len); ++ acb->wqbuf_lastindex += user_len; ++ acb->wqbuf_lastindex %= ++ ARCMSR_MAX_QBUFFER; ++ user_len = 0; ++ } + } +- if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { ++ if (acb->acb_flags & ++ ACB_F_MESSAGE_WQBUFFER_CLEARED) { + acb->acb_flags &= + ~ACB_F_MESSAGE_WQBUFFER_CLEARED; +- arcmsr_post_ioctldata2iop(acb); ++ arcmsr_write_ioctldata2iop(acb); + } + } else { +- /* has error report sensedata */ + struct SENSE_DATA *sensebuffer = + (struct SENSE_DATA *)cmd->sense_buffer; +- sensebuffer->ErrorCode = 0x70; ++ /* has error report sensedata */ ++ sensebuffer->ErrorCode = ++ SCSI_SENSE_CURRENT_ERRORS; + sensebuffer->SenseKey = ILLEGAL_REQUEST; + sensebuffer->AdditionalSenseLength = 0x0A; + sensebuffer->AdditionalSenseCode = 0x20; + sensebuffer->Valid = 1; + retvalue = ARCMSR_MESSAGE_FAIL; + } +- } +- kfree(ver_addr); + } ++ spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); ++ kfree(ver_addr); ++ if (acb->fw_flag == FW_DEADLOCK) ++ pcmdmessagefld->cmdmessage.ReturnCode = ++ ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; ++ else ++ pcmdmessagefld->cmdmessage.ReturnCode = ++ ARCMSR_MESSAGE_RETURNCODE_OK; + break; +- ++ } + case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { + uint8_t *pQbuffer = acb->rqbuffer; +- if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { +- acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; +- arcmsr_iop_message_read(acb); +- } ++ ++ arcmsr_clear_iop2drv_rqueue_buffer(acb); ++ spin_lock_irqsave(&acb->rqbuffer_lock, flags); + acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; + acb->rqbuf_firstindex = 0; + acb->rqbuf_lastindex = 0; + memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); +- if(acb->fw_flag == FW_DEADLOCK) { ++ spin_unlock_irqrestore(&acb->rqbuffer_lock, flags); ++ if (acb->fw_flag == FW_DEADLOCK) + pcmdmessagefld->cmdmessage.ReturnCode = +- ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; +- }else{ ++ ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; ++ else + pcmdmessagefld->cmdmessage.ReturnCode = +- ARCMSR_MESSAGE_RETURNCODE_OK; +- } +- } ++ ARCMSR_MESSAGE_RETURNCODE_OK; + break; +- ++ } + case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { + uint8_t *pQbuffer = acb->wqbuffer; +- if(acb->fw_flag == FW_DEADLOCK) { +- pcmdmessagefld->cmdmessage.ReturnCode = +- ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; +- }else{ +- pcmdmessagefld->cmdmessage.ReturnCode = +- ARCMSR_MESSAGE_RETURNCODE_OK; +- } +- +- if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { +- acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; +- arcmsr_iop_message_read(acb); +- } +- acb->acb_flags |= +- (ACB_F_MESSAGE_WQBUFFER_CLEARED | +- ACB_F_MESSAGE_WQBUFFER_READED); ++ spin_lock_irqsave(&acb->wqbuffer_lock, flags); ++ acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | ++ ACB_F_MESSAGE_WQBUFFER_READED); + acb->wqbuf_firstindex = 0; + acb->wqbuf_lastindex = 0; + memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); +- } ++ spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); ++ if (acb->fw_flag == FW_DEADLOCK) ++ pcmdmessagefld->cmdmessage.ReturnCode = ++ ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; ++ else ++ pcmdmessagefld->cmdmessage.ReturnCode = ++ ARCMSR_MESSAGE_RETURNCODE_OK; + break; +- ++ } + case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { + uint8_t *pQbuffer; +- +- if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { +- acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; +- arcmsr_iop_message_read(acb); +- } +- acb->acb_flags |= +- (ACB_F_MESSAGE_WQBUFFER_CLEARED +- | ACB_F_MESSAGE_RQBUFFER_CLEARED +- | ACB_F_MESSAGE_WQBUFFER_READED); ++ arcmsr_clear_iop2drv_rqueue_buffer(acb); ++ spin_lock_irqsave(&acb->rqbuffer_lock, flags); ++ acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; + acb->rqbuf_firstindex = 0; + acb->rqbuf_lastindex = 0; +- acb->wqbuf_firstindex = 0; +- acb->wqbuf_lastindex = 0; + pQbuffer = acb->rqbuffer; + memset(pQbuffer, 0, sizeof(struct QBUFFER)); ++ spin_unlock_irqrestore(&acb->rqbuffer_lock, flags); ++ spin_lock_irqsave(&acb->wqbuffer_lock, flags); ++ acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | ++ ACB_F_MESSAGE_WQBUFFER_READED); ++ acb->wqbuf_firstindex = 0; ++ acb->wqbuf_lastindex = 0; + pQbuffer = acb->wqbuffer; + memset(pQbuffer, 0, sizeof(struct QBUFFER)); +- if(acb->fw_flag == FW_DEADLOCK) { ++ spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); ++ if (acb->fw_flag == FW_DEADLOCK) + pcmdmessagefld->cmdmessage.ReturnCode = +- ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; +- }else{ ++ ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; ++ else + pcmdmessagefld->cmdmessage.ReturnCode = +- ARCMSR_MESSAGE_RETURNCODE_OK; +- } +- } ++ ARCMSR_MESSAGE_RETURNCODE_OK; + break; +- ++ } + case ARCMSR_MESSAGE_RETURN_CODE_3F: { +- if(acb->fw_flag == FW_DEADLOCK) { ++ if (acb->fw_flag == FW_DEADLOCK) + pcmdmessagefld->cmdmessage.ReturnCode = +- ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; +- }else{ ++ ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; ++ else + pcmdmessagefld->cmdmessage.ReturnCode = +- ARCMSR_MESSAGE_RETURNCODE_3F; +- } ++ ARCMSR_MESSAGE_RETURNCODE_3F; + break; +- } ++ } + case ARCMSR_MESSAGE_SAY_HELLO: { + int8_t *hello_string = "Hello! I am ARCMSR"; +- if(acb->fw_flag == FW_DEADLOCK) { ++ if (acb->fw_flag == FW_DEADLOCK) + pcmdmessagefld->cmdmessage.ReturnCode = +- ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; +- }else{ ++ ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; ++ else + pcmdmessagefld->cmdmessage.ReturnCode = +- ARCMSR_MESSAGE_RETURNCODE_OK; +- } +- memcpy(pcmdmessagefld->messagedatabuffer, hello_string +- , (int16_t)strlen(hello_string)); +- } ++ ARCMSR_MESSAGE_RETURNCODE_OK; ++ memcpy(pcmdmessagefld->messagedatabuffer, ++ hello_string, (int16_t)strlen(hello_string)); + break; +- +- case ARCMSR_MESSAGE_SAY_GOODBYE: +- if(acb->fw_flag == FW_DEADLOCK) { ++ } ++ case ARCMSR_MESSAGE_SAY_GOODBYE: { ++ if (acb->fw_flag == FW_DEADLOCK) + pcmdmessagefld->cmdmessage.ReturnCode = +- ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; +- } ++ ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; ++ else ++ pcmdmessagefld->cmdmessage.ReturnCode = ++ ARCMSR_MESSAGE_RETURNCODE_OK; + arcmsr_iop_parking(acb); + break; +- +- case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: +- if(acb->fw_flag == FW_DEADLOCK) { ++ } ++ case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { ++ if (acb->fw_flag == FW_DEADLOCK) + pcmdmessagefld->cmdmessage.ReturnCode = +- ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; +- } ++ ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; ++ else ++ pcmdmessagefld->cmdmessage.ReturnCode = ++ ARCMSR_MESSAGE_RETURNCODE_OK; + arcmsr_flush_adapter_cache(acb); + break; +- ++ } + default: + retvalue = ARCMSR_MESSAGE_FAIL; ++ pr_info("%s: unknown controlcode!\n", __func__); ++ } ++message_out: ++ if (use_sg) { ++ struct scatterlist *sg = scsi_sglist(cmd); ++ kunmap_atomic(buffer - sg->offset); + } +- message_out: +- sg = scsi_sglist(cmd); +- kunmap_atomic(buffer - sg->offset); + return retvalue; + } + diff --git a/debian/patches/features/all/arcmsr/0014-arcmsr-fix-sparse-warnings-and-errors.patch b/debian/patches/features/all/arcmsr/0014-arcmsr-fix-sparse-warnings-and-errors.patch new file mode 100644 index 000000000..100c1fd61 --- /dev/null +++ b/debian/patches/features/all/arcmsr/0014-arcmsr-fix-sparse-warnings-and-errors.patch @@ -0,0 +1,316 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 15:20:31 +0800 +Subject: [14/19] arcmsr: fix sparse warnings and errors +Origin: https://git.kernel.org/linus/c10b1d544aaaf98ab1792845c106471ee1ee0c05 +Bug-Debian: https://bugs.debian.org/698821 + +Fix sparse utility checking errors and warnings. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr_hba.c | 78 ++++++++++++++++++++-------------------- + 1 file changed, 40 insertions(+), 38 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index 1576805..34a43ed 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -78,7 +78,7 @@ MODULE_VERSION(ARCMSR_DRIVER_VERSION); + #define ARCMSR_SLEEPTIME 10 + #define ARCMSR_RETRYCOUNT 12 + +-wait_queue_head_t wait_q; ++static wait_queue_head_t wait_q; + static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, + struct scsi_cmnd *cmd); + static int arcmsr_iop_confirm(struct AdapterControlBlock *acb); +@@ -353,7 +353,7 @@ static uint8_t arcmsr_hbaB_wait_msgint_ready(struct AdapterControlBlock *acb) + + static uint8_t arcmsr_hbaC_wait_msgint_ready(struct AdapterControlBlock *pACB) + { +- struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)pACB->pmuC; ++ struct MessageUnit_C __iomem *phbcmu = pACB->pmuC; + int i; + + for (i = 0; i < 2000; i++) { +@@ -403,7 +403,7 @@ static void arcmsr_hbaB_flush_cache(struct AdapterControlBlock *acb) + + static void arcmsr_hbaC_flush_cache(struct AdapterControlBlock *pACB) + { +- struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC; ++ struct MessageUnit_C __iomem *reg = pACB->pmuC; + int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ + writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell); +@@ -827,7 +827,7 @@ static uint8_t arcmsr_hbaB_abort_allcmd(struct AdapterControlBlock *acb) + } + static uint8_t arcmsr_hbaC_abort_allcmd(struct AdapterControlBlock *pACB) + { +- struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC; ++ struct MessageUnit_C __iomem *reg = pACB->pmuC; + writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell); + if (!arcmsr_hbaC_wait_msgint_ready(pACB)) { +@@ -915,7 +915,7 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) + } + break; + case ACB_ADAPTER_TYPE_C:{ +- struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC; ++ struct MessageUnit_C __iomem *reg = acb->pmuC; + /* disable all outbound interrupt */ + orig_mask = readl(®->host_int_mask); /* disable outbound message0 int */ + writel(orig_mask|ARCMSR_HBCMU_ALL_INTMASKENABLE, ®->host_int_mask); +@@ -1039,8 +1039,9 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) + /*clear all outbound posted Q*/ + writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, reg->iop2drv_doorbell); /* clear doorbell interrupt */ + for (i = 0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { +- if ((flag_ccb = readl(®->done_qbuffer[i])) != 0) { +- writel(0, ®->done_qbuffer[i]); ++ flag_ccb = reg->done_qbuffer[i]; ++ if (flag_ccb != 0) { ++ reg->done_qbuffer[i] = 0; + pARCMSR_CDB = (struct ARCMSR_CDB *)(acb->vir2phy_offset+(flag_ccb << 5));/*frame must be 32 bytes aligned*/ + pCCB = container_of(pARCMSR_CDB, struct CommandControlBlock, arcmsr_cdb); + error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE0) ? true : false; +@@ -1053,7 +1054,7 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) + } + break; + case ACB_ADAPTER_TYPE_C: { +- struct MessageUnit_C *reg = acb->pmuC; ++ struct MessageUnit_C __iomem *reg = acb->pmuC; + struct ARCMSR_CDB *pARCMSR_CDB; + uint32_t flag_ccb, ccb_cdb_phy; + bool error; +@@ -1171,7 +1172,7 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, + } + break; + case ACB_ADAPTER_TYPE_C: { +- struct MessageUnit_C *reg = acb->pmuC; ++ struct MessageUnit_C __iomem *reg = acb->pmuC; + mask = ~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK|ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK); + writel(intmask_org & mask, ®->host_int_mask); + acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f; +@@ -1257,12 +1258,12 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr + uint32_t ending_index, index = reg->postq_index; + + ending_index = ((index + 1) % ARCMSR_MAX_HBB_POSTQUEUE); +- writel(0, ®->post_qbuffer[ending_index]); ++ reg->post_qbuffer[ending_index] = 0; + if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { +- writel(cdb_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, +- ®->post_qbuffer[index]); ++ reg->post_qbuffer[index] = ++ cdb_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE; + } else { +- writel(cdb_phyaddr, ®->post_qbuffer[index]); ++ reg->post_qbuffer[index] = cdb_phyaddr; + } + index++; + index %= ARCMSR_MAX_HBB_POSTQUEUE;/*if last index number set it to 0 */ +@@ -1271,7 +1272,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr + } + break; + case ACB_ADAPTER_TYPE_C: { +- struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)acb->pmuC; ++ struct MessageUnit_C __iomem *phbcmu = acb->pmuC; + uint32_t ccb_post_stamp, arc_cdb_size; + + arc_cdb_size = (ccb->arc_cdb_size > 0x300) ? 0x300 : ccb->arc_cdb_size; +@@ -1313,7 +1314,7 @@ static void arcmsr_hbaB_stop_bgrb(struct AdapterControlBlock *acb) + + static void arcmsr_hbaC_stop_bgrb(struct AdapterControlBlock *pACB) + { +- struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC; ++ struct MessageUnit_C __iomem *reg = pACB->pmuC; + pACB->acb_flags &= ~ACB_F_MSG_START_BGRB; + writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell); +@@ -1347,7 +1348,7 @@ static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) + dma_free_coherent(&acb->pdev->dev, acb->uncache_size, acb->dma_coherent, acb->dma_coherent_handle); + } + +-void arcmsr_iop_message_read(struct AdapterControlBlock *acb) ++static void arcmsr_iop_message_read(struct AdapterControlBlock *acb) + { + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { +@@ -1419,7 +1420,7 @@ struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb) + } + break; + case ACB_ADAPTER_TYPE_C: { +- struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)acb->pmuC; ++ struct MessageUnit_C __iomem *phbcmu = acb->pmuC; + qbuffer = (struct QBUFFER __iomem *)&phbcmu->message_rbuffer; + } + } +@@ -1443,7 +1444,7 @@ static struct QBUFFER __iomem *arcmsr_get_iop_wqbuffer(struct AdapterControlBloc + } + break; + case ACB_ADAPTER_TYPE_C: { +- struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC; ++ struct MessageUnit_C __iomem *reg = acb->pmuC; + pqbuffer = (struct QBUFFER __iomem *)®->message_wbuffer; + } + +@@ -1640,7 +1641,7 @@ static void arcmsr_hbaA_doorbell_isr(struct AdapterControlBlock *acb) + static void arcmsr_hbaC_doorbell_isr(struct AdapterControlBlock *pACB) + { + uint32_t outbound_doorbell; +- struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC; ++ struct MessageUnit_C __iomem *reg = pACB->pmuC; + /* + ******************************************************************* + ** Maybe here we need to check wrqbuffer_lock is lock or not +@@ -1686,8 +1687,8 @@ static void arcmsr_hbaB_postqueue_isr(struct AdapterControlBlock *acb) + struct CommandControlBlock *pCCB; + bool error; + index = reg->doneq_index; +- while ((flag_ccb = readl(®->done_qbuffer[index])) != 0) { +- writel(0, ®->done_qbuffer[index]); ++ while ((flag_ccb = reg->done_qbuffer[index]) != 0) { ++ reg->done_qbuffer[index] = 0; + pARCMSR_CDB = (struct ARCMSR_CDB *)(acb->vir2phy_offset+(flag_ccb << 5));/*frame must be 32 bytes aligned*/ + pCCB = container_of(pARCMSR_CDB, struct CommandControlBlock, arcmsr_cdb); + error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE0) ? true : false; +@@ -1700,13 +1701,13 @@ static void arcmsr_hbaB_postqueue_isr(struct AdapterControlBlock *acb) + + static void arcmsr_hbaC_postqueue_isr(struct AdapterControlBlock *acb) + { +- struct MessageUnit_C *phbcmu; ++ struct MessageUnit_C __iomem *phbcmu; + struct ARCMSR_CDB *arcmsr_cdb; + struct CommandControlBlock *ccb; + uint32_t flag_ccb, ccb_cdb_phy, throttling = 0; + int error; + +- phbcmu = (struct MessageUnit_C *)acb->pmuC; ++ phbcmu = acb->pmuC; + /* areca cdb command done */ + /* Use correct offset and size for syncing */ + +@@ -1739,7 +1740,7 @@ static void arcmsr_hbaC_postqueue_isr(struct AdapterControlBlock *acb) + */ + static void arcmsr_hbaA_message_isr(struct AdapterControlBlock *acb) + { +- struct MessageUnit_A *reg = acb->pmuA; ++ struct MessageUnit_A __iomem *reg = acb->pmuA; + /*clear interrupt and message state*/ + writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT, ®->outbound_intstatus); + schedule_work(&acb->arcmsr_do_message_isr_bh); +@@ -1763,7 +1764,7 @@ static void arcmsr_hbaB_message_isr(struct AdapterControlBlock *acb) + */ + static void arcmsr_hbaC_message_isr(struct AdapterControlBlock *acb) + { +- struct MessageUnit_C *reg = acb->pmuC; ++ struct MessageUnit_C __iomem *reg = acb->pmuC; + /*clear interrupt and message state*/ + writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, ®->outbound_doorbell_clear); + schedule_work(&acb->arcmsr_do_message_isr_bh); +@@ -1824,7 +1825,7 @@ static int arcmsr_hbaB_handle_isr(struct AdapterControlBlock *acb) + static int arcmsr_hbaC_handle_isr(struct AdapterControlBlock *pACB) + { + uint32_t host_interrupt_status; +- struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)pACB->pmuC; ++ struct MessageUnit_C __iomem *phbcmu = pACB->pmuC; + /* + ********************************************* + ** check outbound intstatus +@@ -2230,7 +2231,7 @@ static struct CommandControlBlock *arcmsr_get_freeccb(struct AdapterControlBlock + list_del_init(&ccb->list); + }else{ + spin_unlock_irqrestore(&acb->ccblist_lock, flags); +- return 0; ++ return NULL; + } + spin_unlock_irqrestore(&acb->ccblist_lock, flags); + return ccb; +@@ -2468,11 +2469,11 @@ static bool arcmsr_hbaB_get_config(struct AdapterControlBlock *acb) + static bool arcmsr_hbaC_get_config(struct AdapterControlBlock *pACB) + { + uint32_t intmask_org, Index, firmware_state = 0; +- struct MessageUnit_C *reg = pACB->pmuC; ++ struct MessageUnit_C __iomem *reg = pACB->pmuC; + char *acb_firm_model = pACB->firm_model; + char *acb_firm_version = pACB->firm_version; +- char *iop_firm_model = (char *)(®->msgcode_rwbuffer[15]); /*firm_model,15,60-67*/ +- char *iop_firm_version = (char *)(®->msgcode_rwbuffer[17]); /*firm_version,17,68-83*/ ++ char __iomem *iop_firm_model = (char __iomem *)(®->msgcode_rwbuffer[15]); /*firm_model,15,60-67*/ ++ char __iomem *iop_firm_version = (char __iomem *)(®->msgcode_rwbuffer[17]); /*firm_version,17,68-83*/ + int count; + /* disable all outbound interrupt */ + intmask_org = readl(®->host_int_mask); /* disable outbound message0 int */ +@@ -2620,7 +2621,8 @@ static int arcmsr_hbaB_polling_ccbdone(struct AdapterControlBlock *acb, + writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, reg->iop2drv_doorbell); + while(1){ + index = reg->doneq_index; +- if ((flag_ccb = readl(®->done_qbuffer[index])) == 0) { ++ flag_ccb = reg->done_qbuffer[index]; ++ if (flag_ccb == 0) { + if (poll_ccb_done){ + rtn = SUCCESS; + break; +@@ -2633,7 +2635,7 @@ static int arcmsr_hbaB_polling_ccbdone(struct AdapterControlBlock *acb, + goto polling_hbb_ccb_retry; + } + } +- writel(0, ®->done_qbuffer[index]); ++ reg->done_qbuffer[index] = 0; + index++; + /*if last index number set it to 0 */ + index %= ARCMSR_MAX_HBB_POSTQUEUE; +@@ -2671,7 +2673,7 @@ static int arcmsr_hbaB_polling_ccbdone(struct AdapterControlBlock *acb, + static int arcmsr_hbaC_polling_ccbdone(struct AdapterControlBlock *acb, + struct CommandControlBlock *poll_ccb) + { +- struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC; ++ struct MessageUnit_C __iomem *reg = acb->pmuC; + uint32_t flag_ccb, ccb_cdb_phy; + struct ARCMSR_CDB *arcmsr_cdb; + bool error; +@@ -2834,7 +2836,7 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + break; + case ACB_ADAPTER_TYPE_C: { + if (cdb_phyaddr_hi32 != 0) { +- struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC; ++ struct MessageUnit_C __iomem *reg = acb->pmuC; + + printk(KERN_NOTICE "arcmsr%d: cdb_phyaddr_hi32=0x%x\n", + acb->adapter_index, cdb_phyaddr_hi32); +@@ -2875,7 +2877,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) + } + break; + case ACB_ADAPTER_TYPE_C: { +- struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC; ++ struct MessageUnit_C __iomem *reg = acb->pmuC; + do { + firmware_state = readl(®->outbound_msgaddr1); + } while ((firmware_state & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0); +@@ -2907,7 +2909,7 @@ static void arcmsr_hbaA_request_device_map(struct AdapterControlBlock *acb) + + static void arcmsr_hbaB_request_device_map(struct AdapterControlBlock *acb) + { +- struct MessageUnit_B __iomem *reg = acb->pmuB; ++ struct MessageUnit_B *reg = acb->pmuB; + if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0 ) || ((acb->acb_flags & ACB_F_ABORT) != 0 )){ + mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); + return; +@@ -2992,7 +2994,7 @@ static void arcmsr_hbaB_start_bgrb(struct AdapterControlBlock *acb) + + static void arcmsr_hbaC_start_bgrb(struct AdapterControlBlock *pACB) + { +- struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)pACB->pmuC; ++ struct MessageUnit_C __iomem *phbcmu = pACB->pmuC; + pACB->acb_flags |= ACB_F_MSG_START_BGRB; + writel(ARCMSR_INBOUND_MESG0_START_BGRB, &phbcmu->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, &phbcmu->inbound_doorbell); +@@ -3039,7 +3041,7 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb) + } + break; + case ACB_ADAPTER_TYPE_C: { +- struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC; ++ struct MessageUnit_C __iomem *reg = acb->pmuC; + uint32_t outbound_doorbell, i; + /* empty doorbell Qbuffer if door bell ringed */ + outbound_doorbell = readl(®->outbound_doorbell); diff --git a/debian/patches/features/all/arcmsr/0015-arcmsr-modify-some-character-strings.patch b/debian/patches/features/all/arcmsr/0015-arcmsr-modify-some-character-strings.patch new file mode 100644 index 000000000..b974084ea --- /dev/null +++ b/debian/patches/features/all/arcmsr/0015-arcmsr-modify-some-character-strings.patch @@ -0,0 +1,75 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 15:22:45 +0800 +Subject: [15/19] arcmsr: modify some character strings +Origin: https://git.kernel.org/linus/aaa64f69480bcde4e203584dfc77d7e4ffb737d6 +Bug-Debian: https://bugs.debian.org/698821 + +Revise comment and some character strings. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr_hba.c | 24 +++++++++++------------- + 1 file changed, 11 insertions(+), 13 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index 34a43ed..26bcdc0 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -2,11 +2,10 @@ + ******************************************************************************* + ** O.S : Linux + ** FILE NAME : arcmsr_hba.c +-** BY : Nick Cheng +-** Description: SCSI RAID Device Driver for +-** ARECA RAID Host adapter ++** BY : Nick Cheng, C.L. Huang ++** Description: SCSI RAID Device Driver for Areca RAID Controller + ******************************************************************************* +-** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved ++** Copyright (C) 2002 - 2014, Areca Technology Corporation All rights reserved + ** + ** Web site: www.areca.com.tw + ** E-mail: support@areca.com.tw +@@ -70,8 +69,8 @@ + #include + #include + #include "arcmsr.h" +-MODULE_AUTHOR("Nick Cheng "); +-MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/16xx/1880) SATA/SAS RAID Host Bus Adapter"); ++MODULE_AUTHOR("Nick Cheng, C.L. Huang "); ++MODULE_DESCRIPTION("Areca ARC11xx/12xx/16xx/188x SAS/SATA RAID Controller Driver"); + MODULE_LICENSE("Dual BSD/GPL"); + MODULE_VERSION(ARCMSR_DRIVER_VERSION); + +@@ -126,8 +125,7 @@ static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, + + static struct scsi_host_template arcmsr_scsi_host_template = { + .module = THIS_MODULE, +- .name = "ARCMSR ARECA SATA/SAS RAID Controller" +- ARCMSR_DRIVER_VERSION, ++ .name = "Areca SAS/SATA RAID driver", + .info = arcmsr_info, + .queuecommand = arcmsr_queue_command, + .eh_abort_handler = arcmsr_abort, +@@ -3387,14 +3385,14 @@ static const char *arcmsr_info(struct Scsi_Host *host) + case PCI_DEVICE_ID_ARECA_1680: + case PCI_DEVICE_ID_ARECA_1681: + case PCI_DEVICE_ID_ARECA_1880: +- type = "SAS"; ++ type = "SAS/SATA"; + break; + default: +- type = "X-TYPE"; ++ type = "unknown"; ++ raid6 = 0; + break; + } +- sprintf(buf, "Areca %s Host Adapter RAID Controller%s\n %s", +- type, raid6 ? "( RAID6 capable)" : "", +- ARCMSR_DRIVER_VERSION); ++ sprintf(buf, "Areca %s RAID Controller %s\narcmsr version %s\n", ++ type, raid6 ? "(RAID6 capable)" : "", ARCMSR_DRIVER_VERSION); + return buf; + } diff --git a/debian/patches/features/all/arcmsr/0016-arcmsr-add-support-new-adapter-arc12x4-series.patch b/debian/patches/features/all/arcmsr/0016-arcmsr-add-support-new-adapter-arc12x4-series.patch new file mode 100644 index 000000000..3d83fe8b2 --- /dev/null +++ b/debian/patches/features/all/arcmsr/0016-arcmsr-add-support-new-adapter-arc12x4-series.patch @@ -0,0 +1,1257 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 15:25:22 +0800 +Subject: [16/19] arcmsr: add support new adapter ARC12x4 series +Origin: https://git.kernel.org/linus/5b37479adee7164b17b6e2030b9a30d04583eb61 +Bug-Debian: https://bugs.debian.org/698821 + +Add code to support the new Areca Raid ARC12x4 series adapters. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr.h | 108 ++++++ + drivers/scsi/arcmsr/arcmsr_hba.c | 761 ++++++++++++++++++++++++++++++++++++++- + 2 files changed, 860 insertions(+), 9 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h +index 799393e..d1c78ef 100644 +--- a/drivers/scsi/arcmsr/arcmsr.h ++++ b/drivers/scsi/arcmsr/arcmsr.h +@@ -63,12 +63,17 @@ struct device_attribute; + #define ARCMSR_MAX_QBUFFER 4096 + #define ARCMSR_DEFAULT_SG_ENTRIES 38 + #define ARCMSR_MAX_HBB_POSTQUEUE 264 ++#define ARCMSR_MAX_ARC1214_POSTQUEUE 256 ++#define ARCMSR_MAX_ARC1214_DONEQUEUE 257 + #define ARCMSR_MAX_XFER_LEN 0x26000 /* 152K */ + #define ARCMSR_CDB_SG_PAGE_LENGTH 256 + #define ARCMST_NUM_MSIX_VECTORS 4 + #ifndef PCI_DEVICE_ID_ARECA_1880 + #define PCI_DEVICE_ID_ARECA_1880 0x1880 + #endif ++#ifndef PCI_DEVICE_ID_ARECA_1214 ++ #define PCI_DEVICE_ID_ARECA_1214 0x1214 ++#endif + /* + ********************************************************************************** + ** +@@ -339,6 +344,56 @@ struct FIRMWARE_INFO + #define ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK 0x80000000 + /* + ******************************************************************************* ++** SPEC. for Areca Type D adapter ++******************************************************************************* ++*/ ++#define ARCMSR_ARC1214_CHIP_ID 0x00004 ++#define ARCMSR_ARC1214_CPU_MEMORY_CONFIGURATION 0x00008 ++#define ARCMSR_ARC1214_I2_HOST_INTERRUPT_MASK 0x00034 ++#define ARCMSR_ARC1214_SAMPLE_RESET 0x00100 ++#define ARCMSR_ARC1214_RESET_REQUEST 0x00108 ++#define ARCMSR_ARC1214_MAIN_INTERRUPT_STATUS 0x00200 ++#define ARCMSR_ARC1214_PCIE_F0_INTERRUPT_ENABLE 0x0020C ++#define ARCMSR_ARC1214_INBOUND_MESSAGE0 0x00400 ++#define ARCMSR_ARC1214_INBOUND_MESSAGE1 0x00404 ++#define ARCMSR_ARC1214_OUTBOUND_MESSAGE0 0x00420 ++#define ARCMSR_ARC1214_OUTBOUND_MESSAGE1 0x00424 ++#define ARCMSR_ARC1214_INBOUND_DOORBELL 0x00460 ++#define ARCMSR_ARC1214_OUTBOUND_DOORBELL 0x00480 ++#define ARCMSR_ARC1214_OUTBOUND_DOORBELL_ENABLE 0x00484 ++#define ARCMSR_ARC1214_INBOUND_LIST_BASE_LOW 0x01000 ++#define ARCMSR_ARC1214_INBOUND_LIST_BASE_HIGH 0x01004 ++#define ARCMSR_ARC1214_INBOUND_LIST_WRITE_POINTER 0x01018 ++#define ARCMSR_ARC1214_OUTBOUND_LIST_BASE_LOW 0x01060 ++#define ARCMSR_ARC1214_OUTBOUND_LIST_BASE_HIGH 0x01064 ++#define ARCMSR_ARC1214_OUTBOUND_LIST_COPY_POINTER 0x0106C ++#define ARCMSR_ARC1214_OUTBOUND_LIST_READ_POINTER 0x01070 ++#define ARCMSR_ARC1214_OUTBOUND_INTERRUPT_CAUSE 0x01088 ++#define ARCMSR_ARC1214_OUTBOUND_INTERRUPT_ENABLE 0x0108C ++#define ARCMSR_ARC1214_MESSAGE_WBUFFER 0x02000 ++#define ARCMSR_ARC1214_MESSAGE_RBUFFER 0x02100 ++#define ARCMSR_ARC1214_MESSAGE_RWBUFFER 0x02200 ++/* Host Interrupt Mask */ ++#define ARCMSR_ARC1214_ALL_INT_ENABLE 0x00001010 ++#define ARCMSR_ARC1214_ALL_INT_DISABLE 0x00000000 ++/* Host Interrupt Status */ ++#define ARCMSR_ARC1214_OUTBOUND_DOORBELL_ISR 0x00001000 ++#define ARCMSR_ARC1214_OUTBOUND_POSTQUEUE_ISR 0x00000010 ++/* DoorBell*/ ++#define ARCMSR_ARC1214_DRV2IOP_DATA_IN_READY 0x00000001 ++#define ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ 0x00000002 ++/*inbound message 0 ready*/ ++#define ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK 0x00000001 ++/*outbound DATA WRITE isr door bell clear*/ ++#define ARCMSR_ARC1214_IOP2DRV_DATA_READ_OK 0x00000002 ++/*outbound message 0 ready*/ ++#define ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE 0x02000000 ++/*outbound message cmd isr door bell clear*/ ++/*ARCMSR_HBAMU_MESSAGE_FIRMWARE_OK*/ ++#define ARCMSR_ARC1214_MESSAGE_FIRMWARE_OK 0x80000000 ++#define ARCMSR_ARC1214_OUTBOUND_LIST_INTERRUPT_CLEAR 0x00000001 ++/* ++******************************************************************************* + ** ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504) + ******************************************************************************* + */ +@@ -496,6 +551,56 @@ struct MessageUnit_C{ + uint32_t msgcode_rwbuffer[256]; /*2200 23FF*/ + }; + /* ++********************************************************************* ++** Messaging Unit (MU) of Type D processor ++********************************************************************* ++*/ ++struct InBound_SRB { ++ uint32_t addressLow; /* pointer to SRB block */ ++ uint32_t addressHigh; ++ uint32_t length; /* in DWORDs */ ++ uint32_t reserved0; ++}; ++ ++struct OutBound_SRB { ++ uint32_t addressLow; /* pointer to SRB block */ ++ uint32_t addressHigh; ++}; ++ ++struct MessageUnit_D { ++ struct InBound_SRB post_qbuffer[ARCMSR_MAX_ARC1214_POSTQUEUE]; ++ volatile struct OutBound_SRB ++ done_qbuffer[ARCMSR_MAX_ARC1214_DONEQUEUE]; ++ u16 postq_index; ++ volatile u16 doneq_index; ++ u32 __iomem *chip_id; /* 0x00004 */ ++ u32 __iomem *cpu_mem_config; /* 0x00008 */ ++ u32 __iomem *i2o_host_interrupt_mask; /* 0x00034 */ ++ u32 __iomem *sample_at_reset; /* 0x00100 */ ++ u32 __iomem *reset_request; /* 0x00108 */ ++ u32 __iomem *host_int_status; /* 0x00200 */ ++ u32 __iomem *pcief0_int_enable; /* 0x0020C */ ++ u32 __iomem *inbound_msgaddr0; /* 0x00400 */ ++ u32 __iomem *inbound_msgaddr1; /* 0x00404 */ ++ u32 __iomem *outbound_msgaddr0; /* 0x00420 */ ++ u32 __iomem *outbound_msgaddr1; /* 0x00424 */ ++ u32 __iomem *inbound_doorbell; /* 0x00460 */ ++ u32 __iomem *outbound_doorbell; /* 0x00480 */ ++ u32 __iomem *outbound_doorbell_enable; /* 0x00484 */ ++ u32 __iomem *inboundlist_base_low; /* 0x01000 */ ++ u32 __iomem *inboundlist_base_high; /* 0x01004 */ ++ u32 __iomem *inboundlist_write_pointer; /* 0x01018 */ ++ u32 __iomem *outboundlist_base_low; /* 0x01060 */ ++ u32 __iomem *outboundlist_base_high; /* 0x01064 */ ++ u32 __iomem *outboundlist_copy_pointer; /* 0x0106C */ ++ u32 __iomem *outboundlist_read_pointer; /* 0x01070 0x01072 */ ++ u32 __iomem *outboundlist_interrupt_cause; /* 0x1088 */ ++ u32 __iomem *outboundlist_interrupt_enable; /* 0x108C */ ++ u32 __iomem *message_wbuffer; /* 0x2000 */ ++ u32 __iomem *message_rbuffer; /* 0x2100 */ ++ u32 __iomem *msgcode_rwbuffer; /* 0x2200 */ ++}; ++/* + ******************************************************************************* + ** Adapter Control Block + ******************************************************************************* +@@ -518,12 +623,15 @@ struct AdapterControlBlock + uint32_t reg_mu_acc_handle0; + spinlock_t eh_lock; + spinlock_t ccblist_lock; ++ spinlock_t postq_lock; ++ spinlock_t doneq_lock; + spinlock_t rqbuffer_lock; + spinlock_t wqbuffer_lock; + union { + struct MessageUnit_A __iomem *pmuA; + struct MessageUnit_B *pmuB; + struct MessageUnit_C __iomem *pmuC; ++ struct MessageUnit_D *pmuD; + }; + /* message unit ATU inbound base address0 */ + void __iomem *mem_base0; +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index 26bcdc0..b3cb969 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -108,6 +108,7 @@ static void arcmsr_message_isr_bh_fn(struct work_struct *work); + static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb); + static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); + static void arcmsr_hbaC_message_isr(struct AdapterControlBlock *pACB); ++static void arcmsr_hbaD_message_isr(struct AdapterControlBlock *acb); + static void arcmsr_hardware_reset(struct AdapterControlBlock *acb); + static const char *arcmsr_info(struct Scsi_Host *); + static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); +@@ -161,6 +162,8 @@ static struct pci_device_id arcmsr_device_id_table[] = { + .driver_data = ACB_ADAPTER_TYPE_B}, + {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1210), + .driver_data = ACB_ADAPTER_TYPE_A}, ++ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1214), ++ .driver_data = ACB_ADAPTER_TYPE_D}, + {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1220), + .driver_data = ACB_ADAPTER_TYPE_A}, + {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1230), +@@ -202,7 +205,8 @@ static struct pci_driver arcmsr_pci_driver = { + static void arcmsr_free_mu(struct AdapterControlBlock *acb) + { + switch (acb->adapter_type) { +- case ACB_ADAPTER_TYPE_B:{ ++ case ACB_ADAPTER_TYPE_B: ++ case ACB_ADAPTER_TYPE_D: { + dma_free_coherent(&acb->pdev->dev, acb->roundup_ccbsize, + acb->dma_coherent2, acb->dma_coherent_handle2); + break; +@@ -251,6 +255,25 @@ static bool arcmsr_remap_pciregion(struct AdapterControlBlock *acb) + } + break; + } ++ case ACB_ADAPTER_TYPE_D: { ++ void __iomem *mem_base0; ++ unsigned long addr, range, flags; ++ ++ addr = (unsigned long)pci_resource_start(pdev, 0); ++ range = pci_resource_len(pdev, 0); ++ flags = pci_resource_flags(pdev, 0); ++ if (flags & IORESOURCE_CACHEABLE) ++ mem_base0 = ioremap(addr, range); ++ else ++ mem_base0 = ioremap_nocache(addr, range); ++ if (!mem_base0) { ++ pr_notice("arcmsr%d: memory mapping region fail\n", ++ acb->host->host_no); ++ return false; ++ } ++ acb->mem_base0 = mem_base0; ++ break; ++ } + } + return true; + } +@@ -271,6 +294,10 @@ static void arcmsr_unmap_pciregion(struct AdapterControlBlock *acb) + case ACB_ADAPTER_TYPE_C:{ + iounmap(acb->pmuC); + } ++ break; ++ case ACB_ADAPTER_TYPE_D: ++ iounmap(acb->mem_base0); ++ break; + } + } + +@@ -367,6 +394,23 @@ static uint8_t arcmsr_hbaC_wait_msgint_ready(struct AdapterControlBlock *pACB) + return false; + } + ++static bool arcmsr_hbaD_wait_msgint_ready(struct AdapterControlBlock *pACB) ++{ ++ struct MessageUnit_D *reg = pACB->pmuD; ++ int i; ++ ++ for (i = 0; i < 2000; i++) { ++ if (readl(reg->outbound_doorbell) ++ & ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE) { ++ writel(ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE, ++ reg->outbound_doorbell); ++ return true; ++ } ++ msleep(10); ++ } /* max 20 seconds */ ++ return false; ++} ++ + static void arcmsr_hbaA_flush_cache(struct AdapterControlBlock *acb) + { + struct MessageUnit_A __iomem *reg = acb->pmuA; +@@ -416,6 +460,24 @@ static void arcmsr_hbaC_flush_cache(struct AdapterControlBlock *pACB) + } while (retry_count != 0); + return; + } ++ ++static void arcmsr_hbaD_flush_cache(struct AdapterControlBlock *pACB) ++{ ++ int retry_count = 15; ++ struct MessageUnit_D *reg = pACB->pmuD; ++ ++ writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, reg->inbound_msgaddr0); ++ do { ++ if (arcmsr_hbaD_wait_msgint_ready(pACB)) ++ break; ++ ++ retry_count--; ++ pr_notice("arcmsr%d: wait 'flush adapter " ++ "cache' timeout, retry count down = %d\n", ++ pACB->host->host_no, retry_count); ++ } while (retry_count != 0); ++} ++ + static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) + { + switch (acb->adapter_type) { +@@ -432,6 +494,10 @@ static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) + case ACB_ADAPTER_TYPE_C: { + arcmsr_hbaC_flush_cache(acb); + } ++ break; ++ case ACB_ADAPTER_TYPE_D: ++ arcmsr_hbaD_flush_cache(acb); ++ break; + } + } + +@@ -475,9 +541,16 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) + acb->vir2phy_offset = (unsigned long)dma_coherent - (unsigned long)dma_coherent_handle; + for(i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++){ + cdb_phyaddr = dma_coherent_handle + offsetof(struct CommandControlBlock, arcmsr_cdb); +- ccb_tmp->cdb_phyaddr = +- ((acb->adapter_type == ACB_ADAPTER_TYPE_C) ? +- cdb_phyaddr : (cdb_phyaddr >> 5)); ++ switch (acb->adapter_type) { ++ case ACB_ADAPTER_TYPE_A: ++ case ACB_ADAPTER_TYPE_B: ++ ccb_tmp->cdb_phyaddr = cdb_phyaddr >> 5; ++ break; ++ case ACB_ADAPTER_TYPE_C: ++ case ACB_ADAPTER_TYPE_D: ++ ccb_tmp->cdb_phyaddr = cdb_phyaddr; ++ break; ++ } + acb->pccb_pool[i] = ccb_tmp; + ccb_tmp->acb = acb; + INIT_LIST_HEAD(&ccb_tmp->list); +@@ -521,6 +594,13 @@ static void arcmsr_message_isr_bh_fn(struct work_struct *work) + devicemap = (char __iomem *)(®->msgcode_rwbuffer[21]); + break; + } ++ case ACB_ADAPTER_TYPE_D: { ++ struct MessageUnit_D *reg = acb->pmuD; ++ ++ signature = (uint32_t __iomem *)(®->msgcode_rwbuffer[0]); ++ devicemap = (char __iomem *)(®->msgcode_rwbuffer[21]); ++ break; ++ } + } + atomic_inc(&acb->rq_map_token); + if (readl(signature) != ARCMSR_SIGNATURE_GET_CONFIG) +@@ -651,6 +731,8 @@ static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) + } + spin_lock_init(&acb->eh_lock); + spin_lock_init(&acb->ccblist_lock); ++ spin_lock_init(&acb->postq_lock); ++ spin_lock_init(&acb->doneq_lock); + spin_lock_init(&acb->rqbuffer_lock); + spin_lock_init(&acb->wqbuffer_lock); + acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | +@@ -836,6 +918,20 @@ static uint8_t arcmsr_hbaC_abort_allcmd(struct AdapterControlBlock *pACB) + } + return true; + } ++ ++static uint8_t arcmsr_hbaD_abort_allcmd(struct AdapterControlBlock *pACB) ++{ ++ struct MessageUnit_D *reg = pACB->pmuD; ++ ++ writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, reg->inbound_msgaddr0); ++ if (!arcmsr_hbaD_wait_msgint_ready(pACB)) { ++ pr_notice("arcmsr%d: wait 'abort all outstanding " ++ "command' timeout\n", pACB->host->host_no); ++ return false; ++ } ++ return true; ++} ++ + static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb) + { + uint8_t rtnval = 0; +@@ -853,6 +949,11 @@ static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb) + case ACB_ADAPTER_TYPE_C: { + rtnval = arcmsr_hbaC_abort_allcmd(acb); + } ++ break; ++ ++ case ACB_ADAPTER_TYPE_D: ++ rtnval = arcmsr_hbaD_abort_allcmd(acb); ++ break; + } + return rtnval; + } +@@ -919,6 +1020,12 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) + writel(orig_mask|ARCMSR_HBCMU_ALL_INTMASKENABLE, ®->host_int_mask); + } + break; ++ case ACB_ADAPTER_TYPE_D: { ++ struct MessageUnit_D *reg = acb->pmuD; ++ /* disable all outbound interrupt */ ++ writel(ARCMSR_ARC1214_ALL_INT_DISABLE, reg->pcief0_int_enable); ++ } ++ break; + } + return orig_mask; + } +@@ -1066,7 +1173,62 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) + error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? true : false; + arcmsr_drain_donequeue(acb, pCCB, error); + } +- } ++ } ++ break; ++ case ACB_ADAPTER_TYPE_D: { ++ struct MessageUnit_D *pmu = acb->pmuD; ++ uint32_t ccb_cdb_phy, outbound_write_pointer; ++ uint32_t doneq_index, index_stripped, addressLow, residual; ++ bool error; ++ struct CommandControlBlock *pCCB; ++ ++ outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1; ++ doneq_index = pmu->doneq_index; ++ residual = atomic_read(&acb->ccboutstandingcount); ++ for (i = 0; i < residual; i++) { ++ while ((doneq_index & 0xFFF) != ++ (outbound_write_pointer & 0xFFF)) { ++ if (doneq_index & 0x4000) { ++ index_stripped = doneq_index & 0xFFF; ++ index_stripped += 1; ++ index_stripped %= ++ ARCMSR_MAX_ARC1214_DONEQUEUE; ++ pmu->doneq_index = index_stripped ? ++ (index_stripped | 0x4000) : ++ (index_stripped + 1); ++ } else { ++ index_stripped = doneq_index; ++ index_stripped += 1; ++ index_stripped %= ++ ARCMSR_MAX_ARC1214_DONEQUEUE; ++ pmu->doneq_index = index_stripped ? ++ index_stripped : ++ ((index_stripped | 0x4000) + 1); ++ } ++ doneq_index = pmu->doneq_index; ++ addressLow = pmu->done_qbuffer[doneq_index & ++ 0xFFF].addressLow; ++ ccb_cdb_phy = (addressLow & 0xFFFFFFF0); ++ pARCMSR_CDB = (struct ARCMSR_CDB *) ++ (acb->vir2phy_offset + ccb_cdb_phy); ++ pCCB = container_of(pARCMSR_CDB, ++ struct CommandControlBlock, arcmsr_cdb); ++ error = (addressLow & ++ ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? ++ true : false; ++ arcmsr_drain_donequeue(acb, pCCB, error); ++ writel(doneq_index, ++ pmu->outboundlist_read_pointer); ++ } ++ mdelay(10); ++ outbound_write_pointer = ++ pmu->done_qbuffer[0].addressLow + 1; ++ doneq_index = pmu->doneq_index; ++ } ++ pmu->postq_index = 0; ++ pmu->doneq_index = 0x40FF; ++ } ++ break; + } + } + +@@ -1175,6 +1337,14 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, + writel(intmask_org & mask, ®->host_int_mask); + acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f; + } ++ break; ++ case ACB_ADAPTER_TYPE_D: { ++ struct MessageUnit_D *reg = acb->pmuD; ++ ++ mask = ARCMSR_ARC1214_ALL_INT_ENABLE; ++ writel(intmask_org | mask, reg->pcief0_int_enable); ++ break; ++ } + } + } + +@@ -1282,6 +1452,38 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr + writel(ccb_post_stamp, &phbcmu->inbound_queueport_low); + } + } ++ break; ++ case ACB_ADAPTER_TYPE_D: { ++ struct MessageUnit_D *pmu = acb->pmuD; ++ u16 index_stripped; ++ u16 postq_index; ++ unsigned long flags; ++ struct InBound_SRB *pinbound_srb; ++ ++ spin_lock_irqsave(&acb->postq_lock, flags); ++ postq_index = pmu->postq_index; ++ pinbound_srb = (struct InBound_SRB *)&(pmu->post_qbuffer[postq_index & 0xFF]); ++ pinbound_srb->addressHigh = dma_addr_hi32(cdb_phyaddr); ++ pinbound_srb->addressLow = dma_addr_lo32(cdb_phyaddr); ++ pinbound_srb->length = ccb->arc_cdb_size >> 2; ++ arcmsr_cdb->msgContext = dma_addr_lo32(cdb_phyaddr); ++ if (postq_index & 0x4000) { ++ index_stripped = postq_index & 0xFF; ++ index_stripped += 1; ++ index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE; ++ pmu->postq_index = index_stripped ? ++ (index_stripped | 0x4000) : index_stripped; ++ } else { ++ index_stripped = postq_index; ++ index_stripped += 1; ++ index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE; ++ pmu->postq_index = index_stripped ? index_stripped : ++ (index_stripped | 0x4000); ++ } ++ writel(postq_index, pmu->inboundlist_write_pointer); ++ spin_unlock_irqrestore(&acb->postq_lock, flags); ++ break; ++ } + } + } + +@@ -1323,6 +1525,18 @@ static void arcmsr_hbaC_stop_bgrb(struct AdapterControlBlock *pACB) + } + return; + } ++ ++static void arcmsr_hbaD_stop_bgrb(struct AdapterControlBlock *pACB) ++{ ++ struct MessageUnit_D *reg = pACB->pmuD; ++ ++ pACB->acb_flags &= ~ACB_F_MSG_START_BGRB; ++ writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, reg->inbound_msgaddr0); ++ if (!arcmsr_hbaD_wait_msgint_ready(pACB)) ++ pr_notice("arcmsr%d: wait 'stop adapter background rebulid' " ++ "timeout\n", pACB->host->host_no); ++} ++ + static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) + { + switch (acb->adapter_type) { +@@ -1338,6 +1552,10 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) + case ACB_ADAPTER_TYPE_C: { + arcmsr_hbaC_stop_bgrb(acb); + } ++ break; ++ case ACB_ADAPTER_TYPE_D: ++ arcmsr_hbaD_stop_bgrb(acb); ++ break; + } + } + +@@ -1362,8 +1580,16 @@ static void arcmsr_iop_message_read(struct AdapterControlBlock *acb) + break; + case ACB_ADAPTER_TYPE_C: { + struct MessageUnit_C __iomem *reg = acb->pmuC; ++ + writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, ®->inbound_doorbell); + } ++ break; ++ case ACB_ADAPTER_TYPE_D: { ++ struct MessageUnit_D *reg = acb->pmuD; ++ writel(ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ, ++ reg->inbound_doorbell); ++ } ++ break; + } + } + +@@ -1398,6 +1624,12 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) + writel(ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK, ®->inbound_doorbell); + } + break; ++ case ACB_ADAPTER_TYPE_D: { ++ struct MessageUnit_D *reg = acb->pmuD; ++ writel(ARCMSR_ARC1214_DRV2IOP_DATA_IN_READY, ++ reg->inbound_doorbell); ++ } ++ break; + } + } + +@@ -1421,6 +1653,12 @@ struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb) + struct MessageUnit_C __iomem *phbcmu = acb->pmuC; + qbuffer = (struct QBUFFER __iomem *)&phbcmu->message_rbuffer; + } ++ break; ++ case ACB_ADAPTER_TYPE_D: { ++ struct MessageUnit_D *reg = acb->pmuD; ++ qbuffer = (struct QBUFFER __iomem *)reg->message_rbuffer; ++ } ++ break; + } + return qbuffer; + } +@@ -1444,8 +1682,13 @@ static struct QBUFFER __iomem *arcmsr_get_iop_wqbuffer(struct AdapterControlBloc + case ACB_ADAPTER_TYPE_C: { + struct MessageUnit_C __iomem *reg = acb->pmuC; + pqbuffer = (struct QBUFFER __iomem *)®->message_wbuffer; +- } +- ++ } ++ break; ++ case ACB_ADAPTER_TYPE_D: { ++ struct MessageUnit_D *reg = acb->pmuD; ++ pqbuffer = (struct QBUFFER __iomem *)reg->message_wbuffer; ++ } ++ break; + } + return pqbuffer; + } +@@ -1500,7 +1743,7 @@ arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, + uint8_t __iomem *iop_data; + uint32_t iop_len; + +- if (acb->adapter_type & ACB_ADAPTER_TYPE_C) ++ if (acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) + return arcmsr_Read_iop_rqbuffer_in_DWORD(acb, prbuffer); + iop_data = (uint8_t __iomem *)prbuffer->data; + iop_len = readl(&prbuffer->data_len); +@@ -1586,7 +1829,7 @@ arcmsr_write_ioctldata2iop(struct AdapterControlBlock *acb) + uint8_t __iomem *iop_data; + int32_t allxfer_len = 0; + +- if (acb->adapter_type & ACB_ADAPTER_TYPE_C) { ++ if (acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) { + arcmsr_write_ioctldata2iop_in_DWORD(acb); + return; + } +@@ -1662,6 +1905,27 @@ static void arcmsr_hbaC_doorbell_isr(struct AdapterControlBlock *pACB) + | ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK + | ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE)); + } ++ ++static void arcmsr_hbaD_doorbell_isr(struct AdapterControlBlock *pACB) ++{ ++ uint32_t outbound_doorbell; ++ struct MessageUnit_D *pmu = pACB->pmuD; ++ ++ outbound_doorbell = readl(pmu->outbound_doorbell); ++ do { ++ writel(outbound_doorbell, pmu->outbound_doorbell); ++ if (outbound_doorbell & ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE) ++ arcmsr_hbaD_message_isr(pACB); ++ if (outbound_doorbell & ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK) ++ arcmsr_iop2drv_data_wrote_handle(pACB); ++ if (outbound_doorbell & ARCMSR_ARC1214_IOP2DRV_DATA_READ_OK) ++ arcmsr_iop2drv_data_read_handle(pACB); ++ outbound_doorbell = readl(pmu->outbound_doorbell); ++ } while (outbound_doorbell & (ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK ++ | ARCMSR_ARC1214_IOP2DRV_DATA_READ_OK ++ | ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE)); ++} ++ + static void arcmsr_hbaA_postqueue_isr(struct AdapterControlBlock *acb) + { + uint32_t flag_ccb; +@@ -1728,6 +1992,59 @@ static void arcmsr_hbaC_postqueue_isr(struct AdapterControlBlock *acb) + } + } + } ++ ++static void arcmsr_hbaD_postqueue_isr(struct AdapterControlBlock *acb) ++{ ++ u32 outbound_write_pointer, doneq_index, index_stripped; ++ uint32_t addressLow, ccb_cdb_phy; ++ int error; ++ struct MessageUnit_D *pmu; ++ struct ARCMSR_CDB *arcmsr_cdb; ++ struct CommandControlBlock *ccb; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&acb->doneq_lock, flags); ++ pmu = acb->pmuD; ++ outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1; ++ doneq_index = pmu->doneq_index; ++ if ((doneq_index & 0xFFF) != (outbound_write_pointer & 0xFFF)) { ++ do { ++ if (doneq_index & 0x4000) { ++ index_stripped = doneq_index & 0xFFF; ++ index_stripped += 1; ++ index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; ++ pmu->doneq_index = index_stripped ++ ? (index_stripped | 0x4000) : ++ (index_stripped + 1); ++ } else { ++ index_stripped = doneq_index; ++ index_stripped += 1; ++ index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; ++ pmu->doneq_index = index_stripped ++ ? index_stripped : ++ ((index_stripped | 0x4000) + 1); ++ } ++ doneq_index = pmu->doneq_index; ++ addressLow = pmu->done_qbuffer[doneq_index & ++ 0xFFF].addressLow; ++ ccb_cdb_phy = (addressLow & 0xFFFFFFF0); ++ arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset ++ + ccb_cdb_phy); ++ ccb = container_of(arcmsr_cdb, ++ struct CommandControlBlock, arcmsr_cdb); ++ error = (addressLow & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ++ ? true : false; ++ arcmsr_drain_donequeue(acb, ccb, error); ++ writel(doneq_index, pmu->outboundlist_read_pointer); ++ } while ((doneq_index & 0xFFF) != ++ (outbound_write_pointer & 0xFFF)); ++ } ++ writel(ARCMSR_ARC1214_OUTBOUND_LIST_INTERRUPT_CLEAR, ++ pmu->outboundlist_interrupt_cause); ++ readl(pmu->outboundlist_interrupt_cause); ++ spin_unlock_irqrestore(&acb->doneq_lock, flags); ++} ++ + /* + ********************************************************************************** + ** Handle a message interrupt +@@ -1768,6 +2085,15 @@ static void arcmsr_hbaC_message_isr(struct AdapterControlBlock *acb) + schedule_work(&acb->arcmsr_do_message_isr_bh); + } + ++static void arcmsr_hbaD_message_isr(struct AdapterControlBlock *acb) ++{ ++ struct MessageUnit_D *reg = acb->pmuD; ++ ++ writel(ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE, reg->outbound_doorbell); ++ readl(reg->outbound_doorbell); ++ schedule_work(&acb->arcmsr_do_message_isr_bh); ++} ++ + static int arcmsr_hbaA_handle_isr(struct AdapterControlBlock *acb) + { + uint32_t outbound_intstatus; +@@ -1845,6 +2171,32 @@ static int arcmsr_hbaC_handle_isr(struct AdapterControlBlock *pACB) + ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR)); + return IRQ_HANDLED; + } ++ ++static irqreturn_t arcmsr_hbaD_handle_isr(struct AdapterControlBlock *pACB) ++{ ++ u32 host_interrupt_status; ++ struct MessageUnit_D *pmu = pACB->pmuD; ++ ++ host_interrupt_status = readl(pmu->host_int_status) & ++ (ARCMSR_ARC1214_OUTBOUND_POSTQUEUE_ISR | ++ ARCMSR_ARC1214_OUTBOUND_DOORBELL_ISR); ++ if (!host_interrupt_status) ++ return IRQ_NONE; ++ do { ++ /* MU post queue interrupts*/ ++ if (host_interrupt_status & ++ ARCMSR_ARC1214_OUTBOUND_POSTQUEUE_ISR) ++ arcmsr_hbaD_postqueue_isr(pACB); ++ if (host_interrupt_status & ++ ARCMSR_ARC1214_OUTBOUND_DOORBELL_ISR) ++ arcmsr_hbaD_doorbell_isr(pACB); ++ host_interrupt_status = readl(pmu->host_int_status); ++ } while (host_interrupt_status & ++ (ARCMSR_ARC1214_OUTBOUND_POSTQUEUE_ISR | ++ ARCMSR_ARC1214_OUTBOUND_DOORBELL_ISR)); ++ return IRQ_HANDLED; ++} ++ + static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) + { + switch (acb->adapter_type) { +@@ -1856,6 +2208,8 @@ static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) + break; + case ACB_ADAPTER_TYPE_C: + return arcmsr_hbaC_handle_isr(acb); ++ case ACB_ADAPTER_TYPE_D: ++ return arcmsr_hbaD_handle_isr(acb); + default: + return IRQ_NONE; + } +@@ -2522,6 +2876,137 @@ static bool arcmsr_hbaC_get_config(struct AdapterControlBlock *pACB) + /*all interrupt service will be enable at arcmsr_iop_init*/ + return true; + } ++ ++static bool arcmsr_hbaD_get_config(struct AdapterControlBlock *acb) ++{ ++ char *acb_firm_model = acb->firm_model; ++ char *acb_firm_version = acb->firm_version; ++ char *acb_device_map = acb->device_map; ++ char __iomem *iop_firm_model; ++ char __iomem *iop_firm_version; ++ char __iomem *iop_device_map; ++ u32 count; ++ struct MessageUnit_D *reg ; ++ void *dma_coherent2; ++ dma_addr_t dma_coherent_handle2; ++ struct pci_dev *pdev = acb->pdev; ++ ++ acb->roundup_ccbsize = roundup(sizeof(struct MessageUnit_D), 32); ++ dma_coherent2 = dma_alloc_coherent(&pdev->dev, acb->roundup_ccbsize, ++ &dma_coherent_handle2, GFP_KERNEL); ++ if (!dma_coherent2) { ++ pr_notice("DMA allocation failed...\n"); ++ return false; ++ } ++ memset(dma_coherent2, 0, acb->roundup_ccbsize); ++ acb->dma_coherent_handle2 = dma_coherent_handle2; ++ acb->dma_coherent2 = dma_coherent2; ++ reg = (struct MessageUnit_D *)dma_coherent2; ++ acb->pmuD = reg; ++ reg->chip_id = acb->mem_base0 + ARCMSR_ARC1214_CHIP_ID; ++ reg->cpu_mem_config = acb->mem_base0 + ++ ARCMSR_ARC1214_CPU_MEMORY_CONFIGURATION; ++ reg->i2o_host_interrupt_mask = acb->mem_base0 + ++ ARCMSR_ARC1214_I2_HOST_INTERRUPT_MASK; ++ reg->sample_at_reset = acb->mem_base0 + ARCMSR_ARC1214_SAMPLE_RESET; ++ reg->reset_request = acb->mem_base0 + ARCMSR_ARC1214_RESET_REQUEST; ++ reg->host_int_status = acb->mem_base0 + ++ ARCMSR_ARC1214_MAIN_INTERRUPT_STATUS; ++ reg->pcief0_int_enable = acb->mem_base0 + ++ ARCMSR_ARC1214_PCIE_F0_INTERRUPT_ENABLE; ++ reg->inbound_msgaddr0 = acb->mem_base0 + ++ ARCMSR_ARC1214_INBOUND_MESSAGE0; ++ reg->inbound_msgaddr1 = acb->mem_base0 + ++ ARCMSR_ARC1214_INBOUND_MESSAGE1; ++ reg->outbound_msgaddr0 = acb->mem_base0 + ++ ARCMSR_ARC1214_OUTBOUND_MESSAGE0; ++ reg->outbound_msgaddr1 = acb->mem_base0 + ++ ARCMSR_ARC1214_OUTBOUND_MESSAGE1; ++ reg->inbound_doorbell = acb->mem_base0 + ++ ARCMSR_ARC1214_INBOUND_DOORBELL; ++ reg->outbound_doorbell = acb->mem_base0 + ++ ARCMSR_ARC1214_OUTBOUND_DOORBELL; ++ reg->outbound_doorbell_enable = acb->mem_base0 + ++ ARCMSR_ARC1214_OUTBOUND_DOORBELL_ENABLE; ++ reg->inboundlist_base_low = acb->mem_base0 + ++ ARCMSR_ARC1214_INBOUND_LIST_BASE_LOW; ++ reg->inboundlist_base_high = acb->mem_base0 + ++ ARCMSR_ARC1214_INBOUND_LIST_BASE_HIGH; ++ reg->inboundlist_write_pointer = acb->mem_base0 + ++ ARCMSR_ARC1214_INBOUND_LIST_WRITE_POINTER; ++ reg->outboundlist_base_low = acb->mem_base0 + ++ ARCMSR_ARC1214_OUTBOUND_LIST_BASE_LOW; ++ reg->outboundlist_base_high = acb->mem_base0 + ++ ARCMSR_ARC1214_OUTBOUND_LIST_BASE_HIGH; ++ reg->outboundlist_copy_pointer = acb->mem_base0 + ++ ARCMSR_ARC1214_OUTBOUND_LIST_COPY_POINTER; ++ reg->outboundlist_read_pointer = acb->mem_base0 + ++ ARCMSR_ARC1214_OUTBOUND_LIST_READ_POINTER; ++ reg->outboundlist_interrupt_cause = acb->mem_base0 + ++ ARCMSR_ARC1214_OUTBOUND_INTERRUPT_CAUSE; ++ reg->outboundlist_interrupt_enable = acb->mem_base0 + ++ ARCMSR_ARC1214_OUTBOUND_INTERRUPT_ENABLE; ++ reg->message_wbuffer = acb->mem_base0 + ARCMSR_ARC1214_MESSAGE_WBUFFER; ++ reg->message_rbuffer = acb->mem_base0 + ARCMSR_ARC1214_MESSAGE_RBUFFER; ++ reg->msgcode_rwbuffer = acb->mem_base0 + ++ ARCMSR_ARC1214_MESSAGE_RWBUFFER; ++ iop_firm_model = (char __iomem *)(®->msgcode_rwbuffer[15]); ++ iop_firm_version = (char __iomem *)(®->msgcode_rwbuffer[17]); ++ iop_device_map = (char __iomem *)(®->msgcode_rwbuffer[21]); ++ if (readl(acb->pmuD->outbound_doorbell) & ++ ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE) { ++ writel(ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE, ++ acb->pmuD->outbound_doorbell);/*clear interrupt*/ ++ } ++ /* post "get config" instruction */ ++ writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, reg->inbound_msgaddr0); ++ /* wait message ready */ ++ if (!arcmsr_hbaD_wait_msgint_ready(acb)) { ++ pr_notice("arcmsr%d: wait get adapter firmware " ++ "miscellaneous data timeout\n", acb->host->host_no); ++ dma_free_coherent(&acb->pdev->dev, acb->roundup_ccbsize, ++ acb->dma_coherent2, acb->dma_coherent_handle2); ++ return false; ++ } ++ 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--; ++ } ++ count = 16; ++ while (count) { ++ *acb_device_map = readb(iop_device_map); ++ acb_device_map++; ++ iop_device_map++; ++ count--; ++ } ++ acb->signature = readl(®->msgcode_rwbuffer[1]); ++ /*firm_signature,1,00-03*/ ++ acb->firm_request_len = readl(®->msgcode_rwbuffer[2]); ++ /*firm_request_len,1,04-07*/ ++ acb->firm_numbers_queue = readl(®->msgcode_rwbuffer[3]); ++ /*firm_numbers_queue,2,08-11*/ ++ acb->firm_sdram_size = readl(®->msgcode_rwbuffer[4]); ++ /*firm_sdram_size,3,12-15*/ ++ acb->firm_hd_channels = readl(®->msgcode_rwbuffer[5]); ++ /*firm_hd_channels,4,16-19*/ ++ acb->firm_cfg_version = readl(®->msgcode_rwbuffer[25]); ++ pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n", ++ acb->host->host_no, ++ acb->firm_model, ++ acb->firm_version); ++ return true; ++} ++ + static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) + { + bool rtn = false; +@@ -2536,6 +3021,9 @@ static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) + case ACB_ADAPTER_TYPE_C: + rtn = arcmsr_hbaC_get_config(acb); + break; ++ case ACB_ADAPTER_TYPE_D: ++ rtn = arcmsr_hbaD_get_config(acb); ++ break; + default: + break; + } +@@ -2725,6 +3213,89 @@ polling_hbc_ccb_retry: + } + return rtn; + } ++ ++static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb, ++ struct CommandControlBlock *poll_ccb) ++{ ++ bool error; ++ uint32_t poll_ccb_done = 0, poll_count = 0, flag_ccb, ccb_cdb_phy; ++ int rtn, doneq_index, index_stripped, outbound_write_pointer; ++ unsigned long flags; ++ struct ARCMSR_CDB *arcmsr_cdb; ++ struct CommandControlBlock *pCCB; ++ struct MessageUnit_D *pmu = acb->pmuD; ++ ++polling_hbaD_ccb_retry: ++ poll_count++; ++ while (1) { ++ outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1; ++ doneq_index = pmu->doneq_index; ++ if ((outbound_write_pointer & 0xFFF) == (doneq_index & 0xFFF)) { ++ if (poll_ccb_done) { ++ rtn = SUCCESS; ++ break; ++ } else { ++ msleep(25); ++ if (poll_count > 40) { ++ rtn = FAILED; ++ break; ++ } ++ goto polling_hbaD_ccb_retry; ++ } ++ } ++ spin_lock_irqsave(&acb->doneq_lock, flags); ++ if (doneq_index & 0x4000) { ++ index_stripped = doneq_index & 0xFFF; ++ index_stripped += 1; ++ index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; ++ pmu->doneq_index = index_stripped ? ++ (index_stripped | 0x4000) : ++ (index_stripped + 1); ++ } else { ++ index_stripped = doneq_index; ++ index_stripped += 1; ++ index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; ++ pmu->doneq_index = index_stripped ? index_stripped : ++ ((index_stripped | 0x4000) + 1); ++ } ++ spin_unlock_irqrestore(&acb->doneq_lock, flags); ++ doneq_index = pmu->doneq_index; ++ flag_ccb = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow; ++ ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0); ++ arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + ++ ccb_cdb_phy); ++ pCCB = container_of(arcmsr_cdb, struct CommandControlBlock, ++ arcmsr_cdb); ++ poll_ccb_done |= (pCCB == poll_ccb) ? 1 : 0; ++ if ((pCCB->acb != acb) || ++ (pCCB->startdone != ARCMSR_CCB_START)) { ++ if (pCCB->startdone == ARCMSR_CCB_ABORTED) { ++ pr_notice("arcmsr%d: scsi id = %d " ++ "lun = %d ccb = '0x%p' poll command " ++ "abort successfully\n" ++ , acb->host->host_no ++ , pCCB->pcmd->device->id ++ , (u32)pCCB->pcmd->device->lun ++ , pCCB); ++ pCCB->pcmd->result = DID_ABORT << 16; ++ arcmsr_ccb_complete(pCCB); ++ continue; ++ } ++ pr_notice("arcmsr%d: polling an illegal " ++ "ccb command done ccb = '0x%p' " ++ "ccboutstandingcount = %d\n" ++ , acb->host->host_no ++ , pCCB ++ , atomic_read(&acb->ccboutstandingcount)); ++ continue; ++ } ++ error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ++ ? true : false; ++ arcmsr_report_ccb_state(acb, pCCB, error); ++ } ++ return rtn; ++} ++ + static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, + struct CommandControlBlock *poll_ccb) + { +@@ -2743,6 +3314,10 @@ static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, + case ACB_ADAPTER_TYPE_C: { + rtn = arcmsr_hbaC_polling_ccbdone(acb, poll_ccb); + } ++ break; ++ case ACB_ADAPTER_TYPE_D: ++ rtn = arcmsr_hbaD_polling_ccbdone(acb, poll_ccb); ++ break; + } + return rtn; + } +@@ -2760,6 +3335,7 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + */ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_B: ++ case ACB_ADAPTER_TYPE_D: + dma_coherent_handle = acb->dma_coherent_handle2; + break; + default: +@@ -2849,6 +3425,27 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + } + } + } ++ break; ++ case ACB_ADAPTER_TYPE_D: { ++ uint32_t __iomem *rwbuffer; ++ struct MessageUnit_D *reg = acb->pmuD; ++ reg->postq_index = 0; ++ reg->doneq_index = 0; ++ rwbuffer = reg->msgcode_rwbuffer; ++ writel(ARCMSR_SIGNATURE_SET_CONFIG, rwbuffer++); ++ writel(cdb_phyaddr_hi32, rwbuffer++); ++ writel(cdb_phyaddr, rwbuffer++); ++ writel(cdb_phyaddr + (ARCMSR_MAX_ARC1214_POSTQUEUE * ++ sizeof(struct InBound_SRB)), rwbuffer++); ++ writel(0x100, rwbuffer); ++ writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, reg->inbound_msgaddr0); ++ if (!arcmsr_hbaD_wait_msgint_ready(acb)) { ++ pr_notice("arcmsr%d: 'set command Q window' timeout\n", ++ acb->host->host_no); ++ return 1; ++ } ++ } ++ break; + } + return 0; + } +@@ -2880,6 +3477,15 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) + firmware_state = readl(®->outbound_msgaddr1); + } while ((firmware_state & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0); + } ++ break; ++ case ACB_ADAPTER_TYPE_D: { ++ struct MessageUnit_D *reg = acb->pmuD; ++ do { ++ firmware_state = readl(reg->outbound_msgaddr1); ++ } while ((firmware_state & ++ ARCMSR_ARC1214_MESSAGE_FIRMWARE_OK) == 0); ++ } ++ break; + } + } + +@@ -2950,6 +3556,35 @@ static void arcmsr_hbaC_request_device_map(struct AdapterControlBlock *acb) + return; + } + ++static void arcmsr_hbaD_request_device_map(struct AdapterControlBlock *acb) ++{ ++ struct MessageUnit_D *reg = acb->pmuD; ++ ++ if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ++ ((acb->acb_flags & ACB_F_BUS_RESET) != 0) || ++ ((acb->acb_flags & ACB_F_ABORT) != 0)) { ++ mod_timer(&acb->eternal_timer, ++ jiffies + msecs_to_jiffies(6 * HZ)); ++ } else { ++ acb->fw_flag = FW_NORMAL; ++ if (atomic_read(&acb->ante_token_value) == ++ atomic_read(&acb->rq_map_token)) { ++ atomic_set(&acb->rq_map_token, 16); ++ } ++ atomic_set(&acb->ante_token_value, ++ atomic_read(&acb->rq_map_token)); ++ if (atomic_dec_and_test(&acb->rq_map_token)) { ++ mod_timer(&acb->eternal_timer, jiffies + ++ msecs_to_jiffies(6 * HZ)); ++ return; ++ } ++ writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ++ reg->inbound_msgaddr0); ++ mod_timer(&acb->eternal_timer, jiffies + ++ msecs_to_jiffies(6 * HZ)); ++ } ++} ++ + static void arcmsr_request_device_map(unsigned long pacb) + { + struct AdapterControlBlock *acb = (struct AdapterControlBlock *)pacb; +@@ -2965,6 +3600,10 @@ static void arcmsr_request_device_map(unsigned long pacb) + case ACB_ADAPTER_TYPE_C: { + arcmsr_hbaC_request_device_map(acb); + } ++ break; ++ case ACB_ADAPTER_TYPE_D: ++ arcmsr_hbaD_request_device_map(acb); ++ break; + } + } + +@@ -3002,6 +3641,19 @@ static void arcmsr_hbaC_start_bgrb(struct AdapterControlBlock *pACB) + } + return; + } ++ ++static void arcmsr_hbaD_start_bgrb(struct AdapterControlBlock *pACB) ++{ ++ struct MessageUnit_D *pmu = pACB->pmuD; ++ ++ pACB->acb_flags |= ACB_F_MSG_START_BGRB; ++ writel(ARCMSR_INBOUND_MESG0_START_BGRB, pmu->inbound_msgaddr0); ++ if (!arcmsr_hbaD_wait_msgint_ready(pACB)) { ++ pr_notice("arcmsr%d: wait 'start adapter " ++ "background rebulid' timeout\n", pACB->host->host_no); ++ } ++} ++ + static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) + { + switch (acb->adapter_type) { +@@ -3013,6 +3665,10 @@ static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) + break; + case ACB_ADAPTER_TYPE_C: + arcmsr_hbaC_start_bgrb(acb); ++ break; ++ case ACB_ADAPTER_TYPE_D: ++ arcmsr_hbaD_start_bgrb(acb); ++ break; + } + } + +@@ -3058,6 +3714,29 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb) + break; + } + } ++ break; ++ case ACB_ADAPTER_TYPE_D: { ++ struct MessageUnit_D *reg = acb->pmuD; ++ uint32_t outbound_doorbell, i; ++ /* empty doorbell Qbuffer if door bell ringed */ ++ outbound_doorbell = readl(reg->outbound_doorbell); ++ writel(outbound_doorbell, reg->outbound_doorbell); ++ writel(ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ, ++ reg->inbound_doorbell); ++ for (i = 0; i < 200; i++) { ++ msleep(20); ++ outbound_doorbell = readl(reg->outbound_doorbell); ++ if (outbound_doorbell & ++ ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK) { ++ writel(outbound_doorbell, ++ reg->outbound_doorbell); ++ writel(ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ, ++ reg->inbound_doorbell); ++ } else ++ break; ++ } ++ } ++ break; + } + } + +@@ -3088,6 +3767,7 @@ static void arcmsr_hardware_reset(struct AdapterControlBlock *acb) + int i, count = 0; + struct MessageUnit_A __iomem *pmuA = acb->pmuA; + struct MessageUnit_C __iomem *pmuC = acb->pmuC; ++ struct MessageUnit_D *pmuD = acb->pmuD; + + /* backup pci config data */ + printk(KERN_NOTICE "arcmsr%d: executing hw bus reset .....\n", acb->host->host_no); +@@ -3108,6 +3788,8 @@ static void arcmsr_hardware_reset(struct AdapterControlBlock *acb) + writel(0xD, &pmuC->write_sequence); + } while (((readl(&pmuC->host_diagnostic) & ARCMSR_ARC1880_DiagWrite_ENABLE) == 0) && (count < 5)); + writel(ARCMSR_ARC1880_RESET_ADAPTER, &pmuC->host_diagnostic); ++ } else if ((acb->dev_id == 0x1214)) { ++ writel(0x20, pmuD->reset_request); + } else { + pci_write_config_byte(acb->pdev, 0x84, 0x20); + } +@@ -3304,6 +3986,66 @@ sleep: + } + break; + } ++ case ACB_ADAPTER_TYPE_D: { ++ if (acb->acb_flags & ACB_F_BUS_RESET) { ++ long timeout; ++ pr_notice("arcmsr: there is an bus reset" ++ " eh proceeding.......\n"); ++ timeout = wait_event_timeout(wait_q, (acb->acb_flags ++ & ACB_F_BUS_RESET) == 0, 220 * HZ); ++ if (timeout) ++ return SUCCESS; ++ } ++ acb->acb_flags |= ACB_F_BUS_RESET; ++ if (!arcmsr_iop_reset(acb)) { ++ struct MessageUnit_D *reg; ++ reg = acb->pmuD; ++ arcmsr_hardware_reset(acb); ++ acb->acb_flags &= ~ACB_F_IOP_INITED; ++ nap: ++ ssleep(ARCMSR_SLEEPTIME); ++ if ((readl(reg->sample_at_reset) & 0x80) != 0) { ++ pr_err("arcmsr%d: waiting for " ++ "hw bus reset return, retry=%d\n", ++ acb->host->host_no, retry_count); ++ if (retry_count > ARCMSR_RETRYCOUNT) { ++ acb->fw_flag = FW_DEADLOCK; ++ pr_err("arcmsr%d: waiting for hw bus" ++ " reset return, " ++ "RETRY TERMINATED!!\n", ++ acb->host->host_no); ++ return FAILED; ++ } ++ retry_count++; ++ goto nap; ++ } ++ acb->acb_flags |= ACB_F_IOP_INITED; ++ /* disable all outbound interrupt */ ++ intmask_org = arcmsr_disable_outbound_ints(acb); ++ arcmsr_get_firmware_spec(acb); ++ arcmsr_start_adapter_bgrb(acb); ++ arcmsr_clear_doorbell_queue_buffer(acb); ++ arcmsr_enable_outbound_ints(acb, intmask_org); ++ atomic_set(&acb->rq_map_token, 16); ++ atomic_set(&acb->ante_token_value, 16); ++ acb->fw_flag = FW_NORMAL; ++ mod_timer(&acb->eternal_timer, ++ jiffies + msecs_to_jiffies(6 * HZ)); ++ acb->acb_flags &= ~ACB_F_BUS_RESET; ++ rtn = SUCCESS; ++ pr_err("arcmsr: scsi bus reset " ++ "eh returns with success\n"); ++ } else { ++ acb->acb_flags &= ~ACB_F_BUS_RESET; ++ atomic_set(&acb->rq_map_token, 16); ++ atomic_set(&acb->ante_token_value, 16); ++ acb->fw_flag = FW_NORMAL; ++ mod_timer(&acb->eternal_timer, ++ jiffies + msecs_to_jiffies(6 * HZ)); ++ rtn = SUCCESS; ++ } ++ break; ++ } + } + return rtn; + } +@@ -3380,6 +4122,7 @@ static const char *arcmsr_info(struct Scsi_Host *host) + case PCI_DEVICE_ID_ARECA_1280: + type = "SATA"; + break; ++ case PCI_DEVICE_ID_ARECA_1214: + case PCI_DEVICE_ID_ARECA_1380: + case PCI_DEVICE_ID_ARECA_1381: + case PCI_DEVICE_ID_ARECA_1680: diff --git a/debian/patches/features/all/arcmsr/0017-arcmsr-call-scsi_scan_host-at-the-end-of-host-initia.patch b/debian/patches/features/all/arcmsr/0017-arcmsr-call-scsi_scan_host-at-the-end-of-host-initia.patch new file mode 100644 index 000000000..a38b6bd6e --- /dev/null +++ b/debian/patches/features/all/arcmsr/0017-arcmsr-call-scsi_scan_host-at-the-end-of-host-initia.patch @@ -0,0 +1,63 @@ +From: Ching Huang +Date: Tue, 19 Aug 2014 15:28:36 +0800 +Subject: [17/19] arcmsr: call scsi_scan_host at the end of host initialization +Origin: https://git.kernel.org/linus/b4eb6ae9075a958ffe24620f985f6bd729a1b138 +Bug-Debian: https://bugs.debian.org/698821 + +Call scsi_scan_host at the end of host initialization and fix and error path +to free allocated resource. + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr_hba.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index b3cb969..3d3cdfe 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -112,6 +112,7 @@ static void arcmsr_hbaD_message_isr(struct AdapterControlBlock *acb); + static void arcmsr_hardware_reset(struct AdapterControlBlock *acb); + static const char *arcmsr_info(struct Scsi_Host *); + static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); ++static void arcmsr_free_irq(struct pci_dev *, struct AdapterControlBlock *); + static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, + int queue_depth, int reason) + { +@@ -755,12 +756,11 @@ static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) + } + error = scsi_add_host(host, &pdev->dev); + if(error){ +- goto RAID_controller_stop; ++ goto free_ccb_pool; + } + if (arcmsr_request_irq(pdev, acb) == FAILED) + goto scsi_host_remove; + arcmsr_iop_init(acb); +- scsi_scan_host(host); + INIT_WORK(&acb->arcmsr_do_message_isr_bh, arcmsr_message_isr_bh_fn); + atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->ante_token_value, 16); +@@ -772,13 +772,17 @@ static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) + add_timer(&acb->eternal_timer); + if(arcmsr_alloc_sysfs_attr(acb)) + goto out_free_sysfs; ++ scsi_scan_host(host); + return 0; + out_free_sysfs: +-scsi_host_remove: +- scsi_remove_host(host); +-RAID_controller_stop: ++ del_timer_sync(&acb->eternal_timer); ++ flush_work(&acb->arcmsr_do_message_isr_bh); + arcmsr_stop_adapter_bgrb(acb); + arcmsr_flush_adapter_cache(acb); ++ arcmsr_free_irq(pdev, acb); ++scsi_host_remove: ++ scsi_remove_host(host); ++free_ccb_pool: + arcmsr_free_ccb_pool(acb); + free_hbb_mu: + arcmsr_free_mu(acb); diff --git a/debian/patches/features/all/arcmsr/0018-arcmsr-simplify-of-updating-doneq_index-and-postq_in.patch b/debian/patches/features/all/arcmsr/0018-arcmsr-simplify-of-updating-doneq_index-and-postq_in.patch new file mode 100644 index 000000000..bd6743e93 --- /dev/null +++ b/debian/patches/features/all/arcmsr/0018-arcmsr-simplify-of-updating-doneq_index-and-postq_in.patch @@ -0,0 +1,232 @@ +From: Ching Huang +Date: Mon, 15 Sep 2014 19:05:33 +0800 +Subject: [18/19] arcmsr: simplify of updating doneq_index and postq_index +Origin: https://git.kernel.org/linus/3b8155d582968f79a62c79358d5e137f99f04407 +Bug-Debian: https://bugs.debian.org/698821 + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr_hba.c | 121 +++++++++++++-------------------------- + 1 file changed, 40 insertions(+), 81 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index 3d3cdfe..0dd38cc 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -1120,7 +1120,7 @@ static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, struct Comma + static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) + { + int i = 0; +- uint32_t flag_ccb; ++ uint32_t flag_ccb, ccb_cdb_phy; + struct ARCMSR_CDB *pARCMSR_CDB; + bool error; + struct CommandControlBlock *pCCB; +@@ -1164,10 +1164,6 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) + break; + case ACB_ADAPTER_TYPE_C: { + struct MessageUnit_C __iomem *reg = acb->pmuC; +- struct ARCMSR_CDB *pARCMSR_CDB; +- uint32_t flag_ccb, ccb_cdb_phy; +- bool error; +- struct CommandControlBlock *pCCB; + while ((readl(®->host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { + /*need to do*/ + flag_ccb = readl(®->outbound_queueport_low); +@@ -1181,35 +1177,25 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) + break; + case ACB_ADAPTER_TYPE_D: { + struct MessageUnit_D *pmu = acb->pmuD; +- uint32_t ccb_cdb_phy, outbound_write_pointer; +- uint32_t doneq_index, index_stripped, addressLow, residual; +- bool error; +- struct CommandControlBlock *pCCB; ++ uint32_t outbound_write_pointer; ++ uint32_t doneq_index, index_stripped, addressLow, residual, toggle; ++ unsigned long flags; + +- outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1; +- doneq_index = pmu->doneq_index; + residual = atomic_read(&acb->ccboutstandingcount); + for (i = 0; i < residual; i++) { +- while ((doneq_index & 0xFFF) != ++ spin_lock_irqsave(&acb->doneq_lock, flags); ++ outbound_write_pointer = ++ pmu->done_qbuffer[0].addressLow + 1; ++ doneq_index = pmu->doneq_index; ++ if ((doneq_index & 0xFFF) != + (outbound_write_pointer & 0xFFF)) { +- if (doneq_index & 0x4000) { +- index_stripped = doneq_index & 0xFFF; +- index_stripped += 1; +- index_stripped %= +- ARCMSR_MAX_ARC1214_DONEQUEUE; +- pmu->doneq_index = index_stripped ? +- (index_stripped | 0x4000) : +- (index_stripped + 1); +- } else { +- index_stripped = doneq_index; +- index_stripped += 1; +- index_stripped %= +- ARCMSR_MAX_ARC1214_DONEQUEUE; +- pmu->doneq_index = index_stripped ? +- index_stripped : +- ((index_stripped | 0x4000) + 1); +- } ++ toggle = doneq_index & 0x4000; ++ index_stripped = (doneq_index & 0xFFF) + 1; ++ index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; ++ pmu->doneq_index = index_stripped ? (index_stripped | toggle) : ++ ((toggle ^ 0x4000) + 1); + doneq_index = pmu->doneq_index; ++ spin_unlock_irqrestore(&acb->doneq_lock, flags); + addressLow = pmu->done_qbuffer[doneq_index & + 0xFFF].addressLow; + ccb_cdb_phy = (addressLow & 0xFFFFFFF0); +@@ -1223,11 +1209,10 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) + arcmsr_drain_donequeue(acb, pCCB, error); + writel(doneq_index, + pmu->outboundlist_read_pointer); ++ } else { ++ spin_unlock_irqrestore(&acb->doneq_lock, flags); ++ mdelay(10); + } +- mdelay(10); +- outbound_write_pointer = +- pmu->done_qbuffer[0].addressLow + 1; +- doneq_index = pmu->doneq_index; + } + pmu->postq_index = 0; + pmu->doneq_index = 0x40FF; +@@ -1460,7 +1445,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr + case ACB_ADAPTER_TYPE_D: { + struct MessageUnit_D *pmu = acb->pmuD; + u16 index_stripped; +- u16 postq_index; ++ u16 postq_index, toggle; + unsigned long flags; + struct InBound_SRB *pinbound_srb; + +@@ -1471,19 +1456,11 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr + pinbound_srb->addressLow = dma_addr_lo32(cdb_phyaddr); + pinbound_srb->length = ccb->arc_cdb_size >> 2; + arcmsr_cdb->msgContext = dma_addr_lo32(cdb_phyaddr); +- if (postq_index & 0x4000) { +- index_stripped = postq_index & 0xFF; +- index_stripped += 1; +- index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE; +- pmu->postq_index = index_stripped ? +- (index_stripped | 0x4000) : index_stripped; +- } else { +- index_stripped = postq_index; +- index_stripped += 1; +- index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE; +- pmu->postq_index = index_stripped ? index_stripped : +- (index_stripped | 0x4000); +- } ++ toggle = postq_index & 0x4000; ++ index_stripped = postq_index + 1; ++ index_stripped &= (ARCMSR_MAX_ARC1214_POSTQUEUE - 1); ++ pmu->postq_index = index_stripped ? (index_stripped | toggle) : ++ (toggle ^ 0x4000); + writel(postq_index, pmu->inboundlist_write_pointer); + spin_unlock_irqrestore(&acb->postq_lock, flags); + break; +@@ -1999,7 +1976,7 @@ static void arcmsr_hbaC_postqueue_isr(struct AdapterControlBlock *acb) + + static void arcmsr_hbaD_postqueue_isr(struct AdapterControlBlock *acb) + { +- u32 outbound_write_pointer, doneq_index, index_stripped; ++ u32 outbound_write_pointer, doneq_index, index_stripped, toggle; + uint32_t addressLow, ccb_cdb_phy; + int error; + struct MessageUnit_D *pmu; +@@ -2013,21 +1990,11 @@ static void arcmsr_hbaD_postqueue_isr(struct AdapterControlBlock *acb) + doneq_index = pmu->doneq_index; + if ((doneq_index & 0xFFF) != (outbound_write_pointer & 0xFFF)) { + do { +- if (doneq_index & 0x4000) { +- index_stripped = doneq_index & 0xFFF; +- index_stripped += 1; +- index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; +- pmu->doneq_index = index_stripped +- ? (index_stripped | 0x4000) : +- (index_stripped + 1); +- } else { +- index_stripped = doneq_index; +- index_stripped += 1; +- index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; +- pmu->doneq_index = index_stripped +- ? index_stripped : +- ((index_stripped | 0x4000) + 1); +- } ++ toggle = doneq_index & 0x4000; ++ index_stripped = (doneq_index & 0xFFF) + 1; ++ index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; ++ pmu->doneq_index = index_stripped ? (index_stripped | toggle) : ++ ((toggle ^ 0x4000) + 1); + doneq_index = pmu->doneq_index; + addressLow = pmu->done_qbuffer[doneq_index & + 0xFFF].addressLow; +@@ -2890,7 +2857,7 @@ static bool arcmsr_hbaD_get_config(struct AdapterControlBlock *acb) + char __iomem *iop_firm_version; + char __iomem *iop_device_map; + u32 count; +- struct MessageUnit_D *reg ; ++ struct MessageUnit_D *reg; + void *dma_coherent2; + dma_addr_t dma_coherent_handle2; + struct pci_dev *pdev = acb->pdev; +@@ -3223,7 +3190,7 @@ static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb, + { + bool error; + uint32_t poll_ccb_done = 0, poll_count = 0, flag_ccb, ccb_cdb_phy; +- int rtn, doneq_index, index_stripped, outbound_write_pointer; ++ int rtn, doneq_index, index_stripped, outbound_write_pointer, toggle; + unsigned long flags; + struct ARCMSR_CDB *arcmsr_cdb; + struct CommandControlBlock *pCCB; +@@ -3232,9 +3199,11 @@ static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb, + polling_hbaD_ccb_retry: + poll_count++; + while (1) { ++ spin_lock_irqsave(&acb->doneq_lock, flags); + outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1; + doneq_index = pmu->doneq_index; + if ((outbound_write_pointer & 0xFFF) == (doneq_index & 0xFFF)) { ++ spin_unlock_irqrestore(&acb->doneq_lock, flags); + if (poll_ccb_done) { + rtn = SUCCESS; + break; +@@ -3247,23 +3216,13 @@ polling_hbaD_ccb_retry: + goto polling_hbaD_ccb_retry; + } + } +- spin_lock_irqsave(&acb->doneq_lock, flags); +- if (doneq_index & 0x4000) { +- index_stripped = doneq_index & 0xFFF; +- index_stripped += 1; +- index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; +- pmu->doneq_index = index_stripped ? +- (index_stripped | 0x4000) : +- (index_stripped + 1); +- } else { +- index_stripped = doneq_index; +- index_stripped += 1; +- index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; +- pmu->doneq_index = index_stripped ? index_stripped : +- ((index_stripped | 0x4000) + 1); +- } +- spin_unlock_irqrestore(&acb->doneq_lock, flags); ++ toggle = doneq_index & 0x4000; ++ index_stripped = (doneq_index & 0xFFF) + 1; ++ index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; ++ pmu->doneq_index = index_stripped ? (index_stripped | toggle) : ++ ((toggle ^ 0x4000) + 1); + doneq_index = pmu->doneq_index; ++ spin_unlock_irqrestore(&acb->doneq_lock, flags); + flag_ccb = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow; + ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0); + arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + diff --git a/debian/patches/features/all/arcmsr/0019-arcmsr-simplify-ioctl-data-read-write.patch b/debian/patches/features/all/arcmsr/0019-arcmsr-simplify-ioctl-data-read-write.patch new file mode 100644 index 000000000..bbc0834ff --- /dev/null +++ b/debian/patches/features/all/arcmsr/0019-arcmsr-simplify-ioctl-data-read-write.patch @@ -0,0 +1,606 @@ +From: Ching Huang +Date: Wed, 24 Sep 2014 17:33:34 +0800 +Subject: [19/19] arcmsr: simplify ioctl data read/write +Origin: https://git.kernel.org/linus/2e9feb434a66311f30bde2430a5609e9e24df62b +Bug-Debian: https://bugs.debian.org/698821 + +Signed-off-by: Ching Huang +Reviewed-by: Tomas Henzl +Signed-off-by: Christoph Hellwig +--- + drivers/scsi/arcmsr/arcmsr.h | 13 +-- + drivers/scsi/arcmsr/arcmsr_attr.c | 127 ++++++++--------------- + drivers/scsi/arcmsr/arcmsr_hba.c | 208 +++++++++++++------------------------- + 3 files changed, 119 insertions(+), 229 deletions(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h +index d1c78ef..3bcaaac 100644 +--- a/drivers/scsi/arcmsr/arcmsr.h ++++ b/drivers/scsi/arcmsr/arcmsr.h +@@ -52,7 +52,7 @@ struct device_attribute; + #define ARCMSR_MAX_FREECCB_NUM 320 + #define ARCMSR_MAX_OUTSTANDING_CMD 255 + #endif +-#define ARCMSR_DRIVER_VERSION "v1.30.00.04-20140428" ++#define ARCMSR_DRIVER_VERSION "v1.30.00.04-20140919" + #define ARCMSR_SCSI_INITIATOR_ID 255 + #define ARCMSR_MAX_XFER_SECTORS 512 + #define ARCMSR_MAX_XFER_SECTORS_B 4096 +@@ -107,10 +107,11 @@ struct CMD_MESSAGE + ** IOP Message Transfer Data for user space + ******************************************************************************* + */ ++#define ARCMSR_API_DATA_BUFLEN 1032 + struct CMD_MESSAGE_FIELD + { + struct CMD_MESSAGE cmdmessage; +- uint8_t messagedatabuffer[1032]; ++ uint8_t messagedatabuffer[ARCMSR_API_DATA_BUFLEN]; + }; + /* IOP message transfer */ + #define ARCMSR_MESSAGE_FAIL 0x0001 +@@ -678,15 +679,15 @@ struct AdapterControlBlock + unsigned int uncache_size; + uint8_t rqbuffer[ARCMSR_MAX_QBUFFER]; + /* data collection buffer for read from 80331 */ +- int32_t rqbuf_firstindex; ++ int32_t rqbuf_getIndex; + /* first of read buffer */ +- int32_t rqbuf_lastindex; ++ int32_t rqbuf_putIndex; + /* last of read buffer */ + uint8_t wqbuffer[ARCMSR_MAX_QBUFFER]; + /* data collection buffer for write to 80331 */ +- int32_t wqbuf_firstindex; ++ int32_t wqbuf_getIndex; + /* first of write buffer */ +- int32_t wqbuf_lastindex; ++ int32_t wqbuf_putIndex; + /* last of write buffer */ + uint8_t devstate[ARCMSR_MAX_TARGETID][ARCMSR_MAX_TARGETLUN]; + /* id0 ..... id15, lun0...lun7 */ +diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c +index 16422ad..9c86481 100644 +--- a/drivers/scsi/arcmsr/arcmsr_attr.c ++++ b/drivers/scsi/arcmsr/arcmsr_attr.c +@@ -50,6 +50,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -68,7 +69,7 @@ static ssize_t arcmsr_sysfs_iop_message_read(struct file *filp, + struct device *dev = container_of(kobj,struct device,kobj); + struct Scsi_Host *host = class_to_shost(dev); + struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; +- uint8_t *pQbuffer,*ptmpQbuffer; ++ uint8_t *ptmpQbuffer; + int32_t allxfer_len = 0; + unsigned long flags; + +@@ -78,57 +79,22 @@ static ssize_t arcmsr_sysfs_iop_message_read(struct file *filp, + /* do message unit read. */ + ptmpQbuffer = (uint8_t *)buf; + spin_lock_irqsave(&acb->rqbuffer_lock, flags); +- if (acb->rqbuf_firstindex != acb->rqbuf_lastindex) { +- pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; +- if (acb->rqbuf_firstindex > acb->rqbuf_lastindex) { +- if ((ARCMSR_MAX_QBUFFER - acb->rqbuf_firstindex) >= 1032) { +- memcpy(ptmpQbuffer, pQbuffer, 1032); +- acb->rqbuf_firstindex += 1032; +- acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; +- allxfer_len = 1032; +- } else { +- if (((ARCMSR_MAX_QBUFFER - acb->rqbuf_firstindex) +- + acb->rqbuf_lastindex) > 1032) { +- memcpy(ptmpQbuffer, pQbuffer, +- ARCMSR_MAX_QBUFFER +- - acb->rqbuf_firstindex); +- ptmpQbuffer += ARCMSR_MAX_QBUFFER +- - acb->rqbuf_firstindex; +- memcpy(ptmpQbuffer, acb->rqbuffer, 1032 +- - (ARCMSR_MAX_QBUFFER - +- acb->rqbuf_firstindex)); +- acb->rqbuf_firstindex = 1032 - +- (ARCMSR_MAX_QBUFFER - +- acb->rqbuf_firstindex); +- allxfer_len = 1032; +- } else { +- memcpy(ptmpQbuffer, pQbuffer, +- ARCMSR_MAX_QBUFFER - +- acb->rqbuf_firstindex); +- ptmpQbuffer += ARCMSR_MAX_QBUFFER - +- acb->rqbuf_firstindex; +- memcpy(ptmpQbuffer, acb->rqbuffer, +- acb->rqbuf_lastindex); +- allxfer_len = ARCMSR_MAX_QBUFFER - +- acb->rqbuf_firstindex + +- acb->rqbuf_lastindex; +- acb->rqbuf_firstindex = +- acb->rqbuf_lastindex; +- } +- } +- } else { +- if ((acb->rqbuf_lastindex - acb->rqbuf_firstindex) > 1032) { +- memcpy(ptmpQbuffer, pQbuffer, 1032); +- acb->rqbuf_firstindex += 1032; +- allxfer_len = 1032; +- } else { +- memcpy(ptmpQbuffer, pQbuffer, acb->rqbuf_lastindex +- - acb->rqbuf_firstindex); +- allxfer_len = acb->rqbuf_lastindex - +- acb->rqbuf_firstindex; +- acb->rqbuf_firstindex = acb->rqbuf_lastindex; +- } ++ if (acb->rqbuf_getIndex != acb->rqbuf_putIndex) { ++ unsigned int tail = acb->rqbuf_getIndex; ++ unsigned int head = acb->rqbuf_putIndex; ++ unsigned int cnt_to_end = CIRC_CNT_TO_END(head, tail, ARCMSR_MAX_QBUFFER); ++ ++ allxfer_len = CIRC_CNT(head, tail, ARCMSR_MAX_QBUFFER); ++ if (allxfer_len > ARCMSR_API_DATA_BUFLEN) ++ allxfer_len = ARCMSR_API_DATA_BUFLEN; ++ ++ if (allxfer_len <= cnt_to_end) ++ memcpy(ptmpQbuffer, acb->rqbuffer + tail, allxfer_len); ++ else { ++ memcpy(ptmpQbuffer, acb->rqbuffer + tail, cnt_to_end); ++ memcpy(ptmpQbuffer + cnt_to_end, acb->rqbuffer, allxfer_len - cnt_to_end); + } ++ acb->rqbuf_getIndex = (acb->rqbuf_getIndex + allxfer_len) % ARCMSR_MAX_QBUFFER; + } + if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { + struct QBUFFER __iomem *prbuffer; +@@ -150,47 +116,42 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp, + struct device *dev = container_of(kobj,struct device,kobj); + struct Scsi_Host *host = class_to_shost(dev); + struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; +- int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; ++ int32_t user_len, cnt2end; + uint8_t *pQbuffer, *ptmpuserbuffer; + unsigned long flags; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; +- if (count > 1032) ++ if (count > ARCMSR_API_DATA_BUFLEN) + return -EINVAL; + /* do message unit write. */ + ptmpuserbuffer = (uint8_t *)buf; + user_len = (int32_t)count; + spin_lock_irqsave(&acb->wqbuffer_lock, flags); +- wqbuf_lastindex = acb->wqbuf_lastindex; +- wqbuf_firstindex = acb->wqbuf_firstindex; +- if (wqbuf_lastindex != wqbuf_firstindex) { ++ if (acb->wqbuf_putIndex != acb->wqbuf_getIndex) { + arcmsr_write_ioctldata2iop(acb); + spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); + return 0; /*need retry*/ + } else { +- my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) +- &(ARCMSR_MAX_QBUFFER - 1); +- if (my_empty_len >= user_len) { +- while (user_len > 0) { +- pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; +- memcpy(pQbuffer, ptmpuserbuffer, 1); +- acb->wqbuf_lastindex++; +- acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; +- ptmpuserbuffer++; +- user_len--; +- } +- if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { +- acb->acb_flags &= +- ~ACB_F_MESSAGE_WQBUFFER_CLEARED; +- arcmsr_write_ioctldata2iop(acb); +- } +- spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); +- return count; +- } else { +- spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); +- return 0; /*need retry*/ ++ pQbuffer = &acb->wqbuffer[acb->wqbuf_putIndex]; ++ cnt2end = ARCMSR_MAX_QBUFFER - acb->wqbuf_putIndex; ++ if (user_len > cnt2end) { ++ memcpy(pQbuffer, ptmpuserbuffer, cnt2end); ++ ptmpuserbuffer += cnt2end; ++ user_len -= cnt2end; ++ acb->wqbuf_putIndex = 0; ++ pQbuffer = acb->wqbuffer; + } ++ memcpy(pQbuffer, ptmpuserbuffer, user_len); ++ acb->wqbuf_putIndex += user_len; ++ acb->wqbuf_putIndex %= ARCMSR_MAX_QBUFFER; ++ if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { ++ acb->acb_flags &= ++ ~ACB_F_MESSAGE_WQBUFFER_CLEARED; ++ arcmsr_write_ioctldata2iop(acb); ++ } ++ spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); ++ return count; + } + } + +@@ -215,12 +176,12 @@ static ssize_t arcmsr_sysfs_iop_message_clear(struct file *filp, + | ACB_F_MESSAGE_RQBUFFER_CLEARED + | ACB_F_MESSAGE_WQBUFFER_READED); + spin_lock_irqsave(&acb->rqbuffer_lock, flags); +- acb->rqbuf_firstindex = 0; +- acb->rqbuf_lastindex = 0; ++ acb->rqbuf_getIndex = 0; ++ acb->rqbuf_putIndex = 0; + spin_unlock_irqrestore(&acb->rqbuffer_lock, flags); + spin_lock_irqsave(&acb->wqbuffer_lock, flags); +- acb->wqbuf_firstindex = 0; +- acb->wqbuf_lastindex = 0; ++ acb->wqbuf_getIndex = 0; ++ acb->wqbuf_putIndex = 0; + spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); + pQbuffer = acb->rqbuffer; + memset(pQbuffer, 0, sizeof (struct QBUFFER)); +@@ -234,7 +195,7 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = { + .name = "mu_read", + .mode = S_IRUSR , + }, +- .size = 1032, ++ .size = ARCMSR_API_DATA_BUFLEN, + .read = arcmsr_sysfs_iop_message_read, + }; + +@@ -243,7 +204,7 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = { + .name = "mu_write", + .mode = S_IWUSR, + }, +- .size = 1032, ++ .size = ARCMSR_API_DATA_BUFLEN, + .write = arcmsr_sysfs_iop_message_write, + }; + +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index 0dd38cc..0b44fb5 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -58,6 +58,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1701,16 +1702,15 @@ arcmsr_Read_iop_rqbuffer_in_DWORD(struct AdapterControlBlock *acb, + buf2 = (uint32_t *)buf1; + } + while (iop_len > 0) { +- pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; ++ pQbuffer = &acb->rqbuffer[acb->rqbuf_putIndex]; + *pQbuffer = *buf1; +- acb->rqbuf_lastindex++; ++ acb->rqbuf_putIndex++; + /* if last, index number set it to 0 */ +- acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; ++ acb->rqbuf_putIndex %= ARCMSR_MAX_QBUFFER; + buf1++; + iop_len--; + } +- if (buf2) +- kfree(buf2); ++ kfree(buf2); + /* let IOP know data has been read */ + arcmsr_iop_message_read(acb); + return 1; +@@ -1729,10 +1729,10 @@ arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, + iop_data = (uint8_t __iomem *)prbuffer->data; + iop_len = readl(&prbuffer->data_len); + while (iop_len > 0) { +- pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; ++ pQbuffer = &acb->rqbuffer[acb->rqbuf_putIndex]; + *pQbuffer = readb(iop_data); +- acb->rqbuf_lastindex++; +- acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; ++ acb->rqbuf_putIndex++; ++ acb->rqbuf_putIndex %= ARCMSR_MAX_QBUFFER; + iop_data++; + iop_len--; + } +@@ -1748,7 +1748,7 @@ static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) + + spin_lock_irqsave(&acb->rqbuffer_lock, flags); + prbuffer = arcmsr_get_iop_rqbuffer(acb); +- buf_empty_len = (acb->rqbuf_lastindex - acb->rqbuf_firstindex - 1) & ++ buf_empty_len = (acb->rqbuf_putIndex - acb->rqbuf_getIndex - 1) & + (ARCMSR_MAX_QBUFFER - 1); + if (buf_empty_len >= readl(&prbuffer->data_len)) { + if (arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) +@@ -1775,12 +1775,12 @@ static void arcmsr_write_ioctldata2iop_in_DWORD(struct AdapterControlBlock *acb) + acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); + pwbuffer = arcmsr_get_iop_wqbuffer(acb); + iop_data = (uint32_t __iomem *)pwbuffer->data; +- while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) ++ while ((acb->wqbuf_getIndex != acb->wqbuf_putIndex) + && (allxfer_len < 124)) { +- pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; ++ pQbuffer = &acb->wqbuffer[acb->wqbuf_getIndex]; + *buf1 = *pQbuffer; +- acb->wqbuf_firstindex++; +- acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; ++ acb->wqbuf_getIndex++; ++ acb->wqbuf_getIndex %= ARCMSR_MAX_QBUFFER; + buf1++; + allxfer_len++; + } +@@ -1818,12 +1818,12 @@ arcmsr_write_ioctldata2iop(struct AdapterControlBlock *acb) + acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); + pwbuffer = arcmsr_get_iop_wqbuffer(acb); + iop_data = (uint8_t __iomem *)pwbuffer->data; +- while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) ++ while ((acb->wqbuf_getIndex != acb->wqbuf_putIndex) + && (allxfer_len < 124)) { +- pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; ++ pQbuffer = &acb->wqbuffer[acb->wqbuf_getIndex]; + writeb(*pQbuffer, iop_data); +- acb->wqbuf_firstindex++; +- acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; ++ acb->wqbuf_getIndex++; ++ acb->wqbuf_getIndex %= ARCMSR_MAX_QBUFFER; + iop_data++; + allxfer_len++; + } +@@ -1838,9 +1838,9 @@ static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) + + spin_lock_irqsave(&acb->wqbuffer_lock, flags); + acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; +- if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) ++ if (acb->wqbuf_getIndex != acb->wqbuf_putIndex) + arcmsr_write_ioctldata2iop(acb); +- if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) ++ if (acb->wqbuf_getIndex == acb->wqbuf_putIndex) + acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; + spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); + } +@@ -2210,14 +2210,14 @@ void arcmsr_clear_iop2drv_rqueue_buffer(struct AdapterControlBlock *acb) + for (i = 0; i < 15; i++) { + if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { + acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; +- acb->rqbuf_firstindex = 0; +- acb->rqbuf_lastindex = 0; ++ acb->rqbuf_getIndex = 0; ++ acb->rqbuf_putIndex = 0; + arcmsr_iop_message_read(acb); + mdelay(30); +- } else if (acb->rqbuf_firstindex != +- acb->rqbuf_lastindex) { +- acb->rqbuf_firstindex = 0; +- acb->rqbuf_lastindex = 0; ++ } else if (acb->rqbuf_getIndex != ++ acb->rqbuf_putIndex) { ++ acb->rqbuf_getIndex = 0; ++ acb->rqbuf_putIndex = 0; + mdelay(30); + } else + break; +@@ -2256,9 +2256,9 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, + switch (controlcode) { + case ARCMSR_MESSAGE_READ_RQBUFFER: { + unsigned char *ver_addr; +- uint8_t *pQbuffer, *ptmpQbuffer; ++ uint8_t *ptmpQbuffer; + uint32_t allxfer_len = 0; +- ver_addr = kmalloc(1032, GFP_ATOMIC); ++ ver_addr = kmalloc(ARCMSR_API_DATA_BUFLEN, GFP_ATOMIC); + if (!ver_addr) { + retvalue = ARCMSR_MESSAGE_FAIL; + pr_info("%s: memory not enough!\n", __func__); +@@ -2266,66 +2266,22 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, + } + ptmpQbuffer = ver_addr; + spin_lock_irqsave(&acb->rqbuffer_lock, flags); +- if (acb->rqbuf_firstindex != acb->rqbuf_lastindex) { +- pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; +- if (acb->rqbuf_firstindex > acb->rqbuf_lastindex) { +- if ((ARCMSR_MAX_QBUFFER - +- acb->rqbuf_firstindex) >= 1032) { +- memcpy(ptmpQbuffer, pQbuffer, 1032); +- acb->rqbuf_firstindex += 1032; +- acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; +- allxfer_len = 1032; +- } else { +- if (((ARCMSR_MAX_QBUFFER - +- acb->rqbuf_firstindex) + +- acb->rqbuf_lastindex) > 1032) { +- memcpy(ptmpQbuffer, +- pQbuffer, ARCMSR_MAX_QBUFFER +- - acb->rqbuf_firstindex); +- ptmpQbuffer += +- ARCMSR_MAX_QBUFFER - +- acb->rqbuf_firstindex; +- memcpy(ptmpQbuffer, +- acb->rqbuffer, 1032 - +- (ARCMSR_MAX_QBUFFER +- - acb->rqbuf_firstindex)); +- acb->rqbuf_firstindex = +- 1032 - (ARCMSR_MAX_QBUFFER +- - acb->rqbuf_firstindex); +- allxfer_len = 1032; +- } else { +- memcpy(ptmpQbuffer, +- pQbuffer, ARCMSR_MAX_QBUFFER +- - acb->rqbuf_firstindex); +- ptmpQbuffer += +- ARCMSR_MAX_QBUFFER - +- acb->rqbuf_firstindex; +- memcpy(ptmpQbuffer, +- acb->rqbuffer, +- acb->rqbuf_lastindex); +- allxfer_len = ARCMSR_MAX_QBUFFER +- - acb->rqbuf_firstindex + +- acb->rqbuf_lastindex; +- acb->rqbuf_firstindex = +- acb->rqbuf_lastindex; +- } +- } +- } else { +- if ((acb->rqbuf_lastindex - +- acb->rqbuf_firstindex) > 1032) { +- memcpy(ptmpQbuffer, pQbuffer, 1032); +- acb->rqbuf_firstindex += 1032; +- allxfer_len = 1032; +- } else { +- memcpy(ptmpQbuffer, pQbuffer, +- acb->rqbuf_lastindex - +- acb->rqbuf_firstindex); +- allxfer_len = acb->rqbuf_lastindex +- - acb->rqbuf_firstindex; +- acb->rqbuf_firstindex = +- acb->rqbuf_lastindex; +- } ++ if (acb->rqbuf_getIndex != acb->rqbuf_putIndex) { ++ unsigned int tail = acb->rqbuf_getIndex; ++ unsigned int head = acb->rqbuf_putIndex; ++ unsigned int cnt_to_end = CIRC_CNT_TO_END(head, tail, ARCMSR_MAX_QBUFFER); ++ ++ allxfer_len = CIRC_CNT(head, tail, ARCMSR_MAX_QBUFFER); ++ if (allxfer_len > ARCMSR_API_DATA_BUFLEN) ++ allxfer_len = ARCMSR_API_DATA_BUFLEN; ++ ++ if (allxfer_len <= cnt_to_end) ++ memcpy(ptmpQbuffer, acb->rqbuffer + tail, allxfer_len); ++ else { ++ memcpy(ptmpQbuffer, acb->rqbuffer + tail, cnt_to_end); ++ memcpy(ptmpQbuffer + cnt_to_end, acb->rqbuffer, allxfer_len - cnt_to_end); + } ++ acb->rqbuf_getIndex = (acb->rqbuf_getIndex + allxfer_len) % ARCMSR_MAX_QBUFFER; + } + memcpy(pcmdmessagefld->messagedatabuffer, ver_addr, + allxfer_len); +@@ -2349,9 +2305,9 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, + } + case ARCMSR_MESSAGE_WRITE_WQBUFFER: { + unsigned char *ver_addr; +- int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; ++ int32_t user_len, cnt2end; + uint8_t *pQbuffer, *ptmpuserbuffer; +- ver_addr = kmalloc(1032, GFP_ATOMIC); ++ ver_addr = kmalloc(ARCMSR_API_DATA_BUFLEN, GFP_ATOMIC); + if (!ver_addr) { + retvalue = ARCMSR_MESSAGE_FAIL; + goto message_out; +@@ -2361,9 +2317,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, + memcpy(ptmpuserbuffer, + pcmdmessagefld->messagedatabuffer, user_len); + spin_lock_irqsave(&acb->wqbuffer_lock, flags); +- wqbuf_lastindex = acb->wqbuf_lastindex; +- wqbuf_firstindex = acb->wqbuf_firstindex; +- if (wqbuf_lastindex != wqbuf_firstindex) { ++ if (acb->wqbuf_putIndex != acb->wqbuf_getIndex) { + struct SENSE_DATA *sensebuffer = + (struct SENSE_DATA *)cmd->sense_buffer; + arcmsr_write_ioctldata2iop(acb); +@@ -2375,48 +2329,22 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, + sensebuffer->Valid = 1; + retvalue = ARCMSR_MESSAGE_FAIL; + } else { +- my_empty_len = (wqbuf_firstindex - wqbuf_lastindex - 1) +- & (ARCMSR_MAX_QBUFFER - 1); +- if (my_empty_len >= user_len) { +- while (user_len > 0) { +- pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; +- if ((acb->wqbuf_lastindex + user_len) +- > ARCMSR_MAX_QBUFFER) { +- memcpy(pQbuffer, ptmpuserbuffer, +- ARCMSR_MAX_QBUFFER - +- acb->wqbuf_lastindex); +- ptmpuserbuffer += +- (ARCMSR_MAX_QBUFFER +- - acb->wqbuf_lastindex); +- user_len -= (ARCMSR_MAX_QBUFFER +- - acb->wqbuf_lastindex); +- acb->wqbuf_lastindex = 0; +- } else { +- memcpy(pQbuffer, ptmpuserbuffer, +- user_len); +- acb->wqbuf_lastindex += user_len; +- acb->wqbuf_lastindex %= +- ARCMSR_MAX_QBUFFER; +- user_len = 0; +- } +- } +- if (acb->acb_flags & +- ACB_F_MESSAGE_WQBUFFER_CLEARED) { +- acb->acb_flags &= ++ pQbuffer = &acb->wqbuffer[acb->wqbuf_putIndex]; ++ cnt2end = ARCMSR_MAX_QBUFFER - acb->wqbuf_putIndex; ++ if (user_len > cnt2end) { ++ memcpy(pQbuffer, ptmpuserbuffer, cnt2end); ++ ptmpuserbuffer += cnt2end; ++ user_len -= cnt2end; ++ acb->wqbuf_putIndex = 0; ++ pQbuffer = acb->wqbuffer; ++ } ++ memcpy(pQbuffer, ptmpuserbuffer, user_len); ++ acb->wqbuf_putIndex += user_len; ++ acb->wqbuf_putIndex %= ARCMSR_MAX_QBUFFER; ++ if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { ++ acb->acb_flags &= + ~ACB_F_MESSAGE_WQBUFFER_CLEARED; +- arcmsr_write_ioctldata2iop(acb); +- } +- } else { +- struct SENSE_DATA *sensebuffer = +- (struct SENSE_DATA *)cmd->sense_buffer; +- /* has error report sensedata */ +- sensebuffer->ErrorCode = +- SCSI_SENSE_CURRENT_ERRORS; +- sensebuffer->SenseKey = ILLEGAL_REQUEST; +- sensebuffer->AdditionalSenseLength = 0x0A; +- sensebuffer->AdditionalSenseCode = 0x20; +- sensebuffer->Valid = 1; +- retvalue = ARCMSR_MESSAGE_FAIL; ++ arcmsr_write_ioctldata2iop(acb); + } + } + spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); +@@ -2435,8 +2363,8 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, + arcmsr_clear_iop2drv_rqueue_buffer(acb); + spin_lock_irqsave(&acb->rqbuffer_lock, flags); + acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; +- acb->rqbuf_firstindex = 0; +- acb->rqbuf_lastindex = 0; ++ acb->rqbuf_getIndex = 0; ++ acb->rqbuf_putIndex = 0; + memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); + spin_unlock_irqrestore(&acb->rqbuffer_lock, flags); + if (acb->fw_flag == FW_DEADLOCK) +@@ -2452,8 +2380,8 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, + spin_lock_irqsave(&acb->wqbuffer_lock, flags); + acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | + ACB_F_MESSAGE_WQBUFFER_READED); +- acb->wqbuf_firstindex = 0; +- acb->wqbuf_lastindex = 0; ++ acb->wqbuf_getIndex = 0; ++ acb->wqbuf_putIndex = 0; + memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); + spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); + if (acb->fw_flag == FW_DEADLOCK) +@@ -2469,16 +2397,16 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, + arcmsr_clear_iop2drv_rqueue_buffer(acb); + spin_lock_irqsave(&acb->rqbuffer_lock, flags); + acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; +- acb->rqbuf_firstindex = 0; +- acb->rqbuf_lastindex = 0; ++ acb->rqbuf_getIndex = 0; ++ acb->rqbuf_putIndex = 0; + pQbuffer = acb->rqbuffer; + memset(pQbuffer, 0, sizeof(struct QBUFFER)); + spin_unlock_irqrestore(&acb->rqbuffer_lock, flags); + spin_lock_irqsave(&acb->wqbuffer_lock, flags); + acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | + ACB_F_MESSAGE_WQBUFFER_READED); +- acb->wqbuf_firstindex = 0; +- acb->wqbuf_lastindex = 0; ++ acb->wqbuf_getIndex = 0; ++ acb->wqbuf_putIndex = 0; + pQbuffer = acb->wqbuffer; + memset(pQbuffer, 0, sizeof(struct QBUFFER)); + spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); diff --git a/debian/patches/series b/debian/patches/series index d60fc6369..db81fcf0a 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -521,3 +521,22 @@ bugfix/x86/acpi-video-add-disable_native_backlight-quirk-for-dell-xps15.patch bugfix/x86/acpi-video-add-disable_native_backlight-quirk-for-samsung-730u3e-740u3e.patch bugfix/x86/acpi-video-add-disable_native_backlight-quirk-for-samsung-510r.patch bugfix/x86/acpi-video-disable-native-backlight-on-samsung-series-9.patch +features/all/arcmsr/0001-arcmsr-fix-command-timeout-under-heavy-load.patch +features/all/arcmsr/0002-arcmsr-add-code-to-support-msi-x-and-msi-interrupt.patch +features/all/arcmsr/0003-arcmsr-add-code-to-support-hibernation.patch +features/all/arcmsr/0004-arcmsr-limit-max.-number-of-scsi-command-request.patch +features/all/arcmsr/0005-arcmsr-return-status-of-abort-command.patch +features/all/arcmsr/0006-arcmsr-store-adapter-type-in-pci-id-table.patch +features/all/arcmsr/0007-arcmsr-revise-message_isr_bh_fn-to-remove-duplicate-.patch +features/all/arcmsr/0008-arcmsr-remove-calling-arcmsr_hbb_enable_driver_mode.patch +features/all/arcmsr/0009-arcmsr-modify-printing-adapter-model-number-and-f-w-.patch +features/all/arcmsr/0010-arcmsr-clear-outbound-doorbell-buffer-completely.patch +features/all/arcmsr/0011-arcmsr-rename-functions-and-variables.patch +features/all/arcmsr/0012-arcmsr-revise-allocation-of-second-dma_coherent_hand.patch +features/all/arcmsr/0013-arcmsr-fix-ioctl-data-read-write-error-for-adapter-t.patch +features/all/arcmsr/0014-arcmsr-fix-sparse-warnings-and-errors.patch +features/all/arcmsr/0015-arcmsr-modify-some-character-strings.patch +features/all/arcmsr/0016-arcmsr-add-support-new-adapter-arc12x4-series.patch +features/all/arcmsr/0017-arcmsr-call-scsi_scan_host-at-the-end-of-host-initia.patch +features/all/arcmsr/0018-arcmsr-simplify-of-updating-doneq_index-and-postq_in.patch +features/all/arcmsr/0019-arcmsr-simplify-ioctl-data-read-write.patch