All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 16/17] arcmsr: support new adapter ARC12x4 series
@ 2014-08-19  7:25 Ching Huang
  2014-08-27 14:00 ` Tomas Henzl
  0 siblings, 1 reply; 13+ messages in thread
From: Ching Huang @ 2014-08-19  7:25 UTC (permalink / raw)
  To: hch, jbottomley, dan.carpenter, thenzl, agordeev, linux-scsi,
	linux-kernel

From: Ching Huang <ching2048@areca.com.tw>

Add code for supporting Areca new Raid adapter ARC12x4 series.

Signed-off-by: Ching Huang <ching2048@areca.com.tw>
---

diff -uprN a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
--- a/drivers/scsi/arcmsr/arcmsr.h	2014-05-06 15:29:54.000000000 +0800
+++ b/drivers/scsi/arcmsr/arcmsr.h	2014-05-06 15:06:04.000000000 +0800
@@ -63,12 +63,17 @@ struct device_attribute;
 #define ARCMSR_MAX_QBUFFER							4096
 #define ARCMSR_DEFAULT_SG_ENTRIES						38
 #define ARCMSR_MAX_HBB_POSTQUEUE						264
+#define ARCMSR_MAX_ARC1214_POSTQUEUE	256
+#define ARCMSR_MAX_ARC1214_DONEQUEUE	257
 #define ARCMSR_MAX_XFER_LEN							0x26000 /* 152K */
 #define ARCMSR_CDB_SG_PAGE_LENGTH						256 
 #define ARCMST_NUM_MSIX_VECTORS		4
 #ifndef PCI_DEVICE_ID_ARECA_1880
 #define PCI_DEVICE_ID_ARECA_1880 0x1880
  #endif
+#ifndef PCI_DEVICE_ID_ARECA_1214
+	#define PCI_DEVICE_ID_ARECA_1214	0x1214
+#endif
 /*
 **********************************************************************************
 **
@@ -339,6 +344,56 @@ struct FIRMWARE_INFO
 #define ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK			0x80000000
 /*
 *******************************************************************************
+**                SPEC. for Areca Type D adapter
+*******************************************************************************
+*/
+#define ARCMSR_ARC1214_CHIP_ID				0x00004
+#define ARCMSR_ARC1214_CPU_MEMORY_CONFIGURATION		0x00008
+#define ARCMSR_ARC1214_I2_HOST_INTERRUPT_MASK		0x00034
+#define ARCMSR_ARC1214_SAMPLE_RESET			0x00100
+#define ARCMSR_ARC1214_RESET_REQUEST			0x00108
+#define ARCMSR_ARC1214_MAIN_INTERRUPT_STATUS		0x00200
+#define ARCMSR_ARC1214_PCIE_F0_INTERRUPT_ENABLE		0x0020C
+#define ARCMSR_ARC1214_INBOUND_MESSAGE0			0x00400
+#define ARCMSR_ARC1214_INBOUND_MESSAGE1			0x00404
+#define ARCMSR_ARC1214_OUTBOUND_MESSAGE0		0x00420
+#define ARCMSR_ARC1214_OUTBOUND_MESSAGE1		0x00424
+#define ARCMSR_ARC1214_INBOUND_DOORBELL			0x00460
+#define ARCMSR_ARC1214_OUTBOUND_DOORBELL		0x00480
+#define ARCMSR_ARC1214_OUTBOUND_DOORBELL_ENABLE		0x00484
+#define ARCMSR_ARC1214_INBOUND_LIST_BASE_LOW		0x01000
+#define ARCMSR_ARC1214_INBOUND_LIST_BASE_HIGH		0x01004
+#define ARCMSR_ARC1214_INBOUND_LIST_WRITE_POINTER	0x01018
+#define ARCMSR_ARC1214_OUTBOUND_LIST_BASE_LOW		0x01060
+#define ARCMSR_ARC1214_OUTBOUND_LIST_BASE_HIGH		0x01064
+#define ARCMSR_ARC1214_OUTBOUND_LIST_COPY_POINTER	0x0106C
+#define ARCMSR_ARC1214_OUTBOUND_LIST_READ_POINTER	0x01070
+#define ARCMSR_ARC1214_OUTBOUND_INTERRUPT_CAUSE		0x01088
+#define ARCMSR_ARC1214_OUTBOUND_INTERRUPT_ENABLE	0x0108C
+#define ARCMSR_ARC1214_MESSAGE_WBUFFER			0x02000
+#define ARCMSR_ARC1214_MESSAGE_RBUFFER			0x02100
+#define ARCMSR_ARC1214_MESSAGE_RWBUFFER			0x02200
+/* Host Interrupt Mask */
+#define ARCMSR_ARC1214_ALL_INT_ENABLE			0x00001010
+#define ARCMSR_ARC1214_ALL_INT_DISABLE			0x00000000
+/* Host Interrupt Status */
+#define ARCMSR_ARC1214_OUTBOUND_DOORBELL_ISR		0x00001000
+#define ARCMSR_ARC1214_OUTBOUND_POSTQUEUE_ISR		0x00000010
+/* DoorBell*/
+#define ARCMSR_ARC1214_DRV2IOP_DATA_IN_READY		0x00000001
+#define ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ		0x00000002
+/*inbound message 0 ready*/
+#define ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK		0x00000001
+/*outbound DATA WRITE isr door bell clear*/
+#define ARCMSR_ARC1214_IOP2DRV_DATA_READ_OK		0x00000002
+/*outbound message 0 ready*/
+#define ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE		0x02000000
+/*outbound message cmd isr door bell clear*/
+/*ARCMSR_HBAMU_MESSAGE_FIRMWARE_OK*/
+#define ARCMSR_ARC1214_MESSAGE_FIRMWARE_OK		0x80000000
+#define ARCMSR_ARC1214_OUTBOUND_LIST_INTERRUPT_CLEAR	0x00000001
+/*
+*******************************************************************************
 **    ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504)
 *******************************************************************************
 */
@@ -496,6 +551,55 @@ struct MessageUnit_C{
 	uint32_t	msgcode_rwbuffer[256];			/*2200 23FF*/
 };
 /*
+*********************************************************************
+**     Messaging Unit (MU) of Type D processor
+*********************************************************************
+*/
+struct InBound_SRB {
+	uint32_t addressLow; /* pointer to SRB block */
+	uint32_t addressHigh;
+	uint32_t length; /* in DWORDs */
+	uint32_t reserved0;
+};
+
+struct OutBound_SRB {
+	uint32_t addressLow; /* pointer to SRB block */
+	uint32_t addressHigh;
+};
+
+struct MessageUnit_D {
+	struct InBound_SRB	post_qbuffer[ARCMSR_MAX_ARC1214_POSTQUEUE];
+	volatile struct OutBound_SRB	done_qbuffer[ARCMSR_MAX_ARC1214_DONEQUEUE];
+	u16 postq_index;
+	volatile u16 doneq_index;
+	u32 __iomem *chip_id;			/* 0x00004 */
+	u32 __iomem *cpu_mem_config;		/* 0x00008 */
+	u32 __iomem *i2o_host_interrupt_mask;	/* 0x00034 */
+	u32 __iomem *sample_at_reset;		/* 0x00100 */
+	u32 __iomem *reset_request;		/* 0x00108 */
+	u32 __iomem *host_int_status;		/* 0x00200 */
+	u32 __iomem *pcief0_int_enable;		/* 0x0020C */
+	u32 __iomem *inbound_msgaddr0;		/* 0x00400 */
+	u32 __iomem *inbound_msgaddr1;		/* 0x00404 */
+	u32 __iomem *outbound_msgaddr0;		/* 0x00420 */
+	u32 __iomem *outbound_msgaddr1;		/* 0x00424 */
+	u32 __iomem *inbound_doorbell;		/* 0x00460 */
+	u32 __iomem *outbound_doorbell;		/* 0x00480 */
+	u32 __iomem *outbound_doorbell_enable;	/* 0x00484 */
+	u32 __iomem *inboundlist_base_low;	/* 0x01000 */
+	u32 __iomem *inboundlist_base_high;	/* 0x01004 */
+	u32 __iomem *inboundlist_write_pointer;	/* 0x01018 */
+	u32 __iomem *outboundlist_base_low;	/* 0x01060 */
+	u32 __iomem *outboundlist_base_high;	/* 0x01064 */
+	u32 __iomem *outboundlist_copy_pointer;	/* 0x0106C */
+	u32 __iomem *outboundlist_read_pointer;	/* 0x01070 0x01072 */
+	u32 __iomem *outboundlist_interrupt_cause;	/* 0x1088 */
+	u32 __iomem *outboundlist_interrupt_enable;	/* 0x108C */
+	u32 __iomem *message_wbuffer;		/* 0x2000 */
+	u32 __iomem *message_rbuffer;		/* 0x2100 */
+	u32 __iomem *msgcode_rwbuffer;		/* 0x2200 */
+};
+/*
 *******************************************************************************
 **                 Adapter Control Block
 *******************************************************************************
@@ -518,12 +622,15 @@ struct AdapterControlBlock
 	uint32_t			reg_mu_acc_handle0;
 	spinlock_t                      			eh_lock;
 	spinlock_t                      			ccblist_lock;
+	spinlock_t			postq_lock;
+	spinlock_t			doneq_lock;
 	spinlock_t			rqbuffer_lock;
 	spinlock_t			wqbuffer_lock;
 	union {
 		struct MessageUnit_A __iomem *pmuA;
 		struct MessageUnit_B 	*pmuB;
 		struct MessageUnit_C __iomem *pmuC;
+		struct MessageUnit_D 	*pmuD;
 	};
 	/* message unit ATU inbound base address0 */
 	void __iomem *mem_base0;
diff -uprN a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
--- a/drivers/scsi/arcmsr/arcmsr_hba.c	2014-08-14 18:41:12.000000000 +0800
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c	2014-08-14 18:38:46.000000000 +0800
@@ -108,6 +108,7 @@ static void arcmsr_message_isr_bh_fn(str
 static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb);
 static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb);
 static void arcmsr_hbaC_message_isr(struct AdapterControlBlock *pACB);
+static void arcmsr_hbaD_message_isr(struct AdapterControlBlock *acb);
 static void arcmsr_hardware_reset(struct AdapterControlBlock *acb);
 static const char *arcmsr_info(struct Scsi_Host *);
 static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
@@ -151,6 +152,7 @@ static struct pci_device_id arcmsr_devic
 	{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1201), .driver_data = ACB_ADAPTER_TYPE_B,},
 	{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1202), .driver_data = ACB_ADAPTER_TYPE_B,},
 	{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1210), .driver_data = ACB_ADAPTER_TYPE_A,},
+	{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1214), .driver_data = ACB_ADAPTER_TYPE_D,},
 	{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1220), .driver_data = ACB_ADAPTER_TYPE_A,},
 	{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1230), .driver_data = ACB_ADAPTER_TYPE_A,},
 	{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1260), .driver_data = ACB_ADAPTER_TYPE_A,},
@@ -181,7 +183,8 @@ static struct pci_driver arcmsr_pci_driv
 static void arcmsr_free_mu(struct AdapterControlBlock *acb)
 {
 	switch (acb->adapter_type) {
-	case ACB_ADAPTER_TYPE_B:{
+	case ACB_ADAPTER_TYPE_B:
+	case ACB_ADAPTER_TYPE_D: {
 		dma_free_coherent(&acb->pdev->dev, acb->roundup_ccbsize,
 			acb->dma_coherent2, acb->dma_coherent_handle2);
 		break;
@@ -230,6 +233,25 @@ static bool arcmsr_remap_pciregion(struc
 		}
 		break;
 	}
+	case ACB_ADAPTER_TYPE_D: {
+		void __iomem *mem_base0;
+		unsigned long addr, range, flags;
+
+		addr = (unsigned long)pci_resource_start(pdev, 0);
+		range = pci_resource_len(pdev, 0);
+		flags = pci_resource_flags(pdev, 0);
+		if (flags & IORESOURCE_CACHEABLE)
+			mem_base0 = ioremap(addr, range);
+		else
+			mem_base0 = ioremap_nocache(addr, range);
+		if (!mem_base0) {
+			pr_notice("arcmsr%d: memory mapping region fail\n",
+				acb->host->host_no);
+			return false;
+		}
+		acb->mem_base0 = mem_base0;
+		break;
+		}
 	}
 	return true;
 }
@@ -250,6 +272,10 @@ static void arcmsr_unmap_pciregion(struc
 	case ACB_ADAPTER_TYPE_C:{
 		iounmap(acb->pmuC);
 	}
+	break;
+	case ACB_ADAPTER_TYPE_D:
+		iounmap(acb->mem_base0);
+		break;
 	}
 }
 
@@ -346,6 +372,23 @@ static uint8_t arcmsr_hbaC_wait_msgint_r
 	return false;
 }
 
+static bool arcmsr_hbaD_wait_msgint_ready(struct AdapterControlBlock *pACB)
+{
+	struct MessageUnit_D *reg = pACB->pmuD;
+	int i;
+
+	for (i = 0; i < 2000; i++) {
+		if (readl(reg->outbound_doorbell)
+			& ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE) {
+			writel(ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE,
+				reg->outbound_doorbell);
+			return true;
+		}
+		msleep(10);
+	} /* max 20 seconds */
+	return false;
+}
+
 static void arcmsr_hbaA_flush_cache(struct AdapterControlBlock *acb)
 {
 	struct MessageUnit_A __iomem *reg = acb->pmuA;
@@ -395,6 +438,25 @@ static void arcmsr_hbaC_flush_cache(stru
 	} while (retry_count != 0);
 	return;
 }
+
+static void arcmsr_hbaD_flush_cache(struct AdapterControlBlock *pACB)
+{
+	int retry_count = 15;
+	struct MessageUnit_D *reg = pACB->pmuD;
+
+	writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, reg->inbound_msgaddr0);
+	do {
+		if (arcmsr_hbaD_wait_msgint_ready(pACB))
+			break;
+		else {
+			retry_count--;
+			pr_notice("arcmsr%d: wait 'flush adapter "
+				"cache' timeout, retry count down = %d\n",
+				pACB->host->host_no, retry_count);
+		}
+	} while (retry_count != 0);
+}
+
 static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
 {
 	switch (acb->adapter_type) {
@@ -411,6 +473,10 @@ static void arcmsr_flush_adapter_cache(s
 	case ACB_ADAPTER_TYPE_C: {
 		arcmsr_hbaC_flush_cache(acb);
 		}
+		break;
+	case ACB_ADAPTER_TYPE_D:
+		arcmsr_hbaD_flush_cache(acb);
+		break;
 	}
 }
 
@@ -454,7 +520,16 @@ static int arcmsr_alloc_ccb_pool(struct 
 	acb->vir2phy_offset = (unsigned long)dma_coherent - (unsigned long)dma_coherent_handle;
 	for(i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++){
 		cdb_phyaddr = dma_coherent_handle + offsetof(struct CommandControlBlock, arcmsr_cdb);
-		ccb_tmp->cdb_phyaddr = ((acb->adapter_type == ACB_ADAPTER_TYPE_C) ? cdb_phyaddr : (cdb_phyaddr >> 5));
+		switch (acb->adapter_type) {
+		case ACB_ADAPTER_TYPE_A:
+		case ACB_ADAPTER_TYPE_B:
+			ccb_tmp->cdb_phyaddr = cdb_phyaddr >> 5;
+			break;
+		case ACB_ADAPTER_TYPE_C:
+		case ACB_ADAPTER_TYPE_D:
+			ccb_tmp->cdb_phyaddr = cdb_phyaddr;
+			break;
+		}
 		acb->pccb_pool[i] = ccb_tmp;
 		ccb_tmp->acb = acb;
 		INIT_LIST_HEAD(&ccb_tmp->list);
@@ -495,6 +570,12 @@ static void arcmsr_message_isr_bh_fn(str
 		devicemap = (char __iomem *)(&reg->msgcode_rwbuffer[21]);
 		break;
 		}
+	case ACB_ADAPTER_TYPE_D: {
+		struct MessageUnit_D *reg  = acb->pmuD;
+		signature = (uint32_t __iomem *)(&reg->msgcode_rwbuffer[0]);
+		devicemap = (char __iomem *)(&reg->msgcode_rwbuffer[21]);
+		break;
+		}
 	}
 	atomic_inc(&acb->rq_map_token);
 	if (readl(signature) != ARCMSR_SIGNATURE_GET_CONFIG)
@@ -625,6 +706,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->doneq_lock);
 	spin_lock_init(&acb->rqbuffer_lock);
 	spin_lock_init(&acb->wqbuffer_lock);
 	acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
@@ -809,6 +892,20 @@ static uint8_t arcmsr_hbaC_abort_allcmd(
 	}
 	return true;
 }
+
+static uint8_t arcmsr_hbaD_abort_allcmd(struct AdapterControlBlock *pACB)
+{
+	struct MessageUnit_D *reg = pACB->pmuD;
+
+	writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, reg->inbound_msgaddr0);
+	if (!arcmsr_hbaD_wait_msgint_ready(pACB)) {
+		pr_notice("arcmsr%d: wait 'abort all outstanding "
+			"command' timeout\n", pACB->host->host_no);
+		return false;
+	}
+	return true;
+}
+
 static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
 {
 	uint8_t rtnval = 0;
@@ -826,6 +923,11 @@ static uint8_t arcmsr_abort_allcmd(struc
 	case ACB_ADAPTER_TYPE_C: {
 		rtnval = arcmsr_hbaC_abort_allcmd(acb);
 		}
+		break;
+
+	case ACB_ADAPTER_TYPE_D:
+		rtnval = arcmsr_hbaD_abort_allcmd(acb);
+		break;
 	}
 	return rtnval;
 }
@@ -892,6 +994,12 @@ static u32 arcmsr_disable_outbound_ints(
 		writel(orig_mask|ARCMSR_HBCMU_ALL_INTMASKENABLE, &reg->host_int_mask);
 		}
 		break;
+	case ACB_ADAPTER_TYPE_D: {
+		struct MessageUnit_D *reg = acb->pmuD;
+		/* disable all outbound interrupt */
+		writel(ARCMSR_ARC1214_ALL_INT_DISABLE, reg->pcief0_int_enable);
+		}
+		break;
 	}
 	return orig_mask;
 }
@@ -1039,7 +1147,60 @@ static void arcmsr_done4abort_postqueue(
 			error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? true : false;
 			arcmsr_drain_donequeue(acb, pCCB, error);
 		}
-	}
+		}
+		break;
+	case ACB_ADAPTER_TYPE_D: {
+		struct MessageUnit_D  *pmu = acb->pmuD;
+		uint32_t ccb_cdb_phy, outbound_write_pointer;
+		uint32_t doneq_index, index_stripped, addressLow, residual;
+		bool error;
+		struct CommandControlBlock *pCCB;
+		outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1;
+		doneq_index = pmu->doneq_index;
+		residual = atomic_read(&acb->ccboutstandingcount);
+		for (i = 0; i < residual; i++) {
+			while ((doneq_index & 0xFFF) !=
+				(outbound_write_pointer & 0xFFF)) {
+				if (doneq_index & 0x4000) {
+					index_stripped = doneq_index & 0xFFF;
+					index_stripped += 1;
+					index_stripped %=
+						ARCMSR_MAX_ARC1214_DONEQUEUE;
+					pmu->doneq_index = index_stripped ?
+						(index_stripped | 0x4000) :
+						(index_stripped + 1);
+				} else {
+					index_stripped = doneq_index;
+					index_stripped += 1;
+					index_stripped %=
+						ARCMSR_MAX_ARC1214_DONEQUEUE;
+					pmu->doneq_index = index_stripped ?
+						index_stripped :
+						((index_stripped | 0x4000) + 1);
+				}
+				doneq_index = pmu->doneq_index;
+				addressLow = pmu->done_qbuffer[doneq_index &
+					0xFFF].addressLow;
+				ccb_cdb_phy = (addressLow & 0xFFFFFFF0);
+				pARCMSR_CDB = (struct  ARCMSR_CDB *)
+					(acb->vir2phy_offset + ccb_cdb_phy);
+				pCCB = container_of(pARCMSR_CDB,
+					struct CommandControlBlock, arcmsr_cdb);
+				error = (addressLow &
+					ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ?
+					true : false;
+				arcmsr_drain_donequeue(acb, pCCB, error);
+				writel(doneq_index, pmu->outboundlist_read_pointer);
+			}
+			mdelay(10);
+			outbound_write_pointer =
+				pmu->done_qbuffer[0].addressLow + 1;
+			doneq_index = pmu->doneq_index;
+		}
+		pmu->postq_index = 0;
+		pmu->doneq_index = 0x40FF;
+		}
+		break;
 	}
 }
 
@@ -1148,6 +1309,13 @@ static void arcmsr_enable_outbound_ints(
 		writel(intmask_org & mask, &reg->host_int_mask);
 		acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f;
 		}
+		break;
+	case ACB_ADAPTER_TYPE_D: {
+		struct MessageUnit_D *reg = acb->pmuD;
+		mask = ARCMSR_ARC1214_ALL_INT_ENABLE;
+		writel(intmask_org | mask, reg->pcief0_int_enable);
+		break;
+		}
 	}
 }
 
@@ -1256,6 +1424,38 @@ static void arcmsr_post_ccb(struct Adapt
 			writel(ccb_post_stamp, &phbcmu->inbound_queueport_low);
 		}
 		}
+		break;
+	case ACB_ADAPTER_TYPE_D: {
+		struct MessageUnit_D  *pmu = acb->pmuD;
+		u16 index_stripped;
+		u16 postq_index;
+		unsigned long flags;
+		struct InBound_SRB *pinbound_srb;
+
+		spin_lock_irqsave(&acb->postq_lock, flags);
+		postq_index = pmu->postq_index;
+		pinbound_srb = (struct InBound_SRB *)&(pmu->post_qbuffer[postq_index & 0xFF]);
+		pinbound_srb->addressHigh = dma_addr_hi32(cdb_phyaddr);
+		pinbound_srb->addressLow = dma_addr_lo32(cdb_phyaddr);
+		pinbound_srb->length = ccb->arc_cdb_size >> 2;
+		arcmsr_cdb->msgContext = dma_addr_lo32(cdb_phyaddr);
+		if (postq_index & 0x4000) {
+			index_stripped = postq_index & 0xFF;
+			index_stripped += 1;
+			index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE;
+			pmu->postq_index = index_stripped ?
+				(index_stripped | 0x4000) : index_stripped;
+		} else {
+			index_stripped = postq_index;
+			index_stripped += 1;
+			index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE;
+			pmu->postq_index = index_stripped ? index_stripped :
+				(index_stripped | 0x4000);
+		}
+		writel(postq_index, pmu->inboundlist_write_pointer);
+		spin_unlock_irqrestore(&acb->postq_lock, flags);
+		break;
+		}
 	}
 }
 
@@ -1297,6 +1497,18 @@ static void arcmsr_hbaC_stop_bgrb(struct
 	}
 	return;
 }
+
+static void arcmsr_hbaD_stop_bgrb(struct AdapterControlBlock *pACB)
+{
+	struct MessageUnit_D *reg = pACB->pmuD;
+
+	pACB->acb_flags &= ~ACB_F_MSG_START_BGRB;
+	writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, reg->inbound_msgaddr0);
+	if (!arcmsr_hbaD_wait_msgint_ready(pACB))
+		pr_notice("arcmsr%d: wait 'stop adapter background rebulid' "
+			"timeout\n", pACB->host->host_no);
+}
+
 static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
 {
 	switch (acb->adapter_type) {
@@ -1312,6 +1524,10 @@ static void arcmsr_stop_adapter_bgrb(str
 	case ACB_ADAPTER_TYPE_C: {
 		arcmsr_hbaC_stop_bgrb(acb);
 		}
+		break;
+	case ACB_ADAPTER_TYPE_D:
+		arcmsr_hbaD_stop_bgrb(acb);
+		break;
 	}
 }
 
@@ -1338,6 +1554,13 @@ static void arcmsr_iop_message_read(stru
 		struct MessageUnit_C __iomem *reg = acb->pmuC;
 		writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, &reg->inbound_doorbell);
 		}
+		break;
+	case ACB_ADAPTER_TYPE_D: {
+		struct MessageUnit_D *reg = acb->pmuD;
+		writel(ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ,
+			reg->inbound_doorbell);
+		}
+		break;
 	}
 }
 
@@ -1372,6 +1595,12 @@ static void arcmsr_iop_message_wrote(str
 		writel(ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK, &reg->inbound_doorbell);
 		}
 		break;
+	case ACB_ADAPTER_TYPE_D: {
+		struct MessageUnit_D *reg = acb->pmuD;
+		writel(ARCMSR_ARC1214_DRV2IOP_DATA_IN_READY,
+			reg->inbound_doorbell);
+		}
+		break;
 	}
 }
 
@@ -1395,6 +1624,12 @@ struct QBUFFER __iomem *arcmsr_get_iop_r
 		struct MessageUnit_C __iomem *phbcmu = acb->pmuC;
 		qbuffer = (struct QBUFFER __iomem *)&phbcmu->message_rbuffer;
 		}
+		break;
+	case ACB_ADAPTER_TYPE_D: {
+		struct MessageUnit_D *reg = acb->pmuD;
+		qbuffer = (struct QBUFFER __iomem *)reg->message_rbuffer;
+		}
+		break;
 	}
 	return qbuffer;
 }
@@ -1418,8 +1653,13 @@ static struct QBUFFER __iomem *arcmsr_ge
 	case ACB_ADAPTER_TYPE_C: {
 		struct MessageUnit_C __iomem *reg = acb->pmuC;
 		pqbuffer = (struct QBUFFER __iomem *)&reg->message_wbuffer;
-	}
-
+		}
+		break;
+	case ACB_ADAPTER_TYPE_D: {
+		struct MessageUnit_D *reg = acb->pmuD;
+		pqbuffer = (struct QBUFFER __iomem *)reg->message_wbuffer;
+		}
+		break;
 	}
 	return pqbuffer;
 }
@@ -1473,7 +1713,7 @@ arcmsr_Read_iop_rqbuffer_data(struct Ada
 	uint8_t __iomem *iop_data;
 	uint32_t iop_len;
 
-	if (acb->adapter_type & ACB_ADAPTER_TYPE_C)
+	if (acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D))
 		return arcmsr_Read_iop_rqbuffer_in_DWORD(acb, prbuffer);
 	iop_data = (uint8_t __iomem *)prbuffer->data;
 	iop_len = readl(&prbuffer->data_len);
@@ -1559,7 +1799,7 @@ arcmsr_write_ioctldata2iop(struct Adapte
 	uint8_t __iomem *iop_data;
 	int32_t allxfer_len = 0;
 
-	if (acb->adapter_type & ACB_ADAPTER_TYPE_C) {
+	if (acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) {
 		arcmsr_write_ioctldata2iop_in_DWORD(acb);
 		return;
 	}
@@ -1635,6 +1875,27 @@ static void arcmsr_hbaC_doorbell_isr(str
 		| ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK
 		| ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE));
 }
+
+static void arcmsr_hbaD_doorbell_isr(struct AdapterControlBlock *pACB)
+{
+	uint32_t outbound_doorbell;
+	struct MessageUnit_D  *pmu = pACB->pmuD;
+
+	outbound_doorbell = readl(pmu->outbound_doorbell);
+	do {
+		writel(outbound_doorbell, pmu->outbound_doorbell);
+		if (outbound_doorbell & ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE)
+			arcmsr_hbaD_message_isr(pACB);
+		if (outbound_doorbell & ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK)
+			arcmsr_iop2drv_data_wrote_handle(pACB);
+		if (outbound_doorbell & ARCMSR_ARC1214_IOP2DRV_DATA_READ_OK)
+			arcmsr_iop2drv_data_read_handle(pACB);
+		outbound_doorbell = readl(pmu->outbound_doorbell);
+	} while (outbound_doorbell & (ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK
+		| ARCMSR_ARC1214_IOP2DRV_DATA_READ_OK
+		| ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE));
+}
+
 static void arcmsr_hbaA_postqueue_isr(struct AdapterControlBlock *acb)
 {
 	uint32_t flag_ccb;
@@ -1700,6 +1961,59 @@ static void arcmsr_hbaC_postqueue_isr(st
 		}
 	}
 }
+
+static void arcmsr_hbaD_postqueue_isr(struct AdapterControlBlock *acb)
+{
+	u32 outbound_write_pointer, doneq_index, index_stripped;
+	uint32_t addressLow, ccb_cdb_phy;
+	int error;
+	struct MessageUnit_D  *pmu;
+	struct ARCMSR_CDB *arcmsr_cdb;
+	struct CommandControlBlock *ccb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&acb->doneq_lock, flags);
+	pmu = acb->pmuD;
+	outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1;
+	doneq_index = pmu->doneq_index;
+	if ((doneq_index & 0xFFF) != (outbound_write_pointer & 0xFFF)) {
+		do {
+			if (doneq_index & 0x4000) {
+				index_stripped = doneq_index & 0xFFF;
+				index_stripped += 1;
+				index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE;
+				pmu->doneq_index = index_stripped
+					? (index_stripped | 0x4000) :
+					(index_stripped + 1);
+			} else {
+				index_stripped = doneq_index;
+				index_stripped += 1;
+				index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE;
+				pmu->doneq_index = index_stripped
+					? index_stripped :
+					((index_stripped | 0x4000) + 1);
+			}
+			doneq_index = pmu->doneq_index;
+			addressLow = pmu->done_qbuffer[doneq_index &
+				0xFFF].addressLow;
+			ccb_cdb_phy = (addressLow & 0xFFFFFFF0);
+			arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset
+				+ ccb_cdb_phy);
+			ccb = container_of(arcmsr_cdb,
+				struct CommandControlBlock, arcmsr_cdb);
+			error = (addressLow & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1)
+				? true : false;
+			arcmsr_drain_donequeue(acb, ccb, error);
+			writel(doneq_index, pmu->outboundlist_read_pointer);
+		} while ((doneq_index & 0xFFF) !=
+			(outbound_write_pointer & 0xFFF));
+	}
+	writel(ARCMSR_ARC1214_OUTBOUND_LIST_INTERRUPT_CLEAR,
+		pmu->outboundlist_interrupt_cause);
+	readl(pmu->outboundlist_interrupt_cause);
+	spin_unlock_irqrestore(&acb->doneq_lock, flags);
+}
+
 /*
 **********************************************************************************
 ** Handle a message interrupt
@@ -1740,6 +2054,15 @@ static void arcmsr_hbaC_message_isr(stru
 	schedule_work(&acb->arcmsr_do_message_isr_bh);
 }
 
+static void arcmsr_hbaD_message_isr(struct AdapterControlBlock *acb)
+{
+	struct MessageUnit_D *reg  = acb->pmuD;
+
+	writel(ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE, reg->outbound_doorbell);
+	readl(reg->outbound_doorbell);
+	schedule_work(&acb->arcmsr_do_message_isr_bh);
+}
+
 static int arcmsr_hbaA_handle_isr(struct AdapterControlBlock *acb)
 {
 	uint32_t outbound_intstatus;
@@ -1817,6 +2140,32 @@ static int arcmsr_hbaC_handle_isr(struct
 		ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR));
 	return IRQ_HANDLED;
 }
+
+static irqreturn_t arcmsr_hbaD_handle_isr(struct AdapterControlBlock *pACB)
+{
+	u32 host_interrupt_status;
+	struct MessageUnit_D  *pmu = pACB->pmuD;
+
+	host_interrupt_status = readl(pmu->host_int_status) &
+		(ARCMSR_ARC1214_OUTBOUND_POSTQUEUE_ISR |
+		ARCMSR_ARC1214_OUTBOUND_DOORBELL_ISR);
+	if (!host_interrupt_status)
+		return IRQ_NONE;
+	do {
+		/* MU post queue interrupts*/
+		if (host_interrupt_status &
+			ARCMSR_ARC1214_OUTBOUND_POSTQUEUE_ISR)
+			arcmsr_hbaD_postqueue_isr(pACB);
+		if (host_interrupt_status &
+			ARCMSR_ARC1214_OUTBOUND_DOORBELL_ISR)
+			arcmsr_hbaD_doorbell_isr(pACB);
+		host_interrupt_status = readl(pmu->host_int_status);
+	} while (host_interrupt_status &
+		(ARCMSR_ARC1214_OUTBOUND_POSTQUEUE_ISR |
+		ARCMSR_ARC1214_OUTBOUND_DOORBELL_ISR));
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb)
 {
 	switch (acb->adapter_type) {
@@ -1829,6 +2178,9 @@ static irqreturn_t arcmsr_interrupt(stru
 	case ACB_ADAPTER_TYPE_C:
 		return arcmsr_hbaC_handle_isr(acb);
 		break;
+	case ACB_ADAPTER_TYPE_D:
+		return arcmsr_hbaD_handle_isr(acb);
+		break;
 	default:
 		return IRQ_NONE;
 	}
@@ -2491,6 +2843,137 @@ static bool arcmsr_hbaC_get_config(struc
 	/*all interrupt service will be enable at arcmsr_iop_init*/
 	return true;
 }
+
+static bool arcmsr_hbaD_get_config(struct AdapterControlBlock *acb)
+{
+	char *acb_firm_model = acb->firm_model;
+	char *acb_firm_version = acb->firm_version;
+	char *acb_device_map = acb->device_map;
+	char __iomem *iop_firm_model;
+	char __iomem *iop_firm_version;
+	char __iomem *iop_device_map;
+	u32 count;
+	struct MessageUnit_D *reg ;
+	void *dma_coherent2;
+	dma_addr_t dma_coherent_handle2;
+	struct pci_dev *pdev = acb->pdev;
+
+	acb->roundup_ccbsize = roundup(sizeof(struct MessageUnit_D), 32);
+	dma_coherent2 = dma_alloc_coherent(&pdev->dev, acb->roundup_ccbsize,
+		&dma_coherent_handle2, GFP_KERNEL);
+	if (!dma_coherent2) {
+		pr_notice("DMA allocation failed...\n");
+		return false;
+	}
+	memset(dma_coherent2, 0, acb->roundup_ccbsize);
+	acb->dma_coherent_handle2 = dma_coherent_handle2;
+	acb->dma_coherent2 = dma_coherent2;
+	reg = (struct MessageUnit_D *)dma_coherent2;
+	acb->pmuD = reg;
+	reg->chip_id = acb->mem_base0 + ARCMSR_ARC1214_CHIP_ID;
+	reg->cpu_mem_config = acb->mem_base0 +
+		ARCMSR_ARC1214_CPU_MEMORY_CONFIGURATION;
+	reg->i2o_host_interrupt_mask = acb->mem_base0 +
+		ARCMSR_ARC1214_I2_HOST_INTERRUPT_MASK;
+	reg->sample_at_reset = acb->mem_base0 + ARCMSR_ARC1214_SAMPLE_RESET;
+	reg->reset_request = acb->mem_base0 + ARCMSR_ARC1214_RESET_REQUEST;
+	reg->host_int_status = acb->mem_base0 +
+		ARCMSR_ARC1214_MAIN_INTERRUPT_STATUS;
+	reg->pcief0_int_enable = acb->mem_base0 +
+		ARCMSR_ARC1214_PCIE_F0_INTERRUPT_ENABLE;
+	reg->inbound_msgaddr0 = acb->mem_base0 +
+		ARCMSR_ARC1214_INBOUND_MESSAGE0;
+	reg->inbound_msgaddr1 = acb->mem_base0 +
+		ARCMSR_ARC1214_INBOUND_MESSAGE1;
+	reg->outbound_msgaddr0 = acb->mem_base0 +
+		ARCMSR_ARC1214_OUTBOUND_MESSAGE0;
+	reg->outbound_msgaddr1 = acb->mem_base0 +
+		ARCMSR_ARC1214_OUTBOUND_MESSAGE1;
+	reg->inbound_doorbell = acb->mem_base0 +
+		ARCMSR_ARC1214_INBOUND_DOORBELL;
+	reg->outbound_doorbell = acb->mem_base0 +
+		ARCMSR_ARC1214_OUTBOUND_DOORBELL;
+	reg->outbound_doorbell_enable = acb->mem_base0 +
+		ARCMSR_ARC1214_OUTBOUND_DOORBELL_ENABLE;
+	reg->inboundlist_base_low = acb->mem_base0 +
+		ARCMSR_ARC1214_INBOUND_LIST_BASE_LOW;
+	reg->inboundlist_base_high = acb->mem_base0 +
+		ARCMSR_ARC1214_INBOUND_LIST_BASE_HIGH;
+	reg->inboundlist_write_pointer = acb->mem_base0 +
+		ARCMSR_ARC1214_INBOUND_LIST_WRITE_POINTER;
+	reg->outboundlist_base_low = acb->mem_base0 +
+		ARCMSR_ARC1214_OUTBOUND_LIST_BASE_LOW;
+	reg->outboundlist_base_high = acb->mem_base0 +
+		ARCMSR_ARC1214_OUTBOUND_LIST_BASE_HIGH;
+	reg->outboundlist_copy_pointer = acb->mem_base0 +
+		ARCMSR_ARC1214_OUTBOUND_LIST_COPY_POINTER;
+	reg->outboundlist_read_pointer = acb->mem_base0 +
+		ARCMSR_ARC1214_OUTBOUND_LIST_READ_POINTER;
+	reg->outboundlist_interrupt_cause = acb->mem_base0 +
+		ARCMSR_ARC1214_OUTBOUND_INTERRUPT_CAUSE;
+	reg->outboundlist_interrupt_enable = acb->mem_base0 +
+		ARCMSR_ARC1214_OUTBOUND_INTERRUPT_ENABLE;
+	reg->message_wbuffer = acb->mem_base0 + ARCMSR_ARC1214_MESSAGE_WBUFFER;
+	reg->message_rbuffer = acb->mem_base0 + ARCMSR_ARC1214_MESSAGE_RBUFFER;
+	reg->msgcode_rwbuffer = acb->mem_base0 +
+		ARCMSR_ARC1214_MESSAGE_RWBUFFER;
+	iop_firm_model = (char __iomem *)(&reg->msgcode_rwbuffer[15]);
+	iop_firm_version = (char __iomem *)(&reg->msgcode_rwbuffer[17]);
+	iop_device_map = (char __iomem *)(&reg->msgcode_rwbuffer[21]);
+	if (readl(acb->pmuD->outbound_doorbell) &
+		ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE) {
+		writel(ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE,
+			acb->pmuD->outbound_doorbell);/*clear interrupt*/
+	}
+	/* post "get config" instruction */
+	writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, reg->inbound_msgaddr0);
+	/* wait message ready */
+	if (!arcmsr_hbaD_wait_msgint_ready(acb)) {
+		pr_notice("arcmsr%d: wait get adapter firmware "
+			"miscellaneous data timeout\n", acb->host->host_no);
+		dma_free_coherent(&acb->pdev->dev, acb->roundup_ccbsize,
+			acb->dma_coherent2, acb->dma_coherent_handle2);
+		return false;
+	}
+	count = 8;
+	while (count) {
+		*acb_firm_model = readb(iop_firm_model);
+		acb_firm_model++;
+		iop_firm_model++;
+		count--;
+	}
+	count = 16;
+	while (count) {
+		*acb_firm_version = readb(iop_firm_version);
+		acb_firm_version++;
+		iop_firm_version++;
+		count--;
+	}
+	count = 16;
+	while (count) {
+		*acb_device_map = readb(iop_device_map);
+		acb_device_map++;
+		iop_device_map++;
+		count--;
+	}
+	acb->signature = readl(&reg->msgcode_rwbuffer[1]);
+	/*firm_signature,1,00-03*/
+	acb->firm_request_len = readl(&reg->msgcode_rwbuffer[2]);
+	/*firm_request_len,1,04-07*/
+	acb->firm_numbers_queue = readl(&reg->msgcode_rwbuffer[3]);
+	/*firm_numbers_queue,2,08-11*/
+	acb->firm_sdram_size = readl(&reg->msgcode_rwbuffer[4]);
+	/*firm_sdram_size,3,12-15*/
+	acb->firm_hd_channels = readl(&reg->msgcode_rwbuffer[5]);
+	/*firm_hd_channels,4,16-19*/
+	acb->firm_cfg_version = readl(&reg->msgcode_rwbuffer[25]);
+	pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n",
+		acb->host->host_no,
+		acb->firm_model,
+		acb->firm_version);
+	return true;
+}
+
 static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
 {
 	bool rtn = false;
@@ -2505,6 +2988,9 @@ static bool arcmsr_get_firmware_spec(str
 	case ACB_ADAPTER_TYPE_C:
 		rtn = arcmsr_hbaC_get_config(acb);
 		break;
+	case ACB_ADAPTER_TYPE_D:
+		rtn = arcmsr_hbaD_get_config(acb);
+		break;
 	default:
 		break;
 	}
@@ -2693,6 +3179,89 @@ polling_hbc_ccb_retry:
 	}
 	return rtn;
 }
+
+static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb,
+				struct CommandControlBlock *poll_ccb)
+{
+	bool error;
+	uint32_t poll_ccb_done = 0, poll_count = 0, flag_ccb, ccb_cdb_phy;
+	int rtn, doneq_index, index_stripped, outbound_write_pointer;
+	unsigned long flags;
+	struct ARCMSR_CDB *arcmsr_cdb;
+	struct CommandControlBlock *pCCB;
+	struct MessageUnit_D *pmu = acb->pmuD;
+
+polling_hbaD_ccb_retry:
+	poll_count++;
+	while (1) {
+		outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1;
+		doneq_index = pmu->doneq_index;
+		if ((outbound_write_pointer & 0xFFF) == (doneq_index & 0xFFF)) {
+			if (poll_ccb_done) {
+				rtn = SUCCESS;
+				break;
+			} else {
+				msleep(25);
+				if (poll_count > 40) {
+					rtn = FAILED;
+					break;
+				}
+				goto polling_hbaD_ccb_retry;
+			}
+		}
+		spin_lock_irqsave(&acb->doneq_lock, flags);
+		if (doneq_index & 0x4000) {
+			index_stripped = doneq_index & 0xFFF;
+			index_stripped += 1;
+			index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE;
+			pmu->doneq_index = index_stripped ?
+				(index_stripped | 0x4000) :
+				(index_stripped + 1);
+		} else {
+			index_stripped = doneq_index;
+			index_stripped += 1;
+			index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE;
+			pmu->doneq_index = index_stripped ? index_stripped :
+				((index_stripped | 0x4000) + 1);
+		}
+		spin_unlock_irqrestore(&acb->doneq_lock, flags);
+		doneq_index = pmu->doneq_index;
+		flag_ccb = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow;
+		ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0);
+		arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset +
+			ccb_cdb_phy);
+		pCCB = container_of(arcmsr_cdb, struct CommandControlBlock,
+			arcmsr_cdb);
+		poll_ccb_done |= (pCCB == poll_ccb) ? 1 : 0;
+		if ((pCCB->acb != acb) ||
+			(pCCB->startdone != ARCMSR_CCB_START)) {
+			if (pCCB->startdone == ARCMSR_CCB_ABORTED) {
+				pr_notice("arcmsr%d: scsi id = %d "
+					"lun = %d ccb = '0x%p' poll command "
+					"abort successfully\n"
+					, acb->host->host_no
+					, pCCB->pcmd->device->id
+					, (u32)pCCB->pcmd->device->lun
+					, pCCB);
+				pCCB->pcmd->result = DID_ABORT << 16;
+				arcmsr_ccb_complete(pCCB);
+				continue;
+			}
+			pr_notice("arcmsr%d: polling an illegal "
+				"ccb command done ccb = '0x%p' "
+				"ccboutstandingcount = %d\n"
+				, acb->host->host_no
+				, pCCB
+				, atomic_read(&acb->ccboutstandingcount));
+			continue;
+		}
+		error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1)
+			? true : false;
+		arcmsr_report_ccb_state(acb, pCCB, error);
+	}
+	return rtn;
+}
+
 static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb,
 					struct CommandControlBlock *poll_ccb)
 {
@@ -2711,6 +3280,10 @@ static int arcmsr_polling_ccbdone(struct
 	case ACB_ADAPTER_TYPE_C: {
 		rtn = arcmsr_hbaC_polling_ccbdone(acb, poll_ccb);
 		}
+		break;
+	case ACB_ADAPTER_TYPE_D:
+		rtn = arcmsr_hbaD_polling_ccbdone(acb, poll_ccb);
+		break;
 	}
 	return rtn;
 }
@@ -2728,6 +3301,7 @@ static int arcmsr_iop_confirm(struct Ada
 	*/
 	switch (acb->adapter_type) {
 		case ACB_ADAPTER_TYPE_B:
+		case ACB_ADAPTER_TYPE_D:
 			dma_coherent_handle = acb->dma_coherent_handle2;
 			break;
 		default:
@@ -2817,6 +3391,27 @@ static int arcmsr_iop_confirm(struct Ada
 			}
 		}
 		}
+		break;
+	case ACB_ADAPTER_TYPE_D: {
+		uint32_t __iomem *rwbuffer;
+		struct MessageUnit_D *reg = acb->pmuD;
+		reg->postq_index = 0;
+		reg->doneq_index = 0;
+		rwbuffer = reg->msgcode_rwbuffer;
+		writel(ARCMSR_SIGNATURE_SET_CONFIG, rwbuffer++);
+		writel(cdb_phyaddr_hi32, rwbuffer++);
+		writel(cdb_phyaddr, rwbuffer++);
+		writel(cdb_phyaddr + (ARCMSR_MAX_ARC1214_POSTQUEUE *
+			sizeof(struct InBound_SRB)), rwbuffer++);
+		writel(0x100, rwbuffer);
+		writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, reg->inbound_msgaddr0);
+		if (!arcmsr_hbaD_wait_msgint_ready(acb)) {
+			pr_notice("arcmsr%d: 'set command Q window' timeout\n",
+				acb->host->host_no);
+			return 1;
+		}
+		}
+		break;
 	}
 	return 0;
 }
@@ -2848,6 +3443,15 @@ static void arcmsr_wait_firmware_ready(s
 			firmware_state = readl(&reg->outbound_msgaddr1);
 		} while ((firmware_state & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0);
 		}
+		break;
+	case ACB_ADAPTER_TYPE_D: {
+		struct MessageUnit_D *reg = acb->pmuD;
+		do {
+			firmware_state = readl(reg->outbound_msgaddr1);
+		} while ((firmware_state &
+			ARCMSR_ARC1214_MESSAGE_FIRMWARE_OK) == 0);
+		}
+		break;
 	}
 }
 
@@ -2918,6 +3522,35 @@ static void arcmsr_hbaC_request_device_m
 	return;
 }
 
+static void arcmsr_hbaD_request_device_map(struct AdapterControlBlock *acb)
+{
+	struct MessageUnit_D *reg = acb->pmuD;
+
+	if (unlikely(atomic_read(&acb->rq_map_token) == 0) ||
+		((acb->acb_flags & ACB_F_BUS_RESET) != 0) ||
+		((acb->acb_flags & ACB_F_ABORT) != 0)) {
+		mod_timer(&acb->eternal_timer,
+			jiffies + msecs_to_jiffies(6 * HZ));
+	} else {
+		acb->fw_flag = FW_NORMAL;
+		if (atomic_read(&acb->ante_token_value) ==
+			atomic_read(&acb->rq_map_token)) {
+			atomic_set(&acb->rq_map_token, 16);
+		}
+		atomic_set(&acb->ante_token_value,
+			atomic_read(&acb->rq_map_token));
+		if (atomic_dec_and_test(&acb->rq_map_token)) {
+			mod_timer(&acb->eternal_timer, jiffies +
+				msecs_to_jiffies(6 * HZ));
+			return;
+		}
+		writel(ARCMSR_INBOUND_MESG0_GET_CONFIG,
+			reg->inbound_msgaddr0);
+		mod_timer(&acb->eternal_timer, jiffies +
+			msecs_to_jiffies(6 * HZ));
+	}
+}
+
 static void arcmsr_request_device_map(unsigned long pacb)
 {
 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *)pacb;
@@ -2933,6 +3566,10 @@ static void arcmsr_request_device_map(un
 		case ACB_ADAPTER_TYPE_C: {
 			arcmsr_hbaC_request_device_map(acb);
 		}
+		break;
+		case ACB_ADAPTER_TYPE_D:
+			arcmsr_hbaD_request_device_map(acb);
+		break;
 	}
 }
 
@@ -2970,6 +3607,19 @@ static void arcmsr_hbaC_start_bgrb(struc
 	}
 	return;
 }
+
+static void arcmsr_hbaD_start_bgrb(struct AdapterControlBlock *pACB)
+{
+	struct MessageUnit_D *pmu = pACB->pmuD;
+
+	pACB->acb_flags |= ACB_F_MSG_START_BGRB;
+	writel(ARCMSR_INBOUND_MESG0_START_BGRB, pmu->inbound_msgaddr0);
+	if (!arcmsr_hbaD_wait_msgint_ready(pACB)) {
+		pr_notice("arcmsr%d: wait 'start adapter "
+			"background rebulid' timeout\n", pACB->host->host_no);
+	}
+}
+
 static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
 {
 	switch (acb->adapter_type) {
@@ -2981,6 +3631,10 @@ static void arcmsr_start_adapter_bgrb(st
 		break;
 	case ACB_ADAPTER_TYPE_C:
 		arcmsr_hbaC_start_bgrb(acb);
+		break;
+	case ACB_ADAPTER_TYPE_D:
+		arcmsr_hbaD_start_bgrb(acb);
+		break;
 	}
 }
 
@@ -3026,6 +3680,29 @@ static void arcmsr_clear_doorbell_queue_
 				break;
 		}
 		}
+		break;
+	case ACB_ADAPTER_TYPE_D: {
+		struct MessageUnit_D *reg = acb->pmuD;
+		uint32_t outbound_doorbell, i;
+		/* empty doorbell Qbuffer if door bell ringed */
+		outbound_doorbell = readl(reg->outbound_doorbell);
+		writel(outbound_doorbell, reg->outbound_doorbell);
+		writel(ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ,
+			reg->inbound_doorbell);
+		for (i = 0; i < 200; i++) {
+			msleep(20);
+			outbound_doorbell = readl(reg->outbound_doorbell);
+			if (outbound_doorbell &
+				ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK) {
+				writel(outbound_doorbell,
+					reg->outbound_doorbell);
+				writel(ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ,
+					reg->inbound_doorbell);
+			} else
+				break;
+		}
+		}
+		break;
 	}
 }
 
@@ -3056,6 +3733,7 @@ static void arcmsr_hardware_reset(struct
 	int i, count = 0;
 	struct MessageUnit_A __iomem *pmuA = acb->pmuA;
 	struct MessageUnit_C __iomem *pmuC = acb->pmuC;
+	struct MessageUnit_D *pmuD = acb->pmuD;
 
 	/* backup pci config data */
 	printk(KERN_NOTICE "arcmsr%d: executing hw bus reset .....\n", acb->host->host_no);
@@ -3076,6 +3754,8 @@ static void arcmsr_hardware_reset(struct
 			writel(0xD, &pmuC->write_sequence);
 		} while (((readl(&pmuC->host_diagnostic) & ARCMSR_ARC1880_DiagWrite_ENABLE) == 0) && (count < 5));
 		writel(ARCMSR_ARC1880_RESET_ADAPTER, &pmuC->host_diagnostic);
+	} else if ((acb->dev_id == 0x1214)) {
+		writel(0x20, pmuD->reset_request);
 	} else {
 		pci_write_config_byte(acb->pdev, 0x84, 0x20);
 	}
@@ -3272,6 +3952,66 @@ sleep:
 			}
 			break;
 		}
+		case ACB_ADAPTER_TYPE_D: {
+			if (acb->acb_flags & ACB_F_BUS_RESET) {
+				long timeout;
+				pr_notice("arcmsr: there is an bus reset"
+					" eh proceeding.......\n");
+				timeout = wait_event_timeout(wait_q, (acb->acb_flags
+					& ACB_F_BUS_RESET) == 0, 220 * HZ);
+				if (timeout)
+					return SUCCESS;
+			}
+			acb->acb_flags |= ACB_F_BUS_RESET;
+			if (!arcmsr_iop_reset(acb)) {
+				struct MessageUnit_D *reg;
+				reg = acb->pmuD;
+				arcmsr_hardware_reset(acb);
+				acb->acb_flags &= ~ACB_F_IOP_INITED;
+			nap:
+				ssleep(ARCMSR_SLEEPTIME);
+				if ((readl(reg->sample_at_reset) & 0x80) != 0) {
+					pr_err("arcmsr%d: waiting for "
+						"hw bus reset return, retry=%d\n",
+						acb->host->host_no, retry_count);
+					if (retry_count > ARCMSR_RETRYCOUNT) {
+						acb->fw_flag = FW_DEADLOCK;
+						pr_err("arcmsr%d: waiting for hw bus"
+							" reset return, "
+							"RETRY TERMINATED!!\n",
+							acb->host->host_no);
+						return FAILED;
+					}
+					retry_count++;
+					goto nap;
+				}
+				acb->acb_flags |= ACB_F_IOP_INITED;
+				/* disable all outbound interrupt */
+				intmask_org = arcmsr_disable_outbound_ints(acb);
+				arcmsr_get_firmware_spec(acb);
+				arcmsr_start_adapter_bgrb(acb);
+				arcmsr_clear_doorbell_queue_buffer(acb);
+				arcmsr_enable_outbound_ints(acb, intmask_org);
+				atomic_set(&acb->rq_map_token, 16);
+				atomic_set(&acb->ante_token_value, 16);
+				acb->fw_flag = FW_NORMAL;
+				mod_timer(&acb->eternal_timer,
+					jiffies + msecs_to_jiffies(6 * HZ));
+				acb->acb_flags &= ~ACB_F_BUS_RESET;
+				rtn = SUCCESS;
+				pr_err("arcmsr: scsi bus reset "
+					"eh returns with success\n");
+			} else {
+				acb->acb_flags &= ~ACB_F_BUS_RESET;
+				atomic_set(&acb->rq_map_token, 16);
+				atomic_set(&acb->ante_token_value, 16);
+				acb->fw_flag = FW_NORMAL;
+				mod_timer(&acb->eternal_timer,
+					jiffies + msecs_to_jiffies(6 * HZ));
+				rtn = SUCCESS;
+			}
+			break;
+		}
 	}
 	return rtn;
 }
@@ -3348,6 +4088,7 @@ static const char *arcmsr_info(struct Sc
 	case PCI_DEVICE_ID_ARECA_1280:
 		type = "SATA";
 		break;
+	case PCI_DEVICE_ID_ARECA_1214:
 	case PCI_DEVICE_ID_ARECA_1380:
 	case PCI_DEVICE_ID_ARECA_1381:
 	case PCI_DEVICE_ID_ARECA_1680:



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 16/17] arcmsr: support new adapter ARC12x4 series
  2014-08-19  7:25 [PATCH v3 16/17] arcmsr: support new adapter ARC12x4 series Ching Huang
@ 2014-08-27 14:00 ` Tomas Henzl
  2014-08-28 15:46   ` Ching Huang
  0 siblings, 1 reply; 13+ messages in thread
From: Tomas Henzl @ 2014-08-27 14:00 UTC (permalink / raw)
  To: Ching Huang, hch, jbottomley, dan.carpenter, linux-scsi, linux-kernel

On 08/19/2014 09:25 AM, Ching Huang wrote:
> From: Ching Huang <ching2048@areca.com.tw>
>
> Add code for supporting Areca new Raid adapter ARC12x4 series.
>
> Signed-off-by: Ching Huang <ching2048@areca.com.tw>
> ---

Hi Ching,
please look at the comments below -

>  }
> @@ -1039,7 +1147,60 @@ static void arcmsr_done4abort_postqueue(
>  			error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? true : false;
>  			arcmsr_drain_donequeue(acb, pCCB, error);
>  		}
> -	}
> +		}
> +		break;
> +	case ACB_ADAPTER_TYPE_D: {
> +		struct MessageUnit_D  *pmu = acb->pmuD;
> +		uint32_t ccb_cdb_phy, outbound_write_pointer;
> +		uint32_t doneq_index, index_stripped, addressLow, residual;
> +		bool error;
> +		struct CommandControlBlock *pCCB;

I have noticed this^ in this driver already before. Sometimes it makes sense
when a variable is declared in a 'case' block but often it is just
a waste of space. In this function this is the third 'bool error' declared.
Is there a reason for this style (this function is not the worst case) ?

> +		outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1;
> +		doneq_index = pmu->doneq_index;
> +		residual = atomic_read(&acb->ccboutstandingcount);
> +		for (i = 0; i < residual; i++) {
> +			while ((doneq_index & 0xFFF) !=
> +				(outbound_write_pointer & 0xFFF)) {
> +				if (doneq_index & 0x4000) {
> +					index_stripped = doneq_index & 0xFFF;
> +					index_stripped += 1;
> +					index_stripped %=
> +						ARCMSR_MAX_ARC1214_DONEQUEUE;
> +					pmu->doneq_index = index_stripped ?
> +						(index_stripped | 0x4000) :
> +						(index_stripped + 1);
> +				} else {
> +					index_stripped = doneq_index;
> +					index_stripped += 1;
> +					index_stripped %=
> +						ARCMSR_MAX_ARC1214_DONEQUEUE;
> +					pmu->doneq_index = index_stripped ?
> +						index_stripped :
> +						((index_stripped | 0x4000) + 1);
> +				}
> +				doneq_index = pmu->doneq_index;
> +				addressLow = pmu->done_qbuffer[doneq_index &
> +					0xFFF].addressLow;
> +				ccb_cdb_phy = (addressLow & 0xFFFFFFF0);
> +				pARCMSR_CDB = (struct  ARCMSR_CDB *)
> +					(acb->vir2phy_offset + ccb_cdb_phy);
> +				pCCB = container_of(pARCMSR_CDB,
> +					struct CommandControlBlock, arcmsr_cdb);
> +				error = (addressLow &
> +					ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ?
> +					true : false;
> +				arcmsr_drain_donequeue(acb, pCCB, error);
> +				writel(doneq_index, pmu->outboundlist_read_pointer);
> +			}
> +			mdelay(10);
> +			outbound_write_pointer =
> +				pmu->done_qbuffer[0].addressLow + 1;
> +			doneq_index = pmu->doneq_index;
> +		}
> +		pmu->postq_index = 0;
> +		pmu->doneq_index = 0x40FF;
> +		}
> +		break;
>  	}
>  }
...

>
>  
> @@ -1256,6 +1424,38 @@ static void arcmsr_post_ccb(struct Adapt
>  			writel(ccb_post_stamp, &phbcmu->inbound_queueport_low);
>  		}
>  		}
> +		break;
> +	case ACB_ADAPTER_TYPE_D: {
> +		struct MessageUnit_D  *pmu = acb->pmuD;
> +		u16 index_stripped;
> +		u16 postq_index;
> +		unsigned long flags;
> +		struct InBound_SRB *pinbound_srb;
> +
> +		spin_lock_irqsave(&acb->postq_lock, flags);
> +		postq_index = pmu->postq_index;
> +		pinbound_srb = (struct InBound_SRB *)&(pmu->post_qbuffer[postq_index & 0xFF]);
> +		pinbound_srb->addressHigh = dma_addr_hi32(cdb_phyaddr);
> +		pinbound_srb->addressLow = dma_addr_lo32(cdb_phyaddr);
> +		pinbound_srb->length = ccb->arc_cdb_size >> 2;
> +		arcmsr_cdb->msgContext = dma_addr_lo32(cdb_phyaddr);
> +		if (postq_index & 0x4000) {
> +			index_stripped = postq_index & 0xFF;
> +			index_stripped += 1;
> +			index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE;
> +			pmu->postq_index = index_stripped ?
> +				(index_stripped | 0x4000) : index_stripped;
> +		} else {
> +			index_stripped = postq_index;
> +			index_stripped += 1;
> +			index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE;
> +			pmu->postq_index = index_stripped ? index_stripped :
> +				(index_stripped | 0x4000);
> +		}

The code above could be a bit easier -
		
		arcmsr_cdb->msgContext = dma_addr_lo32(cdb_phyaddr);
                index_stripped = postq_index + 1;
                index_stripped &= (ARCMSR_MAX_ARC1214_POSTQUEUE - 1);

                if (postq_index & 0x4000)
                        pmu->postq_index = index_stripped ?
                                (index_stripped | 0x4000) : index_stripped;
                else
                        pmu->postq_index = index_stripped ?
                                 index_stripped : (index_stripped | 0x4000);
or am I wrong? This is repeated in the code many times
 

> +		writel(postq_index, pmu->inboundlist_write_pointer);
> +		spin_unlock_irqrestore(&acb->postq_lock, flags);
> +		break;
> +		}
>  	}
>  }
>  
...
> +static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb,
> +				struct CommandControlBlock *poll_ccb)
> +{
> +	bool error;
> +	uint32_t poll_ccb_done = 0, poll_count = 0, flag_ccb, ccb_cdb_phy;
> +	int rtn, doneq_index, index_stripped, outbound_write_pointer;
> +	unsigned long flags;
> +	struct ARCMSR_CDB *arcmsr_cdb;
> +	struct CommandControlBlock *pCCB;
> +	struct MessageUnit_D *pmu = acb->pmuD;
> +
> +polling_hbaD_ccb_retry:
> +	poll_count++;
> +	while (1) {
> +		outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1;
> +		doneq_index = pmu->doneq_index;

You seem to protect the doneq with a spinlock on some other places, arcmsr_hbaD_postqueue_isr
and below in this function. Why not here, is it intentional? 

> +		if ((outbound_write_pointer & 0xFFF) == (doneq_index & 0xFFF)) {
> +			if (poll_ccb_done) {
> +				rtn = SUCCESS;
> +				break;
> +			} else {
> +				msleep(25);
> +				if (poll_count > 40) {
> +					rtn = FAILED;
> +					break;
> +				}
> +				goto polling_hbaD_ccb_retry;
> +			}
> +		}
> +		spin_lock_irqsave(&acb->doneq_lock, flags);
> +		if (doneq_index & 0x4000) {
> +			index_stripped = doneq_index & 0xFFF;
> +			index_stripped += 1;
> +			index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE;
> +			pmu->doneq_index = index_stripped ?
> +				(index_stripped | 0x4000) :
> +				(index_stripped + 1);
> +		} else {
> +			index_stripped = doneq_index;
> +			index_stripped += 1;
> +			index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE;
> +			pmu->doneq_index = index_stripped ? index_stripped :
> +				((index_stripped | 0x4000) + 1);
> +		}
> +		spin_unlock_irqrestore(&acb->doneq_lock, flags);
> +		doneq_index = pmu->doneq_index;
> +		flag_ccb = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow;
> +		ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0);
> +		arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset +
> +			ccb_cdb_phy);
> +		pCCB = container_of(arcmsr_cdb, struct CommandControlBlock,
> +			arcmsr_cdb);
> +		poll_ccb_done |= (pCCB == poll_ccb) ? 1 : 0;
> +		if ((pCCB->acb != acb) ||
> +			(pCCB->startdone != ARCMSR_CCB_START)) {
> +			if (pCCB->startdone == ARCMSR_CCB_ABORTED) {
> +				pr_notice("arcmsr%d: scsi id = %d "
> +					"lun = %d ccb = '0x%p' poll command "
> +					"abort successfully\n"
> +					, acb->host->host_no
> +					, pCCB->pcmd->device->id
> +					, (u32)pCCB->pcmd->device->lun
> +					, pCCB);
> +				pCCB->pcmd->result = DID_ABORT << 16;
> +				arcmsr_ccb_complete(pCCB);
> +				continue;
> +			}
> +			pr_notice("arcmsr%d: polling an illegal "
> +				"ccb command done ccb = '0x%p' "
> +				"ccboutstandingcount = %d\n"
> +				, acb->host->host_no
> +				, pCCB
> +				, atomic_read(&acb->ccboutstandingcount));
> +			continue;
> +		}
> +		error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1)
> +			? true : false;
> +		arcmsr_report_ccb_state(acb, pCCB, error);
> +	}
> +	return rtn;
> +}
> +
>  static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb,
>  					struct CommandControlBlock *poll_ccb)
>  {
> @@ -2711,6 +3280,10 @@ static int arcmsr_polling_ccbdone(struct
>  	case ACB_ADAPTER_TYPE_C: {
>  		rtn = arcmsr_hbaC_polling_ccbdone(acb, poll_ccb);
>  		}
> +		break;
> +	case ACB_ADAPTER_TYPE_D:
> +		rtn = arcmsr_hbaD_polling_ccbdone(acb, poll_ccb);
> +		break;
>  	}
>  	return rtn;
>  }
> @@ -2728,6 +3301,7 @@ static int arcmsr_iop_confirm(struct Ada
>  	*/
>  	switch (acb->adapter_type) {
>  		case ACB_ADAPTER_TYPE_B:
> +		case ACB_ADAPTER_TYPE_D:
>  			dma_coherent_handle = acb->dma_coherent_handle2;
>  			break;
>  		default:
> @@ -2817,6 +3391,27 @@ static int arcmsr_iop_confirm(struct Ada
>  			}
>  		}
>  		}
> +		break;
> +	case ACB_ADAPTER_TYPE_D: {
> +		uint32_t __iomem *rwbuffer;
> +		struct MessageUnit_D *reg = acb->pmuD;
> +		reg->postq_index = 0;
> +		reg->doneq_index = 0;
> +		rwbuffer = reg->msgcode_rwbuffer;
> +		writel(ARCMSR_SIGNATURE_SET_CONFIG, rwbuffer++);
> +		writel(cdb_phyaddr_hi32, rwbuffer++);
> +		writel(cdb_phyaddr, rwbuffer++);
> +		writel(cdb_phyaddr + (ARCMSR_MAX_ARC1214_POSTQUEUE *
> +			sizeof(struct InBound_SRB)), rwbuffer++);
> +		writel(0x100, rwbuffer);
> +		writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, reg->inbound_msgaddr0);
> +		if (!arcmsr_hbaD_wait_msgint_ready(acb)) {
> +			pr_notice("arcmsr%d: 'set command Q window' timeout\n",
> +				acb->host->host_no);
> +			return 1;
> +		}
> +		}
> +		break;
>  	}
>  	return 0;
>  }
> @@ -2848,6 +3443,15 @@ static void arcmsr_wait_firmware_ready(s
>  			firmware_state = readl(&reg->outbound_msgaddr1);
>  		} while ((firmware_state & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0);
>  		}
> +		break;
> +	case ACB_ADAPTER_TYPE_D: {
> +		struct MessageUnit_D *reg = acb->pmuD;
> +		do {
> +			firmware_state = readl(reg->outbound_msgaddr1);
> +		} while ((firmware_state &
> +			ARCMSR_ARC1214_MESSAGE_FIRMWARE_OK) == 0);
> +		}
> +		break;
>  	}
>  }
>  
> @@ -2918,6 +3522,35 @@ static void arcmsr_hbaC_request_device_m
>  	return;
>  }
>  
> +static void arcmsr_hbaD_request_device_map(struct AdapterControlBlock *acb)
> +{
> +	struct MessageUnit_D *reg = acb->pmuD;
> +
> +	if (unlikely(atomic_read(&acb->rq_map_token) == 0) ||
> +		((acb->acb_flags & ACB_F_BUS_RESET) != 0) ||
> +		((acb->acb_flags & ACB_F_ABORT) != 0)) {
> +		mod_timer(&acb->eternal_timer,
> +			jiffies + msecs_to_jiffies(6 * HZ));
> +	} else {
> +		acb->fw_flag = FW_NORMAL;
> +		if (atomic_read(&acb->ante_token_value) ==
> +			atomic_read(&acb->rq_map_token)) {
> +			atomic_set(&acb->rq_map_token, 16);
> +		}
> +		atomic_set(&acb->ante_token_value,
> +			atomic_read(&acb->rq_map_token));
> +		if (atomic_dec_and_test(&acb->rq_map_token)) {
> +			mod_timer(&acb->eternal_timer, jiffies +
> +				msecs_to_jiffies(6 * HZ));
> +			return;
> +		}
> +		writel(ARCMSR_INBOUND_MESG0_GET_CONFIG,
> +			reg->inbound_msgaddr0);
> +		mod_timer(&acb->eternal_timer, jiffies +
> +			msecs_to_jiffies(6 * HZ));
> +	}
> +}
> +
>  static void arcmsr_request_device_map(unsigned long pacb)
>  {
>  	struct AdapterControlBlock *acb = (struct AdapterControlBlock *)pacb;
> @@ -2933,6 +3566,10 @@ static void arcmsr_request_device_map(un
>  		case ACB_ADAPTER_TYPE_C: {
>  			arcmsr_hbaC_request_device_map(acb);
>  		}
> +		break;
> +		case ACB_ADAPTER_TYPE_D:
> +			arcmsr_hbaD_request_device_map(acb);
> +		break;
>  	}
>  }
>  
> @@ -2970,6 +3607,19 @@ static void arcmsr_hbaC_start_bgrb(struc
>  	}
>  	return;
>  }
> +
> +static void arcmsr_hbaD_start_bgrb(struct AdapterControlBlock *pACB)
> +{
> +	struct MessageUnit_D *pmu = pACB->pmuD;
> +
> +	pACB->acb_flags |= ACB_F_MSG_START_BGRB;
> +	writel(ARCMSR_INBOUND_MESG0_START_BGRB, pmu->inbound_msgaddr0);
> +	if (!arcmsr_hbaD_wait_msgint_ready(pACB)) {
> +		pr_notice("arcmsr%d: wait 'start adapter "
> +			"background rebulid' timeout\n", pACB->host->host_no);
> +	}
> +}
> +
>  static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
>  {
>  	switch (acb->adapter_type) {
> @@ -2981,6 +3631,10 @@ static void arcmsr_start_adapter_bgrb(st
>  		break;
>  	case ACB_ADAPTER_TYPE_C:
>  		arcmsr_hbaC_start_bgrb(acb);
> +		break;
> +	case ACB_ADAPTER_TYPE_D:
> +		arcmsr_hbaD_start_bgrb(acb);
> +		break;
>  	}
>  }
>  
> @@ -3026,6 +3680,29 @@ static void arcmsr_clear_doorbell_queue_
>  				break;
>  		}
>  		}
> +		break;
> +	case ACB_ADAPTER_TYPE_D: {
> +		struct MessageUnit_D *reg = acb->pmuD;
> +		uint32_t outbound_doorbell, i;
> +		/* empty doorbell Qbuffer if door bell ringed */
> +		outbound_doorbell = readl(reg->outbound_doorbell);
> +		writel(outbound_doorbell, reg->outbound_doorbell);
> +		writel(ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ,
> +			reg->inbound_doorbell);
> +		for (i = 0; i < 200; i++) {
> +			msleep(20);
> +			outbound_doorbell = readl(reg->outbound_doorbell);
> +			if (outbound_doorbell &
> +				ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK) {
> +				writel(outbound_doorbell,
> +					reg->outbound_doorbell);
> +				writel(ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ,
> +					reg->inbound_doorbell);
> +			} else
> +				break;
> +		}
> +		}
> +		break;
>  	}
>  }
>  
> @@ -3056,6 +3733,7 @@ static void arcmsr_hardware_reset(struct
>  	int i, count = 0;
>  	struct MessageUnit_A __iomem *pmuA = acb->pmuA;
>  	struct MessageUnit_C __iomem *pmuC = acb->pmuC;
> +	struct MessageUnit_D *pmuD = acb->pmuD;
>  
>  	/* backup pci config data */
>  	printk(KERN_NOTICE "arcmsr%d: executing hw bus reset .....\n", acb->host->host_no);
> @@ -3076,6 +3754,8 @@ static void arcmsr_hardware_reset(struct
>  			writel(0xD, &pmuC->write_sequence);
>  		} while (((readl(&pmuC->host_diagnostic) & ARCMSR_ARC1880_DiagWrite_ENABLE) == 0) && (count < 5));
>  		writel(ARCMSR_ARC1880_RESET_ADAPTER, &pmuC->host_diagnostic);
> +	} else if ((acb->dev_id == 0x1214)) {
> +		writel(0x20, pmuD->reset_request);
>  	} else {
>  		pci_write_config_byte(acb->pdev, 0x84, 0x20);
>  	}
> @@ -3272,6 +3952,66 @@ sleep:
>  			}
>  			break;
>  		}
> +		case ACB_ADAPTER_TYPE_D: {
> +			if (acb->acb_flags & ACB_F_BUS_RESET) {
> +				long timeout;
> +				pr_notice("arcmsr: there is an bus reset"
> +					" eh proceeding.......\n");
> +				timeout = wait_event_timeout(wait_q, (acb->acb_flags
> +					& ACB_F_BUS_RESET) == 0, 220 * HZ);
> +				if (timeout)
> +					return SUCCESS;
> +			}
> +			acb->acb_flags |= ACB_F_BUS_RESET;
> +			if (!arcmsr_iop_reset(acb)) {
> +				struct MessageUnit_D *reg;
> +				reg = acb->pmuD;
> +				arcmsr_hardware_reset(acb);
> +				acb->acb_flags &= ~ACB_F_IOP_INITED;
> +			nap:
> +				ssleep(ARCMSR_SLEEPTIME);
> +				if ((readl(reg->sample_at_reset) & 0x80) != 0) {
> +					pr_err("arcmsr%d: waiting for "
> +						"hw bus reset return, retry=%d\n",
> +						acb->host->host_no, retry_count);
> +					if (retry_count > ARCMSR_RETRYCOUNT) {
> +						acb->fw_flag = FW_DEADLOCK;
> +						pr_err("arcmsr%d: waiting for hw bus"
> +							" reset return, "
> +							"RETRY TERMINATED!!\n",
> +							acb->host->host_no);
> +						return FAILED;
> +					}
> +					retry_count++;
> +					goto nap;
> +				}
> +				acb->acb_flags |= ACB_F_IOP_INITED;
> +				/* disable all outbound interrupt */
> +				intmask_org = arcmsr_disable_outbound_ints(acb);
> +				arcmsr_get_firmware_spec(acb);
> +				arcmsr_start_adapter_bgrb(acb);
> +				arcmsr_clear_doorbell_queue_buffer(acb);
> +				arcmsr_enable_outbound_ints(acb, intmask_org);
> +				atomic_set(&acb->rq_map_token, 16);
> +				atomic_set(&acb->ante_token_value, 16);
> +				acb->fw_flag = FW_NORMAL;
> +				mod_timer(&acb->eternal_timer,
> +					jiffies + msecs_to_jiffies(6 * HZ));
> +				acb->acb_flags &= ~ACB_F_BUS_RESET;
> +				rtn = SUCCESS;
> +				pr_err("arcmsr: scsi bus reset "
> +					"eh returns with success\n");
> +			} else {
> +				acb->acb_flags &= ~ACB_F_BUS_RESET;
> +				atomic_set(&acb->rq_map_token, 16);
> +				atomic_set(&acb->ante_token_value, 16);
> +				acb->fw_flag = FW_NORMAL;
> +				mod_timer(&acb->eternal_timer,
> +					jiffies + msecs_to_jiffies(6 * HZ));
> +				rtn = SUCCESS;
> +			}
> +			break;
> +		}
>  	}
>  	return rtn;
>  }
> @@ -3348,6 +4088,7 @@ static const char *arcmsr_info(struct Sc
>  	case PCI_DEVICE_ID_ARECA_1280:
>  		type = "SATA";
>  		break;
> +	case PCI_DEVICE_ID_ARECA_1214:
>  	case PCI_DEVICE_ID_ARECA_1380:
>  	case PCI_DEVICE_ID_ARECA_1381:
>  	case PCI_DEVICE_ID_ARECA_1680:
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 16/17] arcmsr: support new adapter ARC12x4 series
  2014-08-28 15:46   ` Ching Huang
