aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2007-07-08 23:52:06 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-07-18 12:18:07 -0400
commit7aa68e80bd481faae1234bc2a7e4bcc9348f98b4 (patch)
treed5df54a48de9c214fde64dd536e79ed3bba942a5
parent3ac709c113daa19e375e8b0fef318fab1713f687 (diff)
[SCSI] transport_sas: add SAS management protocol support
The sas transport class attaches one bsg device to every SAS object (host, device, expander, etc). LLDs can define a function to handle SMP requests via sas_function_template::smp_handler. 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/Kconfig2
-rw-r--r--drivers/scsi/scsi_transport_sas.c85
-rw-r--r--include/scsi/scsi_transport_sas.h3
3 files changed, 88 insertions, 2 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 07a69117cae4..bebe43e2cc3e 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -282,7 +282,7 @@ config SCSI_ISCSI_ATTRS
282 282
283config SCSI_SAS_ATTRS 283config SCSI_SAS_ATTRS
284 tristate "SAS Transport Attributes" 284 tristate "SAS Transport Attributes"
285 depends on SCSI 285 depends on SCSI && BLK_DEV_BSG
286 help 286 help
287 If you wish to export transport-specific information about 287 If you wish to export transport-specific information about
288 each attached SAS device to sysfs, say Y. 288 each attached SAS device to sysfs, say Y.
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index b2ef71a86292..2871fd05fcf7 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -29,6 +29,8 @@
29#include <linux/err.h> 29#include <linux/err.h>
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/string.h> 31#include <linux/string.h>
32#include <linux/blkdev.h>
33#include <linux/bsg.h>
32 34
33#include <scsi/scsi.h> 35#include <scsi/scsi.h>
34#include <scsi/scsi_device.h> 36#include <scsi/scsi_device.h>
@@ -152,6 +154,76 @@ static struct {
152sas_bitfield_name_search(linkspeed, sas_linkspeed_names) 154sas_bitfield_name_search(linkspeed, sas_linkspeed_names)
153sas_bitfield_name_set(linkspeed, sas_linkspeed_names) 155sas_bitfield_name_set(linkspeed, sas_linkspeed_names)
154 156
157static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost,
158 struct sas_rphy *rphy)
159{
160 struct request *req;
161 int ret;
162 int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *);
163
164 while (!blk_queue_plugged(q)) {
165 req = elv_next_request(q);
166 if (!req)
167 break;
168
169 blkdev_dequeue_request(req);
170
171 spin_unlock_irq(q->queue_lock);
172
173 handler = to_sas_internal(shost->transportt)->f->smp_handler;
174 ret = handler(shost, rphy, req);
175
176 spin_lock_irq(q->queue_lock);
177
178 req->end_io(req, ret);
179 }
180}
181
182static void sas_host_smp_request(struct request_queue *q)
183{
184 sas_smp_request(q, (struct Scsi_Host *)q->queuedata, NULL);
185}
186
187static void sas_non_host_smp_request(struct request_queue *q)
188{
189 struct sas_rphy *rphy = q->queuedata;
190 sas_smp_request(q, rphy_to_shost(rphy), rphy);
191}
192
193static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy,
194 char *name)
195{
196 struct request_queue *q;
197 int error;
198
199 if (!to_sas_internal(shost->transportt)->f->smp_handler) {
200 printk("%s can't handle SMP requests\n", shost->hostt->name);
201 return 0;
202 }
203
204 if (rphy)
205 q = blk_init_queue(sas_non_host_smp_request, NULL);
206 else
207 q = blk_init_queue(sas_host_smp_request, NULL);
208 if (!q)
209 return -ENOMEM;
210
211 error = bsg_register_queue(q, name);
212 if (error) {
213 blk_cleanup_queue(q);
214 return -ENOMEM;
215 }
216
217 if (rphy)
218 q->queuedata = rphy;
219 else
220 q->queuedata = shost;
221
222 set_bit(QUEUE_FLAG_BIDI, &q->queue_flags);
223
224 return 0;
225}
226
155/* 227/*
156 * SAS host attributes 228 * SAS host attributes
157 */ 229 */
@@ -161,12 +233,19 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev,
161{ 233{
162 struct Scsi_Host *shost = dev_to_shost(dev); 234 struct Scsi_Host *shost = dev_to_shost(dev);
163 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 235 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
236 char name[BUS_ID_SIZE];
164 237
165 INIT_LIST_HEAD(&sas_host->rphy_list); 238 INIT_LIST_HEAD(&sas_host->rphy_list);
166 mutex_init(&sas_host->lock); 239 mutex_init(&sas_host->lock);
167 sas_host->next_target_id = 0; 240 sas_host->next_target_id = 0;
168 sas_host->next_expander_id = 0; 241 sas_host->next_expander_id = 0;
169 sas_host->next_port_id = 0; 242 sas_host->next_port_id = 0;
243
244 snprintf(name, sizeof(name), "sas_host%d", shost->host_no);
245 if (sas_bsg_initialize(shost, NULL, name))
246 dev_printk(KERN_ERR, dev, "fail to a bsg device %d\n",
247 shost->host_no);
248
170 return 0; 249 return 0;
171} 250}
172 251
@@ -1221,6 +1300,9 @@ struct sas_rphy *sas_end_device_alloc(struct sas_port *parent)
1221 sas_rphy_initialize(&rdev->rphy); 1300 sas_rphy_initialize(&rdev->rphy);
1222 transport_setup_device(&rdev->rphy.dev); 1301 transport_setup_device(&rdev->rphy.dev);
1223 1302
1303 if (sas_bsg_initialize(shost, &rdev->rphy, rdev->rphy.dev.bus_id))
1304 printk("fail to a bsg device %s\n", rdev->rphy.dev.bus_id);
1305
1224 return &rdev->rphy; 1306 return &rdev->rphy;
1225} 1307}
1226EXPORT_SYMBOL(sas_end_device_alloc); 1308EXPORT_SYMBOL(sas_end_device_alloc);
@@ -1260,6 +1342,9 @@ struct sas_rphy *sas_expander_alloc(struct sas_port *parent,
1260 sas_rphy_initialize(&rdev->rphy); 1342 sas_rphy_initialize(&rdev->rphy);
1261 transport_setup_device(&rdev->rphy.dev); 1343 transport_setup_device(&rdev->rphy.dev);
1262 1344
1345 if (sas_bsg_initialize(shost, &rdev->rphy, rdev->rphy.dev.bus_id))
1346 printk("fail to a bsg device %s\n", rdev->rphy.dev.bus_id);
1347
1263 return &rdev->rphy; 1348 return &rdev->rphy;
1264} 1349}
1265EXPORT_SYMBOL(sas_expander_alloc); 1350EXPORT_SYMBOL(sas_expander_alloc);
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h
index 97eeb5b59ea5..af304fb9d979 100644
--- a/include/scsi/scsi_transport_sas.h
+++ b/include/scsi/scsi_transport_sas.h
@@ -7,7 +7,7 @@
7 7
8struct scsi_transport_template; 8struct scsi_transport_template;
9struct sas_rphy; 9struct sas_rphy;
10 10struct request;
11 11
12enum sas_device_type { 12enum sas_device_type {
13 SAS_PHY_UNUSED, 13 SAS_PHY_UNUSED,
@@ -172,6 +172,7 @@ struct sas_function_template {
172 int (*phy_reset)(struct sas_phy *, int); 172 int (*phy_reset)(struct sas_phy *, int);
173 int (*phy_enable)(struct sas_phy *, int); 173 int (*phy_enable)(struct sas_phy *, int);
174 int (*set_phy_speed)(struct sas_phy *, struct sas_phy_linkrates *); 174 int (*set_phy_speed)(struct sas_phy *, struct sas_phy_linkrates *);
175 int (*smp_handler)(struct Scsi_Host *, struct sas_rphy *, struct request *);
175}; 176};
176 177
177 178