Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 352669
b: refs/heads/master
c: 2bfb509
h: refs/heads/master
i:
  352667: 6436e5e
v: v3
  • Loading branch information
Johannes Berg committed Feb 5, 2013
1 parent 9e7c265 commit 7b67bb5
Show file tree
Hide file tree
Showing 12 changed files with 86 additions and 53 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c9f7a8ab7792b48259af6e94706a5d02dd74caef
refs/heads/master: 2bfb50924c7e92362ac937aef2ab56bc7bd3ca52
2 changes: 1 addition & 1 deletion trunk/drivers/net/wireless/iwlwifi/dvm/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,

memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));

ieee80211_rx(priv->hw, skb);
ieee80211_rx_ni(priv->hw, skb);
}

static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/net/wireless/iwlwifi/dvm/sta.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
sta_id);

spin_lock(&priv->sta_lock);
spin_lock_bh(&priv->sta_lock);

switch (add_sta_resp->status) {
case ADD_STA_SUCCESS_MSK:
Expand Down Expand Up @@ -119,7 +119,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
priv->stations[sta_id].sta.mode ==
STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
addsta->sta.addr);
spin_unlock(&priv->sta_lock);
spin_unlock_bh(&priv->sta_lock);

return ret;
}
Expand Down
16 changes: 8 additions & 8 deletions trunk/drivers/net/wireless/iwlwifi/dvm/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1117,7 +1117,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
IWLAGN_TX_RES_RA_POS;

spin_lock(&priv->sta_lock);
spin_lock_bh(&priv->sta_lock);

if (is_agg)
iwl_rx_reply_tx_agg(priv, tx_resp);
Expand Down Expand Up @@ -1239,11 +1239,11 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
le16_to_cpu(tx_resp->seq_ctl));

iwl_check_abort_status(priv, tx_resp->frame_count, status);
spin_unlock(&priv->sta_lock);
spin_unlock_bh(&priv->sta_lock);

while (!skb_queue_empty(&skbs)) {
skb = __skb_dequeue(&skbs);
ieee80211_tx_status(priv->hw, skb);
ieee80211_tx_status_ni(priv->hw, skb);
}

if (is_offchannel_skb)
Expand Down Expand Up @@ -1290,12 +1290,12 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
tid = ba_resp->tid;
agg = &priv->tid_data[sta_id][tid].agg;

spin_lock(&priv->sta_lock);
spin_lock_bh(&priv->sta_lock);

if (unlikely(!agg->wait_for_ba)) {
if (unlikely(ba_resp->bitmap))
IWL_ERR(priv, "Received BA when not expected\n");
spin_unlock(&priv->sta_lock);
spin_unlock_bh(&priv->sta_lock);
return 0;
}

Expand All @@ -1309,7 +1309,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
IWL_DEBUG_TX_QUEUES(priv,
"Bad queue mapping txq_id=%d, agg_txq[sta:%d,tid:%d]=%d\n",
scd_flow, sta_id, tid, agg->txq_id);
spin_unlock(&priv->sta_lock);
spin_unlock_bh(&priv->sta_lock);
return 0;
}

Expand Down Expand Up @@ -1378,11 +1378,11 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
}
}

spin_unlock(&priv->sta_lock);
spin_unlock_bh(&priv->sta_lock);

while (!skb_queue_empty(&reclaimed_skbs)) {
skb = __skb_dequeue(&reclaimed_skbs);
ieee80211_tx_status(priv->hw, skb);
ieee80211_tx_status_ni(priv->hw, skb);
}