@ 2014-08-28 12:49     ` Tomas Henzl
  2014-09-09 16:30       ` Christoph Hellwig
  0 siblings, 1 reply; 13+ messages in thread
From: Tomas Henzl @ 2014-08-28 12:49 UTC (permalink / raw)
  To: Ching Huang; +Cc: hch, jbottomley, dan.carpenter, linux-scsi, linux-kernel

On 08/28/2014 05:46 PM, Ching Huang wrote:
> On Wed, 2014-08-27 at 16:00 +0200, Tomas Henzl wrote:
>> On 08/19/2014 09:25 AM, Ching Huang wrote:
>>> From: Ching Huang <ching2048@areca.com.tw>
>>>
>>> Add code for supporting Areca new Raid adapter ARC12x4 series.
>>>
>>> Signed-off-by: Ching Huang <ching2048@areca.com.tw>
>>> ---
>> Hi Ching,
>> please look at the comments below -
>>
>>>  }
>>> @@ -1039,7 +1147,60 @@ static void arcmsr_done4abort_postqueue(
>>>  			error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? true : false;
>>>  			arcmsr_drain_donequeue(acb, pCCB, error);
>>>  		}
>>> -	}
>>> +		}
>>> +		break;
>>> +	case ACB_ADAPTER_TYPE_D: {
>>> +		struct MessageUnit_D  *pmu = acb->pmuD;
>>> +		uint32_t ccb_cdb_phy, outbound_write_pointer;
>>> +		uint32_t doneq_index, index_stripped, addressLow, residual;
>>> +		bool error;
>>> +		struct CommandControlBlock *pCCB;
>> I have noticed this^ in this driver already before. Sometimes it makes sense
>> when a variable is declared in a 'case' block but often it is just
>> a waste of space. In this function this is the third 'bool error' declared.
>> Is there a reason for this style (this function is not the worst case) ?
> Yea, there is many variable are duplicate declaration, I will clean it up.
>>> +		outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1;
>>> +		doneq_index = pmu->doneq_index;
>>> +		residual = atomic_read(&acb->ccboutstandingcount);
>>> +		for (i = 0; i < residual; i++) {
>>> +			while ((doneq_index & 0xFFF) !=
>>> +				(outbound_write_pointer & 0xFFF)) {
>>> +				if (doneq_index & 0x4000) {
>>> +					index_stripped = doneq_index & 0xFFF;
>>> +					index_stripped += 1;
>>> +					index_stripped %=
>>> +						ARCMSR_MAX_ARC1214_DONEQUEUE;
>>> +					pmu->doneq_index = index_stripped ?
>>> +						(index_stripped | 0x4000) :
>>> +						(index_stripped + 1);
>>> +				} else {
>>> +					index_stripped = doneq_index;
>>> +					index_stripped += 1;
>>> +					index_stripped %=
>>> +						ARCMSR_MAX_ARC1214_DONEQUEUE;
>>> +					pmu->doneq_index = index_stripped ?
>>> +						index_stripped :
>>> +						((index_stripped | 0x4000) + 1);
>>> +				}
>>> +				doneq_index = pmu->doneq_index;
>>> +				addressLow = pmu->done_qbuffer[doneq_index &
>>> +					0xFFF].addressLow;
>>> +				ccb_cdb_phy = (addressLow & 0xFFFFFFF0);
>>> +				pARCMSR_CDB = (struct  ARCMSR_CDB *)
>>> +					(acb->vir2phy_offset + ccb_cdb_phy);
>>> +				pCCB = container_of(pARCMSR_CDB,
>>> +					struct CommandControlBlock, arcmsr_cdb);
>>> +				error = (addressLow &
>>> +					ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ?
>>> +					true : false;
>>> +				arcmsr_drain_donequeue(acb, pCCB, error);
>>> +				writel(doneq_index, pmu->outboundlist_read_pointer);
>>> +			}
>>> +			mdelay(10);
>>> +			outbound_write_pointer =
>>> +				pmu->done_qbuffer[0].addressLow + 1;
>>> +			doneq_index = pmu->doneq_index;
>>> +		}
>>> +		pmu->postq_index = 0;
>>> +		pmu->doneq_index = 0x40FF;
>>> +		}
>>> +		break;
>>>  	}
>>>  }
>> ...
>>
>>>  
>>> @@ -1256,6 +1424,38 @@ static void arcmsr_post_ccb(struct Adapt
>>>  			writel(ccb_post_stamp, &phbcmu->inbound_queueport_low);
>>>  		}
>>>  		}
>>> +		break;
>>> +	case ACB_ADAPTER_TYPE_D: {
>>> +		struct MessageUnit_D  *pmu = acb->pmuD;
>>> +		u16 index_stripped;
>>> +		u16 postq_index;
> 		u16 postq_index, toggle;
>>> +		unsigned long flags;
>>> +		struct InBound_SRB *pinbound_srb;
>>> +
>>> +		spin_lock_irqsave(&acb->postq_lock, flags);
>>> +		postq_index = pmu->postq_index;
>>> +		pinbound_srb = (struct InBound_SRB *)&(pmu->post_qbuffer[postq_index & 0xFF]);
>>> +		pinbound_srb->addressHigh = dma_addr_hi32(cdb_phyaddr);
>>> +		pinbound_srb->addressLow = dma_addr_lo32(cdb_phyaddr);
>>> +		pinbound_srb->length = ccb->arc_cdb_size >> 2;
>>> +		arcmsr_cdb->msgContext = dma_addr_lo32(cdb_phyaddr);
>>> +		if (postq_index & 0x4000) {
>>> +			index_stripped = postq_index & 0xFF;
>>> +			index_stripped += 1;
>>> +			index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE;
>>> +			pmu->postq_index = index_stripped ?
>>> +				(index_stripped | 0x4000) : index_stripped;
>>> +		} else {
>>> +			index_stripped = postq_index;
>>> +			index_stripped += 1;
>>> +			index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE;
>>> +			pmu->postq_index = index_stripped ? index_stripped :
>>> +				(index_stripped | 0x4000);
>>> +		}
>> The code above could be a bit easier -
> Yea. I simplify it to following.
> 		toggle = postq_index & 0x4000;

I might be wrong but the following two lines:

> 		index_stripped = (postq_index & 0xFF) + 1;

the first '&' is not needed, because we use a modulo in a next step
>		 index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE;
and module is for certain binary numbers equivalent to '&', so this
could be changed into 
		index_stripped = postq_index + 1;
		index_stripped &= (ARCMSR_MAX_ARC1214_POSTQUEUE - 1);
( ARCMSR_MAX_ARC1214_POSTQUEUE is equal 0x100)

and this 
>		pmu->postq_index = index_stripped ? (index_stripped | toggle) :
>			(index_stripped | (toggle ^ 0x4000));
into 
		pmu->postq_index = index_stripped ? (index_stripped | toggle) :
			 (toggle ^ 0x4000);

Let us stop this discussion, it's not a bug, you may or may not include it in your next series,
we can discuss it there. 
For another question, please look below.

>> 		
>> 		arcmsr_cdb->msgContext = dma_addr_lo32(cdb_phyaddr);
>>                 index_stripped = postq_index + 1;
>>                 index_stripped &= (ARCMSR_MAX_ARC1214_POSTQUEUE - 1);
>>
>>                 if (postq_index & 0x4000)
>>                         pmu->postq_index = index_stripped ?
>>                                 (index_stripped | 0x4000) : index_stripped;
>>                 else
>>                         pmu->postq_index = index_stripped ?
>>                                  index_stripped : (index_stripped | 0x4000);
>> or am I wrong? This is repeated in the code many times
> Yea. one for postQueue and 3 times for doneQueue. They all can be simplified as above.
>>  
>>
>>> +		writel(postq_index, pmu->inboundlist_write_pointer);
>>> +		spin_unlock_irqrestore(&acb->postq_lock, flags);
>>> +		break;
>>> +		}
>>>  	}
>>>  }
>>>  
>> ...
>>> +static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb,
>>> +				struct CommandControlBlock *poll_ccb)
>>> +{
>>> +	bool error;
>>> +	uint32_t poll_ccb_done = 0, poll_count = 0, flag_ccb, ccb_cdb_phy;
>>> +	int rtn, doneq_index, index_stripped, outbound_write_pointer;
>>> +	unsigned long flags;
>>> +	struct ARCMSR_CDB *arcmsr_cdb;
>>> +	struct CommandControlBlock *pCCB;
>>> +	struct MessageUnit_D *pmu = acb->pmuD;
>>> +
>>> +polling_hbaD_ccb_retry:
>>> +	poll_count++;
>>> +	while (1) {
>>> +		outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1;
>>> +		doneq_index = pmu->doneq_index;
>> You seem to protect the doneq with a spinlock on some other places, arcmsr_hbaD_postqueue_isr
>> and below in this function. Why not here, is it intentional? 
> Before came here, the h/w interrupt was disabled. Hence, don't worry about other thread
> to change doneq_index.

I guess you mean the hw interrupts from your card. If so and if you know that no other thread on another 
processor can access the doneq_index - why do you use the spinlock just few lines below?

>>> +		if ((outbound_write_pointer & 0xFFF) == (doneq_index & 0xFFF)) {
>>> +			if (poll_ccb_done) {
>>> +				rtn = SUCCESS;
>>> +				break;
>>> +			} else {
>>> +				msleep(25);
>>> +				if (poll_count > 40) {
>>> +					rtn = FAILED;
>>> +					break;
>>> +				}
>>> +				goto polling_hbaD_ccb_retry;
>>> +			}
>>> +		}
>>> +		spin_lock_irqsave(&acb->doneq_lock, flags);
>>> +		if (doneq_index & 0x4000) {
>>> +			index_stripped = doneq_index & 0xFFF;
>>> +			index_stripped += 1;
>>> +			index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE;
>>> +			pmu->doneq_index = index_stripped ?
>>> +				(index_stripped | 0x4000) :
>>> +				(index_stripped + 1);
>>> +		} else {
>>> +			index_stripped = doneq_index;
>>> +			index_stripped += 1;
>>> +			index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE;
>>> +			pmu->doneq_index = index_stripped ? index_stripped :
>>> +				((index_stripped | 0x4000) + 1);
>>> +		}
>>> +		spin_unlock_irqrestore(&acb->doneq_lock, flags);
>>> +		doneq_index = pmu->doneq_index;
>>> +		flag_ccb = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow;
>>> +		ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0);
>>> +		arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset +
>>> +			ccb_cdb_phy);
>>> +		pCCB = container_of(arcmsr_cdb, struct CommandControlBlock,
>>> +			arcmsr_cdb);
>>> +		poll_ccb_done |= (pCCB == poll_ccb) ? 1 : 0;
>>> +		if ((pCCB->acb != acb) ||
>>> +			(pCCB->startdone != ARCMSR_CCB_START)) {
>>> +			if (pCCB->startdone == ARCMSR_CCB_ABORTED) {
>>> +				pr_notice("arcmsr%d: scsi id = %d "
>>> +					"lun = %d ccb = '0x%p' poll command "
>>> +					"abort successfully\n"
>>> +					, acb->host->host_no
>>> +					, pCCB->pcmd->device->id
>>> +					, (u32)pCCB->pcmd->device->lun
>>> +					, pCCB);
>>> +				pCCB->pcmd->result = DID_ABORT << 16;
>>> +				arcmsr_ccb_complete(pCCB);
>>> +				continue;
>>> +			}
>>> +			pr_notice("arcmsr%d: polling an illegal "
>>> +				"ccb command done ccb = '0x%p' "
>>> +				"ccboutstandingcount = %d\n"
>>> +				, acb->host->host_no
>>> +				, pCCB
>>> +				, atomic_read(&acb->ccboutstandingcount));
>>> +			continue;
>>> +		}
>>> +		error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1)
>>> +			? true : false;
>>> +		arcmsr_report_ccb_state(acb, pCCB, error);
>>> +	}
>>> +	return rtn;
>>> +}
>>> +
>>>  static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb,
>>>  					struct CommandControlBlock *poll_ccb)
>>>  {
>>> @@ -2711,6 +3280,10 @@ static int arcmsr_polling_ccbdone(struct
>>>  	case ACB_ADAPTER_TYPE_C: {
>>>  		rtn = arcmsr_hbaC_polling_ccbdone(acb, poll_ccb);
>>>  		}
>>> +		break;
>>> +	case ACB_ADAPTER_TYPE_D:
>>> +		rtn = arcmsr_hbaD_polling_ccbdone(acb, poll_ccb);
>>> +		break;
>>>  	}
>>>  	return rtn;
>>>  }
>>> @@ -2728,6 +3301,7 @@ static int arcmsr_iop_confirm(struct Ada
>>>  	*/
>>>  	switch (acb->adapter_type) {
>>>  		case ACB_ADAPTER_TYPE_B:
>>> +		case ACB_ADAPTER_TYPE_D:
>>>  			dma_coherent_handle = acb->dma_coherent_handle2;
>>>  			break;
>>>  		default:
>>> @@ -2817,6 +3391,27 @@ static int arcmsr_iop_confirm(struct Ada
>>>  			}
>>>  		}
>>>  		}
>>> +		break;
>>> +	case ACB_ADAPTER_TYPE_D: {
>>> +		uint32_t __iomem *rwbuffer;
>>> +		struct MessageUnit_D *reg = acb->pmuD;
>>> +		reg->postq_index = 0;
>>> +		reg->doneq_index = 0;
>>> +		rwbuffer = reg->msgcode_rwbuffer;
>>> +		writel(ARCMSR_SIGNATURE_SET_CONFIG, rwbuffer++);
>>> +		writel(cdb_phyaddr_hi32, rwbuffer++);
>>> +		writel(cdb_phyaddr, rwbuffer++);
>>> +		writel(cdb_phyaddr + (ARCMSR_MAX_ARC1214_POSTQUEUE *
>>> +			sizeof(struct InBound_SRB)), rwbuffer++);
>>> +		writel(0x100, rwbuffer);
>>> +		writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, reg->inbound_msgaddr0);
>>> +		if (!arcmsr_hbaD_wait_msgint_ready(acb)) {
>>> +			pr_notice("arcmsr%d: 'set command Q window' timeout\n",
>>> +				acb->host->host_no);
>>> +			return 1;
>>> +		}
>>> +		}
>>> +		break;
>>>  	}
>>>  	return 0;
>>>  }
>>> @@ -2848,6 +3443,15 @@ static void arcmsr_wait_firmware_ready(s
>>>  			firmware_state = readl(&reg->outbound_msgaddr1);
>>>  		} while ((firmware_state & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0);
>>>  		}
>>> +		break;
>>> +	case ACB_ADAPTER_TYPE_D: {
>>> +		struct MessageUnit_D *reg = acb->pmuD;
>>> +		do {
>>> +			firmware_state = readl(reg->outbound_msgaddr1);
>>> +		} while ((firmware_state &
>>> +			ARCMSR_ARC1214_MESSAGE_FIRMWARE_OK) == 0);
>>> +		}
>>> +		break;
>>>  	}
>>>  }
>>>  
>>> @@ -2918,6 +3522,35 @@ static void arcmsr_hbaC_request_device_m
>>>  	return;
>>>  }
>>>  
>>> +static void arcmsr_hbaD_request_device_map(struct AdapterControlBlock *acb)
>>> +{
>>> +	struct MessageUnit_D *reg = acb->pmuD;
>>> +
>>> +	if (unlikely(atomic_read(&acb->rq_map_token) == 0) ||
>>> +		((acb->acb_flags & ACB_F_BUS_RESET) != 0) ||
>>> +		((acb->acb_flags & ACB_F_ABORT) != 0)) {
>>> +		mod_timer(&acb->eternal_timer,
>>> +			jiffies + msecs_to_jiffies(6 * HZ));
>>> +	} else {
>>> +		acb->fw_flag = FW_NORMAL;
>>> +		if (atomic_read(&acb->ante_token_value) ==
>>> +			atomic_read(&acb->rq_map_token)) {
>>> +			atomic_set(&acb->rq_map_token, 16);
>>> +		}
>>> +		atomic_set(&acb->ante_token_value,
>>> +			atomic_read(&acb->rq_map_token));
>>> +		if (atomic_dec_and_test(&acb->rq_map_token)) {
>>> +			mod_timer(&acb->eternal_timer, jiffies +
>>> +				msecs_to_jiffies(6 * HZ));
>>> +			return;
>>> +		}
>>> +		writel(ARCMSR_INBOUND_MESG0_GET_CONFIG,
>>> +			reg->inbound_msgaddr0);
>>> +		mod_timer(&acb->eternal_timer, jiffies +
>>> +			msecs_to_jiffies(6 * HZ));
>>> +	}
>>> +}
>>> +
>>>  static void arcmsr_request_device_map(unsigned long pacb)
>>>  {
>>>  	struct AdapterControlBlock *acb = (struct AdapterControlBlock *)pacb;
>>> @@ -2933,6 +3566,10 @@ static void arcmsr_request_device_map(un
>>>  		case ACB_ADAPTER_TYPE_C: {
>>>  			arcmsr_hbaC_request_device_map(acb);
>>>  		}
>>> +		break;
>>> +		case ACB_ADAPTER_TYPE_D:
>>> +			arcmsr_hbaD_request_device_map(acb);
>>> +		break;
>>>  	}
>>>  }
>>>  
>>> @@ -2970,6 +3607,19 @@ static void arcmsr_hbaC_start_bgrb(struc
>>>  	}
>>>  	return;
>>>  }
>>> +
>>> +static void arcmsr_hbaD_start_bgrb(struct AdapterControlBlock *pACB)
>>> +{
>>> +	struct MessageUnit_D *pmu = pACB->pmuD;
>>> +
>>> +	pACB->acb_flags |= ACB_F_MSG_START_BGRB;
>>> +	writel(ARCMSR_INBOUND_MESG0_START_BGRB, pmu->inbound_msgaddr0);
>>> +	if (!arcmsr_hbaD_wait_msgint_ready(pACB)) {
>>> +		pr_notice("arcmsr%d: wait 'start adapter "
>>> +			"background rebulid' timeout\n", pACB->host->host_no);
>>> +	}
>>> +}
>>> +
>>>  static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
>>>  {
>>>  	switch (acb->adapter_type) {
>>> @@ -2981,6 +3631,10 @@ static void arcmsr_start_adapter_bgrb(st
>>>  		break;
>>>  	case ACB_ADAPTER_TYPE_C:
>>>  		arcmsr_hbaC_start_bgrb(acb);
>>> +		break;
>>> +	case ACB_ADAPTER_TYPE_D:
>>> +		arcmsr_hbaD_start_bgrb(acb);
>>> +		break;
>>>  	}
>>>  }
>>>  
>>> @@ -3026,6 +3680,29 @@ static void arcmsr_clear_doorbell_queue_
>>>  				break;
>>>  		}
>>>  		}
>>> +		break;
>>> +	case ACB_ADAPTER_TYPE_D: {
>>> +		struct MessageUnit_D *reg = acb->pmuD;
>>> +		uint32_t outbound_doorbell, i;
>>> +		/* empty doorbell Qbuffer if door bell ringed */
>>> +		outbound_doorbell = readl(reg->outbound_doorbell);
>>> +		writel(outbound_doorbell, reg->outbound_doorbell);
>>> +		writel(ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ,
>>> +			reg->inbound_doorbell);
>>> +		for (i = 0; i < 200; i++) {
>>> +			msleep(20);
>>> +			outbound_doorbell = readl(reg->outbound_doorbell);
>>> +			if (outbound_doorbell &
>>> +				ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK) {
>>> +				writel(outbound_doorbell,
>>> +					reg->outbound_doorbell);
>>> +				writel(ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ,
>>> +					reg->inbound_doorbell);
>>> +			} else
>>> +				break;
>>> +		}
>>> +		}
>>> +		break;
>>>  	}
>>>  }
>>>  
>>> @@ -3056,6 +3733,7 @@ static void arcmsr_hardware_reset(struct
>>>  	int i, count = 0;
>>>  	struct MessageUnit_A __iomem *pmuA = acb->pmuA;
>>>  	struct MessageUnit_C __iomem *pmuC = acb->pmuC;
>>> +	struct MessageUnit_D *pmuD = acb->pmuD;
>>>  
>>>  	/* backup pci config data */
>>>  	printk(KERN_NOTICE "arcmsr%d: executing hw bus reset .....\n", acb->host->host_no);
>>> @@ -3076,6 +3754,8 @@ static void arcmsr_hardware_reset(struct
>>>  			writel(0xD, &pmuC->write_sequence);
>>>  		} while (((readl(&pmuC->host_diagnostic) & ARCMSR_ARC1880_DiagWrite_ENABLE) == 0) && (count < 5));
>>>  		writel(ARCMSR_ARC1880_RESET_ADAPTER, &pmuC->host_diagnostic);
>>> +	} else if ((acb->dev_id == 0x1214)) {
>>> +		writel(0x20, pmuD->reset_request);
>>>  	} else {
>>>  		pci_write_config_byte(acb->pdev, 0x84, 0x20);
>>>  	}
>>> @@ -3272,6 +3952,66 @@ sleep:
>>>  			}
>>>  			break;
>>>  		}
>>> +		case ACB_ADAPTER_TYPE_D: {
>>> +			if (acb->acb_flags & ACB_F_BUS_RESET) {
>>> +				long timeout;
>>> +				pr_notice("arcmsr: there is an bus reset"
>>> +					" eh proceeding.......\n");
>>> +				timeout = wait_event_timeout(wait_q, (acb->acb_flags
>>> +					& ACB_F_BUS_RESET) == 0, 220 * HZ);
>>> +				if (timeout)
>>> +					return SUCCESS;
>>> +			}
>>> +			acb->acb_flags |= ACB_F_BUS_RESET;
>>> +			if (!arcmsr_iop_reset(acb)) {
>>> +				struct MessageUnit_D *reg;
>>> +				reg = acb->pmuD;
>>> +				arcmsr_hardware_reset(acb);
>>> +				acb->acb_flags &= ~ACB_F_IOP_INITED;
>>> +			nap:
>>> +				ssleep(ARCMSR_SLEEPTIME);
>>> +				if ((readl(reg->sample_at_reset) & 0x80) != 0) {
>>> +					pr_err("arcmsr%d: waiting for "
>>> +						"hw bus reset return, retry=%d\n",
>>> +						acb->host->host_no, retry_count);
>>> +					if (retry_count > ARCMSR_RETRYCOUNT) {
>>> +						acb->fw_flag = FW_DEADLOCK;
>>> +						pr_err("arcmsr%d: waiting for hw bus"
>>> +							" reset return, "
>>> +							"RETRY TERMINATED!!\n",
>>> +							acb->host->host_no);
>>> +						return FAILED;
>>> +					}
>>> +					retry_count++;
>>> +					goto nap;
>>> +				}
>>> +				acb->acb_flags |= ACB_F_IOP_INITED;
>>> +				/* disable all outbound interrupt */
>>> +				intmask_org = arcmsr_disable_outbound_ints(acb);
>>> +				arcmsr_get_firmware_spec(acb);
>>> +				arcmsr_start_adapter_bgrb(acb);
>>> +				arcmsr_clear_doorbell_queue_buffer(acb);
>>> +				arcmsr_enable_outbound_ints(acb, intmask_org);
>>> +				atomic_set(&acb->rq_map_token, 16);
>>> +				atomic_set(&acb->ante_token_value, 16);
>>> +				acb->fw_flag = FW_NORMAL;
>>> +				mod_timer(&acb->eternal_timer,
>>> +					jiffies + msecs_to_jiffies(6 * HZ));
>>> +				acb->acb_flags &= ~ACB_F_BUS_RESET;
>>> +				rtn = SUCCESS;
>>> +				pr_err("arcmsr: scsi bus reset "
>>> +					"eh returns with success\n");
>>> +			} else {
>>> +				acb->acb_flags &= ~ACB_F_BUS_RESET;
>>> +				atomic_set(&acb->rq_map_token, 16);
>>> +				atomic_set(&acb->ante_token_value, 16);
>>> +				acb->fw_flag = FW_NORMAL;
>>> +				mod_timer(&acb->eternal_timer,
>>> +					jiffies + msecs_to_jiffies(6 * HZ));
>>> +				rtn = SUCCESS;
>>> +			}
>>> +			break;
>>> +		}
>>>  	}
>>>  	return rtn;
>>>  }
>>> @@ -3348,6 +4088,7 @@ static const char *arcmsr_info(struct Sc
>>>  	case PCI_DEVICE_ID_ARECA_1280:
>>>  		type = "SATA";
>>>  		break;
>>> +	case PCI_DEVICE_ID_ARECA_1214:
>>>  	case PCI_DEVICE_ID_ARECA_1380:
>>>  	case PCI_DEVICE_ID_ARECA_1381:
>>>  	case PCI_DEVICE_ID_ARECA_1680:
>>>
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 16/17] arcmsr: support new adapter ARC12x4 series
  2014-08-27 14:00 ` Tomas Henzl
@ 2014-08-28 15:46   ` Ching Huang
  2014-08-28 12:49     ` Tomas Henzl
  0 siblings, 1 reply; 13+ messages in thread
From: Ching Huang @ 2014-08-28 15:46 UTC (permalink / raw)
  To: Tomas Henzl; +Cc: hch, jbottomley, dan.carpenter, linux-scsi, linux-kernel

On Wed, 2014-08-27 at 16:00 +0200, Tomas Henzl wrote:
> On 08/19/2014 09:25 AM, Ching Huang wrote:
> > From: Ching Huang <ching2048@areca.com.tw>
> >
> > Add code for supporting Areca new Raid adapter ARC12x4 series.
> >
> > Signed-off-by: Ching Huang <ching2048@areca.com.tw>
> > ---
> 
> Hi Ching,
> please look at the comments below -
> 
> >  }
> > @@ -1039,7 +1147,60 @@ static void arcmsr_done4abort_postqueue(
> >  			error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? true : false;
> >  			arcmsr_drain_donequeue(acb, pCCB, error);
> >  		}
> > -	}
> > +		}
> > +		break;
> > +	case ACB_ADAPTER_TYPE_D: {
> > +		struct MessageUnit_D  *pmu = acb->pmuD;
> > +		uint32_t ccb_cdb_phy, outbound_write_pointer;
> > +		uint32_t doneq_index, index_stripped, addressLow, residual;
> > +		bool error;
> > +		struct CommandControlBlock *pCCB;
> 
> I have noticed this^ in this driver already before. Sometimes it makes sense
> when a variable is declared in a 'case' block but often it is just
> a waste of space. In this function this is the third 'bool error' declared.
> Is there a reason for this style (this function is not the worst case) ?
Yea, there is many variable are duplicate declaration, I will clean it up.
> 
> > +		outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1;
> > +		doneq_index = pmu->doneq_index;
> > +		residual = atomic_read(&acb->ccboutstandingcount);
> > +		for (i = 0; i < residual; i++) {
> > +			while ((doneq_index & 0xFFF) !=
> > +				(outbound_write_pointer & 0xFFF)) {
> > +				if (doneq_index & 0x4000) {
> > +					index_stripped = doneq_index & 0xFFF;
> > +					index_stripped += 1;
> > +					index_stripped %=
> > +						ARCMSR_MAX_ARC1214_DONEQUEUE;
> > +					pmu->doneq_index = index_stripped ?
> > +						(index_stripped | 0x4000) :
> > +						(index_stripped + 1);
> > +				} else {
> > +					index_stripped = doneq_index;
> > +					index_stripped += 1;
> > +					index_stripped %=
> > +						ARCMSR_MAX_ARC1214_DONEQUEUE;
> > +					pmu->doneq_index = index_stripped ?
> > +						index_stripped :
> > +						((index_stripped | 0x4000) + 1);
> > +				}
> > +				doneq_index = pmu->doneq_index;
> > +				addressLow = pmu->done_qbuffer[doneq_index &
> > +					0xFFF].addressLow;
> > +				ccb_cdb_phy = (addressLow & 0xFFFFFFF0);
> > +				pARCMSR_CDB = (struct  ARCMSR_CDB *)
> > +					(acb->vir2phy_offset + ccb_cdb_phy);
> > +				pCCB = container_of(pARCMSR_CDB,
> > +					struct CommandControlBlock, arcmsr_cdb);
> > +				error = (addressLow &
> > +					ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ?
> > +					true : false;
> > +				arcmsr_drain_donequeue(acb, pCCB, error);
> > +				writel(doneq_index, pmu->outboundlist_read_pointer);
> > +			}
> > +			mdelay(10);
> > +			outbound_write_pointer =
> > +				pmu->done_qbuffer[0].addressLow + 1;
> > +			doneq_index = pmu->doneq_index;
> > +		}
> > +		pmu->postq_index = 0;
> > +		pmu->doneq_index = 0x40FF;
> > +		}
> > +		break;
> >  	}
> >  }
> ...
> 
> >
> >  
> > @@ -1256,6 +1424,38 @@ static void arcmsr_post_ccb(struct Adapt
> >  			writel(ccb_post_stamp, &phbcmu->inbound_queueport_low);
> >  		}
> >  		}
> > +		break;
> > +	case ACB_ADAPTER_TYPE_D: {
> > +		struct MessageUnit_D  *pmu = acb->pmuD;
> > +		u16 index_stripped;
> > +		u16 postq_index;
		u16 postq_index, toggle;
> > +		unsigned long flags;
> > +		struct InBound_SRB *pinbound_srb;
> > +
> > +		spin_lock_irqsave(&acb->postq_lock, flags);
> > +		postq_index = pmu->postq_index;
> > +		pinbound_srb = (struct InBound_SRB *)&(pmu->post_qbuffer[postq_index & 0xFF]);
> > +		pinbound_srb->addressHigh = dma_addr_hi32(cdb_phyaddr);
> > +		pinbound_srb->addressLow = dma_addr_lo32(cdb_phyaddr);
> > +		pinbound_srb->length = ccb->arc_cdb_size >> 2;
> > +		arcmsr_cdb->msgContext = dma_addr_lo32(cdb_phyaddr);
> > +		if (postq_index & 0x4000) {
> > +			index_stripped = postq_index & 0xFF;
> > +			index_stripped += 1;
> > +			index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE;
> > +			pmu->postq_index = index_stripped ?
> > +				(index_stripped | 0x4000) : index_stripped;
> > +		} else {
> > +			index_stripped = postq_index;
> > +			index_stripped += 1;
> > +			index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE;
> > +			pmu->postq_index = index_stripped ? index_stripped :
> > +				(index_stripped | 0x4000);
> > +		}
> 
> The code above could be a bit easier -
Yea. I simplify it to following.
		toggle = postq_index & 0x4000;
		index_stripped = (postq_index & 0xFF) + 1;
		index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE;
		pmu->postq_index = index_stripped ? (index_stripped | toggle) :
			(index_stripped | (toggle ^ 0x4000));
> 		
> 		arcmsr_cdb->msgContext = dma_addr_lo32(cdb_phyaddr);
>                 index_stripped = postq_index + 1;
>                 index_stripped &= (ARCMSR_MAX_ARC1214_POSTQUEUE - 1);
> 
>                 if (postq_index & 0x4000)
>                         pmu->postq_index = index_stripped ?
>                                 (index_stripped | 0x4000) : index_stripped;
>                 else
>                         pmu->postq_index = index_stripped ?
>                                  index_stripped : (index_stripped | 0x4000);
> or am I wrong? This is repeated in the code many times
Yea. one for postQueue and 3 times for doneQueue. They all can be simplified as above.
>  
> 
> > +		writel(postq_index, pmu->inboundlist_write_pointer);
> > +		spin_unlock_irqrestore(&acb->postq_lock, flags);
> > +		break;
> > +		}
> >  	}
> >  }
> >  
> ...
> > +static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb,
> > +				struct CommandControlBlock *poll_ccb)
> > +{
> > +	bool error;
> > +	uint32_t poll_ccb_done = 0, poll_count = 0, flag_ccb, ccb_cdb_phy;
> > +	int rtn, doneq_index, index_stripped, outbound_write_pointer;
> > +	unsigned long flags;
> > +	struct ARCMSR_CDB *arcmsr_cdb;
> > +	struct CommandControlBlock *pCCB;
> > +	struct MessageUnit_D *pmu = acb->pmuD;
> > +
> > +polling_hbaD_ccb_retry:
> > +	poll_count++;
> > +	while (1) {
> > +		outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1;
> > +		doneq_index = pmu->doneq_index;
> 
> You seem to protect the doneq with a spinlock on some other places, arcmsr_hbaD_postqueue_isr
> and below in this function. Why not here, is it intentional? 
Before came here, the h/w interrupt was disabled. Hence, don't worry about other thread
to change doneq_index.
> 
> > +		if ((outbound_write_pointer & 0xFFF) == (doneq_index & 0xFFF)) {
> > +			if (poll_ccb_done) {
> > +				rtn = SUCCESS;
> > +				break;
> > +			} else {
> > +				msleep(25);
> > +				if (poll_count > 40) {
> > +					rtn = FAILED;
> > +					break;
> > +				}
> > +				goto polling_hbaD_ccb_retry;
> > +			}
> > +		}
> > +		spin_lock_irqsave(&acb->doneq_lock, flags);
> > +		if (doneq_index & 0x4000) {
> > +			index_stripped = doneq_index & 0xFFF;
> > +			index_stripped += 1;
> > +			index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE;
> > +			pmu->doneq_index = index_stripped ?
> > +				(index_stripped | 0x4000) :
> > +				(index_stripped + 1);
> > +		} else {
> > +			index_stripped = doneq_index;
> > +			index_stripped += 1;
> > +			index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE;
> > +			pmu->doneq_index = index_stripped ? index_stripped :
> > +				((index_stripped | 0x4000) + 1);
> > +		}
> > +		spin_unlock_irqrestore(&acb->doneq_lock, flags);
> > +		doneq_index = pmu->doneq_index;
> > +		flag_ccb = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow;
> > +		ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0);
> > +		arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset +
> > +			ccb_cdb_phy);
> > +		pCCB = container_of(arcmsr_cdb, struct CommandControlBlock,
> > +			arcmsr_cdb);
> > +		poll_ccb_done |= (pCCB == poll_ccb) ? 1 : 0;
> > +		if ((pCCB->acb != acb) ||
> > +			(pCCB->startdone != ARCMSR_CCB_START)) {
> > +			if (pCCB->startdone == ARCMSR_CCB_ABORTED) {
> > +				pr_notice("arcmsr%d: scsi id = %d "
> > +					"lun = %d ccb = '0x%p' poll command "
> > +					"abort successfully\n"
> > +					, acb->host->host_no
> > +					, pCCB->pcmd->device->id
> > +					, (u32)pCCB->pcmd->device->lun
> > +					, pCCB);
> > +				pCCB->pcmd->result = DID_ABORT << 16;
> > +				arcmsr_ccb_complete(pCCB);
> > +				continue;
> > +			}
> > +			pr_notice("arcmsr%d: polling an illegal "
> > +				"ccb command done ccb = '0x%p' "
> > +				"ccboutstandingcount = %d\n"
> > +				, acb->host->host_no
> > +				, pCCB
> > +				, atomic_read(&acb->ccboutstandingcount));
> > +			continue;
> > +		}
> > +		error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1)
> > +			? true : false;
> > +		arcmsr_report_ccb_state(acb, pCCB, error);
> > +	}
> > +	return rtn;
> > +}
> > +
> >  static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb,
> >  					struct CommandControlBlock *poll_ccb)
> >  {
> > @@ -2711,6 +3280,10 @@ static int arcmsr_polling_ccbdone(struct
> >  	case ACB_ADAPTER_TYPE_C: {
> >  		rtn = arcmsr_hbaC_polling_ccbdone(acb, poll_ccb);
> >  		}
> > +		break;
> > +	case ACB_ADAPTER_TYPE_D:
> > +		rtn = arcmsr_hbaD_polling_ccbdone(acb, poll_ccb);
> > +		break;
> >  	}
> >  	return rtn;
> >  }
> > @@ -2728,6 +3301,7 @@ static int arcmsr_iop_confirm(struct Ada
> >  	*/
> >  	switch (acb->adapter_type) {
> >  		case ACB_ADAPTER_TYPE_B:
> > +		case ACB_ADAPTER_TYPE_D:
> >  			dma_coherent_handle = acb->dma_coherent_handle2;
> >  			break;
> >  		default:
> > @@ -2817,6 +3391,27 @@ static int arcmsr_iop_confirm(struct Ada
> >  			}
> >  		}
> >  		}
> > +		break;
> > +	case ACB_ADAPTER_TYPE_D: {
> > +		uint32_t __iomem *rwbuffer;
> > +		struct MessageUnit_D *reg = acb->pmuD;
> > +		reg->postq_index = 0;
> > +		reg->doneq_index = 0;
> > +		rwbuffer = reg->msgcode_rwbuffer;
> > +		writel(ARCMSR_SIGNATURE_SET_CONFIG, rwbuffer++);
> > +		writel(cdb_phyaddr_hi32, rwbuffer++);
> > +		writel(cdb_phyaddr, rwbuffer++);
> > +		writel(cdb_phyaddr + (ARCMSR_MAX_ARC1214_POSTQUEUE *
> > +			sizeof(struct InBound_SRB)), rwbuffer++);
> > +		writel(0x100, rwbuffer);
> > +		writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, reg->inbound_msgaddr0);
> > +		if (!arcmsr_hbaD_wait_msgint_ready(acb)) {
> > +			pr_notice("arcmsr%d: 'set command Q window' timeout\n",
> > +				acb->host->host_no);
> > +			return 1;
> > +		}
> > +		}
> > +		break;
> >  	}
> >  	return 0;
> >  }
> > @@ -2848,6 +3443,15 @@ static void arcmsr_wait_firmware_ready(s
> >  			firmware_state = readl(&reg->outbound_msgaddr1);
> >  		} while ((firmware_state & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0);
> >  		}
> > +		break;
> > +	case ACB_ADAPTER_TYPE_D: {
> > +		struct MessageUnit_D *reg = acb->pmuD;
> > +		do {
> > +			firmware_state = readl(reg->outbound_msgaddr1);
> > +		} while ((firmware_state &
> > +			ARCMSR_ARC1214_MESSAGE_FIRMWARE_OK) == 0);
> > +		}
> > +		break;
> >  	}
> >  }
> >  
> > @@ -2918,6 +3522,35 @@ static void arcmsr_hbaC_request_device_m
> >  	return;
> >  }
> >  
> > +static void arcmsr_hbaD_request_device_map(struct AdapterControlBlock *acb)
> > +{
> > +	struct MessageUnit_D *reg = acb->pmuD;
> > +
> > +	if (unlikely(atomic_read(&acb->rq_map_token) == 0) ||
> > +		((acb->acb_flags & ACB_F_BUS_RESET) != 0) ||
> > +		((acb->acb_flags & ACB_F_ABORT) != 0)) {
> > +		mod_timer(&acb->eternal_timer,
> > +			jiffies + msecs_to_jiffies(6 * HZ));
> > +	} else {
> > +		acb->fw_flag = FW_NORMAL;
> > +		if (atomic_read(&acb->ante_token_value) ==
> > +			atomic_read(&acb->rq_map_token)) {
> > +			atomic_set(&acb->rq_map_token, 16);
> > +		}
> > +		atomic_set(&acb->ante_token_value,
> > +			atomic_read(&acb->rq_map_token));
> > +		if (atomic_dec_and_test(&acb->rq_map_token)) {
> > +			mod_timer(&acb->eternal_timer, jiffies +
> > +				msecs_to_jiffies(6 * HZ));
> > +			return;
> > +		}
> > +		writel(ARCMSR_INBOUND_MESG0_GET_CONFIG,
> > +			reg->inbound_msgaddr0);
> > +		mod_timer(&acb->eternal_timer, jiffies +
> > +			msecs_to_jiffies(6 * HZ));
> > +	}
> > +}
> > +
> >  static void arcmsr_request_device_map(unsigned long pacb)
> >  {
> >  	struct AdapterControlBlock *acb = (struct AdapterControlBlock *)pacb;
> > @@ -2933,6 +3566,10 @@ static void arcmsr_request_device_map(un
> >  		case ACB_ADAPTER_TYPE_C: {
> >  			arcmsr_hbaC_request_device_map(acb);
> >  		}
> > +		break;
> > +		case ACB_ADAPTER_TYPE_D:
> > +			arcmsr_hbaD_request_device_map(acb);
> > +		break;
> >  	}
> >  }
> >  
> > @@ -2970,6 +3607,19 @@ static void arcmsr_hbaC_start_bgrb(struc
> >  	}
> >  	return;
> >  }
> > +
> > +static void arcmsr_hbaD_start_bgrb(struct AdapterControlBlock *pACB)
> > +{
> > +	struct MessageUnit_D *pmu = pACB->pmuD;
> > +
> > +	pACB->acb_flags |= ACB_F_MSG_START_BGRB;
> > +	writel(ARCMSR_INBOUND_MESG0_START_BGRB, pmu->inbound_msgaddr0);
> > +	if (!arcmsr_hbaD_wait_msgint_ready(pACB)) {
> > +		pr_notice("arcmsr%d: wait 'start adapter "
> > +			"background rebulid' timeout\n", pACB->host->host_no);
> > +	}
> > +}
> > +
> >  static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
> >  {
> >  	switch (acb->adapter_type) {
> > @@ -2981,6 +3631,10 @@ static void arcmsr_start_adapter_bgrb(st
> >  		break;
> >  	case ACB_ADAPTER_TYPE_C:
> >  		arcmsr_hbaC_start_bgrb(acb);
> > +		break;
> > +	case ACB_ADAPTER_TYPE_D:
> > +		arcmsr_hbaD_start_bgrb(acb);
> > +		break;
> >  	}
> >  }
> >  
> > @@ -3026,6 +3680,29 @@ static void arcmsr_clear_doorbell_queue_
> >  				break;
> >  		}
> >  		}
> > +		break;
> > +	case ACB_ADAPTER_TYPE_D: {
> > +		struct MessageUnit_D *reg = acb->pmuD;
> > +		uint32_t outbound_doorbell, i;
> > +		/* empty doorbell Qbuffer if door bell ringed */
> > +		outbound_doorbell = readl(reg->outbound_doorbell);
> > +		writel(outbound_doorbell, reg->outbound_doorbell);
> > +		writel(ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ,
> > +			reg->inbound_doorbell);
> > +		for (i = 0; i < 200; i++) {
> > +			msleep(20);
> > +			outbound_doorbell = readl(reg->outbound_doorbell);
> > +			if (outbound_doorbell &
> > +				ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK) {
> > +				writel(outbound_doorbell,
> > +					reg->outbound_doorbell);
> > +				writel(ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ,
> > +					reg->inbound_doorbell);
> > +			} else
> > +				break;
> > +		}
> > +		}
> > +		break;
> >  	}
> >  }
> >  
> > @@ -3056,6 +3733,7 @@ static void arcmsr_hardware_reset(struct
> >  	int i, count = 0;
> >  	struct MessageUnit_A __iomem *pmuA = acb->pmuA;
> >  	struct MessageUnit_C __iomem *pmuC = acb->pmuC;
> > +	struct MessageUnit_D *pmuD = acb->pmuD;
> >  
> >  	/* backup pci config data */
> >  	printk(KERN_NOTICE "arcmsr%d: executing hw bus reset .....\n", acb->host->host_no);
> > @@ -3076,6 +3754,8 @@ static void arcmsr_hardware_reset(struct
> >  			writel(0xD, &pmuC->write_sequence);
> >  		} while (((readl(&pmuC->host_diagnostic) & ARCMSR_ARC1880_DiagWrite_ENABLE) == 0) && (count < 5));
> >  		writel(ARCMSR_ARC1880_RESET_ADAPTER, &pmuC->host_diagnostic);
> > +	} else if ((acb->dev_id == 0x1214)) {
> > +		writel(0x20, pmuD->reset_request);
> >  	} else {
> >  		pci_write_config_byte(acb->pdev, 0x84, 0x20);
> >  	}
> > @@ -3272,6 +3952,66 @@ sleep:
> >  			}
> >  			break;
> >  		}
> > +		case ACB_ADAPTER_TYPE_D: {
> > +			if (acb->acb_flags & ACB_F_BUS_RESET) {
> > +				long timeout;
> > +				pr_notice("arcmsr: there is an bus reset"
> > +					" eh proceeding.......\n");
> > +				timeout = wait_event_timeout(wait_q, (acb->acb_flags
> > +					& ACB_F_BUS_RESET) == 0, 220 * HZ);
> > +				if (timeout)
> > +					return SUCCESS;
> > +			}
> > +			acb->acb_flags |= ACB_F_BUS_RESET;
> > +			if (!arcmsr_iop_reset(acb)) {
> > +				struct MessageUnit_D *reg;
> > +				reg = acb->pmuD;
> > +				arcmsr_hardware_reset(acb);
> > +				acb->acb_flags &= ~ACB_F_IOP_INITED;
> > +			nap:
> > +				ssleep(ARCMSR_SLEEPTIME);
> > +				if ((readl(reg->sample_at_reset) & 0x80) != 0) {
> > +					pr_err("arcmsr%d: waiting for "
> > +						"hw bus reset return, retry=%d\n",
> > +						acb->host->host_no, retry_count);
> > +					if (retry_count > ARCMSR_RETRYCOUNT) {
> > +						acb->fw_flag = FW_DEADLOCK;
> > +						pr_err("arcmsr%d: waiting for hw bus"
> > +							" reset return, "
> > +							"RETRY TERMINATED!!\n",
> > +							acb->host->host_no);
> > +						return FAILED;
> > +					}
> > +					retry_count++;
> > +					goto nap;
> > +				}
> > +				acb->acb_flags |= ACB_F_IOP_INITED;
> > +				/* disable all outbound interrupt */
> > +				intmask_org = arcmsr_disable_outbound_ints(acb);
> > +				arcmsr_get_firmware_spec(acb);
> > +				arcmsr_start_adapter_bgrb(acb);
> > +				arcmsr_clear_doorbell_queue_buffer(acb);
> > +				arcmsr_enable_outbound_ints(acb, intmask_org);
> > +				atomic_set(&acb->rq_map_token, 16);
> > +				atomic_set(&acb->ante_token_value, 16);
> > +				acb->fw_flag = FW_NORMAL;
> > +				mod_timer(&acb->eternal_timer,
> > +					jiffies + msecs_to_jiffies(6 * HZ));
> > +				acb->acb_flags &= ~ACB_F_BUS_RESET;
> > +				rtn = SUCCESS;
> > +				pr_err("arcmsr: scsi bus reset "
> > +					"eh returns with success\n");
> > +			} else {
> > +				acb->acb_flags &= ~ACB_F_BUS_RESET;
> > +				atomic_set(&acb->rq_map_token, 16);
> > +				atomic_set(&acb->ante_token_value, 16);
> > +				acb->fw_flag = FW_NORMAL;
> > +				mod_timer(&acb->eternal_timer,
> > +					jiffies + msecs_to_jiffies(6 * HZ));
> > +				rtn = SUCCESS;
> > +			}
> > +			break;
> > +		}
> >  	}
> >  	return rtn;
> >  }
> > @@ -3348,6 +4088,7 @@ static const char *arcmsr_info(struct Sc
> >  	case PCI_DEVICE_ID_ARECA_1280:
> >  		type = "SATA";
> >  		break;
> > +	case PCI_DEVICE_ID_ARECA_1214:
> >  	case PCI_DEVICE_ID_ARECA_1380:
> >  	case PCI_DEVICE_ID_ARECA_1381:
> >  	case PCI_DEVICE_ID_ARECA_1680:
> >
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 16/17] arcmsr: support new adapter ARC12x4 series
  2014-08-28 12:49     ` Tomas Henzl
