diff --git a/[refs] b/[refs] index 35359f82bc7b..5b7f0b822aa2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 7aa68e80bd481faae1234bc2a7e4bcc9348f98b4 +refs/heads/master: ba1fc175cc6c0af7e78241e50160344f0f198282 diff --git a/trunk/drivers/scsi/libsas/sas_expander.c b/trunk/drivers/scsi/libsas/sas_expander.c index 969fd3eb494a..a81195354b9c 100644 --- a/trunk/drivers/scsi/libsas/sas_expander.c +++ b/trunk/drivers/scsi/libsas/sas_expander.c @@ -23,6 +23,7 @@ */ #include +#include #include "sas_internal.h" @@ -1972,3 +1973,50 @@ static ssize_t smp_portal_read(struct kobject *kobj, 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/trunk/drivers/scsi/libsas/sas_init.c b/trunk/drivers/scsi/libsas/sas_init.c index 965698c8b7bf..98360272f40a 100644 --- a/trunk/drivers/scsi/libsas/sas_init.c +++ b/trunk/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/trunk/include/scsi/libsas.h b/trunk/include/scsi/libsas.h index 9275a46bf2e3..df36461fe881 100644 --- a/trunk/include/scsi/libsas.h +++ b/trunk/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_ */