diff mbox series

[26/31] scsi: libsas,hisi_sas,mvsas,pm8001: Allocate Scsi_cmd for slow task

Message ID 20210222132405.91369-27-hare@suse.de
State New
Headers show
Series scsi: enable reserved commands for LLDDs | expand

Commit Message

Hannes Reinecke Feb. 22, 2021, 1:24 p.m. UTC
From: John Garry <john.garry@huawei.com>


Allocate a Scsi_cmd for SAS slow tasks, so they can be accounted for in
the blk-mq layer.

Signed-off-by: John Garry <john.garry@huawei.com>

Signed-off-by: Hannes Reinecke <hare@suse.de>

---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 56 ++++++++++++++++--------
 drivers/scsi/libsas/sas_expander.c    |  7 ++-
 drivers/scsi/libsas/sas_init.c        | 61 ++++++++++++++++++++++++---
 drivers/scsi/mvsas/mv_sas.c           |  5 ++-
 drivers/scsi/pm8001/pm8001_hwi.c      |  9 +++-
 drivers/scsi/pm8001/pm8001_sas.c      | 39 +++++++++++------
 drivers/scsi/pm8001/pm80xx_hwi.c      |  9 +++-
 include/scsi/libsas.h                 |  8 +++-
 8 files changed, 148 insertions(+), 46 deletions(-)

-- 
2.29.2

Comments

luojiaxing March 9, 2021, 11:22 a.m. UTC | #1
Hi, Hannes, john


I found some tiny coding issues of this patch. check below.

And if someone else have already point out, please ignore.


On 2021/2/22 21:24, Hannes Reinecke wrote:
> From: John Garry <john.garry@huawei.com>

>

> Allocate a Scsi_cmd for SAS slow tasks, so they can be accounted for in

> the blk-mq layer.

>

> Signed-off-by: John Garry <john.garry@huawei.com>

> Signed-off-by: Hannes Reinecke <hare@suse.de>

> ---

>   drivers/scsi/hisi_sas/hisi_sas_main.c | 56 ++++++++++++++++--------

>   drivers/scsi/libsas/sas_expander.c    |  7 ++-

>   drivers/scsi/libsas/sas_init.c        | 61 ++++++++++++++++++++++++---

>   drivers/scsi/mvsas/mv_sas.c           |  5 ++-

>   drivers/scsi/pm8001/pm8001_hwi.c      |  9 +++-

>   drivers/scsi/pm8001/pm8001_sas.c      | 39 +++++++++++------

>   drivers/scsi/pm8001/pm80xx_hwi.c      |  9 +++-

>   include/scsi/libsas.h                 |  8 +++-

>   8 files changed, 148 insertions(+), 46 deletions(-)

>

> diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c

> index a979edfd9a78..6a69a90a1b82 100644

> --- a/drivers/scsi/hisi_sas/hisi_sas_main.c

> +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c

> @@ -15,6 +15,7 @@ static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device,

>   static int

>   hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,

>   			     struct domain_device *device,

> +			     struct scsi_lun *lun,

>   			     int abort_flag, int tag);

>   static int hisi_sas_softreset_ata_disk(struct domain_device *device);

>   static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,

> @@ -1055,15 +1056,17 @@ static void hisi_sas_dev_gone(struct domain_device *device)

>   	struct hisi_sas_device *sas_dev = device->lldd_dev;

>   	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);

>   	struct device *dev = hisi_hba->dev;

> +	struct scsi_lun lun;

>   	int ret = 0;

>   

>   	dev_info(dev, "dev[%d:%x] is gone\n",

>   		 sas_dev->device_id, sas_dev->dev_type);

>   

>   	down(&hisi_hba->sem);

> +	int_to_scsilun(0, &lun);

>   	if (!test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) {

>   		hisi_sas_internal_task_abort(hisi_hba, device,

> -					     HISI_SAS_INT_ABT_DEV, 0);

> +				&lun, HISI_SAS_INT_ABT_DEV, 0);

>   

>   		hisi_sas_dereg_device(hisi_hba, device);

>   

> @@ -1191,12 +1194,21 @@ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device,

>   {

>   	struct hisi_sas_device *sas_dev = device->lldd_dev;

>   	struct hisi_hba *hisi_hba = sas_dev->hisi_hba;

> +	struct sas_ha_struct *sha = &hisi_hba->sha;

>   	struct device *dev = hisi_hba->dev;

>   	struct sas_task *task;

>   	int res, retry;

>   

>   	for (retry = 0; retry < TASK_RETRY; retry++) {

> -		task = sas_alloc_slow_task(GFP_KERNEL);

> +		struct scsilun lun;



This should be "struct scsi_lun lun"


> +

> +		int_to_scsilun(0, &lun);

> +		if (!dev_is_sata) {



should be " if (!dev_is_sata(device)) "


> +			struct sas_ssp_task ssp_task = parameter;



And I think it should be

const struct sas_ssp_task *ssp_task = parameter;


> +

> +			memcpy(lun.scsi_lun, ssp_task.LUN, 8);



  memcpy(lun.scsi_lun, ssp_task->LUN, 8);


> +		}

> +		task = sas_alloc_slow_task(sha, device, &lun, GFP_KERNEL);

>   		if (!task)

>   			return -ENOMEM;

>   

> @@ -1494,7 +1506,9 @@ static void hisi_sas_terminate_stp_reject(struct hisi_hba *hisi_hba)

>   {

>   	struct device *dev = hisi_hba->dev;

>   	int port_no, rc, i;

> +	struct scsi_lun lun;

>   

> +	int_to_scsilun(0, &lun);

>   	for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {

>   		struct hisi_sas_device *sas_dev = &hisi_hba->devices[i];

>   		struct domain_device *device = sas_dev->sas_device;

> @@ -1503,7 +1517,7 @@ static void hisi_sas_terminate_stp_reject(struct hisi_hba *hisi_hba)

>   			continue;

>   

>   		rc = hisi_sas_internal_task_abort(hisi_hba, device,

> -						  HISI_SAS_INT_ABT_DEV, 0);

> +				&lun, HISI_SAS_INT_ABT_DEV, 0);

>   		if (rc < 0)

>   			dev_err(dev, "STP reject: abort dev failed %d\n", rc);

>   	}

> @@ -1653,7 +1667,7 @@ static int hisi_sas_abort_task(struct sas_task *task)

>   						  &tmf_task);

>   

>   		rc2 = hisi_sas_internal_task_abort(hisi_hba, device,

> -						   HISI_SAS_INT_ABT_CMD, tag);

> +				&lun, HISI_SAS_INT_ABT_CMD, tag);

