[PATCH] libertas: link mesh device to wiphy

Dan Williams dcbw at redhat.com
Wed Jul 27 15:14:51 EDT 2011


On Thu, 2011-07-21 at 20:43 +0100, Daniel Drake wrote:
> The mesh device is now exposed as an interface of the wiphy.
> This exposes the mesh device to the cfg80211 interface, allowing
> mesh channel selection to be reimplemented, and available to
> NetworkManager as it was before.
> 
> Some header tweaking was needed in order to implement lbs_mesh_activated().
> 
> Signed-off-by: Daniel Drake <dsd at laptop.org>

Acked-by: Dan Williams <dcbw at redhat.com>

> ---
>  drivers/net/wireless/libertas/cfg.c     |   36 +++++++++++++++-
>  drivers/net/wireless/libertas/dev.h     |   12 +++++-
>  drivers/net/wireless/libertas/ethtool.c |    1 +
>  drivers/net/wireless/libertas/main.c    |   14 ++++--
>  drivers/net/wireless/libertas/mesh.c    |   68 ++++++++++++++++++++++---------
>  drivers/net/wireless/libertas/mesh.h    |   27 +++++-------
>  drivers/net/wireless/libertas/rx.c      |    1 +
>  drivers/net/wireless/libertas/tx.c      |    1 +
>  8 files changed, 117 insertions(+), 43 deletions(-)
> 
> Replaces previous patch "libertas: reimplement mesh channel selection"
> 
> diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
> index b456a53..63009c7 100644
> --- a/drivers/net/wireless/libertas/cfg.c
> +++ b/drivers/net/wireless/libertas/cfg.c
> @@ -19,6 +19,7 @@
>  #include "decl.h"
>  #include "cfg.h"
>  #include "cmd.h"
> +#include "mesh.h"
>  
> 
>  #define CHAN2G(_channel, _freq, _flags) {        \
> @@ -442,13 +443,16 @@ static int lbs_cfg_set_channel(struct wiphy *wiphy,
>  	struct lbs_private *priv = wiphy_priv(wiphy);
>  	int ret = -ENOTSUPP;
>  
> -	lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d",
> -			   channel->center_freq, channel_type);
> +	lbs_deb_enter_args(LBS_DEB_CFG80211, "iface %s freq %d, type %d",
> +			   netdev_name(netdev), channel->center_freq, channel_type);
>  
>  	if (channel_type != NL80211_CHAN_NO_HT)
>  		goto out;
>  
> -	ret = lbs_set_channel(priv, channel->hw_value);
> +	if (netdev == priv->mesh_dev)
> +		ret = lbs_mesh_set_channel(priv, channel->hw_value);
> +	else
> +		ret = lbs_set_channel(priv, channel->hw_value);
>  
>   out:
>  	lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
> @@ -1292,6 +1296,9 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
>  	int ret = 0;
>  	u8 preamble = RADIO_PREAMBLE_SHORT;
>  
> +	if (dev == priv->mesh_dev)
> +		return -EOPNOTSUPP;
> +
>  	lbs_deb_enter(LBS_DEB_CFG80211);
>  
>  	if (!sme->bssid) {
> @@ -1408,6 +1415,9 @@ static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
>  	struct lbs_private *priv = wiphy_priv(wiphy);
>  	struct cmd_ds_802_11_deauthenticate cmd;
>  
> +	if (dev == priv->mesh_dev)
> +		return -EOPNOTSUPP;
> +
>  	lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code);
>  
>  	/* store for lbs_cfg_ret_disconnect() */
> @@ -1439,6 +1449,9 @@ static int lbs_cfg_set_default_key(struct wiphy *wiphy,
>  {
>  	struct lbs_private *priv = wiphy_priv(wiphy);
>  
> +	if (netdev == priv->mesh_dev)
> +		return -EOPNOTSUPP;
> +
>  	lbs_deb_enter(LBS_DEB_CFG80211);
>  
>  	if (key_index != priv->wep_tx_key) {
> @@ -1460,6 +1473,9 @@ static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev,
>  	u16 key_type;
>  	int ret = 0;
>  
> +	if (netdev == priv->mesh_dev)
> +		return -EOPNOTSUPP;
> +
>  	lbs_deb_enter(LBS_DEB_CFG80211);
>  
>  	lbs_deb_assoc("add_key: cipher 0x%x, mac_addr %pM\n",
> @@ -1603,6 +1619,9 @@ static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev,
>  	s8 signal, noise;
>  	int ret;
>  
> +	if (dev == priv->mesh_dev)
> +		return -EOPNOTSUPP;
> +
>  	if (idx != 0)
>  		ret = -ENOENT;
>  
> @@ -1636,6 +1655,9 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev,
>  	struct lbs_private *priv = wiphy_priv(wiphy);
>  	int ret = 0;
>  
> +	if (dev == priv->mesh_dev)
> +		return -EOPNOTSUPP;
> +
>  	lbs_deb_enter(LBS_DEB_CFG80211);
>  
>  	switch (type) {
> @@ -1959,6 +1981,9 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
>  	struct cfg80211_bss *bss;
>  	DECLARE_SSID_BUF(ssid_buf);
>  
> +	if (dev == priv->mesh_dev)
> +		return -EOPNOTSUPP;
> +
>  	lbs_deb_enter(LBS_DEB_CFG80211);
>  
>  	if (!params->channel) {
> @@ -1995,6 +2020,9 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
>  	struct cmd_ds_802_11_ad_hoc_stop cmd;
>  	int ret = 0;
>  
> +	if (dev == priv->mesh_dev)
> +		return -EOPNOTSUPP;
> +
>  	lbs_deb_enter(LBS_DEB_CFG80211);
>  
>  	memset(&cmd, 0, sizeof(cmd));
> @@ -2117,6 +2145,8 @@ int lbs_cfg_register(struct lbs_private *priv)
>  			BIT(NL80211_IFTYPE_ADHOC);
>  	if (lbs_rtap_supported(priv))
>  		wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
> +	if (lbs_mesh_activated(priv))
> +		wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MESH_POINT);
>  
>  	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz;
>  
> diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
> index adb3490..133ff1c 100644
> --- a/drivers/net/wireless/libertas/dev.h
> +++ b/drivers/net/wireless/libertas/dev.h
> @@ -6,7 +6,6 @@
>  #ifndef _LBS_DEV_H_
>  #define _LBS_DEV_H_
>  
> -#include "mesh.h"
>  #include "defs.h"
>  #include "host.h"
>  
> @@ -22,6 +21,17 @@ struct sleep_params {
>  	uint16_t sp_reserved;
>  };
>  
> +/* Mesh statistics */
> +struct lbs_mesh_stats {
> +	u32	fwd_bcast_cnt;		/* Fwd: Broadcast counter */
> +	u32	fwd_unicast_cnt;	/* Fwd: Unicast counter */
> +	u32	fwd_drop_ttl;		/* Fwd: TTL zero */
> +	u32	fwd_drop_rbt;		/* Fwd: Recently Broadcasted */
> +	u32	fwd_drop_noroute; 	/* Fwd: No route to Destination */
> +	u32	fwd_drop_nobuf;		/* Fwd: Run out of internal buffers */
> +	u32	drop_blind;		/* Rx:  Dropped by blinding table */
> +	u32	tx_failed_cnt;		/* Tx:  Failed transmissions */
> +};
>  
>  /* Private structure for the MV device */
>  struct lbs_private {
> diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
> index 4dfb3bf..885ddc1 100644
> --- a/drivers/net/wireless/libertas/ethtool.c
> +++ b/drivers/net/wireless/libertas/ethtool.c
> @@ -5,6 +5,7 @@
>  
>  #include "decl.h"
>  #include "cmd.h"
> +#include "mesh.h"
>  
> 
>  static void lbs_ethtool_get_drvinfo(struct net_device *dev,
> diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
> index 94652c5..ee28ae5 100644
> --- a/drivers/net/wireless/libertas/main.c
> +++ b/drivers/net/wireless/libertas/main.c
> @@ -23,6 +23,7 @@
>  #include "cfg.h"
>  #include "debugfs.h"
>  #include "cmd.h"
> +#include "mesh.h"
>  
>  #define DRIVER_RELEASE_VERSION "323.p0"
>  const char lbs_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
> @@ -950,17 +951,20 @@ int lbs_start_card(struct lbs_private *priv)
>  	if (ret)
>  		goto done;
>  
> +	if (!lbs_disablemesh)
> +		lbs_init_mesh(priv);
> +	else
> +		pr_info("%s: mesh disabled\n", dev->name);
> +
>  	if (lbs_cfg_register(priv)) {
>  		pr_err("cannot register device\n");
>  		goto done;
>  	}
>  
> -	lbs_update_channel(priv);
> +	if (lbs_mesh_activated(priv))
> +		lbs_start_mesh(priv);
>  
> -	if (!lbs_disablemesh)
> -		lbs_init_mesh(priv);
> -	else
> -		pr_info("%s: mesh disabled\n", dev->name);
> +	lbs_update_channel(priv);
>  
>  	lbs_debugfs_init_one(priv, dev);
>  
> diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
> index be72c08..2a635d2 100644
> --- a/drivers/net/wireless/libertas/mesh.c
> +++ b/drivers/net/wireless/libertas/mesh.c
> @@ -129,6 +129,19 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
>  	return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
>  }
>  
> +int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel)
> +{
> +	return lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, channel);
> +}
> +
> +static uint16_t lbs_mesh_get_channel(struct lbs_private *priv)
> +{
> +	struct wireless_dev *mesh_wdev = priv->mesh_dev->ieee80211_ptr;
> +	if (mesh_wdev->channel)
> +		return mesh_wdev->channel->hw_value;
> +	else
> +		return 1;
> +}
>  
>  /***************************************************************************
>   * Mesh sysfs support
> @@ -812,7 +825,6 @@ static void lbs_persist_config_remove(struct net_device *dev)
>   */
>  int lbs_init_mesh(struct lbs_private *priv)
>  {
> -	struct net_device *dev = priv->dev;
>  	int ret = 0;
>  
>  	lbs_deb_enter(LBS_DEB_MESH);
> @@ -837,11 +849,9 @@ int lbs_init_mesh(struct lbs_private *priv)
>  		   useful */
>  
>  		priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
> -		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
> -				    priv->channel)) {
> +		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1)) {
>  			priv->mesh_tlv = TLV_TYPE_MESH_ID;
> -			if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
> -					    priv->channel))
> +			if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1))
>  				priv->mesh_tlv = 0;
>  		}
>  	} else
> @@ -851,23 +861,16 @@ int lbs_init_mesh(struct lbs_private *priv)
>  		 * 0x100+37; Do not invoke command with old TLV.
>  		 */
>  		priv->mesh_tlv = TLV_TYPE_MESH_ID;
> -		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
> -				    priv->channel))
> +		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1))
>  			priv->mesh_tlv = 0;
>  	}
>  
>  	/* Stop meshing until interface is brought up */
> -	lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, priv->channel);
> +	lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, 1);
>  
>  	if (priv->mesh_tlv) {
>  		sprintf(priv->mesh_ssid, "mesh");
>  		priv->mesh_ssid_len = 4;
> -
> -		lbs_add_mesh(priv);
> -
> -		if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
> -			netdev_err(dev, "cannot register lbs_mesh attribute\n");
> -
>  		ret = 1;
>  	}
>  
> @@ -875,6 +878,13 @@ int lbs_init_mesh(struct lbs_private *priv)
>  	return ret;
>  }
>  
> +void lbs_start_mesh(struct lbs_private *priv)
> +{
> +	lbs_add_mesh(priv);
> +
> +	if (device_create_file(&priv->dev->dev, &dev_attr_lbs_mesh))
> +		netdev_err(priv->dev, "cannot register lbs_mesh attribute\n");
> +}
>  
>  int lbs_deinit_mesh(struct lbs_private *priv)
>  {
> @@ -904,7 +914,8 @@ static int lbs_mesh_stop(struct net_device *dev)
>  	struct lbs_private *priv = dev->ml_priv;
>  
>  	lbs_deb_enter(LBS_DEB_MESH);
> -	lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, priv->channel);
> +	lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP,
> +		lbs_mesh_get_channel(priv));
>  
>  	spin_lock_irq(&priv->driver_lock);
>  
> @@ -947,7 +958,8 @@ static int lbs_mesh_dev_open(struct net_device *dev)
>  
>  	spin_unlock_irq(&priv->driver_lock);
>  
> -	ret = lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, priv->channel);
> +	ret = lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
> +		lbs_mesh_get_channel(priv));
>  
>  out:
>  	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
> @@ -971,18 +983,32 @@ static const struct net_device_ops mesh_netdev_ops = {
>  static int lbs_add_mesh(struct lbs_private *priv)
>  {
>  	struct net_device *mesh_dev = NULL;
> +	struct wireless_dev *mesh_wdev;
>  	int ret = 0;
>  
>  	lbs_deb_enter(LBS_DEB_MESH);
>  
>  	/* Allocate a virtual mesh device */
> +	mesh_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
> +	if (!mesh_wdev) {
> +		lbs_deb_mesh("init mshX wireless device failed\n");
> +		ret = -ENOMEM;
> +		goto done;
> +	}
> +
>  	mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
>  	if (!mesh_dev) {
>  		lbs_deb_mesh("init mshX device failed\n");
>  		ret = -ENOMEM;
> -		goto done;
> +		goto err_free_wdev;
>  	}
> +
> +	mesh_wdev->iftype = NL80211_IFTYPE_MESH_POINT;
> +	mesh_wdev->wiphy = priv->wdev->wiphy;
> +	mesh_wdev->netdev = mesh_dev;
> +
>  	mesh_dev->ml_priv = priv;
> +	mesh_dev->ieee80211_ptr = mesh_wdev;
>  	priv->mesh_dev = mesh_dev;
>  
>  	mesh_dev->netdev_ops = &mesh_netdev_ops;
> @@ -996,7 +1022,7 @@ static int lbs_add_mesh(struct lbs_private *priv)
>  	ret = register_netdev(mesh_dev);
>  	if (ret) {
>  		pr_err("cannot register mshX virtual interface\n");
> -		goto err_free;
> +		goto err_free_netdev;
>  	}
>  
>  	ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
> @@ -1012,9 +1038,12 @@ static int lbs_add_mesh(struct lbs_private *priv)
>  err_unregister:
>  	unregister_netdev(mesh_dev);
>  
> -err_free:
> +err_free_netdev:
>  	free_netdev(mesh_dev);
>  
> +err_free_wdev:
> +	kfree(mesh_wdev);
> +
>  done:
>  	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
>  	return ret;
> @@ -1035,6 +1064,7 @@ void lbs_remove_mesh(struct lbs_private *priv)
>  	lbs_persist_config_remove(mesh_dev);
>  	unregister_netdev(mesh_dev);
>  	priv->mesh_dev = NULL;
> +	kfree(mesh_dev->ieee80211_ptr);
>  	free_netdev(mesh_dev);
>  	lbs_deb_leave(LBS_DEB_MESH);
>  }
> diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h
> index 5014491..6603f34 100644
> --- a/drivers/net/wireless/libertas/mesh.h
> +++ b/drivers/net/wireless/libertas/mesh.h
> @@ -9,30 +9,25 @@
>  #include <net/lib80211.h>
>  
>  #include "host.h"
> +#include "dev.h"
>  
>  #ifdef CONFIG_LIBERTAS_MESH
>  
> -/* Mesh statistics */
> -struct lbs_mesh_stats {
> -	u32	fwd_bcast_cnt;		/* Fwd: Broadcast counter */
> -	u32	fwd_unicast_cnt;	/* Fwd: Unicast counter */
> -	u32	fwd_drop_ttl;		/* Fwd: TTL zero */
> -	u32	fwd_drop_rbt;		/* Fwd: Recently Broadcasted */
> -	u32	fwd_drop_noroute; 	/* Fwd: No route to Destination */
> -	u32	fwd_drop_nobuf;		/* Fwd: Run out of internal buffers */
> -	u32	drop_blind;		/* Rx:  Dropped by blinding table */
> -	u32	tx_failed_cnt;		/* Tx:  Failed transmissions */
> -};
> -
> -
>  struct net_device;
> -struct lbs_private;
>  
>  int lbs_init_mesh(struct lbs_private *priv);
> +void lbs_start_mesh(struct lbs_private *priv);
>  int lbs_deinit_mesh(struct lbs_private *priv);
>  
>  void lbs_remove_mesh(struct lbs_private *priv);
>  
> +static inline bool lbs_mesh_activated(struct lbs_private *priv)
> +{
> +	/* Mesh SSID is only programmed after successful init */
> +	return priv->mesh_ssid_len != 0;
> +}
> +
> +int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel);
>  
>  /* Sending / Receiving */
>  
> @@ -67,11 +62,13 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev,
>  
>  #define lbs_init_mesh(priv)
>  #define lbs_deinit_mesh(priv)
> +#define lbs_start_mesh(priv)
>  #define lbs_add_mesh(priv)
>  #define lbs_remove_mesh(priv)
>  #define lbs_mesh_set_dev(priv, dev, rxpd) (dev)
>  #define lbs_mesh_set_txpd(priv, dev, txpd)
> -#define lbs_mesh_config(priv, enable, chan)
> +#define lbs_mesh_set_channel(priv, channel) (0)
> +#define lbs_mesh_activated(priv) (false)
>  
>  #endif
>  
> diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
> index bfb8898..62e10ee 100644
> --- a/drivers/net/wireless/libertas/rx.c
> +++ b/drivers/net/wireless/libertas/rx.c
> @@ -15,6 +15,7 @@
>  #include "radiotap.h"
>  #include "decl.h"
>  #include "dev.h"
> +#include "mesh.h"
>  
>  struct eth803hdr {
>  	u8 dest_addr[6];
> diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
> index a6e8513..8f12752 100644
> --- a/drivers/net/wireless/libertas/tx.c
> +++ b/drivers/net/wireless/libertas/tx.c
> @@ -12,6 +12,7 @@
>  #include "decl.h"
>  #include "defs.h"
>  #include "dev.h"
> +#include "mesh.h"
>  
>  /**
>   * convert_radiotap_rate_to_mv - converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE





More information about the libertas-dev mailing list