diff options
author | Sakthivel K <Sakthivel.SaravananKamalRaju@pmcs.com> | 2013-03-19 08:38:40 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-05-10 10:47:51 -0400 |
commit | a6cb3d012b983b350ae3892cff2e692665df0e1e (patch) | |
tree | e22bce8642adf4f4b5caf08ab0995a131db2e39e | |
parent | c6b9ef5779c3e1edfa9de949d2a51252bc347663 (diff) |
[SCSI] pm80xx: thermal, sas controller config and error handling update
Modified thermal configuration to happen after interrupt registration
Added SAS controller configuration during initialization
Added error handling logic to handle I_T_Nexus errors and variants
[jejb: fix up tabs and spaces issues]
Signed-off-by: Anand Kumar S <AnandKumar.Santhanam@pmcs.com>
Acked-by: Jack Wang <jack_wang@usish.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.c | 2 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_init.c | 2 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.c | 66 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.h | 2 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm80xx_hwi.c | 150 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm80xx_hwi.h | 44 |
6 files changed, 249 insertions, 17 deletions
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index dbdd9d386f10..95d04cc78c0b 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c | |||
@@ -1670,7 +1670,7 @@ void pm8001_work_fn(struct work_struct *work) | |||
1670 | } break; | 1670 | } break; |
1671 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: | 1671 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: |
1672 | dev = pm8001_dev->sas_device; | 1672 | dev = pm8001_dev->sas_device; |
1673 | pm8001_I_T_nexus_reset(dev); | 1673 | pm8001_I_T_nexus_event_handler(dev); |
1674 | break; | 1674 | break; |
1675 | case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY: | 1675 | case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY: |
1676 | dev = pm8001_dev->sas_device; | 1676 | dev = pm8001_dev->sas_device; |
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 055f7d0e15d8..1c718520036a 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c | |||
@@ -838,6 +838,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev, | |||
838 | if (pm8001_ha->chip_id != chip_8001) { | 838 | if (pm8001_ha->chip_id != chip_8001) { |
839 | for (i = 1; i < pm8001_ha->number_of_intr; i++) | 839 | for (i = 1; i < pm8001_ha->number_of_intr; i++) |
840 | PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i); | 840 | PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i); |
841 | /* setup thermal configuration. */ | ||
842 | pm80xx_set_thermal_config(pm8001_ha); | ||
841 | } | 843 | } |
842 | 844 | ||
843 | pm8001_init_sas_add(pm8001_ha); | 845 | pm8001_init_sas_add(pm8001_ha); |
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index c720917d1388..9af95853f840 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c | |||
@@ -1018,6 +1018,72 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev) | |||
1018 | return rc; | 1018 | return rc; |
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | /* | ||
1022 | * This function handle the IT_NEXUS_XXX event or completion | ||
1023 | * status code for SSP/SATA/SMP I/O request. | ||
1024 | */ | ||
1025 | int pm8001_I_T_nexus_event_handler(struct domain_device *dev) | ||
1026 | { | ||
1027 | int rc = TMF_RESP_FUNC_FAILED; | ||
1028 | struct pm8001_device *pm8001_dev; | ||
1029 | struct pm8001_hba_info *pm8001_ha; | ||
1030 | struct sas_phy *phy; | ||
1031 | u32 device_id = 0; | ||
1032 | |||
1033 | if (!dev || !dev->lldd_dev) | ||
1034 | return -1; | ||
1035 | |||
1036 | pm8001_dev = dev->lldd_dev; | ||
1037 | device_id = pm8001_dev->device_id; | ||
1038 | pm8001_ha = pm8001_find_ha_by_dev(dev); | ||
1039 | |||
1040 | PM8001_EH_DBG(pm8001_ha, | ||
1041 | pm8001_printk("I_T_Nexus handler invoked !!")); | ||
1042 | |||
1043 | phy = sas_get_local_phy(dev); | ||
1044 | |||
1045 | if (dev_is_sata(dev)) { | ||
1046 | DECLARE_COMPLETION_ONSTACK(completion_setstate); | ||
1047 | if (scsi_is_sas_phy_local(phy)) { | ||
1048 | rc = 0; | ||
1049 | goto out; | ||
1050 | } | ||
1051 | /* send internal ssp/sata/smp abort command to FW */ | ||
1052 | rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , | ||
1053 | dev, 1, 0); | ||
1054 | msleep(100); | ||
1055 | |||
1056 | /* deregister the target device */ | ||
1057 | pm8001_dev_gone_notify(dev); | ||
1058 | msleep(200); | ||
1059 | |||
1060 | /*send phy reset to hard reset target */ | ||
1061 | rc = sas_phy_reset(phy, 1); | ||
1062 | msleep(2000); | ||
1063 | pm8001_dev->setds_completion = &completion_setstate; | ||
1064 | |||
1065 | wait_for_completion(&completion_setstate); | ||
1066 | } else { | ||
1067 | /* send internal ssp/sata/smp abort command to FW */ | ||
1068 | rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , | ||
1069 | dev, 1, 0); | ||
1070 | msleep(100); | ||
1071 | |||
1072 | /* deregister the target device */ | ||
1073 | pm8001_dev_gone_notify(dev); | ||
1074 | msleep(200); | ||
1075 | |||
1076 | /*send phy reset to hard reset target */ | ||
1077 | rc = sas_phy_reset(phy, 1); | ||
1078 | msleep(2000); | ||
1079 | } | ||
1080 | PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n", | ||
1081 | pm8001_dev->device_id, rc)); | ||
1082 | out: | ||
1083 | sas_put_local_phy(phy); | ||
1084 | |||
1085 | return rc; | ||
1086 | } | ||
1021 | /* mandatory SAM-3, the task reset the specified LUN*/ | 1087 | /* mandatory SAM-3, the task reset the specified LUN*/ |
1022 | int pm8001_lu_reset(struct domain_device *dev, u8 *lun) | 1088 | int pm8001_lu_reset(struct domain_device *dev, u8 *lun) |
1023 | { | 1089 | { |
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index ab30193f235f..72d46ea398dc 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h | |||
@@ -563,6 +563,7 @@ int pm8001_dev_found(struct domain_device *dev); | |||
563 | void pm8001_dev_gone(struct domain_device *dev); | 563 | void pm8001_dev_gone(struct domain_device *dev); |
564 | int pm8001_lu_reset(struct domain_device *dev, u8 *lun); | 564 | int pm8001_lu_reset(struct domain_device *dev, u8 *lun); |
565 | int pm8001_I_T_nexus_reset(struct domain_device *dev); | 565 | int pm8001_I_T_nexus_reset(struct domain_device *dev); |
566 | int pm8001_I_T_nexus_event_handler(struct domain_device *dev); | ||
566 | int pm8001_query_task(struct sas_task *task); | 567 | int pm8001_query_task(struct sas_task *task); |
567 | void pm8001_open_reject_retry( | 568 | void pm8001_open_reject_retry( |
568 | struct pm8001_hba_info *pm8001_ha, | 569 | struct pm8001_hba_info *pm8001_ha, |
@@ -625,6 +626,7 @@ void pm8001_free_task(struct sas_task *task); | |||
625 | void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag); | 626 | void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag); |
626 | struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha, | 627 | struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha, |
627 | u32 device_id); | 628 | u32 device_id); |
629 | int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha); | ||
628 | 630 | ||
629 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); | 631 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); |
630 | 632 | ||
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index f0dbe79b049c..670998a8ca79 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c | |||
@@ -613,7 +613,7 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha) | |||
613 | * pm80xx_set_thermal_config - support the thermal configuration | 613 | * pm80xx_set_thermal_config - support the thermal configuration |
614 | * @pm8001_ha: our hba card information. | 614 | * @pm8001_ha: our hba card information. |
615 | */ | 615 | */ |
616 | static int | 616 | int |
617 | pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha) | 617 | pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha) |
618 | { | 618 | { |
619 | struct set_ctrl_cfg_req payload; | 619 | struct set_ctrl_cfg_req payload; |
@@ -639,6 +639,86 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha) | |||
639 | } | 639 | } |
640 | 640 | ||
641 | /** | 641 | /** |
642 | * pm80xx_set_sas_protocol_timer_config - support the SAS Protocol | ||
643 | * Timer configuration page | ||
644 | * @pm8001_ha: our hba card information. | ||
645 | */ | ||
646 | static int | ||
647 | pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha) | ||
648 | { | ||
649 | struct set_ctrl_cfg_req payload; | ||
650 | struct inbound_queue_table *circularQ; | ||
651 | SASProtocolTimerConfig_t SASConfigPage; | ||
652 | int rc; | ||
653 | u32 tag; | ||
654 | u32 opc = OPC_INB_SET_CONTROLLER_CONFIG; | ||
655 | |||
656 | memset(&payload, 0, sizeof(struct set_ctrl_cfg_req)); | ||
657 | memset(&SASConfigPage, 0, sizeof(SASProtocolTimerConfig_t)); | ||
658 | |||
659 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | ||
660 | |||
661 | if (rc) | ||
662 | return -1; | ||
663 | |||
664 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
665 | payload.tag = cpu_to_le32(tag); | ||
666 | |||
667 | SASConfigPage.pageCode = SAS_PROTOCOL_TIMER_CONFIG_PAGE; | ||
668 | SASConfigPage.MST_MSI = 3 << 15; | ||
669 | SASConfigPage.STP_SSP_MCT_TMO = (STP_MCT_TMO << 16) | SSP_MCT_TMO; | ||
670 | SASConfigPage.STP_FRM_TMO = (SAS_MAX_OPEN_TIME << 24) | | ||
671 | (SMP_MAX_CONN_TIMER << 16) | STP_FRM_TIMER; | ||
672 | SASConfigPage.STP_IDLE_TMO = STP_IDLE_TIME; | ||
673 | |||
674 | if (SASConfigPage.STP_IDLE_TMO > 0x3FFFFFF) | ||
675 | SASConfigPage.STP_IDLE_TMO = 0x3FFFFFF; | ||
676 | |||
677 | |||
678 | SASConfigPage.OPNRJT_RTRY_INTVL = (SAS_MFD << 16) | | ||
679 | SAS_OPNRJT_RTRY_INTVL; | ||
680 | SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO = (SAS_DOPNRJT_RTRY_TMO << 16) | ||
681 | | SAS_COPNRJT_RTRY_TMO; | ||
682 | SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR = (SAS_DOPNRJT_RTRY_THR << 16) | ||
683 | | SAS_COPNRJT_RTRY_THR; | ||
684 | SASConfigPage.MAX_AIP = SAS_MAX_AIP; | ||
685 | |||
686 | PM8001_INIT_DBG(pm8001_ha, | ||
687 | pm8001_printk("SASConfigPage.pageCode " | ||
688 | "0x%08x\n", SASConfigPage.pageCode)); | ||
689 | PM8001_INIT_DBG(pm8001_ha, | ||
690 | pm8001_printk("SASConfigPage.MST_MSI " | ||
691 | " 0x%08x\n", SASConfigPage.MST_MSI)); | ||
692 | PM8001_INIT_DBG(pm8001_ha, | ||
693 | pm8001_printk("SASConfigPage.STP_SSP_MCT_TMO " | ||
694 | " 0x%08x\n", SASConfigPage.STP_SSP_MCT_TMO)); | ||
695 | PM8001_INIT_DBG(pm8001_ha, | ||
696 | pm8001_printk("SASConfigPage.STP_FRM_TMO " | ||
697 | " 0x%08x\n", SASConfigPage.STP_FRM_TMO)); | ||
698 | PM8001_INIT_DBG(pm8001_ha, | ||
699 | pm8001_printk("SASConfigPage.STP_IDLE_TMO " | ||
700 | " 0x%08x\n", SASConfigPage.STP_IDLE_TMO)); | ||
701 | PM8001_INIT_DBG(pm8001_ha, | ||
702 | pm8001_printk("SASConfigPage.OPNRJT_RTRY_INTVL " | ||
703 | " 0x%08x\n", SASConfigPage.OPNRJT_RTRY_INTVL)); | ||
704 | PM8001_INIT_DBG(pm8001_ha, | ||
705 | pm8001_printk("SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO " | ||
706 | " 0x%08x\n", SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO)); | ||
707 | PM8001_INIT_DBG(pm8001_ha, | ||
708 | pm8001_printk("SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR " | ||
709 | " 0x%08x\n", SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR)); | ||
710 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk("SASConfigPage.MAX_AIP " | ||
711 | " 0x%08x\n", SASConfigPage.MAX_AIP)); | ||
712 | |||
713 | memcpy(&payload.cfg_pg, &SASConfigPage, | ||
714 | sizeof(SASProtocolTimerConfig_t)); | ||
715 | |||
716 | rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); | ||
717 | |||
718 | return rc; | ||
719 | } | ||
720 | |||
721 | /** | ||
642 | * pm80xx_get_encrypt_info - Check for encryption | 722 | * pm80xx_get_encrypt_info - Check for encryption |
643 | * @pm8001_ha: our hba card information. | 723 | * @pm8001_ha: our hba card information. |
644 | */ | 724 | */ |
@@ -800,11 +880,8 @@ static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha) | |||
800 | } else | 880 | } else |
801 | return -EBUSY; | 881 | return -EBUSY; |
802 | 882 | ||
803 | /* configure thermal */ | 883 | /* send SAS protocol timer configuration page to FW */ |
804 | pm80xx_set_thermal_config(pm8001_ha); | 884 | ret = pm80xx_set_sas_protocol_timer_config(pm8001_ha); |
805 | |||
806 | PM8001_INIT_DBG(pm8001_ha, | ||
807 | pm8001_printk("Thermal configuration successful!\n")); | ||
808 | 885 | ||
809 | /* Check for encryption */ | 886 | /* Check for encryption */ |
810 | if (pm8001_ha->chip->encrypt) { | 887 | if (pm8001_ha->chip->encrypt) { |
@@ -1269,6 +1346,11 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
1269 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | 1346 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; |
1270 | break; | 1347 | break; |
1271 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: | 1348 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: |
1349 | case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED: | ||
1350 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO: | ||
1351 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST: | ||
1352 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE: | ||
1353 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED: | ||
1272 | PM8001_IO_DBG(pm8001_ha, | 1354 | PM8001_IO_DBG(pm8001_ha, |
1273 | pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); | 1355 | pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); |
1274 | ts->resp = SAS_TASK_COMPLETE; | 1356 | ts->resp = SAS_TASK_COMPLETE; |
@@ -1472,6 +1554,11 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
1472 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | 1554 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; |
1473 | break; | 1555 | break; |
1474 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: | 1556 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: |
1557 | case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED: | ||
1558 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO: | ||
1559 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST: | ||
1560 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE: | ||
1561 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED: | ||
1475 | PM8001_IO_DBG(pm8001_ha, | 1562 | PM8001_IO_DBG(pm8001_ha, |
1476 | pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); | 1563 | pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); |
1477 | ts->resp = SAS_TASK_COMPLETE; | 1564 | ts->resp = SAS_TASK_COMPLETE; |
@@ -1557,6 +1644,13 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
1557 | ts->resp = SAS_TASK_COMPLETE; | 1644 | ts->resp = SAS_TASK_COMPLETE; |
1558 | ts->stat = SAS_DATA_OVERRUN; | 1645 | ts->stat = SAS_DATA_OVERRUN; |
1559 | break; | 1646 | break; |
1647 | case IO_XFER_ERROR_INTERNAL_CRC_ERROR: | ||
1648 | PM8001_IO_DBG(pm8001_ha, | ||
1649 | pm8001_printk("IO_XFR_ERROR_INTERNAL_CRC_ERROR\n")); | ||
1650 | /* TBC: used default set values */ | ||
1651 | ts->resp = SAS_TASK_COMPLETE; | ||
1652 | ts->stat = SAS_DATA_OVERRUN; | ||
1653 | break; | ||
1560 | case IO_XFER_CMD_FRAME_ISSUED: | 1654 | case IO_XFER_CMD_FRAME_ISSUED: |
1561 | PM8001_IO_DBG(pm8001_ha, | 1655 | PM8001_IO_DBG(pm8001_ha, |
1562 | pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n")); | 1656 | pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n")); |
@@ -1761,6 +1855,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
1761 | ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; | 1855 | ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; |
1762 | break; | 1856 | break; |
1763 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: | 1857 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: |
1858 | case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED: | ||
1859 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO: | ||
1860 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST: | ||
1861 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE: | ||
1862 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED: | ||
1764 | PM8001_IO_DBG(pm8001_ha, | 1863 | PM8001_IO_DBG(pm8001_ha, |
1765 | pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); | 1864 | pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); |
1766 | ts->resp = SAS_TASK_COMPLETE; | 1865 | ts->resp = SAS_TASK_COMPLETE; |
@@ -2051,7 +2150,12 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
2051 | ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; | 2150 | ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; |
2052 | break; | 2151 | break; |
2053 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: | 2152 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: |
2054 | PM8001_IO_DBG(pm8001_ha, | 2153 | case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED: |
2154 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO: | ||
2155 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST: | ||
2156 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE: | ||
2157 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED: | ||
2158 | PM8001_FAIL_DBG(pm8001_ha, | ||
2055 | pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); | 2159 | pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); |
2056 | ts->resp = SAS_TASK_UNDELIVERED; | 2160 | ts->resp = SAS_TASK_UNDELIVERED; |
2057 | ts->stat = SAS_DEV_NO_RESPONSE; | 2161 | ts->stat = SAS_DEV_NO_RESPONSE; |
@@ -2154,6 +2258,20 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
2154 | ts->resp = SAS_TASK_COMPLETE; | 2258 | ts->resp = SAS_TASK_COMPLETE; |
2155 | ts->stat = SAS_OPEN_TO; | 2259 | ts->stat = SAS_OPEN_TO; |
2156 | break; | 2260 | break; |
2261 | case IO_XFER_ERROR_INTERNAL_CRC_ERROR: | ||
2262 | PM8001_FAIL_DBG(pm8001_ha, | ||
2263 | pm8001_printk("IO_XFR_ERROR_INTERNAL_CRC_ERROR\n")); | ||
2264 | /* TBC: used default set values */ | ||
2265 | ts->resp = SAS_TASK_COMPLETE; | ||
2266 | ts->stat = SAS_OPEN_TO; | ||
2267 | break; | ||
2268 | case IO_XFER_DMA_ACTIVATE_TIMEOUT: | ||
2269 | PM8001_FAIL_DBG(pm8001_ha, | ||
2270 | pm8001_printk("IO_XFR_DMA_ACTIVATE_TIMEOUT\n")); | ||
2271 | /* TBC: used default set values */ | ||
2272 | ts->resp = SAS_TASK_COMPLETE; | ||
2273 | ts->stat = SAS_OPEN_TO; | ||
2274 | break; | ||
2157 | default: | 2275 | default: |
2158 | PM8001_IO_DBG(pm8001_ha, | 2276 | PM8001_IO_DBG(pm8001_ha, |
2159 | pm8001_printk("Unknown status 0x%x\n", event)); | 2277 | pm8001_printk("Unknown status 0x%x\n", event)); |
@@ -2305,6 +2423,11 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
2305 | ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; | 2423 | ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; |
2306 | break; | 2424 | break; |
2307 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: | 2425 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: |
2426 | case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED: | ||
2427 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO: | ||
2428 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST: | ||
2429 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE: | ||
2430 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED: | ||
2308 | PM8001_IO_DBG(pm8001_ha, | 2431 | PM8001_IO_DBG(pm8001_ha, |
2309 | pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); | 2432 | pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); |
2310 | ts->resp = SAS_TASK_COMPLETE; | 2433 | ts->resp = SAS_TASK_COMPLETE; |
@@ -2862,6 +2985,9 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
2862 | case HW_EVENT_PORT_RECOVERY_TIMER_TMO: | 2985 | case HW_EVENT_PORT_RECOVERY_TIMER_TMO: |
2863 | PM8001_MSG_DBG(pm8001_ha, | 2986 | PM8001_MSG_DBG(pm8001_ha, |
2864 | pm8001_printk("HW_EVENT_PORT_RECOVERY_TIMER_TMO\n")); | 2987 | pm8001_printk("HW_EVENT_PORT_RECOVERY_TIMER_TMO\n")); |
2988 | pm80xx_hw_event_ack_req(pm8001_ha, 0, | ||
2989 | HW_EVENT_PORT_RECOVERY_TIMER_TMO, | ||
2990 | port_id, phy_id, 0, 0); | ||
2865 | sas_phy_disconnected(sas_phy); | 2991 | sas_phy_disconnected(sas_phy); |
2866 | phy->phy_attached = 0; | 2992 | phy->phy_attached = 0; |
2867 | sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); | 2993 | sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); |
@@ -3499,10 +3625,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3499 | ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_prio << 3); | 3625 | ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_prio << 3); |
3500 | ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7); | 3626 | ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7); |
3501 | memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cdb, 16); | 3627 | memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cdb, 16); |
3502 | circularQ = &pm8001_ha->inbnd_q_tbl[inb++]; | 3628 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; |
3503 | |||
3504 | /* rotate the inb queue */ | ||
3505 | inb = inb%PM8001_MAX_SPCV_INB_NUM; | ||
3506 | 3629 | ||
3507 | /* Check if encryption is set */ | 3630 | /* Check if encryption is set */ |
3508 | if (pm8001_ha->chip->encrypt && | 3631 | if (pm8001_ha->chip->encrypt && |
@@ -3603,10 +3726,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3603 | unsigned long flags; | 3726 | unsigned long flags; |
3604 | u32 opc = OPC_INB_SATA_HOST_OPSTART; | 3727 | u32 opc = OPC_INB_SATA_HOST_OPSTART; |
3605 | memset(&sata_cmd, 0, sizeof(sata_cmd)); | 3728 | memset(&sata_cmd, 0, sizeof(sata_cmd)); |
3606 | circularQ = &pm8001_ha->inbnd_q_tbl[inb++]; | 3729 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; |
3607 | |||
3608 | /* rotate the inb queue */ | ||
3609 | inb = inb%PM8001_MAX_SPCV_INB_NUM; | ||
3610 | 3730 | ||
3611 | if (task->data_dir == PCI_DMA_NONE) { | 3731 | if (task->data_dir == PCI_DMA_NONE) { |
3612 | ATAP = 0x04; /* no data*/ | 3732 | ATAP = 0x04; /* no data*/ |
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h index b7c864f16402..2b760ba75d7b 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.h +++ b/drivers/scsi/pm8001/pm80xx_hwi.h | |||
@@ -197,6 +197,30 @@ | |||
197 | #define CIPHER_MODE_XTS 0x00000002 | 197 | #define CIPHER_MODE_XTS 0x00000002 |
198 | #define KEK_MGMT_SUBOP_KEYCARDUPDATE 0x4 | 198 | #define KEK_MGMT_SUBOP_KEYCARDUPDATE 0x4 |
199 | 199 | ||
200 | /* SAS protocol timer configuration page */ | ||
201 | #define SAS_PROTOCOL_TIMER_CONFIG_PAGE 0x04 | ||
202 | #define STP_MCT_TMO 32 | ||
203 | #define SSP_MCT_TMO 32 | ||
204 | #define SAS_MAX_OPEN_TIME 5 | ||
205 | #define SMP_MAX_CONN_TIMER 0xFF | ||
206 | #define STP_FRM_TIMER 0 | ||
207 | #define STP_IDLE_TIME 5 /* 5 us; controller default */ | ||
208 | #define SAS_MFD 0 | ||
209 | #define SAS_OPNRJT_RTRY_INTVL 2 | ||
210 | #define SAS_DOPNRJT_RTRY_TMO 128 | ||
211 | #define SAS_COPNRJT_RTRY_TMO 128 | ||
212 | |||
213 | /* | ||
214 | Making ORR bigger than IT NEXUS LOSS which is 2000000us = 2 second. | ||
215 | Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128 | ||
216 | is DOPNRJT_RTRY_TMO | ||
217 | */ | ||
218 | #define SAS_DOPNRJT_RTRY_THR 23438 | ||
219 | #define SAS_COPNRJT_RTRY_THR 23438 | ||
220 | #define SAS_MAX_AIP 0x200000 | ||
221 | #define IT_NEXUS_TIMEOUT 0x7D0 | ||
222 | #define PORT_RECOVERY_TIMEOUT ((IT_NEXUS_TIMEOUT/100) + 30) | ||
223 | |||
200 | struct mpi_msg_hdr { | 224 | struct mpi_msg_hdr { |
201 | __le32 header; /* Bits [11:0] - Message operation code */ | 225 | __le32 header; /* Bits [11:0] - Message operation code */ |
202 | /* Bits [15:12] - Message Category */ | 226 | /* Bits [15:12] - Message Category */ |
@@ -996,6 +1020,23 @@ struct ssp_coalesced_comp_resp { | |||
996 | 1020 | ||
997 | /* new outbound structure for spcv - ends */ | 1021 | /* new outbound structure for spcv - ends */ |
998 | 1022 | ||
1023 | /* brief data structure for SAS protocol timer configuration page. | ||
1024 | * | ||
1025 | */ | ||
1026 | struct SASProtocolTimerConfig { | ||
1027 | __le32 pageCode; /* 0 */ | ||
1028 | __le32 MST_MSI; /* 1 */ | ||
1029 | __le32 STP_SSP_MCT_TMO; /* 2 */ | ||
1030 | __le32 STP_FRM_TMO; /* 3 */ | ||
1031 | __le32 STP_IDLE_TMO; /* 4 */ | ||
1032 | __le32 OPNRJT_RTRY_INTVL; /* 5 */ | ||
1033 | __le32 Data_Cmd_OPNRJT_RTRY_TMO; /* 6 */ | ||
1034 | __le32 Data_Cmd_OPNRJT_RTRY_THR; /* 7 */ | ||
1035 | __le32 MAX_AIP; /* 8 */ | ||
1036 | } __attribute__((packed, aligned(4))); | ||
1037 | |||
1038 | typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t; | ||
1039 | |||
999 | #define NDS_BITS 0x0F | 1040 | #define NDS_BITS 0x0F |
1000 | #define PDS_BITS 0xF0 | 1041 | #define PDS_BITS 0xF0 |
1001 | 1042 | ||
@@ -1122,7 +1163,8 @@ struct ssp_coalesced_comp_resp { | |||
1122 | #define IO_DS_INVALID 0x49 | 1163 | #define IO_DS_INVALID 0x49 |
1123 | /* WARNING: the value is not contiguous from here */ | 1164 | /* WARNING: the value is not contiguous from here */ |
1124 | #define IO_XFER_ERR_LAST_PIO_DATAIN_CRC_ERR 0x52 | 1165 | #define IO_XFER_ERR_LAST_PIO_DATAIN_CRC_ERR 0x52 |
1125 | #define IO_XFR_ERROR_INTERNAL_CRC_ERROR 0x54 | 1166 | #define IO_XFER_DMA_ACTIVATE_TIMEOUT 0x53 |
1167 | #define IO_XFER_ERROR_INTERNAL_CRC_ERROR 0x54 | ||
1126 | #define MPI_IO_RQE_BUSY_FULL 0x55 | 1168 | #define MPI_IO_RQE_BUSY_FULL 0x55 |
1127 | #define IO_XFER_ERR_EOB_DATA_OVERRUN 0x56 | 1169 | #define IO_XFER_ERR_EOB_DATA_OVERRUN 0x56 |
1128 | #define IO_XFR_ERROR_INVALID_SSP_RSP_FRAME 0x57 | 1170 | #define IO_XFR_ERROR_INVALID_SSP_RSP_FRAME 0x57 |