diff options
Diffstat (limited to 'drivers/scsi/arcmsr/arcmsr_hba.c')
-rw-r--r-- | drivers/scsi/arcmsr/arcmsr_hba.c | 559 |
1 files changed, 454 insertions, 105 deletions
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 8b46158cc045..0ddfc21e9f7d 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <linux/dma-mapping.h> | 57 | #include <linux/dma-mapping.h> |
58 | #include <linux/timer.h> | 58 | #include <linux/timer.h> |
59 | #include <linux/pci.h> | 59 | #include <linux/pci.h> |
60 | #include <linux/aer.h> | ||
60 | #include <asm/dma.h> | 61 | #include <asm/dma.h> |
61 | #include <asm/io.h> | 62 | #include <asm/io.h> |
62 | #include <asm/system.h> | 63 | #include <asm/system.h> |
@@ -71,7 +72,7 @@ | |||
71 | #include "arcmsr.h" | 72 | #include "arcmsr.h" |
72 | 73 | ||
73 | MODULE_AUTHOR("Erich Chen <erich@areca.com.tw>"); | 74 | MODULE_AUTHOR("Erich Chen <erich@areca.com.tw>"); |
74 | MODULE_DESCRIPTION("ARECA (ARC11xx/12xx) SATA RAID HOST Adapter"); | 75 | MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID HOST Adapter"); |
75 | MODULE_LICENSE("Dual BSD/GPL"); | 76 | MODULE_LICENSE("Dual BSD/GPL"); |
76 | MODULE_VERSION(ARCMSR_DRIVER_VERSION); | 77 | MODULE_VERSION(ARCMSR_DRIVER_VERSION); |
77 | 78 | ||
@@ -93,7 +94,9 @@ static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); | |||
93 | static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb); | 94 | static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb); |
94 | static const char *arcmsr_info(struct Scsi_Host *); | 95 | static const char *arcmsr_info(struct Scsi_Host *); |
95 | static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); | 96 | static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); |
96 | 97 | static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, | |
98 | pci_channel_state_t state); | ||
99 | static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev); | ||
97 | static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth) | 100 | static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth) |
98 | { | 101 | { |
99 | if (queue_depth > ARCMSR_MAX_CMD_PERLUN) | 102 | if (queue_depth > ARCMSR_MAX_CMD_PERLUN) |
@@ -104,7 +107,8 @@ static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_de | |||
104 | 107 | ||
105 | static struct scsi_host_template arcmsr_scsi_host_template = { | 108 | static struct scsi_host_template arcmsr_scsi_host_template = { |
106 | .module = THIS_MODULE, | 109 | .module = THIS_MODULE, |
107 | .name = "ARCMSR ARECA SATA RAID HOST Adapter" ARCMSR_DRIVER_VERSION, | 110 | .name = "ARCMSR ARECA SATA/SAS RAID HOST Adapter" |
111 | ARCMSR_DRIVER_VERSION, | ||
108 | .info = arcmsr_info, | 112 | .info = arcmsr_info, |
109 | .queuecommand = arcmsr_queue_command, | 113 | .queuecommand = arcmsr_queue_command, |
110 | .eh_abort_handler = arcmsr_abort, | 114 | .eh_abort_handler = arcmsr_abort, |
@@ -119,6 +123,10 @@ static struct scsi_host_template arcmsr_scsi_host_template = { | |||
119 | .use_clustering = ENABLE_CLUSTERING, | 123 | .use_clustering = ENABLE_CLUSTERING, |
120 | .shost_attrs = arcmsr_host_attrs, | 124 | .shost_attrs = arcmsr_host_attrs, |
121 | }; | 125 | }; |
126 | static struct pci_error_handlers arcmsr_pci_error_handlers = { | ||
127 | .error_detected = arcmsr_pci_error_detected, | ||
128 | .slot_reset = arcmsr_pci_slot_reset, | ||
129 | }; | ||
122 | 130 | ||
123 | static struct pci_device_id arcmsr_device_id_table[] = { | 131 | static struct pci_device_id arcmsr_device_id_table[] = { |
124 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)}, | 132 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)}, |
@@ -144,7 +152,8 @@ static struct pci_driver arcmsr_pci_driver = { | |||
144 | .id_table = arcmsr_device_id_table, | 152 | .id_table = arcmsr_device_id_table, |
145 | .probe = arcmsr_probe, | 153 | .probe = arcmsr_probe, |
146 | .remove = arcmsr_remove, | 154 | .remove = arcmsr_remove, |
147 | .shutdown = arcmsr_shutdown | 155 | .shutdown = arcmsr_shutdown, |
156 | .err_handler = &arcmsr_pci_error_handlers, | ||
148 | }; | 157 | }; |
149 | 158 | ||
150 | static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id) | 159 | static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id) |
@@ -328,6 +337,8 @@ static int arcmsr_probe(struct pci_dev *pdev, | |||
328 | 337 | ||
329 | arcmsr_iop_init(acb); | 338 | arcmsr_iop_init(acb); |
330 | pci_set_drvdata(pdev, host); | 339 | pci_set_drvdata(pdev, host); |
340 | if (strncmp(acb->firm_version, "V1.42", 5) >= 0) | ||
341 | host->max_sectors= ARCMSR_MAX_XFER_SECTORS_B; | ||
331 | 342 | ||
332 | error = scsi_add_host(host, &pdev->dev); | 343 | error = scsi_add_host(host, &pdev->dev); |
333 | if (error) | 344 | if (error) |
@@ -338,6 +349,7 @@ static int arcmsr_probe(struct pci_dev *pdev, | |||
338 | goto out_free_sysfs; | 349 | goto out_free_sysfs; |
339 | 350 | ||
340 | scsi_scan_host(host); | 351 | scsi_scan_host(host); |
352 | pci_enable_pcie_error_reporting(pdev); | ||
341 | return 0; | 353 | return 0; |
342 | out_free_sysfs: | 354 | out_free_sysfs: |
343 | out_free_irq: | 355 | out_free_irq: |
@@ -369,19 +381,9 @@ static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) | |||
369 | 381 | ||
370 | static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) | 382 | static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) |
371 | { | 383 | { |
372 | struct AdapterControlBlock *acb = ccb->acb; | ||
373 | struct scsi_cmnd *pcmd = ccb->pcmd; | 384 | struct scsi_cmnd *pcmd = ccb->pcmd; |
374 | 385 | ||
375 | if (pcmd->use_sg != 0) { | 386 | scsi_dma_unmap(pcmd); |
376 | struct scatterlist *sl; | ||
377 | |||
378 | sl = (struct scatterlist *)pcmd->request_buffer; | ||
379 | pci_unmap_sg(acb->pdev, sl, pcmd->use_sg, pcmd->sc_data_direction); | ||
380 | } | ||
381 | else if (pcmd->request_bufflen != 0) | ||
382 | pci_unmap_single(acb->pdev, | ||
383 | pcmd->SCp.dma_handle, | ||
384 | pcmd->request_bufflen, pcmd->sc_data_direction); | ||
385 | } | 387 | } |
386 | 388 | ||
387 | static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag) | 389 | static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag) |
@@ -498,7 +500,7 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, | |||
498 | 500 | ||
499 | static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) | 501 | static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) |
500 | { | 502 | { |
501 | struct MessageUnit __iomem *reg=acb->pmu; | 503 | struct MessageUnit __iomem *reg = acb->pmu; |
502 | 504 | ||
503 | writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); | 505 | writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); |
504 | if (arcmsr_wait_msgint_ready(acb)) | 506 | if (arcmsr_wait_msgint_ready(acb)) |
@@ -551,6 +553,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, | |||
551 | int8_t *psge = (int8_t *)&arcmsr_cdb->u; | 553 | int8_t *psge = (int8_t *)&arcmsr_cdb->u; |
552 | uint32_t address_lo, address_hi; | 554 | uint32_t address_lo, address_hi; |
553 | int arccdbsize = 0x30; | 555 | int arccdbsize = 0x30; |
556 | int nseg; | ||
554 | 557 | ||
555 | ccb->pcmd = pcmd; | 558 | ccb->pcmd = pcmd; |
556 | memset(arcmsr_cdb, 0, sizeof (struct ARCMSR_CDB)); | 559 | memset(arcmsr_cdb, 0, sizeof (struct ARCMSR_CDB)); |
@@ -561,20 +564,20 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, | |||
561 | arcmsr_cdb->CdbLength = (uint8_t)pcmd->cmd_len; | 564 | arcmsr_cdb->CdbLength = (uint8_t)pcmd->cmd_len; |
562 | arcmsr_cdb->Context = (unsigned long)arcmsr_cdb; | 565 | arcmsr_cdb->Context = (unsigned long)arcmsr_cdb; |
563 | memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len); | 566 | memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len); |
564 | if (pcmd->use_sg) { | 567 | |
565 | int length, sgcount, i, cdb_sgcount = 0; | 568 | nseg = scsi_dma_map(pcmd); |
566 | struct scatterlist *sl; | 569 | BUG_ON(nseg < 0); |
567 | 570 | ||
568 | /* Get Scatter Gather List from scsiport. */ | 571 | if (nseg) { |
569 | sl = (struct scatterlist *) pcmd->request_buffer; | 572 | int length, i, cdb_sgcount = 0; |
570 | sgcount = pci_map_sg(acb->pdev, sl, pcmd->use_sg, | 573 | struct scatterlist *sg; |
571 | pcmd->sc_data_direction); | 574 | |
572 | /* map stor port SG list to our iop SG List. */ | 575 | /* map stor port SG list to our iop SG List. */ |
573 | for (i = 0; i < sgcount; i++) { | 576 | scsi_for_each_sg(pcmd, sg, nseg, i) { |
574 | /* Get the physical address of the current data pointer */ | 577 | /* Get the physical address of the current data pointer */ |
575 | length = cpu_to_le32(sg_dma_len(sl)); | 578 | length = cpu_to_le32(sg_dma_len(sg)); |
576 | address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sl))); | 579 | address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sg))); |
577 | address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sl))); | 580 | address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sg))); |
578 | if (address_hi == 0) { | 581 | if (address_hi == 0) { |
579 | struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; | 582 | struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; |
580 | 583 | ||
@@ -591,32 +594,12 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, | |||
591 | psge += sizeof (struct SG64ENTRY); | 594 | psge += sizeof (struct SG64ENTRY); |
592 | arccdbsize += sizeof (struct SG64ENTRY); | 595 | arccdbsize += sizeof (struct SG64ENTRY); |
593 | } | 596 | } |
594 | sl++; | ||
595 | cdb_sgcount++; | 597 | cdb_sgcount++; |
596 | } | 598 | } |
597 | arcmsr_cdb->sgcount = (uint8_t)cdb_sgcount; | 599 | arcmsr_cdb->sgcount = (uint8_t)cdb_sgcount; |
598 | arcmsr_cdb->DataLength = pcmd->request_bufflen; | 600 | arcmsr_cdb->DataLength = scsi_bufflen(pcmd); |
599 | if ( arccdbsize > 256) | 601 | if ( arccdbsize > 256) |
600 | arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; | 602 | arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; |
601 | } else if (pcmd->request_bufflen) { | ||
602 | dma_addr_t dma_addr; | ||
603 | dma_addr = pci_map_single(acb->pdev, pcmd->request_buffer, | ||
604 | pcmd->request_bufflen, pcmd->sc_data_direction); | ||
605 | pcmd->SCp.dma_handle = dma_addr; | ||
606 | address_lo = cpu_to_le32(dma_addr_lo32(dma_addr)); | ||
607 | address_hi = cpu_to_le32(dma_addr_hi32(dma_addr)); | ||
608 | if (address_hi == 0) { | ||
609 | struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; | ||
610 | pdma_sg->address = address_lo; | ||
611 | pdma_sg->length = pcmd->request_bufflen; | ||
612 | } else { | ||
613 | struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; | ||
614 | pdma_sg->addresshigh = address_hi; | ||
615 | pdma_sg->address = address_lo; | ||
616 | pdma_sg->length = pcmd->request_bufflen|IS_SG64_ADDR; | ||
617 | } | ||
618 | arcmsr_cdb->sgcount = 1; | ||
619 | arcmsr_cdb->DataLength = pcmd->request_bufflen; | ||
620 | } | 603 | } |
621 | if (pcmd->sc_data_direction == DMA_TO_DEVICE ) { | 604 | if (pcmd->sc_data_direction == DMA_TO_DEVICE ) { |
622 | arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; | 605 | arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; |
@@ -747,7 +730,7 @@ static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) | |||
747 | int id, lun; | 730 | int id, lun; |
748 | /* | 731 | /* |
749 | **************************************************************** | 732 | **************************************************************** |
750 | ** areca cdb command done | 733 | ** areca cdb command done |
751 | **************************************************************** | 734 | **************************************************************** |
752 | */ | 735 | */ |
753 | while (1) { | 736 | while (1) { |
@@ -758,20 +741,20 @@ static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) | |||
758 | (flag_ccb << 5)); | 741 | (flag_ccb << 5)); |
759 | if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { | 742 | if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { |
760 | if (ccb->startdone == ARCMSR_CCB_ABORTED) { | 743 | if (ccb->startdone == ARCMSR_CCB_ABORTED) { |
761 | struct scsi_cmnd *abortcmd=ccb->pcmd; | 744 | struct scsi_cmnd *abortcmd = ccb->pcmd; |
762 | if (abortcmd) { | 745 | if (abortcmd) { |
763 | abortcmd->result |= DID_ABORT >> 16; | 746 | abortcmd->result |= DID_ABORT >> 16; |
764 | arcmsr_ccb_complete(ccb, 1); | 747 | arcmsr_ccb_complete(ccb, 1); |
765 | printk(KERN_NOTICE | 748 | printk(KERN_NOTICE |
766 | "arcmsr%d: ccb='0x%p' isr got aborted command \n" | 749 | "arcmsr%d: ccb ='0x%p' isr got aborted command \n" |
767 | , acb->host->host_no, ccb); | 750 | , acb->host->host_no, ccb); |
768 | } | 751 | } |
769 | continue; | 752 | continue; |
770 | } | 753 | } |
771 | printk(KERN_NOTICE | 754 | printk(KERN_NOTICE |
772 | "arcmsr%d: isr get an illegal ccb command done acb='0x%p'" | 755 | "arcmsr%d: isr get an illegal ccb command done acb = '0x%p'" |
773 | "ccb='0x%p' ccbacb='0x%p' startdone = 0x%x" | 756 | "ccb = '0x%p' ccbacb = '0x%p' startdone = 0x%x" |
774 | " ccboutstandingcount=%d \n" | 757 | " ccboutstandingcount = %d \n" |
775 | , acb->host->host_no | 758 | , acb->host->host_no |
776 | , acb | 759 | , acb |
777 | , ccb | 760 | , ccb |
@@ -791,7 +774,7 @@ static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) | |||
791 | switch(ccb->arcmsr_cdb.DeviceStatus) { | 774 | switch(ccb->arcmsr_cdb.DeviceStatus) { |
792 | case ARCMSR_DEV_SELECT_TIMEOUT: { | 775 | case ARCMSR_DEV_SELECT_TIMEOUT: { |
793 | acb->devstate[id][lun] = ARECA_RAID_GONE; | 776 | acb->devstate[id][lun] = ARECA_RAID_GONE; |
794 | ccb->pcmd->result = DID_TIME_OUT << 16; | 777 | ccb->pcmd->result = DID_NO_CONNECT << 16; |
795 | arcmsr_ccb_complete(ccb, 1); | 778 | arcmsr_ccb_complete(ccb, 1); |
796 | } | 779 | } |
797 | break; | 780 | break; |
@@ -810,8 +793,8 @@ static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) | |||
810 | break; | 793 | break; |
811 | default: | 794 | default: |
812 | printk(KERN_NOTICE | 795 | printk(KERN_NOTICE |
813 | "arcmsr%d: scsi id=%d lun=%d" | 796 | "arcmsr%d: scsi id = %d lun = %d" |
814 | " isr get command error done," | 797 | " isr get command error done, " |
815 | "but got unknown DeviceStatus = 0x%x \n" | 798 | "but got unknown DeviceStatus = 0x%x \n" |
816 | , acb->host->host_no | 799 | , acb->host->host_no |
817 | , id | 800 | , id |
@@ -848,24 +831,21 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_ | |||
848 | struct CMD_MESSAGE_FIELD *pcmdmessagefld; | 831 | struct CMD_MESSAGE_FIELD *pcmdmessagefld; |
849 | int retvalue = 0, transfer_len = 0; | 832 | int retvalue = 0, transfer_len = 0; |
850 | char *buffer; | 833 | char *buffer; |
834 | struct scatterlist *sg; | ||
851 | uint32_t controlcode = (uint32_t ) cmd->cmnd[5] << 24 | | 835 | uint32_t controlcode = (uint32_t ) cmd->cmnd[5] << 24 | |
852 | (uint32_t ) cmd->cmnd[6] << 16 | | 836 | (uint32_t ) cmd->cmnd[6] << 16 | |
853 | (uint32_t ) cmd->cmnd[7] << 8 | | 837 | (uint32_t ) cmd->cmnd[7] << 8 | |
854 | (uint32_t ) cmd->cmnd[8]; | 838 | (uint32_t ) cmd->cmnd[8]; |
855 | /* 4 bytes: Areca io control code */ | 839 | /* 4 bytes: Areca io control code */ |
856 | if (cmd->use_sg) { | ||
857 | struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer; | ||
858 | 840 | ||
859 | buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | 841 | sg = scsi_sglist(cmd); |
860 | if (cmd->use_sg > 1) { | 842 | buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; |
861 | retvalue = ARCMSR_MESSAGE_FAIL; | 843 | if (scsi_sg_count(cmd) > 1) { |
862 | goto message_out; | 844 | retvalue = ARCMSR_MESSAGE_FAIL; |
863 | } | 845 | goto message_out; |
864 | transfer_len += sg->length; | ||
865 | } else { | ||
866 | buffer = cmd->request_buffer; | ||
867 | transfer_len = cmd->request_bufflen; | ||
868 | } | 846 | } |
847 | transfer_len += sg->length; | ||
848 | |||
869 | if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { | 849 | if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { |
870 | retvalue = ARCMSR_MESSAGE_FAIL; | 850 | retvalue = ARCMSR_MESSAGE_FAIL; |
871 | goto message_out; | 851 | goto message_out; |
@@ -1057,12 +1037,9 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_ | |||
1057 | retvalue = ARCMSR_MESSAGE_FAIL; | 1037 | retvalue = ARCMSR_MESSAGE_FAIL; |
1058 | } | 1038 | } |
1059 | message_out: | 1039 | message_out: |
1060 | if (cmd->use_sg) { | 1040 | sg = scsi_sglist(cmd); |
1061 | struct scatterlist *sg; | 1041 | kunmap_atomic(buffer - sg->offset, KM_IRQ0); |
1062 | 1042 | ||
1063 | sg = (struct scatterlist *) cmd->request_buffer; | ||
1064 | kunmap_atomic(buffer - sg->offset, KM_IRQ0); | ||
1065 | } | ||
1066 | return retvalue; | 1043 | return retvalue; |
1067 | } | 1044 | } |
1068 | 1045 | ||
@@ -1085,6 +1062,7 @@ static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, | |||
1085 | case INQUIRY: { | 1062 | case INQUIRY: { |
1086 | unsigned char inqdata[36]; | 1063 | unsigned char inqdata[36]; |
1087 | char *buffer; | 1064 | char *buffer; |
1065 | struct scatterlist *sg; | ||
1088 | 1066 | ||
1089 | if (cmd->device->lun) { | 1067 | if (cmd->device->lun) { |
1090 | cmd->result = (DID_TIME_OUT << 16); | 1068 | cmd->result = (DID_TIME_OUT << 16); |
@@ -1096,7 +1074,7 @@ static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, | |||
1096 | inqdata[1] = 0; | 1074 | inqdata[1] = 0; |
1097 | /* rem media bit & Dev Type Modifier */ | 1075 | /* rem media bit & Dev Type Modifier */ |
1098 | inqdata[2] = 0; | 1076 | inqdata[2] = 0; |
1099 | /* ISO,ECMA,& ANSI versions */ | 1077 | /* ISO, ECMA, & ANSI versions */ |
1100 | inqdata[4] = 31; | 1078 | inqdata[4] = 31; |
1101 | /* length of additional data */ | 1079 | /* length of additional data */ |
1102 | strncpy(&inqdata[8], "Areca ", 8); | 1080 | strncpy(&inqdata[8], "Areca ", 8); |
@@ -1104,21 +1082,14 @@ static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, | |||
1104 | strncpy(&inqdata[16], "RAID controller ", 16); | 1082 | strncpy(&inqdata[16], "RAID controller ", 16); |
1105 | /* Product Identification */ | 1083 | /* Product Identification */ |
1106 | strncpy(&inqdata[32], "R001", 4); /* Product Revision */ | 1084 | strncpy(&inqdata[32], "R001", 4); /* Product Revision */ |
1107 | if (cmd->use_sg) { | ||
1108 | struct scatterlist *sg; | ||
1109 | 1085 | ||
1110 | sg = (struct scatterlist *) cmd->request_buffer; | 1086 | sg = scsi_sglist(cmd); |
1111 | buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | 1087 | buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; |
1112 | } else { | 1088 | |
1113 | buffer = cmd->request_buffer; | ||
1114 | } | ||
1115 | memcpy(buffer, inqdata, sizeof(inqdata)); | 1089 | memcpy(buffer, inqdata, sizeof(inqdata)); |
1116 | if (cmd->use_sg) { | 1090 | sg = scsi_sglist(cmd); |
1117 | struct scatterlist *sg; | 1091 | kunmap_atomic(buffer - sg->offset, KM_IRQ0); |
1118 | 1092 | ||
1119 | sg = (struct scatterlist *) cmd->request_buffer; | ||
1120 | kunmap_atomic(buffer - sg->offset, KM_IRQ0); | ||
1121 | } | ||
1122 | cmd->scsi_done(cmd); | 1093 | cmd->scsi_done(cmd); |
1123 | } | 1094 | } |
1124 | break; | 1095 | break; |
@@ -1153,7 +1124,7 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, | |||
1153 | , acb->host->host_no); | 1124 | , acb->host->host_no); |
1154 | return SCSI_MLQUEUE_HOST_BUSY; | 1125 | return SCSI_MLQUEUE_HOST_BUSY; |
1155 | } | 1126 | } |
1156 | if(target == 16) { | 1127 | if (target == 16) { |
1157 | /* virtual device for iop message transfer */ | 1128 | /* virtual device for iop message transfer */ |
1158 | arcmsr_handle_virtual_command(acb, cmd); | 1129 | arcmsr_handle_virtual_command(acb, cmd); |
1159 | return 0; | 1130 | return 0; |
@@ -1166,7 +1137,7 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, | |||
1166 | printk(KERN_NOTICE | 1137 | printk(KERN_NOTICE |
1167 | "arcmsr%d: block 'read/write'" | 1138 | "arcmsr%d: block 'read/write'" |
1168 | "command with gone raid volume" | 1139 | "command with gone raid volume" |
1169 | " Cmd=%2x, TargetId=%d, Lun=%d \n" | 1140 | " Cmd = %2x, TargetId = %d, Lun = %d \n" |
1170 | , acb->host->host_no | 1141 | , acb->host->host_no |
1171 | , cmd->cmnd[0] | 1142 | , cmd->cmnd[0] |
1172 | , target, lun); | 1143 | , target, lun); |
@@ -1257,7 +1228,7 @@ static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, | |||
1257 | if ((ccb->startdone == ARCMSR_CCB_ABORTED) || | 1228 | if ((ccb->startdone == ARCMSR_CCB_ABORTED) || |
1258 | (ccb == poll_ccb)) { | 1229 | (ccb == poll_ccb)) { |
1259 | printk(KERN_NOTICE | 1230 | printk(KERN_NOTICE |
1260 | "arcmsr%d: scsi id=%d lun=%d ccb='0x%p'" | 1231 | "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'" |
1261 | " poll command abort successfully \n" | 1232 | " poll command abort successfully \n" |
1262 | , acb->host->host_no | 1233 | , acb->host->host_no |
1263 | , ccb->pcmd->device->id | 1234 | , ccb->pcmd->device->id |
@@ -1270,8 +1241,8 @@ static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, | |||
1270 | } | 1241 | } |
1271 | printk(KERN_NOTICE | 1242 | printk(KERN_NOTICE |
1272 | "arcmsr%d: polling get an illegal ccb" | 1243 | "arcmsr%d: polling get an illegal ccb" |
1273 | " command done ccb='0x%p'" | 1244 | " command done ccb ='0x%p'" |
1274 | "ccboutstandingcount=%d \n" | 1245 | "ccboutstandingcount = %d \n" |
1275 | , acb->host->host_no | 1246 | , acb->host->host_no |
1276 | , ccb | 1247 | , ccb |
1277 | , atomic_read(&acb->ccboutstandingcount)); | 1248 | , atomic_read(&acb->ccboutstandingcount)); |
@@ -1288,7 +1259,7 @@ static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, | |||
1288 | switch(ccb->arcmsr_cdb.DeviceStatus) { | 1259 | switch(ccb->arcmsr_cdb.DeviceStatus) { |
1289 | case ARCMSR_DEV_SELECT_TIMEOUT: { | 1260 | case ARCMSR_DEV_SELECT_TIMEOUT: { |
1290 | acb->devstate[id][lun] = ARECA_RAID_GONE; | 1261 | acb->devstate[id][lun] = ARECA_RAID_GONE; |
1291 | ccb->pcmd->result = DID_TIME_OUT << 16; | 1262 | ccb->pcmd->result = DID_NO_CONNECT << 16; |
1292 | arcmsr_ccb_complete(ccb, 1); | 1263 | arcmsr_ccb_complete(ccb, 1); |
1293 | } | 1264 | } |
1294 | break; | 1265 | break; |
@@ -1307,7 +1278,7 @@ static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, | |||
1307 | break; | 1278 | break; |
1308 | default: | 1279 | default: |
1309 | printk(KERN_NOTICE | 1280 | printk(KERN_NOTICE |
1310 | "arcmsr%d: scsi id=%d lun=%d" | 1281 | "arcmsr%d: scsi id = %d lun = %d" |
1311 | " polling and getting command error done" | 1282 | " polling and getting command error done" |
1312 | "but got unknown DeviceStatus = 0x%x \n" | 1283 | "but got unknown DeviceStatus = 0x%x \n" |
1313 | , acb->host->host_no | 1284 | , acb->host->host_no |
@@ -1322,6 +1293,94 @@ static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, | |||
1322 | } | 1293 | } |
1323 | } | 1294 | } |
1324 | } | 1295 | } |
1296 | static void arcmsr_done4_abort_postqueue(struct AdapterControlBlock *acb) | ||
1297 | { | ||
1298 | int i = 0, found = 0; | ||
1299 | int id, lun; | ||
1300 | uint32_t flag_ccb, outbound_intstatus; | ||
1301 | struct MessageUnit __iomem *reg = acb->pmu; | ||
1302 | struct CommandControlBlock *ccb; | ||
1303 | /*clear and abort all outbound posted Q*/ | ||
1304 | |||
1305 | while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) && | ||
1306 | (i++ < 256)){ | ||
1307 | ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + | ||
1308 | (flag_ccb << 5)); | ||
1309 | if (ccb){ | ||
1310 | if ((ccb->acb != acb)||(ccb->startdone != \ | ||
1311 | ARCMSR_CCB_START)){ | ||
1312 | printk(KERN_NOTICE "arcmsr%d: polling get \ | ||
1313 | an illegal ccb" "command done ccb = '0x%p'""ccboutstandingcount = %d \n", | ||
1314 | acb->host->host_no, ccb, | ||
1315 | atomic_read(&acb->ccboutstandingcount)); | ||
1316 | continue; | ||
1317 | } | ||
1318 | |||
1319 | id = ccb->pcmd->device->id; | ||
1320 | lun = ccb->pcmd->device->lun; | ||
1321 | if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)){ | ||
1322 | if (acb->devstate[id][lun] == ARECA_RAID_GONE) | ||
1323 | acb->devstate[id][lun] = ARECA_RAID_GOOD; | ||
1324 | ccb->pcmd->result = DID_OK << 16; | ||
1325 | arcmsr_ccb_complete(ccb, 1); | ||
1326 | } | ||
1327 | else { | ||
1328 | switch(ccb->arcmsr_cdb.DeviceStatus) { | ||
1329 | case ARCMSR_DEV_SELECT_TIMEOUT: { | ||
1330 | acb->devstate[id][lun] = ARECA_RAID_GONE; | ||
1331 | ccb->pcmd->result = DID_NO_CONNECT << 16; | ||
1332 | arcmsr_ccb_complete(ccb, 1); | ||
1333 | } | ||
1334 | break; | ||
1335 | |||
1336 | case ARCMSR_DEV_ABORTED: | ||
1337 | |||
1338 | case ARCMSR_DEV_INIT_FAIL: { | ||
1339 | acb->devstate[id][lun] = | ||
1340 | ARECA_RAID_GONE; | ||
1341 | ccb->pcmd->result = | ||
1342 | DID_BAD_TARGET << 16; | ||
1343 | arcmsr_ccb_complete(ccb, 1); | ||
1344 | } | ||
1345 | break; | ||
1346 | |||
1347 | case ARCMSR_DEV_CHECK_CONDITION: { | ||
1348 | acb->devstate[id][lun] = | ||
1349 | ARECA_RAID_GOOD; | ||
1350 | arcmsr_report_sense_info(ccb); | ||
1351 | arcmsr_ccb_complete(ccb, 1); | ||
1352 | } | ||
1353 | break; | ||
1354 | |||
1355 | default: | ||
1356 | printk(KERN_NOTICE | ||
1357 | "arcmsr%d: scsi id = %d \ | ||
1358 | lun = %d""polling and \ | ||
1359 | getting command error \ | ||
1360 | done""but got unknown \ | ||
1361 | DeviceStatus = 0x%x \n", | ||
1362 | acb->host->host_no, id, | ||
1363 | lun, ccb->arcmsr_cdb.DeviceStatus); | ||
1364 | acb->devstate[id][lun] = | ||
1365 | ARECA_RAID_GONE; | ||
1366 | ccb->pcmd->result = | ||
1367 | DID_BAD_TARGET << 16; | ||
1368 | arcmsr_ccb_complete(ccb, 1); | ||
1369 | break; | ||
1370 | } | ||
1371 | } | ||
1372 | found = 1; | ||
1373 | } | ||
1374 | } | ||
1375 | if (found){ | ||
1376 | outbound_intstatus = readl(®->outbound_intstatus) & \ | ||
1377 | acb->outbound_int_enable; | ||
1378 | writel(outbound_intstatus, ®->outbound_intstatus); | ||
1379 | /*clear interrupt*/ | ||
1380 | } | ||
1381 | return; | ||
1382 | } | ||
1383 | |||
1325 | 1384 | ||
1326 | static void arcmsr_iop_init(struct AdapterControlBlock *acb) | 1385 | static void arcmsr_iop_init(struct AdapterControlBlock *acb) |
1327 | { | 1386 | { |
@@ -1355,7 +1414,6 @@ static void arcmsr_iop_init(struct AdapterControlBlock *acb) | |||
1355 | 1414 | ||
1356 | static void arcmsr_iop_reset(struct AdapterControlBlock *acb) | 1415 | static void arcmsr_iop_reset(struct AdapterControlBlock *acb) |
1357 | { | 1416 | { |
1358 | struct MessageUnit __iomem *reg = acb->pmu; | ||
1359 | struct CommandControlBlock *ccb; | 1417 | struct CommandControlBlock *ccb; |
1360 | uint32_t intmask_org; | 1418 | uint32_t intmask_org; |
1361 | int i = 0; | 1419 | int i = 0; |
@@ -1368,21 +1426,17 @@ static void arcmsr_iop_reset(struct AdapterControlBlock *acb) | |||
1368 | /* disable all outbound interrupt */ | 1426 | /* disable all outbound interrupt */ |
1369 | intmask_org = arcmsr_disable_outbound_ints(acb); | 1427 | intmask_org = arcmsr_disable_outbound_ints(acb); |
1370 | /* clear all outbound posted Q */ | 1428 | /* clear all outbound posted Q */ |
1371 | for (i = 0; i < ARCMSR_MAX_OUTSTANDING_CMD; i++) | 1429 | arcmsr_done4_abort_postqueue(acb); |
1372 | readl(®->outbound_queueport); | ||
1373 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { | 1430 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { |
1374 | ccb = acb->pccb_pool[i]; | 1431 | ccb = acb->pccb_pool[i]; |
1375 | if ((ccb->startdone == ARCMSR_CCB_START) || | 1432 | if (ccb->startdone == ARCMSR_CCB_START) { |
1376 | (ccb->startdone == ARCMSR_CCB_ABORTED)) { | ||
1377 | ccb->startdone = ARCMSR_CCB_ABORTED; | 1433 | ccb->startdone = ARCMSR_CCB_ABORTED; |
1378 | ccb->pcmd->result = DID_ABORT << 16; | ||
1379 | arcmsr_ccb_complete(ccb, 1); | ||
1380 | } | 1434 | } |
1381 | } | 1435 | } |
1382 | /* enable all outbound interrupt */ | 1436 | /* enable all outbound interrupt */ |
1383 | arcmsr_enable_outbound_ints(acb, intmask_org); | 1437 | arcmsr_enable_outbound_ints(acb, intmask_org); |
1384 | } | 1438 | } |
1385 | atomic_set(&acb->ccboutstandingcount, 0); | 1439 | |
1386 | } | 1440 | } |
1387 | 1441 | ||
1388 | static int arcmsr_bus_reset(struct scsi_cmnd *cmd) | 1442 | static int arcmsr_bus_reset(struct scsi_cmnd *cmd) |
@@ -1428,10 +1482,9 @@ static int arcmsr_abort(struct scsi_cmnd *cmd) | |||
1428 | int i = 0; | 1482 | int i = 0; |
1429 | 1483 | ||
1430 | printk(KERN_NOTICE | 1484 | printk(KERN_NOTICE |
1431 | "arcmsr%d: abort device command of scsi id=%d lun=%d \n", | 1485 | "arcmsr%d: abort device command of scsi id = %d lun = %d \n", |
1432 | acb->host->host_no, cmd->device->id, cmd->device->lun); | 1486 | acb->host->host_no, cmd->device->id, cmd->device->lun); |
1433 | acb->num_aborts++; | 1487 | acb->num_aborts++; |
1434 | |||
1435 | /* | 1488 | /* |
1436 | ************************************************ | 1489 | ************************************************ |
1437 | ** the all interrupt service routine is locked | 1490 | ** the all interrupt service routine is locked |
@@ -1486,10 +1539,306 @@ static const char *arcmsr_info(struct Scsi_Host *host) | |||
1486 | type = "X-TYPE"; | 1539 | type = "X-TYPE"; |
1487 | break; | 1540 | break; |
1488 | } | 1541 | } |
1489 | sprintf(buf, "Areca %s Host Adapter RAID Controller%s\n %s", | 1542 | sprintf(buf, "Areca %s Host Adapter RAID Controller%s\n %s", |
1490 | type, raid6 ? "( RAID6 capable)" : "", | 1543 | type, raid6 ? "( RAID6 capable)" : "", |
1491 | ARCMSR_DRIVER_VERSION); | 1544 | ARCMSR_DRIVER_VERSION); |
1492 | return buf; | 1545 | return buf; |
1493 | } | 1546 | } |
1494 | 1547 | ||
1548 | static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev) | ||
1549 | { | ||
1550 | struct Scsi_Host *host; | ||
1551 | struct AdapterControlBlock *acb; | ||
1552 | uint8_t bus, dev_fun; | ||
1553 | int error; | ||
1554 | |||
1555 | error = pci_enable_device(pdev); | ||
1556 | if (error) | ||
1557 | return PCI_ERS_RESULT_DISCONNECT; | ||
1558 | pci_set_master(pdev); | ||
1559 | |||
1560 | host = scsi_host_alloc(&arcmsr_scsi_host_template, sizeof \ | ||
1561 | (struct AdapterControlBlock)); | ||
1562 | if (!host) | ||
1563 | return PCI_ERS_RESULT_DISCONNECT; | ||
1564 | acb = (struct AdapterControlBlock *)host->hostdata; | ||
1565 | memset(acb, 0, sizeof (struct AdapterControlBlock)); | ||
1566 | |||
1567 | error = pci_set_dma_mask(pdev, DMA_64BIT_MASK); | ||
1568 | if (error) { | ||
1569 | error = pci_set_dma_mask(pdev, DMA_32BIT_MASK); | ||
1570 | if (error) { | ||
1571 | printk(KERN_WARNING | ||
1572 | "scsi%d: No suitable DMA mask available\n", | ||
1573 | host->host_no); | ||
1574 | return PCI_ERS_RESULT_DISCONNECT; | ||
1575 | } | ||
1576 | } | ||
1577 | bus = pdev->bus->number; | ||
1578 | dev_fun = pdev->devfn; | ||
1579 | acb = (struct AdapterControlBlock *) host->hostdata; | ||
1580 | memset(acb, 0, sizeof(struct AdapterControlBlock)); | ||
1581 | acb->pdev = pdev; | ||
1582 | acb->host = host; | ||
1583 | host->max_sectors = ARCMSR_MAX_XFER_SECTORS; | ||
1584 | host->max_lun = ARCMSR_MAX_TARGETLUN; | ||
1585 | host->max_id = ARCMSR_MAX_TARGETID;/*16:8*/ | ||
1586 | host->max_cmd_len = 16; /*this is issue of 64bit LBA, over 2T byte*/ | ||
1587 | host->sg_tablesize = ARCMSR_MAX_SG_ENTRIES; | ||
1588 | host->can_queue = ARCMSR_MAX_FREECCB_NUM; /* max simultaneous cmds */ | ||
1589 | host->cmd_per_lun = ARCMSR_MAX_CMD_PERLUN; | ||
1590 | host->this_id = ARCMSR_SCSI_INITIATOR_ID; | ||
1591 | host->unique_id = (bus << 8) | dev_fun; | ||
1592 | host->irq = pdev->irq; | ||
1593 | error = pci_request_regions(pdev, "arcmsr"); | ||
1594 | if (error) | ||
1595 | return PCI_ERS_RESULT_DISCONNECT; | ||
1596 | |||
1597 | acb->pmu = ioremap(pci_resource_start(pdev, 0), | ||
1598 | pci_resource_len(pdev, 0)); | ||
1599 | if (!acb->pmu) { | ||
1600 | printk(KERN_NOTICE "arcmsr%d: memory" | ||
1601 | " mapping region fail \n", acb->host->host_no); | ||
1602 | return PCI_ERS_RESULT_DISCONNECT; | ||
1603 | } | ||
1604 | acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | | ||
1605 | ACB_F_MESSAGE_RQBUFFER_CLEARED | | ||
1606 | ACB_F_MESSAGE_WQBUFFER_READED); | ||
1607 | acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; | ||
1608 | INIT_LIST_HEAD(&acb->ccb_free_list); | ||
1609 | |||
1610 | error = arcmsr_alloc_ccb_pool(acb); | ||
1611 | if (error) | ||
1612 | return PCI_ERS_RESULT_DISCONNECT; | ||
1613 | |||
1614 | error = request_irq(pdev->irq, arcmsr_do_interrupt, | ||
1615 | IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb); | ||
1616 | if (error) | ||
1617 | return PCI_ERS_RESULT_DISCONNECT; | ||
1618 | |||
1619 | arcmsr_iop_init(acb); | ||
1620 | if (strncmp(acb->firm_version, "V1.42", 5) >= 0) | ||
1621 | host->max_sectors = ARCMSR_MAX_XFER_SECTORS_B; | ||
1622 | |||
1623 | pci_set_drvdata(pdev, host); | ||
1624 | |||
1625 | error = scsi_add_host(host, &pdev->dev); | ||
1626 | if (error) | ||
1627 | return PCI_ERS_RESULT_DISCONNECT; | ||
1628 | |||
1629 | error = arcmsr_alloc_sysfs_attr(acb); | ||
1630 | if (error) | ||
1631 | return PCI_ERS_RESULT_DISCONNECT; | ||
1632 | |||
1633 | scsi_scan_host(host); | ||
1634 | return PCI_ERS_RESULT_RECOVERED; | ||
1635 | } | ||
1636 | |||
1637 | static void arcmsr_pci_ers_need_reset_forepart(struct pci_dev *pdev) | ||
1638 | { | ||
1639 | struct Scsi_Host *host = pci_get_drvdata(pdev); | ||
1640 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | ||
1641 | struct MessageUnit __iomem *reg = acb->pmu; | ||
1642 | struct CommandControlBlock *ccb; | ||
1643 | /*clear and abort all outbound posted Q*/ | ||
1644 | int i = 0, found = 0; | ||
1645 | int id, lun; | ||
1646 | uint32_t flag_ccb, outbound_intstatus; | ||
1647 | |||
1648 | while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) && | ||
1649 | (i++ < 256)){ | ||
1650 | ccb = (struct CommandControlBlock *)(acb->vir2phy_offset | ||
1651 | + (flag_ccb << 5)); | ||
1652 | if (ccb){ | ||
1653 | if ((ccb->acb != acb)||(ccb->startdone != | ||
1654 | ARCMSR_CCB_START)){ | ||
1655 | printk(KERN_NOTICE "arcmsr%d: polling \ | ||
1656 | get an illegal ccb"" command done ccb = '0x%p'" | ||
1657 | "ccboutstandingcount = %d \n", | ||
1658 | acb->host->host_no, ccb, | ||
1659 | atomic_read(&acb->ccboutstandingcount)); | ||
1660 | continue; | ||
1661 | } | ||
1495 | 1662 | ||
1663 | id = ccb->pcmd->device->id; | ||
1664 | lun = ccb->pcmd->device->lun; | ||
1665 | if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { | ||
1666 | if (acb->devstate[id][lun] == | ||
1667 | ARECA_RAID_GONE) | ||
1668 | acb->devstate[id][lun] = | ||
1669 | ARECA_RAID_GOOD; | ||
1670 | ccb->pcmd->result = DID_OK << 16; | ||
1671 | arcmsr_ccb_complete(ccb, 1); | ||
1672 | } | ||
1673 | else { | ||
1674 | switch(ccb->arcmsr_cdb.DeviceStatus) { | ||
1675 | case ARCMSR_DEV_SELECT_TIMEOUT: { | ||
1676 | acb->devstate[id][lun] = | ||
1677 | ARECA_RAID_GONE; | ||
1678 | ccb->pcmd->result = | ||
1679 | DID_NO_CONNECT << 16; | ||
1680 | arcmsr_ccb_complete(ccb, 1); | ||
1681 | } | ||
1682 | break; | ||
1683 | |||
1684 | case ARCMSR_DEV_ABORTED: | ||
1685 | |||
1686 | case ARCMSR_DEV_INIT_FAIL: { | ||
1687 | acb->devstate[id][lun] = | ||
1688 | ARECA_RAID_GONE; | ||
1689 | ccb->pcmd->result = | ||
1690 | DID_BAD_TARGET << 16; | ||
1691 | arcmsr_ccb_complete(ccb, 1); | ||
1692 | } | ||
1693 | break; | ||
1694 | |||
1695 | case ARCMSR_DEV_CHECK_CONDITION: { | ||
1696 | acb->devstate[id][lun] = | ||
1697 | ARECA_RAID_GOOD; | ||
1698 | arcmsr_report_sense_info(ccb); | ||
1699 | arcmsr_ccb_complete(ccb, 1); | ||
1700 | } | ||
1701 | break; | ||
1702 | |||
1703 | default: | ||
1704 | printk(KERN_NOTICE | ||
1705 | "arcmsr%d: scsi \ | ||
1706 | id = %d lun = %d" | ||
1707 | " polling and \ | ||
1708 | getting command \ | ||
1709 | error done" | ||
1710 | "but got unknown \ | ||
1711 | DeviceStatus = 0x%x \n" | ||
1712 | , acb->host->host_no, | ||
1713 | id, lun, | ||
1714 | ccb->arcmsr_cdb.DeviceStatus); | ||
1715 | acb->devstate[id][lun] = | ||
1716 | ARECA_RAID_GONE; | ||
1717 | ccb->pcmd->result = | ||
1718 | DID_BAD_TARGET << 16; | ||
1719 | arcmsr_ccb_complete(ccb, 1); | ||
1720 | break; | ||
1721 | } | ||
1722 | } | ||
1723 | found = 1; | ||
1724 | } | ||
1725 | } | ||
1726 | if (found){ | ||
1727 | outbound_intstatus = readl(®->outbound_intstatus) & | ||
1728 | acb->outbound_int_enable; | ||
1729 | writel(outbound_intstatus, ®->outbound_intstatus); | ||
1730 | /*clear interrupt*/ | ||
1731 | } | ||
1732 | return; | ||
1733 | } | ||
1734 | |||
1735 | |||
1736 | static void arcmsr_pci_ers_disconnect_forepart(struct pci_dev *pdev) | ||
1737 | { | ||
1738 | struct Scsi_Host *host = pci_get_drvdata(pdev); | ||
1739 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | ||
1740 | struct MessageUnit __iomem *reg = acb->pmu; | ||
1741 | struct CommandControlBlock *ccb; | ||
1742 | /*clear and abort all outbound posted Q*/ | ||
1743 | int i = 0, found = 0; | ||
1744 | int id, lun; | ||
1745 | uint32_t flag_ccb, outbound_intstatus; | ||
1746 | |||
1747 | while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) && | ||
1748 | (i++ < 256)){ | ||
1749 | ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + | ||
1750 | (flag_ccb << 5)); | ||
1751 | if (ccb){ | ||
1752 | if ((ccb->acb != acb)||(ccb->startdone != | ||
1753 | ARCMSR_CCB_START)){ | ||
1754 | printk(KERN_NOTICE | ||
1755 | "arcmsr%d: polling get an illegal ccb" | ||
1756 | " command done ccb = '0x%p'" | ||
1757 | "ccboutstandingcount = %d \n", | ||
1758 | acb->host->host_no, ccb, | ||
1759 | atomic_read(&acb->ccboutstandingcount)); | ||
1760 | continue; | ||
1761 | } | ||
1762 | |||
1763 | id = ccb->pcmd->device->id; | ||
1764 | lun = ccb->pcmd->device->lun; | ||
1765 | if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { | ||
1766 | if (acb->devstate[id][lun] == ARECA_RAID_GONE) | ||
1767 | acb->devstate[id][lun] = ARECA_RAID_GOOD; | ||
1768 | ccb->pcmd->result = DID_OK << 16; | ||
1769 | arcmsr_ccb_complete(ccb, 1); | ||
1770 | } | ||
1771 | else { | ||
1772 | switch(ccb->arcmsr_cdb.DeviceStatus) { | ||
1773 | case ARCMSR_DEV_SELECT_TIMEOUT: { | ||
1774 | acb->devstate[id][lun] = | ||
1775 | ARECA_RAID_GONE; | ||
1776 | ccb->pcmd->result = | ||
1777 | DID_NO_CONNECT << 16; | ||
1778 | arcmsr_ccb_complete(ccb, 1); | ||
1779 | } | ||
1780 | break; | ||
1781 | |||
1782 | case ARCMSR_DEV_ABORTED: | ||
1783 | |||
1784 | case ARCMSR_DEV_INIT_FAIL: { | ||
1785 | acb->devstate[id][lun] = | ||
1786 | ARECA_RAID_GONE; | ||
1787 | ccb->pcmd->result = | ||
1788 | DID_BAD_TARGET << 16; | ||
1789 | arcmsr_ccb_complete(ccb, 1); | ||
1790 | } | ||
1791 | break; | ||
1792 | |||
1793 | case ARCMSR_DEV_CHECK_CONDITION: { | ||
1794 | acb->devstate[id][lun] = | ||
1795 | ARECA_RAID_GOOD; | ||
1796 | arcmsr_report_sense_info(ccb); | ||
1797 | arcmsr_ccb_complete(ccb, 1); | ||
1798 | } | ||
1799 | break; | ||
1800 | |||
1801 | default: | ||
1802 | printk(KERN_NOTICE "arcmsr%d: \ | ||
1803 | scsi id = %d lun = %d" | ||
1804 | " polling and \ | ||
1805 | getting command error done" | ||
1806 | "but got unknown \ | ||
1807 | DeviceStatus = 0x%x \n" | ||
1808 | , acb->host->host_no, | ||
1809 | id, lun, ccb->arcmsr_cdb.DeviceStatus); | ||
1810 | acb->devstate[id][lun] = | ||
1811 | ARECA_RAID_GONE; | ||
1812 | ccb->pcmd->result = | ||
1813 | DID_BAD_TARGET << 16; | ||
1814 | arcmsr_ccb_complete(ccb, 1); | ||
1815 | break; | ||
1816 | } | ||
1817 | } | ||
1818 | found = 1; | ||
1819 | } | ||
1820 | } | ||
1821 | if (found){ | ||
1822 | outbound_intstatus = readl(®->outbound_intstatus) & | ||
1823 | acb->outbound_int_enable; | ||
1824 | writel(outbound_intstatus, ®->outbound_intstatus); | ||
1825 | /*clear interrupt*/ | ||
1826 | } | ||
1827 | return; | ||
1828 | } | ||
1829 | |||
1830 | static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, | ||
1831 | pci_channel_state_t state) | ||
1832 | { | ||
1833 | switch (state) { | ||
1834 | case pci_channel_io_frozen: | ||
1835 | arcmsr_pci_ers_need_reset_forepart(pdev); | ||
1836 | return PCI_ERS_RESULT_NEED_RESET; | ||
1837 | case pci_channel_io_perm_failure: | ||
1838 | arcmsr_pci_ers_disconnect_forepart(pdev); | ||
1839 | return PCI_ERS_RESULT_DISCONNECT; | ||
1840 | break; | ||
1841 | default: | ||
1842 | return PCI_ERS_RESULT_NEED_RESET; | ||
1843 | } | ||
1844 | } | ||