[PATCH stable] libertas: Extend CMD_MESH_CONFIG to get and set persistent mesh default params.

Brian Cavagnolo brian at cozybit.com
Thu May 15 14:01:47 EDT 2008


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 <brian at cozybit.com>
---
 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






More information about the Devel mailing list