2008-05-17 21:01:24 -07:00
# include <linux/moduleparam.h>
# include <linux/delay.h>
# include <linux/etherdevice.h>
# include <linux/netdevice.h>
# include <linux/if_arp.h>
# include <linux/kthread.h>
# include <linux/kfifo.h>
# include "host.h"
# include "decl.h"
# include "dev.h"
# include "wext.h"
# include "debugfs.h"
# include "scan.h"
# include "assoc.h"
# include "cmd.h"
static int mesh_get_default_parameters ( struct device * dev ,
struct mrvl_mesh_defaults * defs )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = to_net_dev ( dev ) - > ml_priv ;
2008-05-17 21:01:24 -07:00
struct cmd_ds_mesh_config cmd ;
int ret ;
memset ( & cmd , 0 , sizeof ( struct cmd_ds_mesh_config ) ) ;
ret = lbs_mesh_config_send ( priv , & cmd , CMD_ACT_MESH_CONFIG_GET ,
CMD_TYPE_MESH_GET_DEFAULTS ) ;
if ( ret )
return - EOPNOTSUPP ;
memcpy ( defs , & cmd . data [ 0 ] , sizeof ( struct mrvl_mesh_defaults ) ) ;
return 0 ;
}
/**
* @ brief Get function for sysfs attribute bootflag
*/
static ssize_t bootflag_get ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct mrvl_mesh_defaults defs ;
int ret ;
ret = mesh_get_default_parameters ( dev , & defs ) ;
if ( ret )
return ret ;
2008-07-16 12:15:26 -07:00
return snprintf ( buf , 12 , " %d \n " , le32_to_cpu ( defs . bootflag ) ) ;
2008-05-17 21:01:24 -07:00
}
/**
* @ brief Set function for sysfs attribute bootflag
*/
static ssize_t bootflag_set ( struct device * dev , struct device_attribute * attr ,
const char * buf , size_t count )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = to_net_dev ( dev ) - > ml_priv ;
2008-05-17 21:01:24 -07:00
struct cmd_ds_mesh_config cmd ;
uint32_t datum ;
int ret ;
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
2008-07-16 12:15:26 -07:00
ret = sscanf ( buf , " %d " , & datum ) ;
if ( ( ret ! = 1 ) | | ( datum > 1 ) )
2008-05-17 21:01:24 -07:00
return - EINVAL ;
* ( ( __le32 * ) & cmd . data [ 0 ] ) = cpu_to_le32 ( ! ! datum ) ;
cmd . length = cpu_to_le16 ( sizeof ( uint32_t ) ) ;
ret = lbs_mesh_config_send ( priv , & cmd , CMD_ACT_MESH_CONFIG_SET ,
CMD_TYPE_MESH_SET_BOOTFLAG ) ;
if ( ret )
return ret ;
return strlen ( buf ) ;
}
/**
* @ brief Get function for sysfs attribute boottime
*/
static ssize_t boottime_get ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct mrvl_mesh_defaults defs ;
int ret ;
ret = mesh_get_default_parameters ( dev , & defs ) ;
if ( ret )
return ret ;
2008-07-16 12:15:26 -07:00
return snprintf ( buf , 12 , " %d \n " , defs . boottime ) ;
2008-05-17 21:01:24 -07:00
}
/**
* @ brief Set function for sysfs attribute boottime
*/
static ssize_t boottime_set ( struct device * dev ,
struct device_attribute * attr , const char * buf , size_t count )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = to_net_dev ( dev ) - > ml_priv ;
2008-05-17 21:01:24 -07:00
struct cmd_ds_mesh_config cmd ;
uint32_t datum ;
int ret ;
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
2008-07-16 12:15:26 -07:00
ret = sscanf ( buf , " %d " , & datum ) ;
if ( ( ret ! = 1 ) | | ( datum > 255 ) )
2008-05-17 21:01:24 -07:00
return - EINVAL ;
/* A too small boot time will result in the device booting into
* standalone ( no - host ) mode before the host can take control of it ,
* so the change will be hard to revert . This may be a desired
* feature ( e . g to configure a very fast boot time for devices that
* will not be attached to a host ) , but dangerous . So I ' m enforcing a
* lower limit of 20 seconds : remove and recompile the driver if this
* does not work for you .
*/
datum = ( datum < 20 ) ? 20 : datum ;
cmd . data [ 0 ] = datum ;
cmd . length = cpu_to_le16 ( sizeof ( uint8_t ) ) ;
ret = lbs_mesh_config_send ( priv , & cmd , CMD_ACT_MESH_CONFIG_SET ,
CMD_TYPE_MESH_SET_BOOTTIME ) ;
if ( ret )
return ret ;
return strlen ( buf ) ;
}
2008-05-20 15:18:49 -07:00
/**
* @ brief Get function for sysfs attribute channel
*/
static ssize_t channel_get ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct mrvl_mesh_defaults defs ;
int ret ;
ret = mesh_get_default_parameters ( dev , & defs ) ;
if ( ret )
return ret ;
2008-07-16 12:15:26 -07:00
return snprintf ( buf , 12 , " %d \n " , le16_to_cpu ( defs . channel ) ) ;
2008-05-20 15:18:49 -07:00
}
/**
* @ brief Set function for sysfs attribute channel
*/
static ssize_t channel_set ( struct device * dev , struct device_attribute * attr ,
const char * buf , size_t count )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = to_net_dev ( dev ) - > ml_priv ;
2008-05-20 15:18:49 -07:00
struct cmd_ds_mesh_config cmd ;
2008-07-16 12:15:26 -07:00
uint32_t datum ;
2008-05-20 15:18:49 -07:00
int ret ;
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
2008-07-16 12:15:26 -07:00
ret = sscanf ( buf , " %d " , & datum ) ;
2008-05-20 15:18:49 -07:00
if ( ret ! = 1 | | datum < 1 | | datum > 11 )
return - EINVAL ;
* ( ( __le16 * ) & cmd . data [ 0 ] ) = cpu_to_le16 ( datum ) ;
cmd . length = cpu_to_le16 ( sizeof ( uint16_t ) ) ;
ret = lbs_mesh_config_send ( priv , & cmd , CMD_ACT_MESH_CONFIG_SET ,
CMD_TYPE_MESH_SET_DEF_CHANNEL ) ;
if ( ret )
return ret ;
return strlen ( buf ) ;
}
2008-05-17 21:01:24 -07:00
/**
* @ brief Get function for sysfs attribute mesh_id
*/
static ssize_t mesh_id_get ( struct device * dev , struct device_attribute * attr ,
char * buf )
{
struct mrvl_mesh_defaults defs ;
int maxlen ;
int ret ;
ret = mesh_get_default_parameters ( dev , & defs ) ;
if ( ret )
return ret ;
if ( defs . meshie . val . mesh_id_len > IW_ESSID_MAX_SIZE ) {
2008-05-23 12:16:51 +02:00
lbs_pr_err ( " inconsistent mesh ID length " ) ;
2008-05-17 21:01:24 -07:00
defs . meshie . val . mesh_id_len = IW_ESSID_MAX_SIZE ;
}
/* SSID not null terminated: reserve room for \0 + \n */
maxlen = defs . meshie . val . mesh_id_len + 2 ;
maxlen = ( PAGE_SIZE > maxlen ) ? maxlen : PAGE_SIZE ;
defs . meshie . val . mesh_id [ defs . meshie . val . mesh_id_len ] = ' \0 ' ;
return snprintf ( buf , maxlen , " %s \n " , defs . meshie . val . mesh_id ) ;
}
/**
* @ brief Set function for sysfs attribute mesh_id
*/
static ssize_t mesh_id_set ( struct device * dev , struct device_attribute * attr ,
const char * buf , size_t count )
{
struct cmd_ds_mesh_config cmd ;
struct mrvl_mesh_defaults defs ;
struct mrvl_meshie * ie ;
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = to_net_dev ( dev ) - > ml_priv ;
2008-05-17 21:01:24 -07:00
int len ;
int ret ;
if ( count < 2 | | count > IW_ESSID_MAX_SIZE + 1 )
return - EINVAL ;
memset ( & cmd , 0 , sizeof ( struct cmd_ds_mesh_config ) ) ;
ie = ( struct mrvl_meshie * ) & cmd . data [ 0 ] ;
/* fetch all other Information Element parameters */
ret = mesh_get_default_parameters ( dev , & defs ) ;
cmd . length = cpu_to_le16 ( sizeof ( struct mrvl_meshie ) ) ;
/* transfer IE elements */
memcpy ( ie , & defs . meshie , sizeof ( struct mrvl_meshie ) ) ;
len = count - 1 ;
memcpy ( ie - > val . mesh_id , buf , len ) ;
/* SSID len */
ie - > val . mesh_id_len = len ;
/* IE len */
2008-10-30 22:09:54 +01:00
ie - > len = sizeof ( struct mrvl_meshie_val ) - IW_ESSID_MAX_SIZE + len ;
2008-05-17 21:01:24 -07:00
ret = lbs_mesh_config_send ( priv , & cmd , CMD_ACT_MESH_CONFIG_SET ,
CMD_TYPE_MESH_SET_MESH_IE ) ;
if ( ret )
return ret ;
return strlen ( buf ) ;
}
/**
* @ brief Get function for sysfs attribute protocol_id
*/
static ssize_t protocol_id_get ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct mrvl_mesh_defaults defs ;
int ret ;
ret = mesh_get_default_parameters ( dev , & defs ) ;
if ( ret )
return ret ;
return snprintf ( buf , 5 , " %d \n " , defs . meshie . val . active_protocol_id ) ;
}
/**
* @ brief Set function for sysfs attribute protocol_id
*/
static ssize_t protocol_id_set ( struct device * dev ,
struct device_attribute * attr , const char * buf , size_t count )
{
struct cmd_ds_mesh_config cmd ;
struct mrvl_mesh_defaults defs ;
struct mrvl_meshie * ie ;
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = to_net_dev ( dev ) - > ml_priv ;
2008-05-17 21:01:24 -07:00
uint32_t datum ;
int ret ;
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
2008-07-16 12:15:26 -07:00
ret = sscanf ( buf , " %d " , & datum ) ;
if ( ( ret ! = 1 ) | | ( datum > 255 ) )
2008-05-17 21:01:24 -07:00
return - EINVAL ;
/* fetch all other Information Element parameters */
ret = mesh_get_default_parameters ( dev , & defs ) ;
cmd . length = cpu_to_le16 ( sizeof ( struct mrvl_meshie ) ) ;
/* transfer IE elements */
ie = ( struct mrvl_meshie * ) & cmd . data [ 0 ] ;
memcpy ( ie , & defs . meshie , sizeof ( struct mrvl_meshie ) ) ;
/* update protocol id */
ie - > val . active_protocol_id = datum ;
ret = lbs_mesh_config_send ( priv , & cmd , CMD_ACT_MESH_CONFIG_SET ,
CMD_TYPE_MESH_SET_MESH_IE ) ;
if ( ret )
return ret ;
return strlen ( buf ) ;
}
/**
* @ brief Get function for sysfs attribute metric_id
*/
static ssize_t metric_id_get ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct mrvl_mesh_defaults defs ;
int ret ;
ret = mesh_get_default_parameters ( dev , & defs ) ;
if ( ret )
return ret ;
return snprintf ( buf , 5 , " %d \n " , defs . meshie . val . active_metric_id ) ;
}
/**
* @ brief Set function for sysfs attribute metric_id
*/
static ssize_t metric_id_set ( struct device * dev , struct device_attribute * attr ,
const char * buf , size_t count )
{
struct cmd_ds_mesh_config cmd ;
struct mrvl_mesh_defaults defs ;
struct mrvl_meshie * ie ;
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = to_net_dev ( dev ) - > ml_priv ;
2008-05-17 21:01:24 -07:00
uint32_t datum ;
int ret ;
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
2008-07-16 12:15:26 -07:00
ret = sscanf ( buf , " %d " , & datum ) ;
if ( ( ret ! = 1 ) | | ( datum > 255 ) )
2008-05-17 21:01:24 -07:00
return - EINVAL ;
/* fetch all other Information Element parameters */
ret = mesh_get_default_parameters ( dev , & defs ) ;
cmd . length = cpu_to_le16 ( sizeof ( struct mrvl_meshie ) ) ;
/* transfer IE elements */
ie = ( struct mrvl_meshie * ) & cmd . data [ 0 ] ;
memcpy ( ie , & defs . meshie , sizeof ( struct mrvl_meshie ) ) ;
/* update metric id */
ie - > val . active_metric_id = datum ;
ret = lbs_mesh_config_send ( priv , & cmd , CMD_ACT_MESH_CONFIG_SET ,
CMD_TYPE_MESH_SET_MESH_IE ) ;
if ( ret )
return ret ;
return strlen ( buf ) ;
}
/**
* @ brief Get function for sysfs attribute capability
*/
static ssize_t capability_get ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct mrvl_mesh_defaults defs ;
int ret ;
ret = mesh_get_default_parameters ( dev , & defs ) ;
if ( ret )
return ret ;
return snprintf ( buf , 5 , " %d \n " , defs . meshie . val . mesh_capability ) ;
}
/**
* @ brief Set function for sysfs attribute capability
*/
static ssize_t capability_set ( struct device * dev , struct device_attribute * attr ,
const char * buf , size_t count )
{
struct cmd_ds_mesh_config cmd ;
struct mrvl_mesh_defaults defs ;
struct mrvl_meshie * ie ;
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = to_net_dev ( dev ) - > ml_priv ;
2008-05-17 21:01:24 -07:00
uint32_t datum ;
int ret ;
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
2008-07-16 12:15:26 -07:00
ret = sscanf ( buf , " %d " , & datum ) ;
if ( ( ret ! = 1 ) | | ( datum > 255 ) )
2008-05-17 21:01:24 -07:00
return - EINVAL ;
/* fetch all other Information Element parameters */
ret = mesh_get_default_parameters ( dev , & defs ) ;
cmd . length = cpu_to_le16 ( sizeof ( struct mrvl_meshie ) ) ;
/* transfer IE elements */
ie = ( struct mrvl_meshie * ) & cmd . data [ 0 ] ;
memcpy ( ie , & defs . meshie , sizeof ( struct mrvl_meshie ) ) ;
/* update value */
ie - > val . mesh_capability = datum ;
ret = lbs_mesh_config_send ( priv , & cmd , CMD_ACT_MESH_CONFIG_SET ,
CMD_TYPE_MESH_SET_MESH_IE ) ;
if ( ret )
return ret ;
return strlen ( buf ) ;
}
static DEVICE_ATTR ( bootflag , 0644 , bootflag_get , bootflag_set ) ;
static DEVICE_ATTR ( boottime , 0644 , boottime_get , boottime_set ) ;
2008-05-20 15:18:49 -07:00
static DEVICE_ATTR ( channel , 0644 , channel_get , channel_set ) ;
2008-05-17 21:01:24 -07:00
static DEVICE_ATTR ( mesh_id , 0644 , mesh_id_get , mesh_id_set ) ;
static DEVICE_ATTR ( protocol_id , 0644 , protocol_id_get , protocol_id_set ) ;
static DEVICE_ATTR ( metric_id , 0644 , metric_id_get , metric_id_set ) ;
static DEVICE_ATTR ( capability , 0644 , capability_get , capability_set ) ;
static struct attribute * boot_opts_attrs [ ] = {
& dev_attr_bootflag . attr ,
& dev_attr_boottime . attr ,
2008-05-20 15:18:49 -07:00
& dev_attr_channel . attr ,
2008-05-17 21:01:24 -07:00
NULL
} ;
static struct attribute_group boot_opts_group = {
. name = " boot_options " ,
. attrs = boot_opts_attrs ,
} ;
static struct attribute * mesh_ie_attrs [ ] = {
& dev_attr_mesh_id . attr ,
& dev_attr_protocol_id . attr ,
& dev_attr_metric_id . attr ,
& dev_attr_capability . attr ,
NULL
} ;
static struct attribute_group mesh_ie_group = {
. name = " mesh_ie " ,
. attrs = mesh_ie_attrs ,
} ;
void lbs_persist_config_init ( struct net_device * dev )
{
int ret ;
ret = sysfs_create_group ( & ( dev - > dev . kobj ) , & boot_opts_group ) ;
ret = sysfs_create_group ( & ( dev - > dev . kobj ) , & mesh_ie_group ) ;
}
void lbs_persist_config_remove ( struct net_device * dev )
{
sysfs_remove_group ( & ( dev - > dev . kobj ) , & boot_opts_group ) ;
sysfs_remove_group ( & ( dev - > dev . kobj ) , & mesh_ie_group ) ;
}