Skip to content

Commit

Permalink
iwlwifi: enable serialization of synchronous commands
Browse files Browse the repository at this point in the history
Until now it was only possible to have one synchronous command running at
any time. If a synchronous command is in progress when a second request
arrives then the second command will fail. Create a new mutex specific for
this purpose to only allow one synchronous command at a time, but enable
other commands to wait instead of fail if a synchronous command is in
progress.

Signed-off-by: Reinette Chatre <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
  • Loading branch information
rchatre authored and linvjw committed Feb 19, 2010
1 parent 4a6547c commit d2dfe6d
Show file tree
Hide file tree
Showing 7 changed files with 13 additions and 10 deletions.
1 change: 1 addition & 0 deletions drivers/net/wireless/iwlwifi/iwl-agn.c
Original file line number Diff line number Diff line change
Expand Up @@ -3364,6 +3364,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
INIT_LIST_HEAD(&priv->free_frames);

mutex_init(&priv->mutex);
mutex_init(&priv->sync_cmd_mutex);

/* Clear the driver's (not device's) station table */
iwl_clear_stations_table(priv);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/iwlwifi/iwl-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ void iwlcore_free_geos(struct iwl_priv *priv);
/*************** DRIVER STATUS FUNCTIONS *****/

#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */
#define STATUS_INT_ENABLED 2
#define STATUS_RF_KILL_HW 3
#define STATUS_CT_KILL 4
Expand Down
2 changes: 0 additions & 2 deletions drivers/net/wireless/iwlwifi/iwl-debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,

pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
test_bit(STATUS_HCMD_ACTIVE, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_SYNC_ACTIVE: %d\n",
test_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
test_bit(STATUS_INT_ENABLED, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/iwlwifi/iwl-dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -1111,6 +1111,7 @@ struct iwl_priv {
spinlock_t hcmd_lock; /* protect hcmd */
spinlock_t reg_lock; /* protect hw register access */
struct mutex mutex;
struct mutex sync_cmd_mutex; /* enable serialization of sync commands */

/* basic pci-network driver stuff */
struct pci_dev *pci_dev;
Expand Down
14 changes: 7 additions & 7 deletions drivers/net/wireless/iwlwifi/iwl-hcmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,13 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
/* A synchronous command can not have a callback set. */
BUG_ON(cmd->callback);

if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
IWL_ERR(priv,
"Error sending %s: Already sending a host command\n",
IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
get_cmd_string(cmd->id));
ret = -EBUSY;
goto out;
}
mutex_lock(&priv->sync_cmd_mutex);

set_bit(STATUS_HCMD_ACTIVE, &priv->status);
IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s \n",
get_cmd_string(cmd->id));

cmd_idx = iwl_enqueue_hcmd(priv, cmd);
if (cmd_idx < 0) {
Expand All @@ -193,6 +191,8 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));

clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n",
get_cmd_string(cmd->id));
ret = -ETIMEDOUT;
goto cancel;
}
Expand Down Expand Up @@ -237,7 +237,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
cmd->reply_page = 0;
}
out:
clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
mutex_unlock(&priv->sync_cmd_mutex);
return ret;
}
EXPORT_SYMBOL(iwl_send_cmd_sync);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/iwlwifi/iwl-tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)

if (!(meta->flags & CMD_ASYNC)) {
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n",
get_cmd_string(cmd->hdr.cmd));
wake_up_interruptible(&priv->wait_command_queue);
}
}
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/iwlwifi/iwl3945-base.c
Original file line number Diff line number Diff line change
Expand Up @@ -3847,6 +3847,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
INIT_LIST_HEAD(&priv->free_frames);

mutex_init(&priv->mutex);
mutex_init(&priv->sync_cmd_mutex);

/* Clear the driver's (not device's) station table */
iwl_clear_stations_table(priv);
Expand Down

0 comments on commit d2dfe6d

Please sign in to comment.