Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH 2/4] ath9k_hw: distinguish single-chip solutions on initial probe print
From: Kalle Valo @ 2009-10-26 16:14 UTC (permalink / raw)
  To: Luis R. Rodriguez; +Cc: linville, linux-wireless, ath9k-devel
In-Reply-To: <1256567941-26859-3-git-send-email-lrodriguez@atheros.com>

"Luis R. Rodriguez" <lrodriguez@atheros.com> writes:

> Devices with external radios have revisions which we can count on.
> On single chip solutions these EEPROM values for these radio revision
> also exist but are not meaningful as the radios are embedded onto the
> same chip. Each single-chip device evolves together as one device.
>
> Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
> ---
>  drivers/net/wireless/ath/ath9k/ahb.c |   11 ++++-------
>  drivers/net/wireless/ath/ath9k/hw.c  |   27 +++++++++++++++++++++++----
>  drivers/net/wireless/ath/ath9k/hw.h  |    3 +--
>  drivers/net/wireless/ath/ath9k/pci.c |   11 ++++-------
>  4 files changed, 32 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
> index 41422c4..925818c 100644
> --- a/drivers/net/wireless/ath/ath9k/ahb.c
> +++ b/drivers/net/wireless/ath/ath9k/ahb.c
> @@ -69,6 +69,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
>  	int irq;
>  	int ret = 0;
>  	struct ath_hw *ah;
> +	char hw_name[1024];

This is a bit too large to allocate from stack IMHO.


[...]

> --- a/drivers/net/wireless/ath/ath9k/pci.c
> +++ b/drivers/net/wireless/ath/ath9k/pci.c
> @@ -114,6 +114,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  	u32 val;
>  	int ret = 0;
>  	struct ath_hw *ah;
> +	char hw_name[1024];

Ditto.

-- 
Kalle Valo

^ permalink raw reply

* [RFC] firmware_class: make request_firmware_nowait more useful
From: Johannes Berg @ 2009-10-26 16:12 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-wireless

Unfortunately, one cannot hold on to the struct firmware
that request_firmware_nowait() hands off, which is needed
in some cases. Allow this by requiring the callback to
free it (via release_firmware).

Additionally, give it a gfp_t parameter -- all the current
users call it from a GFP_KERNEL context so the GFP_ATOMIC
isn't necessary. This also marks an API break which is
useful in a sense, although that is obviously not the
primary purpose of this change.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
This is a prerequisite for many drivers' conversion to the firmware
loading scheme we talked about at the wireless summit. Due to
suspend/hibernate we need to keep a copy of the firmware loaded, but
because we cannot request_firmware() during probe() we want to use
_nowait() and then proceed registration (or unbind) on the callback.

 drivers/base/firmware_class.c               |   14 ++++++--------
 drivers/firmware/dell_rbu.c                 |    9 +++++++--
 drivers/serial/ucc_uart.c                   |    8 +++++---
 drivers/staging/comedi/drivers/usbdux.c     |    5 ++++-
 drivers/staging/comedi/drivers/usbduxfast.c |    5 ++++-
 drivers/usb/atm/ueagle-atm.c                |    7 ++++---
 include/linux/firmware.h                    |    5 +++--
 7 files changed, 33 insertions(+), 20 deletions(-)

--- wireless-testing.orig/drivers/base/firmware_class.c	2009-10-26 16:45:18.000000000 +0100
+++ wireless-testing/drivers/base/firmware_class.c	2009-10-26 17:08:10.000000000 +0100
@@ -601,12 +601,9 @@ request_firmware_work_func(void *arg)
 	}
 	ret = _request_firmware(&fw, fw_work->name, fw_work->device,
 		fw_work->uevent);
-	if (ret < 0)
-		fw_work->cont(NULL, fw_work->context);
-	else {
-		fw_work->cont(fw, fw_work->context);
-		release_firmware(fw);
-	}
+
+	fw_work->cont(fw, fw_work->context);
+
 	module_put(fw_work->module);
 	kfree(fw_work);
 	return ret;
@@ -619,6 +616,7 @@ request_firmware_work_func(void *arg)
  *	is non-zero else the firmware copy must be done manually.
  * @name: name of firmware file
  * @device: device for which firmware is being loaded
+ * @gfp: allocation flags
  * @context: will be passed over to @cont, and
  *	@fw may be %NULL if firmware request fails.
  * @cont: function will be called asynchronously when the firmware
@@ -631,12 +629,12 @@ request_firmware_work_func(void *arg)
 int
 request_firmware_nowait(
 	struct module *module, int uevent,
-	const char *name, struct device *device, void *context,
+	const char *name, struct device *device, gfp_t gfp, void *context,
 	void (*cont)(const struct firmware *fw, void *context))
 {
 	struct task_struct *task;
 	struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work),
-						GFP_ATOMIC);
+						gfp);
 
 	if (!fw_work)
 		return -ENOMEM;
--- wireless-testing.orig/include/linux/firmware.h	2009-10-26 16:45:53.000000000 +0100
+++ wireless-testing/include/linux/firmware.h	2009-10-26 17:03:56.000000000 +0100
@@ -4,6 +4,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/compiler.h>
+#include <linux/gfp.h>
 
 #define FW_ACTION_NOHOTPLUG 0
 #define FW_ACTION_HOTPLUG 1
@@ -38,7 +39,7 @@ int request_firmware(const struct firmwa
 		     struct device *device);
 int request_firmware_nowait(
 	struct module *module, int uevent,
-	const char *name, struct device *device, void *context,
+	const char *name, struct device *device, gfp_t gfp, void *context,
 	void (*cont)(const struct firmware *fw, void *context));
 
 void release_firmware(const struct firmware *fw);
@@ -51,7 +52,7 @@ static inline int request_firmware(const
 }
 static inline int request_firmware_nowait(
 	struct module *module, int uevent,
-	const char *name, struct device *device, void *context,
+	const char *name, struct device *device, gfp_t gfp, void *context,
 	void (*cont)(const struct firmware *fw, void *context))
 {
 	return -EINVAL;
--- wireless-testing.orig/drivers/firmware/dell_rbu.c	2009-10-26 16:49:06.000000000 +0100
+++ wireless-testing/drivers/firmware/dell_rbu.c	2009-10-26 16:49:52.000000000 +0100
@@ -544,9 +544,12 @@ static void callbackfn_rbu(const struct 
 {
 	rbu_data.entry_created = 0;
 
-	if (!fw || !fw->size)
+	if (!fw)
 		return;
 
+	if (!fw->size)
+		goto out;
+
 	spin_lock(&rbu_data.lock);
 	if (!strcmp(image_type, "mono")) {
 		if (!img_update_realloc(fw->size))
@@ -568,6 +571,8 @@ static void callbackfn_rbu(const struct 
 	} else
 		pr_debug("invalid image type specified.\n");
 	spin_unlock(&rbu_data.lock);
+ out:
+	release_firmware(fw);
 }
 
 static ssize_t read_rbu_image_type(struct kobject *kobj,
@@ -615,7 +620,7 @@ static ssize_t write_rbu_image_type(stru
 			spin_unlock(&rbu_data.lock);
 			req_firm_rc = request_firmware_nowait(THIS_MODULE,
 				FW_ACTION_NOHOTPLUG, "dell_rbu",
-				&rbu_device->dev, &context,
+				&rbu_device->dev, GFP_KERNEL, &context,
 				callbackfn_rbu);
 			if (req_firm_rc) {
 				printk(KERN_ERR
--- wireless-testing.orig/drivers/serial/ucc_uart.c	2009-10-26 16:50:04.000000000 +0100
+++ wireless-testing/drivers/serial/ucc_uart.c	2009-10-26 16:51:10.000000000 +0100
@@ -1179,16 +1179,18 @@ static void uart_firmware_cont(const str
 
 	if (firmware->header.length != fw->size) {
 		dev_err(dev, "invalid firmware\n");
-		return;
+		goto out;
 	}
 
 	ret = qe_upload_firmware(firmware);
 	if (ret) {
 		dev_err(dev, "could not load firmware\n");
-		return;
+		goto out;
 	}
 
 	firmware_loaded = 1;
+ out:
+	release_firmware(fw);
 }
 
 static int ucc_uart_probe(struct of_device *ofdev,
@@ -1247,7 +1249,7 @@ static int ucc_uart_probe(struct of_devi
 			 */
 			ret = request_firmware_nowait(THIS_MODULE,
 				FW_ACTION_HOTPLUG, filename, &ofdev->dev,
-				&ofdev->dev, uart_firmware_cont);
+				GFP_KERNEL, &ofdev->dev, uart_firmware_cont);
 			if (ret) {
 				dev_err(&ofdev->dev,
 					"could not load firmware %s\n",
--- wireless-testing.orig/drivers/staging/comedi/drivers/usbdux.c	2009-10-26 16:51:16.000000000 +0100
+++ wireless-testing/drivers/staging/comedi/drivers/usbdux.c	2009-10-26 16:51:52.000000000 +0100
@@ -2327,9 +2327,11 @@ static void usbdux_firmware_request_comp
 	if (ret) {
 		dev_err(&usbdev->dev,
 			"Could not upload firmware (err=%d)\n", ret);
-		return;
+		goto out;
 	}
 	comedi_usb_auto_config(usbdev, BOARDNAME);
+ out:
+	release_firmware(fw);
 }
 
 /* allocate memory for the urbs and initialise them */
@@ -2580,6 +2582,7 @@ static int usbduxsub_probe(struct usb_in
 				      FW_ACTION_HOTPLUG,
 				      "usbdux_firmware.bin",
 				      &udev->dev,
+				      GFP_KERNEL,
 				      usbduxsub + index,
 				      usbdux_firmware_request_complete_handler);
 
--- wireless-testing.orig/drivers/staging/comedi/drivers/usbduxfast.c	2009-10-26 17:01:20.000000000 +0100
+++ wireless-testing/drivers/staging/comedi/drivers/usbduxfast.c	2009-10-26 17:01:47.000000000 +0100
@@ -1451,10 +1451,12 @@ static void usbduxfast_firmware_request_
 	if (ret) {
 		dev_err(&usbdev->dev,
 			"Could not upload firmware (err=%d)\n", ret);
-		return;
+		goto out;
 	}
 
 	comedi_usb_auto_config(usbdev, BOARDNAME);
+ out:
+	release_firmware(fw);
 }
 
 /*
@@ -1569,6 +1571,7 @@ static int usbduxfastsub_probe(struct us
 				      FW_ACTION_HOTPLUG,
 				      "usbduxfast_firmware.bin",
 				      &udev->dev,
+				      GFP_KERNEL,
 				      usbduxfastsub + index,
 				      usbduxfast_firmware_request_complete_handler);
 
--- wireless-testing.orig/drivers/usb/atm/ueagle-atm.c	2009-10-26 17:01:48.000000000 +0100
+++ wireless-testing/drivers/usb/atm/ueagle-atm.c	2009-10-26 17:03:29.000000000 +0100
@@ -667,12 +667,12 @@ static void uea_upload_pre_firmware(cons
 	else
 		uea_info(usb, "firmware uploaded\n");
 
-	uea_leaves(usb);
-	return;
+	goto err;
 
 err_fw_corrupted:
 	uea_err(usb, "firmware is corrupted\n");
 err:
+	release_firmware(fw_entry);
 	uea_leaves(usb);
 }
 
@@ -705,7 +705,8 @@ static int uea_load_firmware(struct usb_
 		break;
 	}
 
-	ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, usb, uea_upload_pre_firmware);
+	ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev,
+				      GFP_KERNEL, usb, uea_upload_pre_firmware);
 	if (ret)
 		uea_err(usb, "firmware %s is not available\n", fw_name);
 	else



^ permalink raw reply

* [PATCH] libertas: move mesh command handling away
From: Holger Schurig @ 2009-10-26 15:53 UTC (permalink / raw)
  To: linux-wireless, Dan Williams, John Linville

Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de>

--- linux-wl.orig/drivers/net/wireless/libertas/cmd.c
+++ linux-wl/drivers/net/wireless/libertas/cmd.c
@@ -3,7 +3,6 @@
   * It prepares command and sends it to firmware when it is ready.
   */
 
-#include <net/lib80211.h>
 #include <linux/kfifo.h>
 #include <linux/sched.h>
 
@@ -697,173 +696,6 @@
 	return 0;
 }
 
-static int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
-			       u16 cmd_action, void *pdata_buf)
-{
-	struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
-	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
-	cmd->command = cpu_to_le16(CMD_BT_ACCESS);
-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) +
-		sizeof(struct cmd_header));
-	cmd->result = 0;
-	bt_access->action = cpu_to_le16(cmd_action);
-
-	switch (cmd_action) {
-	case CMD_ACT_BT_ACCESS_ADD:
-		memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN);
-		lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", bt_access->addr1, 6);
-		break;
-	case CMD_ACT_BT_ACCESS_DEL:
-		memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN);
-		lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", bt_access->addr1, 6);
-		break;
-	case CMD_ACT_BT_ACCESS_LIST:
-		bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
-		break;
-	case CMD_ACT_BT_ACCESS_RESET:
-		break;
-	case CMD_ACT_BT_ACCESS_SET_INVERT:
-		bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
-		break;
-	case CMD_ACT_BT_ACCESS_GET_INVERT:
-		break;
-	default:
-		break;
-	}
-	lbs_deb_leave(LBS_DEB_CMD);
-	return 0;
-}
-
-static int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
-			       u16 cmd_action, void *pdata_buf)
-{
-	struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
-	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
-	cmd->command = cpu_to_le16(CMD_FWT_ACCESS);
-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) +
-		sizeof(struct cmd_header));
-	cmd->result = 0;
-
-	if (pdata_buf)
-		memcpy(fwt_access, pdata_buf, sizeof(*fwt_access));
-	else
-		memset(fwt_access, 0, sizeof(*fwt_access));
-
-	fwt_access->action = cpu_to_le16(cmd_action);
-
-	lbs_deb_leave(LBS_DEB_CMD);
-	return 0;
-}
-
-int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
-		    struct cmd_ds_mesh_access *cmd)
-{
-	int ret;
-
-	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
-	cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
-	cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
-	cmd->hdr.result = 0;
-
-	cmd->action = cpu_to_le16(cmd_action);
-
-	ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
-
-	lbs_deb_leave(LBS_DEB_CMD);
-	return ret;
-}
-
-static int __lbs_mesh_config_send(struct lbs_private *priv,
-				  struct cmd_ds_mesh_config *cmd,
-				  uint16_t action, uint16_t type)
-{
-	int ret;
-	u16 command = CMD_MESH_CONFIG_OLD;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	/*
-	 * 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, command, cmd);
-
-	lbs_deb_leave(LBS_DEB_CMD);
-	return ret;
-}
-
-int lbs_mesh_config_send(struct lbs_private *priv,
-			 struct cmd_ds_mesh_config *cmd,
-			 uint16_t action, uint16_t type)
-{
-	int ret;
-
-	if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
-		return -EOPNOTSUPP;
-
-	ret = __lbs_mesh_config_send(priv, cmd, action, type);
-	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;
-	DECLARE_SSID_BUF(ssid);
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.channel = cpu_to_le16(chan);
-	ie = (struct mrvl_meshie *)cmd.data;
-
-	switch (action) {
-	case CMD_ACT_MESH_CONFIG_START:
-		ie->id = WLAN_EID_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->len = sizeof(struct mrvl_meshie_val) -
-			IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len;
-		cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
-		break;
-	case CMD_ACT_MESH_CONFIG_STOP:
-		break;
-	default:
-		return -1;
-	}
-	lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
-		    action, priv->mesh_tlv, chan,
-		    print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
-
-	return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
-}
-
 static void lbs_queue_cmd(struct lbs_private *priv,
 			  struct cmd_ctrl_node *cmdnode)
 {
--- linux-wl.orig/drivers/net/wireless/libertas/mesh.h
+++ linux-wl/drivers/net/wireless/libertas/mesh.h
@@ -6,6 +6,7 @@
 
 
 #include <net/iw_handler.h>
+#include <net/lib80211.h>
 
 
 /* Mesh statistics */
@@ -42,6 +43,16 @@
 	struct net_device *dev, struct txpd *txpd);
 
 
