Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 203503
b: refs/heads/master
c: 716c74b
h: refs/heads/master
i:
  203501: 3139f3f
  203499: d2c2c96
  203495: eda98a1
  203487: af37da7
v: v3
  • Loading branch information
Wey-Yi Guy committed Jul 2, 2010
1 parent 39c9a8b commit 9ef5977
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 947279eefb77f79015a79b032eb825a065ab035f
refs/heads/master: 716c74b00717ad9caedb4a46059fb64a3da99808
1 change: 1 addition & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-1000.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ static struct iwl_lib_ops iwl1000_lib = {
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
.txfifo_flush = iwlagn_txfifo_flush,
};

static const struct iwl_ops iwl1000_ops = {
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-5000.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
.txfifo_flush = iwlagn_txfifo_flush,
};

static struct iwl_lib_ops iwl5150_lib = {
Expand Down Expand Up @@ -465,6 +466,7 @@ static struct iwl_lib_ops iwl5150_lib = {
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
.txfifo_flush = iwlagn_txfifo_flush,
};

static const struct iwl_ops iwl5000_ops = {
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-6000.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ static struct iwl_lib_ops iwl6000_lib = {
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
.txfifo_flush = iwlagn_txfifo_flush,
};

static const struct iwl_ops iwl6000_ops = {
Expand Down
63 changes: 63 additions & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1435,3 +1435,66 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv,
priv->stations[sta_id].tid[tid].tfds_in_queue = 0;
}
}

#define IWL_FLUSH_WAIT_MS 2000

int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv)
{
struct iwl_tx_queue *txq;
struct iwl_queue *q;
int cnt;
unsigned long now = jiffies;
int ret = 0;

/* waiting for all the tx frames complete might take a while */
for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
if (cnt == IWL_CMD_QUEUE_NUM)
continue;
txq = &priv->txq[cnt];
q = &txq->q;
while (q->read_ptr != q->write_ptr && !time_after(jiffies,
now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS)))
msleep(1);

if (q->read_ptr != q->write_ptr) {
IWL_ERR(priv, "fail to flush all tx fifo queues\n");
ret = -ETIMEDOUT;
break;
}
}
return ret;
}

#define IWL_TX_QUEUE_MSK 0xfffff

/**
* iwlagn_txfifo_flush: send REPLY_TXFIFO_FLUSH command to uCode
*
* pre-requirements:
* 1. acquire mutex before calling
* 2. make sure rf is on and not in exit state
*/
int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
{
struct iwl_txfifo_flush_cmd flush_cmd;
struct iwl_host_cmd cmd = {
.id = REPLY_TXFIFO_FLUSH,
.len = sizeof(struct iwl_txfifo_flush_cmd),
.flags = CMD_SYNC,
.data = &flush_cmd,
};

might_sleep();

memset(&flush_cmd, 0, sizeof(flush_cmd));
flush_cmd.fifo_control = IWL_TX_FIFO_VO_MSK | IWL_TX_FIFO_VI_MSK |
IWL_TX_FIFO_BE_MSK | IWL_TX_FIFO_BK_MSK;
if (priv->cfg->sku & IWL_SKU_N)
flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;

IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
flush_cmd.fifo_control);
flush_cmd.flush_control = cpu_to_le16(flush_control);

return iwl_send_cmd(priv, &cmd);
}
39 changes: 39 additions & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-agn.c
Original file line number Diff line number Diff line change
Expand Up @@ -3639,6 +3639,44 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "leave\n");
}

static void iwl_mac_flush(struct ieee80211_hw *hw, bool drop)
{
struct iwl_priv *priv = hw->priv;

mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "enter\n");

/* do not support "flush" */
if (!priv->cfg->ops->lib->txfifo_flush)
goto done;

if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n");
goto done;
}
if (iwl_is_rfkill(priv)) {
IWL_DEBUG_TX(priv, "Aborting flush due to RF Kill\n");
goto done;
}

/*
* mac80211 will not push any more frames for transmit
* until the flush is completed
*/
if (drop) {
IWL_DEBUG_MAC80211(priv, "send flush command\n");
if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) {
IWL_ERR(priv, "flush request fail\n");
goto done;
}
}
IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n");
iwlagn_wait_tx_queue_empty(priv);
done:
mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
}

/*****************************************************************************
*
* driver setup and teardown
Expand Down Expand Up @@ -3812,6 +3850,7 @@ static struct ieee80211_ops iwl_hw_ops = {
.sta_add = iwlagn_mac_sta_add,
.sta_remove = iwl_mac_sta_remove,
.channel_switch = iwl_mac_channel_switch,
.flush = iwl_mac_flush,
};

static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-agn.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv,
void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
int iwlagn_hw_nic_init(struct iwl_priv *priv);
int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv);
int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);

/* rx */
void iwlagn_rx_queue_restock(struct iwl_priv *priv);
Expand Down
4 changes: 4 additions & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,10 @@ struct iwl_rem_sta_cmd {
#define IWL_TX_FIFO_VO_MSK cpu_to_le32(BIT(3))
#define IWL_AGG_TX_QUEUE_MSK cpu_to_le32(0xffc00)

#define IWL_DROP_SINGLE 0
#define IWL_DROP_SELECTED 1
#define IWL_DROP_ALL 2

/*
* REPLY_TXFIFO_FLUSH = 0x1e(command and response)
*
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ struct iwl_lib_ops {
/* check for ack health */
bool (*check_ack_health)(struct iwl_priv *priv,
struct iwl_rx_packet *pkt);
int (*txfifo_flush)(struct iwl_priv *priv, u16 flush_control);

struct iwl_debugfs_ops debugfs_ops;
};

Expand Down

0 comments on commit 9ef5977

Please sign in to comment.