@ 2014-09-09 16:30       ` Christoph Hellwig
  2014-09-10  9:58         ` Tomas Henzl
  0 siblings, 1 reply; 13+ messages in thread
From: Christoph Hellwig @ 2014-09-09 16:30 UTC (permalink / raw)
  To: Tomas Henzl
  Cc: Ching Huang, hch, jbottomley, dan.carpenter, linux-scsi, linux-kernel

Ching,

do you have a chance to address Thomas second concern below?  As
far as I can tell (Thomas, please correct me) that's the last
outstanding concern, and I'd really like to merge the arcmsr updates
for the Linux 3.18 merge window.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 16/17] arcmsr: support new adapter ARC12x4 series
  2014-09-09 16:30       ` Christoph Hellwig
@ 2014-09-10  9:58         ` Tomas Henzl
  2014-09-11  3:59           ` Ching Huang
  2014-09-15 13:23           ` Tomas Henzl
  0 siblings, 2 replies; 13+ messages in thread
From: Tomas Henzl @ 2014-09-10  9:58 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Ching Huang, jbottomley, dan.carpenter, linux-scsi, linux-kernel

On 09/09/2014 06:30 PM, Christoph Hellwig wrote:
> Ching,
>
> do you have a chance to address Thomas second concern below?  As
> far as I can tell (Thomas, please correct me) that's the last
> outstanding concern, and I'd really like to merge the arcmsr updates
> for the Linux 3.18 merge window.

Correct, still awaiting a response.

>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 16/17] arcmsr: support new adapter ARC12x4 series
  2014-09-10  9:58         ` Tomas Henzl
@ 2014-09-11  3:59           ` Ching Huang
  2014-09-11 14:21             ` Tomas Henzl
  2014-09-15 13:23           ` Tomas Henzl
  1 sibling, 1 reply; 13+ messages in thread
From: Ching Huang @ 2014-09-11  3:59 UTC (permalink / raw)
  To: Christoph Hellwig, Tomas Henzl
  Cc: jbottomley, dan.carpenter, linux-scsi, linux-kernel

On Wed, 2014-09-10 at 11:58 +0200, Tomas Henzl wrote:
> On 09/09/2014 06:30 PM, Christoph Hellwig wrote:
> > Ching,
> >
> > do you have a chance to address Thomas second concern below?  As
> > far as I can tell (Thomas, please correct me) that's the last
> > outstanding concern, and I'd really like to merge the arcmsr updates
> > for the Linux 3.18 merge window.
> 
> Correct, still awaiting a response.

Christoph, Tomas,

Sorry for the late reply.

I think I misunderstand Tomas' meaning.
The spin lock in arcmsr_hbaD_polling_ccbdone() is necessary to protect doneq_index and have to be modified as following.

