diff options
-rw-r--r-- | drivers/uio/uio.c | 91 | ||||
-rw-r--r-- | include/linux/uio_driver.h | 6 |
2 files changed, 52 insertions, 45 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 | ||
40 | static int uio_major; | 40 | static int uio_major; |
@@ -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.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 | ||
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_unregister(&map->kobj); | ||
184 | } | 190 | } |
185 | kset_unregister(&idev->map_attr_kset); /* Needed ? */ | 191 | kobject_unregister(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_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 | ||
diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h index 44c28e94df50..973386d439da 100644 --- a/include/linux/uio_driver.h +++ b/include/linux/uio_driver.h | |||
@@ -18,20 +18,22 @@ | |||
18 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | 20 | ||
21 | struct uio_map; | ||
22 | |||
21 | /** | 23 | /** |
22 | * struct uio_mem - description of a UIO memory region | 24 | * struct uio_mem - description of a UIO memory region |
23 | * @kobj: kobject for this mapping | ||
24 | * @addr: address of the device's memory | 25 | * @addr: address of the device's memory |
25 | * @size: size of IO | 26 | * @size: size of IO |
26 | * @memtype: type of memory addr points to | 27 | * @memtype: type of memory addr points to |
27 | * @internal_addr: ioremap-ped version of addr, for driver internal use | 28 | * @internal_addr: ioremap-ped version of addr, for driver internal use |
29 | * @map: for use by the UIO core only. | ||
28 | */ | 30 | */ |
29 | struct uio_mem { | 31 | struct uio_mem { |
30 | struct kobject kobj; | ||
31 | unsigned long addr; | 32 | unsigned long addr; |
32 | unsigned long size; | 33 | unsigned long size; |
33 | int memtype; | 34 | int memtype; |
34 | void __iomem *internal_addr; | 35 | void __iomem *internal_addr; |
36 | struct uio_map *map; | ||
35 | }; | 37 | }; |
36 | 38 | ||
37 | #define MAX_UIO_MAPS 5 | 39 | #define MAX_UIO_MAPS 5 |