aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReinette Chatre <reinette.chatre@intel.com>2010-02-19 01:03:04 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-02-19 15:52:49 -0500
commitd2dfe6df755abb365aa3e2e67d88bda3cce5fd12 (patch)
tree5b24bd9cffb0ddfdd54554f2b5bace16c346ef99
parent4a6547c748229ba0425713b4adeb0f2d4000da9e (diff)
iwlwifi: enable serialization of synchronous commands
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 <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c1
7 files changed, 13 insertions, 10 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 4157c6c8645f..52b6beb371fe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3364,6 +3364,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
3364 INIT_LIST_HEAD(&priv->free_frames); 3364 INIT_LIST_HEAD(&priv->free_frames);
3365 3365
3366 mutex_init(&priv->mutex); 3366 mutex_init(&priv->mutex);
3367 mutex_init(&priv->sync_cmd_mutex);
3367 3368
3368 /* Clear the driver's (not device's) station table */ 3369 /* Clear the driver's (not device's) station table */
3369 iwl_clear_stations_table(priv); 3370 iwl_clear_stations_table(priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 530fae8cf16d..6347d4b5c22f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -603,7 +603,7 @@ void iwlcore_free_geos(struct iwl_priv *priv);
603/*************** DRIVER STATUS FUNCTIONS *****/ 603/*************** DRIVER STATUS FUNCTIONS *****/
604 604
605#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ 605#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
606#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ 606/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */
607#define STATUS_INT_ENABLED 2 607#define STATUS_INT_ENABLED 2
608#define STATUS_RF_KILL_HW 3 608#define STATUS_RF_KILL_HW 3
609#define STATUS_CT_KILL 4 609#define STATUS_CT_KILL 4
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 78298be0bdb6..7241fda022c5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -530,8 +530,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
530 530
531 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", 531 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
532 test_bit(STATUS_HCMD_ACTIVE, &priv->status)); 532 test_bit(STATUS_HCMD_ACTIVE, &priv->status));
533 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_SYNC_ACTIVE: %d\n",
534 test_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status));
535 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", 533 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
536 test_bit(STATUS_INT_ENABLED, &priv->status)); 534 test_bit(STATUS_INT_ENABLED, &priv->status));
537 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", 535 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index f81317d478ee..021c68658718 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1111,6 +1111,7 @@ struct iwl_priv {
1111 spinlock_t hcmd_lock; /* protect hcmd */ 1111 spinlock_t hcmd_lock; /* protect hcmd */
1112 spinlock_t reg_lock; /* protect hw register access */ 1112 spinlock_t reg_lock; /* protect hw register access */
1113 struct mutex mutex; 1113 struct mutex mutex;
1114 struct mutex sync_cmd_mutex; /* enable serialization of sync commands */
1114 1115
1115 /* basic pci-network driver stuff */ 1116 /* basic pci-network driver stuff */
1116 struct pci_dev *pci_dev; 1117 struct pci_dev *pci_dev;
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 86783c27d97c..73681c4fefe7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -164,15 +164,13 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
164 /* A synchronous command can not have a callback set. */ 164 /* A synchronous command can not have a callback set. */
165 BUG_ON(cmd->callback); 165 BUG_ON(cmd->callback);
166 166
167 if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) { 167 IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
168 IWL_ERR(priv,
169 "Error sending %s: Already sending a host command\n",
170 get_cmd_string(cmd->id)); 168 get_cmd_string(cmd->id));
171 ret = -EBUSY; 169 mutex_lock(&priv->sync_cmd_mutex);
172 goto out;
173 }
174 170
175 set_bit(STATUS_HCMD_ACTIVE, &priv->status); 171 set_bit(STATUS_HCMD_ACTIVE, &priv->status);
172 IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s \n",
173 get_cmd_string(cmd->id));
176 174
177 cmd_idx = iwl_enqueue_hcmd(priv, cmd); 175 cmd_idx = iwl_enqueue_hcmd(priv, cmd);
178 if (cmd_idx < 0) { 176 if (cmd_idx < 0) {
@@ -193,6 +191,8 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
193 jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); 191 jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
194 192
195 clear_bit(STATUS_HCMD_ACTIVE, &priv->status); 193 clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
194 IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n",
195 get_cmd_string(cmd->id));
196 ret = -ETIMEDOUT; 196 ret = -ETIMEDOUT;
197 goto cancel; 197 goto cancel;
198 } 198 }
@@ -237,7 +237,7 @@ fail:
237 cmd->reply_page = 0; 237 cmd->reply_page = 0;
238 } 238 }
239out: 239out:
240 clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status); 240 mutex_unlock(&priv->sync_cmd_mutex);
241 return ret; 241 return ret;
242} 242}
243EXPORT_SYMBOL(iwl_send_cmd_sync); 243EXPORT_SYMBOL(iwl_send_cmd_sync);
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index d8c11f955e42..38655ad8f43c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -1238,6 +1238,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
1238 1238
1239 if (!(meta->flags & CMD_ASYNC)) { 1239 if (!(meta->flags & CMD_ASYNC)) {
1240 clear_bit(STATUS_HCMD_ACTIVE, &priv->status); 1240 clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
1241 IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n",
1242 get_cmd_string(cmd->hdr.cmd));
1241 wake_up_interruptible(&priv->wait_command_queue); 1243 wake_up_interruptible(&priv->wait_command_queue);
1242 } 1244 }
1243} 1245}
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 0e5a1ca30334..54daa38ecba3 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -3847,6 +3847,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
3847 INIT_LIST_HEAD(&priv->free_frames); 3847 INIT_LIST_HEAD(&priv->free_frames);
3848 3848
3849 mutex_init(&priv->mutex); 3849 mutex_init(&priv->mutex);
3850 mutex_init(&priv->sync_cmd_mutex);
3850 3851
3851 /* Clear the driver's (not device's) station table */ 3852 /* Clear the driver's (not device's) station table */
3852 iwl_clear_stations_table(priv); 3853 iwl_clear_stations_table(priv);