aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl3945-base.c
diff options
context:
space:
mode:
authorSamuel Ortiz <samuel.ortiz@intel.com>2009-01-23 16:45:14 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:01:34 -0500
commita8e74e2774cd1aecfef0460de07e6e178df89232 (patch)
treebccf507738fb8753e7ab16a8de9644e9d99ae07c /drivers/net/wireless/iwlwifi/iwl3945-base.c
parent59606ffa9146538b73bbe1ca1285321cd7474bc0 (diff)
iwl3945: Use iwlcore TX queue management routines
By adding an additional hw_params (tfd_size) and a new iwl_lib ops (txq_init), we can now use the iwlcore TX queue management routines. We had to add a new hw_params because we need to allocate the right DMA buffer for TFDs, and those have a different sizes depending if you're on 3945 or agn. Signed-off-by: Samuel Ortiz <samuel.ortiz@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl3945-base.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c204
1 files changed, 0 insertions, 204 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index bc10e2ae597d..14f95238059a 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -93,210 +93,6 @@ struct iwl_mod_params iwl3945_mod_params = {
93 /* the rest are 0 by default */ 93 /* the rest are 0 by default */
94}; 94};
95 95
96/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
97 * DMA services
98 *
99 * Theory of operation
100 *
101 * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
102 * of buffer descriptors, each of which points to one or more data buffers for
103 * the device to read from or fill. Driver and device exchange status of each
104 * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty
105 * entries in each circular buffer, to protect against confusing empty and full
106 * queue states.
107 *
108 * The device reads or writes the data in the queues via the device's several
109 * DMA/FIFO channels. Each queue is mapped to a single DMA channel.
110 *
111 * For Tx queue, there are low mark and high mark limits. If, after queuing
112 * the packet for Tx, free space become < low mark, Tx queue stopped. When
113 * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
114 * Tx queue resumed.
115 *
116 * The 3945 operates with six queues: One receive queue, one transmit queue
117 * (#4) for sending commands to the device firmware, and four transmit queues
118 * (#0-3) for data tx via EDCA. An additional 2 HCCA queues are unused.
119 ***************************************************/
120
121/**
122 * iwl3945_queue_init - Initialize queue's high/low-water and read/write indexes
123 */
124static int iwl3945_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
125 int count, int slots_num, u32 id)
126{
127 q->n_bd = count;
128 q->n_window = slots_num;
129 q->id = id;
130
131 /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
132 * and iwl_queue_dec_wrap are broken. */
133 BUG_ON(!is_power_of_2(count));
134
135 /* slots_num must be power-of-two size, otherwise
136 * get_cmd_index is broken. */
137 BUG_ON(!is_power_of_2(slots_num));
138
139 q->low_mark = q->n_window / 4;
140 if (q->low_mark < 4)
141 q->low_mark = 4;
142
143 q->high_mark = q->n_window / 8;
144 if (q->high_mark < 2)
145 q->high_mark = 2;
146
147 q->write_ptr = q->read_ptr = 0;
148
149 return 0;
150}
151
152/**
153 * iwl3945_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
154 */
155static int iwl3945_tx_queue_alloc(struct iwl_priv *priv,
156 struct iwl_tx_queue *txq, u32 id)
157{
158 struct pci_dev *dev = priv->pci_dev;
159
160 /* Driver private data, only for Tx (not command) queues,
161 * not shared with device. */
162 if (id != IWL_CMD_QUEUE_NUM) {
163 txq->txb = kmalloc(sizeof(txq->txb[0]) *
164 TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
165 if (!txq->txb) {
166 IWL_ERR(priv, "kmalloc for auxiliary BD "
167 "structures failed\n");
168 goto error;
169 }
170 } else
171 txq->txb = NULL;
172
173 /* Circular buffer of transmit frame descriptors (TFDs),
174 * shared with device */
175 txq->tfds = pci_alloc_consistent(dev,
176 sizeof(struct iwl3945_tfd) * TFD_QUEUE_SIZE_MAX,
177 &txq->q.dma_addr);
178
179 if (!txq->tfds) {
180 IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n",
181 sizeof(struct iwl3945_tfd) * TFD_QUEUE_SIZE_MAX);
182 goto error;
183 }
184 txq->q.id = id;
185
186 return 0;
187
188 error:
189 kfree(txq->txb);
190 txq->txb = NULL;
191
192 return -ENOMEM;
193}
194
195/**
196 * iwl3945_tx_queue_init - Allocate and initialize one tx/cmd queue
197 */
198int iwl3945_tx_queue_init(struct iwl_priv *priv,
199 struct iwl_tx_queue *txq, int slots_num, u32 txq_id)
200{
201 int len, i;
202 int rc = 0;
203
204 /*
205 * Alloc buffer array for commands (Tx or other types of commands).
206 * For the command queue (#4), allocate command space + one big
207 * command for scan, since scan command is very huge; the system will
208 * not have two scans at the same time, so only one is needed.
209 * For data Tx queues (all other queues), no super-size command
210 * space is needed.
211 */
212 len = sizeof(struct iwl_cmd);
213 for (i = 0; i <= slots_num; i++) {
214 if (i == slots_num) {
215 if (txq_id == IWL_CMD_QUEUE_NUM)
216 len += IWL_MAX_SCAN_SIZE;
217 else
218 continue;
219 }
220
221 txq->cmd[i] = kmalloc(len, GFP_KERNEL);
222 if (!txq->cmd[i])
223 goto err;
224 }
225
226 /* Alloc driver data array and TFD circular buffer */
227 rc = iwl3945_tx_queue_alloc(priv, txq, txq_id);
228 if (rc)
229 goto err;
230
231 txq->need_update = 0;
232
233 /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
234 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
235 BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
236
237 /* Initialize queue high/low-water, head/tail indexes */
238 iwl3945_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
239
240 /* Tell device where to find queue, enable DMA channel. */
241 iwl3945_hw_tx_queue_init(priv, txq);
242
243 return 0;
244err:
245 for (i = 0; i < slots_num; i++) {
246 kfree(txq->cmd[i]);
247 txq->cmd[i] = NULL;
248 }
249
250 if (txq_id == IWL_CMD_QUEUE_NUM) {
251 kfree(txq->cmd[slots_num]);
252 txq->cmd[slots_num] = NULL;
253 }
254 return -ENOMEM;
255}
256
257/**
258 * iwl3945_tx_queue_free - Deallocate DMA queue.
259 * @txq: Transmit queue to deallocate.
260 *
261 * Empty queue by removing and destroying all BD's.
262 * Free all buffers.
263 * 0-fill, but do not free "txq" descriptor structure.
264 */
265void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq)
266{
267 struct iwl_queue *q = &txq->q;
268 struct pci_dev *dev = priv->pci_dev;
269 int len, i;
270
271 if (q->n_bd == 0)
272 return;
273
274 /* first, empty all BD's */
275 for (; q->write_ptr != q->read_ptr;
276 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
277 priv->cfg->ops->lib->txq_free_tfd(priv, txq);
278
279 len = sizeof(struct iwl_cmd) * q->n_window;
280 if (q->id == IWL_CMD_QUEUE_NUM)
281 len += IWL_MAX_SCAN_SIZE;
282
283 /* De-alloc array of command/tx buffers */
284 for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
285 kfree(txq->cmd[i]);
286
287 /* De-alloc circular buffer of TFDs */
288 if (txq->q.n_bd)
289 pci_free_consistent(dev, sizeof(struct iwl3945_tfd) *
290 txq->q.n_bd, txq->tfds, txq->q.dma_addr);
291
292 /* De-alloc array of per-TFD driver data */
293 kfree(txq->txb);
294 txq->txb = NULL;
295
296 /* 0-fill queue descriptor structure */
297 memset(txq, 0, sizeof(*txq));
298}
299
300/*************** STATION TABLE MANAGEMENT **** 96/*************** STATION TABLE MANAGEMENT ****
301 * mac80211 should be examined to determine if sta_info is duplicating 97 * mac80211 should be examined to determine if sta_info is duplicating
302 * the functionality provided here 98 * the functionality provided here