提交 e5472978 编写于 作者: T Tomas Winkler 提交者: John W. Linville

iwlwifi: Fix synchronous host command

This patch replaces static variable from send_cmd_sync
with flag in priv->status. It was used for reentrance protection
but clearly made it impossible to stuck more cards into the same machine

In addition it force check of return values of synchronous commands
commands that doesn't requires return value async commands have to be used
Signed-off-by: NTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: NYi Zhu <yi.zhu@intel.com>
Signed-off-by: NJohn W. Linville <linville@tuxdriver.com>
上级 a571ea4e
...@@ -401,23 +401,24 @@ struct iwl3945_rx_queue { ...@@ -401,23 +401,24 @@ struct iwl3945_rx_queue {
#define MIN_B_CHANNELS 1 #define MIN_B_CHANNELS 1
#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ #define STATUS_HCMD_ACTIVE 0 /* host command in progress */
#define STATUS_INT_ENABLED 1 #define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
#define STATUS_RF_KILL_HW 2 #define STATUS_INT_ENABLED 2
#define STATUS_RF_KILL_SW 3 #define STATUS_RF_KILL_HW 3
#define STATUS_INIT 4 #define STATUS_RF_KILL_SW 4
#define STATUS_ALIVE 5 #define STATUS_INIT 5
#define STATUS_READY 6 #define STATUS_ALIVE 6
#define STATUS_TEMPERATURE 7 #define STATUS_READY 7
#define STATUS_GEO_CONFIGURED 8 #define STATUS_TEMPERATURE 8
#define STATUS_EXIT_PENDING 9 #define STATUS_GEO_CONFIGURED 9
#define STATUS_IN_SUSPEND 10 #define STATUS_EXIT_PENDING 10
#define STATUS_STATISTICS 11 #define STATUS_IN_SUSPEND 11
#define STATUS_SCANNING 12 #define STATUS_STATISTICS 12
#define STATUS_SCAN_ABORTING 13 #define STATUS_SCANNING 13
#define STATUS_SCAN_HW 14 #define STATUS_SCAN_ABORTING 14
#define STATUS_POWER_PMI 15 #define STATUS_SCAN_HW 15
#define STATUS_FW_ERROR 16 #define STATUS_POWER_PMI 16
#define STATUS_CONF_PENDING 17 #define STATUS_FW_ERROR 17
#define STATUS_CONF_PENDING 18
#define MAX_TID_COUNT 9 #define MAX_TID_COUNT 9
......
...@@ -1314,8 +1314,8 @@ void iwl4965_chain_noise_reset(struct iwl_priv *priv) ...@@ -1314,8 +1314,8 @@ void iwl4965_chain_noise_reset(struct iwl_priv *priv)
cmd.diff_gain_a = 0; cmd.diff_gain_a = 0;
cmd.diff_gain_b = 0; cmd.diff_gain_b = 0;
cmd.diff_gain_c = 0; cmd.diff_gain_c = 0;
iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD,
sizeof(cmd), &cmd); sizeof(cmd), &cmd, NULL);
msleep(4); msleep(4);
data->state = IWL_CHAIN_NOISE_ACCUMULATE; data->state = IWL_CHAIN_NOISE_ACCUMULATE;
IWL_DEBUG_CALIB("Run chain_noise_calibrate\n"); IWL_DEBUG_CALIB("Run chain_noise_calibrate\n");
...@@ -4563,8 +4563,8 @@ void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) ...@@ -4563,8 +4563,8 @@ void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
/* Update the rate scaling for control frame Tx to AP */ /* Update the rate scaling for control frame Tx to AP */
link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_setting.bcast_sta_id; link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_setting.bcast_sta_id;
iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, sizeof(link_cmd), iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD,
&link_cmd); sizeof(link_cmd), &link_cmd, NULL);
} }
#ifdef CONFIG_IWL4965_HT #ifdef CONFIG_IWL4965_HT
......
...@@ -415,23 +415,24 @@ struct iwl4965_rx_queue { ...@@ -415,23 +415,24 @@ struct iwl4965_rx_queue {
#define MIN_B_CHANNELS 1 #define MIN_B_CHANNELS 1
#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ #define STATUS_HCMD_ACTIVE 0 /* host command in progress */
#define STATUS_INT_ENABLED 1 #define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
#define STATUS_RF_KILL_HW 2 #define STATUS_INT_ENABLED 2
#define STATUS_RF_KILL_SW 3 #define STATUS_RF_KILL_HW 3
#define STATUS_INIT 4 #define STATUS_RF_KILL_SW 4
#define STATUS_ALIVE 5 #define STATUS_INIT 5
#define STATUS_READY 6 #define STATUS_ALIVE 6
#define STATUS_TEMPERATURE 7 #define STATUS_READY 7
#define STATUS_GEO_CONFIGURED 8 #define STATUS_TEMPERATURE 8
#define STATUS_EXIT_PENDING 9 #define STATUS_GEO_CONFIGURED 9
#define STATUS_IN_SUSPEND 10 #define STATUS_EXIT_PENDING 10
#define STATUS_STATISTICS 11 #define STATUS_IN_SUSPEND 11
#define STATUS_SCANNING 12 #define STATUS_STATISTICS 12
#define STATUS_SCAN_ABORTING 13 #define STATUS_SCANNING 13
#define STATUS_SCAN_HW 14 #define STATUS_SCAN_ABORTING 14
#define STATUS_POWER_PMI 15 #define STATUS_SCAN_HW 15
#define STATUS_FW_ERROR 16 #define STATUS_POWER_PMI 16
#define STATUS_CONF_PENDING 17 #define STATUS_FW_ERROR 17
#define STATUS_CONF_PENDING 18
#define MAX_TID_COUNT 9 #define MAX_TID_COUNT 9
......
...@@ -138,9 +138,11 @@ int iwl_setup(struct iwl_priv *priv); ...@@ -138,9 +138,11 @@ int iwl_setup(struct iwl_priv *priv);
*****************************************************/ *****************************************************/
const char *get_cmd_string(u8 cmd); const char *get_cmd_string(u8 cmd);
int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd); int __must_check iwl_send_cmd_sync(struct iwl_priv *priv,
struct iwl_host_cmd *cmd);
int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data); int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id,
u16 len, const void *data);
int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len, int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
const void *data, const void *data,
int (*callback)(struct iwl_priv *priv, int (*callback)(struct iwl_priv *priv,
......
...@@ -151,17 +151,17 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) ...@@ -151,17 +151,17 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
{ {
int cmd_idx; int cmd_idx;
int ret; int ret;
static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */
BUG_ON(cmd->meta.flags & CMD_ASYNC); BUG_ON(cmd->meta.flags & CMD_ASYNC);
/* A synchronous command can not have a callback set. */ /* A synchronous command can not have a callback set. */
BUG_ON(cmd->meta.u.callback != NULL); BUG_ON(cmd->meta.u.callback != NULL);
if (atomic_xchg(&entry, 1)) { if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
IWL_ERROR("Error sending %s: Already sending a host command\n", IWL_ERROR("Error sending %s: Already sending a host command\n",
get_cmd_string(cmd->id)); get_cmd_string(cmd->id));
return -EBUSY; ret = -EBUSY;
goto out;
} }
set_bit(STATUS_HCMD_ACTIVE, &priv->status); set_bit(STATUS_HCMD_ACTIVE, &priv->status);
...@@ -231,7 +231,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) ...@@ -231,7 +231,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
cmd->meta.u.skb = NULL; cmd->meta.u.skb = NULL;
} }
out: out:
atomic_set(&entry, 0); clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
return ret; return ret;
} }
EXPORT_SYMBOL(iwl_send_cmd_sync); EXPORT_SYMBOL(iwl_send_cmd_sync);
......
...@@ -733,17 +733,17 @@ static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_ ...@@ -733,17 +733,17 @@ static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_
{ {
int cmd_idx; int cmd_idx;
int ret; int ret;
static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */
BUG_ON(cmd->meta.flags & CMD_ASYNC); BUG_ON(cmd->meta.flags & CMD_ASYNC);
/* A synchronous command can not have a callback set. */ /* A synchronous command can not have a callback set. */
BUG_ON(cmd->meta.u.callback != NULL); BUG_ON(cmd->meta.u.callback != NULL);
if (atomic_xchg(&entry, 1)) { if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
IWL_ERROR("Error sending %s: Already sending a host command\n", IWL_ERROR("Error sending %s: Already sending a host command\n",
get_cmd_string(cmd->id)); get_cmd_string(cmd->id));
return -EBUSY; ret = -EBUSY;
goto out;
} }
set_bit(STATUS_HCMD_ACTIVE, &priv->status); set_bit(STATUS_HCMD_ACTIVE, &priv->status);
...@@ -813,7 +813,7 @@ static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_ ...@@ -813,7 +813,7 @@ static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_
cmd->meta.u.skb = NULL; cmd->meta.u.skb = NULL;
} }
out: out:
atomic_set(&entry, 0); clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
return ret; return ret;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册