0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/device.h>
0012 #include <linux/module.h>
0013 #include <linux/netdevice.h>
0014 #include <linux/nl80211.h>
0015 #include <linux/rtnetlink.h>
0016 #include <net/cfg80211.h>
0017 #include "sysfs.h"
0018 #include "core.h"
0019 #include "rdev-ops.h"
0020
0021 static inline struct cfg80211_registered_device *dev_to_rdev(
0022 struct device *dev)
0023 {
0024 return container_of(dev, struct cfg80211_registered_device, wiphy.dev);
0025 }
0026
0027 #define SHOW_FMT(name, fmt, member) \
0028 static ssize_t name ## _show(struct device *dev, \
0029 struct device_attribute *attr, \
0030 char *buf) \
0031 { \
0032 return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \
0033 } \
0034 static DEVICE_ATTR_RO(name)
0035
0036 SHOW_FMT(index, "%d", wiphy_idx);
0037 SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
0038 SHOW_FMT(address_mask, "%pM", wiphy.addr_mask);
0039
0040 static ssize_t name_show(struct device *dev,
0041 struct device_attribute *attr,
0042 char *buf)
0043 {
0044 struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy;
0045
0046 return sprintf(buf, "%s\n", wiphy_name(wiphy));
0047 }
0048 static DEVICE_ATTR_RO(name);
0049
0050 static ssize_t addresses_show(struct device *dev,
0051 struct device_attribute *attr,
0052 char *buf)
0053 {
0054 struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy;
0055 char *start = buf;
0056 int i;
0057
0058 if (!wiphy->addresses)
0059 return sprintf(buf, "%pM\n", wiphy->perm_addr);
0060
0061 for (i = 0; i < wiphy->n_addresses; i++)
0062 buf += sprintf(buf, "%pM\n", wiphy->addresses[i].addr);
0063
0064 return buf - start;
0065 }
0066 static DEVICE_ATTR_RO(addresses);
0067
0068 static struct attribute *ieee80211_attrs[] = {
0069 &dev_attr_index.attr,
0070 &dev_attr_macaddress.attr,
0071 &dev_attr_address_mask.attr,
0072 &dev_attr_addresses.attr,
0073 &dev_attr_name.attr,
0074 NULL,
0075 };
0076 ATTRIBUTE_GROUPS(ieee80211);
0077
0078 static void wiphy_dev_release(struct device *dev)
0079 {
0080 struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
0081
0082 cfg80211_dev_free(rdev);
0083 }
0084
0085 #ifdef CONFIG_PM_SLEEP
0086 static void cfg80211_leave_all(struct cfg80211_registered_device *rdev)
0087 {
0088 struct wireless_dev *wdev;
0089
0090 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
0091 cfg80211_leave(rdev, wdev);
0092 }
0093
0094 static int wiphy_suspend(struct device *dev)
0095 {
0096 struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
0097 int ret = 0;
0098
0099 rdev->suspend_at = ktime_get_boottime_seconds();
0100
0101 rtnl_lock();
0102 wiphy_lock(&rdev->wiphy);
0103 if (rdev->wiphy.registered) {
0104 if (!rdev->wiphy.wowlan_config) {
0105 cfg80211_leave_all(rdev);
0106 cfg80211_process_rdev_events(rdev);
0107 }
0108 if (rdev->ops->suspend)
0109 ret = rdev_suspend(rdev, rdev->wiphy.wowlan_config);
0110 if (ret == 1) {
0111
0112 cfg80211_leave_all(rdev);
0113 cfg80211_process_rdev_events(rdev);
0114 ret = rdev_suspend(rdev, NULL);
0115 }
0116 }
0117 wiphy_unlock(&rdev->wiphy);
0118 rtnl_unlock();
0119
0120 return ret;
0121 }
0122
0123 static int wiphy_resume(struct device *dev)
0124 {
0125 struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
0126 int ret = 0;
0127
0128
0129 cfg80211_bss_age(rdev, ktime_get_boottime_seconds() - rdev->suspend_at);
0130
0131 rtnl_lock();
0132 wiphy_lock(&rdev->wiphy);
0133 if (rdev->wiphy.registered && rdev->ops->resume)
0134 ret = rdev_resume(rdev);
0135 wiphy_unlock(&rdev->wiphy);
0136
0137 if (ret)
0138 cfg80211_shutdown_all_interfaces(&rdev->wiphy);
0139
0140 rtnl_unlock();
0141
0142 return ret;
0143 }
0144
0145 static SIMPLE_DEV_PM_OPS(wiphy_pm_ops, wiphy_suspend, wiphy_resume);
0146 #define WIPHY_PM_OPS (&wiphy_pm_ops)
0147 #else
0148 #define WIPHY_PM_OPS NULL
0149 #endif
0150
0151 static const void *wiphy_namespace(struct device *d)
0152 {
0153 struct wiphy *wiphy = container_of(d, struct wiphy, dev);
0154
0155 return wiphy_net(wiphy);
0156 }
0157
0158 struct class ieee80211_class = {
0159 .name = "ieee80211",
0160 .owner = THIS_MODULE,
0161 .dev_release = wiphy_dev_release,
0162 .dev_groups = ieee80211_groups,
0163 .pm = WIPHY_PM_OPS,
0164 .ns_type = &net_ns_type_operations,
0165 .namespace = wiphy_namespace,
0166 };
0167
0168 int wiphy_sysfs_init(void)
0169 {
0170 return class_register(&ieee80211_class);
0171 }
0172
0173 void wiphy_sysfs_exit(void)
0174 {
0175 class_unregister(&ieee80211_class);
0176 }