diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c index 11f68c9210c5d8c854adf3ce1a48328570e90301..79a6acb951fe298d8ecdebd915a21b3ca79f8fe2 100644 --- a/drivers/hwtracing/coresight/coresight-platform.c +++ b/drivers/hwtracing/coresight/coresight-platform.c @@ -518,19 +518,18 @@ static inline bool acpi_validate_dsd_graph(const union acpi_object *graph) /* acpi_get_dsd_graph - Find the _DSD Graph property for the given device. */ static const union acpi_object * -acpi_get_dsd_graph(struct acpi_device *adev) +acpi_get_dsd_graph(struct acpi_device *adev, struct acpi_buffer *buf) { int i; - struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; acpi_status status; const union acpi_object *dsd; status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, - &buf, ACPI_TYPE_PACKAGE); + buf, ACPI_TYPE_PACKAGE); if (ACPI_FAILURE(status)) return NULL; - dsd = buf.pointer; + dsd = buf->pointer; /* * _DSD property consists tuples { Prop_UUID, Package() } @@ -581,12 +580,12 @@ acpi_validate_coresight_graph(const union acpi_object *cs_graph) * returns NULL. */ static const union acpi_object * -acpi_get_coresight_graph(struct acpi_device *adev) +acpi_get_coresight_graph(struct acpi_device *adev, struct acpi_buffer *buf) { const union acpi_object *graph_list, *graph; int i, nr_graphs; - graph_list = acpi_get_dsd_graph(adev); + graph_list = acpi_get_dsd_graph(adev, buf); if (!graph_list) return graph_list; @@ -686,22 +685,24 @@ static int acpi_coresight_parse_link(struct acpi_device *adev, static int acpi_coresight_parse_graph(struct acpi_device *adev, struct coresight_platform_data *pdata) { + int ret = 0; int rc, i, nlinks; const union acpi_object *graph; struct coresight_connection *conns, *ptr; + struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; pdata->nr_inport = pdata->nr_outport = 0; - graph = acpi_get_coresight_graph(adev); + graph = acpi_get_coresight_graph(adev, &buf); /* * There are no graph connections, which is fine for some components. * e.g., ETE */ if (!graph) - return 0; + goto free; nlinks = graph->package.elements[2].integer.value; if (!nlinks) - return 0; + goto free; /* * To avoid scanning the table twice (once for finding the number of @@ -710,16 +711,20 @@ static int acpi_coresight_parse_graph(struct acpi_device *adev, * it to the pdata. */ conns = devm_kcalloc(&adev->dev, nlinks, sizeof(*conns), GFP_KERNEL); - if (!conns) - return -ENOMEM; + if (!conns) { + ret = -ENOMEM; + goto free; + } ptr = conns; for (i = 0; i < nlinks; i++) { const union acpi_object *link = &graph->package.elements[3 + i]; int dir; dir = acpi_coresight_parse_link(adev, link, ptr); - if (dir < 0) - return dir; + if (dir < 0) { + ret = dir; + goto free; + } if (dir == ACPI_CORESIGHT_LINK_MASTER) { if (ptr->outport >= pdata->nr_outport) @@ -740,8 +745,10 @@ static int acpi_coresight_parse_graph(struct acpi_device *adev, } rc = coresight_alloc_conns(&adev->dev, pdata); - if (rc) - return rc; + if (rc) { + ret = rc; + goto free; + } /* Copy the connection information to the final location */ for (i = 0; conns + i < ptr; i++) { @@ -753,7 +760,14 @@ static int acpi_coresight_parse_graph(struct acpi_device *adev, } devm_kfree(&adev->dev, conns); - return 0; +free: + /* + * When ACPI fails to alloc a buffer, it will free the buffer + * created via ACPI_ALLOCATE_BUFFER and set to NULL. + * ACPI_FREE can handle NULL pointers, so free it directly. + */ + ACPI_FREE(buf.pointer); + return ret; } /* diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index c631b16d367d500c7f14d2d59bfafc086b44b96e..5e1b56478929e3264063f1468fd1a22c208801dd 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -611,7 +611,8 @@ static int tmc_etr_alloc_flat_buf(struct tmc_drvdata *drvdata, flat_buf->vaddr = dma_alloc_noncoherent(real_dev, etr_buf->size, &flat_buf->daddr, - DMA_FROM_DEVICE, GFP_KERNEL); + DMA_FROM_DEVICE, + GFP_KERNEL | __GFP_NOWARN); if (!flat_buf->vaddr) { kfree(flat_buf); return -ENOMEM; @@ -1191,16 +1192,6 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) goto out; } - /* - * In sysFS mode we can have multiple writers per sink. Since this - * sink is already enabled no memory is needed and the HW need not be - * touched, even if the buffer size has changed. - */ - if (drvdata->mode == CS_MODE_SYSFS) { - atomic_inc(csdev->refcnt); - goto out; - } - /* * If we don't have a buffer or it doesn't match the requested size, * use the buffer allocated above. Otherwise reuse the existing buffer. @@ -1211,6 +1202,16 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) drvdata->sysfs_buf = new_buf; } + /* + * In sysFS mode we can have multiple writers per sink. Since this + * sink is already enabled no memory is needed and the HW need not be + * touched, even if the buffer size has changed. + */ + if (drvdata->mode == CS_MODE_SYSFS) { + atomic_inc(csdev->refcnt); + goto out; + } + ret = tmc_etr_enable_hw(drvdata, drvdata->sysfs_buf); if (!ret) { drvdata->mode = CS_MODE_SYSFS; diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c index 881a89e245fbbc9970d74303bc61843351d4100c..b36291ce906346176c5813e6da4743dcad249dd4 100644 --- a/drivers/hwtracing/coresight/coresight-trbe.c +++ b/drivers/hwtracing/coresight/coresight-trbe.c @@ -921,6 +921,14 @@ static void arm_trbe_enable_cpu(void *info) enable_percpu_irq(drvdata->irq, IRQ_TYPE_NONE); } +static void arm_trbe_disable_cpu(void *info) +{ + struct trbe_drvdata *drvdata = info; + + disable_percpu_irq(drvdata->irq); + trbe_reset_local(); +} + static void arm_trbe_register_coresight_cpu(struct trbe_drvdata *drvdata, int cpu) { struct trbe_cpudata *cpudata = per_cpu_ptr(drvdata->cpudata, cpu); @@ -937,13 +945,16 @@ static void arm_trbe_register_coresight_cpu(struct trbe_drvdata *drvdata, int cp dev = &cpudata->drvdata->pdev->dev; desc.name = devm_kasprintf(dev, GFP_KERNEL, "trbe%d", cpu); - if (IS_ERR(desc.name)) + if (!desc.name) + goto cpu_clear; + + desc.pdata = coresight_get_platform_data(dev); + if (IS_ERR(desc.pdata)) goto cpu_clear; desc.type = CORESIGHT_DEV_TYPE_SINK; desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_PERCPU_SYSMEM; desc.ops = &arm_trbe_cs_ops; - desc.pdata = dev_get_platdata(dev); desc.groups = arm_trbe_groups; desc.dev = dev; trbe_csdev = coresight_register(&desc); @@ -993,18 +1004,12 @@ static void arm_trbe_probe_cpu(void *info) cpumask_clear_cpu(cpu, &drvdata->supported_cpus); } -static void arm_trbe_remove_coresight_cpu(void *info) +static void arm_trbe_remove_coresight_cpu(struct trbe_drvdata *drvdata, int cpu) { - int cpu = smp_processor_id(); - struct trbe_drvdata *drvdata = info; - struct trbe_cpudata *cpudata = per_cpu_ptr(drvdata->cpudata, cpu); struct coresight_device *trbe_csdev = coresight_get_percpu_sink(cpu); - disable_percpu_irq(drvdata->irq); - trbe_reset_local(); if (trbe_csdev) { coresight_unregister(trbe_csdev); - cpudata->drvdata = NULL; coresight_set_percpu_sink(cpu, NULL); } } @@ -1033,8 +1038,10 @@ static int arm_trbe_remove_coresight(struct trbe_drvdata *drvdata) { int cpu; - for_each_cpu(cpu, &drvdata->supported_cpus) - smp_call_function_single(cpu, arm_trbe_remove_coresight_cpu, drvdata, 1); + for_each_cpu(cpu, &drvdata->supported_cpus) { + smp_call_function_single(cpu, arm_trbe_disable_cpu, drvdata, 1); + arm_trbe_remove_coresight_cpu(drvdata, cpu); + } free_percpu(drvdata->cpudata); return 0; } @@ -1066,10 +1073,8 @@ static int arm_trbe_cpu_teardown(unsigned int cpu, struct hlist_node *node) { struct trbe_drvdata *drvdata = hlist_entry_safe(node, struct trbe_drvdata, hotplug_node); - if (cpumask_test_cpu(cpu, &drvdata->supported_cpus)) { - disable_percpu_irq(drvdata->irq); - trbe_reset_local(); - } + if (cpumask_test_cpu(cpu, &drvdata->supported_cpus)) + arm_trbe_disable_cpu(drvdata); return 0; } @@ -1137,7 +1142,6 @@ static void arm_trbe_remove_irq(struct trbe_drvdata *drvdata) static int arm_trbe_device_probe(struct platform_device *pdev) { - struct coresight_platform_data *pdata; struct trbe_drvdata *drvdata; struct device *dev = &pdev->dev; int ret; @@ -1146,12 +1150,7 @@ static int arm_trbe_device_probe(struct platform_device *pdev) if (!drvdata) return -ENOMEM; - pdata = coresight_get_platform_data(dev); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - dev_set_drvdata(dev, drvdata); - dev->platform_data = pdata; drvdata->pdev = pdev; ret = arm_trbe_probe_irq(pdev, drvdata); if (ret)