static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb,
				struct CommandControlBlock *poll_ccb)
{
	bool error;
	uint32_t poll_ccb_done = 0, poll_count = 0, flag_ccb, ccb_cdb_phy;
	int rtn, doneq_index, index_stripped, outbound_write_pointer, toggle;
	unsigned long flags;
	struct ARCMSR_CDB *arcmsr_cdb;
	struct CommandControlBlock *pCCB;
	struct MessageUnit_D *pmu = acb->pmuD;

polling_hbaD_ccb_retry:
	poll_count++;
	while (1) {
		spin_lock_irqsave(&acb->doneq_lock, flags);
		outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1;
		doneq_index = pmu->doneq_index;
		if ((outbound_write_pointer & 0xFFF) == (doneq_index & 0xFFF)) {
			spin_unlock_irqrestore(&acb->doneq_lock, flags);
			if (poll_ccb_done) {
				rtn = SUCCESS;
				break;
			} else {
				msleep(25);
				if (poll_count > 40) {
					rtn = FAILED;
					break;
				}
				goto polling_hbaD_ccb_retry;
			}
		}
		toggle = doneq_index & 0x4000;
		index_stripped = (doneq_index & 0xFFF) + 1;
		index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE;
		pmu->doneq_index = index_stripped ? (index_stripped | toggle) :
			((index_stripped + 1) | (toggle ^ 0x4000));
		spin_unlock_irqrestore(&acb->doneq_lock, flags);
		doneq_index = pmu->doneq_index;
		flag_ccb = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow;
		ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0);
		arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset +
			ccb_cdb_phy);
		pCCB = container_of(arcmsr_cdb, struct CommandControlBlock,
			arcmsr_cdb);
		poll_ccb_done |= (pCCB == poll_ccb) ? 1 : 0;
		if ((pCCB->acb != acb) ||
			(pCCB->startdone != ARCMSR_CCB_START)) {
			if (pCCB->startdone == ARCMSR_CCB_ABORTED) {
				pr_notice("arcmsr%d: scsi id = %d "
					"lun = %d ccb = '0x%p' poll command "
					"abort successfully\n"
					, acb->host->host_no
					, pCCB->pcmd->device->id
					, (u32)pCCB->pcmd->device->lun
					, pCCB);
				pCCB->pcmd->result = DID_ABORT << 16;
				arcmsr_ccb_complete(pCCB);
				continue;
			}
			pr_notice("arcmsr%d: polling an illegal "
				"ccb command done ccb = '0x%p' "
				"ccboutstandingcount = %d\n"
				, acb->host->host_no
				, pCCB
				, atomic_read(&acb->ccboutstandingcount));
			continue;
		}
		error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1)
			? true : false;
		arcmsr_report_ccb_state(acb, pCCB, error);
	}
	return rtn;
}


