This patch is based on a patch from Shailendra Govardhan.  It introduces
several new iwprivs: {get,set}_bootflag {get,set}_boottime {get,set}_def_chan
{get,set}_def_protid {get,set}_def_metid {get,set}_def_meshcap
{get,set}_def_meshid.  These commands are only supported on Marvell hardware
that implements persistent defaults, such as the OLPC Active Antenna.
Accordingly, this patch may not be suitable for upstream merging.

See http://dev.laptop.org/ticket/6823 for minimal testing results and known
issues.  See 
http://www.laptop.org/teamwiki/index.php/Tech:Wireless#Firmware_image_which_stores_the_mesh_parameters_in_flash
 for iwpriv documentation.

Signed-off-by: Brian Cavagnolo <[EMAIL PROTECTED]>
---
 drivers/net/wireless/libertas/assoc.c |    5 +-
 drivers/net/wireless/libertas/cmd.c   |   69 +++++++++--
 drivers/net/wireless/libertas/cmd.h   |    2 +
 drivers/net/wireless/libertas/defs.h  |   10 ++
 drivers/net/wireless/libertas/host.h  |   17 +++
 drivers/net/wireless/libertas/ioctl.c |  221 +++++++++++++++++++++++++++++++++
 drivers/net/wireless/libertas/ioctl.h |   14 ++
 drivers/net/wireless/libertas/main.c  |   13 ++-
 drivers/net/wireless/libertas/types.h |   31 +++++
 drivers/net/wireless/libertas/wext.c  |   28 ++++-
 10 files changed, 389 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/libertas/assoc.c 
b/drivers/net/wireless/libertas/assoc.c
index e742550..45e1f20 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -210,7 +210,7 @@ static int assoc_helper_channel(struct lbs_private *priv,
                /* Change mesh channel first; 21.p21 firmware won't let
                   you change channel otherwise (even though it'll return
                   an error to this */
-               lbs_mesh_config(priv, 0, assoc_req->channel);
+               lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, 
assoc_req->channel);
        }
 
        lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
@@ -249,7 +249,8 @@ static int assoc_helper_channel(struct lbs_private *priv,
 
  restore_mesh:
        if (priv->mesh_dev)
-               lbs_mesh_config(priv, 1, priv->curbssparams.channel);
+               lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+                                       priv->curbssparams.channel);
 
  done:
        lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
diff --git a/drivers/net/wireless/libertas/cmd.c 
b/drivers/net/wireless/libertas/cmd.c
index 0ae9851..c980816 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -4,6 +4,7 @@
   */
 
 #include <net/iw_handler.h>
+#include <net/ieee80211.h>
 #include "host.h"
 #include "hostcmd.h"
 #include "decl.h"
@@ -1114,24 +1115,68 @@ int lbs_mesh_access(struct lbs_private *priv, uint16_t 
cmd_action,
 }
 EXPORT_SYMBOL_GPL(lbs_mesh_access);
 
