Commit 91c066f2 authored by Tomas Winkler's avatar Tomas Winkler Committed by John W. Linville

iwlwifi: 3945 split tx_complete to command and packet function

This patch
1. removes cmd completion from iwl3945_tx_queue_reclaim
and creates iwl3945_cmd_queue_reclaim.
1. removes 11n relevant elements from this function
2. removes call to ieee80211_tx_status_irqsafe
and uses ieee80211_tx_status only
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarReinette Chatre <reinette.chatre@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 28447f3c
......@@ -227,14 +227,126 @@ __le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv)
return 0; /* "diversity" is default if error */
}
#ifdef CONFIG_IWL3945_DEBUG
#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
static const char *iwl3945_get_tx_fail_reason(u32 status)
{
switch (status & TX_STATUS_MSK) {
case TX_STATUS_SUCCESS:
return "SUCCESS";
TX_STATUS_ENTRY(SHORT_LIMIT);
TX_STATUS_ENTRY(LONG_LIMIT);
TX_STATUS_ENTRY(FIFO_UNDERRUN);
TX_STATUS_ENTRY(MGMNT_ABORT);
TX_STATUS_ENTRY(NEXT_FRAG);
TX_STATUS_ENTRY(LIFE_EXPIRE);
TX_STATUS_ENTRY(DEST_PS);
TX_STATUS_ENTRY(ABORTED);
TX_STATUS_ENTRY(BT_RETRY);
TX_STATUS_ENTRY(STA_INVALID);
TX_STATUS_ENTRY(FRAG_DROPPED);
TX_STATUS_ENTRY(TID_DISABLE);
TX_STATUS_ENTRY(FRAME_FLUSHED);
TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
TX_STATUS_ENTRY(TX_LOCKED);
TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
}
return "UNKNOWN";
}
#else
static inline const char *iwl3945_get_tx_fail_reason(u32 status)
{
return "";
}
#endif
/**
* iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
*
* When FW advances 'R' index, all entries between old and new 'R' index
* need to be reclaimed. As result, some free space forms. If there is
* enough free space (> low mark), wake the stack that feeds us.
*/
static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv,
int txq_id, int index)
{
struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
struct iwl3945_queue *q = &txq->q;
struct iwl3945_tx_info *tx_info;
BUG_ON(txq_id == IWL_CMD_QUEUE_NUM);
for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
tx_info = &txq->txb[txq->q.read_ptr];
ieee80211_tx_status(priv->hw, tx_info->skb[0],
&tx_info->status);
tx_info->skb[0] = NULL;
iwl3945_hw_txq_free_tfd(priv, txq);
}
if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) &&
(txq_id != IWL_CMD_QUEUE_NUM) &&
priv->mac80211_registered)
ieee80211_wake_queue(priv->hw, txq_id);
}
/**
* iwl3945_rx_reply_tx - Handle Tx response
*/
static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
struct iwl3945_rx_mem_buffer *rxb)
{
struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
int txq_id = SEQ_TO_QUEUE(sequence);
int index = SEQ_TO_INDEX(sequence);
struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
struct ieee80211_tx_status *tx_status;
struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
u32 status = le32_to_cpu(tx_resp->status);
int rate_idx;
if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) {
IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
"is out of range [0-%d] %d %d\n", txq_id,
index, txq->q.n_bd, txq->q.write_ptr,
txq->q.read_ptr);
return;
}
tx_status = &(txq->txb[txq->q.read_ptr].status);
tx_status->retry_count = tx_resp->failure_frame;
/* tx_status->rts_retry_count = tx_resp->failure_rts; */
tx_status->flags = ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ?
IEEE80211_TX_STATUS_ACK : 0;
IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
txq_id, iwl3945_get_tx_fail_reason(status), status,
tx_resp->rate, tx_resp->failure_frame);
rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
tx_status->control.tx_rate = &priv->ieee_rates[rate_idx];
IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
iwl3945_tx_queue_reclaim(priv, txq_id, index);
if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
}
/*****************************************************************************
*
* Intel PRO/Wireless 3945ABG/BG Network Connection
*
* RX handler implementations
*
* Used by iwl-base.c
*
*****************************************************************************/
void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb)
......@@ -2510,6 +2622,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv)
{
priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx;
}
......
......@@ -2063,34 +2063,6 @@ int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *h
return 1;
}
#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
static const char *iwl3945_get_tx_fail_reason(u32 status)
{
switch (status & TX_STATUS_MSK) {
case TX_STATUS_SUCCESS:
return "SUCCESS";
TX_STATUS_ENTRY(SHORT_LIMIT);
TX_STATUS_ENTRY(LONG_LIMIT);
TX_STATUS_ENTRY(FIFO_UNDERRUN);
TX_STATUS_ENTRY(MGMNT_ABORT);
TX_STATUS_ENTRY(NEXT_FRAG);
TX_STATUS_ENTRY(LIFE_EXPIRE);
TX_STATUS_ENTRY(DEST_PS);
TX_STATUS_ENTRY(ABORTED);
TX_STATUS_ENTRY(BT_RETRY);
TX_STATUS_ENTRY(STA_INVALID);
TX_STATUS_ENTRY(FRAG_DROPPED);
TX_STATUS_ENTRY(TID_DISABLE);
TX_STATUS_ENTRY(FRAME_FLUSHED);
TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
TX_STATUS_ENTRY(TX_LOCKED);
TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
}
return "UNKNOWN";
}
/**
* iwl3945_scan_cancel - Cancel any currently executing HW scan
*
......@@ -3138,125 +3110,6 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv,
}
#endif
static void iwl3945_txstatus_to_ieee(struct iwl3945_priv *priv,
struct iwl3945_tx_info *tx_sta)
{
tx_sta->status.ack_signal = 0;
tx_sta->status.excessive_retries = 0;
tx_sta->status.queue_length = 0;
tx_sta->status.queue_number = 0;
if (in_interrupt())
ieee80211_tx_status_irqsafe(priv->hw,
tx_sta->skb[0], &(tx_sta->status));
else
ieee80211_tx_status(priv->hw,
tx_sta->skb[0], &(tx_sta->status));
tx_sta->skb[0] = NULL;
}
/**
* iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
*
* When FW advances 'R' index, all entries between old and new 'R' index
* need to be reclaimed. As result, some free space forms. If there is
* enough free space (> low mark), wake the stack that feeds us.
*/
static int iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int index)
{
struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
struct iwl3945_queue *q = &txq->q;
int nfreed = 0;
if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) {
IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
"is out of range [0-%d] %d %d.\n", txq_id,
index, q->n_bd, q->write_ptr, q->read_ptr);
return 0;
}
for (index = iwl_queue_inc_wrap(index, q->n_bd);
q->read_ptr != index;
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
if (txq_id != IWL_CMD_QUEUE_NUM) {
iwl3945_txstatus_to_ieee(priv,
&(txq->txb[txq->q.read_ptr]));
iwl3945_hw_txq_free_tfd(priv, txq);
} else if (nfreed > 1) {
IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
q->write_ptr, q->read_ptr);
queue_work(priv->workqueue, &priv->restart);
}
nfreed++;
}
if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) &&
(txq_id != IWL_CMD_QUEUE_NUM) &&
priv->mac80211_registered)
ieee80211_wake_queue(priv->hw, txq_id);
return nfreed;
}
static int iwl3945_is_tx_success(u32 status)
{
return (status & 0xFF) == 0x1;
}
/******************************************************************************
*
* Generic RX handler implementations
*
******************************************************************************/
/**
* iwl3945_rx_reply_tx - Handle Tx response
*/
static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
struct iwl3945_rx_mem_buffer *rxb)
{
struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
int txq_id = SEQ_TO_QUEUE(sequence);
int index = SEQ_TO_INDEX(sequence);
struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
struct ieee80211_tx_status *tx_status;
struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
u32 status = le32_to_cpu(tx_resp->status);
if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) {
IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
"is out of range [0-%d] %d %d\n", txq_id,
index, txq->q.n_bd, txq->q.write_ptr,
txq->q.read_ptr);
return;
}
tx_status = &(txq->txb[txq->q.read_ptr].status);
tx_status->retry_count = tx_resp->failure_frame;
tx_status->queue_number = status;
tx_status->queue_length = tx_resp->bt_kill_count;
tx_status->queue_length |= tx_resp->failure_rts;
tx_status->flags =
iwl3945_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
txq_id, iwl3945_get_tx_fail_reason(status), status,
tx_resp->rate, tx_resp->failure_frame);
IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
if (index != -1)
iwl3945_tx_queue_reclaim(priv, txq_id, index);
if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
}
static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv,
struct iwl3945_rx_mem_buffer *rxb)
{
......@@ -3603,12 +3456,43 @@ static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv)
priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
iwl3945_rx_scan_complete_notif;
priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
/* Set up hardware specific Rx handlers */
iwl3945_hw_rx_handler_setup(priv);
}
/**
* iwl3945_cmd_queue_reclaim - Reclaim CMD queue entries
* When FW advances 'R' index, all entries between old and new 'R' index
* need to be reclaimed.
*/
static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv,
int txq_id, int index)
{
struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
struct iwl3945_queue *q = &txq->q;
int nfreed = 0;
if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) {
IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
"is out of range [0-%d] %d %d.\n", txq_id,
index, q->n_bd, q->write_ptr, q->read_ptr);
return;
}
for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
if (nfreed > 1) {
IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
q->write_ptr, q->read_ptr);
queue_work(priv->workqueue, &priv->restart);
break;
}
nfreed++;
}
}
/**
* iwl3945_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
* @rxb: Rx buffer to reclaim
......@@ -3628,12 +3512,6 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv,
int cmd_index;
struct iwl3945_cmd *cmd;
/* 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
* in the queue management code. */
if (txq_id != IWL_CMD_QUEUE_NUM)
IWL_ERROR("Error wrong command queue %d command id 0x%X\n",
txq_id, pkt->hdr.cmd);
BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);
cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
......@@ -3647,7 +3525,7 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv,
!cmd->meta.u.callback(priv, cmd, rxb->skb))
rxb->skb = NULL;
iwl3945_tx_queue_reclaim(priv, txq_id, index);
iwl3945_cmd_queue_reclaim(priv, txq_id, index);
if (!(cmd->meta.flags & CMD_ASYNC)) {
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment