diff options
author | Michal Kazior <michal.kazior@tieto.com> | 2013-07-16 03:38:57 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2013-07-30 11:01:19 -0400 |
commit | 818bdd16b229919cfd07447d261154a1343871e1 (patch) | |
tree | ceb7c266179a2add8a729ea6b56265c4d7e8891f /drivers/net | |
parent | a96d7745592274077e517173ec2cdac2a22d5b79 (diff) |
ath10k: defer hw setup to start/stop mac80211 hooks
This fixes suspend-to-disk. The hardware is now
re-initialized upon freeze/thaw properly.
This also makes suspend/resume re-initialize the
hardware as WoWLAN support is not done yet.
With some little work it should be possible to
support hw reconfiguration for hw/fw recovery.
HW must be initialized once before registering to
mac80211 because FW determinates what hw
capabilities can be advertised.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/core.c | 46 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/mac.c | 56 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/pci.c | 11 |
3 files changed, 81 insertions, 32 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 0e4a704516f7..1d4c24583f1d 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c | |||
@@ -601,6 +601,7 @@ err_wmi_detach: | |||
601 | err: | 601 | err: |
602 | return status; | 602 | return status; |
603 | } | 603 | } |
604 | EXPORT_SYMBOL(ath10k_core_start); | ||
604 | 605 | ||
605 | void ath10k_core_stop(struct ath10k *ar) | 606 | void ath10k_core_stop(struct ath10k *ar) |
606 | { | 607 | { |
@@ -608,18 +609,49 @@ void ath10k_core_stop(struct ath10k *ar) | |||
608 | ath10k_htt_detach(&ar->htt); | 609 | ath10k_htt_detach(&ar->htt); |
609 | ath10k_wmi_detach(ar); | 610 | ath10k_wmi_detach(ar); |
610 | } | 611 | } |
612 | EXPORT_SYMBOL(ath10k_core_stop); | ||
613 | |||
614 | /* mac80211 manages fw/hw initialization through start/stop hooks. However in | ||
615 | * order to know what hw capabilities should be advertised to mac80211 it is | ||
616 | * necessary to load the firmware (and tear it down immediately since start | ||
617 | * hook will try to init it again) before registering */ | ||
618 | static int ath10k_core_probe_fw(struct ath10k *ar) | ||
619 | { | ||
620 | int ret; | ||
621 | |||
622 | ret = ath10k_hif_power_up(ar); | ||
623 | if (ret) { | ||
624 | ath10k_err("could not start pci hif (%d)\n", ret); | ||
625 | return ret; | ||
626 | } | ||
627 | |||
628 | ret = ath10k_core_start(ar); | ||
629 | if (ret) { | ||
630 | ath10k_err("could not init core (%d)\n", ret); | ||
631 | ath10k_hif_power_down(ar); | ||
632 | return ret; | ||
633 | } | ||
634 | |||
635 | ath10k_core_stop(ar); | ||
636 | ath10k_hif_power_down(ar); | ||
637 | return 0; | ||
638 | } | ||
611 | 639 | ||
612 | int ath10k_core_register(struct ath10k *ar) | 640 | int ath10k_core_register(struct ath10k *ar) |
613 | { | 641 | { |
614 | int status; | 642 | int status; |
615 | 643 | ||
616 | status = ath10k_core_start(ar); | 644 | status = ath10k_core_probe_fw(ar); |
617 | if (status) | 645 | if (status) { |
618 | goto err; | 646 | ath10k_err("could not probe fw (%d)\n", status); |
647 | return status; | ||
648 | } | ||
619 | 649 | ||
620 | status = ath10k_mac_register(ar); | 650 | status = ath10k_mac_register(ar); |
621 | if (status) | 651 | if (status) { |
622 | goto err_core_stop; | 652 | ath10k_err("could not register to mac80211 (%d)\n", status); |
653 | return status; | ||
654 | } | ||
623 | 655 | ||
624 | status = ath10k_debug_create(ar); | 656 | status = ath10k_debug_create(ar); |
625 | if (status) { | 657 | if (status) { |
@@ -631,9 +663,6 @@ int ath10k_core_register(struct ath10k *ar) | |||
631 | 663 | ||
632 | err_unregister_mac: | 664 | err_unregister_mac: |
633 | ath10k_mac_unregister(ar); | 665 | ath10k_mac_unregister(ar); |
634 | err_core_stop: | ||
635 | ath10k_core_stop(ar); | ||
636 | err: | ||
637 | return status; | 666 | return status; |
638 | } | 667 | } |
639 | EXPORT_SYMBOL(ath10k_core_register); | 668 | EXPORT_SYMBOL(ath10k_core_register); |
@@ -644,7 +673,6 @@ void ath10k_core_unregister(struct ath10k *ar) | |||
644 | * Otherwise we will fail to submit commands to FW and mac80211 will be | 673 | * Otherwise we will fail to submit commands to FW and mac80211 will be |
645 | * unhappy about callback failures. */ | 674 | * unhappy about callback failures. */ |
646 | ath10k_mac_unregister(ar); | 675 | ath10k_mac_unregister(ar); |
647 | ath10k_core_stop(ar); | ||
648 | } | 676 | } |
649 | EXPORT_SYMBOL(ath10k_core_unregister); | 677 | EXPORT_SYMBOL(ath10k_core_unregister); |
650 | 678 | ||
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index b9663e94dba5..2dfd446251b1 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -1738,13 +1738,52 @@ static void ath10k_tx(struct ieee80211_hw *hw, | |||
1738 | /* | 1738 | /* |
1739 | * Initialize various parameters with default vaules. | 1739 | * Initialize various parameters with default vaules. |
1740 | */ | 1740 | */ |
1741 | static void ath10k_halt(struct ath10k *ar) | ||
1742 | { | ||
1743 | lockdep_assert_held(&ar->conf_mutex); | ||
1744 | |||
1745 | del_timer_sync(&ar->scan.timeout); | ||
1746 | ath10k_offchan_tx_purge(ar); | ||
1747 | ath10k_peer_cleanup_all(ar); | ||
1748 | ath10k_core_stop(ar); | ||
1749 | ath10k_hif_power_down(ar); | ||
1750 | |||
1751 | spin_lock_bh(&ar->data_lock); | ||
1752 | if (ar->scan.in_progress) { | ||
1753 | del_timer(&ar->scan.timeout); | ||
1754 | ar->scan.in_progress = false; | ||
1755 | ieee80211_scan_completed(ar->hw, true); | ||
1756 | } | ||
1757 | spin_unlock_bh(&ar->data_lock); | ||
1758 | } | ||
1759 | |||
1741 | static int ath10k_start(struct ieee80211_hw *hw) | 1760 | static int ath10k_start(struct ieee80211_hw *hw) |
1742 | { | 1761 | { |
1743 | struct ath10k *ar = hw->priv; | 1762 | struct ath10k *ar = hw->priv; |
1744 | int ret; | 1763 | int ret = 0; |
1745 | 1764 | ||
1746 | mutex_lock(&ar->conf_mutex); | 1765 | mutex_lock(&ar->conf_mutex); |
1747 | 1766 | ||
1767 | if (ar->state != ATH10K_STATE_OFF) { | ||
1768 | ret = -EINVAL; | ||
1769 | goto exit; | ||
1770 | } | ||
1771 | |||
1772 | ret = ath10k_hif_power_up(ar); | ||
1773 | if (ret) { | ||
1774 | ath10k_err("could not init hif (%d)\n", ret); | ||
1775 | ar->state = ATH10K_STATE_OFF; | ||
1776 | goto exit; | ||
1777 | } | ||
1778 | |||
1779 | ret = ath10k_core_start(ar); | ||
1780 | if (ret) { | ||
1781 | ath10k_err("could not init core (%d)\n", ret); | ||
1782 | ath10k_hif_power_down(ar); | ||
1783 | ar->state = ATH10K_STATE_OFF; | ||
1784 | goto exit; | ||
1785 | } | ||
1786 | |||
1748 | ret = ath10k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS, 1); | 1787 | ret = ath10k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS, 1); |
1749 | if (ret) | 1788 | if (ret) |
1750 | ath10k_warn("could not enable WMI_PDEV_PARAM_PMF_QOS (%d)\n", | 1789 | ath10k_warn("could not enable WMI_PDEV_PARAM_PMF_QOS (%d)\n", |
@@ -1755,9 +1794,9 @@ static int ath10k_start(struct ieee80211_hw *hw) | |||
1755 | ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n", | 1794 | ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n", |
1756 | ret); | 1795 | ret); |
1757 | 1796 | ||
1758 | ar->state = ATH10K_STATE_ON; | ||
1759 | ath10k_regd_update(ar); | 1797 | ath10k_regd_update(ar); |
1760 | 1798 | ||
1799 | exit: | ||
1761 | mutex_unlock(&ar->conf_mutex); | 1800 | mutex_unlock(&ar->conf_mutex); |
1762 | return 0; | 1801 | return 0; |
1763 | } | 1802 | } |
@@ -1767,17 +1806,8 @@ static void ath10k_stop(struct ieee80211_hw *hw) | |||
1767 | struct ath10k *ar = hw->priv; | 1806 | struct ath10k *ar = hw->priv; |
1768 | 1807 | ||
1769 | mutex_lock(&ar->conf_mutex); | 1808 | mutex_lock(&ar->conf_mutex); |
1770 | del_timer_sync(&ar->scan.timeout); | 1809 | if (ar->state == ATH10K_STATE_ON) |
1771 | ath10k_offchan_tx_purge(ar); | 1810 | ath10k_halt(ar); |
1772 | ath10k_peer_cleanup_all(ar); | ||
1773 | |||
1774 | spin_lock_bh(&ar->data_lock); | ||
1775 | if (ar->scan.in_progress) { | ||
1776 | del_timer(&ar->scan.timeout); | ||
1777 | ar->scan.in_progress = false; | ||
1778 | ieee80211_scan_completed(ar->hw, true); | ||
1779 | } | ||
1780 | spin_unlock_bh(&ar->data_lock); | ||
1781 | 1811 | ||
1782 | ar->state = ATH10K_STATE_OFF; | 1812 | ar->state = ATH10K_STATE_OFF; |
1783 | mutex_unlock(&ar->conf_mutex); | 1813 | mutex_unlock(&ar->conf_mutex); |
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 75f5427bb416..bfe856166bb0 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c | |||
@@ -2362,22 +2362,14 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
2362 | goto err_iomap; | 2362 | goto err_iomap; |
2363 | } | 2363 | } |
2364 | 2364 | ||
2365 | ret = ath10k_pci_hif_power_up(ar); | ||
2366 | if (ret) { | ||
2367 | ath10k_err("could not start pci hif (%d)\n", ret); | ||
2368 | goto err_intr; | ||
2369 | } | ||
2370 | |||
2371 | ret = ath10k_core_register(ar); | 2365 | ret = ath10k_core_register(ar); |
2372 | if (ret) { | 2366 | if (ret) { |
2373 | ath10k_err("could not register driver core (%d)\n", ret); | 2367 | ath10k_err("could not register driver core (%d)\n", ret); |
2374 | goto err_hif; | 2368 | goto err_intr; |
2375 | } | 2369 | } |
2376 | 2370 | ||
2377 | return 0; | 2371 | return 0; |
2378 | 2372 | ||
2379 | err_hif: | ||
2380 | ath10k_pci_hif_power_down(ar); | ||
2381 | err_intr: | 2373 | err_intr: |
2382 | ath10k_pci_stop_intr(ar); | 2374 | ath10k_pci_stop_intr(ar); |
2383 | err_iomap: | 2375 | err_iomap: |
@@ -2416,7 +2408,6 @@ static void ath10k_pci_remove(struct pci_dev *pdev) | |||
2416 | tasklet_kill(&ar_pci->msi_fw_err); | 2408 | tasklet_kill(&ar_pci->msi_fw_err); |
2417 | 2409 | ||
2418 | ath10k_core_unregister(ar); | 2410 | ath10k_core_unregister(ar); |
2419 | ath10k_pci_hif_power_down(ar); | ||
2420 | ath10k_pci_stop_intr(ar); | 2411 | ath10k_pci_stop_intr(ar); |
2421 | 2412 | ||
2422 | pci_set_drvdata(pdev, NULL); | 2413 | pci_set_drvdata(pdev, NULL); |