return 0;
Expand Down
10 changes: 6 additions & 4 deletions trunk/drivers/net/wireless/iwlwifi/iwl-op-mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,13 @@ struct iwl_cfg;
* May sleep
* @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the
* HCMD the this Rx responds to.
* Must be atomic and called with BH disabled.
* This callback may sleep, it is called from a threaded IRQ handler.
* @queue_full: notifies that a HW queue is full.
* Must be atomic and called with BH disabled.
* @queue_not_full: notifies that a HW queue is not full any more.
* Must be atomic and called with BH disabled.
* @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that
* the radio is killed. Must be atomic.
* the radio is killed. May sleep.
* @free_skb: allows the transport layer to free skbs that haven't been
* reclaimed by the op_mode. This can happen when the driver is freed and
* there are Tx packets pending in the transport layer.
Expand All @@ -130,8 +130,7 @@ struct iwl_cfg;
* called with BH disabled.
* @nic_config: configure NIC, called before firmware is started.
* May sleep
* @wimax_active: invoked when WiMax becomes active. Must be atomic and called
* with BH disabled.
* @wimax_active: invoked when WiMax becomes active. May sleep
*/
struct iwl_op_mode_ops {
struct iwl_op_mode *(*start)(struct iwl_trans *trans,
Expand Down Expand Up @@ -178,6 +177,7 @@ static inline int iwl_op_mode_rx(struct iwl_op_mode *op_mode,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
might_sleep();
return op_mode->ops->rx(op_mode, rxb, cmd);
}

Expand All @@ -196,6 +196,7 @@ static inline void iwl_op_mode_queue_not_full(struct iwl_op_mode *op_mode,
static inline void iwl_op_mode_hw_rf_kill(struct iwl_op_mode *op_mode,
bool state)
{
might_sleep();
op_mode->ops->hw_rf_kill(op_mode, state);
}

Expand Down Expand Up @@ -223,6 +224,7 @@ static inline void iwl_op_mode_nic_config(struct iwl_op_mode *op_mode)

static inline void iwl_op_mode_wimax_active(struct iwl_op_mode *op_mode)
{
might_sleep();
op_mode->ops->wimax_active(op_mode);
}

Expand Down
29 changes: 27 additions & 2 deletions trunk/drivers/net/wireless/iwlwifi/iwl-trans.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@

#include <linux/ieee80211.h>
#include <linux/mm.h> /* for page_address */
#include <linux/lockdep.h>

#include "iwl-debug.h"
#include "iwl-config.h"
Expand Down Expand Up @@ -526,6 +527,10 @@ struct iwl_trans {

struct dentry *dbgfs_dir;

#ifdef CONFIG_LOCKDEP
struct lockdep_map sync_cmd_lockdep_map;
#endif

/* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
char trans_specific[0] __aligned(sizeof(void *));
Expand Down Expand Up @@ -602,12 +607,22 @@ static inline int iwl_trans_d3_resume(struct iwl_trans *trans,
}

static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
struct iwl_host_cmd *cmd)
{
int ret;

WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
"%s bad state = %d", __func__, trans->state);

return trans->ops->send_cmd(trans, cmd);
if (!(cmd->flags & CMD_ASYNC))
lock_map_acquire_read(&trans->sync_cmd_lockdep_map);

ret = trans->ops->send_cmd(trans, cmd);

if (!(cmd->flags & CMD_ASYNC))
lock_map_release(&trans->sync_cmd_lockdep_map);

return ret;
}

static inline struct iwl_device_cmd *
Expand Down Expand Up @@ -791,4 +806,14 @@ iwl_trans_release_nic_access(struct iwl_trans *trans, unsigned long *flags)
int __must_check iwl_pci_register_driver(void);
void iwl_pci_unregister_driver(void);

static inline void trans_lockdep_init(struct iwl_trans *trans)
{
#ifdef CONFIG_LOCKDEP
static struct lock_class_key __key;

lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map",
&__key, 0);
#endif
}

#endif /* __iwl_trans_h__ */
2 changes: 1 addition & 1 deletion trunk/drivers/net/wireless/iwlwifi/mvm/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,

memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));

ieee80211_rx(mvm->hw, skb);
ieee80211_rx_ni(mvm->hw, skb);
}

/*
Expand Down
12 changes: 6 additions & 6 deletions trunk/drivers/net/wireless/iwlwifi/mvm/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
seq_ctl = le16_to_cpu(hdr->seq_ctrl);
}

ieee80211_tx_status(mvm->hw, skb);
ieee80211_tx_status_ni(mvm->hw, skb);
}

if (txq_id >= IWL_FIRST_AMPDU_QUEUE) {
Expand Down Expand Up @@ -663,12 +663,12 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
struct iwl_mvm_tid_data *tid_data =
&mvmsta->tid_data[tid];

spin_lock(&mvmsta->lock);
spin_lock_bh(&mvmsta->lock);
tid_data->next_reclaimed = next_reclaimed;
IWL_DEBUG_TX_REPLY(mvm, "Next reclaimed packet:%d\n",
next_reclaimed);
iwl_mvm_check_ratid_empty(mvm, sta, tid);
spin_unlock(&mvmsta->lock);
spin_unlock_bh(&mvmsta->lock);
}

#ifdef CONFIG_PM_SLEEP
Expand Down Expand Up @@ -832,7 +832,7 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
return 0;
}

spin_lock(&mvmsta->lock);
spin_lock_bh(&mvmsta->lock);

__skb_queue_head_init(&reclaimed_skbs);

Expand Down Expand Up @@ -886,13 +886,13 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
}
}

spin_unlock(&mvmsta->lock);
spin_unlock_bh(&mvmsta->lock);

rcu_read_unlock();

while (!skb_queue_empty(&reclaimed_skbs)) {
skb = __skb_dequeue(&reclaimed_skbs);
ieee80211_tx_status(mvm->hw, skb);
ieee80211_tx_status_ni(mvm->hw, skb);
}

return 0;
Expand Down
3 changes: 1 addition & 2 deletions trunk/drivers/net/wireless/iwlwifi/pcie/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,6 @@ struct iwl_trans_pcie {
int ict_index;
u32 inta;
bool use_ict;
struct tasklet_struct irq_tasklet;
struct isr_statistics isr_stats;

spinlock_t irq_lock;
Expand Down Expand Up @@ -330,7 +329,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans);
* RX
******************************************************/
int iwl_pcie_rx_init(struct iwl_trans *trans);
void iwl_pcie_tasklet(struct iwl_trans *trans);
irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id);
int iwl_pcie_rx_stop(struct iwl_trans *trans);
void iwl_pcie_rx_free(struct iwl_trans *trans);