+/* Command handling */
+
+struct cmd_ds_command;
+
+int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
+	u16 cmd_action, void *pdata_buf);
+int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
+	u16 cmd_action, void *pdata_buf);
+
+
 /* Persistent configuration */
 
 void lbs_persist_config_init(struct net_device *net);
--- linux-wl.orig/drivers/net/wireless/libertas/persistcfg.c
+++ linux-wl/drivers/net/wireless/libertas/persistcfg.c
@@ -441,6 +441,181 @@
 
 
 /***************************************************************************
+ * Mesh command handling
+ */
+
+int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
+			       u16 cmd_action, void *pdata_buf)
+{
+	struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
+	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
+
+	cmd->command = cpu_to_le16(CMD_BT_ACCESS);
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) +
+		sizeof(struct cmd_header));
+	cmd->result = 0;
+	bt_access->action = cpu_to_le16(cmd_action);
+
+	switch (cmd_action) {
+	case CMD_ACT_BT_ACCESS_ADD:
+		memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN);
+		lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr",
+			bt_access->addr1, 6);
+		break;
+	case CMD_ACT_BT_ACCESS_DEL:
+		memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN);
+		lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr",
+			bt_access->addr1, 6);
+		break;
+	case CMD_ACT_BT_ACCESS_LIST:
+		bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
+		break;
+	case CMD_ACT_BT_ACCESS_RESET:
+		break;
+	case CMD_ACT_BT_ACCESS_SET_INVERT:
+		bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
+		break;
+	case CMD_ACT_BT_ACCESS_GET_INVERT:
+		break;
+	default:
+		break;
+	}
+	lbs_deb_leave(LBS_DEB_CMD);
+	return 0;
+}
+
+int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
+			       u16 cmd_action, void *pdata_buf)
+{
+	struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
+	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
+
+	cmd->command = cpu_to_le16(CMD_FWT_ACCESS);
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) +
+		sizeof(struct cmd_header));
+	cmd->result = 0;
+
+	if (pdata_buf)
+		memcpy(fwt_access, pdata_buf, sizeof(*fwt_access));
+	else
+		memset(fwt_access, 0, sizeof(*fwt_access));
+
+	fwt_access->action = cpu_to_le16(cmd_action);
+
+	lbs_deb_leave(LBS_DEB_CMD);
+	return 0;
+}
+
+int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
+		    struct cmd_ds_mesh_access *cmd)
+{
+	int ret;
+
+	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
+
+	cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
+	cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
+	cmd->hdr.result = 0;
+
+	cmd->action = cpu_to_le16(cmd_action);
+
+	ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
+
+	lbs_deb_leave(LBS_DEB_CMD);
+	return ret;
+}
+
+static int __lbs_mesh_config_send(struct lbs_private *priv,
+				  struct cmd_ds_mesh_config *cmd,
+				  uint16_t action, uint16_t type)
+{
+	int ret;
+	u16 command = CMD_MESH_CONFIG_OLD;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	/*
+	 * 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, command, cmd);
+
+	lbs_deb_leave(LBS_DEB_CMD);
+	return ret;
+}
+
+int lbs_mesh_config_send(struct lbs_private *priv,
+			 struct cmd_ds_mesh_config *cmd,
+			 uint16_t action, uint16_t type)
+{
+	int ret;
+
+	if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
+		return -EOPNOTSUPP;
+
+	ret = __lbs_mesh_config_send(priv, cmd, action, type);
+	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;
+	DECLARE_SSID_BUF(ssid);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.channel = cpu_to_le16(chan);
+	ie = (struct mrvl_meshie *)cmd.data;
+
+	switch (action) {
+	case CMD_ACT_MESH_CONFIG_START:
+		ie->id = WLAN_EID_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->len = sizeof(struct mrvl_meshie_val) -
+			IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len;
+		cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
+		break;
+	case CMD_ACT_MESH_CONFIG_STOP:
+		break;
+	default:
+		return -1;
+	}
+	lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
+		    action, priv->mesh_tlv, chan,
+		    print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
+
+	return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
+}
+
+
+
+/***************************************************************************
  * Persistent configuration support
  */
 

-- 
http://www.holgerschurig.de

^ permalink raw reply

* Re: rtl8187: kernel oops when leds enabled
From: Larry Finger @ 2009-10-26 15:50 UTC (permalink / raw)
  To: Richard Farina; +Cc: linux-wireless
In-Reply-To: <4AE5BD6C.2050303@gmail.com>

On 10/26/2009 10:17 AM, Richard Farina wrote:

> I'm honestly a little surprised that no one has bothered to reproduce
> this in the month since I reported it but maybe it is more unique to my
> setup than it seems.

Your machine seems to be unique in that it happens most of the time.
It took more than 10 tries, but I finally got my copy of the
wireless-testing kernel to oops.

I will be working on a patch.

Larry

^ permalink raw reply

* [PATCH] libertas: move mesh-only ethtool operations away
From: Holger Schurig @ 2009-10-26 15:44 UTC (permalink / raw)
  To: linux-wireless, Dan Williams, John Linville

Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de>

--- linux-wl.orig/drivers/net/wireless/libertas/ethtool.c
+++ linux-wl/drivers/net/wireless/libertas/ethtool.c
@@ -8,17 +8,8 @@
 #include "dev.h"
 #include "wext.h"
 #include "cmd.h"
+#include "mesh.h"
 
-static const char * mesh_stat_strings[]= {
-			"drop_duplicate_bcast",
-			"drop_ttl_zero",
-			"drop_no_fwd_route",
-			"drop_no_buffers",
-			"fwded_unicast_cnt",
-			"fwded_bcast_cnt",
-			"drop_blind_table",
-			"tx_failed_cnt"
-};
 
 static void lbs_ethtool_get_drvinfo(struct net_device *dev,
 					 struct ethtool_drvinfo *info)
@@ -73,73 +64,6 @@
         return ret;
 }
 
-static void lbs_ethtool_get_stats(struct net_device *dev,
-				  struct ethtool_stats *stats, uint64_t *data)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	struct cmd_ds_mesh_access mesh_access;
-	int ret;
-
-	lbs_deb_enter(LBS_DEB_ETHTOOL);
-
-	/* Get Mesh Statistics */
-	ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access);
-
-	if (ret) {
-		memset(data, 0, MESH_STATS_NUM*(sizeof(uint64_t)));
-		return;
-	}
-
-	priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]);
-	priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]);
-	priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]);
-	priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]);
-	priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]);
-	priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]);
-	priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]);
-	priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]);
-
-	data[0] = priv->mstats.fwd_drop_rbt;
-	data[1] = priv->mstats.fwd_drop_ttl;
-	data[2] = priv->mstats.fwd_drop_noroute;
-	data[3] = priv->mstats.fwd_drop_nobuf;
-	data[4] = priv->mstats.fwd_unicast_cnt;
-	data[5] = priv->mstats.fwd_bcast_cnt;
-	data[6] = priv->mstats.drop_blind;
-	data[7] = priv->mstats.tx_failed_cnt;
-
-	lbs_deb_enter(LBS_DEB_ETHTOOL);
-}
-
-static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset)
-{
-	struct lbs_private *priv = dev->ml_priv;
-
-	if (sset == ETH_SS_STATS && dev == priv->mesh_dev)
-		return MESH_STATS_NUM;
-
-	return -EOPNOTSUPP;
-}
-
-static void lbs_ethtool_get_strings(struct net_device *dev,
-				    uint32_t stringset, uint8_t *s)
-{
-	int i;
-
-	lbs_deb_enter(LBS_DEB_ETHTOOL);
-
-	switch (stringset) {
-        case ETH_SS_STATS:
-		for (i=0; i < MESH_STATS_NUM; i++) {
-			memcpy(s + i * ETH_GSTRING_LEN,
-					mesh_stat_strings[i],
-					ETH_GSTRING_LEN);
-		}
-		break;
-        }
-	lbs_deb_enter(LBS_DEB_ETHTOOL);
-}
-
 static void lbs_ethtool_get_wol(struct net_device *dev,
 				struct ethtool_wolinfo *wol)
 {
@@ -187,9 +111,9 @@
 	.get_drvinfo = lbs_ethtool_get_drvinfo,
 	.get_eeprom =  lbs_ethtool_get_eeprom,
 	.get_eeprom_len = lbs_ethtool_get_eeprom_len,
-	.get_sset_count = lbs_ethtool_get_sset_count,
-	.get_ethtool_stats = lbs_ethtool_get_stats,
-	.get_strings = lbs_ethtool_get_strings,
+	.get_sset_count = lbs_mesh_ethtool_get_sset_count,
+	.get_ethtool_stats = lbs_mesh_ethtool_get_stats,
+	.get_strings = lbs_mesh_ethtool_get_strings,
 	.get_wol = lbs_ethtool_get_wol,
 	.set_wol = lbs_ethtool_set_wol,
 };
--- linux-wl.orig/drivers/net/wireless/libertas/mesh.h
+++ linux-wl/drivers/net/wireless/libertas/mesh.h
@@ -53,4 +53,15 @@
 extern struct iw_handler_def mesh_handler_def;
 
 
+/* Ethtool statistics */
+
+struct ethtool_stats;
+
+void lbs_mesh_ethtool_get_stats(struct net_device *dev,
+	struct ethtool_stats *stats, uint64_t *data);
+int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset);
+void lbs_mesh_ethtool_get_strings(struct net_device *dev,
+	uint32_t stringset, uint8_t *s);
+
+
 #endif
--- linux-wl.orig/drivers/net/wireless/libertas/persistcfg.c
+++ linux-wl/drivers/net/wireless/libertas/persistcfg.c
@@ -880,3 +880,87 @@
 	sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group);
 	sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group);
 }
+
+
+
+/***************************************************************************
+ * Ethtool related
+ */
+
+static const char *mesh_stat_strings[] = {
+			"drop_duplicate_bcast",
+			"drop_ttl_zero",
+			"drop_no_fwd_route",
+			"drop_no_buffers",
+			"fwded_unicast_cnt",
+			"fwded_bcast_cnt",
+			"drop_blind_table",
+			"tx_failed_cnt"
+};
+
+void lbs_mesh_ethtool_get_stats(struct net_device *dev,
+	struct ethtool_stats *stats, uint64_t *data)
+{
+	struct lbs_private *priv = dev->ml_priv;
+	struct cmd_ds_mesh_access mesh_access;
+	int ret;
+
+	lbs_deb_enter(LBS_DEB_ETHTOOL);
+
+	/* Get Mesh Statistics */
+	ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access);
+
+	if (ret) {
+		memset(data, 0, MESH_STATS_NUM*(sizeof(uint64_t)));
+		return;
+	}
+
+	priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]);
+	priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]);
+	priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]);
+	priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]);
+	priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]);
+	priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]);
+	priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]);
+	priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]);
+
+	data[0] = priv->mstats.fwd_drop_rbt;
+	data[1] = priv->mstats.fwd_drop_ttl;
+	data[2] = priv->mstats.fwd_drop_noroute;
+	data[3] = priv->mstats.fwd_drop_nobuf;
+	data[4] = priv->mstats.fwd_unicast_cnt;
+	data[5] = priv->mstats.fwd_bcast_cnt;
+	data[6] = priv->mstats.drop_blind;
+	data[7] = priv->mstats.tx_failed_cnt;
+
+	lbs_deb_enter(LBS_DEB_ETHTOOL);
+}
+
+int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset)
+{
+	struct lbs_private *priv = dev->ml_priv;
+
+	if (sset == ETH_SS_STATS && dev == priv->mesh_dev)
+		return MESH_STATS_NUM;
+
+	return -EOPNOTSUPP;
+}
+
+void lbs_mesh_ethtool_get_strings(struct net_device *dev,
+	uint32_t stringset, uint8_t *s)
+{
+	int i;
+
+	lbs_deb_enter(LBS_DEB_ETHTOOL);
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < MESH_STATS_NUM; i++) {
+			memcpy(s + i * ETH_GSTRING_LEN,
+					mesh_stat_strings[i],
+					ETH_GSTRING_LEN);
+		}
+		break;
+	}
+	lbs_deb_enter(LBS_DEB_ETHTOOL);
+}

-- 
http://www.holgerschurig.de

^ permalink raw reply

* [PATCH, v2] libertas: initial move of mesh related functions into persistcfg.c
From: Holger Schurig @ 2009-10-26 15:41 UTC (permalink / raw)
  To: linux-wireless; +Cc: Dan Williams, John Linville
In-Reply-To: <200910261622.22140.hs4233@mail.mn-solutions.de>

This moves mesh initialization, start/stop and rx/tx handling from
the respective *.c files into persistcfg.c.

Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de>

---
v2: don't modify Makefile

--- linux-wl.orig/drivers/net/wireless/libertas/main.c
+++ linux-wl/drivers/net/wireless/libertas/main.c
@@ -94,107 +94,9 @@
 	return 0;
 }
 
-/**
- * Attributes exported through sysfs
- */
-
-/**
- * @brief Get function for sysfs attribute anycast_mask
- */
-static ssize_t lbs_anycast_get(struct device *dev,
-		struct device_attribute *attr, char * buf)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_access mesh_access;
-	int ret;
-
-	memset(&mesh_access, 0, sizeof(mesh_access));
-
-	ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access);
-	if (ret)
-		return ret;
-
-	return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
-}
-
-/**
- * @brief Set function for sysfs attribute anycast_mask
- */
-static ssize_t lbs_anycast_set(struct device *dev,
-		struct device_attribute *attr, const char * buf, size_t count)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_access mesh_access;
-	uint32_t datum;
-	int ret;
-
-	memset(&mesh_access, 0, sizeof(mesh_access));
-	sscanf(buf, "%x", &datum);
-	mesh_access.data[0] = cpu_to_le32(datum);
-
-	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access);
-	if (ret)
-		return ret;
-
-	return strlen(buf);
-}
-
-/**
- * @brief Get function for sysfs attribute prb_rsp_limit
- */
-static ssize_t lbs_prb_rsp_limit_get(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_access mesh_access;
-	int ret;
-	u32 retry_limit;
-
-	memset(&mesh_access, 0, sizeof(mesh_access));
-	mesh_access.data[0] = cpu_to_le32(CMD_ACT_GET);
-
-	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
-			&mesh_access);
-	if (ret)
-		return ret;
-
-	retry_limit = le32_to_cpu(mesh_access.data[1]);
-	return snprintf(buf, 10, "%d\n", retry_limit);
-}
-
-/**
- * @brief Set function for sysfs attribute prb_rsp_limit
- */
-static ssize_t lbs_prb_rsp_limit_set(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_access mesh_access;
-	int ret;
-	unsigned long retry_limit;
-
-	memset(&mesh_access, 0, sizeof(mesh_access));
-	mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET);
-
-	if (!strict_strtoul(buf, 10, &retry_limit))
-		return -ENOTSUPP;
-	if (retry_limit > 15)
-		return -ENOTSUPP;
-
-	mesh_access.data[1] = cpu_to_le32(retry_limit);
-
-	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
-			&mesh_access);
-	if (ret)
-		return ret;
-
-	return strlen(buf);
-}
 
 static int lbs_add_rtap(struct lbs_private *priv);
 static void lbs_remove_rtap(struct lbs_private *priv);
