Skip to content

Commit

Permalink
iwlwifi: add support for device tx flush request
Browse files Browse the repository at this point in the history
"Flush" request can come from two different sources, it can either from
mac80211, or from device when the operation is needed. Here
adding the support for device issue "flush" request.

When receive tx complete with status is TX_STATUS_FAIL_RFKILL_FLUSH,
issue REPLY_TXFIFO_FLUSH command to uCode to flush out all the tx frames
in queues.

In this condition, since mac80211 has no knowledge of "flush" operation,
driver need to stop all the tx queues and wait for the operation
completed before wake up the queues for frames transmission.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
  • Loading branch information
Wey-Yi Guy committed Jul 2, 2010
1 parent 716c74b commit 6555063
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 1 deletion.
1 change: 1 addition & 0 deletions drivers/net/wireless/iwlwifi/iwl-1000.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ static struct iwl_lib_ops iwl1000_lib = {
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
.txfifo_flush = iwlagn_txfifo_flush,
.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
};

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

static struct iwl_lib_ops iwl5150_lib = {
Expand Down Expand Up @@ -467,6 +468,7 @@ static struct iwl_lib_ops iwl5150_lib = {
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
.txfifo_flush = iwlagn_txfifo_flush,
.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
};

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

static const struct iwl_ops iwl6000_ops = {
Expand Down
19 changes: 18 additions & 1 deletion drivers/net/wireless/iwlwifi/iwl-agn-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,9 @@ void iwl_check_abort_status(struct iwl_priv *priv,
u8 frame_count, u32 status)
{
if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
IWL_ERR(priv, "TODO: Implement Tx flush command!!!\n");
IWL_ERR(priv, "Tx flush command to flush out all frames\n");
if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
queue_work(priv->workqueue, &priv->tx_flush);
}
}

Expand Down Expand Up @@ -1498,3 +1500,18 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)

return iwl_send_cmd(priv, &cmd);
}

void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
{
mutex_lock(&priv->mutex);
ieee80211_stop_queues(priv->hw);
if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) {
IWL_ERR(priv, "flush request fail\n");
goto done;
}
IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n");
iwlagn_wait_tx_queue_empty(priv);
done:
ieee80211_wake_queues(priv->hw);
mutex_unlock(&priv->mutex);
}
19 changes: 19 additions & 0 deletions drivers/net/wireless/iwlwifi/iwl-agn.c
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,24 @@ int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
return 0;
}

static void iwl_bg_tx_flush(struct work_struct *work)
{
struct iwl_priv *priv =
container_of(work, struct iwl_priv, tx_flush);

if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;

/* do nothing if rf-kill is on */
if (!iwl_is_ready_rf(priv))
return;

if (priv->cfg->ops->lib->txfifo_flush) {
IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
}
}

/**
* iwl_setup_rx_handlers - Initialize Rx handler callbacks
*
Expand Down Expand Up @@ -3693,6 +3711,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush);
INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);

Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/iwlwifi/iwl-agn.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ 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);
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);

/* rx */
void iwlagn_rx_queue_restock(struct iwl_priv *priv);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/iwlwifi/iwl-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ struct iwl_lib_ops {
bool (*check_ack_health)(struct iwl_priv *priv,
struct iwl_rx_packet *pkt);
int (*txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control);

struct iwl_debugfs_ops debugfs_ops;
};
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/iwlwifi/iwl-dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -1345,6 +1345,7 @@ struct iwl_priv {
struct work_struct ct_enter;
struct work_struct ct_exit;
struct work_struct start_internal_scan;
struct work_struct tx_flush;

struct tasklet_struct irq_tasklet;

Expand Down

0 comments on commit 6555063

Please sign in to comment.