drivers: edac: Update banks for edac sysfs entry

Pass the number of banks and bank name to edac framework to have sysfs
nodes created for each llcc bank for reading out the ce/ue error counts.
Add edac device before registering for interrupt, as the interrupt
handler uses edac device for interrupt processing and would result into
crash if there is any ecc error immidiately after registering the interrupt
and before adding the edac device.

Change-Id: I2c36458684feaf68a63203f871df91f862354e6a
Signed-off-by: Channagoud Kadabi <ckadabi@codeaurora.org>
diff --git a/drivers/edac/qcom_llcc_edac.c b/drivers/edac/qcom_llcc_edac.c
index a8ec359..4b89cbf 100644
--- a/drivers/edac/qcom_llcc_edac.c
+++ b/drivers/edac/qcom_llcc_edac.c
@@ -291,7 +291,7 @@
 
 	qcom_llcc_clear_errors(err_type, drv);
 
-	errors[err_type].func(edev_ctl, 0, 0, errors[err_type].msg);
+	errors[err_type].func(edev_ctl, 0, bank, errors[err_type].msg);
 }
 
 static void qcom_llcc_check_cache_errors
@@ -353,10 +353,26 @@
 	struct erp_drvdata *drv;
 	struct edac_device_ctl_info *edev_ctl;
 	struct device *dev = &pdev->dev;
+	u32 num_banks;
+	struct regmap *llcc_map = NULL;
+
+	llcc_map = syscon_node_to_regmap(dev->parent->of_node);
+	if (IS_ERR(llcc_map)) {
+		dev_err(dev, "no regmap for syscon llcc parent\n");
+		return -ENOMEM;
+	}
+
+	/* Find the number of LLC banks supported */
+	regmap_read(llcc_map, LLCC_COMMON_STATUS0,
+		    &num_banks);
+
+	num_banks &= LLCC_LB_CNT_MASK;
+	num_banks >>= LLCC_LB_CNT_SHIFT;
 
 	/* Allocate edac control info */
 	edev_ctl = edac_device_alloc_ctl_info(sizeof(*drv), "qcom-llcc", 1,
-			NULL, 0, 1, NULL, 0, edac_device_alloc_index());
+			"bank", num_banks, 1, NULL, 0,
+			edac_device_alloc_index());
 
 	if (!edev_ctl)
 		return -ENOMEM;
@@ -374,64 +390,59 @@
 	edev_ctl->panic_on_ue = LLCC_ERP_PANIC_ON_UE;
 
 	drv = edev_ctl->pvt_info;
+	drv->num_banks = num_banks;
+	drv->llcc_map = llcc_map;
 
-	drv->llcc_map = syscon_node_to_regmap(dev->parent->of_node);
-	if (IS_ERR(drv->llcc_map)) {
-		dev_err(dev, "no regmap for syscon llcc parent\n");
-		rc = -ENOMEM;
-		goto out;
-	}
+	rc = edac_device_add_device(edev_ctl);
+	if (rc)
+		goto out_mem;
 
 	if (interrupt_mode) {
 		drv->ecc_irq = platform_get_irq_byname(pdev, "ecc_irq");
 		if (!drv->ecc_irq) {
 			rc = -ENODEV;
-			goto out;
+			goto out_dev;
 		}
 
 		rc = devm_request_irq(dev, drv->ecc_irq, llcc_ecc_irq_handler,
 				IRQF_TRIGGER_HIGH, "llcc_ecc", edev_ctl);
 		if (rc) {
 			dev_err(dev, "failed to request ecc irq\n");
-			goto out;
+			goto out_dev;
 		}
 	}
 
-	/* Find the number of LLC banks supported */
-	regmap_read(drv->llcc_map, LLCC_COMMON_STATUS0,
-		    &drv->num_banks);
-
-	drv->num_banks &= LLCC_LB_CNT_MASK;
-	drv->num_banks >>= LLCC_LB_CNT_SHIFT;
-
 	drv->llcc_banks = devm_kzalloc(&pdev->dev,
 		sizeof(u32) * drv->num_banks, GFP_KERNEL);
 
 	if (!drv->llcc_banks) {
 		dev_err(dev, "Cannot allocate memory for llcc_banks\n");
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto out_dev;
 	}
 
 	rc = of_property_read_u32_array(dev->parent->of_node,
 			"qcom,llcc-banks-off", drv->llcc_banks, drv->num_banks);
 	if (rc) {
 		dev_err(dev, "Cannot read llcc-banks-off property\n");
-		return -EINVAL;
+		goto out_dev;
 	}
 
 	rc = of_property_read_u32(dev->parent->of_node,
 			"qcom,llcc-broadcast-off", &drv->b_off);
 	if (rc) {
 		dev_err(dev, "Cannot read llcc-broadcast-off property\n");
-		return -EINVAL;
+		goto out_dev;
 	}
 
 	platform_set_drvdata(pdev, edev_ctl);
 
-	rc = edac_device_add_device(edev_ctl);
-out:
-	if (rc)
-		edac_device_free_ctl_info(edev_ctl);
+	return 0;
+
+out_dev:
+	edac_device_del_device(edev_ctl->dev);
+out_mem:
+	edac_device_free_ctl_info(edev_ctl);
 
 	return rc;
 }