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 | |
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>
-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: |