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

authored by Nick Cheng and committed by James Bottomley 76d78300 63adcc58

+105 -27
+41
Documentation/scsi/ChangeLog.arcmsr
··· 68 68 ** 2. modify the arcmsr_pci_slot_reset function 69 69 ** 3. modify the arcmsr_pci_ers_disconnect_forepart function 70 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 **************************************************************************
+3 -1
drivers/scsi/arcmsr/arcmsr.h
··· 48 48 /*The limit of outstanding scsi command that firmware can handle*/ 49 49 #define ARCMSR_MAX_OUTSTANDING_CMD 256 50 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 52 #define ARCMSR_SCSI_INITIATOR_ID 255 53 53 #define ARCMSR_MAX_XFER_SECTORS 512 54 54 #define ARCMSR_MAX_XFER_SECTORS_B 4096 ··· 248 248 #define ARCMSR_MESSAGE_START_BGRB 0x00060008 249 249 #define ARCMSR_MESSAGE_START_DRIVER_MODE 0x000E0008 250 250 #define ARCMSR_MESSAGE_SET_POST_WINDOW 0x000F0008 251 + #define ARCMSR_MESSAGE_ACTIVE_EOI_MODE 0x00100008 251 252 /* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */ 252 253 #define ARCMSR_MESSAGE_FIRMWARE_OK 0x80000000 253 254 /* ioctl transfer */ ··· 257 256 #define ARCMSR_DRV2IOP_DATA_READ_OK 0x00000002 258 257 #define ARCMSR_DRV2IOP_CDB_POSTED 0x00000004 259 258 #define ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED 0x00000008 259 + #define ARCMSR_DRV2IOP_END_OF_INTERRUPT 0x00000010 260 260 261 261 /* data tunnel buffer between user space program and its firmware */ 262 262 /* user space data to iop 128bytes */
+61 -26
drivers/scsi/arcmsr/arcmsr_hba.c
··· 315 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 318 dma_addr = dma_coherent_handle; 322 319 ccb_tmp = (struct CommandControlBlock *)dma_coherent; 323 320 for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { ··· 368 371 369 372 out: 370 373 dma_free_coherent(&acb->pdev->dev, 371 - ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20, 372 - acb->dma_coherent, acb->dma_coherent_handle); 374 + (ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 + 375 + sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle); 373 376 return -ENOMEM; 374 377 } 375 378 ··· 506 509 & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 507 510 writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN 508 511 , reg->iop2drv_doorbell_reg); 512 + writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg); 509 513 return 0x00; 510 514 } 511 515 msleep(10); ··· 746 748 , ccb->startdone 747 749 , atomic_read(&acb->ccboutstandingcount)); 748 750 } 751 + else 749 752 arcmsr_report_ccb_state(acb, ccb, flag_ccb); 750 753 } 751 754 ··· 885 886 } 886 887 } 887 888 888 - static void arcmsr_build_ccb(struct AdapterControlBlock *acb, 889 + static int arcmsr_build_ccb(struct AdapterControlBlock *acb, 889 890 struct CommandControlBlock *ccb, struct scsi_cmnd *pcmd) 890 891 { 891 892 struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; ··· 905 906 memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len); 906 907 907 908 nseg = scsi_dma_map(pcmd); 909 + if (nseg > ARCMSR_MAX_SG_ENTRIES) 910 + return FAILED; 908 911 BUG_ON(nseg < 0); 909 912 910 913 if (nseg) { ··· 947 946 arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; 948 947 ccb->ccb_flags |= CCB_FLAG_WRITE; 949 948 } 949 + return SUCCESS; 950 950 } 951 951 952 952 static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb) ··· 1038 1036 switch (acb->adapter_type) { 1039 1037 case ACB_ADAPTER_TYPE_A: { 1040 1038 iounmap(acb->pmuA); 1039 + dma_free_coherent(&acb->pdev->dev, 1040 + ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20, 1041 + acb->dma_coherent, 1042 + acb->dma_coherent_handle); 1041 1043 break; 1042 1044 } 1043 1045 case ACB_ADAPTER_TYPE_B: { 1044 1046 struct MessageUnit_B *reg = acb->pmuB; 1045 1047 iounmap(reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL); 1046 1048 iounmap(reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER); 1049 + dma_free_coherent(&acb->pdev->dev, 1050 + (ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 + 1051 + sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle); 1047 1052 } 1048 1053 } 1049 - dma_free_coherent(&acb->pdev->dev, 1050 - ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20, 1051 - acb->dma_coherent, 1052 - acb->dma_coherent_handle); 1054 + 1053 1055 } 1054 1056 1055 1057 void arcmsr_iop_message_read(struct AdapterControlBlock *acb) ··· 1279 1273 return 1; 1280 1274 1281 1275 writel(~outbound_doorbell, reg->iop2drv_doorbell_reg); 1282 - 1276 + /*in case the last action of doorbell interrupt clearance is cached, this action can push HW to write down the clear bit*/ 1277 + readl(reg->iop2drv_doorbell_reg); 1278 + writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg); 1283 1279 if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { 1284 1280 arcmsr_iop2drv_data_wrote_handle(acb); 1285 1281 } ··· 1388 1380 1389 1381 case ARCMSR_MESSAGE_READ_RQBUFFER: { 1390 1382 unsigned long *ver_addr; 1391 - dma_addr_t buf_handle; 1392 1383 uint8_t *pQbuffer, *ptmpQbuffer; 1393 1384 int32_t allxfer_len = 0; 1385 + void *tmp; 1394 1386 1395 - ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); 1396 - if (!ver_addr) { 1387 + tmp = kmalloc(1032, GFP_KERNEL|GFP_DMA); 1388 + ver_addr = (unsigned long *)tmp; 1389 + if (!tmp) { 1397 1390 retvalue = ARCMSR_MESSAGE_FAIL; 1398 1391 goto message_out; 1399 1392 } ··· 1430 1421 memcpy(pcmdmessagefld->messagedatabuffer, (uint8_t *)ver_addr, allxfer_len); 1431 1422 pcmdmessagefld->cmdmessage.Length = allxfer_len; 1432 1423 pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 1433 - pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); 1424 + kfree(tmp); 1434 1425 } 1435 1426 break; 1436 1427 1437 1428 case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 1438 1429 unsigned long *ver_addr; 1439 - dma_addr_t buf_handle; 1440 1430 int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 1441 1431 uint8_t *pQbuffer, *ptmpuserbuffer; 1432 + void *tmp; 1442 1433 1443 - ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); 1444 - if (!ver_addr) { 1434 + tmp = kmalloc(1032, GFP_KERNEL|GFP_DMA); 1435 + ver_addr = (unsigned long *)tmp; 1436 + if (!tmp) { 1445 1437 retvalue = ARCMSR_MESSAGE_FAIL; 1446 1438 goto message_out; 1447 1439 } ··· 1492 1482 retvalue = ARCMSR_MESSAGE_FAIL; 1493 1483 } 1494 1484 } 1495 - pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); 1485 + kfree(tmp); 1496 1486 } 1497 1487 break; 1498 1488 ··· 1692 1682 ccb = arcmsr_get_freeccb(acb); 1693 1683 if (!ccb) 1694 1684 return SCSI_MLQUEUE_HOST_BUSY; 1695 - 1696 - arcmsr_build_ccb(acb, ccb, cmd); 1685 + if ( arcmsr_build_ccb( acb, ccb, cmd ) == FAILED ) { 1686 + cmd->result = (DID_ERROR << 16) | (RESERVATION_CONFLICT << 1); 1687 + cmd->scsi_done(cmd); 1688 + return 0; 1689 + } 1697 1690 arcmsr_post_ccb(acb, ccb); 1698 1691 return 0; 1699 1692 } ··· 1857 1844 } 1858 1845 } 1859 1846 1860 - static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \ 1847 + static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, 1861 1848 struct CommandControlBlock *poll_ccb) 1862 1849 { 1863 1850 struct MessageUnit_B *reg = acb->pmuB; ··· 1891 1878 (acb->vir2phy_offset + (flag_ccb << 5));/*frame must be 32 bytes aligned*/ 1892 1879 poll_ccb_done = (ccb == poll_ccb) ? 1:0; 1893 1880 if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { 1894 - if (ccb->startdone == ARCMSR_CCB_ABORTED) { 1881 + if ((ccb->startdone == ARCMSR_CCB_ABORTED) || (ccb == poll_ccb)) { 1895 1882 printk(KERN_NOTICE "arcmsr%d: \ 1896 1883 scsi id = %d lun = %d ccb = '0x%p' poll command abort successfully \n" 1897 1884 ,acb->host->host_no ··· 1914 1901 } /*drain reply FIFO*/ 1915 1902 } 1916 1903 1917 - static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, \ 1904 + static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, 1918 1905 struct CommandControlBlock *poll_ccb) 1919 1906 { 1920 1907 switch (acb->adapter_type) { ··· 2039 2026 do { 2040 2027 firmware_state = readl(reg->iop2drv_doorbell_reg); 2041 2028 } while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0); 2029 + writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg); 2042 2030 } 2043 2031 break; 2044 2032 } ··· 2104 2090 } 2105 2091 } 2106 2092 2093 + static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) 2094 + { 2095 + switch (acb->adapter_type) { 2096 + case ACB_ADAPTER_TYPE_A: 2097 + return; 2098 + case ACB_ADAPTER_TYPE_B: 2099 + { 2100 + struct MessageUnit_B *reg = acb->pmuB; 2101 + writel(ARCMSR_MESSAGE_ACTIVE_EOI_MODE, reg->drv2iop_doorbell_reg); 2102 + if(arcmsr_hbb_wait_msgint_ready(acb)) { 2103 + printk(KERN_NOTICE "ARCMSR IOP enables EOI_MODE TIMEOUT"); 2104 + return; 2105 + } 2106 + } 2107 + break; 2108 + } 2109 + return; 2110 + } 2111 + 2107 2112 static void arcmsr_iop_init(struct AdapterControlBlock *acb) 2108 2113 { 2109 2114 uint32_t intmask_org; 2110 2115 2111 - arcmsr_wait_firmware_ready(acb); 2112 - arcmsr_iop_confirm(acb); 2113 2116 /* disable all outbound interrupt */ 2114 2117 intmask_org = arcmsr_disable_outbound_ints(acb); 2118 + arcmsr_wait_firmware_ready(acb); 2119 + arcmsr_iop_confirm(acb); 2115 2120 arcmsr_get_firmware_spec(acb); 2116 2121 /*start background rebuild*/ 2117 2122 arcmsr_start_adapter_bgrb(acb); 2118 2123 /* empty doorbell Qbuffer if door bell ringed */ 2119 2124 arcmsr_clear_doorbell_queue_buffer(acb); 2125 + arcmsr_enable_eoi_mode(acb); 2120 2126 /* enable outbound Post Queue,outbound doorbell Interrupt */ 2121 2127 arcmsr_enable_outbound_ints(acb, intmask_org); 2122 2128 acb->acb_flags |= ACB_F_IOP_INITED; ··· 2309 2275 arcmsr_start_adapter_bgrb(acb); 2310 2276 /* empty doorbell Qbuffer if door bell ringed */ 2311 2277 arcmsr_clear_doorbell_queue_buffer(acb); 2278 + arcmsr_enable_eoi_mode(acb); 2312 2279 /* enable outbound Post Queue,outbound doorbell Interrupt */ 2313 2280 arcmsr_enable_outbound_ints(acb, intmask_org); 2314 2281 acb->acb_flags |= ACB_F_IOP_INITED;