diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2007-07-09 12:52:08 +0900 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-07-18 11:18:20 -0500 |
commit | ba1fc175cc6c0af7e78241e50160344f0f198282 (patch) | |
tree | 019c21e5c4658c50b08e28d2077b37242a1d22db | |
parent | 7aa68e80bd481faae1234bc2a7e4bcc9348f98b4 (diff) |
[SCSI] libsas: add SAS management protocol handler
This patch adds support for SAS Management Protocol (SMP) passthrough
support via bsg. aic94xx can use this.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r-- | drivers/scsi/libsas/sas_expander.c | 48 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_init.c | 1 | ||||
-rw-r--r-- | include/scsi/libsas.h | 2 |
3 files changed, 51 insertions, 0 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 969fd3eb494..a81195354b9 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -23,6 +23,7 @@ */ #include <linux/scatterlist.h> +#include <linux/blkdev.h> #include "sas_internal.h" @@ -1972,3 +1973,50 @@ out: return res; } #endif + +int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, + struct request *req) +{ + struct domain_device *dev; + int ret, type = rphy->identify.device_type; + struct request *rsp = req->next_rq; + + if (!rsp) { + printk("%s: space for a smp response is missing\n", + __FUNCTION__); + return -EINVAL; + } + + /* seems aic94xx doesn't support */ + if (!rphy) { + printk("%s: can we send a smp request to a host?\n", + __FUNCTION__); + return -EINVAL; + } + + if (type != SAS_EDGE_EXPANDER_DEVICE && + type != SAS_FANOUT_EXPANDER_DEVICE) { + printk("%s: can we send a smp request to a device?\n", + __FUNCTION__); + return -EINVAL; + } + + dev = sas_find_dev_by_rphy(rphy); + if (!dev) { + printk("%s: fail to find a domain_device?\n", __FUNCTION__); + return -EINVAL; + } + + /* do we need to support multiple segments? */ + if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { + printk("%s: multiple segments req %u %u, rsp %u %u\n", + __FUNCTION__, req->bio->bi_vcnt, req->data_len, + rsp->bio->bi_vcnt, rsp->data_len); + return -EINVAL; + } + + ret = smp_execute_task(dev, bio_data(req->bio), req->data_len, + bio_data(rsp->bio), rsp->data_len); + + return ret; +} diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index 965698c8b7b..98360272f40 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -259,6 +259,7 @@ static struct sas_function_template sft = { .phy_reset = sas_phy_reset, .set_phy_speed = sas_set_phy_speed, .get_linkerrors = sas_get_linkerrors, + .smp_handler = sas_smp_handler, }; struct scsi_transport_template * diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 9275a46bf2e..df36461fe88 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -674,4 +674,6 @@ extern void sas_target_destroy(struct scsi_target *); extern int sas_slave_alloc(struct scsi_device *); extern int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg); +extern int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, + struct request *req); #endif /* _SASLIB_H_ */ |