aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi/libsas/sas_expander.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libsas/sas_expander.c')
-rw-r--r--drivers/scsi/libsas/sas_expander.c70
1 files changed, 37 insertions, 33 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 570b2cb2da43..6b4fd2375178 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -64,8 +64,8 @@ static void smp_task_done(struct sas_task *task)
/* Give it some long enough timeout. In seconds. */
#define SMP_TIMEOUT 10
-static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
- void *resp, int resp_size)
+static int smp_execute_task_sg(struct domain_device *dev,
+ struct scatterlist *req, struct scatterlist *resp)
{
int res, retry;
struct sas_task *task = NULL;
@@ -86,8 +86,8 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
}
task->dev = dev;
task->task_proto = dev->tproto;
- sg_init_one(&task->smp_task.smp_req, req, req_size);
- sg_init_one(&task->smp_task.smp_resp, resp, resp_size);
+ task->smp_task.smp_req = *req;
+ task->smp_task.smp_resp = *resp;
task->task_done = smp_task_done;
@@ -151,6 +151,17 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
return res;
}
+static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
+ void *resp, int resp_size)
+{
+ struct scatterlist req_sg;
+ struct scatterlist resp_sg;
+
+ sg_init_one(&req_sg, req, req_size);
+ sg_init_one(&resp_sg, resp, resp_size);
+ return smp_execute_task_sg(dev, &req_sg, &resp_sg);
+}
+
/* ---------- Allocations ---------- */
static inline void *alloc_smp_req(int size)
@@ -2130,57 +2141,50 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev)
return res;
}
-int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
- struct request *req)
+void sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
+ struct sas_rphy *rphy)
{
struct domain_device *dev;
- int ret, type;
- struct request *rsp = req->next_rq;
-
- if (!rsp) {
- printk("%s: space for a smp response is missing\n",
- __func__);
- return -EINVAL;
- }
+ unsigned int reslen = 0;
+ int ret = -EINVAL;
/* no rphy means no smp target support (ie aic94xx host) */
if (!rphy)
- return sas_smp_host_handler(shost, req, rsp);
-
- type = rphy->identify.device_type;
+ return sas_smp_host_handler(job, shost);
- if (type != SAS_EDGE_EXPANDER_DEVICE &&
- type != SAS_FANOUT_EXPANDER_DEVICE) {
+ switch (rphy->identify.device_type) {
+ case SAS_EDGE_EXPANDER_DEVICE:
+ case SAS_FANOUT_EXPANDER_DEVICE:
+ break;
+ default:
printk("%s: can we send a smp request to a device?\n",
__func__);
- return -EINVAL;
+ goto out;
}
dev = sas_find_dev_by_rphy(rphy);
if (!dev) {
printk("%s: fail to find a domain_device?\n", __func__);
- return -EINVAL;
+ goto out;
}
/* do we need to support multiple segments? */
- if (bio_multiple_segments(req->bio) ||
- bio_multiple_segments(rsp->bio)) {
+ if (job->request_payload.sg_cnt > 1 ||
+ job->reply_payload.sg_cnt > 1) {
printk("%s: multiple segments req %u, rsp %u\n",
- __func__, blk_rq_bytes(req), blk_rq_bytes(rsp));
- return -EINVAL;
+ __func__, job->request_payload.payload_len,
+ job->reply_payload.payload_len);
+ goto out;
}
- ret = smp_execute_task(dev, bio_data(req->bio), blk_rq_bytes(req),
- bio_data(rsp->bio), blk_rq_bytes(rsp));
+ ret = smp_execute_task_sg(dev, job->request_payload.sg_list,
+ job->reply_payload.sg_list);
if (ret > 0) {
/* positive number is the untransferred residual */
- scsi_req(rsp)->resid_len = ret;
- scsi_req(req)->resid_len = 0;
+ reslen = ret;
ret = 0;
- } else if (ret == 0) {
- scsi_req(rsp)->resid_len = 0;
- scsi_req(req)->resid_len = 0;
}
- return ret;
+out:
+ bsg_job_done(job, ret, reslen);
}