-static int lbs_add_mesh(struct lbs_private *priv);
-static void lbs_remove_mesh(struct lbs_private *priv);
 
 
 /**
@@ -260,74 +162,7 @@
 static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set );
 
 /**
- * Get function for sysfs attribute mesh
- */
-static ssize_t lbs_mesh_get(struct device *dev,
-		struct device_attribute *attr, char * buf)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev);
-}
-
-/**
- *  Set function for sysfs attribute mesh
- */
-static ssize_t lbs_mesh_set(struct device *dev,
-		struct device_attribute *attr, const char * buf, size_t count)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	int enable;
-	int ret, action = CMD_ACT_MESH_CONFIG_STOP;
-
-	sscanf(buf, "%x", &enable);
-	enable = !!enable;
-	if (enable == !!priv->mesh_dev)
-		return count;
-	if (enable)
-		action = CMD_ACT_MESH_CONFIG_START;
-	ret = lbs_mesh_config(priv, action, priv->channel);
-	if (ret)
-		return ret;
-
-	if (enable)
-		lbs_add_mesh(priv);
-	else
-		lbs_remove_mesh(priv);
-
-	return count;
-}
-
-/**
- * lbs_mesh attribute to be exported per ethX interface
- * through sysfs (/sys/class/net/ethX/lbs_mesh)
- */
-static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set);
-
-/**
- * anycast_mask attribute to be exported per mshX interface
- * through sysfs (/sys/class/net/mshX/anycast_mask)
- */
-static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set);
-
-/**
- * prb_rsp_limit attribute to be exported per mshX interface
- * through sysfs (/sys/class/net/mshX/prb_rsp_limit)
- */
-static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get,
-		lbs_prb_rsp_limit_set);
-
-static struct attribute *lbs_mesh_sysfs_entries[] = {
-	&dev_attr_anycast_mask.attr,
-	&dev_attr_prb_rsp_limit.attr,
-	NULL,
-};
-
-static struct attribute_group lbs_mesh_attr_group = {
-	.attrs = lbs_mesh_sysfs_entries,
-};
-
-/**
- *  @brief This function opens the ethX or mshX interface
+ *  @brief This function opens the ethX interface
  *
  *  @param dev     A pointer to net_device structure
  *  @return 	   0 or -EBUSY if monitor mode active
@@ -346,18 +181,12 @@
 		goto out;
 	}
 
-	if (dev == priv->mesh_dev) {
-		priv->mesh_open = 1;
-		priv->mesh_connect_status = LBS_CONNECTED;
-		netif_carrier_on(dev);
-	} else {
-		priv->infra_open = 1;
+	priv->infra_open = 1;
 
-		if (priv->connect_status == LBS_CONNECTED)
-			netif_carrier_on(dev);
-		else
-			netif_carrier_off(dev);
-	}
+	if (priv->connect_status == LBS_CONNECTED)
+		netif_carrier_on(dev);
+	else
+		netif_carrier_off(dev);
 
 	if (!priv->tx_pending_len)
 		netif_wake_queue(dev);
@@ -369,33 +198,6 @@
 }
 
 /**
- *  @brief This function closes the mshX interface
- *
- *  @param dev     A pointer to net_device structure
- *  @return 	   0
- */
-static int lbs_mesh_stop(struct net_device *dev)
-{
-	struct lbs_private *priv = dev->ml_priv;
-
-	lbs_deb_enter(LBS_DEB_MESH);
-	spin_lock_irq(&priv->driver_lock);
-
-	priv->mesh_open = 0;
-	priv->mesh_connect_status = LBS_DISCONNECTED;
-
-	netif_stop_queue(dev);
-	netif_carrier_off(dev);
-
-	spin_unlock_irq(&priv->driver_lock);
-
-	schedule_work(&priv->mcast_work);
-
-	lbs_deb_leave(LBS_DEB_MESH);
-	return 0;
-}
-
-/**
  *  @brief This function closes the ethX interface
  *
  *  @param dev     A pointer to net_device structure
@@ -466,7 +268,7 @@
 }
 EXPORT_SYMBOL_GPL(lbs_host_to_card_done);
 
-static int lbs_set_mac_address(struct net_device *dev, void *addr)
+int lbs_set_mac_address(struct net_device *dev, void *addr)
 {
 	int ret = 0;
 	struct lbs_private *priv = dev->ml_priv;
@@ -600,7 +402,7 @@
 	lbs_deb_leave(LBS_DEB_NET);
 }
 
-static void lbs_set_multicast_list(struct net_device *dev)
+void lbs_set_multicast_list(struct net_device *dev)
 {
 	struct lbs_private *priv = dev->ml_priv;
 
@@ -1177,7 +980,6 @@
 
 
 	priv->card = card;
-	priv->mesh_open = 0;
 	priv->infra_open = 0;
 
 
@@ -1198,6 +1000,7 @@
 	INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
 	INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker);
 
+	priv->mesh_open = 0;
 	sprintf(priv->mesh_ssid, "mesh");
 	priv->mesh_ssid_len = 4;
 
@@ -1292,50 +1095,12 @@
 
 	lbs_update_channel(priv);
 
-	/* Check mesh FW version and appropriately send the mesh start
-	 * command
+	/*
+	 * While rtap isn't related to mesh, only mesh-enabled
+	 * firmware implements the rtap functionality via
+	 * CMD_802_11_MONITOR_MODE.
 	 */
-	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
-		   but we check them in that order because 20.pXX doesn't
-		   give an error -- it just silently fails. */
-
-		/* 5.110.20.pXX firmware will fail the command if the channel
-		   doesn't match the existing channel. But only if the TLV
-		   is correct. If the channel is wrong, _BOTH_ versions will
-		   give an error to 0x100+291, and allow 0x100+37 to succeed.
-		   It's just that 5.110.20.pXX will not have done anything
-		   useful */
-
-		priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
-		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-				    priv->channel)) {
-			priv->mesh_tlv = TLV_TYPE_MESH_ID;
-			if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-					    priv->channel))
-				priv->mesh_tlv = 0;
-		}
-	} 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->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 (lbs_init_mesh(priv)) {
 		if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
 			lbs_pr_err("cannot register lbs_rtap attribute\n");
 	}
@@ -1369,10 +1134,8 @@
 	netif_carrier_off(dev);
 
 	lbs_debugfs_remove_one(priv);
-	if (priv->mesh_tlv) {
-		device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
+	if (lbs_deinit_mesh(priv))
 		device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
-	}
 
 	/* Delete the timeout of the currently processing command */
 	del_timer_sync(&priv->command_timer);
@@ -1405,95 +1168,6 @@
 EXPORT_SYMBOL_GPL(lbs_stop_card);
 
 
-static const struct net_device_ops mesh_netdev_ops = {
-	.ndo_open		= lbs_dev_open,
-	.ndo_stop 		= lbs_mesh_stop,
-	.ndo_start_xmit		= lbs_hard_start_xmit,
-	.ndo_set_mac_address	= lbs_set_mac_address,
-	.ndo_set_multicast_list = lbs_set_multicast_list,
-};
-
-/**
- * @brief This function adds mshX interface
- *
- *  @param priv    A pointer to the struct lbs_private structure
- *  @return 	   0 if successful, -X otherwise
- */
-static int lbs_add_mesh(struct lbs_private *priv)
-{
-	struct net_device *mesh_dev = NULL;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_MESH);
-
-	/* Allocate a virtual mesh device */
-	if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) {
-		lbs_deb_mesh("init mshX device failed\n");
-		ret = -ENOMEM;
-		goto done;
-	}
-	mesh_dev->ml_priv = priv;
-	priv->mesh_dev = mesh_dev;
-
-	mesh_dev->netdev_ops = &mesh_netdev_ops;
-	mesh_dev->ethtool_ops = &lbs_ethtool_ops;
-	memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,
-			sizeof(priv->dev->dev_addr));
-
-	SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
-
-#ifdef	WIRELESS_EXT
-	mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def;
-#endif
-	mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
-	/* Register virtual mesh interface */
-	ret = register_netdev(mesh_dev);
-	if (ret) {
-		lbs_pr_err("cannot register mshX virtual interface\n");
-		goto err_free;
-	}
-
-	ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
-	if (ret)
-		goto err_unregister;
-
-	lbs_persist_config_init(mesh_dev);
-
-	/* Everything successful */
-	ret = 0;
-	goto done;
-
-err_unregister:
-	unregister_netdev(mesh_dev);
-
-err_free:
-	free_netdev(mesh_dev);
-
-done:
-	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
-	return ret;
-}
-
-static void lbs_remove_mesh(struct lbs_private *priv)
-{
-	struct net_device *mesh_dev;
-
-
-	mesh_dev = priv->mesh_dev;
-	if (!mesh_dev)
-		return;
-
-	lbs_deb_enter(LBS_DEB_MESH);
-	netif_stop_queue(mesh_dev);
-	netif_carrier_off(mesh_dev);
-	sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
-	lbs_persist_config_remove(mesh_dev);
-	unregister_netdev(mesh_dev);
-	priv->mesh_dev = NULL;
-	free_netdev(mesh_dev);
-	lbs_deb_leave(LBS_DEB_MESH);
-}
-
 void lbs_queue_event(struct lbs_private *priv, u32 event)
 {
 	unsigned long flags;
--- linux-wl.orig/drivers/net/wireless/libertas/persistcfg.c
+++ linux-wl/drivers/net/wireless/libertas/persistcfg.c
@@ -6,15 +6,444 @@
 #include <linux/kthread.h>
 #include <linux/kfifo.h>
 
-#include "host.h"
+#include "mesh.h"
 #include "decl.h"
-#include "dev.h"
-#include "wext.h"
-#include "debugfs.h"
-#include "scan.h"
-#include "assoc.h"
 #include "cmd.h"
 
+
+/***************************************************************************
+ * Mesh sysfs support
+ */
+
+/**
+ * Attributes exported through sysfs
+ */
+
+/**
+ * @brief Get function for sysfs attribute anycast_mask
+ */
+static ssize_t lbs_anycast_get(struct device *dev,
+		struct device_attribute *attr, char * buf)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_access mesh_access;
+	int ret;
+
+	memset(&mesh_access, 0, sizeof(mesh_access));
+
+	ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access);
+	if (ret)
+		return ret;
+
+	return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
+}
+
+/**
+ * @brief Set function for sysfs attribute anycast_mask
+ */
+static ssize_t lbs_anycast_set(struct device *dev,
+		struct device_attribute *attr, const char * buf, size_t count)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_access mesh_access;
+	uint32_t datum;
+	int ret;
+
+	memset(&mesh_access, 0, sizeof(mesh_access));
+	sscanf(buf, "%x", &datum);
+	mesh_access.data[0] = cpu_to_le32(datum);
+
+	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access);
+	if (ret)
+		return ret;
+
+	return strlen(buf);
+}
+
+/**
+ * @brief Get function for sysfs attribute prb_rsp_limit
+ */
+static ssize_t lbs_prb_rsp_limit_get(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_access mesh_access;
+	int ret;
+	u32 retry_limit;
+
+	memset(&mesh_access, 0, sizeof(mesh_access));
+	mesh_access.data[0] = cpu_to_le32(CMD_ACT_GET);
+
+	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
+			&mesh_access);
+	if (ret)
+		return ret;
+
+	retry_limit = le32_to_cpu(mesh_access.data[1]);
+	return snprintf(buf, 10, "%d\n", retry_limit);
+}
+
+/**
+ * @brief Set function for sysfs attribute prb_rsp_limit
+ */
+static ssize_t lbs_prb_rsp_limit_set(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_access mesh_access;
+	int ret;
+	unsigned long retry_limit;
+
+	memset(&mesh_access, 0, sizeof(mesh_access));
+	mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET);
+
+	if (!strict_strtoul(buf, 10, &retry_limit))
+		return -ENOTSUPP;
+	if (retry_limit > 15)
+		return -ENOTSUPP;
+
+	mesh_access.data[1] = cpu_to_le32(retry_limit);
+
+	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
+			&mesh_access);
+	if (ret)
+		return ret;
+
+	return strlen(buf);
+}
+
+/**
+ * Get function for sysfs attribute mesh
+ */
+static ssize_t lbs_mesh_get(struct device *dev,
+		struct device_attribute *attr, char * buf)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev);
+}
+
+/**
+ *  Set function for sysfs attribute mesh
+ */
+static ssize_t lbs_mesh_set(struct device *dev,
+		struct device_attribute *attr, const char * buf, size_t count)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	int enable;
+	int ret, action = CMD_ACT_MESH_CONFIG_STOP;
+
+	sscanf(buf, "%x", &enable);
+	enable = !!enable;
+	if (enable == !!priv->mesh_dev)
+		return count;
+	if (enable)
+		action = CMD_ACT_MESH_CONFIG_START;
+	ret = lbs_mesh_config(priv, action, priv->channel);
+	if (ret)
+		return ret;
+
+	if (enable)
+		lbs_add_mesh(priv);
+	else
+		lbs_remove_mesh(priv);
+
+	return count;
+}
+
+/**
+ * lbs_mesh attribute to be exported per ethX interface
+ * through sysfs (/sys/class/net/ethX/lbs_mesh)
+ */
+static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set);
+
+/**
+ * anycast_mask attribute to be exported per mshX interface
+ * through sysfs (/sys/class/net/mshX/anycast_mask)
+ */
+static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set);
+
+/**
+ * prb_rsp_limit attribute to be exported per mshX interface
+ * through sysfs (/sys/class/net/mshX/prb_rsp_limit)
+ */
+static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get,
+		lbs_prb_rsp_limit_set);
+
+static struct attribute *lbs_mesh_sysfs_entries[] = {
+	&dev_attr_anycast_mask.attr,
+	&dev_attr_prb_rsp_limit.attr,
+	NULL,
+};
+
+static struct attribute_group lbs_mesh_attr_group = {
+	.attrs = lbs_mesh_sysfs_entries,
+};
+
+
+
+/***************************************************************************
+ * Initializing and starting, stopping mesh
+ */
+
+/*
+ * Check mesh FW version and appropriately send the mesh start
+ * command
+ */
+int lbs_init_mesh(struct lbs_private *priv)
+{
+	struct net_device *dev = priv->dev;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+
+	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
+		   but we check them in that order because 20.pXX doesn't
+		   give an error -- it just silently fails. */
+
+		/* 5.110.20.pXX firmware will fail the command if the channel
+		   doesn't match the existing channel. But only if the TLV
+		   is correct. If the channel is wrong, _BOTH_ versions will
+		   give an error to 0x100+291, and allow 0x100+37 to succeed.
+		   It's just that 5.110.20.pXX will not have done anything
+		   useful */
+
+		priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
+		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+				    priv->channel)) {
+			priv->mesh_tlv = TLV_TYPE_MESH_ID;
+			if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+					    priv->channel))
+				priv->mesh_tlv = 0;
+		}
+	} 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->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");
+
+		ret = 1;
+	}
+
+	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+	return ret;
+}
+
+
+int lbs_deinit_mesh(struct lbs_private *priv)
+{
+	struct net_device *dev = priv->dev;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+
+	if (priv->mesh_tlv) {
+		device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
+		ret = 1;
+	}
+
+	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+	return ret;
+}
+
+
+/**
+ *  @brief This function closes the mshX interface
+ *
+ *  @param dev     A pointer to net_device structure
+ *  @return 	   0
+ */
+static int lbs_mesh_stop(struct net_device *dev)
+{
+	struct lbs_private *priv = dev->ml_priv;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+	spin_lock_irq(&priv->driver_lock);
+
+	priv->mesh_open = 0;
+	priv->mesh_connect_status = LBS_DISCONNECTED;
+
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+
+	spin_unlock_irq(&priv->driver_lock);
+
+	schedule_work(&priv->mcast_work);
+
+	lbs_deb_leave(LBS_DEB_MESH);
+	return 0;
+}
+
+/**
+ *  @brief This function opens the mshX interface
+ *
+ *  @param dev     A pointer to net_device structure
+ *  @return 	   0 or -EBUSY if monitor mode active
+ */
+static int lbs_mesh_dev_open(struct net_device *dev)
+{
+	struct lbs_private *priv = dev->ml_priv;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_NET);
+
+	spin_lock_irq(&priv->driver_lock);
+
+	if (priv->monitormode) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	priv->mesh_open = 1;
+	priv->mesh_connect_status = LBS_CONNECTED;
+	netif_carrier_on(dev);
+
+	if (!priv->tx_pending_len)
+		netif_wake_queue(dev);
+ out:
+
+	spin_unlock_irq(&priv->driver_lock);
+	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+	return ret;
+}
+
+static const struct net_device_ops mesh_netdev_ops = {
+	.ndo_open		= lbs_mesh_dev_open,
+	.ndo_stop 		= lbs_mesh_stop,
+	.ndo_start_xmit		= lbs_hard_start_xmit,
+	.ndo_set_mac_address	= lbs_set_mac_address,
+	.ndo_set_multicast_list = lbs_set_multicast_list,
+};
+
+/**
+ * @brief This function adds mshX interface
+ *
+ *  @param priv    A pointer to the struct lbs_private structure
+ *  @return 	   0 if successful, -X otherwise
+ */
+int lbs_add_mesh(struct lbs_private *priv)
+{
+	struct net_device *mesh_dev = NULL;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+
+	/* Allocate a virtual mesh device */
+	mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
+	if (!mesh_dev) {
+		lbs_deb_mesh("init mshX device failed\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	mesh_dev->ml_priv = priv;
+	priv->mesh_dev = mesh_dev;
+
+	mesh_dev->netdev_ops = &mesh_netdev_ops;
+	mesh_dev->ethtool_ops = &lbs_ethtool_ops;
+	memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,
+			sizeof(priv->dev->dev_addr));
+
+	SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
+
+#ifdef	WIRELESS_EXT
+	mesh_dev->wireless_handlers = &mesh_handler_def;
+#endif
+	mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+	/* Register virtual mesh interface */
+	ret = register_netdev(mesh_dev);
+	if (ret) {
+		lbs_pr_err("cannot register mshX virtual interface\n");
+		goto err_free;
+	}
+
+	ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
+	if (ret)
+		goto err_unregister;
+
+	lbs_persist_config_init(mesh_dev);
+
+	/* Everything successful */
+	ret = 0;
+	goto done;
+
+err_unregister:
+	unregister_netdev(mesh_dev);
+
+err_free:
+	free_netdev(mesh_dev);
+
+done:
+	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+	return ret;
+}
+
+void lbs_remove_mesh(struct lbs_private *priv)
+{
+	struct net_device *mesh_dev;
+
+	mesh_dev = priv->mesh_dev;
+	if (!mesh_dev)
+		return;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+	netif_stop_queue(mesh_dev);
+	netif_carrier_off(mesh_dev);
+	sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
+	lbs_persist_config_remove(mesh_dev);
+	unregister_netdev(mesh_dev);
+	priv->mesh_dev = NULL;
+	free_netdev(mesh_dev);
+	lbs_deb_leave(LBS_DEB_MESH);
+}
+
+
+
+/***************************************************************************
+ * Sending and receiving
+ */
+struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
+	struct net_device *dev, struct rxpd *rxpd)
+{
+	if (priv->mesh_dev) {
+		if (priv->mesh_fw_ver == MESH_FW_OLD) {
+			if (rxpd->rx_control & RxPD_MESH_FRAME)
+				dev = priv->mesh_dev;
+		} else if (priv->mesh_fw_ver == MESH_FW_NEW) {
+			if (rxpd->u.bss.bss_num == MESH_IFACE_ID)
+				dev = priv->mesh_dev;
+		}
+	}
+	return dev;
+}
+
+
+void lbs_mesh_set_txpd(struct lbs_private *priv,
+	struct net_device *dev, struct txpd *txpd)
+{
+	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;
+	}
+}
+
+
+/***************************************************************************
+ * Persistent configuration support
+ */
+
 static int mesh_get_default_parameters(struct device *dev,
 				       struct mrvl_mesh_defaults *defs)
 {
--- linux-wl.orig/drivers/net/wireless/libertas/mesh.h
+++ linux-wl/drivers/net/wireless/libertas/mesh.h
@@ -22,10 +22,34 @@
 
 
 struct net_device;
+struct lbs_private;
+
+int lbs_init_mesh(struct lbs_private *priv);
+int lbs_deinit_mesh(struct lbs_private *priv);
+
+int lbs_add_mesh(struct lbs_private *priv);
+void lbs_remove_mesh(struct lbs_private *priv);
+
+
+/* Sending / Receiving */
+
+struct rxpd;
+struct txpd;
+
+struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
+	struct net_device *dev, struct rxpd *rxpd);
+void lbs_mesh_set_txpd(struct lbs_private *priv,
+	struct net_device *dev, struct txpd *txpd);
+
+
+/* Persistent configuration */
 
 void lbs_persist_config_init(struct net_device *net);
 void lbs_persist_config_remove(struct net_device *net);
 
