This source file includes following definitions.
- bsr_size_show
- bsr_stride_show
- bsr_length_show
- bsr_mmap
- bsr_open
- bsr_cleanup_devs
- bsr_add_node
- bsr_create_devs
- bsr_init
- bsr_exit
1
2
3
4
5
6
7
8
9 #include <linux/kernel.h>
10 #include <linux/of.h>
11 #include <linux/of_address.h>
12 #include <linux/of_device.h>
13 #include <linux/of_platform.h>
14 #include <linux/fs.h>
15 #include <linux/module.h>
16 #include <linux/cdev.h>
17 #include <linux/list.h>
18 #include <linux/mm.h>
19 #include <linux/slab.h>
20 #include <asm/pgtable.h>
21 #include <asm/io.h>
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 #define BSR_MAX_DEVS (32)
44
45 struct bsr_dev {
46 u64 bsr_addr;
47 u64 bsr_len;
48 unsigned bsr_bytes;
49 unsigned bsr_stride;
50 unsigned bsr_type;
51 unsigned bsr_num;
52 int bsr_minor;
53
54 struct list_head bsr_list;
55
56 dev_t bsr_dev;
57 struct cdev bsr_cdev;
58 struct device *bsr_device;
59 char bsr_name[32];
60
61 };
62
63 static unsigned total_bsr_devs;
64 static struct list_head bsr_devs = LIST_HEAD_INIT(bsr_devs);
65 static struct class *bsr_class;
66 static int bsr_major;
67
68 enum {
69 BSR_8 = 0,
70 BSR_16 = 1,
71 BSR_64 = 2,
72 BSR_128 = 3,
73 BSR_4096 = 4,
74 BSR_UNKNOWN = 5,
75 BSR_MAX = 6,
76 };
77
78 static unsigned bsr_types[BSR_MAX];
79
80 static ssize_t
81 bsr_size_show(struct device *dev, struct device_attribute *attr, char *buf)
82 {
83 struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
84 return sprintf(buf, "%u\n", bsr_dev->bsr_bytes);
85 }
86 static DEVICE_ATTR_RO(bsr_size);
87
88 static ssize_t
89 bsr_stride_show(struct device *dev, struct device_attribute *attr, char *buf)
90 {
91 struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
92 return sprintf(buf, "%u\n", bsr_dev->bsr_stride);
93 }
94 static DEVICE_ATTR_RO(bsr_stride);
95
96 static ssize_t
97 bsr_length_show(struct device *dev, struct device_attribute *attr, char *buf)
98 {
99 struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
100 return sprintf(buf, "%llu\n", bsr_dev->bsr_len);
101 }
102 static DEVICE_ATTR_RO(bsr_length);
103
104 static struct attribute *bsr_dev_attrs[] = {
105 &dev_attr_bsr_size.attr,
106 &dev_attr_bsr_stride.attr,
107 &dev_attr_bsr_length.attr,
108 NULL,
109 };
110 ATTRIBUTE_GROUPS(bsr_dev);
111
112 static int bsr_mmap(struct file *filp, struct vm_area_struct *vma)
113 {
114 unsigned long size = vma->vm_end - vma->vm_start;
115 struct bsr_dev *dev = filp->private_data;
116 int ret;
117
118 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
119
120
121 if (dev->bsr_len < PAGE_SIZE && size == PAGE_SIZE)
122 ret = remap_4k_pfn(vma, vma->vm_start, dev->bsr_addr >> 12,
123 vma->vm_page_prot);
124 else if (size <= dev->bsr_len)
125 ret = io_remap_pfn_range(vma, vma->vm_start,
126 dev->bsr_addr >> PAGE_SHIFT,
127 size, vma->vm_page_prot);
128 else
129 return -EINVAL;
130
131 if (ret)
132 return -EAGAIN;
133
134 return 0;
135 }
136
137 static int bsr_open(struct inode *inode, struct file *filp)
138 {
139 struct cdev *cdev = inode->i_cdev;
140 struct bsr_dev *dev = container_of(cdev, struct bsr_dev, bsr_cdev);
141
142 filp->private_data = dev;
143 return 0;
144 }
145
146 static const struct file_operations bsr_fops = {
147 .owner = THIS_MODULE,
148 .mmap = bsr_mmap,
149 .open = bsr_open,
150 .llseek = noop_llseek,
151 };
152
153 static void bsr_cleanup_devs(void)
154 {
155 struct bsr_dev *cur, *n;
156
157 list_for_each_entry_safe(cur, n, &bsr_devs, bsr_list) {
158 if (cur->bsr_device) {
159 cdev_del(&cur->bsr_cdev);
160 device_del(cur->bsr_device);
161 }
162 list_del(&cur->bsr_list);
163 kfree(cur);
164 }
165 }
166
167 static int bsr_add_node(struct device_node *bn)
168 {
169 int bsr_stride_len, bsr_bytes_len, num_bsr_devs;
170 const u32 *bsr_stride;
171 const u32 *bsr_bytes;
172 unsigned i;
173 int ret = -ENODEV;
174
175 bsr_stride = of_get_property(bn, "ibm,lock-stride", &bsr_stride_len);
176 bsr_bytes = of_get_property(bn, "ibm,#lock-bytes", &bsr_bytes_len);
177
178 if (!bsr_stride || !bsr_bytes ||
179 (bsr_stride_len != bsr_bytes_len)) {
180 printk(KERN_ERR "bsr of-node has missing/incorrect property\n");
181 return ret;
182 }
183
184 num_bsr_devs = bsr_bytes_len / sizeof(u32);
185
186 for (i = 0 ; i < num_bsr_devs; i++) {
187 struct bsr_dev *cur = kzalloc(sizeof(struct bsr_dev),
188 GFP_KERNEL);
189 struct resource res;
190 int result;
191
192 if (!cur) {
193 printk(KERN_ERR "Unable to alloc bsr dev\n");
194 ret = -ENOMEM;
195 goto out_err;
196 }
197
198 result = of_address_to_resource(bn, i, &res);
199 if (result < 0) {
200 printk(KERN_ERR "bsr of-node has invalid reg property, skipping\n");
201 kfree(cur);
202 continue;
203 }
204
205 cur->bsr_minor = i + total_bsr_devs;
206 cur->bsr_addr = res.start;
207 cur->bsr_len = resource_size(&res);
208 cur->bsr_bytes = bsr_bytes[i];
209 cur->bsr_stride = bsr_stride[i];
210 cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs);
211
212
213
214 if (cur->bsr_len > 4096 && cur->bsr_len < PAGE_SIZE)
215 cur->bsr_len = 4096;
216
217 switch(cur->bsr_bytes) {
218 case 8:
219 cur->bsr_type = BSR_8;
220 break;
221 case 16:
222 cur->bsr_type = BSR_16;
223 break;
224 case 64:
225 cur->bsr_type = BSR_64;
226 break;
227 case 128:
228 cur->bsr_type = BSR_128;
229 break;
230 case 4096:
231 cur->bsr_type = BSR_4096;
232 break;
233 default:
234 cur->bsr_type = BSR_UNKNOWN;
235 }
236
237 cur->bsr_num = bsr_types[cur->bsr_type];
238 snprintf(cur->bsr_name, 32, "bsr%d_%d",
239 cur->bsr_bytes, cur->bsr_num);
240
241 cdev_init(&cur->bsr_cdev, &bsr_fops);
242 result = cdev_add(&cur->bsr_cdev, cur->bsr_dev, 1);
243 if (result) {
244 kfree(cur);
245 goto out_err;
246 }
247
248 cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev,
249 cur, "%s", cur->bsr_name);
250 if (IS_ERR(cur->bsr_device)) {
251 printk(KERN_ERR "device_create failed for %s\n",
252 cur->bsr_name);
253 cdev_del(&cur->bsr_cdev);
254 kfree(cur);
255 goto out_err;
256 }
257
258 bsr_types[cur->bsr_type] = cur->bsr_num + 1;
259 list_add_tail(&cur->bsr_list, &bsr_devs);
260 }
261
262 total_bsr_devs += num_bsr_devs;
263
264 return 0;
265
266 out_err:
267
268 bsr_cleanup_devs();
269 return ret;
270 }
271
272 static int bsr_create_devs(struct device_node *bn)
273 {
274 int ret;
275
276 while (bn) {
277 ret = bsr_add_node(bn);
278 if (ret) {
279 of_node_put(bn);
280 return ret;
281 }
282 bn = of_find_compatible_node(bn, NULL, "ibm,bsr");
283 }
284 return 0;
285 }
286
287 static int __init bsr_init(void)
288 {
289 struct device_node *np;
290 dev_t bsr_dev;
291 int ret = -ENODEV;
292
293 np = of_find_compatible_node(NULL, NULL, "ibm,bsr");
294 if (!np)
295 goto out_err;
296
297 bsr_class = class_create(THIS_MODULE, "bsr");
298 if (IS_ERR(bsr_class)) {
299 printk(KERN_ERR "class_create() failed for bsr_class\n");
300 ret = PTR_ERR(bsr_class);
301 goto out_err_1;
302 }
303 bsr_class->dev_groups = bsr_dev_groups;
304
305 ret = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr");
306 bsr_major = MAJOR(bsr_dev);
307 if (ret < 0) {
308 printk(KERN_ERR "alloc_chrdev_region() failed for bsr\n");
309 goto out_err_2;
310 }
311
312 ret = bsr_create_devs(np);
313 if (ret < 0) {
314 np = NULL;
315 goto out_err_3;
316 }
317
318 return 0;
319
320 out_err_3:
321 unregister_chrdev_region(bsr_dev, BSR_MAX_DEVS);
322
323 out_err_2:
324 class_destroy(bsr_class);
325
326 out_err_1:
327 of_node_put(np);
328
329 out_err:
330
331 return ret;
332 }
333
334 static void __exit bsr_exit(void)
335 {
336
337 bsr_cleanup_devs();
338
339 if (bsr_class)
340 class_destroy(bsr_class);
341
342 if (bsr_major)
343 unregister_chrdev_region(MKDEV(bsr_major, 0), BSR_MAX_DEVS);
344 }
345
346 module_init(bsr_init);
347 module_exit(bsr_exit);
348 MODULE_LICENSE("GPL");
349 MODULE_AUTHOR("Sonny Rao <sonnyrao@us.ibm.com>");