Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * This file provides /sys/class/ieee80211/<wiphy name>/
0004  * and some default attributes.
0005  *
0006  * Copyright 2005-2006  Jiri Benc <jbenc@suse.cz>
0007  * Copyright 2006   Johannes Berg <johannes@sipsolutions.net>
0008  * Copyright (C) 2020-2021 Intel Corporation
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             /* Driver refuse to configure wowlan */
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     /* Age scan results with time spent in suspend */
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 }