+
+/* WEXT handler */
+
 extern struct iw_handler_def mesh_handler_def;
 
 
--- linux-wl.orig/drivers/net/wireless/libertas/decl.h
+++ linux-wl/drivers/net/wireless/libertas/decl.h
@@ -34,6 +34,9 @@
 void lbs_stop_card(struct lbs_private *priv);
 void lbs_host_to_card_done(struct lbs_private *priv);
 
+int lbs_set_mac_address(struct net_device *dev, void *addr);
+void lbs_set_multicast_list(struct net_device *dev);
+
 int lbs_suspend(struct lbs_private *priv);
 void lbs_resume(struct lbs_private *priv);
 
--- linux-wl.orig/drivers/net/wireless/libertas/rx.c
+++ linux-wl/drivers/net/wireless/libertas/rx.c
@@ -160,15 +160,8 @@
 	p_rx_pd = (struct rxpd *) skb->data;
 	p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd +
 		le32_to_cpu(p_rx_pd->pkt_ptr));
-	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;
-		}
-	}
+
+	dev = lbs_mesh_set_dev(priv, dev, p_rx_pd);
 
 	lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data,
 		 min_t(unsigned int, skb->len, 100));
--- linux-wl.orig/drivers/net/wireless/libertas/tx.c
+++ linux-wl/drivers/net/wireless/libertas/tx.c
@@ -131,12 +131,7 @@
 	txpd->tx_packet_length = cpu_to_le16(pkt_len);
 	txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
 
-	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_mesh_set_txpd(priv, dev, txpd);
 
 	lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd));
 

^ permalink raw reply

* [PATCH] libertas: initial move of mesh related functions into persistcfg.c
From: Holger Schurig @ 2009-10-26 15:22 UTC (permalink / raw)
  To: linux-wireless, Dan Williams, John Linville

This moves mesh initialization, start/stop and rx/tx handling from
the respective *.c files into persistcfg.c.

Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de>

--- linux-wl.orig/drivers/net/wireless/libertas/main.c
+++ linux-wl/drivers/net/wireless/libertas/main.c
@@ -94,107 +94,9 @@
 	return 0;
 }
 
-/**
- * Attributes exported through sysfs
- */
-
-/**
- * @brief Get function for sysfs attribute anycast_mask
- */
-static ssize_t lbs_anycast_get(struct device *dev,
-		struct device_attribute *attr, char * buf)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_access mesh_access;
-	int ret;
-
-	memset(&mesh_access, 0, sizeof(mesh_access));
-
-	ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access);
-	if (ret)
-		return ret;
-
-	return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
-}
-
-/**
- * @brief Set function for sysfs attribute anycast_mask
- */
-static ssize_t lbs_anycast_set(struct device *dev,
-		struct device_attribute *attr, const char * buf, size_t count)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_access mesh_access;
-	uint32_t datum;
-	int ret;
-
-	memset(&mesh_access, 0, sizeof(mesh_access));
-	sscanf(buf, "%x", &datum);
-	mesh_access.data[0] = cpu_to_le32(datum);
-
-	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access);
-	if (ret)
-		return ret;
-
-	return strlen(buf);
-}
-
-/**
- * @brief Get function for sysfs attribute prb_rsp_limit
- */
-static ssize_t lbs_prb_rsp_limit_get(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_access mesh_access;
-	int ret;
-	u32 retry_limit;
-
-	memset(&mesh_access, 0, sizeof(mesh_access));
-	mesh_access.data[0] = cpu_to_le32(CMD_ACT_GET);
-
-	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
-			&mesh_access);
-	if (ret)
-		return ret;
-
-	retry_limit = le32_to_cpu(mesh_access.data[1]);
-	return snprintf(buf, 10, "%d\n", retry_limit);
-}
-
-/**
- * @brief Set function for sysfs attribute prb_rsp_limit
- */
-static ssize_t lbs_prb_rsp_limit_set(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_access mesh_access;
-	int ret;
-	unsigned long retry_limit;
-
-	memset(&mesh_access, 0, sizeof(mesh_access));
-	mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET);
-
-	if (!strict_strtoul(buf, 10, &retry_limit))
-		return -ENOTSUPP;
-	if (retry_limit > 15)
-		return -ENOTSUPP;
-
-	mesh_access.data[1] = cpu_to_le32(retry_limit);
-
-	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
-			&mesh_access);
-	if (ret)
-		return ret;
-
-	return strlen(buf);
-}
 
 static int lbs_add_rtap(struct lbs_private *priv);
 static void lbs_remove_rtap(struct lbs_private *priv);
-static int lbs_add_mesh(struct lbs_private *priv);
-static void lbs_remove_mesh(struct lbs_private *priv);
 
 
 /**
@@ -260,74 +162,7 @@
 static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set );
 
 /**
- * Get function for sysfs attribute mesh
- */
-static ssize_t lbs_mesh_get(struct device *dev,
-		struct device_attribute *attr, char * buf)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev);
-}
-
-/**
- *  Set function for sysfs attribute mesh
- */
-static ssize_t lbs_mesh_set(struct device *dev,
-		struct device_attribute *attr, const char * buf, size_t count)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	int enable;
-	int ret, action = CMD_ACT_MESH_CONFIG_STOP;
-
-	sscanf(buf, "%x", &enable);
-	enable = !!enable;
-	if (enable == !!priv->mesh_dev)
-		return count;
-	if (enable)
-		action = CMD_ACT_MESH_CONFIG_START;
-	ret = lbs_mesh_config(priv, action, priv->channel);
-	if (ret)
-		return ret;
-
-	if (enable)
-		lbs_add_mesh(priv);
-	else
-		lbs_remove_mesh(priv);
-
-	return count;
-}
-
-/**
- * lbs_mesh attribute to be exported per ethX interface
- * through sysfs (/sys/class/net/ethX/lbs_mesh)
- */
-static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set);
-
-/**
- * anycast_mask attribute to be exported per mshX interface
- * through sysfs (/sys/class/net/mshX/anycast_mask)
- */
-static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set);
-
-/**
- * prb_rsp_limit attribute to be exported per mshX interface
- * through sysfs (/sys/class/net/mshX/prb_rsp_limit)
- */
-static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get,
-		lbs_prb_rsp_limit_set);
-
-static struct attribute *lbs_mesh_sysfs_entries[] = {
-	&dev_attr_anycast_mask.attr,
-	&dev_attr_prb_rsp_limit.attr,
-	NULL,
-};
-
-static struct attribute_group lbs_mesh_attr_group = {
-	.attrs = lbs_mesh_sysfs_entries,
-};
-
-/**
- *  @brief This function opens the ethX or mshX interface
+ *  @brief This function opens the ethX interface
  *
  *  @param dev     A pointer to net_device structure
  *  @return 	   0 or -EBUSY if monitor mode active
@@ -346,18 +181,12 @@
 		goto out;
 	}
 
-	if (dev == priv->mesh_dev) {
-		priv->mesh_open = 1;
-		priv->mesh_connect_status = LBS_CONNECTED;
-		netif_carrier_on(dev);
-	} else {
-		priv->infra_open = 1;
+	priv->infra_open = 1;
 
-		if (priv->connect_status == LBS_CONNECTED)
-			netif_carrier_on(dev);
-		else
-			netif_carrier_off(dev);
-	}
+	if (priv->connect_status == LBS_CONNECTED)
+		netif_carrier_on(dev);
+	else
+		netif_carrier_off(dev);
 
 	if (!priv->tx_pending_len)
 		netif_wake_queue(dev);
@@ -369,33 +198,6 @@
 }
 
 /**
- *  @brief This function closes the mshX interface
- *
- *  @param dev     A pointer to net_device structure
- *  @return 	   0
- */
-static int lbs_mesh_stop(struct net_device *dev)
-{
-	struct lbs_private *priv = dev->ml_priv;
-
-	lbs_deb_enter(LBS_DEB_MESH);
-	spin_lock_irq(&priv->driver_lock);
-
-	priv->mesh_open = 0;
-	priv->mesh_connect_status = LBS_DISCONNECTED;
-
-	netif_stop_queue(dev);
-	netif_carrier_off(dev);
-
-	spin_unlock_irq(&priv->driver_lock);
-
-	schedule_work(&priv->mcast_work);
-
-	lbs_deb_leave(LBS_DEB_MESH);
-	return 0;
-}
-
-/**
  *  @brief This function closes the ethX interface
  *
  *  @param dev     A pointer to net_device structure
@@ -466,7 +268,7 @@
 }
 EXPORT_SYMBOL_GPL(lbs_host_to_card_done);
 
-static int lbs_set_mac_address(struct net_device *dev, void *addr)
+int lbs_set_mac_address(struct net_device *dev, void *addr)
 {
 	int ret = 0;
 	struct lbs_private *priv = dev->ml_priv;
@@ -600,7 +402,7 @@
 	lbs_deb_leave(LBS_DEB_NET);
 }
 
-static void lbs_set_multicast_list(struct net_device *dev)
+void lbs_set_multicast_list(struct net_device *dev)
 {
 	struct lbs_private *priv = dev->ml_priv;
 
@@ -1177,7 +979,6 @@
 
 
 	priv->card = card;
-	priv->mesh_open = 0;
 	priv->infra_open = 0;
 
 
@@ -1198,6 +999,7 @@
 	INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
 	INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker);
 
+	priv->mesh_open = 0;
 	sprintf(priv->mesh_ssid, "mesh");
 	priv->mesh_ssid_len = 4;
 
@@ -1292,50 +1094,12 @@
 
 	lbs_update_channel(priv);
 
-	/* Check mesh FW version and appropriately send the mesh start
-	 * command
+	/*
+	 * While rtap isn't related to mesh, only mesh-enabled
+	 * firmware implements the rtap functionality via
+	 * CMD_802_11_MONITOR_MODE.
 	 */
