|
@@ -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);
|
|
|
}
|