^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Alexander Aring <aar@pengutronix.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Based on: net/wireless/sysfs.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <net/cfg802154.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "sysfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "rdev-ops.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static inline struct cfg802154_registered_device *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) dev_to_rdev(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) return container_of(dev, struct cfg802154_registered_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) wpan_phy.dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define SHOW_FMT(name, fmt, member) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static ssize_t name ## _show(struct device *dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static DEVICE_ATTR_RO(name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) SHOW_FMT(index, "%d", wpan_phy_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static ssize_t name_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct wpan_phy *wpan_phy = &dev_to_rdev(dev)->wpan_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return sprintf(buf, "%s\n", dev_name(&wpan_phy->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static DEVICE_ATTR_RO(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static void wpan_phy_release(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct cfg802154_registered_device *rdev = dev_to_rdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) cfg802154_dev_free(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static struct attribute *pmib_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) &dev_attr_index.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) &dev_attr_name.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) ATTRIBUTE_GROUPS(pmib);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static int wpan_phy_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct cfg802154_registered_device *rdev = dev_to_rdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (rdev->ops->suspend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ret = rdev_suspend(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static int wpan_phy_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct cfg802154_registered_device *rdev = dev_to_rdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (rdev->ops->resume) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) ret = rdev_resume(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static SIMPLE_DEV_PM_OPS(wpan_phy_pm_ops, wpan_phy_suspend, wpan_phy_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define WPAN_PHY_PM_OPS (&wpan_phy_pm_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define WPAN_PHY_PM_OPS NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct class wpan_phy_class = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .name = "ieee802154",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .dev_release = wpan_phy_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .dev_groups = pmib_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .pm = WPAN_PHY_PM_OPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int wpan_phy_sysfs_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return class_register(&wpan_phy_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) void wpan_phy_sysfs_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) class_unregister(&wpan_phy_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }