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

Commit 9a382116 authored by Yue Ma's avatar Yue Ma Committed by Gerrit - the friendly Code Review server
Browse files

cnss2: Refactor PCIe bus related code



PCIe bus related APIs should not directly called from common files.
Instead, create equivalent abstract BUS APIs from where it can
decide which corresponding PCIe bus APIs to be invoked. This will
help to extend other buses like USB and SDIO in the future.

Change-Id: I1f115173f2e6c34e3a8cb6f975349112f52697e4
Signed-off-by: default avatarYue Ma <yuem@codeaurora.org>
Signed-off-by: default avatarRajasekaran Kalidoss <rkalidos@codeaurora.org>
parent 5ff075a6
Loading
Loading
Loading
Loading
+192 −0
Original line number Diff line number Diff line
@@ -41,6 +41,38 @@ enum cnss_dev_bus_type cnss_get_bus_type(unsigned long device_id)
	}
}

void *cnss_bus_dev_to_bus_priv(struct device *dev)
{
	if (!dev)
		return NULL;

	switch (cnss_get_dev_bus_type(dev)) {
	case CNSS_BUS_PCI:
		return cnss_get_pci_priv(to_pci_dev(dev));
	default:
		return NULL;
	}
}

struct cnss_plat_data *cnss_bus_dev_to_plat_priv(struct device *dev)
{
	void *bus_priv;

	if (!dev)
		return cnss_get_plat_priv(NULL);

	bus_priv = cnss_bus_dev_to_bus_priv(dev);
	if (!bus_priv)
		return NULL;

	switch (cnss_get_dev_bus_type(dev)) {
	case CNSS_BUS_PCI:
		return cnss_pci_priv_to_plat_priv(bus_priv);
	default:
		return NULL;
	}
}

