@@ -956,8 +956,7 @@ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
956
956
957
957
static void hisi_sas_task_done (struct sas_task * task )
958
958
{
959
- if (!del_timer (& task -> slow_task -> timer ))
960
- return ;
959
+ del_timer (& task -> slow_task -> timer );
961
960
complete (& task -> slow_task -> completion );
962
961
}
963
962
@@ -966,13 +965,17 @@ static void hisi_sas_tmf_timedout(struct timer_list *t)
966
965
struct sas_task_slow * slow = from_timer (slow , t , timer );
967
966
struct sas_task * task = slow -> task ;
968
967
unsigned long flags ;
968
+ bool is_completed = true;
969
969
970
970
spin_lock_irqsave (& task -> task_state_lock , flags );
971
- if (!(task -> task_state_flags & SAS_TASK_STATE_DONE ))
971
+ if (!(task -> task_state_flags & SAS_TASK_STATE_DONE )) {
972
972
task -> task_state_flags |= SAS_TASK_STATE_ABORTED ;
973
+ is_completed = false;
974
+ }
973
975
spin_unlock_irqrestore (& task -> task_state_lock , flags );
974
976
975
- complete (& task -> slow_task -> completion );
977
+ if (!is_completed )
978
+ complete (& task -> slow_task -> completion );
976
979
}
977
980
978
981
#define TASK_TIMEOUT 20
@@ -1023,10 +1026,18 @@ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device,
1023
1026
if ((task -> task_state_flags & SAS_TASK_STATE_ABORTED )) {
1024
1027
if (!(task -> task_state_flags & SAS_TASK_STATE_DONE )) {
1025
1028
struct hisi_sas_slot * slot = task -> lldd_task ;
1029
+ struct hisi_sas_cq * cq =
1030
+ & hisi_hba -> cq [slot -> dlvry_queue ];
1026
1031
1027
1032
dev_err (dev , "abort tmf: TMF task timeout and not done\n" );
1028
- if (slot )
1033
+ if (slot ) {
1034
+ /*
1035
+ * flush tasklet to avoid free'ing task
1036
+ * before using task in IO completion
1037
+ */
1038
+ tasklet_kill (& cq -> tasklet );
1029
1039
slot -> task = NULL ;
1040
+ }
1030
1041
1031
1042
goto ex_err ;
1032
1043
} else
@@ -1402,6 +1413,17 @@ static int hisi_sas_abort_task(struct sas_task *task)
1402
1413
1403
1414
spin_lock_irqsave (& task -> task_state_lock , flags );
1404
1415
if (task -> task_state_flags & SAS_TASK_STATE_DONE ) {
1416
+ struct hisi_sas_slot * slot = task -> lldd_task ;
1417
+ struct hisi_sas_cq * cq ;
1418
+
1419
+ if (slot ) {
1420
+ /*
1421
+ * flush tasklet to avoid free'ing task
1422
+ * before using task in IO completion
1423
+ */
1424
+ cq = & hisi_hba -> cq [slot -> dlvry_queue ];
1425
+ tasklet_kill (& cq -> tasklet );
1426
+ }
1405
1427
spin_unlock_irqrestore (& task -> task_state_lock , flags );
1406
1428
rc = TMF_RESP_FUNC_COMPLETE ;
1407
1429
goto out ;
@@ -1457,12 +1479,19 @@ static int hisi_sas_abort_task(struct sas_task *task)
1457
1479
/* SMP */
1458
1480
struct hisi_sas_slot * slot = task -> lldd_task ;
1459
1481
u32 tag = slot -> idx ;
1482
+ struct hisi_sas_cq * cq = & hisi_hba -> cq [slot -> dlvry_queue ];
1460
1483
1461
1484
rc = hisi_sas_internal_task_abort (hisi_hba , device ,
1462
1485
HISI_SAS_INT_ABT_CMD , tag );
1463
1486
if (((rc < 0 ) || (rc == TMF_RESP_FUNC_FAILED )) &&
1464
- task -> lldd_task )
1465
- hisi_sas_do_release_task (hisi_hba , task , slot );
1487
+ task -> lldd_task ) {
1488
+ /*
1489
+ * flush tasklet to avoid free'ing task
1490
+ * before using task in IO completion
1491
+ */
1492
+ tasklet_kill (& cq -> tasklet );
1493
+ slot -> task = NULL ;
1494
+ }
1466
1495
}
1467
1496
1468
1497
out :
@@ -1828,9 +1857,17 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
1828
1857
if ((task -> task_state_flags & SAS_TASK_STATE_ABORTED )) {
1829
1858
if (!(task -> task_state_flags & SAS_TASK_STATE_DONE )) {
1830
1859
struct hisi_sas_slot * slot = task -> lldd_task ;
1831
-
1832
- if (slot )
1860
+ struct hisi_sas_cq * cq =
1861
+ & hisi_hba -> cq [slot -> dlvry_queue ];
1862
+
1863
+ if (slot ) {
1864
+ /*
1865
+ * flush tasklet to avoid free'ing task
1866
+ * before using task in IO completion
1867
+ */
1868
+ tasklet_kill (& cq -> tasklet );
1833
1869
slot -> task = NULL ;
1870
+ }
1834
1871
dev_err (dev , "internal task abort: timeout and not done.\n" );
1835
1872
res = - EIO ;
1836
1873
goto exit ;
0 commit comments