diff options
author | Ching Huang <ching2048@areca.com.tw> | 2014-08-19 03:17:45 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2014-09-16 12:40:01 -0400 |
commit | bb263c4ecbb186fe394c6c9acc32d8c59b6a7bdd (patch) | |
tree | dd1841d010aae6c78fd2f13b5f5e3b7b32b23754 | |
parent | 6e38adfc58406e7ea6f6701c49abaf046ce076a8 (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>
-rw-r--r-- | drivers/scsi/arcmsr/arcmsr.h | 8 | ||||
-rw-r--r-- | drivers/scsi/arcmsr/arcmsr_attr.c | 101 | ||||
-rw-r--r-- | drivers/scsi/arcmsr/arcmsr_hba.c | 572 |
3 files changed, 442 insertions, 239 deletions
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index 83c0a7dbfef3..799393ede1cc 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h | |||
@@ -518,6 +518,8 @@ struct AdapterControlBlock | |||
518 | uint32_t reg_mu_acc_handle0; | 518 | uint32_t reg_mu_acc_handle0; |
519 | spinlock_t eh_lock; | 519 | spinlock_t eh_lock; |
520 | spinlock_t ccblist_lock; | 520 | spinlock_t ccblist_lock; |
521 | spinlock_t rqbuffer_lock; | ||
522 | spinlock_t wqbuffer_lock; | ||
521 | union { | 523 | union { |
522 | struct MessageUnit_A __iomem *pmuA; | 524 | struct MessageUnit_A __iomem *pmuA; |
523 | struct MessageUnit_B *pmuB; | 525 | struct MessageUnit_B *pmuB; |
@@ -693,8 +695,10 @@ struct SENSE_DATA | |||
693 | #define ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE 0x01 | 695 | #define ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE 0x01 |
694 | #define ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE 0x1F | 696 | #define ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE 0x1F |
695 | 697 | ||
696 | extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *); | 698 | extern void arcmsr_write_ioctldata2iop(struct AdapterControlBlock *); |
697 | extern void arcmsr_iop_message_read(struct AdapterControlBlock *); | 699 | extern uint32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *, |
700 | struct QBUFFER __iomem *); | ||
701 | extern void arcmsr_clear_iop2drv_rqueue_buffer(struct AdapterControlBlock *); | ||
698 | extern struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *); | 702 | extern struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *); |
699 | extern struct device_attribute *arcmsr_host_attrs[]; | 703 | extern struct device_attribute *arcmsr_host_attrs[]; |
700 | extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *); | 704 | extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *); |
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 | ||
109 | static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp, | 144 | 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 | 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; |
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index fc0dfbc70feb..1576805efc7d 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c | |||
@@ -653,6 +653,8 @@ static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
653 | } | 653 | } |
654 | spin_lock_init(&acb->eh_lock); | 654 | spin_lock_init(&acb->eh_lock); |
655 | spin_lock_init(&acb->ccblist_lock); | 655 | spin_lock_init(&acb->ccblist_lock); |
656 | spin_lock_init(&acb->rqbuffer_lock); | ||
657 | spin_lock_init(&acb->wqbuffer_lock); | ||
656 | acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | | 658 | acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | |
657 | ACB_F_MESSAGE_RQBUFFER_CLEARED | | 659 | ACB_F_MESSAGE_RQBUFFER_CLEARED | |
658 | ACB_F_MESSAGE_WQBUFFER_READED); | 660 | ACB_F_MESSAGE_WQBUFFER_READED); |
@@ -1449,68 +1451,175 @@ static struct QBUFFER __iomem *arcmsr_get_iop_wqbuffer(struct AdapterControlBloc | |||
1449 | return pqbuffer; | 1451 | return pqbuffer; |
1450 | } | 1452 | } |
1451 | 1453 | ||
1452 | static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) | 1454 | static uint32_t |
1455 | arcmsr_Read_iop_rqbuffer_in_DWORD(struct AdapterControlBlock *acb, | ||
1456 | struct QBUFFER __iomem *prbuffer) | ||
1453 | { | 1457 | { |
1454 | struct QBUFFER __iomem *prbuffer; | 1458 | uint8_t *pQbuffer; |
1455 | struct QBUFFER *pQbuffer; | 1459 | uint8_t *buf1 = NULL; |
1456 | uint8_t __iomem *iop_data; | 1460 | uint32_t __iomem *iop_data; |
1457 | int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; | 1461 | uint32_t iop_len, data_len, *buf2 = NULL; |
1458 | rqbuf_lastindex = acb->rqbuf_lastindex; | 1462 | |
1459 | rqbuf_firstindex = acb->rqbuf_firstindex; | 1463 | iop_data = (uint32_t __iomem *)prbuffer->data; |
1460 | prbuffer = arcmsr_get_iop_rqbuffer(acb); | 1464 | iop_len = readl(&prbuffer->data_len); |
1461 | iop_data = (uint8_t __iomem *)prbuffer->data; | 1465 | if (iop_len > 0) { |
1462 | iop_len = prbuffer->data_len; | 1466 | buf1 = kmalloc(128, GFP_ATOMIC); |
1463 | my_empty_len = (rqbuf_firstindex - rqbuf_lastindex - 1) & (ARCMSR_MAX_QBUFFER - 1); | 1467 | buf2 = (uint32_t *)buf1; |
1464 | 1468 | if (buf1 == NULL) | |
1465 | if (my_empty_len >= iop_len) | 1469 | return 0; |
1466 | { | 1470 | data_len = iop_len; |
1467 | while (iop_len > 0) { | 1471 | while (data_len >= 4) { |
1468 | pQbuffer = (struct QBUFFER *)&acb->rqbuffer[rqbuf_lastindex]; | 1472 | *buf2++ = readl(iop_data); |
1469 | memcpy(pQbuffer, iop_data, 1); | ||
1470 | rqbuf_lastindex++; | ||
1471 | rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; | ||
1472 | iop_data++; | 1473 | iop_data++; |
1473 | iop_len--; | 1474 | data_len -= 4; |
1474 | } | 1475 | } |
1475 | acb->rqbuf_lastindex = rqbuf_lastindex; | 1476 | if (data_len) |
1476 | arcmsr_iop_message_read(acb); | 1477 | *buf2 = readl(iop_data); |
1478 | buf2 = (uint32_t *)buf1; | ||
1479 | } | ||
1480 | while (iop_len > 0) { | ||
1481 | pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; | ||
1482 | *pQbuffer = *buf1; | ||
1483 | acb->rqbuf_lastindex++; | ||
1484 | /* if last, index number set it to 0 */ | ||
1485 | acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; | ||
1486 | buf1++; | ||
1487 | iop_len--; | ||
1488 | } | ||
1489 | if (buf2) | ||
1490 | kfree(buf2); | ||
1491 | /* let IOP know data has been read */ | ||
1492 | arcmsr_iop_message_read(acb); | ||
1493 | return 1; | ||
1494 | } | ||
1495 | |||
1496 | uint32_t | ||
1497 | arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, | ||
1498 | struct QBUFFER __iomem *prbuffer) { | ||
1499 | |||
1500 | uint8_t *pQbuffer; | ||
1501 | uint8_t __iomem *iop_data; | ||
1502 | uint32_t iop_len; | ||
1503 | |||
1504 | if (acb->adapter_type & ACB_ADAPTER_TYPE_C) | ||
1505 | return arcmsr_Read_iop_rqbuffer_in_DWORD(acb, prbuffer); | ||
1506 | iop_data = (uint8_t __iomem *)prbuffer->data; | ||
1507 | iop_len = readl(&prbuffer->data_len); | ||
1508 | while (iop_len > 0) { | ||
1509 | pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; | ||
1510 | *pQbuffer = readb(iop_data); | ||
1511 | acb->rqbuf_lastindex++; | ||
1512 | acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; | ||
1513 | iop_data++; | ||
1514 | iop_len--; | ||
1477 | } | 1515 | } |
1516 | arcmsr_iop_message_read(acb); | ||
1517 | return 1; | ||
1518 | } | ||
1478 | 1519 | ||
1479 | else { | 1520 | static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) |
1521 | { | ||
1522 | unsigned long flags; | ||
1523 | struct QBUFFER __iomem *prbuffer; | ||
1524 | int32_t buf_empty_len; | ||
1525 | |||
1526 | spin_lock_irqsave(&acb->rqbuffer_lock, flags); | ||
1527 | prbuffer = arcmsr_get_iop_rqbuffer(acb); | ||
1528 | buf_empty_len = (acb->rqbuf_lastindex - acb->rqbuf_firstindex - 1) & | ||
1529 | (ARCMSR_MAX_QBUFFER - 1); | ||
1530 | if (buf_empty_len >= readl(&prbuffer->data_len)) { | ||
1531 | if (arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) | ||
1532 | acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; | ||
1533 | } else | ||
1480 | acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; | 1534 | acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; |
1535 | spin_unlock_irqrestore(&acb->rqbuffer_lock, flags); | ||
1536 | } | ||
1537 | |||
1538 | static void arcmsr_write_ioctldata2iop_in_DWORD(struct AdapterControlBlock *acb) | ||
1539 | { | ||
1540 | uint8_t *pQbuffer; | ||
1541 | struct QBUFFER __iomem *pwbuffer; | ||
1542 | uint8_t *buf1 = NULL; | ||
1543 | uint32_t __iomem *iop_data; | ||
1544 | uint32_t allxfer_len = 0, data_len, *buf2 = NULL, data; | ||
1545 | |||
1546 | if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { | ||
1547 | buf1 = kmalloc(128, GFP_ATOMIC); | ||
1548 | buf2 = (uint32_t *)buf1; | ||
1549 | if (buf1 == NULL) | ||
1550 | return; | ||
1551 | |||
1552 | acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); | ||
1553 | pwbuffer = arcmsr_get_iop_wqbuffer(acb); | ||
1554 | iop_data = (uint32_t __iomem *)pwbuffer->data; | ||
1555 | while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) | ||
1556 | && (allxfer_len < 124)) { | ||
1557 | pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; | ||
1558 | *buf1 = *pQbuffer; | ||
1559 | acb->wqbuf_firstindex++; | ||
1560 | acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; | ||
1561 | buf1++; | ||
1562 | allxfer_len++; | ||
1563 | } | ||
1564 | data_len = allxfer_len; | ||
1565 | buf1 = (uint8_t *)buf2; | ||
1566 | while (data_len >= 4) { | ||
1567 | data = *buf2++; | ||
1568 | writel(data, iop_data); | ||
1569 | iop_data++; | ||
1570 | data_len -= 4; | ||
1571 | } | ||
1572 | if (data_len) { | ||
1573 | data = *buf2; | ||
1574 | writel(data, iop_data); | ||
1575 | } | ||
1576 | writel(allxfer_len, &pwbuffer->data_len); | ||
1577 | kfree(buf1); | ||
1578 | arcmsr_iop_message_wrote(acb); | ||
1481 | } | 1579 | } |
1482 | } | 1580 | } |
1483 | 1581 | ||
1484 | static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) | 1582 | void |
1583 | arcmsr_write_ioctldata2iop(struct AdapterControlBlock *acb) | ||
1485 | { | 1584 | { |
1486 | acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; | 1585 | uint8_t *pQbuffer; |
1487 | if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) { | 1586 | struct QBUFFER __iomem *pwbuffer; |
1488 | uint8_t *pQbuffer; | 1587 | uint8_t __iomem *iop_data; |
1489 | struct QBUFFER __iomem *pwbuffer; | 1588 | int32_t allxfer_len = 0; |
1490 | uint8_t __iomem *iop_data; | ||
1491 | int32_t allxfer_len = 0; | ||
1492 | 1589 | ||
1590 | if (acb->adapter_type & ACB_ADAPTER_TYPE_C) { | ||
1591 | arcmsr_write_ioctldata2iop_in_DWORD(acb); | ||
1592 | return; | ||
1593 | } | ||
1594 | if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { | ||
1493 | acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); | 1595 | acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); |
1494 | pwbuffer = arcmsr_get_iop_wqbuffer(acb); | 1596 | pwbuffer = arcmsr_get_iop_wqbuffer(acb); |
1495 | iop_data = (uint8_t __iomem *)pwbuffer->data; | 1597 | iop_data = (uint8_t __iomem *)pwbuffer->data; |
1496 | 1598 | while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) | |
1497 | while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) && \ | 1599 | && (allxfer_len < 124)) { |
1498 | (allxfer_len < 124)) { | ||
1499 | pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; | 1600 | pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; |
1500 | memcpy(iop_data, pQbuffer, 1); | 1601 | writeb(*pQbuffer, iop_data); |
1501 | acb->wqbuf_firstindex++; | 1602 | acb->wqbuf_firstindex++; |
1502 | acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; | 1603 | acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; |
1503 | iop_data++; | 1604 | iop_data++; |
1504 | allxfer_len++; | 1605 | allxfer_len++; |
1505 | } | 1606 | } |
1506 | pwbuffer->data_len = allxfer_len; | 1607 | writel(allxfer_len, &pwbuffer->data_len); |
1507 | |||
1508 | arcmsr_iop_message_wrote(acb); | 1608 | arcmsr_iop_message_wrote(acb); |
1509 | } | 1609 | } |
1610 | } | ||
1611 | |||
1612 | static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) | ||
1613 | { | ||
1614 | unsigned long flags; | ||
1510 | 1615 | ||
1511 | if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) { | 1616 | spin_lock_irqsave(&acb->wqbuffer_lock, flags); |
1617 | acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; | ||
1618 | if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) | ||
1619 | arcmsr_write_ioctldata2iop(acb); | ||
1620 | if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) | ||
1512 | acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; | 1621 | acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; |
1513 | } | 1622 | spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); |
1514 | } | 1623 | } |
1515 | 1624 | ||
1516 | static void arcmsr_hbaA_doorbell_isr(struct AdapterControlBlock *acb) | 1625 | static void arcmsr_hbaA_doorbell_isr(struct AdapterControlBlock *acb) |
@@ -1768,296 +1877,345 @@ static void arcmsr_iop_parking(struct AdapterControlBlock *acb) | |||
1768 | } | 1877 | } |
1769 | } | 1878 | } |
1770 | 1879 | ||
1771 | void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) | 1880 | |
1881 | void arcmsr_clear_iop2drv_rqueue_buffer(struct AdapterControlBlock *acb) | ||
1772 | { | 1882 | { |
1773 | int32_t wqbuf_firstindex, wqbuf_lastindex; | 1883 | uint32_t i; |
1774 | uint8_t *pQbuffer; | 1884 | |
1775 | struct QBUFFER __iomem *pwbuffer; | 1885 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { |
1776 | uint8_t __iomem *iop_data; | 1886 | for (i = 0; i < 15; i++) { |
1777 | int32_t allxfer_len = 0; | 1887 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { |
1778 | pwbuffer = arcmsr_get_iop_wqbuffer(acb); | 1888 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; |
1779 | iop_data = (uint8_t __iomem *)pwbuffer->data; | 1889 | acb->rqbuf_firstindex = 0; |
1780 | if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { | 1890 | acb->rqbuf_lastindex = 0; |
1781 | acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); | 1891 | arcmsr_iop_message_read(acb); |
1782 | wqbuf_firstindex = acb->wqbuf_firstindex; | 1892 | mdelay(30); |
1783 | wqbuf_lastindex = acb->wqbuf_lastindex; | 1893 | } else if (acb->rqbuf_firstindex != |
1784 | while ((wqbuf_firstindex != wqbuf_lastindex) && (allxfer_len < 124)) { | 1894 | acb->rqbuf_lastindex) { |
1785 | pQbuffer = &acb->wqbuffer[wqbuf_firstindex]; | 1895 | acb->rqbuf_firstindex = 0; |
1786 | memcpy(iop_data, pQbuffer, 1); | 1896 | acb->rqbuf_lastindex = 0; |
1787 | wqbuf_firstindex++; | 1897 | mdelay(30); |
1788 | wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; | 1898 | } else |
1789 | iop_data++; | 1899 | break; |
1790 | allxfer_len++; | ||
1791 | } | 1900 | } |
1792 | acb->wqbuf_firstindex = wqbuf_firstindex; | ||
1793 | pwbuffer->data_len = allxfer_len; | ||
1794 | arcmsr_iop_message_wrote(acb); | ||
1795 | } | 1901 | } |
1796 | } | 1902 | } |
1797 | 1903 | ||
1798 | static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, | 1904 | static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, |
1799 | struct scsi_cmnd *cmd) | 1905 | struct scsi_cmnd *cmd) |
1800 | { | 1906 | { |
1801 | struct CMD_MESSAGE_FIELD *pcmdmessagefld; | ||
1802 | int retvalue = 0, transfer_len = 0; | ||
1803 | char *buffer; | 1907 | char *buffer; |
1908 | unsigned short use_sg; | ||
1909 | int retvalue = 0, transfer_len = 0; | ||
1910 | unsigned long flags; | ||
1911 | struct CMD_MESSAGE_FIELD *pcmdmessagefld; | ||
1912 | uint32_t controlcode = (uint32_t)cmd->cmnd[5] << 24 | | ||
1913 | (uint32_t)cmd->cmnd[6] << 16 | | ||
1914 | (uint32_t)cmd->cmnd[7] << 8 | | ||
1915 | (uint32_t)cmd->cmnd[8]; | ||
1804 | struct scatterlist *sg; | 1916 | struct scatterlist *sg; |
1805 | uint32_t controlcode = (uint32_t ) cmd->cmnd[5] << 24 | | 1917 | |
1806 | (uint32_t ) cmd->cmnd[6] << 16 | | 1918 | use_sg = scsi_sg_count(cmd); |
1807 | (uint32_t ) cmd->cmnd[7] << 8 | | ||
1808 | (uint32_t ) cmd->cmnd[8]; | ||
1809 | /* 4 bytes: Areca io control code */ | ||
1810 | sg = scsi_sglist(cmd); | 1919 | sg = scsi_sglist(cmd); |
1811 | buffer = kmap_atomic(sg_page(sg)) + sg->offset; | 1920 | buffer = kmap_atomic(sg_page(sg)) + sg->offset; |
1812 | if (scsi_sg_count(cmd) > 1) { | 1921 | if (use_sg > 1) { |
1813 | retvalue = ARCMSR_MESSAGE_FAIL; | 1922 | retvalue = ARCMSR_MESSAGE_FAIL; |
1814 | goto message_out; | 1923 | goto message_out; |
1815 | } | 1924 | } |
1816 | transfer_len += sg->length; | 1925 | transfer_len += sg->length; |
1817 | |||
1818 | if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { | 1926 | if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { |
1819 | retvalue = ARCMSR_MESSAGE_FAIL; | 1927 | retvalue = ARCMSR_MESSAGE_FAIL; |
1928 | pr_info("%s: ARCMSR_MESSAGE_FAIL!\n", __func__); | ||
1820 | goto message_out; | 1929 | goto message_out; |
1821 | } | 1930 | } |
1822 | pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; | 1931 | pcmdmessagefld = (struct CMD_MESSAGE_FIELD *)buffer; |
1823 | switch(controlcode) { | 1932 | switch (controlcode) { |
1824 | |||
1825 | case ARCMSR_MESSAGE_READ_RQBUFFER: { | 1933 | case ARCMSR_MESSAGE_READ_RQBUFFER: { |
1826 | unsigned char *ver_addr; | 1934 | unsigned char *ver_addr; |
1827 | uint8_t *pQbuffer, *ptmpQbuffer; | 1935 | uint8_t *pQbuffer, *ptmpQbuffer; |
1828 | int32_t allxfer_len = 0; | 1936 | uint32_t allxfer_len = 0; |
1829 | |||
1830 | ver_addr = kmalloc(1032, GFP_ATOMIC); | 1937 | ver_addr = kmalloc(1032, GFP_ATOMIC); |
1831 | if (!ver_addr) { | 1938 | if (!ver_addr) { |
1832 | retvalue = ARCMSR_MESSAGE_FAIL; | 1939 | retvalue = ARCMSR_MESSAGE_FAIL; |
1940 | pr_info("%s: memory not enough!\n", __func__); | ||
1833 | goto message_out; | 1941 | goto message_out; |
1834 | } | 1942 | } |
1835 | |||
1836 | ptmpQbuffer = ver_addr; | 1943 | ptmpQbuffer = ver_addr; |
1837 | while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) | 1944 | spin_lock_irqsave(&acb->rqbuffer_lock, flags); |
1838 | && (allxfer_len < 1031)) { | 1945 | if (acb->rqbuf_firstindex != acb->rqbuf_lastindex) { |
1839 | pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; | 1946 | pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; |
1840 | memcpy(ptmpQbuffer, pQbuffer, 1); | 1947 | if (acb->rqbuf_firstindex > acb->rqbuf_lastindex) { |
1841 | acb->rqbuf_firstindex++; | 1948 | if ((ARCMSR_MAX_QBUFFER - |
1842 | acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; | 1949 | acb->rqbuf_firstindex) >= 1032) { |
1843 | ptmpQbuffer++; | 1950 | memcpy(ptmpQbuffer, pQbuffer, 1032); |
1844 | allxfer_len++; | 1951 | acb->rqbuf_firstindex += 1032; |
1952 | acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; | ||
1953 | allxfer_len = 1032; | ||
1954 | } else { | ||
1955 | if (((ARCMSR_MAX_QBUFFER - | ||
1956 | acb->rqbuf_firstindex) + | ||
1957 | acb->rqbuf_lastindex) > 1032) { | ||
1958 | memcpy(ptmpQbuffer, | ||
1959 | pQbuffer, ARCMSR_MAX_QBUFFER | ||
1960 | - acb->rqbuf_firstindex); | ||
1961 | ptmpQbuffer += | ||
1962 | ARCMSR_MAX_QBUFFER - | ||
1963 | acb->rqbuf_firstindex; | ||
1964 | memcpy(ptmpQbuffer, | ||
1965 | acb->rqbuffer, 1032 - | ||
1966 | (ARCMSR_MAX_QBUFFER | ||
1967 | - acb->rqbuf_firstindex)); | ||
1968 | acb->rqbuf_firstindex = | ||
1969 | 1032 - (ARCMSR_MAX_QBUFFER | ||
1970 | - acb->rqbuf_firstindex); | ||
1971 | allxfer_len = 1032; | ||
1972 | } else { | ||
1973 | memcpy(ptmpQbuffer, | ||
1974 | pQbuffer, ARCMSR_MAX_QBUFFER | ||
1975 | - acb->rqbuf_firstindex); | ||
1976 | ptmpQbuffer += | ||
1977 | ARCMSR_MAX_QBUFFER - | ||
1978 | acb->rqbuf_firstindex; | ||
1979 | memcpy(ptmpQbuffer, | ||
1980 | acb->rqbuffer, | ||
1981 | acb->rqbuf_lastindex); | ||
1982 | allxfer_len = ARCMSR_MAX_QBUFFER | ||
1983 | - acb->rqbuf_firstindex + | ||
1984 | acb->rqbuf_lastindex; | ||
1985 | acb->rqbuf_firstindex = | ||
1986 | acb->rqbuf_lastindex; | ||
1987 | } | ||
1988 | } | ||
1989 | } else { | ||
1990 | if ((acb->rqbuf_lastindex - | ||
1991 | acb->rqbuf_firstindex) > 1032) { | ||
1992 | memcpy(ptmpQbuffer, pQbuffer, 1032); | ||
1993 | acb->rqbuf_firstindex += 1032; | ||
1994 | allxfer_len = 1032; | ||
1995 | } else { | ||
1996 | memcpy(ptmpQbuffer, pQbuffer, | ||
1997 | acb->rqbuf_lastindex - | ||
1998 | acb->rqbuf_firstindex); | ||
1999 | allxfer_len = acb->rqbuf_lastindex | ||
2000 | - acb->rqbuf_firstindex; | ||
2001 | acb->rqbuf_firstindex = | ||
2002 | acb->rqbuf_lastindex; | ||
2003 | } | ||
2004 | } | ||
1845 | } | 2005 | } |
2006 | memcpy(pcmdmessagefld->messagedatabuffer, ver_addr, | ||
2007 | allxfer_len); | ||
1846 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | 2008 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { |
1847 | |||
1848 | struct QBUFFER __iomem *prbuffer; | 2009 | struct QBUFFER __iomem *prbuffer; |
1849 | uint8_t __iomem *iop_data; | ||
1850 | int32_t iop_len; | ||
1851 | |||
1852 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | 2010 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; |
1853 | prbuffer = arcmsr_get_iop_rqbuffer(acb); | 2011 | prbuffer = arcmsr_get_iop_rqbuffer(acb); |
1854 | iop_data = prbuffer->data; | 2012 | if (arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) |
1855 | iop_len = readl(&prbuffer->data_len); | 2013 | acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; |
1856 | while (iop_len > 0) { | ||
1857 | acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); | ||
1858 | acb->rqbuf_lastindex++; | ||
1859 | acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; | ||
1860 | iop_data++; | ||
1861 | iop_len--; | ||
1862 | } | ||
1863 | arcmsr_iop_message_read(acb); | ||
1864 | } | ||
1865 | memcpy(pcmdmessagefld->messagedatabuffer, ver_addr, allxfer_len); | ||
1866 | pcmdmessagefld->cmdmessage.Length = allxfer_len; | ||
1867 | if(acb->fw_flag == FW_DEADLOCK) { | ||
1868 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | ||
1869 | }else{ | ||
1870 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; | ||
1871 | } | 2014 | } |
2015 | spin_unlock_irqrestore(&acb->rqbuffer_lock, flags); | ||
1872 | kfree(ver_addr); | 2016 | kfree(ver_addr); |
1873 | } | 2017 | pcmdmessagefld->cmdmessage.Length = allxfer_len; |
2018 | if (acb->fw_flag == FW_DEADLOCK) | ||
2019 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
2020 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | ||
2021 | else | ||
2022 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
2023 | ARCMSR_MESSAGE_RETURNCODE_OK; | ||
1874 | break; | 2024 | break; |
1875 | 2025 | } | |
1876 | case ARCMSR_MESSAGE_WRITE_WQBUFFER: { | 2026 | case ARCMSR_MESSAGE_WRITE_WQBUFFER: { |
1877 | unsigned char *ver_addr; | 2027 | unsigned char *ver_addr; |
1878 | int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; | 2028 | int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; |
1879 | uint8_t *pQbuffer, *ptmpuserbuffer; | 2029 | uint8_t *pQbuffer, *ptmpuserbuffer; |
1880 | |||
1881 | ver_addr = kmalloc(1032, GFP_ATOMIC); | 2030 | ver_addr = kmalloc(1032, GFP_ATOMIC); |
1882 | if (!ver_addr) { | 2031 | if (!ver_addr) { |
1883 | retvalue = ARCMSR_MESSAGE_FAIL; | 2032 | retvalue = ARCMSR_MESSAGE_FAIL; |
1884 | goto message_out; | 2033 | goto message_out; |
1885 | } | 2034 | } |
1886 | if(acb->fw_flag == FW_DEADLOCK) { | ||
1887 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
1888 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | ||
1889 | }else{ | ||
1890 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
1891 | ARCMSR_MESSAGE_RETURNCODE_OK; | ||
1892 | } | ||
1893 | ptmpuserbuffer = ver_addr; | 2035 | ptmpuserbuffer = ver_addr; |
1894 | user_len = pcmdmessagefld->cmdmessage.Length; | 2036 | user_len = pcmdmessagefld->cmdmessage.Length; |
1895 | memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); | 2037 | memcpy(ptmpuserbuffer, |
2038 | pcmdmessagefld->messagedatabuffer, user_len); | ||
2039 | spin_lock_irqsave(&acb->wqbuffer_lock, flags); | ||
1896 | wqbuf_lastindex = acb->wqbuf_lastindex; | 2040 | wqbuf_lastindex = acb->wqbuf_lastindex; |
1897 | wqbuf_firstindex = acb->wqbuf_firstindex; | 2041 | wqbuf_firstindex = acb->wqbuf_firstindex; |
1898 | if (wqbuf_lastindex != wqbuf_firstindex) { | 2042 | if (wqbuf_lastindex != wqbuf_firstindex) { |
1899 | struct SENSE_DATA *sensebuffer = | 2043 | struct SENSE_DATA *sensebuffer = |
1900 | (struct SENSE_DATA *)cmd->sense_buffer; | 2044 | (struct SENSE_DATA *)cmd->sense_buffer; |
1901 | arcmsr_post_ioctldata2iop(acb); | 2045 | arcmsr_write_ioctldata2iop(acb); |
1902 | /* has error report sensedata */ | 2046 | /* has error report sensedata */ |
1903 | sensebuffer->ErrorCode = 0x70; | 2047 | sensebuffer->ErrorCode = SCSI_SENSE_CURRENT_ERRORS; |
1904 | sensebuffer->SenseKey = ILLEGAL_REQUEST; | 2048 | sensebuffer->SenseKey = ILLEGAL_REQUEST; |
1905 | sensebuffer->AdditionalSenseLength = 0x0A; | 2049 | sensebuffer->AdditionalSenseLength = 0x0A; |
1906 | sensebuffer->AdditionalSenseCode = 0x20; | 2050 | sensebuffer->AdditionalSenseCode = 0x20; |
1907 | sensebuffer->Valid = 1; | 2051 | sensebuffer->Valid = 1; |
1908 | retvalue = ARCMSR_MESSAGE_FAIL; | 2052 | retvalue = ARCMSR_MESSAGE_FAIL; |
1909 | } else { | 2053 | } else { |
1910 | my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) | 2054 | my_empty_len = (wqbuf_firstindex - wqbuf_lastindex - 1) |
1911 | &(ARCMSR_MAX_QBUFFER - 1); | 2055 | & (ARCMSR_MAX_QBUFFER - 1); |
1912 | if (my_empty_len >= user_len) { | 2056 | if (my_empty_len >= user_len) { |
1913 | while (user_len > 0) { | 2057 | while (user_len > 0) { |
1914 | pQbuffer = | 2058 | pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; |
1915 | &acb->wqbuffer[acb->wqbuf_lastindex]; | 2059 | if ((acb->wqbuf_lastindex + user_len) |
1916 | memcpy(pQbuffer, ptmpuserbuffer, 1); | 2060 | > ARCMSR_MAX_QBUFFER) { |
1917 | acb->wqbuf_lastindex++; | 2061 | memcpy(pQbuffer, ptmpuserbuffer, |
1918 | acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; | 2062 | ARCMSR_MAX_QBUFFER - |
1919 | ptmpuserbuffer++; | 2063 | acb->wqbuf_lastindex); |
1920 | user_len--; | 2064 | ptmpuserbuffer += |
2065 | (ARCMSR_MAX_QBUFFER | ||
2066 | - acb->wqbuf_lastindex); | ||
2067 | user_len -= (ARCMSR_MAX_QBUFFER | ||
2068 | - acb->wqbuf_lastindex); | ||
2069 | acb->wqbuf_lastindex = 0; | ||
2070 | } else { | ||
2071 | memcpy(pQbuffer, ptmpuserbuffer, | ||
2072 | user_len); | ||
2073 | acb->wqbuf_lastindex += user_len; | ||
2074 | acb->wqbuf_lastindex %= | ||
2075 | ARCMSR_MAX_QBUFFER; | ||
2076 | user_len = 0; | ||
2077 | } | ||
1921 | } | 2078 | } |
1922 | if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { | 2079 | if (acb->acb_flags & |
2080 | ACB_F_MESSAGE_WQBUFFER_CLEARED) { | ||
1923 | acb->acb_flags &= | 2081 | acb->acb_flags &= |
1924 | ~ACB_F_MESSAGE_WQBUFFER_CLEARED; | 2082 | ~ACB_F_MESSAGE_WQBUFFER_CLEARED; |
1925 | arcmsr_post_ioctldata2iop(acb); | 2083 | arcmsr_write_ioctldata2iop(acb); |
1926 | } | 2084 | } |
1927 | } else { | 2085 | } else { |
1928 | /* has error report sensedata */ | ||
1929 | struct SENSE_DATA *sensebuffer = | 2086 | struct SENSE_DATA *sensebuffer = |
1930 | (struct SENSE_DATA *)cmd->sense_buffer; | 2087 | (struct SENSE_DATA *)cmd->sense_buffer; |
1931 | sensebuffer->ErrorCode = 0x70; | 2088 | /* has error report sensedata */ |
2089 | sensebuffer->ErrorCode = | ||
2090 | SCSI_SENSE_CURRENT_ERRORS; | ||
1932 | sensebuffer->SenseKey = ILLEGAL_REQUEST; | 2091 | sensebuffer->SenseKey = ILLEGAL_REQUEST; |
1933 | sensebuffer->AdditionalSenseLength = 0x0A; | 2092 | sensebuffer->AdditionalSenseLength = 0x0A; |
1934 | sensebuffer->AdditionalSenseCode = 0x20; | 2093 | sensebuffer->AdditionalSenseCode = 0x20; |
1935 | sensebuffer->Valid = 1; | 2094 | sensebuffer->Valid = 1; |
1936 | retvalue = ARCMSR_MESSAGE_FAIL; | 2095 | retvalue = ARCMSR_MESSAGE_FAIL; |
1937 | } | 2096 | } |
1938 | } | ||
1939 | kfree(ver_addr); | ||
1940 | } | 2097 | } |
2098 | spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); | ||
2099 | kfree(ver_addr); | ||
2100 | if (acb->fw_flag == FW_DEADLOCK) | ||
2101 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
2102 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | ||
2103 | else | ||
2104 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
2105 | ARCMSR_MESSAGE_RETURNCODE_OK; | ||
1941 | break; | 2106 | break; |
1942 | 2107 | } | |
1943 | case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { | 2108 | case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { |
1944 | uint8_t *pQbuffer = acb->rqbuffer; | 2109 | uint8_t *pQbuffer = acb->rqbuffer; |
1945 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | 2110 | |
1946 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | 2111 | arcmsr_clear_iop2drv_rqueue_buffer(acb); |
1947 | arcmsr_iop_message_read(acb); | 2112 | spin_lock_irqsave(&acb->rqbuffer_lock, flags); |
1948 | } | ||
1949 | acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; | 2113 | acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; |
1950 | acb->rqbuf_firstindex = 0; | 2114 | acb->rqbuf_firstindex = 0; |
1951 | acb->rqbuf_lastindex = 0; | 2115 | acb->rqbuf_lastindex = 0; |
1952 | memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); | 2116 | memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); |
1953 | if(acb->fw_flag == FW_DEADLOCK) { | 2117 | spin_unlock_irqrestore(&acb->rqbuffer_lock, flags); |
2118 | if (acb->fw_flag == FW_DEADLOCK) | ||
1954 | pcmdmessagefld->cmdmessage.ReturnCode = | 2119 | pcmdmessagefld->cmdmessage.ReturnCode = |
1955 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | 2120 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; |
1956 | }else{ | 2121 | else |
1957 | pcmdmessagefld->cmdmessage.ReturnCode = | 2122 | pcmdmessagefld->cmdmessage.ReturnCode = |
1958 | ARCMSR_MESSAGE_RETURNCODE_OK; | 2123 | ARCMSR_MESSAGE_RETURNCODE_OK; |
1959 | } | ||
1960 | } | ||
1961 | break; | 2124 | break; |
1962 | 2125 | } | |
1963 | case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { | 2126 | case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { |
1964 | uint8_t *pQbuffer = acb->wqbuffer; | 2127 | uint8_t *pQbuffer = acb->wqbuffer; |
1965 | if(acb->fw_flag == FW_DEADLOCK) { | 2128 | spin_lock_irqsave(&acb->wqbuffer_lock, flags); |
1966 | pcmdmessagefld->cmdmessage.ReturnCode = | 2129 | acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | |
1967 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | 2130 | ACB_F_MESSAGE_WQBUFFER_READED); |
1968 | }else{ | ||
1969 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
1970 | ARCMSR_MESSAGE_RETURNCODE_OK; | ||
1971 | } | ||
1972 | |||
1973 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | ||
1974 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | ||
1975 | arcmsr_iop_message_read(acb); | ||
1976 | } | ||
1977 | acb->acb_flags |= | ||
1978 | (ACB_F_MESSAGE_WQBUFFER_CLEARED | | ||
1979 | ACB_F_MESSAGE_WQBUFFER_READED); | ||
1980 | acb->wqbuf_firstindex = 0; | 2131 | acb->wqbuf_firstindex = 0; |
1981 | acb->wqbuf_lastindex = 0; | 2132 | acb->wqbuf_lastindex = 0; |
1982 | memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); | 2133 | memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); |
1983 | } | 2134 | spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); |
2135 | if (acb->fw_flag == FW_DEADLOCK) | ||
2136 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
2137 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | ||
2138 | else | ||
2139 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
2140 | ARCMSR_MESSAGE_RETURNCODE_OK; | ||
1984 | break; | 2141 | break; |
1985 | 2142 | } | |
1986 | case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { | 2143 | case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { |
1987 | uint8_t *pQbuffer; | 2144 | uint8_t *pQbuffer; |
1988 | 2145 | arcmsr_clear_iop2drv_rqueue_buffer(acb); | |
1989 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | 2146 | spin_lock_irqsave(&acb->rqbuffer_lock, flags); |
1990 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | 2147 | acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; |
1991 | arcmsr_iop_message_read(acb); | ||
1992 | } | ||
1993 | acb->acb_flags |= | ||
1994 | (ACB_F_MESSAGE_WQBUFFER_CLEARED | ||
1995 | | ACB_F_MESSAGE_RQBUFFER_CLEARED | ||
1996 | | ACB_F_MESSAGE_WQBUFFER_READED); | ||
1997 | acb->rqbuf_firstindex = 0; | 2148 | acb->rqbuf_firstindex = 0; |
1998 | acb->rqbuf_lastindex = 0; | 2149 | acb->rqbuf_lastindex = 0; |
1999 | acb->wqbuf_firstindex = 0; | ||
2000 | acb->wqbuf_lastindex = 0; | ||
2001 | pQbuffer = acb->rqbuffer; | 2150 | pQbuffer = acb->rqbuffer; |
2002 | memset(pQbuffer, 0, sizeof(struct QBUFFER)); | 2151 | memset(pQbuffer, 0, sizeof(struct QBUFFER)); |
2152 | spin_unlock_irqrestore(&acb->rqbuffer_lock, flags); | ||
2153 | spin_lock_irqsave(&acb->wqbuffer_lock, flags); | ||
2154 | acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | | ||
2155 | ACB_F_MESSAGE_WQBUFFER_READED); | ||
2156 | acb->wqbuf_firstindex = 0; | ||
2157 | acb->wqbuf_lastindex = 0; | ||
2003 | pQbuffer = acb->wqbuffer; | 2158 | pQbuffer = acb->wqbuffer; |
2004 | memset(pQbuffer, 0, sizeof(struct QBUFFER)); | 2159 | memset(pQbuffer, 0, sizeof(struct QBUFFER)); |
2005 | if(acb->fw_flag == FW_DEADLOCK) { | 2160 | spin_unlock_irqrestore(&acb->wqbuffer_lock, flags); |
2161 | if (acb->fw_flag == FW_DEADLOCK) | ||
2006 | pcmdmessagefld->cmdmessage.ReturnCode = | 2162 | pcmdmessagefld->cmdmessage.ReturnCode = |
2007 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | 2163 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; |
2008 | }else{ | 2164 | else |
2009 | pcmdmessagefld->cmdmessage.ReturnCode = | 2165 | pcmdmessagefld->cmdmessage.ReturnCode = |
2010 | ARCMSR_MESSAGE_RETURNCODE_OK; | 2166 | ARCMSR_MESSAGE_RETURNCODE_OK; |
2011 | } | ||
2012 | } | ||
2013 | break; | 2167 | break; |
2014 | 2168 | } | |
2015 | case ARCMSR_MESSAGE_RETURN_CODE_3F: { | 2169 | case ARCMSR_MESSAGE_RETURN_CODE_3F: { |
2016 | if(acb->fw_flag == FW_DEADLOCK) { | 2170 | if (acb->fw_flag == FW_DEADLOCK) |
2017 | pcmdmessagefld->cmdmessage.ReturnCode = | 2171 | pcmdmessagefld->cmdmessage.ReturnCode = |
2018 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | 2172 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; |
2019 | }else{ | 2173 | else |
2020 | pcmdmessagefld->cmdmessage.ReturnCode = | 2174 | pcmdmessagefld->cmdmessage.ReturnCode = |
2021 | ARCMSR_MESSAGE_RETURNCODE_3F; | 2175 | ARCMSR_MESSAGE_RETURNCODE_3F; |
2022 | } | ||
2023 | break; | 2176 | break; |
2024 | } | 2177 | } |
2025 | case ARCMSR_MESSAGE_SAY_HELLO: { | 2178 | case ARCMSR_MESSAGE_SAY_HELLO: { |
2026 | int8_t *hello_string = "Hello! I am ARCMSR"; | 2179 | int8_t *hello_string = "Hello! I am ARCMSR"; |
2027 | if(acb->fw_flag == FW_DEADLOCK) { | 2180 | if (acb->fw_flag == FW_DEADLOCK) |
2028 | pcmdmessagefld->cmdmessage.ReturnCode = | 2181 | pcmdmessagefld->cmdmessage.ReturnCode = |
2029 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | 2182 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; |
2030 | }else{ | 2183 | else |
2031 | pcmdmessagefld->cmdmessage.ReturnCode = | 2184 | pcmdmessagefld->cmdmessage.ReturnCode = |
2032 | ARCMSR_MESSAGE_RETURNCODE_OK; | 2185 | ARCMSR_MESSAGE_RETURNCODE_OK; |
2033 | } | 2186 | memcpy(pcmdmessagefld->messagedatabuffer, |
2034 | memcpy(pcmdmessagefld->messagedatabuffer, hello_string | 2187 | hello_string, (int16_t)strlen(hello_string)); |
2035 | , (int16_t)strlen(hello_string)); | ||
2036 | } | ||
2037 | break; | 2188 | break; |
2038 | 2189 | } | |
2039 | case ARCMSR_MESSAGE_SAY_GOODBYE: | 2190 | case ARCMSR_MESSAGE_SAY_GOODBYE: { |
2040 | if(acb->fw_flag == FW_DEADLOCK) { | 2191 | if (acb->fw_flag == FW_DEADLOCK) |
2041 | pcmdmessagefld->cmdmessage.ReturnCode = | 2192 | pcmdmessagefld->cmdmessage.ReturnCode = |
2042 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | 2193 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; |
2043 | } | 2194 | else |
2195 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
2196 | ARCMSR_MESSAGE_RETURNCODE_OK; | ||
2044 | arcmsr_iop_parking(acb); | 2197 | arcmsr_iop_parking(acb); |
2045 | break; | 2198 | break; |
2046 | 2199 | } | |
2047 | case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: | 2200 | case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { |
2048 | if(acb->fw_flag == FW_DEADLOCK) { | 2201 | if (acb->fw_flag == FW_DEADLOCK) |
2049 | pcmdmessagefld->cmdmessage.ReturnCode = | 2202 | pcmdmessagefld->cmdmessage.ReturnCode = |
2050 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | 2203 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; |
2051 | } | 2204 | else |
2205 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
2206 | ARCMSR_MESSAGE_RETURNCODE_OK; | ||
2052 | arcmsr_flush_adapter_cache(acb); | 2207 | arcmsr_flush_adapter_cache(acb); |
2053 | break; | 2208 | break; |
2054 | 2209 | } | |
2055 | default: | 2210 | default: |
2056 | retvalue = ARCMSR_MESSAGE_FAIL; | 2211 | retvalue = ARCMSR_MESSAGE_FAIL; |
2212 | pr_info("%s: unknown controlcode!\n", __func__); | ||
2213 | } | ||
2214 | message_out: | ||
2215 | if (use_sg) { | ||
2216 | struct scatterlist *sg = scsi_sglist(cmd); | ||
2217 | kunmap_atomic(buffer - sg->offset); | ||
2057 | } | 2218 | } |
2058 | message_out: | ||
2059 | sg = scsi_sglist(cmd); | ||
2060 | kunmap_atomic(buffer - sg->offset); | ||
2061 | return retvalue; | 2219 | return retvalue; |
2062 | } | 2220 | } |
2063 | 2221 | ||