-	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
-		   but we check them in that order because 20.pXX doesn't
-		   give an error -- it just silently fails. */
-
-		/* 5.110.20.pXX firmware will fail the command if the channel
-		   doesn't match the existing channel. But only if the TLV
-		   is correct. If the channel is wrong, _BOTH_ versions will
-		   give an error to 0x100+291, and allow 0x100+37 to succeed.
-		   It's just that 5.110.20.pXX will not have done anything
-		   useful */
-
-		priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
-		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-				    priv->channel)) {
-			priv->mesh_tlv = TLV_TYPE_MESH_ID;
-			if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-					    priv->channel))
-				priv->mesh_tlv = 0;
-		}
-	} 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->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 (lbs_init_mesh(priv)) {
 		if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
 			lbs_pr_err("cannot register lbs_rtap attribute\n");
 	}
@@ -1369,10 +1133,8 @@
 	netif_carrier_off(dev);
 
 	lbs_debugfs_remove_one(priv);
-	if (priv->mesh_tlv) {
-		device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
+	if (lbs_deinit_mesh(priv))
 		device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
-	}
 
 	/* Delete the timeout of the currently processing command */
 	del_timer_sync(&priv->command_timer);
@@ -1405,95 +1167,6 @@
 EXPORT_SYMBOL_GPL(lbs_stop_card);
 
 
-static const struct net_device_ops mesh_netdev_ops = {
-	.ndo_open		= lbs_dev_open,
-	.ndo_stop 		= lbs_mesh_stop,
-	.ndo_start_xmit		= lbs_hard_start_xmit,
-	.ndo_set_mac_address	= lbs_set_mac_address,
-	.ndo_set_multicast_list = lbs_set_multicast_list,
-};
-
-/**
- * @brief This function adds mshX interface
- *
- *  @param priv    A pointer to the struct lbs_private structure
- *  @return 	   0 if successful, -X otherwise
- */
-static int lbs_add_mesh(struct lbs_private *priv)
-{
-	struct net_device *mesh_dev = NULL;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_MESH);
-
-	/* Allocate a virtual mesh device */
-	if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) {
-		lbs_deb_mesh("init mshX device failed\n");
-		ret = -ENOMEM;
-		goto done;
-	}
-	mesh_dev->ml_priv = priv;
-	priv->mesh_dev = mesh_dev;
-
-	mesh_dev->netdev_ops = &mesh_netdev_ops;
-	mesh_dev->ethtool_ops = &lbs_ethtool_ops;
-	memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,
-			sizeof(priv->dev->dev_addr));
-
-	SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
-
-#ifdef	WIRELESS_EXT
-	mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def;
-#endif
-	mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
-	/* Register virtual mesh interface */
-	ret = register_netdev(mesh_dev);
-	if (ret) {
-		lbs_pr_err("cannot register mshX virtual interface\n");
-		goto err_free;
-	}
-
-	ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
-	if (ret)
-		goto err_unregister;
-
-	lbs_persist_config_init(mesh_dev);
-
-	/* Everything successful */
-	ret = 0;
-	goto done;
-
-err_unregister:
-	unregister_netdev(mesh_dev);
-
-err_free:
-	free_netdev(mesh_dev);
-
-done:
-	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
-	return ret;
-}
-
-static void lbs_remove_mesh(struct lbs_private *priv)
-{
-	struct net_device *mesh_dev;
-
-
-	mesh_dev = priv->mesh_dev;
-	if (!mesh_dev)
-		return;
-
-	lbs_deb_enter(LBS_DEB_MESH);
-	netif_stop_queue(mesh_dev);
-	netif_carrier_off(mesh_dev);
-	sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
-	lbs_persist_config_remove(mesh_dev);
-	unregister_netdev(mesh_dev);
-	priv->mesh_dev = NULL;
-	free_netdev(mesh_dev);
-	lbs_deb_leave(LBS_DEB_MESH);
-}
-
 void lbs_queue_event(struct lbs_private *priv, u32 event)
 {
 	unsigned long flags;
--- linux-wl.orig/drivers/net/wireless/libertas/persistcfg.c
+++ linux-wl/drivers/net/wireless/libertas/persistcfg.c
@@ -6,15 +6,444 @@
 #include <linux/kthread.h>
 #include <linux/kfifo.h>
 
-#include "host.h"
+#include "mesh.h"
 #include "decl.h"
-#include "dev.h"
-#include "wext.h"
-#include "debugfs.h"
-#include "scan.h"
-#include "assoc.h"
 #include "cmd.h"
 
+
+/***************************************************************************
+ * Mesh sysfs support
+ */
+
+/**
+ * Attributes exported through sysfs
+ */
+
+/**
+ * @brief Get function for sysfs attribute anycast_mask
+ */
+static ssize_t lbs_anycast_get(struct device *dev,
+		struct device_attribute *attr, char * buf)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_access mesh_access;
+	int ret;
+
+	memset(&mesh_access, 0, sizeof(mesh_access));
+
+	ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access);
+	if (ret)
+		return ret;
+
+	return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
+}
+
+/**
+ * @brief Set function for sysfs attribute anycast_mask
+ */
+static ssize_t lbs_anycast_set(struct device *dev,
+		struct device_attribute *attr, const char * buf, size_t count)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_access mesh_access;
+	uint32_t datum;
+	int ret;
+
+	memset(&mesh_access, 0, sizeof(mesh_access));
+	sscanf(buf, "%x", &datum);
+	mesh_access.data[0] = cpu_to_le32(datum);
+
+	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access);
+	if (ret)
+		return ret;
+
+	return strlen(buf);
+}
+
+/**
+ * @brief Get function for sysfs attribute prb_rsp_limit
+ */
+static ssize_t lbs_prb_rsp_limit_get(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_access mesh_access;
+	int ret;
+	u32 retry_limit;
+
+	memset(&mesh_access, 0, sizeof(mesh_access));
+	mesh_access.data[0] = cpu_to_le32(CMD_ACT_GET);
+
+	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
+			&mesh_access);
+	if (ret)
+		return ret;
+
+	retry_limit = le32_to_cpu(mesh_access.data[1]);
+	return snprintf(buf, 10, "%d\n", retry_limit);
+}
+
+/**
+ * @brief Set function for sysfs attribute prb_rsp_limit
+ */
+static ssize_t lbs_prb_rsp_limit_set(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_access mesh_access;
+	int ret;
+	unsigned long retry_limit;
+
+	memset(&mesh_access, 0, sizeof(mesh_access));
+	mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET);
+
+	if (!strict_strtoul(buf, 10, &retry_limit))
+		return -ENOTSUPP;
+	if (retry_limit > 15)
+		return -ENOTSUPP;
+
+	mesh_access.data[1] = cpu_to_le32(retry_limit);
+
+	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
+			&mesh_access);
+	if (ret)
+		return ret;
+
+	return strlen(buf);
+}
+
+/**
+ * Get function for sysfs attribute mesh
+ */
+static ssize_t lbs_mesh_get(struct device *dev,
+		struct device_attribute *attr, char * buf)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev);
+}
+
+/**
+ *  Set function for sysfs attribute mesh
+ */
+static ssize_t lbs_mesh_set(struct device *dev,
+		struct device_attribute *attr, const char * buf, size_t count)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	int enable;
+	int ret, action = CMD_ACT_MESH_CONFIG_STOP;
+
+	sscanf(buf, "%x", &enable);
+	enable = !!enable;
+	if (enable == !!priv->mesh_dev)
+		return count;
+	if (enable)
+		action = CMD_ACT_MESH_CONFIG_START;
+	ret = lbs_mesh_config(priv, action, priv->channel);
+	if (ret)
+		return ret;
+
+	if (enable)
+		lbs_add_mesh(priv);
+	else
+		lbs_remove_mesh(priv);
+
+	return count;
+}
+
+/**
+ * lbs_mesh attribute to be exported per ethX interface
+ * through sysfs (/sys/class/net/ethX/lbs_mesh)
+ */
+static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set);
+
+/**
+ * anycast_mask attribute to be exported per mshX interface
+ * through sysfs (/sys/class/net/mshX/anycast_mask)
+ */
+static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set);
+
+/**
+ * prb_rsp_limit attribute to be exported per mshX interface
+ * through sysfs (/sys/class/net/mshX/prb_rsp_limit)
+ */
+static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get,
+		lbs_prb_rsp_limit_set);
+
+static struct attribute *lbs_mesh_sysfs_entries[] = {
+	&dev_attr_anycast_mask.attr,
+	&dev_attr_prb_rsp_limit.attr,
+	NULL,
+};
+
+static struct attribute_group lbs_mesh_attr_group = {
+	.attrs = lbs_mesh_sysfs_entries,
+};
+
+
+
+/***************************************************************************
+ * Initializing and starting, stopping mesh
+ */
+
+/*
+ * Check mesh FW version and appropriately send the mesh start
+ * command
+ */
+int lbs_init_mesh(struct lbs_private *priv)
+{
+	struct net_device *dev = priv->dev;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+
+	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
+		   but we check them in that order because 20.pXX doesn't
+		   give an error -- it just silently fails. */
+
+		/* 5.110.20.pXX firmware will fail the command if the channel
+		   doesn't match the existing channel. But only if the TLV
+		   is correct. If the channel is wrong, _BOTH_ versions will
+		   give an error to 0x100+291, and allow 0x100+37 to succeed.
+		   It's just that 5.110.20.pXX will not have done anything
+		   useful */
+
+		priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
+		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+				    priv->channel)) {
+			priv->mesh_tlv = TLV_TYPE_MESH_ID;
+			if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+					    priv->channel))
+				priv->mesh_tlv = 0;
+		}
+	} 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->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");
+
+		ret = 1;
+	}
+
+	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+	return ret;
+}
+
+
+int lbs_deinit_mesh(struct lbs_private *priv)
+{
+	struct net_device *dev = priv->dev;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+
+	if (priv->mesh_tlv) {
+		device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
+		ret = 1;
+	}
+
+	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+	return ret;
+}
+
+
+/**
+ *  @brief This function closes the mshX interface
+ *
+ *  @param dev     A pointer to net_device structure
+ *  @return 	   0
+ */
+static int lbs_mesh_stop(struct net_device *dev)
+{
+	struct lbs_private *priv = dev->ml_priv;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+	spin_lock_irq(&priv->driver_lock);
+
+	priv->mesh_open = 0;
+	priv->mesh_connect_status = LBS_DISCONNECTED;
+
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+
+	spin_unlock_irq(&priv->driver_lock);
+
+	schedule_work(&priv->mcast_work);
+
+	lbs_deb_leave(LBS_DEB_MESH);
+	return 0;
+}
+
+/**
+ *  @brief This function opens the mshX interface
+ *
+ *  @param dev     A pointer to net_device structure
+ *  @return 	   0 or -EBUSY if monitor mode active
+ */
+static int lbs_mesh_dev_open(struct net_device *dev)
+{
+	struct lbs_private *priv = dev->ml_priv;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_NET);
+
+	spin_lock_irq(&priv->driver_lock);
+
+	if (priv->monitormode) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	priv->mesh_open = 1;
+	priv->mesh_connect_status = LBS_CONNECTED;
+	netif_carrier_on(dev);
+
+	if (!priv->tx_pending_len)
+		netif_wake_queue(dev);
+ out:
+
+	spin_unlock_irq(&priv->driver_lock);
+	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+	return ret;
+}
+
+static const struct net_device_ops mesh_netdev_ops = {
+	.ndo_open		= lbs_mesh_dev_open,
+	.ndo_stop 		= lbs_mesh_stop,
+	.ndo_start_xmit		= lbs_hard_start_xmit,
+	.ndo_set_mac_address	= lbs_set_mac_address,
+	.ndo_set_multicast_list = lbs_set_multicast_list,
+};
+
+/**
+ * @brief This function adds mshX interface
+ *
+ *  @param priv    A pointer to the struct lbs_private structure
+ *  @return 	   0 if successful, -X otherwise
+ */
+int lbs_add_mesh(struct lbs_private *priv)
+{
+	struct net_device *mesh_dev = NULL;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+
+	/* Allocate a virtual mesh device */
+	mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
+	if (!mesh_dev) {
+		lbs_deb_mesh("init mshX device failed\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	mesh_dev->ml_priv = priv;
+	priv->mesh_dev = mesh_dev;
+
+	mesh_dev->netdev_ops = &mesh_netdev_ops;
+	mesh_dev->ethtool_ops = &lbs_ethtool_ops;
+	memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,
+			sizeof(priv->dev->dev_addr));
+
+	SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
+
+#ifdef	WIRELESS_EXT
+	mesh_dev->wireless_handlers = &mesh_handler_def;
+#endif
+	mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+	/* Register virtual mesh interface */
+	ret = register_netdev(mesh_dev);
+	if (ret) {
+		lbs_pr_err("cannot register mshX virtual interface\n");
+		goto err_free;
+	}
+
+	ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
+	if (ret)
+		goto err_unregister;
+
+	lbs_persist_config_init(mesh_dev);
+
+	/* Everything successful */
+	ret = 0;
+	goto done;
+
+err_unregister:
+	unregister_netdev(mesh_dev);
+
+err_free:
+	free_netdev(mesh_dev);
+
+done:
+	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+	return ret;
+}
+
+void lbs_remove_mesh(struct lbs_private *priv)
+{
+	struct net_device *mesh_dev;
+
+	mesh_dev = priv->mesh_dev;
+	if (!mesh_dev)
+		return;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+	netif_stop_queue(mesh_dev);
+	netif_carrier_off(mesh_dev);
+	sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
+	lbs_persist_config_remove(mesh_dev);
+	unregister_netdev(mesh_dev);
+	priv->mesh_dev = NULL;
+	free_netdev(mesh_dev);
+	lbs_deb_leave(LBS_DEB_MESH);
+}
+
+
+
+/***************************************************************************
+ * Sending and receiving
+ */
+struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
+	struct net_device *dev, struct rxpd *rxpd)
+{
+	if (priv->mesh_dev) {
+		if (priv->mesh_fw_ver == MESH_FW_OLD) {
+			if (rxpd->rx_control & RxPD_MESH_FRAME)
+				dev = priv->mesh_dev;
+		} else if (priv->mesh_fw_ver == MESH_FW_NEW) {
+			if (rxpd->u.bss.bss_num == MESH_IFACE_ID)
+				dev = priv->mesh_dev;
+		}
+	}
+	return dev;
+}
+
+
+void lbs_mesh_set_txpd(struct lbs_private *priv,
+	struct net_device *dev, struct txpd *txpd)
+{
+	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;
+	}
+}
+
+
+/***************************************************************************
+ * Persistent configuration support
+ */
+
 static int mesh_get_default_parameters(struct device *dev,
 				       struct mrvl_mesh_defaults *defs)
 {
--- linux-wl.orig/drivers/net/wireless/libertas/mesh.h
+++ linux-wl/drivers/net/wireless/libertas/mesh.h
@@ -22,10 +22,34 @@
 
 
 struct net_device;
+struct lbs_private;
+
+int lbs_init_mesh(struct lbs_private *priv);
+int lbs_deinit_mesh(struct lbs_private *priv);
+
+int lbs_add_mesh(struct lbs_private *priv);
+void lbs_remove_mesh(struct lbs_private *priv);
+
+
+/* Sending / Receiving */
+
+struct rxpd;
+struct txpd;
+
+struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
+	struct net_device *dev, struct rxpd *rxpd);
+void lbs_mesh_set_txpd(struct lbs_private *priv,
+	struct net_device *dev, struct txpd *txpd);
+
+
+/* Persistent configuration */
 
 void lbs_persist_config_init(struct net_device *net);
 void lbs_persist_config_remove(struct net_device *net);
 