>   		if (rc2 < 0) {

>   			dev_err(dev, "abort task: internal abort (%d)\n", rc2);

>   			return TMF_RESP_FUNC_FAILED;

> @@ -1673,9 +1687,9 @@ static int hisi_sas_abort_task(struct sas_task *task)

>   	} else if (task->task_proto & SAS_PROTOCOL_SATA ||

>   		task->task_proto & SAS_PROTOCOL_STP) {

>   		if (task->dev->dev_type == SAS_SATA_DEV) {

> +			int_to_scsilun(0, &lun);

>   			rc = hisi_sas_internal_task_abort(hisi_hba, device,

> -							  HISI_SAS_INT_ABT_DEV,

> -							  0);

> +					&lun, HISI_SAS_INT_ABT_DEV, 0);

>   			if (rc < 0) {

>   				dev_err(dev, "abort task: internal abort failed\n");

>   				goto out;

> @@ -1689,8 +1703,9 @@ static int hisi_sas_abort_task(struct sas_task *task)

>   		u32 tag = slot->idx;

>   		struct hisi_sas_cq *cq = &hisi_hba->cq[slot->dlvry_queue];

>   

> +		int_to_scsilun(0, &lun);

>   		rc = hisi_sas_internal_task_abort(hisi_hba, device,

> -						  HISI_SAS_INT_ABT_CMD, tag);

> +				&lun, HISI_SAS_INT_ABT_CMD, tag);

>   		if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) &&

>   					task->lldd_task) {

>   			/*

> @@ -1716,7 +1731,7 @@ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun)

>   	int rc;

>   

>   	rc = hisi_sas_internal_task_abort(hisi_hba, device,

> -					  HISI_SAS_INT_ABT_DEV, 0);

> +			(struct scsi_lun *)lun, HISI_SAS_INT_ABT_DEV, 0);

>   	if (rc < 0) {

>   		dev_err(dev, "abort task set: internal abort rc=%d\n", rc);

>   		return TMF_RESP_FUNC_FAILED;

> @@ -1804,10 +1819,12 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)

>   {

>   	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);

>   	struct device *dev = hisi_hba->dev;

> +	struct scsi_lun lun;

>   	int rc;

>   

> +	int_to_scsilun(0, &lun);

>   	rc = hisi_sas_internal_task_abort(hisi_hba, device,

> -					  HISI_SAS_INT_ABT_DEV, 0);

> +			&lun, HISI_SAS_INT_ABT_DEV, 0);

>   	if (rc < 0) {

>   		dev_err(dev, "I_T nexus reset: internal abort (%d)\n", rc);

>   		return TMF_RESP_FUNC_FAILED;

> @@ -1837,7 +1854,7 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)

>   

>   	/* Clear internal IO and then lu reset */

>   	rc = hisi_sas_internal_task_abort(hisi_hba, device,

> -					  HISI_SAS_INT_ABT_DEV, 0);

> +			(struct scsi_lun *)lun, HISI_SAS_INT_ABT_DEV, 0);

>   	if (rc < 0) {

>   		dev_err(dev, "lu_reset: internal abort failed\n");

>   		goto out;

> @@ -2018,6 +2035,7 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,

>    * abort command for single IO command or a device

>    * @hisi_hba: host controller struct

>    * @device: domain device

> + * @lun: logical unit number

>    * @abort_flag: mode of operation, device or single IO

>    * @tag: tag of IO to be aborted (only relevant to single

>    *       IO mode)

> @@ -2025,12 +2043,15 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,

>    */

>   static int

>   _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,

> -			      struct domain_device *device, int abort_flag,

> -			      int tag, struct hisi_sas_dq *dq)

> +			      struct domain_device *device,

> +			      struct scsi_lun *lun,

> +			      int abort_flag, int tag,

> +			      struct hisi_sas_dq *dq)

>   {

> -	struct sas_task *task;

>   	struct hisi_sas_device *sas_dev = device->lldd_dev;

> +	struct sas_ha_struct *sha = &hisi_hba->sha;

>   	struct device *dev = hisi_hba->dev;

> +	struct sas_task *task;

>   	int res;

>   

>   	/*

> @@ -2042,7 +2063,8 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,

>   	if (!hisi_hba->hw->prep_abort)

>   		return TMF_RESP_FUNC_FAILED;

>   

> -	task = sas_alloc_slow_task(GFP_KERNEL);

> +	task = sas_alloc_slow_task(sha, device,

> +				   (struct scsi_lun *)lun, GFP_KERNEL);

>   	if (!task)

>   		return -ENOMEM;

>   

> @@ -2115,6 +2137,7 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,

>   static int

>   hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,

>   			     struct domain_device *device,

> +			     struct scsi_lun *lun,

>   			     int abort_flag, int tag)

>   {

>   	struct hisi_sas_slot *slot;

> @@ -2127,7 +2150,7 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,

>   		slot = &hisi_hba->slot_info[tag];

>   		dq = &hisi_hba->dq[slot->dlvry_queue];

>   		return _hisi_sas_internal_task_abort(hisi_hba, device,

> -						     abort_flag, tag, dq);

> +				lun, abort_flag, tag, dq);

>   	case HISI_SAS_INT_ABT_DEV:

>   		for (i = 0; i < hisi_hba->cq_nvecs; i++) {

>   			struct hisi_sas_cq *cq = &hisi_hba->cq[i];

> @@ -2137,8 +2160,7 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,

>   				continue;

>   			dq = &hisi_hba->dq[i];

>   			rc = _hisi_sas_internal_task_abort(hisi_hba, device,

> -							   abort_flag, tag,

> -							   dq);

> +					lun, abort_flag, tag, dq);

>   			if (rc)

>   				return rc;

>   		}

> diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c

> index 8d6bcc19359f..9e4a7c85a037 100644

> --- a/drivers/scsi/libsas/sas_expander.c

> +++ b/drivers/scsi/libsas/sas_expander.c

> @@ -56,9 +56,12 @@ static int smp_execute_task_sg(struct domain_device *dev,

>   {

>   	int res, retry;

>   	struct sas_task *task = NULL;

> +	struct sas_ha_struct *ha = dev->port->ha;

>   	struct sas_internal *i =

> -		to_sas_internal(dev->port->ha->core.shost->transportt);

> +		to_sas_internal(ha->core.shost->transportt);

> +	struct scsi_lun lun;

>   

> +	int_to_scsilun(0, &lun);

>   	mutex_lock(&dev->ex_dev.cmd_mutex);

>   	for (retry = 0; retry < 3; retry++) {

>   		if (test_bit(SAS_DEV_GONE, &dev->state)) {

> @@ -66,7 +69,7 @@ static int smp_execute_task_sg(struct domain_device *dev,

>   			break;

>   		}

>   

> -		task = sas_alloc_slow_task(GFP_KERNEL);

> +		task = sas_alloc_slow_task(ha, dev, &lun, GFP_KERNEL);

>   		if (!task) {

>   			res = -ENOMEM;

>   			break;

> diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c

> index 2b0f98ca6ec3..9d0448b76a2f 100644

> --- a/drivers/scsi/libsas/sas_init.c

> +++ b/drivers/scsi/libsas/sas_init.c

> @@ -14,6 +14,7 @@

>   #include <scsi/sas_ata.h>

>   #include <scsi/scsi_host.h>

>   #include <scsi/scsi_device.h>

> +#include <scsi/scsi_tcq.h>

>   #include <scsi/scsi_transport.h>

>   #include <scsi/scsi_transport_sas.h>

>   

> @@ -37,16 +38,36 @@ struct sas_task *sas_alloc_task(gfp_t flags)

>   }

>   EXPORT_SYMBOL_GPL(sas_alloc_task);

>   

> -struct sas_task *sas_alloc_slow_task(gfp_t flags)

> +struct sas_task *sas_alloc_slow_task(struct sas_ha_struct *ha,

> +				     struct domain_device *dev,

> +				     struct scsi_lun *lun, gfp_t flags)

>   {

>   	struct sas_task *task = sas_alloc_task(flags);

> -	struct sas_task_slow *slow = kmalloc(sizeof(*slow), flags);

> +	struct Scsi_Host *shost = ha->core.shost;

> +	struct sas_task_slow *slow;

>   

> -	if (!task || !slow) {

> -		if (task)

> -			kmem_cache_free(sas_task_cache, task);

> -		kfree(slow);

> +	if (!task)

>   		return NULL;

> +

> +	slow = kzalloc(sizeof(*slow), flags);

> +	if (!slow)

> +		goto out_err_slow;

> +

> +	if (shost->nr_reserved_cmds) {

> +		struct scsi_device *sdev;

> +

> +		if (dev && dev->starget) {

> +			sdev = scsi_device_lookup_by_target(dev->starget,

> +						    scsilun_to_int(lun));

> +			if (!sdev)

> +				goto out_err_scmd;

> +		} else

> +			sdev = ha->core.shost_dev;

> +		slow->scmd = scsi_get_internal_cmd(sdev, DMA_BIDIRECTIONAL,

> +						   REQ_NOWAIT);

> +		if (!slow->scmd)

> +			goto out_err_scmd;

> +		ASSIGN_SAS_TASK(slow->scmd, task);

>   	}

>   

>   	task->slow_task = slow;

> @@ -55,13 +76,31 @@ struct sas_task *sas_alloc_slow_task(gfp_t flags)

>   	init_completion(&slow->completion);

>   

>   	return task;

> +

> +out_err_scmd:

> +	kfree(slow);

> +out_err_slow:

> +	kmem_cache_free(sas_task_cache, task);

> +	return NULL;

>   }

>   EXPORT_SYMBOL_GPL(sas_alloc_slow_task);

>   

>   void sas_free_task(struct sas_task *task)

>   {

>   	if (task) {

> -		kfree(task->slow_task);

> +		/*

> +		 * It could be good to just introduce separate sas_free_slow_task() to

> +		 * avoid the following in the fastpath.

> +		 */

> +		if (task->slow_task) {

> +			struct scsi_cmnd *scmd = task->slow_task->scmd;

> +

> +			if (scmd) {

> +				ASSIGN_SAS_TASK(scmd, NULL);

> +				scsi_put_internal_cmd(scmd);

> +			}

> +			kfree(task->slow_task);

> +		}

>   		kmem_cache_free(sas_task_cache, task);

>   	}

