diff options
-rw-r--r-- | drivers/scsi/Kconfig | 2 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_sas.c | 85 | ||||
-rw-r--r-- | include/scsi/scsi_transport_sas.h | 3 |
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 | ||
283 | config SCSI_SAS_ATTRS | 283 | config 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 { | |||
152 | sas_bitfield_name_search(linkspeed, sas_linkspeed_names) | 154 | sas_bitfield_name_search(linkspeed, sas_linkspeed_names) |
153 | sas_bitfield_name_set(linkspeed, sas_linkspeed_names) | 155 | sas_bitfield_name_set(linkspeed, sas_linkspeed_names) |
154 | 156 | ||
157 | static 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 | |||
182 | static void sas_host_smp_request(struct request_queue *q) | ||
183 | { | ||
184 | sas_smp_request(q, (struct Scsi_Host *)q->queuedata, NULL); | ||
185 | } | ||
186 | |||
187 | static 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 | |||
193 | static 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 | } |
1226 | EXPORT_SYMBOL(sas_end_device_alloc); | 1308 | EXPORT_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 | } |
1265 | EXPORT_SYMBOL(sas_expander_alloc); | 1350 | EXPORT_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 | ||
8 | struct scsi_transport_template; | 8 | struct scsi_transport_template; |
9 | struct sas_rphy; | 9 | struct sas_rphy; |
10 | 10 | struct request; | |
11 | 11 | ||
12 | enum sas_device_type { | 12 | enum 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 | ||