+
+/* WEXT handler */
+
 extern struct iw_handler_def mesh_handler_def;
 
 
--- linux-wl.orig/drivers/net/wireless/libertas/Makefile
+++ linux-wl/drivers/net/wireless/libertas/Makefile
@@ -1,14 +1,14 @@
+libertas-y += tx.o
+libertas-y += persistcfg.o
+libertas-y += main.o
+libertas-y += rx.o
 libertas-y += assoc.o
 libertas-y += cfg.o
 libertas-y += cmd.o
 libertas-y += cmdresp.o
 libertas-y += debugfs.o
 libertas-y += ethtool.o
-libertas-y += main.o
-libertas-y += persistcfg.o
-libertas-y += rx.o
 libertas-y += scan.o
-libertas-y += tx.o
 libertas-y += wext.o
 
 usb8xxx-objs += if_usb.o
--- linux-wl.orig/drivers/net/wireless/libertas/decl.h
+++ linux-wl/drivers/net/wireless/libertas/decl.h
@@ -34,6 +34,9 @@
 void lbs_stop_card(struct lbs_private *priv);
 void lbs_host_to_card_done(struct lbs_private *priv);
 
+int lbs_set_mac_address(struct net_device *dev, void *addr);
+void lbs_set_multicast_list(struct net_device *dev);
+
 int lbs_suspend(struct lbs_private *priv);
 void lbs_resume(struct lbs_private *priv);
 
--- linux-wl.orig/drivers/net/wireless/libertas/rx.c
+++ linux-wl/drivers/net/wireless/libertas/rx.c
@@ -160,15 +160,8 @@
 	p_rx_pd = (struct rxpd *) skb->data;
 	p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd +
 		le32_to_cpu(p_rx_pd->pkt_ptr));
-	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;
-		}
-	}
+
+	dev = lbs_mesh_set_dev(priv, dev, p_rx_pd);
 
 	lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data,
 		 min_t(unsigned int, skb->len, 100));
--- linux-wl.orig/drivers/net/wireless/libertas/tx.c
+++ linux-wl/drivers/net/wireless/libertas/tx.c
@@ -131,12 +131,7 @@
 	txpd->tx_packet_length = cpu_to_le16(pkt_len);
 	txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
 
-	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_mesh_set_txpd(priv, dev, txpd);
 
 	lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd));
 

-- 
http://www.holgerschurig.de

^ permalink raw reply

* [PATCH] libertas: introduce mesh.h
From: Holger Schurig @ 2009-10-26 15:21 UTC (permalink / raw)
  To: linux-wireless, Dan Williams, John Linville

Concentrating mesh related code into one file will allow a less 
intrusive CONFIG_LIBERTAS_MESH.

Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de>

---

Dan, John: this is on top of the patch series with the 19 patches
that isolate the WEXT stuff. So please review and ACK/NACK that
first.


Some day later we'll do "git mv persistcfg.c mesh.c"

This will give us the possiblity to easier make a Kconfig entry 
for MESH ...
or to rip it out, should there be no user for it.

--- linux-wl.orig/drivers/net/wireless/libertas/dev.h
+++ linux-wl/drivers/net/wireless/libertas/dev.h
@@ -6,6 +6,7 @@
 #ifndef _LBS_DEV_H_
 #define _LBS_DEV_H_
 
+#include "mesh.h"
 #include "scan.h"
 #include "assoc.h"
 
@@ -21,17 +22,6 @@
 	uint16_t sp_reserved;
 };
 
-/* Mesh statistics */
-struct lbs_mesh_stats {
-	u32	fwd_bcast_cnt;		/* Fwd: Broadcast counter */
-	u32	fwd_unicast_cnt;	/* Fwd: Unicast counter */
-	u32	fwd_drop_ttl;		/* Fwd: TTL zero */
-	u32	fwd_drop_rbt;		/* Fwd: Recently Broadcasted */
-	u32	fwd_drop_noroute; 	/* Fwd: No route to Destination */
-	u32	fwd_drop_nobuf;		/* Fwd: Run out of internal buffers */
-	u32	drop_blind;		/* Rx:  Dropped by blinding table */
-	u32	tx_failed_cnt;		/* Tx:  Failed transmissions */
-};
 
 /** Private structure for the MV device */
 struct lbs_private {
--- /dev/null
+++ linux-wl/drivers/net/wireless/libertas/mesh.h
@@ -0,0 +1,32 @@
+/**
+  * Contains all definitions needed for the Libertas' MESH 
implementation.
+  */
+#ifndef _LBS_MESH_H_
+#define _LBS_MESH_H_
+
+
+#include <net/iw_handler.h>
+
+
+/* Mesh statistics */
+struct lbs_mesh_stats {
+	u32	fwd_bcast_cnt;		/* Fwd: Broadcast counter */
+	u32	fwd_unicast_cnt;	/* Fwd: Unicast counter */
+	u32	fwd_drop_ttl;		/* Fwd: TTL zero */
+	u32	fwd_drop_rbt;		/* Fwd: Recently Broadcasted */
+	u32	fwd_drop_noroute; 	/* Fwd: No route to Destination */
+	u32	fwd_drop_nobuf;		/* Fwd: Run out of internal buffers */
+	u32	drop_blind;		/* Rx:  Dropped by blinding table */
+	u32	tx_failed_cnt;		/* Tx:  Failed transmissions */
+};
+
+
+struct net_device;
+
+void lbs_persist_config_init(struct net_device *net);
+void lbs_persist_config_remove(struct net_device *net);
+
+extern struct iw_handler_def mesh_handler_def;
+
+
+#endif
--- linux-wl.orig/drivers/net/wireless/libertas/decl.h
+++ linux-wl/drivers/net/wireless/libertas/decl.h
@@ -27,11 +27,6 @@
 int lbs_process_rxed_packet(struct lbs_private *priv, struct 
sk_buff *);
 
 
-/* persistcfg.c */
-void lbs_persist_config_init(struct net_device *net);
-void lbs_persist_config_remove(struct net_device *net);
-
-
 /* main.c */
 struct lbs_private *lbs_add_card(void *card, struct device 
*dmdev);
 void lbs_remove_card(struct lbs_private *priv);
--- linux-wl.orig/drivers/net/wireless/libertas/wext.h
+++ linux-wl/drivers/net/wireless/libertas/wext.h
@@ -7,12 +7,11 @@
 void lbs_send_disconnect_notification(struct lbs_private *priv);
 void lbs_send_mic_failureevent(struct lbs_private *priv, u32 
event);
 
-extern struct iw_handler_def lbs_handler_def;
-extern struct iw_handler_def mesh_handler_def;
-
 struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
 	struct lbs_private *priv,
 	u8 band,
 	u16 channel);
 
+extern struct iw_handler_def lbs_handler_def;
+
 #endif

-- 
http://www.holgerschurig.de

^ permalink raw reply

* rtl8187: kernel oops when leds enabled
From: Richard Farina @ 2009-10-26 15:17 UTC (permalink / raw)
  To: linux-wireless

Using kernel 2.6.31 and compat-wireless stable 2.6.32_rc5 I get this 
kernel oops nearly 100% of the time when I unplug the device.  I have 
tried with the device down, up, and while transmitting, here are the 
three oopses.  Sorry it took me so long for this report, it is an odd 
bug.  When I was running older kernel/compat-wireless this oops was 
about 4-5 screens longs so I couldn't take a picture.  Additionally I 
took the advice of a few of the list members to try the crashkernel 
feature (which is AWESOME  btw) but it doesn't work for this oops.  Let 
me be more specific, I can trigger an oops and the crash kernel kicks 
in, but with this oops the crash kernel never kicks in so I am guessing 
this is bad news.

I'm honestly a little surprised that no one has bothered to reproduce 
this in the month since I reported it but maybe it is more unique to my 
setup than it seems.

Hope these pictures are readable enough to be useful.

http://picpaste.com/pics/cimg1470.1256404028.jpg
http://picpaste.com/pics/cimg1474.1256404126.jpg
http://picpaste.com/pics/cimg1477.1256404170.jpg

I can fairly well generate this error at will and I'm available to test 
reproducing the bug in any possible situation which is suggested and/or 
test patches to fix.

Thanks,
Rick


^ permalink raw reply

* Re: Only device wlan1 but no connection Fritz!WLAN USB stick N2.4
From: Luis R. Rodriguez @ 2009-10-26 14:57 UTC (permalink / raw)
  To: Ed Vaessen; +Cc: linux-wireless
In-Reply-To: <e14196febc59d9ca25868fec63816139.squirrel@webmail.xs4all.nl>

On Mon, Oct 26, 2009 at 6:17 AM, Ed Vaessen <evaessen@xs4all.nl> wrote:
> I have a Fritz!Box Fon WLAN 7170 as router and try to connect wireless to
> it with the Fritz!WLAN USB N2.4 stick using the compat-wireless software.
> Without succes so far.

> Oct 25 15:38:38 vaessen-laptop kernel: [ 399.349605] usb 1-1: USB
> disconnect, address 5
> Oct 25 15:38:39 vaessen-laptop kernel: [ 400.608057] usb 1-1: new high
> speed USB device using ehci_hcd and address 6
> Oct 25 15:38:39 vaessen-laptop kernel: [ 400.771795] usb 1-1:
> configuration #1 chosen from 1 choice
> Oct 25 15:38:39 vaessen-laptop kernel: [ 400.888063] usb 1-1: reset high
> speed USB device using ehci_hcd and address 6
> Oct 25 15:38:40 vaessen-laptop kernel: [ 402.044043] usb 1-1: firmware:
> requesting ar9170.fw
> Oct 25 15:38:41 vaessen-laptop kernel: [ 402.465806] Registered led
> device: ar9170-phy1::tx
> Oct 25 15:38:41 vaessen-laptop kernel: [ 402.465846] Registered led
> device: ar9170-phy1::assoc
> Oct 25 15:38:41 vaessen-laptop kernel: [ 402.465851] usb 1-1: Atheros
> AR9170 is registered as 'phy1'
> Oct 25 15:38:41 vaessen-laptop kernel: [ 402.471136] udev: renamed network
> interface wlan0 to wlan1
>
> It seems the firmware is installed.
> Command iwconfig:
>
> lo no wireless extensions.
>
> eth0 no wireless extensions.
>
> pan0 no wireless extensions.
>
> wlan1 IEEE 802.11bg Mode:Managed Access Point: Not-Associated
> Tx-Power=0 dBm
> Retry long limit:7 RTS thrff Fragment thrff
> Power Managementff
>
> Command sudo lshw -C network gives for the wireless this information:
>
> *-network:1 DISABLED
> description: Wireless interface
> physical id: 2
> bus info: usb@1:1
> logical name: wlan1
> serial: 00:1f:3f:09:2d:40
> capabilities: ethernet physical wireless
> configuration: broadcast=yes driver=ar9170usb
> driverversion=2.6.28-16-generic firmware=N/A link=yes multicast=yes
> wireless=IEEE 802.11bg
>
> This 'firmware=N/A' puzzles me.

That's probably from ethtool, and since John added ethtool support all
we would need to do I think is tag the firmware name on the wiphy
struct (wiphy->fw_version). But we haven't added that yet to ar9170.

> I used System->Administration->Network Tools but cannot ping the Fritz!Box
> router
> The interface information says that wireless interface wlan1 is inactive.
>
> How do I make it active?

Bring the interface up first:

ip link set dev wlan1 up

Then use iw to scan for example

  Luis

^ permalink raw reply

* Re: [RFT 00/15] ath9k_hw ar9271 updates & AR5416 force bias
From: John W. Linville @ 2009-10-26 14:41 UTC (permalink / raw)
  To: Luis R. Rodriguez; +Cc: linux-wireless, Sujith, ath9k-devel
In-Reply-To: <43e72e890910260723o58ad4635g4f6bebfa28f673bb@mail.gmail.com>

On Mon, Oct 26, 2009 at 07:23:44AM -0700, Luis R. Rodriguez wrote:
> On Mon, Oct 26, 2009 at 7:19 AM, Luis R. Rodriguez
> <lrodriguez@atheros.com> wrote:
> > On Wed, Oct 21, 2009 at 8:42 PM, Luis R. Rodriguez
> > <lrodriguez@atheros.com> wrote:
> >> On Mon, Oct 19, 2009 at 3:33 PM, Luis R. Rodriguez
> >> <lrodriguez@atheros.com> wrote:
> >>> This series started off to extend support for ar9271 on ath9k_hw
> >>> but after review of the phy related code I noticed a fix for
> >>> AR5416 was only partially being implemented and used for all
> >>> chipsets. This series then adds the changes I've noticed so far
> >>> required for ar9271 but also fixes and completes the orientation
> >>> fix for AR5416 (force bias). Since I'm touching phy.c I also extend
> >>> documentation for it.
> >>>
> >>> I don't have AR9285 cards with me but I do have an AR5416 cardbus
> >>> card -- I'd appreciate it if someone can give this a test on AR9285
> >
> > Alright well I made it back to California and tested an AR9285 and
> > things are peachy so I will submit this now.
> 
> Johh, actually instead of resubmitting can you take these in as-is?
> They should apply on top of the latest tree. Please let me know.

