mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 12:25:00 -04:00
Merge "cnss2: Try to recover PCIe link to collect dump after link down"
This commit is contained in:
commit
b14de778e8
5 changed files with 83 additions and 15 deletions
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 @@ out:
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue