RE: [PATCH 2/5] arcmsr: Support Hibernation

2013-02-07 Thread NickCheng
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

2013-02-07 Thread NickCheng
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

2013-02-07 Thread NickCheng
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

2013-02-07 Thread NickCheng
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

2013-02-07 Thread NickCheng
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

2013-02-07 Thread NickCheng
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

2013-02-07 Thread NickCheng
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

2013-02-07 Thread NickCheng
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

2013-02-07 Thread NickCheng
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

2013-02-07 Thread NickCheng
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

2013-02-07 Thread NickCheng
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

2013-02-07 Thread NickCheng
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

2013-02-07 Thread NickCheng
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

2013-02-07 Thread NickCheng
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

2013-02-07 Thread NickCheng
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

2013-02-07 Thread NickCheng
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

2013-02-06 Thread NickCheng
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

2013-02-06 Thread NickCheng
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

2013-02-06 Thread NickCheng
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

2013-02-06 Thread NickCheng
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

2013-02-06 Thread NickCheng
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

2013-02-06 Thread NickCheng
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

2012-12-04 Thread NickCheng
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

2012-12-04 Thread NickCheng
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

2012-12-04 Thread NickCheng
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

2012-12-04 Thread NickCheng
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

2012-12-04 Thread NickCheng
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

2012-12-04 Thread NickCheng
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

2012-11-16 Thread NickCheng
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

2012-11-16 Thread NickCheng
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

2012-11-16 Thread NickCheng
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

2012-11-16 Thread NickCheng
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

2012-11-16 Thread NickCheng
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

2012-11-16 Thread NickCheng
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

2012-11-14 Thread NickCheng
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

2012-11-14 Thread NickCheng
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

2012-11-14 Thread NickCheng
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

2012-11-14 Thread NickCheng
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

2012-11-14 Thread NickCheng
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

2012-11-14 Thread NickCheng
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

2012-10-12 Thread NickCheng
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

2012-10-12 Thread NickCheng
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

2012-10-12 Thread NickCheng
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

2012-10-12 Thread NickCheng
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

2012-10-09 Thread NickCheng
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

2012-10-09 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2012-10-03 Thread NickCheng
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

2008-02-26 Thread nickcheng
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

2008-02-26 Thread nickcheng
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

2008-02-25 Thread nickcheng
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

2008-02-25 Thread nickcheng
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

2008-02-24 Thread nickcheng
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

2008-02-24 Thread nickcheng
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