aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/uio/uio.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2007-12-04 17:41:54 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-01-24 23:40:26 -0500
commit81e7c6a636c81d9eeaeaa732bfbace44535fab00 (patch)
treefecb19e67acb96c2c9a11194ebebca63f0139f02 /drivers/uio/uio.c
parent9f66fa2a4690a16da0dbaae2f44ddfc313802504 (diff)
UIO: fix kobject usage
The uio kobject code is "wierd". This patch should hopefully fix it up to be sane and not leak memory anymore. Cc: Kay Sievers <kay.sievers@vrfy.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Benedikt Spranger <b.spranger@linutronix.de> Signed-off-by: Hans J. Koch <hjk@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/uio/uio.c')
-rw-r--r--drivers/uio/uio.c91
1 files changed, 48 insertions, 43 deletions
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 606aae7490ab..acc387de988f 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -34,7 +34,7 @@ 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
40static int uio_major; 40static int uio_major;
@@ -51,47 +51,48 @@ static struct uio_class {
51 * attributes 51 * attributes
52 */ 52 */
53 53
54static struct attribute attr_addr = { 54struct 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
59static struct attribute attr_size = {
60 .name = "size",
61 .mode = S_IRUGO,
62};
63 60
64static struct attribute* map_attrs[] = { 61static ssize_t map_attr_show(struct kobject *kobj, struct kobj_attribute *attr,
65 &attr_addr, &attr_size, NULL
66};
67
68static 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
82static void map_attr_release(struct kobject *kobj) 76static struct kobj_attribute attr_attribute =
83{ 77 __ATTR(addr, S_IRUGO, map_attr_show, NULL);
84 /* TODO ??? */ 78static struct kobj_attribute size_attribute =
85} 79 __ATTR(size, S_IRUGO, map_attr_show, NULL);
86 80
87static struct sysfs_ops map_attr_ops = { 81static 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
87static void map_release(struct kobject *kobj)
88{
89 struct uio_map *map = to_map(kobj);
90 kfree(map);
91}
92
91static struct kobj_type map_attr_type = { 93static 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
97static ssize_t show_name(struct device *dev, 98static 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.kobj.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_ng(&map->kobj, &map_attr_type);
173 ret = kobject_add(&mem->kobj); 173 map->mem = mem;
174 mem->map = map;
175 ret = kobject_add_ng(&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
180err_remove_maps: 185err:
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_unregister(&map->kobj);
184 } 190 }
185 kset_unregister(&idev->map_attr_kset); /* Needed ? */ 191 kobject_unregister(idev->map_dir);
186err_remove_group:
187 sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp); 192 sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
188err_group: 193err_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_unregister(&mem->map->kobj);
202 } 207 }
203 kset_unregister(&idev->map_attr_kset); 208 kobject_unregister(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