-int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan)
+int lbs_mesh_config_send(struct lbs_private *priv, struct cmd_ds_mesh_config 
*cmd,
+                       u16 action, u16 type)
+{
+       int ret;
+
+       lbs_deb_enter(LBS_DEB_CMD);
+
+       cmd->hdr.command = cpu_to_le16(CMD_MESH_CONFIG);
+       cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
+       cmd->hdr.result = 0;
+
+       cmd->type = cpu_to_le16(type);
+       cmd->action = cpu_to_le16(action);
+
+       ret = lbs_cmd_with_response(priv, CMD_MESH_CONFIG, cmd);
+
+       lbs_deb_leave(LBS_DEB_CMD);
+       return ret;
+}
+
+/* This function is the CMD_MESH_CONFIG legacy function.  It only handles the
+ * START and STOP actions.  The extended actions supported by CMD_MESH_CONFIG
+ * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
+ * lbs_mesh_config_send.
+ */
+int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
 {
        struct cmd_ds_mesh_config cmd;
+       struct mrvl_meshie *ie;
 
        memset(&cmd, 0, sizeof(cmd));
-       cmd.action = cpu_to_le16(enable);
        cmd.channel = cpu_to_le16(chan);
-       cmd.type = cpu_to_le16(priv->mesh_tlv);
-       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
-       if (enable) {
-               cmd.length = cpu_to_le16(priv->mesh_ssid_len);
-               memcpy(cmd.data, priv->mesh_ssid, priv->mesh_ssid_len);
+       ie = (struct mrvl_meshie *)cmd.data;
+
+       switch(action) {
+       case CMD_ACT_MESH_CONFIG_START:
+               ie->hdr.id = MFIE_TYPE_GENERIC;
+               ie->val.oui[0] = 0x00;
+               ie->val.oui[1] = 0x50;
+               ie->val.oui[2] = 0x43;
+               ie->val.type = MARVELL_MESH_IE_TYPE;
+               ie->val.subtype = MARVELL_MESH_IE_SUBTYPE;
+               ie->val.version = MARVELL_MESH_IE_VERSION;
+               ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP;
+               ie->val.active_metric_id = MARVELL_MESH_METRIC_ID;
+               ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
+               ie->val.mesh_id_len = priv->mesh_ssid_len;
+               memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
+               ie->hdr.len = sizeof(struct mrvl_meshie_val) -
+                       IW_ESSID_MAX_SIZE + priv->mesh_ssid_len;
+               cmd.length = sizeof(struct mrvl_meshie_val);
+               break;
+       case CMD_ACT_MESH_CONFIG_STOP:
+               break;
+       default:
+               return -1;
        }
-       lbs_deb_cmd("mesh config enable %d TLV %x channel %d SSID %s\n",
-                   enable, priv->mesh_tlv, chan,
-                   escape_essid(priv->mesh_ssid, priv->mesh_ssid_len));
-       return lbs_cmd_with_response(priv, CMD_MESH_CONFIG, &cmd);
+       lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
+                       action, priv->mesh_tlv, chan,
+                       escape_essid(priv->mesh_ssid, priv->mesh_ssid_len));
+
+       return lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
 }
 
 static int lbs_cmd_bcn_ctrl(struct lbs_private * priv,
diff --git a/drivers/net/wireless/libertas/cmd.h 
b/drivers/net/wireless/libertas/cmd.h
index e334f0e..ea9deb3 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -41,6 +41,8 @@ int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
 int lbs_get_channel(struct lbs_private *priv);
 int lbs_set_channel(struct lbs_private *priv, u8 channel);
 
+int lbs_mesh_config_send(struct lbs_private *priv, struct cmd_ds_mesh_config 
*cmd,
+               u16 action, u16 type);
 int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
 
 int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria);
