diff options
author | Nick Cheng <nick.cheng@areca.com.tw> | 2007-09-13 05:26:40 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-12 14:48:27 -0400 |
commit | 1a4f550a09f89e3a15eff1971bc9db977571b9f6 (patch) | |
tree | 3ba5dea468391701664d4ca4c0b0e2a569521d89 /drivers | |
parent | bfd129445f23c037d9a440ebfa4109e11c220301 (diff) |
[SCSI] arcmsr: 1.20.00.15: add SATA RAID plus other fixes
Description:
** support ARC1200/1201/1202 SATA RAID adapter, which is named
ACB_ADAPTER_TYPE_B
** modify the arcmsr_pci_slot_reset function
** modify the arcmsr_pci_ers_disconnect_forepart function
** modify the arcmsr_pci_ers_need_reset_forepart function
Signed-off-by: Nick Cheng <nick.cheng@areca.com.tw>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/Kconfig | 23 | ||||
-rw-r--r-- | drivers/scsi/arcmsr/arcmsr.h | 192 | ||||
-rw-r--r-- | drivers/scsi/arcmsr/arcmsr_attr.c | 64 | ||||
-rw-r--r-- | drivers/scsi/arcmsr/arcmsr_hba.c | 2249 |
4 files changed, 1545 insertions, 983 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index e1efa0eac4ff..69b2fac6f098 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -543,19 +543,32 @@ config SCSI_IN2000 | |||
543 | module will be called in2000. | 543 | module will be called in2000. |
544 | 544 | ||
545 | config SCSI_ARCMSR | 545 | config SCSI_ARCMSR |
546 | tristate "ARECA ARC11X0[PCI-X]/ARC12X0[PCI-EXPRESS] SATA-RAID support" | 546 | tristate "ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID Host Adapter" |
547 | depends on PCI && SCSI | 547 | depends on PCI && SCSI |
548 | help | 548 | help |
549 | This driver supports all of ARECA's SATA RAID controller cards. | 549 | This driver supports all of ARECA's SATA/SAS RAID controller cards. |
550 | This is an ARECA-maintained driver by Erich Chen. | 550 | This is an ARECA-maintained driver by Erich Chen. |
551 | If you have any problems, please mail to: < erich@areca.com.tw > | 551 | If you have any problems, please mail to: <erich@areca.com.tw>. |
552 | Areca supports Linux RAID config tools. | 552 | Areca supports Linux RAID config tools. |
553 | 553 | Please link <http://www.areca.com.tw> | |
554 | < http://www.areca.com.tw > | ||
555 | 554 | ||
556 | To compile this driver as a module, choose M here: the | 555 | To compile this driver as a module, choose M here: the |
557 | module will be called arcmsr (modprobe arcmsr). | 556 | module will be called arcmsr (modprobe arcmsr). |
558 | 557 | ||
558 | config SCSI_ARCMSR_AER | ||
559 | bool "Enable PCI Error Recovery Capability in Areca Driver(ARCMSR)" | ||
560 | depends on SCSI_ARCMSR && PCIEAER | ||
561 | default n | ||
562 | help | ||
563 | The advanced error reporting(AER) capability is "NOT" provided by | ||
564 | ARC1200/1201/1202 SATA RAID controllers cards. | ||
565 | If your card is one of ARC1200/1201/1202, please use the default setting, n. | ||
566 | If your card is other models, you could pick it | ||
567 | on condition that the kernel version is greater than 2.6.19. | ||
568 | This function is maintained driver by Nick Cheng. If you have any | ||
569 | problems or suggestion, you are welcome to contact with <nick.cheng@areca.com.tw>. | ||
570 | To enable this function, choose Y here. | ||
571 | |||
559 | source "drivers/scsi/megaraid/Kconfig.megaraid" | 572 | source "drivers/scsi/megaraid/Kconfig.megaraid" |
560 | 573 | ||
561 | config SCSI_HPTIOP | 574 | config SCSI_HPTIOP |
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index f0b8bf4534f0..ace7a15b413e 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h | |||
@@ -9,7 +9,7 @@ | |||
9 | ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved. | 9 | ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved. |
10 | ** | 10 | ** |
11 | ** Web site: www.areca.com.tw | 11 | ** Web site: www.areca.com.tw |
12 | ** E-mail: erich@areca.com.tw | 12 | ** E-mail: support@areca.com.tw |
13 | ** | 13 | ** |
14 | ** This program is free software; you can redistribute it and/or modify | 14 | ** This program is free software; you can redistribute it and/or modify |
15 | ** it under the terms of the GNU General Public License version 2 as | 15 | ** it under the terms of the GNU General Public License version 2 as |
@@ -45,19 +45,26 @@ | |||
45 | #include <linux/interrupt.h> | 45 | #include <linux/interrupt.h> |
46 | 46 | ||
47 | struct class_device_attribute; | 47 | struct class_device_attribute; |
48 | 48 | /*The limit of outstanding scsi command that firmware can handle*/ | |
49 | #define ARCMSR_MAX_OUTSTANDING_CMD 256 | 49 | #define ARCMSR_MAX_OUTSTANDING_CMD 256 |
50 | #define ARCMSR_MAX_FREECCB_NUM 288 | 50 | #define ARCMSR_MAX_FREECCB_NUM 320 |
51 | #define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.14" | 51 | #define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2007/08/30" |
52 | #define ARCMSR_SCSI_INITIATOR_ID 255 | 52 | #define ARCMSR_SCSI_INITIATOR_ID 255 |
53 | #define ARCMSR_MAX_XFER_SECTORS 512 | 53 | #define ARCMSR_MAX_XFER_SECTORS 512 |
54 | #define ARCMSR_MAX_XFER_SECTORS_B 4096 | 54 | #define ARCMSR_MAX_XFER_SECTORS_B 4096 |
55 | #define ARCMSR_MAX_TARGETID 17 | 55 | #define ARCMSR_MAX_TARGETID 17 |
56 | #define ARCMSR_MAX_TARGETLUN 8 | 56 | #define ARCMSR_MAX_TARGETLUN 8 |
57 | #define ARCMSR_MAX_CMD_PERLUN ARCMSR_MAX_OUTSTANDING_CMD | 57 | #define ARCMSR_MAX_CMD_PERLUN ARCMSR_MAX_OUTSTANDING_CMD |
58 | #define ARCMSR_MAX_QBUFFER 4096 | 58 | #define ARCMSR_MAX_QBUFFER 4096 |
59 | #define ARCMSR_MAX_SG_ENTRIES 38 | 59 | #define ARCMSR_MAX_SG_ENTRIES 38 |
60 | 60 | #define ARCMSR_MAX_HBB_POSTQUEUE 264 | |
61 | /* | ||
62 | ********************************************************************************** | ||
63 | ** | ||
64 | ********************************************************************************** | ||
65 | */ | ||
66 | #define ARC_SUCCESS 0 | ||
67 | #define ARC_FAILURE 1 | ||
61 | /* | 68 | /* |
62 | ******************************************************************************* | 69 | ******************************************************************************* |
63 | ** split 64bits dma addressing | 70 | ** split 64bits dma addressing |
@@ -90,7 +97,7 @@ struct CMD_MESSAGE_FIELD | |||
90 | uint8_t messagedatabuffer[1032]; | 97 | uint8_t messagedatabuffer[1032]; |
91 | }; | 98 | }; |
92 | /* IOP message transfer */ | 99 | /* IOP message transfer */ |
93 | #define ARCMSR_MESSAGE_FAIL 0x0001 | 100 | #define ARCMSR_MESSAGE_FAIL 0x0001 |
94 | /* DeviceType */ | 101 | /* DeviceType */ |
95 | #define ARECA_SATA_RAID 0x90000000 | 102 | #define ARECA_SATA_RAID 0x90000000 |
96 | /* FunctionCode */ | 103 | /* FunctionCode */ |
@@ -163,27 +170,27 @@ struct QBUFFER | |||
163 | }; | 170 | }; |
164 | /* | 171 | /* |
165 | ******************************************************************************* | 172 | ******************************************************************************* |
166 | ** FIRMWARE INFO | 173 | ** FIRMWARE INFO for Intel IOP R 80331 processor (Type A) |
167 | ******************************************************************************* | 174 | ******************************************************************************* |
168 | */ | 175 | */ |
169 | struct FIRMWARE_INFO | 176 | struct FIRMWARE_INFO |
170 | { | 177 | { |
171 | uint32_t signature; /*0, 00-03*/ | 178 | uint32_t signature; /*0, 00-03*/ |
172 | uint32_t request_len; /*1, 04-07*/ | 179 | uint32_t request_len; /*1, 04-07*/ |
173 | uint32_t numbers_queue; /*2, 08-11*/ | 180 | uint32_t numbers_queue; /*2, 08-11*/ |
174 | uint32_t sdram_size; /*3, 12-15*/ | 181 | uint32_t sdram_size; /*3, 12-15*/ |
175 | uint32_t ide_channels; /*4, 16-19*/ | 182 | uint32_t ide_channels; /*4, 16-19*/ |
176 | char vendor[40]; /*5, 20-59*/ | 183 | char vendor[40]; /*5, 20-59*/ |
177 | char model[8]; /*15, 60-67*/ | 184 | char model[8]; /*15, 60-67*/ |
178 | char firmware_ver[16]; /*17, 68-83*/ | 185 | char firmware_ver[16]; /*17, 68-83*/ |
179 | char device_map[16]; /*21, 84-99*/ | 186 | char device_map[16]; /*21, 84-99*/ |
180 | }; | 187 | }; |
181 | /* signature of set and get firmware config */ | 188 | /* signature of set and get firmware config */ |
182 | #define ARCMSR_SIGNATURE_GET_CONFIG 0x87974060 | 189 | #define ARCMSR_SIGNATURE_GET_CONFIG 0x87974060 |
183 | #define ARCMSR_SIGNATURE_SET_CONFIG 0x87974063 | 190 | #define ARCMSR_SIGNATURE_SET_CONFIG 0x87974063 |
184 | /* message code of inbound message register */ | 191 | /* message code of inbound message register */ |
185 | #define ARCMSR_INBOUND_MESG0_NOP 0x00000000 | 192 | #define ARCMSR_INBOUND_MESG0_NOP 0x00000000 |
186 | #define ARCMSR_INBOUND_MESG0_GET_CONFIG 0x00000001 | 193 | #define ARCMSR_INBOUND_MESG0_GET_CONFIG 0x00000001 |
187 | #define ARCMSR_INBOUND_MESG0_SET_CONFIG 0x00000002 | 194 | #define ARCMSR_INBOUND_MESG0_SET_CONFIG 0x00000002 |
188 | #define ARCMSR_INBOUND_MESG0_ABORT_CMD 0x00000003 | 195 | #define ARCMSR_INBOUND_MESG0_ABORT_CMD 0x00000003 |
189 | #define ARCMSR_INBOUND_MESG0_STOP_BGRB 0x00000004 | 196 | #define ARCMSR_INBOUND_MESG0_STOP_BGRB 0x00000004 |
@@ -203,6 +210,60 @@ struct FIRMWARE_INFO | |||
203 | #define ARCMSR_CCBREPLY_FLAG_ERROR 0x10000000 | 210 | #define ARCMSR_CCBREPLY_FLAG_ERROR 0x10000000 |
204 | /* outbound firmware ok */ | 211 | /* outbound firmware ok */ |
205 | #define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK 0x80000000 | 212 | #define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK 0x80000000 |
213 | |||
214 | /* | ||
215 | ************************************************************************ | ||
216 | ** SPEC. for Areca Type B adapter | ||
217 | ************************************************************************ | ||
218 | */ | ||
219 | /* ARECA HBB COMMAND for its FIRMWARE */ | ||
220 | /* window of "instruction flags" from driver to iop */ | ||
221 | #define ARCMSR_DRV2IOP_DOORBELL 0x00020400 | ||
222 | #define ARCMSR_DRV2IOP_DOORBELL_MASK 0x00020404 | ||
223 | /* window of "instruction flags" from iop to driver */ | ||
224 | #define ARCMSR_IOP2DRV_DOORBELL 0x00020408 | ||
225 | #define ARCMSR_IOP2DRV_DOORBELL_MASK 0x0002040C | ||
226 | /* ARECA FLAG LANGUAGE */ | ||
227 | /* ioctl transfer */ | ||
228 | #define ARCMSR_IOP2DRV_DATA_WRITE_OK 0x00000001 | ||
229 | /* ioctl transfer */ | ||
230 | #define ARCMSR_IOP2DRV_DATA_READ_OK 0x00000002 | ||
231 | #define ARCMSR_IOP2DRV_CDB_DONE 0x00000004 | ||
232 | #define ARCMSR_IOP2DRV_MESSAGE_CMD_DONE 0x00000008 | ||
233 | |||
234 | #define ARCMSR_DOORBELL_HANDLE_INT 0x0000000F | ||
235 | #define ARCMSR_DOORBELL_INT_CLEAR_PATTERN 0xFF00FFF0 | ||
236 | #define ARCMSR_MESSAGE_INT_CLEAR_PATTERN 0xFF00FFF7 | ||
237 | /* (ARCMSR_INBOUND_MESG0_GET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ | ||
238 | #define ARCMSR_MESSAGE_GET_CONFIG 0x00010008 | ||
239 | /* (ARCMSR_INBOUND_MESG0_SET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ | ||
240 | #define ARCMSR_MESSAGE_SET_CONFIG 0x00020008 | ||
241 | /* (ARCMSR_INBOUND_MESG0_ABORT_CMD<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ | ||
242 | #define ARCMSR_MESSAGE_ABORT_CMD 0x00030008 | ||
243 | /* (ARCMSR_INBOUND_MESG0_STOP_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ | ||
244 | #define ARCMSR_MESSAGE_STOP_BGRB 0x00040008 | ||
245 | /* (ARCMSR_INBOUND_MESG0_FLUSH_CACHE<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ | ||
246 | #define ARCMSR_MESSAGE_FLUSH_CACHE 0x00050008 | ||
247 | /* (ARCMSR_INBOUND_MESG0_START_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ | ||
248 | #define ARCMSR_MESSAGE_START_BGRB 0x00060008 | ||
249 | #define ARCMSR_MESSAGE_START_DRIVER_MODE 0x000E0008 | ||
250 | #define ARCMSR_MESSAGE_SET_POST_WINDOW 0x000F0008 | ||
251 | /* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */ | ||
252 | #define ARCMSR_MESSAGE_FIRMWARE_OK 0x80000000 | ||
253 | /* ioctl transfer */ | ||
254 | #define ARCMSR_DRV2IOP_DATA_WRITE_OK 0x00000001 | ||
255 | /* ioctl transfer */ | ||
256 | #define ARCMSR_DRV2IOP_DATA_READ_OK 0x00000002 | ||
257 | #define ARCMSR_DRV2IOP_CDB_POSTED 0x00000004 | ||
258 | #define ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED 0x00000008 | ||
259 | |||
260 | /* data tunnel buffer between user space program and its firmware */ | ||
261 | /* user space data to iop 128bytes */ | ||
262 | #define ARCMSR_IOCTL_WBUFFER 0x0000fe00 | ||
263 | /* iop data to user space 128bytes */ | ||
264 | #define ARCMSR_IOCTL_RBUFFER 0x0000ff00 | ||
265 | /* iop message_rwbuffer for message command */ | ||
266 | #define ARCMSR_MSGCODE_RWBUFFER 0x0000fa00 | ||
206 | /* | 267 | /* |
207 | ******************************************************************************* | 268 | ******************************************************************************* |
208 | ** ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504) | 269 | ** ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504) |
@@ -214,7 +275,6 @@ struct ARCMSR_CDB | |||
214 | uint8_t TargetID; | 275 | uint8_t TargetID; |
215 | uint8_t LUN; | 276 | uint8_t LUN; |
216 | uint8_t Function; | 277 | uint8_t Function; |
217 | |||
218 | uint8_t CdbLength; | 278 | uint8_t CdbLength; |
219 | uint8_t sgcount; | 279 | uint8_t sgcount; |
220 | uint8_t Flags; | 280 | uint8_t Flags; |
@@ -224,20 +284,18 @@ struct ARCMSR_CDB | |||
224 | #define ARCMSR_CDB_FLAG_SIMPLEQ 0x00 | 284 | #define ARCMSR_CDB_FLAG_SIMPLEQ 0x00 |
225 | #define ARCMSR_CDB_FLAG_HEADQ 0x08 | 285 | #define ARCMSR_CDB_FLAG_HEADQ 0x08 |
226 | #define ARCMSR_CDB_FLAG_ORDEREDQ 0x10 | 286 | #define ARCMSR_CDB_FLAG_ORDEREDQ 0x10 |
227 | uint8_t Reserved1; | ||
228 | 287 | ||
288 | uint8_t Reserved1; | ||
229 | uint32_t Context; | 289 | uint32_t Context; |
230 | uint32_t DataLength; | 290 | uint32_t DataLength; |
231 | |||
232 | uint8_t Cdb[16]; | 291 | uint8_t Cdb[16]; |
233 | |||
234 | uint8_t DeviceStatus; | 292 | uint8_t DeviceStatus; |
235 | #define ARCMSR_DEV_CHECK_CONDITION 0x02 | 293 | #define ARCMSR_DEV_CHECK_CONDITION 0x02 |
236 | #define ARCMSR_DEV_SELECT_TIMEOUT 0xF0 | 294 | #define ARCMSR_DEV_SELECT_TIMEOUT 0xF0 |
237 | #define ARCMSR_DEV_ABORTED 0xF1 | 295 | #define ARCMSR_DEV_ABORTED 0xF1 |
238 | #define ARCMSR_DEV_INIT_FAIL 0xF2 | 296 | #define ARCMSR_DEV_INIT_FAIL 0xF2 |
239 | uint8_t SenseData[15]; | ||
240 | 297 | ||
298 | uint8_t SenseData[15]; | ||
241 | union | 299 | union |
242 | { | 300 | { |
243 | struct SG32ENTRY sg32entry[ARCMSR_MAX_SG_ENTRIES]; | 301 | struct SG32ENTRY sg32entry[ARCMSR_MAX_SG_ENTRIES]; |
@@ -246,10 +304,10 @@ struct ARCMSR_CDB | |||
246 | }; | 304 | }; |
247 | /* | 305 | /* |
248 | ******************************************************************************* | 306 | ******************************************************************************* |
249 | ** Messaging Unit (MU) of the Intel R 80331 I/O processor (80331) | 307 | ** Messaging Unit (MU) of the Intel R 80331 I/O processor(Type A) and Type B processor |
250 | ******************************************************************************* | 308 | ******************************************************************************* |
251 | */ | 309 | */ |
252 | struct MessageUnit | 310 | struct MessageUnit_A |
253 | { | 311 | { |
254 | uint32_t resrved0[4]; /*0000 000F*/ | 312 | uint32_t resrved0[4]; /*0000 000F*/ |
255 | uint32_t inbound_msgaddr0; /*0010 0013*/ | 313 | uint32_t inbound_msgaddr0; /*0010 0013*/ |
@@ -274,6 +332,30 @@ struct MessageUnit | |||
274 | uint32_t message_rbuffer[32]; /*0F00 0F7F 32*/ | 332 | uint32_t message_rbuffer[32]; /*0F00 0F7F 32*/ |
275 | uint32_t reserved6[32]; /*0F80 0FFF 32*/ | 333 | uint32_t reserved6[32]; /*0F80 0FFF 32*/ |
276 | }; | 334 | }; |
335 | |||
336 | struct MessageUnit_B | ||
337 | { | ||
338 | uint32_t post_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; | ||
339 | uint32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; | ||
340 | uint32_t postq_index; | ||
341 | uint32_t doneq_index; | ||
342 | uint32_t *drv2iop_doorbell_reg; | ||
343 | uint32_t *drv2iop_doorbell_mask_reg; | ||
344 | uint32_t *iop2drv_doorbell_reg; | ||
345 | uint32_t *iop2drv_doorbell_mask_reg; | ||
346 | uint32_t *msgcode_rwbuffer_reg; | ||
347 | uint32_t *ioctl_wbuffer_reg; | ||
348 | uint32_t *ioctl_rbuffer_reg; | ||
349 | }; | ||
350 | |||
351 | struct MessageUnit | ||
352 | { | ||
353 | union | ||
354 | { | ||
355 | struct MessageUnit_A pmu_A; | ||
356 | struct MessageUnit_B pmu_B; | ||
357 | } u; | ||
358 | }; | ||
277 | /* | 359 | /* |
278 | ******************************************************************************* | 360 | ******************************************************************************* |
279 | ** Adapter Control Block | 361 | ** Adapter Control Block |
@@ -281,37 +363,45 @@ struct MessageUnit | |||
281 | */ | 363 | */ |
282 | struct AdapterControlBlock | 364 | struct AdapterControlBlock |
283 | { | 365 | { |
366 | uint32_t adapter_type; /* adapter A,B..... */ | ||
367 | #define ACB_ADAPTER_TYPE_A 0x00000001 /* hba I IOP */ | ||
368 | #define ACB_ADAPTER_TYPE_B 0x00000002 /* hbb M IOP */ | ||
369 | #define ACB_ADAPTER_TYPE_C 0x00000004 /* hbc P IOP */ | ||
370 | #define ACB_ADAPTER_TYPE_D 0x00000008 /* hbd A IOP */ | ||
284 | struct pci_dev * pdev; | 371 | struct pci_dev * pdev; |
285 | struct Scsi_Host * host; | 372 | struct Scsi_Host * host; |
286 | unsigned long vir2phy_offset; | 373 | unsigned long vir2phy_offset; |
287 | /* Offset is used in making arc cdb physical to virtual calculations */ | 374 | /* Offset is used in making arc cdb physical to virtual calculations */ |
288 | uint32_t outbound_int_enable; | 375 | uint32_t outbound_int_enable; |
289 | 376 | ||
290 | struct MessageUnit __iomem * pmu; | 377 | struct MessageUnit * pmu; |
291 | /* message unit ATU inbound base address0 */ | 378 | /* message unit ATU inbound base address0 */ |
292 | 379 | ||
293 | uint32_t acb_flags; | 380 | uint32_t acb_flags; |
294 | #define ACB_F_SCSISTOPADAPTER 0x0001 | 381 | #define ACB_F_SCSISTOPADAPTER 0x0001 |
295 | #define ACB_F_MSG_STOP_BGRB 0x0002 | 382 | #define ACB_F_MSG_STOP_BGRB 0x0002 |
296 | /* stop RAID background rebuild */ | 383 | /* stop RAID background rebuild */ |
297 | #define ACB_F_MSG_START_BGRB 0x0004 | 384 | #define ACB_F_MSG_START_BGRB 0x0004 |
298 | /* stop RAID background rebuild */ | 385 | /* stop RAID background rebuild */ |
299 | #define ACB_F_IOPDATA_OVERFLOW 0x0008 | 386 | #define ACB_F_IOPDATA_OVERFLOW 0x0008 |
300 | /* iop message data rqbuffer overflow */ | 387 | /* iop message data rqbuffer overflow */ |
301 | #define ACB_F_MESSAGE_WQBUFFER_CLEARED 0x0010 | 388 | #define ACB_F_MESSAGE_WQBUFFER_CLEARED 0x0010 |
302 | /* message clear wqbuffer */ | 389 | /* message clear wqbuffer */ |
303 | #define ACB_F_MESSAGE_RQBUFFER_CLEARED 0x0020 | 390 | #define ACB_F_MESSAGE_RQBUFFER_CLEARED 0x0020 |
304 | /* message clear rqbuffer */ | 391 | /* message clear rqbuffer */ |
305 | #define ACB_F_MESSAGE_WQBUFFER_READED 0x0040 | 392 | #define ACB_F_MESSAGE_WQBUFFER_READED 0x0040 |
306 | #define ACB_F_BUS_RESET 0x0080 | 393 | #define ACB_F_BUS_RESET 0x0080 |
307 | #define ACB_F_IOP_INITED 0x0100 | 394 | #define ACB_F_IOP_INITED 0x0100 |
308 | /* iop init */ | 395 | /* iop init */ |
309 | 396 | ||
310 | struct CommandControlBlock * pccb_pool[ARCMSR_MAX_FREECCB_NUM]; | 397 | struct CommandControlBlock * pccb_pool[ARCMSR_MAX_FREECCB_NUM]; |
311 | /* used for memory free */ | 398 | /* used for memory free */ |
312 | struct list_head ccb_free_list; | 399 | struct list_head ccb_free_list; |
313 | /* head of free ccb list */ | 400 | /* head of free ccb list */ |
401 | |||
314 | atomic_t ccboutstandingcount; | 402 | atomic_t ccboutstandingcount; |
403 | /*The present outstanding command number that in the IOP that | ||
404 | waiting for being handled by FW*/ | ||
315 | 405 | ||
316 | void * dma_coherent; | 406 | void * dma_coherent; |
317 | /* dma_coherent used for memory free */ | 407 | /* dma_coherent used for memory free */ |
@@ -353,7 +443,7 @@ struct CommandControlBlock | |||
353 | { | 443 | { |
354 | struct ARCMSR_CDB arcmsr_cdb; | 444 | struct ARCMSR_CDB arcmsr_cdb; |
355 | /* | 445 | /* |
356 | ** 0-503 (size of CDB=504): | 446 | ** 0-503 (size of CDB = 504): |
357 | ** arcmsr messenger scsi command descriptor size 504 bytes | 447 | ** arcmsr messenger scsi command descriptor size 504 bytes |
358 | */ | 448 | */ |
359 | uint32_t cdb_shifted_phyaddr; | 449 | uint32_t cdb_shifted_phyaddr; |
@@ -466,7 +556,9 @@ struct SENSE_DATA | |||
466 | #define ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE 0x01 | 556 | #define ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE 0x01 |
467 | #define ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE 0x1F | 557 | #define ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE 0x1F |
468 | 558 | ||
469 | extern void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb); | 559 | extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *); |
560 | extern void arcmsr_iop_message_read(struct AdapterControlBlock *); | ||
561 | extern struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *); | ||
470 | extern struct class_device_attribute *arcmsr_host_attrs[]; | 562 | extern struct class_device_attribute *arcmsr_host_attrs[]; |
471 | extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb); | 563 | extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *); |
472 | void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb); | 564 | void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb); |
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index 06c0dce3b839..0f0a1ae99434 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c | |||
@@ -8,7 +8,7 @@ | |||
8 | ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved | 8 | ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved |
9 | ** | 9 | ** |
10 | ** Web site: www.areca.com.tw | 10 | ** Web site: www.areca.com.tw |
11 | ** E-mail: erich@areca.com.tw | 11 | ** E-mail: support@areca.com.tw |
12 | ** | 12 | ** |
13 | ** This program is free software; you can redistribute it and/or modify | 13 | ** This program is free software; you can redistribute it and/or modify |
14 | ** it under the terms of the GNU General Public License version 2 as | 14 | ** it under the terms of the GNU General Public License version 2 as |
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/init.h> | 49 | #include <linux/init.h> |
50 | #include <linux/errno.h> | 50 | #include <linux/errno.h> |
51 | #include <linux/delay.h> | 51 | #include <linux/delay.h> |
52 | #include <linux/pci.h> | ||
52 | 53 | ||
53 | #include <scsi/scsi_cmnd.h> | 54 | #include <scsi/scsi_cmnd.h> |
54 | #include <scsi/scsi_device.h> | 55 | #include <scsi/scsi_device.h> |
@@ -58,15 +59,11 @@ | |||
58 | 59 | ||
59 | struct class_device_attribute *arcmsr_host_attrs[]; | 60 | struct class_device_attribute *arcmsr_host_attrs[]; |
60 | 61 | ||
61 | static ssize_t | 62 | static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off, size_t count) |
62 | arcmsr_sysfs_iop_message_read(struct kobject *kobj, | ||
63 | struct bin_attribute *bin_attr, | ||
64 | char *buf, loff_t off, size_t count) | ||
65 | { | 63 | { |
66 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); | 64 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); |
67 | struct Scsi_Host *host = class_to_shost(cdev); | 65 | struct Scsi_Host *host = class_to_shost(cdev); |
68 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | 66 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; |
69 | struct MessageUnit __iomem *reg = acb->pmu; | ||
70 | uint8_t *pQbuffer,*ptmpQbuffer; | 67 | uint8_t *pQbuffer,*ptmpQbuffer; |
71 | int32_t allxfer_len = 0; | 68 | int32_t allxfer_len = 0; |
72 | 69 | ||
@@ -85,12 +82,13 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj, | |||
85 | allxfer_len++; | 82 | allxfer_len++; |
86 | } | 83 | } |
87 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | 84 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { |
88 | struct QBUFFER __iomem * prbuffer = (struct QBUFFER __iomem *) | 85 | struct QBUFFER *prbuffer; |
89 | ®->message_rbuffer; | 86 | uint8_t *iop_data; |
90 | uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data; | ||
91 | int32_t iop_len; | 87 | int32_t iop_len; |
92 | 88 | ||
93 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | 89 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; |
90 | prbuffer = arcmsr_get_iop_rqbuffer(acb); | ||
91 | iop_data = (uint8_t *)prbuffer->data; | ||
94 | iop_len = readl(&prbuffer->data_len); | 92 | iop_len = readl(&prbuffer->data_len); |
95 | while (iop_len > 0) { | 93 | while (iop_len > 0) { |
96 | acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); | 94 | acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); |
@@ -99,16 +97,12 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj, | |||
99 | iop_data++; | 97 | iop_data++; |
100 | iop_len--; | 98 | iop_len--; |
101 | } | 99 | } |
102 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, | 100 | arcmsr_iop_message_read(acb); |
103 | ®->inbound_doorbell); | ||
104 | } | 101 | } |
105 | return (allxfer_len); | 102 | return (allxfer_len); |
106 | } | 103 | } |
107 | 104 | ||
108 | static ssize_t | 105 | static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off, size_t count) |
109 | arcmsr_sysfs_iop_message_write(struct kobject *kobj, | ||
110 | struct bin_attribute *bin_attr, | ||
111 | char *buf, loff_t off, size_t count) | ||
112 | { | 106 | { |
113 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); | 107 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); |
114 | struct Scsi_Host *host = class_to_shost(cdev); | 108 | struct Scsi_Host *host = class_to_shost(cdev); |
@@ -126,7 +120,7 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, | |||
126 | wqbuf_lastindex = acb->wqbuf_lastindex; | 120 | wqbuf_lastindex = acb->wqbuf_lastindex; |
127 | wqbuf_firstindex = acb->wqbuf_firstindex; | 121 | wqbuf_firstindex = acb->wqbuf_firstindex; |
128 | if (wqbuf_lastindex != wqbuf_firstindex) { | 122 | if (wqbuf_lastindex != wqbuf_firstindex) { |
129 | arcmsr_post_Qbuffer(acb); | 123 | arcmsr_post_ioctldata2iop(acb); |
130 | return 0; /*need retry*/ | 124 | return 0; /*need retry*/ |
131 | } else { | 125 | } else { |
132 | my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) | 126 | my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) |
@@ -144,7 +138,7 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, | |||
144 | if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { | 138 | if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { |
145 | acb->acb_flags &= | 139 | acb->acb_flags &= |
146 | ~ACB_F_MESSAGE_WQBUFFER_CLEARED; | 140 | ~ACB_F_MESSAGE_WQBUFFER_CLEARED; |
147 | arcmsr_post_Qbuffer(acb); | 141 | arcmsr_post_ioctldata2iop(acb); |
148 | } | 142 | } |
149 | return count; | 143 | return count; |
150 | } else { | 144 | } else { |
@@ -153,15 +147,11 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, | |||
153 | } | 147 | } |
154 | } | 148 | } |
155 | 149 | ||
156 | static ssize_t | 150 | static ssize_t arcmsr_sysfs_iop_message_clear(struct kobject *kobj, char *buf, loff_t off, size_t count) |
157 | arcmsr_sysfs_iop_message_clear(struct kobject *kobj, | ||
158 | struct bin_attribute *bin_attr, | ||
159 | char *buf, loff_t off, size_t count) | ||
160 | { | 151 | { |
161 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); | 152 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); |
162 | struct Scsi_Host *host = class_to_shost(cdev); | 153 | struct Scsi_Host *host = class_to_shost(cdev); |
163 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | 154 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; |
164 | struct MessageUnit __iomem *reg = acb->pmu; | ||
165 | uint8_t *pQbuffer; | 155 | uint8_t *pQbuffer; |
166 | 156 | ||
167 | if (!capable(CAP_SYS_ADMIN)) | 157 | if (!capable(CAP_SYS_ADMIN)) |
@@ -169,8 +159,7 @@ arcmsr_sysfs_iop_message_clear(struct kobject *kobj, | |||
169 | 159 | ||
170 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | 160 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { |
171 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | 161 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; |
172 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK | 162 | arcmsr_iop_message_read(acb); |
173 | , ®->inbound_doorbell); | ||
174 | } | 163 | } |
175 | acb->acb_flags |= | 164 | acb->acb_flags |= |
176 | (ACB_F_MESSAGE_WQBUFFER_CLEARED | 165 | (ACB_F_MESSAGE_WQBUFFER_CLEARED |
@@ -191,6 +180,7 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = { | |||
191 | .attr = { | 180 | .attr = { |
192 | .name = "mu_read", | 181 | .name = "mu_read", |
193 | .mode = S_IRUSR , | 182 | .mode = S_IRUSR , |
183 | .owner = THIS_MODULE, | ||
194 | }, | 184 | }, |
195 | .size = 1032, | 185 | .size = 1032, |
196 | .read = arcmsr_sysfs_iop_message_read, | 186 | .read = arcmsr_sysfs_iop_message_read, |
@@ -200,6 +190,7 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = { | |||
200 | .attr = { | 190 | .attr = { |
201 | .name = "mu_write", | 191 | .name = "mu_write", |
202 | .mode = S_IWUSR, | 192 | .mode = S_IWUSR, |
193 | .owner = THIS_MODULE, | ||
203 | }, | 194 | }, |
204 | .size = 1032, | 195 | .size = 1032, |
205 | .write = arcmsr_sysfs_iop_message_write, | 196 | .write = arcmsr_sysfs_iop_message_write, |
@@ -209,6 +200,7 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = { | |||
209 | .attr = { | 200 | .attr = { |
210 | .name = "mu_clear", | 201 | .name = "mu_clear", |
211 | .mode = S_IWUSR, | 202 | .mode = S_IWUSR, |
203 | .owner = THIS_MODULE, | ||
212 | }, | 204 | }, |
213 | .size = 1, | 205 | .size = 1, |
214 | .write = arcmsr_sysfs_iop_message_clear, | 206 | .write = arcmsr_sysfs_iop_message_clear, |
@@ -219,31 +211,26 @@ int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb) | |||
219 | struct Scsi_Host *host = acb->host; | 211 | struct Scsi_Host *host = acb->host; |
220 | int error; | 212 | int error; |
221 | 213 | ||
222 | error = sysfs_create_bin_file(&host->shost_classdev.kobj, | 214 | error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr); |
223 | &arcmsr_sysfs_message_read_attr); | ||
224 | if (error) { | 215 | if (error) { |
225 | printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n"); | 216 | printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n"); |
226 | goto error_bin_file_message_read; | 217 | goto error_bin_file_message_read; |
227 | } | 218 | } |
228 | error = sysfs_create_bin_file(&host->shost_classdev.kobj, | 219 | error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr); |
229 | &arcmsr_sysfs_message_write_attr); | ||
230 | if (error) { | 220 | if (error) { |
231 | printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n"); | 221 | printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n"); |
232 | goto error_bin_file_message_write; | 222 | goto error_bin_file_message_write; |
233 | } | 223 | } |
234 | error = sysfs_create_bin_file(&host->shost_classdev.kobj, | 224 | error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr); |
235 | &arcmsr_sysfs_message_clear_attr); | ||
236 | if (error) { | 225 | if (error) { |
237 | printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n"); | 226 | printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n"); |
238 | goto error_bin_file_message_clear; | 227 | goto error_bin_file_message_clear; |
239 | } | 228 | } |
240 | return 0; | 229 | return 0; |
241 | error_bin_file_message_clear: | 230 | error_bin_file_message_clear: |
242 | sysfs_remove_bin_file(&host->shost_classdev.kobj, | 231 | sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr); |
243 | &arcmsr_sysfs_message_write_attr); | ||
244 | error_bin_file_message_write: | 232 | error_bin_file_message_write: |
245 | sysfs_remove_bin_file(&host->shost_classdev.kobj, | 233 | sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr); |
246 | &arcmsr_sysfs_message_read_attr); | ||
247 | error_bin_file_message_read: | 234 | error_bin_file_message_read: |
248 | return error; | 235 | return error; |
249 | } | 236 | } |
@@ -252,12 +239,9 @@ void | |||
252 | arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) { | 239 | arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) { |
253 | struct Scsi_Host *host = acb->host; | 240 | struct Scsi_Host *host = acb->host; |
254 | 241 | ||
255 | sysfs_remove_bin_file(&host->shost_classdev.kobj, | 242 | sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr); |
256 | &arcmsr_sysfs_message_clear_attr); | 243 | sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr); |
257 | sysfs_remove_bin_file(&host->shost_classdev.kobj, | 244 | sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr); |
258 | &arcmsr_sysfs_message_write_attr); | ||
259 | sysfs_remove_bin_file(&host->shost_classdev.kobj, | ||
260 | &arcmsr_sysfs_message_read_attr); | ||
261 | } | 245 | } |
262 | 246 | ||
263 | 247 | ||
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 0ddfc21e9f7d..d70398ac64db 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c | |||
@@ -9,7 +9,7 @@ | |||
9 | ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved | 9 | ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved |
10 | ** | 10 | ** |
11 | ** Web site: www.areca.com.tw | 11 | ** Web site: www.areca.com.tw |
12 | ** E-mail: erich@areca.com.tw | 12 | ** E-mail: support@areca.com.tw |
13 | ** | 13 | ** |
14 | ** This program is free software; you can redistribute it and/or modify | 14 | ** This program is free software; you can redistribute it and/or modify |
15 | ** it under the terms of the GNU General Public License version 2 as | 15 | ** it under the terms of the GNU General Public License version 2 as |
@@ -71,33 +71,37 @@ | |||
71 | #include <scsi/scsicam.h> | 71 | #include <scsi/scsicam.h> |
72 | #include "arcmsr.h" | 72 | #include "arcmsr.h" |
73 | 73 | ||
74 | MODULE_AUTHOR("Erich Chen <erich@areca.com.tw>"); | 74 | MODULE_AUTHOR("Erich Chen <support@areca.com.tw>"); |
75 | MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID HOST Adapter"); | 75 | MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID HOST Adapter"); |
76 | MODULE_LICENSE("Dual BSD/GPL"); | 76 | MODULE_LICENSE("Dual BSD/GPL"); |
77 | MODULE_VERSION(ARCMSR_DRIVER_VERSION); | 77 | MODULE_VERSION(ARCMSR_DRIVER_VERSION); |
78 | 78 | ||
79 | static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_cmnd *cmd); | 79 | static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, |
80 | struct scsi_cmnd *cmd); | ||
81 | static int arcmsr_iop_confirm(struct AdapterControlBlock *acb); | ||
80 | static int arcmsr_abort(struct scsi_cmnd *); | 82 | static int arcmsr_abort(struct scsi_cmnd *); |
81 | static int arcmsr_bus_reset(struct scsi_cmnd *); | 83 | static int arcmsr_bus_reset(struct scsi_cmnd *); |
82 | static int arcmsr_bios_param(struct scsi_device *sdev, | 84 | static int arcmsr_bios_param(struct scsi_device *sdev, |
83 | struct block_device *bdev, sector_t capacity, int *info); | 85 | struct block_device *bdev, sector_t capacity, int *info); |
84 | static int arcmsr_queue_command(struct scsi_cmnd * cmd, | 86 | static int arcmsr_queue_command(struct scsi_cmnd *cmd, |
85 | void (*done) (struct scsi_cmnd *)); | 87 | void (*done) (struct scsi_cmnd *)); |
86 | static int arcmsr_probe(struct pci_dev *pdev, | 88 | static int arcmsr_probe(struct pci_dev *pdev, |
87 | const struct pci_device_id *id); | 89 | const struct pci_device_id *id); |
88 | static void arcmsr_remove(struct pci_dev *pdev); | 90 | static void arcmsr_remove(struct pci_dev *pdev); |
89 | static void arcmsr_shutdown(struct pci_dev *pdev); | 91 | static void arcmsr_shutdown(struct pci_dev *pdev); |
90 | static void arcmsr_iop_init(struct AdapterControlBlock *acb); | 92 | static void arcmsr_iop_init(struct AdapterControlBlock *acb); |
91 | static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb); | 93 | static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb); |
94 | static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); | ||
92 | static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); | 95 | static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); |
93 | static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); | 96 | static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb); |
94 | static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb); | 97 | static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb); |
95 | static const char *arcmsr_info(struct Scsi_Host *); | 98 | static const char *arcmsr_info(struct Scsi_Host *); |
96 | static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); | 99 | static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); |
97 | static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, | 100 | static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, |
98 | pci_channel_state_t state); | 101 | pci_channel_state_t state); |
99 | static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev); | 102 | static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev); |
100 | static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth) | 103 | static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, |
104 | int queue_depth) | ||
101 | { | 105 | { |
102 | if (queue_depth > ARCMSR_MAX_CMD_PERLUN) | 106 | if (queue_depth > ARCMSR_MAX_CMD_PERLUN) |
103 | queue_depth = ARCMSR_MAX_CMD_PERLUN; | 107 | queue_depth = ARCMSR_MAX_CMD_PERLUN; |
@@ -123,17 +127,21 @@ static struct scsi_host_template arcmsr_scsi_host_template = { | |||
123 | .use_clustering = ENABLE_CLUSTERING, | 127 | .use_clustering = ENABLE_CLUSTERING, |
124 | .shost_attrs = arcmsr_host_attrs, | 128 | .shost_attrs = arcmsr_host_attrs, |
125 | }; | 129 | }; |
130 | #ifdef CONFIG_SCSI_ARCMSR_AER | ||
126 | static struct pci_error_handlers arcmsr_pci_error_handlers = { | 131 | static struct pci_error_handlers arcmsr_pci_error_handlers = { |
127 | .error_detected = arcmsr_pci_error_detected, | 132 | .error_detected = arcmsr_pci_error_detected, |
128 | .slot_reset = arcmsr_pci_slot_reset, | 133 | .slot_reset = arcmsr_pci_slot_reset, |
129 | }; | 134 | }; |
130 | 135 | #endif | |
131 | static struct pci_device_id arcmsr_device_id_table[] = { | 136 | static struct pci_device_id arcmsr_device_id_table[] = { |
132 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)}, | 137 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)}, |
133 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1120)}, | 138 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1120)}, |
134 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1130)}, | 139 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1130)}, |
135 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1160)}, | 140 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1160)}, |
136 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1170)}, | 141 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1170)}, |
142 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1200)}, | ||
143 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1201)}, | ||
144 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1202)}, | ||
137 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1210)}, | 145 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1210)}, |
138 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1220)}, | 146 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1220)}, |
139 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1230)}, | 147 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1230)}, |
@@ -153,20 +161,20 @@ static struct pci_driver arcmsr_pci_driver = { | |||
153 | .probe = arcmsr_probe, | 161 | .probe = arcmsr_probe, |
154 | .remove = arcmsr_remove, | 162 | .remove = arcmsr_remove, |
155 | .shutdown = arcmsr_shutdown, | 163 | .shutdown = arcmsr_shutdown, |
164 | #ifdef CONFIG_SCSI_ARCMSR_AER | ||
156 | .err_handler = &arcmsr_pci_error_handlers, | 165 | .err_handler = &arcmsr_pci_error_handlers, |
166 | #endif | ||
157 | }; | 167 | }; |
158 | 168 | ||
159 | static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id) | 169 | static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id) |
160 | { | 170 | { |
161 | irqreturn_t handle_state; | 171 | irqreturn_t handle_state; |
162 | struct AdapterControlBlock *acb; | 172 | struct AdapterControlBlock *acb = dev_id; |
163 | unsigned long flags; | ||
164 | |||
165 | acb = (struct AdapterControlBlock *)dev_id; | ||
166 | 173 | ||
167 | spin_lock_irqsave(acb->host->host_lock, flags); | 174 | spin_lock(acb->host->host_lock); |
168 | handle_state = arcmsr_interrupt(acb); | 175 | handle_state = arcmsr_interrupt(acb); |
169 | spin_unlock_irqrestore(acb->host->host_lock, flags); | 176 | spin_unlock(acb->host->host_lock); |
177 | |||
170 | return handle_state; | 178 | return handle_state; |
171 | } | 179 | } |
172 | 180 | ||
@@ -198,68 +206,159 @@ static int arcmsr_bios_param(struct scsi_device *sdev, | |||
198 | return 0; | 206 | return 0; |
199 | } | 207 | } |
200 | 208 | ||
201 | static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) | 209 | static void arcmsr_define_adapter_type(struct AdapterControlBlock *acb) |
202 | { | 210 | { |
203 | struct pci_dev *pdev = acb->pdev; | 211 | struct pci_dev *pdev = acb->pdev; |
204 | struct MessageUnit __iomem *reg = acb->pmu; | 212 | u16 dev_id; |
205 | u32 ccb_phyaddr_hi32; | 213 | pci_read_config_word(pdev, PCI_DEVICE_ID, &dev_id); |
206 | void *dma_coherent; | 214 | switch (dev_id) { |
207 | dma_addr_t dma_coherent_handle, dma_addr; | 215 | case 0x1201 : { |
208 | struct CommandControlBlock *ccb_tmp; | 216 | acb->adapter_type = ACB_ADAPTER_TYPE_B; |
209 | int i, j; | 217 | } |
218 | break; | ||
219 | |||
220 | default : acb->adapter_type = ACB_ADAPTER_TYPE_A; | ||
221 | } | ||
222 | } | ||
210 | 223 | ||
211 | dma_coherent = dma_alloc_coherent(&pdev->dev, | 224 | static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) |
225 | { | ||
226 | |||
227 | switch (acb->adapter_type) { | ||
228 | |||
229 | case ACB_ADAPTER_TYPE_A: { | ||
230 | struct pci_dev *pdev = acb->pdev; | ||
231 | void *dma_coherent; | ||
232 | dma_addr_t dma_coherent_handle, dma_addr; | ||
233 | struct CommandControlBlock *ccb_tmp; | ||
234 | uint32_t intmask_org; | ||
235 | int i, j; | ||
236 | |||
237 | acb->pmu = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); | ||
238 | if (!acb->pmu) { | ||
239 | printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", | ||
240 | acb->host->host_no); | ||
241 | } | ||
242 | |||
243 | dma_coherent = dma_alloc_coherent(&pdev->dev, | ||
212 | ARCMSR_MAX_FREECCB_NUM * | 244 | ARCMSR_MAX_FREECCB_NUM * |
213 | sizeof (struct CommandControlBlock) + 0x20, | 245 | sizeof (struct CommandControlBlock) + 0x20, |
214 | &dma_coherent_handle, GFP_KERNEL); | 246 | &dma_coherent_handle, GFP_KERNEL); |
215 | if (!dma_coherent) | 247 | if (!dma_coherent) |
216 | return -ENOMEM; | 248 | return -ENOMEM; |
217 | 249 | ||
218 | acb->dma_coherent = dma_coherent; | 250 | acb->dma_coherent = dma_coherent; |
219 | acb->dma_coherent_handle = dma_coherent_handle; | 251 | acb->dma_coherent_handle = dma_coherent_handle; |
220 | 252 | ||
221 | if (((unsigned long)dma_coherent & 0x1F)) { | 253 | if (((unsigned long)dma_coherent & 0x1F)) { |
222 | dma_coherent = dma_coherent + | 254 | dma_coherent = dma_coherent + |
223 | (0x20 - ((unsigned long)dma_coherent & 0x1F)); | 255 | (0x20 - ((unsigned long)dma_coherent & 0x1F)); |
224 | dma_coherent_handle = dma_coherent_handle + | 256 | dma_coherent_handle = dma_coherent_handle + |
225 | (0x20 - ((unsigned long)dma_coherent_handle & 0x1F)); | 257 | (0x20 - ((unsigned long)dma_coherent_handle & 0x1F)); |
226 | } | 258 | } |
227 | 259 | ||
228 | dma_addr = dma_coherent_handle; | 260 | dma_addr = dma_coherent_handle; |
229 | ccb_tmp = (struct CommandControlBlock *)dma_coherent; | 261 | ccb_tmp = (struct CommandControlBlock *)dma_coherent; |
230 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { | 262 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { |
231 | ccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5; | 263 | ccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5; |
232 | ccb_tmp->acb = acb; | 264 | ccb_tmp->acb = acb; |
233 | acb->pccb_pool[i] = ccb_tmp; | 265 | acb->pccb_pool[i] = ccb_tmp; |
234 | list_add_tail(&ccb_tmp->list, &acb->ccb_free_list); | 266 | list_add_tail(&ccb_tmp->list, &acb->ccb_free_list); |
235 | dma_addr = dma_addr + sizeof (struct CommandControlBlock); | 267 | dma_addr = dma_addr + sizeof(struct CommandControlBlock); |
236 | ccb_tmp++; | 268 | ccb_tmp++; |
237 | } | 269 | } |
238 | 270 | ||
239 | acb->vir2phy_offset = (unsigned long)ccb_tmp - | 271 | acb->vir2phy_offset = (unsigned long)ccb_tmp -(unsigned long)dma_addr; |
240 | (unsigned long)dma_addr; | 272 | for (i = 0; i < ARCMSR_MAX_TARGETID; i++) |
241 | for (i = 0; i < ARCMSR_MAX_TARGETID; i++) | 273 | for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) |
242 | for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) | 274 | acb->devstate[i][j] = ARECA_RAID_GONE; |
243 | acb->devstate[i][j] = ARECA_RAID_GOOD; | ||
244 | 275 | ||
245 | /* | 276 | /* |
246 | ** here we need to tell iop 331 our ccb_tmp.HighPart | 277 | ** here we need to tell iop 331 our ccb_tmp.HighPart |
247 | ** if ccb_tmp.HighPart is not zero | 278 | ** if ccb_tmp.HighPart is not zero |
248 | */ | 279 | */ |
249 | ccb_phyaddr_hi32 = (uint32_t) ((dma_coherent_handle >> 16) >> 16); | 280 | intmask_org = arcmsr_disable_outbound_ints(acb); |
250 | if (ccb_phyaddr_hi32 != 0) { | 281 | } |
251 | writel(ARCMSR_SIGNATURE_SET_CONFIG, ®->message_rwbuffer[0]); | 282 | break; |
252 | writel(ccb_phyaddr_hi32, ®->message_rwbuffer[1]); | 283 | |
253 | writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, ®->inbound_msgaddr0); | 284 | case ACB_ADAPTER_TYPE_B: { |
254 | if (arcmsr_wait_msgint_ready(acb)) | 285 | |
255 | printk(KERN_NOTICE "arcmsr%d: " | 286 | struct pci_dev *pdev = acb->pdev; |
256 | "'set ccb high part physical address' timeout\n", | 287 | struct MessageUnit_B *reg; |
257 | acb->host->host_no); | 288 | void *mem_base0, *mem_base1; |
258 | } | 289 | void *dma_coherent; |
290 | dma_addr_t dma_coherent_handle, dma_addr; | ||
291 | uint32_t intmask_org; | ||
292 | struct CommandControlBlock *ccb_tmp; | ||
293 | int i, j; | ||
294 | |||
295 | dma_coherent = dma_alloc_coherent(&pdev->dev, | ||
296 | ((ARCMSR_MAX_FREECCB_NUM * | ||
297 | sizeof(struct CommandControlBlock) + 0x20) + | ||
298 | sizeof(struct MessageUnit_B)), | ||
299 | &dma_coherent_handle, GFP_KERNEL); | ||
300 | if (!dma_coherent) | ||
301 | return -ENOMEM; | ||
259 | 302 | ||
260 | writel(readl(®->outbound_intmask) | | 303 | acb->dma_coherent = dma_coherent; |
261 | ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, | 304 | acb->dma_coherent_handle = dma_coherent_handle; |
262 | ®->outbound_intmask); | 305 | |
306 | if (((unsigned long)dma_coherent & 0x1F)) { | ||
307 | dma_coherent = dma_coherent + | ||
308 | (0x20 - ((unsigned long)dma_coherent & 0x1F)); | ||
309 | dma_coherent_handle = dma_coherent_handle + | ||
310 | (0x20 - ((unsigned long)dma_coherent_handle & 0x1F)); | ||
311 | } | ||
312 | |||
313 | reg = (struct MessageUnit_B *)(dma_coherent + | ||
314 | ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock)); | ||
315 | |||
316 | dma_addr = dma_coherent_handle; | ||
317 | ccb_tmp = (struct CommandControlBlock *)dma_coherent; | ||
318 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { | ||
319 | ccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5; | ||
320 | ccb_tmp->acb = acb; | ||
321 | acb->pccb_pool[i] = ccb_tmp; | ||
322 | list_add_tail(&ccb_tmp->list, &acb->ccb_free_list); | ||
323 | dma_addr = dma_addr + sizeof(struct CommandControlBlock); | ||
324 | ccb_tmp++; | ||
325 | } | ||
326 | |||
327 | reg = (struct MessageUnit_B *)(dma_coherent + | ||
328 | ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock)); | ||
329 | acb->pmu = (struct MessageUnit_B *)reg; | ||
330 | mem_base0 = ioremap(pci_resource_start(pdev, 0), | ||
331 | pci_resource_len(pdev, 0)); | ||
332 | mem_base1 = ioremap(pci_resource_start(pdev, 2), | ||
333 | pci_resource_len(pdev, 2)); | ||
334 | reg->drv2iop_doorbell_reg = (uint32_t *)((char *)mem_base0 + | ||
335 | ARCMSR_DRV2IOP_DOORBELL); | ||
336 | reg->drv2iop_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 + | ||
337 | ARCMSR_DRV2IOP_DOORBELL_MASK); | ||
338 | reg->iop2drv_doorbell_reg = (uint32_t *)((char *)mem_base0 + | ||
339 | ARCMSR_IOP2DRV_DOORBELL); | ||
340 | reg->iop2drv_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 + | ||
341 | ARCMSR_IOP2DRV_DOORBELL_MASK); | ||
342 | reg->ioctl_wbuffer_reg = (uint32_t *)((char *)mem_base1 + | ||
343 | ARCMSR_IOCTL_WBUFFER); | ||
344 | reg->ioctl_rbuffer_reg = (uint32_t *)((char *)mem_base1 + | ||
345 | ARCMSR_IOCTL_RBUFFER); | ||
346 | reg->msgcode_rwbuffer_reg = (uint32_t *)((char *)mem_base1 + | ||
347 | ARCMSR_MSGCODE_RWBUFFER); | ||
348 | |||
349 | acb->vir2phy_offset = (unsigned long)ccb_tmp -(unsigned long)dma_addr; | ||
350 | for (i = 0; i < ARCMSR_MAX_TARGETID; i++) | ||
351 | for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) | ||
352 | acb->devstate[i][j] = ARECA_RAID_GOOD; | ||
353 | |||
354 | /* | ||
355 | ** here we need to tell iop 331 our ccb_tmp.HighPart | ||
356 | ** if ccb_tmp.HighPart is not zero | ||
357 | */ | ||
358 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
359 | } | ||
360 | break; | ||
361 | } | ||
263 | return 0; | 362 | return 0; |
264 | } | 363 | } |
265 | 364 | ||
@@ -310,16 +409,11 @@ static int arcmsr_probe(struct pci_dev *pdev, | |||
310 | host->unique_id = (bus << 8) | dev_fun; | 409 | host->unique_id = (bus << 8) | dev_fun; |
311 | host->irq = pdev->irq; | 410 | host->irq = pdev->irq; |
312 | error = pci_request_regions(pdev, "arcmsr"); | 411 | error = pci_request_regions(pdev, "arcmsr"); |
313 | if (error) | 412 | if (error) { |
314 | goto out_host_put; | 413 | goto out_host_put; |
315 | |||
316 | acb->pmu = ioremap(pci_resource_start(pdev, 0), | ||
317 | pci_resource_len(pdev, 0)); | ||
318 | if (!acb->pmu) { | ||
319 | printk(KERN_NOTICE "arcmsr%d: memory" | ||
320 | " mapping region fail \n", acb->host->host_no); | ||
321 | goto out_release_regions; | ||
322 | } | 414 | } |
415 | arcmsr_define_adapter_type(acb); | ||
416 | |||
323 | acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | | 417 | acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | |
324 | ACB_F_MESSAGE_RQBUFFER_CLEARED | | 418 | ACB_F_MESSAGE_RQBUFFER_CLEARED | |
325 | ACB_F_MESSAGE_WQBUFFER_READED); | 419 | ACB_F_MESSAGE_WQBUFFER_READED); |
@@ -328,10 +422,10 @@ static int arcmsr_probe(struct pci_dev *pdev, | |||
328 | 422 | ||
329 | error = arcmsr_alloc_ccb_pool(acb); | 423 | error = arcmsr_alloc_ccb_pool(acb); |
330 | if (error) | 424 | if (error) |
331 | goto out_iounmap; | 425 | goto out_release_regions; |
332 | 426 | ||
333 | error = request_irq(pdev->irq, arcmsr_do_interrupt, | 427 | error = request_irq(pdev->irq, arcmsr_do_interrupt, |
334 | IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb); | 428 | IRQF_SHARED, "arcmsr", acb); |
335 | if (error) | 429 | if (error) |
336 | goto out_free_ccb_pool; | 430 | goto out_free_ccb_pool; |
337 | 431 | ||
@@ -349,14 +443,15 @@ static int arcmsr_probe(struct pci_dev *pdev, | |||
349 | goto out_free_sysfs; | 443 | goto out_free_sysfs; |
350 | 444 | ||
351 | scsi_scan_host(host); | 445 | scsi_scan_host(host); |
446 | #ifdef CONFIG_SCSI_ARCMSR_AER | ||
352 | pci_enable_pcie_error_reporting(pdev); | 447 | pci_enable_pcie_error_reporting(pdev); |
448 | #endif | ||
353 | return 0; | 449 | return 0; |
354 | out_free_sysfs: | 450 | out_free_sysfs: |
355 | out_free_irq: | 451 | out_free_irq: |
356 | free_irq(pdev->irq, acb); | 452 | free_irq(pdev->irq, acb); |
357 | out_free_ccb_pool: | 453 | out_free_ccb_pool: |
358 | arcmsr_free_ccb_pool(acb); | 454 | arcmsr_free_ccb_pool(acb); |
359 | out_iounmap: | ||
360 | iounmap(acb->pmu); | 455 | iounmap(acb->pmu); |
361 | out_release_regions: | 456 | out_release_regions: |
362 | pci_release_regions(pdev); | 457 | pci_release_regions(pdev); |
@@ -368,17 +463,84 @@ static int arcmsr_probe(struct pci_dev *pdev, | |||
368 | return error; | 463 | return error; |
369 | } | 464 | } |
370 | 465 | ||
371 | static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) | 466 | static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) |
467 | { | ||
468 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; | ||
469 | uint32_t Index; | ||
470 | uint8_t Retries = 0x00; | ||
471 | |||
472 | do { | ||
473 | for (Index = 0; Index < 100; Index++) { | ||
474 | if (readl(®->outbound_intstatus) & | ||
475 | ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { | ||
476 | writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT, | ||
477 | ®->outbound_intstatus); | ||
478 | return 0x00; | ||
479 | } | ||
480 | msleep(10); | ||
481 | }/*max 1 seconds*/ | ||
482 | |||
483 | } while (Retries++ < 20);/*max 20 sec*/ | ||
484 | return 0xff; | ||
485 | } | ||
486 | |||
487 | static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) | ||
488 | { | ||
489 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; | ||
490 | uint32_t Index; | ||
491 | uint8_t Retries = 0x00; | ||
492 | |||
493 | do { | ||
494 | for (Index = 0; Index < 100; Index++) { | ||
495 | if (readl(reg->iop2drv_doorbell_reg) | ||
496 | & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { | ||
497 | writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN | ||
498 | , reg->iop2drv_doorbell_reg); | ||
499 | return 0x00; | ||
500 | } | ||
501 | msleep(10); | ||
502 | }/*max 1 seconds*/ | ||
503 | |||
504 | } while (Retries++ < 20);/*max 20 sec*/ | ||
505 | return 0xff; | ||
506 | } | ||
507 | |||
508 | static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) | ||
372 | { | 509 | { |
373 | struct MessageUnit __iomem *reg = acb->pmu; | 510 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; |
374 | 511 | ||
375 | writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); | 512 | writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); |
376 | if (arcmsr_wait_msgint_ready(acb)) | 513 | if (arcmsr_hba_wait_msgint_ready(acb)) |
377 | printk(KERN_NOTICE | 514 | printk(KERN_NOTICE |
378 | "arcmsr%d: wait 'abort all outstanding command' timeout \n" | 515 | "arcmsr%d: wait 'abort all outstanding command' timeout \n" |
379 | , acb->host->host_no); | 516 | , acb->host->host_no); |
380 | } | 517 | } |
381 | 518 | ||
519 | static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) | ||
520 | { | ||
521 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; | ||
522 | |||
523 | writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell_reg); | ||
524 | if (arcmsr_hbb_wait_msgint_ready(acb)) | ||
525 | printk(KERN_NOTICE | ||
526 | "arcmsr%d: wait 'abort all outstanding command' timeout \n" | ||
527 | , acb->host->host_no); | ||
528 | } | ||
529 | |||
530 | static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) | ||
531 | { | ||
532 | switch (acb->adapter_type) { | ||
533 | case ACB_ADAPTER_TYPE_A: { | ||
534 | arcmsr_abort_hba_allcmd(acb); | ||
535 | } | ||
536 | break; | ||
537 | |||
538 | case ACB_ADAPTER_TYPE_B: { | ||
539 | arcmsr_abort_hbb_allcmd(acb); | ||
540 | } | ||
541 | } | ||
542 | } | ||
543 | |||
382 | static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) | 544 | static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) |
383 | { | 545 | { |
384 | struct scsi_cmnd *pcmd = ccb->pcmd; | 546 | struct scsi_cmnd *pcmd = ccb->pcmd; |
@@ -400,28 +562,239 @@ static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag) | |||
400 | pcmd->scsi_done(pcmd); | 562 | pcmd->scsi_done(pcmd); |
401 | } | 563 | } |
402 | 564 | ||
565 | static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) | ||
566 | { | ||
567 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; | ||
568 | int retry_count = 30; | ||
569 | |||
570 | writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); | ||
571 | do { | ||
572 | if (!arcmsr_hba_wait_msgint_ready(acb)) | ||
573 | break; | ||
574 | else { | ||
575 | retry_count--; | ||
576 | printk(KERN_NOTICE "arcmsr%d: wait 'flush adapter cache' \ | ||
577 | timeout, retry count down = %d \n", acb->host->host_no, retry_count); | ||
578 | } | ||
579 | } while (retry_count != 0); | ||
580 | } | ||
581 | |||
582 | static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) | ||
583 | { | ||
584 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; | ||
585 | int retry_count = 30; | ||
586 | |||
587 | writel(ARCMSR_MESSAGE_FLUSH_CACHE, reg->drv2iop_doorbell_reg); | ||
588 | do { | ||
589 | if (!arcmsr_hbb_wait_msgint_ready(acb)) | ||
590 | break; | ||
591 | else { | ||
592 | retry_count--; | ||
593 | printk(KERN_NOTICE "arcmsr%d: wait 'flush adapter cache' \ | ||
594 | timeout,retry count down = %d \n", acb->host->host_no, retry_count); | ||
595 | } | ||
596 | } while (retry_count != 0); | ||
597 | } | ||
598 | |||
599 | static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) | ||
600 | { | ||
601 | switch (acb->adapter_type) { | ||
602 | |||
603 | case ACB_ADAPTER_TYPE_A: { | ||
604 | arcmsr_flush_hba_cache(acb); | ||
605 | } | ||
606 | break; | ||
607 | |||
608 | case ACB_ADAPTER_TYPE_B: { | ||
609 | arcmsr_flush_hbb_cache(acb); | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | |||
614 | static void arcmsr_report_sense_info(struct CommandControlBlock *ccb) | ||
615 | { | ||
616 | |||
617 | struct scsi_cmnd *pcmd = ccb->pcmd; | ||
618 | struct SENSE_DATA *sensebuffer = (struct SENSE_DATA *)pcmd->sense_buffer; | ||
619 | |||
620 | pcmd->result = DID_OK << 16; | ||
621 | if (sensebuffer) { | ||
622 | int sense_data_length = | ||
623 | sizeof(struct SENSE_DATA) < sizeof(pcmd->sense_buffer) | ||
624 | ? sizeof(struct SENSE_DATA) : sizeof(pcmd->sense_buffer); | ||
625 | memset(sensebuffer, 0, sizeof(pcmd->sense_buffer)); | ||
626 | memcpy(sensebuffer, ccb->arcmsr_cdb.SenseData, sense_data_length); | ||
627 | sensebuffer->ErrorCode = SCSI_SENSE_CURRENT_ERRORS; | ||
628 | sensebuffer->Valid = 1; | ||
629 | } | ||
630 | } | ||
631 | |||
632 | static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) | ||
633 | { | ||
634 | u32 orig_mask = 0; | ||
635 | switch (acb->adapter_type) { | ||
636 | |||
637 | case ACB_ADAPTER_TYPE_A : { | ||
638 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; | ||
639 | orig_mask = readl(®->outbound_intmask)|\ | ||
640 | ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; | ||
641 | writel(orig_mask|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, \ | ||
642 | ®->outbound_intmask); | ||
643 | } | ||
644 | break; | ||
645 | |||
646 | case ACB_ADAPTER_TYPE_B : { | ||
647 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; | ||
648 | orig_mask = readl(reg->iop2drv_doorbell_mask_reg) & \ | ||
649 | (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); | ||
650 | writel(0, reg->iop2drv_doorbell_mask_reg); | ||
651 | } | ||
652 | break; | ||
653 | } | ||
654 | return orig_mask; | ||
655 | } | ||
656 | |||
657 | static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb, \ | ||
658 | struct CommandControlBlock *ccb, uint32_t flag_ccb) | ||
659 | { | ||
660 | |||
661 | uint8_t id, lun; | ||
662 | id = ccb->pcmd->device->id; | ||
663 | lun = ccb->pcmd->device->lun; | ||
664 | if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { | ||
665 | if (acb->devstate[id][lun] == ARECA_RAID_GONE) | ||
666 | acb->devstate[id][lun] = ARECA_RAID_GOOD; | ||
667 | ccb->pcmd->result = DID_OK << 16; | ||
668 | arcmsr_ccb_complete(ccb, 1); | ||
669 | } else { | ||
670 | switch (ccb->arcmsr_cdb.DeviceStatus) { | ||
671 | case ARCMSR_DEV_SELECT_TIMEOUT: { | ||
672 | acb->devstate[id][lun] = ARECA_RAID_GONE; | ||
673 | ccb->pcmd->result = DID_NO_CONNECT << 16; | ||
674 | arcmsr_ccb_complete(ccb, 1); | ||
675 | } | ||
676 | break; | ||
677 | |||
678 | case ARCMSR_DEV_ABORTED: | ||
679 | |||
680 | case ARCMSR_DEV_INIT_FAIL: { | ||
681 | acb->devstate[id][lun] = ARECA_RAID_GONE; | ||
682 | ccb->pcmd->result = DID_BAD_TARGET << 16; | ||
683 | arcmsr_ccb_complete(ccb, 1); | ||
684 | } | ||
685 | break; | ||
686 | |||
687 | case ARCMSR_DEV_CHECK_CONDITION: { | ||
688 | acb->devstate[id][lun] = ARECA_RAID_GOOD; | ||
689 | arcmsr_report_sense_info(ccb); | ||
690 | arcmsr_ccb_complete(ccb, 1); | ||
691 | } | ||
692 | break; | ||
693 | |||
694 | default: | ||
695 | printk(KERN_NOTICE | ||
696 | "arcmsr%d: scsi id = %d lun = %d" | ||
697 | " isr get command error done, " | ||
698 | "but got unknown DeviceStatus = 0x%x \n" | ||
699 | , acb->host->host_no | ||
700 | , id | ||
701 | , lun | ||
702 | , ccb->arcmsr_cdb.DeviceStatus); | ||
703 | acb->devstate[id][lun] = ARECA_RAID_GONE; | ||
704 | ccb->pcmd->result = DID_NO_CONNECT << 16; | ||
705 | arcmsr_ccb_complete(ccb, 1); | ||
706 | break; | ||
707 | } | ||
708 | } | ||
709 | } | ||
710 | |||
711 | static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, uint32_t flag_ccb) | ||
712 | |||
713 | { | ||
714 | struct CommandControlBlock *ccb; | ||
715 | |||
716 | ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + (flag_ccb << 5)); | ||
717 | if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { | ||
718 | if (ccb->startdone == ARCMSR_CCB_ABORTED) { | ||
719 | struct scsi_cmnd *abortcmd = ccb->pcmd; | ||
720 | if (abortcmd) { | ||
721 | abortcmd->result |= DID_ABORT << 16; | ||
722 | arcmsr_ccb_complete(ccb, 1); | ||
723 | printk(KERN_NOTICE "arcmsr%d: ccb ='0x%p' \ | ||
724 | isr got aborted command \n", acb->host->host_no, ccb); | ||
725 | } | ||
726 | } | ||
727 | printk(KERN_NOTICE "arcmsr%d: isr get an illegal ccb command \ | ||
728 | done acb = '0x%p'" | ||
729 | "ccb = '0x%p' ccbacb = '0x%p' startdone = 0x%x" | ||
730 | " ccboutstandingcount = %d \n" | ||
731 | , acb->host->host_no | ||
732 | , acb | ||
733 | , ccb | ||
734 | , ccb->acb | ||
735 | , ccb->startdone | ||
736 | , atomic_read(&acb->ccboutstandingcount)); | ||
737 | } | ||
738 | arcmsr_report_ccb_state(acb, ccb, flag_ccb); | ||
739 | } | ||
740 | |||
741 | static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) | ||
742 | { | ||
743 | int i = 0; | ||
744 | uint32_t flag_ccb; | ||
745 | |||
746 | switch (acb->adapter_type) { | ||
747 | |||
748 | case ACB_ADAPTER_TYPE_A: { | ||
749 | struct MessageUnit_A __iomem *reg = \ | ||
750 | (struct MessageUnit_A *)acb->pmu; | ||
751 | uint32_t outbound_intstatus; | ||
752 | outbound_intstatus = readl(®->outbound_intstatus) & \ | ||
753 | acb->outbound_int_enable; | ||
754 | /*clear and abort all outbound posted Q*/ | ||
755 | writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/ | ||
756 | while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) \ | ||
757 | && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { | ||
758 | arcmsr_drain_donequeue(acb, flag_ccb); | ||
759 | } | ||
760 | } | ||
761 | break; | ||
762 | |||
763 | case ACB_ADAPTER_TYPE_B: { | ||
764 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; | ||
765 | /*clear all outbound posted Q*/ | ||
766 | for (i = 0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { | ||
767 | if ((flag_ccb = readl(®->done_qbuffer[i])) != 0) { | ||
768 | writel(0, ®->done_qbuffer[i]); | ||
769 | arcmsr_drain_donequeue(acb, flag_ccb); | ||
770 | } | ||
771 | writel(0, ®->post_qbuffer[i]); | ||
772 | } | ||
773 | reg->doneq_index = 0; | ||
774 | reg->postq_index = 0; | ||
775 | } | ||
776 | break; | ||
777 | } | ||
778 | } | ||
403 | static void arcmsr_remove(struct pci_dev *pdev) | 779 | static void arcmsr_remove(struct pci_dev *pdev) |
404 | { | 780 | { |
405 | struct Scsi_Host *host = pci_get_drvdata(pdev); | 781 | struct Scsi_Host *host = pci_get_drvdata(pdev); |
406 | struct AdapterControlBlock *acb = | 782 | struct AdapterControlBlock *acb = |
407 | (struct AdapterControlBlock *) host->hostdata; | 783 | (struct AdapterControlBlock *) host->hostdata; |
408 | struct MessageUnit __iomem *reg = acb->pmu; | ||
409 | int poll_count = 0; | 784 | int poll_count = 0; |
410 | 785 | ||
411 | arcmsr_free_sysfs_attr(acb); | 786 | arcmsr_free_sysfs_attr(acb); |
412 | scsi_remove_host(host); | 787 | scsi_remove_host(host); |
413 | arcmsr_stop_adapter_bgrb(acb); | 788 | arcmsr_stop_adapter_bgrb(acb); |
414 | arcmsr_flush_adapter_cache(acb); | 789 | arcmsr_flush_adapter_cache(acb); |
415 | writel(readl(®->outbound_intmask) | | 790 | arcmsr_disable_outbound_ints(acb); |
416 | ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, | ||
417 | ®->outbound_intmask); | ||
418 | acb->acb_flags |= ACB_F_SCSISTOPADAPTER; | 791 | acb->acb_flags |= ACB_F_SCSISTOPADAPTER; |
419 | acb->acb_flags &= ~ACB_F_IOP_INITED; | 792 | acb->acb_flags &= ~ACB_F_IOP_INITED; |
420 | 793 | ||
421 | for (poll_count = 0; poll_count < 256; poll_count++) { | 794 | for (poll_count = 0; poll_count < ARCMSR_MAX_OUTSTANDING_CMD; poll_count++) { |
422 | if (!atomic_read(&acb->ccboutstandingcount)) | 795 | if (!atomic_read(&acb->ccboutstandingcount)) |
423 | break; | 796 | break; |
424 | arcmsr_interrupt(acb); | 797 | arcmsr_interrupt(acb);/* FIXME: need spinlock */ |
425 | msleep(25); | 798 | msleep(25); |
426 | } | 799 | } |
427 | 800 | ||
@@ -429,8 +802,7 @@ static void arcmsr_remove(struct pci_dev *pdev) | |||
429 | int i; | 802 | int i; |
430 | 803 | ||
431 | arcmsr_abort_allcmd(acb); | 804 | arcmsr_abort_allcmd(acb); |
432 | for (i = 0; i < ARCMSR_MAX_OUTSTANDING_CMD; i++) | 805 | arcmsr_done4abort_postqueue(acb); |
433 | readl(®->outbound_queueport); | ||
434 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { | 806 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { |
435 | struct CommandControlBlock *ccb = acb->pccb_pool[i]; | 807 | struct CommandControlBlock *ccb = acb->pccb_pool[i]; |
436 | if (ccb->startdone == ARCMSR_CCB_START) { | 808 | if (ccb->startdone == ARCMSR_CCB_START) { |
@@ -477,75 +849,32 @@ static void arcmsr_module_exit(void) | |||
477 | module_init(arcmsr_module_init); | 849 | module_init(arcmsr_module_init); |
478 | module_exit(arcmsr_module_exit); | 850 | module_exit(arcmsr_module_exit); |
479 | 851 | ||
480 | static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) | 852 | static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ |
481 | { | 853 | u32 intmask_org) |
482 | struct MessageUnit __iomem *reg = acb->pmu; | ||
483 | u32 orig_mask = readl(®->outbound_intmask); | ||
484 | |||
485 | writel(orig_mask | ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, | ||
486 | ®->outbound_intmask); | ||
487 | return orig_mask; | ||
488 | } | ||
489 | |||
490 | static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, | ||
491 | u32 orig_mask) | ||
492 | { | 854 | { |
493 | struct MessageUnit __iomem *reg = acb->pmu; | ||
494 | u32 mask; | 855 | u32 mask; |
495 | 856 | ||
496 | mask = orig_mask & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | | 857 | switch (acb->adapter_type) { |
497 | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); | ||
498 | writel(mask, ®->outbound_intmask); | ||
499 | } | ||
500 | |||
501 | static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) | ||
502 | { | ||
503 | struct MessageUnit __iomem *reg = acb->pmu; | ||
504 | |||
505 | writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); | ||
506 | if (arcmsr_wait_msgint_ready(acb)) | ||
507 | printk(KERN_NOTICE | ||
508 | "arcmsr%d: wait 'flush adapter cache' timeout \n" | ||
509 | , acb->host->host_no); | ||
510 | } | ||
511 | 858 | ||
512 | static void arcmsr_report_sense_info(struct CommandControlBlock *ccb) | 859 | case ACB_ADAPTER_TYPE_A : { |
513 | { | 860 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; |
514 | struct scsi_cmnd *pcmd = ccb->pcmd; | 861 | mask = intmask_org & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | |
515 | struct SENSE_DATA *sensebuffer = (struct SENSE_DATA *)pcmd->sense_buffer; | 862 | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); |
863 | writel(mask, ®->outbound_intmask); | ||
864 | acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; | ||
865 | } | ||
866 | break; | ||
516 | 867 | ||
517 | pcmd->result = DID_OK << 16; | 868 | case ACB_ADAPTER_TYPE_B : { |
518 | if (sensebuffer) { | 869 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; |
519 | int sense_data_length = | 870 | mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK | \ |
520 | sizeof (struct SENSE_DATA) < sizeof (pcmd->sense_buffer) | 871 | ARCMSR_IOP2DRV_DATA_READ_OK | ARCMSR_IOP2DRV_CDB_DONE); |
521 | ? sizeof (struct SENSE_DATA) : sizeof (pcmd->sense_buffer); | 872 | writel(mask, reg->iop2drv_doorbell_mask_reg); |
522 | memset(sensebuffer, 0, sizeof (pcmd->sense_buffer)); | 873 | acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; |
523 | memcpy(sensebuffer, ccb->arcmsr_cdb.SenseData, sense_data_length); | 874 | } |
524 | sensebuffer->ErrorCode = SCSI_SENSE_CURRENT_ERRORS; | ||
525 | sensebuffer->Valid = 1; | ||
526 | } | 875 | } |
527 | } | 876 | } |
528 | 877 | ||
529 | static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb) | ||
530 | { | ||
531 | struct MessageUnit __iomem *reg = acb->pmu; | ||
532 | uint32_t Index; | ||
533 | uint8_t Retries = 0x00; | ||
534 | |||
535 | do { | ||
536 | for (Index = 0; Index < 100; Index++) { | ||
537 | if (readl(®->outbound_intstatus) | ||
538 | & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { | ||
539 | writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT | ||
540 | , ®->outbound_intstatus); | ||
541 | return 0x00; | ||
542 | } | ||
543 | msleep_interruptible(10); | ||
544 | }/*max 1 seconds*/ | ||
545 | } while (Retries++ < 20);/*max 20 sec*/ | ||
546 | return 0xff; | ||
547 | } | ||
548 | |||
549 | static void arcmsr_build_ccb(struct AdapterControlBlock *acb, | 878 | static void arcmsr_build_ccb(struct AdapterControlBlock *acb, |
550 | struct CommandControlBlock *ccb, struct scsi_cmnd *pcmd) | 879 | struct CommandControlBlock *ccb, struct scsi_cmnd *pcmd) |
551 | { | 880 | { |
@@ -556,7 +885,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, | |||
556 | int nseg; | 885 | int nseg; |
557 | 886 | ||
558 | ccb->pcmd = pcmd; | 887 | ccb->pcmd = pcmd; |
559 | memset(arcmsr_cdb, 0, sizeof (struct ARCMSR_CDB)); | 888 | memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); |
560 | arcmsr_cdb->Bus = 0; | 889 | arcmsr_cdb->Bus = 0; |
561 | arcmsr_cdb->TargetID = pcmd->device->id; | 890 | arcmsr_cdb->TargetID = pcmd->device->id; |
562 | arcmsr_cdb->LUN = pcmd->device->lun; | 891 | arcmsr_cdb->LUN = pcmd->device->lun; |
@@ -609,52 +938,85 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, | |||
609 | 938 | ||
610 | static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb) | 939 | static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb) |
611 | { | 940 | { |
612 | struct MessageUnit __iomem *reg = acb->pmu; | ||
613 | uint32_t cdb_shifted_phyaddr = ccb->cdb_shifted_phyaddr; | 941 | uint32_t cdb_shifted_phyaddr = ccb->cdb_shifted_phyaddr; |
614 | struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; | 942 | struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; |
615 | |||
616 | atomic_inc(&acb->ccboutstandingcount); | 943 | atomic_inc(&acb->ccboutstandingcount); |
617 | ccb->startdone = ARCMSR_CCB_START; | 944 | ccb->startdone = ARCMSR_CCB_START; |
618 | if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) | 945 | |
619 | writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, | 946 | switch (acb->adapter_type) { |
947 | case ACB_ADAPTER_TYPE_A: { | ||
948 | struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu; | ||
949 | |||
950 | if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) | ||
951 | writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, | ||
620 | ®->inbound_queueport); | 952 | ®->inbound_queueport); |
621 | else | 953 | else { |
622 | writel(cdb_shifted_phyaddr, ®->inbound_queueport); | 954 | writel(cdb_shifted_phyaddr, ®->inbound_queueport); |
623 | } | 955 | } |
956 | } | ||
957 | break; | ||
624 | 958 | ||
625 | void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb) | 959 | case ACB_ADAPTER_TYPE_B: { |
626 | { | 960 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; |
627 | struct MessageUnit __iomem *reg = acb->pmu; | 961 | uint32_t ending_index, index = reg->postq_index; |
628 | struct QBUFFER __iomem *pwbuffer = (struct QBUFFER __iomem *) ®->message_wbuffer; | ||
629 | uint8_t __iomem *iop_data = (uint8_t __iomem *) pwbuffer->data; | ||
630 | int32_t allxfer_len = 0; | ||
631 | 962 | ||
632 | if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { | 963 | ending_index = ((index + 1) % ARCMSR_MAX_HBB_POSTQUEUE); |
633 | acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); | 964 | writel(0, ®->post_qbuffer[ending_index]); |
634 | while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) | 965 | if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { |
635 | && (allxfer_len < 124)) { | 966 | writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,\ |
636 | writeb(acb->wqbuffer[acb->wqbuf_firstindex], iop_data); | 967 | ®->post_qbuffer[index]); |
637 | acb->wqbuf_firstindex++; | 968 | } |
638 | acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; | 969 | else { |
639 | iop_data++; | 970 | writel(cdb_shifted_phyaddr, ®->post_qbuffer[index]); |
640 | allxfer_len++; | 971 | } |
972 | index++; | ||
973 | index %= ARCMSR_MAX_HBB_POSTQUEUE;/*if last index number set it to 0 */ | ||
974 | reg->postq_index = index; | ||
975 | writel(ARCMSR_DRV2IOP_CDB_POSTED, reg->drv2iop_doorbell_reg); | ||
641 | } | 976 | } |
642 | writel(allxfer_len, &pwbuffer->data_len); | 977 | break; |
643 | writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK | ||
644 | , ®->inbound_doorbell); | ||
645 | } | 978 | } |
646 | } | 979 | } |
647 | 980 | ||
648 | static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) | 981 | static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) |
649 | { | 982 | { |
650 | struct MessageUnit __iomem *reg = acb->pmu; | 983 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; |
651 | |||
652 | acb->acb_flags &= ~ACB_F_MSG_START_BGRB; | 984 | acb->acb_flags &= ~ACB_F_MSG_START_BGRB; |
653 | writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0); | 985 | writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0); |
654 | if (arcmsr_wait_msgint_ready(acb)) | 986 | |
987 | if (arcmsr_hba_wait_msgint_ready(acb)) { | ||
988 | printk(KERN_NOTICE | ||
989 | "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" | ||
990 | , acb->host->host_no); | ||
991 | } | ||
992 | } | ||
993 | |||
994 | static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) | ||
995 | { | ||
996 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; | ||
997 | acb->acb_flags &= ~ACB_F_MSG_START_BGRB; | ||
998 | writel(ARCMSR_MESSAGE_STOP_BGRB, reg->drv2iop_doorbell_reg); | ||
999 | |||
1000 | if (arcmsr_hbb_wait_msgint_ready(acb)) { | ||
655 | printk(KERN_NOTICE | 1001 | printk(KERN_NOTICE |
656 | "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" | 1002 | "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" |
657 | , acb->host->host_no); | 1003 | , acb->host->host_no); |
1004 | } | ||
1005 | } | ||
1006 | |||
1007 | static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) | ||
1008 | { | ||
1009 | switch (acb->adapter_type) { | ||
1010 | case ACB_ADAPTER_TYPE_A: { | ||
1011 | arcmsr_stop_hba_bgrb(acb); | ||
1012 | } | ||
1013 | break; | ||
1014 | |||
1015 | case ACB_ADAPTER_TYPE_B: { | ||
1016 | arcmsr_stop_hbb_bgrb(acb); | ||
1017 | } | ||
1018 | break; | ||
1019 | } | ||
658 | } | 1020 | } |
659 | 1021 | ||
660 | static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) | 1022 | static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) |
@@ -665,151 +1027,260 @@ static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) | |||
665 | acb->dma_coherent_handle); | 1027 | acb->dma_coherent_handle); |
666 | } | 1028 | } |
667 | 1029 | ||
668 | static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) | 1030 | void arcmsr_iop_message_read(struct AdapterControlBlock *acb) |
669 | { | 1031 | { |
670 | struct MessageUnit __iomem *reg = acb->pmu; | 1032 | switch (acb->adapter_type) { |
671 | struct CommandControlBlock *ccb; | 1033 | case ACB_ADAPTER_TYPE_A: { |
672 | uint32_t flag_ccb, outbound_intstatus, outbound_doorbell; | 1034 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; |
1035 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); | ||
1036 | } | ||
1037 | break; | ||
673 | 1038 | ||
674 | outbound_intstatus = readl(®->outbound_intstatus) | 1039 | case ACB_ADAPTER_TYPE_B: { |
675 | & acb->outbound_int_enable; | 1040 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; |
676 | writel(outbound_intstatus, ®->outbound_intstatus); | 1041 | writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg); |
677 | if (outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { | ||
678 | outbound_doorbell = readl(®->outbound_doorbell); | ||
679 | writel(outbound_doorbell, ®->outbound_doorbell); | ||
680 | if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { | ||
681 | struct QBUFFER __iomem * prbuffer = | ||
682 | (struct QBUFFER __iomem *) ®->message_rbuffer; | ||
683 | uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data; | ||
684 | int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; | ||
685 | |||
686 | rqbuf_lastindex = acb->rqbuf_lastindex; | ||
687 | rqbuf_firstindex = acb->rqbuf_firstindex; | ||
688 | iop_len = readl(&prbuffer->data_len); | ||
689 | my_empty_len = (rqbuf_firstindex - rqbuf_lastindex - 1) | ||
690 | &(ARCMSR_MAX_QBUFFER - 1); | ||
691 | if (my_empty_len >= iop_len) { | ||
692 | while (iop_len > 0) { | ||
693 | acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); | ||
694 | acb->rqbuf_lastindex++; | ||
695 | acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; | ||
696 | iop_data++; | ||
697 | iop_len--; | ||
698 | } | ||
699 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, | ||
700 | ®->inbound_doorbell); | ||
701 | } else | ||
702 | acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; | ||
703 | } | ||
704 | if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { | ||
705 | acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; | ||
706 | if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) { | ||
707 | struct QBUFFER __iomem * pwbuffer = | ||
708 | (struct QBUFFER __iomem *) ®->message_wbuffer; | ||
709 | uint8_t __iomem * iop_data = (uint8_t __iomem *) pwbuffer->data; | ||
710 | int32_t allxfer_len = 0; | ||
711 | |||
712 | acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); | ||
713 | while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) | ||
714 | && (allxfer_len < 124)) { | ||
715 | writeb(acb->wqbuffer[acb->wqbuf_firstindex], iop_data); | ||
716 | acb->wqbuf_firstindex++; | ||
717 | acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; | ||
718 | iop_data++; | ||
719 | allxfer_len++; | ||
720 | } | ||
721 | writel(allxfer_len, &pwbuffer->data_len); | ||
722 | writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK, | ||
723 | ®->inbound_doorbell); | ||
724 | } | ||
725 | if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) | ||
726 | acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; | ||
727 | } | 1042 | } |
1043 | break; | ||
728 | } | 1044 | } |
729 | if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { | 1045 | } |
730 | int id, lun; | 1046 | |
1047 | static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) | ||
1048 | { | ||
1049 | switch (acb->adapter_type) { | ||
1050 | case ACB_ADAPTER_TYPE_A: { | ||
1051 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; | ||
731 | /* | 1052 | /* |
732 | **************************************************************** | 1053 | ** push inbound doorbell tell iop, driver data write ok |
733 | ** areca cdb command done | 1054 | ** and wait reply on next hwinterrupt for next Qbuffer post |
734 | **************************************************************** | ||
735 | */ | 1055 | */ |
736 | while (1) { | 1056 | writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK, ®->inbound_doorbell); |
737 | if ((flag_ccb = readl(®->outbound_queueport)) == 0xFFFFFFFF) | 1057 | } |
738 | break;/*chip FIFO no ccb for completion already*/ | 1058 | break; |
739 | /* check if command done with no error*/ | 1059 | |
740 | ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + | 1060 | case ACB_ADAPTER_TYPE_B: { |
741 | (flag_ccb << 5)); | 1061 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; |
742 | if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { | 1062 | /* |
743 | if (ccb->startdone == ARCMSR_CCB_ABORTED) { | 1063 | ** push inbound doorbell tell iop, driver data write ok |
744 | struct scsi_cmnd *abortcmd = ccb->pcmd; | 1064 | ** and wait reply on next hwinterrupt for next Qbuffer post |
745 | if (abortcmd) { | 1065 | */ |
746 | abortcmd->result |= DID_ABORT >> 16; | 1066 | writel(ARCMSR_DRV2IOP_DATA_WRITE_OK, reg->drv2iop_doorbell_reg); |
747 | arcmsr_ccb_complete(ccb, 1); | 1067 | } |
748 | printk(KERN_NOTICE | 1068 | break; |
749 | "arcmsr%d: ccb ='0x%p' isr got aborted command \n" | 1069 | } |
750 | , acb->host->host_no, ccb); | 1070 | } |
751 | } | 1071 | |
752 | continue; | 1072 | struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb) |
753 | } | 1073 | { |
754 | printk(KERN_NOTICE | 1074 | static struct QBUFFER *qbuffer; |
755 | "arcmsr%d: isr get an illegal ccb command done acb = '0x%p'" | 1075 | |
756 | "ccb = '0x%p' ccbacb = '0x%p' startdone = 0x%x" | 1076 | switch (acb->adapter_type) { |
757 | " ccboutstandingcount = %d \n" | 1077 | |
758 | , acb->host->host_no | 1078 | case ACB_ADAPTER_TYPE_A: { |
759 | , acb | 1079 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; |
760 | , ccb | 1080 | qbuffer = (struct QBUFFER __iomem *) ®->message_rbuffer; |
761 | , ccb->acb | 1081 | } |
762 | , ccb->startdone | 1082 | break; |
763 | , atomic_read(&acb->ccboutstandingcount)); | 1083 | |
764 | continue; | 1084 | case ACB_ADAPTER_TYPE_B: { |
765 | } | 1085 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; |
766 | id = ccb->pcmd->device->id; | 1086 | qbuffer = (struct QBUFFER __iomem *) reg->ioctl_rbuffer_reg; |
767 | lun = ccb->pcmd->device->lun; | 1087 | } |
768 | if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { | 1088 | break; |
769 | if (acb->devstate[id][lun] == ARECA_RAID_GONE) | 1089 | } |
770 | acb->devstate[id][lun] = ARECA_RAID_GOOD; | 1090 | return qbuffer; |
771 | ccb->pcmd->result = DID_OK << 16; | 1091 | } |
772 | arcmsr_ccb_complete(ccb, 1); | 1092 | |
773 | } else { | 1093 | static struct QBUFFER *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb) |
774 | switch(ccb->arcmsr_cdb.DeviceStatus) { | 1094 | { |
775 | case ARCMSR_DEV_SELECT_TIMEOUT: { | 1095 | static struct QBUFFER *pqbuffer; |
776 | acb->devstate[id][lun] = ARECA_RAID_GONE; | 1096 | |
777 | ccb->pcmd->result = DID_NO_CONNECT << 16; | 1097 | switch (acb->adapter_type) { |
778 | arcmsr_ccb_complete(ccb, 1); | 1098 | |
779 | } | 1099 | case ACB_ADAPTER_TYPE_A: { |
780 | break; | 1100 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; |
781 | case ARCMSR_DEV_ABORTED: | 1101 | pqbuffer = (struct QBUFFER *) ®->message_wbuffer; |
782 | case ARCMSR_DEV_INIT_FAIL: { | 1102 | } |
783 | acb->devstate[id][lun] = ARECA_RAID_GONE; | 1103 | break; |
784 | ccb->pcmd->result = DID_BAD_TARGET << 16; | 1104 | |
785 | arcmsr_ccb_complete(ccb, 1); | 1105 | case ACB_ADAPTER_TYPE_B: { |
786 | } | 1106 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; |
787 | break; | 1107 | pqbuffer = (struct QBUFFER __iomem *)reg->ioctl_wbuffer_reg; |
788 | case ARCMSR_DEV_CHECK_CONDITION: { | 1108 | } |
789 | acb->devstate[id][lun] = ARECA_RAID_GOOD; | 1109 | break; |
790 | arcmsr_report_sense_info(ccb); | 1110 | } |
791 | arcmsr_ccb_complete(ccb, 1); | 1111 | return pqbuffer; |
792 | } | 1112 | } |
793 | break; | 1113 | |
794 | default: | 1114 | static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) |
795 | printk(KERN_NOTICE | 1115 | { |
796 | "arcmsr%d: scsi id = %d lun = %d" | 1116 | struct QBUFFER *prbuffer; |
797 | " isr get command error done, " | 1117 | struct QBUFFER *pQbuffer; |
798 | "but got unknown DeviceStatus = 0x%x \n" | 1118 | uint8_t *iop_data; |
799 | , acb->host->host_no | 1119 | int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; |
800 | , id | 1120 | |
801 | , lun | 1121 | rqbuf_lastindex = acb->rqbuf_lastindex; |
802 | , ccb->arcmsr_cdb.DeviceStatus); | 1122 | rqbuf_firstindex = acb->rqbuf_firstindex; |
803 | acb->devstate[id][lun] = ARECA_RAID_GONE; | 1123 | prbuffer = arcmsr_get_iop_rqbuffer(acb); |
804 | ccb->pcmd->result = DID_NO_CONNECT << 16; | 1124 | iop_data = (uint8_t *)prbuffer->data; |
805 | arcmsr_ccb_complete(ccb, 1); | 1125 | iop_len = prbuffer->data_len; |
806 | break; | 1126 | my_empty_len = (rqbuf_firstindex - rqbuf_lastindex -1)&(ARCMSR_MAX_QBUFFER -1); |
807 | } | 1127 | |
808 | } | 1128 | if (my_empty_len >= iop_len) |
809 | }/*drain reply FIFO*/ | 1129 | { |
1130 | while (iop_len > 0) { | ||
1131 | pQbuffer = (struct QBUFFER *)&acb->rqbuffer[rqbuf_lastindex]; | ||
1132 | memcpy(pQbuffer, iop_data,1); | ||
1133 | rqbuf_lastindex++; | ||
1134 | rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; | ||
1135 | iop_data++; | ||
1136 | iop_len--; | ||
1137 | } | ||
1138 | acb->rqbuf_lastindex = rqbuf_lastindex; | ||
1139 | arcmsr_iop_message_read(acb); | ||
1140 | } | ||
1141 | |||
1142 | else { | ||
1143 | acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; | ||
1144 | } | ||
1145 | } | ||
1146 | |||
1147 | static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) | ||
1148 | { | ||
1149 | acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; | ||
1150 | if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) { | ||
1151 | uint8_t *pQbuffer; | ||
1152 | struct QBUFFER *pwbuffer; | ||
1153 | uint8_t *iop_data; | ||
1154 | int32_t allxfer_len = 0; | ||
1155 | |||
1156 | acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); | ||
1157 | pwbuffer = arcmsr_get_iop_wqbuffer(acb); | ||
1158 | iop_data = (uint8_t __iomem *)pwbuffer->data; | ||
1159 | |||
1160 | while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) && \ | ||
1161 | (allxfer_len < 124)) { | ||
1162 | pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; | ||
1163 | memcpy(iop_data, pQbuffer, 1); | ||
1164 | acb->wqbuf_firstindex++; | ||
1165 | acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; | ||
1166 | iop_data++; | ||
1167 | allxfer_len++; | ||
1168 | } | ||
1169 | pwbuffer->data_len = allxfer_len; | ||
1170 | |||
1171 | arcmsr_iop_message_wrote(acb); | ||
1172 | } | ||
1173 | |||
1174 | if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) { | ||
1175 | acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; | ||
1176 | } | ||
1177 | } | ||
1178 | |||
1179 | static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) | ||
1180 | { | ||
1181 | uint32_t outbound_doorbell; | ||
1182 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; | ||
1183 | |||
1184 | outbound_doorbell = readl(®->outbound_doorbell); | ||
1185 | writel(outbound_doorbell, ®->outbound_doorbell); | ||
1186 | if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { | ||
1187 | arcmsr_iop2drv_data_wrote_handle(acb); | ||
1188 | } | ||
1189 | |||
1190 | if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { | ||
1191 | arcmsr_iop2drv_data_read_handle(acb); | ||
1192 | } | ||
1193 | } | ||
1194 | |||
1195 | static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) | ||
1196 | { | ||
1197 | uint32_t flag_ccb; | ||
1198 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; | ||
1199 | |||
1200 | while ((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) { | ||
1201 | arcmsr_drain_donequeue(acb, flag_ccb); | ||
1202 | } | ||
1203 | } | ||
1204 | |||
1205 | static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) | ||
1206 | { | ||
1207 | uint32_t index; | ||
1208 | uint32_t flag_ccb; | ||
1209 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; | ||
1210 | |||
1211 | index = reg->doneq_index; | ||
1212 | |||
1213 | while ((flag_ccb = readl(®->done_qbuffer[index])) != 0) { | ||
1214 | writel(0, ®->done_qbuffer[index]); | ||
1215 | arcmsr_drain_donequeue(acb, flag_ccb); | ||
1216 | index++; | ||
1217 | index %= ARCMSR_MAX_HBB_POSTQUEUE; | ||
1218 | reg->doneq_index = index; | ||
1219 | } | ||
1220 | } | ||
1221 | |||
1222 | static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) | ||
1223 | { | ||
1224 | uint32_t outbound_intstatus; | ||
1225 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; | ||
1226 | |||
1227 | outbound_intstatus = readl(®->outbound_intstatus) & \ | ||
1228 | acb->outbound_int_enable; | ||
1229 | if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) { | ||
1230 | return 1; | ||
1231 | } | ||
1232 | writel(outbound_intstatus, ®->outbound_intstatus); | ||
1233 | if (outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { | ||
1234 | arcmsr_hba_doorbell_isr(acb); | ||
1235 | } | ||
1236 | if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { | ||
1237 | arcmsr_hba_postqueue_isr(acb); | ||
1238 | } | ||
1239 | return 0; | ||
1240 | } | ||
1241 | |||
1242 | static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) | ||
1243 | { | ||
1244 | uint32_t outbound_doorbell; | ||
1245 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; | ||
1246 | |||
1247 | outbound_doorbell = readl(reg->iop2drv_doorbell_reg) & \ | ||
1248 | acb->outbound_int_enable; | ||
1249 | if (!outbound_doorbell) | ||
1250 | return 1; | ||
1251 | |||
1252 | writel(~outbound_doorbell, reg->iop2drv_doorbell_reg); | ||
1253 | |||
1254 | if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { | ||
1255 | arcmsr_iop2drv_data_wrote_handle(acb); | ||
1256 | } | ||
1257 | if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { | ||
1258 | arcmsr_iop2drv_data_read_handle(acb); | ||
1259 | } | ||
1260 | if (outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { | ||
1261 | arcmsr_hbb_postqueue_isr(acb); | ||
1262 | } | ||
1263 | |||
1264 | return 0; | ||
1265 | } | ||
1266 | |||
1267 | static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) | ||
1268 | { | ||
1269 | switch (acb->adapter_type) { | ||
1270 | case ACB_ADAPTER_TYPE_A: { | ||
1271 | if (arcmsr_handle_hba_isr(acb)) { | ||
1272 | return IRQ_NONE; | ||
1273 | } | ||
1274 | } | ||
1275 | break; | ||
1276 | |||
1277 | case ACB_ADAPTER_TYPE_B: { | ||
1278 | if (arcmsr_handle_hbb_isr(acb)) { | ||
1279 | return IRQ_NONE; | ||
1280 | } | ||
1281 | } | ||
1282 | break; | ||
810 | } | 1283 | } |
811 | if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) | ||
812 | return IRQ_NONE; | ||
813 | return IRQ_HANDLED; | 1284 | return IRQ_HANDLED; |
814 | } | 1285 | } |
815 | 1286 | ||
@@ -818,16 +1289,47 @@ static void arcmsr_iop_parking(struct AdapterControlBlock *acb) | |||
818 | if (acb) { | 1289 | if (acb) { |
819 | /* stop adapter background rebuild */ | 1290 | /* stop adapter background rebuild */ |
820 | if (acb->acb_flags & ACB_F_MSG_START_BGRB) { | 1291 | if (acb->acb_flags & ACB_F_MSG_START_BGRB) { |
1292 | uint32_t intmask_org; | ||
821 | acb->acb_flags &= ~ACB_F_MSG_START_BGRB; | 1293 | acb->acb_flags &= ~ACB_F_MSG_START_BGRB; |
1294 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
822 | arcmsr_stop_adapter_bgrb(acb); | 1295 | arcmsr_stop_adapter_bgrb(acb); |
823 | arcmsr_flush_adapter_cache(acb); | 1296 | arcmsr_flush_adapter_cache(acb); |
1297 | arcmsr_enable_outbound_ints(acb, intmask_org); | ||
824 | } | 1298 | } |
825 | } | 1299 | } |
826 | } | 1300 | } |
827 | 1301 | ||
828 | static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_cmnd *cmd) | 1302 | void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) |
1303 | { | ||
1304 | int32_t wqbuf_firstindex, wqbuf_lastindex; | ||
1305 | uint8_t *pQbuffer; | ||
1306 | struct QBUFFER *pwbuffer; | ||
1307 | uint8_t *iop_data; | ||
1308 | int32_t allxfer_len = 0; | ||
1309 | |||
1310 | pwbuffer = arcmsr_get_iop_wqbuffer(acb); | ||
1311 | iop_data = (uint8_t __iomem *)pwbuffer->data; | ||
1312 | if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { | ||
1313 | acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); | ||
1314 | wqbuf_firstindex = acb->wqbuf_firstindex; | ||
1315 | wqbuf_lastindex = acb->wqbuf_lastindex; | ||
1316 | while ((wqbuf_firstindex != wqbuf_lastindex) && (allxfer_len < 124)) { | ||
1317 | pQbuffer = &acb->wqbuffer[wqbuf_firstindex]; | ||
1318 | memcpy(iop_data, pQbuffer, 1); | ||
1319 | wqbuf_firstindex++; | ||
1320 | wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; | ||
1321 | iop_data++; | ||
1322 | allxfer_len++; | ||
1323 | } | ||
1324 | acb->wqbuf_firstindex = wqbuf_firstindex; | ||
1325 | pwbuffer->data_len = allxfer_len; | ||
1326 | arcmsr_iop_message_wrote(acb); | ||
1327 | } | ||
1328 | } | ||
1329 | |||
1330 | static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ | ||
1331 | struct scsi_cmnd *cmd) | ||
829 | { | 1332 | { |
830 | struct MessageUnit __iomem *reg = acb->pmu; | ||
831 | struct CMD_MESSAGE_FIELD *pcmdmessagefld; | 1333 | struct CMD_MESSAGE_FIELD *pcmdmessagefld; |
832 | int retvalue = 0, transfer_len = 0; | 1334 | int retvalue = 0, transfer_len = 0; |
833 | char *buffer; | 1335 | char *buffer; |
@@ -836,7 +1338,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_ | |||
836 | (uint32_t ) cmd->cmnd[6] << 16 | | 1338 | (uint32_t ) cmd->cmnd[6] << 16 | |
837 | (uint32_t ) cmd->cmnd[7] << 8 | | 1339 | (uint32_t ) cmd->cmnd[7] << 8 | |
838 | (uint32_t ) cmd->cmnd[8]; | 1340 | (uint32_t ) cmd->cmnd[8]; |
839 | /* 4 bytes: Areca io control code */ | 1341 | /* 4 bytes: Areca io control code */ |
840 | 1342 | ||
841 | sg = scsi_sglist(cmd); | 1343 | sg = scsi_sglist(cmd); |
842 | buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | 1344 | buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; |
@@ -852,194 +1354,199 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_ | |||
852 | } | 1354 | } |
853 | pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; | 1355 | pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; |
854 | switch(controlcode) { | 1356 | switch(controlcode) { |
1357 | |||
855 | case ARCMSR_MESSAGE_READ_RQBUFFER: { | 1358 | case ARCMSR_MESSAGE_READ_RQBUFFER: { |
856 | unsigned long *ver_addr; | 1359 | unsigned long *ver_addr; |
857 | dma_addr_t buf_handle; | 1360 | dma_addr_t buf_handle; |
858 | uint8_t *pQbuffer, *ptmpQbuffer; | 1361 | uint8_t *pQbuffer, *ptmpQbuffer; |
859 | int32_t allxfer_len = 0; | 1362 | int32_t allxfer_len = 0; |
1363 | |||
1364 | ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); | ||
1365 | if (!ver_addr) { | ||
1366 | retvalue = ARCMSR_MESSAGE_FAIL; | ||
1367 | goto message_out; | ||
1368 | } | ||
1369 | ptmpQbuffer = (uint8_t *) ver_addr; | ||
1370 | while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) | ||
1371 | && (allxfer_len < 1031)) { | ||
1372 | pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; | ||
1373 | memcpy(ptmpQbuffer, pQbuffer, 1); | ||
1374 | acb->rqbuf_firstindex++; | ||
1375 | acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; | ||
1376 | ptmpQbuffer++; | ||
1377 | allxfer_len++; | ||
1378 | } | ||
1379 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | ||
860 | 1380 | ||
861 | ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); | 1381 | struct QBUFFER *prbuffer; |
862 | if (!ver_addr) { | 1382 | uint8_t *iop_data; |
863 | retvalue = ARCMSR_MESSAGE_FAIL; | 1383 | int32_t iop_len; |
864 | goto message_out; | 1384 | |
865 | } | 1385 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; |
866 | ptmpQbuffer = (uint8_t *) ver_addr; | 1386 | prbuffer = arcmsr_get_iop_rqbuffer(acb); |
867 | while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) | 1387 | iop_data = (uint8_t *)prbuffer->data; |
868 | && (allxfer_len < 1031)) { | 1388 | iop_len = readl(&prbuffer->data_len); |
869 | pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; | 1389 | while (iop_len > 0) { |
870 | memcpy(ptmpQbuffer, pQbuffer, 1); | 1390 | acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); |
871 | acb->rqbuf_firstindex++; | 1391 | acb->rqbuf_lastindex++; |
872 | acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; | 1392 | acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; |
873 | ptmpQbuffer++; | 1393 | iop_data++; |
874 | allxfer_len++; | 1394 | iop_len--; |
875 | } | ||
876 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | ||
877 | struct QBUFFER __iomem * prbuffer = (struct QBUFFER __iomem *) | ||
878 | ®->message_rbuffer; | ||
879 | uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data; | ||
880 | int32_t iop_len; | ||
881 | |||
882 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | ||
883 | iop_len = readl(&prbuffer->data_len); | ||
884 | while (iop_len > 0) { | ||
885 | acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); | ||
886 | acb->rqbuf_lastindex++; | ||
887 | acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; | ||
888 | iop_data++; | ||
889 | iop_len--; | ||
890 | } | ||
891 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, | ||
892 | ®->inbound_doorbell); | ||
893 | } | 1395 | } |
894 | memcpy(pcmdmessagefld->messagedatabuffer, | 1396 | arcmsr_iop_message_read(acb); |
895 | (uint8_t *)ver_addr, allxfer_len); | 1397 | } |
896 | pcmdmessagefld->cmdmessage.Length = allxfer_len; | 1398 | memcpy(pcmdmessagefld->messagedatabuffer, (uint8_t *)ver_addr, allxfer_len); |
897 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; | 1399 | pcmdmessagefld->cmdmessage.Length = allxfer_len; |
898 | pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); | 1400 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; |
1401 | pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); | ||
899 | } | 1402 | } |
900 | break; | 1403 | break; |
901 | case ARCMSR_MESSAGE_WRITE_WQBUFFER: { | ||
902 | unsigned long *ver_addr; | ||
903 | dma_addr_t buf_handle; | ||
904 | int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; | ||
905 | uint8_t *pQbuffer, *ptmpuserbuffer; | ||
906 | 1404 | ||
907 | ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); | 1405 | case ARCMSR_MESSAGE_WRITE_WQBUFFER: { |
908 | if (!ver_addr) { | 1406 | unsigned long *ver_addr; |
909 | retvalue = ARCMSR_MESSAGE_FAIL; | 1407 | dma_addr_t buf_handle; |
910 | goto message_out; | 1408 | int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; |
911 | } | 1409 | uint8_t *pQbuffer, *ptmpuserbuffer; |
912 | ptmpuserbuffer = (uint8_t *)ver_addr; | 1410 | |
913 | user_len = pcmdmessagefld->cmdmessage.Length; | 1411 | ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); |
914 | memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); | 1412 | if (!ver_addr) { |
915 | wqbuf_lastindex = acb->wqbuf_lastindex; | 1413 | retvalue = ARCMSR_MESSAGE_FAIL; |
916 | wqbuf_firstindex = acb->wqbuf_firstindex; | 1414 | goto message_out; |
917 | if (wqbuf_lastindex != wqbuf_firstindex) { | 1415 | } |
1416 | ptmpuserbuffer = (uint8_t *)ver_addr; | ||
1417 | user_len = pcmdmessagefld->cmdmessage.Length; | ||
1418 | memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); | ||
1419 | wqbuf_lastindex = acb->wqbuf_lastindex; | ||
1420 | wqbuf_firstindex = acb->wqbuf_firstindex; | ||
1421 | if (wqbuf_lastindex != wqbuf_firstindex) { | ||
1422 | struct SENSE_DATA *sensebuffer = | ||
1423 | (struct SENSE_DATA *)cmd->sense_buffer; | ||
1424 | arcmsr_post_ioctldata2iop(acb); | ||
1425 | /* has error report sensedata */ | ||
1426 | sensebuffer->ErrorCode = 0x70; | ||
1427 | sensebuffer->SenseKey = ILLEGAL_REQUEST; | ||
1428 | sensebuffer->AdditionalSenseLength = 0x0A; | ||
1429 | sensebuffer->AdditionalSenseCode = 0x20; | ||
1430 | sensebuffer->Valid = 1; | ||
1431 | retvalue = ARCMSR_MESSAGE_FAIL; | ||
1432 | } else { | ||
1433 | my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) | ||
1434 | &(ARCMSR_MAX_QBUFFER - 1); | ||
1435 | if (my_empty_len >= user_len) { | ||
1436 | while (user_len > 0) { | ||
1437 | pQbuffer = | ||
1438 | &acb->wqbuffer[acb->wqbuf_lastindex]; | ||
1439 | memcpy(pQbuffer, ptmpuserbuffer, 1); | ||
1440 | acb->wqbuf_lastindex++; | ||
1441 | acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; | ||
1442 | ptmpuserbuffer++; | ||
1443 | user_len--; | ||
1444 | } | ||
1445 | if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { | ||
1446 | acb->acb_flags &= | ||
1447 | ~ACB_F_MESSAGE_WQBUFFER_CLEARED; | ||
1448 | arcmsr_post_ioctldata2iop(acb); | ||
1449 | } | ||
1450 | } else { | ||
1451 | /* has error report sensedata */ | ||
918 | struct SENSE_DATA *sensebuffer = | 1452 | struct SENSE_DATA *sensebuffer = |
919 | (struct SENSE_DATA *)cmd->sense_buffer; | 1453 | (struct SENSE_DATA *)cmd->sense_buffer; |
920 | arcmsr_post_Qbuffer(acb); | ||
921 | /* has error report sensedata */ | ||
922 | sensebuffer->ErrorCode = 0x70; | 1454 | sensebuffer->ErrorCode = 0x70; |
923 | sensebuffer->SenseKey = ILLEGAL_REQUEST; | 1455 | sensebuffer->SenseKey = ILLEGAL_REQUEST; |
924 | sensebuffer->AdditionalSenseLength = 0x0A; | 1456 | sensebuffer->AdditionalSenseLength = 0x0A; |
925 | sensebuffer->AdditionalSenseCode = 0x20; | 1457 | sensebuffer->AdditionalSenseCode = 0x20; |
926 | sensebuffer->Valid = 1; | 1458 | sensebuffer->Valid = 1; |
927 | retvalue = ARCMSR_MESSAGE_FAIL; | 1459 | retvalue = ARCMSR_MESSAGE_FAIL; |
928 | } else { | 1460 | } |
929 | my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) | ||
930 | &(ARCMSR_MAX_QBUFFER - 1); | ||
931 | if (my_empty_len >= user_len) { | ||
932 | while (user_len > 0) { | ||
933 | pQbuffer = | ||
934 | &acb->wqbuffer[acb->wqbuf_lastindex]; | ||
935 | memcpy(pQbuffer, ptmpuserbuffer, 1); | ||
936 | acb->wqbuf_lastindex++; | ||
937 | acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; | ||
938 | ptmpuserbuffer++; | ||
939 | user_len--; | ||
940 | } | ||
941 | if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { | ||
942 | acb->acb_flags &= | ||
943 | ~ACB_F_MESSAGE_WQBUFFER_CLEARED; | ||
944 | arcmsr_post_Qbuffer(acb); | ||
945 | } | ||
946 | } else { | ||
947 | /* has error report sensedata */ | ||
948 | struct SENSE_DATA *sensebuffer = | ||
949 | (struct SENSE_DATA *)cmd->sense_buffer; | ||
950 | sensebuffer->ErrorCode = 0x70; | ||
951 | sensebuffer->SenseKey = ILLEGAL_REQUEST; | ||
952 | sensebuffer->AdditionalSenseLength = 0x0A; | ||
953 | sensebuffer->AdditionalSenseCode = 0x20; | ||
954 | sensebuffer->Valid = 1; | ||
955 | retvalue = ARCMSR_MESSAGE_FAIL; | ||
956 | } | ||
957 | } | 1461 | } |
958 | pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); | 1462 | pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); |
959 | } | 1463 | } |
960 | break; | 1464 | break; |
1465 | |||
961 | case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { | 1466 | case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { |
962 | uint8_t *pQbuffer = acb->rqbuffer; | 1467 | uint8_t *pQbuffer = acb->rqbuffer; |
963 | 1468 | ||
964 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | 1469 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { |
965 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | 1470 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; |
966 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, | 1471 | arcmsr_iop_message_read(acb); |
967 | ®->inbound_doorbell); | 1472 | } |
968 | } | 1473 | acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; |
969 | acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; | 1474 | acb->rqbuf_firstindex = 0; |
970 | acb->rqbuf_firstindex = 0; | 1475 | acb->rqbuf_lastindex = 0; |
971 | acb->rqbuf_lastindex = 0; | 1476 | memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); |
972 | memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); | 1477 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; |
973 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
974 | ARCMSR_MESSAGE_RETURNCODE_OK; | ||
975 | } | 1478 | } |
976 | break; | 1479 | break; |
1480 | |||
977 | case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { | 1481 | case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { |
978 | uint8_t *pQbuffer = acb->wqbuffer; | 1482 | uint8_t *pQbuffer = acb->wqbuffer; |
979 | 1483 | ||
980 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | 1484 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { |
981 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | 1485 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; |
982 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK | 1486 | arcmsr_iop_message_read(acb); |
983 | , ®->inbound_doorbell); | 1487 | } |
984 | } | 1488 | acb->acb_flags |= |
985 | acb->acb_flags |= | 1489 | (ACB_F_MESSAGE_WQBUFFER_CLEARED | |
986 | (ACB_F_MESSAGE_WQBUFFER_CLEARED | | 1490 | ACB_F_MESSAGE_WQBUFFER_READED); |
987 | ACB_F_MESSAGE_WQBUFFER_READED); | 1491 | acb->wqbuf_firstindex = 0; |
988 | acb->wqbuf_firstindex = 0; | 1492 | acb->wqbuf_lastindex = 0; |
989 | acb->wqbuf_lastindex = 0; | 1493 | memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); |
990 | memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); | 1494 | pcmdmessagefld->cmdmessage.ReturnCode = |
991 | pcmdmessagefld->cmdmessage.ReturnCode = | 1495 | ARCMSR_MESSAGE_RETURNCODE_OK; |
992 | ARCMSR_MESSAGE_RETURNCODE_OK; | ||
993 | } | 1496 | } |
994 | break; | 1497 | break; |
1498 | |||
995 | case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { | 1499 | case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { |
996 | uint8_t *pQbuffer; | 1500 | uint8_t *pQbuffer; |
997 | 1501 | ||
998 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | 1502 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { |
999 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | 1503 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; |
1000 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK | 1504 | arcmsr_iop_message_read(acb); |
1001 | , ®->inbound_doorbell); | 1505 | } |
1002 | } | 1506 | acb->acb_flags |= |
1003 | acb->acb_flags |= | 1507 | (ACB_F_MESSAGE_WQBUFFER_CLEARED |
1004 | (ACB_F_MESSAGE_WQBUFFER_CLEARED | 1508 | | ACB_F_MESSAGE_RQBUFFER_CLEARED |
1005 | | ACB_F_MESSAGE_RQBUFFER_CLEARED | 1509 | | ACB_F_MESSAGE_WQBUFFER_READED); |
1006 | | ACB_F_MESSAGE_WQBUFFER_READED); | 1510 | acb->rqbuf_firstindex = 0; |
1007 | acb->rqbuf_firstindex = 0; | 1511 | acb->rqbuf_lastindex = 0; |
1008 | acb->rqbuf_lastindex = 0; | 1512 | acb->wqbuf_firstindex = 0; |
1009 | acb->wqbuf_firstindex = 0; | 1513 | acb->wqbuf_lastindex = 0; |
1010 | acb->wqbuf_lastindex = 0; | 1514 | pQbuffer = acb->rqbuffer; |
1011 | pQbuffer = acb->rqbuffer; | 1515 | memset(pQbuffer, 0, sizeof(struct QBUFFER)); |
1012 | memset(pQbuffer, 0, sizeof (struct QBUFFER)); | 1516 | pQbuffer = acb->wqbuffer; |
1013 | pQbuffer = acb->wqbuffer; | 1517 | memset(pQbuffer, 0, sizeof(struct QBUFFER)); |
1014 | memset(pQbuffer, 0, sizeof (struct QBUFFER)); | 1518 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; |
1015 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; | ||
1016 | } | 1519 | } |
1017 | break; | 1520 | break; |
1521 | |||
1018 | case ARCMSR_MESSAGE_RETURN_CODE_3F: { | 1522 | case ARCMSR_MESSAGE_RETURN_CODE_3F: { |
1019 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; | 1523 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; |
1020 | } | 1524 | } |
1021 | break; | 1525 | break; |
1526 | |||
1022 | case ARCMSR_MESSAGE_SAY_HELLO: { | 1527 | case ARCMSR_MESSAGE_SAY_HELLO: { |
1023 | int8_t * hello_string = "Hello! I am ARCMSR"; | 1528 | int8_t *hello_string = "Hello! I am ARCMSR"; |
1024 | 1529 | ||
1025 | memcpy(pcmdmessagefld->messagedatabuffer, hello_string | 1530 | memcpy(pcmdmessagefld->messagedatabuffer, hello_string |
1026 | , (int16_t)strlen(hello_string)); | 1531 | , (int16_t)strlen(hello_string)); |
1027 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; | 1532 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; |
1028 | } | 1533 | } |
1029 | break; | 1534 | break; |
1535 | |||
1030 | case ARCMSR_MESSAGE_SAY_GOODBYE: | 1536 | case ARCMSR_MESSAGE_SAY_GOODBYE: |
1031 | arcmsr_iop_parking(acb); | 1537 | arcmsr_iop_parking(acb); |
1032 | break; | 1538 | break; |
1539 | |||
1033 | case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: | 1540 | case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: |
1034 | arcmsr_flush_adapter_cache(acb); | 1541 | arcmsr_flush_adapter_cache(acb); |
1035 | break; | 1542 | break; |
1543 | |||
1036 | default: | 1544 | default: |
1037 | retvalue = ARCMSR_MESSAGE_FAIL; | 1545 | retvalue = ARCMSR_MESSAGE_FAIL; |
1038 | } | 1546 | } |
1039 | message_out: | 1547 | message_out: |
1040 | sg = scsi_sglist(cmd); | 1548 | sg = scsi_sglist(cmd); |
1041 | kunmap_atomic(buffer - sg->offset, KM_IRQ0); | 1549 | kunmap_atomic(buffer - sg->offset, KM_IRQ0); |
1042 | |||
1043 | return retvalue; | 1550 | return retvalue; |
1044 | } | 1551 | } |
1045 | 1552 | ||
@@ -1109,8 +1616,7 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, | |||
1109 | void (* done)(struct scsi_cmnd *)) | 1616 | void (* done)(struct scsi_cmnd *)) |
1110 | { | 1617 | { |
1111 | struct Scsi_Host *host = cmd->device->host; | 1618 | struct Scsi_Host *host = cmd->device->host; |
1112 | struct AdapterControlBlock *acb = | 1619 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; |
1113 | (struct AdapterControlBlock *) host->hostdata; | ||
1114 | struct CommandControlBlock *ccb; | 1620 | struct CommandControlBlock *ccb; |
1115 | int target = cmd->device->id; | 1621 | int target = cmd->device->id; |
1116 | int lun = cmd->device->lun; | 1622 | int lun = cmd->device->lun; |
@@ -1153,26 +1659,27 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, | |||
1153 | ccb = arcmsr_get_freeccb(acb); | 1659 | ccb = arcmsr_get_freeccb(acb); |
1154 | if (!ccb) | 1660 | if (!ccb) |
1155 | return SCSI_MLQUEUE_HOST_BUSY; | 1661 | return SCSI_MLQUEUE_HOST_BUSY; |
1662 | |||
1156 | arcmsr_build_ccb(acb, ccb, cmd); | 1663 | arcmsr_build_ccb(acb, ccb, cmd); |
1157 | arcmsr_post_ccb(acb, ccb); | 1664 | arcmsr_post_ccb(acb, ccb); |
1158 | return 0; | 1665 | return 0; |
1159 | } | 1666 | } |
1160 | 1667 | ||
1161 | static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) | 1668 | static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) |
1162 | { | 1669 | { |
1163 | struct MessageUnit __iomem *reg = acb->pmu; | 1670 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; |
1164 | char *acb_firm_model = acb->firm_model; | 1671 | char *acb_firm_model = acb->firm_model; |
1165 | char *acb_firm_version = acb->firm_version; | 1672 | char *acb_firm_version = acb->firm_version; |
1166 | char __iomem *iop_firm_model = (char __iomem *) ®->message_rwbuffer[15]; | 1673 | char *iop_firm_model = (char *) (®->message_rwbuffer[15]); |
1167 | char __iomem *iop_firm_version = (char __iomem *) ®->message_rwbuffer[17]; | 1674 | char *iop_firm_version = (char *) (®->message_rwbuffer[17]); |
1168 | int count; | 1675 | int count; |
1169 | 1676 | ||
1170 | writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); | 1677 | writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); |
1171 | if (arcmsr_wait_msgint_ready(acb)) | 1678 | if (arcmsr_hba_wait_msgint_ready(acb)) { |
1172 | printk(KERN_NOTICE | 1679 | printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ |
1173 | "arcmsr%d: wait " | 1680 | miscellaneous data' timeout \n", acb->host->host_no); |
1174 | "'get adapter firmware miscellaneous data' timeout \n" | 1681 | } |
1175 | , acb->host->host_no); | 1682 | |
1176 | count = 8; | 1683 | count = 8; |
1177 | while (count) { | 1684 | while (count) { |
1178 | *acb_firm_model = readb(iop_firm_model); | 1685 | *acb_firm_model = readb(iop_firm_model); |
@@ -1180,6 +1687,7 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) | |||
1180 | iop_firm_model++; | 1687 | iop_firm_model++; |
1181 | count--; | 1688 | count--; |
1182 | } | 1689 | } |
1690 | |||
1183 | count = 16; | 1691 | count = 16; |
1184 | while (count) { | 1692 | while (count) { |
1185 | *acb_firm_version = readb(iop_firm_version); | 1693 | *acb_firm_version = readb(iop_firm_version); |
@@ -1187,28 +1695,93 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) | |||
1187 | iop_firm_version++; | 1695 | iop_firm_version++; |
1188 | count--; | 1696 | count--; |
1189 | } | 1697 | } |
1190 | printk(KERN_INFO | 1698 | |
1191 | "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n" | 1699 | printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n" |
1192 | , acb->host->host_no | 1700 | , acb->host->host_no |
1193 | , acb->firm_version); | 1701 | , acb->firm_version); |
1702 | |||
1194 | acb->firm_request_len = readl(®->message_rwbuffer[1]); | 1703 | acb->firm_request_len = readl(®->message_rwbuffer[1]); |
1195 | acb->firm_numbers_queue = readl(®->message_rwbuffer[2]); | 1704 | acb->firm_numbers_queue = readl(®->message_rwbuffer[2]); |
1196 | acb->firm_sdram_size = readl(®->message_rwbuffer[3]); | 1705 | acb->firm_sdram_size = readl(®->message_rwbuffer[3]); |
1197 | acb->firm_hd_channels = readl(®->message_rwbuffer[4]); | 1706 | acb->firm_hd_channels = readl(®->message_rwbuffer[4]); |
1198 | } | 1707 | } |
1199 | 1708 | ||
1200 | static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, | 1709 | static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) |
1710 | { | ||
1711 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; | ||
1712 | uint32_t *lrwbuffer = reg->msgcode_rwbuffer_reg; | ||
1713 | char *acb_firm_model = acb->firm_model; | ||
1714 | char *acb_firm_version = acb->firm_version; | ||
1715 | char *iop_firm_model = (char *) (&lrwbuffer[15]); | ||
1716 | /*firm_model,15,60-67*/ | ||
1717 | char *iop_firm_version = (char *) (&lrwbuffer[17]); | ||
1718 | /*firm_version,17,68-83*/ | ||
1719 | int count; | ||
1720 | |||
1721 | writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell_reg); | ||
1722 | if (arcmsr_hbb_wait_msgint_ready(acb)) { | ||
1723 | printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ | ||
1724 | miscellaneous data' timeout \n", acb->host->host_no); | ||
1725 | } | ||
1726 | |||
1727 | count = 8; | ||
1728 | while (count) | ||
1729 | { | ||
1730 | *acb_firm_model = readb(iop_firm_model); | ||
1731 | acb_firm_model++; | ||
1732 | iop_firm_model++; | ||
1733 | count--; | ||
1734 | } | ||
1735 | |||
1736 | count = 16; | ||
1737 | while (count) | ||
1738 | { | ||
1739 | *acb_firm_version = readb(iop_firm_version); | ||
1740 | acb_firm_version++; | ||
1741 | iop_firm_version++; | ||
1742 | count--; | ||
1743 | } | ||
1744 | |||
1745 | printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", | ||
1746 | acb->host->host_no, | ||
1747 | acb->firm_version); | ||
1748 | |||
1749 | lrwbuffer++; | ||
1750 | acb->firm_request_len = readl(lrwbuffer++); | ||
1751 | /*firm_request_len,1,04-07*/ | ||
1752 | acb->firm_numbers_queue = readl(lrwbuffer++); | ||
1753 | /*firm_numbers_queue,2,08-11*/ | ||
1754 | acb->firm_sdram_size = readl(lrwbuffer++); | ||
1755 | /*firm_sdram_size,3,12-15*/ | ||
1756 | acb->firm_hd_channels = readl(lrwbuffer); | ||
1757 | /*firm_ide_channels,4,16-19*/ | ||
1758 | } | ||
1759 | |||
1760 | static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) | ||
1761 | { | ||
1762 | switch (acb->adapter_type) { | ||
1763 | case ACB_ADAPTER_TYPE_A: { | ||
1764 | arcmsr_get_hba_config(acb); | ||
1765 | } | ||
1766 | break; | ||
1767 | |||
1768 | case ACB_ADAPTER_TYPE_B: { | ||
1769 | arcmsr_get_hbb_config(acb); | ||
1770 | } | ||
1771 | break; | ||
1772 | } | ||
1773 | } | ||
1774 | |||
1775 | static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, | ||
1201 | struct CommandControlBlock *poll_ccb) | 1776 | struct CommandControlBlock *poll_ccb) |
1202 | { | 1777 | { |
1203 | struct MessageUnit __iomem *reg = acb->pmu; | 1778 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; |
1204 | struct CommandControlBlock *ccb; | 1779 | struct CommandControlBlock *ccb; |
1205 | uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0; | 1780 | uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0; |
1206 | int id, lun; | ||
1207 | 1781 | ||
1208 | polling_ccb_retry: | 1782 | polling_hba_ccb_retry: |
1209 | poll_count++; | 1783 | poll_count++; |
1210 | outbound_intstatus = readl(®->outbound_intstatus) | 1784 | outbound_intstatus = readl(®->outbound_intstatus) & acb->outbound_int_enable; |
1211 | & acb->outbound_int_enable; | ||
1212 | writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/ | 1785 | writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/ |
1213 | while (1) { | 1786 | while (1) { |
1214 | if ((flag_ccb = readl(®->outbound_queueport)) == 0xFFFFFFFF) { | 1787 | if ((flag_ccb = readl(®->outbound_queueport)) == 0xFFFFFFFF) { |
@@ -1218,17 +1791,14 @@ static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, | |||
1218 | msleep(25); | 1791 | msleep(25); |
1219 | if (poll_count > 100) | 1792 | if (poll_count > 100) |
1220 | break; | 1793 | break; |
1221 | goto polling_ccb_retry; | 1794 | goto polling_hba_ccb_retry; |
1222 | } | 1795 | } |
1223 | } | 1796 | } |
1224 | ccb = (struct CommandControlBlock *) | 1797 | ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + (flag_ccb << 5)); |
1225 | (acb->vir2phy_offset + (flag_ccb << 5)); | 1798 | poll_ccb_done = (ccb == poll_ccb) ? 1:0; |
1226 | if ((ccb->acb != acb) || | 1799 | if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { |
1227 | (ccb->startdone != ARCMSR_CCB_START)) { | 1800 | if ((ccb->startdone == ARCMSR_CCB_ABORTED) || (ccb == poll_ccb)) { |
1228 | if ((ccb->startdone == ARCMSR_CCB_ABORTED) || | 1801 | printk(KERN_NOTICE "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'" |
1229 | (ccb == poll_ccb)) { | ||
1230 | printk(KERN_NOTICE | ||
1231 | "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'" | ||
1232 | " poll command abort successfully \n" | 1802 | " poll command abort successfully \n" |
1233 | , acb->host->host_no | 1803 | , acb->host->host_no |
1234 | , ccb->pcmd->device->id | 1804 | , ccb->pcmd->device->id |
@@ -1239,176 +1809,280 @@ static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, | |||
1239 | poll_ccb_done = 1; | 1809 | poll_ccb_done = 1; |
1240 | continue; | 1810 | continue; |
1241 | } | 1811 | } |
1242 | printk(KERN_NOTICE | 1812 | printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb" |
1243 | "arcmsr%d: polling get an illegal ccb" | 1813 | " command done ccb = '0x%p'" |
1244 | " command done ccb ='0x%p'" | ||
1245 | "ccboutstandingcount = %d \n" | 1814 | "ccboutstandingcount = %d \n" |
1246 | , acb->host->host_no | 1815 | , acb->host->host_no |
1247 | , ccb | 1816 | , ccb |
1248 | , atomic_read(&acb->ccboutstandingcount)); | 1817 | , atomic_read(&acb->ccboutstandingcount)); |
1249 | continue; | 1818 | continue; |
1250 | } | 1819 | } |
1251 | id = ccb->pcmd->device->id; | 1820 | arcmsr_report_ccb_state(acb, ccb, flag_ccb); |
1252 | lun = ccb->pcmd->device->lun; | 1821 | } |
1253 | if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { | 1822 | } |
1254 | if (acb->devstate[id][lun] == ARECA_RAID_GONE) | 1823 | |
1255 | acb->devstate[id][lun] = ARECA_RAID_GOOD; | 1824 | static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \ |
1256 | ccb->pcmd->result = DID_OK << 16; | 1825 | struct CommandControlBlock *poll_ccb) |
1257 | arcmsr_ccb_complete(ccb, 1); | 1826 | { |
1258 | } else { | 1827 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; |
1259 | switch(ccb->arcmsr_cdb.DeviceStatus) { | 1828 | struct CommandControlBlock *ccb; |
1260 | case ARCMSR_DEV_SELECT_TIMEOUT: { | 1829 | uint32_t flag_ccb, poll_ccb_done = 0, poll_count = 0; |
1261 | acb->devstate[id][lun] = ARECA_RAID_GONE; | 1830 | int index; |
1262 | ccb->pcmd->result = DID_NO_CONNECT << 16; | 1831 | |
1263 | arcmsr_ccb_complete(ccb, 1); | 1832 | polling_hbb_ccb_retry: |
1264 | } | 1833 | poll_count++; |
1265 | break; | 1834 | /* clear doorbell interrupt */ |
1266 | case ARCMSR_DEV_ABORTED: | 1835 | writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg); |
1267 | case ARCMSR_DEV_INIT_FAIL: { | 1836 | while (1) { |
1268 | acb->devstate[id][lun] = ARECA_RAID_GONE; | 1837 | index = reg->doneq_index; |
1269 | ccb->pcmd->result = DID_BAD_TARGET << 16; | 1838 | if ((flag_ccb = readl(®->done_qbuffer[index])) == 0) { |
1270 | arcmsr_ccb_complete(ccb, 1); | 1839 | if (poll_ccb_done) |
1840 | break; | ||
1841 | else { | ||
1842 | msleep(25); | ||
1843 | if (poll_count > 100) | ||
1844 | break; | ||
1845 | goto polling_hbb_ccb_retry; | ||
1271 | } | 1846 | } |
1272 | break; | 1847 | } |
1273 | case ARCMSR_DEV_CHECK_CONDITION: { | 1848 | writel(0, ®->done_qbuffer[index]); |
1274 | acb->devstate[id][lun] = ARECA_RAID_GOOD; | 1849 | index++; |
1275 | arcmsr_report_sense_info(ccb); | 1850 | /*if last index number set it to 0 */ |
1851 | index %= ARCMSR_MAX_HBB_POSTQUEUE; | ||
1852 | reg->doneq_index = index; | ||
1853 | /* check ifcommand done with no error*/ | ||
1854 | ccb = (struct CommandControlBlock *)\ | ||
1855 | (acb->vir2phy_offset + (flag_ccb << 5));/*frame must be 32 bytes aligned*/ | ||
1856 | poll_ccb_done = (ccb == poll_ccb) ? 1:0; | ||
1857 | if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { | ||
1858 | if (ccb->startdone == ARCMSR_CCB_ABORTED) { | ||
1859 | printk(KERN_NOTICE "arcmsr%d: \ | ||
1860 | scsi id = %d lun = %d ccb = '0x%p' poll command abort successfully \n" | ||
1861 | ,acb->host->host_no | ||
1862 | ,ccb->pcmd->device->id | ||
1863 | ,ccb->pcmd->device->lun | ||
1864 | ,ccb); | ||
1865 | ccb->pcmd->result = DID_ABORT << 16; | ||
1276 | arcmsr_ccb_complete(ccb, 1); | 1866 | arcmsr_ccb_complete(ccb, 1); |
1867 | continue; | ||
1277 | } | 1868 | } |
1278 | break; | 1869 | printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb" |
1279 | default: | 1870 | " command done ccb = '0x%p'" |
1280 | printk(KERN_NOTICE | 1871 | "ccboutstandingcount = %d \n" |
1281 | "arcmsr%d: scsi id = %d lun = %d" | ||
1282 | " polling and getting command error done" | ||
1283 | "but got unknown DeviceStatus = 0x%x \n" | ||
1284 | , acb->host->host_no | 1872 | , acb->host->host_no |
1285 | , id | 1873 | , ccb |
1286 | , lun | 1874 | , atomic_read(&acb->ccboutstandingcount)); |
1287 | , ccb->arcmsr_cdb.DeviceStatus); | 1875 | continue; |
1288 | acb->devstate[id][lun] = ARECA_RAID_GONE; | ||
1289 | ccb->pcmd->result = DID_BAD_TARGET << 16; | ||
1290 | arcmsr_ccb_complete(ccb, 1); | ||
1291 | break; | ||
1292 | } | 1876 | } |
1877 | arcmsr_report_ccb_state(acb, ccb, flag_ccb); | ||
1878 | } /*drain reply FIFO*/ | ||
1879 | } | ||
1880 | |||
1881 | static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, \ | ||
1882 | struct CommandControlBlock *poll_ccb) | ||
1883 | { | ||
1884 | switch (acb->adapter_type) { | ||
1885 | |||
1886 | case ACB_ADAPTER_TYPE_A: { | ||
1887 | arcmsr_polling_hba_ccbdone(acb,poll_ccb); | ||
1888 | } | ||
1889 | break; | ||
1890 | |||
1891 | case ACB_ADAPTER_TYPE_B: { | ||
1892 | arcmsr_polling_hbb_ccbdone(acb,poll_ccb); | ||
1293 | } | 1893 | } |
1294 | } | 1894 | } |
1295 | } | 1895 | } |
1296 | static void arcmsr_done4_abort_postqueue(struct AdapterControlBlock *acb) | 1896 | |
1897 | static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) | ||
1297 | { | 1898 | { |
1298 | int i = 0, found = 0; | 1899 | uint32_t cdb_phyaddr, ccb_phyaddr_hi32; |
1299 | int id, lun; | 1900 | dma_addr_t dma_coherent_handle; |
1300 | uint32_t flag_ccb, outbound_intstatus; | 1901 | /* |
1301 | struct MessageUnit __iomem *reg = acb->pmu; | 1902 | ******************************************************************** |
1302 | struct CommandControlBlock *ccb; | 1903 | ** here we need to tell iop 331 our freeccb.HighPart |
1303 | /*clear and abort all outbound posted Q*/ | 1904 | ** if freeccb.HighPart is not zero |
1304 | 1905 | ******************************************************************** | |
1305 | while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) && | 1906 | */ |
1306 | (i++ < 256)){ | 1907 | dma_coherent_handle = acb->dma_coherent_handle; |
1307 | ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + | 1908 | cdb_phyaddr = (uint32_t)(dma_coherent_handle); |
1308 | (flag_ccb << 5)); | 1909 | ccb_phyaddr_hi32 = (uint32_t)((cdb_phyaddr >> 16) >> 16); |
1309 | if (ccb){ | 1910 | /* |
1310 | if ((ccb->acb != acb)||(ccb->startdone != \ | 1911 | *********************************************************************** |
1311 | ARCMSR_CCB_START)){ | 1912 | ** if adapter type B, set window of "post command Q" |
1312 | printk(KERN_NOTICE "arcmsr%d: polling get \ | 1913 | *********************************************************************** |
1313 | an illegal ccb" "command done ccb = '0x%p'""ccboutstandingcount = %d \n", | 1914 | */ |
1314 | acb->host->host_no, ccb, | 1915 | switch (acb->adapter_type) { |
1315 | atomic_read(&acb->ccboutstandingcount)); | 1916 | |
1316 | continue; | 1917 | case ACB_ADAPTER_TYPE_A: { |
1918 | if (ccb_phyaddr_hi32 != 0) { | ||
1919 | struct MessageUnit_A __iomem *reg = \ | ||
1920 | (struct MessageUnit_A *)acb->pmu; | ||
1921 | uint32_t intmask_org; | ||
1922 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
1923 | writel(ARCMSR_SIGNATURE_SET_CONFIG, \ | ||
1924 | ®->message_rwbuffer[0]); | ||
1925 | writel(ccb_phyaddr_hi32, ®->message_rwbuffer[1]); | ||
1926 | writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, \ | ||
1927 | ®->inbound_msgaddr0); | ||
1928 | if (arcmsr_hba_wait_msgint_ready(acb)) { | ||
1929 | printk(KERN_NOTICE "arcmsr%d: ""set ccb high \ | ||
1930 | part physical address timeout\n", | ||
1931 | acb->host->host_no); | ||
1932 | return 1; | ||
1317 | } | 1933 | } |
1934 | arcmsr_enable_outbound_ints(acb, intmask_org); | ||
1935 | } | ||
1936 | } | ||
1937 | break; | ||
1318 | 1938 | ||
1319 | id = ccb->pcmd->device->id; | 1939 | case ACB_ADAPTER_TYPE_B: { |
1320 | lun = ccb->pcmd->device->lun; | 1940 | unsigned long post_queue_phyaddr; |
1321 | if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)){ | 1941 | uint32_t *rwbuffer; |
1322 | if (acb->devstate[id][lun] == ARECA_RAID_GONE) | ||
1323 | acb->devstate[id][lun] = ARECA_RAID_GOOD; | ||
1324 | ccb->pcmd->result = DID_OK << 16; | ||
1325 | arcmsr_ccb_complete(ccb, 1); | ||
1326 | } | ||
1327 | else { | ||
1328 | switch(ccb->arcmsr_cdb.DeviceStatus) { | ||
1329 | case ARCMSR_DEV_SELECT_TIMEOUT: { | ||
1330 | acb->devstate[id][lun] = ARECA_RAID_GONE; | ||
1331 | ccb->pcmd->result = DID_NO_CONNECT << 16; | ||
1332 | arcmsr_ccb_complete(ccb, 1); | ||
1333 | } | ||
1334 | break; | ||
1335 | 1942 | ||
1336 | case ARCMSR_DEV_ABORTED: | 1943 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; |
1944 | uint32_t intmask_org; | ||
1945 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
1946 | reg->postq_index = 0; | ||
1947 | reg->doneq_index = 0; | ||
1948 | writel(ARCMSR_MESSAGE_SET_POST_WINDOW, reg->drv2iop_doorbell_reg); | ||
1949 | if (arcmsr_hbb_wait_msgint_ready(acb)) { | ||
1950 | printk(KERN_NOTICE "arcmsr%d:can not set diver mode\n", \ | ||
1951 | acb->host->host_no); | ||
1952 | return 1; | ||
1953 | } | ||
1954 | post_queue_phyaddr = cdb_phyaddr + ARCMSR_MAX_FREECCB_NUM * \ | ||
1955 | sizeof(struct CommandControlBlock) + offsetof(struct MessageUnit_B, post_qbuffer) ; | ||
1956 | rwbuffer = reg->msgcode_rwbuffer_reg; | ||
1957 | /* driver "set config" signature */ | ||
1958 | writel(ARCMSR_SIGNATURE_SET_CONFIG, rwbuffer++); | ||
1959 | /* normal should be zero */ | ||
1960 | writel(ccb_phyaddr_hi32, rwbuffer++); | ||
1961 | /* postQ size (256 + 8)*4 */ | ||
1962 | writel(post_queue_phyaddr, rwbuffer++); | ||
1963 | /* doneQ size (256 + 8)*4 */ | ||
1964 | writel(post_queue_phyaddr + 1056, rwbuffer++); | ||
1965 | /* ccb maxQ size must be --> [(256 + 8)*4]*/ | ||
1966 | writel(1056, rwbuffer); | ||
1967 | |||
1968 | writel(ARCMSR_MESSAGE_SET_CONFIG, reg->drv2iop_doorbell_reg); | ||
1969 | if (arcmsr_hbb_wait_msgint_ready(acb)) { | ||
1970 | printk(KERN_NOTICE "arcmsr%d: 'set command Q window' \ | ||
1971 | timeout \n",acb->host->host_no); | ||
1972 | return 1; | ||
1973 | } | ||
1337 | 1974 | ||
1338 | case ARCMSR_DEV_INIT_FAIL: { | 1975 | writel(ARCMSR_MESSAGE_START_DRIVER_MODE, reg->drv2iop_doorbell_reg); |
1339 | acb->devstate[id][lun] = | 1976 | if (arcmsr_hbb_wait_msgint_ready(acb)) { |
1340 | ARECA_RAID_GONE; | 1977 | printk(KERN_NOTICE "arcmsr%d: 'can not set diver mode \n"\ |
1341 | ccb->pcmd->result = | 1978 | ,acb->host->host_no); |
1342 | DID_BAD_TARGET << 16; | 1979 | return 1; |
1343 | arcmsr_ccb_complete(ccb, 1); | 1980 | } |
1344 | } | 1981 | arcmsr_enable_outbound_ints(acb, intmask_org); |
1345 | break; | 1982 | } |
1983 | break; | ||
1984 | } | ||
1985 | return 0; | ||
1986 | } | ||
1346 | 1987 | ||
1347 | case ARCMSR_DEV_CHECK_CONDITION: { | 1988 | static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) |
1348 | acb->devstate[id][lun] = | 1989 | { |
1349 | ARECA_RAID_GOOD; | 1990 | uint32_t firmware_state = 0; |
1350 | arcmsr_report_sense_info(ccb); | ||
1351 | arcmsr_ccb_complete(ccb, 1); | ||
1352 | } | ||
1353 | break; | ||
1354 | 1991 | ||
1355 | default: | 1992 | switch (acb->adapter_type) { |
1356 | printk(KERN_NOTICE | 1993 | |
1357 | "arcmsr%d: scsi id = %d \ | 1994 | case ACB_ADAPTER_TYPE_A: { |
1358 | lun = %d""polling and \ | 1995 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; |
1359 | getting command error \ | 1996 | do { |
1360 | done""but got unknown \ | 1997 | firmware_state = readl(®->outbound_msgaddr1); |
1361 | DeviceStatus = 0x%x \n", | 1998 | } while ((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0); |
1362 | acb->host->host_no, id, | 1999 | } |
1363 | lun, ccb->arcmsr_cdb.DeviceStatus); | 2000 | break; |
1364 | acb->devstate[id][lun] = | 2001 | |
1365 | ARECA_RAID_GONE; | 2002 | case ACB_ADAPTER_TYPE_B: { |
1366 | ccb->pcmd->result = | 2003 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; |
1367 | DID_BAD_TARGET << 16; | 2004 | do { |
1368 | arcmsr_ccb_complete(ccb, 1); | 2005 | firmware_state = readl(reg->iop2drv_doorbell_reg); |
1369 | break; | 2006 | } while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0); |
1370 | } | 2007 | } |
1371 | } | 2008 | break; |
1372 | found = 1; | ||
1373 | } | ||
1374 | } | 2009 | } |
1375 | if (found){ | 2010 | } |
1376 | outbound_intstatus = readl(®->outbound_intstatus) & \ | 2011 | |
1377 | acb->outbound_int_enable; | 2012 | static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) |
1378 | writel(outbound_intstatus, ®->outbound_intstatus); | 2013 | { |
1379 | /*clear interrupt*/ | 2014 | struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; |
2015 | acb->acb_flags |= ACB_F_MSG_START_BGRB; | ||
2016 | writel(ARCMSR_INBOUND_MESG0_START_BGRB, ®->inbound_msgaddr0); | ||
2017 | if (arcmsr_hba_wait_msgint_ready(acb)) { | ||
2018 | printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \ | ||
2019 | rebulid' timeout \n", acb->host->host_no); | ||
1380 | } | 2020 | } |
1381 | return; | ||
1382 | } | 2021 | } |
1383 | 2022 | ||
2023 | static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) | ||
2024 | { | ||
2025 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; | ||
2026 | acb->acb_flags |= ACB_F_MSG_START_BGRB; | ||
2027 | writel(ARCMSR_MESSAGE_START_BGRB, reg->drv2iop_doorbell_reg); | ||
2028 | if (arcmsr_hbb_wait_msgint_ready(acb)) { | ||
2029 | printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \ | ||
2030 | rebulid' timeout \n",acb->host->host_no); | ||
2031 | } | ||
2032 | } | ||
1384 | 2033 | ||
1385 | static void arcmsr_iop_init(struct AdapterControlBlock *acb) | 2034 | static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) |
1386 | { | 2035 | { |
1387 | struct MessageUnit __iomem *reg = acb->pmu; | 2036 | switch (acb->adapter_type) { |
1388 | uint32_t intmask_org, mask, outbound_doorbell, firmware_state = 0; | 2037 | case ACB_ADAPTER_TYPE_A: |
2038 | arcmsr_start_hba_bgrb(acb); | ||
2039 | break; | ||
2040 | case ACB_ADAPTER_TYPE_B: | ||
2041 | arcmsr_start_hbb_bgrb(acb); | ||
2042 | break; | ||
2043 | } | ||
2044 | } | ||
1389 | 2045 | ||
1390 | do { | 2046 | static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb) |
1391 | firmware_state = readl(®->outbound_msgaddr1); | 2047 | { |
1392 | } while (!(firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK)); | 2048 | switch (acb->adapter_type) { |
1393 | intmask_org = readl(®->outbound_intmask) | 2049 | case ACB_ADAPTER_TYPE_A: { |
1394 | | ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; | 2050 | struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu; |
1395 | arcmsr_get_firmware_spec(acb); | 2051 | uint32_t outbound_doorbell; |
2052 | /* empty doorbell Qbuffer if door bell ringed */ | ||
2053 | outbound_doorbell = readl(®->outbound_doorbell); | ||
2054 | /*clear doorbell interrupt */ | ||
2055 | writel(outbound_doorbell, ®->outbound_doorbell); | ||
2056 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); | ||
2057 | } | ||
2058 | break; | ||
1396 | 2059 | ||
1397 | acb->acb_flags |= ACB_F_MSG_START_BGRB; | 2060 | case ACB_ADAPTER_TYPE_B: { |
1398 | writel(ARCMSR_INBOUND_MESG0_START_BGRB, ®->inbound_msgaddr0); | 2061 | struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; |
1399 | if (arcmsr_wait_msgint_ready(acb)) { | 2062 | /*clear interrupt and message state*/ |
1400 | printk(KERN_NOTICE "arcmsr%d: " | 2063 | writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg); |
1401 | "wait 'start adapter background rebulid' timeout\n", | 2064 | writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg); |
1402 | acb->host->host_no); | 2065 | /* let IOP know data has been read */ |
2066 | } | ||
2067 | break; | ||
1403 | } | 2068 | } |
2069 | } | ||
1404 | 2070 | ||
1405 | outbound_doorbell = readl(®->outbound_doorbell); | 2071 | static void arcmsr_iop_init(struct AdapterControlBlock *acb) |
1406 | writel(outbound_doorbell, ®->outbound_doorbell); | 2072 | { |
1407 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); | 2073 | uint32_t intmask_org; |
1408 | mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | 2074 | |
1409 | | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); | 2075 | arcmsr_wait_firmware_ready(acb); |
1410 | writel(intmask_org & mask, ®->outbound_intmask); | 2076 | arcmsr_iop_confirm(acb); |
1411 | acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; | 2077 | /* disable all outbound interrupt */ |
2078 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
2079 | arcmsr_get_firmware_spec(acb); | ||
2080 | /*start background rebuild*/ | ||
2081 | arcmsr_start_adapter_bgrb(acb); | ||
2082 | /* empty doorbell Qbuffer if door bell ringed */ | ||
2083 | arcmsr_clear_doorbell_queue_buffer(acb); | ||
2084 | /* enable outbound Post Queue,outbound doorbell Interrupt */ | ||
2085 | arcmsr_enable_outbound_ints(acb, intmask_org); | ||
1412 | acb->acb_flags |= ACB_F_IOP_INITED; | 2086 | acb->acb_flags |= ACB_F_IOP_INITED; |
1413 | } | 2087 | } |
1414 | 2088 | ||
@@ -1422,21 +2096,21 @@ static void arcmsr_iop_reset(struct AdapterControlBlock *acb) | |||
1422 | /* talk to iop 331 outstanding command aborted */ | 2096 | /* talk to iop 331 outstanding command aborted */ |
1423 | arcmsr_abort_allcmd(acb); | 2097 | arcmsr_abort_allcmd(acb); |
1424 | /* wait for 3 sec for all command aborted*/ | 2098 | /* wait for 3 sec for all command aborted*/ |
1425 | msleep_interruptible(3000); | 2099 | ssleep(3); |
1426 | /* disable all outbound interrupt */ | 2100 | /* disable all outbound interrupt */ |
1427 | intmask_org = arcmsr_disable_outbound_ints(acb); | 2101 | intmask_org = arcmsr_disable_outbound_ints(acb); |
1428 | /* clear all outbound posted Q */ | 2102 | /* clear all outbound posted Q */ |
1429 | arcmsr_done4_abort_postqueue(acb); | 2103 | arcmsr_done4abort_postqueue(acb); |
1430 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { | 2104 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { |
1431 | ccb = acb->pccb_pool[i]; | 2105 | ccb = acb->pccb_pool[i]; |
1432 | if (ccb->startdone == ARCMSR_CCB_START) { | 2106 | if (ccb->startdone == ARCMSR_CCB_START) { |
1433 | ccb->startdone = ARCMSR_CCB_ABORTED; | 2107 | ccb->startdone = ARCMSR_CCB_ABORTED; |
2108 | arcmsr_ccb_complete(ccb, 1); | ||
1434 | } | 2109 | } |
1435 | } | 2110 | } |
1436 | /* enable all outbound interrupt */ | 2111 | /* enable all outbound interrupt */ |
1437 | arcmsr_enable_outbound_ints(acb, intmask_org); | 2112 | arcmsr_enable_outbound_ints(acb, intmask_org); |
1438 | } | 2113 | } |
1439 | |||
1440 | } | 2114 | } |
1441 | 2115 | ||
1442 | static int arcmsr_bus_reset(struct scsi_cmnd *cmd) | 2116 | static int arcmsr_bus_reset(struct scsi_cmnd *cmd) |
@@ -1450,7 +2124,7 @@ static int arcmsr_bus_reset(struct scsi_cmnd *cmd) | |||
1450 | for (i = 0; i < 400; i++) { | 2124 | for (i = 0; i < 400; i++) { |
1451 | if (!atomic_read(&acb->ccboutstandingcount)) | 2125 | if (!atomic_read(&acb->ccboutstandingcount)) |
1452 | break; | 2126 | break; |
1453 | arcmsr_interrupt(acb); | 2127 | arcmsr_interrupt(acb);/* FIXME: need spinlock */ |
1454 | msleep(25); | 2128 | msleep(25); |
1455 | } | 2129 | } |
1456 | arcmsr_iop_reset(acb); | 2130 | arcmsr_iop_reset(acb); |
@@ -1468,7 +2142,7 @@ static void arcmsr_abort_one_cmd(struct AdapterControlBlock *acb, | |||
1468 | /* | 2142 | /* |
1469 | ** Wait for 3 sec for all command done. | 2143 | ** Wait for 3 sec for all command done. |
1470 | */ | 2144 | */ |
1471 | msleep_interruptible(3000); | 2145 | ssleep(3); |
1472 | 2146 | ||
1473 | intmask = arcmsr_disable_outbound_ints(acb); | 2147 | intmask = arcmsr_disable_outbound_ints(acb); |
1474 | arcmsr_polling_ccbdone(acb, ccb); | 2148 | arcmsr_polling_ccbdone(acb, ccb); |
@@ -1515,6 +2189,8 @@ static const char *arcmsr_info(struct Scsi_Host *host) | |||
1515 | 2189 | ||
1516 | switch (acb->pdev->device) { | 2190 | switch (acb->pdev->device) { |
1517 | case PCI_DEVICE_ID_ARECA_1110: | 2191 | case PCI_DEVICE_ID_ARECA_1110: |
2192 | case PCI_DEVICE_ID_ARECA_1200: | ||
2193 | case PCI_DEVICE_ID_ARECA_1202: | ||
1518 | case PCI_DEVICE_ID_ARECA_1210: | 2194 | case PCI_DEVICE_ID_ARECA_1210: |
1519 | raid6 = 0; | 2195 | raid6 = 0; |
1520 | /*FALLTHRU*/ | 2196 | /*FALLTHRU*/ |
@@ -1522,6 +2198,7 @@ static const char *arcmsr_info(struct Scsi_Host *host) | |||
1522 | case PCI_DEVICE_ID_ARECA_1130: | 2198 | case PCI_DEVICE_ID_ARECA_1130: |
1523 | case PCI_DEVICE_ID_ARECA_1160: | 2199 | case PCI_DEVICE_ID_ARECA_1160: |
1524 | case PCI_DEVICE_ID_ARECA_1170: | 2200 | case PCI_DEVICE_ID_ARECA_1170: |
2201 | case PCI_DEVICE_ID_ARECA_1201: | ||
1525 | case PCI_DEVICE_ID_ARECA_1220: | 2202 | case PCI_DEVICE_ID_ARECA_1220: |
1526 | case PCI_DEVICE_ID_ARECA_1230: | 2203 | case PCI_DEVICE_ID_ARECA_1230: |
1527 | case PCI_DEVICE_ID_ARECA_1260: | 2204 | case PCI_DEVICE_ID_ARECA_1260: |
@@ -1544,287 +2221,82 @@ static const char *arcmsr_info(struct Scsi_Host *host) | |||
1544 | ARCMSR_DRIVER_VERSION); | 2221 | ARCMSR_DRIVER_VERSION); |
1545 | return buf; | 2222 | return buf; |
1546 | } | 2223 | } |
1547 | 2224 | #ifdef CONFIG_SCSI_ARCMSR_AER | |
1548 | static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev) | 2225 | static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev) |
1549 | { | 2226 | { |
1550 | struct Scsi_Host *host; | 2227 | struct Scsi_Host *host = pci_get_drvdata(pdev); |
1551 | struct AdapterControlBlock *acb; | 2228 | struct AdapterControlBlock *acb = |
1552 | uint8_t bus, dev_fun; | 2229 | (struct AdapterControlBlock *) host->hostdata; |
1553 | int error; | 2230 | uint32_t intmask_org; |
1554 | 2231 | int i, j; | |
1555 | error = pci_enable_device(pdev); | ||
1556 | if (error) | ||
1557 | return PCI_ERS_RESULT_DISCONNECT; | ||
1558 | pci_set_master(pdev); | ||
1559 | |||
1560 | host = scsi_host_alloc(&arcmsr_scsi_host_template, sizeof \ | ||
1561 | (struct AdapterControlBlock)); | ||
1562 | if (!host) | ||
1563 | return PCI_ERS_RESULT_DISCONNECT; | ||
1564 | acb = (struct AdapterControlBlock *)host->hostdata; | ||
1565 | memset(acb, 0, sizeof (struct AdapterControlBlock)); | ||
1566 | |||
1567 | error = pci_set_dma_mask(pdev, DMA_64BIT_MASK); | ||
1568 | if (error) { | ||
1569 | error = pci_set_dma_mask(pdev, DMA_32BIT_MASK); | ||
1570 | if (error) { | ||
1571 | printk(KERN_WARNING | ||
1572 | "scsi%d: No suitable DMA mask available\n", | ||
1573 | host->host_no); | ||
1574 | return PCI_ERS_RESULT_DISCONNECT; | ||
1575 | } | ||
1576 | } | ||
1577 | bus = pdev->bus->number; | ||
1578 | dev_fun = pdev->devfn; | ||
1579 | acb = (struct AdapterControlBlock *) host->hostdata; | ||
1580 | memset(acb, 0, sizeof(struct AdapterControlBlock)); | ||
1581 | acb->pdev = pdev; | ||
1582 | acb->host = host; | ||
1583 | host->max_sectors = ARCMSR_MAX_XFER_SECTORS; | ||
1584 | host->max_lun = ARCMSR_MAX_TARGETLUN; | ||
1585 | host->max_id = ARCMSR_MAX_TARGETID;/*16:8*/ | ||
1586 | host->max_cmd_len = 16; /*this is issue of 64bit LBA, over 2T byte*/ | ||
1587 | host->sg_tablesize = ARCMSR_MAX_SG_ENTRIES; | ||
1588 | host->can_queue = ARCMSR_MAX_FREECCB_NUM; /* max simultaneous cmds */ | ||
1589 | host->cmd_per_lun = ARCMSR_MAX_CMD_PERLUN; | ||
1590 | host->this_id = ARCMSR_SCSI_INITIATOR_ID; | ||
1591 | host->unique_id = (bus << 8) | dev_fun; | ||
1592 | host->irq = pdev->irq; | ||
1593 | error = pci_request_regions(pdev, "arcmsr"); | ||
1594 | if (error) | ||
1595 | return PCI_ERS_RESULT_DISCONNECT; | ||
1596 | 2232 | ||
1597 | acb->pmu = ioremap(pci_resource_start(pdev, 0), | 2233 | if (pci_enable_device(pdev)) { |
1598 | pci_resource_len(pdev, 0)); | ||
1599 | if (!acb->pmu) { | ||
1600 | printk(KERN_NOTICE "arcmsr%d: memory" | ||
1601 | " mapping region fail \n", acb->host->host_no); | ||
1602 | return PCI_ERS_RESULT_DISCONNECT; | 2234 | return PCI_ERS_RESULT_DISCONNECT; |
1603 | } | 2235 | } |
2236 | pci_set_master(pdev); | ||
2237 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
1604 | acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | | 2238 | acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | |
1605 | ACB_F_MESSAGE_RQBUFFER_CLEARED | | 2239 | ACB_F_MESSAGE_RQBUFFER_CLEARED | |
1606 | ACB_F_MESSAGE_WQBUFFER_READED); | 2240 | ACB_F_MESSAGE_WQBUFFER_READED); |
1607 | acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; | 2241 | acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; |
1608 | INIT_LIST_HEAD(&acb->ccb_free_list); | 2242 | for (i = 0; i < ARCMSR_MAX_TARGETID; i++) |
1609 | 2243 | for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) | |
1610 | error = arcmsr_alloc_ccb_pool(acb); | 2244 | acb->devstate[i][j] = ARECA_RAID_GONE; |
1611 | if (error) | ||
1612 | return PCI_ERS_RESULT_DISCONNECT; | ||
1613 | |||
1614 | error = request_irq(pdev->irq, arcmsr_do_interrupt, | ||
1615 | IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb); | ||
1616 | if (error) | ||
1617 | return PCI_ERS_RESULT_DISCONNECT; | ||
1618 | |||
1619 | arcmsr_iop_init(acb); | ||
1620 | if (strncmp(acb->firm_version, "V1.42", 5) >= 0) | ||
1621 | host->max_sectors = ARCMSR_MAX_XFER_SECTORS_B; | ||
1622 | |||
1623 | pci_set_drvdata(pdev, host); | ||
1624 | |||
1625 | error = scsi_add_host(host, &pdev->dev); | ||
1626 | if (error) | ||
1627 | return PCI_ERS_RESULT_DISCONNECT; | ||
1628 | 2245 | ||
1629 | error = arcmsr_alloc_sysfs_attr(acb); | 2246 | arcmsr_wait_firmware_ready(acb); |
1630 | if (error) | 2247 | arcmsr_iop_confirm(acb); |
1631 | return PCI_ERS_RESULT_DISCONNECT; | 2248 | /* disable all outbound interrupt */ |
2249 | arcmsr_get_firmware_spec(acb); | ||
2250 | /*start background rebuild*/ | ||
2251 | arcmsr_start_adapter_bgrb(acb); | ||
2252 | /* empty doorbell Qbuffer if door bell ringed */ | ||
2253 | arcmsr_clear_doorbell_queue_buffer(acb); | ||
2254 | /* enable outbound Post Queue,outbound doorbell Interrupt */ | ||
2255 | arcmsr_enable_outbound_ints(acb, intmask_org); | ||
2256 | acb->acb_flags |= ACB_F_IOP_INITED; | ||
1632 | 2257 | ||
1633 | scsi_scan_host(host); | 2258 | pci_enable_pcie_error_reporting(pdev); |
1634 | return PCI_ERS_RESULT_RECOVERED; | 2259 | return PCI_ERS_RESULT_RECOVERED; |
1635 | } | 2260 | } |
1636 | 2261 | ||
1637 | static void arcmsr_pci_ers_need_reset_forepart(struct pci_dev *pdev) | 2262 | static void arcmsr_pci_ers_need_reset_forepart(struct pci_dev *pdev) |
1638 | { | 2263 | { |
1639 | struct Scsi_Host *host = pci_get_drvdata(pdev); | 2264 | struct Scsi_Host *host = pci_get_drvdata(pdev); |
1640 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | 2265 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *)host->hostdata; |
1641 | struct MessageUnit __iomem *reg = acb->pmu; | ||
1642 | struct CommandControlBlock *ccb; | 2266 | struct CommandControlBlock *ccb; |
1643 | /*clear and abort all outbound posted Q*/ | 2267 | uint32_t intmask_org; |
1644 | int i = 0, found = 0; | 2268 | int i = 0; |
1645 | int id, lun; | ||
1646 | uint32_t flag_ccb, outbound_intstatus; | ||
1647 | |||
1648 | while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) && | ||
1649 | (i++ < 256)){ | ||
1650 | ccb = (struct CommandControlBlock *)(acb->vir2phy_offset | ||
1651 | + (flag_ccb << 5)); | ||
1652 | if (ccb){ | ||
1653 | if ((ccb->acb != acb)||(ccb->startdone != | ||
1654 | ARCMSR_CCB_START)){ | ||
1655 | printk(KERN_NOTICE "arcmsr%d: polling \ | ||
1656 | get an illegal ccb"" command done ccb = '0x%p'" | ||
1657 | "ccboutstandingcount = %d \n", | ||
1658 | acb->host->host_no, ccb, | ||
1659 | atomic_read(&acb->ccboutstandingcount)); | ||
1660 | continue; | ||
1661 | } | ||
1662 | |||
1663 | id = ccb->pcmd->device->id; | ||
1664 | lun = ccb->pcmd->device->lun; | ||
1665 | if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { | ||
1666 | if (acb->devstate[id][lun] == | ||
1667 | ARECA_RAID_GONE) | ||
1668 | acb->devstate[id][lun] = | ||
1669 | ARECA_RAID_GOOD; | ||
1670 | ccb->pcmd->result = DID_OK << 16; | ||
1671 | arcmsr_ccb_complete(ccb, 1); | ||
1672 | } | ||
1673 | else { | ||
1674 | switch(ccb->arcmsr_cdb.DeviceStatus) { | ||
1675 | case ARCMSR_DEV_SELECT_TIMEOUT: { | ||
1676 | acb->devstate[id][lun] = | ||
1677 | ARECA_RAID_GONE; | ||
1678 | ccb->pcmd->result = | ||
1679 | DID_NO_CONNECT << 16; | ||
1680 | arcmsr_ccb_complete(ccb, 1); | ||
1681 | } | ||
1682 | break; | ||
1683 | |||
1684 | case ARCMSR_DEV_ABORTED: | ||
1685 | |||
1686 | case ARCMSR_DEV_INIT_FAIL: { | ||
1687 | acb->devstate[id][lun] = | ||
1688 | ARECA_RAID_GONE; | ||
1689 | ccb->pcmd->result = | ||
1690 | DID_BAD_TARGET << 16; | ||
1691 | arcmsr_ccb_complete(ccb, 1); | ||
1692 | } | ||
1693 | break; | ||
1694 | |||
1695 | case ARCMSR_DEV_CHECK_CONDITION: { | ||
1696 | acb->devstate[id][lun] = | ||
1697 | ARECA_RAID_GOOD; | ||
1698 | arcmsr_report_sense_info(ccb); | ||
1699 | arcmsr_ccb_complete(ccb, 1); | ||
1700 | } | ||
1701 | break; | ||
1702 | 2269 | ||
1703 | default: | 2270 | if (atomic_read(&acb->ccboutstandingcount) != 0) { |
1704 | printk(KERN_NOTICE | 2271 | /* talk to iop 331 outstanding command aborted */ |
1705 | "arcmsr%d: scsi \ | 2272 | arcmsr_abort_allcmd(acb); |
1706 | id = %d lun = %d" | 2273 | /* wait for 3 sec for all command aborted*/ |
1707 | " polling and \ | 2274 | ssleep(3); |
1708 | getting command \ | 2275 | /* disable all outbound interrupt */ |
1709 | error done" | 2276 | intmask_org = arcmsr_disable_outbound_ints(acb); |
1710 | "but got unknown \ | 2277 | /* clear all outbound posted Q */ |
1711 | DeviceStatus = 0x%x \n" | 2278 | arcmsr_done4abort_postqueue(acb); |
1712 | , acb->host->host_no, | 2279 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { |
1713 | id, lun, | 2280 | ccb = acb->pccb_pool[i]; |
1714 | ccb->arcmsr_cdb.DeviceStatus); | 2281 | if (ccb->startdone == ARCMSR_CCB_START) { |
1715 | acb->devstate[id][lun] = | 2282 | ccb->startdone = ARCMSR_CCB_ABORTED; |
1716 | ARECA_RAID_GONE; | 2283 | arcmsr_ccb_complete(ccb, 1); |
1717 | ccb->pcmd->result = | ||
1718 | DID_BAD_TARGET << 16; | ||
1719 | arcmsr_ccb_complete(ccb, 1); | ||
1720 | break; | ||
1721 | } | ||
1722 | } | ||
1723 | found = 1; | ||
1724 | } | 2284 | } |
1725 | } | 2285 | } |
1726 | if (found){ | 2286 | /* enable all outbound interrupt */ |
1727 | outbound_intstatus = readl(®->outbound_intstatus) & | 2287 | arcmsr_enable_outbound_ints(acb, intmask_org); |
1728 | acb->outbound_int_enable; | 2288 | } |
1729 | writel(outbound_intstatus, ®->outbound_intstatus); | 2289 | pci_disable_device(pdev); |
1730 | /*clear interrupt*/ | ||
1731 | } | ||
1732 | return; | ||
1733 | } | 2290 | } |
1734 | 2291 | ||
1735 | |||
1736 | static void arcmsr_pci_ers_disconnect_forepart(struct pci_dev *pdev) | 2292 | static void arcmsr_pci_ers_disconnect_forepart(struct pci_dev *pdev) |
1737 | { | 2293 | { |
1738 | struct Scsi_Host *host = pci_get_drvdata(pdev); | 2294 | struct Scsi_Host *host = pci_get_drvdata(pdev); |
1739 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | 2295 | struct AdapterControlBlock *acb = \ |
1740 | struct MessageUnit __iomem *reg = acb->pmu; | 2296 | (struct AdapterControlBlock *)host->hostdata; |
1741 | struct CommandControlBlock *ccb; | ||
1742 | /*clear and abort all outbound posted Q*/ | ||
1743 | int i = 0, found = 0; | ||
1744 | int id, lun; | ||
1745 | uint32_t flag_ccb, outbound_intstatus; | ||
1746 | |||
1747 | while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) && | ||
1748 | (i++ < 256)){ | ||
1749 | ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + | ||
1750 | (flag_ccb << 5)); | ||
1751 | if (ccb){ | ||
1752 | if ((ccb->acb != acb)||(ccb->startdone != | ||
1753 | ARCMSR_CCB_START)){ | ||
1754 | printk(KERN_NOTICE | ||
1755 | "arcmsr%d: polling get an illegal ccb" | ||
1756 | " command done ccb = '0x%p'" | ||
1757 | "ccboutstandingcount = %d \n", | ||
1758 | acb->host->host_no, ccb, | ||
1759 | atomic_read(&acb->ccboutstandingcount)); | ||
1760 | continue; | ||
1761 | } | ||
1762 | |||
1763 | id = ccb->pcmd->device->id; | ||
1764 | lun = ccb->pcmd->device->lun; | ||
1765 | if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { | ||
1766 | if (acb->devstate[id][lun] == ARECA_RAID_GONE) | ||
1767 | acb->devstate[id][lun] = ARECA_RAID_GOOD; | ||
1768 | ccb->pcmd->result = DID_OK << 16; | ||
1769 | arcmsr_ccb_complete(ccb, 1); | ||
1770 | } | ||
1771 | else { | ||
1772 | switch(ccb->arcmsr_cdb.DeviceStatus) { | ||
1773 | case ARCMSR_DEV_SELECT_TIMEOUT: { | ||
1774 | acb->devstate[id][lun] = | ||
1775 | ARECA_RAID_GONE; | ||
1776 | ccb->pcmd->result = | ||
1777 | DID_NO_CONNECT << 16; | ||
1778 | arcmsr_ccb_complete(ccb, 1); | ||
1779 | } | ||
1780 | break; | ||
1781 | |||
1782 | case ARCMSR_DEV_ABORTED: | ||
1783 | |||
1784 | case ARCMSR_DEV_INIT_FAIL: { | ||
1785 | acb->devstate[id][lun] = | ||
1786 | ARECA_RAID_GONE; | ||
1787 | ccb->pcmd->result = | ||
1788 | DID_BAD_TARGET << 16; | ||
1789 | arcmsr_ccb_complete(ccb, 1); | ||
1790 | } | ||
1791 | break; | ||
1792 | 2297 | ||
1793 | case ARCMSR_DEV_CHECK_CONDITION: { | 2298 | arcmsr_stop_adapter_bgrb(acb); |
1794 | acb->devstate[id][lun] = | 2299 | arcmsr_flush_adapter_cache(acb); |
1795 | ARECA_RAID_GOOD; | ||
1796 | arcmsr_report_sense_info(ccb); | ||
1797 | arcmsr_ccb_complete(ccb, 1); | ||
1798 | } | ||
1799 | break; | ||
1800 | |||
1801 | default: | ||
1802 | printk(KERN_NOTICE "arcmsr%d: \ | ||
1803 | scsi id = %d lun = %d" | ||
1804 | " polling and \ | ||
1805 | getting command error done" | ||
1806 | "but got unknown \ | ||
1807 | DeviceStatus = 0x%x \n" | ||
1808 | , acb->host->host_no, | ||
1809 | id, lun, ccb->arcmsr_cdb.DeviceStatus); | ||
1810 | acb->devstate[id][lun] = | ||
1811 | ARECA_RAID_GONE; | ||
1812 | ccb->pcmd->result = | ||
1813 | DID_BAD_TARGET << 16; | ||
1814 | arcmsr_ccb_complete(ccb, 1); | ||
1815 | break; | ||
1816 | } | ||
1817 | } | ||
1818 | found = 1; | ||
1819 | } | ||
1820 | } | ||
1821 | if (found){ | ||
1822 | outbound_intstatus = readl(®->outbound_intstatus) & | ||
1823 | acb->outbound_int_enable; | ||
1824 | writel(outbound_intstatus, ®->outbound_intstatus); | ||
1825 | /*clear interrupt*/ | ||
1826 | } | ||
1827 | return; | ||
1828 | } | 2300 | } |
1829 | 2301 | ||
1830 | static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, | 2302 | static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, |
@@ -1840,5 +2312,6 @@ static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, | |||
1840 | break; | 2312 | break; |
1841 | default: | 2313 | default: |
1842 | return PCI_ERS_RESULT_NEED_RESET; | 2314 | return PCI_ERS_RESULT_NEED_RESET; |
1843 | } | 2315 | } |
1844 | } | 2316 | } |
2317 | #endif | ||