aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJavier Cardona <javier@cozybit.com>2008-05-17 03:55:10 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-21 21:47:39 -0400
commitedaea5ce05ca804cc55438c586ca2f947d49f56f (patch)
treebe82d922cb908221d247e21d04ddf5517e7a4953
parent75bf45a7b4ab81cfa5c5eab68b57bbfee8b8ede2 (diff)
libertas: 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. Signed-off-by: Javier Cardona <javier@cozybit.com> Signed-off-by: David Woodhouse <dwmw2@infradead.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/libertas/assoc.c6
-rw-r--r--drivers/net/wireless/libertas/cmd.c68
-rw-r--r--drivers/net/wireless/libertas/cmd.h3
-rw-r--r--drivers/net/wireless/libertas/defs.h10
-rw-r--r--drivers/net/wireless/libertas/host.h17
-rw-r--r--drivers/net/wireless/libertas/main.c13
-rw-r--r--drivers/net/wireless/libertas/types.h30
-rw-r--r--drivers/net/wireless/libertas/wext.c5
8 files changed, 132 insertions, 20 deletions
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index c9c3640ce9fb..953a44f750e1 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -603,7 +603,8 @@ static int assoc_helper_channel(struct lbs_private *priv,
603 /* Change mesh channel first; 21.p21 firmware won't let 603 /* Change mesh channel first; 21.p21 firmware won't let
604 you change channel otherwise (even though it'll return 604 you change channel otherwise (even though it'll return
605 an error to this */ 605 an error to this */
606 lbs_mesh_config(priv, 0, assoc_req->channel); 606 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP,
607 assoc_req->channel);
607 } 608 }
608 609
609 lbs_deb_assoc("ASSOC: channel: %d -> %d\n", 610 lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
@@ -642,7 +643,8 @@ static int assoc_helper_channel(struct lbs_private *priv,
642 643
643 restore_mesh: 644 restore_mesh:
644 if (priv->mesh_dev) 645 if (priv->mesh_dev)
645 lbs_mesh_config(priv, 1, priv->curbssparams.channel); 646 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
647 priv->curbssparams.channel);
646 648
647 done: 649 done:
648 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); 650 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 b494aba869c5..7ccec987faaa 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -4,6 +4,7 @@
4 */ 4 */
5 5
6#include <net/iw_handler.h> 6#include <net/iw_handler.h>
7#include <net/ieee80211.h>
7#include <linux/kfifo.h> 8#include <linux/kfifo.h>
8#include "host.h" 9#include "host.h"
9#include "hostcmd.h" 10#include "hostcmd.h"
@@ -998,24 +999,69 @@ int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
998 return ret; 999 return ret;
999} 1000}
1000 1001
1001int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan) 1002int lbs_mesh_config_send(struct lbs_private *priv,
1003 struct cmd_ds_mesh_config *cmd,
1004 uint16_t action, uint16_t type)
1005{
1006 int ret;
1007
1008 lbs_deb_enter(LBS_DEB_CMD);
1009
1010 cmd->hdr.command = cpu_to_le16(CMD_MESH_CONFIG);
1011 cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
1012 cmd->hdr.result = 0;
1013
1014 cmd->type = cpu_to_le16(type);
1015 cmd->action = cpu_to_le16(action);
1016
1017 ret = lbs_cmd_with_response(priv, CMD_MESH_CONFIG, cmd);
1018
1019 lbs_deb_leave(LBS_DEB_CMD);
1020 return ret;
1021}
1022
1023/* This function is the CMD_MESH_CONFIG legacy function. It only handles the
1024 * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG
1025 * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
1026 * lbs_mesh_config_send.
1027 */
1028int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
1002{ 1029{
1003 struct cmd_ds_mesh_config cmd; 1030 struct cmd_ds_mesh_config cmd;
1031 struct mrvl_meshie *ie;
1004 1032
1005 memset(&cmd, 0, sizeof(cmd)); 1033 memset(&cmd, 0, sizeof(cmd));
1006 cmd.action = cpu_to_le16(enable);
1007 cmd.channel = cpu_to_le16(chan); 1034 cmd.channel = cpu_to_le16(chan);
1008 cmd.type = cpu_to_le16(priv->mesh_tlv); 1035 ie = (struct mrvl_meshie *)cmd.data;
1009 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 1036
1010 1037 switch (action) {
1011 if (enable) { 1038 case CMD_ACT_MESH_CONFIG_START:
1012 cmd.length = cpu_to_le16(priv->mesh_ssid_len); 1039 ie->hdr.id = MFIE_TYPE_GENERIC;
1013 memcpy(cmd.data, priv->mesh_ssid, priv->mesh_ssid_len); 1040 ie->val.oui[0] = 0x00;
1041 ie->val.oui[1] = 0x50;
1042 ie->val.oui[2] = 0x43;
1043 ie->val.type = MARVELL_MESH_IE_TYPE;
1044 ie->val.subtype = MARVELL_MESH_IE_SUBTYPE;
1045 ie->val.version = MARVELL_MESH_IE_VERSION;
1046 ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP;
1047 ie->val.active_metric_id = MARVELL_MESH_METRIC_ID;
1048 ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
1049 ie->val.mesh_id_len = priv->mesh_ssid_len;
1050 memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
1051 ie->hdr.len = sizeof(struct mrvl_meshie_val) -
1052 IW_ESSID_MAX_SIZE + priv->mesh_ssid_len;
1053 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
1054 break;
1055 case CMD_ACT_MESH_CONFIG_STOP:
1056 break;
1057 default:
1058 return -1;
1014 } 1059 }
1015 lbs_deb_cmd("mesh config enable %d TLV %x channel %d SSID %s\n", 1060 lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
1016 enable, priv->mesh_tlv, chan, 1061 action, priv->mesh_tlv, chan,
1017 escape_essid(priv->mesh_ssid, priv->mesh_ssid_len)); 1062 escape_essid(priv->mesh_ssid, priv->mesh_ssid_len));
1018 return lbs_cmd_with_response(priv, CMD_MESH_CONFIG, &cmd); 1063
1064 return lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
1019} 1065}
1020 1066
1021static int lbs_cmd_bcn_ctrl(struct lbs_private * priv, 1067static 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 f4019c22adfc..00d290e2818f 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -39,6 +39,9 @@ int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
39int lbs_get_channel(struct lbs_private *priv); 39int lbs_get_channel(struct lbs_private *priv);
40int lbs_set_channel(struct lbs_private *priv, u8 channel); 40int lbs_set_channel(struct lbs_private *priv, u8 channel);
41 41
42int lbs_mesh_config_send(struct lbs_private *priv,
43 struct cmd_ds_mesh_config *cmd,
44 uint16_t action, uint16_t type);
42int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); 45int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
43 46
44int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria); 47int 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 d39520111062..3793cb92296a 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
170 170
171#define MARVELL_MESH_IE_LENGTH 9 171#define MARVELL_MESH_IE_LENGTH 9
172 172
173/* Values used to populate the struct mrvl_mesh_ie. The only time you need this
174 * is when enabling the mesh using CMD_MESH_CONFIG.
175 */
176#define MARVELL_MESH_IE_TYPE 4
177#define MARVELL_MESH_IE_SUBTYPE 0
178#define MARVELL_MESH_IE_VERSION 0
179#define MARVELL_MESH_PROTO_ID_HWMP 0
180#define MARVELL_MESH_METRIC_ID 0
181#define MARVELL_MESH_CAPABILITY 0
182
173/** INT status Bit Definition*/ 183/** INT status Bit Definition*/
174#define MRVDRV_TX_DNLD_RDY 0x0001 184#define MRVDRV_TX_DNLD_RDY 0x0001
175#define MRVDRV_RX_UPLD_RDY 0x0002 185#define MRVDRV_RX_UPLD_RDY 0x0002
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index 3915c3144fad..c92e41b4faf4 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -256,6 +256,23 @@ enum cmd_mesh_access_opts {
256 CMD_ACT_MESH_GET_AUTOSTART_ENABLED, 256 CMD_ACT_MESH_GET_AUTOSTART_ENABLED,
257}; 257};
258 258
259/* Define actions and types for CMD_MESH_CONFIG */
260enum cmd_mesh_config_actions {
261 CMD_ACT_MESH_CONFIG_STOP = 0,
262 CMD_ACT_MESH_CONFIG_START,
263 CMD_ACT_MESH_CONFIG_SET,
264 CMD_ACT_MESH_CONFIG_GET,
265};
266
267enum cmd_mesh_config_types {
268 CMD_TYPE_MESH_SET_BOOTFLAG = 1,
269 CMD_TYPE_MESH_SET_BOOTTIME,
270 CMD_TYPE_MESH_SET_DEF_CHANNEL,
271 CMD_TYPE_MESH_SET_MESH_IE,
272 CMD_TYPE_MESH_GET_DEFAULTS,
273 CMD_TYPE_MESH_GET_MESH_IE, /* GET_DEFAULTS is superset of GET_MESHIE */
274};
275
259/** Card Event definition */ 276/** Card Event definition */
260#define MACREG_INT_CODE_TX_PPA_FREE 0 277#define MACREG_INT_CODE_TX_PPA_FREE 0
261#define MACREG_INT_CODE_TX_DMA_DONE 1 278#define MACREG_INT_CODE_TX_DMA_DONE 1
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index a87febad8c29..01299c8ed27c 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -344,14 +344,15 @@ static ssize_t lbs_mesh_set(struct device *dev,
344{ 344{
345 struct lbs_private *priv = to_net_dev(dev)->priv; 345 struct lbs_private *priv = to_net_dev(dev)->priv;
346 int enable; 346 int enable;
347 int ret; 347 int ret, action = CMD_ACT_MESH_CONFIG_STOP;
348 348
349 sscanf(buf, "%x", &enable); 349 sscanf(buf, "%x", &enable);
350 enable = !!enable; 350 enable = !!enable;
351 if (enable == !!priv->mesh_dev) 351 if (enable == !!priv->mesh_dev)
352 return count; 352 return count;
353 353 if (enable)
354 ret = lbs_mesh_config(priv, enable, priv->curbssparams.channel); 354 action = CMD_ACT_MESH_CONFIG_START;
355 ret = lbs_mesh_config(priv, action, priv->curbssparams.channel);
355 if (ret) 356 if (ret)
356 return ret; 357 return ret;
357 358
@@ -1257,9 +1258,11 @@ int lbs_start_card(struct lbs_private *priv)
1257 useful */ 1258 useful */
1258 1259
1259 priv->mesh_tlv = 0x100 + 291; 1260 priv->mesh_tlv = 0x100 + 291;
1260 if (lbs_mesh_config(priv, 1, priv->curbssparams.channel)) { 1261 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
1262 priv->curbssparams.channel)) {
1261 priv->mesh_tlv = 0x100 + 37; 1263 priv->mesh_tlv = 0x100 + 37;
1262 if (lbs_mesh_config(priv, 1, priv->curbssparams.channel)) 1264 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
1265 priv->curbssparams.channel))
1263 priv->mesh_tlv = 0; 1266 priv->mesh_tlv = 0;
1264 } 1267 }
1265 if (priv->mesh_tlv) { 1268 if (priv->mesh_tlv) {
diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h
index 4031be420862..e0c2599da92f 100644
--- a/drivers/net/wireless/libertas/types.h
+++ b/drivers/net/wireless/libertas/types.h
@@ -6,6 +6,8 @@
6 6
7#include <linux/if_ether.h> 7#include <linux/if_ether.h>
8#include <asm/byteorder.h> 8#include <asm/byteorder.h>
9#include <linux/wireless.h>
10#include <net/ieee80211.h>
9 11
10struct ieeetypes_cfparamset { 12struct ieeetypes_cfparamset {
11 u8 elementid; 13 u8 elementid;
@@ -252,4 +254,32 @@ struct mrvlietypes_ledbhv {
252 struct led_bhv ledbhv[1]; 254 struct led_bhv ledbhv[1];
253} __attribute__ ((packed)); 255} __attribute__ ((packed));
254 256
257/* Meant to be packed as the value member of a struct ieee80211_info_element.
258 * Note that the len member of the ieee80211_info_element varies depending on
259 * the mesh_id_len */
260struct mrvl_meshie_val {
261 uint8_t oui[P80211_OUI_LEN];
262 uint8_t type;
263 uint8_t subtype;
264 uint8_t version;
265 uint8_t active_protocol_id;
266 uint8_t active_metric_id;
267 uint8_t mesh_capability;
268 uint8_t mesh_id_len;
269 uint8_t mesh_id[IW_ESSID_MAX_SIZE];
270} __attribute__ ((packed));
271
272struct mrvl_meshie {
273 struct ieee80211_info_element hdr;
274 struct mrvl_meshie_val val;
275} __attribute__ ((packed));
276
277struct mrvl_mesh_defaults {
278 __le32 bootflag;
279 uint8_t boottime;
280 uint8_t reserved;
281 __le16 channel;
282 struct mrvl_meshie meshie;
283} __attribute__ ((packed));
284
255#endif 285#endif
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 0973d015a520..d4b19f11b785 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -1002,7 +1002,7 @@ static int lbs_mesh_set_freq(struct net_device *dev,
1002 else if (priv->mode == IW_MODE_ADHOC) 1002 else if (priv->mode == IW_MODE_ADHOC)
1003 lbs_stop_adhoc_network(priv); 1003 lbs_stop_adhoc_network(priv);
1004 } 1004 }
1005 lbs_mesh_config(priv, 1, fwrq->m); 1005 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, fwrq->m);
1006 lbs_update_channel(priv); 1006 lbs_update_channel(priv);
1007 ret = 0; 1007 ret = 0;
1008 1008
@@ -2011,7 +2011,8 @@ static int lbs_mesh_set_essid(struct net_device *dev,
2011 priv->mesh_ssid_len = dwrq->length; 2011 priv->mesh_ssid_len = dwrq->length;
2012 } 2012 }
2013 2013
2014 lbs_mesh_config(priv, 1, priv->curbssparams.channel); 2014 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
2015 priv->curbssparams.channel);
2015 out: 2016 out:
2016 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); 2017 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
2017 return ret; 2018 return ret;