> 
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 16/17] arcmsr: support new adapter ARC12x4 series
  2014-09-11  3:59           ` Ching Huang
@ 2014-09-11 14:21             ` Tomas Henzl
  2014-09-12  3:31               ` Ching Huang
  0 siblings, 1 reply; 13+ messages in thread
From: Tomas Henzl @ 2014-09-11 14:21 UTC (permalink / raw)
  To: Ching Huang, Christoph Hellwig
  Cc: jbottomley, dan.carpenter, linux-scsi, linux-kernel

On 09/11/2014 05:59 AM, Ching Huang wrote:
> On Wed, 2014-09-10 at 11:58 +0200, Tomas Henzl wrote:
>> On 09/09/2014 06:30 PM, Christoph Hellwig wrote:
>>> Ching,
>>>
>>> do you have a chance to address Thomas second concern below?  As
>>> far as I can tell (Thomas, please correct me) that's the last
>>> outstanding concern, and I'd really like to merge the arcmsr updates
>>> for the Linux 3.18 merge window.
>> Correct, still awaiting a response.
> Christoph, Tomas,
>
> Sorry for the late reply.
>
> I think I misunderstand Tomas' meaning.
> The spin lock in arcmsr_hbaD_polling_ccbdone() is necessary to protect doneq_index and have to be modified as following.

OK, so you are going to repost 16/17 ? If so, please describe all changes you'll do, in that new post.

>
> static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb,
> 				struct CommandControlBlock *poll_ccb)
> {
> 	bool error;
> 	uint32_t poll_ccb_done = 0, poll_count = 0, flag_ccb, ccb_cdb_phy;
> 	int rtn, doneq_index, index_stripped, outbound_write_pointer, toggle;
> 	unsigned long flags;
> 	struct ARCMSR_CDB *arcmsr_cdb;
> 	struct CommandControlBlock *pCCB;
> 	struct MessageUnit_D *pmu = acb->pmuD;
>
> polling_hbaD_ccb_retry:
> 	poll_count++;
> 	while (1) {
> 		spin_lock_irqsave(&acb->doneq_lock, flags);
> 		outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1;
> 		doneq_index = pmu->doneq_index;
> 		if ((outbound_write_pointer & 0xFFF) == (doneq_index & 0xFFF)) {
> 			spin_unlock_irqrestore(&acb->doneq_lock, flags);
> 			if (poll_ccb_done) {
> 				rtn = SUCCESS;
> 				break;
> 			} else {
> 				msleep(25);
> 				if (poll_count > 40) {
> 					rtn = FAILED;
> 					break;
> 				}
> 				goto polling_hbaD_ccb_retry;
> 			}
> 		}
> 		toggle = doneq_index & 0x4000;
> 		index_stripped = (doneq_index & 0xFFF) + 1;
> 		index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE;
> 		pmu->doneq_index = index_stripped ? (index_stripped | toggle) :
> 			((index_stripped + 1) | (toggle ^ 0x4000));
> 		spin_unlock_irqrestore(&acb->doneq_lock, flags);
> 		doneq_index = pmu->doneq_index;
> 		flag_ccb = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow;
> 		ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0);
> 		arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset +
> 			ccb_cdb_phy);
> 		pCCB = container_of(arcmsr_cdb, struct CommandControlBlock,
> 			arcmsr_cdb);
> 		poll_ccb_done |= (pCCB == poll_ccb) ? 1 : 0;
> 		if ((pCCB->acb != acb) ||
> 			(pCCB->startdone != ARCMSR_CCB_START)) {
> 			if (pCCB->startdone == ARCMSR_CCB_ABORTED) {
> 				pr_notice("arcmsr%d: scsi id = %d "
> 					"lun = %d ccb = '0x%p' poll command "
> 					"abort successfully\n"
> 					, acb->host->host_no
> 					, pCCB->pcmd->device->id
> 					, (u32)pCCB->pcmd->device->lun
> 					, pCCB);
> 				pCCB->pcmd->result = DID_ABORT << 16;
> 				arcmsr_ccb_complete(pCCB);
> 				continue;
> 			}
> 			pr_notice("arcmsr%d: polling an illegal "
> 				"ccb command done ccb = '0x%p' "
> 				"ccboutstandingcount = %d\n"
> 				, acb->host->host_no
> 				, pCCB
> 				, atomic_read(&acb->ccboutstandingcount));
> 			continue;
> 		}
> 		error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1)
> 			? true : false;
> 		arcmsr_report_ccb_state(acb, pCCB, error);
> 	}
> 	return rtn;
> }
>
>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 16/17] arcmsr: support new adapter ARC12x4 series
  2014-09-11 14:21             ` Tomas Henzl
