* [PATCH 2.6.29-rc8-wl] libertas: support mesh for various firmware versions
@ 2009-03-25 16:51 Bing Zhao
2009-03-26 20:06 ` Dan Williams
0 siblings, 1 reply; 2+ messages in thread
From: Bing Zhao @ 2009-03-25 16:51 UTC (permalink / raw)
To: libertas-dev, Dan Williams; +Cc: linux-wireless
rebased to fix the conflict with 6ec54de.
>From 915a19e7208524bda46872d70d6b346e06843c9f Mon Sep 17 00:00:00 2001
From: Bing Zhao <bzhao@marvell.com>
Date: Mon, 16 Mar 2009 14:52:36 -0700
Subject: [PATCH] libertas: support mesh for various firmware versions
CMD_MESH_CONFIG command ID and a couple of structure members in TxPD,
RxPD have been changed in firmware version 10.x.y.z and newer.
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
drivers/net/wireless/libertas/cmd.c | 26 +++++++++++++++++-
drivers/net/wireless/libertas/defs.h | 21 ++++++++++++++
drivers/net/wireless/libertas/dev.h | 1 +
drivers/net/wireless/libertas/host.h | 3 +-
drivers/net/wireless/libertas/hostcmd.h | 28 +++++++++++++++++---
drivers/net/wireless/libertas/main.c | 44 +++++++++++++++++++------------
drivers/net/wireless/libertas/rx.c | 32 ++++++----------------
drivers/net/wireless/libertas/tx.c | 8 ++++-
drivers/net/wireless/libertas/types.h | 2 +
9 files changed, 116 insertions(+), 49 deletions(-)
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 639dd02..17d6f9c 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -119,6 +119,19 @@ int lbs_update_hw_spec(struct lbs_private *priv)
lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
cmd.hwifversion, cmd.version);
+ /* Determine mesh_fw_ver from fwrelease and fwcapinfo */
+ /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */
+ /* 5.110.22 have mesh command with 0xa3 command id */
+ /* 10.0.0.p0 FW brings in mesh config command with different id */
+ /* Check FW version MSB and initialize mesh_fw_ver */
+ if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5)
+ priv->mesh_fw_ver = MESH_FW_OLD;
+ else if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) &&
+ (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK))
+ priv->mesh_fw_ver = MESH_FW_NEW;
+ else
+ priv->mesh_fw_ver = MESH_NONE;
+
/* Clamp region code to 8-bit since FW spec indicates that it should
* only ever be 8-bit, even though the field size is 16-bit. Some firmware
* returns non-zero high 8 bits here.
@@ -1036,17 +1049,26 @@ static int __lbs_mesh_config_send(struct lbs_private *priv,
uint16_t action, uint16_t type)
{
int ret;
+ u16 command = CMD_MESH_CONFIG_OLD;
lbs_deb_enter(LBS_DEB_CMD);
- cmd->hdr.command = cpu_to_le16(CMD_MESH_CONFIG);
+ /*
+ * Command id is 0xac for v10 FW along with mesh interface
+ * id in bits 14-13-12.
+ */
+ if (priv->mesh_fw_ver == MESH_FW_NEW)
+ command = CMD_MESH_CONFIG |
+ (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
+
+ cmd->hdr.command = cpu_to_le16(command);
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);
+ ret = lbs_cmd_with_response(priv, command, cmd);
lbs_deb_leave(LBS_DEB_CMD);
return ret;
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index e8dfde3..48da157 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -227,6 +227,20 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
#define TxPD_CONTROL_WDS_FRAME (1<<17)
#define TxPD_MESH_FRAME TxPD_CONTROL_WDS_FRAME
+/** Mesh interface ID */
+#define MESH_IFACE_ID 0x0001
+/** Mesh id should be in bits 14-13-12 */
+#define MESH_IFACE_BIT_OFFSET 0x000c
+/** Mesh enable bit in FW capability */
+#define MESH_CAPINFO_ENABLE_MASK (1<<16)
+
+/** FW definition from Marvell v5 */
+#define MRVL_FW_V5 (0x05)
+/** FW definition from Marvell v10 */
+#define MRVL_FW_V10 (0x0a)
+/** FW major revision definition */
+#define MRVL_FW_MAJOR_REV(x) ((x)>>24)
+
/** RxPD status */
#define MRVDRV_RXPD_STATUS_OK 0x0001
@@ -380,6 +394,13 @@ enum KEY_INFO_WPA {
KEY_INFO_WPA_ENABLED = 0x04
};
+/** mesh_fw_ver */
+enum _mesh_fw_ver {
+ MESH_NONE = 0, /* MESH is not supported */
+ MESH_FW_OLD, /* MESH is supported in FW V5 */
+ MESH_FW_NEW, /* MESH is supported in FW V10 and newer */
+};
+
/* Default values for fwt commands. */
#define FWT_DEFAULT_METRIC 0
#define FWT_DEFAULT_DIR 1
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index dd682c4..5f3f6b2 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -101,6 +101,7 @@ struct lbs_mesh_stats {
/** Private structure for the MV device */
struct lbs_private {
int mesh_open;
+ int mesh_fw_ver;
int infra_open;
int mesh_autostart_enabled;
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index d4457ef..8ff8ac9 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -83,7 +83,8 @@
#define CMD_FWT_ACCESS 0x0095
#define CMD_802_11_MONITOR_MODE 0x0098
#define CMD_MESH_ACCESS 0x009b
-#define CMD_MESH_CONFIG 0x00a3
+#define CMD_MESH_CONFIG_OLD 0x00a3
+#define CMD_MESH_CONFIG 0x00ac
#define CMD_SET_BOOT2_VER 0x00a5
#define CMD_802_11_BEACON_CTRL 0x00b0
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index a899aeb..391c54a 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -13,8 +13,19 @@
/* TxPD descriptor */
struct txpd {
- /* Current Tx packet status */
- __le32 tx_status;
+ /* union to cope up with later FW revisions */
+ union {
+ /* Current Tx packet status */
+ __le32 tx_status;
+ struct {
+ /* BSS type: client, AP, etc. */
+ u8 bss_type;
+ /* BSS number */
+ u8 bss_num;
+ /* Reserved */
+ __le16 reserved;
+ } bss;
+ } u;
/* Tx control */
__le32 tx_control;
__le32 tx_packet_location;
@@ -36,8 +47,17 @@ struct txpd {
/* RxPD Descriptor */
struct rxpd {
- /* Current Rx packet status */
- __le16 status;
+ /* union to cope up with later FW revisions */
+ union {
+ /* Current Rx packet status */
+ __le16 status;
+ struct {
+ /* BSS type: client, AP, etc. */
+ u8 bss_type;
+ /* BSS number */
+ u8 bss_num;
+ } bss;
+ } u;
/* SNR */
u8 snr;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index d93553f..f14d341 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1316,8 +1316,10 @@ int lbs_start_card(struct lbs_private *priv)
lbs_update_channel(priv);
- /* 5.0.16p0 is known to NOT support any mesh */
- if (priv->fwrelease > 0x05001000) {
+ /* Check mesh FW version and appropriately send the mesh start
+ * command
+ */
+ if (priv->mesh_fw_ver == MESH_FW_OLD) {
/* Enable mesh, if supported, and work out which TLV it uses.
0x100 + 291 is an unofficial value used in 5.110.20.pXX
0x100 + 37 is the official value used in 5.110.21.pXX
@@ -1331,27 +1333,35 @@ int lbs_start_card(struct lbs_private *priv)
It's just that 5.110.20.pXX will not have done anything
useful */
- priv->mesh_tlv = 0x100 + 291;
+ priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
priv->curbssparams.channel)) {
- priv->mesh_tlv = 0x100 + 37;
+ priv->mesh_tlv = TLV_TYPE_MESH_ID;
if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
priv->curbssparams.channel))
priv->mesh_tlv = 0;
}
- if (priv->mesh_tlv) {
- lbs_add_mesh(priv);
-
- if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
- lbs_pr_err("cannot register lbs_mesh attribute\n");
-
- /* While rtap isn't related to mesh, only mesh-enabled
- * firmware implements the rtap functionality via
- * CMD_802_11_MONITOR_MODE.
- */
- if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
- lbs_pr_err("cannot register lbs_rtap attribute\n");
- }
+ } else if (priv->mesh_fw_ver == MESH_FW_NEW) {
+ /* 10.0.0.pXX new firmwares should succeed with TLV
+ * 0x100+37; Do not invoke command with old TLV.
+ */
+ priv->mesh_tlv = TLV_TYPE_MESH_ID;
+ if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+ priv->curbssparams.channel))
+ priv->mesh_tlv = 0;
+ }
+ if (priv->mesh_tlv) {
+ lbs_add_mesh(priv);
+
+ if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
+ lbs_pr_err("cannot register lbs_mesh attribute\n");
+
+ /* While rtap isn't related to mesh, only mesh-enabled
+ * firmware implements the rtap functionality via
+ * CMD_802_11_MONITOR_MODE.
+ */
+ if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
+ lbs_pr_err("cannot register lbs_rtap attribute\n");
}
lbs_debugfs_init_one(priv, dev);
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index e661e10..2ca2f7b 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -160,8 +160,15 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
p_rx_pkt = (struct rxpackethdr *) skb->data;
p_rx_pd = &p_rx_pkt->rx_pd;
- if (priv->mesh_dev && (p_rx_pd->rx_control & RxPD_MESH_FRAME))
- dev = priv->mesh_dev;
+ if (priv->mesh_dev) {
+ if (priv->mesh_fw_ver == MESH_FW_OLD) {
+ if (p_rx_pd->rx_control & RxPD_MESH_FRAME)
+ dev = priv->mesh_dev;
+ } else if (priv->mesh_fw_ver == MESH_FW_NEW) {
+ if (p_rx_pd->u.bss.bss_num == MESH_IFACE_ID)
+ dev = priv->mesh_dev;
+ }
+ }
lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data,
min_t(unsigned int, skb->len, 100));
@@ -173,17 +180,6 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
goto done;
}
- /*
- * Check rxpd status and update 802.3 stat,
- */
- if (!(p_rx_pd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) {
- lbs_deb_rx("rx err: frame received with bad status\n");
- lbs_pr_alert("rxpd not ok\n");
- priv->stats.rx_errors++;
- ret = 0;
- goto done;
- }
-
lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
@@ -332,14 +328,6 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
goto done;
}
- /*
- * Check rxpd status and update 802.3 stat,
- */
- if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) {
- //lbs_deb_rx("rx err: frame received with bad status\n");
- priv->stats.rx_errors++;
- }
-
lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
@@ -351,8 +339,6 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
radiotap_hdr.hdr.it_pad = 0;
radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
- if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
- radiotap_hdr.flags |= IEEE80211_RADIOTAP_F_BADFCS;
radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
/* XXX must check no carryout */
radiotap_hdr.antsignal = prxpd->snr + prxpd->nf;
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index 68bec31..6be3b27 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -132,8 +132,12 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
txpd->tx_packet_length = cpu_to_le16(pkt_len);
txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
- if (dev == priv->mesh_dev)
- txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
+ if (dev == priv->mesh_dev) {
+ if (priv->mesh_fw_ver == MESH_FW_OLD)
+ txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
+ else if (priv->mesh_fw_ver == MESH_FW_NEW)
+ txpd->u.bss.bss_num = MESH_IFACE_ID;
+ }
lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd));
diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h
index fb7a2d1..de03b9c 100644
--- a/drivers/net/wireless/libertas/types.h
+++ b/drivers/net/wireless/libertas/types.h
@@ -94,6 +94,8 @@ struct ieeetypes_assocrsp {
#define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19)
#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22)
#define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 23)
+#define TLV_TYPE_MESH_ID (PROPRIETARY_TLV_BASE_ID + 37)
+#define TLV_TYPE_OLD_MESH_ID (PROPRIETARY_TLV_BASE_ID + 291)
/** TLV related data structures*/
struct mrvlietypesheader {
--
1.5.3.6
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH 2.6.29-rc8-wl] libertas: support mesh for various firmware versions
2009-03-25 16:51 [PATCH 2.6.29-rc8-wl] libertas: support mesh for various firmware versions Bing Zhao
@ 2009-03-26 20:06 ` Dan Williams
0 siblings, 0 replies; 2+ messages in thread
From: Dan Williams @ 2009-03-26 20:06 UTC (permalink / raw)
To: Bing Zhao; +Cc: libertas-dev, linux-wireless
On Wed, 2009-03-25 at 09:51 -0700, Bing Zhao wrote:
> rebased to fix the conflict with 6ec54de.
>
>
> From 915a19e7208524bda46872d70d6b346e06843c9f Mon Sep 17 00:00:00 2001
> From: Bing Zhao <bzhao@marvell.com>
> Date: Mon, 16 Mar 2009 14:52:36 -0700
> Subject: [PATCH] libertas: support mesh for various firmware versions
>
> CMD_MESH_CONFIG command ID and a couple of structure members in TxPD,
> RxPD have been changed in firmware version 10.x.y.z and newer.
>
> Signed-off-by: Kiran Divekar <dkiran@marvell.com>
> Signed-off-by: Bing Zhao <bzhao@marvell.com>
Acked-by: Dan Williams <dcbw@redhat.com>
> ---
> drivers/net/wireless/libertas/cmd.c | 26 +++++++++++++++++-
> drivers/net/wireless/libertas/defs.h | 21 ++++++++++++++
> drivers/net/wireless/libertas/dev.h | 1 +
> drivers/net/wireless/libertas/host.h | 3 +-
> drivers/net/wireless/libertas/hostcmd.h | 28 +++++++++++++++++---
> drivers/net/wireless/libertas/main.c | 44 +++++++++++++++++++------------
> drivers/net/wireless/libertas/rx.c | 32 ++++++----------------
> drivers/net/wireless/libertas/tx.c | 8 ++++-
> drivers/net/wireless/libertas/types.h | 2 +
> 9 files changed, 116 insertions(+), 49 deletions(-)
>
> diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
> index 639dd02..17d6f9c 100644
> --- a/drivers/net/wireless/libertas/cmd.c
> +++ b/drivers/net/wireless/libertas/cmd.c
> @@ -119,6 +119,19 @@ int lbs_update_hw_spec(struct lbs_private *priv)
> lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
> cmd.hwifversion, cmd.version);
>
> + /* Determine mesh_fw_ver from fwrelease and fwcapinfo */
> + /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */
> + /* 5.110.22 have mesh command with 0xa3 command id */
> + /* 10.0.0.p0 FW brings in mesh config command with different id */
> + /* Check FW version MSB and initialize mesh_fw_ver */
> + if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5)
> + priv->mesh_fw_ver = MESH_FW_OLD;
> + else if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) &&
> + (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK))
> + priv->mesh_fw_ver = MESH_FW_NEW;
> + else
> + priv->mesh_fw_ver = MESH_NONE;
> +
> /* Clamp region code to 8-bit since FW spec indicates that it should
> * only ever be 8-bit, even though the field size is 16-bit. Some firmware
> * returns non-zero high 8 bits here.
> @@ -1036,17 +1049,26 @@ static int __lbs_mesh_config_send(struct lbs_private *priv,
> uint16_t action, uint16_t type)
> {
> int ret;
> + u16 command = CMD_MESH_CONFIG_OLD;
>
> lbs_deb_enter(LBS_DEB_CMD);
>
> - cmd->hdr.command = cpu_to_le16(CMD_MESH_CONFIG);
> + /*
> + * Command id is 0xac for v10 FW along with mesh interface
> + * id in bits 14-13-12.
> + */
> + if (priv->mesh_fw_ver == MESH_FW_NEW)
> + command = CMD_MESH_CONFIG |
> + (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
> +
> + cmd->hdr.command = cpu_to_le16(command);
> 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);
> + ret = lbs_cmd_with_response(priv, command, cmd);
>
> lbs_deb_leave(LBS_DEB_CMD);
> return ret;
> diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
> index e8dfde3..48da157 100644
> --- a/drivers/net/wireless/libertas/defs.h
> +++ b/drivers/net/wireless/libertas/defs.h
> @@ -227,6 +227,20 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
> #define TxPD_CONTROL_WDS_FRAME (1<<17)
> #define TxPD_MESH_FRAME TxPD_CONTROL_WDS_FRAME
>
> +/** Mesh interface ID */
> +#define MESH_IFACE_ID 0x0001
> +/** Mesh id should be in bits 14-13-12 */
> +#define MESH_IFACE_BIT_OFFSET 0x000c
> +/** Mesh enable bit in FW capability */
> +#define MESH_CAPINFO_ENABLE_MASK (1<<16)
> +
> +/** FW definition from Marvell v5 */
> +#define MRVL_FW_V5 (0x05)
> +/** FW definition from Marvell v10 */
> +#define MRVL_FW_V10 (0x0a)
> +/** FW major revision definition */
> +#define MRVL_FW_MAJOR_REV(x) ((x)>>24)
> +
> /** RxPD status */
>
> #define MRVDRV_RXPD_STATUS_OK 0x0001
> @@ -380,6 +394,13 @@ enum KEY_INFO_WPA {
> KEY_INFO_WPA_ENABLED = 0x04
> };
>
> +/** mesh_fw_ver */
> +enum _mesh_fw_ver {
> + MESH_NONE = 0, /* MESH is not supported */
> + MESH_FW_OLD, /* MESH is supported in FW V5 */
> + MESH_FW_NEW, /* MESH is supported in FW V10 and newer */
> +};
> +
> /* Default values for fwt commands. */
> #define FWT_DEFAULT_METRIC 0
> #define FWT_DEFAULT_DIR 1
> diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
> index dd682c4..5f3f6b2 100644
> --- a/drivers/net/wireless/libertas/dev.h
> +++ b/drivers/net/wireless/libertas/dev.h
> @@ -101,6 +101,7 @@ struct lbs_mesh_stats {
> /** Private structure for the MV device */
> struct lbs_private {
> int mesh_open;
> + int mesh_fw_ver;
> int infra_open;
> int mesh_autostart_enabled;
>
> diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
> index d4457ef..8ff8ac9 100644
> --- a/drivers/net/wireless/libertas/host.h
> +++ b/drivers/net/wireless/libertas/host.h
> @@ -83,7 +83,8 @@
> #define CMD_FWT_ACCESS 0x0095
> #define CMD_802_11_MONITOR_MODE 0x0098
> #define CMD_MESH_ACCESS 0x009b
> -#define CMD_MESH_CONFIG 0x00a3
> +#define CMD_MESH_CONFIG_OLD 0x00a3
> +#define CMD_MESH_CONFIG 0x00ac
> #define CMD_SET_BOOT2_VER 0x00a5
> #define CMD_802_11_BEACON_CTRL 0x00b0
>
> diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
> index a899aeb..391c54a 100644
> --- a/drivers/net/wireless/libertas/hostcmd.h
> +++ b/drivers/net/wireless/libertas/hostcmd.h
> @@ -13,8 +13,19 @@
>
> /* TxPD descriptor */
> struct txpd {
> - /* Current Tx packet status */
> - __le32 tx_status;
> + /* union to cope up with later FW revisions */
> + union {
> + /* Current Tx packet status */
> + __le32 tx_status;
> + struct {
> + /* BSS type: client, AP, etc. */
> + u8 bss_type;
> + /* BSS number */
> + u8 bss_num;
> + /* Reserved */
> + __le16 reserved;
> + } bss;
> + } u;
> /* Tx control */
> __le32 tx_control;
> __le32 tx_packet_location;
> @@ -36,8 +47,17 @@ struct txpd {
>
> /* RxPD Descriptor */
> struct rxpd {
> - /* Current Rx packet status */
> - __le16 status;
> + /* union to cope up with later FW revisions */
> + union {
> + /* Current Rx packet status */
> + __le16 status;
> + struct {
> + /* BSS type: client, AP, etc. */
> + u8 bss_type;
> + /* BSS number */
> + u8 bss_num;
> + } bss;
> + } u;
>
> /* SNR */
> u8 snr;
> diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
> index d93553f..f14d341 100644
> --- a/drivers/net/wireless/libertas/main.c
> +++ b/drivers/net/wireless/libertas/main.c
> @@ -1316,8 +1316,10 @@ int lbs_start_card(struct lbs_private *priv)
>
> lbs_update_channel(priv);
>
> - /* 5.0.16p0 is known to NOT support any mesh */
> - if (priv->fwrelease > 0x05001000) {
> + /* Check mesh FW version and appropriately send the mesh start
> + * command
> + */
> + if (priv->mesh_fw_ver == MESH_FW_OLD) {
> /* Enable mesh, if supported, and work out which TLV it uses.
> 0x100 + 291 is an unofficial value used in 5.110.20.pXX
> 0x100 + 37 is the official value used in 5.110.21.pXX
> @@ -1331,27 +1333,35 @@ int lbs_start_card(struct lbs_private *priv)
> It's just that 5.110.20.pXX will not have done anything
> useful */
>
> - priv->mesh_tlv = 0x100 + 291;
> + priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
> if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
> priv->curbssparams.channel)) {
> - priv->mesh_tlv = 0x100 + 37;
> + priv->mesh_tlv = TLV_TYPE_MESH_ID;
> if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
> priv->curbssparams.channel))
> priv->mesh_tlv = 0;
> }
> - if (priv->mesh_tlv) {
> - lbs_add_mesh(priv);
> -
> - if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
> - lbs_pr_err("cannot register lbs_mesh attribute\n");
> -
> - /* While rtap isn't related to mesh, only mesh-enabled
> - * firmware implements the rtap functionality via
> - * CMD_802_11_MONITOR_MODE.
> - */
> - if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
> - lbs_pr_err("cannot register lbs_rtap attribute\n");
> - }
> + } else if (priv->mesh_fw_ver == MESH_FW_NEW) {
> + /* 10.0.0.pXX new firmwares should succeed with TLV
> + * 0x100+37; Do not invoke command with old TLV.
> + */
> + priv->mesh_tlv = TLV_TYPE_MESH_ID;
> + if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
> + priv->curbssparams.channel))
> + priv->mesh_tlv = 0;
> + }
> + if (priv->mesh_tlv) {
> + lbs_add_mesh(priv);
> +
> + if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
> + lbs_pr_err("cannot register lbs_mesh attribute\n");
> +
> + /* While rtap isn't related to mesh, only mesh-enabled
> + * firmware implements the rtap functionality via
> + * CMD_802_11_MONITOR_MODE.
> + */
> + if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
> + lbs_pr_err("cannot register lbs_rtap attribute\n");
> }
>
> lbs_debugfs_init_one(priv, dev);
> diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
> index e661e10..2ca2f7b 100644
> --- a/drivers/net/wireless/libertas/rx.c
> +++ b/drivers/net/wireless/libertas/rx.c
> @@ -160,8 +160,15 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
>
> p_rx_pkt = (struct rxpackethdr *) skb->data;
> p_rx_pd = &p_rx_pkt->rx_pd;
> - if (priv->mesh_dev && (p_rx_pd->rx_control & RxPD_MESH_FRAME))
> - dev = priv->mesh_dev;
> + if (priv->mesh_dev) {
> + if (priv->mesh_fw_ver == MESH_FW_OLD) {
> + if (p_rx_pd->rx_control & RxPD_MESH_FRAME)
> + dev = priv->mesh_dev;
> + } else if (priv->mesh_fw_ver == MESH_FW_NEW) {
> + if (p_rx_pd->u.bss.bss_num == MESH_IFACE_ID)
> + dev = priv->mesh_dev;
> + }
> + }
>
> lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data,
> min_t(unsigned int, skb->len, 100));
> @@ -173,17 +180,6 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
> goto done;
> }
>
> - /*
> - * Check rxpd status and update 802.3 stat,
> - */
> - if (!(p_rx_pd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) {
> - lbs_deb_rx("rx err: frame received with bad status\n");
> - lbs_pr_alert("rxpd not ok\n");
> - priv->stats.rx_errors++;
> - ret = 0;
> - goto done;
> - }
> -
> lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
> skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
>
> @@ -332,14 +328,6 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
> goto done;
> }
>
> - /*
> - * Check rxpd status and update 802.3 stat,
> - */
> - if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) {
> - //lbs_deb_rx("rx err: frame received with bad status\n");
> - priv->stats.rx_errors++;
> - }
> -
> lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
> skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
>
> @@ -351,8 +339,6 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
> radiotap_hdr.hdr.it_pad = 0;
> radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
> radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
> - if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
> - radiotap_hdr.flags |= IEEE80211_RADIOTAP_F_BADFCS;
> radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
> /* XXX must check no carryout */
> radiotap_hdr.antsignal = prxpd->snr + prxpd->nf;
> diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
> index 68bec31..6be3b27 100644
> --- a/drivers/net/wireless/libertas/tx.c
> +++ b/drivers/net/wireless/libertas/tx.c
> @@ -132,8 +132,12 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
> txpd->tx_packet_length = cpu_to_le16(pkt_len);
> txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
>
> - if (dev == priv->mesh_dev)
> - txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
> + if (dev == priv->mesh_dev) {
> + if (priv->mesh_fw_ver == MESH_FW_OLD)
> + txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
> + else if (priv->mesh_fw_ver == MESH_FW_NEW)
> + txpd->u.bss.bss_num = MESH_IFACE_ID;
> + }
>
> lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd));
>
> diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h
> index fb7a2d1..de03b9c 100644
> --- a/drivers/net/wireless/libertas/types.h
> +++ b/drivers/net/wireless/libertas/types.h
> @@ -94,6 +94,8 @@ struct ieeetypes_assocrsp {
> #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19)
> #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22)
> #define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 23)
> +#define TLV_TYPE_MESH_ID (PROPRIETARY_TLV_BASE_ID + 37)
> +#define TLV_TYPE_OLD_MESH_ID (PROPRIETARY_TLV_BASE_ID + 291)
>
> /** TLV related data structures*/
> struct mrvlietypesheader {
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2009-03-26 20:08 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-03-25 16:51 [PATCH 2.6.29-rc8-wl] libertas: support mesh for various firmware versions Bing Zhao
2009-03-26 20:06 ` Dan Williams
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).