Update Linux to v5.4.2
Change-Id: Idf6911045d9d382da2cfe01b1edff026404ac8fd
diff --git a/drivers/soc/qcom/llcc-slice.c b/drivers/soc/qcom/llcc-slice.c
index 54063a3..9090ea1 100644
--- a/drivers/soc/qcom/llcc-slice.c
+++ b/drivers/soc/qcom/llcc-slice.c
@@ -13,6 +13,7 @@
#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
+#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/soc/qcom/llcc-qcom.h>
@@ -45,7 +46,7 @@
#define BANK_OFFSET_STRIDE 0x80000
-static struct llcc_drv_data *drv_data;
+static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
static const struct regmap_config llcc_regmap_config = {
.reg_bits = 32,
@@ -67,6 +68,9 @@
struct llcc_slice_desc *desc;
u32 sz, count;
+ if (IS_ERR(drv_data))
+ return ERR_CAST(drv_data);
+
cfg = drv_data->cfg;
sz = drv_data->cfg_size;
@@ -94,7 +98,8 @@
*/
void llcc_slice_putd(struct llcc_slice_desc *desc)
{
- kfree(desc);
+ if (!IS_ERR_OR_NULL(desc))
+ kfree(desc);
}
EXPORT_SYMBOL_GPL(llcc_slice_putd);
@@ -106,22 +111,27 @@
u32 slice_status;
int ret;
- act_ctrl_reg = drv_data->bcast_off + LLCC_TRP_ACT_CTRLn(sid);
- status_reg = drv_data->bcast_off + LLCC_TRP_STATUSn(sid);
+ if (IS_ERR(drv_data))
+ return PTR_ERR(drv_data);
+
+ act_ctrl_reg = LLCC_TRP_ACT_CTRLn(sid);
+ status_reg = LLCC_TRP_STATUSn(sid);
/* Set the ACTIVE trigger */
act_ctrl_reg_val |= ACT_CTRL_ACT_TRIG;
- ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val);
+ ret = regmap_write(drv_data->bcast_regmap, act_ctrl_reg,
+ act_ctrl_reg_val);
if (ret)
return ret;
/* Clear the ACTIVE trigger */
act_ctrl_reg_val &= ~ACT_CTRL_ACT_TRIG;
- ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val);
+ ret = regmap_write(drv_data->bcast_regmap, act_ctrl_reg,
+ act_ctrl_reg_val);
if (ret)
return ret;
- ret = regmap_read_poll_timeout(drv_data->regmap, status_reg,
+ ret = regmap_read_poll_timeout(drv_data->bcast_regmap, status_reg,
slice_status, !(slice_status & status),
0, LLCC_STATUS_READ_DELAY);
return ret;
@@ -139,6 +149,12 @@
int ret;
u32 act_ctrl_val;
+ if (IS_ERR(drv_data))
+ return PTR_ERR(drv_data);
+
+ if (IS_ERR_OR_NULL(desc))
+ return -EINVAL;
+
mutex_lock(&drv_data->lock);
if (test_bit(desc->slice_id, drv_data->bitmap)) {
mutex_unlock(&drv_data->lock);
@@ -173,6 +189,12 @@
u32 act_ctrl_val;
int ret;
+ if (IS_ERR(drv_data))
+ return PTR_ERR(drv_data);
+
+ if (IS_ERR_OR_NULL(desc))
+ return -EINVAL;
+
mutex_lock(&drv_data->lock);
if (!test_bit(desc->slice_id, drv_data->bitmap)) {
mutex_unlock(&drv_data->lock);
@@ -200,6 +222,9 @@
*/
int llcc_get_slice_id(struct llcc_slice_desc *desc)
{
+ if (IS_ERR_OR_NULL(desc))
+ return -EINVAL;
+
return desc->slice_id;
}
EXPORT_SYMBOL_GPL(llcc_get_slice_id);
@@ -210,6 +235,9 @@
*/
size_t llcc_get_slice_size(struct llcc_slice_desc *desc)
{
+ if (IS_ERR_OR_NULL(desc))
+ return 0;
+
return desc->slice_size;
}
EXPORT_SYMBOL_GPL(llcc_get_slice_size);
@@ -223,19 +251,16 @@
u32 attr0_val;
u32 max_cap_cacheline;
u32 sz;
- int ret;
+ int ret = 0;
const struct llcc_slice_config *llcc_table;
struct llcc_slice_desc desc;
- u32 bcast_off = drv_data->bcast_off;
sz = drv_data->cfg_size;
llcc_table = drv_data->cfg;
for (i = 0; i < sz; i++) {
- attr1_cfg = bcast_off +
- LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id);
- attr0_cfg = bcast_off +
- LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id);
+ attr1_cfg = LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id);
+ attr0_cfg = LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id);
attr1_val = llcc_table[i].cache_mode;
attr1_val |= llcc_table[i].probe_target_ways <<
@@ -260,10 +285,12 @@
attr0_val = llcc_table[i].res_ways & ATTR0_RES_WAYS_MASK;
attr0_val |= llcc_table[i].bonus_ways << ATTR0_BONUS_WAYS_SHIFT;
- ret = regmap_write(drv_data->regmap, attr1_cfg, attr1_val);
+ ret = regmap_write(drv_data->bcast_regmap, attr1_cfg,
+ attr1_val);
if (ret)
return ret;
- ret = regmap_write(drv_data->regmap, attr0_cfg, attr0_val);
+ ret = regmap_write(drv_data->bcast_regmap, attr0_cfg,
+ attr0_val);
if (ret)
return ret;
if (llcc_table[i].activate_on_init) {
@@ -274,33 +301,62 @@
return ret;
}
+int qcom_llcc_remove(struct platform_device *pdev)
+{
+ /* Set the global pointer to a error code to avoid referencing it */
+ drv_data = ERR_PTR(-ENODEV);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qcom_llcc_remove);
+
+static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev,
+ const char *name)
+{
+ struct resource *res;
+ void __iomem *base;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+ if (!res)
+ return ERR_PTR(-ENODEV);
+
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return ERR_CAST(base);
+
+ return devm_regmap_init_mmio(&pdev->dev, base, &llcc_regmap_config);
+}
+
int qcom_llcc_probe(struct platform_device *pdev,
const struct llcc_slice_config *llcc_cfg, u32 sz)
{
u32 num_banks;
struct device *dev = &pdev->dev;
- struct resource *res;
- void __iomem *base;
int ret, i;
+ struct platform_device *llcc_edac;
drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
- if (!drv_data)
- return -ENOMEM;
+ if (!drv_data) {
+ ret = -ENOMEM;
+ goto err;
+ }
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(base))
- return PTR_ERR(base);
+ drv_data->regmap = qcom_llcc_init_mmio(pdev, "llcc_base");
+ if (IS_ERR(drv_data->regmap)) {
+ ret = PTR_ERR(drv_data->regmap);
+ goto err;
+ }
- drv_data->regmap = devm_regmap_init_mmio(dev, base,
- &llcc_regmap_config);
- if (IS_ERR(drv_data->regmap))
- return PTR_ERR(drv_data->regmap);
+ drv_data->bcast_regmap =
+ qcom_llcc_init_mmio(pdev, "llcc_broadcast_base");
+ if (IS_ERR(drv_data->bcast_regmap)) {
+ ret = PTR_ERR(drv_data->bcast_regmap);
+ goto err;
+ }
ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0,
&num_banks);
if (ret)
- return ret;
+ goto err;
num_banks &= LLCC_LB_CNT_MASK;
num_banks >>= LLCC_LB_CNT_SHIFT;
@@ -312,27 +368,45 @@
drv_data->offsets = devm_kcalloc(dev, num_banks, sizeof(u32),
GFP_KERNEL);
- if (!drv_data->offsets)
- return -ENOMEM;
+ if (!drv_data->offsets) {
+ ret = -ENOMEM;
+ goto err;
+ }
for (i = 0; i < num_banks; i++)
drv_data->offsets[i] = i * BANK_OFFSET_STRIDE;
- drv_data->bcast_off = num_banks * BANK_OFFSET_STRIDE;
-
drv_data->bitmap = devm_kcalloc(dev,
BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long),
GFP_KERNEL);
- if (!drv_data->bitmap)
- return -ENOMEM;
+ if (!drv_data->bitmap) {
+ ret = -ENOMEM;
+ goto err;
+ }
drv_data->cfg = llcc_cfg;
drv_data->cfg_size = sz;
mutex_init(&drv_data->lock);
platform_set_drvdata(pdev, drv_data);
- return qcom_llcc_cfg_program(pdev);
+ ret = qcom_llcc_cfg_program(pdev);
+ if (ret)
+ goto err;
+
+ drv_data->ecc_irq = platform_get_irq(pdev, 0);
+ if (drv_data->ecc_irq >= 0) {
+ llcc_edac = platform_device_register_data(&pdev->dev,
+ "qcom_llcc_edac", -1, drv_data,
+ sizeof(*drv_data));
+ if (IS_ERR(llcc_edac))
+ dev_err(dev, "Failed to register llcc edac driver\n");
+ }
+
+ return 0;
+err:
+ drv_data = ERR_PTR(-ENODEV);
+ return ret;
}
EXPORT_SYMBOL_GPL(qcom_llcc_probe);
-
MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Qualcomm Last Level Cache Controller");