Expand Down
40 changes: 25 additions & 15 deletions trunk/drivers/net/wireless/iwlwifi/pcie/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@
* 'processed' and 'read' driver indexes as well)
* + A received packet is processed and handed to the kernel network stack,
* detached from the iwl->rxq. The driver 'processed' index is updated.
* + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
* list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
* INDEX is not incremented and iwl->status(RX_STALLED) is set. If there
* were enough free buffers and RX_STALLED is set it is cleared.
* + The Host/Firmware iwl->rxq is replenished at irq thread time from the
* rx_free list. If there are no allocated buffers in iwl->rxq->rx_free,
* the READ INDEX is not incremented and iwl->status(RX_STALLED) is set.
* If there were enough free buffers and RX_STALLED is set it is cleared.
*
*
* Driver sequence:
Expand Down Expand Up @@ -214,9 +214,9 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
/*
* If the device isn't enabled - not need to try to add buffers...
* This can happen when we stop the device and still have an interrupt
* pending. We stop the APM before we sync the interrupts / tasklets
* because we have to (see comment there). On the other hand, since
* the APM is stopped, we cannot access the HW (in particular not prph).
* pending. We stop the APM before we sync the interrupts because we
* have to (see comment there). On the other hand, since the APM is
* stopped, we cannot access the HW (in particular not prph).
* So don't try to restock if the APM has been already stopped.
*/
if (!test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status))
Expand Down Expand Up @@ -796,11 +796,14 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
wake_up(&trans_pcie->wait_command_queue);

local_bh_disable();
iwl_op_mode_nic_error(trans->op_mode);
local_bh_enable();
}

void iwl_pcie_tasklet(struct iwl_trans *trans)
irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
{
struct iwl_trans *trans = dev_id;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
u32 inta = 0;
Expand All @@ -811,6 +814,8 @@ void iwl_pcie_tasklet(struct iwl_trans *trans)
u32 inta_mask;
#endif

lock_map_acquire(&trans->sync_cmd_lockdep_map);

spin_lock_irqsave(&trans_pcie->irq_lock, flags);

/* Ack/clear/reset pending uCode interrupts.
Expand Down Expand Up @@ -855,7 +860,7 @@ void iwl_pcie_tasklet(struct iwl_trans *trans)

handled |= CSR_INT_BIT_HW_ERR;

return;
goto out;
}

#ifdef CONFIG_IWLWIFI_DEBUG
Expand Down Expand Up @@ -1005,6 +1010,10 @@ void iwl_pcie_tasklet(struct iwl_trans *trans)
/* Re-enable RF_KILL if it occurred */
else if (handled & CSR_INT_BIT_RF_KILL)
iwl_enable_rfkill_int(trans);

out:
lock_map_release(&trans->sync_cmd_lockdep_map);
return IRQ_HANDLED;
}

/******************************************************************************
Expand Down Expand Up @@ -1127,7 +1136,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)

/* Disable (but don't clear!) interrupts here to avoid
* back-to-back ISRs and sporadic interrupts from our NIC.
* If we have something to service, the tasklet will re-enable ints.
* If we have something to service, the irq thread will re-enable ints.
* If we *don't* have something, we'll re-enable before leaving here. */
inta_mask = iwl_read32(trans, CSR_INT_MASK);
iwl_write32(trans, CSR_INT_MASK, 0x00000000);
Expand Down Expand Up @@ -1167,9 +1176,9 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
#endif

trans_pcie->inta |= inta;
/* iwl_pcie_tasklet() will service interrupts and re-enable them */
/* the thread will service interrupts and re-enable them */
if (likely(inta))
tasklet_schedule(&trans_pcie->irq_tasklet);
return IRQ_WAKE_THREAD;
else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
!trans_pcie->inta)
iwl_enable_interrupts(trans);
Expand Down Expand Up @@ -1277,9 +1286,10 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
trans_pcie->inta |= inta;

/* iwl_pcie_tasklet() will service interrupts and re-enable them */
if (likely(inta))
tasklet_schedule(&trans_pcie->irq_tasklet);
else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
if (likely(inta)) {
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
return IRQ_WAKE_THREAD;
} else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
!trans_pcie->inta) {
/* Allow interrupt if was disabled by this handler and
* no tasklet was schedules, We should not enable interrupt,
Expand Down
Loading

0 comments on commit 7b67bb5

Please sign in to comment.