int cnss_bus_init(struct cnss_plat_data *plat_priv)
{
	if (!plat_priv)
@@ -150,11 +182,19 @@ void cnss_bus_fw_boot_timeout_hdlr(unsigned long data)

void cnss_bus_collect_dump_info(struct cnss_plat_data *plat_priv)
{
	int ret;

	if (!plat_priv)
		return;

	switch (plat_priv->bus_type) {
	case CNSS_BUS_PCI:
		ret = cnss_pci_set_mhi_state(plat_priv->bus_priv,
					     CNSS_MHI_RDDM);
		if (ret) {
			cnss_pr_err("Failed to complete RDDM, err = %d\n", ret);
			break;
		}
		return cnss_pci_collect_dump_info(plat_priv->bus_priv);
	default:
		cnss_pr_err("Unsupported bus type: %d\n",
@@ -162,3 +202,155 @@ void cnss_bus_collect_dump_info(struct cnss_plat_data *plat_priv)
		return;
	}
}

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

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

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

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

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

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

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

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

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

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

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

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

int cnss_bus_register_driver_hdlr(struct cnss_plat_data *plat_priv, void *data)
{
	if (!plat_priv)
		return -ENODEV;

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

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

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

int cnss_bus_call_driver_modem_status(struct cnss_plat_data *plat_priv,
				      int modem_current_status)
{
	if (!plat_priv)
		return -ENODEV;

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

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

	switch (plat_priv->bus_type) {
	case CNSS_BUS_PCI:
		return cnss_pci_recovery_update_status(plat_priv->bus_priv);
	default:
		cnss_pr_err("Unsupported bus type: %d\n",
			    plat_priv->bus_type);
		return -EINVAL;
	}
}
+13 −1
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@

enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev);
enum cnss_dev_bus_type cnss_get_bus_type(unsigned long device_id);
void *cnss_bus_dev_to_bus_priv(struct device *dev);
struct cnss_plat_data *cnss_bus_dev_to_plat_priv(struct device *dev);
int cnss_bus_init(struct cnss_plat_data *plat_priv);
void cnss_bus_deinit(struct cnss_plat_data *plat_priv);
int cnss_bus_load_m3(struct cnss_plat_data *plat_priv);
@@ -35,5 +37,15 @@ u32 cnss_bus_get_wake_irq(struct cnss_plat_data *plat_priv);
int cnss_bus_force_fw_assert_hdlr(struct cnss_plat_data *plat_priv);
void cnss_bus_fw_boot_timeout_hdlr(unsigned long data);
void cnss_bus_collect_dump_info(struct cnss_plat_data *plat_priv);

int cnss_bus_call_driver_probe(struct cnss_plat_data *plat_priv);
int cnss_bus_call_driver_remove(struct cnss_plat_data *plat_priv);
int cnss_bus_dev_powerup(struct cnss_plat_data *plat_priv);
int cnss_bus_dev_shutdown(struct cnss_plat_data *plat_priv);
int cnss_bus_dev_crash_shutdown(struct cnss_plat_data *plat_priv);
int cnss_bus_dev_ramdump(struct cnss_plat_data *plat_priv);
int cnss_bus_register_driver_hdlr(struct cnss_plat_data *plat_priv, void *data);
int cnss_bus_unregister_driver_hdlr(struct cnss_plat_data *plat_priv);
int cnss_bus_call_driver_modem_status(struct cnss_plat_data *plat_priv,
				      int modem_current_status);
int cnss_bus_recovery_update_status(struct cnss_plat_data *plat_priv);
#endif /* _CNSS_BUS_H */
+30 −537
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@
#include "main.h"
#include "bus.h"
#include "debug.h"
#include "pci.h"

#define CNSS_DUMP_FORMAT_VER		0x11
#define CNSS_DUMP_FORMAT_VER_V2		0x22
@@ -55,13 +54,6 @@ module_param(enable_waltest, bool, 0600);
MODULE_PARM_DESC(enable_waltest, "Enable to handle firmware waltest");
#endif

enum cnss_debug_quirks {
	LINK_DOWN_SELF_RECOVERY,
	SKIP_DEVICE_BOOT,
	USE_CORE_ONLY_FW,
	SKIP_RECOVERY,
};

unsigned long quirks;
#ifdef CONFIG_CNSS2_DEBUG
module_param(quirks, ulong, 0600);
@@ -93,44 +85,11 @@ static void cnss_set_plat_priv(struct platform_device *plat_dev,
	plat_env = plat_priv;
}

static struct cnss_plat_data *cnss_get_plat_priv(struct platform_device
						 *plat_dev)
struct cnss_plat_data *cnss_get_plat_priv(struct platform_device *plat_dev)
{
	return plat_env;
}

void *cnss_bus_dev_to_bus_priv(struct device *dev)
{
	if (!dev)
		return NULL;

	switch (cnss_get_dev_bus_type(dev)) {
	case CNSS_BUS_PCI:
		return cnss_get_pci_priv(to_pci_dev(dev));
	default:
		return NULL;
	}
}

struct cnss_plat_data *cnss_bus_dev_to_plat_priv(struct device *dev)
{
	void *bus_priv;

	if (!dev)
		return cnss_get_plat_priv(NULL);

	bus_priv = cnss_bus_dev_to_bus_priv(dev);
	if (!bus_priv)
		return NULL;

	switch (cnss_get_dev_bus_type(dev)) {
	case CNSS_BUS_PCI:
		return cnss_pci_priv_to_plat_priv(bus_priv);
	default:
		return NULL;
	}
}

static int cnss_pm_notify(struct notifier_block *b,
			  unsigned long event, void *p)
{
@@ -475,6 +434,16 @@ int cnss_set_fw_log_mode(struct device *dev, u8 fw_log_mode)
}
EXPORT_SYMBOL(cnss_set_fw_log_mode);

unsigned long *cnss_get_debug_quirks(void)
{
	return &quirks;
}

bool *cnss_get_qmi_bypass(void)
{
	return &qmi_bypass;
}

static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
{
	int ret = 0;
@@ -505,79 +474,6 @@ out:
	return ret;
}

static int cnss_driver_call_probe(struct cnss_plat_data *plat_priv)
{
	int ret = 0;
	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;

	if (test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state)) {
		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
		cnss_pr_dbg("Skip driver probe\n");
		goto out;
	}

	if (!plat_priv->driver_ops) {
		cnss_pr_err("driver_ops is NULL\n");
		ret = -EINVAL;
		goto out;
	}

	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
	    test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
		ret = plat_priv->driver_ops->reinit(pci_priv->pci_dev,
						    pci_priv->pci_device_id);
		if (ret) {
			cnss_pr_err("Failed to reinit host driver, err = %d\n",
				    ret);
			goto out;
		}
		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
	} else if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state)) {
		ret = plat_priv->driver_ops->probe(pci_priv->pci_dev,
						   pci_priv->pci_device_id);
		if (ret) {
			cnss_pr_err("Failed to probe host driver, err = %d\n",
				    ret);
			goto out;
		}
		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
		clear_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
		set_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state);
	}

	return 0;

out:
	return ret;
}

static int cnss_driver_call_remove(struct cnss_plat_data *plat_priv)
{
	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;

	if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state) ||
	    test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state) ||
	    test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state)) {
		cnss_pr_dbg("Skip driver remove\n");
		return 0;
	}

	if (!plat_priv->driver_ops) {
		cnss_pr_err("driver_ops is NULL\n");
		return -EINVAL;
	}

	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
	    test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
		plat_priv->driver_ops->shutdown(pci_priv->pci_dev);
	} else if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) {
		plat_priv->driver_ops->remove(pci_priv->pci_dev);
		clear_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state);
	}

	return 0;
}

static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv)
{
	int ret = 0;
@@ -601,7 +497,7 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv)
						    QMI_WLFW_CALIBRATION_V01);
	} else if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
		   test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
		ret = cnss_driver_call_probe(plat_priv);
		ret = cnss_bus_call_driver_probe(plat_priv);
	} else {
		complete(&plat_priv->power_up_complete);
	}
@@ -614,9 +510,7 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv)
	return 0;

shutdown:
	cnss_pci_stop_mhi(plat_priv->bus_priv);
	cnss_suspend_pci_link(plat_priv->bus_priv);
	cnss_power_off_device(plat_priv);
	cnss_bus_dev_shutdown(plat_priv);

	clear_bit(CNSS_FW_READY, &plat_priv->driver_state);
	clear_bit(CNSS_FW_MEM_READY, &plat_priv->driver_state);
@@ -788,44 +682,6 @@ int cnss_power_down(struct device *dev)
}
EXPORT_SYMBOL(cnss_power_down);

int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops)
{
	int ret = 0;
	struct cnss_plat_data *plat_priv = cnss_get_plat_priv(NULL);

	if (!plat_priv) {
		cnss_pr_err("plat_priv is NULL!\n");
		return -ENODEV;
	}

	if (plat_priv->driver_ops) {
		cnss_pr_err("Driver has already registered!\n");
		return -EEXIST;
	}

	ret = cnss_driver_event_post(plat_priv,
				     CNSS_DRIVER_EVENT_REGISTER_DRIVER,
				     CNSS_EVENT_SYNC_UNINTERRUPTIBLE,
				     driver_ops);
	return ret;
}
EXPORT_SYMBOL(cnss_wlan_register_driver);

void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver_ops)
{
	struct cnss_plat_data *plat_priv = cnss_get_plat_priv(NULL);

	if (!plat_priv) {
		cnss_pr_err("plat_priv is NULL!\n");
		return;
	}

	cnss_driver_event_post(plat_priv,
			       CNSS_DRIVER_EVENT_UNREGISTER_DRIVER,
			       CNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL);
}
EXPORT_SYMBOL(cnss_wlan_unregister_driver);

