Skip to content

Commit

Permalink
[SCSI] bsg: make class backlinks
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: James Bottomley <[email protected]>
  • Loading branch information
James Bottomley authored and James Bottomley committed Jul 21, 2007
1 parent 0e78d15 commit 39dca55
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 21 deletions.
21 changes: 17 additions & 4 deletions block/bsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -936,20 +936,29 @@ void bsg_unregister_queue(struct request_queue *q)

mutex_lock(&bsg_mutex);
sysfs_remove_link(&q->kobj, "bsg");
class_device_destroy(bsg_class, MKDEV(bsg_major, bcd->minor));
class_device_unregister(bcd->class_dev);
put_device(bcd->dev);
bcd->class_dev = NULL;
bcd->dev = NULL;
list_del_init(&bcd->list);
bsg_device_nr--;
mutex_unlock(&bsg_mutex);
}
EXPORT_SYMBOL_GPL(bsg_unregister_queue);

int bsg_register_queue(struct request_queue *q, const char *name)
int bsg_register_queue(struct request_queue *q, struct device *gdev,
const char *name)
{
struct bsg_class_device *bcd, *__bcd;
dev_t dev;
int ret = -EMFILE;
struct class_device *class_dev = NULL;
const char *devname;

if (name)
devname = name;
else
devname = gdev->bus_id;

/*
* we need a proper transport to send commands, not a stacked device
Expand Down Expand Up @@ -982,11 +991,13 @@ int bsg_register_queue(struct request_queue *q, const char *name)
bsg_minor_idx = 0;

bcd->queue = q;
bcd->dev = get_device(gdev);
dev = MKDEV(bsg_major, bcd->minor);
class_dev = class_device_create(bsg_class, NULL, dev, bcd->dev, "%s", name);
class_dev = class_device_create(bsg_class, NULL, dev, gdev, "%s",
devname);
if (IS_ERR(class_dev)) {
ret = PTR_ERR(class_dev);
goto err;
goto err_put;
}
bcd->class_dev = class_dev;

Expand All @@ -1004,6 +1015,8 @@ int bsg_register_queue(struct request_queue *q, const char *name)

err_unregister:
class_device_unregister(class_dev);
err_put:
put_device(gdev);
err:
mutex_unlock(&bsg_mutex);
return ret;
Expand Down
2 changes: 1 addition & 1 deletion drivers/scsi/scsi_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
* released by the sdev_class .release */
get_device(&sdev->sdev_gendev);

error = bsg_register_queue(rq, sdev->sdev_gendev.bus_id);
error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL);

if (error)
sdev_printk(KERN_INFO, sdev,
Expand Down
32 changes: 18 additions & 14 deletions drivers/scsi/scsi_transport_sas.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,25 +191,34 @@ static void sas_non_host_smp_request(struct request_queue *q)
sas_smp_request(q, rphy_to_shost(rphy), rphy);
}

static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy,
char *name)
static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
{
struct request_queue *q;
int error;
struct device *dev;
char namebuf[BUS_ID_SIZE];
const char *name;

if (!to_sas_internal(shost->transportt)->f->smp_handler) {
printk("%s can't handle SMP requests\n", shost->hostt->name);
return 0;
}

if (rphy)
if (rphy) {
q = blk_init_queue(sas_non_host_smp_request, NULL);
else
dev = &rphy->dev;
name = dev->bus_id;
} else {
q = blk_init_queue(sas_host_smp_request, NULL);
dev = &shost->shost_gendev;
snprintf(namebuf, sizeof(namebuf),
"sas_host%d", shost->host_no);
name = namebuf;
}
if (!q)
return -ENOMEM;

error = bsg_register_queue(q, name);
error = bsg_register_queue(q, dev, name);
if (error) {
blk_cleanup_queue(q);
return -ENOMEM;
Expand Down Expand Up @@ -255,16 +264,14 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev,
{
struct Scsi_Host *shost = dev_to_shost(dev);
struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
char name[BUS_ID_SIZE];

INIT_LIST_HEAD(&sas_host->rphy_list);
mutex_init(&sas_host->lock);
sas_host->next_target_id = 0;
sas_host->next_expander_id = 0;
sas_host->next_port_id = 0;

snprintf(name, sizeof(name), "sas_host%d", shost->host_no);
if (sas_bsg_initialize(shost, NULL, name))
if (sas_bsg_initialize(shost, NULL))
dev_printk(KERN_ERR, dev, "fail to a bsg device %d\n",
shost->host_no);

Expand Down Expand Up @@ -1332,9 +1339,6 @@ struct sas_rphy *sas_end_device_alloc(struct sas_port *parent)
sas_rphy_initialize(&rdev->rphy);
transport_setup_device(&rdev->rphy.dev);

if (sas_bsg_initialize(shost, &rdev->rphy, rdev->rphy.dev.bus_id))
printk("fail to a bsg device %s\n", rdev->rphy.dev.bus_id);

return &rdev->rphy;
}
EXPORT_SYMBOL(sas_end_device_alloc);
Expand Down Expand Up @@ -1374,9 +1378,6 @@ struct sas_rphy *sas_expander_alloc(struct sas_port *parent,
sas_rphy_initialize(&rdev->rphy);
transport_setup_device(&rdev->rphy.dev);

if (sas_bsg_initialize(shost, &rdev->rphy, rdev->rphy.dev.bus_id))
printk("fail to a bsg device %s\n", rdev->rphy.dev.bus_id);

return &rdev->rphy;
}
EXPORT_SYMBOL(sas_expander_alloc);
Expand Down Expand Up @@ -1404,6 +1405,9 @@ int sas_rphy_add(struct sas_rphy *rphy)
return error;
transport_add_device(&rphy->dev);
transport_configure_device(&rphy->dev);
if (sas_bsg_initialize(shost, rphy))
printk("fail to a bsg device %s\n", rphy->dev.bus_id);


mutex_lock(&sas_host->lock);
list_add_tail(&rphy->list, &sas_host->rphy_list);
Expand Down
4 changes: 2 additions & 2 deletions include/linux/bsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ struct bsg_class_device {
struct request_queue *queue;
};

extern int bsg_register_queue(struct request_queue *, const char *);
extern int bsg_register_queue(struct request_queue *, struct device *, const char *);
extern void bsg_unregister_queue(struct request_queue *);
#else
#define bsg_register_queue(disk, name) (0)
#define bsg_register_queue(disk, dev, name) (0)
#define bsg_unregister_queue(disk) do { } while (0)
#endif

Expand Down

0 comments on commit 39dca55

Please sign in to comment.