瀏覽代碼

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
Yu Ouyang 1 年之前
父節點
當前提交
e2eff914bc
共有 3 個文件被更改,包括 46 次插入18 次删除
  1. 44 16
      cnss2/main.c
  2. 1 1
      cnss2/main.h
  3. 1 1
      cnss2/pci.c

+ 44 - 16
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;
 }
 

+ 1 - 1
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);

+ 1 - 1
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;