diff options
author | Nick Cheng <nick.cheng@areca.com.tw> | 2008-02-05 02:53:24 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-02-07 19:02:44 -0500 |
commit | 76d78300a6eb8b7f08e47703b7e68a659ffc2053 (patch) | |
tree | 8677873e725417a8b8eaede4d4a76e247ed15eaa | |
parent | 63adcc5862cf95f29c8c07d59458f102700da100 (diff) |
[SCSI] arcmsr: updates (1.20.00.15)
- add arcmsr_enable_eoi_mode()and readl(reg->iop2drv_doorbell_reg) in
arcmsr_handle_hbb_isr() on adapter Type B in case of the doorbell
interrupt clearance is cached
- add conditional declaration for arcmsr_pci_error_detected() and
arcmsr_pci_slot_reset
- check if the sg list member number exceeds arcmsr default limit in
arcmsr_build_ccb()
- change the returned value type of arcmsr_build_ccb()from "void" to
"int" returns FAILED in arcmsr_queue_command()
- modify arcmsr_drain_donequeue() to ignore unknown command and let
kernel process command timeout. This could handle IO request violating
maximum segments, i.e. Linux XFS over DM-CRYPT. Thanks to Milan Broz's
comments <mbroz@redhat.com>
- fix the release of dma memory for type B in arcmsr_free_ccb_pool()
- fix the arcmsr_polling_hbb_ccbdone()
Signed-off-by: Nick Cheng <nick.cheng@areca.com.tw>
Cc: Milan Broz <mbroz@redhat.com>
Cc: <thenzl@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r-- | Documentation/scsi/ChangeLog.arcmsr | 41 | ||||
-rw-r--r-- | drivers/scsi/arcmsr/arcmsr.h | 4 | ||||
-rw-r--r-- | drivers/scsi/arcmsr/arcmsr_hba.c | 87 |
3 files changed, 105 insertions, 27 deletions
diff --git a/Documentation/scsi/ChangeLog.arcmsr b/Documentation/scsi/ChangeLog.arcmsr index cd8403a33ee6..de2bcacfa870 100644 --- a/Documentation/scsi/ChangeLog.arcmsr +++ b/Documentation/scsi/ChangeLog.arcmsr | |||
@@ -68,4 +68,45 @@ | |||
68 | ** 2. modify the arcmsr_pci_slot_reset function | 68 | ** 2. modify the arcmsr_pci_slot_reset function |
69 | ** 3. modify the arcmsr_pci_ers_disconnect_forepart function | 69 | ** 3. modify the arcmsr_pci_ers_disconnect_forepart function |
70 | ** 4. modify the arcmsr_pci_ers_need_reset_forepart function | 70 | ** 4. modify the arcmsr_pci_ers_need_reset_forepart function |
71 | ** 1.20.00.15 09/27/2007 Erich Chen & Nick Cheng | ||
72 | ** 1. add arcmsr_enable_eoi_mode() on adapter Type B | ||
73 | ** 2. add readl(reg->iop2drv_doorbell_reg) in arcmsr_handle_hbb_isr() | ||
74 | ** in case of the doorbell interrupt clearance is cached | ||
75 | ** 1.20.00.15 10/01/2007 Erich Chen & Nick Cheng | ||
76 | ** 1. modify acb->devstate[i][j] | ||
77 | ** as ARECA_RAID_GOOD instead of | ||
78 | ** ARECA_RAID_GONE in arcmsr_alloc_ccb_pool | ||
79 | ** 1.20.00.15 11/06/2007 Erich Chen & Nick Cheng | ||
80 | ** 1. add conditional declaration for | ||
81 | ** arcmsr_pci_error_detected() and | ||
82 | ** arcmsr_pci_slot_reset | ||
83 | ** 1.20.00.15 11/23/2007 Erich Chen & Nick Cheng | ||
84 | ** 1.check if the sg list member number | ||
85 | ** exceeds arcmsr default limit in arcmsr_build_ccb() | ||
86 | ** 2.change the returned value type of arcmsr_build_ccb() | ||
87 | ** from "void" to "int" | ||
88 | ** 3.add the conditional check if arcmsr_build_ccb() | ||
89 | ** returns FAILED | ||
90 | ** 1.20.00.15 12/04/2007 Erich Chen & Nick Cheng | ||
91 | ** 1. modify arcmsr_drain_donequeue() to ignore unknown | ||
92 | ** command and let kernel process command timeout. | ||
93 | ** This could handle IO request violating max. segments | ||
94 | ** while Linux XFS over DM-CRYPT. | ||
95 | ** Thanks to Milan Broz's comments <mbroz@redhat.com> | ||
96 | ** 1.20.00.15 12/24/2007 Erich Chen & Nick Cheng | ||
97 | ** 1.fix the portability problems | ||
98 | ** 2.fix type B where we should _not_ iounmap() acb->pmu; | ||
99 | ** it's not ioremapped. | ||
100 | ** 3.add return -ENOMEM if ioremap() fails | ||
101 | ** 4.transfer IS_SG64_ADDR w/ cpu_to_le32() | ||
102 | ** in arcmsr_build_ccb | ||
103 | ** 5. modify acb->devstate[i][j] as ARECA_RAID_GONE instead of | ||
104 | ** ARECA_RAID_GOOD in arcmsr_alloc_ccb_pool() | ||
105 | ** 6.fix arcmsr_cdb->Context as (unsigned long)arcmsr_cdb | ||
106 | ** 7.add the checking state of | ||
107 | ** (outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT) == 0 | ||
108 | ** in arcmsr_handle_hba_isr | ||
109 | ** 8.replace pci_alloc_consistent()/pci_free_consistent() with kmalloc()/kfree() in arcmsr_iop_message_xfer() | ||
110 | ** 9. fix the release of dma memory for type B in arcmsr_free_ccb_pool() | ||
111 | ** 10.fix the arcmsr_polling_hbb_ccbdone() | ||
71 | ************************************************************************** | 112 | ************************************************************************** |
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index a67e29f83ae5..57786502e3ec 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h | |||
@@ -48,7 +48,7 @@ struct class_device_attribute; | |||
48 | /*The limit of outstanding scsi command that firmware can handle*/ | 48 | /*The limit of outstanding scsi command that firmware can handle*/ |
49 | #define ARCMSR_MAX_OUTSTANDING_CMD 256 | 49 | #define ARCMSR_MAX_OUTSTANDING_CMD 256 |
50 | #define ARCMSR_MAX_FREECCB_NUM 320 | 50 | #define ARCMSR_MAX_FREECCB_NUM 320 |
51 | #define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2007/08/30" | 51 | #define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2007/12/24" |
52 | #define ARCMSR_SCSI_INITIATOR_ID 255 | 52 | #define ARCMSR_SCSI_INITIATOR_ID 255 |
53 | #define ARCMSR_MAX_XFER_SECTORS 512 | 53 | #define ARCMSR_MAX_XFER_SECTORS 512 |
54 | #define ARCMSR_MAX_XFER_SECTORS_B 4096 | 54 | #define ARCMSR_MAX_XFER_SECTORS_B 4096 |
@@ -248,6 +248,7 @@ struct FIRMWARE_INFO | |||
248 | #define ARCMSR_MESSAGE_START_BGRB 0x00060008 | 248 | #define ARCMSR_MESSAGE_START_BGRB 0x00060008 |
249 | #define ARCMSR_MESSAGE_START_DRIVER_MODE 0x000E0008 | 249 | #define ARCMSR_MESSAGE_START_DRIVER_MODE 0x000E0008 |
250 | #define ARCMSR_MESSAGE_SET_POST_WINDOW 0x000F0008 | 250 | #define ARCMSR_MESSAGE_SET_POST_WINDOW 0x000F0008 |
251 | #define ARCMSR_MESSAGE_ACTIVE_EOI_MODE 0x00100008 | ||
251 | /* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */ | 252 | /* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */ |
252 | #define ARCMSR_MESSAGE_FIRMWARE_OK 0x80000000 | 253 | #define ARCMSR_MESSAGE_FIRMWARE_OK 0x80000000 |
253 | /* ioctl transfer */ | 254 | /* ioctl transfer */ |
@@ -256,6 +257,7 @@ struct FIRMWARE_INFO | |||
256 | #define ARCMSR_DRV2IOP_DATA_READ_OK 0x00000002 | 257 | #define ARCMSR_DRV2IOP_DATA_READ_OK 0x00000002 |
257 | #define ARCMSR_DRV2IOP_CDB_POSTED 0x00000004 | 258 | #define ARCMSR_DRV2IOP_CDB_POSTED 0x00000004 |
258 | #define ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED 0x00000008 | 259 | #define ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED 0x00000008 |
260 | #define ARCMSR_DRV2IOP_END_OF_INTERRUPT 0x00000010 | ||
259 | 261 | ||
260 | /* data tunnel buffer between user space program and its firmware */ | 262 | /* data tunnel buffer between user space program and its firmware */ |
261 | /* user space data to iop 128bytes */ | 263 | /* user space data to iop 128bytes */ |
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index f4a202e8df26..4f9ff32cfed0 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c | |||
@@ -315,9 +315,6 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) | |||
315 | (0x20 - ((unsigned long)dma_coherent_handle & 0x1F)); | 315 | (0x20 - ((unsigned long)dma_coherent_handle & 0x1F)); |
316 | } | 316 | } |
317 | 317 | ||
318 | reg = (struct MessageUnit_B *)(dma_coherent + | ||
319 | ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock)); | ||
320 | |||
321 | dma_addr = dma_coherent_handle; | 318 | dma_addr = dma_coherent_handle; |
322 | ccb_tmp = (struct CommandControlBlock *)dma_coherent; | 319 | ccb_tmp = (struct CommandControlBlock *)dma_coherent; |
323 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { | 320 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { |
@@ -371,8 +368,8 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) | |||
371 | 368 | ||
372 | out: | 369 | out: |
373 | dma_free_coherent(&acb->pdev->dev, | 370 | dma_free_coherent(&acb->pdev->dev, |
374 | ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20, | 371 | (ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 + |
375 | acb->dma_coherent, acb->dma_coherent_handle); | 372 | sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle); |
376 | return -ENOMEM; | 373 | return -ENOMEM; |
377 | } | 374 | } |
378 | 375 | ||
@@ -509,6 +506,7 @@ static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) | |||
509 | & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { | 506 | & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { |
510 | writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN | 507 | writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN |
511 | , reg->iop2drv_doorbell_reg); | 508 | , reg->iop2drv_doorbell_reg); |
509 | writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg); | ||
512 | return 0x00; | 510 | return 0x00; |
513 | } | 511 | } |
514 | msleep(10); | 512 | msleep(10); |
@@ -748,6 +746,7 @@ static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, uint32_t fla | |||
748 | , ccb->startdone | 746 | , ccb->startdone |
749 | , atomic_read(&acb->ccboutstandingcount)); | 747 | , atomic_read(&acb->ccboutstandingcount)); |
750 | } | 748 | } |
749 | else | ||
751 | arcmsr_report_ccb_state(acb, ccb, flag_ccb); | 750 | arcmsr_report_ccb_state(acb, ccb, flag_ccb); |
752 | } | 751 | } |
753 | 752 | ||
@@ -886,7 +885,7 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ | |||
886 | } | 885 | } |
887 | } | 886 | } |
888 | 887 | ||
889 | static void arcmsr_build_ccb(struct AdapterControlBlock *acb, | 888 | static int arcmsr_build_ccb(struct AdapterControlBlock *acb, |
890 | struct CommandControlBlock *ccb, struct scsi_cmnd *pcmd) | 889 | struct CommandControlBlock *ccb, struct scsi_cmnd *pcmd) |
891 | { | 890 | { |
892 | struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; | 891 | struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; |
@@ -906,6 +905,8 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, | |||
906 | memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len); | 905 | memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len); |
907 | 906 | ||
908 | nseg = scsi_dma_map(pcmd); | 907 | nseg = scsi_dma_map(pcmd); |
908 | if (nseg > ARCMSR_MAX_SG_ENTRIES) | ||
909 | return FAILED; | ||
909 | BUG_ON(nseg < 0); | 910 | BUG_ON(nseg < 0); |
910 | 911 | ||
911 | if (nseg) { | 912 | if (nseg) { |
@@ -946,6 +947,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, | |||
946 | arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; | 947 | arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; |
947 | ccb->ccb_flags |= CCB_FLAG_WRITE; | 948 | ccb->ccb_flags |= CCB_FLAG_WRITE; |
948 | } | 949 | } |
950 | return SUCCESS; | ||
949 | } | 951 | } |
950 | 952 | ||
951 | static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb) | 953 | static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb) |
@@ -1036,18 +1038,22 @@ static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) | |||
1036 | switch (acb->adapter_type) { | 1038 | switch (acb->adapter_type) { |
1037 | case ACB_ADAPTER_TYPE_A: { | 1039 | case ACB_ADAPTER_TYPE_A: { |
1038 | iounmap(acb->pmuA); | 1040 | iounmap(acb->pmuA); |
1041 | dma_free_coherent(&acb->pdev->dev, | ||
1042 | ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20, | ||
1043 | acb->dma_coherent, | ||
1044 | acb->dma_coherent_handle); | ||
1039 | break; | 1045 | break; |
1040 | } | 1046 | } |
1041 | case ACB_ADAPTER_TYPE_B: { | 1047 | case ACB_ADAPTER_TYPE_B: { |
1042 | struct MessageUnit_B *reg = acb->pmuB; | 1048 | struct MessageUnit_B *reg = acb->pmuB; |
1043 | iounmap(reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL); | 1049 | iounmap(reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL); |
1044 | iounmap(reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER); | 1050 | iounmap(reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER); |
1051 | dma_free_coherent(&acb->pdev->dev, | ||
1052 | (ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 + | ||
1053 | sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle); | ||
1045 | } | 1054 | } |
1046 | } | 1055 | } |
1047 | dma_free_coherent(&acb->pdev->dev, | 1056 | |
1048 | ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20, | ||
1049 | acb->dma_coherent, | ||
1050 | acb->dma_coherent_handle); | ||
1051 | } | 1057 | } |
1052 | 1058 | ||
1053 | void arcmsr_iop_message_read(struct AdapterControlBlock *acb) | 1059 | void arcmsr_iop_message_read(struct AdapterControlBlock *acb) |
@@ -1273,7 +1279,9 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) | |||
1273 | return 1; | 1279 | return 1; |
1274 | 1280 | ||
1275 | writel(~outbound_doorbell, reg->iop2drv_doorbell_reg); | 1281 | writel(~outbound_doorbell, reg->iop2drv_doorbell_reg); |
1276 | 1282 | /*in case the last action of doorbell interrupt clearance is cached, this action can push HW to write down the clear bit*/ | |
1283 | readl(reg->iop2drv_doorbell_reg); | ||
1284 | writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg); | ||
1277 | if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { | 1285 | if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { |
1278 | arcmsr_iop2drv_data_wrote_handle(acb); | 1286 | arcmsr_iop2drv_data_wrote_handle(acb); |
1279 | } | 1287 | } |
@@ -1380,12 +1388,13 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ | |||
1380 | 1388 | ||
1381 | case ARCMSR_MESSAGE_READ_RQBUFFER: { | 1389 | case ARCMSR_MESSAGE_READ_RQBUFFER: { |
1382 | unsigned long *ver_addr; | 1390 | unsigned long *ver_addr; |
1383 | dma_addr_t buf_handle; | ||
1384 | uint8_t *pQbuffer, *ptmpQbuffer; | 1391 | uint8_t *pQbuffer, *ptmpQbuffer; |
1385 | int32_t allxfer_len = 0; | 1392 | int32_t allxfer_len = 0; |
1393 | void *tmp; | ||
1386 | 1394 | ||
1387 | ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); | 1395 | tmp = kmalloc(1032, GFP_KERNEL|GFP_DMA); |
1388 | if (!ver_addr) { | 1396 | ver_addr = (unsigned long *)tmp; |
1397 | if (!tmp) { | ||
1389 | retvalue = ARCMSR_MESSAGE_FAIL; | 1398 | retvalue = ARCMSR_MESSAGE_FAIL; |
1390 | goto message_out; | 1399 | goto message_out; |
1391 | } | 1400 | } |
@@ -1421,18 +1430,19 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ | |||
1421 | memcpy(pcmdmessagefld->messagedatabuffer, (uint8_t *)ver_addr, allxfer_len); | 1430 | memcpy(pcmdmessagefld->messagedatabuffer, (uint8_t *)ver_addr, allxfer_len); |
1422 | pcmdmessagefld->cmdmessage.Length = allxfer_len; | 1431 | pcmdmessagefld->cmdmessage.Length = allxfer_len; |
1423 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; | 1432 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; |
1424 | pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); | 1433 | kfree(tmp); |
1425 | } | 1434 | } |
1426 | break; | 1435 | break; |
1427 | 1436 | ||
1428 | case ARCMSR_MESSAGE_WRITE_WQBUFFER: { | 1437 | case ARCMSR_MESSAGE_WRITE_WQBUFFER: { |
1429 | unsigned long *ver_addr; | 1438 | unsigned long *ver_addr; |
1430 | dma_addr_t buf_handle; | ||
1431 | int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; | 1439 | int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; |
1432 | uint8_t *pQbuffer, *ptmpuserbuffer; | 1440 | uint8_t *pQbuffer, *ptmpuserbuffer; |
1441 | void *tmp; | ||
1433 | 1442 | ||
1434 | ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); | 1443 | tmp = kmalloc(1032, GFP_KERNEL|GFP_DMA); |
1435 | if (!ver_addr) { | 1444 | ver_addr = (unsigned long *)tmp; |
1445 | if (!tmp) { | ||
1436 | retvalue = ARCMSR_MESSAGE_FAIL; | 1446 | retvalue = ARCMSR_MESSAGE_FAIL; |
1437 | goto message_out; | 1447 | goto message_out; |
1438 | } | 1448 | } |
@@ -1482,7 +1492,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ | |||
1482 | retvalue = ARCMSR_MESSAGE_FAIL; | 1492 | retvalue = ARCMSR_MESSAGE_FAIL; |
1483 | } | 1493 | } |
1484 | } | 1494 | } |
1485 | pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); | 1495 | kfree(tmp); |
1486 | } | 1496 | } |
1487 | break; | 1497 | break; |
1488 | 1498 | ||
@@ -1682,8 +1692,11 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, | |||
1682 | ccb = arcmsr_get_freeccb(acb); | 1692 | ccb = arcmsr_get_freeccb(acb); |
1683 | if (!ccb) | 1693 | if (!ccb) |
1684 | return SCSI_MLQUEUE_HOST_BUSY; | 1694 | return SCSI_MLQUEUE_HOST_BUSY; |
1685 | 1695 | if ( arcmsr_build_ccb( acb, ccb, cmd ) == FAILED ) { | |
1686 | arcmsr_build_ccb(acb, ccb, cmd); | 1696 | cmd->result = (DID_ERROR << 16) | (RESERVATION_CONFLICT << 1); |
1697 | cmd->scsi_done(cmd); | ||
1698 | return 0; | ||
1699 | } | ||
1687 | arcmsr_post_ccb(acb, ccb); | 1700 | arcmsr_post_ccb(acb, ccb); |
1688 | return 0; | 1701 | return 0; |
1689 | } | 1702 | } |
@@ -1844,7 +1857,7 @@ static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, | |||
1844 | } | 1857 | } |
1845 | } | 1858 | } |
1846 | 1859 | ||
1847 | static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \ | 1860 | static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, |
1848 | struct CommandControlBlock *poll_ccb) | 1861 | struct CommandControlBlock *poll_ccb) |
1849 | { | 1862 | { |
1850 | struct MessageUnit_B *reg = acb->pmuB; | 1863 | struct MessageUnit_B *reg = acb->pmuB; |
@@ -1878,7 +1891,7 @@ static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \ | |||
1878 | (acb->vir2phy_offset + (flag_ccb << 5));/*frame must be 32 bytes aligned*/ | 1891 | (acb->vir2phy_offset + (flag_ccb << 5));/*frame must be 32 bytes aligned*/ |
1879 | poll_ccb_done = (ccb == poll_ccb) ? 1:0; | 1892 | poll_ccb_done = (ccb == poll_ccb) ? 1:0; |
1880 | if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { | 1893 | if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { |
1881 | if (ccb->startdone == ARCMSR_CCB_ABORTED) { | 1894 | if ((ccb->startdone == ARCMSR_CCB_ABORTED) || (ccb == poll_ccb)) { |
1882 | printk(KERN_NOTICE "arcmsr%d: \ | 1895 | printk(KERN_NOTICE "arcmsr%d: \ |
1883 | scsi id = %d lun = %d ccb = '0x%p' poll command abort successfully \n" | 1896 | scsi id = %d lun = %d ccb = '0x%p' poll command abort successfully \n" |
1884 | ,acb->host->host_no | 1897 | ,acb->host->host_no |
@@ -1901,7 +1914,7 @@ static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \ | |||
1901 | } /*drain reply FIFO*/ | 1914 | } /*drain reply FIFO*/ |
1902 | } | 1915 | } |
1903 | 1916 | ||
1904 | static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, \ | 1917 | static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, |
1905 | struct CommandControlBlock *poll_ccb) | 1918 | struct CommandControlBlock *poll_ccb) |
1906 | { | 1919 | { |
1907 | switch (acb->adapter_type) { | 1920 | switch (acb->adapter_type) { |
@@ -2026,6 +2039,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) | |||
2026 | do { | 2039 | do { |
2027 | firmware_state = readl(reg->iop2drv_doorbell_reg); | 2040 | firmware_state = readl(reg->iop2drv_doorbell_reg); |
2028 | } while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0); | 2041 | } while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0); |
2042 | writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg); | ||
2029 | } | 2043 | } |
2030 | break; | 2044 | break; |
2031 | } | 2045 | } |
@@ -2090,19 +2104,39 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb) | |||
2090 | } | 2104 | } |
2091 | } | 2105 | } |
2092 | 2106 | ||
2107 | static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) | ||
2108 | { | ||
2109 | switch (acb->adapter_type) { | ||
2110 | case ACB_ADAPTER_TYPE_A: | ||
2111 | return; | ||
2112 | case ACB_ADAPTER_TYPE_B: | ||
2113 | { | ||
2114 | struct MessageUnit_B *reg = acb->pmuB; | ||
2115 | writel(ARCMSR_MESSAGE_ACTIVE_EOI_MODE, reg->drv2iop_doorbell_reg); | ||
2116 | if(arcmsr_hbb_wait_msgint_ready(acb)) { | ||
2117 | printk(KERN_NOTICE "ARCMSR IOP enables EOI_MODE TIMEOUT"); | ||
2118 | return; | ||
2119 | } | ||
2120 | } | ||
2121 | break; | ||
2122 | } | ||
2123 | return; | ||
2124 | } | ||
2125 | |||
2093 | static void arcmsr_iop_init(struct AdapterControlBlock *acb) | 2126 | static void arcmsr_iop_init(struct AdapterControlBlock *acb) |
2094 | { | 2127 | { |
2095 | uint32_t intmask_org; | 2128 | uint32_t intmask_org; |
2096 | 2129 | ||
2097 | arcmsr_wait_firmware_ready(acb); | ||
2098 | arcmsr_iop_confirm(acb); | ||
2099 | /* disable all outbound interrupt */ | 2130 | /* disable all outbound interrupt */ |
2100 | intmask_org = arcmsr_disable_outbound_ints(acb); | 2131 | intmask_org = arcmsr_disable_outbound_ints(acb); |
2132 | arcmsr_wait_firmware_ready(acb); | ||
2133 | arcmsr_iop_confirm(acb); | ||
2101 | arcmsr_get_firmware_spec(acb); | 2134 | arcmsr_get_firmware_spec(acb); |
2102 | /*start background rebuild*/ | 2135 | /*start background rebuild*/ |
2103 | arcmsr_start_adapter_bgrb(acb); | 2136 | arcmsr_start_adapter_bgrb(acb); |
2104 | /* empty doorbell Qbuffer if door bell ringed */ | 2137 | /* empty doorbell Qbuffer if door bell ringed */ |
2105 | arcmsr_clear_doorbell_queue_buffer(acb); | 2138 | arcmsr_clear_doorbell_queue_buffer(acb); |
2139 | arcmsr_enable_eoi_mode(acb); | ||
2106 | /* enable outbound Post Queue,outbound doorbell Interrupt */ | 2140 | /* enable outbound Post Queue,outbound doorbell Interrupt */ |
2107 | arcmsr_enable_outbound_ints(acb, intmask_org); | 2141 | arcmsr_enable_outbound_ints(acb, intmask_org); |
2108 | acb->acb_flags |= ACB_F_IOP_INITED; | 2142 | acb->acb_flags |= ACB_F_IOP_INITED; |
@@ -2275,6 +2309,7 @@ static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev) | |||
2275 | arcmsr_start_adapter_bgrb(acb); | 2309 | arcmsr_start_adapter_bgrb(acb); |
2276 | /* empty doorbell Qbuffer if door bell ringed */ | 2310 | /* empty doorbell Qbuffer if door bell ringed */ |
2277 | arcmsr_clear_doorbell_queue_buffer(acb); | 2311 | arcmsr_clear_doorbell_queue_buffer(acb); |
2312 | arcmsr_enable_eoi_mode(acb); | ||
2278 | /* enable outbound Post Queue,outbound doorbell Interrupt */ | 2313 | /* enable outbound Post Queue,outbound doorbell Interrupt */ |
2279 | arcmsr_enable_outbound_ints(acb, intmask_org); | 2314 | arcmsr_enable_outbound_ints(acb, intmask_org); |
2280 | acb->acb_flags |= ACB_F_IOP_INITED; | 2315 | acb->acb_flags |= ACB_F_IOP_INITED; |