diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-09-01 09:43:18 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-09-01 09:43:18 -0700 |
commit | 28a4f91f5f251689c69155bc6a0b1afc9916c874 (patch) | |
tree | 76692f3610d8292b7775ab70049a5b68c618cf3a /drivers | |
parent | 8e1e49550dc85694abd04d86a8ee36bc98bd8b9e (diff) | |
parent | 29c8ab79e91d35b93cfab87bf67a11516f7b2051 (diff) | |
download | lwn-28a4f91f5f251689c69155bc6a0b1afc9916c874.tar.gz lwn-28a4f91f5f251689c69155bc6a0b1afc9916c874.zip |
Merge tag 'driver-core-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core updates from Greg KH:
"Here is a small set of driver core updates and additions for 6.6-rc1.
Included in here are:
- stable kernel documentation updates
- class structure const work from Ivan on various subsystems
- kernfs tweaks
- driver core tests!
- kobject sanity cleanups
- kobject structure reordering to save space
- driver core error code handling fixups
- other minor driver core cleanups
All of these have been in linux-next for a while with no reported
problems"
* tag 'driver-core-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (32 commits)
driver core: Call in reversed order in device_platform_notify_remove()
driver core: Return proper error code when dev_set_name() fails
kobject: Remove redundant checks for whether ktype is NULL
kobject: Add sanity check for kset->kobj.ktype in kset_register()
drivers: base: test: Add missing MODULE_* macros to root device tests
drivers: base: test: Add missing MODULE_* macros for platform devices tests
drivers: base: Free devm resources when unregistering a device
drivers: base: Add basic devm tests for platform devices
drivers: base: Add basic devm tests for root devices
kernfs: fix missing kernfs_iattr_rwsem locking
docs: stable-kernel-rules: mention that regressions must be prevented
docs: stable-kernel-rules: fine-tune various details
docs: stable-kernel-rules: make the examples for option 1 a proper list
docs: stable-kernel-rules: move text around to improve flow
docs: stable-kernel-rules: improve structure by changing headlines
base/node: Remove duplicated include
kernfs: attach uuid for every kernfs and report it in fsid
kernfs: add stub helper for kernfs_generic_poll()
x86/resctrl: make pseudo_lock_class a static const structure
x86/MSR: make msr_class a static const structure
...
Diffstat (limited to 'drivers')
25 files changed, 523 insertions, 127 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 704ba73e1459..b7d7f410c256 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2306,12 +2306,12 @@ static void device_platform_notify(struct device *dev) static void device_platform_notify_remove(struct device *dev) { - acpi_device_notify_remove(dev); + if (platform_notify_remove) + platform_notify_remove(dev); software_node_notify_remove(dev); - if (platform_notify_remove) - platform_notify_remove(dev); + acpi_device_notify_remove(dev); } /** @@ -3528,18 +3528,17 @@ int device_add(struct device *dev) * the name, and force the use of dev_name() */ if (dev->init_name) { - dev_set_name(dev, "%s", dev->init_name); + error = dev_set_name(dev, "%s", dev->init_name); dev->init_name = NULL; } + if (dev_name(dev)) + error = 0; /* subsystems can specify simple device enumeration */ - if (!dev_name(dev) && dev->bus && dev->bus->dev_name) - dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id); - - if (!dev_name(dev)) { - error = -EINVAL; + else if (dev->bus && dev->bus->dev_name) + error = dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id); + if (error) goto name_error; - } pr_debug("device: '%s': %s\n", dev_name(dev), __func__); @@ -3815,6 +3814,17 @@ void device_del(struct device *dev) device_platform_notify_remove(dev); device_links_purge(dev); + /* + * If a device does not have a driver attached, we need to clean + * up any managed resources. We do this in device_release(), but + * it's never called (and we leak the device) if a managed + * resource holds a reference to the device. So release all + * managed resources here, like we do in driver_detach(). We + * still need to do so again in device_release() in case someone + * adds a new resource after this point, though. + */ + devres_release_all(dev); + bus_notify(dev, BUS_NOTIFY_REMOVED_DEVICE); kobject_uevent(&dev->kobj, KOBJ_REMOVE); glue_dir = get_glue_dir(dev); diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 43dab03958f1..9ea22e165acd 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -19,6 +19,7 @@ #include <linux/cpufeature.h> #include <linux/tick.h> #include <linux/pm_qos.h> +#include <linux/delay.h> #include <linux/sched/isolation.h> #include "base.h" @@ -50,12 +51,30 @@ static int cpu_subsys_online(struct device *dev) int cpuid = dev->id; int from_nid, to_nid; int ret; + int retries = 0; from_nid = cpu_to_node(cpuid); if (from_nid == NUMA_NO_NODE) return -ENODEV; +retry: ret = cpu_device_up(dev); + + /* + * If -EBUSY is returned, it is likely that hotplug is temporarily + * disabled when cpu_hotplug_disable() was called. This condition is + * transient. So we retry after waiting for an exponentially + * increasing delay up to a total of at least 620ms as some PCI + * device initialization can take quite a while. + */ + if (ret == -EBUSY) { + retries++; + if (retries > 5) + return ret; + msleep(10 * (1 << retries)); + goto retry; + } + /* * When hot adding memory to memoryless node and enabling a cpu * on the node, node number of the cpu may internally change. diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 878aa7646b37..a528cec24264 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -693,6 +693,8 @@ re_probe: device_remove(dev); driver_sysfs_remove(dev); + if (dev->bus && dev->bus->dma_cleanup) + dev->bus->dma_cleanup(dev); device_unbind_cleanup(dev); goto re_probe; diff --git a/drivers/base/node.c b/drivers/base/node.c index 8e871ba9162f..493d533f8375 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -20,7 +20,6 @@ #include <linux/pm_runtime.h> #include <linux/swap.h> #include <linux/slab.h> -#include <linux/hugetlb.h> static struct bus_type node_subsys = { .name = "node", diff --git a/drivers/base/test/.kunitconfig b/drivers/base/test/.kunitconfig new file mode 100644 index 000000000000..473923f0998b --- /dev/null +++ b/drivers/base/test/.kunitconfig @@ -0,0 +1,2 @@ +CONFIG_KUNIT=y +CONFIG_DM_KUNIT_TEST=y diff --git a/drivers/base/test/Kconfig b/drivers/base/test/Kconfig index 610a1ba7a467..9d42051f8f8e 100644 --- a/drivers/base/test/Kconfig +++ b/drivers/base/test/Kconfig @@ -9,6 +9,10 @@ config TEST_ASYNC_DRIVER_PROBE If unsure say N. +config DM_KUNIT_TEST + tristate "KUnit Tests for the device model" if !KUNIT_ALL_TESTS + depends on KUNIT + config DRIVER_PE_KUNIT_TEST bool "KUnit Tests for property entry API" if !KUNIT_ALL_TESTS depends on KUNIT=y diff --git a/drivers/base/test/Makefile b/drivers/base/test/Makefile index 7f76fee6f989..e321dfc7e922 100644 --- a/drivers/base/test/Makefile +++ b/drivers/base/test/Makefile @@ -1,5 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_TEST_ASYNC_DRIVER_PROBE) += test_async_driver_probe.o +obj-$(CONFIG_DM_KUNIT_TEST) += root-device-test.o +obj-$(CONFIG_DM_KUNIT_TEST) += platform-device-test.o + obj-$(CONFIG_DRIVER_PE_KUNIT_TEST) += property-entry-test.o CFLAGS_property-entry-test.o += $(DISABLE_STRUCTLEAK_PLUGIN) diff --git a/drivers/base/test/platform-device-test.c b/drivers/base/test/platform-device-test.c new file mode 100644 index 000000000000..ea05b8785743 --- /dev/null +++ b/drivers/base/test/platform-device-test.c @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <kunit/resource.h> + +#include <linux/device.h> +#include <linux/platform_device.h> + +#define DEVICE_NAME "test" + +struct test_priv { + bool probe_done; + bool release_done; + wait_queue_head_t probe_wq; + wait_queue_head_t release_wq; + struct device *dev; +}; + +static int platform_device_devm_init(struct kunit *test) +{ + struct test_priv *priv; + + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); + init_waitqueue_head(&priv->probe_wq); + init_waitqueue_head(&priv->release_wq); + + test->priv = priv; + + return 0; +} + +static void devm_device_action(void *ptr) +{ + struct test_priv *priv = ptr; + + priv->release_done = true; + wake_up_interruptible(&priv->release_wq); +} + +static void devm_put_device_action(void *ptr) +{ + struct test_priv *priv = ptr; + + put_device(priv->dev); + priv->release_done = true; + wake_up_interruptible(&priv->release_wq); +} + +#define RELEASE_TIMEOUT_MS 100 + +/* + * Tests that a platform bus, non-probed device will run its + * device-managed actions when unregistered. + */ +static void platform_device_devm_register_unregister_test(struct kunit *test) +{ + struct platform_device *pdev; + struct test_priv *priv = test->priv; + int ret; + + pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); + + ret = platform_device_add(pdev); + KUNIT_ASSERT_EQ(test, ret, 0); + + priv->dev = &pdev->dev; + + ret = devm_add_action_or_reset(priv->dev, devm_device_action, priv); + KUNIT_ASSERT_EQ(test, ret, 0); + + platform_device_unregister(pdev); + + ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_EXPECT_GT(test, ret, 0); +} + +/* + * Tests that a platform bus, non-probed device will run its + * device-managed actions when unregistered, even if someone still holds + * a reference to it. + */ +static void platform_device_devm_register_get_unregister_with_devm_test(struct kunit *test) +{ + struct platform_device *pdev; + struct test_priv *priv = test->priv; + int ret; + + pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); + + ret = platform_device_add(pdev); + KUNIT_ASSERT_EQ(test, ret, 0); + + priv->dev = &pdev->dev; + + get_device(priv->dev); + + ret = devm_add_action_or_reset(priv->dev, devm_put_device_action, priv); + KUNIT_ASSERT_EQ(test, ret, 0); + + platform_device_unregister(pdev); + + ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_EXPECT_GT(test, ret, 0); +} + +static int fake_probe(struct platform_device *pdev) +{ + struct test_priv *priv = platform_get_drvdata(pdev); + + priv->probe_done = true; + wake_up_interruptible(&priv->probe_wq); + + return 0; +} + +static struct platform_driver fake_driver = { + .probe = fake_probe, + .driver = { + .name = DEVICE_NAME, + }, +}; + +/* + * Tests that a platform bus, probed device will run its device-managed + * actions when unregistered. + */ +static void probed_platform_device_devm_register_unregister_test(struct kunit *test) +{ + struct platform_device *pdev; + struct test_priv *priv = test->priv; + int ret; + + ret = platform_driver_register(&fake_driver); + KUNIT_ASSERT_EQ(test, ret, 0); + + pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); + + priv->dev = &pdev->dev; + platform_set_drvdata(pdev, priv); + + ret = platform_device_add(pdev); + KUNIT_ASSERT_EQ(test, ret, 0); + + ret = wait_event_interruptible_timeout(priv->probe_wq, priv->probe_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_ASSERT_GT(test, ret, 0); + + ret = devm_add_action_or_reset(priv->dev, devm_device_action, priv); + KUNIT_ASSERT_EQ(test, ret, 0); + + platform_device_unregister(pdev); + + ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_EXPECT_GT(test, ret, 0); + + platform_driver_unregister(&fake_driver); +} + +/* + * Tests that a platform bus, probed device will run its device-managed + * actions when unregistered, even if someone still holds a reference to + * it. + */ +static void probed_platform_device_devm_register_get_unregister_with_devm_test(struct kunit *test) +{ + struct platform_device *pdev; + struct test_priv *priv = test->priv; + int ret; + + ret = platform_driver_register(&fake_driver); + KUNIT_ASSERT_EQ(test, ret, 0); + + pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); + + priv->dev = &pdev->dev; + platform_set_drvdata(pdev, priv); + + ret = platform_device_add(pdev); + KUNIT_ASSERT_EQ(test, ret, 0); + + ret = wait_event_interruptible_timeout(priv->probe_wq, priv->probe_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_ASSERT_GT(test, ret, 0); + + get_device(priv->dev); + + ret = devm_add_action_or_reset(priv->dev, devm_put_device_action, priv); + KUNIT_ASSERT_EQ(test, ret, 0); + + platform_device_unregister(pdev); + + ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_EXPECT_GT(test, ret, 0); + + platform_driver_unregister(&fake_driver); +} + +static struct kunit_case platform_device_devm_tests[] = { + KUNIT_CASE(platform_device_devm_register_unregister_test), + KUNIT_CASE(platform_device_devm_register_get_unregister_with_devm_test), + KUNIT_CASE(probed_platform_device_devm_register_unregister_test), + KUNIT_CASE(probed_platform_device_devm_register_get_unregister_with_devm_test), + {} +}; + +static struct kunit_suite platform_device_devm_test_suite = { + .name = "platform-device-devm", + .init = platform_device_devm_init, + .test_cases = platform_device_devm_tests, +}; + +kunit_test_suite(platform_device_devm_test_suite); + +MODULE_DESCRIPTION("Test module for platform devices"); +MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/base/test/root-device-test.c b/drivers/base/test/root-device-test.c new file mode 100644 index 000000000000..9aea23c9123e --- /dev/null +++ b/drivers/base/test/root-device-test.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright 2023 Maxime Ripard <mripard@kernel.org> + +#include <kunit/resource.h> + +#include <linux/device.h> + +#define DEVICE_NAME "test" + +struct test_priv { + bool probe_done; + bool release_done; + wait_queue_head_t release_wq; + struct device *dev; +}; + +static int root_device_devm_init(struct kunit *test) +{ + struct test_priv *priv; + + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); + init_waitqueue_head(&priv->release_wq); + + test->priv = priv; + + return 0; +} + +static void devm_device_action(void *ptr) +{ + struct test_priv *priv = ptr; + + priv->release_done = true; + wake_up_interruptible(&priv->release_wq); +} + +#define RELEASE_TIMEOUT_MS 100 + +/* + * Tests that a bus-less, non-probed device will run its device-managed + * actions when unregistered. + */ +static void root_device_devm_register_unregister_test(struct kunit *test) +{ + struct test_priv *priv = test->priv; + int ret; + + priv->dev = root_device_register(DEVICE_NAME); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev); + + ret = devm_add_action_or_reset(priv->dev, devm_device_action, priv); + KUNIT_ASSERT_EQ(test, ret, 0); + + root_device_unregister(priv->dev); + + ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_EXPECT_GT(test, ret, 0); +} + +static void devm_put_device_action(void *ptr) +{ + struct test_priv *priv = ptr; + + put_device(priv->dev); + priv->release_done = true; + wake_up_interruptible(&priv->release_wq); +} + +/* + * Tests that a bus-less, non-probed device will run its device-managed + * actions when unregistered, even if someone still holds a reference to + * it. + */ +static void root_device_devm_register_get_unregister_with_devm_test(struct kunit *test) +{ + struct test_priv *priv = test->priv; + int ret; + + priv->dev = root_device_register(DEVICE_NAME); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev); + + get_device(priv->dev); + + ret = devm_add_action_or_reset(priv->dev, devm_put_device_action, priv); + KUNIT_ASSERT_EQ(test, ret, 0); + + root_device_unregister(priv->dev); + + ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done, + msecs_to_jiffies(RELEASE_TIMEOUT_MS)); + KUNIT_EXPECT_GT(test, ret, 0); +} + +static struct kunit_case root_device_devm_tests[] = { + KUNIT_CASE(root_device_devm_register_unregister_test), + KUNIT_CASE(root_device_devm_register_get_unregister_with_devm_test), + {} +}; + +static struct kunit_suite root_device_devm_test_suite = { + .name = "root-device-devm", + .init = root_device_devm_init, + .test_cases = root_device_devm_tests, +}; + +kunit_test_suite(root_device_devm_test_suite); + +MODULE_DESCRIPTION("Test module for root devices"); +MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/base/test/test_async_driver_probe.c b/drivers/base/test/test_async_driver_probe.c index 929410d0dd6f..3465800baa6c 100644 --- a/drivers/base/test/test_async_driver_probe.c +++ b/drivers/base/test/test_async_driver_probe.c @@ -84,7 +84,7 @@ test_platform_device_register_node(char *name, int id, int nid) pdev = platform_device_alloc(name, id); if (!pdev) - return NULL; + return ERR_PTR(-ENOMEM); if (nid != NUMA_NO_NODE) set_dev_node(&pdev->dev, nid); diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index ea6b4013bc38..23f6f2eda84c 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -28,8 +28,13 @@ DEFINE_IDR(dev_nums_idr); static DEFINE_MUTEX(idr_lock); -struct class *tpm_class; -struct class *tpmrm_class; +const struct class tpm_class = { + .name = "tpm", + .shutdown_pre = tpm_class_shutdown, +}; +const struct class tpmrm_class = { + .name = "tmprm", +}; dev_t tpm_devt; static int tpm_request_locality(struct tpm_chip *chip) @@ -336,7 +341,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev, device_initialize(&chip->dev); - chip->dev.class = tpm_class; + chip->dev.class = &tpm_class; chip->dev.release = tpm_dev_release; chip->dev.parent = pdev; chip->dev.groups = chip->groups; diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 586ca10b0d72..66b16d26eecc 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -476,18 +476,15 @@ static int __init tpm_init(void) { int rc; - tpm_class = class_create("tpm"); - if (IS_ERR(tpm_class)) { + rc = class_register(&tpm_class); + if (rc) { pr_err("couldn't create tpm class\n"); - return PTR_ERR(tpm_class); + return rc; } - tpm_class->shutdown_pre = tpm_class_shutdown; - - tpmrm_class = class_create("tpmrm"); - if (IS_ERR(tpmrm_class)) { + rc = class_register(&tpmrm_class); + if (rc) { pr_err("couldn't create tpmrm class\n"); - rc = PTR_ERR(tpmrm_class); goto out_destroy_tpm_class; } @@ -508,9 +505,9 @@ static int __init tpm_init(void) out_unreg_chrdev: unregister_chrdev_region(tpm_devt, 2 * TPM_NUM_DEVICES); out_destroy_tpmrm_class: - class_destroy(tpmrm_class); + class_unregister(&tpmrm_class); out_destroy_tpm_class: - class_destroy(tpm_class); + class_unregister(&tpm_class); return rc; } @@ -518,8 +515,8 @@ out_destroy_tpm_class: static void __exit tpm_exit(void) { idr_destroy(&dev_nums_idr); - class_destroy(tpm_class); - class_destroy(tpmrm_class); + class_unregister(&tpm_class); + class_unregister(&tpmrm_class); unregister_chrdev_region(tpm_devt, 2*TPM_NUM_DEVICES); tpm_dev_common_exit(); } diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 460bb85dd142..61445f1dc46d 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -230,8 +230,8 @@ enum tpm2_pt_props { * compiler warnings about stack frame size. */ #define TPM_MAX_RNG_DATA 128 -extern struct class *tpm_class; -extern struct class *tpmrm_class; +extern const struct class tpm_class; +extern const struct class tpmrm_class; extern dev_t tpm_devt; extern const struct file_operations tpm_fops; extern const struct file_operations tpmrm_fops; diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c index ffb35f0154c1..363afdd4d1d3 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c @@ -606,7 +606,7 @@ int tpm_devs_add(struct tpm_chip *chip) device_initialize(&chip->devs); chip->devs.parent = chip->dev.parent; - chip->devs.class = tpmrm_class; + chip->devs.class = &tpmrm_class; /* * Get extra reference on main device to hold on behalf of devs. diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c index ea6b79b3aeeb..d55aaabab1ed 100644 --- a/drivers/hid/hid-roccat-arvo.c +++ b/drivers/hid/hid-roccat-arvo.c @@ -23,8 +23,6 @@ #include "hid-roccat-common.h" #include "hid-roccat-arvo.h" -static struct class *arvo_class; - static ssize_t arvo_sysfs_show_mode_key(struct device *dev, struct device_attribute *attr, char *buf) { @@ -268,6 +266,11 @@ static const struct attribute_group *arvo_groups[] = { NULL, }; +static const struct class arvo_class = { + .name = "arvo", + .dev_groups = arvo_groups, +}; + static int arvo_init_arvo_device_struct(struct usb_device *usb_dev, struct arvo_device *arvo) { @@ -309,7 +312,7 @@ static int arvo_init_specials(struct hid_device *hdev) goto exit_free; } - retval = roccat_connect(arvo_class, hdev, + retval = roccat_connect(&arvo_class, hdev, sizeof(struct arvo_roccat_report)); if (retval < 0) { hid_err(hdev, "couldn't init char dev\n"); @@ -433,21 +436,20 @@ static int __init arvo_init(void) { int retval; - arvo_class = class_create("arvo"); - if (IS_ERR(arvo_class)) - return PTR_ERR(arvo_class); - arvo_class->dev_groups = arvo_groups; + retval = class_register(&arvo_class); + if (retval) + return retval; retval = hid_register_driver(&arvo_driver); if (retval) - class_destroy(arvo_class); + class_unregister(&arvo_class); return retval; } static void __exit arvo_exit(void) { hid_unregister_driver(&arvo_driver); - class_destroy(arvo_class); + class_unregister(&arvo_class); } module_init(arvo_init); diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c index 3903a2cea00c..458060403397 100644 --- a/drivers/hid/hid-roccat-isku.c +++ b/drivers/hid/hid-roccat-isku.c @@ -23,8 +23,6 @@ #include "hid-roccat-common.h" #include "hid-roccat-isku.h" -static struct class *isku_class; - static void isku_profile_activated(struct isku_device *isku, uint new_profile) { isku->actual_profile = new_profile; @@ -248,6 +246,11 @@ static const struct attribute_group *isku_groups[] = { NULL, }; +static const struct class isku_class = { + .name = "isku", + .dev_groups = isku_groups, +}; + static int isku_init_isku_device_struct(struct usb_device *usb_dev, struct isku_device *isku) { @@ -289,7 +292,7 @@ static int isku_init_specials(struct hid_device *hdev) goto exit_free; } - retval = roccat_connect(isku_class, hdev, + retval = roccat_connect(&isku_class, hdev, sizeof(struct isku_roccat_report)); if (retval < 0) { hid_err(hdev, "couldn't init char dev\n"); @@ -435,21 +438,21 @@ static struct hid_driver isku_driver = { static int __init isku_init(void) { int retval; - isku_class = class_create("isku"); - if (IS_ERR(isku_class)) - return PTR_ERR(isku_class); - isku_class->dev_groups = isku_groups; + + retval = class_register(&isku_class); + if (retval) + return retval; retval = hid_register_driver(&isku_driver); if (retval) - class_destroy(isku_class); + class_unregister(&isku_class); return retval; } static void __exit isku_exit(void) { hid_unregister_driver(&isku_driver); - class_destroy(isku_class); + class_unregister(&isku_class); } module_init(isku_init); diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index 945ae236fb45..00a1abc7e839 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c @@ -89,9 +89,6 @@ static int kone_send(struct usb_device *usb_dev, uint usb_command, return ((len < 0) ? len : ((len != size) ? -EIO : 0)); } -/* kone_class is used for creating sysfs attributes via roccat char device */ -static struct class *kone_class; - static void kone_set_settings_checksum(struct kone_settings *settings) { uint16_t checksum = 0; @@ -657,6 +654,12 @@ static const struct attribute_group *kone_groups[] = { NULL, }; +/* kone_class is used for creating sysfs attributes via roccat char device */ +static const struct class kone_class = { + .name = "kone", + .dev_groups = kone_groups, +}; + static int kone_init_kone_device_struct(struct usb_device *usb_dev, struct kone_device *kone) { @@ -712,8 +715,8 @@ static int kone_init_specials(struct hid_device *hdev) goto exit_free; } - retval = roccat_connect(kone_class, hdev, - sizeof(struct kone_roccat_report)); + retval = roccat_connect(&kone_class, hdev, + sizeof(struct kone_roccat_report)); if (retval < 0) { hid_err(hdev, "couldn't init char dev\n"); /* be tolerant about not getting chrdev */ @@ -890,21 +893,20 @@ static int __init kone_init(void) int retval; /* class name has to be same as driver name */ - kone_class = class_create("kone"); - if (IS_ERR(kone_class)) - return PTR_ERR(kone_class); - kone_class->dev_groups = kone_groups; + retval = class_register(&kone_class); + if (retval) + return retval; retval = hid_register_driver(&kone_driver); if (retval) - class_destroy(kone_class); + class_unregister(&kone_class); return retval; } static void __exit kone_exit(void) { hid_unregister_driver(&kone_driver); - class_destroy(kone_class); + class_unregister(&kone_class); } module_init(kone_init); diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c index 97b83b6f53dd..22b895436a7c 100644 --- a/drivers/hid/hid-roccat-koneplus.c +++ b/drivers/hid/hid-roccat-koneplus.c @@ -26,8 +26,6 @@ static uint profile_numbers[5] = {0, 1, 2, 3, 4}; -static struct class *koneplus_class; - static void koneplus_profile_activated(struct koneplus_device *koneplus, uint new_profile) { @@ -356,6 +354,11 @@ static const struct attribute_group *koneplus_groups[] = { NULL, }; +static const struct class koneplus_class = { + .name = "koneplus", + .dev_groups = koneplus_groups, +}; + static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev, struct koneplus_device *koneplus) { @@ -394,8 +397,8 @@ static int koneplus_init_specials(struct hid_device *hdev) goto exit_free; } - retval = roccat_connect(koneplus_class, hdev, - sizeof(struct koneplus_roccat_report)); + retval = roccat_connect(&koneplus_class, hdev, + sizeof(struct koneplus_roccat_report)); if (retval < 0) { hid_err(hdev, "couldn't init char dev\n"); } else { @@ -549,21 +552,20 @@ static int __init koneplus_init(void) int retval; /* class name has to be same as driver name */ - koneplus_class = class_create("koneplus"); - if (IS_ERR(koneplus_class)) - return PTR_ERR(koneplus_class); - koneplus_class->dev_groups = koneplus_groups; + retval = class_register(&koneplus_class); + if (retval) + return retval; retval = hid_register_driver(&koneplus_driver); if (retval) - class_destroy(koneplus_class); + class_unregister(&koneplus_class); return retval; } static void __exit koneplus_exit(void) { hid_unregister_driver(&koneplus_driver); - class_destroy(koneplus_class); + class_unregister(&koneplus_class); } module_init(koneplus_init); diff --git a/drivers/hid/hid-roccat-konepure.c b/drivers/hid/hid-roccat-konepure.c index a297756f2410..beca8aef8bbb 100644 --- a/drivers/hid/hid-roccat-konepure.c +++ b/drivers/hid/hid-roccat-konepure.c @@ -36,8 +36,6 @@ struct konepure_mouse_report_button { uint8_t unknown[2]; } __packed; -static struct class *konepure_class; - ROCCAT_COMMON2_BIN_ATTRIBUTE_W(control, 0x04, 0x03); ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(actual_profile, 0x05, 0x03); ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(profile_settings, 0x06, 0x1f); @@ -72,6 +70,11 @@ static const struct attribute_group *konepure_groups[] = { NULL, }; +static const struct class konepure_class = { + .name = "konepure", + .dev_groups = konepure_groups, +}; + static int konepure_init_specials(struct hid_device *hdev) { struct usb_interface *intf = to_usb_interface(hdev->dev.parent); @@ -98,8 +101,8 @@ static int konepure_init_specials(struct hid_device *hdev) goto exit_free; } - retval = roccat_connect(konepure_class, hdev, - sizeof(struct konepure_mouse_report_button)); + retval = roccat_connect(&konepure_class, hdev, + sizeof(struct konepure_mouse_report_button)); if (retval < 0) { hid_err(hdev, "couldn't init char dev\n"); } else { @@ -207,21 +210,20 @@ static int __init konepure_init(void) { int retval; - konepure_class = class_create("konepure"); - if (IS_ERR(konepure_class)) - return PTR_ERR(konepure_class); - konepure_class->dev_groups = konepure_groups; + retval = class_register(&konepure_class); + if (retval) + return retval; retval = hid_register_driver(&konepure_driver); if (retval) - class_destroy(konepure_class); + class_unregister(&konepure_class); return retval; } static void __exit konepure_exit(void) { hid_unregister_driver(&konepure_driver); - class_destroy(konepure_class); + class_unregister(&konepure_class); } module_init(konepure_init); diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c index 1a1d96e11683..86af538c10d6 100644 --- a/drivers/hid/hid-roccat-kovaplus.c +++ b/drivers/hid/hid-roccat-kovaplus.c @@ -24,8 +24,6 @@ static uint profile_numbers[5] = {0, 1, 2, 3, 4}; -static struct class *kovaplus_class; - static uint kovaplus_convert_event_cpi(uint value) { return (value == 7 ? 4 : (value == 4 ? 3 : value)); @@ -409,6 +407,11 @@ static const struct attribute_group *kovaplus_groups[] = { NULL, }; +static const struct class kovaplus_class = { + .name = "kovaplus", + .dev_groups = kovaplus_groups, +}; + static int kovaplus_init_kovaplus_device_struct(struct usb_device *usb_dev, struct kovaplus_device *kovaplus) { @@ -463,8 +466,8 @@ static int kovaplus_init_specials(struct hid_device *hdev) goto exit_free; } - retval = roccat_connect(kovaplus_class, hdev, - sizeof(struct kovaplus_roccat_report)); + retval = roccat_connect(&kovaplus_class, hdev, + sizeof(struct kovaplus_roccat_report)); if (retval < 0) { hid_err(hdev, "couldn't init char dev\n"); } else { @@ -638,21 +641,20 @@ static int __init kovaplus_init(void) { int retval; - kovaplus_class = class_create("kovaplus"); - if (IS_ERR(kovaplus_class)) - return PTR_ERR(kovaplus_class); - kovaplus_class->dev_groups = kovaplus_groups; + retval = class_register(&kovaplus_class); + if (retval) + return retval; retval = hid_register_driver(&kovaplus_driver); if (retval) - class_destroy(kovaplus_class); + class_unregister(&kovaplus_class); return retval; } static void __exit kovaplus_exit(void) { hid_unregister_driver(&kovaplus_driver); - class_destroy(kovaplus_class); + class_unregister(&kovaplus_class); } module_init(kovaplus_init); diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c index 15528c3b013c..5663b9cd9c69 100644 --- a/drivers/hid/hid-roccat-pyra.c +++ b/drivers/hid/hid-roccat-pyra.c @@ -26,9 +26,6 @@ static uint profile_numbers[5] = {0, 1, 2, 3, 4}; -/* pyra_class is used for creating sysfs attributes via roccat char device */ -static struct class *pyra_class; - static void profile_activated(struct pyra_device *pyra, unsigned int new_profile) { @@ -366,6 +363,12 @@ static const struct attribute_group *pyra_groups[] = { NULL, }; +/* pyra_class is used for creating sysfs attributes via roccat char device */ +static const struct class pyra_class = { + .name = "pyra", + .dev_groups = pyra_groups, +}; + static int pyra_init_pyra_device_struct(struct usb_device *usb_dev, struct pyra_device *pyra) { @@ -413,7 +416,7 @@ static int pyra_init_specials(struct hid_device *hdev) goto exit_free; } - retval = roccat_connect(pyra_class, hdev, + retval = roccat_connect(&pyra_class, hdev, sizeof(struct pyra_roccat_report)); if (retval < 0) { hid_err(hdev, "couldn't init char dev\n"); @@ -585,21 +588,20 @@ static int __init pyra_init(void) int retval; /* class name has to be same as driver name */ - pyra_class = class_create("pyra"); - if (IS_ERR(pyra_class)) - return PTR_ERR(pyra_class); - pyra_class->dev_groups = pyra_groups; + retval = class_register(&pyra_class); + if (retval) + return retval; retval = hid_register_driver(&pyra_driver); if (retval) - class_destroy(pyra_class); + class_unregister(&pyra_class); return retval; } static void __exit pyra_exit(void) { hid_unregister_driver(&pyra_driver); - class_destroy(pyra_class); + class_unregister(&pyra_class); } module_init(pyra_init); diff --git a/drivers/hid/hid-roccat-ryos.c b/drivers/hid/hid-roccat-ryos.c index 0eb17a3b925d..57714a4525e2 100644 --- a/drivers/hid/hid-roccat-ryos.c +++ b/drivers/hid/hid-roccat-ryos.c @@ -28,8 +28,6 @@ struct ryos_report_special { uint8_t data[4]; } __packed; -static struct class *ryos_class; - ROCCAT_COMMON2_BIN_ATTRIBUTE_W(control, 0x04, 0x03); ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(profile, 0x05, 0x03); ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(keys_primary, 0x06, 0x7d); @@ -80,6 +78,11 @@ static const struct attribute_group *ryos_groups[] = { NULL, }; +static const struct class ryos_class = { + .name = "ryos", + .dev_groups = ryos_groups, +}; + static int ryos_init_specials(struct hid_device *hdev) { struct usb_interface *intf = to_usb_interface(hdev->dev.parent); @@ -106,7 +109,7 @@ static int ryos_init_specials(struct hid_device *hdev) goto exit_free; } - retval = roccat_connect(ryos_class, hdev, + retval = roccat_connect(&ryos_class, hdev, sizeof(struct ryos_report_special)); if (retval < 0) { hid_err(hdev, "couldn't init char dev\n"); @@ -216,21 +219,20 @@ static int __init ryos_init(void) { int retval; - ryos_class = class_create("ryos"); - if (IS_ERR(ryos_class)) - return PTR_ERR(ryos_class); - ryos_class->dev_groups = ryos_groups; + retval = class_register(&ryos_class); + if (retval) + return retval; retval = hid_register_driver(&ryos_driver); if (retval) - class_destroy(ryos_class); + class_unregister(&ryos_class); return retval; } static void __exit ryos_exit(void) { hid_unregister_driver(&ryos_driver); - class_destroy(ryos_class); + class_unregister(&ryos_class); } module_init(ryos_init); diff --git a/drivers/hid/hid-roccat-savu.c b/drivers/hid/hid-roccat-savu.c index 93be7acef673..2baa47a0efc5 100644 --- a/drivers/hid/hid-roccat-savu.c +++ b/drivers/hid/hid-roccat-savu.c @@ -22,8 +22,6 @@ #include "hid-roccat-common.h" #include "hid-roccat-savu.h" -static struct class *savu_class; - ROCCAT_COMMON2_BIN_ATTRIBUTE_W(control, 0x4, 0x03); ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(profile, 0x5, 0x03); ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(general, 0x6, 0x10); @@ -52,6 +50,11 @@ static const struct attribute_group *savu_groups[] = { NULL, }; +static const struct class savu_class = { + .name = "savu", + .dev_groups = savu_groups, +}; + static int savu_init_specials(struct hid_device *hdev) { struct usb_interface *intf = to_usb_interface(hdev->dev.parent); @@ -78,7 +81,7 @@ static int savu_init_specials(struct hid_device *hdev) goto exit_free; } - retval = roccat_connect(savu_class, hdev, + retval = roccat_connect(&savu_class, hdev, sizeof(struct savu_roccat_report)); if (retval < 0) { hid_err(hdev, "couldn't init char dev\n"); @@ -204,21 +207,20 @@ static int __init savu_init(void) { int retval; - savu_class = class_create("savu"); - if (IS_ERR(savu_class)) - return PTR_ERR(savu_class); - savu_class->dev_groups = savu_groups; + retval = class_register(&savu_class); + if (retval) + return retval; retval = hid_register_driver(&savu_driver); if (retval) - class_destroy(savu_class); + class_unregister(&savu_class); return retval; } static void __exit savu_exit(void) { hid_unregister_driver(&savu_driver); - class_destroy(savu_class); + class_unregister(&savu_class); } module_init(savu_init); diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c index 6da80e442fdd..c7f7562e22e5 100644 --- a/drivers/hid/hid-roccat.c +++ b/drivers/hid/hid-roccat.c @@ -295,7 +295,7 @@ EXPORT_SYMBOL_GPL(roccat_report_event); * Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on * success, a negative error code on failure. */ -int roccat_connect(struct class *klass, struct hid_device *hid, int report_size) +int roccat_connect(const struct class *klass, struct hid_device *hid, int report_size) { unsigned int minor; struct roccat_device *device; diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index e63c56a0d57f..13c8dd8cd350 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -32,7 +32,9 @@ static int hidraw_major; static struct cdev hidraw_cdev; -static struct class *hidraw_class; +static const struct class hidraw_class = { + .name = "hidraw", +}; static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; static DECLARE_RWSEM(minors_rwsem); @@ -329,7 +331,7 @@ static void drop_ref(struct hidraw *hidraw, int exists_bit) hid_hw_close(hidraw->hid); wake_up_interruptible(&hidraw->wait); } - device_destroy(hidraw_class, + device_destroy(&hidraw_class, MKDEV(hidraw_major, hidraw->minor)); } else { --hidraw->open; @@ -569,7 +571,7 @@ int hidraw_connect(struct hid_device *hid) goto out; } - dev->dev = device_create(hidraw_class, &hid->dev, MKDEV(hidraw_major, minor), + dev->dev = device_create(&hidraw_class, &hid->dev, MKDEV(hidraw_major, minor), NULL, "%s%d", "hidraw", minor); if (IS_ERR(dev->dev)) { @@ -623,11 +625,9 @@ int __init hidraw_init(void) hidraw_major = MAJOR(dev_id); - hidraw_class = class_create("hidraw"); - if (IS_ERR(hidraw_class)) { - result = PTR_ERR(hidraw_class); + result = class_register(&hidraw_class); + if (result) goto error_cdev; - } cdev_init(&hidraw_cdev, &hidraw_ops); result = cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES); @@ -639,7 +639,7 @@ out: return result; error_class: - class_destroy(hidraw_class); + class_unregister(&hidraw_class); error_cdev: unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES); goto out; @@ -650,7 +650,7 @@ void hidraw_exit(void) dev_t dev_id = MKDEV(hidraw_major, 0); cdev_del(&hidraw_cdev); - class_destroy(hidraw_class); + class_unregister(&hidraw_class); unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES); } |