>   }

> @@ -95,6 +134,7 @@ void sas_hash_addr(u8 *hashed, const u8 *sas_addr)

>   

>   int sas_register_ha(struct sas_ha_struct *sas_ha)

>   {

> +	struct Scsi_Host *shost = sas_ha->core.shost;

>   	char name[64];

>   	int error = 0;

>   

> @@ -111,6 +151,13 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)

>   

>   	sas_ha->event_thres = SAS_PHY_SHUTDOWN_THRES;

>   

> +	if (shost->nr_reserved_cmds) {

> +		sas_ha->core.shost_dev = scsi_get_host_dev(shost);

> +		if (!sas_ha->core.shost_dev) {

> +			pr_notice("couldn't register sas host device\n");

> +			return -ENOMEM;

> +		}

> +	}

>   	error = sas_register_phys(sas_ha);

>   	if (error) {

>   		pr_notice("couldn't register sas phys:%d\n", error);

> diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c

> index 543b435f4c8c..99bdb88b3e86 100644

> --- a/drivers/scsi/mvsas/mv_sas.c

> +++ b/drivers/scsi/mvsas/mv_sas.c

> @@ -1278,13 +1278,16 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,

>   				      u8 *lun, struct mvs_tmf_task *tmf)

>   {

>   	int res, retry;

> +	struct sas_ha_struct *ha = dev->port->ha;

>   	struct sas_task *task = NULL;

> +	struct scsi_lun scsilun;

>   

>   	if (!(dev->tproto & SAS_PROTOCOL_SSP))

>   		return TMF_RESP_FUNC_ESUPP;

>   

> +	memcpy(scsilun.scsi_lun, lun, 8);

>   	for (retry = 0; retry < 3; retry++) {

> -		task = sas_alloc_slow_task(GFP_KERNEL);

> +		task = sas_alloc_slow_task(ha, dev, &scsilun, GFP_KERNEL);

>   		if (!task)

>   			return -ENOMEM;

>   

> diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c

> index 3998fcd69acb..105962b0c815 100644

> --- a/drivers/scsi/pm8001/pm8001_hwi.c

> +++ b/drivers/scsi/pm8001/pm8001_hwi.c

> @@ -1701,6 +1701,7 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,

>   	struct task_abort_req task_abort;

>   	struct inbound_queue_table *circularQ;

>   	u32 opc = OPC_INB_SATA_ABORT;

> +	struct scsi_lun lun;

>   	int ret;

>   

>   	if (!pm8001_ha_dev) {

> @@ -1708,7 +1709,9 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,

>   		return;

>   	}

>   

> -	task = sas_alloc_slow_task(GFP_ATOMIC);

> +	int_to_scsilun(0, &lun);

> +	task = sas_alloc_slow_task(pm8001_ha->sas, pm8001_ha_dev->sas_device,

> +				   &lun, GFP_ATOMIC);

>   

>   	if (!task) {

>   		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task\n");

> @@ -1752,8 +1755,10 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,

>   	struct domain_device *dev = pm8001_ha_dev->sas_device;

>   	struct inbound_queue_table *circularQ;

>   	u32 opc = OPC_INB_SATA_HOST_OPSTART;

> +	struct scsi_lun lun;;

>   

> -	task = sas_alloc_slow_task(GFP_ATOMIC);

> +	int_to_scsilun(0, &lun);

> +	task = sas_alloc_slow_task(pm8001_ha->sas, dev, &lun, GFP_ATOMIC);

>   

>   	if (!task) {

>   		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task !!!\n");

> diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c

> index 01e91347eb41..b1f12d671611 100644

> --- a/drivers/scsi/pm8001/pm8001_sas.c

> +++ b/drivers/scsi/pm8001/pm8001_sas.c

> @@ -717,7 +717,9 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,

>   		return TMF_RESP_FUNC_ESUPP;

>   

>   	for (retry = 0; retry < 3; retry++) {

> -		task = sas_alloc_slow_task(GFP_KERNEL);

> +		task = sas_alloc_slow_task(pm8001_ha->sas,

> +					   pm8001_dev->sas_device,

> +					   (struct scsi_lun *)lun, GFP_KERNEL);

>   		if (!task)

>   			return -ENOMEM;

>   

> @@ -791,7 +793,7 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,

>   

>   static int

>   pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,

> -	struct pm8001_device *pm8001_dev, u32 flag,

> +	struct pm8001_device *pm8001_dev, u8 *lun, u32 flag,

>   	u32 task_tag)

>   {

>   	struct domain_device *dev = pm8001_dev->sas_device;

> @@ -801,7 +803,8 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,

>   	struct sas_task *task = NULL;

>   

>   	for (retry = 0; retry < 3; retry++) {

> -		task = sas_alloc_slow_task(GFP_KERNEL);

> +		task = sas_alloc_slow_task(pm8001_ha->sas, dev,

> +					   (struct scsi_lun *)lun, GFP_KERNEL);

>   		if (!task)

>   			return -ENOMEM;

>   

> @@ -875,13 +878,15 @@ static void pm8001_dev_gone_notify(struct domain_device *dev)

>   	spin_lock_irqsave(&pm8001_ha->lock, flags);

>   	if (pm8001_dev) {

>   		u32 device_id = pm8001_dev->device_id;

> +		struct scsi_lun lun;

>   

> +		int_to_scsilun(0, &lun);

>   		pm8001_dbg(pm8001_ha, DISC, "found dev[%d:%x] is gone.\n",

>   			   pm8001_dev->device_id, pm8001_dev->dev_type);

>   		if (atomic_read(&pm8001_dev->running_req)) {

>   			spin_unlock_irqrestore(&pm8001_ha->lock, flags);

>   			pm8001_exec_internal_task_abort(pm8001_ha,

> -				pm8001_dev, 1, 0);

> +				pm8001_dev, lun.scsi_lun, 1, 0);

>   			while (atomic_read(&pm8001_dev->running_req))

>   				msleep(20);

>   			spin_lock_irqsave(&pm8001_ha->lock, flags);

> @@ -991,6 +996,9 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)

>   	phy = sas_get_local_phy(dev);

>   

>   	if (dev_is_sata(dev)) {

> +		struct scsi_lun lun;

> +

> +		int_to_scsilun(0, &lun);

>   		if (scsi_is_sas_phy_local(phy)) {

>   			rc = 0;

>   			goto out;

> @@ -1005,7 +1013,7 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)

>   		}

>   		msleep(2000);

>   		rc = pm8001_exec_internal_task_abort(pm8001_ha,

> -			pm8001_dev, 1, 0);

> +			pm8001_dev, lun.scsi_lun, 1, 0);

>   		if (rc) {

>   			pm8001_dbg(pm8001_ha, EH, "task abort failed %x\n"

>   				   "with rc %d\n", pm8001_dev->device_id, rc);

> @@ -1032,7 +1040,9 @@ int pm8001_I_T_nexus_event_handler(struct domain_device *dev)

>   	struct pm8001_device *pm8001_dev;

>   	struct pm8001_hba_info *pm8001_ha;

>   	struct sas_phy *phy;

> +	struct scsi_lun lun;

>   

> +	int_to_scsilun(0, &lun);

>   	if (!dev || !dev->lldd_dev)

>   		return -1;

>   

> @@ -1051,7 +1061,7 @@ int pm8001_I_T_nexus_event_handler(struct domain_device *dev)

>   		}

>   		/* send internal ssp/sata/smp abort command to FW */

>   		rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,

> -						     1, 0);

> +						     lun.scsi_lun, 1, 0);

>   		msleep(100);

>   

>   		/* deregister the target device */

> @@ -1067,7 +1077,7 @@ int pm8001_I_T_nexus_event_handler(struct domain_device *dev)

>   	} else {

>   		/* send internal ssp/sata/smp abort command to FW */

>   		rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,

> -						     1, 0);

> +						     lun.scsi_lun, 1, 0);

>   		msleep(100);

>   

>   		/* deregister the target device */

> @@ -1095,8 +1105,8 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun)

>   	DECLARE_COMPLETION_ONSTACK(completion_setstate);

>   	if (dev_is_sata(dev)) {

>   		struct sas_phy *phy = sas_get_local_phy(dev);

> -		rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,

> -			1, 0);

> +		rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,

> +			lun, 1, 0);

>   		rc = sas_phy_reset(phy, 1);

>   		sas_put_local_phy(phy);

>   		pm8001_dev->setds_completion = &completion_setstate;

> @@ -1211,9 +1221,10 @@ int pm8001_abort_task(struct sas_task *task)

>   						   &tmf_task);

>   		if (rc == TMF_RESP_FUNC_SUCC)

>   			pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,

> -				0, tag);

> +				lun.scsi_lun, 0, tag);

>   	} else if (task->task_proto & SAS_PROTOCOL_SATA ||

>   		task->task_proto & SAS_PROTOCOL_STP) {

> +		memset(lun.scsi_lun, 0, sizeof(lun.scsi_lun));

>   		if (pm8001_ha->chip_id == chip_8006) {

>   			DECLARE_COMPLETION_ONSTACK(completion_reset);

>   			DECLARE_COMPLETION_ONSTACK(completion);

> @@ -1280,7 +1291,7 @@ int pm8001_abort_task(struct sas_task *task)

>   			 * going to free the task.

>   			 */

>   			ret = pm8001_exec_internal_task_abort(pm8001_ha,

> -				pm8001_dev, 1, tag);

> +				pm8001_dev, lun.scsi_lun, 1, tag);

>   			if (ret)

>   				goto out;

>   			ret = wait_for_completion_timeout(

> @@ -1297,13 +1308,15 @@ int pm8001_abort_task(struct sas_task *task)

>   			wait_for_completion(&completion);

>   		} else {

>   			rc = pm8001_exec_internal_task_abort(pm8001_ha,

> -				pm8001_dev, 0, tag);

> +				pm8001_dev, lun.scsi_lun, 0, tag);

>   		}

>   		rc = TMF_RESP_FUNC_COMPLETE;

>   	} else if (task->task_proto & SAS_PROTOCOL_SMP) {

>   		/* SMP */

> +

> +		int_to_scsilun(0, &lun);

>   		rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,

> -			0, tag);

> +			lun.scsi_lun, 0, tag);

>   

>   	}

>   out:

> diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c

> index bc1929b230c4..03bfb4d72895 100644

> --- a/drivers/scsi/pm8001/pm80xx_hwi.c

> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c

> @@ -1772,6 +1772,7 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,

>   	struct task_abort_req task_abort;

>   	struct inbound_queue_table *circularQ;

>   	u32 opc = OPC_INB_SATA_ABORT;

> +	struct scsi_lun lun;

>   	int ret;

>   

>   	if (!pm8001_ha_dev) {

> @@ -1779,7 +1780,9 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,

>   		return;

>   	}

>   

> -	task = sas_alloc_slow_task(GFP_ATOMIC);

> +	int_to_scsilun(0, &lun);

> +	task = sas_alloc_slow_task(pm8001_ha->sas,pm8001_ha_dev->sas_device,

> +				   &lun, GFP_ATOMIC);

>   

>   	if (!task) {

>   		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task\n");

> @@ -1827,8 +1830,10 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,

>   	struct domain_device *dev = pm8001_ha_dev->sas_device;

>   	struct inbound_queue_table *circularQ;

>   	u32 opc = OPC_INB_SATA_HOST_OPSTART;

> +	struct scsi_lun lun;

>   

> -	task = sas_alloc_slow_task(GFP_ATOMIC);

> +	int_to_scsilun(0, &lun);

> +	task = sas_alloc_slow_task(pm8001_ha->sas, dev, &lun, GFP_ATOMIC);

>   

>   	if (!task) {

>   		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task !!!\n");

> diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h

> index 3a024eced38c..9b8c06a8329a 100644

> --- a/include/scsi/libsas.h

> +++ b/include/scsi/libsas.h

> @@ -349,7 +349,7 @@ struct asd_sas_phy {

>   

>   struct scsi_core {

>   	struct Scsi_Host *shost;

> -

> +	struct scsi_device *shost_dev;

>   };

>   

>   enum sas_ha_state {

> @@ -605,6 +605,7 @@ struct sas_task_slow {

>   	struct timer_list     timer;

>   	struct completion     completion;

>   	struct sas_task       *task;

> +	struct scsi_cmnd      *scmd;

>   };

>   

>   #define SAS_TASK_STATE_PENDING      1

> @@ -614,7 +615,10 @@ struct sas_task_slow {

>   #define SAS_TASK_AT_INITIATOR       16

>   

>   extern struct sas_task *sas_alloc_task(gfp_t flags);

> -extern struct sas_task *sas_alloc_slow_task(gfp_t flags);

> +extern struct sas_task *sas_alloc_slow_task(struct sas_ha_struct *ha,

> +					    struct domain_device *dev,

> +					    struct scsi_lun *lun,

> +					    gfp_t flags);

>   extern void sas_free_task(struct sas_task *task);

>   

>   struct sas_domain_function_template {
John Garry March 9, 2021, 2:05 p.m. UTC | #2
On 09/03/2021 11:22, luojiaxing wrote:
> Hi, Hannes, john

> 

> 

> I found some tiny coding issues of this patch. check below.

> 

> And if someone else have already point out, please ignore.

> 


JFYI, I have put the patches on this following branch, and fixed up to 
get building+working:
https://github.com/hisilicon/kernel-dev/commits/private-topic-sas-5.11-resv7

Thanks,
John

> 

> On 2021/2/22 21:24, Hannes Reinecke wrote:

>> From: John Garry <john.garry@huawei.com>
luojiaxing March 11, 2021, 8:51 a.m. UTC | #3
On 2021/3/9 22:05, John Garry wrote:
> On 09/03/2021 11:22, luojiaxing wrote:

>> Hi, Hannes, john

>>

>>

>> I found some tiny coding issues of this patch. check below.

>>

>> And if someone else have already point out, please ignore.

>>

>

> JFYI, I have put the patches on this following branch, and fixed up to 

> get building+working:

> https://github.com/hisilicon/kernel-dev/commits/private-topic-sas-5.11-resv7 

>



Thanks,  I will run some full test on it later. If other issue is found, 
we discuss then


Jiaxing


>

> Thanks,

> John

>

>>

>> On 2021/2/22 21:24, Hannes Reinecke wrote:

>>> From: John Garry <john.garry@huawei.com>

>

>

> .

>
diff mbox series

Patch

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index a979edfd9a78..6a69a90a1b82 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -15,6 +15,7 @@  static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device,
 static int
 hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
 			     struct domain_device *device,
+			     struct scsi_lun *lun,
 			     int abort_flag, int tag);
 static int hisi_sas_softreset_ata_disk(struct domain_device *device);
 static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
@@ -1055,15 +1056,17 @@  static void hisi_sas_dev_gone(struct domain_device *device)
 	struct hisi_sas_device *sas_dev = device->lldd_dev;
 	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
 	struct device *dev = hisi_hba->dev;
+	struct scsi_lun lun;
 	int ret = 0;
 
 	dev_info(dev, "dev[%d:%x] is gone\n",
 		 sas_dev->device_id, sas_dev->dev_type);
 
 	down(&hisi_hba->sem);
+	int_to_scsilun(0, &lun);
 	if (!test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) {
 		hisi_sas_internal_task_abort(hisi_hba, device,
-					     HISI_SAS_INT_ABT_DEV, 0);
+				&lun, HISI_SAS_INT_ABT_DEV, 0);
 
 		hisi_sas_dereg_device(hisi_hba, device);
 
@@ -1191,12 +1194,21 @@  static int hisi_sas_exec_internal_tmf_task(struct domain_device *device,
 {
 	struct hisi_sas_device *sas_dev = device->lldd_dev;
 	struct hisi_hba *hisi_hba = sas_dev->hisi_hba;
+	struct sas_ha_struct *sha = &hisi_hba->sha;
 	struct device *dev = hisi_hba->dev;
 	struct sas_task *task;
 	int res, retry;
 
 	for (retry = 0; retry < TASK_RETRY; retry++) {
-		task = sas_alloc_slow_task(GFP_KERNEL);
+		struct scsilun lun;
+
+		int_to_scsilun(0, &lun);
+		if (!dev_is_sata) {
+			struct sas_ssp_task ssp_task = parameter;
+
+			memcpy(lun.scsi_lun, ssp_task.LUN, 8);
+		}
+		task = sas_alloc_slow_task(sha, device, &lun, GFP_KERNEL);
 		if (!task)
 			return -ENOMEM;
 
@@ -1494,7 +1506,9 @@  static void hisi_sas_terminate_stp_reject(struct hisi_hba *hisi_hba)
 {
 	struct device *dev = hisi_hba->dev;
 	int port_no, rc, i;
+	struct scsi_lun lun;
 
+	int_to_scsilun(0, &lun);
 	for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
 		struct hisi_sas_device *sas_dev = &hisi_hba->devices[i];
 		struct domain_device *device = sas_dev->sas_device;
@@ -1503,7 +1517,7 @@  static void hisi_sas_terminate_stp_reject(struct hisi_hba *hisi_hba)
 			continue;
 
 		rc = hisi_sas_internal_task_abort(hisi_hba, device,
-						  HISI_SAS_INT_ABT_DEV, 0);
+				&lun, HISI_SAS_INT_ABT_DEV, 0);
 		if (rc < 0)
 			dev_err(dev, "STP reject: abort dev failed %d\n", rc);
 	}
@@ -1653,7 +1667,7 @@  static int hisi_sas_abort_task(struct sas_task *task)
 						  &tmf_task);
 
 		rc2 = hisi_sas_internal_task_abort(hisi_hba, device,
-						   HISI_SAS_INT_ABT_CMD, tag);
+				&lun, HISI_SAS_INT_ABT_CMD, tag);
 		if (rc2 < 0) {
 			dev_err(dev, "abort task: internal abort (%d)\n", rc2);
 			return TMF_RESP_FUNC_FAILED;
@@ -1673,9 +1687,9 @@  static int hisi_sas_abort_task(struct sas_task *task)
 	} else if (task->task_proto & SAS_PROTOCOL_SATA ||
 		task->task_proto & SAS_PROTOCOL_STP) {
 		if (task->dev->dev_type == SAS_SATA_DEV) {
+			int_to_scsilun(0, &lun);
 			rc = hisi_sas_internal_task_abort(hisi_hba, device,
-							  HISI_SAS_INT_ABT_DEV,
-							  0);
+					&lun, HISI_SAS_INT_ABT_DEV, 0);
 			if (rc < 0) {
 				dev_err(dev, "abort task: internal abort failed\n");
 				goto out;
@@ -1689,8 +1703,9 @@  static int hisi_sas_abort_task(struct sas_task *task)
 		u32 tag = slot->idx;
 		struct hisi_sas_cq *cq = &hisi_hba->cq[slot->dlvry_queue];
 
+		int_to_scsilun(0, &lun);
 		rc = hisi_sas_internal_task_abort(hisi_hba, device,
-						  HISI_SAS_INT_ABT_CMD, tag);
+				&lun, HISI_SAS_INT_ABT_CMD, tag);
 		if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) &&
 					task->lldd_task) {
 			/*
@@ -1716,7 +1731,7 @@  static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun)
 	int rc;
 
 	rc = hisi_sas_internal_task_abort(hisi_hba, device,
-					  HISI_SAS_INT_ABT_DEV, 0);
+			(struct scsi_lun *)lun, HISI_SAS_INT_ABT_DEV, 0);
 	if (rc < 0) {
 		dev_err(dev, "abort task set: internal abort rc=%d\n", rc);
 		return TMF_RESP_FUNC_FAILED;
@@ -1804,10 +1819,12 @@  static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
 {
 	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
 	struct device *dev = hisi_hba->dev;
+	struct scsi_lun lun;
 	int rc;
 
+	int_to_scsilun(0, &lun);
 	rc = hisi_sas_internal_task_abort(hisi_hba, device,
-					  HISI_SAS_INT_ABT_DEV, 0);
+			&lun, HISI_SAS_INT_ABT_DEV, 0);
 	if (rc < 0) {
 		dev_err(dev, "I_T nexus reset: internal abort (%d)\n", rc);
 		return TMF_RESP_FUNC_FAILED;
@@ -1837,7 +1854,7 @@  static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
 
 	/* Clear internal IO and then lu reset */
 	rc = hisi_sas_internal_task_abort(hisi_hba, device,
-					  HISI_SAS_INT_ABT_DEV, 0);
+			(struct scsi_lun *)lun, HISI_SAS_INT_ABT_DEV, 0);
 	if (rc < 0) {
 		dev_err(dev, "lu_reset: internal abort failed\n");
 		goto out;
@@ -2018,6 +2035,7 @@  hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
  * abort command for single IO command or a device
  * @hisi_hba: host controller struct
  * @device: domain device
+ * @lun: logical unit number
  * @abort_flag: mode of operation, device or single IO
  * @tag: tag of IO to be aborted (only relevant to single
  *       IO mode)
@@ -2025,12 +2043,15 @@  hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
  */
 static int
 _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
-			      struct domain_device *device, int abort_flag,
-			      int tag, struct hisi_sas_dq *dq)
+			      struct domain_device *device,
+			      struct scsi_lun *lun,
+			      int abort_flag, int tag,
+			      struct hisi_sas_dq *dq)
 {
-	struct sas_task *task;
 	struct hisi_sas_device *sas_dev = device->lldd_dev;
+	struct sas_ha_struct *sha = &hisi_hba->sha;
 	struct device *dev = hisi_hba->dev;
+	struct sas_task *task;
 	int res;
 
 	/*
@@ -2042,7 +2063,8 @@  _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
 	if (!hisi_hba->hw->prep_abort)
 		return TMF_RESP_FUNC_FAILED;
 
-	task = sas_alloc_slow_task(GFP_KERNEL);
+	task = sas_alloc_slow_task(sha, device,
+				   (struct scsi_lun *)lun, GFP_KERNEL);
 	if (!task)
 		return -ENOMEM;
 
@@ -2115,6 +2137,7 @@  _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
 static int
 hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
 			     struct domain_device *device,
+			     struct scsi_lun *lun,
 			     int abort_flag, int tag)
 {
 	struct hisi_sas_slot *slot;
@@ -2127,7 +2150,7 @@  hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
 		slot = &hisi_hba->slot_info[tag];
 		dq = &hisi_hba->dq[slot->dlvry_queue];
 		return _hisi_sas_internal_task_abort(hisi_hba, device,
-						     abort_flag, tag, dq);
+				lun, abort_flag, tag, dq);
 	case HISI_SAS_INT_ABT_DEV:
 		for (i = 0; i < hisi_hba->cq_nvecs; i++) {
 			struct hisi_sas_cq *cq = &hisi_hba->cq[i];
@@ -2137,8 +2160,7 @@  hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
 				continue;
 			dq = &hisi_hba->dq[i];
 			rc = _hisi_sas_internal_task_abort(hisi_hba, device,
-							   abort_flag, tag,
-							   dq);
+					lun, abort_flag, tag, dq);
 			if (rc)
 				return rc;
 		}
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 8d6bcc19359f..9e4a7c85a037 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -56,9 +56,12 @@  static int smp_execute_task_sg(struct domain_device *dev,
 {
 	int res, retry;
 	struct sas_task *task = NULL;
+	struct sas_ha_struct *ha = dev->port->ha;
 	struct sas_internal *i =
-		to_sas_internal(dev->port->ha->core.shost->transportt);
+		to_sas_internal(ha->core.shost->transportt);
+	struct scsi_lun lun;
 
+	int_to_scsilun(0, &lun);
 	mutex_lock(&dev->ex_dev.cmd_mutex);
 	for (retry = 0; retry < 3; retry++) {
 		if (test_bit(SAS_DEV_GONE, &dev->state)) {
@@ -66,7 +69,7 @@  static int smp_execute_task_sg(struct domain_device *dev,
 			break;
 		}
 
-		task = sas_alloc_slow_task(GFP_KERNEL);
+		task = sas_alloc_slow_task(ha, dev, &lun, GFP_KERNEL);
 		if (!task) {
 			res = -ENOMEM;
 			break;
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 2b0f98ca6ec3..9d0448b76a2f 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -14,6 +14,7 @@ 
 #include <scsi/sas_ata.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
+#include <scsi/scsi_tcq.h>
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_sas.h>
 
@@ -37,16 +38,36 @@  struct sas_task *sas_alloc_task(gfp_t flags)
 }
 EXPORT_SYMBOL_GPL(sas_alloc_task);
 
-struct sas_task *sas_alloc_slow_task(gfp_t flags)
+struct sas_task *sas_alloc_slow_task(struct sas_ha_struct *ha,
+				     struct domain_device *dev,
+				     struct scsi_lun *lun, gfp_t flags)
 {
 	struct sas_task *task = sas_alloc_task(flags);
-	struct sas_task_slow *slow = kmalloc(sizeof(*slow), flags);
+	struct Scsi_Host *shost = ha->core.shost;
+	struct sas_task_slow *slow;
 
-	if (!task || !slow) {
-		if (task)
-			kmem_cache_free(sas_task_cache, task);
-		kfree(slow);
+	if (!task)
 		return NULL;
+
+	slow = kzalloc(sizeof(*slow), flags);
+	if (!slow)
+		goto out_err_slow;
+
+	if (shost->nr_reserved_cmds) {
+		struct scsi_device *sdev;
+
+		if (dev && dev->starget) {
+			sdev = scsi_device_lookup_by_target(dev->starget,
+						    scsilun_to_int(lun));
+			if (!sdev)
+				goto out_err_scmd;
+		} else
+			sdev = ha->core.shost_dev;
+		slow->scmd = scsi_get_internal_cmd(sdev, DMA_BIDIRECTIONAL,
+						   REQ_NOWAIT);
+		if (!slow->scmd)
+			goto out_err_scmd;
+		ASSIGN_SAS_TASK(slow->scmd, task);
 	}
 
 	task->slow_task = slow;
@@ -55,13 +76,31 @@  struct sas_task *sas_alloc_slow_task(gfp_t flags)
 	init_completion(&slow->completion);
 
 	return task;
+
+out_err_scmd:
+	kfree(slow);
+out_err_slow:
+	kmem_cache_free(sas_task_cache, task);
+	return NULL;
 }
 EXPORT_SYMBOL_GPL(sas_alloc_slow_task);
 
 void sas_free_task(struct sas_task *task)
 {
 	if (task) {
-		kfree(task->slow_task);
+		/*
+		 * It could be good to just introduce separate sas_free_slow_task() to
+		 * avoid the following in the fastpath.
+		 */
+		if (task->slow_task) {
+			struct scsi_cmnd *scmd = task->slow_task->scmd;
+
+			if (scmd) {
+				ASSIGN_SAS_TASK(scmd, NULL);
+				scsi_put_internal_cmd(scmd);
+			}
+			kfree(task->slow_task);
+		}
 		kmem_cache_free(sas_task_cache, task);
 	}
 }
@@ -95,6 +134,7 @@  void sas_hash_addr(u8 *hashed, const u8 *sas_addr)
 
 int sas_register_ha(struct sas_ha_struct *sas_ha)
 {
+	struct Scsi_Host *shost = sas_ha->core.shost;
 	char name[64];
 	int error = 0;
 
@@ -111,6 +151,13 @@  int sas_register_ha(struct sas_ha_struct *sas_ha)
 
 	sas_ha->event_thres = SAS_PHY_SHUTDOWN_THRES;
 
+	if (shost->nr_reserved_cmds) {
+		sas_ha->core.shost_dev = scsi_get_host_dev(shost);
+		if (!sas_ha->core.shost_dev) {
+			pr_notice("couldn't register sas host device\n");
+			return -ENOMEM;
+		}
+	}
 	error = sas_register_phys(sas_ha);
 	if (error) {
 		pr_notice("couldn't register sas phys:%d\n", error);
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index 543b435f4c8c..99bdb88b3e86 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -1278,13 +1278,16 @@  static int mvs_exec_internal_tmf_task(struct domain_device *dev,
 				      u8 *lun, struct mvs_tmf_task *tmf)
 {
 	int res, retry;
+	struct sas_ha_struct *ha = dev->port->ha;
 	struct sas_task *task = NULL;
+	struct scsi_lun scsilun;
 
 	if (!(dev->tproto & SAS_PROTOCOL_SSP))
 		return TMF_RESP_FUNC_ESUPP;
 
+	memcpy(scsilun.scsi_lun, lun, 8);
 	for (retry = 0; retry < 3; retry++) {
-		task = sas_alloc_slow_task(GFP_KERNEL);
+		task = sas_alloc_slow_task(ha, dev, &scsilun, GFP_KERNEL);
 		if (!task)
 			return -ENOMEM;
 
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 3998fcd69acb..105962b0c815 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1701,6 +1701,7 @@  static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 	struct task_abort_req task_abort;
 	struct inbound_queue_table *circularQ;
 	u32 opc = OPC_INB_SATA_ABORT;
+	struct scsi_lun lun;
 	int ret;
 
 	if (!pm8001_ha_dev) {
@@ -1708,7 +1709,9 @@  static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 		return;
 	}
 
-	task = sas_alloc_slow_task(GFP_ATOMIC);
+	int_to_scsilun(0, &lun);
+	task = sas_alloc_slow_task(pm8001_ha->sas, pm8001_ha_dev->sas_device,
+				   &lun, GFP_ATOMIC);
 
 	if (!task) {
 		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task\n");
@@ -1752,8 +1755,10 @@  static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	struct domain_device *dev = pm8001_ha_dev->sas_device;
 	struct inbound_queue_table *circularQ;
 	u32 opc = OPC_INB_SATA_HOST_OPSTART;
+	struct scsi_lun lun;;
 
-	task = sas_alloc_slow_task(GFP_ATOMIC);
+	int_to_scsilun(0, &lun);
+	task = sas_alloc_slow_task(pm8001_ha->sas, dev, &lun, GFP_ATOMIC);
 
 	if (!task) {
 		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task !!!\n");
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 01e91347eb41..b1f12d671611 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -717,7 +717,9 @@  static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
 		return TMF_RESP_FUNC_ESUPP;
 
 	for (retry = 0; retry < 3; retry++) {
-		task = sas_alloc_slow_task(GFP_KERNEL);
+		task = sas_alloc_slow_task(pm8001_ha->sas,
+					   pm8001_dev->sas_device,
+					   (struct scsi_lun *)lun, GFP_KERNEL);
 		if (!task)
 			return -ENOMEM;
 
@@ -791,7 +793,7 @@  static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
 
 static int
 pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
-	struct pm8001_device *pm8001_dev, u32 flag,
+	struct pm8001_device *pm8001_dev, u8 *lun, u32 flag,
 	u32 task_tag)
 {
 	struct domain_device *dev = pm8001_dev->sas_device;
@@ -801,7 +803,8 @@  pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
 	struct sas_task *task = NULL;
 
 	for (retry = 0; retry < 3; retry++) {
-		task = sas_alloc_slow_task(GFP_KERNEL);
+		task = sas_alloc_slow_task(pm8001_ha->sas, dev,
+					   (struct scsi_lun *)lun, GFP_KERNEL);
 		if (!task)
 			return -ENOMEM;
 
@@ -875,13 +878,15 @@  static void pm8001_dev_gone_notify(struct domain_device *dev)
 	spin_lock_irqsave(&pm8001_ha->lock, flags);
 	if (pm8001_dev) {
 		u32 device_id = pm8001_dev->device_id;
+		struct scsi_lun lun;
 
+		int_to_scsilun(0, &lun);
 		pm8001_dbg(pm8001_ha, DISC, "found dev[%d:%x] is gone.\n",
 			   pm8001_dev->device_id, pm8001_dev->dev_type);
 		if (atomic_read(&pm8001_dev->running_req)) {
 			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 			pm8001_exec_internal_task_abort(pm8001_ha,
-				pm8001_dev, 1, 0);
+				pm8001_dev, lun.scsi_lun, 1, 0);
 			while (atomic_read(&pm8001_dev->running_req))
 				msleep(20);
 			spin_lock_irqsave(&pm8001_ha->lock, flags);
@@ -991,6 +996,9 @@  int pm8001_I_T_nexus_reset(struct domain_device *dev)
 	phy = sas_get_local_phy(dev);
 
 	if (dev_is_sata(dev)) {
+		struct scsi_lun lun;
+
+		int_to_scsilun(0, &lun);
 		if (scsi_is_sas_phy_local(phy)) {
 			rc = 0;
 			goto out;
@@ -1005,7 +1013,7 @@  int pm8001_I_T_nexus_reset(struct domain_device *dev)
 		}
 		msleep(2000);
 		rc = pm8001_exec_internal_task_abort(pm8001_ha,
-			pm8001_dev, 1, 0);
+			pm8001_dev, lun.scsi_lun, 1, 0);
 		if (rc) {
 			pm8001_dbg(pm8001_ha, EH, "task abort failed %x\n"
 				   "with rc %d\n", pm8001_dev->device_id, rc);
@@ -1032,7 +1040,9 @@  int pm8001_I_T_nexus_event_handler(struct domain_device *dev)
 	struct pm8001_device *pm8001_dev;
 	struct pm8001_hba_info *pm8001_ha;
 	struct sas_phy *phy;
+	struct scsi_lun lun;
 
+	int_to_scsilun(0, &lun);
 	if (!dev || !dev->lldd_dev)
 		return -1;
 
@@ -1051,7 +1061,7 @@  int pm8001_I_T_nexus_event_handler(struct domain_device *dev)
 		}
 		/* send internal ssp/sata/smp abort command to FW */
 		rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
-						     1, 0);
+						     lun.scsi_lun, 1, 0);
 		msleep(100);
 
 		/* deregister the target device */
@@ -1067,7 +1077,7 @@  int pm8001_I_T_nexus_event_handler(struct domain_device *dev)
 	} else {
 		/* send internal ssp/sata/smp abort command to FW */
 		rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
-						     1, 0);
+						     lun.scsi_lun, 1, 0);
 		msleep(100);
 
 		/* deregister the target device */
@@ -1095,8 +1105,8 @@  int pm8001_lu_reset(struct domain_device *dev, u8 *lun)
 	DECLARE_COMPLETION_ONSTACK(completion_setstate);
 	if (dev_is_sata(dev)) {
 		struct sas_phy *phy = sas_get_local_phy(dev);
-		rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
-			1, 0);
+		rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
+			lun, 1, 0);
 		rc = sas_phy_reset(phy, 1);
 		sas_put_local_phy(phy);
 		pm8001_dev->setds_completion = &completion_setstate;
@@ -1211,9 +1221,10 @@  int pm8001_abort_task(struct sas_task *task)
 						   &tmf_task);
 		if (rc == TMF_RESP_FUNC_SUCC)
 			pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
-				0, tag);
+				lun.scsi_lun, 0, tag);
 	} else if (task->task_proto & SAS_PROTOCOL_SATA ||
 		task->task_proto & SAS_PROTOCOL_STP) {
+		memset(lun.scsi_lun, 0, sizeof(lun.scsi_lun));
 		if (pm8001_ha->chip_id == chip_8006) {
 			DECLARE_COMPLETION_ONSTACK(completion_reset);
 			DECLARE_COMPLETION_ONSTACK(completion);
@@ -1280,7 +1291,7 @@  int pm8001_abort_task(struct sas_task *task)
 			 * going to free the task.
 			 */
 			ret = pm8001_exec_internal_task_abort(pm8001_ha,
-				pm8001_dev, 1, tag);
+				pm8001_dev, lun.scsi_lun, 1, tag);
 			if (ret)
 				goto out;
 			ret = wait_for_completion_timeout(
@@ -1297,13 +1308,15 @@  int pm8001_abort_task(struct sas_task *task)
 			wait_for_completion(&completion);
 		} else {
 			rc = pm8001_exec_internal_task_abort(pm8001_ha,
-				pm8001_dev, 0, tag);
+				pm8001_dev, lun.scsi_lun, 0, tag);
 		}
 		rc = TMF_RESP_FUNC_COMPLETE;
 	} else if (task->task_proto & SAS_PROTOCOL_SMP) {
 		/* SMP */
+
+		int_to_scsilun(0, &lun);
 		rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
-			0, tag);
+			lun.scsi_lun, 0, tag);
 
 	}
 out:
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index bc1929b230c4..03bfb4d72895 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1772,6 +1772,7 @@  static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 	struct task_abort_req task_abort;
 	struct inbound_queue_table *circularQ;
 	u32 opc = OPC_INB_SATA_ABORT;
+	struct scsi_lun lun;
 	int ret;
 
 	if (!pm8001_ha_dev) {
@@ -1779,7 +1780,9 @@  static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 		return;
 	}
 
-	task = sas_alloc_slow_task(GFP_ATOMIC);
+	int_to_scsilun(0, &lun);
+	task = sas_alloc_slow_task(pm8001_ha->sas,pm8001_ha_dev->sas_device,
+				   &lun, GFP_ATOMIC);
 
 	if (!task) {
 		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task\n");
@@ -1827,8 +1830,10 @@  static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	struct domain_device *dev = pm8001_ha_dev->sas_device;
 	struct inbound_queue_table *circularQ;
 	u32 opc = OPC_INB_SATA_HOST_OPSTART;
+	struct scsi_lun lun;
 
-	task = sas_alloc_slow_task(GFP_ATOMIC);
+	int_to_scsilun(0, &lun);
+	task = sas_alloc_slow_task(pm8001_ha->sas, dev, &lun, GFP_ATOMIC);
 
 	if (!task) {
 		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task !!!\n");
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 3a024eced38c..9b8c06a8329a 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -349,7 +349,7 @@  struct asd_sas_phy {
 
 struct scsi_core {
 	struct Scsi_Host *shost;
-
+	struct scsi_device *shost_dev;
 };
 
 enum sas_ha_state {
@@ -605,6 +605,7 @@  struct sas_task_slow {
 	struct timer_list     timer;
 	struct completion     completion;
 	struct sas_task       *task;
+	struct scsi_cmnd      *scmd;
 };
 
 #define SAS_TASK_STATE_PENDING      1
@@ -614,7 +615,10 @@  struct sas_task_slow {
 #define SAS_TASK_AT_INITIATOR       16
 
 extern struct sas_task *sas_alloc_task(gfp_t flags);
-extern struct sas_task *sas_alloc_slow_task(gfp_t flags);
+extern struct sas_task *sas_alloc_slow_task(struct sas_ha_struct *ha,
+					    struct domain_device *dev,
+					    struct scsi_lun *lun,
+					    gfp_t flags);
 extern void sas_free_task(struct sas_task *task);
 
 struct sas_domain_function_template {