[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