2019-05-27 09:55:21 +03:00
// SPDX-License-Identifier: GPL-2.0-only
/*
2014-11-02 06:18:36 +03:00
*
* Authors :
* Alexander Aring < aar @ pengutronix . de >
*
* Based on : net / mac80211 / cfg . c
*/
2014-11-05 22:51:17 +03:00
# include <net/rtnetlink.h>
2014-11-02 06:18:36 +03:00
# include <net/cfg802154.h>
2014-11-02 06:18:38 +03:00
# include "ieee802154_i.h"
2014-11-12 05:36:55 +03:00
# include "driver-ops.h"
2014-11-02 23:43:05 +03:00
# include "cfg.h"
2014-11-02 06:18:38 +03:00
static struct net_device *
ieee802154_add_iface_deprecated ( struct wpan_phy * wpan_phy ,
2015-04-30 18:44:57 +03:00
const char * name ,
unsigned char name_assign_type , int type )
2014-11-02 06:18:38 +03:00
{
2014-11-05 22:51:15 +03:00
struct ieee802154_local * local = wpan_phy_priv ( wpan_phy ) ;
2014-11-05 22:51:17 +03:00
struct net_device * dev ;
2014-11-05 22:51:15 +03:00
2014-11-05 22:51:17 +03:00
rtnl_lock ( ) ;
2015-04-30 18:44:57 +03:00
dev = ieee802154_if_add ( local , name , name_assign_type , type ,
2014-11-17 10:20:52 +03:00
cpu_to_le64 ( 0x0000000000000000ULL ) ) ;
2014-11-05 22:51:17 +03:00
rtnl_unlock ( ) ;
return dev ;
2014-11-02 06:18:38 +03:00
}
static void ieee802154_del_iface_deprecated ( struct wpan_phy * wpan_phy ,
struct net_device * dev )
{
2014-11-05 22:51:14 +03:00
struct ieee802154_sub_if_data * sdata = IEEE802154_DEV_TO_SUB_IF ( dev ) ;
ieee802154_if_remove ( sdata ) ;
2014-11-02 06:18:38 +03:00
}
2015-06-24 12:36:36 +03:00
# ifdef CONFIG_PM
static int ieee802154_suspend ( struct wpan_phy * wpan_phy )
{
struct ieee802154_local * local = wpan_phy_priv ( wpan_phy ) ;
if ( ! local - > open_count )
goto suspend ;
ieee802154_stop_queue ( & local - > hw ) ;
synchronize_net ( ) ;
/* stop hardware - this must stop RX */
ieee802154_stop_device ( local ) ;
suspend :
local - > suspended = true ;
return 0 ;
}
static int ieee802154_resume ( struct wpan_phy * wpan_phy )
{
struct ieee802154_local * local = wpan_phy_priv ( wpan_phy ) ;
int ret ;
/* nothing to do if HW shouldn't run */
if ( ! local - > open_count )
goto wake_up ;
/* restart hardware */
ret = drv_start ( local ) ;
if ( ret )
return ret ;
wake_up :
ieee802154_wake_queue ( & local - > hw ) ;
local - > suspended = false ;
return 0 ;
}
# else
# define ieee802154_suspend NULL
# define ieee802154_resume NULL
# endif
2014-11-17 10:20:51 +03:00
static int
ieee802154_add_iface ( struct wpan_phy * phy , const char * name ,
2015-04-30 18:44:57 +03:00
unsigned char name_assign_type ,
2014-11-17 10:20:52 +03:00
enum nl802154_iftype type , __le64 extended_addr )
2014-11-17 10:20:51 +03:00
{
struct ieee802154_local * local = wpan_phy_priv ( phy ) ;
struct net_device * err ;
2015-04-30 18:44:57 +03:00
err = ieee802154_if_add ( local , name , name_assign_type , type ,
extended_addr ) ;
2015-01-02 17:49:41 +03:00
return PTR_ERR_OR_ZERO ( err ) ;
2014-11-17 10:20:51 +03:00
}
2014-11-17 10:20:53 +03:00
static int
ieee802154_del_iface ( struct wpan_phy * wpan_phy , struct wpan_dev * wpan_dev )
{
ieee802154_if_remove ( IEEE802154_WPAN_DEV_TO_SUB_IF ( wpan_dev ) ) ;
return 0 ;
}
2014-11-12 05:36:55 +03:00
static int
2014-11-17 10:20:46 +03:00
ieee802154_set_channel ( struct wpan_phy * wpan_phy , u8 page , u8 channel )
2014-11-12 05:36:55 +03:00
{
struct ieee802154_local * local = wpan_phy_priv ( wpan_phy ) ;
int ret ;
ASSERT_RTNL ( ) ;
2015-05-17 22:44:44 +03:00
if ( wpan_phy - > current_page = = page & &
wpan_phy - > current_channel = = channel )
return 0 ;
2014-11-12 05:36:55 +03:00
ret = drv_set_channel ( local , page , channel ) ;
if ( ! ret ) {
wpan_phy - > current_page = page ;
wpan_phy - > current_channel = channel ;
}
return ret ;
}
2014-12-10 17:33:13 +03:00
static int
ieee802154_set_cca_mode ( struct wpan_phy * wpan_phy ,
const struct wpan_phy_cca * cca )
{
struct ieee802154_local * local = wpan_phy_priv ( wpan_phy ) ;
int ret ;
ASSERT_RTNL ( ) ;
2015-05-17 22:44:44 +03:00
if ( wpan_phy_cca_cmp ( & wpan_phy - > cca , cca ) )
return 0 ;
2014-12-10 17:33:13 +03:00
ret = drv_set_cca_mode ( local , cca ) ;
if ( ! ret )
wpan_phy - > cca = * cca ;
return ret ;
}
2015-05-27 14:42:10 +03:00
static int
ieee802154_set_cca_ed_level ( struct wpan_phy * wpan_phy , s32 ed_level )
{
struct ieee802154_local * local = wpan_phy_priv ( wpan_phy ) ;
int ret ;
ASSERT_RTNL ( ) ;
if ( wpan_phy - > cca_ed_level = = ed_level )
return 0 ;
ret = drv_set_cca_ed_level ( local , ed_level ) ;
if ( ! ret )
wpan_phy - > cca_ed_level = ed_level ;
return ret ;
}
2015-05-27 06:40:54 +03:00
static int
ieee802154_set_tx_power ( struct wpan_phy * wpan_phy , s32 power )
{
struct ieee802154_local * local = wpan_phy_priv ( wpan_phy ) ;
int ret ;
ASSERT_RTNL ( ) ;
if ( wpan_phy - > transmit_power = = power )
return 0 ;
ret = drv_set_tx_power ( local , power ) ;
if ( ! ret )
wpan_phy - > transmit_power = power ;
return ret ;
}
2014-11-17 10:20:46 +03:00
static int
ieee802154_set_pan_id ( struct wpan_phy * wpan_phy , struct wpan_dev * wpan_dev ,
2014-11-17 10:20:55 +03:00
__le16 pan_id )
2014-11-12 05:36:57 +03:00
{
2015-06-21 17:45:20 +03:00
int ret ;
2014-11-12 05:36:57 +03:00
ASSERT_RTNL ( ) ;
2015-05-17 22:44:44 +03:00
if ( wpan_dev - > pan_id = = pan_id )
return 0 ;
2015-06-21 17:45:20 +03:00
ret = mac802154_wpan_update_llsec ( wpan_dev - > netdev ) ;
if ( ! ret )
wpan_dev - > pan_id = pan_id ;
return ret ;
2014-11-12 05:36:57 +03:00
}
2014-11-12 05:36:59 +03:00
static int
ieee802154_set_backoff_exponent ( struct wpan_phy * wpan_phy ,
struct wpan_dev * wpan_dev ,
2014-11-17 10:20:46 +03:00
u8 min_be , u8 max_be )
2014-11-12 05:36:59 +03:00
{
ASSERT_RTNL ( ) ;
wpan_dev - > min_be = min_be ;
wpan_dev - > max_be = max_be ;
return 0 ;
}
2014-11-12 05:36:58 +03:00
static int
ieee802154_set_short_addr ( struct wpan_phy * wpan_phy , struct wpan_dev * wpan_dev ,
2014-11-17 10:20:55 +03:00
__le16 short_addr )
2014-11-12 05:36:58 +03:00
{
ASSERT_RTNL ( ) ;
2014-11-17 10:20:55 +03:00
wpan_dev - > short_addr = short_addr ;
2014-11-12 05:36:58 +03:00
return 0 ;
}
2014-11-17 10:20:46 +03:00
static int
ieee802154_set_max_csma_backoffs ( struct wpan_phy * wpan_phy ,
struct wpan_dev * wpan_dev ,
u8 max_csma_backoffs )
2014-11-12 05:37:01 +03:00
{
ASSERT_RTNL ( ) ;
wpan_dev - > csma_retries = max_csma_backoffs ;
return 0 ;
}
2014-11-17 10:20:46 +03:00
static int
ieee802154_set_max_frame_retries ( struct wpan_phy * wpan_phy ,
struct wpan_dev * wpan_dev ,
s8 max_frame_retries )
2014-11-12 05:37:03 +03:00
{
ASSERT_RTNL ( ) ;
wpan_dev - > frame_retries = max_frame_retries ;
return 0 ;
}
2014-11-17 10:20:46 +03:00
static int
ieee802154_set_lbt_mode ( struct wpan_phy * wpan_phy , struct wpan_dev * wpan_dev ,
bool mode )
2014-11-12 05:37:05 +03:00
{
ASSERT_RTNL ( ) ;
wpan_dev - > lbt = mode ;
return 0 ;
}
2015-08-10 22:15:58 +03:00
static int
ieee802154_set_ackreq_default ( struct wpan_phy * wpan_phy ,
struct wpan_dev * wpan_dev , bool ackreq )
{
ASSERT_RTNL ( ) ;
wpan_dev - > ackreq = ackreq ;
return 0 ;
}
2015-09-28 10:00:25 +03:00
# ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
static void
ieee802154_get_llsec_table ( struct wpan_phy * wpan_phy ,
struct wpan_dev * wpan_dev ,
struct ieee802154_llsec_table * * table )
{
struct net_device * dev = wpan_dev - > netdev ;
struct ieee802154_sub_if_data * sdata = IEEE802154_DEV_TO_SUB_IF ( dev ) ;
* table = & sdata - > sec . table ;
}
static void
ieee802154_lock_llsec_table ( struct wpan_phy * wpan_phy ,
struct wpan_dev * wpan_dev )
{
struct net_device * dev = wpan_dev - > netdev ;
struct ieee802154_sub_if_data * sdata = IEEE802154_DEV_TO_SUB_IF ( dev ) ;
mutex_lock ( & sdata - > sec_mtx ) ;
}
static void
ieee802154_unlock_llsec_table ( struct wpan_phy * wpan_phy ,
struct wpan_dev * wpan_dev )
{
struct net_device * dev = wpan_dev - > netdev ;
struct ieee802154_sub_if_data * sdata = IEEE802154_DEV_TO_SUB_IF ( dev ) ;
mutex_unlock ( & sdata - > sec_mtx ) ;
}
static int
ieee802154_set_llsec_params ( struct wpan_phy * wpan_phy ,
struct wpan_dev * wpan_dev ,
const struct ieee802154_llsec_params * params ,
int changed )
{
struct net_device * dev = wpan_dev - > netdev ;
struct ieee802154_sub_if_data * sdata = IEEE802154_DEV_TO_SUB_IF ( dev ) ;
int res ;
mutex_lock ( & sdata - > sec_mtx ) ;
res = mac802154_llsec_set_params ( & sdata - > sec , params , changed ) ;
mutex_unlock ( & sdata - > sec_mtx ) ;
return res ;
}
static int
ieee802154_get_llsec_params ( struct wpan_phy * wpan_phy ,
struct wpan_dev * wpan_dev ,
struct ieee802154_llsec_params * params )
{
struct net_device * dev = wpan_dev - > netdev ;
struct ieee802154_sub_if_data * sdata = IEEE802154_DEV_TO_SUB_IF ( dev ) ;
int res ;
mutex_lock ( & sdata - > sec_mtx ) ;
res = mac802154_llsec_get_params ( & sdata - > sec , params ) ;
mutex_unlock ( & sdata - > sec_mtx ) ;
return res ;
}
static int
ieee802154_add_llsec_key ( struct wpan_phy * wpan_phy , struct wpan_dev * wpan_dev ,
const struct ieee802154_llsec_key_id * id ,
const struct ieee802154_llsec_key * key )
{
struct net_device * dev = wpan_dev - > netdev ;
struct ieee802154_sub_if_data * sdata = IEEE802154_DEV_TO_SUB_IF ( dev ) ;
int res ;
mutex_lock ( & sdata - > sec_mtx ) ;
res = mac802154_llsec_key_add ( & sdata - > sec , id , key ) ;
mutex_unlock ( & sdata - > sec_mtx ) ;
return res ;
}
static int
ieee802154_del_llsec_key ( struct wpan_phy * wpan_phy , struct wpan_dev * wpan_dev ,
const struct ieee802154_llsec_key_id * id )
{
struct net_device * dev = wpan_dev - > netdev ;
struct ieee802154_sub_if_data * sdata = IEEE802154_DEV_TO_SUB_IF ( dev ) ;
int res ;
mutex_lock ( & sdata - > sec_mtx ) ;
res = mac802154_llsec_key_del ( & sdata - > sec , id ) ;
mutex_unlock ( & sdata - > sec_mtx ) ;
return res ;
}
static int
ieee802154_add_seclevel ( struct wpan_phy * wpan_phy , struct wpan_dev * wpan_dev ,
const struct ieee802154_llsec_seclevel * sl )
{
struct net_device * dev = wpan_dev - > netdev ;
struct ieee802154_sub_if_data * sdata = IEEE802154_DEV_TO_SUB_IF ( dev ) ;
int res ;
mutex_lock ( & sdata - > sec_mtx ) ;
res = mac802154_llsec_seclevel_add ( & sdata - > sec , sl ) ;
mutex_unlock ( & sdata - > sec_mtx ) ;
return res ;
}
static int
ieee802154_del_seclevel ( struct wpan_phy * wpan_phy , struct wpan_dev * wpan_dev ,
const struct ieee802154_llsec_seclevel * sl )
{
struct net_device * dev = wpan_dev - > netdev ;
struct ieee802154_sub_if_data * sdata = IEEE802154_DEV_TO_SUB_IF ( dev ) ;
int res ;
mutex_lock ( & sdata - > sec_mtx ) ;
res = mac802154_llsec_seclevel_del ( & sdata - > sec , sl ) ;
mutex_unlock ( & sdata - > sec_mtx ) ;
return res ;
}
static int
ieee802154_add_device ( struct wpan_phy * wpan_phy , struct wpan_dev * wpan_dev ,
const struct ieee802154_llsec_device * dev_desc )
{
struct net_device * dev = wpan_dev - > netdev ;
struct ieee802154_sub_if_data * sdata = IEEE802154_DEV_TO_SUB_IF ( dev ) ;
int res ;
mutex_lock ( & sdata - > sec_mtx ) ;
res = mac802154_llsec_dev_add ( & sdata - > sec , dev_desc ) ;
mutex_unlock ( & sdata - > sec_mtx ) ;
return res ;
}
static int
ieee802154_del_device ( struct wpan_phy * wpan_phy , struct wpan_dev * wpan_dev ,
__le64 extended_addr )
{
struct net_device * dev = wpan_dev - > netdev ;
struct ieee802154_sub_if_data * sdata = IEEE802154_DEV_TO_SUB_IF ( dev ) ;
int res ;
mutex_lock ( & sdata - > sec_mtx ) ;
res = mac802154_llsec_dev_del ( & sdata - > sec , extended_addr ) ;
mutex_unlock ( & sdata - > sec_mtx ) ;
return res ;
}
static int
ieee802154_add_devkey ( struct wpan_phy * wpan_phy , struct wpan_dev * wpan_dev ,
__le64 extended_addr ,
const struct ieee802154_llsec_device_key * key )
{
struct net_device * dev = wpan_dev - > netdev ;
struct ieee802154_sub_if_data * sdata = IEEE802154_DEV_TO_SUB_IF ( dev ) ;
int res ;
mutex_lock ( & sdata - > sec_mtx ) ;
res = mac802154_llsec_devkey_add ( & sdata - > sec , extended_addr , key ) ;
mutex_unlock ( & sdata - > sec_mtx ) ;
return res ;
}
static int
ieee802154_del_devkey ( struct wpan_phy * wpan_phy , struct wpan_dev * wpan_dev ,
__le64 extended_addr ,
const struct ieee802154_llsec_device_key * key )
{
struct net_device * dev = wpan_dev - > netdev ;
struct ieee802154_sub_if_data * sdata = IEEE802154_DEV_TO_SUB_IF ( dev ) ;
int res ;
mutex_lock ( & sdata - > sec_mtx ) ;
res = mac802154_llsec_devkey_del ( & sdata - > sec , extended_addr , key ) ;
mutex_unlock ( & sdata - > sec_mtx ) ;
return res ;
}
# endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
2014-11-02 06:18:36 +03:00
const struct cfg802154_ops mac802154_config_ops = {
2014-11-02 06:18:38 +03:00
. add_virtual_intf_deprecated = ieee802154_add_iface_deprecated ,
. del_virtual_intf_deprecated = ieee802154_del_iface_deprecated ,
2015-06-24 12:36:36 +03:00
. suspend = ieee802154_suspend ,
. resume = ieee802154_resume ,
2014-11-17 10:20:51 +03:00
. add_virtual_intf = ieee802154_add_iface ,
2014-11-17 10:20:53 +03:00
. del_virtual_intf = ieee802154_del_iface ,
2014-11-12 05:36:55 +03:00
. set_channel = ieee802154_set_channel ,
2014-12-10 17:33:13 +03:00
. set_cca_mode = ieee802154_set_cca_mode ,
2015-05-27 14:42:10 +03:00
. set_cca_ed_level = ieee802154_set_cca_ed_level ,
2015-05-27 06:40:54 +03:00
. set_tx_power = ieee802154_set_tx_power ,
2014-11-12 05:36:57 +03:00
. set_pan_id = ieee802154_set_pan_id ,
2014-11-12 05:36:58 +03:00
. set_short_addr = ieee802154_set_short_addr ,
2014-11-12 05:36:59 +03:00
. set_backoff_exponent = ieee802154_set_backoff_exponent ,
2014-11-12 05:37:01 +03:00
. set_max_csma_backoffs = ieee802154_set_max_csma_backoffs ,
2014-11-12 05:37:03 +03:00
. set_max_frame_retries = ieee802154_set_max_frame_retries ,
2014-11-12 05:37:05 +03:00
. set_lbt_mode = ieee802154_set_lbt_mode ,
2015-08-10 22:15:58 +03:00
. set_ackreq_default = ieee802154_set_ackreq_default ,
2015-09-28 10:00:25 +03:00
# ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
. get_llsec_table = ieee802154_get_llsec_table ,
. lock_llsec_table = ieee802154_lock_llsec_table ,
. unlock_llsec_table = ieee802154_unlock_llsec_table ,
/* TODO above */
. set_llsec_params = ieee802154_set_llsec_params ,
. get_llsec_params = ieee802154_get_llsec_params ,
. add_llsec_key = ieee802154_add_llsec_key ,
. del_llsec_key = ieee802154_del_llsec_key ,
. add_seclevel = ieee802154_add_seclevel ,
. del_seclevel = ieee802154_del_seclevel ,
. add_device = ieee802154_add_device ,
. del_device = ieee802154_del_device ,
. add_devkey = ieee802154_add_devkey ,
. del_devkey = ieee802154_del_devkey ,
# endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
2014-11-02 06:18:36 +03:00
} ;