diff --git a/drivers/net/wireless/libertas/defs.h 
b/drivers/net/wireless/libertas/defs.h
index 3053cc2..750d702 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -170,6 +170,16 @@ static inline void lbs_deb_hex(unsigned int grp, const 
char *prompt, u8 *buf, in
 
 #define MARVELL_MESH_IE_LENGTH         9
 
+/* Values used to populate the struct mrvl_mesh_ie.  The only time you need 
this
+ * is when enabling the mesh using CMD_MESH_CONFIG. 
+ */
+#define MARVELL_MESH_IE_TYPE   4
+#define MARVELL_MESH_IE_SUBTYPE        0
+#define MARVELL_MESH_IE_VERSION        0
+#define MARVELL_MESH_PROTO_ID_HWMP     0
+#define MARVELL_MESH_METRIC_ID 0
+#define MARVELL_MESH_CAPABILITY        0
+
 /** INT status Bit Definition*/
 #define MRVDRV_TX_DNLD_RDY             0x0001
 #define MRVDRV_RX_UPLD_RDY             0x0002
diff --git a/drivers/net/wireless/libertas/host.h 
b/drivers/net/wireless/libertas/host.h
index 0f77bd1..f734b4b 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -261,6 +261,23 @@ enum cmd_mesh_access_opts {
        CMD_ACT_MESH_SET_PRB_RSP_RETRY_LIMIT = 17,
 };
 
+/* Define actions and types for CMD_MESH_CONFIG */
+enum cmd_mesh_config_actions {
+       CMD_ACT_MESH_CONFIG_STOP = 0,
+       CMD_ACT_MESH_CONFIG_START,
+       CMD_ACT_MESH_CONFIG_SET,
+       CMD_ACT_MESH_CONFIG_GET,
+};
+
+enum cmd_mesh_config_types {
+       CMD_TYPE_MESH_SET_BOOTFLAG = 1,
+       CMD_TYPE_MESH_SET_BOOTTIME,
+       CMD_TYPE_MESH_SET_DEF_CHANNEL,
+       CMD_TYPE_MESH_SET_MESH_IE,
+       CMD_TYPE_MESH_GET_DEFAULTS,
+       CMD_TYPE_MESH_GET_MESH_IE, /* GET_DEFAULTS is superset of GET_MESHIE */
+};
+
 /** Card Event definition */
 #define MACREG_INT_CODE_TX_PPA_FREE            0
 #define MACREG_INT_CODE_TX_DMA_DONE            1
diff --git a/drivers/net/wireless/libertas/ioctl.c 
b/drivers/net/wireless/libertas/ioctl.c
index 83cc454..1ac746c 100644
--- a/drivers/net/wireless/libertas/ioctl.c
+++ b/drivers/net/wireless/libertas/ioctl.c
@@ -895,6 +895,203 @@ static int lbs_mesh_ioctl(struct lbs_private * priv, 
struct iwreq * wrq,
 }
 
 /**
+ *  @brief              Setter for integer persistent default mesh settings.
+ *  @param priv         A pointer to struct lbs_private structure
+ *  @param req          A pointer to iwreq structure
+ *  @return            0 --success, otherwise fail
+ */
+static int lbs_mesh_set_defaults_ioctl(struct lbs_private *priv,
+               struct iwreq *wrq)
+{
+       int ret = 0, val;
+       u16 type = 0;
+       struct cmd_ds_mesh_config cmd;
+
+       memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
+
+       val = SUBCMD_DATA(wrq);
+       switch (wrq->u.mode) {
+               case LBS_SUBCMD_MESH_SET_BOOTTIME:
+                       if ((val < 0) || (val > 255))
+                               return -EINVAL;
+                       cmd.data[0] = (u8)val;
+                       cmd.length = cpu_to_le16(sizeof(u8));
+                       type = CMD_TYPE_MESH_SET_BOOTTIME;
+                       break;
+               case LBS_SUBCMD_MESH_SET_BOOTFLAG:
+                       if ((val < 0) || (val > 1))
+                               return -EINVAL;
+                       *((u32 *)&cmd.data[0]) = cpu_to_le32((u32)val);
+                       cmd.length = cpu_to_le32(sizeof(u32));
+                       type = CMD_TYPE_MESH_SET_BOOTFLAG;
+                       break;
+               case LBS_SUBCMD_MESH_SET_DEFAULT_CHANNEL:
+                       if ((val < 1) || (val > 11))
+                               return -EINVAL;
+                       *((u16 *)&cmd.data[0]) = cpu_to_le16((u16)val);
+                       cmd.length = cpu_to_le16(sizeof(u16));
+                       type = CMD_TYPE_MESH_SET_DEF_CHANNEL;
+                       break;
+               default:
+                       return -EOPNOTSUPP;
+       }
+
+       ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, type);
+       if (ret)
+               return -EFAULT;
+
+       return 0;
+}
+
+/**
+ *  @brief              Getter for integer persistent default mesh settings.
+ *  @param priv         A pointer to struct lbs_private structure
+ *  @param req          A pointer to iwreq structure
+ *  @param cmd          The ioctl cmd (i.e., LBS_SETNONE_GETONEINT)
+ *  @return            0 --success, otherwise fail
+ */
+static int lbs_mesh_get_defaults_ioctl(struct lbs_private *priv,
+                               struct iwreq *wrq, int cmd)
+{
+       int ret;
+       struct cmd_ds_mesh_config cmd_in;
+       struct mrvl_mesh_defaults *defs;
+
+       memset(&cmd_in, 0, sizeof(struct cmd_ds_mesh_config));
+
+       ret = lbs_mesh_config_send(priv, &cmd_in, CMD_ACT_MESH_CONFIG_GET,
+                       CMD_TYPE_MESH_GET_DEFAULTS);
+
+       if (ret)
+               /* The device does not support persistent defaults */
+               return -EOPNOTSUPP;
+
+       defs = (struct mrvl_mesh_defaults *)&cmd_in.data[0];
+       if (cmd == LBS_SETNONE_GETONEINT) {
+               switch (wrq->u.mode) {
+               case LBS_SUBCMD_MESH_GET_BOOTFLAG:
+                       wrq->u.param.value = cpu_to_le32(defs->bootflag);
+                       break;
+               case LBS_SUBCMD_MESH_GET_BOOTTIME:
+                       wrq->u.param.value = defs->boottime;
+                       break;
+               case LBS_SUBCMD_MESH_GET_DEFAULT_CHANNEL:
+                       wrq->u.param.value = cpu_to_le16(defs->channel);
+                       break;
+               case LBS_SUBCMD_MESH_GET_DEFAULT_PROTO_ID:
+                       wrq->u.param.value =
+                               defs->meshie.val.active_protocol_id;
+                       break;
+               case LBS_SUBCMD_MESH_GET_DEFAULT_METRIC_ID:
+                       wrq->u.param.value = defs->meshie.val.active_metric_id;
+                       break;
+               case LBS_SUBCMD_MESH_GET_DEFAULT_MESH_CAP:
+                       wrq->u.param.value = defs->meshie.val.mesh_capability;
+                       break;
+               default:
+                       return -EOPNOTSUPP;
+               }
+       } else if(cmd == LBS_SET128CHAR_GET128CHAR) {
+               switch (wrq->u.data.flags) {
+               case LBS_SUBCMD_MESH_GET_DEFAULT_MESH_ID:
+                       wrq->u.data.length = defs->meshie.val.mesh_id_len;
+                       ret = copy_to_user(wrq->u.data.pointer,
+                                          (char *)defs->meshie.val.mesh_id,
+                                          wrq->u.data.length);
+                       if (ret)
+                               return -EFAULT;
+                       break;
+               default:
+                       return -EOPNOTSUPP;
+               }
+       } else {
+               return -EOPNOTSUPP;
+       }
+       return 0;
+}
+
+/**
+ *  @brief              Setter for the persistent default marvell mesh ie
+ *  @param priv         A pointer to struct lbs_private structure
+ *  @param req          A pointer to iwreq structure
+ *  @param cmd          The ioctl cmd (i.e., LBS_SETONEINT_GETNONE)
+ *  @return            0 --success, otherwise fail
+ */
+static int lbs_mesh_set_meshie_ioctl(struct lbs_private *priv,
+                               struct iwreq *wrq, int cmd)
+{
+       int ret = 0, val;
+       struct cmd_ds_mesh_config cmd_in, cmd_out;
+       struct mrvl_mesh_defaults *defs;
+       struct mrvl_meshie *ie;
+       char str[128];
+
+       memset(&cmd_in, 0, sizeof(struct cmd_ds_mesh_config));
+       memset(&cmd_out, 0, sizeof(struct cmd_ds_mesh_config));
+
+       ret = lbs_mesh_config_send(priv, &cmd_in, CMD_ACT_MESH_CONFIG_GET,
+                       CMD_TYPE_MESH_GET_DEFAULTS);
+       if (ret)
+               return -EOPNOTSUPP;
+       defs = (struct mrvl_mesh_defaults *)&cmd_in.data[0];
+
+       if (cmd == LBS_SETONEINT_GETNONE) {
+               switch (wrq->u.mode) {
+               case LBS_SUBCMD_MESH_SET_DEFAULT_PROTO_ID:
+                       val = SUBCMD_DATA(wrq);
+                       if ((val < 0) || (val > 255))
+                               return -EINVAL;
+                       defs->meshie.val.active_protocol_id = (u8)val;
+                       break;
+               case LBS_SUBCMD_MESH_SET_DEFAULT_METRIC_ID:
+                       val = SUBCMD_DATA(wrq);
+                       if ((val < 0) || (val > 255))
+                               return -EINVAL;
+                       defs->meshie.val.active_metric_id = (u8)val;
+                       break;
+               case LBS_SUBCMD_MESH_SET_DEFAULT_MESH_CAP:
+                       val = SUBCMD_DATA(wrq);
+                       if ((val < 0) || (val > 255))
+                               return -EINVAL;
+                       defs->meshie.val.mesh_capability = (u8)val;
+                       break;
+               default:
+                       return -EOPNOTSUPP;
+               }
+       } else if(cmd == LBS_SET128CHAR_GET128CHAR) {
+               switch (wrq->u.data.flags) {
+               case  LBS_SUBCMD_MESH_SET_DEFAULT_MESH_ID:
+                       if ((wrq->u.data.length < 2) ||
+                           (wrq->u.data.length > IW_ESSID_MAX_SIZE + 1))
+                               return -EINVAL;
+                       ret = copy_from_user(str, wrq->u.data.pointer,
+                                            wrq->u.data.length);
+                       if (ret)
+                               return -EFAULT;
+                       ie = &defs->meshie;
+                       ie->val.mesh_id_len = strlen(str);
+                       memcpy(ie->val.mesh_id, str, ie->val.mesh_id_len);
+                       ie->hdr.len = sizeof(struct mrvl_meshie_val)
+                               - IW_ESSID_MAX_SIZE + ie->val.mesh_id_len;
+                       break;
+               default:
+                       return -EOPNOTSUPP;
+               }
+       } else {
+               return -EOPNOTSUPP;
+       }
+
+       memcpy((u8 *)&cmd_out.data[0], (u8 *)&defs->meshie,
+               sizeof(struct mrvl_meshie));
+       cmd_out.length = cpu_to_le16(sizeof(struct mrvl_meshie));
+       ret = lbs_mesh_config_send(priv, &cmd_out, CMD_ACT_MESH_CONFIG_SET,
+                               CMD_TYPE_MESH_SET_MESH_IE);
+       if (ret)
+               return -EFAULT;
+       return 0;
+}
+
+/**
  *  @brief Control Beacon transmissions
  *  @param priv                 A pointer to struct lbs_private structure
  *  @param wrq                 A pointer to iwreq structure
@@ -1145,6 +1342,16 @@ int lbs_do_ioctl(struct net_device *dev, struct ifreq 
*req, int cmd)
                        ret = lbs_mesh_ioctl(priv, wrq, cmd,
                                        CMD_ACT_MESH_SET_PRB_RSP_RETRY_LIMIT);
                        break;
+               case LBS_SUBCMD_MESH_SET_BOOTFLAG:
+               case LBS_SUBCMD_MESH_SET_BOOTTIME:
+               case LBS_SUBCMD_MESH_SET_DEFAULT_CHANNEL:
+                       ret = lbs_mesh_set_defaults_ioctl(priv, wrq);
+                       break;
+               case LBS_SUBCMD_MESH_SET_DEFAULT_PROTO_ID:
+               case LBS_SUBCMD_MESH_SET_DEFAULT_METRIC_ID:
+               case LBS_SUBCMD_MESH_SET_DEFAULT_MESH_CAP:
+                       ret = lbs_mesh_set_meshie_ioctl(priv, wrq, cmd);
+                       break;
                default:
                        ret = -EOPNOTSUPP;
                        break;
@@ -1188,6 +1395,12 @@ int lbs_do_ioctl(struct net_device *dev, struct ifreq 
*req, int cmd)
                        ret = lbs_mesh_ioctl(priv, wrq, cmd,
                                        CMD_ACT_MESH_GET_LINK_COSTS);
                        break;
+               case LBS_SUBCMD_MESH_SET_DEFAULT_MESH_ID:
+                       ret = lbs_mesh_set_meshie_ioctl(priv, wrq, cmd);
+                       break;
+               case LBS_SUBCMD_MESH_GET_DEFAULT_MESH_ID:
+                       ret = lbs_mesh_get_defaults_ioctl(priv, wrq, cmd);
+                       break;
                }
                break;
 
@@ -1222,6 +1435,14 @@ int lbs_do_ioctl(struct net_device *dev, struct ifreq 
*req, int cmd)
                case LBS_SUBCMD_BT_GET_INVERT:
                        ret = lbs_bt_get_invert_ioctl(priv, req);
                        break;
+               case LBS_SUBCMD_MESH_GET_BOOTFLAG:
+               case LBS_SUBCMD_MESH_GET_BOOTTIME:
+               case LBS_SUBCMD_MESH_GET_DEFAULT_CHANNEL:
+               case LBS_SUBCMD_MESH_GET_DEFAULT_PROTO_ID:
+               case LBS_SUBCMD_MESH_GET_DEFAULT_METRIC_ID:
+               case LBS_SUBCMD_MESH_GET_DEFAULT_MESH_CAP:
+                       ret = lbs_mesh_get_defaults_ioctl(priv, wrq, cmd);
+                       break;
                default:
                        ret = -EOPNOTSUPP;
                }
diff --git a/drivers/net/wireless/libertas/ioctl.h 
b/drivers/net/wireless/libertas/ioctl.h
index 811ecf2..266fe3b 100644
--- a/drivers/net/wireless/libertas/ioctl.h
+++ b/drivers/net/wireless/libertas/ioctl.h
@@ -19,6 +19,12 @@
 #define LBS_SUBCMD_MESH_GET_BCAST_RATE         19
 #define LBS_SUBCMD_MESH_GET_RREQ_DELAY         20
 #define LBS_SUBCMD_MESH_GET_ROUTE_EXP          21
+#define LBS_SUBCMD_MESH_GET_BOOTFLAG           22
+#define LBS_SUBCMD_MESH_GET_BOOTTIME           23
+#define LBS_SUBCMD_MESH_GET_DEFAULT_CHANNEL    24
+#define LBS_SUBCMD_MESH_GET_DEFAULT_PROTO_ID   25
+#define LBS_SUBCMD_MESH_GET_DEFAULT_METRIC_ID  26
+#define LBS_SUBCMD_MESH_GET_DEFAULT_MESH_CAP   27
 
 #define LBS_SETONEINT_GETNONE                  (SIOCIWFIRSTPRIV + 24)
 #define LBS_SUBCMD_SET_REGION                  8
@@ -28,6 +34,12 @@
 #define LBS_SUBCMD_MESH_SET_RREQ_DELAY         21
 #define LBS_SUBCMD_MESH_SET_ROUTE_EXP          22
 #define LBS_SUBCMD_MESH_SET_PRB_RSP_RETRY_LIMIT 23
+#define LBS_SUBCMD_MESH_SET_BOOTFLAG           24
+#define LBS_SUBCMD_MESH_SET_BOOTTIME           25
+#define LBS_SUBCMD_MESH_SET_DEFAULT_CHANNEL    26
+#define LBS_SUBCMD_MESH_SET_DEFAULT_PROTO_ID   27
+#define LBS_SUBCMD_MESH_SET_DEFAULT_METRIC_ID  28
+#define LBS_SUBCMD_MESH_SET_DEFAULT_MESH_CAP   29
 
 #define LBS_SET128CHAR_GET128CHAR              (SIOCIWFIRSTPRIV + 25)
 #define LBS_SUBCMD_BT_ADD                      18
@@ -41,6 +53,8 @@
 #define LBS_SUBCMD_FWT_LIST_ROUTE              26
 #define LBS_SUBCMD_MESH_SET_LINK_COSTS         27
 #define LBS_SUBCMD_MESH_GET_LINK_COSTS         28
+#define LBS_SUBCMD_MESH_SET_DEFAULT_MESH_ID    29
+#define LBS_SUBCMD_MESH_GET_DEFAULT_MESH_ID    30
 
 #define LBS_SET_GET_SIXTEEN_INT                        (SIOCIWFIRSTPRIV + 29)
 #define LBS_LED_GPIO_CTRL                      5
diff --git a/drivers/net/wireless/libertas/main.c 
b/drivers/net/wireless/libertas/main.c
index e012d08..0060354 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -339,14 +339,15 @@ static ssize_t lbs_mesh_set(struct device *dev,
 {
        struct lbs_private *priv = to_net_dev(dev)->priv;
        int enable;
-       int ret;
+       int ret, action = CMD_ACT_MESH_CONFIG_STOP;
 
        sscanf(buf, "%x", &enable);
        enable = !!enable;
        if (enable == !!priv->mesh_dev)
                return count;
-
-       ret = lbs_mesh_config(priv, enable, priv->curbssparams.channel);
+       if (enable)
+               action = CMD_ACT_MESH_CONFIG_START;
+       ret = lbs_mesh_config(priv, action, priv->curbssparams.channel);
        if (ret)
                return ret;
 
@@ -1220,9 +1221,11 @@ int lbs_start_card(struct lbs_private *priv)
 
        lbs_update_channel(priv);
        priv->mesh_tlv = 0x100 + 291;
-       if (lbs_mesh_config(priv, 1, priv->curbssparams.channel)) {
+       if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+                                       priv->curbssparams.channel)) {
                priv->mesh_tlv = 0x100 + 37;
-               if (lbs_mesh_config(priv, 1, priv->curbssparams.channel))
+               if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+                                       priv->curbssparams.channel))
                        priv->mesh_tlv = 0;
        }
        if (priv->mesh_tlv) {
diff --git a/drivers/net/wireless/libertas/types.h 
b/drivers/net/wireless/libertas/types.h
index 4031be4..abe18f6 100644
--- a/drivers/net/wireless/libertas/types.h
+++ b/drivers/net/wireless/libertas/types.h
@@ -6,6 +6,8 @@
 
 #include <linux/if_ether.h>
 #include <asm/byteorder.h>
+#include <linux/wireless.h>
+#include <net/ieee80211.h>
 
 struct ieeetypes_cfparamset {
        u8 elementid;
@@ -252,4 +254,33 @@ struct mrvlietypes_ledbhv {
        struct led_bhv ledbhv[1];
 } __attribute__ ((packed));
 
+/* Meant to be packed as the value member of a struct ieee80211_info_element.
+ * Note that the len member of the ieee80211_info_element varies depending on
+ * the mesh_id_len */
+struct mrvl_meshie_val {
+       u8 oui[P80211_OUI_LEN];
+       u8 type;
+       u8 subtype;
+       u8 version;
+       u8 active_protocol_id;
+       u8 active_metric_id;
+       u8 mesh_capability;
+       u8 mesh_id_len;
+       u8 mesh_id[IW_ESSID_MAX_SIZE];
+} __attribute__ ((packed));
+
+struct mrvl_meshie {
+       struct ieee80211_info_element hdr;
+       struct mrvl_meshie_val val;
+} __attribute__ ((packed));
+
+struct mrvl_mesh_defaults
+{
+       __le32 bootflag;
+       u8 boottime;
+       u8 reserved;
+       __le16 channel;
+       struct mrvl_meshie meshie;      
+} __attribute__ ((packed));
+
 #endif
