aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libsas/sas_expander.c48
-rw-r--r--drivers/scsi/libsas/sas_init.c1
-rw-r--r--include/scsi/libsas.h2
3 files changed, 51 insertions, 0 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 969fd3eb494a..a81195354b9c 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -23,6 +23,7 @@
23 */ 23 */
24 24
25#include <linux/scatterlist.h> 25#include <linux/scatterlist.h>
26#include <linux/blkdev.h>
26 27
27#include "sas_internal.h" 28#include "sas_internal.h"
28 29
@@ -1972,3 +1973,50 @@ out:
1972 return res; 1973 return res;
1973} 1974}
1974#endif 1975#endif
1976
1977int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1978 struct request *req)
1979{
1980 struct domain_device *dev;
1981 int ret, type = rphy->identify.device_type;
1982 struct request *rsp = req->next_rq;
1983
1984 if (!rsp) {
1985 printk("%s: space for a smp response is missing\n",
1986 __FUNCTION__);
1987 return -EINVAL;
1988 }
1989
1990 /* seems aic94xx doesn't support */
1991 if (!rphy) {
1992 printk("%s: can we send a smp request to a host?\n",
1993 __FUNCTION__);
1994 return -EINVAL;
1995 }
1996
1997 if (type != SAS_EDGE_EXPANDER_DEVICE &&
1998 type != SAS_FANOUT_EXPANDER_DEVICE) {
1999 printk("%s: can we send a smp request to a device?\n",
2000 __FUNCTION__);
2001 return -EINVAL;
2002 }
2003
2004 dev = sas_find_dev_by_rphy(rphy);
2005 if (!dev) {
2006 printk("%s: fail to find a domain_device?\n", __FUNCTION__);
2007 return -EINVAL;
2008 }
2009
2010 /* do we need to support multiple segments? */
2011 if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
2012 printk("%s: multiple segments req %u %u, rsp %u %u\n",
2013 __FUNCTION__, req->bio->bi_vcnt, req->data_len,
2014 rsp->bio->bi_vcnt, rsp->data_len);
2015 return -EINVAL;
2016 }
2017
2018 ret = smp_execute_task(dev, bio_data(req->bio), req->data_len,
2019 bio_data(rsp->bio), rsp->data_len);
2020
2021 return ret;
2022}
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 965698c8b7bf..98360272f40a 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 = {
259 .phy_reset = sas_phy_reset, 259 .phy_reset = sas_phy_reset,
260 .set_phy_speed = sas_set_phy_speed, 260 .set_phy_speed = sas_set_phy_speed,
261 .get_linkerrors = sas_get_linkerrors, 261 .get_linkerrors = sas_get_linkerrors,
262 .smp_handler = sas_smp_handler,
262}; 263};
263 264
264struct scsi_transport_template * 265struct scsi_transport_template *
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 9275a46bf2e3..df36461fe881 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -674,4 +674,6 @@ extern void sas_target_destroy(struct scsi_target *);
674extern int sas_slave_alloc(struct scsi_device *); 674extern int sas_slave_alloc(struct scsi_device *);
675extern int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg); 675extern int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg);
676 676
677extern int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
678 struct request *req);
677#endif /* _SASLIB_H_ */ 679#endif /* _SASLIB_H_ */