diff options
Diffstat (limited to 'drivers/net/wireless/libertas/mesh.c')
-rw-r--r-- | drivers/net/wireless/libertas/mesh.c | 68 |
1 files changed, 49 insertions, 19 deletions
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index be72c08ea2a7..2a635d279ffe 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); } |