diff options
author | James Bottomley <James.Bottomley@steeleye.com> | 2007-07-20 19:22:17 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-07-21 09:58:23 -0400 |
commit | 39dca558a5b52b63e49bc234a7e887be092aa690 (patch) | |
tree | 31c3c412458e657fdbedc73f50b7de26c7ed0c4a | |
parent | 0e78d158b67fba3977f577f293c323359d80dd0e (diff) |
[SCSI] bsg: make class backlinks
Currently, bsg doesn't make class backlinks (a process whereby you'd get
a link to bsg in the device directory in the same way you get one for
sg). This is because the bsg device is uninitialised, so the class
device has nothing it can attach to. The fix is to make the bsg device
point to the cdevice of the entity creating the bsg, necessitating
changing the bsg_register_queue() prototype into a form that takes the
generic device.
Acked-by: FUJITA Tomonori <tomof@acm.org>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r-- | block/bsg.c | 21 | ||||
-rw-r--r-- | drivers/scsi/scsi_sysfs.c | 2 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_sas.c | 32 | ||||
-rw-r--r-- | include/linux/bsg.h | 4 |
4 files changed, 38 insertions, 21 deletions
diff --git a/block/bsg.c b/block/bsg.c index 0e3d5d490d2..4eebcd5c731 100644 --- a/block/bsg.c +++ b/block/bsg.c | |||
@@ -936,20 +936,29 @@ void bsg_unregister_queue(struct request_queue *q) | |||
936 | 936 | ||
937 | mutex_lock(&bsg_mutex); | 937 | mutex_lock(&bsg_mutex); |
938 | sysfs_remove_link(&q->kobj, "bsg"); | 938 | sysfs_remove_link(&q->kobj, "bsg"); |
939 | class_device_destroy(bsg_class, MKDEV(bsg_major, bcd->minor)); | 939 | class_device_unregister(bcd->class_dev); |
940 | put_device(bcd->dev); | ||
940 | bcd->class_dev = NULL; | 941 | bcd->class_dev = NULL; |
942 | bcd->dev = NULL; | ||
941 | list_del_init(&bcd->list); | 943 | list_del_init(&bcd->list); |
942 | bsg_device_nr--; | 944 | bsg_device_nr--; |
943 | mutex_unlock(&bsg_mutex); | 945 | mutex_unlock(&bsg_mutex); |
944 | } | 946 | } |
945 | EXPORT_SYMBOL_GPL(bsg_unregister_queue); | 947 | EXPORT_SYMBOL_GPL(bsg_unregister_queue); |
946 | 948 | ||
947 | int bsg_register_queue(struct request_queue *q, const char *name) | 949 | int bsg_register_queue(struct request_queue *q, struct device *gdev, |
950 | const char *name) | ||
948 | { | 951 | { |
949 | struct bsg_class_device *bcd, *__bcd; | 952 | struct bsg_class_device *bcd, *__bcd; |
950 | dev_t dev; | 953 | dev_t dev; |
951 | int ret = -EMFILE; | 954 | int ret = -EMFILE; |
952 | struct class_device *class_dev = NULL; | 955 | struct class_device *class_dev = NULL; |
956 | const char *devname; | ||
957 | |||
958 | if (name) | ||
959 | devname = name; | ||
960 | else | ||
961 | devname = gdev->bus_id; | ||
953 | 962 | ||
954 | /* | 963 | /* |
955 | * we need a proper transport to send commands, not a stacked device | 964 | * we need a proper transport to send commands, not a stacked device |
@@ -982,11 +991,13 @@ retry: | |||
982 | bsg_minor_idx = 0; | 991 | bsg_minor_idx = 0; |
983 | 992 | ||
984 | bcd->queue = q; | 993 | bcd->queue = q; |
994 | bcd->dev = get_device(gdev); | ||
985 | dev = MKDEV(bsg_major, bcd->minor); | 995 | dev = MKDEV(bsg_major, bcd->minor); |
986 | class_dev = class_device_create(bsg_class, NULL, dev, bcd->dev, "%s", name); | 996 | class_dev = class_device_create(bsg_class, NULL, dev, gdev, "%s", |
997 | devname); | ||
987 | if (IS_ERR(class_dev)) { | 998 | if (IS_ERR(class_dev)) { |
988 | ret = PTR_ERR(class_dev); | 999 | ret = PTR_ERR(class_dev); |
989 | goto err; | 1000 | goto err_put; |
990 | } | 1001 | } |
991 | bcd->class_dev = class_dev; | 1002 | bcd->class_dev = class_dev; |
992 | 1003 | ||
@@ -1004,6 +1015,8 @@ retry: | |||
1004 | 1015 | ||
1005 | err_unregister: | 1016 | err_unregister: |
1006 | class_device_unregister(class_dev); | 1017 | class_device_unregister(class_dev); |
1018 | err_put: | ||
1019 | put_device(gdev); | ||
1007 | err: | 1020 | err: |
1008 | mutex_unlock(&bsg_mutex); | 1021 | mutex_unlock(&bsg_mutex); |
1009 | return ret; | 1022 | return ret; |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index ad5f21fd5d4..34cdce6738a 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -736,7 +736,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) | |||
736 | * released by the sdev_class .release */ | 736 | * released by the sdev_class .release */ |
737 | get_device(&sdev->sdev_gendev); | 737 | get_device(&sdev->sdev_gendev); |
738 | 738 | ||
739 | error = bsg_register_queue(rq, sdev->sdev_gendev.bus_id); | 739 | error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL); |
740 | 740 | ||
741 | if (error) | 741 | if (error) |
742 | sdev_printk(KERN_INFO, sdev, | 742 | sdev_printk(KERN_INFO, sdev, |
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 573f588154d..3120f4b3a11 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c | |||
@@ -191,25 +191,34 @@ static void sas_non_host_smp_request(struct request_queue *q) | |||
191 | sas_smp_request(q, rphy_to_shost(rphy), rphy); | 191 | sas_smp_request(q, rphy_to_shost(rphy), rphy); |
192 | } | 192 | } |
193 | 193 | ||
194 | static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy, | 194 | static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy) |
195 | char *name) | ||
196 | { | 195 | { |
197 | struct request_queue *q; | 196 | struct request_queue *q; |
198 | int error; | 197 | int error; |
198 | struct device *dev; | ||
199 | char namebuf[BUS_ID_SIZE]; | ||
200 | const char *name; | ||
199 | 201 | ||
200 | if (!to_sas_internal(shost->transportt)->f->smp_handler) { | 202 | if (!to_sas_internal(shost->transportt)->f->smp_handler) { |
201 | printk("%s can't handle SMP requests\n", shost->hostt->name); | 203 | printk("%s can't handle SMP requests\n", shost->hostt->name); |
202 | return 0; | 204 | return 0; |
203 | } | 205 | } |
204 | 206 | ||
205 | if (rphy) | 207 | if (rphy) { |
206 | q = blk_init_queue(sas_non_host_smp_request, NULL); | 208 | q = blk_init_queue(sas_non_host_smp_request, NULL); |
207 | else | 209 | dev = &rphy->dev; |
210 | name = dev->bus_id; | ||
211 | } else { | ||
208 | q = blk_init_queue(sas_host_smp_request, NULL); | 212 | q = blk_init_queue(sas_host_smp_request, NULL); |
213 | dev = &shost->shost_gendev; | ||
214 | snprintf(namebuf, sizeof(namebuf), | ||
215 | "sas_host%d", shost->host_no); | ||
216 | name = namebuf; | ||
217 | } | ||
209 | if (!q) | 218 | if (!q) |
210 | return -ENOMEM; | 219 | return -ENOMEM; |
211 | 220 | ||
212 | error = bsg_register_queue(q, name); | 221 | error = bsg_register_queue(q, dev, name); |
213 | if (error) { | 222 | if (error) { |
214 | blk_cleanup_queue(q); | 223 | blk_cleanup_queue(q); |
215 | return -ENOMEM; | 224 | return -ENOMEM; |
@@ -255,7 +264,6 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev, | |||
255 | { | 264 | { |
256 | struct Scsi_Host *shost = dev_to_shost(dev); | 265 | struct Scsi_Host *shost = dev_to_shost(dev); |
257 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); | 266 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); |
258 | char name[BUS_ID_SIZE]; | ||
259 | 267 | ||
260 | INIT_LIST_HEAD(&sas_host->rphy_list); | 268 | INIT_LIST_HEAD(&sas_host->rphy_list); |
261 | mutex_init(&sas_host->lock); | 269 | mutex_init(&sas_host->lock); |
@@ -263,8 +271,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev, | |||
263 | sas_host->next_expander_id = 0; | 271 | sas_host->next_expander_id = 0; |
264 | sas_host->next_port_id = 0; | 272 | sas_host->next_port_id = 0; |
265 | 273 | ||
266 | snprintf(name, sizeof(name), "sas_host%d", shost->host_no); | 274 | if (sas_bsg_initialize(shost, NULL)) |
267 | if (sas_bsg_initialize(shost, NULL, name)) | ||
268 | dev_printk(KERN_ERR, dev, "fail to a bsg device %d\n", | 275 | dev_printk(KERN_ERR, dev, "fail to a bsg device %d\n", |
269 | shost->host_no); | 276 | shost->host_no); |
270 | 277 | ||
@@ -1332,9 +1339,6 @@ struct sas_rphy *sas_end_device_alloc(struct sas_port *parent) | |||
1332 | sas_rphy_initialize(&rdev->rphy); | 1339 | sas_rphy_initialize(&rdev->rphy); |
1333 | transport_setup_device(&rdev->rphy.dev); | 1340 | transport_setup_device(&rdev->rphy.dev); |
1334 | 1341 | ||
1335 | if (sas_bsg_initialize(shost, &rdev->rphy, rdev->rphy.dev.bus_id)) | ||
1336 | printk("fail to a bsg device %s\n", rdev->rphy.dev.bus_id); | ||
1337 | |||
1338 | return &rdev->rphy; | 1342 | return &rdev->rphy; |
1339 | } | 1343 | } |
1340 | EXPORT_SYMBOL(sas_end_device_alloc); | 1344 | EXPORT_SYMBOL(sas_end_device_alloc); |
@@ -1374,9 +1378,6 @@ struct sas_rphy *sas_expander_alloc(struct sas_port *parent, | |||
1374 | sas_rphy_initialize(&rdev->rphy); | 1378 | sas_rphy_initialize(&rdev->rphy); |
1375 | transport_setup_device(&rdev->rphy.dev); | 1379 | transport_setup_device(&rdev->rphy.dev); |
1376 | 1380 | ||
1377 | if (sas_bsg_initialize(shost, &rdev->rphy, rdev->rphy.dev.bus_id)) | ||
1378 | printk("fail to a bsg device %s\n", rdev->rphy.dev.bus_id); | ||
1379 | |||
1380 | return &rdev->rphy; | 1381 | return &rdev->rphy; |
1381 | } | 1382 | } |
1382 | EXPORT_SYMBOL(sas_expander_alloc); | 1383 | EXPORT_SYMBOL(sas_expander_alloc); |
@@ -1404,6 +1405,9 @@ int sas_rphy_add(struct sas_rphy *rphy) | |||
1404 | return error; | 1405 | return error; |
1405 | transport_add_device(&rphy->dev); | 1406 | transport_add_device(&rphy->dev); |
1406 | transport_configure_device(&rphy->dev); | 1407 | transport_configure_device(&rphy->dev); |
1408 | if (sas_bsg_initialize(shost, rphy)) | ||
1409 | printk("fail to a bsg device %s\n", rphy->dev.bus_id); | ||
1410 | |||
1407 | 1411 | ||
1408 | mutex_lock(&sas_host->lock); | 1412 | mutex_lock(&sas_host->lock); |
1409 | list_add_tail(&rphy->list, &sas_host->rphy_list); | 1413 | list_add_tail(&rphy->list, &sas_host->rphy_list); |
diff --git a/include/linux/bsg.h b/include/linux/bsg.h index 8547b10c388..f415f89e0ac 100644 --- a/include/linux/bsg.h +++ b/include/linux/bsg.h | |||
@@ -57,10 +57,10 @@ struct bsg_class_device { | |||
57 | struct request_queue *queue; | 57 | struct request_queue *queue; |
58 | }; | 58 | }; |
59 | 59 | ||
60 | extern int bsg_register_queue(struct request_queue *, const char *); | 60 | extern int bsg_register_queue(struct request_queue *, struct device *, const char *); |
61 | extern void bsg_unregister_queue(struct request_queue *); | 61 | extern void bsg_unregister_queue(struct request_queue *); |
62 | #else | 62 | #else |
63 | #define bsg_register_queue(disk, name) (0) | 63 | #define bsg_register_queue(disk, dev, name) (0) |
64 | #define bsg_unregister_queue(disk) do { } while (0) | 64 | #define bsg_unregister_queue(disk) do { } while (0) |
65 | #endif | 65 | #endif |
66 | 66 | ||