Files
android_kernel_samsung_sm86…/cnss2/pci.h
Naman Padhiar b791c15d0c cnss2: Optimize link down recovery sequence
Remove unwanted delay from PCIe link down recovery sequence
1. Wait for wake event from PCIe driver instead of hardcoded wait.
2. After link recovers, wait for device to move to RDDM mode
   instead of starting rddm timer.
3. If device fails to move to RDDM, assert HOST SOL and initiate
   side band recovery.

Change-Id: I5a4096ac781dd8f5011b07b0ffb669815a968570
CRs-Fixed: 3590419
2023-09-24 19:07:57 -07:00

337 lines
9.7 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _CNSS_PCI_H
#define _CNSS_PCI_H
#include <linux/cma.h>
#include <linux/iommu.h>
#include <linux/qcom-iommu-util.h>
#include <linux/mhi.h>
#if IS_ENABLED(CONFIG_MHI_BUS_MISC)
#include <linux/mhi_misc.h>
#endif
#if IS_ENABLED(CONFIG_PCI_MSM)
#include <linux/msm_pcie.h>
#endif
#include <linux/of_reserved_mem.h>
#include <linux/pci.h>
#include <linux/sched_clock.h>
#include <linux/version.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 2, 0))
#include <linux/sched/clock.h>
#endif
#include "main.h"
#define PM_OPTIONS_DEFAULT 0
#define PCI_LINK_DOWN 0
#ifdef CONFIG_CNSS_SUPPORT_DUAL_DEV
#define LINK_TRAINING_RETRY_MAX_TIMES 2
#else
#define LINK_TRAINING_RETRY_MAX_TIMES 3
#endif
#define LINK_TRAINING_RETRY_DELAY_MS 500
#define MSI_USERS 4
#define CNSS_MHI_IN_MISSION_MODE(ee) (ee == MHI_EE_AMSS || \
ee == MHI_EE_WFW || \
ee == MHI_EE_FP)
enum cnss_mhi_state {
CNSS_MHI_INIT,
CNSS_MHI_DEINIT,
CNSS_MHI_POWER_ON,
CNSS_MHI_POWERING_OFF,
CNSS_MHI_POWER_OFF,
CNSS_MHI_FORCE_POWER_OFF,
CNSS_MHI_SUSPEND,
CNSS_MHI_RESUME,
CNSS_MHI_TRIGGER_RDDM,
CNSS_MHI_RDDM,
CNSS_MHI_RDDM_DONE,
};
enum pci_link_status {
PCI_GEN1,
PCI_GEN2,
PCI_DEF,
};
enum cnss_rtpm_id {
RTPM_ID_CNSS,
RTPM_ID_MHI,
RTPM_ID_MAX,
};
enum cnss_pci_reg_dev_mask {
REG_MASK_QCA6390,
REG_MASK_QCA6490,
REG_MASK_KIWI,
REG_MASK_MANGO,
REG_MASK_PEACH,
};
enum cnss_smmu_fault_time {
SMMU_CB_ENTRY,
SMMU_CB_DOORBELL_RING,
SMMU_CB_EXIT,
SMMU_CB_MAX,
};
struct cnss_msi_user {
char *name;
int num_vectors;
u32 base_vector;
};
struct cnss_msi_config {
int total_vectors;
int total_users;
struct cnss_msi_user *users;
};
struct cnss_pci_reg {
char *name;
u32 offset;
};
struct cnss_pci_debug_reg {
u32 offset;
u32 val;
};
struct cnss_misc_reg {
unsigned long dev_mask;
u8 wr;
u32 offset;
u32 val;
};
struct cnss_pm_stats {
atomic_t runtime_get;
atomic_t runtime_put;
atomic_t runtime_get_id[RTPM_ID_MAX];
atomic_t runtime_put_id[RTPM_ID_MAX];
u64 runtime_get_timestamp_id[RTPM_ID_MAX];
u64 runtime_put_timestamp_id[RTPM_ID_MAX];
};
struct cnss_print_optimize {
int msi_log_chk[MSI_USERS];
int msi_addr_chk;
};
struct cnss_pci_data {
struct pci_dev *pci_dev;
struct cnss_plat_data *plat_priv;
const struct pci_device_id *pci_device_id;
u32 device_id;
u16 revision_id;
u64 dma_bit_mask;
struct cnss_wlan_driver *driver_ops;
u8 pci_link_state;
u8 pci_link_down_ind;
struct pci_saved_state *saved_state;
struct pci_saved_state *default_state;
#if IS_ENABLED(CONFIG_PCI_MSM)
struct msm_pcie_register_event msm_pci_event;
#endif
struct cnss_pm_stats pm_stats;
atomic_t auto_suspended;
atomic_t drv_connected;
u8 drv_connected_last;
u32 qmi_send_usage_count;
u16 def_link_speed;
u16 def_link_width;
u16 cur_link_speed;
int wake_gpio;
int wake_irq;
u32 wake_counter;
u8 monitor_wake_intr;
struct iommu_domain *iommu_domain;
u8 smmu_s1_enable;
dma_addr_t smmu_iova_start;
size_t smmu_iova_len;
dma_addr_t smmu_iova_ipa_start;
dma_addr_t smmu_iova_ipa_current;
size_t smmu_iova_ipa_len;
void __iomem *bar;
struct cnss_msi_config *msi_config;
u32 msi_ep_base_data;
u32 msix_addr;
struct mhi_controller *mhi_ctrl;
unsigned long mhi_state;
u32 remap_window;
struct completion wake_event_complete;
struct timer_list dev_rddm_timer;
struct timer_list boot_debug_timer;
struct delayed_work time_sync_work;
u8 disable_pc;
struct mutex bus_lock; /* mutex for suspend and resume bus */
struct cnss_pci_debug_reg *debug_reg;
struct cnss_misc_reg *wcss_reg;
struct cnss_misc_reg *pcie_reg;
struct cnss_misc_reg *wlaon_reg;
struct cnss_misc_reg *syspm_reg;
unsigned long misc_reg_dev_mask;
u8 iommu_geometry;
bool drv_supported;
bool is_smmu_fault;
unsigned long long smmu_fault_timestamp[SMMU_CB_MAX];
};
static inline void cnss_set_pci_priv(struct pci_dev *pci_dev, void *data)
{
pci_set_drvdata(pci_dev, data);
}
static inline struct cnss_pci_data *cnss_get_pci_priv(struct pci_dev *pci_dev)
{
return pci_get_drvdata(pci_dev);
}
static inline struct cnss_plat_data *cnss_pci_priv_to_plat_priv(void *bus_priv)
{
struct cnss_pci_data *pci_priv = bus_priv;
return pci_priv->plat_priv;
}
static inline void cnss_pci_set_monitor_wake_intr(void *bus_priv, bool val)
{
struct cnss_pci_data *pci_priv = bus_priv;
pci_priv->monitor_wake_intr = val;
}
static inline bool cnss_pci_get_monitor_wake_intr(void *bus_priv)
{
struct cnss_pci_data *pci_priv = bus_priv;
return pci_priv->monitor_wake_intr;
}
static inline void cnss_pci_set_auto_suspended(void *bus_priv, int val)
{
struct cnss_pci_data *pci_priv = bus_priv;
atomic_set(&pci_priv->auto_suspended, val);
}
static inline int cnss_pci_get_auto_suspended(void *bus_priv)
{
struct cnss_pci_data *pci_priv = bus_priv;
return atomic_read(&pci_priv->auto_suspended);
}
static inline void cnss_pci_set_drv_connected(void *bus_priv, int val)
{
struct cnss_pci_data *pci_priv = bus_priv;
atomic_set(&pci_priv->drv_connected, val);
}
static inline int cnss_pci_get_drv_connected(void *bus_priv)
{
struct cnss_pci_data *pci_priv = bus_priv;
return atomic_read(&pci_priv->drv_connected);
}
void cnss_mhi_controller_set_base(struct cnss_pci_data *pci_priv,
phys_addr_t base);
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);
void cnss_pci_add_fw_prefix_name(struct cnss_pci_data *pci_priv,
char *prefix_name, char *name);
int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv);
int cnss_pci_alloc_qdss_mem(struct cnss_pci_data *pci_priv);
void cnss_pci_free_qdss_mem(struct cnss_pci_data *pci_priv);
int cnss_pci_load_tme_patch(struct cnss_pci_data *pci_priv);
int cnss_pci_load_m3(struct cnss_pci_data *pci_priv);
void cnss_pci_free_blob_mem(struct cnss_pci_data *pci_priv);
int cnss_pci_load_aux(struct cnss_pci_data *pci_priv);
int cnss_pci_handle_dev_sol_irq(struct cnss_pci_data *pci_priv);
int cnss_pci_start_mhi(struct cnss_pci_data *pci_priv);
void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic);
#ifdef CONFIG_CNSS2_SSR_DRIVER_DUMP
void cnss_pci_collect_host_dump_info(struct cnss_pci_data *pci_priv);
#else
static inline
void cnss_pci_collect_host_dump_info(struct cnss_pci_data *pci_priv)
{
}
#endif
void cnss_pci_device_crashed(struct cnss_pci_data *pci_priv);
void cnss_pci_clear_dump_info(struct cnss_pci_data *pci_priv);
u32 cnss_pci_get_wake_msi(struct cnss_pci_data *pci_priv);
int cnss_pci_force_fw_assert_hdlr(struct cnss_pci_data *pci_priv);
int cnss_pci_qmi_send_get(struct cnss_pci_data *pci_priv);
int cnss_pci_qmi_send_put(struct cnss_pci_data *pci_priv);
void cnss_pci_fw_boot_timeout_hdlr(struct cnss_pci_data *pci_priv);
int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv);
int cnss_pci_call_driver_remove(struct cnss_pci_data *pci_priv);
int cnss_pci_dev_powerup(struct cnss_pci_data *pci_priv);
int cnss_pci_dev_shutdown(struct cnss_pci_data *pci_priv);
int cnss_pci_dev_crash_shutdown(struct cnss_pci_data *pci_priv);
int cnss_pci_dev_ramdump(struct cnss_pci_data *pci_priv);
int cnss_pci_register_driver_hdlr(struct cnss_pci_data *pci_priv, void *data);
int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv);
int cnss_pci_call_driver_modem_status(struct cnss_pci_data *pci_priv,
int modem_current_status);
void cnss_pci_pm_runtime_show_usage_count(struct cnss_pci_data *pci_priv);
int cnss_pci_pm_request_resume(struct cnss_pci_data *pci_priv);
int cnss_pci_pm_runtime_resume(struct cnss_pci_data *pci_priv);
int cnss_pci_pm_runtime_get(struct cnss_pci_data *pci_priv,
enum cnss_rtpm_id id);
int cnss_pci_pm_runtime_get_sync(struct cnss_pci_data *pci_priv,
enum cnss_rtpm_id id);
void cnss_pci_pm_runtime_get_noresume(struct cnss_pci_data *pci_priv,
enum cnss_rtpm_id id);
int cnss_pci_pm_runtime_put_autosuspend(struct cnss_pci_data *pci_priv,
enum cnss_rtpm_id id);
void cnss_pci_pm_runtime_put_noidle(struct cnss_pci_data *pci_priv,
enum cnss_rtpm_id id);
void cnss_pci_pm_runtime_mark_last_busy(struct cnss_pci_data *pci_priv);
int cnss_pci_update_status(struct cnss_pci_data *pci_priv,
enum cnss_driver_status status);
int cnss_pci_call_driver_uevent(struct cnss_pci_data *pci_priv,
enum cnss_driver_status status, void *data);
int cnss_pcie_is_device_down(struct cnss_pci_data *pci_priv);
int cnss_pci_suspend_bus(struct cnss_pci_data *pci_priv);
int cnss_pci_resume_bus(struct cnss_pci_data *pci_priv);
int cnss_pci_debug_reg_read(struct cnss_pci_data *pci_priv, u32 offset,
u32 *val, bool raw_access);
int cnss_pci_debug_reg_write(struct cnss_pci_data *pci_priv, u32 offset,
u32 val, bool raw_access);
int cnss_pci_get_iova(struct cnss_pci_data *pci_priv, u64 *addr, u64 *size);
int cnss_pci_get_iova_ipa(struct cnss_pci_data *pci_priv, u64 *addr,
u64 *size);
bool cnss_pci_is_smmu_s1_enabled(struct cnss_pci_data *pci_priv);
void cnss_pci_handle_linkdown(struct cnss_pci_data *pci_priv);
int cnss_pci_update_time_sync_period(struct cnss_pci_data *pci_priv,
unsigned int time_sync_period);
int cnss_pci_set_therm_cdev_state(struct cnss_pci_data *pci_priv,
unsigned long thermal_state,
int tcdev_id);
int cnss_pci_get_user_msi_assignment(struct cnss_pci_data *pci_priv,
char *user_name,
int *num_vectors,
u32 *user_base_data,
u32 *base_vector);
void cnss_register_iommu_fault_handler_irq(struct cnss_pci_data *pci_priv);
#endif /* _CNSS_PCI_H */