1e23e9ec1SAlexander Aring /* This program is free software; you can redistribute it and/or modify 2e23e9ec1SAlexander Aring * it under the terms of the GNU General Public License version 2 3e23e9ec1SAlexander Aring * as published by the Free Software Foundation. 4e23e9ec1SAlexander Aring * 5e23e9ec1SAlexander Aring * This program is distributed in the hope that it will be useful, 6e23e9ec1SAlexander Aring * but WITHOUT ANY WARRANTY; without even the implied warranty of 7e23e9ec1SAlexander Aring * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 8e23e9ec1SAlexander Aring * GNU General Public License for more details. 9e23e9ec1SAlexander Aring * 10e23e9ec1SAlexander Aring * Authors: 11e23e9ec1SAlexander Aring * Alexander Aring <aar@pengutronix.de> 12e23e9ec1SAlexander Aring * 13e23e9ec1SAlexander Aring * Based on: net/wireless/sysfs.c 14e23e9ec1SAlexander Aring */ 15e23e9ec1SAlexander Aring 16e23e9ec1SAlexander Aring #include <linux/device.h> 17a6cb869bSVarka Bhadram #include <linux/rtnetlink.h> 18e23e9ec1SAlexander Aring 19e23e9ec1SAlexander Aring #include <net/cfg802154.h> 20e23e9ec1SAlexander Aring 21a5dd1d72SAlexander Aring #include "core.h" 22c5fbbc46SAlexander Aring #include "sysfs.h" 23a6cb869bSVarka Bhadram #include "rdev-ops.h" 24a5dd1d72SAlexander Aring 25a5dd1d72SAlexander Aring static inline struct cfg802154_registered_device * 26a5dd1d72SAlexander Aring dev_to_rdev(struct device *dev) 27a5dd1d72SAlexander Aring { 28a5dd1d72SAlexander Aring return container_of(dev, struct cfg802154_registered_device, 29a5dd1d72SAlexander Aring wpan_phy.dev); 30a5dd1d72SAlexander Aring } 31a5dd1d72SAlexander Aring 32a6fd693fSAlexander Aring #define SHOW_FMT(name, fmt, member) \ 33a6fd693fSAlexander Aring static ssize_t name ## _show(struct device *dev, \ 34a6fd693fSAlexander Aring struct device_attribute *attr, \ 35a6fd693fSAlexander Aring char *buf) \ 36a6fd693fSAlexander Aring { \ 37a6fd693fSAlexander Aring return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \ 38a6fd693fSAlexander Aring } \ 39a6fd693fSAlexander Aring static DEVICE_ATTR_RO(name) 40a6fd693fSAlexander Aring 41a6fd693fSAlexander Aring SHOW_FMT(index, "%d", wpan_phy_idx); 42a6fd693fSAlexander Aring 43a6fd693fSAlexander Aring static ssize_t name_show(struct device *dev, 44a6fd693fSAlexander Aring struct device_attribute *attr, 45a6fd693fSAlexander Aring char *buf) 46a6fd693fSAlexander Aring { 47a6fd693fSAlexander Aring struct wpan_phy *wpan_phy = &dev_to_rdev(dev)->wpan_phy; 48a6fd693fSAlexander Aring 49a6fd693fSAlexander Aring return sprintf(buf, "%s\n", dev_name(&wpan_phy->dev)); 50a6fd693fSAlexander Aring } 51a6fd693fSAlexander Aring static DEVICE_ATTR_RO(name); 52a6fd693fSAlexander Aring 53a5dd1d72SAlexander Aring static void wpan_phy_release(struct device *dev) 54e23e9ec1SAlexander Aring { 55a5dd1d72SAlexander Aring struct cfg802154_registered_device *rdev = dev_to_rdev(dev); 56e23e9ec1SAlexander Aring 57a5dd1d72SAlexander Aring cfg802154_dev_free(rdev); 58e23e9ec1SAlexander Aring } 59e23e9ec1SAlexander Aring 60e23e9ec1SAlexander Aring static struct attribute *pmib_attrs[] = { 61a6fd693fSAlexander Aring &dev_attr_index.attr, 62a6fd693fSAlexander Aring &dev_attr_name.attr, 63e23e9ec1SAlexander Aring NULL, 64e23e9ec1SAlexander Aring }; 65e23e9ec1SAlexander Aring ATTRIBUTE_GROUPS(pmib); 66e23e9ec1SAlexander Aring 67a6cb869bSVarka Bhadram #ifdef CONFIG_PM_SLEEP 68a6cb869bSVarka Bhadram static int wpan_phy_suspend(struct device *dev) 69a6cb869bSVarka Bhadram { 70a6cb869bSVarka Bhadram struct cfg802154_registered_device *rdev = dev_to_rdev(dev); 71a6cb869bSVarka Bhadram int ret = 0; 72a6cb869bSVarka Bhadram 73a6cb869bSVarka Bhadram if (rdev->ops->suspend) { 74a6cb869bSVarka Bhadram rtnl_lock(); 75a6cb869bSVarka Bhadram ret = rdev_suspend(rdev); 76a6cb869bSVarka Bhadram rtnl_unlock(); 77a6cb869bSVarka Bhadram } 78a6cb869bSVarka Bhadram 79a6cb869bSVarka Bhadram return ret; 80a6cb869bSVarka Bhadram } 81a6cb869bSVarka Bhadram 82a6cb869bSVarka Bhadram static int wpan_phy_resume(struct device *dev) 83a6cb869bSVarka Bhadram { 84a6cb869bSVarka Bhadram struct cfg802154_registered_device *rdev = dev_to_rdev(dev); 85a6cb869bSVarka Bhadram int ret = 0; 86a6cb869bSVarka Bhadram 87a6cb869bSVarka Bhadram if (rdev->ops->resume) { 88a6cb869bSVarka Bhadram rtnl_lock(); 89a6cb869bSVarka Bhadram ret = rdev_resume(rdev); 90a6cb869bSVarka Bhadram rtnl_unlock(); 91a6cb869bSVarka Bhadram } 92a6cb869bSVarka Bhadram 93a6cb869bSVarka Bhadram return ret; 94a6cb869bSVarka Bhadram } 95a6cb869bSVarka Bhadram 96a6cb869bSVarka Bhadram static SIMPLE_DEV_PM_OPS(wpan_phy_pm_ops, wpan_phy_suspend, wpan_phy_resume); 97a6cb869bSVarka Bhadram #define WPAN_PHY_PM_OPS (&wpan_phy_pm_ops) 98a6cb869bSVarka Bhadram #else 99a6cb869bSVarka Bhadram #define WPAN_PHY_PM_OPS NULL 100a6cb869bSVarka Bhadram #endif 101a6cb869bSVarka Bhadram 102e23e9ec1SAlexander Aring struct class wpan_phy_class = { 103e23e9ec1SAlexander Aring .name = "ieee802154", 104e23e9ec1SAlexander Aring .dev_release = wpan_phy_release, 105e23e9ec1SAlexander Aring .dev_groups = pmib_groups, 106a6cb869bSVarka Bhadram .pm = WPAN_PHY_PM_OPS, 107e23e9ec1SAlexander Aring }; 108e23e9ec1SAlexander Aring 109e23e9ec1SAlexander Aring int wpan_phy_sysfs_init(void) 110e23e9ec1SAlexander Aring { 111e23e9ec1SAlexander Aring return class_register(&wpan_phy_class); 112e23e9ec1SAlexander Aring } 113e23e9ec1SAlexander Aring 114e23e9ec1SAlexander Aring void wpan_phy_sysfs_exit(void) 115e23e9ec1SAlexander Aring { 116e23e9ec1SAlexander Aring class_unregister(&wpan_phy_class); 117e23e9ec1SAlexander Aring } 118