linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 3/3] arcmsr: Fix bug of updating ARECA Raid adapter firmware through ioctl(ARCHTTP) interface
@ 2013-07-17  3:04 黃清隆
  0 siblings, 0 replies; only message in thread
From: 黃清隆 @ 2013-07-17  3:04 UTC (permalink / raw)
  To: linux-scsi, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 164 bytes --]

From: Chingching2048@areca.com.tw

Fix bug of updating ARECA Raid adapter firmware through ioctl(ARCHTTP) 
interface
Signed-off-by: Chingching2048@areca.com.tw
---

[-- Attachment #2: patch3 --]
[-- Type: application/octet-stream, Size: 34441 bytes --]

diff -uprN a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
--- a/drivers/scsi/arcmsr/arcmsr_attr.c	2012-11-29 19:35:16.000000000 +0800
+++ b/drivers/scsi/arcmsr/arcmsr_attr.c	2013-07-16 02:31:38.000000000 +0800
@@ -86,6 +86,7 @@ arcmsr_sysfs_iop_message_read(struct fil
 			if ((ARCMSR_MAX_QBUFFER - acb->rqbuf_firstindex) >= 1032) {
 				memcpy(ptmpQbuffer, pQbuffer, 1032);
 				acb->rqbuf_firstindex += 1032;
+				acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
 				allxfer_len = 1032;
 			} else {
 				if (((ARCMSR_MAX_QBUFFER - acb->rqbuf_firstindex) + acb->rqbuf_lastindex) > 1032) {
@@ -116,36 +117,10 @@ arcmsr_sysfs_iop_message_read(struct fil
 	}
 	if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
 		struct QBUFFER __iomem *prbuffer;
-		uint8_t __iomem *iop_data, *vaddr, *temp;
-			int32_t data_len_residual, data_len, rqbuf_lastindex;
-			acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-		rqbuf_lastindex = acb->rqbuf_lastindex;
+		acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
 		prbuffer = arcmsr_get_iop_rqbuffer(acb);
-		iop_data = (uint8_t __iomem *)prbuffer->data;
-		data_len_residual = data_len = readl(&prbuffer->data_len);
-		if (data_len > 0) {
-			temp = vaddr = kmalloc(data_len, GFP_ATOMIC);
-			do {
-				memcpy(temp, iop_data, 4);
-				temp += 4;
-				iop_data += 4;
-				data_len_residual -= 4;
-			} while (data_len_residual > 0);
-			pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex];
-			temp = vaddr;
-			if ((rqbuf_lastindex + data_len) > ARCMSR_MAX_QBUFFER) {
-				memcpy(pQbuffer, temp, ARCMSR_MAX_QBUFFER - rqbuf_lastindex);
-				temp += (ARCMSR_MAX_QBUFFER - rqbuf_lastindex);
-				rqbuf_lastindex = (rqbuf_lastindex + data_len) % ARCMSR_MAX_QBUFFER;
-				memcpy(&acb->rqbuffer[0], temp, rqbuf_lastindex);
-			} else {
-				memcpy(pQbuffer, temp, data_len);
-				rqbuf_lastindex = (rqbuf_lastindex + data_len) % ARCMSR_MAX_QBUFFER;
-			}
-			kfree(vaddr);
-		}
-		acb->rqbuf_lastindex = rqbuf_lastindex;
-		arcmsr_iop_message_read(acb);
+		if (arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
+			acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
 	}
 	spin_unlock_irqrestore(&acb->rqbuffer_lock, flags);
 	return (allxfer_len);
@@ -177,7 +152,7 @@ arcmsr_sysfs_iop_message_write(struct fi
 	wqbuf_lastindex = acb->wqbuf_lastindex;
 	wqbuf_firstindex = acb->wqbuf_firstindex;
 	if (wqbuf_lastindex != wqbuf_firstindex) {
-		arcmsr_post_ioctldata2iop(acb);
+		arcmsr_write_ioctldata2iop(acb);
 		spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
 		return 0;	/*need retry*/
 	} else {
@@ -198,7 +173,7 @@ arcmsr_sysfs_iop_message_write(struct fi
 				ACB_F_MESSAGE_WQBUFFER_CLEARED) {
 				acb->acb_flags &=
 					~ACB_F_MESSAGE_WQBUFFER_CLEARED;
-				arcmsr_post_ioctldata2iop(acb);
+				arcmsr_write_ioctldata2iop(acb);
 			}
 			spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
 			return count;
@@ -226,10 +201,7 @@ arcmsr_sysfs_iop_message_clear(struct fi
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
-		acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-		arcmsr_iop_message_read(acb);
-	}
+	arcmsr_clear_iop2drv_rqueue_buffer(acb);
 	acb->acb_flags |=
 		(ACB_F_MESSAGE_WQBUFFER_CLEARED
 		| ACB_F_MESSAGE_RQBUFFER_CLEARED
diff -uprN a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
--- a/drivers/scsi/arcmsr/arcmsr.h	2013-05-07 01:49:08.000000000 +0800
+++ b/drivers/scsi/arcmsr/arcmsr.h	2013-07-13 00:22:10.000000000 +0800
@@ -51,7 +51,7 @@ struct device_attribute;
 #else
 	#define ARCMSR_MAX_FREECCB_NUM	320
 #endif
-#define ARCMSR_DRIVER_VERSION		"Driver Version 1.20.00.15 2013/05/06"
+#define ARCMSR_DRIVER_VERSION		"Driver Version 1.20.00.15 2013/07/12"
 #define ARCMSR_SCSI_INITIATOR_ID		255
 #define ARCMSR_MAX_XFER_SECTORS		512
 #define ARCMSR_MAX_XFER_SECTORS_B		4096
@@ -796,8 +796,10 @@ struct SENSE_DATA
 #define ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE	0x01
 #define ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE		0x1F
 
-extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *);
-extern void arcmsr_iop_message_read(struct AdapterControlBlock *);
+extern void arcmsr_write_ioctldata2iop(struct AdapterControlBlock *);
+extern uint32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *,
+    struct QBUFFER __iomem *);
+extern void arcmsr_clear_iop2drv_rqueue_buffer(struct AdapterControlBlock *);
 extern struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *);
 extern struct device_attribute *arcmsr_host_attrs[];
 extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *);
diff -uprN a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
--- a/drivers/scsi/arcmsr/arcmsr_hba.c	2013-05-16 04:20:04.000000000 +0800
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c	2013-07-16 02:25:12.000000000 +0800
@@ -291,6 +291,7 @@ static void arcmsr_unmap_pciregion(struc
 	}
 	case ACB_ADAPTER_TYPE_D: {
 		iounmap(acb->mem_base0);
+		break;
 	}
 	}
 }
@@ -543,19 +544,19 @@ arcmsr_flush_adapter_cache(struct Adapte
 
 	case ACB_ADAPTER_TYPE_A: {
 		arcmsr_hbaA_flush_cache(acb);
-		}
 		break;
-
+		}
 	case ACB_ADAPTER_TYPE_B: {
 		arcmsr_hbaB_flush_cache(acb);
-		}
 		break;
+		}
 	case ACB_ADAPTER_TYPE_C: {
 		arcmsr_hbaC_flush_cache(acb);
-		}
 		break;
+		}
 	case ACB_ADAPTER_TYPE_D: {
 		arcmsr_hbaD_flush_cache(acb);
+		break;
 	}
 	}
 }
@@ -728,6 +729,7 @@ arcmsr_alloc_ccb_pool(struct AdapterCont
 			dma_coherent_handle = dma_coherent_handle
 				+ roundup_ccbsize;
 		}
+		break;
 	}
 	}
 	for (i = 0; i < ARCMSR_MAX_TARGETID; i++)
@@ -1267,21 +1269,23 @@ arcmsr_abort_allcmd(struct AdapterContro
 	switch (acb->adapter_type) {
 	case ACB_ADAPTER_TYPE_A: {
 		rtnval = arcmsr_hbaA_abort_allcmd(acb);
-		}
 		break;
+		}
 
 	case ACB_ADAPTER_TYPE_B: {
 		rtnval = arcmsr_hbaB_abort_allcmd(acb);
-		}
 		break;
+		}
 
 	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;
 }
@@ -1696,9 +1700,8 @@ arcmsr_enable_outbound_ints(struct Adapt
 		writel(mask, &reg->outbound_intmask);
 		acb->outbound_int_enable = ~(intmask_org & mask) &
 			0x000000ff;
-		}
 		break;
-
+		}
 	case ACB_ADAPTER_TYPE_B: {
 		struct MessageUnit_B *reg = acb->pmuB;
 		mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK |
@@ -1708,8 +1711,8 @@ arcmsr_enable_outbound_ints(struct Adapt
 		writel(mask, reg->iop2drv_doorbell_mask);
 		acb->outbound_int_enable = (intmask_org | mask) &
 			0x0000000f;
-		}
 		break;
+		}
 	case ACB_ADAPTER_TYPE_C: {
 		struct MessageUnit_C __iomem *reg = acb->pmuC;
 		mask = ~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK |
@@ -1718,12 +1721,13 @@ arcmsr_enable_outbound_ints(struct Adapt
 		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 __iomem *reg = acb->pmuD;
 		mask = ARCMSR_ARC1214_ALL_INT_ENABLE;
 		writel(intmask_org | mask, reg->pcief0_int_enable);
+		break;
 	}
 	}
 }
@@ -1863,7 +1867,7 @@ arcmsr_post_ccb(struct AdapterControlBlo
 		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 = arccdbsize / 4;
+		pinbound_srb->length = arccdbsize >> 2;
 		arcmsr_cdb->msgContext = dma_addr_lo32(cdb_phyaddr);
 		if (postq_index & 0x4000) {
 			index_stripped = postq_index & 0xFF;
@@ -1878,6 +1882,7 @@ arcmsr_post_ccb(struct AdapterControlBlo
 		}
 		writel(postq_index, pmu->inboundlist_write_pointer);
 		spin_unlock_irqrestore(&acb->postq_lock, flags);
+		break;
 	}
 	}
 }
@@ -1921,7 +1926,6 @@ arcmsr_hbaC_stop_bgrb(struct AdapterCont
 		"background rebulid' timeout\n"
 		, pACB->host->host_no);
 	}
-	return;
 }
 
 static void
@@ -1938,7 +1942,6 @@ arcmsr_hbaD_stop_bgrb(struct AdapterCont
 		"rebulid' timeout\n"
 		, pACB->host->host_no);
 	}
-	return;
 }
 
 static void
@@ -2124,193 +2127,174 @@ struct QBUFFER __iomem
 	return pqbuffer;
 }
 
+static uint32_t
+arcmsr_Read_iop_rqbuffer_in_DWORD(struct AdapterControlBlock *acb,
+	struct QBUFFER __iomem *prbuffer) {
+
+	uint8_t *pQbuffer;
+	uint8_t *buf1 = 0;
+	uint32_t __iomem *iop_data;
+	uint32_t iop_len, data_len, *buf2 = 0;
+
+	iop_data = (uint32_t *)prbuffer->data;
+	iop_len = readl(&prbuffer->data_len);
+	if ( iop_len > 0 ) {
+		buf1 = kmalloc(128, GFP_ATOMIC);
+		buf2 = (uint32_t *)buf1;
+		if( buf1 == NULL)
+			return (0);
+		data_len = iop_len;
+		while (data_len >= 4) {
+			*buf2++ = *iop_data++;
+			data_len -= 4;
+		}
+		if(data_len)
+			*buf2 = *iop_data;
+		buf2 = (uint32_t *)buf1;
+	}
+	while (iop_len > 0) {
+		pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex];
+		*pQbuffer = *buf1;
+		acb->rqbuf_lastindex++;
+		/* if last, index number set it to 0 */
+		acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
+		buf1++;
+		iop_len--;
+	}
+	if (buf2)
+		kfree( (uint8_t *)buf2);
+	/* let IOP know data has been read */
+	arcmsr_iop_message_read(acb);
+	return (1);
+}
+
+uint32_t
+arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb,
+    struct QBUFFER __iomem *prbuffer) {
+
+	uint8_t *pQbuffer;
+	uint8_t __iomem *iop_data;
+	uint32_t iop_len;
+
+	if (acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) {
+		return(arcmsr_Read_iop_rqbuffer_in_DWORD(acb, prbuffer));
+	}
+	iop_data = (uint8_t *)prbuffer->data;
+	iop_len = readl(&prbuffer->data_len);
+	while (iop_len > 0) {
+		pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex];
+		*pQbuffer = *iop_data;
+		acb->rqbuf_lastindex++;
+		acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
+		iop_data++;
+		iop_len--;
+	}
+	arcmsr_iop_message_read(acb);
+	return (1);
+}
+
 void
 arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb)
 {
-	uint8_t __iomem *iop_data, *pQbuffer, *vaddr, *temp;
-	int32_t buf_empty_len, data_len, data_len_residual;
-	uint32_t rqbuf_firstindex, rqbuf_lastindex;
 	unsigned long flags;
 	struct QBUFFER __iomem  *prbuffer;
+	int32_t buf_empty_len;
+
 	spin_lock_irqsave(&acb->rqbuffer_lock, flags);
-	rqbuf_lastindex = acb->rqbuf_lastindex;
-	rqbuf_firstindex = acb->rqbuf_firstindex;
 	prbuffer = arcmsr_get_iop_rqbuffer(acb);
-	iop_data = (uint8_t __iomem *)prbuffer->data;
-	data_len_residual = data_len = readl(&prbuffer->data_len);
-	buf_empty_len = (rqbuf_firstindex - rqbuf_lastindex - 1) &
-		(ARCMSR_MAX_QBUFFER - 1);
-	if (buf_empty_len >= data_len) {
-		if (data_len > 0) {
-			temp = vaddr = kmalloc(data_len, GFP_ATOMIC);
-			if (!vaddr) {
-				goto leave;
-			}
-			acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-			while (data_len_residual >= 4) {
-				memcpy(temp, iop_data, 4);
-				temp += 4;
-				iop_data += 4;
-				data_len_residual -= 4;
-			}
-			if ((data_len_residual > 0) &&
-			(data_len_residual < 4)) {
-				memcpy(temp, iop_data, data_len_residual);
-			}
-			pQbuffer = &acb->rqbuffer[rqbuf_lastindex];
-			temp = vaddr;
-			if ((rqbuf_lastindex + data_len) >
-			ARCMSR_MAX_QBUFFER) {
-				memcpy(pQbuffer, temp,
-				ARCMSR_MAX_QBUFFER - rqbuf_lastindex);
-				temp += (ARCMSR_MAX_QBUFFER -
-				rqbuf_lastindex);
-				rqbuf_lastindex = (rqbuf_lastindex + data_len)
-				% ARCMSR_MAX_QBUFFER;
-				memcpy(&acb->rqbuffer[0], temp,
-				rqbuf_lastindex);
-			} else {
-				memcpy(pQbuffer, temp, data_len);
-				rqbuf_lastindex = (rqbuf_lastindex + data_len)
-				% ARCMSR_MAX_QBUFFER;
-			}
-			kfree(vaddr);
-			acb->rqbuf_lastindex = rqbuf_lastindex;
-			arcmsr_iop_message_read(acb);
-		}
+	buf_empty_len = (acb->rqbuf_lastindex - acb->rqbuf_firstindex -1) &
+		(ARCMSR_MAX_QBUFFER -1);
+	if (buf_empty_len >= prbuffer->data_len) {
+		if (arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
+			acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
 	} else {
 		acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
 	}
-	leave:
 	spin_unlock_irqrestore(&acb->rqbuffer_lock, flags);
 }
 
-void
-arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb)
+static void
+arcmsr_write_ioctldata2iop_in_DWORD(struct AdapterControlBlock *acb)
 {
-	unsigned long flags;
-	spin_lock_irqsave(&acb->wqbuffer_lock, flags);
-	acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED;
-	if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) {
-		uint8_t *pQbuffer;
-		struct QBUFFER __iomem *pwbuffer;
-		uint8_t __iomem *iop_data;
-		int32_t allxfer_len = 0;
+	uint8_t *pQbuffer;
+	struct QBUFFER __iomem *pwbuffer;
+	uint8_t *buf1 = 0;
+	uint32_t __iomem *iop_data;
+	uint32_t allxfer_len = 0, data_len, *buf2 = 0;
+	
+	if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) {
+		buf1 = kmalloc(128, GFP_ATOMIC);
+		buf2 = (uint32_t *)buf1;
+		if( buf1 == NULL)
+			return;
 
 		acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED);
 		pwbuffer = arcmsr_get_iop_wqbuffer(acb);
-		iop_data = (uint8_t __iomem *)pwbuffer->data;
-		if (acb->wqbuf_firstindex > acb->wqbuf_lastindex) {
-			if ((ARCMSR_MAX_QBUFFER - acb->wqbuf_firstindex) >= 4) {
-				do {
-					pQbuffer =
-					&acb->wqbuffer[acb->wqbuf_firstindex];
-					if (acb->wqbuf_firstindex + 4
-					> ARCMSR_MAX_QBUFFER) {
-						memcpy(iop_data, pQbuffer,
-						ARCMSR_MAX_QBUFFER
-						- acb->wqbuf_firstindex);
-						iop_data += ARCMSR_MAX_QBUFFER
-						- acb->wqbuf_firstindex;
-						acb->wqbuf_firstindex += 4;
-						acb->wqbuf_firstindex %=
-						ARCMSR_MAX_QBUFFER;
-						memcpy(iop_data,
-						&acb->wqbuffer[0],
-						acb->wqbuf_firstindex);
-						iop_data +=
-						acb->wqbuf_firstindex;
-					} else {
-						if ((acb->wqbuf_lastindex
-						- acb->wqbuf_firstindex) > 4) {
-							memcpy(iop_data,
-							pQbuffer, 4);
-							acb->wqbuf_firstindex
-							+= 4;
-							acb->wqbuf_firstindex
-							%= ARCMSR_MAX_QBUFFER;
-							iop_data += 4;
-						} else {
-							memcpy(iop_data, pQbuffer,
-							acb->wqbuf_lastindex
-							- acb->wqbuf_firstindex);
-							allxfer_len +=
-							acb->wqbuf_lastindex -
-							acb->wqbuf_firstindex;
-							acb->wqbuf_firstindex =
-							acb->wqbuf_lastindex;
-							break;
-						}
-					}
-					allxfer_len += 4;
-				} while ((acb->wqbuf_firstindex !=
-				acb->wqbuf_lastindex) && (allxfer_len < 124));
-			} else {
-				pQbuffer =
-				&acb->wqbuffer[acb->wqbuf_firstindex];
-				memcpy(iop_data, pQbuffer, ARCMSR_MAX_QBUFFER
-				- acb->wqbuf_firstindex);
-				iop_data += ARCMSR_MAX_QBUFFER
-				- acb->wqbuf_firstindex;
-				allxfer_len = ARCMSR_MAX_QBUFFER
-				- acb->wqbuf_firstindex;
-				acb->wqbuf_firstindex = 0;
-				do {
-					pQbuffer =
-					&acb->wqbuffer[acb->wqbuf_firstindex];
-					if ((acb->wqbuf_lastindex -
-					acb->wqbuf_firstindex) > 4) {
-						memcpy(iop_data, pQbuffer, 4);
-						acb->wqbuf_firstindex += 4;
-						acb->wqbuf_firstindex %=
-						ARCMSR_MAX_QBUFFER;
-						iop_data += 4;
-					} else {
-						memcpy(iop_data, pQbuffer,
-						acb->wqbuf_lastindex -
-						acb->wqbuf_firstindex);
-						allxfer_len +=
-						acb->wqbuf_lastindex
-						- acb->wqbuf_firstindex;
-						acb->wqbuf_firstindex =
-						acb->wqbuf_lastindex;
-						break;
-					}
-					allxfer_len += 4;
-				} while ((acb->wqbuf_firstindex !=
-				acb->wqbuf_lastindex) && (allxfer_len < 124));
-			}
-		} else {
-			do {
-				pQbuffer =
-				&acb->wqbuffer[acb->wqbuf_firstindex];
-				if ((acb->wqbuf_lastindex -
-				acb->wqbuf_firstindex) > 4) {
-					memcpy(iop_data, pQbuffer, 4);
-					acb->wqbuf_firstindex += 4;
-					acb->wqbuf_firstindex %=
-					ARCMSR_MAX_QBUFFER;
-					iop_data += 4;
-				} else {
-					memcpy(iop_data, pQbuffer,
-					acb->wqbuf_lastindex -
-					acb->wqbuf_firstindex);
-					allxfer_len += acb->wqbuf_lastindex
-					- acb->wqbuf_firstindex;
-					acb->wqbuf_firstindex =
-					acb->wqbuf_lastindex;
-					break;
-				}
-				allxfer_len += 4;
-			} while ((acb->wqbuf_firstindex !=
-			acb->wqbuf_lastindex) && (allxfer_len < 124));
+		iop_data = (uint32_t *)pwbuffer->data;
+		while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex)
+			&& (allxfer_len < 124)) {
+			pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex];
+			*buf1 = *pQbuffer;
+			acb->wqbuf_firstindex++;
+			acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
+			buf1++;
+			allxfer_len++;
+		}
+		data_len = allxfer_len;
+		buf1 = (uint8_t *)buf2;
+		while (data_len >= 4) {
+			*iop_data++ = *buf2++;
+			data_len -= 4;
 		}
+		if (data_len)
+			*iop_data = *buf2;
 		writel(allxfer_len, &pwbuffer->data_len);
-		arcmsr_iop_message_wrote(acb);/*notice IOP the message has been written*/
+		kfree( buf1);
+		arcmsr_iop_message_wrote(acb);
 	}
-	if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) {
-		acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED;
+}
+
+void
+arcmsr_write_ioctldata2iop(struct AdapterControlBlock *acb)
+{
+	uint8_t *pQbuffer;
+	struct QBUFFER __iomem *pwbuffer;
+	uint8_t __iomem *iop_data;
+	int32_t allxfer_len=0;
+	
+	if (acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) {
+		arcmsr_write_ioctldata2iop_in_DWORD(acb);
+		return;
 	}
+	if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) {
+		acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED);
+		pwbuffer = arcmsr_get_iop_wqbuffer(acb);
+		iop_data = (uint8_t *)pwbuffer->data;
+		while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 
+			&& (allxfer_len < 124)) {
+			pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex];
+			*iop_data = *pQbuffer;
+			acb->wqbuf_firstindex++;
+			acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
+			iop_data++;
+			allxfer_len++;
+		}
+		writel(allxfer_len, &pwbuffer->data_len);
+		arcmsr_iop_message_wrote(acb);
+	}
+}
+
+void
+arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&acb->wqbuffer_lock, flags);
+	acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED;
+	if (acb->wqbuf_firstindex != acb->wqbuf_lastindex)
+		arcmsr_write_ioctldata2iop(acb);
+	if (acb->wqbuf_firstindex == acb->wqbuf_lastindex)
+		acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED;
 	spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
 }
 
@@ -2361,7 +2345,6 @@ arcmsr_hbaC_doorbell_isr(struct AdapterC
 	} while (outbound_doorbell & (ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK
 	| ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK
 	| ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE));
-	return;
 }
 
 static void
@@ -2390,7 +2373,6 @@ arcmsr_hbaD_doorbell_isr(struct AdapterC
 	} while (outbound_doorbell & (ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK
 	| ARCMSR_ARC1214_IOP2DRV_DATA_READ_OK
 	| ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE));
-	return;
 }
 
 static void
@@ -2710,132 +2692,24 @@ arcmsr_iop_parking(struct AdapterControl
 }
 
 void
-arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb)
+arcmsr_clear_iop2drv_rqueue_buffer(struct AdapterControlBlock *acb)
 {
-	if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) {
-		if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) {
-			uint8_t *pQbuffer;
-			uint8_t __iomem *iop_data;
-			int32_t allxfer_len = 0;
-			struct QBUFFER __iomem *pwbuffer;
-			acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED);
-			pwbuffer = arcmsr_get_iop_wqbuffer(acb);
-			iop_data = (uint8_t __iomem *)pwbuffer->data;
-			if (acb->wqbuf_firstindex > acb->wqbuf_lastindex) {
-				if ((ARCMSR_MAX_QBUFFER -
-					acb->wqbuf_firstindex) >= 4) {
-					do {
-						pQbuffer =
-						&acb->wqbuffer[acb->wqbuf_firstindex];
-						if (acb->wqbuf_firstindex + 4 >
-						ARCMSR_MAX_QBUFFER) {
-							memcpy(iop_data, pQbuffer,
-							ARCMSR_MAX_QBUFFER - acb->wqbuf_firstindex);
-							iop_data += ARCMSR_MAX_QBUFFER
-							- acb->wqbuf_firstindex;
-							acb->wqbuf_firstindex += 4;
-							acb->wqbuf_firstindex %=
-							ARCMSR_MAX_QBUFFER;
-							memcpy(iop_data,
-							&acb->wqbuffer[0],
-							acb->wqbuf_firstindex);
-							iop_data +=
-							acb->wqbuf_firstindex;
-						} else {
-							if ((acb->wqbuf_lastindex -
-							acb->wqbuf_firstindex) > 4) {
-								memcpy(iop_data,
-								pQbuffer, 4);
-								acb->wqbuf_firstindex
-								+= 4;
-								acb->wqbuf_firstindex
-								%= ARCMSR_MAX_QBUFFER;
-								iop_data += 4;
-							} else {
-								memcpy(iop_data,
-								pQbuffer,
-								acb->wqbuf_lastindex
-								- acb->wqbuf_firstindex);
-								allxfer_len +=
-								acb->wqbuf_lastindex
-								- acb->wqbuf_firstindex;
-								acb->wqbuf_firstindex
-								= acb->wqbuf_lastindex;
-								break;
-							}
-						}
-						allxfer_len += 4;
-					} while ((acb->wqbuf_firstindex !=
-					acb->wqbuf_lastindex) &&
-					(allxfer_len < 124));
-				} else {
-					pQbuffer =
-					&acb->wqbuffer[acb->wqbuf_firstindex];
-					memcpy(iop_data, pQbuffer,
-					ARCMSR_MAX_QBUFFER -
-					acb->wqbuf_firstindex);
-					iop_data += ARCMSR_MAX_QBUFFER
-					- acb->wqbuf_firstindex;
-					allxfer_len = ARCMSR_MAX_QBUFFER
-					- acb->wqbuf_firstindex;
-					acb->wqbuf_firstindex = 0;
-					do {
-						pQbuffer =
-						&acb->wqbuffer[acb->wqbuf_firstindex];
-						if ((acb->wqbuf_lastindex -
-						acb->wqbuf_firstindex) > 4) {
-							memcpy(iop_data,
-							pQbuffer, 4);
-							acb->wqbuf_firstindex
-							+= 4;
-							acb->wqbuf_firstindex
-							%= ARCMSR_MAX_QBUFFER;
-							iop_data += 4;
-						} else {
-							memcpy(iop_data, pQbuffer,
-							acb->wqbuf_lastindex
-							- acb->wqbuf_firstindex);
-							allxfer_len +=
-							acb->wqbuf_lastindex
-							- acb->wqbuf_firstindex;
-							acb->wqbuf_firstindex =
-							acb->wqbuf_lastindex;
-							break;
-						}
-						allxfer_len += 4;
-					} while ((acb->wqbuf_firstindex
-					!= acb->wqbuf_lastindex) &&
-					(allxfer_len < 124));
-				}
-			} else {
-				do {
-					pQbuffer =
-					&acb->wqbuffer[acb->wqbuf_firstindex];
-					if ((acb->wqbuf_lastindex -
-					acb->wqbuf_firstindex) > 4) {
-						memcpy(iop_data,
-						pQbuffer, 4);
-						acb->wqbuf_firstindex
-						+= 4;
-						acb->wqbuf_firstindex
-						%= ARCMSR_MAX_QBUFFER;
-						iop_data += 4;
-					} else {
-						memcpy(iop_data, pQbuffer,
-						acb->wqbuf_lastindex -
-						acb->wqbuf_firstindex);
-						allxfer_len += acb->wqbuf_lastindex
-						- acb->wqbuf_firstindex;
-						acb->wqbuf_firstindex =
-						acb->wqbuf_lastindex;
-						break;
-					}
-					allxfer_len += 4;
-				} while ((acb->wqbuf_firstindex !=
-				acb->wqbuf_lastindex) && (allxfer_len < 124));
-			}
-			writel(allxfer_len, &pwbuffer->data_len);
-			arcmsr_iop_message_wrote(acb);
+	uint32_t	i;
+
+	if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
+		for (i=0; i < 15; i++) {
+			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
+				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
+				acb->rqbuf_firstindex = 0;
+				acb->rqbuf_lastindex = 0;
+				arcmsr_iop_message_read(acb);
+				mdelay(30);
+			} else if (acb->rqbuf_firstindex != acb->rqbuf_lastindex) {
+				acb->rqbuf_firstindex = 0;
+				acb->rqbuf_lastindex = 0;
+				mdelay(30);
+			} else 
+				break;
 		}
 	}
 }
@@ -2889,6 +2763,7 @@ arcmsr_iop_message_xfer(struct AdapterCo
 					acb->rqbuf_firstindex) >= 1032) {
 					memcpy(ptmpQbuffer, pQbuffer, 1032);
 					acb->rqbuf_firstindex += 1032;
+					acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
 					allxfer_len = 1032;
 				} else {
 					if (((ARCMSR_MAX_QBUFFER -
@@ -2941,58 +2816,16 @@ arcmsr_iop_message_xfer(struct AdapterCo
 				}
 			}
 		}
+		memcpy(pcmdmessagefld->messagedatabuffer, ver_addr, allxfer_len);
 		if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
 			struct QBUFFER __iomem *prbuffer;
-			uint8_t __iomem *iop_data, *vaddr, *temp;
-			uint32_t data_len_residual, data_len, rqbuf_lastindex;
-			rqbuf_lastindex = acb->rqbuf_lastindex;
+			acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
 			prbuffer = arcmsr_get_iop_rqbuffer(acb);
-			iop_data = (uint8_t __iomem *)prbuffer->data;
-			data_len_residual = data_len = readl(&prbuffer->data_len);
-			if (data_len > 0) {
-				temp = vaddr = kmalloc(data_len, GFP_ATOMIC);
-				if (!vaddr) {
-					goto leave;
-				}
-				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-				while (data_len_residual >= 4) {
-					memcpy(temp, iop_data, 4);
-					temp += 4;
-					iop_data += 4;
-					data_len_residual -= 4;
-				}
-				if ((data_len_residual > 0) &&
-				(data_len_residual < 4)) {
-					memcpy(temp, iop_data,
-					data_len_residual);
-				}
-				pQbuffer =
-				&acb->rqbuffer[acb->rqbuf_lastindex];
-				temp = vaddr;
-				if ((rqbuf_lastindex + data_len) >
-				ARCMSR_MAX_QBUFFER) {
-					memcpy(pQbuffer, temp,
-					ARCMSR_MAX_QBUFFER - rqbuf_lastindex);
-					temp += (ARCMSR_MAX_QBUFFER -
-					rqbuf_lastindex);
-					rqbuf_lastindex = (rqbuf_lastindex +
-					data_len) % ARCMSR_MAX_QBUFFER;
-					memcpy(&acb->rqbuffer[0],
-					temp, rqbuf_lastindex);
-				} else {
-					memcpy(pQbuffer, temp, data_len);
-					rqbuf_lastindex =
-					(rqbuf_lastindex + data_len) %
-					ARCMSR_MAX_QBUFFER;
-				}
-				kfree(vaddr);
-				acb->rqbuf_lastindex = rqbuf_lastindex;
-				arcmsr_iop_message_read(acb);
-			}
+			if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
+				acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
 		}
-		leave:
 		spin_unlock_irqrestore(&acb->rqbuffer_lock, flags);
-		memcpy(pcmdmessagefld->messagedatabuffer, ver_addr, allxfer_len);
+		kfree(ver_addr);
 		pcmdmessagefld->cmdmessage.Length = allxfer_len;
 		if (acb->fw_flag == FW_DEADLOCK) {
 			pcmdmessagefld->cmdmessage.ReturnCode =
@@ -3001,7 +2834,6 @@ arcmsr_iop_message_xfer(struct AdapterCo
 			pcmdmessagefld->cmdmessage.ReturnCode =
 			ARCMSR_MESSAGE_RETURNCODE_OK;
 		}
-		kfree(ver_addr);
 		break;
 	}
 	case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
@@ -3014,13 +2846,6 @@ arcmsr_iop_message_xfer(struct AdapterCo
 			retvalue = ARCMSR_MESSAGE_FAIL;
 			goto message_out;
 		}
-		if (acb->fw_flag == FW_DEADLOCK) {
-			pcmdmessagefld->cmdmessage.ReturnCode =
-			ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON;
-		} else {
-			pcmdmessagefld->cmdmessage.ReturnCode =
-			ARCMSR_MESSAGE_RETURNCODE_OK;
-		}
 		ptmpuserbuffer = ver_addr;
 		user_len = pcmdmessagefld->cmdmessage.Length;
 		memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer,
@@ -3031,7 +2856,7 @@ arcmsr_iop_message_xfer(struct AdapterCo
 		if (wqbuf_lastindex != wqbuf_firstindex) {
 			struct SENSE_DATA *sensebuffer =
 			(struct SENSE_DATA *)cmd->sense_buffer;
-			arcmsr_post_ioctldata2iop(acb);
+			arcmsr_write_ioctldata2iop(acb);
 			/* has error report sensedata */
 			sensebuffer->ErrorCode = SCSI_SENSE_CURRENT_ERRORS;
 			sensebuffer->SenseKey = ILLEGAL_REQUEST;
@@ -3068,7 +2893,7 @@ arcmsr_iop_message_xfer(struct AdapterCo
 				ACB_F_MESSAGE_WQBUFFER_CLEARED) {
 					acb->acb_flags &=
 					~ACB_F_MESSAGE_WQBUFFER_CLEARED;
-					arcmsr_post_ioctldata2iop(acb);
+					arcmsr_write_ioctldata2iop(acb);
 				}
 			} else {
 				struct SENSE_DATA *sensebuffer =
@@ -3085,16 +2910,20 @@ arcmsr_iop_message_xfer(struct AdapterCo
 		}
 		spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
 		kfree(ver_addr);
+		if (acb->fw_flag == FW_DEADLOCK) {
+			pcmdmessagefld->cmdmessage.ReturnCode =
+			ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON;
+		} else {
+			pcmdmessagefld->cmdmessage.ReturnCode =
+			ARCMSR_MESSAGE_RETURNCODE_OK;
+		}
 		break;
 	}
 	case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
 		uint8_t *pQbuffer = acb->rqbuffer;
 
+		arcmsr_clear_iop2drv_rqueue_buffer(acb);
 		spin_lock_irqsave(&acb->rqbuffer_lock, flags);
-		if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
-			acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-			arcmsr_iop_message_read(acb);
-		}
 		acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
 		acb->rqbuf_firstindex = 0;
 		acb->rqbuf_lastindex = 0;
@@ -3111,32 +2940,25 @@ arcmsr_iop_message_xfer(struct AdapterCo
 	}
 	case ARCMSR_MESSAGE_CLEAR_WQBUFFER: {
 		uint8_t *pQbuffer = acb->wqbuffer;
-		if (acb->fw_flag == FW_DEADLOCK) {
-			pcmdmessagefld->cmdmessage.ReturnCode =
-			ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON;
-		} else {
-			pcmdmessagefld->cmdmessage.ReturnCode =
-			ARCMSR_MESSAGE_RETURNCODE_OK;
-		}
 		spin_lock_irqsave(&acb->wqbuffer_lock, flags);
-		if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
-			acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-			arcmsr_iop_message_read(acb);
-		}
 		acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
 		ACB_F_MESSAGE_WQBUFFER_READED);
 		acb->wqbuf_firstindex = 0;
 		acb->wqbuf_lastindex = 0;
 		memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
 		spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
