2019-06-01 11:08:46 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2007-04-23 23:20:05 +04:00
/*
* 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 >
2021-01-22 18:19:43 +03:00
* Copyright ( C ) 2020 - 2021 Intel Corporation
2007-04-23 23:20:05 +04:00
*/
# 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"
2012-06-27 18:19:42 +04:00
# include "rdev-ops.h"
2007-04-23 23:20:05 +04:00
static inline struct cfg80211_registered_device * dev_to_rdev (
struct device * dev )
{
return container_of ( dev , struct cfg80211_registered_device , wiphy . dev ) ;
}
2008-10-28 16:00:54 +03:00
# 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 ) ; \
2013-07-25 02:05:35 +04:00
} \
static DEVICE_ATTR_RO ( name )
2007-04-23 23:20:05 +04:00
2009-02-21 08:04:19 +03:00
SHOW_FMT ( index , " %d " , wiphy_idx ) ;
2008-10-28 16:00:54 +03:00
SHOW_FMT ( macaddress , " %pM " , wiphy . perm_addr ) ;
2010-01-20 14:02:33 +03:00
SHOW_FMT ( address_mask , " %pM " , wiphy . addr_mask ) ;
2010-10-11 21:28:59 +04:00
static ssize_t name_show ( struct device * dev ,
struct device_attribute * attr ,
2017-01-04 10:24:49 +03:00
char * buf )
{
2010-10-11 21:28:59 +04:00
struct wiphy * wiphy = & dev_to_rdev ( dev ) - > wiphy ;
2017-01-04 10:24:49 +03:00
return sprintf ( buf , " %s \n " , wiphy_name ( wiphy ) ) ;
2010-10-11 21:28:59 +04:00
}
2013-07-25 02:05:35 +04:00
static DEVICE_ATTR_RO ( name ) ;
2010-10-11 21:28:59 +04:00
2010-01-20 14:02:33 +03:00
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 + + )
2016-09-15 11:57:50 +03:00
buf + = sprintf ( buf , " %pM \n " , wiphy - > addresses [ i ] . addr ) ;
2010-01-20 14:02:33 +03:00
return buf - start ;
}
2013-07-25 02:05:35 +04:00
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 ,
2007-04-23 23:20:05 +04:00
} ;
2013-07-25 02:05:35 +04:00
ATTRIBUTE_GROUPS ( ieee80211 ) ;
2007-04-23 23:20:05 +04:00
static void wiphy_dev_release ( struct device * dev )
{
struct cfg80211_registered_device * rdev = dev_to_rdev ( dev ) ;
cfg80211_dev_free ( rdev ) ;
}
2015-05-16 15:35:54 +03:00
# ifdef CONFIG_PM_SLEEP
2013-02-28 13:55:25 +04:00
static void cfg80211_leave_all ( struct cfg80211_registered_device * rdev )
{
struct wireless_dev * wdev ;
2016-05-03 16:52:04 +03:00
list_for_each_entry ( wdev , & rdev - > wiphy . wdev_list , list )
2013-02-28 13:55:25 +04:00
cfg80211_leave ( rdev , wdev ) ;
}
2015-05-16 15:35:54 +03:00
static int wiphy_suspend ( struct device * dev )
2009-01-19 19:20:52 +03:00
{
struct cfg80211_registered_device * rdev = dev_to_rdev ( dev ) ;
int ret = 0 ;
2018-06-18 18:11:14 +03:00
rdev - > suspend_at = ktime_get_boottime_seconds ( ) ;
2009-02-12 01:14:43 +03:00
2013-02-28 13:55:25 +04:00
rtnl_lock ( ) ;
2021-01-22 18:19:43 +03:00
wiphy_lock ( & rdev - > wiphy ) ;
2013-02-28 13:55:25 +04:00
if ( rdev - > wiphy . registered ) {
2016-10-26 08:56:59 +03:00
if ( ! rdev - > wiphy . wowlan_config ) {
2013-02-28 13:55:25 +04:00
cfg80211_leave_all ( rdev ) ;
2016-10-26 08:56:59 +03:00
cfg80211_process_rdev_events ( rdev ) ;
}
2013-02-28 13:55:25 +04:00
if ( rdev - > ops - > suspend )
2013-05-15 11:30:07 +04:00
ret = rdev_suspend ( rdev , rdev - > wiphy . wowlan_config ) ;
2013-02-28 13:55:25 +04:00
if ( ret = = 1 ) {
/* Driver refuse to configure wowlan */
cfg80211_leave_all ( rdev ) ;
2016-10-26 08:56:59 +03:00
cfg80211_process_rdev_events ( rdev ) ;
2013-02-28 13:55:25 +04:00
ret = rdev_suspend ( rdev , NULL ) ;
}
2009-01-19 19:20:52 +03:00
}
2021-01-22 18:19:43 +03:00
wiphy_unlock ( & rdev - > wiphy ) ;
2013-02-28 13:55:25 +04:00
rtnl_unlock ( ) ;
2009-01-19 19:20:52 +03:00
return ret ;
}
static int wiphy_resume ( struct device * dev )
{
struct cfg80211_registered_device * rdev = dev_to_rdev ( dev ) ;
int ret = 0 ;
2009-02-12 01:14:43 +03:00
/* Age scan results with time spent in suspend */
2018-06-18 18:11:14 +03:00
cfg80211_bss_age ( rdev , ktime_get_boottime_seconds ( ) - rdev - > suspend_at ) ;
2009-02-12 01:14:43 +03:00
2017-03-28 11:11:31 +03:00
rtnl_lock ( ) ;
2021-01-22 18:19:43 +03:00
wiphy_lock ( & rdev - > wiphy ) ;
2017-03-28 11:11:31 +03:00
if ( rdev - > wiphy . registered & & rdev - > ops - > resume )
ret = rdev_resume ( rdev ) ;
2021-01-22 18:19:43 +03:00
wiphy_unlock ( & rdev - > wiphy ) ;
2021-06-08 12:32:29 +03:00
if ( ret )
cfg80211_shutdown_all_interfaces ( & rdev - > wiphy ) ;
2017-03-28 11:11:31 +03:00
rtnl_unlock ( ) ;
2009-01-19 19:20:52 +03:00
return ret ;
}
2015-05-16 15:35:54 +03:00
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
2013-05-15 11:30:07 +04:00
# endif
2009-01-19 19:20:52 +03:00
2010-08-05 19:45:15 +04:00
static const void * wiphy_namespace ( struct device * d )
{
struct wiphy * wiphy = container_of ( d , struct wiphy , dev ) ;
return wiphy_net ( wiphy ) ;
}
2007-04-23 23:20:05 +04:00
struct class ieee80211_class = {
. name = " ieee80211 " ,
. owner = THIS_MODULE ,
. dev_release = wiphy_dev_release ,
2013-07-25 02:05:35 +04:00
. dev_groups = ieee80211_groups ,
2015-05-16 15:35:54 +03:00
. pm = WIPHY_PM_OPS ,
2010-08-05 19:45:15 +04:00
. ns_type = & net_ns_type_operations ,
. namespace = wiphy_namespace ,
2007-04-23 23:20:05 +04:00
} ;
int wiphy_sysfs_init ( void )
{
return class_register ( & ieee80211_class ) ;
}
void wiphy_sysfs_exit ( void )
{
class_unregister ( & ieee80211_class ) ;
}