forked from mirrors/linux
		
	 cdd30ebb1b
			
		
	
	
		cdd30ebb1b
		
	
	
	
	
		
			
			Clean up the existing export namespace code along the same lines of
commit 33def8498f ("treewide: Convert macro and uses of __section(foo)
to __section("foo")") and for the same reason, it is not desired for the
namespace argument to be a macro expansion itself.
Scripted using
  git grep -l -e MODULE_IMPORT_NS -e EXPORT_SYMBOL_NS | while read file;
  do
    awk -i inplace '
      /^#define EXPORT_SYMBOL_NS/ {
        gsub(/__stringify\(ns\)/, "ns");
        print;
        next;
      }
      /^#define MODULE_IMPORT_NS/ {
        gsub(/__stringify\(ns\)/, "ns");
        print;
        next;
      }
      /MODULE_IMPORT_NS/ {
        $0 = gensub(/MODULE_IMPORT_NS\(([^)]*)\)/, "MODULE_IMPORT_NS(\"\\1\")", "g");
      }
      /EXPORT_SYMBOL_NS/ {
        if ($0 ~ /(EXPORT_SYMBOL_NS[^(]*)\(([^,]+),/) {
  	if ($0 !~ /(EXPORT_SYMBOL_NS[^(]*)\(([^,]+), ([^)]+)\)/ &&
  	    $0 !~ /(EXPORT_SYMBOL_NS[^(]*)\(\)/ &&
  	    $0 !~ /^my/) {
  	  getline line;
  	  gsub(/[[:space:]]*\\$/, "");
  	  gsub(/[[:space:]]/, "", line);
  	  $0 = $0 " " line;
  	}
  	$0 = gensub(/(EXPORT_SYMBOL_NS[^(]*)\(([^,]+), ([^)]+)\)/,
  		    "\\1(\\2, \"\\3\")", "g");
        }
      }
      { print }' $file;
  done
Requested-by: Masahiro Yamada <masahiroy@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://mail.google.com/mail/u/2/#inbox/FMfcgzQXKWgMmjdFwwdsfgxzKpVHWPlc
Acked-by: Greg KH <gregkh@linuxfoundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
		
	
			
		
			
				
	
	
		
			283 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			283 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| /*
 | |
|  * Generic Counter interface
 | |
|  * Copyright (C) 2020 William Breathitt Gray
 | |
|  */
 | |
| #include <linux/cdev.h>
 | |
| #include <linux/counter.h>
 | |
| #include <linux/device.h>
 | |
| #include <linux/device/bus.h>
 | |
| #include <linux/export.h>
 | |
| #include <linux/fs.h>
 | |
| #include <linux/gfp.h>
 | |
| #include <linux/idr.h>
 | |
| #include <linux/init.h>
 | |
| #include <linux/kdev_t.h>
 | |
| #include <linux/module.h>
 | |
| #include <linux/mutex.h>
 | |
| #include <linux/slab.h>
 | |
| #include <linux/types.h>
 | |
| #include <linux/wait.h>
 | |
| 
 | |
| #include "counter-chrdev.h"
 | |
| #include "counter-sysfs.h"
 | |
| 
 | |
| #define COUNTER_NAME	"counter"
 | |
| 
 | |
| /* Provides a unique ID for each counter device */
 | |
| static DEFINE_IDA(counter_ida);
 | |
| 
 | |
| struct counter_device_allochelper {
 | |
| 	struct counter_device counter;
 | |
| 
 | |
| 	/*
 | |
| 	 * This ensures private data behaves like if it were kmalloced
 | |
| 	 * separately. Also ensures the minimum alignment for safe DMA
 | |
| 	 * operations (which may or may not mean cache alignment).
 | |
| 	 */
 | |
| 	unsigned long privdata[] __aligned(ARCH_DMA_MINALIGN);
 | |
| };
 | |
| 
 | |
| static void counter_device_release(struct device *dev)
 | |
| {
 | |
| 	struct counter_device *const counter =
 | |
| 		container_of(dev, struct counter_device, dev);
 | |
| 
 | |
| 	counter_chrdev_remove(counter);
 | |
| 	ida_free(&counter_ida, dev->id);
 | |
| 
 | |
| 	kfree(container_of(counter, struct counter_device_allochelper, counter));
 | |
| }
 | |
| 
 | |
| static const struct device_type counter_device_type = {
 | |
| 	.name = "counter_device",
 | |
| 	.release = counter_device_release,
 | |
| };
 | |
| 
 | |
| static const struct bus_type counter_bus_type = {
 | |
| 	.name = "counter",
 | |
| 	.dev_name = "counter",
 | |
| };
 | |
| 
 | |
| static dev_t counter_devt;
 | |
| 
 | |
| /**
 | |
|  * counter_priv - access counter device private data
 | |
|  * @counter: counter device
 | |
|  *
 | |
|  * Get the counter device private data
 | |
|  */
 | |
| void *counter_priv(const struct counter_device *const counter)
 | |
| {
 | |
| 	struct counter_device_allochelper *ch =
 | |
| 		container_of(counter, struct counter_device_allochelper, counter);
 | |
| 
 | |
| 	return &ch->privdata;
 | |
| }
 | |
| EXPORT_SYMBOL_NS_GPL(counter_priv, "COUNTER");
 | |
| 
 | |
| /**
 | |
|  * counter_alloc - allocate a counter_device
 | |
|  * @sizeof_priv: size of the driver private data
 | |
|  *
 | |
|  * This is part one of counter registration. The structure is allocated
 | |
|  * dynamically to ensure the right lifetime for the embedded struct device.
 | |
|  *
 | |
|  * If this succeeds, call counter_put() to get rid of the counter_device again.
 | |
|  */
 | |
| struct counter_device *counter_alloc(size_t sizeof_priv)
 | |
| {
 | |
| 	struct counter_device_allochelper *ch;
 | |
| 	struct counter_device *counter;
 | |
| 	struct device *dev;
 | |
| 	int err;
 | |
| 
 | |
| 	ch = kzalloc(sizeof(*ch) + sizeof_priv, GFP_KERNEL);
 | |
| 	if (!ch)
 | |
| 		return NULL;
 | |
| 
 | |
| 	counter = &ch->counter;
 | |
| 	dev = &counter->dev;
 | |
| 
 | |
| 	/* Acquire unique ID */
 | |
| 	err = ida_alloc(&counter_ida, GFP_KERNEL);
 | |
| 	if (err < 0)
 | |
| 		goto err_ida_alloc;
 | |
| 	dev->id = err;
 | |
| 
 | |
| 	mutex_init(&counter->ops_exist_lock);
 | |
| 	dev->type = &counter_device_type;
 | |
| 	dev->bus = &counter_bus_type;
 | |
| 	dev->devt = MKDEV(MAJOR(counter_devt), dev->id);
 | |
| 
 | |
| 	err = counter_chrdev_add(counter);
 | |
| 	if (err < 0)
 | |
| 		goto err_chrdev_add;
 | |
| 
 | |
| 	device_initialize(dev);
 | |
| 
 | |
| 	err = dev_set_name(dev, COUNTER_NAME "%d", dev->id);
 | |
| 	if (err)
 | |
| 		goto err_dev_set_name;
 | |
| 
 | |
| 	return counter;
 | |
| 
 | |
| err_dev_set_name:
 | |
| 
 | |
| 	counter_chrdev_remove(counter);
 | |
| err_chrdev_add:
 | |
| 
 | |
| 	ida_free(&counter_ida, dev->id);
 | |
| err_ida_alloc:
 | |
| 
 | |
| 	kfree(ch);
 | |
| 
 | |
| 	return NULL;
 | |
| }
 | |
| EXPORT_SYMBOL_NS_GPL(counter_alloc, "COUNTER");
 | |
| 
 | |
| void counter_put(struct counter_device *counter)
 | |
| {
 | |
| 	put_device(&counter->dev);
 | |
| }
 | |
| EXPORT_SYMBOL_NS_GPL(counter_put, "COUNTER");
 | |
| 
 | |
| /**
 | |
|  * counter_add - complete registration of a counter
 | |
|  * @counter: the counter to add
 | |
|  *
 | |
|  * This is part two of counter registration.
 | |
|  *
 | |
|  * If this succeeds, call counter_unregister() to get rid of the counter_device again.
 | |
|  */
 | |
| int counter_add(struct counter_device *counter)
 | |
| {
 | |
| 	int err;
 | |
| 	struct device *dev = &counter->dev;
 | |
| 
 | |
| 	if (counter->parent) {
 | |
| 		dev->parent = counter->parent;
 | |
| 		dev->of_node = counter->parent->of_node;
 | |
| 	}
 | |
| 
 | |
| 	err = counter_sysfs_add(counter);
 | |
| 	if (err < 0)
 | |
| 		return err;
 | |
| 
 | |
| 	/* implies device_add(dev) */
 | |
| 	return cdev_device_add(&counter->chrdev, dev);
 | |
| }
 | |
| EXPORT_SYMBOL_NS_GPL(counter_add, "COUNTER");
 | |
| 
 | |
| /**
 | |
|  * counter_unregister - unregister Counter from the system
 | |
|  * @counter:	pointer to Counter to unregister
 | |
|  *
 | |
|  * The Counter is unregistered from the system.
 | |
|  */
 | |
| void counter_unregister(struct counter_device *const counter)
 | |
| {
 | |
| 	if (!counter)
 | |
| 		return;
 | |
| 
 | |
| 	cdev_device_del(&counter->chrdev, &counter->dev);
 | |
| 
 | |
| 	mutex_lock(&counter->ops_exist_lock);
 | |
| 
 | |
| 	counter->ops = NULL;
 | |
| 	wake_up(&counter->events_wait);
 | |
| 
 | |
| 	mutex_unlock(&counter->ops_exist_lock);
 | |
| }
 | |
| EXPORT_SYMBOL_NS_GPL(counter_unregister, "COUNTER");
 | |
| 
 | |
| static void devm_counter_release(void *counter)
 | |
| {
 | |
| 	counter_unregister(counter);
 | |
| }
 | |
| 
 | |
| static void devm_counter_put(void *counter)
 | |
| {
 | |
| 	counter_put(counter);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * devm_counter_alloc - allocate a counter_device
 | |
|  * @dev: the device to register the release callback for
 | |
|  * @sizeof_priv: size of the driver private data
 | |
|  *
 | |
|  * This is the device managed version of counter_add(). It registers a cleanup
 | |
|  * callback to care for calling counter_put().
 | |
|  */
 | |
| struct counter_device *devm_counter_alloc(struct device *dev, size_t sizeof_priv)
 | |
| {
 | |
| 	struct counter_device *counter;
 | |
| 	int err;
 | |
| 
 | |
| 	counter = counter_alloc(sizeof_priv);
 | |
| 	if (!counter)
 | |
| 		return NULL;
 | |
| 
 | |
| 	err = devm_add_action_or_reset(dev, devm_counter_put, counter);
 | |
| 	if (err < 0)
 | |
| 		return NULL;
 | |
| 
 | |
| 	return counter;
 | |
| }
 | |
| EXPORT_SYMBOL_NS_GPL(devm_counter_alloc, "COUNTER");
 | |
| 
 | |
| /**
 | |
|  * devm_counter_add - complete registration of a counter
 | |
|  * @dev: the device to register the release callback for
 | |
|  * @counter: the counter to add
 | |
|  *
 | |
|  * This is the device managed version of counter_add(). It registers a cleanup
 | |
|  * callback to care for calling counter_unregister().
 | |
|  */
 | |
| int devm_counter_add(struct device *dev,
 | |
| 		     struct counter_device *const counter)
 | |
| {
 | |
| 	int err;
 | |
| 
 | |
| 	err = counter_add(counter);
 | |
| 	if (err < 0)
 | |
| 		return err;
 | |
| 
 | |
| 	return devm_add_action_or_reset(dev, devm_counter_release, counter);
 | |
| }
 | |
| EXPORT_SYMBOL_NS_GPL(devm_counter_add, "COUNTER");
 | |
| 
 | |
| #define COUNTER_DEV_MAX 256
 | |
| 
 | |
| static int __init counter_init(void)
 | |
| {
 | |
| 	int err;
 | |
| 
 | |
| 	err = bus_register(&counter_bus_type);
 | |
| 	if (err < 0)
 | |
| 		return err;
 | |
| 
 | |
| 	err = alloc_chrdev_region(&counter_devt, 0, COUNTER_DEV_MAX,
 | |
| 				  COUNTER_NAME);
 | |
| 	if (err < 0)
 | |
| 		goto err_unregister_bus;
 | |
| 
 | |
| 	return 0;
 | |
| 
 | |
| err_unregister_bus:
 | |
| 	bus_unregister(&counter_bus_type);
 | |
| 	return err;
 | |
| }
 | |
| 
 | |
| static void __exit counter_exit(void)
 | |
| {
 | |
| 	unregister_chrdev_region(counter_devt, COUNTER_DEV_MAX);
 | |
| 	bus_unregister(&counter_bus_type);
 | |
| }
 | |
| 
 | |
| subsys_initcall(counter_init);
 | |
| module_exit(counter_exit);
 | |
| 
 | |
| MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
 | |
| MODULE_DESCRIPTION("Generic Counter interface");
 | |
| MODULE_LICENSE("GPL v2");
 |