* [PATCH 1/3] iwlwifi: fix enqueue hcmd race conditions
@ 2011-03-31 15:36 Stanislaw Gruszka
2011-03-31 15:36 ` [PATCH 2/3] iwlwifi: more priv->mutex serialization Stanislaw Gruszka
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Stanislaw Gruszka @ 2011-03-31 15:36 UTC (permalink / raw)
To: Wey-Yi Guy; +Cc: Intel Linux Wireless, linux-wireless, Stanislaw Gruszka
We mark command as huge by using meta->flags from other (non huge) command,
but flags can be possibly overridden, when non huge command is enqueued,
what can lead to:
WARNING: at lib/dma-debug.c:696 dma_debug_device_change+0x1a3/0x1f0()
DMA-API: device driver has pending DMA allocations while released from device [count=1]
To fix introduce additional CMD_MAPPED to mark command as mapped and
serialize iwl_enqueue_hcmd() with iwl_tx_cmd_complete() using
hcmd_lock. Serialization will also fix possible race conditions,
because q->read_ptr, q->write_ptr are modified/used in parallel.
On the way fix whitespace.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/iwlwifi/iwl-dev.h | 1 +
drivers/net/wireless/iwlwifi/iwl-tx.c | 62 +++++++++++++++++---------------
2 files changed, 34 insertions(+), 29 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 68b953f..9e63bd8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -309,6 +309,7 @@ enum {
CMD_SIZE_HUGE = (1 << 0),
CMD_ASYNC = (1 << 1),
CMD_WANT_SKB = (1 << 2),
+ CMD_MAPPED = (1 << 3),
};
#define DEF_CMD_PAYLOAD_SIZE 320
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 277c917..39a4180 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -149,32 +149,31 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv)
struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
struct iwl_queue *q = &txq->q;
int i;
- bool huge = false;
if (q->n_bd == 0)
return;
while (q->read_ptr != q->write_ptr) {
- /* we have no way to tell if it is a huge cmd ATM */
i = get_cmd_index(q, q->read_ptr, 0);
- if (txq->meta[i].flags & CMD_SIZE_HUGE)
- huge = true;
- else
+ if (txq->meta[i].flags & CMD_MAPPED) {
pci_unmap_single(priv->pci_dev,
dma_unmap_addr(&txq->meta[i], mapping),
dma_unmap_len(&txq->meta[i], len),
PCI_DMA_BIDIRECTIONAL);
+ txq->meta[i].flags = 0;
+ }
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
}
- if (huge) {
- i = q->n_window;
+ i = q->n_window;
+ if (txq->meta[i].flags & CMD_MAPPED) {
pci_unmap_single(priv->pci_dev,
dma_unmap_addr(&txq->meta[i], mapping),
dma_unmap_len(&txq->meta[i], len),
PCI_DMA_BIDIRECTIONAL);
+ txq->meta[i].flags = 0;
}
}
@@ -463,7 +462,11 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
return -EIO;
}
+ spin_lock_irqsave(&priv->hcmd_lock, flags);
+
if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
+ spin_unlock_irqrestore(&priv->hcmd_lock, flags);
+
IWL_ERR(priv, "No space in command queue\n");
if (priv->cfg->ops->lib->tt_ops.ct_kill_check) {
is_ct_kill =
@@ -476,22 +479,17 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
return -ENOSPC;
}
- spin_lock_irqsave(&priv->hcmd_lock, flags);
-
- /* If this is a huge cmd, mark the huge flag also on the meta.flags
- * of the _original_ cmd. This is used for DMA mapping clean up.
- */
- if (cmd->flags & CMD_SIZE_HUGE) {
- idx = get_cmd_index(q, q->write_ptr, 0);
- txq->meta[idx].flags = CMD_SIZE_HUGE;
- }
-
idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE);
out_cmd = txq->cmd[idx];
out_meta = &txq->meta[idx];
+ if (WARN_ON(out_meta->flags & CMD_MAPPED)) {
+ spin_unlock_irqrestore(&priv->hcmd_lock, flags);
+ return -ENOSPC;
+ }
+
memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */
- out_meta->flags = cmd->flags;
+ out_meta->flags = cmd->flags | CMD_MAPPED;
if (cmd->flags & CMD_WANT_SKB)
out_meta->source = cmd;
if (cmd->flags & CMD_ASYNC)
@@ -609,6 +607,10 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
struct iwl_device_cmd *cmd;
struct iwl_cmd_meta *meta;
struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
+ unsigned long flags;
+ void (*callback) (struct iwl_priv *priv, struct iwl_device_cmd *cmd,
+ struct iwl_rx_packet *pkt);
+
/* If a Tx command is being handled and it isn't in the actual
* command queue then there a command routing bug has been introduced
@@ -622,14 +624,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
return;
}
- /* If this is a huge cmd, clear the huge flag on the meta.flags
- * of the _original_ cmd. So that iwl_cmd_queue_free won't unmap
- * the DMA buffer for the scan (huge) command.
- */
- if (huge) {
- cmd_index = get_cmd_index(&txq->q, index, 0);
- txq->meta[cmd_index].flags = 0;
- }
+ spin_lock_irqsave(&priv->hcmd_lock, flags);
+
cmd_index = get_cmd_index(&txq->q, index, huge);
cmd = txq->cmd[cmd_index];
meta = &txq->meta[cmd_index];
@@ -639,12 +635,13 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
dma_unmap_len(meta, len),
PCI_DMA_BIDIRECTIONAL);
+ callback = NULL;
/* Input error checking is done when commands are added to queue. */
if (meta->flags & CMD_WANT_SKB) {
meta->source->reply_page = (unsigned long)rxb_addr(rxb);
rxb->page = NULL;
- } else if (meta->callback)
- meta->callback(priv, cmd, pkt);
+ } else
+ callback = meta->callback;
iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);
@@ -654,5 +651,12 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
get_cmd_string(cmd->hdr.cmd));
wake_up_interruptible(&priv->wait_command_queue);
}
+
+ /* Mark as unmapped */
meta->flags = 0;
+
+ spin_unlock_irqrestore(&priv->hcmd_lock, flags);
+
+ if (callback)
+ callback(priv, cmd, pkt);
}
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/3] iwlwifi: more priv->mutex serialization
2011-03-31 15:36 [PATCH 1/3] iwlwifi: fix enqueue hcmd race conditions Stanislaw Gruszka
@ 2011-03-31 15:36 ` Stanislaw Gruszka
2011-03-31 16:15 ` wwguy
2011-03-31 15:36 ` [PATCH 3/3] iwlwifi: remove sync_cmd_mutex Stanislaw Gruszka
2011-03-31 16:36 ` [PATCH 1/3] iwlwifi: fix enqueue hcmd race conditions Guy, Wey-Yi W
2 siblings, 1 reply; 10+ messages in thread
From: Stanislaw Gruszka @ 2011-03-31 15:36 UTC (permalink / raw)
To: Wey-Yi Guy; +Cc: Intel Linux Wireless, linux-wireless, Stanislaw Gruszka
Check status bits with mutex taken, because when we wait for mutex
unlock, status can change. Patch should also make remaining sync
commands be send with priv->mutex taken. That will prevent execute
these commands when we are currently reset firmware, what could
possibly cause troubles.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/iwlwifi/iwl-agn.c | 34 ++++++++++++++++++-------------
1 files changed, 20 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 7adc60e..0c49d1a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -483,12 +483,14 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
container_of(work, struct iwl_priv, bt_full_concurrency);
struct iwl_rxon_context *ctx;
+ mutex_lock(&priv->mutex);
+
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
+ goto out;
/* dont send host command if rf-kill is on */
if (!iwl_is_ready_rf(priv))
- return;
+ goto out;
IWL_DEBUG_INFO(priv, "BT coex in %s mode\n",
priv->bt_full_concurrent ?
@@ -498,15 +500,15 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
* LQ & RXON updated cmds must be sent before BT Config cmd
* to avoid 3-wire collisions
*/
- mutex_lock(&priv->mutex);
for_each_context(priv, ctx) {
if (priv->cfg->ops->hcmd->set_rxon_chain)
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
iwlcore_commit_rxon(priv, ctx);
}
- mutex_unlock(&priv->mutex);
priv->cfg->ops->hcmd->send_bt_config(priv);
+out:
+ mutex_unlock(&priv->mutex);
}
/**
@@ -2814,10 +2816,13 @@ static void iwl_bg_init_alive_start(struct work_struct *data)
struct iwl_priv *priv =
container_of(data, struct iwl_priv, init_alive_start.work);
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ mutex_lock(&priv->mutex);
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
+ mutex_unlock(&priv->mutex);
return;
+ }
- mutex_lock(&priv->mutex);
priv->cfg->ops->lib->init_alive_start(priv);
mutex_unlock(&priv->mutex);
}
@@ -2827,15 +2832,16 @@ static void iwl_bg_alive_start(struct work_struct *data)
struct iwl_priv *priv =
container_of(data, struct iwl_priv, alive_start.work);
+ mutex_lock(&priv->mutex);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
+ goto unlock;
/* enable dram interrupt */
if (priv->cfg->ops->lib->isr_ops.reset)
priv->cfg->ops->lib->isr_ops.reset(priv);
- mutex_lock(&priv->mutex);
iwl_alive_start(priv);
+unlock:
mutex_unlock(&priv->mutex);
}
@@ -3457,21 +3463,22 @@ void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "enter\n");
+ mutex_lock(&priv->mutex);
+
if (iwl_is_rfkill(priv))
- goto out_exit;
+ goto out;
if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
test_bit(STATUS_SCANNING, &priv->status))
- goto out_exit;
+ goto out;
if (!iwl_is_associated_ctx(ctx))
- goto out_exit;
+ goto out;
/* channel switch in progress */
if (priv->switch_rxon.switch_in_progress == true)
- goto out_exit;
+ goto out;
- mutex_lock(&priv->mutex);
if (priv->cfg->ops->lib->set_channel_switch) {
ch = channel->hw_value;
@@ -3527,7 +3534,6 @@ void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
}
out:
mutex_unlock(&priv->mutex);
-out_exit:
if (!priv->switch_rxon.switch_in_progress)
ieee80211_chswitch_done(ctx->vif, false);
IWL_DEBUG_MAC80211(priv, "leave\n");
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/3] iwlwifi: remove sync_cmd_mutex
2011-03-31 15:36 [PATCH 1/3] iwlwifi: fix enqueue hcmd race conditions Stanislaw Gruszka
2011-03-31 15:36 ` [PATCH 2/3] iwlwifi: more priv->mutex serialization Stanislaw Gruszka
@ 2011-03-31 15:36 ` Stanislaw Gruszka
2011-03-31 16:18 ` wwguy
2011-03-31 16:36 ` [PATCH 1/3] iwlwifi: fix enqueue hcmd race conditions Guy, Wey-Yi W
2 siblings, 1 reply; 10+ messages in thread
From: Stanislaw Gruszka @ 2011-03-31 15:36 UTC (permalink / raw)
To: Wey-Yi Guy; +Cc: Intel Linux Wireless, linux-wireless, Stanislaw Gruszka
We now use priv->mutex to serialize sync command, remove old
priv->sync_cmd_mutex and add assertion that priv->mutex must be locked.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ----
drivers/net/wireless/iwlwifi/iwl-dev.h | 1 -
drivers/net/wireless/iwlwifi/iwl-hcmd.c | 13 +++++--------
3 files changed, 5 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 0c49d1a..6f188fd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2565,9 +2565,6 @@ static void __iwl_down(struct iwl_priv *priv)
priv->bt_full_concurrent = false;
priv->bt_ci_compliance = 0;
- /* Unblock any waiting calls */
- wake_up_interruptible_all(&priv->wait_command_queue);
-
/* Wipe out the EXIT_PENDING status bit if we are not actually
* exiting the module */
if (!exit_pending)
@@ -3814,7 +3811,6 @@ 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);
priv->ieee_channels = NULL;
priv->ieee_rates = NULL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 9e63bd8..ca30f95 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1306,7 +1306,6 @@ 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;
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 02499f6..c71c0a4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -171,14 +171,13 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
int cmd_idx;
int ret;
- BUG_ON(cmd->flags & CMD_ASYNC);
+ lockdep_assert_held(&priv->mutex);
/* A synchronous command can not have a callback set. */
- BUG_ON(cmd->callback);
+ BUG_ON((cmd->flags & CMD_ASYNC) || cmd->callback);
IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
get_cmd_string(cmd->id));
- mutex_lock(&priv->sync_cmd_mutex);
set_bit(STATUS_HCMD_ACTIVE, &priv->status);
IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n",
@@ -189,7 +188,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
ret = cmd_idx;
IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
get_cmd_string(cmd->id), ret);
- goto out;
+ return ret;
}
ret = wait_event_interruptible_timeout(priv->wait_command_queue,
@@ -229,8 +228,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
goto cancel;
}
- ret = 0;
- goto out;
+ return 0;
cancel:
if (cmd->flags & CMD_WANT_SKB) {
@@ -248,8 +246,7 @@ fail:
iwl_free_pages(priv, cmd->reply_page);
cmd->reply_page = 0;
}
-out:
- mutex_unlock(&priv->sync_cmd_mutex);
+
return ret;
}
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 2/3] iwlwifi: more priv->mutex serialization
2011-03-31 15:36 ` [PATCH 2/3] iwlwifi: more priv->mutex serialization Stanislaw Gruszka
@ 2011-03-31 16:15 ` wwguy
0 siblings, 0 replies; 10+ messages in thread
From: wwguy @ 2011-03-31 16:15 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: Intel Linux Wireless, linux-wireless@vger.kernel.org
On Thu, 2011-03-31 at 08:36 -0700, Stanislaw Gruszka wrote:
> Check status bits with mutex taken, because when we wait for mutex
> unlock, status can change. Patch should also make remaining sync
> commands be send with priv->mutex taken. That will prevent execute
> these commands when we are currently reset firmware, what could
> possibly cause troubles.
>
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Acked-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
> ---
> drivers/net/wireless/iwlwifi/iwl-agn.c | 34 ++++++++++++++++++-------------
> 1 files changed, 20 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
> index 7adc60e..0c49d1a 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-agn.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
> @@ -483,12 +483,14 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
> container_of(work, struct iwl_priv, bt_full_concurrency);
> struct iwl_rxon_context *ctx;
>
> + mutex_lock(&priv->mutex);
> +
> if (test_bit(STATUS_EXIT_PENDING, &priv->status))
> - return;
> + goto out;
>
> /* dont send host command if rf-kill is on */
> if (!iwl_is_ready_rf(priv))
> - return;
> + goto out;
>
> IWL_DEBUG_INFO(priv, "BT coex in %s mode\n",
> priv->bt_full_concurrent ?
> @@ -498,15 +500,15 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
> * LQ & RXON updated cmds must be sent before BT Config cmd
> * to avoid 3-wire collisions
> */
> - mutex_lock(&priv->mutex);
> for_each_context(priv, ctx) {
> if (priv->cfg->ops->hcmd->set_rxon_chain)
> priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
> iwlcore_commit_rxon(priv, ctx);
> }
> - mutex_unlock(&priv->mutex);
>
> priv->cfg->ops->hcmd->send_bt_config(priv);
> +out:
> + mutex_unlock(&priv->mutex);
> }
>
> /**
> @@ -2814,10 +2816,13 @@ static void iwl_bg_init_alive_start(struct work_struct *data)
> struct iwl_priv *priv =
> container_of(data, struct iwl_priv, init_alive_start.work);
>
> - if (test_bit(STATUS_EXIT_PENDING, &priv->status))
> + mutex_lock(&priv->mutex);
> +
> + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
> + mutex_unlock(&priv->mutex);
> return;
> + }
>
> - mutex_lock(&priv->mutex);
> priv->cfg->ops->lib->init_alive_start(priv);
> mutex_unlock(&priv->mutex);
> }
> @@ -2827,15 +2832,16 @@ static void iwl_bg_alive_start(struct work_struct *data)
> struct iwl_priv *priv =
> container_of(data, struct iwl_priv, alive_start.work);
>
> + mutex_lock(&priv->mutex);
> if (test_bit(STATUS_EXIT_PENDING, &priv->status))
> - return;
> + goto unlock;
>
> /* enable dram interrupt */
> if (priv->cfg->ops->lib->isr_ops.reset)
> priv->cfg->ops->lib->isr_ops.reset(priv);
>
> - mutex_lock(&priv->mutex);
> iwl_alive_start(priv);
> +unlock:
> mutex_unlock(&priv->mutex);
> }
>
> @@ -3457,21 +3463,22 @@ void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
>
> IWL_DEBUG_MAC80211(priv, "enter\n");
>
> + mutex_lock(&priv->mutex);
> +
> if (iwl_is_rfkill(priv))
> - goto out_exit;
> + goto out;
>
> if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
> test_bit(STATUS_SCANNING, &priv->status))
> - goto out_exit;
> + goto out;
>
> if (!iwl_is_associated_ctx(ctx))
> - goto out_exit;
> + goto out;
>
> /* channel switch in progress */
> if (priv->switch_rxon.switch_in_progress == true)
> - goto out_exit;
> + goto out;
>
> - mutex_lock(&priv->mutex);
> if (priv->cfg->ops->lib->set_channel_switch) {
>
> ch = channel->hw_value;
> @@ -3527,7 +3534,6 @@ void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
> }
> out:
> mutex_unlock(&priv->mutex);
> -out_exit:
> if (!priv->switch_rxon.switch_in_progress)
> ieee80211_chswitch_done(ctx->vif, false);
> IWL_DEBUG_MAC80211(priv, "leave\n");
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 3/3] iwlwifi: remove sync_cmd_mutex
2011-03-31 15:36 ` [PATCH 3/3] iwlwifi: remove sync_cmd_mutex Stanislaw Gruszka
@ 2011-03-31 16:18 ` wwguy
0 siblings, 0 replies; 10+ messages in thread
From: wwguy @ 2011-03-31 16:18 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: Intel Linux Wireless, linux-wireless@vger.kernel.org
On Thu, 2011-03-31 at 08:36 -0700, Stanislaw Gruszka wrote:
> We now use priv->mutex to serialize sync command, remove old
> priv->sync_cmd_mutex and add assertion that priv->mutex must be locked.
>
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Acked-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
> ---
> drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ----
> drivers/net/wireless/iwlwifi/iwl-dev.h | 1 -
> drivers/net/wireless/iwlwifi/iwl-hcmd.c | 13 +++++--------
> 3 files changed, 5 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
> index 0c49d1a..6f188fd 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-agn.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
> @@ -2565,9 +2565,6 @@ static void __iwl_down(struct iwl_priv *priv)
> priv->bt_full_concurrent = false;
> priv->bt_ci_compliance = 0;
>
> - /* Unblock any waiting calls */
> - wake_up_interruptible_all(&priv->wait_command_queue);
> -
> /* Wipe out the EXIT_PENDING status bit if we are not actually
> * exiting the module */
> if (!exit_pending)
> @@ -3814,7 +3811,6 @@ 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);
>
> priv->ieee_channels = NULL;
> priv->ieee_rates = NULL;
> diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
> index 9e63bd8..ca30f95 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-dev.h
> +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
> @@ -1306,7 +1306,6 @@ 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;
> diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
> index 02499f6..c71c0a4 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
> @@ -171,14 +171,13 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
> int cmd_idx;
> int ret;
>
> - BUG_ON(cmd->flags & CMD_ASYNC);
> + lockdep_assert_held(&priv->mutex);
>
> /* A synchronous command can not have a callback set. */
> - BUG_ON(cmd->callback);
> + BUG_ON((cmd->flags & CMD_ASYNC) || cmd->callback);
>
> IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
> get_cmd_string(cmd->id));
> - mutex_lock(&priv->sync_cmd_mutex);
>
> set_bit(STATUS_HCMD_ACTIVE, &priv->status);
> IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n",
> @@ -189,7 +188,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
> ret = cmd_idx;
> IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
> get_cmd_string(cmd->id), ret);
> - goto out;
> + return ret;
> }
>
> ret = wait_event_interruptible_timeout(priv->wait_command_queue,
> @@ -229,8 +228,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
> goto cancel;
> }
>
> - ret = 0;
> - goto out;
> + return 0;
>
> cancel:
> if (cmd->flags & CMD_WANT_SKB) {
> @@ -248,8 +246,7 @@ fail:
> iwl_free_pages(priv, cmd->reply_page);
> cmd->reply_page = 0;
> }
> -out:
> - mutex_unlock(&priv->sync_cmd_mutex);
> +
> return ret;
> }
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH 1/3] iwlwifi: fix enqueue hcmd race conditions
2011-03-31 15:36 [PATCH 1/3] iwlwifi: fix enqueue hcmd race conditions Stanislaw Gruszka
2011-03-31 15:36 ` [PATCH 2/3] iwlwifi: more priv->mutex serialization Stanislaw Gruszka
2011-03-31 15:36 ` [PATCH 3/3] iwlwifi: remove sync_cmd_mutex Stanislaw Gruszka
@ 2011-03-31 16:36 ` Guy, Wey-Yi W
2011-04-01 7:22 ` Stanislaw Gruszka
2 siblings, 1 reply; 10+ messages in thread
From: Guy, Wey-Yi W @ 2011-03-31 16:36 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: Intel Linux Wireless, linux-wireless@vger.kernel.org
Stanislaw,
-----Original Message-----
From: Stanislaw Gruszka [mailto:sgruszka@redhat.com]
Sent: Thursday, March 31, 2011 8:36 AM
To: Guy, Wey-Yi W
Cc: Intel Linux Wireless; linux-wireless@vger.kernel.org; Stanislaw Gruszka
Subject: [PATCH 1/3] iwlwifi: fix enqueue hcmd race conditions
We mark command as huge by using meta->flags from other (non huge) command,
but flags can be possibly overridden, when non huge command is enqueued,
what can lead to:
WARNING: at lib/dma-debug.c:696 dma_debug_device_change+0x1a3/0x1f0()
DMA-API: device driver has pending DMA allocations while released from device [count=1]
To fix introduce additional CMD_MAPPED to mark command as mapped and
serialize iwl_enqueue_hcmd() with iwl_tx_cmd_complete() using
hcmd_lock. Serialization will also fix possible race conditions,
because q->read_ptr, q->write_ptr are modified/used in parallel.
On the way fix whitespace.
Do you have a bug# against this?
Thanks
Wey
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/3] iwlwifi: fix enqueue hcmd race conditions
2011-03-31 16:36 ` [PATCH 1/3] iwlwifi: fix enqueue hcmd race conditions Guy, Wey-Yi W
@ 2011-04-01 7:22 ` Stanislaw Gruszka
2011-04-01 15:07 ` wwguy
0 siblings, 1 reply; 10+ messages in thread
From: Stanislaw Gruszka @ 2011-04-01 7:22 UTC (permalink / raw)
To: Guy, Wey-Yi W; +Cc: Intel Linux Wireless, linux-wireless@vger.kernel.org
Hi Wey
> Do you have a bug# against this?
No, I was fixing problems happened on my local system.
Stanislaw
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/3] iwlwifi: fix enqueue hcmd race conditions
2011-04-01 7:22 ` Stanislaw Gruszka
@ 2011-04-01 15:07 ` wwguy
2011-04-06 14:18 ` Stanislaw Gruszka
0 siblings, 1 reply; 10+ messages in thread
From: wwguy @ 2011-04-01 15:07 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: Intel Linux Wireless, linux-wireless@vger.kernel.org
On Fri, 2011-04-01 at 00:22 -0700, Stanislaw Gruszka wrote:
> Hi Wey
>
> > Do you have a bug# against this?
> No, I was fixing problems happened on my local system.
>
fair enough :-), thanks for the update
Wey
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/3] iwlwifi: fix enqueue hcmd race conditions
2011-04-01 15:07 ` wwguy
@ 2011-04-06 14:18 ` Stanislaw Gruszka
2011-04-06 14:21 ` Guy, Wey-Yi
0 siblings, 1 reply; 10+ messages in thread
From: Stanislaw Gruszka @ 2011-04-06 14:18 UTC (permalink / raw)
To: wwguy, John W. Linville
Cc: Intel Linux Wireless, linux-wireless@vger.kernel.org
On Fri, Apr 01, 2011 at 08:07:25AM -0700, wwguy wrote:
> > > Do you have a bug# against this?
> > No, I was fixing problems happened on my local system.
> >
> fair enough :-), thanks for the update
So we could consider patch as acked.
Stanislaw
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/3] iwlwifi: fix enqueue hcmd race conditions
2011-04-06 14:18 ` Stanislaw Gruszka
@ 2011-04-06 14:21 ` Guy, Wey-Yi
0 siblings, 0 replies; 10+ messages in thread
From: Guy, Wey-Yi @ 2011-04-06 14:21 UTC (permalink / raw)
To: Stanislaw Gruszka
Cc: John W. Linville, Intel Linux Wireless,
linux-wireless@vger.kernel.org
On Wed, 2011-04-06 at 07:18 -0700, Stanislaw Gruszka wrote:
> On Fri, Apr 01, 2011 at 08:07:25AM -0700, wwguy wrote:
> > > > Do you have a bug# against this?
> > > No, I was fixing problems happened on my local system.
> > >
> > fair enough :-), thanks for the update
>
> So we could consider patch as acked.
forgot to "ack", sorry :-)
Wey
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-04-06 14:41 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-31 15:36 [PATCH 1/3] iwlwifi: fix enqueue hcmd race conditions Stanislaw Gruszka
2011-03-31 15:36 ` [PATCH 2/3] iwlwifi: more priv->mutex serialization Stanislaw Gruszka
2011-03-31 16:15 ` wwguy
2011-03-31 15:36 ` [PATCH 3/3] iwlwifi: remove sync_cmd_mutex Stanislaw Gruszka
2011-03-31 16:18 ` wwguy
2011-03-31 16:36 ` [PATCH 1/3] iwlwifi: fix enqueue hcmd race conditions Guy, Wey-Yi W
2011-04-01 7:22 ` Stanislaw Gruszka
2011-04-01 15:07 ` wwguy
2011-04-06 14:18 ` Stanislaw Gruszka
2011-04-06 14:21 ` Guy, Wey-Yi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).