RE: [PATCH 2/5] arcmsr: Support Hibernation
Please ignore the last mails with checkpatch file. Thanks, -Original Message- From: NickCheng [mailto:nick.ch...@areca.com.tw] Sent: Friday, February 08, 2013 2:03 PM To: 'linux-s...@vger.kernel.org' Cc: 'linux-kernel@vger.kernel.org'; 'j...@kernel.org'; 黃清隆 Subject: [PATCH 2/5] arcmsr: Support Hibernation From: Nick Cheng Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng --- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 5/5] arcmsr: Modify ARC-1214 Inband Messages Behavior
From: Nick Cheng Modify ARC-1214 inband messages behavior to make up for HW seldom malfunction. Signed-off-by: Nick Cheng --- patch5 Description: Binary data
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng --- patch2 Description: Binary data
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng --- patch3 Description: Binary data
[PATCH 4/5] arcmsr: Support a New RAID Model, ARC-1214
From: Nick Cheng Add a New RAID Model, ARC-1214, which can support 8 SATA HDs at most, so far. Signed-off-by: Nick Cheng --- checkpatch4 Description: Binary data
[PATCH 5/5] arcmsr: Modify ARC-1214 Inband Messages Behavior
From: Nick Cheng Modify ARC-1214 inband messages behavior to make up for HW seldom malfunction. Signed-off-by: Nick Cheng --- checkpatch5 Description: Binary data
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng --- checkpatch3 Description: Binary data
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng --- checkpatch2 Description: Binary data
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng nick.ch...@areca.com.tw Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- checkpatch2 Description: Binary data
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng nick.ch...@areca.com.tw Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- checkpatch3 Description: Binary data
[PATCH 5/5] arcmsr: Modify ARC-1214 Inband Messages Behavior
From: Nick Cheng nick.ch...@areca.com.tw Modify ARC-1214 inband messages behavior to make up for HW seldom malfunction. Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- checkpatch5 Description: Binary data
[PATCH 4/5] arcmsr: Support a New RAID Model, ARC-1214
From: Nick Cheng nick.ch...@areca.com.tw Add a New RAID Model, ARC-1214, which can support 8 SATA HDs at most, so far. Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- checkpatch4 Description: Binary data
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng nick.ch...@areca.com.tw Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- patch2 Description: Binary data
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng nick.ch...@areca.com.tw Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- patch3 Description: Binary data
[PATCH 5/5] arcmsr: Modify ARC-1214 Inband Messages Behavior
From: Nick Cheng nick.ch...@areca.com.tw Modify ARC-1214 inband messages behavior to make up for HW seldom malfunction. Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- patch5 Description: Binary data
RE: [PATCH 2/5] arcmsr: Support Hibernation
Please ignore the last mails with checkpatch file. Thanks, -Original Message- From: NickCheng [mailto:nick.ch...@areca.com.tw] Sent: Friday, February 08, 2013 2:03 PM To: 'linux-s...@vger.kernel.org' Cc: 'linux-kernel@vger.kernel.org'; 'j...@kernel.org'; 黃清隆 Subject: [PATCH 2/5] arcmsr: Support Hibernation From: Nick Cheng nick.ch...@areca.com.tw Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 5/5] arcmsr: Modify ARC-1214 Inband Messages Behavior
From: Nick Cheng Modify ARC-1214 inband messages behavior to make up for HW seldom malfunction. Signed-off-by: Nick Cheng --- patch5 Description: Binary data
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng --- patch2 Description: Binary data
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng --- patch3 Description: Binary data
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng nick.ch...@areca.com.tw Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- patch2 Description: Binary data
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng nick.ch...@areca.com.tw Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- patch3 Description: Binary data
[PATCH 5/5] arcmsr: Modify ARC-1214 Inband Messages Behavior
From: Nick Cheng nick.ch...@areca.com.tw Modify ARC-1214 inband messages behavior to make up for HW seldom malfunction. Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- patch5 Description: Binary data
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng --- patch2 Description: Binary data
[PATCH 5/5] arcmsr: Modify ARC-1214 Inband Messages Behavior
From: Nick Cheng Modify ARC-1214 inband messages behavior to make up for HW seldom malfunction. Signed-off-by: Nick Cheng --- patch5 Description: Binary data
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng --- patch3 Description: Binary data
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng nick.ch...@areca.com.tw Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- patch3 Description: Binary data
[PATCH 5/5] arcmsr: Modify ARC-1214 Inband Messages Behavior
From: Nick Cheng nick.ch...@areca.com.tw Modify ARC-1214 inband messages behavior to make up for HW seldom malfunction. Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- patch5 Description: Binary data
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng nick.ch...@areca.com.tw Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- patch2 Description: Binary data
[PATCH 5/5] arcmsr: Modify ARC-1214 IO Behavior
From: Nick Cheng Modify ARC-1214 IO behavior to make up for HW seldom malfunction. Signed-off-by: Nick Cheng --- patch5 Description: Binary data
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng --- patch3 Description: Binary data
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng --- patch2 Description: Binary data
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng nick.ch...@areca.com.tw Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- patch2 Description: Binary data
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng nick.ch...@areca.com.tw Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- patch3 Description: Binary data
[PATCH 5/5] arcmsr: Modify ARC-1214 IO Behavior
From: Nick Cheng nick.ch...@areca.com.tw Modify ARC-1214 IO behavior to make up for HW seldom malfunction. Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- patch5 Description: Binary data
[PATCH 5/5] arcmsr: Modify ARC-1214 IO Behavior
From: Nick Cheng Modify ARC-1214 IO behavior to make up for HW seldom malfunction. Signed-off-by: Nick Cheng --- patch5 Description: Binary data
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng --- patch3 Description: Binary data
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng --- patch2 Description: Binary data
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng nick.ch...@areca.com.tw Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- patch2 Description: Binary data
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng nick.ch...@areca.com.tw Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- patch3 Description: Binary data
[PATCH 5/5] arcmsr: Modify ARC-1214 IO Behavior
From: Nick Cheng nick.ch...@areca.com.tw Modify ARC-1214 IO behavior to make up for HW seldom malfunction. Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- patch5 Description: Binary data
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng --- diff -uprN a//drivers/scsi/arcmsr/arcmsr_hba.c b//drivers/scsi/arcmsr/arcmsr_hba.c --- a//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-12 16:34:58.219955247 +0800 +++ b//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-12 16:35:16.267955072 +0800 @@ -805,8 +805,9 @@ static int arcmsr_probe(struct pci_dev * { struct Scsi_Host *host; struct AdapterControlBlock *acb; - uint8_t bus,dev_fun; - int error; + uint8_t bus, dev_fun; + struct msix_entry entries[ARCMST_NUM_MSIX_VECTORS]; + int error, i, j; error = pci_enable_device(pdev); if (error) { return -ENODEV; @@ -871,10 +872,46 @@ static int arcmsr_probe(struct pci_dev * if (error) { goto RAID_controller_stop; } - error = request_irq(pdev->irq, arcmsr_do_interrupt, - IRQF_SHARED, "arcmsr", acb); - if (error) { - goto scsi_host_remove; + if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) { + if (!pci_enable_msix(pdev, entries, ARCMST_NUM_MSIX_VECTORS)) { + for (i = 0; i < ARCMST_NUM_MSIX_VECTORS; i++) { + entries[i].entry = i; + if (request_irq(entries[i].vector, + arcmsr_do_interrupt, 0, "arcmsr", + acb)) { + for (j = 0 ; j < i ; j++) + free_irq(entries[i].vector, + acb); + goto scsi_host_remove; + } + acb->entries[i] = entries[i]; + } + acb->acb_flags |= ACB_F_MSIX_ENABLED; + } else { + if (request_irq(pdev->irq, arcmsr_do_interrupt, + IRQF_SHARED, "arcmsr", acb)) { + printk("arcmsr%d: request_irq =%d failed!\n", + acb->host->host_no, pdev->irq); + goto scsi_host_remove; + } + } + } else if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) { + if (!pci_enable_msi(pdev)) { + acb->acb_flags |= ACB_F_MSI_ENABLED; + } + if (request_irq(pdev->irq, arcmsr_do_interrupt, + IRQF_SHARED, "arcmsr", acb)) { + printk("arcmsr%d: request_irq =%d failed!\n", + acb->host->host_no, pdev->irq); + goto scsi_host_remove; + } + } else { + if (request_irq(pdev->irq, arcmsr_do_interrupt, + IRQF_SHARED, "arcmsr", acb)) { + printk("arcmsr%d: request_irq =%d failed!\n", + acb->host->host_no, pdev->irq); + goto scsi_host_remove; + } } host->irq = pdev->irq; scsi_scan_host(host); @@ -895,6 +932,11 @@ static int arcmsr_probe(struct pci_dev * return 0; out_free_sysfs: scsi_host_remove: + if (acb->acb_flags & ACB_F_MSI_ENABLED) { + pci_disable_msi(pdev); + } else if (acb->acb_flags & ACB_F_MSIX_ENABLED) { + pci_disable_msix(pdev); + } scsi_remove_host(host); RAID_controller_stop: arcmsr_stop_adapter_bgrb(acb); -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng --- diff -uprN a//drivers/scsi/arcmsr/arcmsr.h b//drivers/scsi/arcmsr/arcmsr.h --- a//drivers/scsi/arcmsr/arcmsr.h 2012-10-12 16:28:42.175958900 +0800 +++ b//drivers/scsi/arcmsr/arcmsr.h 2012-10-12 16:29:10.215958628 +0800 @@ -63,7 +63,8 @@ struct device_attribute; #define ARCMSR_DEFAULT_SG_ENTRIES 38 #define ARCMSR_MAX_HBB_POSTQUEUE 264 #define ARCMSR_MAX_XFER_LEN0x26000 -#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMST_NUM_MSIX_VECTORS4 #ifndef PCI_DEVICE_ID_ARECA_1880 #define PCI_DEVICE_ID_ARECA_18800x1880 #endif @@ -511,6 +512,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; @@ -547,6 +549,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; diff -uprN a//drivers/scsi/arcmsr/arcmsr_hba.c b//drivers/scsi/arcmsr/arcmsr_hba.c --- a//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-12 16:28:42.175958900 +0800 +++ b//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-12 16:29:10.239958629 +0800 @@ -89,11 +89,18 @@ static int arcmsr_bios_param(struct scsi 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); +#ifdef CONFIG_PM + static int arcmsr_suspend(struct pci_dev *pdev, + pm_message_t state); + static int arcmsr_resume(struct pci_dev *pdev); +#endif 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 orig_mask); static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); static void arcmsr_hbaA_flush_cache(struct AdapterControlBlock *acb); static void arcmsr_hbaB_flush_cache(struct AdapterControlBlock *acb); @@ -166,6 +173,10 @@ static struct pci_driver arcmsr_pci_driv .id_table = arcmsr_device_id_table, .probe = arcmsr_probe, .remove = arcmsr_remove, + #ifdef CONFIG_PM + .suspend= arcmsr_suspend, + .resume = arcmsr_resume, + #endif .shutdown = arcmsr_shutdown, }; /* @@ -662,6 +673,134 @@ arcmsr_message_isr_bh_fn(struct work_str } } +#ifdef CONFIG_PM + static int + arcmsr_suspend(struct pci_dev *pdev, pm_message_t state) + { + int i; + 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); + 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 < ARCMST_NUM_MSIX_VECTORS; i++) { + free_irq(acb->entries[i].vector, acb); + } + pci_disable_msix(pdev); + } else { + free_irq(pdev->irq, acb); + } + del_timer_sync(>eternal_timer); + flush_scheduled_work(); + arcmsr_stop_adapter_bgrb(acb); + arcmsr_flush_adapter_cache(acb); + arcmsr_enable_outbound_ints(acb, intmask_org); + 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, i, j; + struct Scsi_Host *host
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng nick.ch...@areca.com.tw Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN a//drivers/scsi/arcmsr/arcmsr.h b//drivers/scsi/arcmsr/arcmsr.h --- a//drivers/scsi/arcmsr/arcmsr.h 2012-10-12 16:28:42.175958900 +0800 +++ b//drivers/scsi/arcmsr/arcmsr.h 2012-10-12 16:29:10.215958628 +0800 @@ -63,7 +63,8 @@ struct device_attribute; #define ARCMSR_DEFAULT_SG_ENTRIES 38 #define ARCMSR_MAX_HBB_POSTQUEUE 264 #define ARCMSR_MAX_XFER_LEN0x26000 -#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMST_NUM_MSIX_VECTORS4 #ifndef PCI_DEVICE_ID_ARECA_1880 #define PCI_DEVICE_ID_ARECA_18800x1880 #endif @@ -511,6 +512,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; @@ -547,6 +549,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; diff -uprN a//drivers/scsi/arcmsr/arcmsr_hba.c b//drivers/scsi/arcmsr/arcmsr_hba.c --- a//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-12 16:28:42.175958900 +0800 +++ b//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-12 16:29:10.239958629 +0800 @@ -89,11 +89,18 @@ static int arcmsr_bios_param(struct scsi 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); +#ifdef CONFIG_PM + static int arcmsr_suspend(struct pci_dev *pdev, + pm_message_t state); + static int arcmsr_resume(struct pci_dev *pdev); +#endif 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 orig_mask); static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); static void arcmsr_hbaA_flush_cache(struct AdapterControlBlock *acb); static void arcmsr_hbaB_flush_cache(struct AdapterControlBlock *acb); @@ -166,6 +173,10 @@ static struct pci_driver arcmsr_pci_driv .id_table = arcmsr_device_id_table, .probe = arcmsr_probe, .remove = arcmsr_remove, + #ifdef CONFIG_PM + .suspend= arcmsr_suspend, + .resume = arcmsr_resume, + #endif .shutdown = arcmsr_shutdown, }; /* @@ -662,6 +673,134 @@ arcmsr_message_isr_bh_fn(struct work_str } } +#ifdef CONFIG_PM + static int + arcmsr_suspend(struct pci_dev *pdev, pm_message_t state) + { + int i; + 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); + 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 ARCMST_NUM_MSIX_VECTORS; i++) { + free_irq(acb-entries[i].vector, acb); + } + pci_disable_msix(pdev); + } else { + free_irq(pdev-irq, acb); + } + del_timer_sync(acb-eternal_timer); + flush_scheduled_work(); + arcmsr_stop_adapter_bgrb(acb); + arcmsr_flush_adapter_cache(acb); + arcmsr_enable_outbound_ints(acb, intmask_org); + 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, i,
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng nick.ch...@areca.com.tw Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN a//drivers/scsi/arcmsr/arcmsr_hba.c b//drivers/scsi/arcmsr/arcmsr_hba.c --- a//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-12 16:34:58.219955247 +0800 +++ b//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-12 16:35:16.267955072 +0800 @@ -805,8 +805,9 @@ static int arcmsr_probe(struct pci_dev * { struct Scsi_Host *host; struct AdapterControlBlock *acb; - uint8_t bus,dev_fun; - int error; + uint8_t bus, dev_fun; + struct msix_entry entries[ARCMST_NUM_MSIX_VECTORS]; + int error, i, j; error = pci_enable_device(pdev); if (error) { return -ENODEV; @@ -871,10 +872,46 @@ static int arcmsr_probe(struct pci_dev * if (error) { goto RAID_controller_stop; } - error = request_irq(pdev-irq, arcmsr_do_interrupt, - IRQF_SHARED, arcmsr, acb); - if (error) { - goto scsi_host_remove; + if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) { + if (!pci_enable_msix(pdev, entries, ARCMST_NUM_MSIX_VECTORS)) { + for (i = 0; i ARCMST_NUM_MSIX_VECTORS; i++) { + entries[i].entry = i; + if (request_irq(entries[i].vector, + arcmsr_do_interrupt, 0, arcmsr, + acb)) { + for (j = 0 ; j i ; j++) + free_irq(entries[i].vector, + acb); + goto scsi_host_remove; + } + acb-entries[i] = entries[i]; + } + acb-acb_flags |= ACB_F_MSIX_ENABLED; + } else { + if (request_irq(pdev-irq, arcmsr_do_interrupt, + IRQF_SHARED, arcmsr, acb)) { + printk(arcmsr%d: request_irq =%d failed!\n, + acb-host-host_no, pdev-irq); + goto scsi_host_remove; + } + } + } else if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) { + if (!pci_enable_msi(pdev)) { + acb-acb_flags |= ACB_F_MSI_ENABLED; + } + if (request_irq(pdev-irq, arcmsr_do_interrupt, + IRQF_SHARED, arcmsr, acb)) { + printk(arcmsr%d: request_irq =%d failed!\n, + acb-host-host_no, pdev-irq); + goto scsi_host_remove; + } + } else { + if (request_irq(pdev-irq, arcmsr_do_interrupt, + IRQF_SHARED, arcmsr, acb)) { + printk(arcmsr%d: request_irq =%d failed!\n, + acb-host-host_no, pdev-irq); + goto scsi_host_remove; + } } host-irq = pdev-irq; scsi_scan_host(host); @@ -895,6 +932,11 @@ static int arcmsr_probe(struct pci_dev * return 0; out_free_sysfs: scsi_host_remove: + if (acb-acb_flags ACB_F_MSI_ENABLED) { + pci_disable_msi(pdev); + } else if (acb-acb_flags ACB_F_MSIX_ENABLED) { + pci_disable_msix(pdev); + } scsi_remove_host(host); RAID_controller_stop: arcmsr_stop_adapter_bgrb(acb); -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/5] arcmsr: Re-name the HBA Type
From: Nick Cheng Replace the nameing, hba, hbb and hbc, with hbaA, hbaB abd hbaC respectively Signed-off-by: Nick Cheng --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:43:58.542648536 +0800 @@ -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 "Driver Version 1.20.00.15 2012/09/30" #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 #define ARCMSR_MAX_XFER_SECTORS_B 4096 diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:43:58.542648536 +0800 @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -95,16 +96,16 @@ static void arcmsr_iop_init(struct Adapt static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb); static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); 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); @@ -308,7 +309,7 @@ static void arcmsr_define_adapter_type(s } } -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; @@ -326,7 +327,7 @@ static uint8_t arcmsr_hba_wait_msgint_re 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; @@ -346,7 +347,7 @@ static uint8_t arcmsr_hbb_wait_msgint_re 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; @@ -364,13 +365,13 @@ static uint8_t arcmsr_hbc_wait_msgint_re 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--; @@ -380,13 +381,13 @@ static void arcmsr_flush_hba_cache(struc } 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;
[PATCH 1/5] arcmsr: Re-name the HBA Type
From: Nick Cheng nick.ch...@areca.com.tw Replace the nameing, hba, hbb and hbc, with hbaA, hbaB abd hbaC respectively Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:43:58.542648536 +0800 @@ -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 Driver Version 1.20.00.15 2012/09/30 #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 #define ARCMSR_MAX_XFER_SECTORS_B 4096 diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:43:58.542648536 +0800 @@ -61,6 +61,7 @@ #include linux/aer.h #include asm/dma.h #include asm/io.h +#include asm/system.h #include asm/uaccess.h #include scsi/scsi_host.h #include scsi/scsi.h @@ -95,16 +96,16 @@ static void arcmsr_iop_init(struct Adapt static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb); static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); 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); @@ -308,7 +309,7 @@ static void arcmsr_define_adapter_type(s } } -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; @@ -326,7 +327,7 @@ static uint8_t arcmsr_hba_wait_msgint_re 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; @@ -346,7 +347,7 @@ static uint8_t arcmsr_hbb_wait_msgint_re 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; @@ -364,13 +365,13 @@ static uint8_t arcmsr_hbc_wait_msgint_re 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, reg-inbound_msgaddr0); do { - if (arcmsr_hba_wait_msgint_ready(acb)) + if (arcmsr_hbaA_wait_msgint_ready(acb)) break; else { retry_count--; @@ -380,13 +381,13 @@ static void arcmsr_flush_hba_cache(struc } 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
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:16:18.114629695 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:17:44.826628853 +0800 @@ -63,7 +63,8 @@ struct device_attribute; #define ARCMSR_DEFAULT_SG_ENTRIES 38 #define ARCMSR_MAX_HBB_POSTQUEUE 264 #define ARCMSR_MAX_XFER_LEN 0x26000 /* 152K */ -#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMST_NUM_MSIX_VECTORS4 #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_toutbound_int_enable; uint32_tcdb_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_headccb_free_list; diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:16:18.214629692 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:17:44.834628853 +0800 @@ -61,7 +61,6 @@ #include #include #include -#include #include #include #include @@ -82,7 +81,7 @@ MODULE_VERSION(ARCMSR_DRIVER_VERSION); 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); +static void arcmsr_iop_confirm(struct AdapterControlBlock *acb); static int arcmsr_abort(struct scsi_cmnd *); static int arcmsr_bus_reset(struct scsi_cmnd *); static int arcmsr_bios_param(struct scsi_device *sdev, @@ -97,6 +96,8 @@ static void arcmsr_shutdown(struct pci_d 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_hbaA_flush_cache(struct AdapterControlBlock *acb); static void arcmsr_hbaB_flush_cache(struct AdapterControlBlock *acb); @@ -227,8 +228,8 @@ static bool arcmsr_remap_pciregion(struc printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", acb->host->host_no); return false; } - if (readl(>pmuC->outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { - writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, >pmuC->outbound_doorbell_clear);/*clear interrupt*/ + if (ioread32(>pmuC->outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { + iowrite32(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, >pmuC->outbound_doorbell_clear);/*clear interrupt*/ return true; } break; @@ -357,9 +358,9 @@ static uint8_t arcmsr_hbaC_wait_msgint_r int i; for (i = 0; i < 2000; i++) { - if (readl(>outbound_doorbell) + if (ioread32(>outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { - writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, + iowrite32(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, >outbound_doorbell_clear); /*clear interrupt*/ return true; } @@ -404,9 +405,11 @@ static void arcmsr_hbaB_flush_cache(stru 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,
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:08:33.338634210 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:50:32.694644708 +0800 @@ -42,7 +42,7 @@ ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *** ** For history of changes, see Documentation/scsi/ChangeLog.arcmsr -** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt +** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt *** */ #include @@ -90,6 +90,8 @@ static int arcmsr_bios_param(struct scsi 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); @@ -167,6 +169,8 @@ static struct pci_driver arcmsr_pci_driv .id_table = arcmsr_device_id_table, .probe = arcmsr_probe, .remove = arcmsr_remove, + .suspend= arcmsr_suspend, + .resume = arcmsr_resume, .shutdown = arcmsr_shutdown, }; /* @@ -603,6 +607,80 @@ static void arcmsr_message_isr_bh_fn(str } } +static int arcmsr_suspend(struct pci_dev *pdev, pm_message_t state) +{ + int i; + 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); + del_timer_sync(>eternal_timer); + flush_scheduled_work(); + arcmsr_stop_adapter_bgrb(acb); + arcmsr_flush_adapter_cache(acb); + arcmsr_enable_outbound_ints(acb, intmask_org); + 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, i, j; + 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)) { + printk("%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) { + printk(KERN_WARNING + "scsi%d: No suitable DMA mask available\n", + host->host_no); + goto controller_unregister; + } + } + pci_set_master(pdev); + arcmsr_iop_init(acb); + if (request_irq(pdev->irq, arcmsr_do_interrupt, IRQF_SHARED, "arcmsr", acb)) { + printk("arcmsr%d: request_irq =%d failed!\n", acb->host->host_no, pdev->irq); + goto controller_stop; + } + timer_init: + INIT_WORK(>arcmsr_do_message_isr_bh, + arcmsr_message_isr_bh_fn); + atomic_set(>rq_map_token, 16); + atomic_set(>ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + init_timer(>eternal_timer); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6 * HZ); + acb->eternal_timer.data = (unsigned long) acb; + acb->eternal_timer.function = _request_device_map; + add_timer(>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 int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct Scsi_Host *host; @@ -1539,14 +1617,7 @@ static void
[PATCH 1/5] arcmsr: Re-name the HBA Type
From: Nick Cheng Replace the nameing, hba, hbb and hbc, with hbaA, hbaB abd hbaC respectively Signed-off-by: Nick Cheng --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:43:58.542648536 +0800 @@ -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 "Driver Version 1.20.00.15 2012/09/30" #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 #define ARCMSR_MAX_XFER_SECTORS_B 4096 diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:43:58.542648536 +0800 @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -95,16 +96,16 @@ static void arcmsr_iop_init(struct Adapt static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb); static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); 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); @@ -308,7 +309,7 @@ static void arcmsr_define_adapter_type(s } } -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; @@ -326,7 +327,7 @@ static uint8_t arcmsr_hba_wait_msgint_re 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; @@ -346,7 +347,7 @@ static uint8_t arcmsr_hbb_wait_msgint_re 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; @@ -364,13 +365,13 @@ static uint8_t arcmsr_hbc_wait_msgint_re 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--; @@ -380,13 +381,13 @@ static void arcmsr_flush_hba_cache(struc } 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;
[PATCH 5/5] arcmsr: Add the spinlock for queue buffer access
From: Nick Cheng Add the spinlock for queue buffer access Signed-off-by: Nick Cheng --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:31:31.742620819 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:31:04.098621088 +0800 @@ -617,6 +617,8 @@ struct AdapterControlBlock spinlock_t eh_lock; spinlock_t ccblist_lock; spinlock_t postq_lock; + spinlock_t rqbuffer_lock; + spinlock_t wqbuffer_lock; union { struct MessageUnit_A __iomem *pmuA; struct MessageUnit_B*pmuB; diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:31:31.754620820 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:31:04.118621087 +0800 @@ -987,6 +987,8 @@ static int arcmsr_probe(struct pci_dev * spin_lock_init(>eh_lock); spin_lock_init(>ccblist_lock); spin_lock_init(>postq_lock); + spin_lock_init(>rqbuffer_lock); + spin_lock_init(>wqbuffer_lock); acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | ACB_F_MESSAGE_RQBUFFER_CLEARED | ACB_F_MESSAGE_WQBUFFER_READED); @@ -1927,10 +1929,12 @@ static struct QBUFFER __iomem *arcmsr_ge static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) { + uint8_t __iomem *iop_data; struct QBUFFER __iomem *prbuffer; struct QBUFFER *pQbuffer; - uint8_t __iomem *iop_data; int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; + unsigned long flags; + spin_lock_irqsave(>rqbuffer_lock, flags); rqbuf_lastindex = acb->rqbuf_lastindex; rqbuf_firstindex = acb->rqbuf_firstindex; prbuffer = arcmsr_get_iop_rqbuffer(acb); @@ -1952,10 +1956,13 @@ static void arcmsr_iop2drv_data_wrote_ha } else { acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; } + spin_unlock_irqrestore(>rqbuffer_lock, flags); } static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) { + unsigned long flags; + spin_lock_irqsave(>wqbuffer_lock, flags); acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) { uint8_t *pQbuffer; @@ -1984,6 +1991,7 @@ static void arcmsr_iop2drv_data_read_han if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) { acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; } + spin_unlock_irqrestore(>wqbuffer_lock, flags); } static void arcmsr_hbaA_doorbell_isr(struct AdapterControlBlock *acb) @@ -2403,6 +2411,7 @@ static int arcmsr_iop_message_xfer(struc unsigned char *ver_addr; uint8_t *pQbuffer, *ptmpQbuffer; int32_t allxfer_len = 0; + unsigned long flags; ver_addr = kmalloc(1032, GFP_ATOMIC); if (!ver_addr) { @@ -2411,6 +2420,7 @@ static int arcmsr_iop_message_xfer(struc } ptmpQbuffer = ver_addr; + spin_lock_irqsave(>rqbuffer_lock, flags); while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) && (allxfer_len < 1031)) { pQbuffer = >rqbuffer[acb->rqbuf_firstindex]; @@ -2439,6 +2449,7 @@ static int arcmsr_iop_message_xfer(struc } arcmsr_iop_message_read(acb); } + spin_unlock_irqrestore(>rqbuffer_lock, flags); memcpy(pcmdmessagefld->messagedatabuffer, ver_addr, allxfer_len); pcmdmessagefld->cmdmessage.Length = allxfer_len; if(acb->fw_flag == FW_DEADLOCK) { @@ -2452,8 +2463,9 @@ static int arcmsr_iop_message_xfer(struc case ARCMSR_MESSAGE_WRITE_WQBUFFER: { unsigned char *ver_addr; - int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; uint8_t *pQbuffer, *ptmpuserbuffer; + int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; + unsigned long flags; ver_addr = kmalloc(1032, GFP_ATOMIC); if (!ver_addr) { @@ -2470,6 +2482,7 @@ static int arcmsr_iop_message_xfer(struc ptmpuserbuffer = ver_addr; user_len = pcmdmessagefld->cmdmessage.Length; memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); +
[PATCH 5/5] SCSI: Add the spinlock for queue buffer access
From: Nick Cheng Add the spinlock for queue buffer access Signed-off-by: Nick Cheng< nick.ch...@areca.com.tw > --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:31:31.742620819 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:31:04.098621088 +0800 @@ -617,6 +617,8 @@ struct AdapterControlBlock spinlock_t eh_lock; spinlock_t ccblist_lock; spinlock_t postq_lock; + spinlock_t rqbuffer_lock; + spinlock_t wqbuffer_lock; union { struct MessageUnit_A __iomem *pmuA; struct MessageUnit_B*pmuB; diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:31:31.754620820 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:31:04.118621087 +0800 @@ -987,6 +987,8 @@ static int arcmsr_probe(struct pci_dev * spin_lock_init(>eh_lock); spin_lock_init(>ccblist_lock); spin_lock_init(>postq_lock); + spin_lock_init(>rqbuffer_lock); + spin_lock_init(>wqbuffer_lock); acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | ACB_F_MESSAGE_RQBUFFER_CLEARED | ACB_F_MESSAGE_WQBUFFER_READED); @@ -1927,10 +1929,12 @@ static struct QBUFFER __iomem *arcmsr_ge static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) { + uint8_t __iomem *iop_data; struct QBUFFER __iomem *prbuffer; struct QBUFFER *pQbuffer; - uint8_t __iomem *iop_data; int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; + unsigned long flags; + spin_lock_irqsave(>rqbuffer_lock, flags); rqbuf_lastindex = acb->rqbuf_lastindex; rqbuf_firstindex = acb->rqbuf_firstindex; prbuffer = arcmsr_get_iop_rqbuffer(acb); @@ -1952,10 +1956,13 @@ static void arcmsr_iop2drv_data_wrote_ha } else { acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; } + spin_unlock_irqrestore(>rqbuffer_lock, flags); } static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) { + unsigned long flags; + spin_lock_irqsave(>wqbuffer_lock, flags); acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) { uint8_t *pQbuffer; @@ -1984,6 +1991,7 @@ static void arcmsr_iop2drv_data_read_han if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) { acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; } + spin_unlock_irqrestore(>wqbuffer_lock, flags); } static void arcmsr_hbaA_doorbell_isr(struct AdapterControlBlock *acb) @@ -2403,6 +2411,7 @@ static int arcmsr_iop_message_xfer(struc unsigned char *ver_addr; uint8_t *pQbuffer, *ptmpQbuffer; int32_t allxfer_len = 0; + unsigned long flags; ver_addr = kmalloc(1032, GFP_ATOMIC); if (!ver_addr) { @@ -2411,6 +2420,7 @@ static int arcmsr_iop_message_xfer(struc } ptmpQbuffer = ver_addr; + spin_lock_irqsave(>rqbuffer_lock, flags); while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) && (allxfer_len < 1031)) { pQbuffer = >rqbuffer[acb->rqbuf_firstindex]; @@ -2439,6 +2449,7 @@ static int arcmsr_iop_message_xfer(struc } arcmsr_iop_message_read(acb); } + spin_unlock_irqrestore(>rqbuffer_lock, flags); memcpy(pcmdmessagefld->messagedatabuffer, ver_addr, allxfer_len); pcmdmessagefld->cmdmessage.Length = allxfer_len; if(acb->fw_flag == FW_DEADLOCK) { @@ -2452,8 +2463,9 @@ static int arcmsr_iop_message_xfer(struc case ARCMSR_MESSAGE_WRITE_WQBUFFER: { unsigned char *ver_addr; - int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; uint8_t *pQbuffer, *ptmpuserbuffer; + int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; + unsigned long flags; ver_addr = kmalloc(1032, GFP_ATOMIC); if (!ver_addr) { @@ -2470,6 +2482,7 @@ static int arcmsr_iop_message_xfer(struc ptmpuserbuffer = ver_addr; user_len = pcmdmessagefld->cmdmessage.Length; memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); +
[PATCH 3/5] SCSI: Support MSI and MSI-X
From: Nick Cheng Support MSI or MSI-X for whole series of RAID controllers. Meanwhole correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng< nick.ch...@areca.com.tw > --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:16:18.114629695 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:17:44.826628853 +0800 @@ -63,7 +63,8 @@ struct device_attribute; #define ARCMSR_DEFAULT_SG_ENTRIES 38 #define ARCMSR_MAX_HBB_POSTQUEUE 264 #define ARCMSR_MAX_XFER_LEN 0x26000 /* 152K */ -#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMST_NUM_MSIX_VECTORS4 #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_toutbound_int_enable; uint32_tcdb_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_headccb_free_list; diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:16:18.214629692 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:17:44.834628853 +0800 @@ -61,7 +61,6 @@ #include #include #include -#include #include #include #include @@ -82,7 +81,7 @@ MODULE_VERSION(ARCMSR_DRIVER_VERSION); 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); +static void arcmsr_iop_confirm(struct AdapterControlBlock *acb); static int arcmsr_abort(struct scsi_cmnd *); static int arcmsr_bus_reset(struct scsi_cmnd *); static int arcmsr_bios_param(struct scsi_device *sdev, @@ -97,6 +96,8 @@ static void arcmsr_shutdown(struct pci_d 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_hbaA_flush_cache(struct AdapterControlBlock *acb); static void arcmsr_hbaB_flush_cache(struct AdapterControlBlock *acb); @@ -227,8 +228,8 @@ static bool arcmsr_remap_pciregion(struc printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", acb->host->host_no); return false; } - if (readl(>pmuC->outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { - writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, >pmuC->outbound_doorbell_clear);/*clear interrupt*/ + if (ioread32(>pmuC->outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { + iowrite32(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, >pmuC->outbound_doorbell_clear);/*clear interrupt*/ return true; } break; @@ -357,9 +358,9 @@ static uint8_t arcmsr_hbaC_wait_msgint_r int i; for (i = 0; i < 2000; i++) { - if (readl(>outbound_doorbell) + if (ioread32(>outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { - writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, + iowrite32(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, >outbound_doorbell_clear); /*clear interrupt*/ return true; } @@ -404,9 +405,11 @@ static void arcmsr_hbaB_flush_cache(stru 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 */ -
[PATCH 2/5] SCSI: Support Hibernation
From: Nick Cheng Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng< nick.ch...@areca.com.tw > --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:08:33.338634210 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:50:32.694644708 +0800 @@ -42,7 +42,7 @@ ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *** ** For history of changes, see Documentation/scsi/ChangeLog.arcmsr -** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt +** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt *** */ #include @@ -90,6 +90,8 @@ static int arcmsr_bios_param(struct scsi 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); @@ -167,6 +169,8 @@ static struct pci_driver arcmsr_pci_driv .id_table = arcmsr_device_id_table, .probe = arcmsr_probe, .remove = arcmsr_remove, + .suspend= arcmsr_suspend, + .resume = arcmsr_resume, .shutdown = arcmsr_shutdown, }; /* @@ -603,6 +607,80 @@ static void arcmsr_message_isr_bh_fn(str } } +static int arcmsr_suspend(struct pci_dev *pdev, pm_message_t state) +{ + int i; + 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); + del_timer_sync(>eternal_timer); + flush_scheduled_work(); + arcmsr_stop_adapter_bgrb(acb); + arcmsr_flush_adapter_cache(acb); + arcmsr_enable_outbound_ints(acb, intmask_org); + 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, i, j; + 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)) { + printk("%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) { + printk(KERN_WARNING + "scsi%d: No suitable DMA mask available\n", + host->host_no); + goto controller_unregister; + } + } + pci_set_master(pdev); + arcmsr_iop_init(acb); + if (request_irq(pdev->irq, arcmsr_do_interrupt, IRQF_SHARED, "arcmsr", acb)) { + printk("arcmsr%d: request_irq =%d failed!\n", acb->host->host_no, pdev->irq); + goto controller_stop; + } + timer_init: + INIT_WORK(>arcmsr_do_message_isr_bh, + arcmsr_message_isr_bh_fn); + atomic_set(>rq_map_token, 16); + atomic_set(>ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + init_timer(>eternal_timer); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6 * HZ); + acb->eternal_timer.data = (unsigned long) acb; + acb->eternal_timer.function = _request_device_map; + add_timer(>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 int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct Scsi_Host *host; @@ -1539,14
[PATCH 1/5] SCSI: Re-name the HBA Type
From: Nick Cheng Replace the nameing, hba, hbb and hbc, with hbaA, hbaB abd hbaC respectively Signed-off-by: Nick Cheng< nick.ch...@areca.com.tw > --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:43:58.542648536 +0800 @@ -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 "Driver Version 1.20.00.15 2012/09/30" #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 #define ARCMSR_MAX_XFER_SECTORS_B 4096 diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:43:58.542648536 +0800 @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -95,16 +96,16 @@ static void arcmsr_iop_init(struct Adapt static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb); static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); 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); @@ -308,7 +309,7 @@ static void arcmsr_define_adapter_type(s } } -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; @@ -326,7 +327,7 @@ static uint8_t arcmsr_hba_wait_msgint_re 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; @@ -346,7 +347,7 @@ static uint8_t arcmsr_hbb_wait_msgint_re 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; @@ -364,13 +365,13 @@ static uint8_t arcmsr_hbc_wait_msgint_re 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--; @@ -380,13 +381,13 @@ static void arcmsr_flush_hba_cache(struc } 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))
[PATCH 5/5] SCSI: Add the spinlock for queue buffer access
From: Nick Cheng Add the spinlock for queue buffer access Signed-off-by: Nick Cheng< nick.ch...@areca.com.tw > --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:31:31.742620819 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:31:04.098621088 +0800 @@ -617,6 +617,8 @@ struct AdapterControlBlock spinlock_t eh_lock; spinlock_t ccblist_lock; spinlock_t postq_lock; + spinlock_t rqbuffer_lock; + spinlock_t wqbuffer_lock; union { struct MessageUnit_A __iomem *pmuA; struct MessageUnit_B*pmuB; diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:31:31.754620820 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:31:04.118621087 +0800 @@ -987,6 +987,8 @@ static int arcmsr_probe(struct pci_dev * spin_lock_init(>eh_lock); spin_lock_init(>ccblist_lock); spin_lock_init(>postq_lock); + spin_lock_init(>rqbuffer_lock); + spin_lock_init(>wqbuffer_lock); acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | ACB_F_MESSAGE_RQBUFFER_CLEARED | ACB_F_MESSAGE_WQBUFFER_READED); @@ -1927,10 +1929,12 @@ static struct QBUFFER __iomem *arcmsr_ge static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) { + uint8_t __iomem *iop_data; struct QBUFFER __iomem *prbuffer; struct QBUFFER *pQbuffer; - uint8_t __iomem *iop_data; int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; + unsigned long flags; + spin_lock_irqsave(>rqbuffer_lock, flags); rqbuf_lastindex = acb->rqbuf_lastindex; rqbuf_firstindex = acb->rqbuf_firstindex; prbuffer = arcmsr_get_iop_rqbuffer(acb); @@ -1952,10 +1956,13 @@ static void arcmsr_iop2drv_data_wrote_ha } else { acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; } + spin_unlock_irqrestore(>rqbuffer_lock, flags); } static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) { + unsigned long flags; + spin_lock_irqsave(>wqbuffer_lock, flags); acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) { uint8_t *pQbuffer; @@ -1984,6 +1991,7 @@ static void arcmsr_iop2drv_data_read_han if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) { acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; } + spin_unlock_irqrestore(>wqbuffer_lock, flags); } static void arcmsr_hbaA_doorbell_isr(struct AdapterControlBlock *acb) @@ -2403,6 +2411,7 @@ static int arcmsr_iop_message_xfer(struc unsigned char *ver_addr; uint8_t *pQbuffer, *ptmpQbuffer; int32_t allxfer_len = 0; + unsigned long flags; ver_addr = kmalloc(1032, GFP_ATOMIC); if (!ver_addr) { @@ -2411,6 +2420,7 @@ static int arcmsr_iop_message_xfer(struc } ptmpQbuffer = ver_addr; + spin_lock_irqsave(>rqbuffer_lock, flags); while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) && (allxfer_len < 1031)) { pQbuffer = >rqbuffer[acb->rqbuf_firstindex]; @@ -2439,6 +2449,7 @@ static int arcmsr_iop_message_xfer(struc } arcmsr_iop_message_read(acb); } + spin_unlock_irqrestore(>rqbuffer_lock, flags); memcpy(pcmdmessagefld->messagedatabuffer, ver_addr, allxfer_len); pcmdmessagefld->cmdmessage.Length = allxfer_len; if(acb->fw_flag == FW_DEADLOCK) { @@ -2452,8 +2463,9 @@ static int arcmsr_iop_message_xfer(struc case ARCMSR_MESSAGE_WRITE_WQBUFFER: { unsigned char *ver_addr; - int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; uint8_t *pQbuffer, *ptmpuserbuffer; + int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; + unsigned long flags; ver_addr = kmalloc(1032, GFP_ATOMIC); if (!ver_addr) { @@ -2470,6 +2482,7 @@ static int arcmsr_iop_message_xfer(struc ptmpuserbuffer = ver_addr; user_len = pcmdmessagefld->cmdmessage.Length; memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); +
[PATCH 3/5] SCSI: Support MSI and MSI-X
From: Nick Cheng Support MSI or MSI-X for whole series of RAID controllers. Meanwhole correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng< nick.ch...@areca.com.tw > diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:16:18.114629695 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:17:44.826628853 +0800 @@ -63,7 +63,8 @@ struct device_attribute; #define ARCMSR_DEFAULT_SG_ENTRIES 38 #define ARCMSR_MAX_HBB_POSTQUEUE 264 #define ARCMSR_MAX_XFER_LEN 0x26000 /* 152K */ -#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMST_NUM_MSIX_VECTORS4 #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_toutbound_int_enable; uint32_tcdb_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_headccb_free_list; diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:16:18.214629692 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:17:44.834628853 +0800 @@ -61,7 +61,6 @@ #include #include #include -#include #include #include #include @@ -82,7 +81,7 @@ MODULE_VERSION(ARCMSR_DRIVER_VERSION); 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); +static void arcmsr_iop_confirm(struct AdapterControlBlock *acb); static int arcmsr_abort(struct scsi_cmnd *); static int arcmsr_bus_reset(struct scsi_cmnd *); static int arcmsr_bios_param(struct scsi_device *sdev, @@ -97,6 +96,8 @@ static void arcmsr_shutdown(struct pci_d 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_hbaA_flush_cache(struct AdapterControlBlock *acb); static void arcmsr_hbaB_flush_cache(struct AdapterControlBlock *acb); @@ -227,8 +228,8 @@ static bool arcmsr_remap_pciregion(struc printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", acb->host->host_no); return false; } - if (readl(>pmuC->outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { - writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, >pmuC->outbound_doorbell_clear);/*clear interrupt*/ + if (ioread32(>pmuC->outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { + iowrite32(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, >pmuC->outbound_doorbell_clear);/*clear interrupt*/ return true; } break; @@ -357,9 +358,9 @@ static uint8_t arcmsr_hbaC_wait_msgint_r int i; for (i = 0; i < 2000; i++) { - if (readl(>outbound_doorbell) + if (ioread32(>outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { - writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, + iowrite32(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, >outbound_doorbell_clear); /*clear interrupt*/ return true; } @@ -404,9 +405,11 @@ static void arcmsr_hbaB_flush_cache(stru 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 */ -
[PATCH 2/5] SCSI: Support Hibernation
From: Nick Cheng Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng< nick.ch...@areca.com.tw > --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:08:33.338634210 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:50:32.694644708 +0800 @@ -42,7 +42,7 @@ ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *** ** For history of changes, see Documentation/scsi/ChangeLog.arcmsr -** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt +** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt *** */ #include @@ -90,6 +90,8 @@ static int arcmsr_bios_param(struct scsi 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); @@ -167,6 +169,8 @@ static struct pci_driver arcmsr_pci_driv .id_table = arcmsr_device_id_table, .probe = arcmsr_probe, .remove = arcmsr_remove, + .suspend= arcmsr_suspend, + .resume = arcmsr_resume, .shutdown = arcmsr_shutdown, }; /* @@ -603,6 +607,80 @@ static void arcmsr_message_isr_bh_fn(str } } +static int arcmsr_suspend(struct pci_dev *pdev, pm_message_t state) +{ + int i; + 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); + del_timer_sync(>eternal_timer); + flush_scheduled_work(); + arcmsr_stop_adapter_bgrb(acb); + arcmsr_flush_adapter_cache(acb); + arcmsr_enable_outbound_ints(acb, intmask_org); + 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, i, j; + 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)) { + printk("%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) { + printk(KERN_WARNING + "scsi%d: No suitable DMA mask available\n", + host->host_no); + goto controller_unregister; + } + } + pci_set_master(pdev); + arcmsr_iop_init(acb); + if (request_irq(pdev->irq, arcmsr_do_interrupt, IRQF_SHARED, "arcmsr", acb)) { + printk("arcmsr%d: request_irq =%d failed!\n", acb->host->host_no, pdev->irq); + goto controller_stop; + } + timer_init: + INIT_WORK(>arcmsr_do_message_isr_bh, + arcmsr_message_isr_bh_fn); + atomic_set(>rq_map_token, 16); + atomic_set(>ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + init_timer(>eternal_timer); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6 * HZ); + acb->eternal_timer.data = (unsigned long) acb; + acb->eternal_timer.function = _request_device_map; + add_timer(>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 int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct Scsi_Host *host; @@ -1539,14
[PATCH 1/5] SCSI: Re-name the HBA Type
From: Nick Cheng Replace the nameing, hba, hbb and hbc, with hbaA, hbaB abd hbaC respectively Signed-off-by: Nick Cheng< nick.ch...@areca.com.tw > --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:43:58.542648536 +0800 @@ -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 "Driver Version 1.20.00.15 2012/09/30" #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 #define ARCMSR_MAX_XFER_SECTORS_B 4096 diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:43:58.542648536 +0800 @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -95,16 +96,16 @@ static void arcmsr_iop_init(struct Adapt static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb); static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); 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); @@ -308,7 +309,7 @@ static void arcmsr_define_adapter_type(s } } -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; @@ -326,7 +327,7 @@ static uint8_t arcmsr_hba_wait_msgint_re 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; @@ -346,7 +347,7 @@ static uint8_t arcmsr_hbb_wait_msgint_re 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; @@ -364,13 +365,13 @@ static uint8_t arcmsr_hbc_wait_msgint_re 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--; @@ -380,13 +381,13 @@ static void arcmsr_flush_hba_cache(struc } 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))
[PATCH 1/5] SCSI: Re-name the HBA Type
From: Nick Cheng nick.ch...@areca.com.tw Replace the nameing, hba, hbb and hbc, with hbaA, hbaB abd hbaC respectively Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:43:58.542648536 +0800 @@ -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 Driver Version 1.20.00.15 2012/09/30 #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 #define ARCMSR_MAX_XFER_SECTORS_B 4096 diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:43:58.542648536 +0800 @@ -61,6 +61,7 @@ #include linux/aer.h #include asm/dma.h #include asm/io.h +#include asm/system.h #include asm/uaccess.h #include scsi/scsi_host.h #include scsi/scsi.h @@ -95,16 +96,16 @@ static void arcmsr_iop_init(struct Adapt static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb); static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); 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); @@ -308,7 +309,7 @@ static void arcmsr_define_adapter_type(s } } -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; @@ -326,7 +327,7 @@ static uint8_t arcmsr_hba_wait_msgint_re 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; @@ -346,7 +347,7 @@ static uint8_t arcmsr_hbb_wait_msgint_re 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; @@ -364,13 +365,13 @@ static uint8_t arcmsr_hbc_wait_msgint_re 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, reg-inbound_msgaddr0); do { - if (arcmsr_hba_wait_msgint_ready(acb)) + if (arcmsr_hbaA_wait_msgint_ready(acb)) break; else { retry_count--; @@ -380,13 +381,13 @@ static void arcmsr_flush_hba_cache(struc } 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
[PATCH 2/5] SCSI: Support Hibernation
From: Nick Cheng nick.ch...@areca.com.tw Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:08:33.338634210 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:50:32.694644708 +0800 @@ -42,7 +42,7 @@ ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *** ** For history of changes, see Documentation/scsi/ChangeLog.arcmsr -** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt +** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt *** */ #include linux/module.h @@ -90,6 +90,8 @@ static int arcmsr_bios_param(struct scsi 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); @@ -167,6 +169,8 @@ static struct pci_driver arcmsr_pci_driv .id_table = arcmsr_device_id_table, .probe = arcmsr_probe, .remove = arcmsr_remove, + .suspend= arcmsr_suspend, + .resume = arcmsr_resume, .shutdown = arcmsr_shutdown, }; /* @@ -603,6 +607,80 @@ static void arcmsr_message_isr_bh_fn(str } } +static int arcmsr_suspend(struct pci_dev *pdev, pm_message_t state) +{ + int i; + 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); + del_timer_sync(acb-eternal_timer); + flush_scheduled_work(); + arcmsr_stop_adapter_bgrb(acb); + arcmsr_flush_adapter_cache(acb); + arcmsr_enable_outbound_ints(acb, intmask_org); + 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, i, j; + 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)) { + printk(%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) { + printk(KERN_WARNING + scsi%d: No suitable DMA mask available\n, + host-host_no); + goto controller_unregister; + } + } + pci_set_master(pdev); + arcmsr_iop_init(acb); + if (request_irq(pdev-irq, arcmsr_do_interrupt, IRQF_SHARED, arcmsr, acb)) { + printk(arcmsr%d: request_irq =%d failed!\n, acb-host-host_no, pdev-irq); + goto controller_stop; + } + timer_init: + 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 int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) {
[PATCH 3/5] SCSI: Support MSI and MSI-X
From: Nick Cheng nick.ch...@areca.com.tw Support MSI or MSI-X for whole series of RAID controllers. Meanwhole correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng nick.ch...@areca.com.tw diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:16:18.114629695 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:17:44.826628853 +0800 @@ -63,7 +63,8 @@ struct device_attribute; #define ARCMSR_DEFAULT_SG_ENTRIES 38 #define ARCMSR_MAX_HBB_POSTQUEUE 264 #define ARCMSR_MAX_XFER_LEN 0x26000 /* 152K */ -#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMST_NUM_MSIX_VECTORS4 #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_toutbound_int_enable; uint32_tcdb_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_headccb_free_list; diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:16:18.214629692 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:17:44.834628853 +0800 @@ -61,7 +61,6 @@ #include linux/aer.h #include asm/dma.h #include asm/io.h -#include asm/system.h #include asm/uaccess.h #include scsi/scsi_host.h #include scsi/scsi.h @@ -82,7 +81,7 @@ MODULE_VERSION(ARCMSR_DRIVER_VERSION); 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); +static void arcmsr_iop_confirm(struct AdapterControlBlock *acb); static int arcmsr_abort(struct scsi_cmnd *); static int arcmsr_bus_reset(struct scsi_cmnd *); static int arcmsr_bios_param(struct scsi_device *sdev, @@ -97,6 +96,8 @@ static void arcmsr_shutdown(struct pci_d 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_hbaA_flush_cache(struct AdapterControlBlock *acb); static void arcmsr_hbaB_flush_cache(struct AdapterControlBlock *acb); @@ -227,8 +228,8 @@ static bool arcmsr_remap_pciregion(struc printk(KERN_NOTICE arcmsr%d: memory mapping region fail \n, acb-host-host_no); return false; } - if (readl(acb-pmuC-outbound_doorbell) ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { - writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, acb-pmuC-outbound_doorbell_clear);/*clear interrupt*/ + if (ioread32(acb-pmuC-outbound_doorbell) ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { + iowrite32(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, acb-pmuC-outbound_doorbell_clear);/*clear interrupt*/ return true; } break; @@ -357,9 +358,9 @@ static uint8_t arcmsr_hbaC_wait_msgint_r int i; for (i = 0; i 2000; i++) { - if (readl(phbcmu-outbound_doorbell) + if (ioread32(phbcmu-outbound_doorbell) ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { - writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, + iowrite32(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, phbcmu-outbound_doorbell_clear); /*clear interrupt*/ return true; } @@ -404,9 +405,11 @@ static void arcmsr_hbaB_flush_cache(stru static void arcmsr_hbaC_flush_cache(struct AdapterControlBlock *pACB) { struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB-pmuC; -
[PATCH 5/5] SCSI: Add the spinlock for queue buffer access
From: Nick Cheng nick.ch...@areca.com.tw Add the spinlock for queue buffer access Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:31:31.742620819 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:31:04.098621088 +0800 @@ -617,6 +617,8 @@ struct AdapterControlBlock spinlock_t eh_lock; spinlock_t ccblist_lock; spinlock_t postq_lock; + spinlock_t rqbuffer_lock; + spinlock_t wqbuffer_lock; union { struct MessageUnit_A __iomem *pmuA; struct MessageUnit_B*pmuB; diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:31:31.754620820 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:31:04.118621087 +0800 @@ -987,6 +987,8 @@ static int arcmsr_probe(struct pci_dev * spin_lock_init(acb-eh_lock); spin_lock_init(acb-ccblist_lock); spin_lock_init(acb-postq_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); @@ -1927,10 +1929,12 @@ static struct QBUFFER __iomem *arcmsr_ge static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) { + uint8_t __iomem *iop_data; struct QBUFFER __iomem *prbuffer; struct QBUFFER *pQbuffer; - uint8_t __iomem *iop_data; int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; + unsigned long flags; + spin_lock_irqsave(acb-rqbuffer_lock, flags); rqbuf_lastindex = acb-rqbuf_lastindex; rqbuf_firstindex = acb-rqbuf_firstindex; prbuffer = arcmsr_get_iop_rqbuffer(acb); @@ -1952,10 +1956,13 @@ static void arcmsr_iop2drv_data_wrote_ha } else { acb-acb_flags |= ACB_F_IOPDATA_OVERFLOW; } + spin_unlock_irqrestore(acb-rqbuffer_lock, flags); } static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) { + unsigned long flags; + spin_lock_irqsave(acb-wqbuffer_lock, flags); acb-acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; if (acb-wqbuf_firstindex != acb-wqbuf_lastindex) { uint8_t *pQbuffer; @@ -1984,6 +1991,7 @@ static void arcmsr_iop2drv_data_read_han 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) @@ -2403,6 +2411,7 @@ static int arcmsr_iop_message_xfer(struc unsigned char *ver_addr; uint8_t *pQbuffer, *ptmpQbuffer; int32_t allxfer_len = 0; + unsigned long flags; ver_addr = kmalloc(1032, GFP_ATOMIC); if (!ver_addr) { @@ -2411,6 +2420,7 @@ static int arcmsr_iop_message_xfer(struc } ptmpQbuffer = ver_addr; + spin_lock_irqsave(acb-rqbuffer_lock, flags); while ((acb-rqbuf_firstindex != acb-rqbuf_lastindex) (allxfer_len 1031)) { pQbuffer = acb-rqbuffer[acb-rqbuf_firstindex]; @@ -2439,6 +2449,7 @@ static int arcmsr_iop_message_xfer(struc } arcmsr_iop_message_read(acb); } + spin_unlock_irqrestore(acb-rqbuffer_lock, flags); memcpy(pcmdmessagefld-messagedatabuffer, ver_addr, allxfer_len); pcmdmessagefld-cmdmessage.Length = allxfer_len; if(acb-fw_flag == FW_DEADLOCK) { @@ -2452,8 +2463,9 @@ static int arcmsr_iop_message_xfer(struc case ARCMSR_MESSAGE_WRITE_WQBUFFER: { unsigned char *ver_addr; - int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; uint8_t *pQbuffer, *ptmpuserbuffer; + int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; + unsigned long flags; ver_addr = kmalloc(1032, GFP_ATOMIC); if (!ver_addr) { @@ -2470,6 +2482,7 @@ static int arcmsr_iop_message_xfer(struc ptmpuserbuffer = ver_addr; user_len = pcmdmessagefld-cmdmessage.Length; memcpy(ptmpuserbuffer,
[PATCH 1/5] SCSI: Re-name the HBA Type
From: Nick Cheng nick.ch...@areca.com.tw Replace the nameing, hba, hbb and hbc, with hbaA, hbaB abd hbaC respectively Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:43:58.542648536 +0800 @@ -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 Driver Version 1.20.00.15 2012/09/30 #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 #define ARCMSR_MAX_XFER_SECTORS_B 4096 diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:43:58.542648536 +0800 @@ -61,6 +61,7 @@ #include linux/aer.h #include asm/dma.h #include asm/io.h +#include asm/system.h #include asm/uaccess.h #include scsi/scsi_host.h #include scsi/scsi.h @@ -95,16 +96,16 @@ static void arcmsr_iop_init(struct Adapt static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb); static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); 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); @@ -308,7 +309,7 @@ static void arcmsr_define_adapter_type(s } } -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; @@ -326,7 +327,7 @@ static uint8_t arcmsr_hba_wait_msgint_re 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; @@ -346,7 +347,7 @@ static uint8_t arcmsr_hbb_wait_msgint_re 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; @@ -364,13 +365,13 @@ static uint8_t arcmsr_hbc_wait_msgint_re 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, reg-inbound_msgaddr0); do { - if (arcmsr_hba_wait_msgint_ready(acb)) + if (arcmsr_hbaA_wait_msgint_ready(acb)) break; else { retry_count--; @@ -380,13 +381,13 @@ static void arcmsr_flush_hba_cache(struc } 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
[PATCH 2/5] SCSI: Support Hibernation
From: Nick Cheng nick.ch...@areca.com.tw Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:08:33.338634210 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:50:32.694644708 +0800 @@ -42,7 +42,7 @@ ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *** ** For history of changes, see Documentation/scsi/ChangeLog.arcmsr -** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt +** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt *** */ #include linux/module.h @@ -90,6 +90,8 @@ static int arcmsr_bios_param(struct scsi 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); @@ -167,6 +169,8 @@ static struct pci_driver arcmsr_pci_driv .id_table = arcmsr_device_id_table, .probe = arcmsr_probe, .remove = arcmsr_remove, + .suspend= arcmsr_suspend, + .resume = arcmsr_resume, .shutdown = arcmsr_shutdown, }; /* @@ -603,6 +607,80 @@ static void arcmsr_message_isr_bh_fn(str } } +static int arcmsr_suspend(struct pci_dev *pdev, pm_message_t state) +{ + int i; + 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); + del_timer_sync(acb-eternal_timer); + flush_scheduled_work(); + arcmsr_stop_adapter_bgrb(acb); + arcmsr_flush_adapter_cache(acb); + arcmsr_enable_outbound_ints(acb, intmask_org); + 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, i, j; + 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)) { + printk(%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) { + printk(KERN_WARNING + scsi%d: No suitable DMA mask available\n, + host-host_no); + goto controller_unregister; + } + } + pci_set_master(pdev); + arcmsr_iop_init(acb); + if (request_irq(pdev-irq, arcmsr_do_interrupt, IRQF_SHARED, arcmsr, acb)) { + printk(arcmsr%d: request_irq =%d failed!\n, acb-host-host_no, pdev-irq); + goto controller_stop; + } + timer_init: + 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 int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) {
[PATCH 3/5] SCSI: Support MSI and MSI-X
From: Nick Cheng nick.ch...@areca.com.tw Support MSI or MSI-X for whole series of RAID controllers. Meanwhole correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:16:18.114629695 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:17:44.826628853 +0800 @@ -63,7 +63,8 @@ struct device_attribute; #define ARCMSR_DEFAULT_SG_ENTRIES 38 #define ARCMSR_MAX_HBB_POSTQUEUE 264 #define ARCMSR_MAX_XFER_LEN 0x26000 /* 152K */ -#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMST_NUM_MSIX_VECTORS4 #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_toutbound_int_enable; uint32_tcdb_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_headccb_free_list; diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:16:18.214629692 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:17:44.834628853 +0800 @@ -61,7 +61,6 @@ #include linux/aer.h #include asm/dma.h #include asm/io.h -#include asm/system.h #include asm/uaccess.h #include scsi/scsi_host.h #include scsi/scsi.h @@ -82,7 +81,7 @@ MODULE_VERSION(ARCMSR_DRIVER_VERSION); 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); +static void arcmsr_iop_confirm(struct AdapterControlBlock *acb); static int arcmsr_abort(struct scsi_cmnd *); static int arcmsr_bus_reset(struct scsi_cmnd *); static int arcmsr_bios_param(struct scsi_device *sdev, @@ -97,6 +96,8 @@ static void arcmsr_shutdown(struct pci_d 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_hbaA_flush_cache(struct AdapterControlBlock *acb); static void arcmsr_hbaB_flush_cache(struct AdapterControlBlock *acb); @@ -227,8 +228,8 @@ static bool arcmsr_remap_pciregion(struc printk(KERN_NOTICE arcmsr%d: memory mapping region fail \n, acb-host-host_no); return false; } - if (readl(acb-pmuC-outbound_doorbell) ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { - writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, acb-pmuC-outbound_doorbell_clear);/*clear interrupt*/ + if (ioread32(acb-pmuC-outbound_doorbell) ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { + iowrite32(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, acb-pmuC-outbound_doorbell_clear);/*clear interrupt*/ return true; } break; @@ -357,9 +358,9 @@ static uint8_t arcmsr_hbaC_wait_msgint_r int i; for (i = 0; i 2000; i++) { - if (readl(phbcmu-outbound_doorbell) + if (ioread32(phbcmu-outbound_doorbell) ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { - writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, + iowrite32(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, phbcmu-outbound_doorbell_clear); /*clear interrupt*/ return true; } @@ -404,9 +405,11 @@ static void arcmsr_hbaB_flush_cache(stru static void arcmsr_hbaC_flush_cache(struct AdapterControlBlock *pACB) { struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB-pmuC; -
[PATCH 5/5] SCSI: Add the spinlock for queue buffer access
From: Nick Cheng nick.ch...@areca.com.tw Add the spinlock for queue buffer access Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:31:31.742620819 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:31:04.098621088 +0800 @@ -617,6 +617,8 @@ struct AdapterControlBlock spinlock_t eh_lock; spinlock_t ccblist_lock; spinlock_t postq_lock; + spinlock_t rqbuffer_lock; + spinlock_t wqbuffer_lock; union { struct MessageUnit_A __iomem *pmuA; struct MessageUnit_B*pmuB; diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:31:31.754620820 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:31:04.118621087 +0800 @@ -987,6 +987,8 @@ static int arcmsr_probe(struct pci_dev * spin_lock_init(acb-eh_lock); spin_lock_init(acb-ccblist_lock); spin_lock_init(acb-postq_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); @@ -1927,10 +1929,12 @@ static struct QBUFFER __iomem *arcmsr_ge static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) { + uint8_t __iomem *iop_data; struct QBUFFER __iomem *prbuffer; struct QBUFFER *pQbuffer; - uint8_t __iomem *iop_data; int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; + unsigned long flags; + spin_lock_irqsave(acb-rqbuffer_lock, flags); rqbuf_lastindex = acb-rqbuf_lastindex; rqbuf_firstindex = acb-rqbuf_firstindex; prbuffer = arcmsr_get_iop_rqbuffer(acb); @@ -1952,10 +1956,13 @@ static void arcmsr_iop2drv_data_wrote_ha } else { acb-acb_flags |= ACB_F_IOPDATA_OVERFLOW; } + spin_unlock_irqrestore(acb-rqbuffer_lock, flags); } static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) { + unsigned long flags; + spin_lock_irqsave(acb-wqbuffer_lock, flags); acb-acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; if (acb-wqbuf_firstindex != acb-wqbuf_lastindex) { uint8_t *pQbuffer; @@ -1984,6 +1991,7 @@ static void arcmsr_iop2drv_data_read_han 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) @@ -2403,6 +2411,7 @@ static int arcmsr_iop_message_xfer(struc unsigned char *ver_addr; uint8_t *pQbuffer, *ptmpQbuffer; int32_t allxfer_len = 0; + unsigned long flags; ver_addr = kmalloc(1032, GFP_ATOMIC); if (!ver_addr) { @@ -2411,6 +2420,7 @@ static int arcmsr_iop_message_xfer(struc } ptmpQbuffer = ver_addr; + spin_lock_irqsave(acb-rqbuffer_lock, flags); while ((acb-rqbuf_firstindex != acb-rqbuf_lastindex) (allxfer_len 1031)) { pQbuffer = acb-rqbuffer[acb-rqbuf_firstindex]; @@ -2439,6 +2449,7 @@ static int arcmsr_iop_message_xfer(struc } arcmsr_iop_message_read(acb); } + spin_unlock_irqrestore(acb-rqbuffer_lock, flags); memcpy(pcmdmessagefld-messagedatabuffer, ver_addr, allxfer_len); pcmdmessagefld-cmdmessage.Length = allxfer_len; if(acb-fw_flag == FW_DEADLOCK) { @@ -2452,8 +2463,9 @@ static int arcmsr_iop_message_xfer(struc case ARCMSR_MESSAGE_WRITE_WQBUFFER: { unsigned char *ver_addr; - int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; uint8_t *pQbuffer, *ptmpuserbuffer; + int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; + unsigned long flags; ver_addr = kmalloc(1032, GFP_ATOMIC); if (!ver_addr) { @@ -2470,6 +2482,7 @@ static int arcmsr_iop_message_xfer(struc ptmpuserbuffer = ver_addr; user_len = pcmdmessagefld-cmdmessage.Length; memcpy(ptmpuserbuffer,
[PATCH 5/5] arcmsr: Add the spinlock for queue buffer access
From: Nick Cheng nick.ch...@areca.com.tw Add the spinlock for queue buffer access Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:31:31.742620819 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:31:04.098621088 +0800 @@ -617,6 +617,8 @@ struct AdapterControlBlock spinlock_t eh_lock; spinlock_t ccblist_lock; spinlock_t postq_lock; + spinlock_t rqbuffer_lock; + spinlock_t wqbuffer_lock; union { struct MessageUnit_A __iomem *pmuA; struct MessageUnit_B*pmuB; diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:31:31.754620820 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:31:04.118621087 +0800 @@ -987,6 +987,8 @@ static int arcmsr_probe(struct pci_dev * spin_lock_init(acb-eh_lock); spin_lock_init(acb-ccblist_lock); spin_lock_init(acb-postq_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); @@ -1927,10 +1929,12 @@ static struct QBUFFER __iomem *arcmsr_ge static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) { + uint8_t __iomem *iop_data; struct QBUFFER __iomem *prbuffer; struct QBUFFER *pQbuffer; - uint8_t __iomem *iop_data; int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; + unsigned long flags; + spin_lock_irqsave(acb-rqbuffer_lock, flags); rqbuf_lastindex = acb-rqbuf_lastindex; rqbuf_firstindex = acb-rqbuf_firstindex; prbuffer = arcmsr_get_iop_rqbuffer(acb); @@ -1952,10 +1956,13 @@ static void arcmsr_iop2drv_data_wrote_ha } else { acb-acb_flags |= ACB_F_IOPDATA_OVERFLOW; } + spin_unlock_irqrestore(acb-rqbuffer_lock, flags); } static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) { + unsigned long flags; + spin_lock_irqsave(acb-wqbuffer_lock, flags); acb-acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; if (acb-wqbuf_firstindex != acb-wqbuf_lastindex) { uint8_t *pQbuffer; @@ -1984,6 +1991,7 @@ static void arcmsr_iop2drv_data_read_han 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) @@ -2403,6 +2411,7 @@ static int arcmsr_iop_message_xfer(struc unsigned char *ver_addr; uint8_t *pQbuffer, *ptmpQbuffer; int32_t allxfer_len = 0; + unsigned long flags; ver_addr = kmalloc(1032, GFP_ATOMIC); if (!ver_addr) { @@ -2411,6 +2420,7 @@ static int arcmsr_iop_message_xfer(struc } ptmpQbuffer = ver_addr; + spin_lock_irqsave(acb-rqbuffer_lock, flags); while ((acb-rqbuf_firstindex != acb-rqbuf_lastindex) (allxfer_len 1031)) { pQbuffer = acb-rqbuffer[acb-rqbuf_firstindex]; @@ -2439,6 +2449,7 @@ static int arcmsr_iop_message_xfer(struc } arcmsr_iop_message_read(acb); } + spin_unlock_irqrestore(acb-rqbuffer_lock, flags); memcpy(pcmdmessagefld-messagedatabuffer, ver_addr, allxfer_len); pcmdmessagefld-cmdmessage.Length = allxfer_len; if(acb-fw_flag == FW_DEADLOCK) { @@ -2452,8 +2463,9 @@ static int arcmsr_iop_message_xfer(struc case ARCMSR_MESSAGE_WRITE_WQBUFFER: { unsigned char *ver_addr; - int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; uint8_t *pQbuffer, *ptmpuserbuffer; + int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; + unsigned long flags; ver_addr = kmalloc(1032, GFP_ATOMIC); if (!ver_addr) { @@ -2470,6 +2482,7 @@ static int arcmsr_iop_message_xfer(struc ptmpuserbuffer = ver_addr; user_len = pcmdmessagefld-cmdmessage.Length; memcpy(ptmpuserbuffer,
[PATCH 1/5] arcmsr: Re-name the HBA Type
From: Nick Cheng nick.ch...@areca.com.tw Replace the nameing, hba, hbb and hbc, with hbaA, hbaB abd hbaC respectively Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 18:43:58.542648536 +0800 @@ -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 Driver Version 1.20.00.15 2012/09/30 #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 #define ARCMSR_MAX_XFER_SECTORS_B 4096 diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:29:18.030657090 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:43:58.542648536 +0800 @@ -61,6 +61,7 @@ #include linux/aer.h #include asm/dma.h #include asm/io.h +#include asm/system.h #include asm/uaccess.h #include scsi/scsi_host.h #include scsi/scsi.h @@ -95,16 +96,16 @@ static void arcmsr_iop_init(struct Adapt static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb); static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); 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); @@ -308,7 +309,7 @@ static void arcmsr_define_adapter_type(s } } -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; @@ -326,7 +327,7 @@ static uint8_t arcmsr_hba_wait_msgint_re 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; @@ -346,7 +347,7 @@ static uint8_t arcmsr_hbb_wait_msgint_re 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; @@ -364,13 +365,13 @@ static uint8_t arcmsr_hbc_wait_msgint_re 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, reg-inbound_msgaddr0); do { - if (arcmsr_hba_wait_msgint_ready(acb)) + if (arcmsr_hbaA_wait_msgint_ready(acb)) break; else { retry_count--; @@ -380,13 +381,13 @@ static void arcmsr_flush_hba_cache(struc } 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
[PATCH 2/5] arcmsr: Support Hibernation
From: Nick Cheng nick.ch...@areca.com.tw Support hibernation for whole series of RAID controllers Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:08:33.338634210 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 18:50:32.694644708 +0800 @@ -42,7 +42,7 @@ ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *** ** For history of changes, see Documentation/scsi/ChangeLog.arcmsr -** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt +** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt *** */ #include linux/module.h @@ -90,6 +90,8 @@ static int arcmsr_bios_param(struct scsi 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); @@ -167,6 +169,8 @@ static struct pci_driver arcmsr_pci_driv .id_table = arcmsr_device_id_table, .probe = arcmsr_probe, .remove = arcmsr_remove, + .suspend= arcmsr_suspend, + .resume = arcmsr_resume, .shutdown = arcmsr_shutdown, }; /* @@ -603,6 +607,80 @@ static void arcmsr_message_isr_bh_fn(str } } +static int arcmsr_suspend(struct pci_dev *pdev, pm_message_t state) +{ + int i; + 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); + del_timer_sync(acb-eternal_timer); + flush_scheduled_work(); + arcmsr_stop_adapter_bgrb(acb); + arcmsr_flush_adapter_cache(acb); + arcmsr_enable_outbound_ints(acb, intmask_org); + 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, i, j; + 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)) { + printk(%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) { + printk(KERN_WARNING + scsi%d: No suitable DMA mask available\n, + host-host_no); + goto controller_unregister; + } + } + pci_set_master(pdev); + arcmsr_iop_init(acb); + if (request_irq(pdev-irq, arcmsr_do_interrupt, IRQF_SHARED, arcmsr, acb)) { + printk(arcmsr%d: request_irq =%d failed!\n, acb-host-host_no, pdev-irq); + goto controller_stop; + } + timer_init: + 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 int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) {
[PATCH 3/5] arcmsr: Support MSI and MSI-X
From: Nick Cheng nick.ch...@areca.com.tw Support MSI or MSI-X for whole series of RAID controllers. Meanwhile correct the register access as iowrite32/ioread32 Signed-off-by: Nick Cheng nick.ch...@areca.com.tw --- diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr.h linux-development//drivers/scsi/arcmsr/arcmsr.h --- linux-vanilla//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:16:18.114629695 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr.h 2012-10-03 19:17:44.826628853 +0800 @@ -63,7 +63,8 @@ struct device_attribute; #define ARCMSR_DEFAULT_SG_ENTRIES 38 #define ARCMSR_MAX_HBB_POSTQUEUE 264 #define ARCMSR_MAX_XFER_LEN 0x26000 /* 152K */ -#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMST_NUM_MSIX_VECTORS4 #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_toutbound_int_enable; uint32_tcdb_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_headccb_free_list; diff -uprN -X linux-vanilla/Documentation/dontdiff linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c linux-development//drivers/scsi/arcmsr/arcmsr_hba.c --- linux-vanilla//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:16:18.214629692 +0800 +++ linux-development//drivers/scsi/arcmsr/arcmsr_hba.c 2012-10-03 19:17:44.834628853 +0800 @@ -61,7 +61,6 @@ #include linux/aer.h #include asm/dma.h #include asm/io.h -#include asm/system.h #include asm/uaccess.h #include scsi/scsi_host.h #include scsi/scsi.h @@ -82,7 +81,7 @@ MODULE_VERSION(ARCMSR_DRIVER_VERSION); 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); +static void arcmsr_iop_confirm(struct AdapterControlBlock *acb); static int arcmsr_abort(struct scsi_cmnd *); static int arcmsr_bus_reset(struct scsi_cmnd *); static int arcmsr_bios_param(struct scsi_device *sdev, @@ -97,6 +96,8 @@ static void arcmsr_shutdown(struct pci_d 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_hbaA_flush_cache(struct AdapterControlBlock *acb); static void arcmsr_hbaB_flush_cache(struct AdapterControlBlock *acb); @@ -227,8 +228,8 @@ static bool arcmsr_remap_pciregion(struc printk(KERN_NOTICE arcmsr%d: memory mapping region fail \n, acb-host-host_no); return false; } - if (readl(acb-pmuC-outbound_doorbell) ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { - writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, acb-pmuC-outbound_doorbell_clear);/*clear interrupt*/ + if (ioread32(acb-pmuC-outbound_doorbell) ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { + iowrite32(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, acb-pmuC-outbound_doorbell_clear);/*clear interrupt*/ return true; } break; @@ -357,9 +358,9 @@ static uint8_t arcmsr_hbaC_wait_msgint_r int i; for (i = 0; i 2000; i++) { - if (readl(phbcmu-outbound_doorbell) + if (ioread32(phbcmu-outbound_doorbell) ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { - writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, + iowrite32(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, phbcmu-outbound_doorbell_clear); /*clear interrupt*/ return true; } @@ -404,9 +405,11 @@ static void arcmsr_hbaB_flush_cache(stru static void arcmsr_hbaC_flush_cache(struct AdapterControlBlock *pACB) { struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB-pmuC; -
RE: arcmsr & areca-1660 - strange behaviour under heavy load
Hi Nikola, As I said, we will test on our site. Our support team will help you to settle the issue. Sorry for your inconvenience, -Original Message- From: Nikola Ciprich [mailto:[EMAIL PROTECTED] Sent: Tuesday, February 26, 2008 5:36 PM To: Andrew Morton Cc: linux-kernel@vger.kernel.org; [EMAIL PROTECTED]; Nick Cheng; Erich Chen; [EMAIL PROTECTED] Subject: Re: arcmsr & areca-1660 - strange behaviour under heavy load Hi On Sun, 24 Feb 2008, Andrew Morton wrote: Hi Andrew, thanks a lot for reply, I'm attaching requested information. please let me know if You need more information/testing, whatever. I'll be glad to help. BR nik >> Areca support doesn't seem to be very interested in the problem :-( > > (cc's added) > > Please get the machine into this state of memory exhaustion then take > copies of the output of the following, and send them via reply-to-all to > this email: > > - cat /proc/meminfo > > - cat /proc/slabinfo > > - dmesg -c > /dev/null ; echo m > /proc/sysrq-trigger ; dmesg -c > > Thanks. > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to [EMAIL PROTECTED] > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ > > -- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: arcmsr areca-1660 - strange behaviour under heavy load
Hi Nikola, As I said, we will test on our site. Our support team will help you to settle the issue. Sorry for your inconvenience, -Original Message- From: Nikola Ciprich [mailto:[EMAIL PROTECTED] Sent: Tuesday, February 26, 2008 5:36 PM To: Andrew Morton Cc: linux-kernel@vger.kernel.org; [EMAIL PROTECTED]; Nick Cheng; Erich Chen; [EMAIL PROTECTED] Subject: Re: arcmsr areca-1660 - strange behaviour under heavy load Hi On Sun, 24 Feb 2008, Andrew Morton wrote: Hi Andrew, thanks a lot for reply, I'm attaching requested information. please let me know if You need more information/testing, whatever. I'll be glad to help. BR nik Areca support doesn't seem to be very interested in the problem :-( (cc's added) Please get the machine into this state of memory exhaustion then take copies of the output of the following, and send them via reply-to-all to this email: - cat /proc/meminfo - cat /proc/slabinfo - dmesg -c /dev/null ; echo m /proc/sysrq-trigger ; dmesg -c Thanks. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1
Hi Aron, Thanks for your patience. If you still got into trouble, please let me know. Thank you again, -Original Message- From: Aron Stansvik [mailto:[EMAIL PROTECTED] Sent: Tuesday, February 26, 2008 6:52 AM To: erich Cc: [EMAIL PROTECTED]; [EMAIL PROTECTED]; [EMAIL PROTECTED]; linux-kernel@vger.kernel.org Subject: Re: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1 Hi Erich. 2008/2/25, nickcheng <[EMAIL PROTECTED]>: > Hi Aron, > From our field experiences and customers' feedbacks, all of them direct to > vibration and power issues. > The vibration could be caused by FANs not only by themselves. Okay. I have a chassi fan that is quite close to the drives, I will try disabling it. I've also ordered two Nexus TwinDisk anti vibration harddrive mounts with which I'll place the disks in my 5.25" slots instead, away from any fans. If this doesn't work, I'm stumped, as I really don't think it's the power supply and I don't have the money to buy a new one. > You mentioned it could be the F/W issue. > If the environment does not meet the prerequisite, FW could not work > correctly. > Actually FW just reacts to the situations not it causes the issue. Of course, I understand this. Just trying to figure this problem out.. > Please check it out!! I'll report back with my findings with moving disk away from fans and using anti-vibrations mounts. Thanks for taking your time to reply. Aron > Thank you, > > > -Original Message- > From: Aron Stansvik [mailto:[EMAIL PROTECTED] > Sent: Sunday, February 24, 2008 1:54 AM > To: [EMAIL PROTECTED] > Cc: erich; [EMAIL PROTECTED]; [EMAIL PROTECTED]; > linux-kernel@vger.kernel.org > > Subject: Re: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1 > > Hello again Areca and LKML hackers. > > 2008/2/18, Aron Stansvik <[EMAIL PROTECTED]>: > > Hello Nick. > > > > Sorry that I'm not answering until now. I've been busy. > > > > 2008/2/13, nickcheng <[EMAIL PROTECTED]>: > > > > > Hi Aron, > > > From our experience and some customers' feedback, your issue could be > caused > > > by power instability or vibration to your HDs. > > > Please check step by step: > > > (1).under your original environment, increase the SCSI command value, > > > default=30, with the shell script, set_scsicmd_timeout(). 90 or 120 is > > > enough. > > > (2).if method 1 does not work, find out the vibration source or change > the > > > power supply > > > > > > I will try to increase that value. I don't think it's vibration; the > > disks are firmly in place in a very heavy chassi (Silverstone > > SST-TJ05B-T). And I really don't think there's something wrong with > > the power supply, it's a pretty new Silverstone ST65ZF 650W. This is > > my own personal workstation, so I don't just have another power supply > > to test with :/ > > > > I will report back on my success/failure. Thanks for your answer. > > I've now tried with both 90 and 120 for the timeout value, and the > problem still persists. It seems to happen when lots of small writes > are occuring, e.g. when installing something. > > I really don't think the disks are vibrating, I don't see how they > could. One more thing I'm going to test is to use the legacy ATA power > connector instead of the SATA power connector. This was what I was > using before when I only had a single drive and no RAID controller. > Maybe my power supply is malfunctioning and not giving enough power on > the SATA power connectors.. but I doubt it. > > Is there anything else that could cause this? Have you guys at Areca > tested the ARC-1200 with Raptors in RAID1? > > :( > > Regards, > Aron > > > > > > > Aron > > > > > > > If your still have any questions, please feel free to let me know. > > > > > > P.S. The attached driver source, arcmsr-1.20.00.15-71224, has been > > > upstreamed to kernel.org and will be released in kernel 2.6.25. If you > like, > > > you could update your driver with it. > > > It fixes some minor bugs, but these bugs are nothing to do with your > issue. > > > > > > > > > -Original Message- > > > From: erich [mailto:[EMAIL PROTECTED] > > > Sent: Wednesday, February 13, 2008 4:33 PM > > > To: (廣安科技)鄭守謙 > > > Subject: Fw: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1 > > > > > > > > > > > > - Original Message - > > > From: "Andrew Morton
RE: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1
Hi Aron, Thanks for your patience. If you still got into trouble, please let me know. Thank you again, -Original Message- From: Aron Stansvik [mailto:[EMAIL PROTECTED] Sent: Tuesday, February 26, 2008 6:52 AM To: erich Cc: [EMAIL PROTECTED]; [EMAIL PROTECTED]; [EMAIL PROTECTED]; linux-kernel@vger.kernel.org Subject: Re: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1 Hi Erich. 2008/2/25, nickcheng [EMAIL PROTECTED]: Hi Aron, From our field experiences and customers' feedbacks, all of them direct to vibration and power issues. The vibration could be caused by FANs not only by themselves. Okay. I have a chassi fan that is quite close to the drives, I will try disabling it. I've also ordered two Nexus TwinDisk anti vibration harddrive mounts with which I'll place the disks in my 5.25 slots instead, away from any fans. If this doesn't work, I'm stumped, as I really don't think it's the power supply and I don't have the money to buy a new one. You mentioned it could be the F/W issue. If the environment does not meet the prerequisite, FW could not work correctly. Actually FW just reacts to the situations not it causes the issue. Of course, I understand this. Just trying to figure this problem out.. Please check it out!! I'll report back with my findings with moving disk away from fans and using anti-vibrations mounts. Thanks for taking your time to reply. Aron Thank you, -Original Message- From: Aron Stansvik [mailto:[EMAIL PROTECTED] Sent: Sunday, February 24, 2008 1:54 AM To: [EMAIL PROTECTED] Cc: erich; [EMAIL PROTECTED]; [EMAIL PROTECTED]; linux-kernel@vger.kernel.org Subject: Re: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1 Hello again Areca and LKML hackers. 2008/2/18, Aron Stansvik [EMAIL PROTECTED]: Hello Nick. Sorry that I'm not answering until now. I've been busy. 2008/2/13, nickcheng [EMAIL PROTECTED]: Hi Aron, From our experience and some customers' feedback, your issue could be caused by power instability or vibration to your HDs. Please check step by step: (1).under your original environment, increase the SCSI command value, default=30, with the shell script, set_scsicmd_timeout(). 90 or 120 is enough. (2).if method 1 does not work, find out the vibration source or change the power supply I will try to increase that value. I don't think it's vibration; the disks are firmly in place in a very heavy chassi (Silverstone SST-TJ05B-T). And I really don't think there's something wrong with the power supply, it's a pretty new Silverstone ST65ZF 650W. This is my own personal workstation, so I don't just have another power supply to test with :/ I will report back on my success/failure. Thanks for your answer. I've now tried with both 90 and 120 for the timeout value, and the problem still persists. It seems to happen when lots of small writes are occuring, e.g. when installing something. I really don't think the disks are vibrating, I don't see how they could. One more thing I'm going to test is to use the legacy ATA power connector instead of the SATA power connector. This was what I was using before when I only had a single drive and no RAID controller. Maybe my power supply is malfunctioning and not giving enough power on the SATA power connectors.. but I doubt it. Is there anything else that could cause this? Have you guys at Areca tested the ARC-1200 with Raptors in RAID1? :( Regards, Aron Aron If your still have any questions, please feel free to let me know. P.S. The attached driver source, arcmsr-1.20.00.15-71224, has been upstreamed to kernel.org and will be released in kernel 2.6.25. If you like, you could update your driver with it. It fixes some minor bugs, but these bugs are nothing to do with your issue. -Original Message- From: erich [mailto:[EMAIL PROTECTED] Sent: Wednesday, February 13, 2008 4:33 PM To: (廣安科技)鄭守謙 Subject: Fw: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1 - Original Message - From: Andrew Morton [EMAIL PROTECTED] To: Aron Stansvik [EMAIL PROTECTED] Cc: linux-kernel@vger.kernel.org; [EMAIL PROTECTED]; erich [EMAIL PROTECTED] Sent: Wednesday, February 13, 2008 4:03 PM Subject: Re: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1 (cc's added) On Mon, 11 Feb 2008 17:44:08 +0100 Aron Stansvik [EMAIL PROTECTED] wrote: Hello LKML. Under semi-high disk I/O (e.g. installing a compiled KDE), I get the following (accompanied by seconds of lock-ups on the machine): [ 7727.345183] arcmsr0: abort device command of scsi id = 0 lun = 0 [ 7730.348776] arcmsr0
RE: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1
Hi Aron, >From our field experiences and customers' feedbacks, all of them direct to vibration and power issues. The vibration could be caused by FANs not only by themselves. You mentioned it could be the F/W issue. If the environment does not meet the prerequisite, FW could not work correctly. Actually FW just reacts to the situations not it causes the issue. Please check it out!! Thank you, -Original Message- From: Aron Stansvik [mailto:[EMAIL PROTECTED] Sent: Sunday, February 24, 2008 1:54 AM To: [EMAIL PROTECTED] Cc: erich; [EMAIL PROTECTED]; [EMAIL PROTECTED]; linux-kernel@vger.kernel.org Subject: Re: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1 Hello again Areca and LKML hackers. 2008/2/18, Aron Stansvik <[EMAIL PROTECTED]>: > Hello Nick. > > Sorry that I'm not answering until now. I've been busy. > > 2008/2/13, nickcheng <[EMAIL PROTECTED]>: > > > Hi Aron, > > From our experience and some customers' feedback, your issue could be caused > > by power instability or vibration to your HDs. > > Please check step by step: > > (1).under your original environment, increase the SCSI command value, > > default=30, with the shell script, set_scsicmd_timeout(). 90 or 120 is > > enough. > > (2).if method 1 does not work, find out the vibration source or change the > > power supply > > > I will try to increase that value. I don't think it's vibration; the > disks are firmly in place in a very heavy chassi (Silverstone > SST-TJ05B-T). And I really don't think there's something wrong with > the power supply, it's a pretty new Silverstone ST65ZF 650W. This is > my own personal workstation, so I don't just have another power supply > to test with :/ > > I will report back on my success/failure. Thanks for your answer. I've now tried with both 90 and 120 for the timeout value, and the problem still persists. It seems to happen when lots of small writes are occuring, e.g. when installing something. I really don't think the disks are vibrating, I don't see how they could. One more thing I'm going to test is to use the legacy ATA power connector instead of the SATA power connector. This was what I was using before when I only had a single drive and no RAID controller. Maybe my power supply is malfunctioning and not giving enough power on the SATA power connectors.. but I doubt it. Is there anything else that could cause this? Have you guys at Areca tested the ARC-1200 with Raptors in RAID1? :( Regards, Aron > > > Aron > > > > If your still have any questions, please feel free to let me know. > > > > P.S. The attached driver source, arcmsr-1.20.00.15-71224, has been > > upstreamed to kernel.org and will be released in kernel 2.6.25. If you like, > > you could update your driver with it. > > It fixes some minor bugs, but these bugs are nothing to do with your issue. > > > > > > -Original Message- > > From: erich [mailto:[EMAIL PROTECTED] > > Sent: Wednesday, February 13, 2008 4:33 PM > > To: (廣安科技)鄭守謙 > > Subject: Fw: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1 > > > > > > > > - Original Message - > > From: "Andrew Morton" <[EMAIL PROTECTED]> > > To: "Aron Stansvik" <[EMAIL PROTECTED]> > > Cc: ; <[EMAIL PROTECTED]>; "erich" > > <[EMAIL PROTECTED]> > > Sent: Wednesday, February 13, 2008 4:03 PM > > Subject: Re: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1 > > > > > > > > > > (cc's added) > > > > > > On Mon, 11 Feb 2008 17:44:08 +0100 "Aron Stansvik" <[EMAIL PROTECTED]> > > > wrote: > > > > > >> Hello LKML. > > >> > > >> Under semi-high disk I/O (e.g. installing a compiled KDE), I get the > > >> following (accompanied by seconds of lock-ups on the machine): > > >> > > >> [ 7727.345183] arcmsr0: abort device command of scsi id = 0 lun = 0 > > >> [ 7730.348776] arcmsr0: scsi id = 0 lun = 0 ccb = > > >> '0xdfb461c0' poll command abort successfully > > >> [ 8053.795943] arcmsr0: abort device command of scsi id = 0 lun = 0 > > >> [ 8056.799528] arcmsr0: scsi id = 0 lun = 0 ccb = > > >> '0xdfb595e0' poll command abort successfully > > >> [ 8884.592810] arcmsr0: abort device command of scsi id = 0 lun = 0 > > >> [ 8887.596392] arcmsr0: scsi id = 0 lun = 0 ccb = > > >> '0xdfb56d80' poll command abort successfully > > >> [ 8917.760216] arcm
RE: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1
Hi Aron, From our field experiences and customers' feedbacks, all of them direct to vibration and power issues. The vibration could be caused by FANs not only by themselves. You mentioned it could be the F/W issue. If the environment does not meet the prerequisite, FW could not work correctly. Actually FW just reacts to the situations not it causes the issue. Please check it out!! Thank you, -Original Message- From: Aron Stansvik [mailto:[EMAIL PROTECTED] Sent: Sunday, February 24, 2008 1:54 AM To: [EMAIL PROTECTED] Cc: erich; [EMAIL PROTECTED]; [EMAIL PROTECTED]; linux-kernel@vger.kernel.org Subject: Re: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1 Hello again Areca and LKML hackers. 2008/2/18, Aron Stansvik [EMAIL PROTECTED]: Hello Nick. Sorry that I'm not answering until now. I've been busy. 2008/2/13, nickcheng [EMAIL PROTECTED]: Hi Aron, From our experience and some customers' feedback, your issue could be caused by power instability or vibration to your HDs. Please check step by step: (1).under your original environment, increase the SCSI command value, default=30, with the shell script, set_scsicmd_timeout(). 90 or 120 is enough. (2).if method 1 does not work, find out the vibration source or change the power supply I will try to increase that value. I don't think it's vibration; the disks are firmly in place in a very heavy chassi (Silverstone SST-TJ05B-T). And I really don't think there's something wrong with the power supply, it's a pretty new Silverstone ST65ZF 650W. This is my own personal workstation, so I don't just have another power supply to test with :/ I will report back on my success/failure. Thanks for your answer. I've now tried with both 90 and 120 for the timeout value, and the problem still persists. It seems to happen when lots of small writes are occuring, e.g. when installing something. I really don't think the disks are vibrating, I don't see how they could. One more thing I'm going to test is to use the legacy ATA power connector instead of the SATA power connector. This was what I was using before when I only had a single drive and no RAID controller. Maybe my power supply is malfunctioning and not giving enough power on the SATA power connectors.. but I doubt it. Is there anything else that could cause this? Have you guys at Areca tested the ARC-1200 with Raptors in RAID1? :( Regards, Aron Aron If your still have any questions, please feel free to let me know. P.S. The attached driver source, arcmsr-1.20.00.15-71224, has been upstreamed to kernel.org and will be released in kernel 2.6.25. If you like, you could update your driver with it. It fixes some minor bugs, but these bugs are nothing to do with your issue. -Original Message- From: erich [mailto:[EMAIL PROTECTED] Sent: Wednesday, February 13, 2008 4:33 PM To: (廣安科技)鄭守謙 Subject: Fw: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1 - Original Message - From: Andrew Morton [EMAIL PROTECTED] To: Aron Stansvik [EMAIL PROTECTED] Cc: linux-kernel@vger.kernel.org; [EMAIL PROTECTED]; erich [EMAIL PROTECTED] Sent: Wednesday, February 13, 2008 4:03 PM Subject: Re: Aborted commands with arcmsr and 2xWD1500ADFD in RAID1 (cc's added) On Mon, 11 Feb 2008 17:44:08 +0100 Aron Stansvik [EMAIL PROTECTED] wrote: Hello LKML. Under semi-high disk I/O (e.g. installing a compiled KDE), I get the following (accompanied by seconds of lock-ups on the machine): [ 7727.345183] arcmsr0: abort device command of scsi id = 0 lun = 0 [ 7730.348776] arcmsr0: scsi id = 0 lun = 0 ccb = '0xdfb461c0' poll command abort successfully [ 8053.795943] arcmsr0: abort device command of scsi id = 0 lun = 0 [ 8056.799528] arcmsr0: scsi id = 0 lun = 0 ccb = '0xdfb595e0' poll command abort successfully [ 8884.592810] arcmsr0: abort device command of scsi id = 0 lun = 0 [ 8887.596392] arcmsr0: scsi id = 0 lun = 0 ccb = '0xdfb56d80' poll command abort successfully [ 8917.760216] arcmsr0: abort device command of scsi id = 0 lun = 0 [ 8920.763797] arcmsr0: scsi id = 0 lun = 0 ccb = '0xdfb472c0' poll command abort successfully [ 9074.106547] arcmsr0: abort device command of scsi id = 0 lun = 0 This is my setup: 1 x MSI K8N Master2-FAR 1 x Opteron 252 1 x Areca ARC1200 (sitting in a PCIe x4 socket) 2 x WD1500ADFD in RAID1 [EMAIL PROTECTED]:~$ uname -a Linux rubik 2.6.24-7-generic #1 SMP Thu Feb 7 01:29:58 UTC 2008 i686 GNU/Linux [EMAIL PROTECTED]:~$ modinfo arcmsr filename: /lib/modules/2.6.24-7-generic/kernel/drivers/scsi/arcmsr/arcmsr.ko version:Driver Version 1.20.00.15 2007/08/30 license:Dual