diff options
author | Reinette Chatre <reinette.chatre@intel.com> | 2010-02-19 01:03:04 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-02-19 15:52:49 -0500 |
commit | d2dfe6df755abb365aa3e2e67d88bda3cce5fd12 (patch) | |
tree | 5b24bd9cffb0ddfdd54554f2b5bace16c346ef99 | |
parent | 4a6547c748229ba0425713b4adeb0f2d4000da9e (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.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-hcmd.c | 14 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 |
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 | } |
239 | out: | 239 | out: |
240 | clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status); | 240 | mutex_unlock(&priv->sync_cmd_mutex); |
241 | return ret; | 241 | return ret; |
242 | } | 242 | } |
243 | EXPORT_SYMBOL(iwl_send_cmd_sync); | 243 | EXPORT_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); |