Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* IBM POWER Barrier Synchronization Register Driver
0003  *
0004  * Copyright IBM Corporation 2008
0005  *
0006  * Author: Sonny Rao <sonnyrao@us.ibm.com>
0007  */
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/of.h>
0011 #include <linux/of_address.h>
0012 #include <linux/of_device.h>
0013 #include <linux/of_platform.h>
0014 #include <linux/fs.h>
0015 #include <linux/module.h>
0016 #include <linux/cdev.h>
0017 #include <linux/list.h>
0018 #include <linux/mm.h>
0019 #include <linux/slab.h>
0020 #include <asm/io.h>
0021 
0022 /*
0023  This driver exposes a special register which can be used for fast
0024  synchronization across a large SMP machine.  The hardware is exposed
0025  as an array of bytes where each process will write to one of the bytes to
0026  indicate it has finished the current stage and this update is broadcast to
0027  all processors without having to bounce a cacheline between them. In
0028  POWER5 and POWER6 there is one of these registers per SMP,  but it is
0029  presented in two forms; first, it is given as a whole and then as a number
0030  of smaller registers which alias to parts of the single whole register.
0031  This can potentially allow multiple groups of processes to each have their
0032  own private synchronization device.
0033 
0034  Note that this hardware *must* be written to using *only* single byte writes.
0035  It may be read using 1, 2, 4, or 8 byte loads which must be aligned since
0036  this region is treated as cache-inhibited  processes should also use a
0037  full sync before and after writing to the BSR to ensure all stores and
0038  the BSR update have made it to all chips in the system
0039 */
0040 
0041 /* This is arbitrary number, up to Power6 it's been 17 or fewer  */
0042 #define BSR_MAX_DEVS (32)
0043 
0044 struct bsr_dev {
0045     u64      bsr_addr;     /* Real address */
0046     u64      bsr_len;      /* length of mem region we can map */
0047     unsigned bsr_bytes;    /* size of the BSR reg itself */
0048     unsigned bsr_stride;   /* interval at which BSR repeats in the page */
0049     unsigned bsr_type;     /* maps to enum below */
0050     unsigned bsr_num;      /* bsr id number for its type */
0051     int      bsr_minor;
0052 
0053     struct list_head bsr_list;
0054 
0055     dev_t    bsr_dev;
0056     struct cdev bsr_cdev;
0057     struct device *bsr_device;
0058     char     bsr_name[32];
0059 
0060 };
0061 
0062 static unsigned total_bsr_devs;
0063 static LIST_HEAD(bsr_devs);
0064 static struct class *bsr_class;
0065 static int bsr_major;
0066 
0067 enum {
0068     BSR_8    = 0,
0069     BSR_16   = 1,
0070     BSR_64   = 2,
0071     BSR_128  = 3,
0072     BSR_4096 = 4,
0073     BSR_UNKNOWN = 5,
0074     BSR_MAX  = 6,
0075 };
0076 
0077 static unsigned bsr_types[BSR_MAX];
0078 
0079 static ssize_t
0080 bsr_size_show(struct device *dev, struct device_attribute *attr, char *buf)
0081 {
0082     struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
0083     return sprintf(buf, "%u\n", bsr_dev->bsr_bytes);
0084 }
0085 static DEVICE_ATTR_RO(bsr_size);
0086 
0087 static ssize_t
0088 bsr_stride_show(struct device *dev, struct device_attribute *attr, char *buf)
0089 {
0090     struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
0091     return sprintf(buf, "%u\n", bsr_dev->bsr_stride);
0092 }
0093 static DEVICE_ATTR_RO(bsr_stride);
0094 
0095 static ssize_t
0096 bsr_length_show(struct device *dev, struct device_attribute *attr, char *buf)
0097 {
0098     struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
0099     return sprintf(buf, "%llu\n", bsr_dev->bsr_len);
0100 }
0101 static DEVICE_ATTR_RO(bsr_length);
0102 
0103 static struct attribute *bsr_dev_attrs[] = {
0104     &dev_attr_bsr_size.attr,
0105     &dev_attr_bsr_stride.attr,
0106     &dev_attr_bsr_length.attr,
0107     NULL,
0108 };
0109 ATTRIBUTE_GROUPS(bsr_dev);
0110 
0111 static int bsr_mmap(struct file *filp, struct vm_area_struct *vma)
0112 {
0113     unsigned long size   = vma->vm_end - vma->vm_start;
0114     struct bsr_dev *dev = filp->private_data;
0115     int ret;
0116 
0117     vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
0118 
0119     /* check for the case of a small BSR device and map one 4k page for it*/
0120     if (dev->bsr_len < PAGE_SIZE && size == PAGE_SIZE)
0121         ret = remap_4k_pfn(vma, vma->vm_start, dev->bsr_addr >> 12,
0122                    vma->vm_page_prot);
0123     else if (size <= dev->bsr_len)
0124         ret = io_remap_pfn_range(vma, vma->vm_start,
0125                      dev->bsr_addr >> PAGE_SHIFT,
0126                      size, vma->vm_page_prot);
0127     else
0128         return -EINVAL;
0129 
0130     if (ret)
0131         return -EAGAIN;
0132 
0133     return 0;
0134 }
0135 
0136 static int bsr_open(struct inode *inode, struct file *filp)
0137 {
0138     struct cdev *cdev = inode->i_cdev;
0139     struct bsr_dev *dev = container_of(cdev, struct bsr_dev, bsr_cdev);
0140 
0141     filp->private_data = dev;
0142     return 0;
0143 }
0144 
0145 static const struct file_operations bsr_fops = {
0146     .owner = THIS_MODULE,
0147     .mmap  = bsr_mmap,
0148     .open  = bsr_open,
0149     .llseek = noop_llseek,
0150 };
0151 
0152 static void bsr_cleanup_devs(void)
0153 {
0154     struct bsr_dev *cur, *n;
0155 
0156     list_for_each_entry_safe(cur, n, &bsr_devs, bsr_list) {
0157         if (cur->bsr_device) {
0158             cdev_del(&cur->bsr_cdev);
0159             device_del(cur->bsr_device);
0160         }
0161         list_del(&cur->bsr_list);
0162         kfree(cur);
0163     }
0164 }
0165 
0166 static int bsr_add_node(struct device_node *bn)
0167 {
0168     int bsr_stride_len, bsr_bytes_len, num_bsr_devs;
0169     const u32 *bsr_stride;
0170     const u32 *bsr_bytes;
0171     unsigned i;
0172     int ret = -ENODEV;
0173 
0174     bsr_stride = of_get_property(bn, "ibm,lock-stride", &bsr_stride_len);
0175     bsr_bytes  = of_get_property(bn, "ibm,#lock-bytes", &bsr_bytes_len);
0176 
0177     if (!bsr_stride || !bsr_bytes ||
0178         (bsr_stride_len != bsr_bytes_len)) {
0179         printk(KERN_ERR "bsr of-node has missing/incorrect property\n");
0180         return ret;
0181     }
0182 
0183     num_bsr_devs = bsr_bytes_len / sizeof(u32);
0184 
0185     for (i = 0 ; i < num_bsr_devs; i++) {
0186         struct bsr_dev *cur = kzalloc(sizeof(struct bsr_dev),
0187                           GFP_KERNEL);
0188         struct resource res;
0189         int result;
0190 
0191         if (!cur) {
0192             printk(KERN_ERR "Unable to alloc bsr dev\n");
0193             ret = -ENOMEM;
0194             goto out_err;
0195         }
0196 
0197         result = of_address_to_resource(bn, i, &res);
0198         if (result < 0) {
0199             printk(KERN_ERR "bsr of-node has invalid reg property, skipping\n");
0200             kfree(cur);
0201             continue;
0202         }
0203 
0204         cur->bsr_minor  = i + total_bsr_devs;
0205         cur->bsr_addr   = res.start;
0206         cur->bsr_len    = resource_size(&res);
0207         cur->bsr_bytes  = bsr_bytes[i];
0208         cur->bsr_stride = bsr_stride[i];
0209         cur->bsr_dev    = MKDEV(bsr_major, i + total_bsr_devs);
0210 
0211         /* if we have a bsr_len of > 4k and less then PAGE_SIZE (64k pages) */
0212         /* we can only map 4k of it, so only advertise the 4k in sysfs */
0213         if (cur->bsr_len > 4096 && cur->bsr_len < PAGE_SIZE)
0214             cur->bsr_len = 4096;
0215 
0216         switch(cur->bsr_bytes) {
0217         case 8:
0218             cur->bsr_type = BSR_8;
0219             break;
0220         case 16:
0221             cur->bsr_type = BSR_16;
0222             break;
0223         case 64:
0224             cur->bsr_type = BSR_64;
0225             break;
0226         case 128:
0227             cur->bsr_type = BSR_128;
0228             break;
0229         case 4096:
0230             cur->bsr_type = BSR_4096;
0231             break;
0232         default:
0233             cur->bsr_type = BSR_UNKNOWN;
0234         }
0235 
0236         cur->bsr_num = bsr_types[cur->bsr_type];
0237         snprintf(cur->bsr_name, 32, "bsr%d_%d",
0238              cur->bsr_bytes, cur->bsr_num);
0239 
0240         cdev_init(&cur->bsr_cdev, &bsr_fops);
0241         result = cdev_add(&cur->bsr_cdev, cur->bsr_dev, 1);
0242         if (result) {
0243             kfree(cur);
0244             goto out_err;
0245         }
0246 
0247         cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev,
0248                         cur, "%s", cur->bsr_name);
0249         if (IS_ERR(cur->bsr_device)) {
0250             printk(KERN_ERR "device_create failed for %s\n",
0251                    cur->bsr_name);
0252             cdev_del(&cur->bsr_cdev);
0253             kfree(cur);
0254             goto out_err;
0255         }
0256 
0257         bsr_types[cur->bsr_type] = cur->bsr_num + 1;
0258         list_add_tail(&cur->bsr_list, &bsr_devs);
0259     }
0260 
0261     total_bsr_devs += num_bsr_devs;
0262 
0263     return 0;
0264 
0265  out_err:
0266 
0267     bsr_cleanup_devs();
0268     return ret;
0269 }
0270 
0271 static int bsr_create_devs(struct device_node *bn)
0272 {
0273     int ret;
0274 
0275     while (bn) {
0276         ret = bsr_add_node(bn);
0277         if (ret) {
0278             of_node_put(bn);
0279             return ret;
0280         }
0281         bn = of_find_compatible_node(bn, NULL, "ibm,bsr");
0282     }
0283     return 0;
0284 }
0285 
0286 static int __init bsr_init(void)
0287 {
0288     struct device_node *np;
0289     dev_t bsr_dev;
0290     int ret = -ENODEV;
0291 
0292     np = of_find_compatible_node(NULL, NULL, "ibm,bsr");
0293     if (!np)
0294         goto out_err;
0295 
0296     bsr_class = class_create(THIS_MODULE, "bsr");
0297     if (IS_ERR(bsr_class)) {
0298         printk(KERN_ERR "class_create() failed for bsr_class\n");
0299         ret = PTR_ERR(bsr_class);
0300         goto out_err_1;
0301     }
0302     bsr_class->dev_groups = bsr_dev_groups;
0303 
0304     ret = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr");
0305     bsr_major = MAJOR(bsr_dev);
0306     if (ret < 0) {
0307         printk(KERN_ERR "alloc_chrdev_region() failed for bsr\n");
0308         goto out_err_2;
0309     }
0310 
0311     ret = bsr_create_devs(np);
0312     if (ret < 0) {
0313         np = NULL;
0314         goto out_err_3;
0315     }
0316 
0317     return 0;
0318 
0319  out_err_3:
0320     unregister_chrdev_region(bsr_dev, BSR_MAX_DEVS);
0321 
0322  out_err_2:
0323     class_destroy(bsr_class);
0324 
0325  out_err_1:
0326     of_node_put(np);
0327 
0328  out_err:
0329 
0330     return ret;
0331 }
0332 
0333 static void __exit  bsr_exit(void)
0334 {
0335 
0336     bsr_cleanup_devs();
0337 
0338     if (bsr_class)
0339         class_destroy(bsr_class);
0340 
0341     if (bsr_major)
0342         unregister_chrdev_region(MKDEV(bsr_major, 0), BSR_MAX_DEVS);
0343 }
0344 
0345 module_init(bsr_init);
0346 module_exit(bsr_exit);
0347 MODULE_LICENSE("GPL");
0348 MODULE_AUTHOR("Sonny Rao <sonnyrao@us.ibm.com>");