summaryrefslogtreecommitdiff
path: root/drivers/scsi/scsi_transport_sas.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2017-08-25 17:37:41 +0200
committerMartin K. Petersen <martin.petersen@oracle.com>2017-08-29 21:51:45 -0400
commit651a013649943710a900551ec6e03d2084e1a65a (patch)
tree14a92a3104c919eb439970de5471643b6f915ffc /drivers/scsi/scsi_transport_sas.c
parenteaa79a6cd733e1f978613a5fcf5f7c1cdb38eb2a (diff)
scsi: scsi_transport_sas: switch to bsg-lib for SMP passthrough
Simplify the SMP passthrough code by switching it to the generic bsg-lib helpers that abstract away the details of the request code, and gets drivers out of seeing struct scsi_request. For the libsas host SMP code there is a small behavior difference in that we now always clear the residual len for successful commands, similar to the three other SMP handler implementations. Given that there is no partial command handling in the host SMP handler this should not matter in practice. [mkp: typos and checkpatch fixes] Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/scsi_transport_sas.c')
-rw-r--r--drivers/scsi/scsi_transport_sas.c118
1 files changed, 29 insertions, 89 deletions
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index e2e948f1ce28..319dff970237 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -169,39 +169,22 @@ static struct sas_end_device *sas_sdev_to_rdev(struct scsi_device *sdev)
return rdev;
}
-static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost,
- struct sas_rphy *rphy)
+static int sas_smp_dispatch(struct bsg_job *job)
{
- struct request *req;
- blk_status_t ret;
- int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *);
+ struct Scsi_Host *shost = dev_to_shost(job->dev);
+ struct sas_rphy *rphy = NULL;
- while ((req = blk_fetch_request(q)) != NULL) {
- spin_unlock_irq(q->queue_lock);
+ if (!scsi_is_host_device(job->dev))
+ rphy = dev_to_rphy(job->dev);
- scsi_req(req)->resid_len = blk_rq_bytes(req);
- if (req->next_rq)
- scsi_req(req->next_rq)->resid_len =
- blk_rq_bytes(req->next_rq);
- handler = to_sas_internal(shost->transportt)->f->smp_handler;
- ret = handler(shost, rphy, req);
- scsi_req(req)->result = ret;
-
- blk_end_request_all(req, 0);
-
- spin_lock_irq(q->queue_lock);
+ if (!job->req->next_rq) {
+ dev_warn(job->dev, "space for a smp response is missing\n");
+ bsg_job_done(job, -EINVAL, 0);
+ return 0;
}
-}
-static void sas_host_smp_request(struct request_queue *q)
-{
- sas_smp_request(q, (struct Scsi_Host *)q->queuedata, NULL);
-}
-
-static void sas_non_host_smp_request(struct request_queue *q)
-{
- struct sas_rphy *rphy = q->queuedata;
- sas_smp_request(q, rphy_to_shost(rphy), rphy);
+ to_sas_internal(shost->transportt)->f->smp_handler(job, shost, rphy);
+ return 0;
}
static void sas_host_release(struct device *dev)
@@ -217,81 +200,36 @@ static void sas_host_release(struct device *dev)
static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
{
struct request_queue *q;
- int error;
- struct device *dev;
- char namebuf[20];
- const char *name;
- void (*release)(struct device *);
if (!to_sas_internal(shost->transportt)->f->smp_handler) {
printk("%s can't handle SMP requests\n", shost->hostt->name);
return 0;
}
- q = blk_alloc_queue(GFP_KERNEL);
- if (!q)
- return -ENOMEM;
- q->initialize_rq_fn = scsi_initialize_rq;
- q->cmd_size = sizeof(struct scsi_request);
-
if (rphy) {
- q->request_fn = sas_non_host_smp_request;
- dev = &rphy->dev;
- name = dev_name(dev);
- release = NULL;
+ q = bsg_setup_queue(&rphy->dev, dev_name(&rphy->dev),
+ sas_smp_dispatch, 0, NULL);
+ if (IS_ERR(q))
+ return PTR_ERR(q);
+ rphy->q = q;
} else {
- q->request_fn = sas_host_smp_request;
- dev = &shost->shost_gendev;
- snprintf(namebuf, sizeof(namebuf),
- "sas_host%d", shost->host_no);
- name = namebuf;
- release = sas_host_release;
+ char name[20];
+
+ snprintf(name, sizeof(name), "sas_host%d", shost->host_no);
+ q = bsg_setup_queue(&shost->shost_gendev, name,
+ sas_smp_dispatch, 0, sas_host_release);
+ if (IS_ERR(q))
+ return PTR_ERR(q);
+ to_sas_host_attrs(shost)->q = q;
}
- error = blk_init_allocated_queue(q);
- if (error)
- goto out_cleanup_queue;
/*
* by default assume old behaviour and bounce for any highmem page
*/
blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
-
- error = bsg_register_queue(q, dev, name, release);
- if (error)
- goto out_cleanup_queue;
-
- if (rphy)
- rphy->q = q;
- else
- to_sas_host_attrs(shost)->q = q;
-
- if (rphy)
- q->queuedata = rphy;
- else
- q->queuedata = shost;
-
queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
queue_flag_set_unlocked(QUEUE_FLAG_SCSI_PASSTHROUGH, q);
return 0;
-
-out_cleanup_queue:
- blk_cleanup_queue(q);
- return error;
-}
-
-static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy)
-{
- struct request_queue *q;
-
- if (rphy)
- q = rphy->q;
- else
- q = to_sas_host_attrs(shost)->q;
-
- if (!q)
- return;
-
- bsg_unregister_queue(q);
}
/*
@@ -321,9 +259,10 @@ static int sas_host_remove(struct transport_container *tc, struct device *dev,
struct device *cdev)
{
struct Scsi_Host *shost = dev_to_shost(dev);
+ struct request_queue *q = to_sas_host_attrs(shost)->q;
- sas_bsg_remove(shost, NULL);
-
+ if (q)
+ bsg_unregister_queue(q);
return 0;
}
@@ -1713,7 +1652,8 @@ sas_rphy_remove(struct sas_rphy *rphy)
}
sas_rphy_unlink(rphy);
- sas_bsg_remove(NULL, rphy);
+ if (rphy->q)
+ bsg_unregister_queue(rphy->q);
transport_remove_device(dev);
device_del(dev);
}