Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b14de778 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "cnss2: Try to recover PCIe link to collect dump after link down"

parents 0cf5ba6f 08b5c57b
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -448,6 +448,21 @@ int cnss_bus_check_link_status(struct cnss_plat_data *plat_priv)
	}
}

int cnss_bus_recover_link_down(struct cnss_plat_data *plat_priv)
{
	if (!plat_priv)
		return -ENODEV;

	switch (plat_priv->bus_type) {
	case CNSS_BUS_PCI:
		return cnss_pci_recover_link_down(plat_priv->bus_priv);
	default:
		cnss_pr_dbg("Unsupported bus type: %d\n",
			    plat_priv->bus_type);
		return -EINVAL;
	}
}

int cnss_bus_debug_reg_read(struct cnss_plat_data *plat_priv, u32 offset,
			    u32 *val)
{
+1 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ int cnss_bus_update_status(struct cnss_plat_data *plat_priv,
			   enum cnss_driver_status status);
int cnss_bus_is_device_down(struct cnss_plat_data *plat_priv);
int cnss_bus_check_link_status(struct cnss_plat_data *plat_priv);
int cnss_bus_recover_link_down(struct cnss_plat_data *plat_priv);
int cnss_bus_debug_reg_read(struct cnss_plat_data *plat_priv, u32 offset,
			    u32 *val);
int cnss_bus_debug_reg_write(struct cnss_plat_data *plat_priv, u32 offset,
+9 −1
Original line number Diff line number Diff line
@@ -732,7 +732,7 @@ int cnss_idle_shutdown(struct device *dev)

	reinit_completion(&plat_priv->recovery_complete);
	ret = wait_for_completion_timeout(&plat_priv->recovery_complete,
					  RECOVERY_TIMEOUT);
					  msecs_to_jiffies(RECOVERY_TIMEOUT));
	if (!ret) {
		cnss_pr_err("Timeout waiting for recovery to complete\n");
		CNSS_ASSERT(0);
@@ -1083,6 +1083,14 @@ static int cnss_do_recovery(struct cnss_plat_data *plat_priv,
		if (test_bit(LINK_DOWN_SELF_RECOVERY,
			     &plat_priv->ctrl_params.quirks))
			goto self_recovery;
		if (!cnss_bus_recover_link_down(plat_priv)) {
			/* clear recovery bit here to avoid skipping
			 * the recovery work for RDDM later
			 */
			clear_bit(CNSS_DRIVER_RECOVERY,
				  &plat_priv->driver_state);
			return 0;
		}
		break;
	case CNSS_REASON_RDDM:
		cnss_bus_collect_dump_info(plat_priv, false);
+56 −14
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@
#define WAKE_MSI_NAME			"WAKE"

#define DEV_RDDM_TIMEOUT		5000
#define WAKE_EVENT_TIMEOUT		5000

#ifdef CONFIG_CNSS_EMULATION
#define EMULATION_HW			1
@@ -826,6 +827,42 @@ int cnss_resume_pci_link(struct cnss_pci_data *pci_priv)
	return ret;
}

int cnss_pci_recover_link_down(struct cnss_pci_data *pci_priv)
{
	int ret;

	switch (pci_priv->device_id) {
	case QCA6390_DEVICE_ID:
	case QCA6490_DEVICE_ID:
		break;
	default:
		return -EOPNOTSUPP;
	}

	/* Always wait here to avoid missing WAKE assert for RDDM
	 * before link recovery
	 */
	msleep(WAKE_EVENT_TIMEOUT);

	ret = cnss_suspend_pci_link(pci_priv);
	if (ret)
		cnss_pr_err("Failed to suspend PCI link, err = %d\n", ret);

	ret = cnss_resume_pci_link(pci_priv);
	if (ret) {
		cnss_pr_err("Failed to resume PCI link, err = %d\n", ret);
		del_timer(&pci_priv->dev_rddm_timer);
		return ret;
	}

	mod_timer(&pci_priv->dev_rddm_timer,
		  jiffies + msecs_to_jiffies(DEV_RDDM_TIMEOUT));

	mhi_debug_reg_dump(pci_priv->mhi_ctrl);

	return 0;
}

int cnss_pci_prevent_l1(struct device *dev)
{
	struct pci_dev *pci_dev = to_pci_dev(dev);
@@ -900,6 +937,7 @@ int cnss_pci_link_down(struct device *dev)
	pci_priv->pci_link_down_ind = true;
	spin_unlock_irqrestore(&pci_link_down_lock, flags);

	reinit_completion(&pci_priv->wake_event);
	cnss_pr_err("PCI link down is detected, schedule recovery\n");

	cnss_schedule_recovery(dev, CNSS_REASON_LINK_DOWN);
@@ -2384,23 +2422,25 @@ static void cnss_pci_event_cb(struct msm_pcie_notify *notify)
	case MSM_PCIE_EVENT_LINKDOWN:
		if (test_bit(ENABLE_PCI_LINK_DOWN_PANIC,
			     &plat_priv->ctrl_params.quirks))
			panic("cnss: PCI link is down!\n");
			panic("cnss: PCI link is down\n");

		spin_lock_irqsave(&pci_link_down_lock, flags);
		if (pci_priv->pci_link_down_ind) {
			cnss_pr_dbg("PCI link down recovery is in progress, ignore!\n");
			cnss_pr_dbg("PCI link down recovery is in progress, ignore\n");
			spin_unlock_irqrestore(&pci_link_down_lock, flags);
			return;
		}
		pci_priv->pci_link_down_ind = true;
		spin_unlock_irqrestore(&pci_link_down_lock, flags);

		cnss_fatal_err("PCI link down, schedule recovery!\n");
		reinit_completion(&pci_priv->wake_event);
		cnss_fatal_err("PCI link down, schedule recovery\n");
		if (pci_dev->device == QCA6174_DEVICE_ID)
			disable_irq(pci_dev->irq);
		cnss_schedule_recovery(&pci_dev->dev, CNSS_REASON_LINK_DOWN);
		break;
	case MSM_PCIE_EVENT_WAKEUP:
		complete(&pci_priv->wake_event);
		if (cnss_pci_get_monitor_wake_intr(pci_priv) &&
		    cnss_pci_get_auto_suspended(pci_priv)) {
			cnss_pci_set_monitor_wake_intr(pci_priv, false);
@@ -3790,18 +3830,21 @@ static int cnss_pci_enable_bus(struct cnss_pci_data *pci_priv)
		goto release_region;
	}

	pci_set_master(pci_dev);

	pci_priv->bar = pci_iomap(pci_dev, PCI_BAR_NUM, 0);
	if (!pci_priv->bar) {
		cnss_pr_err("Failed to do PCI IO map!\n");
		ret = -EIO;
		goto clear_master;
		goto release_region;
	}

	/* Save default config space without BME enabled */
	pci_save_state(pci_dev);
	pci_priv->default_state = pci_store_saved_state(pci_dev);

	pci_set_master(pci_dev);

	return 0;

clear_master:
	pci_clear_master(pci_dev);
release_region:
	pci_release_region(pci_dev, PCI_BAR_NUM);
disable_device:
@@ -3814,12 +3857,14 @@ static void cnss_pci_disable_bus(struct cnss_pci_data *pci_priv)
{
	struct pci_dev *pci_dev = pci_priv->pci_dev;

	pci_clear_master(pci_dev);
	pci_load_and_free_saved_state(pci_dev, &pci_priv->saved_state);

	if (pci_priv->bar) {
		pci_iounmap(pci_dev, pci_priv->bar);
		pci_priv->bar = NULL;
	}

	pci_clear_master(pci_dev);
	pci_release_region(pci_dev, PCI_BAR_NUM);
	if (pci_is_enabled(pci_dev))
		pci_disable_device(pci_dev);
@@ -4621,9 +4666,6 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
	if (ret)
		goto dereg_pci_event;

	pci_save_state(pci_dev);
	pci_priv->default_state = pci_store_saved_state(pci_dev);

	switch (pci_dev->device) {
	case QCA6174_DEVICE_ID:
		pci_read_config_word(pci_dev, QCA6174_REV_ID_OFFSET,
@@ -4640,6 +4682,7 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
		cnss_pci_set_wlaon_pwr_ctrl(pci_priv, false, false, false);
		timer_setup(&pci_priv->dev_rddm_timer,
			    cnss_dev_rddm_timeout_hdlr, 0);
		init_completion(&pci_priv->wake_event);
		INIT_DELAYED_WORK(&pci_priv->time_sync_work,
				  cnss_pci_time_sync_work_hdlr);

@@ -4703,14 +4746,13 @@ static void cnss_pci_remove(struct pci_dev *pci_dev)
	case QCA6490_DEVICE_ID:
		cnss_pci_unregister_mhi(pci_priv);
		cnss_pci_disable_msi(pci_priv);
		complete_all(&pci_priv->wake_event);
		del_timer(&pci_priv->dev_rddm_timer);
		break;
	default:
		break;
	}

	pci_load_and_free_saved_state(pci_dev, &pci_priv->saved_state);

	cnss_pci_disable_bus(pci_priv);
	cnss_dereg_pci_event(pci_priv);
	cnss_pci_deinit_smmu(pci_priv);
+2 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ struct cnss_pci_data {
	u8 drv_connected_last;
	u16 def_link_speed;
	u16 def_link_width;
	struct completion wake_event;
	u8 monitor_wake_intr;
	struct iommu_domain *iommu_domain;
	u8 smmu_s1_enable;
@@ -164,6 +165,7 @@ static inline int cnss_pci_get_drv_connected(void *bus_priv)
int cnss_pci_check_link_status(struct cnss_pci_data *pci_priv);
int cnss_suspend_pci_link(struct cnss_pci_data *pci_priv);
int cnss_resume_pci_link(struct cnss_pci_data *pci_priv);
int cnss_pci_recover_link_down(struct cnss_pci_data *pci_priv);
int cnss_pci_init(struct cnss_plat_data *plat_priv);
void cnss_pci_deinit(struct cnss_plat_data *plat_priv);
int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv);