iPXE
ath9k_init.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008-2011 Atheros Communications Inc.
00003  *
00004  * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
00005  * Original from Linux kernel 3.0.1
00006  *
00007  * Permission to use, copy, modify, and/or distribute this software for any
00008  * purpose with or without fee is hereby granted, provided that the above
00009  * copyright notice and this permission notice appear in all copies.
00010  *
00011  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00012  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00013  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00014  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00015  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00016  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00017  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00018  */
00019 
00020 FILE_LICENCE ( BSD2 );
00021 
00022 #include <ipxe/malloc.h>
00023 #include <ipxe/pci_io.h>
00024 #include <ipxe/pci.h>
00025 #include <ipxe/ethernet.h>
00026 
00027 #include "ath9k.h"
00028 
00029 int is_ath9k_unloaded;
00030 /* We use the hw_value as an index into our private channel structure */
00031 
00032 #define CHAN2G(_freq, _idx)  { \
00033         .band = NET80211_BAND_2GHZ, \
00034         .center_freq = (_freq), \
00035         .hw_value = (_idx), \
00036         .maxpower = 20, \
00037 }
00038 
00039 #define CHAN5G(_freq, _idx) { \
00040         .band = NET80211_BAND_5GHZ, \
00041         .center_freq = (_freq), \
00042         .hw_value = (_idx), \
00043         .maxpower = 20, \
00044 }
00045 
00046 /* Some 2 GHz radios are actually tunable on 2312-2732
00047  * on 5 MHz steps, we support the channels which we know
00048  * we have calibration data for all cards though to make
00049  * this static */
00050 static const struct net80211_channel ath9k_2ghz_chantable[] = {
00051         CHAN2G(2412, 0), /* Channel 1 */
00052         CHAN2G(2417, 1), /* Channel 2 */
00053         CHAN2G(2422, 2), /* Channel 3 */
00054         CHAN2G(2427, 3), /* Channel 4 */
00055         CHAN2G(2432, 4), /* Channel 5 */
00056         CHAN2G(2437, 5), /* Channel 6 */
00057         CHAN2G(2442, 6), /* Channel 7 */
00058         CHAN2G(2447, 7), /* Channel 8 */
00059         CHAN2G(2452, 8), /* Channel 9 */
00060         CHAN2G(2457, 9), /* Channel 10 */
00061         CHAN2G(2462, 10), /* Channel 11 */
00062         CHAN2G(2467, 11), /* Channel 12 */
00063         CHAN2G(2472, 12), /* Channel 13 */
00064         CHAN2G(2484, 13), /* Channel 14 */
00065 };
00066 
00067 /* Some 5 GHz radios are actually tunable on XXXX-YYYY
00068  * on 5 MHz steps, we support the channels which we know
00069  * we have calibration data for all cards though to make
00070  * this static */
00071 static const struct net80211_channel ath9k_5ghz_chantable[] = {
00072         /* _We_ call this UNII 1 */
00073         CHAN5G(5180, 14), /* Channel 36 */
00074         CHAN5G(5200, 15), /* Channel 40 */
00075         CHAN5G(5220, 16), /* Channel 44 */
00076         CHAN5G(5240, 17), /* Channel 48 */
00077         /* _We_ call this UNII 2 */
00078         CHAN5G(5260, 18), /* Channel 52 */
00079         CHAN5G(5280, 19), /* Channel 56 */
00080         CHAN5G(5300, 20), /* Channel 60 */
00081         CHAN5G(5320, 21), /* Channel 64 */
00082         /* _We_ call this "Middle band" */
00083         CHAN5G(5500, 22), /* Channel 100 */
00084         CHAN5G(5520, 23), /* Channel 104 */
00085         CHAN5G(5540, 24), /* Channel 108 */
00086         CHAN5G(5560, 25), /* Channel 112 */
00087         CHAN5G(5580, 26), /* Channel 116 */
00088         CHAN5G(5600, 27), /* Channel 120 */
00089         CHAN5G(5620, 28), /* Channel 124 */
00090         CHAN5G(5640, 29), /* Channel 128 */
00091         CHAN5G(5660, 30), /* Channel 132 */
00092         CHAN5G(5680, 31), /* Channel 136 */
00093         CHAN5G(5700, 32), /* Channel 140 */
00094         /* _We_ call this UNII 3 */
00095         CHAN5G(5745, 33), /* Channel 149 */
00096         CHAN5G(5765, 34), /* Channel 153 */
00097         CHAN5G(5785, 35), /* Channel 157 */
00098         CHAN5G(5805, 36), /* Channel 161 */
00099         CHAN5G(5825, 37), /* Channel 165 */
00100 };
00101 
00102 /* Atheros hardware rate code addition for short premble */
00103 #define SHPCHECK(__hw_rate, __flags) \
00104         ((__flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0)
00105 
00106 #define RATE(_bitrate, _hw_rate, _flags) {              \
00107         .bitrate        = (_bitrate),                   \
00108         .flags          = (_flags),                     \
00109         .hw_value       = (_hw_rate),                   \
00110         .hw_value_short = (SHPCHECK(_hw_rate, _flags))  \
00111 }
00112 
00113 static struct ath9k_legacy_rate ath9k_legacy_rates[] = {
00114         RATE(10, 0x1b, 0),
00115         RATE(20, 0x1a, IEEE80211_TX_RC_USE_SHORT_PREAMBLE),
00116         RATE(55, 0x19, IEEE80211_TX_RC_USE_SHORT_PREAMBLE),
00117         RATE(110, 0x18, IEEE80211_TX_RC_USE_SHORT_PREAMBLE),
00118         RATE(60, 0x0b, 0),
00119         RATE(90, 0x0f, 0),
00120         RATE(120, 0x0a, 0),
00121         RATE(180, 0x0e, 0),
00122         RATE(240, 0x09, 0),
00123         RATE(360, 0x0d, 0),
00124         RATE(480, 0x08, 0),
00125         RATE(540, 0x0c, 0),
00126 };
00127 
00128 static void ath9k_deinit_softc(struct ath_softc *sc);
00129 
00130 /*
00131  * Read and write, they both share the same lock. We do this to serialize
00132  * reads and writes on Atheros 802.11n PCI devices only. This is required
00133  * as the FIFO on these devices can only accept sanely 2 requests.
00134  */
00135 
00136 static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
00137 {
00138         struct ath_hw *ah = (struct ath_hw *) hw_priv;
00139         struct ath_common *common = ath9k_hw_common(ah);
00140         struct ath_softc *sc = (struct ath_softc *) common->priv;
00141 
00142         writel(val, sc->mem + reg_offset);
00143 }
00144 
00145 static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
00146 {
00147         struct ath_hw *ah = (struct ath_hw *) hw_priv;
00148         struct ath_common *common = ath9k_hw_common(ah);
00149         struct ath_softc *sc = (struct ath_softc *) common->priv;
00150         u32 val;
00151 
00152         val = readl(sc->mem + reg_offset);
00153         return val;
00154 }
00155 
00156 static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
00157 {
00158         struct ath_hw *ah = (struct ath_hw *) hw_priv;
00159         struct ath_common *common = ath9k_hw_common(ah);
00160         struct ath_softc *sc = (struct ath_softc *) common->priv;
00161         u32 val;
00162 
00163         val = readl(sc->mem + reg_offset);
00164         val &= ~clr;
00165         val |= set;
00166         writel(val, sc->mem + reg_offset);
00167 
00168         return val;
00169 }
00170 
00171 /**************************/
00172 /*     Initialization     */
00173 /**************************/
00174 
00175 /*
00176  *  This function will allocate both the DMA descriptor structure, and the
00177  *  buffers it contains.  These are used to contain the descriptors used
00178  *  by the system.
00179 */
00180 int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
00181                       struct list_head *head, const char *name,
00182                       int nbuf, int ndesc, int is_tx)
00183 {
00184 #define DS2PHYS(_dd, _ds)                                               \
00185         ((_dd)->dd_desc_paddr + ((char *)(_ds) - (char *)(_dd)->dd_desc))
00186 #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF9F) ? 1 : 0)
00187         u8 *ds;
00188         struct ath_buf *bf;
00189         int i, bsize, error, desc_len;
00190 
00191         DBG2("ath9k: %s DMA: %d buffers %d desc/buf\n",
00192                 name, nbuf, ndesc);
00193 
00194         INIT_LIST_HEAD(head);
00195 
00196         if (is_tx)
00197                 desc_len = sc->sc_ah->caps.tx_desc_len;
00198         else
00199                 desc_len = sizeof(struct ath_desc);
00200 
00201         /* ath_desc must be a multiple of DWORDs */
00202         if ((desc_len % 4) != 0) {
00203                 DBG("ath9k: ath_desc not DWORD aligned\n");
00204                 error = -ENOMEM;
00205                 goto fail;
00206         }
00207 
00208         dd->dd_desc_len = desc_len * nbuf * ndesc;
00209 
00210         /*
00211          * Need additional DMA memory because we can't use
00212          * descriptors that cross the 4K page boundary.
00213          * However, iPXE only utilizes 16 buffers, which
00214          * will never make up more than half of one page,
00215          * so we will only ever skip 1 descriptor, if that.
00216          */
00217         if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
00218                 u32 ndesc_skipped = 1;
00219                 u32 dma_len;
00220 
00221                 dma_len = ndesc_skipped * desc_len;
00222                 dd->dd_desc_len += dma_len;
00223         }
00224 
00225         /* allocate descriptors */
00226         dd->dd_desc = malloc_dma(dd->dd_desc_len, 16);
00227         if (dd->dd_desc == NULL) {
00228                 error = -ENOMEM;
00229                 goto fail;
00230         }
00231         dd->dd_desc_paddr = virt_to_bus(dd->dd_desc);
00232         ds = (u8 *) dd->dd_desc;
00233         DBG2("ath9k: %s DMA map: %p (%d) -> %llx (%d)\n",
00234                 name, ds, (u32) dd->dd_desc_len,
00235                 ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
00236 
00237         /* allocate buffers */
00238         bsize = sizeof(struct ath_buf) * nbuf;
00239         bf = zalloc(bsize);
00240         if (bf == NULL) {
00241                 error = -ENOMEM;
00242                 goto fail2;
00243         }
00244         dd->dd_bufptr = bf;
00245 
00246         for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {
00247                 bf->bf_desc = ds;
00248                 bf->bf_daddr = DS2PHYS(dd, ds);
00249 
00250                 if (!(sc->sc_ah->caps.hw_caps &
00251                       ATH9K_HW_CAP_4KB_SPLITTRANS)) {
00252                         /*
00253                          * Skip descriptor addresses which can cause 4KB
00254                          * boundary crossing (addr + length) with a 32 dword
00255                          * descriptor fetch.
00256                          */
00257                         while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
00258                                 ds += (desc_len * ndesc);
00259                                 bf->bf_desc = ds;
00260                                 bf->bf_daddr = DS2PHYS(dd, ds);
00261                         }
00262                 }
00263                 list_add_tail(&bf->list, head);
00264         }
00265         return 0;
00266 fail2:
00267         free_dma(dd->dd_desc, dd->dd_desc_len);
00268 fail:
00269         memset(dd, 0, sizeof(*dd));
00270         return error;
00271 #undef ATH_DESC_4KB_BOUND_CHECK
00272 #undef DS2PHYS
00273 }
00274 
00275 void ath9k_init_crypto(struct ath_softc *sc)
00276 {
00277         struct ath_common *common = ath9k_hw_common(sc->sc_ah);
00278         unsigned int i = 0;
00279 
00280         /* Get the hardware key cache size. */
00281         common->keymax = AR_KEYTABLE_SIZE;
00282 
00283         /*
00284          * Reset the key cache since some parts do not
00285          * reset the contents on initial power up.
00286          */
00287         for (i = 0; i < common->keymax; i++)
00288                 ath_hw_keyreset(common, (u16) i);
00289 
00290         /*
00291          * Check whether the separate key cache entries
00292          * are required to handle both tx+rx MIC keys.
00293          * With split mic keys the number of stations is limited
00294          * to 27 otherwise 59.
00295          */
00296         if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
00297                 common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
00298 }
00299 
00300 static int ath9k_init_queues(struct ath_softc *sc)
00301 {
00302         int i = 0;
00303 
00304         for (i = 0; i < WME_NUM_AC; i++) {
00305                 sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
00306                 sc->tx.txq_map[i]->mac80211_qnum = i;
00307         }
00308         return 0;
00309 }
00310 
00311 static int ath9k_init_channels_rates(struct ath_softc *sc)
00312 {
00313         unsigned int i;
00314 
00315         memcpy(&sc->rates, ath9k_legacy_rates, sizeof(ath9k_legacy_rates));
00316 
00317         if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
00318                 memcpy(&sc->hwinfo->channels[sc->hwinfo->nr_channels], ath9k_2ghz_chantable, sizeof(ath9k_2ghz_chantable));
00319 
00320                 sc->hwinfo->nr_channels += ARRAY_SIZE(ath9k_2ghz_chantable);
00321 
00322                 for (i = 0; i < ARRAY_SIZE(ath9k_legacy_rates); i++)
00323                         sc->hwinfo->rates[NET80211_BAND_2GHZ][i] = ath9k_legacy_rates[i].bitrate;
00324                 sc->hwinfo->nr_rates[NET80211_BAND_2GHZ] = ARRAY_SIZE(ath9k_legacy_rates);
00325         }
00326 
00327         if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
00328                 memcpy(&sc->hwinfo->channels[sc->hwinfo->nr_channels], ath9k_5ghz_chantable, sizeof(ath9k_5ghz_chantable));
00329 
00330                 sc->hwinfo->nr_channels += ARRAY_SIZE(ath9k_5ghz_chantable);
00331 
00332                 for (i = 4; i < ARRAY_SIZE(ath9k_legacy_rates); i++)
00333                         sc->hwinfo->rates[NET80211_BAND_5GHZ][i - 4] = ath9k_legacy_rates[i].bitrate;
00334                 sc->hwinfo->nr_rates[NET80211_BAND_5GHZ] = ARRAY_SIZE(ath9k_legacy_rates) - 4;
00335         }
00336         return 0;
00337 }
00338 
00339 static void ath9k_init_misc(struct ath_softc *sc)
00340 {
00341         struct ath_common *common = ath9k_hw_common(sc->sc_ah);
00342 
00343         common->ani.timer = 0;
00344 
00345         sc->config.txpowlimit = ATH_TXPOWER_MAX;
00346 
00347         common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
00348         common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
00349 
00350         ath9k_hw_set_diversity(sc->sc_ah, 1);
00351         sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
00352 
00353         memcpy(common->bssidmask, eth_broadcast, ETH_ALEN);
00354 }
00355 
00356 static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
00357                             const struct ath_bus_ops *bus_ops)
00358 {
00359         struct ath_hw *ah = NULL;
00360         struct ath_common *common;
00361         int ret = 0, i;
00362         int csz = 0;
00363 
00364         ah = zalloc(sizeof(struct ath_hw));
00365         if (!ah)
00366                 return -ENOMEM;
00367 
00368         ah->dev = sc->dev;
00369         ah->hw_version.devid = devid;
00370         ah->hw_version.subsysid = subsysid;
00371         ah->reg_ops.read = ath9k_ioread32;
00372         ah->reg_ops.write = ath9k_iowrite32;
00373         ah->reg_ops.rmw = ath9k_reg_rmw;
00374         sc->sc_ah = ah;
00375 
00376         sc->hwinfo = zalloc(sizeof(*sc->hwinfo));
00377         if (!sc->hwinfo) {
00378                 DBG("ath9k: cannot allocate 802.11 hardware info structure\n");
00379                 return -ENOMEM;
00380         }
00381 
00382         ah->ah_flags |= AH_USE_EEPROM;
00383         sc->sc_ah->led_pin = -1;
00384 
00385         common = ath9k_hw_common(ah);
00386         common->ops = &ah->reg_ops;
00387         common->bus_ops = bus_ops;
00388         common->ah = ah;
00389         common->dev = sc->dev;
00390         common->priv = sc;
00391 
00392         sc->intr_tq = ath9k_tasklet;
00393 
00394         /*
00395          * Cache line size is used to size and align various
00396          * structures used to communicate with the hardware.
00397          */
00398         ath_read_cachesize(common, &csz);
00399         common->cachelsz = csz << 2; /* convert to bytes */
00400 
00401         /* Initializes the hardware for all supported chipsets */
00402         ret = ath9k_hw_init(ah);
00403         if (ret)
00404                 goto err_hw;
00405 
00406         memcpy(sc->hwinfo->hwaddr, common->macaddr, ETH_ALEN);
00407 
00408         ret = ath9k_init_queues(sc);
00409         if (ret)
00410                 goto err_queues;
00411 
00412         ret = ath9k_init_channels_rates(sc);
00413         if (ret)
00414                 goto err_btcoex;
00415 
00416         ath9k_init_crypto(sc);
00417         ath9k_init_misc(sc);
00418 
00419         return 0;
00420 
00421 err_btcoex:
00422         for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
00423                 if (ATH_TXQ_SETUP(sc, i))
00424                         ath_tx_cleanupq(sc, &sc->tx.txq[i]);
00425 err_queues:
00426         ath9k_hw_deinit(ah);
00427 err_hw:
00428         free(sc->hwinfo);
00429         sc->hwinfo = NULL;
00430 
00431         free(ah);
00432         sc->sc_ah = NULL;
00433 
00434         return ret;
00435 }
00436 
00437 static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
00438 {
00439         struct net80211_channel *chan;
00440         struct ath_hw *ah = sc->sc_ah;
00441         struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
00442         int i;
00443 
00444         for (i = 0; i < sc->hwinfo->nr_channels; i++) {
00445                 chan = &sc->hwinfo->channels[i];
00446                 if(chan->band != band)
00447                         continue;
00448                 ah->curchan = &ah->channels[chan->hw_value];
00449                 ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, 1);
00450                 chan->maxpower = reg->max_power_level / 2;
00451         }
00452 }
00453 
00454 static void ath9k_init_txpower_limits(struct ath_softc *sc)
00455 {
00456         struct ath_hw *ah = sc->sc_ah;
00457         struct ath9k_channel *curchan = ah->curchan;
00458 
00459         if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
00460                 ath9k_init_band_txpower(sc, NET80211_BAND_2GHZ);
00461         if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
00462                 ath9k_init_band_txpower(sc, NET80211_BAND_5GHZ);
00463 
00464         ah->curchan = curchan;
00465 }
00466 
00467 void ath9k_set_hw_capab(struct ath_softc *sc, struct net80211_device *dev __unused)
00468 {
00469         sc->hwinfo->flags = NET80211_HW_RX_HAS_FCS;
00470         sc->hwinfo->signal_type = NET80211_SIGNAL_DB;
00471         sc->hwinfo->signal_max = 40; /* 35dB should give perfect 54Mbps */
00472         sc->hwinfo->channel_change_time = 5000;
00473 
00474         if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
00475         {
00476                 sc->hwinfo->bands |= NET80211_BAND_BIT_2GHZ;
00477                 sc->hwinfo->modes |= NET80211_MODE_B | NET80211_MODE_G;
00478         }
00479         if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
00480         {
00481                 sc->hwinfo->bands |= NET80211_BAND_BIT_5GHZ;
00482                 sc->hwinfo->modes |= NET80211_MODE_A;
00483         }
00484 }
00485 
00486 int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
00487                     const struct ath_bus_ops *bus_ops)
00488 {
00489         struct net80211_device *dev = sc->dev;
00490         /*struct ath_common *common;
00491         struct ath_hw *ah;*/
00492         int error = 0;
00493         /*struct ath_regulatory *reg;*/
00494 
00495         /* Bring up device */
00496         error = ath9k_init_softc(devid, sc, subsysid, bus_ops);
00497         if (error != 0)
00498                 goto error_init;
00499 
00500         /*ah = sc->sc_ah;
00501         common = ath9k_hw_common(ah);*/
00502         ath9k_set_hw_capab(sc, dev);
00503         /* TODO Cottsay: reg */
00504         /* Initialize regulatory */
00505         /*error = ath_regd_init(&common->regulatory, sc->dev->wiphy,
00506                               ath9k_reg_notifier);
00507         if (error)
00508                 goto error_regd;
00509 
00510         reg = &common->regulatory;*/
00511 
00512         /* Setup TX DMA */
00513         error = ath_tx_init(sc, ATH_TXBUF);
00514         if (error != 0)
00515                 goto error_tx;
00516 
00517         /* Setup RX DMA */
00518         error = ath_rx_init(sc, ATH_RXBUF);
00519         if (error != 0)
00520                 goto error_rx;
00521 
00522         ath9k_init_txpower_limits(sc);
00523 
00524         /* Register with mac80211 */
00525         error = net80211_register(dev, &ath9k_ops, sc->hwinfo);
00526         if (error)
00527                 goto error_register;
00528 
00529         /* TODO Cottsay: reg */
00530         /* Handle world regulatory */
00531         /*if (!ath_is_world_regd(reg)) {
00532                 error = regulatory_hint(hw->wiphy, reg->alpha2);
00533                 if (error)
00534                         goto error_world;
00535         }*/
00536 
00537         sc->hw_pll_work = ath_hw_pll_work;
00538         sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
00539 
00540         /* TODO Cottsay: rfkill */
00541         /*ath_start_rfkill_poll(sc);*/
00542 
00543         return 0;
00544 
00545 //error_world:
00546 //      net80211_unregister(dev);
00547 error_register:
00548         ath_rx_cleanup(sc);
00549 error_rx:
00550         ath_tx_cleanup(sc);
00551 error_tx:
00552         ath9k_deinit_softc(sc);
00553 error_init:
00554         return error;
00555 }
00556 
00557 /*****************************/
00558 /*     De-Initialization     */
00559 /*****************************/
00560 
00561 static void ath9k_deinit_softc(struct ath_softc *sc)
00562 {
00563         int i = 0;
00564 
00565         for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
00566                 if (ATH_TXQ_SETUP(sc, i))
00567                         ath_tx_cleanupq(sc, &sc->tx.txq[i]);
00568 
00569         ath9k_hw_deinit(sc->sc_ah);
00570 
00571         free(sc->hwinfo);
00572         sc->hwinfo = NULL;
00573         free(sc->sc_ah);
00574         sc->sc_ah = NULL;
00575 }
00576 
00577 void ath9k_deinit_device(struct ath_softc *sc)
00578 {
00579         struct net80211_device *dev = sc->dev;
00580 
00581         net80211_unregister(dev);
00582         ath_rx_cleanup(sc);
00583         ath_tx_cleanup(sc);
00584         ath9k_deinit_softc(sc);
00585 }
00586 
00587 void ath_descdma_cleanup(struct ath_softc *sc __unused,
00588                          struct ath_descdma *dd,
00589                          struct list_head *head)
00590 {
00591         free_dma(dd->dd_desc, dd->dd_desc_len);
00592 
00593         INIT_LIST_HEAD(head);
00594         free(dd->dd_bufptr);
00595         memset(dd, 0, sizeof(*dd));
00596 }