aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-rx.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c212
1 files changed, 67 insertions, 145 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index f3f3efe38ce2..8e314003b63a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -41,142 +41,6 @@
41#include "iwl-agn-calib.h" 41#include "iwl-agn-calib.h"
42#include "iwl-agn.h" 42#include "iwl-agn.h"
43 43
44/******************************************************************************
45 *
46 * RX path functions
47 *
48 ******************************************************************************/
49
50/*
51 * Rx theory of operation
52 *
53 * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs),
54 * each of which point to Receive Buffers to be filled by the NIC. These get
55 * used not only for Rx frames, but for any command response or notification
56 * from the NIC. The driver and NIC manage the Rx buffers by means
57 * of indexes into the circular buffer.
58 *
59 * Rx Queue Indexes
60 * The host/firmware share two index registers for managing the Rx buffers.
61 *
62 * The READ index maps to the first position that the firmware may be writing
63 * to -- the driver can read up to (but not including) this position and get
64 * good data.
65 * The READ index is managed by the firmware once the card is enabled.
66 *
67 * The WRITE index maps to the last position the driver has read from -- the
68 * position preceding WRITE is the last slot the firmware can place a packet.
69 *
70 * The queue is empty (no good data) if WRITE = READ - 1, and is full if
71 * WRITE = READ.
72 *
73 * During initialization, the host sets up the READ queue position to the first
74 * INDEX position, and WRITE to the last (READ - 1 wrapped)
75 *
76 * When the firmware places a packet in a buffer, it will advance the READ index
77 * and fire the RX interrupt. The driver can then query the READ index and
78 * process as many packets as possible, moving the WRITE index forward as it
79 * resets the Rx queue buffers with new memory.
80 *
81 * The management in the driver is as follows:
82 * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When
83 * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
84 * to replenish the iwl->rxq->rx_free.
85 * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
86 * iwl->rxq is replenished and the READ INDEX is updated (updating the
87 * 'processed' and 'read' driver indexes as well)
88 * + A received packet is processed and handed to the kernel network stack,
89 * detached from the iwl->rxq. The driver 'processed' index is updated.
90 * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
91 * list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
92 * INDEX is not incremented and iwl->status(RX_STALLED) is set. If there
93 * were enough free buffers and RX_STALLED is set it is cleared.
94 *
95 *
96 * Driver sequence:
97 *
98 * iwl_rx_queue_alloc() Allocates rx_free
99 * iwl_rx_replenish() Replenishes rx_free list from rx_used, and calls
100 * iwl_rx_queue_restock
101 * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx
102 * queue, updates firmware pointers, and updates
103 * the WRITE index. If insufficient rx_free buffers
104 * are available, schedules iwl_rx_replenish
105 *
106 * -- enable interrupts --
107 * ISR - iwl_rx() Detach iwl_rx_mem_buffers from pool up to the
108 * READ INDEX, detaching the SKB from the pool.
109 * Moves the packet buffer from queue to rx_used.
110 * Calls iwl_rx_queue_restock to refill any empty
111 * slots.
112 * ...
113 *
114 */
115
116/**
117 * iwl_rx_queue_space - Return number of free slots available in queue.
118 */
119int iwl_rx_queue_space(const struct iwl_rx_queue *q)
120{
121 int s = q->read - q->write;
122 if (s <= 0)
123 s += RX_QUEUE_SIZE;
124 /* keep some buffer to not confuse full and empty queue */
125 s -= 2;
126 if (s < 0)
127 s = 0;
128 return s;
129}
130
131/**
132 * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
133 */
134void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
135{
136 unsigned long flags;
137 u32 reg;
138
139 spin_lock_irqsave(&q->lock, flags);
140
141 if (q->need_update == 0)
142 goto exit_unlock;
143
144 if (priv->cfg->base_params->shadow_reg_enable) {
145 /* shadow register enabled */
146 /* Device expects a multiple of 8 */
147 q->write_actual = (q->write & ~0x7);
148 iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual);
149 } else {
150 /* If power-saving is in use, make sure device is awake */
151 if (test_bit(STATUS_POWER_PMI, &priv->status)) {
152 reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
153
154 if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
155 IWL_DEBUG_INFO(priv,
156 "Rx queue requesting wakeup,"
157 " GP1 = 0x%x\n", reg);
158 iwl_set_bit(priv, CSR_GP_CNTRL,
159 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
160 goto exit_unlock;
161 }
162
163 q->write_actual = (q->write & ~0x7);
164 iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
165 q->write_actual);
166
167 /* Else device is assumed to be awake */
168 } else {
169 /* Device expects a multiple of 8 */
170 q->write_actual = (q->write & ~0x7);
171 iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
172 q->write_actual);
173 }
174 }
175 q->need_update = 0;
176
177 exit_unlock:
178 spin_unlock_irqrestore(&q->lock, flags);
179}
180 44
181/****************************************************************************** 45/******************************************************************************
182 * 46 *
@@ -306,7 +170,7 @@ static bool iwl_good_ack_health(struct iwl_priv *priv,
306 int actual_delta, expected_delta, ba_timeout_delta; 170 int actual_delta, expected_delta, ba_timeout_delta;
307 struct statistics_tx *old; 171 struct statistics_tx *old;
308 172
309 if (priv->_agn.agg_tids_count) 173 if (priv->agg_tids_count)
310 return true; 174 return true;
311 175
312 old = &priv->statistics.tx; 176 old = &priv->statistics.tx;
@@ -624,8 +488,8 @@ static void iwl_rx_statistics(struct iwl_priv *priv,
624 iwl_rx_calc_noise(priv); 488 iwl_rx_calc_noise(priv);
625 queue_work(priv->workqueue, &priv->run_time_calib_work); 489 queue_work(priv->workqueue, &priv->run_time_calib_work);
626 } 490 }
627 if (priv->cfg->ops->lib->temperature && change) 491 if (priv->cfg->lib->temperature && change)
628 priv->cfg->ops->lib->temperature(priv); 492 priv->cfg->lib->temperature(priv);
629} 493}
630 494
631static void iwl_rx_reply_statistics(struct iwl_priv *priv, 495static void iwl_rx_reply_statistics(struct iwl_priv *priv,
@@ -728,8 +592,8 @@ static void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
728{ 592{
729 struct iwl_rx_packet *pkt = rxb_addr(rxb); 593 struct iwl_rx_packet *pkt = rxb_addr(rxb);
730 594
731 priv->_agn.last_phy_res_valid = true; 595 priv->last_phy_res_valid = true;
732 memcpy(&priv->_agn.last_phy_res, pkt->u.raw, 596 memcpy(&priv->last_phy_res, pkt->u.raw,
733 sizeof(struct iwl_rx_phy_res)); 597 sizeof(struct iwl_rx_phy_res));
734} 598}
735 599
@@ -977,11 +841,11 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
977 phy_res->cfg_phy_cnt + len); 841 phy_res->cfg_phy_cnt + len);
978 ampdu_status = le32_to_cpu(rx_pkt_status); 842 ampdu_status = le32_to_cpu(rx_pkt_status);
979 } else { 843 } else {
980 if (!priv->_agn.last_phy_res_valid) { 844 if (!priv->last_phy_res_valid) {
981 IWL_ERR(priv, "MPDU frame without cached PHY data\n"); 845 IWL_ERR(priv, "MPDU frame without cached PHY data\n");
982 return; 846 return;
983 } 847 }
984 phy_res = &priv->_agn.last_phy_res; 848 phy_res = &priv->last_phy_res;
985 amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; 849 amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw;
986 header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); 850 header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
987 len = le16_to_cpu(amsdu->byte_count); 851 len = le16_to_cpu(amsdu->byte_count);
@@ -1102,6 +966,64 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
1102 /* block ack */ 966 /* block ack */
1103 handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba; 967 handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba;
1104 968
1105 /* Set up hardware specific Rx handlers */ 969 /* init calibration handlers */
1106 priv->cfg->ops->lib->rx_handler_setup(priv); 970 priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
971 iwlagn_rx_calib_result;
972 priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
973
974 /* set up notification wait support */
975 spin_lock_init(&priv->notif_wait_lock);
976 INIT_LIST_HEAD(&priv->notif_waits);
977 init_waitqueue_head(&priv->notif_waitq);
978
979 /* Set up BT Rx handlers */
980 if (priv->cfg->lib->bt_rx_handler_setup)
981 priv->cfg->lib->bt_rx_handler_setup(priv);
982
983}
984
985void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
986{
987 struct iwl_rx_packet *pkt = rxb_addr(rxb);
988
989 /*
990 * Do the notification wait before RX handlers so
991 * even if the RX handler consumes the RXB we have
992 * access to it in the notification wait entry.
993 */
994 if (!list_empty(&priv->notif_waits)) {
995 struct iwl_notification_wait *w;
996
997 spin_lock(&priv->notif_wait_lock);
998 list_for_each_entry(w, &priv->notif_waits, list) {
999 if (w->cmd != pkt->hdr.cmd)
1000 continue;
1001 IWL_DEBUG_RX(priv,
1002 "Notif: %s, 0x%02x - wake the callers up\n",
1003 get_cmd_string(pkt->hdr.cmd),
1004 pkt->hdr.cmd);
1005 w->triggered = true;
1006 if (w->fn)
1007 w->fn(priv, pkt, w->fn_data);
1008 }
1009 spin_unlock(&priv->notif_wait_lock);
1010
1011 wake_up_all(&priv->notif_waitq);
1012 }
1013
1014 if (priv->pre_rx_handler)
1015 priv->pre_rx_handler(priv, rxb);
1016
1017 /* Based on type of command response or notification,
1018 * handle those that need handling via function in
1019 * rx_handlers table. See iwl_setup_rx_handlers() */
1020 if (priv->rx_handlers[pkt->hdr.cmd]) {
1021 priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
1022 priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
1023 } else {
1024 /* No handling needed */
1025 IWL_DEBUG_RX(priv,
1026 "No handler needed for %s, 0x%02x\n",
1027 get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
1028 }
1107} 1029}