Commit bb263c4e authored by Ching Huang's avatar Ching Huang Committed by Christoph Hellwig

arcmsr: fix ioctl data read/write error for adapter type C

Rewrite ioctl entry and its relate function.  This patch fix ioctl data
read/write error and change data I/O access from byte to Dword.
Signed-off-by: default avatarChing Huang <ching2048@areca.com.tw>
Reviewed-by: default avatarTomas Henzl <thenzl@redhat.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 6e38adfc
...@@ -518,6 +518,8 @@ struct AdapterControlBlock ...@@ -518,6 +518,8 @@ struct AdapterControlBlock
uint32_t reg_mu_acc_handle0; uint32_t reg_mu_acc_handle0;
spinlock_t eh_lock; spinlock_t eh_lock;
spinlock_t ccblist_lock; spinlock_t ccblist_lock;
spinlock_t rqbuffer_lock;
spinlock_t wqbuffer_lock;
union { union {
struct MessageUnit_A __iomem *pmuA; struct MessageUnit_A __iomem *pmuA;
struct MessageUnit_B *pmuB; struct MessageUnit_B *pmuB;
...@@ -693,8 +695,10 @@ struct SENSE_DATA ...@@ -693,8 +695,10 @@ struct SENSE_DATA
#define ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE 0x01 #define ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE 0x01
#define ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE 0x1F #define ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE 0x1F
extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *); extern void arcmsr_write_ioctldata2iop(struct AdapterControlBlock *);
extern void arcmsr_iop_message_read(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 QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *);
extern struct device_attribute *arcmsr_host_attrs[]; extern struct device_attribute *arcmsr_host_attrs[];
extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *); extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *);
......
...@@ -70,40 +70,75 @@ static ssize_t arcmsr_sysfs_iop_message_read(struct file *filp, ...@@ -70,40 +70,75 @@ static ssize_t arcmsr_sysfs_iop_message_read(struct file *filp,
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
uint8_t *pQbuffer,*ptmpQbuffer; uint8_t *pQbuffer,*ptmpQbuffer;
int32_t allxfer_len = 0; int32_t allxfer_len = 0;
unsigned long flags;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
/* do message unit read. */ /* do message unit read. */
ptmpQbuffer = (uint8_t *)buf; ptmpQbuffer = (uint8_t *)buf;
while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) spin_lock_irqsave(&acb->rqbuffer_lock, flags);
&& (allxfer_len < 1031)) { if (acb->rqbuf_firstindex != acb->rqbuf_lastindex) {
pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
memcpy(ptmpQbuffer, pQbuffer, 1); if (acb->rqbuf_firstindex > acb->rqbuf_lastindex) {
acb->rqbuf_firstindex++; if ((ARCMSR_MAX_QBUFFER - acb->rqbuf_firstindex) >= 1032) {
acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; memcpy(ptmpQbuffer, pQbuffer, 1032);
ptmpQbuffer++; acb->rqbuf_firstindex += 1032;
allxfer_len++; acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
allxfer_len = 1032;
} else {
if (((ARCMSR_MAX_QBUFFER - acb->rqbuf_firstindex)
+ acb->rqbuf_lastindex) > 1032) {
memcpy(ptmpQbuffer, pQbuffer,
ARCMSR_MAX_QBUFFER
- acb->rqbuf_firstindex);
ptmpQbuffer += ARCMSR_MAX_QBUFFER
- acb->rqbuf_firstindex;
memcpy(ptmpQbuffer, acb->rqbuffer, 1032
- (ARCMSR_MAX_QBUFFER -
acb->rqbuf_firstindex));
acb->rqbuf_firstindex = 1032 -
(ARCMSR_MAX_QBUFFER -
acb->rqbuf_firstindex);
allxfer_len = 1032;
} else {
memcpy(ptmpQbuffer, pQbuffer,
ARCMSR_MAX_QBUFFER -
acb->rqbuf_firstindex);
ptmpQbuffer += ARCMSR_MAX_QBUFFER -
acb->rqbuf_firstindex;
memcpy(ptmpQbuffer, acb->rqbuffer,
acb->rqbuf_lastindex);
allxfer_len = ARCMSR_MAX_QBUFFER -
acb->rqbuf_firstindex +
acb->rqbuf_lastindex;
acb->rqbuf_firstindex =
acb->rqbuf_lastindex;
}
}
} else {
if ((acb->rqbuf_lastindex - acb->rqbuf_firstindex) > 1032) {
memcpy(ptmpQbuffer, pQbuffer, 1032);
acb->rqbuf_firstindex += 1032;
allxfer_len = 1032;
} else {
memcpy(ptmpQbuffer, pQbuffer, acb->rqbuf_lastindex
- acb->rqbuf_firstindex);
allxfer_len = acb->rqbuf_lastindex -
acb->rqbuf_firstindex;
acb->rqbuf_firstindex = acb->rqbuf_lastindex;
}
}
} }
if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
struct QBUFFER __iomem *prbuffer; struct QBUFFER __iomem *prbuffer;
uint8_t __iomem *iop_data;
int32_t iop_len;
acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
prbuffer = arcmsr_get_iop_rqbuffer(acb); prbuffer = arcmsr_get_iop_rqbuffer(acb);
iop_data = prbuffer->data; if (arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
iop_len = readl(&prbuffer->data_len); acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
while (iop_len > 0) {
acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data);
acb->rqbuf_lastindex++;
acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
iop_data++;
iop_len--;
}
arcmsr_iop_message_read(acb);
} }
return (allxfer_len); spin_unlock_irqrestore(&acb->rqbuffer_lock, flags);
return allxfer_len;
} }
static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp, static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp,
...@@ -117,6 +152,7 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp, ...@@ -117,6 +152,7 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp,
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
uint8_t *pQbuffer, *ptmpuserbuffer; uint8_t *pQbuffer, *ptmpuserbuffer;
unsigned long flags;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
...@@ -125,18 +161,19 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp, ...@@ -125,18 +161,19 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp,
/* do message unit write. */ /* do message unit write. */
ptmpuserbuffer = (uint8_t *)buf; ptmpuserbuffer = (uint8_t *)buf;
user_len = (int32_t)count; user_len = (int32_t)count;
spin_lock_irqsave(&acb->wqbuffer_lock, flags);
wqbuf_lastindex = acb->wqbuf_lastindex; wqbuf_lastindex = acb->wqbuf_lastindex;
wqbuf_firstindex = acb->wqbuf_firstindex; wqbuf_firstindex = acb->wqbuf_firstindex;
if (wqbuf_lastindex != 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*/ return 0; /*need retry*/
} else { } else {
my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1)
&(ARCMSR_MAX_QBUFFER - 1); &(ARCMSR_MAX_QBUFFER - 1);
if (my_empty_len >= user_len) { if (my_empty_len >= user_len) {
while (user_len > 0) { while (user_len > 0) {
pQbuffer = pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex];
&acb->wqbuffer[acb->wqbuf_lastindex];
memcpy(pQbuffer, ptmpuserbuffer, 1); memcpy(pQbuffer, ptmpuserbuffer, 1);
acb->wqbuf_lastindex++; acb->wqbuf_lastindex++;
acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
...@@ -146,10 +183,12 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp, ...@@ -146,10 +183,12 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp,
if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
acb->acb_flags &= acb->acb_flags &=
~ACB_F_MESSAGE_WQBUFFER_CLEARED; ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
arcmsr_post_ioctldata2iop(acb); arcmsr_write_ioctldata2iop(acb);
} }
spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
return count; return count;
} else { } else {
spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
return 0; /*need retry*/ return 0; /*need retry*/
} }
} }
...@@ -165,22 +204,24 @@ static ssize_t arcmsr_sysfs_iop_message_clear(struct file *filp, ...@@ -165,22 +204,24 @@ static ssize_t arcmsr_sysfs_iop_message_clear(struct file *filp,
struct Scsi_Host *host = class_to_shost(dev); struct Scsi_Host *host = class_to_shost(dev);
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
uint8_t *pQbuffer; uint8_t *pQbuffer;
unsigned long flags;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { arcmsr_clear_iop2drv_rqueue_buffer(acb);
acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
arcmsr_iop_message_read(acb);
}
acb->acb_flags |= acb->acb_flags |=
(ACB_F_MESSAGE_WQBUFFER_CLEARED (ACB_F_MESSAGE_WQBUFFER_CLEARED
| ACB_F_MESSAGE_RQBUFFER_CLEARED | ACB_F_MESSAGE_RQBUFFER_CLEARED
| ACB_F_MESSAGE_WQBUFFER_READED); | ACB_F_MESSAGE_WQBUFFER_READED);
spin_lock_irqsave(&acb->rqbuffer_lock, flags);
acb->rqbuf_firstindex = 0; acb->rqbuf_firstindex = 0;
acb->rqbuf_lastindex = 0; acb->rqbuf_lastindex = 0;
spin_unlock_irqrestore(&acb->rqbuffer_lock, flags);
spin_lock_irqsave(&acb->wqbuffer_lock, flags);
acb->wqbuf_firstindex = 0; acb->wqbuf_firstindex = 0;
acb->wqbuf_lastindex = 0; acb->wqbuf_lastindex = 0;
spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
pQbuffer = acb->rqbuffer; pQbuffer = acb->rqbuffer;
memset(pQbuffer, 0, sizeof (struct QBUFFER)); memset(pQbuffer, 0, sizeof (struct QBUFFER));
pQbuffer = acb->wqbuffer; pQbuffer = acb->wqbuffer;
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment