2014-11-02 06:18:36 +03:00
/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* 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
}
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 ( ) ;
2015-05-17 22:44:44 +03:00
if ( wpan_dev - > min_be = = min_be & &
wpan_dev - > max_be = = max_be )
return 0 ;
2014-11-12 05:36:59 +03:00
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 ( ) ;
2015-05-17 22:44:44 +03:00
if ( wpan_dev - > short_addr = = short_addr )
return 0 ;
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 ( ) ;
2015-05-17 22:44:44 +03:00
if ( wpan_dev - > csma_retries = = max_csma_backoffs )
return 0 ;
2014-11-12 05:37:01 +03:00
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 ( ) ;
2015-05-17 22:44:44 +03:00
if ( wpan_dev - > frame_retries = = max_frame_retries )
return 0 ;
2014-11-12 05:37:03 +03:00
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 ( ) ;
2015-05-17 22:44:44 +03:00
if ( wpan_dev - > lbt = = mode )
return 0 ;
2014-11-12 05:37:05 +03:00
wpan_dev - > lbt = mode ;
return 0 ;
}
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 ,
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 ,
2014-11-02 06:18:36 +03:00
} ;