I'm a little buried ATM, but sure -- that'll be fine...

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* [PATCH 1/4] ath9k_hw: move mac name and rf name helpers to hw code
From: Luis R. Rodriguez @ 2009-10-26 14:38 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ath9k-devel, Luis R. Rodriguez
In-Reply-To: <1256567941-26859-1-git-send-email-lrodriguez@atheros.com>

These are shared between ath9k and the future ath9k_htc driver.

Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
---
 drivers/net/wireless/ath/ath9k/ahb.c  |    5 ++-
 drivers/net/wireless/ath/ath9k/hw.c   |   62 +++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/hw.h   |    3 ++
 drivers/net/wireless/ath/ath9k/main.c |   58 ------------------------------
 drivers/net/wireless/ath/ath9k/pci.c  |    5 ++-
 5 files changed, 71 insertions(+), 62 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 25531f2..41422c4 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -137,9 +137,10 @@ static int ath_ahb_probe(struct platform_device *pdev)
 	       "%s: Atheros AR%s MAC/BB Rev:%x, "
 	       "AR%s RF Rev:%x, mem=0x%lx, irq=%d\n",
 	       wiphy_name(hw->wiphy),
-	       ath_mac_bb_name(ah->hw_version.macVersion),
+	       ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
 	       ah->hw_version.macRev,
-	       ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)),
+	       ath9k_hw_rf_name((ah->hw_version.analog5GhzRev &
+				 AR_RADIO_SREV_MAJOR)),
 	       ah->hw_version.phyRev,
 	       (unsigned long)mem, irq);
 
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index db95876..cf543e3 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -3928,3 +3928,65 @@ void ath_gen_timer_isr(struct ath_hw *ah)
 	}
 }
 EXPORT_SYMBOL(ath_gen_timer_isr);
+
+static struct {
+	u32 version;
+	const char * name;
+} ath_mac_bb_names[] = {
+	/* Devices with external radios */
+	{ AR_SREV_VERSION_5416_PCI,	"5416" },
+	{ AR_SREV_VERSION_5416_PCIE,	"5418" },
+	{ AR_SREV_VERSION_9100,		"9100" },
+	{ AR_SREV_VERSION_9160,		"9160" },
+	/* Single-chip solutions */
+	{ AR_SREV_VERSION_9280,		"9280" },
+	{ AR_SREV_VERSION_9285,		"9285" },
+	{ AR_SREV_VERSION_9287,         "9287" }
+};
+
+/* For devices with external radios */
+static struct {
+	u16 version;
+	const char * name;
+} ath_rf_names[] = {
+	{ 0,				"5133" },
+	{ AR_RAD5133_SREV_MAJOR,	"5133" },
+	{ AR_RAD5122_SREV_MAJOR,	"5122" },
+	{ AR_RAD2133_SREV_MAJOR,	"2133" },
+	{ AR_RAD2122_SREV_MAJOR,	"2122" }
+};
+
+/*
+ * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown.
+ */
+const char *ath9k_hw_mac_bb_name(u32 mac_bb_version)
+{
+	int i;
+
+	for (i=0; i<ARRAY_SIZE(ath_mac_bb_names); i++) {
+		if (ath_mac_bb_names[i].version == mac_bb_version) {
+			return ath_mac_bb_names[i].name;
+		}
+	}
+
+	return "????";
+}
+EXPORT_SYMBOL(ath9k_hw_mac_bb_name);
+
+/*
+ * Return the RF name. "????" is returned if the RF is unknown.
+ * Used for devices with external radios.
+ */
+const char *ath9k_hw_rf_name(u16 rf_version)
+{
+	int i;
+
+	for (i=0; i<ARRAY_SIZE(ath_rf_names); i++) {
+		if (ath_rf_names[i].version == rf_version) {
+			return ath_rf_names[i].name;
+		}
+	}
+
+	return "????";
+}
+EXPORT_SYMBOL(ath9k_hw_rf_name);
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 936ef5b..100fcba 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -720,6 +720,9 @@ void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
 void ath_gen_timer_isr(struct ath_hw *hw);
 u32 ath9k_hw_gettsf32(struct ath_hw *ah);
 
+const char *ath9k_hw_mac_bb_name(u32 mac_bb_version);
+const char *ath9k_hw_rf_name(u16 rf_version);
+
 #define ATH_PCIE_CAP_LINK_CTRL	0x70
 #define ATH_PCIE_CAP_LINK_L0S	1
 #define ATH_PCIE_CAP_LINK_L1	2
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 69cf702..9fefc51 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -3191,64 +3191,6 @@ struct ieee80211_ops ath9k_ops = {
 	.rfkill_poll        = ath9k_rfkill_poll_state,
 };
 
-static struct {
-	u32 version;
-	const char * name;
-} ath_mac_bb_names[] = {
-	{ AR_SREV_VERSION_5416_PCI,	"5416" },
-	{ AR_SREV_VERSION_5416_PCIE,	"5418" },
-	{ AR_SREV_VERSION_9100,		"9100" },
-	{ AR_SREV_VERSION_9160,		"9160" },
-	{ AR_SREV_VERSION_9280,		"9280" },
-	{ AR_SREV_VERSION_9285,		"9285" },
-	{ AR_SREV_VERSION_9287,         "9287" }
-};
-
-static struct {
-	u16 version;
-	const char * name;
-} ath_rf_names[] = {
-	{ 0,				"5133" },
-	{ AR_RAD5133_SREV_MAJOR,	"5133" },
-	{ AR_RAD5122_SREV_MAJOR,	"5122" },
-	{ AR_RAD2133_SREV_MAJOR,	"2133" },
-	{ AR_RAD2122_SREV_MAJOR,	"2122" }
-};
-
-/*
- * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown.
- */
-const char *
-ath_mac_bb_name(u32 mac_bb_version)
-{
-	int i;
-
-	for (i=0; i<ARRAY_SIZE(ath_mac_bb_names); i++) {
-		if (ath_mac_bb_names[i].version == mac_bb_version) {
-			return ath_mac_bb_names[i].name;
-		}
-	}
-
-	return "????";
-}
-
-/*
- * Return the RF name. "????" is returned if the RF is unknown.
- */
-const char *
-ath_rf_name(u16 rf_version)
-{
-	int i;
-
-	for (i=0; i<ARRAY_SIZE(ath_rf_names); i++) {
-		if (ath_rf_names[i].version == rf_version) {
-			return ath_rf_names[i].name;
-		}
-	}
-
-	return "????";
-}
-
 static int __init ath9k_init(void)
 {
 	int error;
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 63059b6..76f3890 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -222,9 +222,10 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	       "%s: Atheros AR%s MAC/BB Rev:%x "
 	       "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n",
 	       wiphy_name(hw->wiphy),
-	       ath_mac_bb_name(ah->hw_version.macVersion),
+	       ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
 	       ah->hw_version.macRev,
-	       ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)),
+	       ath9k_hw_rf_name((ah->hw_version.analog5GhzRev &
+				 AR_RADIO_SREV_MAJOR)),
 	       ah->hw_version.phyRev,
 	       (unsigned long)mem, pdev->irq);
 
-- 
1.6.0.4


^ permalink raw reply related

* [PATCH 3/4] ath9k_hw: add AR9271 single chip name mapping
From: Luis R. Rodriguez @ 2009-10-26 14:39 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ath9k-devel, Luis R. Rodriguez
In-Reply-To: <1256567941-26859-1-git-send-email-lrodriguez@atheros.com>

Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
---
 drivers/net/wireless/ath/ath9k/hw.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index f65b591..50be381 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -3941,7 +3941,8 @@ static struct {
 	/* Single-chip solutions */
 	{ AR_SREV_VERSION_9280,		"9280" },
 	{ AR_SREV_VERSION_9285,		"9285" },
-	{ AR_SREV_VERSION_9287,         "9287" }
+	{ AR_SREV_VERSION_9287,         "9287" },
+	{ AR_SREV_VERSION_9271,         "9271" },
 };
 
 /* For devices with external radios */
-- 
1.6.0.4


^ permalink raw reply related

* [PATCH 2/4] ath9k_hw: distinguish single-chip solutions on initial probe print
From: Luis R. Rodriguez @ 2009-10-26 14:38 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ath9k-devel, Luis R. Rodriguez
In-Reply-To: <1256567941-26859-1-git-send-email-lrodriguez@atheros.com>

Devices with external radios have revisions which we can count on.
On single chip solutions these EEPROM values for these radio revision
also exist but are not meaningful as the radios are embedded onto the
same chip. Each single-chip device evolves together as one device.

Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
---
 drivers/net/wireless/ath/ath9k/ahb.c |   11 ++++-------
 drivers/net/wireless/ath/ath9k/hw.c  |   27 +++++++++++++++++++++++----
 drivers/net/wireless/ath/ath9k/hw.h  |    3 +--
 drivers/net/wireless/ath/ath9k/pci.c |   11 ++++-------
 4 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 41422c4..925818c 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -69,6 +69,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
 	int irq;
 	int ret = 0;
 	struct ath_hw *ah;
+	char hw_name[1024];
 
 	if (!pdev->dev.platform_data) {
 		dev_err(&pdev->dev, "no platform data specified\n");
@@ -133,15 +134,11 @@ static int ath_ahb_probe(struct platform_device *pdev)
 	}
 
 	ah = sc->sc_ah;
