2019-05-27 09:55:21 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2012-05-16 00:50:30 +04:00
/*
* Loopback IEEE 802.15 .4 interface
*
* Copyright 2007 - 2012 Siemens AG
*
* Written by :
* Sergey Lapin < slapin @ ossfans . org >
* Dmitry Eremin - Solenikov < dbaryshkov @ gmail . com >
* Alexander Smirnov < alex . bluesman . smirnov @ gmail . com >
*/
# include <linux/module.h>
# include <linux/timer.h>
# include <linux/platform_device.h>
# include <linux/netdevice.h>
ieee802154: Introduce the use of the managed version of kzalloc
This patch moves data allocated using kzalloc to managed data allocated
using devm_kzalloc and cleans now unnecessary kfrees in probe and remove
functions. An explicit linux/device.h include is added to make sure
the devm_*() routine declarations are unambiguously available.
The following Coccinelle semantic patch was used for making the change:
@platform@
identifier p, probefn, removefn;
@@
struct platform_driver p = {
.probe = probefn,
.remove = removefn,
};
@prb@
identifier platform.probefn, pdev;
expression e, e1, e2;
@@
probefn(struct platform_device *pdev, ...) {
<+...
- e = kzalloc(e1, e2)
+ e = devm_kzalloc(&pdev->dev, e1, e2)
...
?-kfree(e);
...+>
}
@rem depends on prb@
identifier platform.removefn;
expression e;
@@
removefn(...) {
<...
- kfree(e);
...>
}
Signed-off-by: Himangi Saraogi <himangi774@gmail.com>
Acked-by: Julia Lawall <julia.lawall@lip6.fr>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-05-19 20:55:11 +04:00
# include <linux/device.h>
2012-05-16 00:50:30 +04:00
# include <linux/spinlock.h>
# include <net/mac802154.h>
2014-10-25 11:41:02 +04:00
# include <net/cfg802154.h>
2012-05-16 00:50:30 +04:00
2015-05-17 22:44:58 +03:00
static int numlbs = 2 ;
2015-05-17 22:45:05 +03:00
2015-05-17 22:45:03 +03:00
static LIST_HEAD ( fakelb_phys ) ;
2016-09-01 12:24:57 +03:00
static DEFINE_MUTEX ( fakelb_phys_lock ) ;
2015-05-17 22:45:05 +03:00
static LIST_HEAD ( fakelb_ifup_phys ) ;
static DEFINE_RWLOCK ( fakelb_ifup_phys_lock ) ;
2012-05-16 00:50:30 +04:00
2015-05-17 22:45:00 +03:00
struct fakelb_phy {
2014-10-25 19:16:34 +04:00
struct ieee802154_hw * hw ;
2012-05-16 00:50:30 +04:00
2015-05-17 22:45:06 +03:00
u8 page ;
u8 channel ;
2015-06-14 17:48:44 +03:00
bool suspended ;
2012-05-16 00:50:30 +04:00
struct list_head list ;
2015-05-17 22:45:05 +03:00
struct list_head list_ifup ;
2012-05-16 00:50:30 +04:00
} ;
2015-05-17 22:45:10 +03:00
static int fakelb_hw_ed ( struct ieee802154_hw * hw , u8 * level )
2012-05-16 00:50:30 +04:00
{
2017-09-22 15:14:05 +03:00
WARN_ON ( ! level ) ;
2012-05-16 00:50:30 +04:00
* level = 0xbe ;
return 0 ;
}
2015-05-17 22:45:10 +03:00
static int fakelb_hw_channel ( struct ieee802154_hw * hw , u8 page , u8 channel )
2012-05-16 00:50:30 +04:00
{
2015-05-17 22:45:06 +03:00
struct fakelb_phy * phy = hw - > priv ;
2012-05-16 00:50:30 +04:00
2015-05-17 22:45:06 +03:00
write_lock_bh ( & fakelb_ifup_phys_lock ) ;
phy - > page = page ;
phy - > channel = channel ;
write_unlock_bh ( & fakelb_ifup_phys_lock ) ;
2012-05-16 00:50:30 +04:00
return 0 ;
}
2015-05-17 22:45:10 +03:00
static int fakelb_hw_xmit ( struct ieee802154_hw * hw , struct sk_buff * skb )
2012-05-16 00:50:30 +04:00
{
2015-05-17 22:45:10 +03:00
struct fakelb_phy * current_phy = hw - > priv , * phy ;
2012-05-16 00:50:30 +04:00
2015-05-17 22:45:05 +03:00
read_lock_bh ( & fakelb_ifup_phys_lock ) ;
2015-06-14 17:48:44 +03:00
WARN_ON ( current_phy - > suspended ) ;
2015-05-17 22:45:05 +03:00
list_for_each_entry ( phy , & fakelb_ifup_phys , list_ifup ) {
2015-05-17 22:45:01 +03:00
if ( current_phy = = phy )
continue ;
2015-05-17 22:45:06 +03:00
if ( current_phy - > page = = phy - > page & &
2015-05-17 22:45:08 +03:00
current_phy - > channel = = phy - > channel ) {
struct sk_buff * newskb = pskb_copy ( skb , GFP_ATOMIC ) ;
if ( newskb )
ieee802154_rx_irqsafe ( phy - > hw , newskb , 0xcc ) ;
}
2012-05-16 00:50:30 +04:00
}
2015-05-17 22:45:05 +03:00
read_unlock_bh ( & fakelb_ifup_phys_lock ) ;
2012-05-16 00:50:30 +04:00
2015-05-17 22:45:09 +03:00
ieee802154_xmit_complete ( hw , skb , false ) ;
2012-05-16 00:50:30 +04:00
return 0 ;
}
2015-05-17 22:45:10 +03:00
static int fakelb_hw_start ( struct ieee802154_hw * hw )
{
2015-05-17 22:45:00 +03:00
struct fakelb_phy * phy = hw - > priv ;
2012-05-16 00:50:30 +04:00
2015-05-17 22:45:05 +03:00
write_lock_bh ( & fakelb_ifup_phys_lock ) ;
2015-06-14 17:48:44 +03:00
phy - > suspended = false ;
2015-05-17 22:45:05 +03:00
list_add ( & phy - > list_ifup , & fakelb_ifup_phys ) ;
write_unlock_bh ( & fakelb_ifup_phys_lock ) ;
2012-05-16 00:50:30 +04:00
2015-05-17 22:45:05 +03:00
return 0 ;
2012-05-16 00:50:30 +04:00
}
2015-05-17 22:45:10 +03:00
static void fakelb_hw_stop ( struct ieee802154_hw * hw )
{
2015-05-17 22:45:00 +03:00
struct fakelb_phy * phy = hw - > priv ;
2012-05-16 00:50:30 +04:00
2015-05-17 22:45:05 +03:00
write_lock_bh ( & fakelb_ifup_phys_lock ) ;
2015-06-14 17:48:44 +03:00
phy - > suspended = true ;
2015-05-17 22:45:05 +03:00
list_del ( & phy - > list_ifup ) ;
write_unlock_bh ( & fakelb_ifup_phys_lock ) ;
2012-05-16 00:50:30 +04:00
}
2016-07-07 00:32:31 +03:00
static int
fakelb_set_promiscuous_mode ( struct ieee802154_hw * hw , const bool on )
{
return 0 ;
}
2014-10-28 20:21:18 +03:00
static const struct ieee802154_ops fakelb_ops = {
2012-05-16 00:50:30 +04:00
. owner = THIS_MODULE ,
2015-05-17 22:45:09 +03:00
. xmit_async = fakelb_hw_xmit ,
2012-05-16 00:50:30 +04:00
. ed = fakelb_hw_ed ,
. set_channel = fakelb_hw_channel ,
. start = fakelb_hw_start ,
. stop = fakelb_hw_stop ,
2016-07-07 00:32:31 +03:00
. set_promiscuous_mode = fakelb_set_promiscuous_mode ,
2012-05-16 00:50:30 +04:00
} ;
/* Number of dummy devices to be set up by this module. */
module_param ( numlbs , int , 0 ) ;
MODULE_PARM_DESC ( numlbs , " number of pseudo devices " ) ;
2015-05-17 22:45:03 +03:00
static int fakelb_add_one ( struct device * dev )
2012-05-16 00:50:30 +04:00
{
2015-05-17 22:45:10 +03:00
struct ieee802154_hw * hw ;
2015-05-17 22:45:00 +03:00
struct fakelb_phy * phy ;
2012-05-16 00:50:30 +04:00
int err ;
2015-05-17 22:45:00 +03:00
hw = ieee802154_alloc_hw ( sizeof ( * phy ) , & fakelb_ops ) ;
2014-10-25 19:16:34 +04:00
if ( ! hw )
2012-05-16 00:50:30 +04:00
return - ENOMEM ;
2015-05-17 22:45:00 +03:00
phy = hw - > priv ;
phy - > hw = hw ;
2012-05-16 00:50:30 +04:00
/* 868 MHz BPSK 802.15.4-2003 */
2015-05-17 22:44:42 +03:00
hw - > phy - > supported . channels [ 0 ] | = 1 ;
2012-05-16 00:50:30 +04:00
/* 915 MHz BPSK 802.15.4-2003 */
2015-05-17 22:44:42 +03:00
hw - > phy - > supported . channels [ 0 ] | = 0x7fe ;
2012-05-16 00:50:30 +04:00
/* 2.4 GHz O-QPSK 802.15.4-2003 */
2015-05-17 22:44:42 +03:00
hw - > phy - > supported . channels [ 0 ] | = 0x7FFF800 ;
2012-05-16 00:50:30 +04:00
/* 868 MHz ASK 802.15.4-2006 */
2015-05-17 22:44:42 +03:00
hw - > phy - > supported . channels [ 1 ] | = 1 ;
2012-05-16 00:50:30 +04:00
/* 915 MHz ASK 802.15.4-2006 */
2015-05-17 22:44:42 +03:00
hw - > phy - > supported . channels [ 1 ] | = 0x7fe ;
2012-05-16 00:50:30 +04:00
/* 868 MHz O-QPSK 802.15.4-2006 */
2015-05-17 22:44:42 +03:00
hw - > phy - > supported . channels [ 2 ] | = 1 ;
2012-05-16 00:50:30 +04:00
/* 915 MHz O-QPSK 802.15.4-2006 */
2015-05-17 22:44:42 +03:00
hw - > phy - > supported . channels [ 2 ] | = 0x7fe ;
2012-05-16 00:50:30 +04:00
/* 2.4 GHz CSS 802.15.4a-2007 */
2015-05-17 22:44:42 +03:00
hw - > phy - > supported . channels [ 3 ] | = 0x3fff ;
2012-05-16 00:50:30 +04:00
/* UWB Sub-gigahertz 802.15.4a-2007 */
2015-05-17 22:44:42 +03:00
hw - > phy - > supported . channels [ 4 ] | = 1 ;
2012-05-16 00:50:30 +04:00
/* UWB Low band 802.15.4a-2007 */
2015-05-17 22:44:42 +03:00
hw - > phy - > supported . channels [ 4 ] | = 0x1e ;
2012-05-16 00:50:30 +04:00
/* UWB High band 802.15.4a-2007 */
2015-05-17 22:44:42 +03:00
hw - > phy - > supported . channels [ 4 ] | = 0xffe0 ;
2012-05-16 00:50:30 +04:00
/* 750 MHz O-QPSK 802.15.4c-2009 */
2015-05-17 22:44:42 +03:00
hw - > phy - > supported . channels [ 5 ] | = 0xf ;
2012-05-16 00:50:30 +04:00
/* 750 MHz MPSK 802.15.4c-2009 */
2015-05-17 22:44:42 +03:00
hw - > phy - > supported . channels [ 5 ] | = 0xf0 ;
2012-05-16 00:50:30 +04:00
/* 950 MHz BPSK 802.15.4d-2009 */
2015-05-17 22:44:42 +03:00
hw - > phy - > supported . channels [ 6 ] | = 0x3ff ;
2012-05-16 00:50:30 +04:00
/* 950 MHz GFSK 802.15.4d-2009 */
2015-05-17 22:44:42 +03:00
hw - > phy - > supported . channels [ 6 ] | = 0x3ffc00 ;
2012-05-16 00:50:30 +04:00
2015-05-17 22:45:07 +03:00
ieee802154_random_extended_addr ( & hw - > phy - > perm_extended_addr ) ;
/* fake phy channel 13 as default */
hw - > phy - > current_channel = 13 ;
phy - > channel = hw - > phy - > current_channel ;
2016-07-07 00:32:31 +03:00
hw - > flags = IEEE802154_HW_PROMISCUOUS ;
2014-10-25 19:16:34 +04:00
hw - > parent = dev ;
2012-05-16 00:50:30 +04:00
2014-10-25 19:16:34 +04:00
err = ieee802154_register_hw ( hw ) ;
2012-05-16 00:50:30 +04:00
if ( err )
goto err_reg ;
2016-09-01 12:24:57 +03:00
mutex_lock ( & fakelb_phys_lock ) ;
2015-05-17 22:45:03 +03:00
list_add_tail ( & phy - > list , & fakelb_phys ) ;
2016-09-01 12:24:57 +03:00
mutex_unlock ( & fakelb_phys_lock ) ;
2012-05-16 00:50:30 +04:00
return 0 ;
err_reg :
2015-05-17 22:45:00 +03:00
ieee802154_free_hw ( phy - > hw ) ;
2012-05-16 00:50:30 +04:00
return err ;
}
2015-05-17 22:45:00 +03:00
static void fakelb_del ( struct fakelb_phy * phy )
2012-05-16 00:50:30 +04:00
{
2015-05-17 22:45:00 +03:00
list_del ( & phy - > list ) ;
2012-05-16 00:50:30 +04:00
2015-05-17 22:45:00 +03:00
ieee802154_unregister_hw ( phy - > hw ) ;
ieee802154_free_hw ( phy - > hw ) ;
2012-05-16 00:50:30 +04:00
}
2012-12-03 18:24:12 +04:00
static int fakelb_probe ( struct platform_device * pdev )
2012-05-16 00:50:30 +04:00
{
2015-05-17 22:45:00 +03:00
struct fakelb_phy * phy , * tmp ;
2015-05-17 22:45:10 +03:00
int err , i ;
2012-05-16 00:50:30 +04:00
for ( i = 0 ; i < numlbs ; i + + ) {
2015-05-17 22:45:03 +03:00
err = fakelb_add_one ( & pdev - > dev ) ;
2012-05-16 00:50:30 +04:00
if ( err < 0 )
goto err_slave ;
}
2016-11-22 16:02:07 +03:00
dev_info ( & pdev - > dev , " added %i fake ieee802154 hardware devices \n " , numlbs ) ;
2012-05-16 00:50:30 +04:00
return 0 ;
err_slave :
2016-09-01 12:24:57 +03:00
mutex_lock ( & fakelb_phys_lock ) ;
2015-05-17 22:45:03 +03:00
list_for_each_entry_safe ( phy , tmp , & fakelb_phys , list )
2015-05-17 22:45:00 +03:00
fakelb_del ( phy ) ;
2016-09-01 12:24:57 +03:00
mutex_unlock ( & fakelb_phys_lock ) ;
2012-05-16 00:50:30 +04:00
return err ;
}
2012-12-03 18:24:12 +04:00
static int fakelb_remove ( struct platform_device * pdev )
2012-05-16 00:50:30 +04:00
{
2015-05-17 22:45:10 +03:00
struct fakelb_phy * phy , * tmp ;
2012-05-16 00:50:30 +04:00
2016-09-01 12:24:57 +03:00
mutex_lock ( & fakelb_phys_lock ) ;
2015-05-17 22:45:10 +03:00
list_for_each_entry_safe ( phy , tmp , & fakelb_phys , list )
2015-05-17 22:45:00 +03:00
fakelb_del ( phy ) ;
2016-09-01 12:24:57 +03:00
mutex_unlock ( & fakelb_phys_lock ) ;
2012-05-16 00:50:30 +04:00
return 0 ;
}
static struct platform_device * ieee802154fake_dev ;
static struct platform_driver ieee802154fake_driver = {
. probe = fakelb_probe ,
2012-12-03 18:24:12 +04:00
. remove = fakelb_remove ,
2012-05-16 00:50:30 +04:00
. driver = {
. name = " ieee802154fakelb " ,
} ,
} ;
static __init int fakelb_init_module ( void )
{
ieee802154fake_dev = platform_device_register_simple (
" ieee802154fakelb " , - 1 , NULL , 0 ) ;
2018-07-14 19:33:06 +03:00
pr_warn ( " fakelb driver is marked as deprecated, please use mac802154_hwsim! \n " ) ;
2012-05-16 00:50:30 +04:00
return platform_driver_register ( & ieee802154fake_driver ) ;
}
static __exit void fake_remove_module ( void )
{
platform_driver_unregister ( & ieee802154fake_driver ) ;
platform_device_unregister ( ieee802154fake_dev ) ;
}
module_init ( fakelb_init_module ) ;
module_exit ( fake_remove_module ) ;
MODULE_LICENSE ( " GPL " ) ;