diff options
author | Jeff Mahoney <jeffm@suse.de> | 2012-08-18 15:20:40 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-09-14 12:59:29 -0400 |
commit | 26898afd67dfd707aa291648ca731063c8333c7f (patch) | |
tree | e4cc7b2d58df67319c90995e9deeb847669ca046 /drivers/scsi | |
parent | 6c648d95a6af4a79241a916871df17c84c68ea20 (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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/st.c | 195 | ||||
-rw-r--r-- | drivers/scsi/st.h | 1 |
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 *); | |||
193 | 193 | ||
194 | static int do_create_sysfs_files(void); | 194 | static int do_create_sysfs_files(void); |
195 | static void do_remove_sysfs_files(void); | 195 | static void do_remove_sysfs_files(void); |
196 | static int do_create_class_files(struct scsi_tape *, int, int); | ||
197 | 196 | ||
198 | static struct scsi_driver st_template = { | 197 | static struct scsi_driver st_template = { |
199 | .owner = THIS_MODULE, | 198 | .owner = THIS_MODULE, |
@@ -3990,16 +3989,98 @@ static const struct file_operations st_fops = | |||
3990 | .llseek = noop_llseek, | 3989 | .llseek = noop_llseek, |
3991 | }; | 3990 | }; |
3992 | 3991 | ||
3992 | static int create_one_cdev(struct scsi_tape *tape, int mode, int rew) | ||
3993 | { | ||
3994 | int i, error; | ||
3995 | dev_t cdev_devno; | ||
3996 | struct cdev *cdev; | ||
3997 | struct device *dev; | ||
3998 | struct st_modedef *STm = &(tape->modes[mode]); | ||
3999 | char name[10]; | ||
4000 | int dev_num = tape->index; | ||
4001 | |||
4002 | cdev_devno = MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, rew)); | ||
4003 | |||
4004 | cdev = cdev_alloc(); | ||
4005 | if (!cdev) { | ||
4006 | pr_err("st%d: out of memory. Device not attached.\n", dev_num); | ||
4007 | error = -ENOMEM; | ||
4008 | goto out; | ||
4009 | } | ||
4010 | cdev->owner = THIS_MODULE; | ||
4011 | cdev->ops = &st_fops; | ||
4012 | |||
4013 | error = cdev_add(cdev, cdev_devno, 1); | ||
4014 | if (error) { | ||
4015 | pr_err("st%d: Can't add %s-rewind mode %d\n", dev_num, | ||
4016 | rew ? "non" : "auto", mode); | ||
4017 | pr_err("st%d: Device not attached.\n", dev_num); | ||
4018 | goto out_free; | ||
4019 | } | ||
4020 | STm->cdevs[rew] = cdev; | ||
4021 | |||
4022 | i = mode << (4 - ST_NBR_MODE_BITS); | ||
4023 | snprintf(name, 10, "%s%s%s", rew ? "n" : "", | ||
4024 | tape->disk->disk_name, st_formats[i]); | ||
4025 | |||
4026 | dev = device_create(&st_sysfs_class, &tape->device->sdev_gendev, | ||
4027 | cdev_devno, &tape->modes[mode], "%s", name); | ||
4028 | if (IS_ERR(dev)) { | ||
4029 | pr_err("st%d: device_create failed\n", dev_num); | ||
4030 | error = PTR_ERR(dev); | ||
4031 | goto out_free; | ||
4032 | } | ||
4033 | |||
4034 | STm->devs[rew] = dev; | ||
4035 | |||
4036 | return 0; | ||
4037 | out_free: | ||
4038 | cdev_del(STm->cdevs[rew]); | ||
4039 | STm->cdevs[rew] = NULL; | ||
4040 | out: | ||
4041 | return error; | ||
4042 | } | ||
4043 | |||
4044 | static int create_cdevs(struct scsi_tape *tape) | ||
4045 | { | ||
4046 | int mode, error; | ||
4047 | for (mode = 0; mode < ST_NBR_MODES; ++mode) { | ||
4048 | error = create_one_cdev(tape, mode, 0); | ||
4049 | if (error) | ||
4050 | return error; | ||
4051 | error = create_one_cdev(tape, mode, 1); | ||
4052 | if (error) | ||
4053 | return error; | ||
4054 | } | ||
4055 | |||
4056 | return sysfs_create_link(&tape->device->sdev_gendev.kobj, | ||
4057 | &tape->modes[0].devs[0]->kobj, "tape"); | ||
4058 | } | ||
4059 | |||
4060 | static void remove_cdevs(struct scsi_tape *tape) | ||
4061 | { | ||
4062 | int mode, rew; | ||
4063 | sysfs_remove_link(&tape->device->sdev_gendev.kobj, "tape"); | ||
4064 | for (mode = 0; mode < ST_NBR_MODES; mode++) { | ||
4065 | struct st_modedef *STm = &(tape->modes[mode]); | ||
4066 | for (rew = 0; rew < 2; rew++) { | ||
4067 | if (STm->cdevs[rew]) | ||
4068 | cdev_del(STm->cdevs[rew]); | ||
4069 | if (STm->devs[rew]) | ||
4070 | device_unregister(STm->devs[rew]); | ||
4071 | } | ||
4072 | } | ||
4073 | } | ||
4074 | |||
3993 | static int st_probe(struct device *dev) | 4075 | static int st_probe(struct device *dev) |
3994 | { | 4076 | { |
3995 | struct scsi_device *SDp = to_scsi_device(dev); | 4077 | struct scsi_device *SDp = to_scsi_device(dev); |
3996 | struct gendisk *disk = NULL; | 4078 | struct gendisk *disk = NULL; |
3997 | struct cdev *cdev = NULL; | ||
3998 | struct scsi_tape *tpnt = NULL; | 4079 | struct scsi_tape *tpnt = NULL; |
3999 | struct st_modedef *STm; | 4080 | struct st_modedef *STm; |
4000 | struct st_partstat *STps; | 4081 | struct st_partstat *STps; |
4001 | struct st_buffer *buffer; | 4082 | struct st_buffer *buffer; |
4002 | int i, j, mode, dev_num, error; | 4083 | int i, dev_num, error; |
4003 | char *stp; | 4084 | char *stp; |
4004 | 4085 | ||
4005 | if (SDp->type != TYPE_TAPE) | 4086 | if (SDp->type != TYPE_TAPE) |
@@ -4125,36 +4206,10 @@ static int st_probe(struct device *dev) | |||
4125 | 4206 | ||
4126 | dev_set_drvdata(dev, tpnt); | 4207 | dev_set_drvdata(dev, tpnt); |
4127 | 4208 | ||
4128 | for (mode = 0; mode < ST_NBR_MODES; ++mode) { | ||
4129 | STm = &(tpnt->modes[mode]); | ||
4130 | for (j=0; j < 2; j++) { | ||
4131 | cdev = cdev_alloc(); | ||
4132 | if (!cdev) { | ||
4133 | printk(KERN_ERR | ||
4134 | "st%d: out of memory. Device not attached.\n", | ||
4135 | dev_num); | ||
4136 | cdev_del(cdev); | ||
4137 | goto out_free_tape; | ||
4138 | } | ||
4139 | cdev->owner = THIS_MODULE; | ||
4140 | cdev->ops = &st_fops; | ||
4141 | |||
4142 | error = cdev_add(cdev, | ||
4143 | MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, j)), | ||
4144 | 1); | ||
4145 | if (error) { | ||
4146 | printk(KERN_ERR "st%d: Can't add %s-rewind mode %d\n", | ||
4147 | dev_num, j ? "non" : "auto", mode); | ||
4148 | printk(KERN_ERR "st%d: Device not attached.\n", dev_num); | ||
4149 | goto out_free_tape; | ||
4150 | } | ||
4151 | STm->cdevs[j] = cdev; | ||
4152 | 4209 | ||
4153 | } | 4210 | error = create_cdevs(tpnt); |
4154 | error = do_create_class_files(tpnt, dev_num, mode); | 4211 | if (error) |
4155 | if (error) | 4212 | goto out_remove_devs; |
4156 | goto out_free_tape; | ||
4157 | } | ||
4158 | scsi_autopm_put_device(SDp); | 4213 | scsi_autopm_put_device(SDp); |
4159 | 4214 | ||
4160 | sdev_printk(KERN_NOTICE, SDp, | 4215 | sdev_printk(KERN_NOTICE, SDp, |
@@ -4165,20 +4220,8 @@ static int st_probe(struct device *dev) | |||
4165 | 4220 | ||
4166 | return 0; | 4221 | return 0; |
4167 | 4222 | ||
4168 | out_free_tape: | 4223 | out_remove_devs: |
4169 | sysfs_remove_link(&tpnt->device->sdev_gendev.kobj, | 4224 | remove_cdevs(tpnt); |
4170 | "tape"); | ||
4171 | for (mode=0; mode < ST_NBR_MODES; mode++) { | ||
4172 | STm = &(tpnt->modes[mode]); | ||
4173 | for (j=0; j < 2; j++) { | ||
4174 | if (STm->cdevs[j]) { | ||
4175 | device_destroy(&st_sysfs_class, | ||
4176 | MKDEV(SCSI_TAPE_MAJOR, | ||
4177 | TAPE_MINOR(i, mode, j))); | ||
4178 | cdev_del(STm->cdevs[j]); | ||
4179 | } | ||
4180 | } | ||
4181 | } | ||
4182 | out_put_index: | 4225 | out_put_index: |
4183 | spin_lock(&st_index_lock); | 4226 | spin_lock(&st_index_lock); |
4184 | idr_remove(&st_index_idr, dev_num); | 4227 | idr_remove(&st_index_idr, dev_num); |
@@ -4196,24 +4239,10 @@ out: | |||
4196 | static int st_remove(struct device *dev) | 4239 | static int st_remove(struct device *dev) |
4197 | { | 4240 | { |
4198 | struct scsi_tape *tpnt = dev_get_drvdata(dev); | 4241 | struct scsi_tape *tpnt = dev_get_drvdata(dev); |
4199 | int rew, mode; | ||
4200 | dev_t cdev_devno; | ||
4201 | struct cdev *cdev; | ||
4202 | int index = tpnt->index; | 4242 | int index = tpnt->index; |
4203 | 4243 | ||
4204 | scsi_autopm_get_device(to_scsi_device(dev)); | 4244 | scsi_autopm_get_device(to_scsi_device(dev)); |
4205 | sysfs_remove_link(&tpnt->device->sdev_gendev.kobj, "tape"); | 4245 | remove_cdevs(tpnt); |
4206 | for (mode = 0; mode < ST_NBR_MODES; ++mode) { | ||
4207 | for (rew = 0; rew < 2; rew++) { | ||
4208 | cdev = tpnt->modes[mode].cdevs[rew]; | ||
4209 | if (!cdev) | ||
4210 | continue; | ||
4211 | cdev_devno = cdev->dev; | ||
4212 | device_destroy(&st_sysfs_class, cdev_devno); | ||
4213 | cdev_del(tpnt->modes[mode].cdevs[rew]); | ||
4214 | tpnt->modes[mode].cdevs[rew] = NULL; | ||
4215 | } | ||
4216 | } | ||
4217 | 4246 | ||
4218 | mutex_lock(&st_ref_mutex); | 4247 | mutex_lock(&st_ref_mutex); |
4219 | kref_put(&tpnt->kref, scsi_tape_release); | 4248 | kref_put(&tpnt->kref, scsi_tape_release); |
@@ -4462,50 +4491,6 @@ static struct device_attribute st_dev_attrs[] = { | |||
4462 | __ATTR_NULL, | 4491 | __ATTR_NULL, |
4463 | }; | 4492 | }; |
4464 | 4493 | ||
4465 | static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode) | ||
4466 | { | ||
4467 | int i, rew, error; | ||
4468 | char name[10]; | ||
4469 | struct device *st_class_member; | ||
4470 | |||
4471 | for (rew=0; rew < 2; rew++) { | ||
4472 | /* Make sure that the minor numbers corresponding to the four | ||
4473 | first modes always get the same names */ | ||
4474 | i = mode << (4 - ST_NBR_MODE_BITS); | ||
4475 | snprintf(name, 10, "%s%s%s", rew ? "n" : "", | ||
4476 | STp->disk->disk_name, st_formats[i]); | ||
4477 | st_class_member = | ||
4478 | device_create(&st_sysfs_class, | ||
4479 | &STp->device->sdev_gendev, | ||
4480 | MKDEV(SCSI_TAPE_MAJOR, | ||
4481 | TAPE_MINOR(dev_num, mode, rew)), | ||
4482 | &STp->modes[mode], "%s", name); | ||
4483 | if (IS_ERR(st_class_member)) { | ||
4484 | printk(KERN_WARNING "st%d: device_create failed\n", | ||
4485 | dev_num); | ||
4486 | error = PTR_ERR(st_class_member); | ||
4487 | goto out; | ||
4488 | } | ||
4489 | |||
4490 | if (mode == 0 && rew == 0) { | ||
4491 | error = sysfs_create_link(&STp->device->sdev_gendev.kobj, | ||
4492 | &st_class_member->kobj, | ||
4493 | "tape"); | ||
4494 | if (error) { | ||
4495 | printk(KERN_ERR | ||
4496 | "st%d: Can't create sysfs link from SCSI device.\n", | ||
4497 | dev_num); | ||
4498 | goto out; | ||
4499 | } | ||
4500 | } | ||
4501 | } | ||
4502 | |||
4503 | return 0; | ||
4504 | |||
4505 | out: | ||
4506 | return error; | ||
4507 | } | ||
4508 | |||
4509 | /* The following functions may be useful for a larger audience. */ | 4494 | /* The following functions may be useful for a larger audience. */ |
4510 | static int sgl_map_user_pages(struct st_buffer *STbp, | 4495 | static int sgl_map_user_pages(struct st_buffer *STbp, |
4511 | const unsigned int max_pages, unsigned long uaddr, | 4496 | 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 { | |||
67 | short default_density; /* Forced density, -1 = no value */ | 67 | short default_density; /* Forced density, -1 = no value */ |
68 | int default_blksize; /* Forced blocksize, -1 = no value */ | 68 | int default_blksize; /* Forced blocksize, -1 = no value */ |
69 | struct scsi_tape *tape; | 69 | struct scsi_tape *tape; |
70 | struct device *devs[2]; /* Auto-rewind and non-rewind devices */ | ||
70 | struct cdev *cdevs[2]; /* Auto-rewind and non-rewind devices */ | 71 | struct cdev *cdevs[2]; /* Auto-rewind and non-rewind devices */ |
71 | }; | 72 | }; |
72 | 73 | ||