@ 2014-09-12  3:31               ` Ching Huang
  0 siblings, 0 replies; 13+ messages in thread
From: Ching Huang @ 2014-09-12  3:31 UTC (permalink / raw)
  To: Tomas Henzl
  Cc: Christoph Hellwig, jbottomley, dan.carpenter, linux-scsi, linux-kernel

On Thu, 2014-09-11 at 16:21 +0200, Tomas Henzl wrote:
> On 09/11/2014 05:59 AM, Ching Huang wrote:
> > On Wed, 2014-09-10 at 11:58 +0200, Tomas Henzl wrote:
> >> On 09/09/2014 06:30 PM, Christoph Hellwig wrote:
> >>> Ching,
> >>>
> >>> do you have a chance to address Thomas second concern below?  As
> >>> far as I can tell (Thomas, please correct me) that's the last
> >>> outstanding concern, and I'd really like to merge the arcmsr updates
> >>> for the Linux 3.18 merge window.
> >> Correct, still awaiting a response.
> > Christoph, Tomas,
> >
> > Sorry for the late reply.
> >
> > I think I misunderstand Tomas' meaning.
> > The spin lock in arcmsr_hbaD_polling_ccbdone() is necessary to protect doneq_index and have to be modified as following.
> 
> OK, so you are going to repost 16/17 ? If so, please describe all changes you'll do, in that new post.
> 
By previous review, I will post two patches.
One for 13/17 and another for 16/17.
These patches are relative to http://git.infradead.org/users/hch/scsi-queue.git/tree/arcmsr-for-3.18:/drivers/scsi/arcmsr
> >
> > static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb,
> > 				struct CommandControlBlock *poll_ccb)
> > {
> > 	bool error;
> > 	uint32_t poll_ccb_done = 0, poll_count = 0, flag_ccb, ccb_cdb_phy;
> > 	int rtn, doneq_index, index_stripped, outbound_write_pointer, toggle;
> > 	unsigned long flags;
> > 	struct ARCMSR_CDB *arcmsr_cdb;
> > 	struct CommandControlBlock *pCCB;
> > 	struct MessageUnit_D *pmu = acb->pmuD;
> >
> > polling_hbaD_ccb_retry:
> > 	poll_count++;
> > 	while (1) {
> > 		spin_lock_irqsave(&acb->doneq_lock, flags);
> > 		outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1;
> > 		doneq_index = pmu->doneq_index;
> > 		if ((outbound_write_pointer & 0xFFF) == (doneq_index & 0xFFF)) {
> > 			spin_unlock_irqrestore(&acb->doneq_lock, flags);
> > 			if (poll_ccb_done) {
> > 				rtn = SUCCESS;
> > 				break;
> > 			} else {
> > 				msleep(25);
> > 				if (poll_count > 40) {
> > 					rtn = FAILED;
> > 					break;
> > 				}
> > 				goto polling_hbaD_ccb_retry;
> > 			}
> > 		}
> > 		toggle = doneq_index & 0x4000;
> > 		index_stripped = (doneq_index & 0xFFF) + 1;
> > 		index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE;
> > 		pmu->doneq_index = index_stripped ? (index_stripped | toggle) :
> > 			((index_stripped + 1) | (toggle ^ 0x4000));
> > 		spin_unlock_irqrestore(&acb->doneq_lock, flags);
> > 		doneq_index = pmu->doneq_index;
> > 		flag_ccb = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow;
> > 		ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0);
> > 		arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset +
> > 			ccb_cdb_phy);
> > 		pCCB = container_of(arcmsr_cdb, struct CommandControlBlock,
> > 			arcmsr_cdb);
> > 		poll_ccb_done |= (pCCB == poll_ccb) ? 1 : 0;
> > 		if ((pCCB->acb != acb) ||
> > 			(pCCB->startdone != ARCMSR_CCB_START)) {
> > 			if (pCCB->startdone == ARCMSR_CCB_ABORTED) {
> > 				pr_notice("arcmsr%d: scsi id = %d "
> > 					"lun = %d ccb = '0x%p' poll command "
> > 					"abort successfully\n"
> > 					, acb->host->host_no
> > 					, pCCB->pcmd->device->id
> > 					, (u32)pCCB->pcmd->device->lun
> > 					, pCCB);
> > 				pCCB->pcmd->result = DID_ABORT << 16;
> > 				arcmsr_ccb_complete(pCCB);
> > 				continue;
> > 			}
> > 			pr_notice("arcmsr%d: polling an illegal "
> > 				"ccb command done ccb = '0x%p' "
> > 				"ccboutstandingcount = %d\n"
> > 				, acb->host->host_no
> > 				, pCCB
> > 				, atomic_read(&acb->ccboutstandingcount));
> > 			continue;
> > 		}
> > 		error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1)
> > 			? true : false;
> > 		arcmsr_report_ccb_state(acb, pCCB, error);
> > 	}
> > 	return rtn;
> > }
> >
> >
> >>> --
> >>> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> >>> the body of a message to majordomo@vger.kernel.org
> >>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 16/17] arcmsr: support new adapter ARC12x4 series
  2014-09-10  9:58         ` Tomas Henzl
  2014-09-11  3:59           ` Ching Huang
@ 2014-09-15 13:23           ` Tomas Henzl
  2014-09-15 17:05             ` Christoph Hellwig
  1 sibling, 1 reply; 13+ messages in thread
From: Tomas Henzl @ 2014-09-15 13:23 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Ching Huang, jbottomley, dan.carpenter, linux-scsi, linux-kernel

On 09/10/2014 11:58 AM, Tomas Henzl wrote:
> On 09/09/2014 06:30 PM, Christoph Hellwig wrote:
>> Ching,
>>
>> do you have a chance to address Thomas second concern below?  As
>> far as I can tell (Thomas, please correct me) that's the last
>> outstanding concern, and I'd really like to merge the arcmsr updates
>> for the Linux 3.18 merge window.
> Correct, still awaiting a response.

Christoph,

you may add my 'reviewed-by' to the arcmsr series
http://git.infradead.org/users/hch/scsi-queue.git/tree/arcmsr-for-3.18:/drivers/scsi/arcmsr
with the '[PATCH v5 2/2] arcmsr: simplify of updating doneq_index and postq_index'
( https://lkml.org/lkml/2014/9/15/177 ) on top of the series
that last patch fixes the 16/17 from your git.
I hope the series is an iteration in the right direction.
Skip the the '[PATCH v4 1/2] arcmsr: simplify ioctl data read/write', Ching will repost it later.

Tomas

>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 16/17] arcmsr: support new adapter ARC12x4 series
  2014-09-15 13:23           ` Tomas Henzl