static int cnss_get_resources(struct cnss_plat_data *plat_priv)
{
	int ret = 0;
@@ -857,13 +713,11 @@ static int cnss_modem_notifier_nb(struct notifier_block *nb,
{
	struct cnss_plat_data *plat_priv =
		container_of(nb, struct cnss_plat_data, modem_nb);
	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
	struct cnss_esoc_info *esoc_info;
	struct cnss_wlan_driver *driver_ops;

	cnss_pr_dbg("Modem notifier: event %lu\n", code);

	if (!pci_priv)
	if (!plat_priv)
		return NOTIFY_DONE;

	esoc_info = &plat_priv->esoc_info;
@@ -875,13 +729,10 @@ static int cnss_modem_notifier_nb(struct notifier_block *nb,
	else
		return NOTIFY_DONE;

	driver_ops = plat_priv->driver_ops;
	if (!driver_ops || !driver_ops->modem_status)
	if (!cnss_bus_call_driver_modem_status(plat_priv,
					       esoc_info->modem_current_status))
		return NOTIFY_DONE;

	driver_ops->modem_status(pci_priv->pci_dev,
				 esoc_info->modem_current_status);

	return NOTIFY_OK;
}

@@ -955,246 +806,6 @@ static void cnss_unregister_esoc(struct cnss_plat_data *plat_priv)
		devm_unregister_esoc_client(dev, esoc_info->esoc_desc);
}

static int cnss_qca6174_powerup(struct cnss_plat_data *plat_priv)
{
	int ret = 0;
	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;

	if (!pci_priv) {
		cnss_pr_err("pci_priv is NULL!\n");
		return -ENODEV;
	}

	ret = cnss_power_on_device(plat_priv);
	if (ret) {
		cnss_pr_err("Failed to power on device, err = %d\n", ret);
		goto out;
	}

	ret = cnss_resume_pci_link(pci_priv);
	if (ret) {
		cnss_pr_err("Failed to resume PCI link, err = %d\n", ret);
		goto power_off;
	}

	ret = cnss_driver_call_probe(plat_priv);
	if (ret)
		goto suspend_link;

	return 0;
suspend_link:
	cnss_suspend_pci_link(pci_priv);
power_off:
	cnss_power_off_device(plat_priv);
out:
	return ret;
}

static int cnss_qca6174_shutdown(struct cnss_plat_data *plat_priv)
{
	int ret = 0;
	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;

	if (!pci_priv)
		return -ENODEV;

	cnss_pm_request_resume(pci_priv);

	cnss_driver_call_remove(plat_priv);

	cnss_request_bus_bandwidth(&plat_priv->plat_dev->dev,
				   CNSS_BUS_WIDTH_NONE);
	cnss_pci_set_monitor_wake_intr(pci_priv, false);
	cnss_pci_set_auto_suspended(pci_priv, 0);

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

	cnss_power_off_device(plat_priv);

	clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);

	return ret;
}

static void cnss_qca6174_crash_shutdown(struct cnss_plat_data *plat_priv)
{
	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;

	if (!plat_priv->driver_ops)
		return;

	plat_priv->driver_ops->crash_shutdown(pci_priv->pci_dev);
}

static int cnss_qca6290_powerup(struct cnss_plat_data *plat_priv)
{
	int ret = 0;
	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
	unsigned int timeout;

	if (!pci_priv) {
		cnss_pr_err("pci_priv is NULL!\n");
		return -ENODEV;
	}

	if (plat_priv->ramdump_info_v2.dump_data_valid ||
	    test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
		cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_DEINIT);
		cnss_pci_clear_dump_info(pci_priv);
	}

	ret = cnss_power_on_device(plat_priv);
	if (ret) {
		cnss_pr_err("Failed to power on device, err = %d\n", ret);
		goto out;
	}

	ret = cnss_resume_pci_link(pci_priv);
	if (ret) {
		cnss_pr_err("Failed to resume PCI link, err = %d\n", ret);
		goto power_off;
	}

	timeout = cnss_get_qmi_timeout();

	ret = cnss_pci_start_mhi(pci_priv);
	if (ret) {
		cnss_pr_err("Failed to start MHI, err = %d\n", ret);
		if (!test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state) &&
		    !pci_priv->pci_link_down_ind && timeout)
			mod_timer(&plat_priv->fw_boot_timer,
				  jiffies + msecs_to_jiffies(timeout >> 1));
		return 0;
	}

	if (test_bit(USE_CORE_ONLY_FW, &quirks)) {
		clear_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state);
		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
		return 0;
	}

	cnss_set_pin_connect_status(plat_priv);

	if (qmi_bypass) {
		ret = cnss_driver_call_probe(plat_priv);
		if (ret)
			goto stop_mhi;
	} else if (timeout) {
		mod_timer(&plat_priv->fw_boot_timer,
			  jiffies + msecs_to_jiffies(timeout << 1));
	}

	return 0;

stop_mhi:
	cnss_pci_stop_mhi(pci_priv);
	cnss_suspend_pci_link(pci_priv);
power_off:
	cnss_power_off_device(plat_priv);
out:
	return ret;
}

