diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2010-01-08 00:06:07 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-01-12 14:02:05 -0500 |
commit | 285f2ddae03ca207877262f5a9dbd9cddd8b3913 (patch) | |
tree | 7b26606956f4d6f4c1f564718769501b34d3f640 /drivers/net/wireless/ath/ath9k/init.c | |
parent | 1b04b9308ebc7f6accb319cf51c9b8ec29f79707 (diff) |
ath9k: Cleanup init/deinit routines
The device initialization and termination functions
were messy and convoluted. Introduce helper functions
to clarify init_softc() and simplify things in general.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/init.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/init.c | 515 |
1 files changed, 261 insertions, 254 deletions
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 2bea0892918e..16d1efb4b8b2 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -128,7 +128,7 @@ static struct ieee80211_rate ath9k_legacy_rates[] = { | |||
128 | RATE(540, 0x0c, 0), | 128 | RATE(540, 0x0c, 0), |
129 | }; | 129 | }; |
130 | 130 | ||
131 | static void ath9k_uninit_hw(struct ath_softc *sc); | 131 | static void ath9k_deinit_softc(struct ath_softc *sc); |
132 | 132 | ||
133 | /* | 133 | /* |
134 | * Read and write, they both share the same lock. We do this to serialize | 134 | * Read and write, they both share the same lock. We do this to serialize |
@@ -333,67 +333,13 @@ fail: | |||
333 | #undef DS2PHYS | 333 | #undef DS2PHYS |
334 | } | 334 | } |
335 | 335 | ||
336 | static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | 336 | static void ath9k_init_crypto(struct ath_softc *sc) |
337 | const struct ath_bus_ops *bus_ops) | ||
338 | { | 337 | { |
339 | struct ath_hw *ah = NULL; | 338 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
340 | struct ath_common *common; | 339 | int i = 0; |
341 | int r = 0, i; | ||
342 | int csz = 0; | ||
343 | int qnum; | ||
344 | |||
345 | /* XXX: hardware will not be ready until ath_open() being called */ | ||
346 | sc->sc_flags |= SC_OP_INVALID; | ||
347 | |||
348 | spin_lock_init(&sc->wiphy_lock); | ||
349 | spin_lock_init(&sc->sc_resetlock); | ||
350 | spin_lock_init(&sc->sc_serial_rw); | ||
351 | spin_lock_init(&sc->sc_pm_lock); | ||
352 | mutex_init(&sc->mutex); | ||
353 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); | ||
354 | tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, | ||
355 | (unsigned long)sc); | ||
356 | |||
357 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); | ||
358 | if (!ah) | ||
359 | return -ENOMEM; | ||
360 | |||
361 | ah->hw_version.devid = devid; | ||
362 | ah->hw_version.subsysid = subsysid; | ||
363 | sc->sc_ah = ah; | ||
364 | |||
365 | common = ath9k_hw_common(ah); | ||
366 | common->ops = &ath9k_common_ops; | ||
367 | common->bus_ops = bus_ops; | ||
368 | common->ah = ah; | ||
369 | common->hw = sc->hw; | ||
370 | common->priv = sc; | ||
371 | common->debug_mask = ath9k_debug; | ||
372 | |||
373 | /* | ||
374 | * Cache line size is used to size and align various | ||
375 | * structures used to communicate with the hardware. | ||
376 | */ | ||
377 | ath_read_cachesize(common, &csz); | ||
378 | /* XXX assert csz is non-zero */ | ||
379 | common->cachelsz = csz << 2; /* convert to bytes */ | ||
380 | |||
381 | r = ath9k_hw_init(ah); | ||
382 | if (r) { | ||
383 | ath_print(common, ATH_DBG_FATAL, | ||
384 | "Unable to initialize hardware; " | ||
385 | "initialization status: %d\n", r); | ||
386 | goto bad_free_hw; | ||
387 | } | ||
388 | |||
389 | if (ath9k_init_debug(ah) < 0) { | ||
390 | ath_print(common, ATH_DBG_FATAL, | ||
391 | "Unable to create debugfs files\n"); | ||
392 | goto bad_free_hw; | ||
393 | } | ||
394 | 340 | ||
395 | /* Get the hardware key cache size. */ | 341 | /* Get the hardware key cache size. */ |
396 | common->keymax = ah->caps.keycache_size; | 342 | common->keymax = sc->sc_ah->caps.keycache_size; |
397 | if (common->keymax > ATH_KEYMAX) { | 343 | if (common->keymax > ATH_KEYMAX) { |
398 | ath_print(common, ATH_DBG_ANY, | 344 | ath_print(common, ATH_DBG_ANY, |
399 | "Warning, using only %u entries in %u key cache\n", | 345 | "Warning, using only %u entries in %u key cache\n", |
@@ -406,185 +352,273 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
406 | * reset the contents on initial power up. | 352 | * reset the contents on initial power up. |
407 | */ | 353 | */ |
408 | for (i = 0; i < common->keymax; i++) | 354 | for (i = 0; i < common->keymax; i++) |
409 | ath9k_hw_keyreset(ah, (u16) i); | 355 | ath9k_hw_keyreset(sc->sc_ah, (u16) i); |
410 | 356 | ||
411 | /* default to MONITOR mode */ | 357 | if (ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, |
412 | sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR; | 358 | ATH9K_CIPHER_TKIP, NULL)) { |
359 | /* | ||
360 | * Whether we should enable h/w TKIP MIC. | ||
361 | * XXX: if we don't support WME TKIP MIC, then we wouldn't | ||
362 | * report WMM capable, so it's always safe to turn on | ||
363 | * TKIP MIC in this case. | ||
364 | */ | ||
365 | ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, 0, 1, NULL); | ||
366 | } | ||
413 | 367 | ||
414 | /* | 368 | /* |
415 | * Allocate hardware transmit queues: one queue for | 369 | * Check whether the separate key cache entries |
416 | * beacon frames and one data queue for each QoS | 370 | * are required to handle both tx+rx MIC keys. |
417 | * priority. Note that the hal handles reseting | 371 | * With split mic keys the number of stations is limited |
418 | * these queues at the needed time. | 372 | * to 27 otherwise 59. |
419 | */ | 373 | */ |
420 | sc->beacon.beaconq = ath9k_hw_beaconq_setup(ah); | 374 | if (ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, |
375 | ATH9K_CIPHER_TKIP, NULL) | ||
376 | && ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, | ||
377 | ATH9K_CIPHER_MIC, NULL) | ||
378 | && ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_TKIP_SPLIT, | ||
379 | 0, NULL)) | ||
380 | common->splitmic = 1; | ||
381 | |||
382 | /* turn on mcast key search if possible */ | ||
383 | if (!ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) | ||
384 | (void)ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_MCAST_KEYSRCH, | ||
385 | 1, 1, NULL); | ||
386 | |||
387 | } | ||
388 | |||
389 | static int ath9k_init_btcoex(struct ath_softc *sc) | ||
390 | { | ||
391 | int r, qnum; | ||
392 | |||
393 | switch (sc->sc_ah->btcoex_hw.scheme) { | ||
394 | case ATH_BTCOEX_CFG_NONE: | ||
395 | break; | ||
396 | case ATH_BTCOEX_CFG_2WIRE: | ||
397 | ath9k_hw_btcoex_init_2wire(sc->sc_ah); | ||
398 | break; | ||
399 | case ATH_BTCOEX_CFG_3WIRE: | ||
400 | ath9k_hw_btcoex_init_3wire(sc->sc_ah); | ||
401 | r = ath_init_btcoex_timer(sc); | ||
402 | if (r) | ||
403 | return -1; | ||
404 | qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); | ||
405 | ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum); | ||
406 | sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | ||
407 | break; | ||
408 | default: | ||
409 | WARN_ON(1); | ||
410 | break; | ||
411 | } | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | static int ath9k_init_queues(struct ath_softc *sc) | ||
417 | { | ||
418 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
419 | int i = 0; | ||
420 | |||
421 | for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++) | ||
422 | sc->tx.hwq_map[i] = -1; | ||
423 | |||
424 | sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); | ||
421 | if (sc->beacon.beaconq == -1) { | 425 | if (sc->beacon.beaconq == -1) { |
422 | ath_print(common, ATH_DBG_FATAL, | 426 | ath_print(common, ATH_DBG_FATAL, |
423 | "Unable to setup a beacon xmit queue\n"); | 427 | "Unable to setup a beacon xmit queue\n"); |
424 | r = -EIO; | 428 | goto err; |
425 | goto bad2; | ||
426 | } | 429 | } |
430 | |||
427 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); | 431 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); |
428 | if (sc->beacon.cabq == NULL) { | 432 | if (sc->beacon.cabq == NULL) { |
429 | ath_print(common, ATH_DBG_FATAL, | 433 | ath_print(common, ATH_DBG_FATAL, |
430 | "Unable to setup CAB xmit queue\n"); | 434 | "Unable to setup CAB xmit queue\n"); |
431 | r = -EIO; | 435 | goto err; |
432 | goto bad2; | ||
433 | } | 436 | } |
434 | 437 | ||
435 | sc->config.cabqReadytime = ATH_CABQ_READY_TIME; | 438 | sc->config.cabqReadytime = ATH_CABQ_READY_TIME; |
436 | ath_cabq_update(sc); | 439 | ath_cabq_update(sc); |
437 | 440 | ||
438 | for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++) | ||
439 | sc->tx.hwq_map[i] = -1; | ||
440 | |||
441 | /* Setup data queues */ | ||
442 | /* NB: ensure BK queue is the lowest priority h/w queue */ | ||
443 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { | 441 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { |
444 | ath_print(common, ATH_DBG_FATAL, | 442 | ath_print(common, ATH_DBG_FATAL, |
445 | "Unable to setup xmit queue for BK traffic\n"); | 443 | "Unable to setup xmit queue for BK traffic\n"); |
446 | r = -EIO; | 444 | goto err; |
447 | goto bad2; | ||
448 | } | 445 | } |
449 | 446 | ||
450 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { | 447 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { |
451 | ath_print(common, ATH_DBG_FATAL, | 448 | ath_print(common, ATH_DBG_FATAL, |
452 | "Unable to setup xmit queue for BE traffic\n"); | 449 | "Unable to setup xmit queue for BE traffic\n"); |
453 | r = -EIO; | 450 | goto err; |
454 | goto bad2; | ||
455 | } | 451 | } |
456 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { | 452 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { |
457 | ath_print(common, ATH_DBG_FATAL, | 453 | ath_print(common, ATH_DBG_FATAL, |
458 | "Unable to setup xmit queue for VI traffic\n"); | 454 | "Unable to setup xmit queue for VI traffic\n"); |
459 | r = -EIO; | 455 | goto err; |
460 | goto bad2; | ||
461 | } | 456 | } |
462 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { | 457 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { |
463 | ath_print(common, ATH_DBG_FATAL, | 458 | ath_print(common, ATH_DBG_FATAL, |
464 | "Unable to setup xmit queue for VO traffic\n"); | 459 | "Unable to setup xmit queue for VO traffic\n"); |
465 | r = -EIO; | 460 | goto err; |
466 | goto bad2; | ||
467 | } | 461 | } |
468 | 462 | ||
469 | /* Initializes the noise floor to a reasonable default value. | 463 | return 0; |
470 | * Later on this will be updated during ANI processing. */ | ||
471 | 464 | ||
472 | common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR; | 465 | err: |
473 | setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); | 466 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) |
467 | if (ATH_TXQ_SETUP(sc, i)) | ||
468 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | ||
474 | 469 | ||
475 | if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, | 470 | return -EIO; |
476 | ATH9K_CIPHER_TKIP, NULL)) { | 471 | } |
477 | /* | 472 | |
478 | * Whether we should enable h/w TKIP MIC. | 473 | static void ath9k_init_channels_rates(struct ath_softc *sc) |
479 | * XXX: if we don't support WME TKIP MIC, then we wouldn't | 474 | { |
480 | * report WMM capable, so it's always safe to turn on | 475 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) { |
481 | * TKIP MIC in this case. | 476 | sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; |
482 | */ | 477 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; |
483 | ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, | 478 | sc->sbands[IEEE80211_BAND_2GHZ].n_channels = |
484 | 0, 1, NULL); | 479 | ARRAY_SIZE(ath9k_2ghz_chantable); |
480 | sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; | ||
481 | sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates = | ||
482 | ARRAY_SIZE(ath9k_legacy_rates); | ||
485 | } | 483 | } |
486 | 484 | ||
487 | /* | 485 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { |
488 | * Check whether the separate key cache entries | 486 | sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; |
489 | * are required to handle both tx+rx MIC keys. | 487 | sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; |
490 | * With split mic keys the number of stations is limited | 488 | sc->sbands[IEEE80211_BAND_5GHZ].n_channels = |
491 | * to 27 otherwise 59. | 489 | ARRAY_SIZE(ath9k_5ghz_chantable); |
492 | */ | 490 | sc->sbands[IEEE80211_BAND_5GHZ].bitrates = |
493 | if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, | 491 | ath9k_legacy_rates + 4; |
494 | ATH9K_CIPHER_TKIP, NULL) | 492 | sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates = |
495 | && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, | 493 | ARRAY_SIZE(ath9k_legacy_rates) - 4; |
496 | ATH9K_CIPHER_MIC, NULL) | 494 | } |
497 | && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT, | 495 | } |
498 | 0, NULL)) | ||
499 | common->splitmic = 1; | ||
500 | 496 | ||
501 | /* turn on mcast key search if possible */ | 497 | static void ath9k_init_misc(struct ath_softc *sc) |
502 | if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) | 498 | { |
503 | (void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1, | 499 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
504 | 1, NULL); | 500 | int i = 0; |
501 | |||
502 | common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR; | ||
503 | setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); | ||
505 | 504 | ||
506 | sc->config.txpowlimit = ATH_TXPOWER_MAX; | 505 | sc->config.txpowlimit = ATH_TXPOWER_MAX; |
507 | 506 | ||
508 | /* 11n Capabilities */ | 507 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { |
509 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { | ||
510 | sc->sc_flags |= SC_OP_TXAGGR; | 508 | sc->sc_flags |= SC_OP_TXAGGR; |
511 | sc->sc_flags |= SC_OP_RXAGGR; | 509 | sc->sc_flags |= SC_OP_RXAGGR; |
512 | } | 510 | } |
513 | 511 | ||
514 | common->tx_chainmask = ah->caps.tx_chainmask; | 512 | common->tx_chainmask = sc->sc_ah->caps.tx_chainmask; |
515 | common->rx_chainmask = ah->caps.rx_chainmask; | 513 | common->rx_chainmask = sc->sc_ah->caps.rx_chainmask; |
516 | 514 | ||
517 | ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); | 515 | ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); |
518 | sc->rx.defant = ath9k_hw_getdefantenna(ah); | 516 | sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); |
519 | 517 | ||
520 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 518 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) |
521 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); | 519 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); |
522 | 520 | ||
523 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ | 521 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; |
524 | 522 | ||
525 | /* initialize beacon slots */ | ||
526 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { | 523 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { |
527 | sc->beacon.bslot[i] = NULL; | 524 | sc->beacon.bslot[i] = NULL; |
528 | sc->beacon.bslot_aphy[i] = NULL; | 525 | sc->beacon.bslot_aphy[i] = NULL; |
529 | } | 526 | } |
527 | } | ||
530 | 528 | ||
531 | /* setup channels and rates */ | 529 | static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, |
530 | const struct ath_bus_ops *bus_ops) | ||
531 | { | ||
532 | struct ath_hw *ah = NULL; | ||
533 | struct ath_common *common; | ||
534 | int ret = 0, i; | ||
535 | int csz = 0; | ||
532 | 536 | ||
533 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) { | 537 | sc->sc_flags |= SC_OP_INVALID; |
534 | sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; | ||
535 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; | ||
536 | sc->sbands[IEEE80211_BAND_2GHZ].n_channels = | ||
537 | ARRAY_SIZE(ath9k_2ghz_chantable); | ||
538 | sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; | ||
539 | sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates = | ||
540 | ARRAY_SIZE(ath9k_legacy_rates); | ||
541 | } | ||
542 | 538 | ||
543 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { | 539 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); |
544 | sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; | 540 | if (!ah) |
545 | sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; | 541 | return -ENOMEM; |
546 | sc->sbands[IEEE80211_BAND_5GHZ].n_channels = | 542 | |
547 | ARRAY_SIZE(ath9k_5ghz_chantable); | 543 | ah->hw_version.devid = devid; |
548 | sc->sbands[IEEE80211_BAND_5GHZ].bitrates = | 544 | ah->hw_version.subsysid = subsysid; |
549 | ath9k_legacy_rates + 4; | 545 | sc->sc_ah = ah; |
550 | sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates = | 546 | |
551 | ARRAY_SIZE(ath9k_legacy_rates) - 4; | 547 | common = ath9k_hw_common(ah); |
548 | common->ops = &ath9k_common_ops; | ||
549 | common->bus_ops = bus_ops; | ||
550 | common->ah = ah; | ||
551 | common->hw = sc->hw; | ||
552 | common->priv = sc; | ||
553 | common->debug_mask = ath9k_debug; | ||
554 | |||
555 | spin_lock_init(&sc->wiphy_lock); | ||
556 | spin_lock_init(&sc->sc_resetlock); | ||
557 | spin_lock_init(&sc->sc_serial_rw); | ||
558 | spin_lock_init(&sc->sc_pm_lock); | ||
559 | mutex_init(&sc->mutex); | ||
560 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); | ||
561 | tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, | ||
562 | (unsigned long)sc); | ||
563 | |||
564 | /* | ||
565 | * Cache line size is used to size and align various | ||
566 | * structures used to communicate with the hardware. | ||
567 | */ | ||
568 | ath_read_cachesize(common, &csz); | ||
569 | common->cachelsz = csz << 2; /* convert to bytes */ | ||
570 | |||
571 | ret = ath9k_hw_init(ah); | ||
572 | if (ret) { | ||
573 | ath_print(common, ATH_DBG_FATAL, | ||
574 | "Unable to initialize hardware; " | ||
575 | "initialization status: %d\n", ret); | ||
576 | goto err_hw; | ||
552 | } | 577 | } |
553 | 578 | ||
554 | switch (ah->btcoex_hw.scheme) { | 579 | ret = ath9k_init_debug(ah); |
555 | case ATH_BTCOEX_CFG_NONE: | 580 | if (ret) { |
556 | break; | 581 | ath_print(common, ATH_DBG_FATAL, |
557 | case ATH_BTCOEX_CFG_2WIRE: | 582 | "Unable to create debugfs files\n"); |
558 | ath9k_hw_btcoex_init_2wire(ah); | 583 | goto err_debug; |
559 | break; | ||
560 | case ATH_BTCOEX_CFG_3WIRE: | ||
561 | ath9k_hw_btcoex_init_3wire(ah); | ||
562 | r = ath_init_btcoex_timer(sc); | ||
563 | if (r) | ||
564 | goto bad2; | ||
565 | qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); | ||
566 | ath9k_hw_init_btcoex_hw(ah, qnum); | ||
567 | sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | ||
568 | break; | ||
569 | default: | ||
570 | WARN_ON(1); | ||
571 | break; | ||
572 | } | 584 | } |
573 | 585 | ||
586 | ret = ath9k_init_queues(sc); | ||
587 | if (ret) | ||
588 | goto err_queues; | ||
589 | |||
590 | ret = ath9k_init_btcoex(sc); | ||
591 | if (ret) | ||
592 | goto err_btcoex; | ||
593 | |||
594 | ath9k_init_crypto(sc); | ||
595 | ath9k_init_channels_rates(sc); | ||
596 | ath9k_init_misc(sc); | ||
597 | |||
574 | return 0; | 598 | return 0; |
575 | bad2: | 599 | |
576 | /* cleanup tx queues */ | 600 | err_btcoex: |
577 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | 601 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) |
578 | if (ATH_TXQ_SETUP(sc, i)) | 602 | if (ATH_TXQ_SETUP(sc, i)) |
579 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 603 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
604 | err_queues: | ||
605 | ath9k_exit_debug(ah); | ||
606 | err_debug: | ||
607 | ath9k_hw_deinit(ah); | ||
608 | err_hw: | ||
609 | tasklet_kill(&sc->intr_tq); | ||
610 | tasklet_kill(&sc->bcon_tasklet); | ||
580 | 611 | ||
581 | bad_free_hw: | 612 | kfree(ah); |
582 | ath9k_uninit_hw(sc); | 613 | sc->sc_ah = NULL; |
583 | return r; | 614 | |
615 | return ret; | ||
584 | } | 616 | } |
585 | 617 | ||
586 | void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | 618 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) |
587 | { | 619 | { |
620 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
621 | |||
588 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | 622 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
589 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | 623 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | |
590 | IEEE80211_HW_SIGNAL_DBM | | 624 | IEEE80211_HW_SIGNAL_DBM | |
@@ -621,85 +655,85 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
621 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) | 655 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) |
622 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 656 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
623 | &sc->sbands[IEEE80211_BAND_5GHZ]; | 657 | &sc->sbands[IEEE80211_BAND_5GHZ]; |
658 | |||
659 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { | ||
660 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) | ||
661 | setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); | ||
662 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) | ||
663 | setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); | ||
664 | } | ||
665 | |||
666 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); | ||
624 | } | 667 | } |
625 | 668 | ||
626 | /* Device driver core initialization */ | 669 | int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, |
627 | int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | ||
628 | const struct ath_bus_ops *bus_ops) | 670 | const struct ath_bus_ops *bus_ops) |
629 | { | 671 | { |
630 | struct ieee80211_hw *hw = sc->hw; | 672 | struct ieee80211_hw *hw = sc->hw; |
631 | struct ath_common *common; | 673 | struct ath_common *common; |
632 | struct ath_hw *ah; | 674 | struct ath_hw *ah; |
633 | int error = 0, i; | 675 | int error = 0; |
634 | struct ath_regulatory *reg; | 676 | struct ath_regulatory *reg; |
635 | 677 | ||
636 | dev_dbg(sc->dev, "Attach ATH hw\n"); | 678 | /* Bring up device */ |
637 | 679 | error = ath9k_init_softc(devid, sc, subsysid, bus_ops); | |
638 | error = ath_init_softc(devid, sc, subsysid, bus_ops); | ||
639 | if (error != 0) | 680 | if (error != 0) |
640 | return error; | 681 | goto error_init; |
641 | 682 | ||
642 | ah = sc->sc_ah; | 683 | ah = sc->sc_ah; |
643 | common = ath9k_hw_common(ah); | 684 | common = ath9k_hw_common(ah); |
685 | ath9k_set_hw_capab(sc, hw); | ||
644 | 686 | ||
645 | /* get mac address from hardware and set in mac80211 */ | 687 | /* Initialize regulatory */ |
646 | |||
647 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); | ||
648 | |||
649 | ath_set_hw_capab(sc, hw); | ||
650 | |||
651 | error = ath_regd_init(&common->regulatory, sc->hw->wiphy, | 688 | error = ath_regd_init(&common->regulatory, sc->hw->wiphy, |
652 | ath9k_reg_notifier); | 689 | ath9k_reg_notifier); |
653 | if (error) | 690 | if (error) |
654 | return error; | 691 | goto error_regd; |
655 | 692 | ||
656 | reg = &common->regulatory; | 693 | reg = &common->regulatory; |
657 | 694 | ||
658 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { | 695 | /* Setup TX DMA */ |
659 | if (test_bit(ATH9K_MODE_11G, ah->caps.wireless_modes)) | ||
660 | setup_ht_cap(sc, | ||
661 | &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); | ||
662 | if (test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) | ||
663 | setup_ht_cap(sc, | ||
664 | &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); | ||
665 | } | ||
666 | |||
667 | /* initialize tx/rx engine */ | ||
668 | error = ath_tx_init(sc, ATH_TXBUF); | 696 | error = ath_tx_init(sc, ATH_TXBUF); |
669 | if (error != 0) | 697 | if (error != 0) |
670 | goto error_attach; | 698 | goto error_tx; |
671 | 699 | ||
700 | /* Setup RX DMA */ | ||
672 | error = ath_rx_init(sc, ATH_RXBUF); | 701 | error = ath_rx_init(sc, ATH_RXBUF); |
673 | if (error != 0) | 702 | if (error != 0) |
674 | goto error_attach; | 703 | goto error_rx; |
675 | |||
676 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); | ||
677 | INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); | ||
678 | sc->wiphy_scheduler_int = msecs_to_jiffies(500); | ||
679 | 704 | ||
705 | /* Register with mac80211 */ | ||
680 | error = ieee80211_register_hw(hw); | 706 | error = ieee80211_register_hw(hw); |
707 | if (error) | ||
708 | goto error_register; | ||
681 | 709 | ||
710 | /* Handle world regulatory */ | ||
682 | if (!ath_is_world_regd(reg)) { | 711 | if (!ath_is_world_regd(reg)) { |
683 | error = regulatory_hint(hw->wiphy, reg->alpha2); | 712 | error = regulatory_hint(hw->wiphy, reg->alpha2); |
684 | if (error) | 713 | if (error) |
685 | goto error_attach; | 714 | goto error_world; |
686 | } | 715 | } |
687 | 716 | ||
688 | /* Initialize LED control */ | 717 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); |
689 | ath_init_leds(sc); | 718 | INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); |
719 | sc->wiphy_scheduler_int = msecs_to_jiffies(500); | ||
690 | 720 | ||
721 | ath_init_leds(sc); | ||
691 | ath_start_rfkill_poll(sc); | 722 | ath_start_rfkill_poll(sc); |
692 | 723 | ||
693 | return 0; | 724 | return 0; |
694 | 725 | ||
695 | error_attach: | 726 | error_world: |
696 | /* cleanup tx queues */ | 727 | ieee80211_unregister_hw(hw); |
697 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | 728 | error_register: |
698 | if (ATH_TXQ_SETUP(sc, i)) | 729 | ath_rx_cleanup(sc); |
699 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 730 | error_rx: |
700 | 731 | ath_tx_cleanup(sc); | |
701 | ath9k_uninit_hw(sc); | 732 | error_tx: |
702 | 733 | /* Nothing */ | |
734 | error_regd: | ||
735 | ath9k_deinit_softc(sc); | ||
736 | error_init: | ||
703 | return error; | 737 | return error; |
704 | } | 738 | } |
705 | 739 | ||
@@ -707,29 +741,34 @@ error_attach: | |||
707 | /* De-Initialization */ | 741 | /* De-Initialization */ |
708 | /*****************************/ | 742 | /*****************************/ |
709 | 743 | ||
710 | static void ath9k_uninit_hw(struct ath_softc *sc) | 744 | static void ath9k_deinit_softc(struct ath_softc *sc) |
711 | { | 745 | { |
712 | struct ath_hw *ah = sc->sc_ah; | 746 | int i = 0; |
713 | 747 | ||
714 | BUG_ON(!ah); | 748 | if ((sc->btcoex.no_stomp_timer) && |
749 | sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | ||
750 | ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); | ||
715 | 751 | ||
716 | ath9k_exit_debug(ah); | 752 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) |
717 | ath9k_hw_detach(ah); | 753 | if (ATH_TXQ_SETUP(sc, i)) |
718 | sc->sc_ah = NULL; | 754 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
755 | |||
756 | ath9k_exit_debug(sc->sc_ah); | ||
757 | ath9k_hw_deinit(sc->sc_ah); | ||
758 | |||
759 | tasklet_kill(&sc->intr_tq); | ||
760 | tasklet_kill(&sc->bcon_tasklet); | ||
719 | } | 761 | } |
720 | 762 | ||
721 | static void ath_clean_core(struct ath_softc *sc) | 763 | void ath9k_deinit_device(struct ath_softc *sc) |
722 | { | 764 | { |
723 | struct ieee80211_hw *hw = sc->hw; | 765 | struct ieee80211_hw *hw = sc->hw; |
724 | struct ath_hw *ah = sc->sc_ah; | ||
725 | int i = 0; | 766 | int i = 0; |
726 | 767 | ||
727 | ath9k_ps_wakeup(sc); | 768 | ath9k_ps_wakeup(sc); |
728 | 769 | ||
729 | dev_dbg(sc->dev, "Detach ATH hw\n"); | ||
730 | |||
731 | ath_deinit_leds(sc); | ||
732 | wiphy_rfkill_stop_polling(sc->hw->wiphy); | 770 | wiphy_rfkill_stop_polling(sc->hw->wiphy); |
771 | ath_deinit_leds(sc); | ||
733 | 772 | ||
734 | for (i = 0; i < sc->num_sec_wiphy; i++) { | 773 | for (i = 0; i < sc->num_sec_wiphy; i++) { |
735 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | 774 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; |
@@ -739,24 +778,12 @@ static void ath_clean_core(struct ath_softc *sc) | |||
739 | ieee80211_unregister_hw(aphy->hw); | 778 | ieee80211_unregister_hw(aphy->hw); |
740 | ieee80211_free_hw(aphy->hw); | 779 | ieee80211_free_hw(aphy->hw); |
741 | } | 780 | } |
781 | kfree(sc->sec_wiphy); | ||
782 | |||
742 | ieee80211_unregister_hw(hw); | 783 | ieee80211_unregister_hw(hw); |
743 | ath_rx_cleanup(sc); | 784 | ath_rx_cleanup(sc); |
744 | ath_tx_cleanup(sc); | 785 | ath_tx_cleanup(sc); |
745 | 786 | ath9k_deinit_softc(sc); | |
746 | tasklet_kill(&sc->intr_tq); | ||
747 | tasklet_kill(&sc->bcon_tasklet); | ||
748 | |||
749 | if (!(sc->sc_flags & SC_OP_INVALID)) | ||
750 | ath9k_setpower(sc, ATH9K_PM_AWAKE); | ||
751 | |||
752 | /* cleanup tx queues */ | ||
753 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
754 | if (ATH_TXQ_SETUP(sc, i)) | ||
755 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | ||
756 | |||
757 | if ((sc->btcoex.no_stomp_timer) && | ||
758 | ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | ||
759 | ath_gen_timer_free(ah, sc->btcoex.no_stomp_timer); | ||
760 | } | 787 | } |
761 | 788 | ||
762 | void ath_descdma_cleanup(struct ath_softc *sc, | 789 | void ath_descdma_cleanup(struct ath_softc *sc, |
@@ -771,26 +798,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, | |||
771 | memset(dd, 0, sizeof(*dd)); | 798 | memset(dd, 0, sizeof(*dd)); |
772 | } | 799 | } |
773 | 800 | ||
774 | void ath_detach(struct ath_softc *sc) | ||
775 | { | ||
776 | ath_clean_core(sc); | ||
777 | ath9k_uninit_hw(sc); | ||
778 | } | ||
779 | |||
780 | void ath_cleanup(struct ath_softc *sc) | ||
781 | { | ||
782 | struct ath_hw *ah = sc->sc_ah; | ||
783 | struct ath_common *common = ath9k_hw_common(ah); | ||
784 | |||
785 | ath_clean_core(sc); | ||
786 | free_irq(sc->irq, sc); | ||
787 | ath_bus_cleanup(common); | ||
788 | kfree(sc->sec_wiphy); | ||
789 | ieee80211_free_hw(sc->hw); | ||
790 | |||
791 | ath9k_uninit_hw(sc); | ||
792 | } | ||
793 | |||
794 | /************************/ | 801 | /************************/ |
795 | /* Module Hooks */ | 802 | /* Module Hooks */ |
796 | /************************/ | 803 | /************************/ |