1 /*
2 * Copyright (c) 2008-2011 Atheros Communications Inc.
3 *
4 * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
5 * Original from Linux kernel 3.0.1
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 FILE_LICENCE ( BSD2 );
21
22 #include <ipxe/malloc.h>
23 #include <ipxe/pci_io.h>
24 #include <ipxe/pci.h>
25 #include <ipxe/ethernet.h>
26
27 #include "ath9k.h"
28
29 int is_ath9k_unloaded;
30 /* We use the hw_value as an index into our private channel structure */
31
32 #define CHAN2G(_freq, _idx) { \
33 .band = NET80211_BAND_2GHZ, \
34 .center_freq = (_freq), \
35 .hw_value = (_idx), \
36 .maxpower = 20, \
37 }
38
39 #define CHAN5G(_freq, _idx) { \
40 .band = NET80211_BAND_5GHZ, \
41 .center_freq = (_freq), \
42 .hw_value = (_idx), \
43 .maxpower = 20, \
44 }
45
46 /* Some 2 GHz radios are actually tunable on 2312-2732
47 * on 5 MHz steps, we support the channels which we know
48 * we have calibration data for all cards though to make
49 * this static */
50 static const struct net80211_channel ath9k_2ghz_chantable[] = {
51 CHAN2G(2412, 0), /* Channel 1 */
52 CHAN2G(2417, 1), /* Channel 2 */
53 CHAN2G(2422, 2), /* Channel 3 */
54 CHAN2G(2427, 3), /* Channel 4 */
55 CHAN2G(2432, 4), /* Channel 5 */
56 CHAN2G(2437, 5), /* Channel 6 */
57 CHAN2G(2442, 6), /* Channel 7 */
58 CHAN2G(2447, 7), /* Channel 8 */
59 CHAN2G(2452, 8), /* Channel 9 */
60 CHAN2G(2457, 9), /* Channel 10 */
61 CHAN2G(2462, 10), /* Channel 11 */
62 CHAN2G(2467, 11), /* Channel 12 */
63 CHAN2G(2472, 12), /* Channel 13 */
64 CHAN2G(2484, 13), /* Channel 14 */
65 };
66
67 /* Some 5 GHz radios are actually tunable on XXXX-YYYY
68 * on 5 MHz steps, we support the channels which we know
69 * we have calibration data for all cards though to make
70 * this static */
71 static const struct net80211_channel ath9k_5ghz_chantable[] = {
72 /* _We_ call this UNII 1 */
73 CHAN5G(5180, 14), /* Channel 36 */
74 CHAN5G(5200, 15), /* Channel 40 */
75 CHAN5G(5220, 16), /* Channel 44 */
76 CHAN5G(5240, 17), /* Channel 48 */
77 /* _We_ call this UNII 2 */
78 CHAN5G(5260, 18), /* Channel 52 */
79 CHAN5G(5280, 19), /* Channel 56 */
80 CHAN5G(5300, 20), /* Channel 60 */
81 CHAN5G(5320, 21), /* Channel 64 */
82 /* _We_ call this "Middle band" */
83 CHAN5G(5500, 22), /* Channel 100 */
84 CHAN5G(5520, 23), /* Channel 104 */
85 CHAN5G(5540, 24), /* Channel 108 */
86 CHAN5G(5560, 25), /* Channel 112 */
87 CHAN5G(5580, 26), /* Channel 116 */
88 CHAN5G(5600, 27), /* Channel 120 */
89 CHAN5G(5620, 28), /* Channel 124 */
90 CHAN5G(5640, 29), /* Channel 128 */
91 CHAN5G(5660, 30), /* Channel 132 */
92 CHAN5G(5680, 31), /* Channel 136 */
93 CHAN5G(5700, 32), /* Channel 140 */
94 /* _We_ call this UNII 3 */
95 CHAN5G(5745, 33), /* Channel 149 */
96 CHAN5G(5765, 34), /* Channel 153 */
97 CHAN5G(5785, 35), /* Channel 157 */
98 CHAN5G(5805, 36), /* Channel 161 */
99 CHAN5G(5825, 37), /* Channel 165 */
100 };
101
102 /* Atheros hardware rate code addition for short premble */
103 #define SHPCHECK(__hw_rate, __flags) \
104 ((__flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0)
105
106 #define RATE(_bitrate, _hw_rate, _flags) { \
107 .bitrate = (_bitrate), \
108 .flags = (_flags), \
109 .hw_value = (_hw_rate), \
110 .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \
111 }
112
113 static struct ath9k_legacy_rate ath9k_legacy_rates[] = {
114 RATE(10, 0x1b, 0),
115 RATE(20, 0x1a, IEEE80211_TX_RC_USE_SHORT_PREAMBLE),
116 RATE(55, 0x19, IEEE80211_TX_RC_USE_SHORT_PREAMBLE),
117 RATE(110, 0x18, IEEE80211_TX_RC_USE_SHORT_PREAMBLE),
118 RATE(60, 0x0b, 0),
119 RATE(90, 0x0f, 0),
120 RATE(120, 0x0a, 0),
121 RATE(180, 0x0e, 0),
122 RATE(240, 0x09, 0),
123 RATE(360, 0x0d, 0),
124 RATE(480, 0x08, 0),
125 RATE(540, 0x0c, 0),
126 };
127
128 static void ath9k_deinit_softc(struct ath_softc *sc);
129
130 /*
131 * Read and write, they both share the same lock. We do this to serialize
132 * reads and writes on Atheros 802.11n PCI devices only. This is required
133 * as the FIFO on these devices can only accept sanely 2 requests.
134 */
135
ath9k_iowrite32(void * hw_priv,u32 val,u32 reg_offset)136 static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
137 {
138 struct ath_hw *ah = (struct ath_hw *) hw_priv;
139 struct ath_common *common = ath9k_hw_common(ah);
140 struct ath_softc *sc = (struct ath_softc *) common->priv;
141
142 writel(val, sc->mem + reg_offset);
143 }
144
ath9k_ioread32(void * hw_priv,u32 reg_offset)145 static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
146 {
147 struct ath_hw *ah = (struct ath_hw *) hw_priv;
148 struct ath_common *common = ath9k_hw_common(ah);
149 struct ath_softc *sc = (struct ath_softc *) common->priv;
150 u32 val;
151
152 val = readl(sc->mem + reg_offset);
153 return val;
154 }
155
ath9k_reg_rmw(void * hw_priv,u32 reg_offset,u32 set,u32 clr)156 static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
157 {
158 struct ath_hw *ah = (struct ath_hw *) hw_priv;
159 struct ath_common *common = ath9k_hw_common(ah);
160 struct ath_softc *sc = (struct ath_softc *) common->priv;
161 u32 val;
162
163 val = readl(sc->mem + reg_offset);
164 val &= ~clr;
165 val |= set;
166 writel(val, sc->mem + reg_offset);
167
168 return val;
169 }
170
171 /**************************/
172 /* Initialization */
173 /**************************/
174
175 /*
176 * This function will allocate both the DMA descriptor structure, and the
177 * buffers it contains. These are used to contain the descriptors used
178 * by the system.
179 */
ath_descdma_setup(struct ath_softc * sc,struct ath_descdma * dd,struct list_head * head,const char * name,int nbuf,int ndesc,int is_tx)180 int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
181 struct list_head *head, const char *name,
182 int nbuf, int ndesc, int is_tx)
183 {
184 #define DS2PHYS(_dd, _ds) \
185 ((_dd)->dd_desc_paddr + ((char *)(_ds) - (char *)(_dd)->dd_desc))
186 #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF9F) ? 1 : 0)
187 u8 *ds;
188 struct ath_buf *bf;
189 int i, bsize, error, desc_len;
190
191 DBG2("ath9k: %s DMA: %d buffers %d desc/buf\n",
192 name, nbuf, ndesc);
193
194 INIT_LIST_HEAD(head);
195
196 if (is_tx)
197 desc_len = sc->sc_ah->caps.tx_desc_len;
198 else
199 desc_len = sizeof(struct ath_desc);
200
201 /* ath_desc must be a multiple of DWORDs */
202 if ((desc_len % 4) != 0) {
203 DBG("ath9k: ath_desc not DWORD aligned\n");
204 error = -ENOMEM;
205 goto fail;
206 }
207
208 dd->dd_desc_len = desc_len * nbuf * ndesc;
209
210 /*
211 * Need additional DMA memory because we can't use
212 * descriptors that cross the 4K page boundary.
213 * However, iPXE only utilizes 16 buffers, which
214 * will never make up more than half of one page,
215 * so we will only ever skip 1 descriptor, if that.
216 */
217 if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
218 u32 ndesc_skipped = 1;
219 u32 dma_len;
220
221 dma_len = ndesc_skipped * desc_len;
222 dd->dd_desc_len += dma_len;
223 }
224
225 /* allocate descriptors */
226 dd->dd_desc = malloc_dma(dd->dd_desc_len, 16);
227 if (dd->dd_desc == NULL) {
228 error = -ENOMEM;
229 goto fail;
230 }
231 dd->dd_desc_paddr = virt_to_bus(dd->dd_desc);
232 ds = (u8 *) dd->dd_desc;
233 DBG2("ath9k: %s DMA map: %p (%d) -> %llx (%d)\n",
234 name, ds, (u32) dd->dd_desc_len,
235 ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
236
237 /* allocate buffers */
238 bsize = sizeof(struct ath_buf) * nbuf;
239 bf = zalloc(bsize);
240 if (bf == NULL) {
241 error = -ENOMEM;
242 goto fail2;
243 }
244 dd->dd_bufptr = bf;
245
246 for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {
247 bf->bf_desc = ds;
248 bf->bf_daddr = DS2PHYS(dd, ds);
249
250 if (!(sc->sc_ah->caps.hw_caps &
251 ATH9K_HW_CAP_4KB_SPLITTRANS)) {
252 /*
253 * Skip descriptor addresses which can cause 4KB
254 * boundary crossing (addr + length) with a 32 dword
255 * descriptor fetch.
256 */
257 while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
258 ds += (desc_len * ndesc);
259 bf->bf_desc = ds;
260 bf->bf_daddr = DS2PHYS(dd, ds);
261 }
262 }
263 list_add_tail(&bf->list, head);
264 }
265 return 0;
266 fail2:
267 free_dma(dd->dd_desc, dd->dd_desc_len);
268 fail:
269 memset(dd, 0, sizeof(*dd));
270 return error;
271 #undef ATH_DESC_4KB_BOUND_CHECK
272 #undef DS2PHYS
273 }
274
ath9k_init_crypto(struct ath_softc * sc)275 void ath9k_init_crypto(struct ath_softc *sc)
276 {
277 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
278 unsigned int i = 0;
279
280 /* Get the hardware key cache size. */
281 common->keymax = AR_KEYTABLE_SIZE;
282
283 /*
284 * Reset the key cache since some parts do not
285 * reset the contents on initial power up.
286 */
287 for (i = 0; i < common->keymax; i++)
288 ath_hw_keyreset(common, (u16) i);
289
290 /*
291 * Check whether the separate key cache entries
292 * are required to handle both tx+rx MIC keys.
293 * With split mic keys the number of stations is limited
294 * to 27 otherwise 59.
295 */
296 if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
297 common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
298 }
299
ath9k_init_queues(struct ath_softc * sc)300 static int ath9k_init_queues(struct ath_softc *sc)
301 {
302 int i = 0;
303
304 for (i = 0; i < WME_NUM_AC; i++) {
305 sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
306 sc->tx.txq_map[i]->mac80211_qnum = i;
307 }
308 return 0;
309 }
310
ath9k_init_channels_rates(struct ath_softc * sc)311 static int ath9k_init_channels_rates(struct ath_softc *sc)
312 {
313 unsigned int i;
314
315 memcpy(&sc->rates, ath9k_legacy_rates, sizeof(ath9k_legacy_rates));
316
317 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
318 memcpy(&sc->hwinfo->channels[sc->hwinfo->nr_channels], ath9k_2ghz_chantable, sizeof(ath9k_2ghz_chantable));
319
320 sc->hwinfo->nr_channels += ARRAY_SIZE(ath9k_2ghz_chantable);
321
322 for (i = 0; i < ARRAY_SIZE(ath9k_legacy_rates); i++)
323 sc->hwinfo->rates[NET80211_BAND_2GHZ][i] = ath9k_legacy_rates[i].bitrate;
324 sc->hwinfo->nr_rates[NET80211_BAND_2GHZ] = ARRAY_SIZE(ath9k_legacy_rates);
325 }
326
327 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
328 memcpy(&sc->hwinfo->channels[sc->hwinfo->nr_channels], ath9k_5ghz_chantable, sizeof(ath9k_5ghz_chantable));
329
330 sc->hwinfo->nr_channels += ARRAY_SIZE(ath9k_5ghz_chantable);
331
332 for (i = 4; i < ARRAY_SIZE(ath9k_legacy_rates); i++)
333 sc->hwinfo->rates[NET80211_BAND_5GHZ][i - 4] = ath9k_legacy_rates[i].bitrate;
334 sc->hwinfo->nr_rates[NET80211_BAND_5GHZ] = ARRAY_SIZE(ath9k_legacy_rates) - 4;
335 }
336 return 0;
337 }
338
ath9k_init_misc(struct ath_softc * sc)339 static void ath9k_init_misc(struct ath_softc *sc)
340 {
341 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
342
343 common->ani.timer = 0;
344
345 sc->config.txpowlimit = ATH_TXPOWER_MAX;
346
347 common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
348 common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
349
350 ath9k_hw_set_diversity(sc->sc_ah, 1);
351 sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
352
353 memcpy(common->bssidmask, eth_broadcast, ETH_ALEN);
354 }
355
ath9k_init_softc(u16 devid,struct ath_softc * sc,u16 subsysid,const struct ath_bus_ops * bus_ops)356 static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
357 const struct ath_bus_ops *bus_ops)
358 {
359 struct ath_hw *ah = NULL;
360 struct ath_common *common;
361 int ret = 0, i;
362 int csz = 0;
363
364 ah = zalloc(sizeof(struct ath_hw));
365 if (!ah)
366 return -ENOMEM;
367
368 ah->dev = sc->dev;
369 ah->hw_version.devid = devid;
370 ah->hw_version.subsysid = subsysid;
371 ah->reg_ops.read = ath9k_ioread32;
372 ah->reg_ops.write = ath9k_iowrite32;
373 ah->reg_ops.rmw = ath9k_reg_rmw;
374 sc->sc_ah = ah;
375
376 sc->hwinfo = zalloc(sizeof(*sc->hwinfo));
377 if (!sc->hwinfo) {
378 DBG("ath9k: cannot allocate 802.11 hardware info structure\n");
379 return -ENOMEM;
380 }
381
382 ah->ah_flags |= AH_USE_EEPROM;
383 sc->sc_ah->led_pin = -1;
384
385 common = ath9k_hw_common(ah);
386 common->ops = &ah->reg_ops;
387 common->bus_ops = bus_ops;
388 common->ah = ah;
389 common->dev = sc->dev;
390 common->priv = sc;
391
392 sc->intr_tq = ath9k_tasklet;
393
394 /*
395 * Cache line size is used to size and align various
396 * structures used to communicate with the hardware.
397 */
398 ath_read_cachesize(common, &csz);
399 common->cachelsz = csz << 2; /* convert to bytes */
400
401 /* Initializes the hardware for all supported chipsets */
402 ret = ath9k_hw_init(ah);
403 if (ret)
404 goto err_hw;
405
406 memcpy(sc->hwinfo->hwaddr, common->macaddr, ETH_ALEN);
407
408 ret = ath9k_init_queues(sc);
409 if (ret)
410 goto err_queues;
411
412 ret = ath9k_init_channels_rates(sc);
413 if (ret)
414 goto err_btcoex;
415
416 ath9k_init_crypto(sc);
417 ath9k_init_misc(sc);
418
419 return 0;
420
421 err_btcoex:
422 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
423 if (ATH_TXQ_SETUP(sc, i))
424 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
425 err_queues:
426 ath9k_hw_deinit(ah);
427 err_hw:
428 free(sc->hwinfo);
429 sc->hwinfo = NULL;
430
431 free(ah);
432 sc->sc_ah = NULL;
433
434 return ret;
435 }
436
ath9k_init_band_txpower(struct ath_softc * sc,int band)437 static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
438 {
439 struct net80211_channel *chan;
440 struct ath_hw *ah = sc->sc_ah;
441 struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
442 int i;
443
444 for (i = 0; i < sc->hwinfo->nr_channels; i++) {
445 chan = &sc->hwinfo->channels[i];
446 if(chan->band != band)
447 continue;
448 ah->curchan = &ah->channels[chan->hw_value];
449 ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, 1);
450 chan->maxpower = reg->max_power_level / 2;
451 }
452 }
453
ath9k_init_txpower_limits(struct ath_softc * sc)454 static void ath9k_init_txpower_limits(struct ath_softc *sc)
455 {
456 struct ath_hw *ah = sc->sc_ah;
457 struct ath9k_channel *curchan = ah->curchan;
458
459 if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
460 ath9k_init_band_txpower(sc, NET80211_BAND_2GHZ);
461 if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
462 ath9k_init_band_txpower(sc, NET80211_BAND_5GHZ);
463
464 ah->curchan = curchan;
465 }
466
ath9k_set_hw_capab(struct ath_softc * sc,struct net80211_device * dev __unused)467 void ath9k_set_hw_capab(struct ath_softc *sc, struct net80211_device *dev __unused)
468 {
469 sc->hwinfo->flags = NET80211_HW_RX_HAS_FCS;
470 sc->hwinfo->signal_type = NET80211_SIGNAL_DB;
471 sc->hwinfo->signal_max = 40; /* 35dB should give perfect 54Mbps */
472 sc->hwinfo->channel_change_time = 5000;
473
474 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
475 {
476 sc->hwinfo->bands |= NET80211_BAND_BIT_2GHZ;
477 sc->hwinfo->modes |= NET80211_MODE_B | NET80211_MODE_G;
478 }
479 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
480 {
481 sc->hwinfo->bands |= NET80211_BAND_BIT_5GHZ;
482 sc->hwinfo->modes |= NET80211_MODE_A;
483 }
484 }
485
ath9k_init_device(u16 devid,struct ath_softc * sc,u16 subsysid,const struct ath_bus_ops * bus_ops)486 int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
487 const struct ath_bus_ops *bus_ops)
488 {
489 struct net80211_device *dev = sc->dev;
490 /*struct ath_common *common;
491 struct ath_hw *ah;*/
492 int error = 0;
493 /*struct ath_regulatory *reg;*/
494
495 /* Bring up device */
496 error = ath9k_init_softc(devid, sc, subsysid, bus_ops);
497 if (error != 0)
498 goto error_init;
499
500 /*ah = sc->sc_ah;
501 common = ath9k_hw_common(ah);*/
502 ath9k_set_hw_capab(sc, dev);
503 /* TODO Cottsay: reg */
504 /* Initialize regulatory */
505 /*error = ath_regd_init(&common->regulatory, sc->dev->wiphy,
506 ath9k_reg_notifier);
507 if (error)
508 goto error_regd;
509
510 reg = &common->regulatory;*/
511
512 /* Setup TX DMA */
513 error = ath_tx_init(sc, ATH_TXBUF);
514 if (error != 0)
515 goto error_tx;
516
517 /* Setup RX DMA */
518 error = ath_rx_init(sc, ATH_RXBUF);
519 if (error != 0)
520 goto error_rx;
521
522 ath9k_init_txpower_limits(sc);
523
524 /* Register with mac80211 */
525 error = net80211_register(dev, &ath9k_ops, sc->hwinfo);
526 if (error)
527 goto error_register;
528
529 /* TODO Cottsay: reg */
530 /* Handle world regulatory */
531 /*if (!ath_is_world_regd(reg)) {
532 error = regulatory_hint(hw->wiphy, reg->alpha2);
533 if (error)
534 goto error_world;
535 }*/
536
537 sc->hw_pll_work = ath_hw_pll_work;
538 sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
539
540 /* TODO Cottsay: rfkill */
541 /*ath_start_rfkill_poll(sc);*/
542
543 return 0;
544
545 //error_world:
546 // net80211_unregister(dev);
547 error_register:
548 ath_rx_cleanup(sc);
549 error_rx:
550 ath_tx_cleanup(sc);
551 error_tx:
552 ath9k_deinit_softc(sc);
553 error_init:
554 return error;
555 }
556
557 /*****************************/
558 /* De-Initialization */
559 /*****************************/
560
ath9k_deinit_softc(struct ath_softc * sc)561 static void ath9k_deinit_softc(struct ath_softc *sc)
562 {
563 int i = 0;
564
565 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
566 if (ATH_TXQ_SETUP(sc, i))
567 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
568
569 ath9k_hw_deinit(sc->sc_ah);
570
571 free(sc->hwinfo);
572 sc->hwinfo = NULL;
573 free(sc->sc_ah);
574 sc->sc_ah = NULL;
575 }
576
ath9k_deinit_device(struct ath_softc * sc)577 void ath9k_deinit_device(struct ath_softc *sc)
578 {
579 struct net80211_device *dev = sc->dev;
580
581 net80211_unregister(dev);
582 ath_rx_cleanup(sc);
583 ath_tx_cleanup(sc);
584 ath9k_deinit_softc(sc);
585 }
586
ath_descdma_cleanup(struct ath_softc * sc __unused,struct ath_descdma * dd,struct list_head * head)587 void ath_descdma_cleanup(struct ath_softc *sc __unused,
588 struct ath_descdma *dd,
589 struct list_head *head)
590 {
591 free_dma(dd->dd_desc, dd->dd_desc_len);
592
593 INIT_LIST_HEAD(head);
594 free(dd->dd_bufptr);
595 memset(dd, 0, sizeof(*dd));
596 }
597