aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwtracing/coresight/coresight-etm3x.c
diff options
context:
space:
mode:
authorMathieu Poirier <mathieu.poirier@linaro.org>2016-02-17 19:51:52 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-02-20 17:11:01 -0500
commit22fd532eaa0c24d86e23d8e9e3b7feac4a8cac80 (patch)
treec979062322116b12cf155ce5e22e9c11b20cbb16 /drivers/hwtracing/coresight/coresight-etm3x.c
parent1925a470ce69cdfa2b82ac1565d58dfd39cd877d (diff)
coresight: etm3x: adding operation mode for etm_enable()
Adding a new mode to source API enable() in order to distinguish where the request comes from. That way it is possible to perform different operations based on where the request was issued from. The ETM4x driver is also modified to keep in sync with the new interface. Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hwtracing/coresight/coresight-etm3x.c')
-rw-r--r--drivers/hwtracing/coresight/coresight-etm3x.c68
1 files changed, 60 insertions, 8 deletions
diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c
index 1952dc31fee4..e16501b41ed8 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x.c
@@ -306,7 +306,7 @@ int etm_get_trace_id(struct etm_drvdata *drvdata)
306 if (!drvdata) 306 if (!drvdata)
307 goto out; 307 goto out;
308 308
309 if (!drvdata->enable) 309 if (!local_read(&drvdata->mode))
310 return drvdata->traceid; 310 return drvdata->traceid;
311 311
312 pm_runtime_get_sync(drvdata->dev); 312 pm_runtime_get_sync(drvdata->dev);
@@ -332,7 +332,7 @@ static int etm_trace_id(struct coresight_device *csdev)
332 return etm_get_trace_id(drvdata); 332 return etm_get_trace_id(drvdata);
333} 333}
334 334
335static int etm_enable(struct coresight_device *csdev) 335static int etm_enable_sysfs(struct coresight_device *csdev)
336{ 336{
337 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 337 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
338 int ret; 338 int ret;
@@ -351,18 +351,44 @@ static int etm_enable(struct coresight_device *csdev)
351 goto err; 351 goto err;
352 } 352 }
353 353
354 drvdata->enable = true;
355 drvdata->sticky_enable = true; 354 drvdata->sticky_enable = true;
356
357 spin_unlock(&drvdata->spinlock); 355 spin_unlock(&drvdata->spinlock);
358 356
359 dev_info(drvdata->dev, "ETM tracing enabled\n"); 357 dev_info(drvdata->dev, "ETM tracing enabled\n");
360 return 0; 358 return 0;
359
361err: 360err:
362 spin_unlock(&drvdata->spinlock); 361 spin_unlock(&drvdata->spinlock);
363 return ret; 362 return ret;
364} 363}
365 364
365static int etm_enable(struct coresight_device *csdev, u32 mode)
366{
367 int ret;
368 u32 val;
369 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
370
371 val = local_cmpxchg(&drvdata->mode, CS_MODE_DISABLED, mode);
372
373 /* Someone is already using the tracer */
374 if (val)
375 return -EBUSY;
376
377 switch (mode) {
378 case CS_MODE_SYSFS:
379 ret = etm_enable_sysfs(csdev);
380 break;
381 default:
382 ret = -EINVAL;
383 }
384
385 /* The tracer didn't start */
386 if (ret)
387 local_set(&drvdata->mode, CS_MODE_DISABLED);
388
389 return ret;
390}
391
366static void etm_disable_hw(void *info) 392static void etm_disable_hw(void *info)
367{ 393{
368 int i; 394 int i;
@@ -387,7 +413,7 @@ static void etm_disable_hw(void *info)
387 dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu); 413 dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
388} 414}
389 415
390static void etm_disable(struct coresight_device *csdev) 416static void etm_disable_sysfs(struct coresight_device *csdev)
391{ 417{
392 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 418 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
393 419
@@ -405,7 +431,6 @@ static void etm_disable(struct coresight_device *csdev)
405 * ensures that register writes occur when cpu is powered. 431 * ensures that register writes occur when cpu is powered.
406 */ 432 */
407 smp_call_function_single(drvdata->cpu, etm_disable_hw, drvdata, 1); 433 smp_call_function_single(drvdata->cpu, etm_disable_hw, drvdata, 1);
408 drvdata->enable = false;
409 434
410 spin_unlock(&drvdata->spinlock); 435 spin_unlock(&drvdata->spinlock);
411 put_online_cpus(); 436 put_online_cpus();
@@ -413,6 +438,33 @@ static void etm_disable(struct coresight_device *csdev)
413 dev_info(drvdata->dev, "ETM tracing disabled\n"); 438 dev_info(drvdata->dev, "ETM tracing disabled\n");
414} 439}
415 440
441static void etm_disable(struct coresight_device *csdev)
442{
443 u32 mode;
444 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
445
446 /*
447 * For as long as the tracer isn't disabled another entity can't
448 * change its status. As such we can read the status here without
449 * fearing it will change under us.
450 */
451 mode = local_read(&drvdata->mode);
452
453 switch (mode) {
454 case CS_MODE_DISABLED:
455 break;
456 case CS_MODE_SYSFS:
457 etm_disable_sysfs(csdev);
458 break;
459 default:
460 WARN_ON_ONCE(mode);
461 return;
462 }
463
464 if (mode)
465 local_set(&drvdata->mode, CS_MODE_DISABLED);
466}
467
416static const struct coresight_ops_source etm_source_ops = { 468static const struct coresight_ops_source etm_source_ops = {
417 .cpu_id = etm_cpu_id, 469 .cpu_id = etm_cpu_id,
418 .trace_id = etm_trace_id, 470 .trace_id = etm_trace_id,
@@ -440,7 +492,7 @@ static int etm_cpu_callback(struct notifier_block *nfb, unsigned long action,
440 etmdrvdata[cpu]->os_unlock = true; 492 etmdrvdata[cpu]->os_unlock = true;
441 } 493 }
442 494
443 if (etmdrvdata[cpu]->enable) 495 if (local_read(&etmdrvdata[cpu]->mode))
444 etm_enable_hw(etmdrvdata[cpu]); 496 etm_enable_hw(etmdrvdata[cpu]);
445 spin_unlock(&etmdrvdata[cpu]->spinlock); 497 spin_unlock(&etmdrvdata[cpu]->spinlock);
446 break; 498 break;
@@ -453,7 +505,7 @@ static int etm_cpu_callback(struct notifier_block *nfb, unsigned long action,
453 505
454 case CPU_DYING: 506 case CPU_DYING:
455 spin_lock(&etmdrvdata[cpu]->spinlock); 507 spin_lock(&etmdrvdata[cpu]->spinlock);
456 if (etmdrvdata[cpu]->enable) 508 if (local_read(&etmdrvdata[cpu]->mode))
457 etm_disable_hw(etmdrvdata[cpu]); 509 etm_disable_hw(etmdrvdata[cpu]);
458 spin_unlock(&etmdrvdata[cpu]->spinlock); 510 spin_unlock(&etmdrvdata[cpu]->spinlock);
459 break; 511 break;