summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.de>2012-08-18 15:20:40 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-09-14 17:59:29 +0100
commit26898afd67dfd707aa291648ca731063c8333c7f (patch)
treee4cc7b2d58df67319c90995e9deeb847669ca046
parent6c648d95a6af4a79241a916871df17c84c68ea20 (diff)
[SCSI] st: clean up device file creation and removal
This patch cleans up the st device file creation and removal. Reviewed-by: Lee Duncan <lduncan@suse.com> Signed-off-by: Jeff Mahoney <jeffm@suse.com> Acked-by: Kai Mäkisara <kai.makisara@kolumbus.fi> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/st.c195
-rw-r--r--drivers/scsi/st.h1
2 files changed, 91 insertions, 105 deletions
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 052622fdba02..ceca095e5d8d 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -193,7 +193,6 @@ static int st_remove(struct device *);
static int do_create_sysfs_files(void);
static void do_remove_sysfs_files(void);
-static int do_create_class_files(struct scsi_tape *, int, int);
static struct scsi_driver st_template = {
.owner = THIS_MODULE,
@@ -3990,16 +3989,98 @@ static const struct file_operations st_fops =
.llseek = noop_llseek,
};
+static int create_one_cdev(struct scsi_tape *tape, int mode, int rew)
+{
+ int i, error;
+ dev_t cdev_devno;
+ struct cdev *cdev;
+ struct device *dev;
+ struct st_modedef *STm = &(tape->modes[mode]);
+ char name[10];
+ int dev_num = tape->index;
+
+ cdev_devno = MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, rew));
+
+ cdev = cdev_alloc();
+ if (!cdev) {
+ pr_err("st%d: out of memory. Device not attached.\n", dev_num);
+ error = -ENOMEM;
+ goto out;
+ }
+ cdev->owner = THIS_MODULE;
+ cdev->ops = &st_fops;
+
+ error = cdev_add(cdev, cdev_devno, 1);
+ if (error) {
+ pr_err("st%d: Can't add %s-rewind mode %d\n", dev_num,
+ rew ? "non" : "auto", mode);
+ pr_err("st%d: Device not attached.\n", dev_num);
+ goto out_free;
+ }
+ STm->cdevs[rew] = cdev;
+
+ i = mode << (4 - ST_NBR_MODE_BITS);
+ snprintf(name, 10, "%s%s%s", rew ? "n" : "",
+ tape->disk->disk_name, st_formats[i]);
+
+ dev = device_create(&st_sysfs_class, &tape->device->sdev_gendev,
+ cdev_devno, &tape->modes[mode], "%s", name);
+ if (IS_ERR(dev)) {
+ pr_err("st%d: device_create failed\n", dev_num);
+ error = PTR_ERR(dev);
+ goto out_free;
+ }
+
+ STm->devs[rew] = dev;
+
+ return 0;
+out_free:
+ cdev_del(STm->cdevs[rew]);
+ STm->cdevs[rew] = NULL;
+out:
+ return error;
+}
+
+static int create_cdevs(struct scsi_tape *tape)
+{
+ int mode, error;
+ for (mode = 0; mode < ST_NBR_MODES; ++mode) {
+ error = create_one_cdev(tape, mode, 0);
+ if (error)
+ return error;
+ error = create_one_cdev(tape, mode, 1);
+ if (error)
+ return error;
+ }
+
+ return sysfs_create_link(&tape->device->sdev_gendev.kobj,
+ &tape->modes[0].devs[0]->kobj, "tape");
+}
+
+static void remove_cdevs(struct scsi_tape *tape)
+{
+ int mode, rew;
+ sysfs_remove_link(&tape->device->sdev_gendev.kobj, "tape");
+ for (mode = 0; mode < ST_NBR_MODES; mode++) {
+ struct st_modedef *STm = &(tape->modes[mode]);
+ for (rew = 0; rew < 2; rew++) {
+ if (STm->cdevs[rew])
+ cdev_del(STm->cdevs[rew]);
+ if (STm->devs[rew])
+ device_unregister(STm->devs[rew]);
+ }
+ }
+}
+
static int st_probe(struct device *dev)
{
struct scsi_device *SDp = to_scsi_device(dev);
struct gendisk *disk = NULL;
- struct cdev *cdev = NULL;
struct scsi_tape *tpnt = NULL;
struct st_modedef *STm;
struct st_partstat *STps;
struct st_buffer *buffer;
- int i, j, mode, dev_num, error;
+ int i, dev_num, error;
char *stp;
if (SDp->type != TYPE_TAPE)
@@ -4125,36 +4206,10 @@ static int st_probe(struct device *dev)
dev_set_drvdata(dev, tpnt);
- for (mode = 0; mode < ST_NBR_MODES; ++mode) {
- STm = &(tpnt->modes[mode]);
- for (j=0; j < 2; j++) {
- cdev = cdev_alloc();
- if (!cdev) {
- printk(KERN_ERR
- "st%d: out of memory. Device not attached.\n",
- dev_num);
- cdev_del(cdev);
- goto out_free_tape;
- }
- cdev->owner = THIS_MODULE;
- cdev->ops = &st_fops;
-
- error = cdev_add(cdev,
- MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, j)),
- 1);
- if (error) {
- printk(KERN_ERR "st%d: Can't add %s-rewind mode %d\n",
- dev_num, j ? "non" : "auto", mode);
- printk(KERN_ERR "st%d: Device not attached.\n", dev_num);
- goto out_free_tape;
- }
- STm->cdevs[j] = cdev;
- }
- error = do_create_class_files(tpnt, dev_num, mode);
- if (error)
- goto out_free_tape;
- }
+ error = create_cdevs(tpnt);
+ if (error)
+ goto out_remove_devs;
scsi_autopm_put_device(SDp);
sdev_printk(KERN_NOTICE, SDp,
@@ -4165,20 +4220,8 @@ static int st_probe(struct device *dev)
return 0;
-out_free_tape:
- sysfs_remove_link(&tpnt->device->sdev_gendev.kobj,
- "tape");
- for (mode=0; mode < ST_NBR_MODES; mode++) {
- STm = &(tpnt->modes[mode]);
- for (j=0; j < 2; j++) {
- if (STm->cdevs[j]) {
- device_destroy(&st_sysfs_class,
- MKDEV(SCSI_TAPE_MAJOR,
- TAPE_MINOR(i, mode, j)));
- cdev_del(STm->cdevs[j]);
- }
- }
- }
+out_remove_devs:
+ remove_cdevs(tpnt);
out_put_index:
spin_lock(&st_index_lock);
idr_remove(&st_index_idr, dev_num);
@@ -4196,24 +4239,10 @@ out:
static int st_remove(struct device *dev)
{
struct scsi_tape *tpnt = dev_get_drvdata(dev);
- int rew, mode;
- dev_t cdev_devno;
- struct cdev *cdev;
int index = tpnt->index;
scsi_autopm_get_device(to_scsi_device(dev));
- sysfs_remove_link(&tpnt->device->sdev_gendev.kobj, "tape");
- for (mode = 0; mode < ST_NBR_MODES; ++mode) {
- for (rew = 0; rew < 2; rew++) {
- cdev = tpnt->modes[mode].cdevs[rew];
- if (!cdev)
- continue;
- cdev_devno = cdev->dev;
- device_destroy(&st_sysfs_class, cdev_devno);
- cdev_del(tpnt->modes[mode].cdevs[rew]);
- tpnt->modes[mode].cdevs[rew] = NULL;
- }
- }
+ remove_cdevs(tpnt);
mutex_lock(&st_ref_mutex);
kref_put(&tpnt->kref, scsi_tape_release);
@@ -4462,50 +4491,6 @@ static struct device_attribute st_dev_attrs[] = {
__ATTR_NULL,
};
-static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
-{
- int i, rew, error;
- char name[10];
- struct device *st_class_member;
-
- for (rew=0; rew < 2; rew++) {
- /* Make sure that the minor numbers corresponding to the four
- first modes always get the same names */
- i = mode << (4 - ST_NBR_MODE_BITS);
- snprintf(name, 10, "%s%s%s", rew ? "n" : "",
- STp->disk->disk_name, st_formats[i]);
- st_class_member =
- device_create(&st_sysfs_class,
- &STp->device->sdev_gendev,
- MKDEV(SCSI_TAPE_MAJOR,
- TAPE_MINOR(dev_num, mode, rew)),
- &STp->modes[mode], "%s", name);
- if (IS_ERR(st_class_member)) {
- printk(KERN_WARNING "st%d: device_create failed\n",
- dev_num);
- error = PTR_ERR(st_class_member);
- goto out;
- }
-
- if (mode == 0 && rew == 0) {
- error = sysfs_create_link(&STp->device->sdev_gendev.kobj,
- &st_class_member->kobj,
- "tape");
- if (error) {
- printk(KERN_ERR
- "st%d: Can't create sysfs link from SCSI device.\n",
- dev_num);
- goto out;
- }
- }
- }
-
- return 0;
-
-out:
- return error;
-}
-
/* The following functions may be useful for a larger audience. */
static int sgl_map_user_pages(struct st_buffer *STbp,
const unsigned int max_pages, unsigned long uaddr,
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index 8a23640981c8..b7a07c7bf4f8 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -67,6 +67,7 @@ struct st_modedef {
short default_density; /* Forced density, -1 = no value */
int default_blksize; /* Forced blocksize, -1 = no value */
struct scsi_tape *tape;
+ struct device *devs[2]; /* Auto-rewind and non-rewind devices */
struct cdev *cdevs[2]; /* Auto-rewind and non-rewind devices */
};