Something went wrong. Try again.
Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188// SPDX-License-Identifier: GPL-2.0-only/* * This file provides /sys/class/ieee80211/<wiphy name>/ * and some default attributes. * * Copyright 2005-2006 Jiri Benc <jbenc@suse.cz> * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> * Copyright (C) 2020-2021, 2023-2024 Intel Corporation */
#include <linux/device.h>#include <linux/module.h>#include <linux/netdevice.h>#include <linux/nl80211.h>#include <linux/rtnetlink.h>#include <net/cfg80211.h>#include "sysfs.h"#include "core.h"#include "rdev-ops.h"
static inline struct cfg80211_registered_device *dev_to_rdev( struct device *dev){ return container_of(dev, struct cfg80211_registered_device, wiphy.dev);}
#define SHOW_FMT(name, fmt, member) \static ssize_t name ## _show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \{ \ return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \} \static DEVICE_ATTR_RO(name)
SHOW_FMT(index, "%d", wiphy_idx);SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);SHOW_FMT(address_mask, "%pM", wiphy.addr_mask);
static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf){ struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy;
return sprintf(buf, "%s\n", wiphy_name(wiphy));}static DEVICE_ATTR_RO(name);
static ssize_t addresses_show(struct device *dev, struct device_attribute *attr, char *buf){ struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy; char *start = buf; int i;
if (!wiphy->addresses) return sprintf(buf, "%pM\n", wiphy->perm_addr);
for (i = 0; i < wiphy->n_addresses; i++) buf += sprintf(buf, "%pM\n", wiphy->addresses[i].addr);
return buf - start;}static DEVICE_ATTR_RO(addresses);
static struct attribute *ieee80211_attrs[] = { &dev_attr_index.attr, &dev_attr_macaddress.attr, &dev_attr_address_mask.attr, &dev_attr_addresses.attr, &dev_attr_name.attr, NULL,};ATTRIBUTE_GROUPS(ieee80211);
static void wiphy_dev_release(struct device *dev){ struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
cfg80211_dev_free(rdev);}
#ifdef CONFIG_PM_SLEEPstatic void cfg80211_leave_all(struct cfg80211_registered_device *rdev){ struct wireless_dev *wdev;
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) cfg80211_leave(rdev, wdev, -1);}
static int wiphy_suspend(struct device *dev){ struct cfg80211_registered_device *rdev = dev_to_rdev(dev); int ret = 0;
rdev->suspend_at = ktime_get_boottime_seconds();
rtnl_lock(); if (!rdev->wiphy.registered) goto out_unlock_rtnl;
if (rdev->wiphy.wowlan_config) { scoped_guard(wiphy, &rdev->wiphy) { cfg80211_process_wiphy_works(rdev, NULL); if (rdev->ops->suspend) ret = rdev_suspend(rdev, rdev->wiphy.wowlan_config); if (ret <= 0) goto out_unlock_rtnl; } }
/* Driver refused to configure wowlan (ret = 1) or no wowlan */
cfg80211_leave_all(rdev); scoped_guard(wiphy, &rdev->wiphy) { cfg80211_process_rdev_events(rdev); cfg80211_process_wiphy_works(rdev, NULL); if (rdev->ops->suspend) ret = rdev_suspend(rdev, NULL); }out_unlock_rtnl: if (ret == 0) rdev->suspended = true; rtnl_unlock();
return ret;}
static int wiphy_resume(struct device *dev){ struct cfg80211_registered_device *rdev = dev_to_rdev(dev); int ret = 0;
/* Age scan results with time spent in suspend */ cfg80211_bss_age(rdev, ktime_get_boottime_seconds() - rdev->suspend_at);
rtnl_lock(); wiphy_lock(&rdev->wiphy); if (rdev->wiphy.registered && rdev->ops->resume) ret = rdev_resume(rdev); rdev->suspended = false; queue_work(system_dfl_wq, &rdev->wiphy_work); wiphy_unlock(&rdev->wiphy);
if (ret) cfg80211_shutdown_all_interfaces(&rdev->wiphy);
rtnl_unlock();
return ret;}
static SIMPLE_DEV_PM_OPS(wiphy_pm_ops, wiphy_suspend, wiphy_resume);#define WIPHY_PM_OPS (&wiphy_pm_ops)#else#define WIPHY_PM_OPS NULL#endif
static const struct ns_common *wiphy_namespace(const struct device *d){ struct wiphy *wiphy = container_of(d, struct wiphy, dev);
return to_ns_common(wiphy_net(wiphy));}
struct class ieee80211_class = { .name = "ieee80211", .dev_release = wiphy_dev_release, .dev_groups = ieee80211_groups, .pm = WIPHY_PM_OPS, .ns_type = &net_ns_type_operations, .namespace = wiphy_namespace,};
int wiphy_sysfs_init(void){ return class_register(&ieee80211_class);}
void wiphy_sysfs_exit(void){ class_unregister(&ieee80211_class);}