+		if (acb->fw_flag == FW_DEADLOCK) {
+			pcmdmessagefld->cmdmessage.ReturnCode =
+			ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON;
+		} else {
+			pcmdmessagefld->cmdmessage.ReturnCode =
+			ARCMSR_MESSAGE_RETURNCODE_OK;
+		}
 		break;
 	}
 	case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
 		uint8_t *pQbuffer;
-		if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
-			acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-			arcmsr_iop_message_read(acb);
-		}
+		arcmsr_clear_iop2drv_rqueue_buffer(acb);
 		spin_lock_irqsave(&acb->rqbuffer_lock, flags);
 		acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
 		acb->rqbuf_firstindex = 0;
@@ -3376,11 +3198,10 @@ arcmsr_hbaA_get_config(struct AdapterCon
 		iop_device_map++;
 		count--;
 	}
-	pr_notice("Areca RAID Controller%d: F/W %s "
-		"& Model %s\n",
+	pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n",
 		acb->host->host_no,
-		acb->firm_version,
-		acb->firm_model);
+		acb->firm_model,
+		acb->firm_version);
 	acb->signature = readl(&reg->message_rwbuffer[0]);
 	acb->firm_request_len = readl(&reg->message_rwbuffer[1]);
 	acb->firm_numbers_queue = readl(&reg->message_rwbuffer[2]);
@@ -3472,11 +3293,10 @@ arcmsr_hbaB_get_config(struct AdapterCon
 		count--;
 	}
 
-	pr_notice("Areca RAID Controller%d: "
-		"F/W %s & Model %s\n",
+	pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n",
 		acb->host->host_no,
-		acb->firm_version,
-		acb->firm_model);
+		acb->firm_model,
+		acb->firm_version);
 
 	acb->signature = readl(&reg->message_rwbuffer[1]);
 	/*firm_signature,1,00-03*/
@@ -3543,11 +3363,10 @@ arcmsr_hbaC_get_config(struct AdapterCon
 		iop_firm_version++;
 		count--;
 	}
-	pr_notice("Areca RAID Controller%d: F/W %s & "
-	"Model %s\n",
-	pACB->host->host_no,
-	pACB->firm_version,
-	pACB->firm_model);
+	pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n",
+		pACB->host->host_no,
+		pACB->firm_model,
+		pACB->firm_version);
 	pACB->firm_request_len = readl(&reg->msgcode_rwbuffer[1]);
 	pACB->firm_numbers_queue = readl(&reg->msgcode_rwbuffer[2]);
 	pACB->firm_sdram_size = readl(&reg->msgcode_rwbuffer[3]);
@@ -3686,8 +3505,10 @@ arcmsr_hbaD_get_config(struct AdapterCon
 	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: F/W %s & Model %s\n",
-	acb->host->host_no, acb->firm_version, acb->firm_model);
+	pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n",
+		acb->host->host_no,
+		acb->firm_model,
+		acb->firm_version);
 	return true;
 }
 
@@ -4026,6 +3847,7 @@ arcmsr_polling_ccbdone(struct AdapterCon
 	}
 	case ACB_ADAPTER_TYPE_D: {
 		rtn = arcmsr_hbaD_polling_ccbdone(acb, poll_ccb);
+		break;
 	}
 	}
 	return rtn;
@@ -4227,7 +4049,6 @@ arcmsr_hbaA_request_device_map(struct Ad
 		mod_timer(&acb->eternal_timer, jiffies +
 			msecs_to_jiffies(6 * HZ));
 	}
-	return;
 }
 
 static void
@@ -4258,7 +4079,6 @@ arcmsr_hbaB_request_device_map(struct Ad
 		mod_timer(&acb->eternal_timer, jiffies +
 			msecs_to_jiffies(6 * HZ));
 	}
-	return;
 }
 
 static void
@@ -4291,7 +4111,6 @@ arcmsr_hbaC_request_device_map(struct Ad
 		mod_timer(&acb->eternal_timer, jiffies +
 			msecs_to_jiffies(6 * HZ));
 	}
-	return;
 }
 
 static void
@@ -4321,7 +4140,6 @@ arcmsr_hbaD_request_device_map(struct Ad
 		mod_timer(&acb->eternal_timer, jiffies +
 			msecs_to_jiffies(6 * HZ));
 	}
-	return;
 }
 
 static void
@@ -4344,6 +4162,7 @@ arcmsr_request_device_map(unsigned long
 		}
 		case ACB_ADAPTER_TYPE_D: {
 			arcmsr_hbaD_request_device_map(acb);
+			break;
 		}
 	}
 }
@@ -4451,23 +4270,45 @@ arcmsr_clear_doorbell_queue_buffer(struc
 	case ACB_ADAPTER_TYPE_C: {
 		struct MessageUnit_C *reg =
 			(struct MessageUnit_C *)acb->pmuC;
-		uint32_t outbound_doorbell;
+		uint32_t outbound_doorbell, i;
 		/* empty doorbell Qbuffer if door bell ringed */
 		outbound_doorbell = readl(&reg->outbound_doorbell);
 		writel(outbound_doorbell, &reg->outbound_doorbell_clear);
 		writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK,
 			&reg->inbound_doorbell);
+		for (i=0; i < 200; i++) {
+			msleep(10);
+			outbound_doorbell = readl(&reg->outbound_doorbell);
+			if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) {
+				writel(outbound_doorbell,
+				&reg->outbound_doorbell_clear);
+				writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK,
+				&reg->inbound_doorbell);
+			} else
+				break;
+		}
 		}
 		break;
 	case ACB_ADAPTER_TYPE_D: {
 		struct MessageUnit_D __iomem *reg =
 			(struct MessageUnit_D *)acb->pmuD;
-		uint32_t outbound_doorbell;
+		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(10);
+			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;
 	}
 	}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2013-07-17  3:04 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-17  3:04 [PATCH 3/3] arcmsr: Fix bug of updating ARECA Raid adapter firmware through ioctl(ARCHTTP) interface 黃清隆

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).