diff --git a/drivers/net/wireless/libertas/wext.c 
b/drivers/net/wireless/libertas/wext.c
index 271db96..c07ac39 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -1007,7 +1007,7 @@ static int lbs_mesh_set_freq(struct net_device *dev,
                else if (priv->mode == IW_MODE_ADHOC)
                        lbs_stop_adhoc_network(priv);
        }
-       lbs_mesh_config(priv, 1, fwrq->m);
+       lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, fwrq->m);
        lbs_update_channel(priv);
        ret = 0;
 
@@ -2016,7 +2016,7 @@ static int lbs_mesh_set_essid(struct net_device *dev,
                priv->mesh_ssid_len = dwrq->length;
        }
 
-       lbs_mesh_config(priv, 1, priv->curbssparams.channel);
+       lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 
priv->curbssparams.channel);
  out:
        lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
        return ret;
@@ -2225,6 +2225,16 @@ static const struct iw_priv_args lbs_private_args[] = {
            { LBS_SUBCMD_MESH_GET_BCAST_RATE, 0, INT_PARAM, "mesh_get_bcastr"},
            { LBS_SUBCMD_MESH_GET_RREQ_DELAY, 0, INT_PARAM, "get_rreq_delay"},
            { LBS_SUBCMD_MESH_GET_ROUTE_EXP, 0, INT_PARAM, "get_route_exp"},
+           { LBS_SUBCMD_MESH_GET_BOOTFLAG, 0, INT_PARAM, "get_bootflag"},
+           { LBS_SUBCMD_MESH_GET_BOOTTIME, 0, INT_PARAM, "get_boottime"},
+           { LBS_SUBCMD_MESH_GET_DEFAULT_CHANNEL, 0, INT_PARAM,
+                                                       "get_def_chan"},
+           { LBS_SUBCMD_MESH_GET_DEFAULT_PROTO_ID, 0, INT_PARAM,
+                                                       "get_def_protid"},
+           { LBS_SUBCMD_MESH_GET_DEFAULT_METRIC_ID, 0, INT_PARAM,
+                                                       "get_def_metid"},
+           { LBS_SUBCMD_MESH_GET_DEFAULT_MESH_CAP, 0, INT_PARAM,
+                                                       "get_def_meshcap"},
        { LBS_SETONEINT_GETNONE, INT_PARAM, 0, ""},
            { LBS_SUBCMD_SET_REGION, INT_PARAM, 0, "setregioncode"},
            { LBS_SUBCMD_MESH_SET_TTL, INT_PARAM, 0, "mesh_set_ttl"},
@@ -2234,6 +2244,16 @@ static const struct iw_priv_args lbs_private_args[] = {
            { LBS_SUBCMD_MESH_SET_ROUTE_EXP, INT_PARAM, 0, "set_route_exp"},
            { LBS_SUBCMD_MESH_SET_PRB_RSP_RETRY_LIMIT, INT_PARAM, 0,
                                                        "setprspretrylt"},
+           { LBS_SUBCMD_MESH_SET_BOOTFLAG, INT_PARAM, 0, "set_bootflag"},
+           { LBS_SUBCMD_MESH_SET_BOOTTIME, INT_PARAM, 0, "set_boottime"},
+           { LBS_SUBCMD_MESH_SET_DEFAULT_CHANNEL, INT_PARAM, 0,
+                                                       "set_def_chan"},
+           { LBS_SUBCMD_MESH_SET_DEFAULT_PROTO_ID, INT_PARAM, 0,
+                                                       "set_def_protid"},
+           { LBS_SUBCMD_MESH_SET_DEFAULT_METRIC_ID, INT_PARAM, 0,
+                                                       "set_def_metid"},
+           { LBS_SUBCMD_MESH_SET_DEFAULT_MESH_CAP, INT_PARAM, 0,
+                                                       "set_def_meshcap"},
        { LBS_SET128CHAR_GET128CHAR, CHAR128_PARAM, CHAR128_PARAM, ""},
            { LBS_SUBCMD_BT_ADD, CHAR128_PARAM, CHAR128_PARAM, "bt_add"},
            { LBS_SUBCMD_BT_DEL, CHAR128_PARAM, CHAR128_PARAM, "bt_del"},
@@ -2246,6 +2266,10 @@ static const struct iw_priv_args lbs_private_args[] = {
            { LBS_SUBCMD_FWT_LIST_ROUTE, CHAR128_PARAM, CHAR128_PARAM, 
"fwt_list_route"},
            { LBS_SUBCMD_MESH_SET_LINK_COSTS, CHAR128_PARAM, CHAR128_PARAM, 
"set_link_costs"},
            { LBS_SUBCMD_MESH_GET_LINK_COSTS, CHAR128_PARAM, CHAR128_PARAM, 
"get_link_costs"},
+           { LBS_SUBCMD_MESH_SET_DEFAULT_MESH_ID, CHAR128_PARAM, CHAR128_PARAM,
+                                                       "set_def_meshid"},
+           { LBS_SUBCMD_MESH_GET_DEFAULT_MESH_ID, CHAR128_PARAM, CHAR128_PARAM,
+                                                       "get_def_meshid"},
        { LBS_SET_GET_SIXTEEN_INT, INT16_PARAM, INT16_PARAM, ""},
            { LBS_LED_GPIO_CTRL, INT16_PARAM, INT16_PARAM, "ledgpio"},
            { LBS_BCN_CTRL, INT16_PARAM, INT16_PARAM, "bcn_control"},
-- 
1.5.2.5



_______________________________________________
Devel mailing list
[email protected]
http://lists.laptop.org/listinfo/devel

Reply via email to