From e2eff914bcd6b7f9773054a8a30b15b95c2e33bb Mon Sep 17 00:00:00 2001 From: Yu Ouyang Date: Wed, 3 Apr 2024 14:52:25 +0800 Subject: [PATCH] cnss2: Avoid to call NULL plat_env For dual chip solution, first chip may fail to probe because of pcie driver is not ready. During second chip probing, first chip may retry to probe. So, second chip may set/get plat_env[0], first chip may set/get plat_env[1]. If sencond chip not attached, plat_env[0] will be cleaned. When cnss_pci_probe() is called by first chip, cnss_get_plat_priv_by_rc_num() will call plat_env[0]. However it is already NULL. Change-Id: Ib959b1a524bf777fc6a826b2771611cb28b8cb99 CRs-Fixed: 3778085 --- cnss2/main.c | 60 ++++++++++++++++++++++++++++++++++++++-------------- cnss2/main.h | 2 +- cnss2/pci.c | 2 +- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/cnss2/main.c b/cnss2/main.c index 15f766df99..bcb9397494 100644 --- a/cnss2/main.c +++ b/cnss2/main.c @@ -99,7 +99,7 @@ enum cnss_recovery_type { #ifdef CONFIG_CNSS_SUPPORT_DUAL_DEV #define CNSS_MAX_DEV_NUM 2 static struct cnss_plat_data *plat_env[CNSS_MAX_DEV_NUM]; -static int plat_env_count; +static atomic_t plat_env_count; #else static struct cnss_plat_data *plat_env; #endif @@ -131,14 +131,41 @@ bool cnss_check_driver_loading_allowed(void) } #ifdef CONFIG_CNSS_SUPPORT_DUAL_DEV +static void cnss_init_plat_env_count(void) +{ + atomic_set(&plat_env_count, 0); +} + +static void cnss_inc_plat_env_count(void) +{ + atomic_inc(&plat_env_count); +} + +static void cnss_dec_plat_env_count(void) +{ + atomic_dec(&plat_env_count); +} + +static int cnss_get_plat_env_count(void) +{ + return atomic_read(&plat_env_count); +} + +int cnss_get_max_plat_env_count(void) +{ + return CNSS_MAX_DEV_NUM; +} + static void cnss_set_plat_priv(struct platform_device *plat_dev, struct cnss_plat_data *plat_priv) { - cnss_pr_dbg("Set plat_priv at %d", plat_env_count); + int env_count = cnss_get_plat_env_count(); + + cnss_pr_dbg("Set plat_priv at %d", env_count); if (plat_priv) { - plat_priv->plat_idx = plat_env_count; + plat_priv->plat_idx = env_count; plat_env[plat_priv->plat_idx] = plat_priv; - plat_env_count++; + cnss_inc_plat_env_count(); } } @@ -150,8 +177,8 @@ struct cnss_plat_data *cnss_get_plat_priv(struct platform_device if (!plat_dev) return NULL; - for (i = 0; i < plat_env_count; i++) { - if (plat_env[i]->plat_dev == plat_dev) + for (i = 0; i < CNSS_MAX_DEV_NUM; i++) { + if (plat_env[i] && plat_env[i]->plat_dev == plat_dev) return plat_env[i]; } return NULL; @@ -163,7 +190,7 @@ struct cnss_plat_data *cnss_get_first_plat_priv(struct platform_device int i; if (!plat_dev) { - for (i = 0; i < plat_env_count; i++) { + for (i = 0; i < CNSS_MAX_DEV_NUM; i++) { if (plat_env[i]) return plat_env[i]; } @@ -175,7 +202,7 @@ static void cnss_clear_plat_priv(struct cnss_plat_data *plat_priv) { cnss_pr_dbg("Clear plat_priv at %d", plat_priv->plat_idx); plat_env[plat_priv->plat_idx] = NULL; - plat_env_count--; + cnss_dec_plat_env_count(); } static int cnss_set_device_name(struct cnss_plat_data *plat_priv) @@ -189,19 +216,15 @@ static int cnss_set_device_name(struct cnss_plat_data *plat_priv) static int cnss_plat_env_available(void) { int ret = 0; + int env_count = cnss_get_plat_env_count(); - if (plat_env_count >= CNSS_MAX_DEV_NUM) { + if (env_count >= CNSS_MAX_DEV_NUM) { cnss_pr_err("ERROR: No space to store plat_priv\n"); ret = -ENOMEM; } return ret; } -int cnss_get_plat_env_count(void) -{ - return plat_env_count; -} - struct cnss_plat_data *cnss_get_plat_env(int index) { return plat_env[index]; @@ -211,8 +234,8 @@ struct cnss_plat_data *cnss_get_plat_priv_by_rc_num(int rc_num) { int i; - for (i = 0; i < plat_env_count; i++) { - if (plat_env[i]->rc_num == rc_num) + for (i = 0; i < CNSS_MAX_DEV_NUM; i++) { + if (plat_env[i] && plat_env[i]->rc_num == rc_num) return plat_env[i]; } return NULL; @@ -251,6 +274,10 @@ cnss_get_pld_bus_ops_name(struct cnss_plat_data *plat_priv) } #else +static void cnss_init_plat_env_count(void) +{ +} + static void cnss_set_plat_priv(struct platform_device *plat_dev, struct cnss_plat_data *plat_priv) { @@ -5676,6 +5703,7 @@ static int __init cnss_initialize(void) if (ret < 0) cnss_pr_err("CNSS genl init failed %d\n", ret); + cnss_init_plat_env_count(); return ret; } diff --git a/cnss2/main.h b/cnss2/main.h index 61cdb45ce0..5f11d95334 100644 --- a/cnss2/main.h +++ b/cnss2/main.h @@ -675,7 +675,7 @@ struct cnss_plat_data *cnss_get_first_plat_priv(struct platform_device *plat_dev void cnss_pm_stay_awake(struct cnss_plat_data *plat_priv); void cnss_pm_relax(struct cnss_plat_data *plat_priv); struct cnss_plat_data *cnss_get_plat_priv_by_rc_num(int rc_num); -int cnss_get_plat_env_count(void); +int cnss_get_max_plat_env_count(void); struct cnss_plat_data *cnss_get_plat_env(int index); void cnss_get_qrtr_info(struct cnss_plat_data *plat_priv); void cnss_get_sleep_clk_supported(struct cnss_plat_data *plat_priv); diff --git a/cnss2/pci.c b/cnss2/pci.c index 1380a3fe46..ea19d3c2de 100644 --- a/cnss2/pci.c +++ b/cnss2/pci.c @@ -2406,7 +2406,7 @@ static int cnss_pci_config_msi_data(struct cnss_pci_data *pci_priv) static struct cnss_plat_data * cnss_get_plat_priv_by_driver_ops(struct cnss_wlan_driver *driver_ops) { - int plat_env_count = cnss_get_plat_env_count(); + int plat_env_count = cnss_get_max_plat_env_count(); struct cnss_plat_data *plat_env; struct cnss_pci_data *pci_priv; int i = 0;