1 /* IBM POWER Barrier Synchronization Register Driver
3 * Copyright IBM Corporation 2008
5 * Author: Sonny Rao <sonnyrao@us.ibm.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/kernel.h>
24 #include <linux/of_device.h>
25 #include <linux/of_platform.h>
26 #include <linux/module.h>
27 #include <linux/cdev.h>
28 #include <linux/list.h>
30 #include <asm/pgtable.h>
34 This driver exposes a special register which can be used for fast
35 synchronization across a large SMP machine. The hardware is exposed
36 as an array of bytes where each process will write to one of the bytes to
37 indicate it has finished the current stage and this update is broadcast to
38 all processors without having to bounce a cacheline between them. In
39 POWER5 and POWER6 there is one of these registers per SMP, but it is
40 presented in two forms; first, it is given as a whole and then as a number
41 of smaller registers which alias to parts of the single whole register.
42 This can potentially allow multiple groups of processes to each have their
43 own private synchronization device.
45 Note that this hardware *must* be written to using *only* single byte writes.
46 It may be read using 1, 2, 4, or 8 byte loads which must be aligned since
47 this region is treated as cache-inhibited processes should also use a
48 full sync before and after writing to the BSR to ensure all stores and
49 the BSR update have made it to all chips in the system
52 /* This is arbitrary number, up to Power6 it's been 17 or fewer */
53 #define BSR_MAX_DEVS (32)
56 u64 bsr_addr
; /* Real address */
57 u64 bsr_len
; /* length of mem region we can map */
58 unsigned bsr_bytes
; /* size of the BSR reg itself */
59 unsigned bsr_stride
; /* interval at which BSR repeats in the page */
60 unsigned bsr_type
; /* maps to enum below */
61 unsigned bsr_num
; /* bsr id number for its type */
64 struct list_head bsr_list
;
68 struct device
*bsr_device
;
73 static unsigned total_bsr_devs
;
74 static struct list_head bsr_devs
= LIST_HEAD_INIT(bsr_devs
);
75 static struct class *bsr_class
;
88 static unsigned bsr_types
[BSR_MAX
];
91 bsr_size_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
93 struct bsr_dev
*bsr_dev
= dev_get_drvdata(dev
);
94 return sprintf(buf
, "%u\n", bsr_dev
->bsr_bytes
);
98 bsr_stride_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
100 struct bsr_dev
*bsr_dev
= dev_get_drvdata(dev
);
101 return sprintf(buf
, "%u\n", bsr_dev
->bsr_stride
);
105 bsr_len_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
107 struct bsr_dev
*bsr_dev
= dev_get_drvdata(dev
);
108 return sprintf(buf
, "%llu\n", bsr_dev
->bsr_len
);
111 static struct device_attribute bsr_dev_attrs
[] = {
112 __ATTR(bsr_size
, S_IRUGO
, bsr_size_show
, NULL
),
113 __ATTR(bsr_stride
, S_IRUGO
, bsr_stride_show
, NULL
),
114 __ATTR(bsr_length
, S_IRUGO
, bsr_len_show
, NULL
),
118 static int bsr_mmap(struct file
*filp
, struct vm_area_struct
*vma
)
120 unsigned long size
= vma
->vm_end
- vma
->vm_start
;
121 struct bsr_dev
*dev
= filp
->private_data
;
124 vma
->vm_page_prot
= pgprot_noncached(vma
->vm_page_prot
);
126 /* check for the case of a small BSR device and map one 4k page for it*/
127 if (dev
->bsr_len
< PAGE_SIZE
&& size
== PAGE_SIZE
)
128 ret
= remap_4k_pfn(vma
, vma
->vm_start
, dev
->bsr_addr
>> 12,
130 else if (size
<= dev
->bsr_len
)
131 ret
= io_remap_pfn_range(vma
, vma
->vm_start
,
132 dev
->bsr_addr
>> PAGE_SHIFT
,
133 size
, vma
->vm_page_prot
);
143 static int bsr_open(struct inode
* inode
, struct file
* filp
)
145 struct cdev
*cdev
= inode
->i_cdev
;
146 struct bsr_dev
*dev
= container_of(cdev
, struct bsr_dev
, bsr_cdev
);
148 filp
->private_data
= dev
;
152 static const struct file_operations bsr_fops
= {
153 .owner
= THIS_MODULE
,
158 static void bsr_cleanup_devs(void)
160 struct bsr_dev
*cur
, *n
;
162 list_for_each_entry_safe(cur
, n
, &bsr_devs
, bsr_list
) {
163 if (cur
->bsr_device
) {
164 cdev_del(&cur
->bsr_cdev
);
165 device_del(cur
->bsr_device
);
167 list_del(&cur
->bsr_list
);
172 static int bsr_add_node(struct device_node
*bn
)
174 int bsr_stride_len
, bsr_bytes_len
, num_bsr_devs
;
175 const u32
*bsr_stride
;
176 const u32
*bsr_bytes
;
180 bsr_stride
= of_get_property(bn
, "ibm,lock-stride", &bsr_stride_len
);
181 bsr_bytes
= of_get_property(bn
, "ibm,#lock-bytes", &bsr_bytes_len
);
183 if (!bsr_stride
|| !bsr_bytes
||
184 (bsr_stride_len
!= bsr_bytes_len
)) {
185 printk(KERN_ERR
"bsr of-node has missing/incorrect property\n");
189 num_bsr_devs
= bsr_bytes_len
/ sizeof(u32
);
191 for (i
= 0 ; i
< num_bsr_devs
; i
++) {
192 struct bsr_dev
*cur
= kzalloc(sizeof(struct bsr_dev
),
198 printk(KERN_ERR
"Unable to alloc bsr dev\n");
203 result
= of_address_to_resource(bn
, i
, &res
);
205 printk(KERN_ERR
"bsr of-node has invalid reg property, skipping\n");
210 cur
->bsr_minor
= i
+ total_bsr_devs
;
211 cur
->bsr_addr
= res
.start
;
212 cur
->bsr_len
= res
.end
- res
.start
+ 1;
213 cur
->bsr_bytes
= bsr_bytes
[i
];
214 cur
->bsr_stride
= bsr_stride
[i
];
215 cur
->bsr_dev
= MKDEV(bsr_major
, i
+ total_bsr_devs
);
217 /* if we have a bsr_len of > 4k and less then PAGE_SIZE (64k pages) */
218 /* we can only map 4k of it, so only advertise the 4k in sysfs */
219 if (cur
->bsr_len
> 4096 && cur
->bsr_len
< PAGE_SIZE
)
222 switch(cur
->bsr_bytes
) {
224 cur
->bsr_type
= BSR_8
;
227 cur
->bsr_type
= BSR_16
;
230 cur
->bsr_type
= BSR_64
;
233 cur
->bsr_type
= BSR_128
;
236 cur
->bsr_type
= BSR_4096
;
239 cur
->bsr_type
= BSR_UNKNOWN
;
242 cur
->bsr_num
= bsr_types
[cur
->bsr_type
];
243 snprintf(cur
->bsr_name
, 32, "bsr%d_%d",
244 cur
->bsr_bytes
, cur
->bsr_num
);
246 cdev_init(&cur
->bsr_cdev
, &bsr_fops
);
247 result
= cdev_add(&cur
->bsr_cdev
, cur
->bsr_dev
, 1);
253 cur
->bsr_device
= device_create(bsr_class
, NULL
, cur
->bsr_dev
,
255 if (!cur
->bsr_device
) {
256 printk(KERN_ERR
"device_create failed for %s\n",
258 cdev_del(&cur
->bsr_cdev
);
263 bsr_types
[cur
->bsr_type
] = cur
->bsr_num
+ 1;
264 list_add_tail(&cur
->bsr_list
, &bsr_devs
);
267 total_bsr_devs
+= num_bsr_devs
;
277 static int bsr_create_devs(struct device_node
*bn
)
282 ret
= bsr_add_node(bn
);
287 bn
= of_find_compatible_node(bn
, NULL
, "ibm,bsr");
292 static int __init
bsr_init(void)
294 struct device_node
*np
;
295 dev_t bsr_dev
= MKDEV(bsr_major
, 0);
299 np
= of_find_compatible_node(NULL
, NULL
, "ibm,bsr");
303 bsr_class
= class_create(THIS_MODULE
, "bsr");
304 if (IS_ERR(bsr_class
)) {
305 printk(KERN_ERR
"class_create() failed for bsr_class\n");
308 bsr_class
->dev_attrs
= bsr_dev_attrs
;
310 result
= alloc_chrdev_region(&bsr_dev
, 0, BSR_MAX_DEVS
, "bsr");
311 bsr_major
= MAJOR(bsr_dev
);
313 printk(KERN_ERR
"alloc_chrdev_region() failed for bsr\n");
317 if ((ret
= bsr_create_devs(np
)) < 0) {
325 unregister_chrdev_region(bsr_dev
, BSR_MAX_DEVS
);
328 class_destroy(bsr_class
);
338 static void __exit
bsr_exit(void)
344 class_destroy(bsr_class
);
347 unregister_chrdev_region(MKDEV(bsr_major
, 0), BSR_MAX_DEVS
);
350 module_init(bsr_init
);
351 module_exit(bsr_exit
);
352 MODULE_LICENSE("GPL");
353 MODULE_AUTHOR("Sonny Rao <sonnyrao@us.ibm.com>");