|
@@ -54,6 +54,8 @@ static int ath10k_pci_post_rx_pipe(struct hif_ce_pipe_info *pipe_info,
|
|
|
int num);
|
|
|
static void ath10k_pci_rx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info);
|
|
|
static void ath10k_pci_stop_ce(struct ath10k *ar);
|
|
|
+static void ath10k_pci_device_reset(struct ath10k *ar);
|
|
|
+static int ath10k_pci_reset_target(struct ath10k *ar);
|
|
|
|
|
|
static const struct ce_attr host_ce_config_wlan[] = {
|
|
|
/* host->target HTC control and raw streams */
|
|
@@ -1734,6 +1736,66 @@ static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar)
|
|
|
ath10k_pci_sleep(ar);
|
|
|
}
|
|
|
|
|
|
+static int ath10k_pci_hif_power_up(struct ath10k *ar)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Bring the target up cleanly.
|
|
|
+ *
|
|
|
+ * The target may be in an undefined state with an AUX-powered Target
|
|
|
+ * and a Host in WoW mode. If the Host crashes, loses power, or is
|
|
|
+ * restarted (without unloading the driver) then the Target is left
|
|
|
+ * (aux) powered and running. On a subsequent driver load, the Target
|
|
|
+ * is in an unexpected state. We try to catch that here in order to
|
|
|
+ * reset the Target and retry the probe.
|
|
|
+ */
|
|
|
+ ath10k_pci_device_reset(ar);
|
|
|
+
|
|
|
+ ret = ath10k_pci_reset_target(ar);
|
|
|
+ if (ret)
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ if (ath10k_target_ps) {
|
|
|
+ ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save enabled\n");
|
|
|
+ } else {
|
|
|
+ /* Force AWAKE forever */
|
|
|
+ ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save disabled\n");
|
|
|
+ ath10k_do_pci_wake(ar);
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = ath10k_pci_ce_init(ar);
|
|
|
+ if (ret)
|
|
|
+ goto err_ps;
|
|
|
+
|
|
|
+ ret = ath10k_pci_init_config(ar);
|
|
|
+ if (ret)
|
|
|
+ goto err_ce;
|
|
|
+
|
|
|
+ ret = ath10k_pci_wake_target_cpu(ar);
|
|
|
+ if (ret) {
|
|
|
+ ath10k_err("could not wake up target CPU (%d)\n", ret);
|
|
|
+ goto err_ce;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+err_ce:
|
|
|
+ ath10k_pci_ce_deinit(ar);
|
|
|
+err_ps:
|
|
|
+ if (!ath10k_target_ps)
|
|
|
+ ath10k_do_pci_sleep(ar);
|
|
|
+err:
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static void ath10k_pci_hif_power_down(struct ath10k *ar)
|
|
|
+{
|
|
|
+ ath10k_pci_ce_deinit(ar);
|
|
|
+ if (!ath10k_target_ps)
|
|
|
+ ath10k_do_pci_sleep(ar);
|
|
|
+}
|
|
|
+
|
|
|
static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
|
|
|
.send_head = ath10k_pci_hif_send_head,
|
|
|
.exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg,
|
|
@@ -1744,6 +1806,8 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
|
|
|
.send_complete_check = ath10k_pci_hif_send_complete_check,
|
|
|
.set_callbacks = ath10k_pci_hif_set_callbacks,
|
|
|
.get_free_queue_number = ath10k_pci_hif_get_free_queue_number,
|
|
|
+ .power_up = ath10k_pci_hif_power_up,
|
|
|
+ .power_down = ath10k_pci_hif_power_down,
|
|
|
};
|
|
|
|
|
|
static void ath10k_pci_ce_tasklet(unsigned long ptr)
|
|
@@ -2245,54 +2309,22 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
|
|
goto err_iomap;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Bring the target up cleanly.
|
|
|
- *
|
|
|
- * The target may be in an undefined state with an AUX-powered Target
|
|
|
- * and a Host in WoW mode. If the Host crashes, loses power, or is
|
|
|
- * restarted (without unloading the driver) then the Target is left
|
|
|
- * (aux) powered and running. On a subsequent driver load, the Target
|
|
|
- * is in an unexpected state. We try to catch that here in order to
|
|
|
- * reset the Target and retry the probe.
|
|
|
- */
|
|
|
- ath10k_pci_device_reset(ar);
|
|
|
-
|
|
|
- ret = ath10k_pci_reset_target(ar);
|
|
|
- if (ret)
|
|
|
- goto err_intr;
|
|
|
-
|
|
|
- if (ath10k_target_ps) {
|
|
|
- ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save enabled\n");
|
|
|
- } else {
|
|
|
- /* Force AWAKE forever */
|
|
|
- ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save disabled\n");
|
|
|
- ath10k_do_pci_wake(ar);
|
|
|
- }
|
|
|
-
|
|
|
- ret = ath10k_pci_ce_init(ar);
|
|
|
- if (ret)
|
|
|
- goto err_intr;
|
|
|
-
|
|
|
- ret = ath10k_pci_init_config(ar);
|
|
|
- if (ret)
|
|
|
- goto err_ce;
|
|
|
-
|
|
|
- ret = ath10k_pci_wake_target_cpu(ar);
|
|
|
+ ret = ath10k_pci_hif_power_up(ar);
|
|
|
if (ret) {
|
|
|
- ath10k_err("could not wake up target CPU (%d)\n", ret);
|
|
|
- goto err_ce;
|
|
|
+ ath10k_err("could not start pci hif (%d)\n", ret);
|
|
|
+ goto err_intr;
|
|
|
}
|
|
|
|
|
|
ret = ath10k_core_register(ar);
|
|
|
if (ret) {
|
|
|
ath10k_err("could not register driver core (%d)\n", ret);
|
|
|
- goto err_ce;
|
|
|
+ goto err_hif;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
-err_ce:
|
|
|
- ath10k_pci_ce_deinit(ar);
|
|
|
+err_hif:
|
|
|
+ ath10k_pci_hif_power_down(ar);
|
|
|
err_intr:
|
|
|
ath10k_pci_stop_intr(ar);
|
|
|
err_iomap:
|
|
@@ -2331,7 +2363,7 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
|
|
|
tasklet_kill(&ar_pci->msi_fw_err);
|
|
|
|
|
|
ath10k_core_unregister(ar);
|
|
|
- ath10k_pci_ce_deinit(ar);
|
|
|
+ ath10k_pci_hif_power_down(ar);
|
|
|
ath10k_pci_stop_intr(ar);
|
|
|
|
|
|
pci_set_drvdata(pdev, NULL);
|