static int cnss_qca6290_shutdown(struct cnss_plat_data *plat_priv)
{
	int ret = 0;
	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;

	if (!pci_priv)
		return -ENODEV;

	cnss_pm_request_resume(pci_priv);

	cnss_driver_call_remove(plat_priv);

	cnss_request_bus_bandwidth(&plat_priv->plat_dev->dev,
				   CNSS_BUS_WIDTH_NONE);
	cnss_pci_set_monitor_wake_intr(pci_priv, false);
	cnss_pci_set_auto_suspended(pci_priv, 0);

	cnss_pci_stop_mhi(pci_priv);

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

	cnss_power_off_device(plat_priv);

	clear_bit(CNSS_FW_READY, &plat_priv->driver_state);
	clear_bit(CNSS_FW_MEM_READY, &plat_priv->driver_state);
	clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);

	return ret;
}

static void cnss_qca6290_crash_shutdown(struct cnss_plat_data *plat_priv)
{
	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
	int ret = 0;

	cnss_pr_dbg("Crash shutdown with driver_state 0x%lx\n",
		    plat_priv->driver_state);

	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) ||
	    test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
	    test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) {
		cnss_pr_dbg("Ignore crash shutdown\n");
		return;
	}

	ret = cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RDDM_KERNEL_PANIC);
	if (ret) {
		cnss_pr_err("Fail to complete RDDM, err = %d\n", ret);
		return;
	}

	cnss_pci_collect_dump_info(pci_priv);
}

static int cnss_powerup(struct cnss_plat_data *plat_priv)
{
	int ret;

	switch (plat_priv->device_id) {
	case QCA6174_DEVICE_ID:
		ret = cnss_qca6174_powerup(plat_priv);
		break;
	case QCA6290_EMULATION_DEVICE_ID:
	case QCA6290_DEVICE_ID:
		ret = cnss_qca6290_powerup(plat_priv);
		break;
	default:
		cnss_pr_err("Unknown device_id found: 0x%lx\n",
			    plat_priv->device_id);
		ret = -ENODEV;
	}

	return ret;
}

static int cnss_shutdown(struct cnss_plat_data *plat_priv)
{
	int ret;

	switch (plat_priv->device_id) {
	case QCA6174_DEVICE_ID:
		ret = cnss_qca6174_shutdown(plat_priv);
		break;
	case QCA6290_EMULATION_DEVICE_ID:
	case QCA6290_DEVICE_ID:
		ret = cnss_qca6290_shutdown(plat_priv);
		break;
	default:
		cnss_pr_err("Unknown device_id found: 0x%lx\n",
			    plat_priv->device_id);
		ret = -ENODEV;
	}

	return ret;
}

static int cnss_subsys_powerup(const struct subsys_desc *subsys_desc)
{
	struct cnss_plat_data *plat_priv;
@@ -1215,7 +826,7 @@ static int cnss_subsys_powerup(const struct subsys_desc *subsys_desc)
		return 0;
	}

	return cnss_powerup(plat_priv);
	return cnss_bus_dev_powerup(plat_priv);
}

static int cnss_subsys_shutdown(const struct subsys_desc *subsys_desc,
@@ -1239,68 +850,12 @@ static int cnss_subsys_shutdown(const struct subsys_desc *subsys_desc,
		return 0;
	}

	return cnss_shutdown(plat_priv);
}

static int cnss_qca6290_ramdump(struct cnss_plat_data *plat_priv)
{
	struct cnss_ramdump_info_v2 *info_v2 = &plat_priv->ramdump_info_v2;
	struct cnss_dump_data *dump_data = &info_v2->dump_data;
	struct cnss_dump_seg *dump_seg = info_v2->dump_data_vaddr;
	struct ramdump_segment *ramdump_segs, *s;
	int i, ret = 0;

	if (!info_v2->dump_data_valid ||
	    dump_data->nentries == 0)
		return 0;

	ramdump_segs = kcalloc(dump_data->nentries,
			       sizeof(*ramdump_segs),
			       GFP_KERNEL);
	if (!ramdump_segs)
		return -ENOMEM;

	s = ramdump_segs;
	for (i = 0; i < dump_data->nentries; i++) {
		s->address = dump_seg->address;
		s->v_address = dump_seg->v_address;
		s->size = dump_seg->size;
		s++;
		dump_seg++;
	}

	ret = do_elf_ramdump(info_v2->ramdump_dev, ramdump_segs,
			     dump_data->nentries);
	kfree(ramdump_segs);

	cnss_pci_set_mhi_state(plat_priv->bus_priv, CNSS_MHI_DEINIT);
	cnss_pci_clear_dump_info(plat_priv->bus_priv);

	return ret;
}

static int cnss_qca6174_ramdump(struct cnss_plat_data *plat_priv)
{
	int ret = 0;
	struct cnss_ramdump_info *ramdump_info;
	struct ramdump_segment segment;

	ramdump_info = &plat_priv->ramdump_info;
	if (!ramdump_info->ramdump_size)
		return -EINVAL;

	memset(&segment, 0, sizeof(segment));
	segment.v_address = ramdump_info->ramdump_va;
	segment.size = ramdump_info->ramdump_size;
	ret = do_ramdump(ramdump_info->ramdump_dev, &segment, 1);

	return ret;
	return cnss_bus_dev_shutdown(plat_priv);
}

static int cnss_subsys_ramdump(int enable,
			       const struct subsys_desc *subsys_desc)
{
	int ret = 0;
	struct cnss_plat_data *plat_priv = dev_get_drvdata(subsys_desc->dev);

	if (!plat_priv) {
@@ -1311,21 +866,7 @@ static int cnss_subsys_ramdump(int enable,
	if (!enable)
		return 0;

	switch (plat_priv->device_id) {
	case QCA6174_DEVICE_ID:
		ret = cnss_qca6174_ramdump(plat_priv);
		break;
	case QCA6290_EMULATION_DEVICE_ID:
	case QCA6290_DEVICE_ID:
		ret = cnss_qca6290_ramdump(plat_priv);
		break;
	default:
		cnss_pr_err("Unknown device_id found: 0x%lx\n",
			    plat_priv->device_id);
		ret = -ENODEV;
	}

	return ret;
	return cnss_bus_dev_ramdump(plat_priv);
}

void *cnss_get_virt_ramdump_mem(struct device *dev, unsigned long *size)
@@ -1368,19 +909,7 @@ static void cnss_subsys_crash_shutdown(const struct subsys_desc *subsys_desc)
		cnss_pr_err("plat_priv is NULL!\n");
		return;
	}

	switch (plat_priv->device_id) {
	case QCA6174_DEVICE_ID:
		cnss_qca6174_crash_shutdown(plat_priv);
		break;
	case QCA6290_EMULATION_DEVICE_ID:
	case QCA6290_DEVICE_ID:
		cnss_qca6290_crash_shutdown(plat_priv);
		break;
	default:
		cnss_pr_err("Unknown device_id found: 0x%lx\n",
			    plat_priv->device_id);
	}
	cnss_bus_dev_crash_shutdown(plat_priv);
}

static const char *cnss_recovery_reason_to_str(enum cnss_recovery_reason reason)
@@ -1402,20 +931,15 @@ static const char *cnss_recovery_reason_to_str(enum cnss_recovery_reason reason)
static int cnss_do_recovery(struct cnss_plat_data *plat_priv,
			    enum cnss_recovery_reason reason)
{
	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
	struct cnss_subsys_info *subsys_info =
		&plat_priv->subsys_info;
	int ret = 0;

	plat_priv->recovery_count++;

	if (plat_priv->device_id == QCA6174_DEVICE_ID)
		goto self_recovery;

	if (plat_priv->driver_ops &&
	    test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state))
		plat_priv->driver_ops->update_status(pci_priv->pci_dev,
						     CNSS_RECOVERY);
	cnss_bus_recovery_update_status(plat_priv);

	if (test_bit(SKIP_RECOVERY, &quirks)) {
		cnss_pr_dbg("Skip device recovery\n");
@@ -1429,11 +953,6 @@ static int cnss_do_recovery(struct cnss_plat_data *plat_priv,
		break;
	case CNSS_REASON_RDDM:
		clear_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
		ret = cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RDDM);
		if (ret) {
			cnss_pr_err("Failed to complete RDDM, err = %d\n", ret);
			break;
		}
		cnss_bus_collect_dump_info(plat_priv);
		break;
	case CNSS_REASON_DEFAULT:
@@ -1454,8 +973,8 @@ static int cnss_do_recovery(struct cnss_plat_data *plat_priv,
	return 0;

self_recovery:
	cnss_shutdown(plat_priv);
	cnss_powerup(plat_priv);
	cnss_bus_dev_shutdown(plat_priv);
	cnss_bus_dev_powerup(plat_priv);

	return 0;
}
@@ -1568,38 +1087,12 @@ int cnss_force_fw_assert(struct device *dev)
}
EXPORT_SYMBOL(cnss_force_fw_assert);

static int cnss_register_driver_hdlr(struct cnss_plat_data *plat_priv,
				     void *data)
{
	int ret = 0;

	set_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
	plat_priv->driver_ops = data;

	ret = cnss_powerup(plat_priv);
	if (ret) {
		clear_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
		plat_priv->driver_ops = NULL;
	}

	return ret;
}

static int cnss_unregister_driver_hdlr(struct cnss_plat_data *plat_priv)
{
	set_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
	cnss_shutdown(plat_priv);
	plat_priv->driver_ops = NULL;

	return 0;
}

static int cnss_cold_boot_cal_start_hdlr(struct cnss_plat_data *plat_priv)
{
	int ret = 0;

	set_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
	ret = cnss_powerup(plat_priv);
	ret = cnss_bus_dev_powerup(plat_priv);
	if (ret)
		clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);

@@ -1610,7 +1103,7 @@ static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv)
{
	plat_priv->cal_done = true;
	cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_OFF_V01);
	cnss_shutdown(plat_priv);
	cnss_bus_dev_shutdown(plat_priv);
	clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);

	return 0;
@@ -1618,12 +1111,12 @@ static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv)

static int cnss_power_up_hdlr(struct cnss_plat_data *plat_priv)
{
	return cnss_powerup(plat_priv);
	return cnss_bus_dev_powerup(plat_priv);
}

static int cnss_power_down_hdlr(struct cnss_plat_data *plat_priv)
{
	cnss_shutdown(plat_priv);
	cnss_bus_dev_shutdown(plat_priv);

	return 0;
}
@@ -1682,11 +1175,11 @@ static void cnss_driver_event_work(struct work_struct *work)
			ret = cnss_cold_boot_cal_done_hdlr(plat_priv);
			break;
		case CNSS_DRIVER_EVENT_REGISTER_DRIVER:
			ret = cnss_register_driver_hdlr(plat_priv,
			ret = cnss_bus_register_driver_hdlr(plat_priv,
							    event->data);
			break;
		case CNSS_DRIVER_EVENT_UNREGISTER_DRIVER:
			ret = cnss_unregister_driver_hdlr(plat_priv);
			ret = cnss_bus_unregister_driver_hdlr(plat_priv);
			break;
		case CNSS_DRIVER_EVENT_RECOVERY:
			ret = cnss_driver_recovery_hdlr(plat_priv,
+10 −4
Original line number Diff line number Diff line
@@ -164,6 +164,13 @@ struct cnss_pin_connect_result {
	u32 host_pin_result;
};

enum cnss_debug_quirks {
	LINK_DOWN_SELF_RECOVERY,
	SKIP_DEVICE_BOOT,
	USE_CORE_ONLY_FW,
	SKIP_RECOVERY,
};

struct cnss_plat_data {
	struct platform_device *plat_dev;
	void *bus_priv;
@@ -179,7 +186,6 @@ struct cnss_plat_data {
	struct cnss_platform_cap cap;
	struct pm_qos_request qos_request;
	unsigned long device_id;
	struct cnss_wlan_driver *driver_ops;
	enum cnss_driver_status driver_status;
	u32 recovery_count;
	unsigned long driver_state;
@@ -210,8 +216,8 @@ struct cnss_plat_data {
	bool cal_done;
};

void *cnss_bus_dev_to_bus_priv(struct device *dev);
struct cnss_plat_data *cnss_bus_dev_to_plat_priv(struct device *dev);
struct cnss_plat_data *cnss_get_plat_priv(struct platform_device *plat_dev);
unsigned long *cnss_get_debug_quirks(void);
int cnss_driver_event_post(struct cnss_plat_data *plat_priv,
			   enum cnss_driver_event_type type,
			   u32 flags, void *data);
@@ -238,5 +244,5 @@ int cnss_register_ramdump(struct cnss_plat_data *plat_priv);
void cnss_unregister_ramdump(struct cnss_plat_data *plat_priv);
void cnss_set_pin_connect_status(struct cnss_plat_data *plat_priv);
u32 cnss_get_wake_msi(struct cnss_plat_data *plat_priv);

bool *cnss_get_qmi_bypass(void);
#endif /* _CNSS_MAIN_H */
+542 −9

File changed.

Preview size limit exceeded, changes collapsed.

Loading