+	ath9k_hw_name(ah, hw_name);
 	printk(KERN_INFO
-	       "%s: Atheros AR%s MAC/BB Rev:%x, "
-	       "AR%s RF Rev:%x, mem=0x%lx, irq=%d\n",
+	       "%s: %s mem=0x%lx, irq=%d\n",
 	       wiphy_name(hw->wiphy),
-	       ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
-	       ah->hw_version.macRev,
-	       ath9k_hw_rf_name((ah->hw_version.analog5GhzRev &
-				 AR_RADIO_SREV_MAJOR)),
-	       ah->hw_version.phyRev,
+	       hw_name,
 	       (unsigned long)mem, irq);
 
 	return 0;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index cf543e3..f65b591 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -3959,7 +3959,7 @@ static struct {
 /*
  * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown.
  */
-const char *ath9k_hw_mac_bb_name(u32 mac_bb_version)
+static const char *ath9k_hw_mac_bb_name(u32 mac_bb_version)
 {
 	int i;
 
@@ -3971,13 +3971,12 @@ const char *ath9k_hw_mac_bb_name(u32 mac_bb_version)
 
 	return "????";
 }
-EXPORT_SYMBOL(ath9k_hw_mac_bb_name);
 
 /*
  * Return the RF name. "????" is returned if the RF is unknown.
  * Used for devices with external radios.
  */
-const char *ath9k_hw_rf_name(u16 rf_version)
+static const char *ath9k_hw_rf_name(u16 rf_version)
 {
 	int i;
 
@@ -3989,4 +3988,24 @@ const char *ath9k_hw_rf_name(u16 rf_version)
 
 	return "????";
 }
-EXPORT_SYMBOL(ath9k_hw_rf_name);
+
+void ath9k_hw_name(struct ath_hw *ah, char *hw_name)
+{
+	/* chipsets >= AR9280 are single-chip */
+	if (AR_SREV_9280_10_OR_LATER(ah)) {
+		sprintf(hw_name,
+			"Atheros single-chip AR%s Rev:%x",
+			ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
+			ah->hw_version.macRev);
+	}
+	else {
+		sprintf(hw_name,
+			"Atheros AR%s MAC/BB Rev:%x AR%s RF Rev:%x: ",
+			ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
+			ah->hw_version.macRev,
+			ath9k_hw_rf_name((ah->hw_version.analog5GhzRev &
+					 AR_RADIO_SREV_MAJOR)),
+			ah->hw_version.phyRev);
+	}
+}
+EXPORT_SYMBOL(ath9k_hw_name);
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 100fcba..3ceb4c6 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -720,8 +720,7 @@ void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
 void ath_gen_timer_isr(struct ath_hw *hw);
 u32 ath9k_hw_gettsf32(struct ath_hw *ah);
 
-const char *ath9k_hw_mac_bb_name(u32 mac_bb_version);
-const char *ath9k_hw_rf_name(u16 rf_version);
+void ath9k_hw_name(struct ath_hw *ah, char *hw_name);
 
 #define ATH_PCIE_CAP_LINK_CTRL	0x70
 #define ATH_PCIE_CAP_LINK_L0S	1
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 76f3890..963d6fe 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -114,6 +114,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	u32 val;
 	int ret = 0;
 	struct ath_hw *ah;
+	char hw_name[1024];
 
 	if (pci_enable_device(pdev))
 		return -EIO;
@@ -218,15 +219,11 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	sc->irq = pdev->irq;
 
 	ah = sc->sc_ah;
+	ath9k_hw_name(ah, hw_name);
 	printk(KERN_INFO
-	       "%s: Atheros AR%s MAC/BB Rev:%x "
-	       "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n",
+	       "%s: %s mem=0x%lx, irq=%d\n",
 	       wiphy_name(hw->wiphy),
-	       ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
-	       ah->hw_version.macRev,
-	       ath9k_hw_rf_name((ah->hw_version.analog5GhzRev &
-				 AR_RADIO_SREV_MAJOR)),
-	       ah->hw_version.phyRev,
+	       hw_name,
 	       (unsigned long)mem, pdev->irq);
 
 	return 0;
-- 
1.6.0.4


^ permalink raw reply related

* [PATCH 0/4] ath9k_hw: modify hw identification message
From: Luis R. Rodriguez @ 2009-10-26 14:38 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ath9k-devel, Luis R. Rodriguez

While reviewing ar9271 radio revisions I determined the radio revision
does not apply although it can be populated in the EEPROM. This changes
the hw probe print to reflect this for single chips and throws the code
into hw code to be shared with ath9k_htc.

Luis R. Rodriguez (4):
  ath9k_hw: move mac name and rf name helpers to hw code
  ath9k_hw: distinguish single-chip solutions on initial probe print
  ath9k_hw: add AR9271 single chip name mapping
  ath9k_hw: add some debug print for hw initialization

 drivers/net/wireless/ath/ath9k/ahb.c   |   10 ++--
 drivers/net/wireless/ath/ath9k/calib.c |    3 +
 drivers/net/wireless/ath/ath9k/hw.c    |   90 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/hw.h    |    2 +
 drivers/net/wireless/ath/ath9k/main.c  |   58 --------------------
 drivers/net/wireless/ath/ath9k/pci.c   |   10 ++--
 6 files changed, 103 insertions(+), 70 deletions(-)


^ permalink raw reply

* [PATCH 4/4] ath9k_hw: add some debug print for hw initialization
From: Luis R. Rodriguez @ 2009-10-26 14:39 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ath9k-devel, Luis R. Rodriguez
In-Reply-To: <1256567941-26859-1-git-send-email-lrodriguez@atheros.com>

This helps debugging hw bring up.

Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
---
 drivers/net/wireless/ath/ath9k/calib.c |    3 +++
 drivers/net/wireless/ath/ath9k/hw.c    |    8 ++++++++
 2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 551f880..07b7618 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -1084,6 +1084,9 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
 
+	ath_print(common, ATH_DBG_CALIBRATE, "Running carrier leakage "
+		  "calibration fix\n");
+
 	REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
 	if (IS_CHAN_HT20(chan)) {
 		REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 50be381..04b6afc 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1005,8 +1005,11 @@ int ath9k_hw_init(struct ath_hw *ah)
 static void ath9k_hw_init_bb(struct ath_hw *ah,
 			     struct ath9k_channel *chan)
 {
+	struct ath_common *common = ath9k_hw_common(ah);
 	u32 synthDelay;
 
+	ath_print(common, ATH_DBG_RESET, "initializing baseband\n");
+
 	synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
 	if (IS_CHAN_B(chan))
 		synthDelay = (4 * synthDelay) / 22;
@@ -1591,6 +1594,8 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah)
 {
 	u32 regval;
 
+	ath_print(ath9k_hw_common(ah), ATH_DBG_RESET,
+		  "Configuring DMA read/write settings\n");
 	/*
 	 * set AHB_MODE not to do cacheline prefetches
 	*/
@@ -2145,6 +2150,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 	/*
 	 * For big endian systems turn on swapping for descriptors
 	 */
+	ath_print(common, ATH_DBG_RESET,
+		  "Configuring byte swap settings\n");
+
 	if (AR_SREV_9100(ah)) {
 		u32 mask;
 		mask = REG_READ(ah, AR_CFG);
-- 
1.6.0.4


^ permalink raw reply related

* Re: RECAP: indication of channel noise
From: Holger Schurig @ 2009-10-26 14:30 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Felix Fietkau
In-Reply-To: <1256565132.12462.9.camel@johannes.local>

> >   NL80211_BSS_NOISE_MBM

Hmm, this could better be NL80211_CHANNEL_NOISE_MBM, to make
clear that this is not heat-related internal noise of the chip.



For the rest of your remarks: ok


-- 
M&N Solutions GmbH          Ein Unternehmen der Datagroup AG
Holger Schurig
Raiffeisenstr. 10
61191 Rosbach
Tel: 06003/9141-15          Fax 06003/9141-49
http://www.mn-solutions.de/

Handelsregister Friedberg, HRB 5903
Geschäftsführer: P.Schrittenlocher

^ permalink raw reply

* Re: [RFT 00/15] ath9k_hw ar9271 updates & AR5416 force bias
From: Luis R. Rodriguez @ 2009-10-26 14:23 UTC (permalink / raw)
  To: linux-wireless, Sujith, John W. Linville; +Cc: ath9k-devel, Luis R. Rodriguez
In-Reply-To: <43e72e890910260719j508670a8p87bb7a5cf31d843d@mail.gmail.com>

On Mon, Oct 26, 2009 at 7:19 AM, Luis R. Rodriguez
<lrodriguez@atheros.com> wrote:
> On Wed, Oct 21, 2009 at 8:42 PM, Luis R. Rodriguez
> <lrodriguez@atheros.com> wrote:
>> On Mon, Oct 19, 2009 at 3:33 PM, Luis R. Rodriguez
>> <lrodriguez@atheros.com> wrote:
>>> This series started off to extend support for ar9271 on ath9k_hw
>>> but after review of the phy related code I noticed a fix for
>>> AR5416 was only partially being implemented and used for all
>>> chipsets. This series then adds the changes I've noticed so far
>>> required for ar9271 but also fixes and completes the orientation
>>> fix for AR5416 (force bias). Since I'm touching phy.c I also extend
>>> documentation for it.
>>>
>>> I don't have AR9285 cards with me but I do have an AR5416 cardbus
>>> card -- I'd appreciate it if someone can give this a test on AR9285
>
> Alright well I made it back to California and tested an AR9285 and
> things are peachy so I will submit this now.

Johh, actually instead of resubmitting can you take these in as-is?
They should apply on top of the latest tree. Please let me know.

 Luis

^ permalink raw reply

* Re: [RFT 00/15] ath9k_hw ar9271 updates & AR5416 force bias
From: Luis R. Rodriguez @ 2009-10-26 14:19 UTC (permalink / raw)
  To: linux-wireless, Sujith; +Cc: ath9k-devel, Luis R. Rodriguez
In-Reply-To: <43e72e890910212042i6a6a1bc3h1cd2a742f462353f@mail.gmail.com>

On Wed, Oct 21, 2009 at 8:42 PM, Luis R. Rodriguez
<lrodriguez@atheros.com> wrote:
> On Mon, Oct 19, 2009 at 3:33 PM, Luis R. Rodriguez
> <lrodriguez@atheros.com> wrote:
>> This series started off to extend support for ar9271 on ath9k_hw
>> but after review of the phy related code I noticed a fix for
>> AR5416 was only partially being implemented and used for all
>> chipsets. This series then adds the changes I've noticed so far
>> required for ar9271 but also fixes and completes the orientation
>> fix for AR5416 (force bias). Since I'm touching phy.c I also extend
>> documentation for it.
>>
>> I don't have AR9285 cards with me but I do have an AR5416 cardbus
>> card -- I'd appreciate it if someone can give this a test on AR9285

Alright well I made it back to California and tested an AR9285 and
things are peachy so I will submit this now.

  Luis

^ permalink raw reply

* [PATCH] airo: Reorder tests, check bounds before element
From: Roel Kluin @ 2009-10-26 14:28 UTC (permalink / raw)
  To: John W. Linville, linux-wireless, Andrew Morton, LKML

Test whether index is within bounds before reading the element

Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
---
 drivers/net/wireless/airo.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 7116a1a..abf896a 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -4790,9 +4790,8 @@ static int proc_stats_rid_open( struct inode *inode,
 static int get_dec_u16( char *buffer, int *start, int limit ) {
 	u16 value;
 	int valid = 0;
-	for( value = 0; buffer[*start] >= '0' &&
-		     buffer[*start] <= '9' &&
-		     *start < limit; (*start)++ ) {
+	for (value = 0; *start < limit && buffer[*start] >= '0' &&
+			buffer[*start] <= '9'; (*start)++) {
 		valid = 1;
 		value *= 10;
 		value += buffer[*start] - '0';


^ permalink raw reply related

* Re: RECAP: indication of channel noise
From: Johannes Berg @ 2009-10-26 13:52 UTC (permalink / raw)
  To: Holger Schurig; +Cc: linux-wireless, Felix Fietkau
In-Reply-To: <200910261442.44774.h.schurig@mn-solutions.de>

[-- Attachment #1: Type: text/plain, Size: 1066 bytes --]

On Mon, 2009-10-26 at 14:42 +0100, Holger Schurig wrote:

> [snip descriptions]

sounds about right

> We did not yet come up with a clear API definition for this. My 
> idea for an initial "retrieve site survey" response is:
> 
> NL80211_CMD_NEW_SURVEY_RESULTS
>   NL80211_ATTR_GENERATION
>   NL80211_ATTR_IFINDEX
>   NL80211_BSS_FREQUENCY
>   NL80211_BSS_NOISE_MBM
> 
> Of course this will extend over time, but that is easy due to 
> nl80211.

I'm not really happy with having "BSS" in there. And the ifindex is
kinda not necessary either I think, you really want the wiphy index.
Also it's not necessary in the response since the request will contain
the wiphy index (or interface index).

I'd introduce a new
NL80211_CMD_GET_SURVEY_RESULT

which you use together with a dumpit call, for channels, which lists
channels one by one similar to nl80211_dump_scan()/nl80211_send_bss()
but with nl80211_dump_survey()/nl80211_send_survey_channel().

In this case I think a "last updated" value would be rather important
too.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply

* RECAP: indication of channel noise
From: Holger Schurig @ 2009-10-26 13:42 UTC (permalink / raw)
  To: linux-wireless, Johannes Berg, Felix Fietkau

On IRC, Johannes, Felix and I talked about how to indicate the 
noise level towards user-space.

Noise is not really a property of the link, althought derived 
values like SNR are. It can be nice to debug stuff.


However, what hardware value hardware says is a noise level 
variues. For ath5k, it's internal, thermal noise. For ath9k, 
it's external medium noise. Some hardware can determine noise 
only while in a connection, others can do it at any time.

However, noise is only one property of a channel, a wider 
approach would be to define a "site survey API". This could 
include hw cycle counters, e.g. to find out the channel 
utilization.

The idea is to have one API call "do site survey", where you tell 
the driver to scan on specified/all channels to determine those 
values.

And then there's an API call to retrieve this information. For 
hardware where you cannot really scan (e.g. Libertas, Orinoco), 
you can simply call the "retrieve site survey" call without the 
prior scanning and you just get what the hardware knows anyway. 

This makes the retrieve systeam call "cheap" in order to only get 
the noise level, but the API rich in case the hardware has much 
more versatile capabilities.



We did not yet come up with a clear API definition for this. My 
idea for an initial "retrieve site survey" response is:

NL80211_CMD_NEW_SURVEY_RESULTS
  NL80211_ATTR_GENERATION
  NL80211_ATTR_IFINDEX
  NL80211_BSS_FREQUENCY
  NL80211_BSS_NOISE_MBM

Of course this will extend over time, but that is easy due to 
nl80211.

-- 
M&N Solutions GmbH          Ein Unternehmen der Datagroup AG
Holger Schurig
Raiffeisenstr. 10
61191 Rosbach
Tel: 06003/9141-15          Fax 06003/9141-49
http://www.mn-solutions.de/

Handelsregister Friedberg, HRB 5903
Geschäftsführer: P.Schrittenlocher

^ permalink raw reply

* Re: "Reserved instruction in kernel code" on ath9k insertion
From: Johannes Berg @ 2009-10-26 13:31 UTC (permalink / raw)
  To: Tomasz Chmielewski; +Cc: Luis R. Rodriguez, linux-wireless
In-Reply-To: <4AE5A3DC.1090804@wpkg.org>

[-- Attachment #1: Type: text/plain, Size: 523 bytes --]

On Mon, 2009-10-26 at 14:27 +0100, Tomasz Chmielewski wrote:

> >> [  165.440000]     Not tainted
> > 
> > This says not tainted.
> 
> (...)
> 
> >> [  165.440000] Disabling lock debugging due to kernel taint
> > 
> > But this says kernel taint.
> 
> Yep, I saw this as well.
> 
> About every oops or panic on this hardware says "Disabling lock 
> debugging due to kernel taint", no idea why.

Umm, oopsing itself taints the kernel, so _after/during_ the oops lock
debugging _gets_ disabled.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply

* RECAP: plan for cfg80211 & mesh
From: Holger Schurig @ 2009-10-26 13:30 UTC (permalink / raw)
  To: linux-wireless, Dan Williams

After some talk on IRC I have the following plan:

* all WEXT code for the normal STA code goes into
  assoc.c, wext.c and scan.c. Therefore, all my
  patches not marked as RFC should be reviewed and
  go into the kernel.

* There will be no CONFIG_LIBERTAS_WEXT or
  CONFIG_LIBERTAS_CFG80211 command line option, so we
  have one "flip-day", where we go from WEXT based
  confuguration to CFG80211-based configuration (note
  that cfg80211 allowes WEXT-based tools via compat-wext.c)

* for Libertas' mesh, we'll get an CONFIG_LIBERTAS_MESH
  config.

* Liberas' mesh code also depend on WIRELESS_WEXT, it needs
  4 WEXT ioctls: get ssid, set ssid, get mode and set channel.
  For the beginning, libertas+cfg80211 will behave similar to
  libertas+wext. That means: at module probing + initialization
  time, it probes the firmware for mesh. It will the create a
  (cfg80211 controlled) interface for STA, and if firmware
  supports MESH, it creates an (wext controlled) mshX device.

* I plan to code the mesh code, as it seems now quite simple.
  Testing must be done by third-parties.

  I want to move all mesh related code into one or two files,
  probably persistcfg+ethtool+mesh-stuff from main.c into
  mesh.h/mesh.c. Or rename persistcfg.c to mesh.c, something
  around this lines. This makes CONFIG_LIBERTAS_MESH less
  intrusive.

* That means we have a bunch of WEXT cleanup patches, that
  move things around in order to isolate WEXT related stuff
  into some files. And another bunch of MESH cleanup
  patches, that isolate MESH in some files.

  And then, at "flag day" there will come a patch that
  adds the full cfg80211 support, the CONFIG_LIBERTAS_MESH
  Kconfig and removes the WEXT-code, now isolated in
  scan.c, assoc.c and wext.c.

  At some later time, if people are still interested in
  MESH (OLPC people should document by maintaining it)
  we can fully get rid of MESH-related WEXT code by
  converting it to CFG80211, too. Otherwise, we might
  rip out MESH, which will also be easier because of
  the isolation.

* It's not clear yet if the first libertas+cfg80211
  will support adhoc, monitor reception and monitor
  packet injection. All of this might come on the
  "flag day" --- or later. Full station mode will
  come, sans some bugs :-)


Dan, I hope this recap is what we talked about. If not, please 
correct me. All other parties, please comment.

-- 
M&N Solutions GmbH          Ein Unternehmen der Datagroup AG
Holger Schurig
Raiffeisenstr. 10
61191 Rosbach
Tel: 06003/9141-15          Fax 06003/9141-49
http://www.mn-solutions.de/

Handelsregister Friedberg, HRB 5903
Geschäftsführer: P.Schrittenlocher

^ permalink raw reply

* Re: "Reserved instruction in kernel code" on ath9k insertion
From: Tomasz Chmielewski @ 2009-10-26 13:27 UTC (permalink / raw)
  To: Luis R. Rodriguez; +Cc: linux-wireless
In-Reply-To: <43e72e890910260617n6efbd260gcafbf5d1d2c84e23@mail.gmail.com>

Luis R. Rodriguez wrote:
> On Sat, Oct 24, 2009 at 12:50 PM, Tomasz Chmielewski <mangoo@wpkg.org> wrote:
>> When I do "modprobe ath9k" on ASUS-WL-500gP (MIPS) with _ath5k_ card (so, no
>> ath9k hardware), it says "Reserved instruction in kernel code" - is it
>> expected?
> 
> No.
> 
>> The kernel is 2.6.31.1.
>>
>>
>> # modprobe ath9k
>> [  165.440000] Reserved instruction in kernel code[#1]:
>> [  165.440000] Cpu 0
>> [  165.440000] $ 0   : 00000000 1000dc00 00000000 00000000
>> [  165.440000] $ 4   : c1135b20 00000001 c044e69c ffffffff
>> [  165.440000] $ 8   : 0000000a 8101f6d8 ffffffe0 0000002b
>> [  165.440000] $12   : 00000e44 00000006 80333ae8 5f657361
>> [  165.440000] $16   : 00000001 c1135ca4 80370000 81418000
>> [  165.440000] $20   : 00000000 00000000 00000000 004fe008
>> [  165.440000] $24   : 00000010 c1115118
>> [  165.440000] $28   : 81da6000 81da7ea8 7febead8 81418014
>> [  165.440000] Hi    : 00000000
>> [  165.440000] Lo    : 00000000
>> [  165.440000] epc   : c044e694 0xc044e694
>> [  165.440000]     Not tainted
> 
> This says not tainted.

(...)

>> [  165.440000] Disabling lock debugging due to kernel taint
> 
> But this says kernel taint.

Yep, I saw this as well.

About every oops or panic on this hardware says "Disabling lock 
debugging due to kernel taint", no idea why.



-- 
Tomasz Chmielewski
http://wpkg.org

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox