Skip to contentSkip to conversation

Extend MESH_CONFIG command to access non-volatile configuration.

PATCH In review Javier Cardona 2 participants 2 messages May 20, 2008 Networking drivers (wireless)

lore
Share & tools
lore
#0 lore raw

PATCH 1/2 Extend MESH_CONFIG command to access non-volatile configuration.

This patch is based on a patch from Shailendra Govardhan and Brian Cavagnolo. It extends the MESH_CONFIG command to configure non-volatile parameters on libertas devices that support them (e.g. OLPC Active Antenna).

This patch only implements the driver/firmware interface.

See http://dev.laptop.org/ticket/6823 for minimal testing results and known issues.

---
 drivers/net/wireless/libertas/assoc.c |    6 ++-
 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/main.c  |   13 ++++--
 drivers/net/wireless/libertas/types.h |   30 ++++++++++++++
 drivers/net/wireless/libertas/wext.c  |    5 +-
 8 files changed, 131 insertions(+), 21 deletions(-)
drivers/net/wireless/libertas/assoc.c +4 -2
index c9c3640..b17f9df 100644
@@ -603,7 +603,8 @@ 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",
@@ -642,7 +643,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);
drivers/net/wireless/libertas/cmd.c +57 -12

87 lines not on this page · raw message

drivers/net/wireless/libertas/cmd.h +2 -0
index 3dfc2d4..a80de18 100644
@@ -40,6 +40,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);
drivers/net/wireless/libertas/defs.h +10 -0
index d395201..0120d6c 100644
@@ -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
drivers/net/wireless/libertas/host.h +17 -0
index 3915c31..c92e41b 100644
@@ -256,6 +256,23 @@ enum cmd_mesh_access_opts {
 	CMD_ACT_MESH_GET_AUTOSTART_ENABLED,
 };
 
+/* 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
drivers/net/wireless/libertas/main.c +8 -5
index 406f54d..5001888 100644
@@ -343,14 +343,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;
 
@@ -1235,9 +1236,11 @@ int lbs_start_card(struct lbs_private *priv)
 		   useful */
 
 		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) {
drivers/net/wireless/libertas/types.h +30 -0
index 4031be4..e0c2599 100644
@@ -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,32 @@ 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 {
+	uint8_t oui[P80211_OUI_LEN];
+	uint8_t type;
+	uint8_t subtype;
+	uint8_t version;
+	uint8_t active_protocol_id;
+	uint8_t active_metric_id;
+	uint8_t mesh_capability;
+	uint8_t mesh_id_len;
+	uint8_t 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;
+	uint8_t boottime;
+	uint8_t reserved;
+	__le16 channel;
+	struct mrvl_meshie meshie;
+} __attribute__ ((packed));
+
 #endif
drivers/net/wireless/libertas/wext.c +3 -2
index 0973d01..8c9292e 100644
@@ -1002,7 +1002,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;
 
@@ -2011,7 +2011,8 @@ 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;
Signature · 1 line
1.5.2.4
#1 lore raw
Quoted 8 lines · Javier Cardona

This patch is based on a patch from Shailendra Govardhan and Brian Cavagnolo. It extends the MESH_CONFIG command to configure non-volatile parameters on libertas devices that support them (e.g. OLPC Active Antenna).

This patch only implements the driver/firmware interface.

See http://dev.laptop.org/ticket/6823 for minimal testing results and known issues.

Thanks. That looks much better, modulo a few cosmetic things which I'll fix up, and this (which I'll also fix):

+ cmd.length = sizeof(struct mrvl_meshie_val);

Sparse would have told you about that, if you built with 'C=2 CF=-D__CHECK_ENDIAN__':

drivers/net/wireless/libertas/cmd.c:1052:14: warning: incorrect type in assignment (different base types)
drivers/net/wireless/libertas/cmd.c:1052:14: expected restricted unsigned short [addressable] [assigned] [usertype] length
drivers/net/wireless/libertas/cmd.c:1052:14: got unsigned int

I'd recommend always testing on a big-endian box, too. Sparse is good, but no substitute for the real thing.

Signature · 1 line
dwmw2