Skip to content

Commit

Permalink
libertas: link mesh device to wiphy
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Dan Williams <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
  • Loading branch information
Daniel Drake authored and linvjw committed Aug 8, 2011
1 parent 04b0c5c commit 49fee69
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 43 deletions.
36 changes: 33 additions & 3 deletions drivers/net/wireless/libertas/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "decl.h"
#include "cfg.h"
#include "cmd.h"
#include "mesh.h"


#define CHAN2G(_channel, _freq, _flags) { \
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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() */
Expand Down Expand Up @@ -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) {
Expand All @@ -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",
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;

Expand Down
12 changes: 11 additions & 1 deletion drivers/net/wireless/libertas/dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#ifndef _LBS_DEV_H_
#define _LBS_DEV_H_

#include "mesh.h"
#include "defs.h"
#include "host.h"

Expand All @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/libertas/ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "decl.h"
#include "cmd.h"
#include "mesh.h"


static void lbs_ethtool_get_drvinfo(struct net_device *dev,
Expand Down
14 changes: 9 additions & 5 deletions drivers/net/wireless/libertas/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down
68 changes: 49 additions & 19 deletions drivers/net/wireless/libertas/mesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -851,30 +861,30 @@ 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;
}

lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
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)
{
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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);
}
Expand Down
Loading

0 comments on commit 49fee69

Please sign in to comment.