@ 2014-09-15 17:05             ` Christoph Hellwig
  2014-09-16  2:42               ` Ching Huang
  0 siblings, 1 reply; 13+ messages in thread
From: Christoph Hellwig @ 2014-09-15 17:05 UTC (permalink / raw)
  To: Tomas Henzl
  Cc: Christoph Hellwig, Ching Huang, jbottomley, dan.carpenter,
	linux-scsi, linux-kernel

On Mon, Sep 15, 2014 at 03:23:36PM +0200, Tomas Henzl wrote:
> Christoph,
> 
> you may add my 'reviewed-by' to the arcmsr series
> http://git.infradead.org/users/hch/scsi-queue.git/tree/arcmsr-for-3.18:/drivers/scsi/arcmsr
> with the '[PATCH v5 2/2] arcmsr: simplify of updating doneq_index and postq_index'
> ( https://lkml.org/lkml/2014/9/15/177 ) on top of the series
> that last patch fixes the 16/17 from your git.
> I hope the series is an iteration in the right direction.
> Skip the the '[PATCH v4 1/2] arcmsr: simplify ioctl data read/write', Ching will repost it later.

Thanks a lot Tomas for all the review, and thanks Ching for the patches
and updates.  I'll merge the branch and the additional patch today.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 16/17] arcmsr: support new adapter ARC12x4 series
  2014-09-15 17:05             ` Christoph Hellwig
@ 2014-09-16  2:42               ` Ching Huang
  2014-09-16 22:40                 ` Christoph Hellwig
  0 siblings, 1 reply; 13+ messages in thread
From: Ching Huang @ 2014-09-16  2:42 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Tomas Henzl, jbottomley, dan.carpenter, linux-scsi, linux-kernel

On Mon, 2014-09-15 at 10:05 -0700, Christoph Hellwig wrote:
> On Mon, Sep 15, 2014 at 03:23:36PM +0200, Tomas Henzl wrote:
> > Christoph,
> > 
> > you may add my 'reviewed-by' to the arcmsr series
> > http://git.infradead.org/users/hch/scsi-queue.git/tree/arcmsr-for-3.18:/drivers/scsi/arcmsr
> > with the '[PATCH v5 2/2] arcmsr: simplify of updating doneq_index and postq_index'
> > ( https://lkml.org/lkml/2014/9/15/177 ) on top of the series
> > that last patch fixes the 16/17 from your git.
> > I hope the series is an iteration in the right direction.
> > Skip the the '[PATCH v4 1/2] arcmsr: simplify ioctl data read/write', Ching will repost it later.
> 
> Thanks a lot Tomas for all the review, and thanks Ching for the patches
> and updates.  I'll merge the branch and the additional patch today.
> 

Christoph,

The [PATCH v5 2/2] was depend on [PATCH v4 1/2].
If you skip patch 1/2, then patch 2/2 may cause line number mismatch.
How should I do? Please advise.




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 16/17] arcmsr: support new adapter ARC12x4 series
  2014-09-16  2:42               ` Ching Huang
@ 2014-09-16 22:40                 ` Christoph Hellwig
  0 siblings, 0 replies; 13+ messages in thread
From: Christoph Hellwig @ 2014-09-16 22:40 UTC (permalink / raw)
  To: Ching Huang
  Cc: Tomas Henzl, jbottomley, dan.carpenter, linux-scsi, linux-kernel

On Tue, Sep 16, 2014 at 10:42:08AM +0800, Ching Huang wrote:
> The [PATCH v5 2/2] was depend on [PATCH v4 1/2].
> If you skip patch 1/2, then patch 2/2 may cause line number mismatch.
> How should I do? Please advise.

Hi Ching,

[PATCH v5 2/2] applied without a problem.  Please look at my
drivers-for-3.18 branch and send any additional patches relative to
that.

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2014-09-16 22:40 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-19  7:25 [PATCH v3 16/17] arcmsr: support new adapter ARC12x4 series Ching Huang
2014-08-27 14:00 ` Tomas Henzl
2014-08-28 15:46   ` Ching Huang
2014-08-28 12:49     ` Tomas Henzl
2014-09-09 16:30       ` Christoph Hellwig
2014-09-10  9:58         ` Tomas Henzl
2014-09-11  3:59           ` Ching Huang
2014-09-11 14:21             ` Tomas Henzl
2014-09-12  3:31               ` Ching Huang
2014-09-15 13:23           ` Tomas Henzl
2014-09-15 17:05             ` Christoph Hellwig
2014-09-16  2:42               ` Ching Huang
2014-09-16 22:40                 ` Christoph Hellwig

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.