diff options
Diffstat (limited to 'drivers/uio/uio.c')
-rw-r--r-- | drivers/uio/uio.c | 95 |
1 files changed, 50 insertions, 45 deletions
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 865f32b63b5c..cc246faa3590 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c | |||
@@ -34,12 +34,12 @@ struct uio_device { | |||
34 | wait_queue_head_t wait; | 34 | wait_queue_head_t wait; |
35 | int vma_count; | 35 | int vma_count; |
36 | struct uio_info *info; | 36 | struct uio_info *info; |
37 | struct kset map_attr_kset; | 37 | struct kobject *map_dir; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | static int uio_major; | 40 | static int uio_major; |
41 | static DEFINE_IDR(uio_idr); | 41 | static DEFINE_IDR(uio_idr); |
42 | static struct file_operations uio_fops; | 42 | static const struct file_operations uio_fops; |
43 | 43 | ||
44 | /* UIO class infrastructure */ | 44 | /* UIO class infrastructure */ |
45 | static struct uio_class { | 45 | static struct uio_class { |
@@ -51,47 +51,48 @@ static struct uio_class { | |||
51 | * attributes | 51 | * attributes |
52 | */ | 52 | */ |
53 | 53 | ||
54 | static struct attribute attr_addr = { | 54 | struct uio_map { |
55 | .name = "addr", | 55 | struct kobject kobj; |
56 | .mode = S_IRUGO, | 56 | struct uio_mem *mem; |
57 | }; | 57 | }; |
58 | #define to_map(map) container_of(map, struct uio_map, kobj) | ||
58 | 59 | ||
59 | static struct attribute attr_size = { | ||
60 | .name = "size", | ||
61 | .mode = S_IRUGO, | ||
62 | }; | ||
63 | 60 | ||
64 | static struct attribute* map_attrs[] = { | 61 | static ssize_t map_attr_show(struct kobject *kobj, struct kobj_attribute *attr, |
65 | &attr_addr, &attr_size, NULL | ||
66 | }; | ||
67 | |||
68 | static ssize_t map_attr_show(struct kobject *kobj, struct attribute *attr, | ||
69 | char *buf) | 62 | char *buf) |
70 | { | 63 | { |
71 | struct uio_mem *mem = container_of(kobj, struct uio_mem, kobj); | 64 | struct uio_map *map = to_map(kobj); |
65 | struct uio_mem *mem = map->mem; | ||
72 | 66 | ||
73 | if (strncmp(attr->name,"addr",4) == 0) | 67 | if (strncmp(attr->attr.name, "addr", 4) == 0) |
74 | return sprintf(buf, "0x%lx\n", mem->addr); | 68 | return sprintf(buf, "0x%lx\n", mem->addr); |
75 | 69 | ||
76 | if (strncmp(attr->name,"size",4) == 0) | 70 | if (strncmp(attr->attr.name, "size", 4) == 0) |
77 | return sprintf(buf, "0x%lx\n", mem->size); | 71 | return sprintf(buf, "0x%lx\n", mem->size); |
78 | 72 | ||
79 | return -ENODEV; | 73 | return -ENODEV; |
80 | } | 74 | } |
81 | 75 | ||
82 | static void map_attr_release(struct kobject *kobj) | 76 | static struct kobj_attribute attr_attribute = |
83 | { | 77 | __ATTR(addr, S_IRUGO, map_attr_show, NULL); |
84 | /* TODO ??? */ | 78 | static struct kobj_attribute size_attribute = |
85 | } | 79 | __ATTR(size, S_IRUGO, map_attr_show, NULL); |
86 | 80 | ||
87 | static struct sysfs_ops map_attr_ops = { | 81 | static struct attribute *attrs[] = { |
88 | .show = map_attr_show, | 82 | &attr_attribute.attr, |
83 | &size_attribute.attr, | ||
84 | NULL, /* need to NULL terminate the list of attributes */ | ||
89 | }; | 85 | }; |
90 | 86 | ||
87 | static void map_release(struct kobject *kobj) | ||
88 | { | ||
89 | struct uio_map *map = to_map(kobj); | ||
90 | kfree(map); | ||
91 | } | ||
92 | |||
91 | static struct kobj_type map_attr_type = { | 93 | static struct kobj_type map_attr_type = { |
92 | .release = map_attr_release, | 94 | .release = map_release, |
93 | .sysfs_ops = &map_attr_ops, | 95 | .default_attrs = attrs, |
94 | .default_attrs = map_attrs, | ||
95 | }; | 96 | }; |
96 | 97 | ||
97 | static ssize_t show_name(struct device *dev, | 98 | static ssize_t show_name(struct device *dev, |
@@ -148,6 +149,7 @@ static int uio_dev_add_attributes(struct uio_device *idev) | |||
148 | int mi; | 149 | int mi; |
149 | int map_found = 0; | 150 | int map_found = 0; |
150 | struct uio_mem *mem; | 151 | struct uio_mem *mem; |
152 | struct uio_map *map; | ||
151 | 153 | ||
152 | ret = sysfs_create_group(&idev->dev->kobj, &uio_attr_grp); | 154 | ret = sysfs_create_group(&idev->dev->kobj, &uio_attr_grp); |
153 | if (ret) | 155 | if (ret) |
@@ -159,31 +161,34 @@ static int uio_dev_add_attributes(struct uio_device *idev) | |||
159 | break; | 161 | break; |
160 | if (!map_found) { | 162 | if (!map_found) { |
161 | map_found = 1; | 163 | map_found = 1; |
162 | kobject_set_name(&idev->map_attr_kset.kobj,"maps"); | 164 | idev->map_dir = kobject_create_and_add("maps", |
163 | idev->map_attr_kset.ktype = &map_attr_type; | 165 | &idev->dev->kobj); |
164 | idev->map_attr_kset.kobj.parent = &idev->dev->kobj; | 166 | if (!idev->map_dir) |
165 | ret = kset_register(&idev->map_attr_kset); | 167 | goto err; |
166 | if (ret) | ||
167 | goto err_remove_group; | ||
168 | } | 168 | } |
169 | kobject_init(&mem->kobj); | 169 | map = kzalloc(sizeof(*map), GFP_KERNEL); |
170 | kobject_set_name(&mem->kobj,"map%d",mi); | 170 | if (!map) |
171 | mem->kobj.parent = &idev->map_attr_kset.kobj; | 171 | goto err; |
172 | mem->kobj.kset = &idev->map_attr_kset; | 172 | kobject_init(&map->kobj, &map_attr_type); |
173 | ret = kobject_add(&mem->kobj); | 173 | map->mem = mem; |
174 | mem->map = map; | ||
175 | ret = kobject_add(&map->kobj, idev->map_dir, "map%d", mi); | ||
176 | if (ret) | ||
177 | goto err; | ||
178 | ret = kobject_uevent(&map->kobj, KOBJ_ADD); | ||
174 | if (ret) | 179 | if (ret) |
175 | goto err_remove_maps; | 180 | goto err; |
176 | } | 181 | } |
177 | 182 | ||
178 | return 0; | 183 | return 0; |
179 | 184 | ||
180 | err_remove_maps: | 185 | err: |
181 | for (mi--; mi>=0; mi--) { | 186 | for (mi--; mi>=0; mi--) { |
182 | mem = &idev->info->mem[mi]; | 187 | mem = &idev->info->mem[mi]; |
183 | kobject_unregister(&mem->kobj); | 188 | map = mem->map; |
189 | kobject_put(&map->kobj); | ||
184 | } | 190 | } |
185 | kset_unregister(&idev->map_attr_kset); /* Needed ? */ | 191 | kobject_put(idev->map_dir); |
186 | err_remove_group: | ||
187 | sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp); | 192 | sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp); |
188 | err_group: | 193 | err_group: |
189 | dev_err(idev->dev, "error creating sysfs files (%d)\n", ret); | 194 | dev_err(idev->dev, "error creating sysfs files (%d)\n", ret); |
@@ -198,9 +203,9 @@ static void uio_dev_del_attributes(struct uio_device *idev) | |||
198 | mem = &idev->info->mem[mi]; | 203 | mem = &idev->info->mem[mi]; |
199 | if (mem->size == 0) | 204 | if (mem->size == 0) |
200 | break; | 205 | break; |
201 | kobject_unregister(&mem->kobj); | 206 | kobject_put(&mem->map->kobj); |
202 | } | 207 | } |
203 | kset_unregister(&idev->map_attr_kset); | 208 | kobject_put(idev->map_dir); |
204 | sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp); | 209 | sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp); |
205 | } | 210 | } |
206 | 211 | ||
@@ -503,7 +508,7 @@ static int uio_mmap(struct file *filep, struct vm_area_struct *vma) | |||
503 | } | 508 | } |
504 | } | 509 | } |
505 | 510 | ||
506 | static struct file_operations uio_fops = { | 511 | static const struct file_operations uio_fops = { |
507 | .owner = THIS_MODULE, | 512 | .owner = THIS_MODULE, |
508 | .open = uio_open, | 513 | .open = uio_open, |
509 | .release = uio_release, | 514 | .release = uio_release, |