提交 818bdd16 编写于 作者: M Michal Kazior 提交者: Kalle Valo

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: NMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: NKalle Valo <kvalo@qca.qualcomm.com>
上级 a96d7745
...@@ -601,6 +601,7 @@ int ath10k_core_start(struct ath10k *ar) ...@@ -601,6 +601,7 @@ int ath10k_core_start(struct ath10k *ar)
err: err:
return status; return status;
} }
EXPORT_SYMBOL(ath10k_core_start);
void ath10k_core_stop(struct ath10k *ar) void ath10k_core_stop(struct ath10k *ar)
{ {
...@@ -608,18 +609,49 @@ void ath10k_core_stop(struct ath10k *ar) ...@@ -608,18 +609,49 @@ void ath10k_core_stop(struct ath10k *ar)
ath10k_htt_detach(&ar->htt); ath10k_htt_detach(&ar->htt);
ath10k_wmi_detach(ar); ath10k_wmi_detach(ar);
} }
EXPORT_SYMBOL(ath10k_core_stop);
/* mac80211 manages fw/hw initialization through start/stop hooks. However in
* order to know what hw capabilities should be advertised to mac80211 it is
* necessary to load the firmware (and tear it down immediately since start
* hook will try to init it again) before registering */
static int ath10k_core_probe_fw(struct ath10k *ar)
{
int ret;
ret = ath10k_hif_power_up(ar);
if (ret) {
ath10k_err("could not start pci hif (%d)\n", ret);
return ret;
}
ret = ath10k_core_start(ar);
if (ret) {
ath10k_err("could not init core (%d)\n", ret);
ath10k_hif_power_down(ar);
return ret;
}
ath10k_core_stop(ar);
ath10k_hif_power_down(ar);
return 0;
}
int ath10k_core_register(struct ath10k *ar) int ath10k_core_register(struct ath10k *ar)
{ {
int status; int status;
status = ath10k_core_start(ar); status = ath10k_core_probe_fw(ar);
if (status) if (status) {
goto err; ath10k_err("could not probe fw (%d)\n", status);
return status;
}
status = ath10k_mac_register(ar); status = ath10k_mac_register(ar);
if (status) if (status) {
goto err_core_stop; ath10k_err("could not register to mac80211 (%d)\n", status);
return status;
}
status = ath10k_debug_create(ar); status = ath10k_debug_create(ar);
if (status) { if (status) {
...@@ -631,9 +663,6 @@ int ath10k_core_register(struct ath10k *ar) ...@@ -631,9 +663,6 @@ int ath10k_core_register(struct ath10k *ar)
err_unregister_mac: err_unregister_mac:
ath10k_mac_unregister(ar); ath10k_mac_unregister(ar);
err_core_stop:
ath10k_core_stop(ar);
err:
return status; return status;
} }
EXPORT_SYMBOL(ath10k_core_register); EXPORT_SYMBOL(ath10k_core_register);
...@@ -644,7 +673,6 @@ void ath10k_core_unregister(struct ath10k *ar) ...@@ -644,7 +673,6 @@ void ath10k_core_unregister(struct ath10k *ar)
* Otherwise we will fail to submit commands to FW and mac80211 will be * Otherwise we will fail to submit commands to FW and mac80211 will be
* unhappy about callback failures. */ * unhappy about callback failures. */
ath10k_mac_unregister(ar); ath10k_mac_unregister(ar);
ath10k_core_stop(ar);
} }
EXPORT_SYMBOL(ath10k_core_unregister); EXPORT_SYMBOL(ath10k_core_unregister);
......
...@@ -1738,13 +1738,52 @@ static void ath10k_tx(struct ieee80211_hw *hw, ...@@ -1738,13 +1738,52 @@ static void ath10k_tx(struct ieee80211_hw *hw,
/* /*
* Initialize various parameters with default vaules. * Initialize various parameters with default vaules.
*/ */
static void ath10k_halt(struct ath10k *ar)
{
lockdep_assert_held(&ar->conf_mutex);
del_timer_sync(&ar->scan.timeout);
ath10k_offchan_tx_purge(ar);
ath10k_peer_cleanup_all(ar);
ath10k_core_stop(ar);
ath10k_hif_power_down(ar);
spin_lock_bh(&ar->data_lock);
if (ar->scan.in_progress) {
del_timer(&ar->scan.timeout);
ar->scan.in_progress = false;
ieee80211_scan_completed(ar->hw, true);
}
spin_unlock_bh(&ar->data_lock);
}
static int ath10k_start(struct ieee80211_hw *hw) static int ath10k_start(struct ieee80211_hw *hw)
{ {
struct ath10k *ar = hw->priv; struct ath10k *ar = hw->priv;
int ret; int ret = 0;
mutex_lock(&ar->conf_mutex); mutex_lock(&ar->conf_mutex);
if (ar->state != ATH10K_STATE_OFF) {
ret = -EINVAL;
goto exit;
}
ret = ath10k_hif_power_up(ar);
if (ret) {
ath10k_err("could not init hif (%d)\n", ret);
ar->state = ATH10K_STATE_OFF;
goto exit;
}
ret = ath10k_core_start(ar);
if (ret) {
ath10k_err("could not init core (%d)\n", ret);
ath10k_hif_power_down(ar);
ar->state = ATH10K_STATE_OFF;
goto exit;
}
ret = ath10k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS, 1); ret = ath10k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS, 1);
if (ret) if (ret)
ath10k_warn("could not enable WMI_PDEV_PARAM_PMF_QOS (%d)\n", 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,9 +1794,9 @@ static int ath10k_start(struct ieee80211_hw *hw)
ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n", ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n",
ret); ret);
ar->state = ATH10K_STATE_ON;
ath10k_regd_update(ar); ath10k_regd_update(ar);
exit:
mutex_unlock(&ar->conf_mutex); mutex_unlock(&ar->conf_mutex);
return 0; return 0;
} }
...@@ -1767,17 +1806,8 @@ static void ath10k_stop(struct ieee80211_hw *hw) ...@@ -1767,17 +1806,8 @@ static void ath10k_stop(struct ieee80211_hw *hw)
struct ath10k *ar = hw->priv; struct ath10k *ar = hw->priv;
mutex_lock(&ar->conf_mutex); mutex_lock(&ar->conf_mutex);
del_timer_sync(&ar->scan.timeout); if (ar->state == ATH10K_STATE_ON)
ath10k_offchan_tx_purge(ar); ath10k_halt(ar);
ath10k_peer_cleanup_all(ar);
spin_lock_bh(&ar->data_lock);
if (ar->scan.in_progress) {
del_timer(&ar->scan.timeout);
ar->scan.in_progress = false;
ieee80211_scan_completed(ar->hw, true);
}
spin_unlock_bh(&ar->data_lock);
ar->state = ATH10K_STATE_OFF; ar->state = ATH10K_STATE_OFF;
mutex_unlock(&ar->conf_mutex); mutex_unlock(&ar->conf_mutex);
......
...@@ -2362,22 +2362,14 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ...@@ -2362,22 +2362,14 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
goto err_iomap; goto err_iomap;
} }
ret = ath10k_pci_hif_power_up(ar);
if (ret) {
ath10k_err("could not start pci hif (%d)\n", ret);
goto err_intr;
}
ret = ath10k_core_register(ar); ret = ath10k_core_register(ar);
if (ret) { if (ret) {
ath10k_err("could not register driver core (%d)\n", ret); ath10k_err("could not register driver core (%d)\n", ret);
goto err_hif; goto err_intr;
} }
return 0; return 0;
err_hif:
ath10k_pci_hif_power_down(ar);
err_intr: err_intr:
ath10k_pci_stop_intr(ar); ath10k_pci_stop_intr(ar);
err_iomap: err_iomap:
...@@ -2416,7 +2408,6 @@ static void ath10k_pci_remove(struct pci_dev *pdev) ...@@ -2416,7 +2408,6 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
tasklet_kill(&ar_pci->msi_fw_err); tasklet_kill(&ar_pci->msi_fw_err);
ath10k_core_unregister(ar); ath10k_core_unregister(ar);
ath10k_pci_hif_power_down(ar);
ath10k_pci_stop_intr(ar); ath10k_pci_stop_intr(ar);
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册