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 >
*
* This file is GPLv2 as found in COPYING .
*/
# 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 ,
char * buf ) {
struct wiphy * wiphy = & dev_to_rdev ( dev ) - > wiphy ;
return sprintf ( buf , " %s \n " , dev_name ( & wiphy - > dev ) ) ;
}
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 + + )
buf + = sprintf ( buf , " %pM \n " , & wiphy - > addresses [ i ] . addr ) ;
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 ) ;
}
2007-08-14 17:15:12 +04:00
static int wiphy_uevent ( struct device * dev , struct kobj_uevent_env * env )
2007-04-23 23:20:05 +04:00
{
/* TODO, we probably need stuff here */
return 0 ;
}
2013-06-23 14:51:21 +04:00
# ifdef CONFIG_PM
2013-02-28 13:55:25 +04:00
static void cfg80211_leave_all ( struct cfg80211_registered_device * rdev )
{
struct wireless_dev * wdev ;
list_for_each_entry ( wdev , & rdev - > wdev_list , list )
cfg80211_leave ( rdev , wdev ) ;
}
2009-01-19 19:20:52 +03:00
static int wiphy_suspend ( struct device * dev , pm_message_t state )
{
struct cfg80211_registered_device * rdev = dev_to_rdev ( dev ) ;
int ret = 0 ;
2009-02-12 01:14:43 +03:00
rdev - > suspend_at = get_seconds ( ) ;
2013-02-28 13:55:25 +04:00
rtnl_lock ( ) ;
if ( rdev - > wiphy . registered ) {
2013-05-15 11:30:07 +04:00
if ( ! rdev - > wiphy . wowlan_config )
2013-02-28 13:55:25 +04:00
cfg80211_leave_all ( rdev ) ;
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 ) ;
ret = rdev_suspend ( rdev , NULL ) ;
}
2009-01-19 19:20:52 +03:00
}
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 */
cfg80211_bss_age ( rdev , get_seconds ( ) - rdev - > suspend_at ) ;
2009-01-19 19:20:52 +03:00
if ( rdev - > ops - > resume ) {
rtnl_lock ( ) ;
2011-08-12 16:00:59 +04:00
if ( rdev - > wiphy . registered )
2012-06-27 18:19:42 +04:00
ret = rdev_resume ( rdev ) ;
2009-01-19 19:20:52 +03:00
rtnl_unlock ( ) ;
}
return ret ;
}
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 ,
2007-04-23 23:20:05 +04:00
. dev_uevent = wiphy_uevent ,
2013-05-15 11:30:07 +04:00
# ifdef CONFIG_PM
2009-01-19 19:20:52 +03:00
. suspend = wiphy_suspend ,
. resume = wiphy_resume ,
2013-05-15 11:30:07 +04:00
# endif
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 ) ;
}