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

Commit 2b4bdeef authored by Yue Ma's avatar Yue Ma
Browse files

cnss: Add API to recover from PCI link down



Sometimes PCI framework and PCI bus driver fail to detect PCI link down
failure. Expose the API to WLAN host driver so that it can recover when
detects the failure by itself. Also expose an MSM PCIe API to WLAN host
driver which will used for MSM platform.

Change-Id: Ia49ef0728a3759190c0283a90ddcce4b465dd993
CRs-fixed: 707986
Signed-off-by: default avatarYue Ma <yuem@codeaurora.org>
parent 408d933c
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <soc/qcom/ramdump.h>
#include <linux/msm-bus.h>
#include <linux/msm-bus-board.h>
#include <linux/spinlock.h>
#include <linux/suspend.h>
#include <linux/rwsem.h>
#ifdef CONFIG_PCI_MSM
@@ -98,6 +99,8 @@ static struct cnss_fw_files FW_FILES_DEFAULT = {

#define CNSS_PINCTRL_STATE_ACTIVE "default"

static DEFINE_SPINLOCK(pci_link_down_lock);

struct cnss_wlan_gpio_info {
	char *name;
	u32 num;
@@ -763,11 +766,45 @@ DECLARE_WORK(recovery_work, recovery_work_handler);

void cnss_pci_link_down_cb(struct msm_pcie_notify *notify)
{
	unsigned long flags;

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

	pr_err("PCI link down, schedule recovery\n");
	schedule_work(&recovery_work);
}

void cnss_wlan_pci_link_down(void)
{
	unsigned long flags;

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

	pr_err("PCI link down detected by host driver, schedule recovery!\n");
	schedule_work(&recovery_work);
}
EXPORT_SYMBOL(cnss_wlan_pci_link_down);

int cnss_pcie_shadow_control(struct pci_dev *dev, bool enable)
{
	return msm_pcie_shadow_control(dev, enable);
}
EXPORT_SYMBOL(cnss_pcie_shadow_control);

int cnss_wlan_register_driver(struct cnss_wlan_driver *driver)
{
	int ret = 0;
+2 −0
Original line number Diff line number Diff line
@@ -78,6 +78,8 @@ extern int cnss_get_wlan_unsafe_channel(u16 *unsafe_ch_list,
		u16 *ch_count, u16 buf_len);
extern int cnss_wlan_set_dfs_nol(void *info, u16 info_len);
extern int cnss_wlan_get_dfs_nol(void *info, u16 info_len);
extern void cnss_wlan_pci_link_down(void);
extern int cnss_pcie_shadow_control(struct pci_dev *dev, bool enable);
extern int cnss_wlan_register_driver(struct cnss_wlan_driver *driver);
extern void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver);
extern int cnss_get_fw_files(struct cnss_fw_files *pfw_files);