Skip to content

Commit a6cb3d0

Browse files
Sakthivel KJames Bottomley
authored andcommitted
[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>
1 parent c6b9ef5 commit a6cb3d0

File tree

6 files changed

+249
-17
lines changed

6 files changed

+249
-17
lines changed

drivers/scsi/pm8001/pm8001_hwi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1670,7 +1670,7 @@ void pm8001_work_fn(struct work_struct *work)
16701670
} break;
16711671
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
16721672
dev = pm8001_dev->sas_device;
1673-
pm8001_I_T_nexus_reset(dev);
1673+
pm8001_I_T_nexus_event_handler(dev);
16741674
break;
16751675
case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
16761676
dev = pm8001_dev->sas_device;

drivers/scsi/pm8001/pm8001_init.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
838838
if (pm8001_ha->chip_id != chip_8001) {
839839
for (i = 1; i < pm8001_ha->number_of_intr; i++)
840840
PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i);
841+
/* setup thermal configuration. */
842+
pm80xx_set_thermal_config(pm8001_ha);
841843
}
842844

843845
pm8001_init_sas_add(pm8001_ha);

drivers/scsi/pm8001/pm8001_sas.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,72 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)
10181018
return rc;
10191019
}
10201020

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+
}
10211087
/* mandatory SAM-3, the task reset the specified LUN*/
10221088
int pm8001_lu_reset(struct domain_device *dev, u8 *lun)
10231089
{

drivers/scsi/pm8001/pm8001_sas.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,7 @@ int pm8001_dev_found(struct domain_device *dev);
563563
void pm8001_dev_gone(struct domain_device *dev);
564564
int pm8001_lu_reset(struct domain_device *dev, u8 *lun);
565565
int pm8001_I_T_nexus_reset(struct domain_device *dev);
566+
int pm8001_I_T_nexus_event_handler(struct domain_device *dev);
566567
int pm8001_query_task(struct sas_task *task);
567568
void pm8001_open_reject_retry(
568569
struct pm8001_hba_info *pm8001_ha,
@@ -625,6 +626,7 @@ void pm8001_free_task(struct sas_task *task);
625626
void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag);
626627
struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha,
627628
u32 device_id);
629+
int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha);
628630

629631
int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue);
630632

drivers/scsi/pm8001/pm80xx_hwi.c

Lines changed: 135 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
613613
* pm80xx_set_thermal_config - support the thermal configuration
614614
* @pm8001_ha: our hba card information.
615615
*/
616-
static int
616+
int
617617
pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
618618
{
619619
struct set_ctrl_cfg_req payload;
@@ -638,6 +638,86 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
638638

639639
}
640640

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+
641721
/**
642722
* pm80xx_get_encrypt_info - Check for encryption
643723
* @pm8001_ha: our hba card information.
@@ -800,11 +880,8 @@ static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha)
800880
} else
801881
return -EBUSY;
802882

803-
/* configure thermal */
804-
pm80xx_set_thermal_config(pm8001_ha);
805-
806-
PM8001_INIT_DBG(pm8001_ha,
807-
pm8001_printk("Thermal configuration successful!\n"));
883+
/* send SAS protocol timer configuration page to FW */
884+
ret = pm80xx_set_sas_protocol_timer_config(pm8001_ha);
808885

809886
/* Check for encryption */
810887
if (pm8001_ha->chip->encrypt) {
@@ -1269,6 +1346,11 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
12691346
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
12701347
break;
12711348
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:
12721354
PM8001_IO_DBG(pm8001_ha,
12731355
pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
12741356
ts->resp = SAS_TASK_COMPLETE;
@@ -1472,6 +1554,11 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
14721554
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
14731555
break;
14741556
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:
14751562
PM8001_IO_DBG(pm8001_ha,
14761563
pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
14771564
ts->resp = SAS_TASK_COMPLETE;
@@ -1557,6 +1644,13 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
15571644
ts->resp = SAS_TASK_COMPLETE;
15581645
ts->stat = SAS_DATA_OVERRUN;
15591646
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;
15601654
case IO_XFER_CMD_FRAME_ISSUED:
15611655
PM8001_IO_DBG(pm8001_ha,
15621656
pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n"));
@@ -1761,6 +1855,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
17611855
ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
17621856
break;
17631857
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:
17641863
PM8001_IO_DBG(pm8001_ha,
17651864
pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
17661865
ts->resp = SAS_TASK_COMPLETE;
@@ -2051,7 +2150,12 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
20512150
ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
20522151
break;
20532152
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,
20552159
pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
20562160
ts->resp = SAS_TASK_UNDELIVERED;
20572161
ts->stat = SAS_DEV_NO_RESPONSE;
@@ -2154,6 +2258,20 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
21542258
ts->resp = SAS_TASK_COMPLETE;
21552259
ts->stat = SAS_OPEN_TO;
21562260
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;
21572275
default:
21582276
PM8001_IO_DBG(pm8001_ha,
21592277
pm8001_printk("Unknown status 0x%x\n", event));
@@ -2305,6 +2423,11 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
23052423
ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
23062424
break;
23072425
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:
23082431
PM8001_IO_DBG(pm8001_ha,
23092432
pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
23102433
ts->resp = SAS_TASK_COMPLETE;
@@ -2862,6 +2985,9 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
28622985
case HW_EVENT_PORT_RECOVERY_TIMER_TMO:
28632986
PM8001_MSG_DBG(pm8001_ha,
28642987
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);
28652991
sas_phy_disconnected(sas_phy);
28662992
phy->phy_attached = 0;
28672993
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,
34993625
ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_prio << 3);
35003626
ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7);
35013627
memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cdb, 16);
3502-
circularQ = &pm8001_ha->inbnd_q_tbl[inb++];
3503-
3504-
/* rotate the inb queue */
3505-
inb = inb%PM8001_MAX_SPCV_INB_NUM;
3628+
circularQ = &pm8001_ha->inbnd_q_tbl[0];
35063629

35073630
/* Check if encryption is set */
35083631
if (pm8001_ha->chip->encrypt &&
@@ -3603,10 +3726,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
36033726
unsigned long flags;
36043727
u32 opc = OPC_INB_SATA_HOST_OPSTART;
36053728
memset(&sata_cmd, 0, sizeof(sata_cmd));
3606-
circularQ = &pm8001_ha->inbnd_q_tbl[inb++];
3607-
3608-
/* rotate the inb queue */
3609-
inb = inb%PM8001_MAX_SPCV_INB_NUM;
3729+
circularQ = &pm8001_ha->inbnd_q_tbl[0];
36103730

36113731
if (task->data_dir == PCI_DMA_NONE) {
36123732
ATAP = 0x04; /* no data*/

0 commit comments

Comments
 (0)