]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
libertas: link mesh device to wiphy
authorDaniel Drake <dsd@laptop.org>
Thu, 21 Jul 2011 19:43:17 +0000 (20:43 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 8 Aug 2011 18:26:31 +0000 (14:26 -0400)
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@laptop.org>
Acked-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/libertas/dev.h
drivers/net/wireless/libertas/ethtool.c
drivers/net/wireless/libertas/main.c
drivers/net/wireless/libertas/mesh.c
drivers/net/wireless/libertas/mesh.h
drivers/net/wireless/libertas/rx.c
drivers/net/wireless/libertas/tx.c

index b456a53b64b19b22aa3442b13ca1a2859ea622c6..63009c7eb2f1a0105795bc853f244d4d8810b9c1 100644 (file)
@@ -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;
 
index adb3490e3cf52e427210d2c34eb1db2fd1ae247b..133ff1cac524e5a3471a8bfb873946e656f6b0f6 100644 (file)
@@ -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 {
index 4dfb3bfd2cf3f923710939869cea359d503d3c1f..885ddc1c4fed70d8b6a2a47042cba18016069c00 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "decl.h"
 #include "cmd.h"
+#include "mesh.h"
 
 
 static void lbs_ethtool_get_drvinfo(struct net_device *dev,
index 94652c5a25de396ebe4fceeeb4ccd79663d4b862..ee28ae510935a41610179a9e98c16e3b0fc437f4 100644 (file)
@@ -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);
 
index be72c08ea2a79acf457c4ef3e5e7b82ae927cbfc..2a635d279ffebb4acc060de364acf23469640549 100644 (file)
@@ -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);
 }
index 50144913f2abefd8a86fe93f81e42ed7eeaedcde..6603f341c8746f0b6ed66078ac4d8d02b2ce4f53 100644 (file)
@@ -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
 
index bfb8898ae518908f8394ef94a6f158b74f1bb232..62e10eeadd7e11339ff4ee2b67cdf04d097a6bbf 100644 (file)
@@ -15,6 +15,7 @@
 #include "radiotap.h"
 #include "decl.h"
 #include "dev.h"
+#include "mesh.h"
 
 struct eth803hdr {
        u8 dest_addr[6];
index a6e85134cfe1c24e8bd0e3aa4f95e8178b2078ec..8f127520d7863f6ff5eb09b49272d7227b75c5ab 100644 (file)
@@ -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