aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/arcmsr/arcmsr_attr.c
diff options
context:
space:
mode:
authorChing Huang <ching2048@areca.com.tw>2014-08-19 03:17:45 -0400
committerChristoph Hellwig <hch@lst.de>2014-09-16 12:40:01 -0400
commitbb263c4ecbb186fe394c6c9acc32d8c59b6a7bdd (patch)
treedd1841d010aae6c78fd2f13b5f5e3b7b32b23754 /drivers/scsi/arcmsr/arcmsr_attr.c
parent6e38adfc58406e7ea6f6701c49abaf046ce076a8 (diff)
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: Ching Huang <ching2048@areca.com.tw> Reviewed-by: Tomas Henzl <thenzl@redhat.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/arcmsr/arcmsr_attr.c')
-rw-r--r--drivers/scsi/arcmsr/arcmsr_attr.c101
1 files changed, 71 insertions, 30 deletions
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
index acdae33de521..16422adcc531 100644
--- a/drivers/scsi/arcmsr/arcmsr_attr.c
+++ b/drivers/scsi/arcmsr/arcmsr_attr.c
@@ -70,40 +70,75 @@ static ssize_t arcmsr_sysfs_iop_message_read(struct file *filp,
70 struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; 70 struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
71 uint8_t *pQbuffer,*ptmpQbuffer; 71 uint8_t *pQbuffer,*ptmpQbuffer;
72 int32_t allxfer_len = 0; 72 int32_t allxfer_len = 0;
73 unsigned long flags;
73 74
74 if (!capable(CAP_SYS_ADMIN)) 75 if (!capable(CAP_SYS_ADMIN))
75 return -EACCES; 76 return -EACCES;
76 77
77 /* do message unit read. */ 78 /* do message unit read. */
78 ptmpQbuffer = (uint8_t *)buf; 79 ptmpQbuffer = (uint8_t *)buf;
79 while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 80 spin_lock_irqsave(&acb->rqbuffer_lock, flags);
80 && (allxfer_len < 1031)) { 81 if (acb->rqbuf_firstindex != acb->rqbuf_lastindex) {
81 pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 82 pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
82 memcpy(ptmpQbuffer, pQbuffer, 1); 83 if (acb->rqbuf_firstindex > acb->rqbuf_lastindex) {
83 acb->rqbuf_firstindex++; 84 if ((ARCMSR_MAX_QBUFFER - acb->rqbuf_firstindex) >= 1032) {
84 acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 85 memcpy(ptmpQbuffer, pQbuffer, 1032);
85 ptmpQbuffer++; 86 acb->rqbuf_firstindex += 1032;
86 allxfer_len++; 87 acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
88 allxfer_len = 1032;
89 } else {
90 if (((ARCMSR_MAX_QBUFFER - acb->rqbuf_firstindex)
91 + acb->rqbuf_lastindex) > 1032) {
92 memcpy(ptmpQbuffer, pQbuffer,
93 ARCMSR_MAX_QBUFFER
94 - acb->rqbuf_firstindex);
95 ptmpQbuffer += ARCMSR_MAX_QBUFFER
96 - acb->rqbuf_firstindex;
97 memcpy(ptmpQbuffer, acb->rqbuffer, 1032
98 - (ARCMSR_MAX_QBUFFER -
99 acb->rqbuf_firstindex));
100 acb->rqbuf_firstindex = 1032 -
101 (ARCMSR_MAX_QBUFFER -
102 acb->rqbuf_firstindex);
103 allxfer_len = 1032;
104 } else {
105 memcpy(ptmpQbuffer, pQbuffer,
106 ARCMSR_MAX_QBUFFER -
107 acb->rqbuf_firstindex);
108 ptmpQbuffer += ARCMSR_MAX_QBUFFER -
109 acb->rqbuf_firstindex;
110 memcpy(ptmpQbuffer, acb->rqbuffer,
111 acb->rqbuf_lastindex);
112 allxfer_len = ARCMSR_MAX_QBUFFER -
113 acb->rqbuf_firstindex +
114 acb->rqbuf_lastindex;
115 acb->rqbuf_firstindex =
116 acb->rqbuf_lastindex;
117 }
118 }
119 } else {
120 if ((acb->rqbuf_lastindex - acb->rqbuf_firstindex) > 1032) {
121 memcpy(ptmpQbuffer, pQbuffer, 1032);
122 acb->rqbuf_firstindex += 1032;
123 allxfer_len = 1032;
124 } else {
125 memcpy(ptmpQbuffer, pQbuffer, acb->rqbuf_lastindex
126 - acb->rqbuf_firstindex);
127 allxfer_len = acb->rqbuf_lastindex -
128 acb->rqbuf_firstindex;
129 acb->rqbuf_firstindex = acb->rqbuf_lastindex;
130 }
131 }
87 } 132 }
88 if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 133 if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
89 struct QBUFFER __iomem *prbuffer; 134 struct QBUFFER __iomem *prbuffer;
90 uint8_t __iomem *iop_data;
91 int32_t iop_len;
92
93 acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 135 acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
94 prbuffer = arcmsr_get_iop_rqbuffer(acb); 136 prbuffer = arcmsr_get_iop_rqbuffer(acb);
95 iop_data = prbuffer->data; 137 if (arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
96 iop_len = readl(&prbuffer->data_len); 138 acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
97 while (iop_len > 0) {
98 acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data);
99 acb->rqbuf_lastindex++;
100 acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
101 iop_data++;
102 iop_len--;
103 }
104 arcmsr_iop_message_read(acb);
105 } 139 }
106 return (allxfer_len); 140 spin_unlock_irqrestore(&acb->rqbuffer_lock, flags);
141 return allxfer_len;
107} 142}
108 143
109static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp, 144static 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 struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; 152 struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
118 int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 153 int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
119 uint8_t *pQbuffer, *ptmpuserbuffer; 154 uint8_t *pQbuffer, *ptmpuserbuffer;
155 unsigned long flags;
120 156
121 if (!capable(CAP_SYS_ADMIN)) 157 if (!capable(CAP_SYS_ADMIN))
122 return -EACCES; 158 return -EACCES;
@@ -125,18 +161,19 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp,
125 /* do message unit write. */ 161 /* do message unit write. */
126 ptmpuserbuffer = (uint8_t *)buf; 162 ptmpuserbuffer = (uint8_t *)buf;
127 user_len = (int32_t)count; 163 user_len = (int32_t)count;
164 spin_lock_irqsave(&acb->wqbuffer_lock, flags);
128 wqbuf_lastindex = acb->wqbuf_lastindex; 165 wqbuf_lastindex = acb->wqbuf_lastindex;
129 wqbuf_firstindex = acb->wqbuf_firstindex; 166 wqbuf_firstindex = acb->wqbuf_firstindex;
130 if (wqbuf_lastindex != wqbuf_firstindex) { 167 if (wqbuf_lastindex != wqbuf_firstindex) {
131 arcmsr_post_ioctldata2iop(acb); 168 arcmsr_write_ioctldata2iop(acb);
169 spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
132 return 0; /*need retry*/ 170 return 0; /*need retry*/
133 } else { 171 } else {
134 my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) 172 my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1)
135 &(ARCMSR_MAX_QBUFFER - 1); 173 &(ARCMSR_MAX_QBUFFER - 1);
136 if (my_empty_len >= user_len) { 174 if (my_empty_len >= user_len) {
137 while (user_len > 0) { 175 while (user_len > 0) {
138 pQbuffer = 176 pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex];
139 &acb->wqbuffer[acb->wqbuf_lastindex];
140 memcpy(pQbuffer, ptmpuserbuffer, 1); 177 memcpy(pQbuffer, ptmpuserbuffer, 1);
141 acb->wqbuf_lastindex++; 178 acb->wqbuf_lastindex++;
142 acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 179 acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
@@ -146,10 +183,12 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp,
146 if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 183 if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
147 acb->acb_flags &= 184 acb->acb_flags &=
148 ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 185 ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
149 arcmsr_post_ioctldata2iop(acb); 186 arcmsr_write_ioctldata2iop(acb);
150 } 187 }
188 spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
151 return count; 189 return count;
152 } else { 190 } else {
191 spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
153 return 0; /*need retry*/ 192 return 0; /*need retry*/
154 } 193 }
155 } 194 }
@@ -165,22 +204,24 @@ static ssize_t arcmsr_sysfs_iop_message_clear(struct file *filp,
165 struct Scsi_Host *host = class_to_shost(dev); 204 struct Scsi_Host *host = class_to_shost(dev);
166 struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; 205 struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
167 uint8_t *pQbuffer; 206 uint8_t *pQbuffer;
207 unsigned long flags;
168 208
169 if (!capable(CAP_SYS_ADMIN)) 209 if (!capable(CAP_SYS_ADMIN))
170 return -EACCES; 210 return -EACCES;
171 211
172 if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 212 arcmsr_clear_iop2drv_rqueue_buffer(acb);
173 acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
174 arcmsr_iop_message_read(acb);
175 }
176 acb->acb_flags |= 213 acb->acb_flags |=
177 (ACB_F_MESSAGE_WQBUFFER_CLEARED 214 (ACB_F_MESSAGE_WQBUFFER_CLEARED
178 | ACB_F_MESSAGE_RQBUFFER_CLEARED 215 | ACB_F_MESSAGE_RQBUFFER_CLEARED
179 | ACB_F_MESSAGE_WQBUFFER_READED); 216 | ACB_F_MESSAGE_WQBUFFER_READED);
217 spin_lock_irqsave(&acb->rqbuffer_lock, flags);
180 acb->rqbuf_firstindex = 0; 218 acb->rqbuf_firstindex = 0;
181 acb->rqbuf_lastindex = 0; 219 acb->rqbuf_lastindex = 0;
220 spin_unlock_irqrestore(&acb->rqbuffer_lock, flags);
221 spin_lock_irqsave(&acb->wqbuffer_lock, flags);
182 acb->wqbuf_firstindex = 0; 222 acb->wqbuf_firstindex = 0;
183 acb->wqbuf_lastindex = 0; 223 acb->wqbuf_lastindex = 0;
224 spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
184 pQbuffer = acb->rqbuffer; 225 pQbuffer = acb->rqbuffer;
185 memset(pQbuffer, 0, sizeof (struct QBUFFER)); 226 memset(pQbuffer, 0, sizeof (struct QBUFFER));
186 pQbuffer = acb->wqbuffer; 227 pQbuffer = acb->wqbuffer;