diff options
| author | Ching Huang <ching2048@areca.com.tw> | 2014-08-19 03:25:22 -0400 |
|---|---|---|
| committer | Christoph Hellwig <hch@lst.de> | 2014-09-16 12:40:08 -0400 |
| commit | 5b37479adee7164b17b6e2030b9a30d04583eb61 (patch) | |
| tree | a7b0f99fed9c02309262f2857e36c8c380dbe9f0 /drivers/scsi/arcmsr | |
| parent | aaa64f69480bcde4e203584dfc77d7e4ffb737d6 (diff) | |
arcmsr: add support new adapter ARC12x4 series
Add code to support the new Areca Raid ARC12x4 series adapters.
Signed-off-by: Ching Huang <ching2048@areca.com.tw>
Reviewed-by: Tomas Henzl <thenzl@redhat.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/arcmsr')
| -rw-r--r-- | drivers/scsi/arcmsr/arcmsr.h | 108 | ||||
| -rw-r--r-- | drivers/scsi/arcmsr/arcmsr_hba.c | 761 |
2 files changed, 860 insertions, 9 deletions
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index 799393ede1cc..d1c78efc202e 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h | |||
| @@ -63,12 +63,17 @@ struct device_attribute; | |||
| 63 | #define ARCMSR_MAX_QBUFFER 4096 | 63 | #define ARCMSR_MAX_QBUFFER 4096 |
| 64 | #define ARCMSR_DEFAULT_SG_ENTRIES 38 | 64 | #define ARCMSR_DEFAULT_SG_ENTRIES 38 |
| 65 | #define ARCMSR_MAX_HBB_POSTQUEUE 264 | 65 | #define ARCMSR_MAX_HBB_POSTQUEUE 264 |
| 66 | #define ARCMSR_MAX_ARC1214_POSTQUEUE 256 | ||
| 67 | #define ARCMSR_MAX_ARC1214_DONEQUEUE 257 | ||
| 66 | #define ARCMSR_MAX_XFER_LEN 0x26000 /* 152K */ | 68 | #define ARCMSR_MAX_XFER_LEN 0x26000 /* 152K */ |
| 67 | #define ARCMSR_CDB_SG_PAGE_LENGTH 256 | 69 | #define ARCMSR_CDB_SG_PAGE_LENGTH 256 |
| 68 | #define ARCMST_NUM_MSIX_VECTORS 4 | 70 | #define ARCMST_NUM_MSIX_VECTORS 4 |
| 69 | #ifndef PCI_DEVICE_ID_ARECA_1880 | 71 | #ifndef PCI_DEVICE_ID_ARECA_1880 |
| 70 | #define PCI_DEVICE_ID_ARECA_1880 0x1880 | 72 | #define PCI_DEVICE_ID_ARECA_1880 0x1880 |
| 71 | #endif | 73 | #endif |
| 74 | #ifndef PCI_DEVICE_ID_ARECA_1214 | ||
| 75 | #define PCI_DEVICE_ID_ARECA_1214 0x1214 | ||
| 76 | #endif | ||
| 72 | /* | 77 | /* |
| 73 | ********************************************************************************** | 78 | ********************************************************************************** |
| 74 | ** | 79 | ** |
| @@ -339,6 +344,56 @@ struct FIRMWARE_INFO | |||
| 339 | #define ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK 0x80000000 | 344 | #define ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK 0x80000000 |
| 340 | /* | 345 | /* |
| 341 | ******************************************************************************* | 346 | ******************************************************************************* |
| 347 | ** SPEC. for Areca Type D adapter | ||
| 348 | ******************************************************************************* | ||
| 349 | */ | ||
| 350 | #define ARCMSR_ARC1214_CHIP_ID 0x00004 | ||
| 351 | #define ARCMSR_ARC1214_CPU_MEMORY_CONFIGURATION 0x00008 | ||
| 352 | #define ARCMSR_ARC1214_I2_HOST_INTERRUPT_MASK 0x00034 | ||
| 353 | #define ARCMSR_ARC1214_SAMPLE_RESET 0x00100 | ||
| 354 | #define ARCMSR_ARC1214_RESET_REQUEST 0x00108 | ||
| 355 | #define ARCMSR_ARC1214_MAIN_INTERRUPT_STATUS 0x00200 | ||
| 356 | #define ARCMSR_ARC1214_PCIE_F0_INTERRUPT_ENABLE 0x0020C | ||
| 357 | #define ARCMSR_ARC1214_INBOUND_MESSAGE0 0x00400 | ||
| 358 | #define ARCMSR_ARC1214_INBOUND_MESSAGE1 0x00404 | ||
| 359 | #define ARCMSR_ARC1214_OUTBOUND_MESSAGE0 0x00420 | ||
| 360 | #define ARCMSR_ARC1214_OUTBOUND_MESSAGE1 0x00424 | ||
| 361 | #define ARCMSR_ARC1214_INBOUND_DOORBELL 0x00460 | ||
| 362 | #define ARCMSR_ARC1214_OUTBOUND_DOORBELL 0x00480 | ||
| 363 | #define ARCMSR_ARC1214_OUTBOUND_DOORBELL_ENABLE 0x00484 | ||
| 364 | #define ARCMSR_ARC1214_INBOUND_LIST_BASE_LOW 0x01000 | ||
| 365 | #define ARCMSR_ARC1214_INBOUND_LIST_BASE_HIGH 0x01004 | ||
| 366 | #define ARCMSR_ARC1214_INBOUND_LIST_WRITE_POINTER 0x01018 | ||
| 367 | #define ARCMSR_ARC1214_OUTBOUND_LIST_BASE_LOW 0x01060 | ||
| 368 | #define ARCMSR_ARC1214_OUTBOUND_LIST_BASE_HIGH 0x01064 | ||
| 369 | #define ARCMSR_ARC1214_OUTBOUND_LIST_COPY_POINTER 0x0106C | ||
| 370 | #define ARCMSR_ARC1214_OUTBOUND_LIST_READ_POINTER 0x01070 | ||
| 371 | #define ARCMSR_ARC1214_OUTBOUND_INTERRUPT_CAUSE 0x01088 | ||
| 372 | #define ARCMSR_ARC1214_OUTBOUND_INTERRUPT_ENABLE 0x0108C | ||
| 373 | #define ARCMSR_ARC1214_MESSAGE_WBUFFER 0x02000 | ||
| 374 | #define ARCMSR_ARC1214_MESSAGE_RBUFFER 0x02100 | ||
| 375 | #define ARCMSR_ARC1214_MESSAGE_RWBUFFER 0x02200 | ||
| 376 | /* Host Interrupt Mask */ | ||
| 377 | #define ARCMSR_ARC1214_ALL_INT_ENABLE 0x00001010 | ||
| 378 | #define ARCMSR_ARC1214_ALL_INT_DISABLE 0x00000000 | ||
| 379 | /* Host Interrupt Status */ | ||
| 380 | #define ARCMSR_ARC1214_OUTBOUND_DOORBELL_ISR 0x00001000 | ||
| 381 | #define ARCMSR_ARC1214_OUTBOUND_POSTQUEUE_ISR 0x00000010 | ||
| 382 | /* DoorBell*/ | ||
| 383 | #define ARCMSR_ARC1214_DRV2IOP_DATA_IN_READY 0x00000001 | ||
| 384 | #define ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ 0x00000002 | ||
| 385 | /*inbound message 0 ready*/ | ||
| 386 | #define ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK 0x00000001 | ||
| 387 | /*outbound DATA WRITE isr door bell clear*/ | ||
| 388 | #define ARCMSR_ARC1214_IOP2DRV_DATA_READ_OK 0x00000002 | ||
| 389 | /*outbound message 0 ready*/ | ||
| 390 | #define ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE 0x02000000 | ||
| 391 | /*outbound message cmd isr door bell clear*/ | ||
| 392 | /*ARCMSR_HBAMU_MESSAGE_FIRMWARE_OK*/ | ||
| 393 | #define ARCMSR_ARC1214_MESSAGE_FIRMWARE_OK 0x80000000 | ||
| 394 | #define ARCMSR_ARC1214_OUTBOUND_LIST_INTERRUPT_CLEAR 0x00000001 | ||
| 395 | /* | ||
| 396 | ******************************************************************************* | ||
| 342 | ** ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504) | 397 | ** ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504) |
| 343 | ******************************************************************************* | 398 | ******************************************************************************* |
| 344 | */ | 399 | */ |
| @@ -496,6 +551,56 @@ struct MessageUnit_C{ | |||
| 496 | uint32_t msgcode_rwbuffer[256]; /*2200 23FF*/ | 551 | uint32_t msgcode_rwbuffer[256]; /*2200 23FF*/ |
| 497 | }; | 552 | }; |
| 498 | /* | 553 | /* |
| 554 | ********************************************************************* | ||
| 555 | ** Messaging Unit (MU) of Type D processor | ||
| 556 | ********************************************************************* | ||
| 557 | */ | ||
| 558 | struct InBound_SRB { | ||
| 559 | uint32_t addressLow; /* pointer to SRB block */ | ||
| 560 | uint32_t addressHigh; | ||
| 561 | uint32_t length; /* in DWORDs */ | ||
| 562 | uint32_t reserved0; | ||
| 563 | }; | ||
| 564 | |||
| 565 | struct OutBound_SRB { | ||
| 566 | uint32_t addressLow; /* pointer to SRB block */ | ||
| 567 | uint32_t addressHigh; | ||
| 568 | }; | ||
| 569 | |||
| 570 | struct MessageUnit_D { | ||
| 571 | struct InBound_SRB post_qbuffer[ARCMSR_MAX_ARC1214_POSTQUEUE]; | ||
| 572 | volatile struct OutBound_SRB | ||
| 573 | done_qbuffer[ARCMSR_MAX_ARC1214_DONEQUEUE]; | ||
| 574 | u16 postq_index; | ||
| 575 | volatile u16 doneq_index; | ||
| 576 | u32 __iomem *chip_id; /* 0x00004 */ | ||
| 577 | u32 __iomem *cpu_mem_config; /* 0x00008 */ | ||
| 578 | u32 __iomem *i2o_host_interrupt_mask; /* 0x00034 */ | ||
| 579 | u32 __iomem *sample_at_reset; /* 0x00100 */ | ||
| 580 | u32 __iomem *reset_request; /* 0x00108 */ | ||
| 581 | u32 __iomem *host_int_status; /* 0x00200 */ | ||
| 582 | u32 __iomem *pcief0_int_enable; /* 0x0020C */ | ||
| 583 | u32 __iomem *inbound_msgaddr0; /* 0x00400 */ | ||
| 584 | u32 __iomem *inbound_msgaddr1; /* 0x00404 */ | ||
| 585 | u32 __iomem *outbound_msgaddr0; /* 0x00420 */ | ||
| 586 | u32 __iomem *outbound_msgaddr1; /* 0x00424 */ | ||
| 587 | u32 __iomem *inbound_doorbell; /* 0x00460 */ | ||
| 588 | u32 __iomem *outbound_doorbell; /* 0x00480 */ | ||
| 589 | u32 __iomem *outbound_doorbell_enable; /* 0x00484 */ | ||
| 590 | u32 __iomem *inboundlist_base_low; /* 0x01000 */ | ||
| 591 | u32 __iomem *inboundlist_base_high; /* 0x01004 */ | ||
| 592 | u32 __iomem *inboundlist_write_pointer; /* 0x01018 */ | ||
| 593 | u32 __iomem *outboundlist_base_low; /* 0x01060 */ | ||
| 594 | u32 __iomem *outboundlist_base_high; /* 0x01064 */ | ||
| 595 | u32 __iomem *outboundlist_copy_pointer; /* 0x0106C */ | ||
| 596 | u32 __iomem *outboundlist_read_pointer; /* 0x01070 0x01072 */ | ||
| 597 | u32 __iomem *outboundlist_interrupt_cause; /* 0x1088 */ | ||
| 598 | u32 __iomem *outboundlist_interrupt_enable; /* 0x108C */ | ||
| 599 | u32 __iomem *message_wbuffer; /* 0x2000 */ | ||
| 600 | u32 __iomem *message_rbuffer; /* 0x2100 */ | ||
| 601 | u32 __iomem *msgcode_rwbuffer; /* 0x2200 */ | ||
| 602 | }; | ||
| 603 | /* | ||
| 499 | ******************************************************************************* | 604 | ******************************************************************************* |
| 500 | ** Adapter Control Block | 605 | ** Adapter Control Block |
| 501 | ******************************************************************************* | 606 | ******************************************************************************* |
| @@ -518,12 +623,15 @@ struct AdapterControlBlock | |||
| 518 | uint32_t reg_mu_acc_handle0; | 623 | uint32_t reg_mu_acc_handle0; |
| 519 | spinlock_t eh_lock; | 624 | spinlock_t eh_lock; |
| 520 | spinlock_t ccblist_lock; | 625 | spinlock_t ccblist_lock; |
| 626 | spinlock_t postq_lock; | ||
| 627 | spinlock_t doneq_lock; | ||
| 521 | spinlock_t rqbuffer_lock; | 628 | spinlock_t rqbuffer_lock; |
| 522 | spinlock_t wqbuffer_lock; | 629 | spinlock_t wqbuffer_lock; |
| 523 | union { | 630 | union { |
| 524 | struct MessageUnit_A __iomem *pmuA; | 631 | struct MessageUnit_A __iomem *pmuA; |
| 525 | struct MessageUnit_B *pmuB; | 632 | struct MessageUnit_B *pmuB; |
| 526 | struct MessageUnit_C __iomem *pmuC; | 633 | struct MessageUnit_C __iomem *pmuC; |
| 634 | struct MessageUnit_D *pmuD; | ||
| 527 | }; | 635 | }; |
| 528 | /* message unit ATU inbound base address0 */ | 636 | /* message unit ATU inbound base address0 */ |
| 529 | void __iomem *mem_base0; | 637 | void __iomem *mem_base0; |
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 26bcdc0fa8bf..b3cb969c72d5 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c | |||
| @@ -108,6 +108,7 @@ static void arcmsr_message_isr_bh_fn(struct work_struct *work); | |||
| 108 | static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb); | 108 | static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb); |
| 109 | static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); | 109 | static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); |
| 110 | static void arcmsr_hbaC_message_isr(struct AdapterControlBlock *pACB); | 110 | static void arcmsr_hbaC_message_isr(struct AdapterControlBlock *pACB); |
| 111 | static void arcmsr_hbaD_message_isr(struct AdapterControlBlock *acb); | ||
| 111 | static void arcmsr_hardware_reset(struct AdapterControlBlock *acb); | 112 | static void arcmsr_hardware_reset(struct AdapterControlBlock *acb); |
| 112 | static const char *arcmsr_info(struct Scsi_Host *); | 113 | static const char *arcmsr_info(struct Scsi_Host *); |
| 113 | static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); | 114 | static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); |
| @@ -161,6 +162,8 @@ static struct pci_device_id arcmsr_device_id_table[] = { | |||
| 161 | .driver_data = ACB_ADAPTER_TYPE_B}, | 162 | .driver_data = ACB_ADAPTER_TYPE_B}, |
| 162 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1210), | 163 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1210), |
| 163 | .driver_data = ACB_ADAPTER_TYPE_A}, | 164 | .driver_data = ACB_ADAPTER_TYPE_A}, |
| 165 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1214), | ||
| 166 | .driver_data = ACB_ADAPTER_TYPE_D}, | ||
| 164 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1220), | 167 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1220), |
| 165 | .driver_data = ACB_ADAPTER_TYPE_A}, | 168 | .driver_data = ACB_ADAPTER_TYPE_A}, |
| 166 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1230), | 169 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1230), |
| @@ -202,7 +205,8 @@ static struct pci_driver arcmsr_pci_driver = { | |||
| 202 | static void arcmsr_free_mu(struct AdapterControlBlock *acb) | 205 | static void arcmsr_free_mu(struct AdapterControlBlock *acb) |
| 203 | { | 206 | { |
| 204 | switch (acb->adapter_type) { | 207 | switch (acb->adapter_type) { |
| 205 | case ACB_ADAPTER_TYPE_B:{ | 208 | case ACB_ADAPTER_TYPE_B: |
| 209 | case ACB_ADAPTER_TYPE_D: { | ||
| 206 | dma_free_coherent(&acb->pdev->dev, acb->roundup_ccbsize, | 210 | dma_free_coherent(&acb->pdev->dev, acb->roundup_ccbsize, |
| 207 | acb->dma_coherent2, acb->dma_coherent_handle2); | 211 | acb->dma_coherent2, acb->dma_coherent_handle2); |
| 208 | break; | 212 | break; |
| @@ -251,6 +255,25 @@ static bool arcmsr_remap_pciregion(struct AdapterControlBlock *acb) | |||
| 251 | } | 255 | } |
| 252 | break; | 256 | break; |
| 253 | } | 257 | } |
| 258 | case ACB_ADAPTER_TYPE_D: { | ||
| 259 | void __iomem *mem_base0; | ||
| 260 | unsigned long addr, range, flags; | ||
| 261 | |||
| 262 | addr = (unsigned long)pci_resource_start(pdev, 0); | ||
| 263 | range = pci_resource_len(pdev, 0); | ||
| 264 | flags = pci_resource_flags(pdev, 0); | ||
| 265 | if (flags & IORESOURCE_CACHEABLE) | ||
| 266 | mem_base0 = ioremap(addr, range); | ||
| 267 | else | ||
| 268 | mem_base0 = ioremap_nocache(addr, range); | ||
| 269 | if (!mem_base0) { | ||
| 270 | pr_notice("arcmsr%d: memory mapping region fail\n", | ||
| 271 | acb->host->host_no); | ||
| 272 | return false; | ||
| 273 | } | ||
| 274 | acb->mem_base0 = mem_base0; | ||
| 275 | break; | ||
| 276 | } | ||
| 254 | } | 277 | } |
| 255 | return true; | 278 | return true; |
| 256 | } | 279 | } |
| @@ -271,6 +294,10 @@ static void arcmsr_unmap_pciregion(struct AdapterControlBlock *acb) | |||
| 271 | case ACB_ADAPTER_TYPE_C:{ | 294 | case ACB_ADAPTER_TYPE_C:{ |
| 272 | iounmap(acb->pmuC); | 295 | iounmap(acb->pmuC); |
| 273 | } | 296 | } |
| 297 | break; | ||
| 298 | case ACB_ADAPTER_TYPE_D: | ||
| 299 | iounmap(acb->mem_base0); | ||
| 300 | break; | ||
| 274 | } | 301 | } |
| 275 | } | 302 | } |
| 276 | 303 | ||
| @@ -367,6 +394,23 @@ static uint8_t arcmsr_hbaC_wait_msgint_ready(struct AdapterControlBlock *pACB) | |||
| 367 | return false; | 394 | return false; |
| 368 | } | 395 | } |
| 369 | 396 | ||
| 397 | static bool arcmsr_hbaD_wait_msgint_ready(struct AdapterControlBlock *pACB) | ||
| 398 | { | ||
| 399 | struct MessageUnit_D *reg = pACB->pmuD; | ||
| 400 | int i; | ||
| 401 | |||
| 402 | for (i = 0; i < 2000; i++) { | ||
| 403 | if (readl(reg->outbound_doorbell) | ||
| 404 | & ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE) { | ||
| 405 | writel(ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE, | ||
| 406 | reg->outbound_doorbell); | ||
| 407 | return true; | ||
| 408 | } | ||
| 409 | msleep(10); | ||
| 410 | } /* max 20 seconds */ | ||
| 411 | return false; | ||
| 412 | } | ||
| 413 | |||
| 370 | static void arcmsr_hbaA_flush_cache(struct AdapterControlBlock *acb) | 414 | static void arcmsr_hbaA_flush_cache(struct AdapterControlBlock *acb) |
| 371 | { | 415 | { |
| 372 | struct MessageUnit_A __iomem *reg = acb->pmuA; | 416 | struct MessageUnit_A __iomem *reg = acb->pmuA; |
| @@ -416,6 +460,24 @@ static void arcmsr_hbaC_flush_cache(struct AdapterControlBlock *pACB) | |||
| 416 | } while (retry_count != 0); | 460 | } while (retry_count != 0); |
| 417 | return; | 461 | return; |
| 418 | } | 462 | } |
| 463 | |||
| 464 | static void arcmsr_hbaD_flush_cache(struct AdapterControlBlock *pACB) | ||
| 465 | { | ||
| 466 | int retry_count = 15; | ||
| 467 | struct MessageUnit_D *reg = pACB->pmuD; | ||
| 468 | |||
| 469 | writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, reg->inbound_msgaddr0); | ||
| 470 | do { | ||
| 471 | if (arcmsr_hbaD_wait_msgint_ready(pACB)) | ||
| 472 | break; | ||
| 473 | |||
| 474 | retry_count--; | ||
| 475 | pr_notice("arcmsr%d: wait 'flush adapter " | ||
| 476 | "cache' timeout, retry count down = %d\n", | ||
| 477 | pACB->host->host_no, retry_count); | ||
| 478 | } while (retry_count != 0); | ||
| 479 | } | ||
| 480 | |||
| 419 | static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) | 481 | static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) |
| 420 | { | 482 | { |
| 421 | switch (acb->adapter_type) { | 483 | switch (acb->adapter_type) { |
| @@ -432,6 +494,10 @@ static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) | |||
| 432 | case ACB_ADAPTER_TYPE_C: { | 494 | case ACB_ADAPTER_TYPE_C: { |
| 433 | arcmsr_hbaC_flush_cache(acb); | 495 | arcmsr_hbaC_flush_cache(acb); |
| 434 | } | 496 | } |
| 497 | break; | ||
| 498 | case ACB_ADAPTER_TYPE_D: | ||
| 499 | arcmsr_hbaD_flush_cache(acb); | ||
| 500 | break; | ||
| 435 | } | 501 | } |
| 436 | } | 502 | } |
| 437 | 503 | ||
| @@ -475,9 +541,16 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) | |||
| 475 | acb->vir2phy_offset = (unsigned long)dma_coherent - (unsigned long)dma_coherent_handle; | 541 | acb->vir2phy_offset = (unsigned long)dma_coherent - (unsigned long)dma_coherent_handle; |
| 476 | for(i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++){ | 542 | for(i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++){ |
| 477 | cdb_phyaddr = dma_coherent_handle + offsetof(struct CommandControlBlock, arcmsr_cdb); | 543 | cdb_phyaddr = dma_coherent_handle + offsetof(struct CommandControlBlock, arcmsr_cdb); |
| 478 | ccb_tmp->cdb_phyaddr = | 544 | switch (acb->adapter_type) { |
| 479 | ((acb->adapter_type == ACB_ADAPTER_TYPE_C) ? | 545 | case ACB_ADAPTER_TYPE_A: |
| 480 | cdb_phyaddr : (cdb_phyaddr >> 5)); | 546 | case ACB_ADAPTER_TYPE_B: |
| 547 | ccb_tmp->cdb_phyaddr = cdb_phyaddr >> 5; | ||
| 548 | break; | ||
| 549 | case ACB_ADAPTER_TYPE_C: | ||
| 550 | case ACB_ADAPTER_TYPE_D: | ||
| 551 | ccb_tmp->cdb_phyaddr = cdb_phyaddr; | ||
| 552 | break; | ||
| 553 | } | ||
| 481 | acb->pccb_pool[i] = ccb_tmp; | 554 | acb->pccb_pool[i] = ccb_tmp; |
| 482 | ccb_tmp->acb = acb; | 555 | ccb_tmp->acb = acb; |
| 483 | INIT_LIST_HEAD(&ccb_tmp->list); | 556 | INIT_LIST_HEAD(&ccb_tmp->list); |
| @@ -521,6 +594,13 @@ static void arcmsr_message_isr_bh_fn(struct work_struct *work) | |||
| 521 | devicemap = (char __iomem *)(®->msgcode_rwbuffer[21]); | 594 | devicemap = (char __iomem *)(®->msgcode_rwbuffer[21]); |
| 522 | break; | 595 | break; |
| 523 | } | 596 | } |
| 597 | case ACB_ADAPTER_TYPE_D: { | ||
| 598 | struct MessageUnit_D *reg = acb->pmuD; | ||
| 599 | |||
| 600 | signature = (uint32_t __iomem *)(®->msgcode_rwbuffer[0]); | ||
| 601 | devicemap = (char __iomem *)(®->msgcode_rwbuffer[21]); | ||
| 602 | break; | ||
| 603 | } | ||
| 524 | } | 604 | } |
| 525 | atomic_inc(&acb->rq_map_token); | 605 | atomic_inc(&acb->rq_map_token); |
| 526 | if (readl(signature) != ARCMSR_SIGNATURE_GET_CONFIG) | 606 | if (readl(signature) != ARCMSR_SIGNATURE_GET_CONFIG) |
| @@ -651,6 +731,8 @@ static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 651 | } | 731 | } |
| 652 | spin_lock_init(&acb->eh_lock); | 732 | spin_lock_init(&acb->eh_lock); |
| 653 | spin_lock_init(&acb->ccblist_lock); | 733 | spin_lock_init(&acb->ccblist_lock); |
| 734 | spin_lock_init(&acb->postq_lock); | ||
| 735 | spin_lock_init(&acb->doneq_lock); | ||
| 654 | spin_lock_init(&acb->rqbuffer_lock); | 736 | spin_lock_init(&acb->rqbuffer_lock); |
| 655 | spin_lock_init(&acb->wqbuffer_lock); | 737 | spin_lock_init(&acb->wqbuffer_lock); |
| 656 | acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | | 738 | acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | |
| @@ -836,6 +918,20 @@ static uint8_t arcmsr_hbaC_abort_allcmd(struct AdapterControlBlock *pACB) | |||
| 836 | } | 918 | } |
| 837 | return true; | 919 | return true; |
| 838 | } | 920 | } |
| 921 | |||
| 922 | static uint8_t arcmsr_hbaD_abort_allcmd(struct AdapterControlBlock *pACB) | ||
| 923 | { | ||
| 924 | struct MessageUnit_D *reg = pACB->pmuD; | ||
| 925 | |||
| 926 | writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, reg->inbound_msgaddr0); | ||
| 927 | if (!arcmsr_hbaD_wait_msgint_ready(pACB)) { | ||
| 928 | pr_notice("arcmsr%d: wait 'abort all outstanding " | ||
| 929 | "command' timeout\n", pACB->host->host_no); | ||
| 930 | return false; | ||
| 931 | } | ||
| 932 | return true; | ||
| 933 | } | ||
| 934 | |||
| 839 | static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb) | 935 | static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb) |
| 840 | { | 936 | { |
| 841 | uint8_t rtnval = 0; | 937 | uint8_t rtnval = 0; |
| @@ -853,6 +949,11 @@ static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb) | |||
| 853 | case ACB_ADAPTER_TYPE_C: { | 949 | case ACB_ADAPTER_TYPE_C: { |
| 854 | rtnval = arcmsr_hbaC_abort_allcmd(acb); | 950 | rtnval = arcmsr_hbaC_abort_allcmd(acb); |
| 855 | } | 951 | } |
| 952 | break; | ||
| 953 | |||
| 954 | case ACB_ADAPTER_TYPE_D: | ||
| 955 | rtnval = arcmsr_hbaD_abort_allcmd(acb); | ||
| 956 | break; | ||
| 856 | } | 957 | } |
| 857 | return rtnval; | 958 | return rtnval; |
| 858 | } | 959 | } |
| @@ -919,6 +1020,12 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) | |||
| 919 | writel(orig_mask|ARCMSR_HBCMU_ALL_INTMASKENABLE, ®->host_int_mask); | 1020 | writel(orig_mask|ARCMSR_HBCMU_ALL_INTMASKENABLE, ®->host_int_mask); |
| 920 | } | 1021 | } |
| 921 | break; | 1022 | break; |
| 1023 | case ACB_ADAPTER_TYPE_D: { | ||
| 1024 | struct MessageUnit_D *reg = acb->pmuD; | ||
| 1025 | /* disable all outbound interrupt */ | ||
| 1026 | writel(ARCMSR_ARC1214_ALL_INT_DISABLE, reg->pcief0_int_enable); | ||
| 1027 | } | ||
| 1028 | break; | ||
| 922 | } | 1029 | } |
| 923 | return orig_mask; | 1030 | return orig_mask; |
| 924 | } | 1031 | } |
| @@ -1066,7 +1173,62 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) | |||
| 1066 | error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? true : false; | 1173 | error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? true : false; |
| 1067 | arcmsr_drain_donequeue(acb, pCCB, error); | 1174 | arcmsr_drain_donequeue(acb, pCCB, error); |
| 1068 | } | 1175 | } |
| 1069 | } | 1176 | } |
| 1177 | break; | ||
| 1178 | case ACB_ADAPTER_TYPE_D: { | ||
| 1179 | struct MessageUnit_D *pmu = acb->pmuD; | ||
| 1180 | uint32_t ccb_cdb_phy, outbound_write_pointer; | ||
| 1181 | uint32_t doneq_index, index_stripped, addressLow, residual; | ||
| 1182 | bool error; | ||
| 1183 | struct CommandControlBlock *pCCB; | ||
| 1184 | |||
| 1185 | outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1; | ||
| 1186 | doneq_index = pmu->doneq_index; | ||
| 1187 | residual = atomic_read(&acb->ccboutstandingcount); | ||
| 1188 | for (i = 0; i < residual; i++) { | ||
| 1189 | while ((doneq_index & 0xFFF) != | ||
| 1190 | (outbound_write_pointer & 0xFFF)) { | ||
| 1191 | if (doneq_index & 0x4000) { | ||
| 1192 | index_stripped = doneq_index & 0xFFF; | ||
| 1193 | index_stripped += 1; | ||
| 1194 | index_stripped %= | ||
| 1195 | ARCMSR_MAX_ARC1214_DONEQUEUE; | ||
| 1196 | pmu->doneq_index = index_stripped ? | ||
| 1197 | (index_stripped | 0x4000) : | ||
| 1198 | (index_stripped + 1); | ||
| 1199 | } else { | ||
| 1200 | index_stripped = doneq_index; | ||
| 1201 | index_stripped += 1; | ||
| 1202 | index_stripped %= | ||
| 1203 | ARCMSR_MAX_ARC1214_DONEQUEUE; | ||
| 1204 | pmu->doneq_index = index_stripped ? | ||
| 1205 | index_stripped : | ||
| 1206 | ((index_stripped | 0x4000) + 1); | ||
| 1207 | } | ||
| 1208 | doneq_index = pmu->doneq_index; | ||
| 1209 | addressLow = pmu->done_qbuffer[doneq_index & | ||
| 1210 | 0xFFF].addressLow; | ||
| 1211 | ccb_cdb_phy = (addressLow & 0xFFFFFFF0); | ||
| 1212 | pARCMSR_CDB = (struct ARCMSR_CDB *) | ||
| 1213 | (acb->vir2phy_offset + ccb_cdb_phy); | ||
| 1214 | pCCB = container_of(pARCMSR_CDB, | ||
| 1215 | struct CommandControlBlock, arcmsr_cdb); | ||
| 1216 | error = (addressLow & | ||
| 1217 | ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? | ||
| 1218 | true : false; | ||
| 1219 | arcmsr_drain_donequeue(acb, pCCB, error); | ||
| 1220 | writel(doneq_index, | ||
| 1221 | pmu->outboundlist_read_pointer); | ||
| 1222 | } | ||
| 1223 | mdelay(10); | ||
| 1224 | outbound_write_pointer = | ||
| 1225 | pmu->done_qbuffer[0].addressLow + 1; | ||
| 1226 | doneq_index = pmu->doneq_index; | ||
| 1227 | } | ||
| 1228 | pmu->postq_index = 0; | ||
| 1229 | pmu->doneq_index = 0x40FF; | ||
| 1230 | } | ||
| 1231 | break; | ||
| 1070 | } | 1232 | } |
| 1071 | } | 1233 | } |
| 1072 | 1234 | ||
| @@ -1175,6 +1337,14 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, | |||
| 1175 | writel(intmask_org & mask, ®->host_int_mask); | 1337 | writel(intmask_org & mask, ®->host_int_mask); |
| 1176 | acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f; | 1338 | acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f; |
| 1177 | } | 1339 | } |
| 1340 | break; | ||
| 1341 | case ACB_ADAPTER_TYPE_D: { | ||
| 1342 | struct MessageUnit_D *reg = acb->pmuD; | ||
| 1343 | |||
| 1344 | mask = ARCMSR_ARC1214_ALL_INT_ENABLE; | ||
| 1345 | writel(intmask_org | mask, reg->pcief0_int_enable); | ||
| 1346 | break; | ||
| 1347 | } | ||
| 1178 | } | 1348 | } |
| 1179 | } | 1349 | } |
| 1180 | 1350 | ||
| @@ -1282,6 +1452,38 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr | |||
| 1282 | writel(ccb_post_stamp, &phbcmu->inbound_queueport_low); | 1452 | writel(ccb_post_stamp, &phbcmu->inbound_queueport_low); |
| 1283 | } | 1453 | } |
| 1284 | } | 1454 | } |
| 1455 | break; | ||
| 1456 | case ACB_ADAPTER_TYPE_D: { | ||
| 1457 | struct MessageUnit_D *pmu = acb->pmuD; | ||
| 1458 | u16 index_stripped; | ||
| 1459 | u16 postq_index; | ||
| 1460 | unsigned long flags; | ||
| 1461 | struct InBound_SRB *pinbound_srb; | ||
| 1462 | |||
| 1463 | spin_lock_irqsave(&acb->postq_lock, flags); | ||
| 1464 | postq_index = pmu->postq_index; | ||
| 1465 | pinbound_srb = (struct InBound_SRB *)&(pmu->post_qbuffer[postq_index & 0xFF]); | ||
| 1466 | pinbound_srb->addressHigh = dma_addr_hi32(cdb_phyaddr); | ||
| 1467 | pinbound_srb->addressLow = dma_addr_lo32(cdb_phyaddr); | ||
| 1468 | pinbound_srb->length = ccb->arc_cdb_size >> 2; | ||
| 1469 | arcmsr_cdb->msgContext = dma_addr_lo32(cdb_phyaddr); | ||
| 1470 | if (postq_index & 0x4000) { | ||
| 1471 | index_stripped = postq_index & 0xFF; | ||
| 1472 | index_stripped += 1; | ||
| 1473 | index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE; | ||
| 1474 | pmu->postq_index = index_stripped ? | ||
| 1475 | (index_stripped | 0x4000) : index_stripped; | ||
| 1476 | } else { | ||
| 1477 | index_stripped = postq_index; | ||
| 1478 | index_stripped += 1; | ||
| 1479 | index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE; | ||
| 1480 | pmu->postq_index = index_stripped ? index_stripped : | ||
| 1481 | (index_stripped | 0x4000); | ||
| 1482 | } | ||
| 1483 | writel(postq_index, pmu->inboundlist_write_pointer); | ||
| 1484 | spin_unlock_irqrestore(&acb->postq_lock, flags); | ||
| 1485 | break; | ||
| 1486 | } | ||
| 1285 | } | 1487 | } |
| 1286 | } | 1488 | } |
| 1287 | 1489 | ||
| @@ -1323,6 +1525,18 @@ static void arcmsr_hbaC_stop_bgrb(struct AdapterControlBlock *pACB) | |||
| 1323 | } | 1525 | } |
| 1324 | return; | 1526 | return; |
| 1325 | } | 1527 | } |
| 1528 | |||
| 1529 | static void arcmsr_hbaD_stop_bgrb(struct AdapterControlBlock *pACB) | ||
| 1530 | { | ||
| 1531 | struct MessageUnit_D *reg = pACB->pmuD; | ||
| 1532 | |||
| 1533 | pACB->acb_flags &= ~ACB_F_MSG_START_BGRB; | ||
| 1534 | writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, reg->inbound_msgaddr0); | ||
| 1535 | if (!arcmsr_hbaD_wait_msgint_ready(pACB)) | ||
| 1536 | pr_notice("arcmsr%d: wait 'stop adapter background rebulid' " | ||
| 1537 | "timeout\n", pACB->host->host_no); | ||
| 1538 | } | ||
| 1539 | |||
| 1326 | static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) | 1540 | static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) |
| 1327 | { | 1541 | { |
| 1328 | switch (acb->adapter_type) { | 1542 | switch (acb->adapter_type) { |
| @@ -1338,6 +1552,10 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) | |||
| 1338 | case ACB_ADAPTER_TYPE_C: { | 1552 | case ACB_ADAPTER_TYPE_C: { |
| 1339 | arcmsr_hbaC_stop_bgrb(acb); | 1553 | arcmsr_hbaC_stop_bgrb(acb); |
| 1340 | } | 1554 | } |
| 1555 | break; | ||
| 1556 | case ACB_ADAPTER_TYPE_D: | ||
| 1557 | arcmsr_hbaD_stop_bgrb(acb); | ||
| 1558 | break; | ||
| 1341 | } | 1559 | } |
| 1342 | } | 1560 | } |
| 1343 | 1561 | ||
| @@ -1362,8 +1580,16 @@ static void arcmsr_iop_message_read(struct AdapterControlBlock *acb) | |||
| 1362 | break; | 1580 | break; |
| 1363 | case ACB_ADAPTER_TYPE_C: { | 1581 | case ACB_ADAPTER_TYPE_C: { |
| 1364 | struct MessageUnit_C __iomem *reg = acb->pmuC; | 1582 | struct MessageUnit_C __iomem *reg = acb->pmuC; |
| 1583 | |||
| 1365 | writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, ®->inbound_doorbell); | 1584 | writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, ®->inbound_doorbell); |
| 1366 | } | 1585 | } |
| 1586 | break; | ||
| 1587 | case ACB_ADAPTER_TYPE_D: { | ||
| 1588 | struct MessageUnit_D *reg = acb->pmuD; | ||
| 1589 | writel(ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ, | ||
| 1590 | reg->inbound_doorbell); | ||
| 1591 | } | ||
| 1592 | break; | ||
| 1367 | } | 1593 | } |
| 1368 | } | 1594 | } |
| 1369 | 1595 | ||
| @@ -1398,6 +1624,12 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) | |||
| 1398 | writel(ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK, ®->inbound_doorbell); | 1624 | writel(ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK, ®->inbound_doorbell); |
| 1399 | } | 1625 | } |
| 1400 | break; | 1626 | break; |
| 1627 | case ACB_ADAPTER_TYPE_D: { | ||
| 1628 | struct MessageUnit_D *reg = acb->pmuD; | ||
| 1629 | writel(ARCMSR_ARC1214_DRV2IOP_DATA_IN_READY, | ||
| 1630 | reg->inbound_doorbell); | ||
| 1631 | } | ||
| 1632 | break; | ||
| 1401 | } | 1633 | } |
| 1402 | } | 1634 | } |
| 1403 | 1635 | ||
| @@ -1421,6 +1653,12 @@ struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb) | |||
| 1421 | struct MessageUnit_C __iomem *phbcmu = acb->pmuC; | 1653 | struct MessageUnit_C __iomem *phbcmu = acb->pmuC; |
| 1422 | qbuffer = (struct QBUFFER __iomem *)&phbcmu->message_rbuffer; | 1654 | qbuffer = (struct QBUFFER __iomem *)&phbcmu->message_rbuffer; |
| 1423 | } | 1655 | } |
| 1656 | break; | ||
| 1657 | case ACB_ADAPTER_TYPE_D: { | ||
| 1658 | struct MessageUnit_D *reg = acb->pmuD; | ||
| 1659 | qbuffer = (struct QBUFFER __iomem *)reg->message_rbuffer; | ||
| 1660 | } | ||
| 1661 | break; | ||
| 1424 | } | 1662 | } |
| 1425 | return qbuffer; | 1663 | return qbuffer; |
| 1426 | } | 1664 | } |
| @@ -1444,8 +1682,13 @@ static struct QBUFFER __iomem *arcmsr_get_iop_wqbuffer(struct AdapterControlBloc | |||
| 1444 | case ACB_ADAPTER_TYPE_C: { | 1682 | case ACB_ADAPTER_TYPE_C: { |
| 1445 | struct MessageUnit_C __iomem *reg = acb->pmuC; | 1683 | struct MessageUnit_C __iomem *reg = acb->pmuC; |
| 1446 | pqbuffer = (struct QBUFFER __iomem *)®->message_wbuffer; | 1684 | pqbuffer = (struct QBUFFER __iomem *)®->message_wbuffer; |
| 1447 | } | 1685 | } |
| 1448 | 1686 | break; | |
| 1687 | case ACB_ADAPTER_TYPE_D: { | ||
| 1688 | struct MessageUnit_D *reg = acb->pmuD; | ||
| 1689 | pqbuffer = (struct QBUFFER __iomem *)reg->message_wbuffer; | ||
| 1690 | } | ||
| 1691 | break; | ||
| 1449 | } | 1692 | } |
| 1450 | return pqbuffer; | 1693 | return pqbuffer; |
| 1451 | } | 1694 | } |
| @@ -1500,7 +1743,7 @@ arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, | |||
| 1500 | uint8_t __iomem *iop_data; | 1743 | uint8_t __iomem *iop_data; |
| 1501 | uint32_t iop_len; | 1744 | uint32_t iop_len; |
| 1502 | 1745 | ||
| 1503 | if (acb->adapter_type & ACB_ADAPTER_TYPE_C) | 1746 | if (acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) |
| 1504 | return arcmsr_Read_iop_rqbuffer_in_DWORD(acb, prbuffer); | 1747 | return arcmsr_Read_iop_rqbuffer_in_DWORD(acb, prbuffer); |
| 1505 | iop_data = (uint8_t __iomem *)prbuffer->data; | 1748 | iop_data = (uint8_t __iomem *)prbuffer->data; |
| 1506 | iop_len = readl(&prbuffer->data_len); | 1749 | iop_len = readl(&prbuffer->data_len); |
| @@ -1586,7 +1829,7 @@ arcmsr_write_ioctldata2iop(struct AdapterControlBlock *acb) | |||
| 1586 | uint8_t __iomem *iop_data; | 1829 | uint8_t __iomem *iop_data; |
| 1587 | int32_t allxfer_len = 0; | 1830 | int32_t allxfer_len = 0; |
| 1588 | 1831 | ||
| 1589 | if (acb->adapter_type & ACB_ADAPTER_TYPE_C) { | 1832 | if (acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) { |
| 1590 | arcmsr_write_ioctldata2iop_in_DWORD(acb); | 1833 | arcmsr_write_ioctldata2iop_in_DWORD(acb); |
| 1591 | return; | 1834 | return; |
| 1592 | } | 1835 | } |
| @@ -1662,6 +1905,27 @@ static void arcmsr_hbaC_doorbell_isr(struct AdapterControlBlock *pACB) | |||
| 1662 | | ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK | 1905 | | ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK |
| 1663 | | ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE)); | 1906 | | ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE)); |
| 1664 | } | 1907 | } |
| 1908 | |||
| 1909 | static void arcmsr_hbaD_doorbell_isr(struct AdapterControlBlock *pACB) | ||
| 1910 | { | ||
| 1911 | uint32_t outbound_doorbell; | ||
| 1912 | struct MessageUnit_D *pmu = pACB->pmuD; | ||
| 1913 | |||
| 1914 | outbound_doorbell = readl(pmu->outbound_doorbell); | ||
| 1915 | do { | ||
| 1916 | writel(outbound_doorbell, pmu->outbound_doorbell); | ||
| 1917 | if (outbound_doorbell & ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE) | ||
| 1918 | arcmsr_hbaD_message_isr(pACB); | ||
| 1919 | if (outbound_doorbell & ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK) | ||
| 1920 | arcmsr_iop2drv_data_wrote_handle(pACB); | ||
| 1921 | if (outbound_doorbell & ARCMSR_ARC1214_IOP2DRV_DATA_READ_OK) | ||
| 1922 | arcmsr_iop2drv_data_read_handle(pACB); | ||
| 1923 | outbound_doorbell = readl(pmu->outbound_doorbell); | ||
| 1924 | } while (outbound_doorbell & (ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK | ||
| 1925 | | ARCMSR_ARC1214_IOP2DRV_DATA_READ_OK | ||
| 1926 | | ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE)); | ||
| 1927 | } | ||
| 1928 | |||
| 1665 | static void arcmsr_hbaA_postqueue_isr(struct AdapterControlBlock *acb) | 1929 | static void arcmsr_hbaA_postqueue_isr(struct AdapterControlBlock *acb) |
| 1666 | { | 1930 | { |
| 1667 | uint32_t flag_ccb; | 1931 | uint32_t flag_ccb; |
| @@ -1728,6 +1992,59 @@ static void arcmsr_hbaC_postqueue_isr(struct AdapterControlBlock *acb) | |||
| 1728 | } | 1992 | } |
| 1729 | } | 1993 | } |
| 1730 | } | 1994 | } |
| 1995 | |||
| 1996 | static void arcmsr_hbaD_postqueue_isr(struct AdapterControlBlock *acb) | ||
| 1997 | { | ||
| 1998 | u32 outbound_write_pointer, doneq_index, index_stripped; | ||
| 1999 | uint32_t addressLow, ccb_cdb_phy; | ||
| 2000 | int error; | ||
| 2001 | struct MessageUnit_D *pmu; | ||
| 2002 | struct ARCMSR_CDB *arcmsr_cdb; | ||
| 2003 | struct CommandControlBlock *ccb; | ||
| 2004 | unsigned long flags; | ||
| 2005 | |||
| 2006 | spin_lock_irqsave(&acb->doneq_lock, flags); | ||
| 2007 | pmu = acb->pmuD; | ||
| 2008 | outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1; | ||
| 2009 | doneq_index = pmu->doneq_index; | ||
| 2010 | if ((doneq_index & 0xFFF) != (outbound_write_pointer & 0xFFF)) { | ||
| 2011 | do { | ||
| 2012 | if (doneq_index & 0x4000) { | ||
| 2013 | index_stripped = doneq_index & 0xFFF; | ||
| 2014 | index_stripped += 1; | ||
| 2015 | index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; | ||
| 2016 | pmu->doneq_index = index_stripped | ||
| 2017 | ? (index_stripped | 0x4000) : | ||
| 2018 | (index_stripped + 1); | ||
| 2019 | } else { | ||
| 2020 | index_stripped = doneq_index; | ||
| 2021 | index_stripped += 1; | ||
| 2022 | index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; | ||
| 2023 | pmu->doneq_index = index_stripped | ||
| 2024 | ? index_stripped : | ||
| 2025 | ((index_stripped | 0x4000) + 1); | ||
| 2026 | } | ||
| 2027 | doneq_index = pmu->doneq_index; | ||
| 2028 | addressLow = pmu->done_qbuffer[doneq_index & | ||
| 2029 | 0xFFF].addressLow; | ||
| 2030 | ccb_cdb_phy = (addressLow & 0xFFFFFFF0); | ||
| 2031 | arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset | ||
| 2032 | + ccb_cdb_phy); | ||
| 2033 | ccb = container_of(arcmsr_cdb, | ||
| 2034 | struct CommandControlBlock, arcmsr_cdb); | ||
| 2035 | error = (addressLow & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) | ||
| 2036 | ? true : false; | ||
| 2037 | arcmsr_drain_donequeue(acb, ccb, error); | ||
| 2038 | writel(doneq_index, pmu->outboundlist_read_pointer); | ||
| 2039 | } while ((doneq_index & 0xFFF) != | ||
| 2040 | (outbound_write_pointer & 0xFFF)); | ||
| 2041 | } | ||
| 2042 | writel(ARCMSR_ARC1214_OUTBOUND_LIST_INTERRUPT_CLEAR, | ||
| 2043 | pmu->outboundlist_interrupt_cause); | ||
| 2044 | readl(pmu->outboundlist_interrupt_cause); | ||
| 2045 | spin_unlock_irqrestore(&acb->doneq_lock, flags); | ||
| 2046 | } | ||
| 2047 | |||
| 1731 | /* | 2048 | /* |
| 1732 | ********************************************************************************** | 2049 | ********************************************************************************** |
| 1733 | ** Handle a message interrupt | 2050 | ** Handle a message interrupt |
| @@ -1768,6 +2085,15 @@ static void arcmsr_hbaC_message_isr(struct AdapterControlBlock *acb) | |||
| 1768 | schedule_work(&acb->arcmsr_do_message_isr_bh); | 2085 | schedule_work(&acb->arcmsr_do_message_isr_bh); |
| 1769 | } | 2086 | } |
| 1770 | 2087 | ||
| 2088 | static void arcmsr_hbaD_message_isr(struct AdapterControlBlock *acb) | ||
| 2089 | { | ||
| 2090 | struct MessageUnit_D *reg = acb->pmuD; | ||
| 2091 | |||
| 2092 | writel(ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE, reg->outbound_doorbell); | ||
| 2093 | readl(reg->outbound_doorbell); | ||
| 2094 | schedule_work(&acb->arcmsr_do_message_isr_bh); | ||
| 2095 | } | ||
| 2096 | |||
| 1771 | static int arcmsr_hbaA_handle_isr(struct AdapterControlBlock *acb) | 2097 | static int arcmsr_hbaA_handle_isr(struct AdapterControlBlock *acb) |
| 1772 | { | 2098 | { |
| 1773 | uint32_t outbound_intstatus; | 2099 | uint32_t outbound_intstatus; |
| @@ -1845,6 +2171,32 @@ static int arcmsr_hbaC_handle_isr(struct AdapterControlBlock *pACB) | |||
| 1845 | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR)); | 2171 | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR)); |
| 1846 | return IRQ_HANDLED; | 2172 | return IRQ_HANDLED; |
| 1847 | } | 2173 | } |
| 2174 | |||
| 2175 | static irqreturn_t arcmsr_hbaD_handle_isr(struct AdapterControlBlock *pACB) | ||
| 2176 | { | ||
| 2177 | u32 host_interrupt_status; | ||
| 2178 | struct MessageUnit_D *pmu = pACB->pmuD; | ||
| 2179 | |||
| 2180 | host_interrupt_status = readl(pmu->host_int_status) & | ||
| 2181 | (ARCMSR_ARC1214_OUTBOUND_POSTQUEUE_ISR | | ||
| 2182 | ARCMSR_ARC1214_OUTBOUND_DOORBELL_ISR); | ||
| 2183 | if (!host_interrupt_status) | ||
| 2184 | return IRQ_NONE; | ||
| 2185 | do { | ||
| 2186 | /* MU post queue interrupts*/ | ||
| 2187 | if (host_interrupt_status & | ||
| 2188 | ARCMSR_ARC1214_OUTBOUND_POSTQUEUE_ISR) | ||
| 2189 | arcmsr_hbaD_postqueue_isr(pACB); | ||
| 2190 | if (host_interrupt_status & | ||
| 2191 | ARCMSR_ARC1214_OUTBOUND_DOORBELL_ISR) | ||
| 2192 | arcmsr_hbaD_doorbell_isr(pACB); | ||
| 2193 | host_interrupt_status = readl(pmu->host_int_status); | ||
| 2194 | } while (host_interrupt_status & | ||
| 2195 | (ARCMSR_ARC1214_OUTBOUND_POSTQUEUE_ISR | | ||
| 2196 | ARCMSR_ARC1214_OUTBOUND_DOORBELL_ISR)); | ||
| 2197 | return IRQ_HANDLED; | ||
| 2198 | } | ||
| 2199 | |||
| 1848 | static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) | 2200 | static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) |
| 1849 | { | 2201 | { |
| 1850 | switch (acb->adapter_type) { | 2202 | switch (acb->adapter_type) { |
| @@ -1856,6 +2208,8 @@ static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) | |||
| 1856 | break; | 2208 | break; |
| 1857 | case ACB_ADAPTER_TYPE_C: | 2209 | case ACB_ADAPTER_TYPE_C: |
| 1858 | return arcmsr_hbaC_handle_isr(acb); | 2210 | return arcmsr_hbaC_handle_isr(acb); |
| 2211 | case ACB_ADAPTER_TYPE_D: | ||
| 2212 | return arcmsr_hbaD_handle_isr(acb); | ||
| 1859 | default: | 2213 | default: |
| 1860 | return IRQ_NONE; | 2214 | return IRQ_NONE; |
| 1861 | } | 2215 | } |
| @@ -2522,6 +2876,137 @@ static bool arcmsr_hbaC_get_config(struct AdapterControlBlock *pACB) | |||
| 2522 | /*all interrupt service will be enable at arcmsr_iop_init*/ | 2876 | /*all interrupt service will be enable at arcmsr_iop_init*/ |
| 2523 | return true; | 2877 | return true; |
| 2524 | } | 2878 | } |
| 2879 | |||
| 2880 | static bool arcmsr_hbaD_get_config(struct AdapterControlBlock *acb) | ||
| 2881 | { | ||
| 2882 | char *acb_firm_model = acb->firm_model; | ||
| 2883 | char *acb_firm_version = acb->firm_version; | ||
| 2884 | char *acb_device_map = acb->device_map; | ||
| 2885 | char __iomem *iop_firm_model; | ||
| 2886 | char __iomem *iop_firm_version; | ||
| 2887 | char __iomem *iop_device_map; | ||
| 2888 | u32 count; | ||
| 2889 | struct MessageUnit_D *reg ; | ||
| 2890 | void *dma_coherent2; | ||
| 2891 | dma_addr_t dma_coherent_handle2; | ||
| 2892 | struct pci_dev *pdev = acb->pdev; | ||
| 2893 | |||
| 2894 | acb->roundup_ccbsize = roundup(sizeof(struct MessageUnit_D), 32); | ||
| 2895 | dma_coherent2 = dma_alloc_coherent(&pdev->dev, acb->roundup_ccbsize, | ||
| 2896 | &dma_coherent_handle2, GFP_KERNEL); | ||
| 2897 | if (!dma_coherent2) { | ||
| 2898 | pr_notice("DMA allocation failed...\n"); | ||
| 2899 | return false; | ||
| 2900 | } | ||
| 2901 | memset(dma_coherent2, 0, acb->roundup_ccbsize); | ||
| 2902 | acb->dma_coherent_handle2 = dma_coherent_handle2; | ||
| 2903 | acb->dma_coherent2 = dma_coherent2; | ||
| 2904 | reg = (struct MessageUnit_D *)dma_coherent2; | ||
| 2905 | acb->pmuD = reg; | ||
| 2906 | reg->chip_id = acb->mem_base0 + ARCMSR_ARC1214_CHIP_ID; | ||
| 2907 | reg->cpu_mem_config = acb->mem_base0 + | ||
| 2908 | ARCMSR_ARC1214_CPU_MEMORY_CONFIGURATION; | ||
| 2909 | reg->i2o_host_interrupt_mask = acb->mem_base0 + | ||
| 2910 | ARCMSR_ARC1214_I2_HOST_INTERRUPT_MASK; | ||
| 2911 | reg->sample_at_reset = acb->mem_base0 + ARCMSR_ARC1214_SAMPLE_RESET; | ||
| 2912 | reg->reset_request = acb->mem_base0 + ARCMSR_ARC1214_RESET_REQUEST; | ||
| 2913 | reg->host_int_status = acb->mem_base0 + | ||
| 2914 | ARCMSR_ARC1214_MAIN_INTERRUPT_STATUS; | ||
| 2915 | reg->pcief0_int_enable = acb->mem_base0 + | ||
| 2916 | ARCMSR_ARC1214_PCIE_F0_INTERRUPT_ENABLE; | ||
| 2917 | reg->inbound_msgaddr0 = acb->mem_base0 + | ||
| 2918 | ARCMSR_ARC1214_INBOUND_MESSAGE0; | ||
| 2919 | reg->inbound_msgaddr1 = acb->mem_base0 + | ||
| 2920 | ARCMSR_ARC1214_INBOUND_MESSAGE1; | ||
| 2921 | reg->outbound_msgaddr0 = acb->mem_base0 + | ||
| 2922 | ARCMSR_ARC1214_OUTBOUND_MESSAGE0; | ||
| 2923 | reg->outbound_msgaddr1 = acb->mem_base0 + | ||
| 2924 | ARCMSR_ARC1214_OUTBOUND_MESSAGE1; | ||
| 2925 | reg->inbound_doorbell = acb->mem_base0 + | ||
| 2926 | ARCMSR_ARC1214_INBOUND_DOORBELL; | ||
| 2927 | reg->outbound_doorbell = acb->mem_base0 + | ||
| 2928 | ARCMSR_ARC1214_OUTBOUND_DOORBELL; | ||
| 2929 | reg->outbound_doorbell_enable = acb->mem_base0 + | ||
| 2930 | ARCMSR_ARC1214_OUTBOUND_DOORBELL_ENABLE; | ||
| 2931 | reg->inboundlist_base_low = acb->mem_base0 + | ||
| 2932 | ARCMSR_ARC1214_INBOUND_LIST_BASE_LOW; | ||
| 2933 | reg->inboundlist_base_high = acb->mem_base0 + | ||
| 2934 | ARCMSR_ARC1214_INBOUND_LIST_BASE_HIGH; | ||
| 2935 | reg->inboundlist_write_pointer = acb->mem_base0 + | ||
| 2936 | ARCMSR_ARC1214_INBOUND_LIST_WRITE_POINTER; | ||
| 2937 | reg->outboundlist_base_low = acb->mem_base0 + | ||
| 2938 | ARCMSR_ARC1214_OUTBOUND_LIST_BASE_LOW; | ||
| 2939 | reg->outboundlist_base_high = acb->mem_base0 + | ||
| 2940 | ARCMSR_ARC1214_OUTBOUND_LIST_BASE_HIGH; | ||
| 2941 | reg->outboundlist_copy_pointer = acb->mem_base0 + | ||
| 2942 | ARCMSR_ARC1214_OUTBOUND_LIST_COPY_POINTER; | ||
| 2943 | reg->outboundlist_read_pointer = acb->mem_base0 + | ||
| 2944 | ARCMSR_ARC1214_OUTBOUND_LIST_READ_POINTER; | ||
| 2945 | reg->outboundlist_interrupt_cause = acb->mem_base0 + | ||
| 2946 | ARCMSR_ARC1214_OUTBOUND_INTERRUPT_CAUSE; | ||
| 2947 | reg->outboundlist_interrupt_enable = acb->mem_base0 + | ||
| 2948 | ARCMSR_ARC1214_OUTBOUND_INTERRUPT_ENABLE; | ||
| 2949 | reg->message_wbuffer = acb->mem_base0 + ARCMSR_ARC1214_MESSAGE_WBUFFER; | ||
| 2950 | reg->message_rbuffer = acb->mem_base0 + ARCMSR_ARC1214_MESSAGE_RBUFFER; | ||
| 2951 | reg->msgcode_rwbuffer = acb->mem_base0 + | ||
| 2952 | ARCMSR_ARC1214_MESSAGE_RWBUFFER; | ||
| 2953 | iop_firm_model = (char __iomem *)(®->msgcode_rwbuffer[15]); | ||
| 2954 | iop_firm_version = (char __iomem *)(®->msgcode_rwbuffer[17]); | ||
| 2955 | iop_device_map = (char __iomem *)(®->msgcode_rwbuffer[21]); | ||
| 2956 | if (readl(acb->pmuD->outbound_doorbell) & | ||
| 2957 | ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE) { | ||
| 2958 | writel(ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE, | ||
| 2959 | acb->pmuD->outbound_doorbell);/*clear interrupt*/ | ||
| 2960 | } | ||
| 2961 | /* post "get config" instruction */ | ||
| 2962 | writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, reg->inbound_msgaddr0); | ||
| 2963 | /* wait message ready */ | ||
| 2964 | if (!arcmsr_hbaD_wait_msgint_ready(acb)) { | ||
| 2965 | pr_notice("arcmsr%d: wait get adapter firmware " | ||
| 2966 | "miscellaneous data timeout\n", acb->host->host_no); | ||
| 2967 | dma_free_coherent(&acb->pdev->dev, acb->roundup_ccbsize, | ||
| 2968 | acb->dma_coherent2, acb->dma_coherent_handle2); | ||
| 2969 | return false; | ||
| 2970 | } | ||
| 2971 | count = 8; | ||
| 2972 | while (count) { | ||
| 2973 | *acb_firm_model = readb(iop_firm_model); | ||
| 2974 | acb_firm_model++; | ||
| 2975 | iop_firm_model++; | ||
| 2976 | count--; | ||
| 2977 | } | ||
| 2978 | count = 16; | ||
| 2979 | while (count) { | ||
| 2980 | *acb_firm_version = readb(iop_firm_version); | ||
| 2981 | acb_firm_version++; | ||
| 2982 | iop_firm_version++; | ||
| 2983 | count--; | ||
| 2984 | } | ||
| 2985 | count = 16; | ||
| 2986 | while (count) { | ||
| 2987 | *acb_device_map = readb(iop_device_map); | ||
| 2988 | acb_device_map++; | ||
| 2989 | iop_device_map++; | ||
| 2990 | count--; | ||
| 2991 | } | ||
| 2992 | acb->signature = readl(®->msgcode_rwbuffer[1]); | ||
| 2993 | /*firm_signature,1,00-03*/ | ||
| 2994 | acb->firm_request_len = readl(®->msgcode_rwbuffer[2]); | ||
| 2995 | /*firm_request_len,1,04-07*/ | ||
| 2996 | acb->firm_numbers_queue = readl(®->msgcode_rwbuffer[3]); | ||
| 2997 | /*firm_numbers_queue,2,08-11*/ | ||
| 2998 | acb->firm_sdram_size = readl(®->msgcode_rwbuffer[4]); | ||
| 2999 | /*firm_sdram_size,3,12-15*/ | ||
| 3000 | acb->firm_hd_channels = readl(®->msgcode_rwbuffer[5]); | ||
| 3001 | /*firm_hd_channels,4,16-19*/ | ||
| 3002 | acb->firm_cfg_version = readl(®->msgcode_rwbuffer[25]); | ||
| 3003 | pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n", | ||
| 3004 | acb->host->host_no, | ||
| 3005 | acb->firm_model, | ||
| 3006 | acb->firm_version); | ||
| 3007 | return true; | ||
| 3008 | } | ||
| 3009 | |||
| 2525 | static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) | 3010 | static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) |
| 2526 | { | 3011 | { |
| 2527 | bool rtn = false; | 3012 | bool rtn = false; |
| @@ -2536,6 +3021,9 @@ static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) | |||
| 2536 | case ACB_ADAPTER_TYPE_C: | 3021 | case ACB_ADAPTER_TYPE_C: |
| 2537 | rtn = arcmsr_hbaC_get_config(acb); | 3022 | rtn = arcmsr_hbaC_get_config(acb); |
| 2538 | break; | 3023 | break; |
| 3024 | case ACB_ADAPTER_TYPE_D: | ||
| 3025 | rtn = arcmsr_hbaD_get_config(acb); | ||
| 3026 | break; | ||
| 2539 | default: | 3027 | default: |
| 2540 | break; | 3028 | break; |
| 2541 | } | 3029 | } |
| @@ -2725,6 +3213,89 @@ polling_hbc_ccb_retry: | |||
| 2725 | } | 3213 | } |
| 2726 | return rtn; | 3214 | return rtn; |
| 2727 | } | 3215 | } |
| 3216 | |||
| 3217 | static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb, | ||
| 3218 | struct CommandControlBlock *poll_ccb) | ||
| 3219 | { | ||
| 3220 | bool error; | ||
| 3221 | uint32_t poll_ccb_done = 0, poll_count = 0, flag_ccb, ccb_cdb_phy; | ||
| 3222 | int rtn, doneq_index, index_stripped, outbound_write_pointer; | ||
| 3223 | unsigned long flags; | ||
| 3224 | struct ARCMSR_CDB *arcmsr_cdb; | ||
| 3225 | struct CommandControlBlock *pCCB; | ||
| 3226 | struct MessageUnit_D *pmu = acb->pmuD; | ||
| 3227 | |||
| 3228 | polling_hbaD_ccb_retry: | ||
| 3229 | poll_count++; | ||
| 3230 | while (1) { | ||
| 3231 | outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1; | ||
| 3232 | doneq_index = pmu->doneq_index; | ||
| 3233 | if ((outbound_write_pointer & 0xFFF) == (doneq_index & 0xFFF)) { | ||
| 3234 | if (poll_ccb_done) { | ||
| 3235 | rtn = SUCCESS; | ||
| 3236 | break; | ||
| 3237 | } else { | ||
| 3238 | msleep(25); | ||
| 3239 | if (poll_count > 40) { | ||
| 3240 | rtn = FAILED; | ||
| 3241 | break; | ||
| 3242 | } | ||
| 3243 | goto polling_hbaD_ccb_retry; | ||
| 3244 | } | ||
| 3245 | } | ||
| 3246 | spin_lock_irqsave(&acb->doneq_lock, flags); | ||
| 3247 | if (doneq_index & 0x4000) { | ||
| 3248 | index_stripped = doneq_index & 0xFFF; | ||
| 3249 | index_stripped += 1; | ||
| 3250 | index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; | ||
| 3251 | pmu->doneq_index = index_stripped ? | ||
| 3252 | (index_stripped | 0x4000) : | ||
| 3253 | (index_stripped + 1); | ||
| 3254 | } else { | ||
| 3255 | index_stripped = doneq_index; | ||
| 3256 | index_stripped += 1; | ||
| 3257 | index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; | ||
| 3258 | pmu->doneq_index = index_stripped ? index_stripped : | ||
| 3259 | ((index_stripped | 0x4000) + 1); | ||
| 3260 | } | ||
| 3261 | spin_unlock_irqrestore(&acb->doneq_lock, flags); | ||
| 3262 | doneq_index = pmu->doneq_index; | ||
| 3263 | flag_ccb = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow; | ||
| 3264 | ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0); | ||
| 3265 | arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + | ||
| 3266 | ccb_cdb_phy); | ||
| 3267 | pCCB = container_of(arcmsr_cdb, struct CommandControlBlock, | ||
| 3268 | arcmsr_cdb); | ||
| 3269 | poll_ccb_done |= (pCCB == poll_ccb) ? 1 : 0; | ||
| 3270 | if ((pCCB->acb != acb) || | ||
| 3271 | (pCCB->startdone != ARCMSR_CCB_START)) { | ||
| 3272 | if (pCCB->startdone == ARCMSR_CCB_ABORTED) { | ||
| 3273 | pr_notice("arcmsr%d: scsi id = %d " | ||
| 3274 | "lun = %d ccb = '0x%p' poll command " | ||
| 3275 | "abort successfully\n" | ||
| 3276 | , acb->host->host_no | ||
| 3277 | , pCCB->pcmd->device->id | ||
| 3278 | , (u32)pCCB->pcmd->device->lun | ||
| 3279 | , pCCB); | ||
| 3280 | pCCB->pcmd->result = DID_ABORT << 16; | ||
| 3281 | arcmsr_ccb_complete(pCCB); | ||
| 3282 | continue; | ||
| 3283 | } | ||
| 3284 | pr_notice("arcmsr%d: polling an illegal " | ||
| 3285 | "ccb command done ccb = '0x%p' " | ||
| 3286 | "ccboutstandingcount = %d\n" | ||
| 3287 | , acb->host->host_no | ||
| 3288 | , pCCB | ||
| 3289 | , atomic_read(&acb->ccboutstandingcount)); | ||
| 3290 | continue; | ||
| 3291 | } | ||
| 3292 | error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) | ||
| 3293 | ? true : false; | ||
| 3294 | arcmsr_report_ccb_state(acb, pCCB, error); | ||
| 3295 | } | ||
| 3296 | return rtn; | ||
| 3297 | } | ||
| 3298 | |||
| 2728 | static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, | 3299 | static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, |
| 2729 | struct CommandControlBlock *poll_ccb) | 3300 | struct CommandControlBlock *poll_ccb) |
| 2730 | { | 3301 | { |
| @@ -2743,6 +3314,10 @@ static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, | |||
| 2743 | case ACB_ADAPTER_TYPE_C: { | 3314 | case ACB_ADAPTER_TYPE_C: { |
| 2744 | rtn = arcmsr_hbaC_polling_ccbdone(acb, poll_ccb); | 3315 | rtn = arcmsr_hbaC_polling_ccbdone(acb, poll_ccb); |
| 2745 | } | 3316 | } |
| 3317 | break; | ||
| 3318 | case ACB_ADAPTER_TYPE_D: | ||
| 3319 | rtn = arcmsr_hbaD_polling_ccbdone(acb, poll_ccb); | ||
| 3320 | break; | ||
| 2746 | } | 3321 | } |
| 2747 | return rtn; | 3322 | return rtn; |
| 2748 | } | 3323 | } |
| @@ -2760,6 +3335,7 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) | |||
| 2760 | */ | 3335 | */ |
| 2761 | switch (acb->adapter_type) { | 3336 | switch (acb->adapter_type) { |
| 2762 | case ACB_ADAPTER_TYPE_B: | 3337 | case ACB_ADAPTER_TYPE_B: |
| 3338 | case ACB_ADAPTER_TYPE_D: | ||
| 2763 | dma_coherent_handle = acb->dma_coherent_handle2; | 3339 | dma_coherent_handle = acb->dma_coherent_handle2; |
| 2764 | break; | 3340 | break; |
| 2765 | default: | 3341 | default: |
| @@ -2849,6 +3425,27 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) | |||
| 2849 | } | 3425 | } |
| 2850 | } | 3426 | } |
| 2851 | } | 3427 | } |
| 3428 | break; | ||
| 3429 | case ACB_ADAPTER_TYPE_D: { | ||
| 3430 | uint32_t __iomem *rwbuffer; | ||
| 3431 | struct MessageUnit_D *reg = acb->pmuD; | ||
| 3432 | reg->postq_index = 0; | ||
| 3433 | reg->doneq_index = 0; | ||
| 3434 | rwbuffer = reg->msgcode_rwbuffer; | ||
| 3435 | writel(ARCMSR_SIGNATURE_SET_CONFIG, rwbuffer++); | ||
| 3436 | writel(cdb_phyaddr_hi32, rwbuffer++); | ||
| 3437 | writel(cdb_phyaddr, rwbuffer++); | ||
| 3438 | writel(cdb_phyaddr + (ARCMSR_MAX_ARC1214_POSTQUEUE * | ||
| 3439 | sizeof(struct InBound_SRB)), rwbuffer++); | ||
| 3440 | writel(0x100, rwbuffer); | ||
| 3441 | writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, reg->inbound_msgaddr0); | ||
| 3442 | if (!arcmsr_hbaD_wait_msgint_ready(acb)) { | ||
| 3443 | pr_notice("arcmsr%d: 'set command Q window' timeout\n", | ||
| 3444 | acb->host->host_no); | ||
| 3445 | return 1; | ||
| 3446 | } | ||
| 3447 | } | ||
| 3448 | break; | ||
| 2852 | } | 3449 | } |
| 2853 | return 0; | 3450 | return 0; |
| 2854 | } | 3451 | } |
| @@ -2880,6 +3477,15 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) | |||
| 2880 | firmware_state = readl(®->outbound_msgaddr1); | 3477 | firmware_state = readl(®->outbound_msgaddr1); |
| 2881 | } while ((firmware_state & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0); | 3478 | } while ((firmware_state & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0); |
| 2882 | } | 3479 | } |
| 3480 | break; | ||
| 3481 | case ACB_ADAPTER_TYPE_D: { | ||
| 3482 | struct MessageUnit_D *reg = acb->pmuD; | ||
| 3483 | do { | ||
| 3484 | firmware_state = readl(reg->outbound_msgaddr1); | ||
| 3485 | } while ((firmware_state & | ||
| 3486 | ARCMSR_ARC1214_MESSAGE_FIRMWARE_OK) == 0); | ||
| 3487 | } | ||
| 3488 | break; | ||
| 2883 | } | 3489 | } |
| 2884 | } | 3490 | } |
| 2885 | 3491 | ||
| @@ -2950,6 +3556,35 @@ static void arcmsr_hbaC_request_device_map(struct AdapterControlBlock *acb) | |||
| 2950 | return; | 3556 | return; |
| 2951 | } | 3557 | } |
| 2952 | 3558 | ||
| 3559 | static void arcmsr_hbaD_request_device_map(struct AdapterControlBlock *acb) | ||
| 3560 | { | ||
| 3561 | struct MessageUnit_D *reg = acb->pmuD; | ||
| 3562 | |||
| 3563 | if (unlikely(atomic_read(&acb->rq_map_token) == 0) || | ||
| 3564 | ((acb->acb_flags & ACB_F_BUS_RESET) != 0) || | ||
| 3565 | ((acb->acb_flags & ACB_F_ABORT) != 0)) { | ||
| 3566 | mod_timer(&acb->eternal_timer, | ||
| 3567 | jiffies + msecs_to_jiffies(6 * HZ)); | ||
| 3568 | } else { | ||
| 3569 | acb->fw_flag = FW_NORMAL; | ||
| 3570 | if (atomic_read(&acb->ante_token_value) == | ||
| 3571 | atomic_read(&acb->rq_map_token)) { | ||
| 3572 | atomic_set(&acb->rq_map_token, 16); | ||
| 3573 | } | ||
| 3574 | atomic_set(&acb->ante_token_value, | ||
| 3575 | atomic_read(&acb->rq_map_token)); | ||
| 3576 | if (atomic_dec_and_test(&acb->rq_map_token)) { | ||
| 3577 | mod_timer(&acb->eternal_timer, jiffies + | ||
| 3578 | msecs_to_jiffies(6 * HZ)); | ||
| 3579 | return; | ||
| 3580 | } | ||
| 3581 | writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, | ||
| 3582 | reg->inbound_msgaddr0); | ||
| 3583 | mod_timer(&acb->eternal_timer, jiffies + | ||
| 3584 | msecs_to_jiffies(6 * HZ)); | ||
| 3585 | } | ||
| 3586 | } | ||
| 3587 | |||
| 2953 | static void arcmsr_request_device_map(unsigned long pacb) | 3588 | static void arcmsr_request_device_map(unsigned long pacb) |
| 2954 | { | 3589 | { |
| 2955 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *)pacb; | 3590 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *)pacb; |
| @@ -2965,6 +3600,10 @@ static void arcmsr_request_device_map(unsigned long pacb) | |||
| 2965 | case ACB_ADAPTER_TYPE_C: { | 3600 | case ACB_ADAPTER_TYPE_C: { |
| 2966 | arcmsr_hbaC_request_device_map(acb); | 3601 | arcmsr_hbaC_request_device_map(acb); |
| 2967 | } | 3602 | } |
| 3603 | break; | ||
| 3604 | case ACB_ADAPTER_TYPE_D: | ||
| 3605 | arcmsr_hbaD_request_device_map(acb); | ||
| 3606 | break; | ||
| 2968 | } | 3607 | } |
| 2969 | } | 3608 | } |
| 2970 | 3609 | ||
| @@ -3002,6 +3641,19 @@ static void arcmsr_hbaC_start_bgrb(struct AdapterControlBlock *pACB) | |||
| 3002 | } | 3641 | } |
| 3003 | return; | 3642 | return; |
| 3004 | } | 3643 | } |
| 3644 | |||
| 3645 | static void arcmsr_hbaD_start_bgrb(struct AdapterControlBlock *pACB) | ||
| 3646 | { | ||
| 3647 | struct MessageUnit_D *pmu = pACB->pmuD; | ||
| 3648 | |||
| 3649 | pACB->acb_flags |= ACB_F_MSG_START_BGRB; | ||
| 3650 | writel(ARCMSR_INBOUND_MESG0_START_BGRB, pmu->inbound_msgaddr0); | ||
| 3651 | if (!arcmsr_hbaD_wait_msgint_ready(pACB)) { | ||
| 3652 | pr_notice("arcmsr%d: wait 'start adapter " | ||
| 3653 | "background rebulid' timeout\n", pACB->host->host_no); | ||
| 3654 | } | ||
| 3655 | } | ||
| 3656 | |||
| 3005 | static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) | 3657 | static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) |
| 3006 | { | 3658 | { |
| 3007 | switch (acb->adapter_type) { | 3659 | switch (acb->adapter_type) { |
| @@ -3013,6 +3665,10 @@ static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) | |||
| 3013 | break; | 3665 | break; |
| 3014 | case ACB_ADAPTER_TYPE_C: | 3666 | case ACB_ADAPTER_TYPE_C: |
| 3015 | arcmsr_hbaC_start_bgrb(acb); | 3667 | arcmsr_hbaC_start_bgrb(acb); |
| 3668 | break; | ||
| 3669 | case ACB_ADAPTER_TYPE_D: | ||
| 3670 | arcmsr_hbaD_start_bgrb(acb); | ||
| 3671 | break; | ||
| 3016 | } | 3672 | } |
| 3017 | } | 3673 | } |
| 3018 | 3674 | ||
| @@ -3058,6 +3714,29 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb) | |||
| 3058 | break; | 3714 | break; |
| 3059 | } | 3715 | } |
| 3060 | } | 3716 | } |
| 3717 | break; | ||
| 3718 | case ACB_ADAPTER_TYPE_D: { | ||
| 3719 | struct MessageUnit_D *reg = acb->pmuD; | ||
| 3720 | uint32_t outbound_doorbell, i; | ||
| 3721 | /* empty doorbell Qbuffer if door bell ringed */ | ||
| 3722 | outbound_doorbell = readl(reg->outbound_doorbell); | ||
| 3723 | writel(outbound_doorbell, reg->outbound_doorbell); | ||
| 3724 | writel(ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ, | ||
| 3725 | reg->inbound_doorbell); | ||
| 3726 | for (i = 0; i < 200; i++) { | ||
| 3727 | msleep(20); | ||
| 3728 | outbound_doorbell = readl(reg->outbound_doorbell); | ||
| 3729 | if (outbound_doorbell & | ||
| 3730 | ARCMSR_ARC1214_IOP2DRV_DATA_WRITE_OK) { | ||
| 3731 | writel(outbound_doorbell, | ||
| 3732 | reg->outbound_doorbell); | ||
| 3733 | writel(ARCMSR_ARC1214_DRV2IOP_DATA_OUT_READ, | ||
| 3734 | reg->inbound_doorbell); | ||
| 3735 | } else | ||
| 3736 | break; | ||
| 3737 | } | ||
| 3738 | } | ||
| 3739 | break; | ||
| 3061 | } | 3740 | } |
| 3062 | } | 3741 | } |
| 3063 | 3742 | ||
| @@ -3088,6 +3767,7 @@ static void arcmsr_hardware_reset(struct AdapterControlBlock *acb) | |||
| 3088 | int i, count = 0; | 3767 | int i, count = 0; |
| 3089 | struct MessageUnit_A __iomem *pmuA = acb->pmuA; | 3768 | struct MessageUnit_A __iomem *pmuA = acb->pmuA; |
| 3090 | struct MessageUnit_C __iomem *pmuC = acb->pmuC; | 3769 | struct MessageUnit_C __iomem *pmuC = acb->pmuC; |
| 3770 | struct MessageUnit_D *pmuD = acb->pmuD; | ||
| 3091 | 3771 | ||
| 3092 | /* backup pci config data */ | 3772 | /* backup pci config data */ |
| 3093 | printk(KERN_NOTICE "arcmsr%d: executing hw bus reset .....\n", acb->host->host_no); | 3773 | printk(KERN_NOTICE "arcmsr%d: executing hw bus reset .....\n", acb->host->host_no); |
| @@ -3108,6 +3788,8 @@ static void arcmsr_hardware_reset(struct AdapterControlBlock *acb) | |||
| 3108 | writel(0xD, &pmuC->write_sequence); | 3788 | writel(0xD, &pmuC->write_sequence); |
| 3109 | } while (((readl(&pmuC->host_diagnostic) & ARCMSR_ARC1880_DiagWrite_ENABLE) == 0) && (count < 5)); | 3789 | } while (((readl(&pmuC->host_diagnostic) & ARCMSR_ARC1880_DiagWrite_ENABLE) == 0) && (count < 5)); |
| 3110 | writel(ARCMSR_ARC1880_RESET_ADAPTER, &pmuC->host_diagnostic); | 3790 | writel(ARCMSR_ARC1880_RESET_ADAPTER, &pmuC->host_diagnostic); |
| 3791 | } else if ((acb->dev_id == 0x1214)) { | ||
| 3792 | writel(0x20, pmuD->reset_request); | ||
| 3111 | } else { | 3793 | } else { |
| 3112 | pci_write_config_byte(acb->pdev, 0x84, 0x20); | 3794 | pci_write_config_byte(acb->pdev, 0x84, 0x20); |
| 3113 | } | 3795 | } |
| @@ -3304,6 +3986,66 @@ sleep: | |||
| 3304 | } | 3986 | } |
| 3305 | break; | 3987 | break; |
| 3306 | } | 3988 | } |
| 3989 | case ACB_ADAPTER_TYPE_D: { | ||
| 3990 | if (acb->acb_flags & ACB_F_BUS_RESET) { | ||
| 3991 | long timeout; | ||
| 3992 | pr_notice("arcmsr: there is an bus reset" | ||
| 3993 | " eh proceeding.......\n"); | ||
| 3994 | timeout = wait_event_timeout(wait_q, (acb->acb_flags | ||
| 3995 | & ACB_F_BUS_RESET) == 0, 220 * HZ); | ||
| 3996 | if (timeout) | ||
| 3997 | return SUCCESS; | ||
| 3998 | } | ||
| 3999 | acb->acb_flags |= ACB_F_BUS_RESET; | ||
| 4000 | if (!arcmsr_iop_reset(acb)) { | ||
| 4001 | struct MessageUnit_D *reg; | ||
| 4002 | reg = acb->pmuD; | ||
| 4003 | arcmsr_hardware_reset(acb); | ||
| 4004 | acb->acb_flags &= ~ACB_F_IOP_INITED; | ||
| 4005 | nap: | ||
| 4006 | ssleep(ARCMSR_SLEEPTIME); | ||
| 4007 | if ((readl(reg->sample_at_reset) & 0x80) != 0) { | ||
| 4008 | pr_err("arcmsr%d: waiting for " | ||
| 4009 | "hw bus reset return, retry=%d\n", | ||
| 4010 | acb->host->host_no, retry_count); | ||
| 4011 | if (retry_count > ARCMSR_RETRYCOUNT) { | ||
| 4012 | acb->fw_flag = FW_DEADLOCK; | ||
| 4013 | pr_err("arcmsr%d: waiting for hw bus" | ||
| 4014 | " reset return, " | ||
| 4015 | "RETRY TERMINATED!!\n", | ||
| 4016 | acb->host->host_no); | ||
| 4017 | return FAILED; | ||
| 4018 | } | ||
| 4019 | retry_count++; | ||
| 4020 | goto nap; | ||
| 4021 | } | ||
| 4022 | acb->acb_flags |= ACB_F_IOP_INITED; | ||
| 4023 | /* disable all outbound interrupt */ | ||
| 4024 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
| 4025 | arcmsr_get_firmware_spec(acb); | ||
| 4026 | arcmsr_start_adapter_bgrb(acb); | ||
| 4027 | arcmsr_clear_doorbell_queue_buffer(acb); | ||
| 4028 | arcmsr_enable_outbound_ints(acb, intmask_org); | ||
| 4029 | atomic_set(&acb->rq_map_token, 16); | ||
| 4030 | atomic_set(&acb->ante_token_value, 16); | ||
| 4031 | acb->fw_flag = FW_NORMAL; | ||
| 4032 | mod_timer(&acb->eternal_timer, | ||
| 4033 | jiffies + msecs_to_jiffies(6 * HZ)); | ||
| 4034 | acb->acb_flags &= ~ACB_F_BUS_RESET; | ||
| 4035 | rtn = SUCCESS; | ||
| 4036 | pr_err("arcmsr: scsi bus reset " | ||
| 4037 | "eh returns with success\n"); | ||
| 4038 | } else { | ||
| 4039 | acb->acb_flags &= ~ACB_F_BUS_RESET; | ||
| 4040 | atomic_set(&acb->rq_map_token, 16); | ||
| 4041 | atomic_set(&acb->ante_token_value, 16); | ||
| 4042 | acb->fw_flag = FW_NORMAL; | ||
| 4043 | mod_timer(&acb->eternal_timer, | ||
| 4044 | jiffies + msecs_to_jiffies(6 * HZ)); | ||
| 4045 | rtn = SUCCESS; | ||
| 4046 | } | ||
| 4047 | break; | ||
| 4048 | } | ||
| 3307 | } | 4049 | } |
| 3308 | return rtn; | 4050 | return rtn; |
| 3309 | } | 4051 | } |
| @@ -3380,6 +4122,7 @@ static const char *arcmsr_info(struct Scsi_Host *host) | |||
| 3380 | case PCI_DEVICE_ID_ARECA_1280: | 4122 | case PCI_DEVICE_ID_ARECA_1280: |
| 3381 | type = "SATA"; | 4123 | type = "SATA"; |
| 3382 | break; | 4124 | break; |
| 4125 | case PCI_DEVICE_ID_ARECA_1214: | ||
| 3383 | case PCI_DEVICE_ID_ARECA_1380: | 4126 | case PCI_DEVICE_ID_ARECA_1380: |
| 3384 | case PCI_DEVICE_ID_ARECA_1381: | 4127 | case PCI_DEVICE_ID_ARECA_1381: |
| 3385 | case PCI_DEVICE_ID_ARECA_1680: | 4128 | case PCI_DEVICE_ID_ARECA_1680: |
