libertas: set mac control synchronously during init
PATCH 1/1 libertas: set mac control synchronously during init
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.
--- 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(-)
drivers/net/wireless/libertas/cmd.c +16 -0
@@ -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
drivers/net/wireless/libertas/cmd.h +1 -0
@@ -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);
drivers/net/wireless/libertas/main.c +3 -1
@@ -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;
Signature · 1 line
1.7.11.4
Quoted 7 lines · Daniel Drake
CMD_MAC_CONTROLis currently sent async to the firmware, and is sent from thelbs_setup_firmware()path during device init.This means that device init can complete with commands pending, and the
if_sdiodriver will sometimes power down the device (after init) with this command still pending.
Quoted 7 lines
This was causing an occasional spurious command timeout after init, leading to a device reset.
Fix this by making
CMD_MAC_CONTROLsynchronous when called from thelbs_setup_firmware()path.Signed-off-by Daniel Drake <[email protected]>
Thanks!
Quoted 60 lines
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(-)drivers/net/wireless/libertas/cmd.c +16
-0@@ -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 drivers/net/wireless/libertas/cmd.h +1
-0@@ -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);drivers/net/wireless/libertas/main.c +3
-1@@ -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;