aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSakthivel K <Sakthivel.SaravananKamalRaju@pmcs.com>2013-03-19 08:38:40 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-05-10 10:47:51 -0400
commita6cb3d012b983b350ae3892cff2e692665df0e1e (patch)
treee22bce8642adf4f4b5caf08ab0995a131db2e39e
parentc6b9ef5779c3e1edfa9de949d2a51252bc347663 (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.c2
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c2
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c66
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h2
-rw-r--r--drivers/scsi/pm8001/pm80xx_hwi.c150
-rw-r--r--drivers/scsi/pm8001/pm80xx_hwi.h44
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*/
1025int 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));
1082out:
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*/
1022int pm8001_lu_reset(struct domain_device *dev, u8 *lun) 1088int 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);
563void pm8001_dev_gone(struct domain_device *dev); 563void pm8001_dev_gone(struct domain_device *dev);
564int pm8001_lu_reset(struct domain_device *dev, u8 *lun); 564int pm8001_lu_reset(struct domain_device *dev, u8 *lun);
565int pm8001_I_T_nexus_reset(struct domain_device *dev); 565int pm8001_I_T_nexus_reset(struct domain_device *dev);
566int pm8001_I_T_nexus_event_handler(struct domain_device *dev);
566int pm8001_query_task(struct sas_task *task); 567int pm8001_query_task(struct sas_task *task);
567void pm8001_open_reject_retry( 568void 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);
625void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag); 626void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag);
626struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha, 627struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha,
627 u32 device_id); 628 u32 device_id);
629int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha);
628 630
629int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); 631int 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 */
616static int 616int
617pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha) 617pm80xx_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*/
646static int
647pm80xx_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)