struct device *dev = hisi_hba->dev;
        struct hisi_sas_dq *dq = NULL;
 
-       if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags)))
-               return -EINVAL;
+       if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) {
+               if (in_softirq())
+                       return -EINVAL;
+
+               down(&hisi_hba->sem);
+               up(&hisi_hba->sem);
+       }
 
        /* protect task_prep and start_delivery sequence */
        rc = hisi_sas_task_prep(task, &dq, is_tmf, tmf, &pass);
                clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
                up(&hisi_hba->sem);
                scsi_unblock_requests(shost);
-               goto out;
+               clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags);
+               return rc;
        }
 
-       clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
-
        /* Init and wait for PHYs to come up and all libsas event finished. */
        hisi_hba->hw->phys_init(hisi_hba);
        msleep(1000);
        hisi_sas_refresh_port_id(hisi_hba);
+       clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
        up(&hisi_hba->sem);
 
        if (hisi_hba->reject_stp_links_msk)
                hisi_sas_terminate_stp_reject(hisi_hba);
        hisi_sas_reset_init_all_devices(hisi_hba);
        scsi_unblock_requests(shost);
+       clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags);
 
        state = hisi_hba->hw->get_phys_state(hisi_hba);
        hisi_sas_rescan_topology(hisi_hba, old_state, state);
        dev_info(dev, "controller reset complete\n");
 
-out:
-       clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags);
-
-       return rc;
+       return 0;
 }
 
 static int hisi_sas_abort_task(struct sas_task *task)
 
                return -ENODEV;
        }
 
-       set_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags);
+       if (test_and_set_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags))
+               return -1;
+
        scsi_block_requests(shost);
        set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
        flush_workqueue(hisi_hba->wq);