diff mbox

libertas: set mac control synchronously during init

Message ID 20120911153812.08740FAA7C@dev.laptop.org (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Daniel Drake Sept. 11, 2012, 3:38 p.m. UTC
CMD_MAC_CONTROL is currently sent async to the firmware, and is sent
from the lbs_setup_firmware() path during device init.

This means that device init can complete with commands pending, and
the if_sdio driver will sometimes power down the device (after init)
with this command still pending.

This was causing an occasional spurious command timeout after init,
leading to a device reset.

Fix this by making CMD_MAC_CONTROL synchronous when called from the
lbs_setup_firmware() path.

Signed-off-by: Daniel Drake <dsd@laptop.org>
---
 drivers/net/wireless/libertas/cmd.c  | 16 ++++++++++++++++
 drivers/net/wireless/libertas/cmd.h  |  1 +
 drivers/net/wireless/libertas/main.c |  4 +++-
 3 files changed, 20 insertions(+), 1 deletion(-)

Comments

Dan Williams Sept. 11, 2012, 4:04 p.m. UTC | #1
On Tue, 2012-09-11 at 11:38 -0400, Daniel Drake wrote:
> CMD_MAC_CONTROL is currently sent async to the firmware, and is sent
> from the lbs_setup_firmware() path during device init.
> 
> This means that device init can complete with commands pending, and
> the if_sdio driver will sometimes power down the device (after init)
> with this command still pending.
> 
> This was causing an occasional spurious command timeout after init,
> leading to a device reset.
> 
> Fix this by making CMD_MAC_CONTROL synchronous when called from the
> lbs_setup_firmware() path.
> 
> Signed-off-by: Daniel Drake <dsd@laptop.org>

Thanks!

Signed-off-by: Dan Williams <dcbw@redhat.com>

>  drivers/net/wireless/libertas/cmd.c  | 16 ++++++++++++++++
>  drivers/net/wireless/libertas/cmd.h  |  1 +
>  drivers/net/wireless/libertas/main.c |  4 +++-
>  3 files changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
> index 26e6832..aaa2973 100644
> --- a/drivers/net/wireless/libertas/cmd.c
> +++ b/drivers/net/wireless/libertas/cmd.c
> @@ -1159,6 +1159,22 @@ void lbs_set_mac_control(struct lbs_private *priv)
>  	lbs_deb_leave(LBS_DEB_CMD);
>  }
>  
> +int lbs_set_mac_control_sync(struct lbs_private *priv)
> +{
> +	struct cmd_ds_mac_control cmd;
> +	int ret = 0;
> +
> +	lbs_deb_enter(LBS_DEB_CMD);
> +
> +	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
> +	cmd.action = cpu_to_le16(priv->mac_control);
> +	cmd.reserved = 0;
> +	ret = lbs_cmd_with_response(priv, CMD_MAC_CONTROL, &cmd);
> +
> +	lbs_deb_leave(LBS_DEB_CMD);
> +	return ret;
> +}
> +
>  /**
>   *  lbs_allocate_cmd_buffer - allocates the command buffer and links
>   *  it to command free queue
> diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
> index ab07608..4279e8a 100644
> --- a/drivers/net/wireless/libertas/cmd.h
> +++ b/drivers/net/wireless/libertas/cmd.h
> @@ -96,6 +96,7 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv);
>  int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
>  
>  void lbs_set_mac_control(struct lbs_private *priv);
> +int lbs_set_mac_control_sync(struct lbs_private *priv);
>  
>  int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
>  		     s16 *maxlevel);
> diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
> index fe1ea43..0c02f04 100644
> --- a/drivers/net/wireless/libertas/main.c
> +++ b/drivers/net/wireless/libertas/main.c
> @@ -682,8 +682,10 @@ static int lbs_setup_firmware(struct lbs_private *priv)
>  
>  	/* Send cmd to FW to enable 11D function */
>  	ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1);
> +	if (ret)
> +		goto done;
>  
> -	lbs_set_mac_control(priv);
> +	ret = lbs_set_mac_control_sync(priv);
>  done:
>  	lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
>  	return ret;


--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 26e6832..aaa2973 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -1159,6 +1159,22 @@  void lbs_set_mac_control(struct lbs_private *priv)
 	lbs_deb_leave(LBS_DEB_CMD);
 }
 
+int lbs_set_mac_control_sync(struct lbs_private *priv)
+{
+	struct cmd_ds_mac_control cmd;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+	cmd.action = cpu_to_le16(priv->mac_control);
+	cmd.reserved = 0;
+	ret = lbs_cmd_with_response(priv, CMD_MAC_CONTROL, &cmd);
+
+	lbs_deb_leave(LBS_DEB_CMD);
+	return ret;
+}
+
 /**
  *  lbs_allocate_cmd_buffer - allocates the command buffer and links
  *  it to command free queue
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
index ab07608..4279e8a 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -96,6 +96,7 @@  void lbs_ps_confirm_sleep(struct lbs_private *priv);
 int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
 
 void lbs_set_mac_control(struct lbs_private *priv);
+int lbs_set_mac_control_sync(struct lbs_private *priv);
 
 int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
 		     s16 *maxlevel);
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index fe1ea43..0c02f04 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -682,8 +682,10 @@  static int lbs_setup_firmware(struct lbs_private *priv)
 
 	/* Send cmd to FW to enable 11D function */
 	ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1);
+	if (ret)
+		goto done;
 
-	lbs_set_mac_control(priv);
+	ret = lbs_set_mac_control_sync(priv);
 done:
 	lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
 	return ret;