+ }
+ 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 {