aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2008-05-29 04:35:12 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-03 15:00:24 -0400
commit17b889290a184b52ee394c31dd5a52b8c1b3456d (patch)
tree2e8889673a9f26b1a1afb2291ede6032eeadd1bb /drivers/net/wireless
parenta5e8b5056ea8762e67c9fa980c8db48009ed2a67 (diff)
iwlwifi: move tx reclaim flow into iwl-tx
This patch 1. moves TX reclaim flow into iwl-tx 2. separates command queue and tx queue reclaim flow Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c108
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c93
6 files changed, 116 insertions, 98 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 98f3df0210d7..1d95e8c65276 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -3132,7 +3132,7 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
3132 /* calculate mac80211 ampdu sw queue to wake */ 3132 /* calculate mac80211 ampdu sw queue to wake */
3133 int ampdu_q = 3133 int ampdu_q =
3134 scd_flow - IWL_BACK_QUEUE_FIRST_ID + priv->hw->queues; 3134 scd_flow - IWL_BACK_QUEUE_FIRST_ID + priv->hw->queues;
3135 int freed = iwl4965_tx_queue_reclaim(priv, scd_flow, index); 3135 int freed = iwl_tx_queue_reclaim(priv, scd_flow, index);
3136 priv->stations[ba_resp->sta_id]. 3136 priv->stations[ba_resp->sta_id].
3137 tid[ba_resp->tid].tfds_in_queue -= freed; 3137 tid[ba_resp->tid].tfds_in_queue -= freed;
3138 if (iwl_queue_space(&txq->q) > txq->q.low_mark && 3138 if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
@@ -3673,7 +3673,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
3673 index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); 3673 index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
3674 IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn " 3674 IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
3675 "%d index %d\n", scd_ssn , index); 3675 "%d index %d\n", scd_ssn , index);
3676 freed = iwl4965_tx_queue_reclaim(priv, txq_id, index); 3676 freed = iwl_tx_queue_reclaim(priv, txq_id, index);
3677 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; 3677 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
3678 3678
3679 if (iwl_queue_space(&txq->q) > txq->q.low_mark && 3679 if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
@@ -3705,7 +3705,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
3705 IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); 3705 IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
3706#ifdef CONFIG_IWL4965_HT 3706#ifdef CONFIG_IWL4965_HT
3707 if (index != -1) { 3707 if (index != -1) {
3708 int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index); 3708 int freed = iwl_tx_queue_reclaim(priv, txq_id, index);
3709 if (tid != MAX_TID_COUNT) 3709 if (tid != MAX_TID_COUNT)
3710 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; 3710 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
3711 if (iwl_queue_space(&txq->q) > txq->q.low_mark && 3711 if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index cfabcb00f331..dc9f3b683795 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -1159,7 +1159,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
1159 index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); 1159 index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
1160 IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn " 1160 IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
1161 "%d index %d\n", scd_ssn , index); 1161 "%d index %d\n", scd_ssn , index);
1162 freed = iwl4965_tx_queue_reclaim(priv, txq_id, index); 1162 freed = iwl_tx_queue_reclaim(priv, txq_id, index);
1163 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; 1163 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
1164 1164
1165 if (iwl_queue_space(&txq->q) > txq->q.low_mark && 1165 if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
@@ -1191,7 +1191,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
1191 IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); 1191 IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
1192#ifdef CONFIG_IWL4965_HT 1192#ifdef CONFIG_IWL4965_HT
1193 if (index != -1) { 1193 if (index != -1) {
1194 int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index); 1194 int freed = iwl_tx_queue_reclaim(priv, txq_id, index);
1195 if (tid != MAX_TID_COUNT) 1195 if (tid != MAX_TID_COUNT)
1196 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; 1196 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
1197 if (iwl_queue_space(&txq->q) > txq->q.low_mark && 1197 if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 9449b61c8c0e..8264b4e65857 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -205,6 +205,8 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
205int iwl_rx_queue_restock(struct iwl_priv *priv); 205int iwl_rx_queue_restock(struct iwl_priv *priv);
206int iwl_rx_queue_space(const struct iwl_rx_queue *q); 206int iwl_rx_queue_space(const struct iwl_rx_queue *q);
207void iwl_rx_allocate(struct iwl_priv *priv); 207void iwl_rx_allocate(struct iwl_priv *priv);
208void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
209int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
208/* Handlers */ 210/* Handlers */
209void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, 211void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
210 struct iwl_rx_mem_buffer *rxb); 212 struct iwl_rx_mem_buffer *rxb);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 934331304703..8c258d6a61c9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -714,7 +714,6 @@ extern int iwl4965_get_temperature(const struct iwl_priv *priv);
714extern u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid); 714extern u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid);
715 715
716extern int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel); 716extern int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel);
717extern int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
718extern int iwl_queue_space(const struct iwl_queue *q); 717extern int iwl_queue_space(const struct iwl_queue *q);
719static inline int iwl_queue_used(const struct iwl_queue *q, int i) 718static inline int iwl_queue_used(const struct iwl_queue *q, int i)
720{ 719{
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 885a4c11ac49..b2b2ed29602a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -1060,6 +1060,114 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
1060 return ret ? ret : idx; 1060 return ret ? ret : idx;
1061} 1061}
1062 1062
1063int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
1064{
1065 struct iwl_tx_queue *txq = &priv->txq[txq_id];
1066 struct iwl_queue *q = &txq->q;
1067 struct iwl_tx_info *tx_info;
1068 int nfreed = 0;
1069
1070 if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
1071 IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
1072 "is out of range [0-%d] %d %d.\n", txq_id,
1073 index, q->n_bd, q->write_ptr, q->read_ptr);
1074 return 0;
1075 }
1076
1077 for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
1078 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
1079
1080 tx_info = &txq->txb[txq->q.read_ptr];
1081 ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]);
1082 tx_info->skb[0] = NULL;
1083 iwl_hw_txq_free_tfd(priv, txq);
1084
1085 nfreed++;
1086 }
1087 return nfreed;
1088}
1089EXPORT_SYMBOL(iwl_tx_queue_reclaim);
1090
1091
1092/**
1093 * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd
1094 *
1095 * When FW advances 'R' index, all entries between old and new 'R' index
1096 * need to be reclaimed. As result, some free space forms. If there is
1097 * enough free space (> low mark), wake the stack that feeds us.
1098 */
1099static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
1100{
1101 struct iwl_tx_queue *txq = &priv->txq[txq_id];
1102 struct iwl_queue *q = &txq->q;
1103 int nfreed = 0;
1104
1105 if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
1106 IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
1107 "is out of range [0-%d] %d %d.\n", txq_id,
1108 index, q->n_bd, q->write_ptr, q->read_ptr);
1109 return;
1110 }
1111
1112 for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
1113 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
1114
1115 if (nfreed > 1) {
1116 IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
1117 q->write_ptr, q->read_ptr);
1118 queue_work(priv->workqueue, &priv->restart);
1119 }
1120 nfreed++;
1121 }
1122}
1123
1124/**
1125 * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
1126 * @rxb: Rx buffer to reclaim
1127 *
1128 * If an Rx buffer has an async callback associated with it the callback
1129 * will be executed. The attached skb (if present) will only be freed
1130 * if the callback returns 1
1131 */
1132void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
1133{
1134 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
1135 u16 sequence = le16_to_cpu(pkt->hdr.sequence);
1136 int txq_id = SEQ_TO_QUEUE(sequence);
1137 int index = SEQ_TO_INDEX(sequence);
1138 int huge = sequence & SEQ_HUGE_FRAME;
1139 int cmd_index;
1140 struct iwl_cmd *cmd;
1141
1142 /* If a Tx command is being handled and it isn't in the actual
1143 * command queue then there a command routing bug has been introduced
1144 * in the queue management code. */
1145 if (txq_id != IWL_CMD_QUEUE_NUM)
1146 IWL_ERROR("Error wrong command queue %d command id 0x%X\n",
1147 txq_id, pkt->hdr.cmd);
1148 BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);
1149
1150 cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
1151 cmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
1152
1153 /* Input error checking is done when commands are added to queue. */
1154 if (cmd->meta.flags & CMD_WANT_SKB) {
1155 cmd->meta.source->u.skb = rxb->skb;
1156 rxb->skb = NULL;
1157 } else if (cmd->meta.u.callback &&
1158 !cmd->meta.u.callback(priv, cmd, rxb->skb))
1159 rxb->skb = NULL;
1160
1161 iwl_hcmd_queue_reclaim(priv, txq_id, index);
1162
1163 if (!(cmd->meta.flags & CMD_ASYNC)) {
1164 clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
1165 wake_up_interruptible(&priv->wait_command_queue);
1166 }
1167}
1168EXPORT_SYMBOL(iwl_tx_cmd_complete);
1169
1170
1063#ifdef CONFIG_IWLWIF_DEBUG 1171#ifdef CONFIG_IWLWIF_DEBUG
1064#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x 1172#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
1065 1173
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 10d773413aa5..4322cd604f41 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1535,51 +1535,6 @@ static int iwl4965_get_measurement(struct iwl_priv *priv,
1535} 1535}
1536#endif 1536#endif
1537 1537
1538static void iwl4965_txstatus_to_ieee(struct iwl_priv *priv,
1539 struct iwl_tx_info *tx_sta)
1540{
1541 ieee80211_tx_status_irqsafe(priv->hw, tx_sta->skb[0]);
1542 tx_sta->skb[0] = NULL;
1543}
1544
1545/**
1546 * iwl4965_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
1547 *
1548 * When FW advances 'R' index, all entries between old and new 'R' index
1549 * need to be reclaimed. As result, some free space forms. If there is
1550 * enough free space (> low mark), wake the stack that feeds us.
1551 */
1552int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
1553{
1554 struct iwl_tx_queue *txq = &priv->txq[txq_id];
1555 struct iwl_queue *q = &txq->q;
1556 int nfreed = 0;
1557
1558 if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
1559 IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
1560 "is out of range [0-%d] %d %d.\n", txq_id,
1561 index, q->n_bd, q->write_ptr, q->read_ptr);
1562 return 0;
1563 }
1564
1565 for (index = iwl_queue_inc_wrap(index, q->n_bd);
1566 q->read_ptr != index;
1567 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
1568 if (txq_id != IWL_CMD_QUEUE_NUM) {
1569 iwl4965_txstatus_to_ieee(priv,
1570 &(txq->txb[txq->q.read_ptr]));
1571 iwl_hw_txq_free_tfd(priv, txq);
1572 } else if (nfreed > 1) {
1573 IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
1574 q->write_ptr, q->read_ptr);
1575 queue_work(priv->workqueue, &priv->restart);
1576 }
1577 nfreed++;
1578 }
1579
1580 return nfreed;
1581}
1582
1583/****************************************************************************** 1538/******************************************************************************
1584 * 1539 *
1585 * Generic RX handler implementations 1540 * Generic RX handler implementations
@@ -1961,52 +1916,6 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
1961 priv->cfg->ops->lib->rx_handler_setup(priv); 1916 priv->cfg->ops->lib->rx_handler_setup(priv);
1962} 1917}
1963 1918
1964/**
1965 * iwl4965_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
1966 * @rxb: Rx buffer to reclaim
1967 *
1968 * If an Rx buffer has an async callback associated with it the callback
1969 * will be executed. The attached skb (if present) will only be freed
1970 * if the callback returns 1
1971 */
1972static void iwl4965_tx_cmd_complete(struct iwl_priv *priv,
1973 struct iwl_rx_mem_buffer *rxb)
1974{
1975 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
1976 u16 sequence = le16_to_cpu(pkt->hdr.sequence);
1977 int txq_id = SEQ_TO_QUEUE(sequence);
1978 int index = SEQ_TO_INDEX(sequence);
1979 int huge = sequence & SEQ_HUGE_FRAME;
1980 int cmd_index;
1981 struct iwl_cmd *cmd;
1982
1983 /* If a Tx command is being handled and it isn't in the actual
1984 * command queue then there a command routing bug has been introduced
1985 * in the queue management code. */
1986 if (txq_id != IWL_CMD_QUEUE_NUM)
1987 IWL_ERROR("Error wrong command queue %d command id 0x%X\n",
1988 txq_id, pkt->hdr.cmd);
1989 BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);
1990
1991 cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
1992 cmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
1993
1994 /* Input error checking is done when commands are added to queue. */
1995 if (cmd->meta.flags & CMD_WANT_SKB) {
1996 cmd->meta.source->u.skb = rxb->skb;
1997 rxb->skb = NULL;
1998 } else if (cmd->meta.u.callback &&
1999 !cmd->meta.u.callback(priv, cmd, rxb->skb))
2000 rxb->skb = NULL;
2001
2002 iwl4965_tx_queue_reclaim(priv, txq_id, index);
2003
2004 if (!(cmd->meta.flags & CMD_ASYNC)) {
2005 clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
2006 wake_up_interruptible(&priv->wait_command_queue);
2007 }
2008}
2009
2010/* 1919/*
2011 * this should be called while priv->lock is locked 1920 * this should be called while priv->lock is locked
2012*/ 1921*/
@@ -2095,7 +2004,7 @@ void iwl_rx_handle(struct iwl_priv *priv)
2095 * fire off the (possibly) blocking iwl_send_cmd() 2004 * fire off the (possibly) blocking iwl_send_cmd()
2096 * as we reclaim the driver command queue */ 2005 * as we reclaim the driver command queue */
2097 if (rxb && rxb->skb) 2006 if (rxb && rxb->skb)
2098 iwl4965_tx_cmd_complete(priv, rxb); 2007 iwl_tx_cmd_complete(priv, rxb);
2099 else 2008 else
2100 IWL_WARNING("Claim null rxb?\n"); 2009 IWL_WARNING("Claim null rxb?\n");
2101 } 2010 }