2011-06-06 10:43:46 +00:00
# include <linux/hardirq.h>
2007-02-10 12:25:27 -02:00
# include <linux/netdevice.h>
# include <linux/ethtool.h>
# include <linux/delay.h>
# include "decl.h"
2007-12-12 20:06:06 -05:00
# include "cmd.h"
2011-07-21 20:43:17 +01:00
# include "mesh.h"
2007-12-12 20:06:06 -05:00
2007-02-10 12:25:27 -02:00
2007-11-15 18:05:47 -05:00
static void lbs_ethtool_get_drvinfo ( struct net_device * dev ,
2007-02-10 12:25:27 -02:00
struct ethtool_drvinfo * info )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-02-10 12:25:27 -02:00
2011-11-15 10:40:49 -08:00
snprintf ( info - > fw_version , sizeof ( info - > fw_version ) ,
" %u.%u.%u.p%u " ,
2008-04-02 18:04:35 +02:00
priv - > fwrelease > > 24 & 0xff ,
priv - > fwrelease > > 16 & 0xff ,
priv - > fwrelease > > 8 & 0xff ,
priv - > fwrelease & 0xff ) ;
2011-11-15 10:40:49 -08:00
strlcpy ( info - > driver , " libertas " , sizeof ( info - > driver ) ) ;
strlcpy ( info - > version , lbs_driver_version , sizeof ( info - > version ) ) ;
2007-02-10 12:25:27 -02:00
}
2011-04-26 15:25:29 -07:00
/*
* All 8388 parts have 16 KiB EEPROM size at the time of writing .
2007-02-10 12:25:27 -02:00
* In case that changes this needs fixing .
*/
2007-11-15 18:05:47 -05:00
# define LBS_EEPROM_LEN 16384
2007-02-10 12:25:27 -02:00
2007-11-15 18:05:47 -05:00
static int lbs_ethtool_get_eeprom_len ( struct net_device * dev )
2007-02-10 12:25:27 -02:00
{
2007-11-15 18:05:47 -05:00
return LBS_EEPROM_LEN ;
2007-02-10 12:25:27 -02:00
}
2007-11-15 18:05:47 -05:00
static int lbs_ethtool_get_eeprom ( struct net_device * dev ,
2007-02-10 12:25:27 -02:00
struct ethtool_eeprom * eeprom , u8 * bytes )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2008-03-26 10:03:48 +01:00
struct cmd_ds_802_11_eeprom_access cmd ;
2007-02-10 12:25:27 -02:00
int ret ;
2008-03-26 10:03:48 +01:00
lbs_deb_enter ( LBS_DEB_ETHTOOL ) ;
2007-02-10 12:25:27 -02:00
2008-03-26 10:03:48 +01:00
if ( eeprom - > offset + eeprom - > len > LBS_EEPROM_LEN | |
eeprom - > len > LBS_EEPROM_READ_LEN ) {
ret = - EINVAL ;
goto out ;
2007-02-10 12:25:27 -02:00
}
2008-03-26 10:03:48 +01:00
cmd . hdr . size = cpu_to_le16 ( sizeof ( struct cmd_ds_802_11_eeprom_access ) -
LBS_EEPROM_READ_LEN + eeprom - > len ) ;
cmd . action = cpu_to_le16 ( CMD_ACT_GET ) ;
cmd . offset = cpu_to_le16 ( eeprom - > offset ) ;
cmd . len = cpu_to_le16 ( eeprom - > len ) ;
ret = lbs_cmd_with_response ( priv , CMD_802_11_EEPROM_ACCESS , & cmd ) ;
if ( ! ret )
memcpy ( bytes , cmd . value , eeprom - > len ) ;
out :
lbs_deb_leave_args ( LBS_DEB_ETHTOOL , " ret %d " , ret ) ;
2007-05-25 11:27:16 -04:00
return ret ;
2007-02-10 12:25:27 -02:00
}
2007-12-12 20:06:06 -05:00
static void lbs_ethtool_get_wol ( struct net_device * dev ,
struct ethtool_wolinfo * wol )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-12-12 20:06:06 -05:00
wol - > supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_PHY ;
2010-06-05 13:30:12 +02:00
if ( priv - > wol_criteria = = EHS_REMOVE_WAKEUP )
return ;
2007-12-12 20:06:06 -05:00
if ( priv - > wol_criteria & EHS_WAKE_ON_UNICAST_DATA )
wol - > wolopts | = WAKE_UCAST ;
if ( priv - > wol_criteria & EHS_WAKE_ON_MULTICAST_DATA )
wol - > wolopts | = WAKE_MCAST ;
if ( priv - > wol_criteria & EHS_WAKE_ON_BROADCAST_DATA )
wol - > wolopts | = WAKE_BCAST ;
if ( priv - > wol_criteria & EHS_WAKE_ON_MAC_EVENT )
wol - > wolopts | = WAKE_PHY ;
}
static int lbs_ethtool_set_wol ( struct net_device * dev ,
struct ethtool_wolinfo * wol )
{
2009-02-19 19:32:39 -05:00
struct lbs_private * priv = dev - > ml_priv ;
2007-12-12 20:06:06 -05:00
if ( wol - > wolopts & ~ ( WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_PHY ) )
return - EOPNOTSUPP ;
2010-05-19 03:24:38 -07:00
priv - > wol_criteria = 0 ;
2009-11-09 18:04:12 -08:00
if ( wol - > wolopts & WAKE_UCAST )
2010-05-19 03:24:38 -07:00
priv - > wol_criteria | = EHS_WAKE_ON_UNICAST_DATA ;
2009-11-09 18:04:12 -08:00
if ( wol - > wolopts & WAKE_MCAST )
2010-05-19 03:24:38 -07:00
priv - > wol_criteria | = EHS_WAKE_ON_MULTICAST_DATA ;
2009-11-09 18:04:12 -08:00
if ( wol - > wolopts & WAKE_BCAST )
2010-05-19 03:24:38 -07:00
priv - > wol_criteria | = EHS_WAKE_ON_BROADCAST_DATA ;
2009-11-09 18:04:12 -08:00
if ( wol - > wolopts & WAKE_PHY )
2010-05-19 03:24:38 -07:00
priv - > wol_criteria | = EHS_WAKE_ON_MAC_EVENT ;
2009-11-09 18:04:13 -08:00
if ( wol - > wolopts = = 0 )
2010-05-19 03:24:38 -07:00
priv - > wol_criteria | = EHS_REMOVE_WAKEUP ;
return 0 ;
2007-12-12 20:06:06 -05:00
}
2009-09-02 01:03:33 -07:00
const struct ethtool_ops lbs_ethtool_ops = {
2007-11-15 18:05:47 -05:00
. get_drvinfo = lbs_ethtool_get_drvinfo ,
. get_eeprom = lbs_ethtool_get_eeprom ,
. get_eeprom_len = lbs_ethtool_get_eeprom_len ,
2009-12-02 15:26:02 +01:00
# ifdef CONFIG_LIBERTAS_MESH
2009-11-25 13:10:49 +01:00
. get_sset_count = lbs_mesh_ethtool_get_sset_count ,
. get_ethtool_stats = lbs_mesh_ethtool_get_stats ,
. get_strings = lbs_mesh_ethtool_get_strings ,
2009-12-02 15:26:02 +01:00
# endif
2007-12-12 20:06:06 -05:00
. get_wol = lbs_ethtool_get_wol ,
. set_wol = lbs_ethtool_set_wol ,
2007-02-10 12:25:27 -02:00
} ;