* [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, ®->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, ®->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(®->message_rwbuffer[0]);
acb->firm_request_len = readl(®->message_rwbuffer[1]);
acb->firm_numbers_queue = readl(®->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(®->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(®->msgcode_rwbuffer[1]);
pACB->firm_numbers_queue = readl(®->msgcode_rwbuffer[2]);
pACB->firm_sdram_size = readl(®->msgcode_rwbuffer[3]);
@@ -3686,8 +3505,10 @@ arcmsr_hbaD_get_config(struct AdapterCon
acb->firm_hd_channels = readl(®->msgcode_rwbuffer[5]);
/*firm_hd_channels,4,16-19*/
acb->firm_cfg_version = readl(®->msgcode_rwbuffer[25]);
- pr_notice("Areca RAID Controller%d: 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(®->outbound_doorbell);
writel(outbound_doorbell, ®->outbound_doorbell_clear);
writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK,
®->inbound_doorbell);
+ for (i=0; i < 200; i++) {
+ msleep(10);
+ outbound_doorbell = readl(®->outbound_doorbell);
+ if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) {
+ writel(outbound_doorbell,
+ ®->outbound_doorbell_clear);
+ writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK,
+ ®->inbound_doorbell);
+ } else
+ break;
+ }
}
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).