diff options
author | Peng Du <pdu@nvidia.com> | 2014-06-30 11:03:19 -0700 |
---|---|---|
committer | Mandar Padmawar <mpadmawar@nvidia.com> | 2014-07-04 06:13:58 -0700 |
commit | 8e332826d660e52478ce7c3a407d8e004448cc28 (patch) | |
tree | ec12fe2dfe1c87d77a3ef5f6e3c8b34bca70068a /arch/arm64 | |
parent | 1832058fa5aecebd18def8549526fff5233bf488 (diff) |
arm64: tegra: misc fixes to hardwood driver
* Set NS bit when kernel is non-secure
* fix potential race in late_init
* enable hotplug notifier in late_init
* set buf occupied if immediately available
* better debugging print
Change-Id: I7acd736888f05facc559c7c965e20aea6f43060c
Signed-off-by: Peng Du <pdu@nvidia.com>
Reviewed-on: http://git-master/r/432822
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Thomas Cherry <tcherry@nvidia.com>
Diffstat (limited to 'arch/arm64')
-rw-r--r-- | arch/arm64/mach-tegra/denver-hardwood.c | 125 |
1 files changed, 73 insertions, 52 deletions
diff --git a/arch/arm64/mach-tegra/denver-hardwood.c b/arch/arm64/mach-tegra/denver-hardwood.c index 923f6fd5fc33..912cfee0d2b5 100644 --- a/arch/arm64/mach-tegra/denver-hardwood.c +++ b/arch/arm64/mach-tegra/denver-hardwood.c @@ -33,6 +33,8 @@ #include <asm/cacheflush.h> +#include "common.h" /* tegra_cpu_is_secure */ + #include "denver-knobs.h" /* backdoor detection */ #include "denver-hardwood.h" @@ -50,6 +52,8 @@ #define TRACER_OSDUMP_BUFFER_CMD_DATA 101 #define HW_CMD(c, b, m) ((c) | ((b) << 8) | ((m) << 16)) +#define PHYS_NS_BIT (1ULL << 40) + struct hardwood_buf { void *va; dma_addr_t pa; @@ -81,8 +85,9 @@ static int minor_map[N_CPU] = { -1 }; static int TRACER_IRQS[] = { 48, 54 }; -static bool hardwood_init_done; static bool hardwood_supported; +static bool hardwood_init_done; +static DEFINE_MUTEX(hardwood_init_lock); /* Thread for probing buffers when some CPUs are hot-unplugged */ static struct task_struct *agent_thread; @@ -90,7 +95,7 @@ static bool agent_stopped; static void hardwood_init_agent(void); -static void hardwood_late_init(int cpu); +static void hardwood_late_init(void); static bool check_buffers(struct hardwood_device *dev, bool lock); @@ -106,9 +111,11 @@ static irqreturn_t hardwood_handler(int irq, void *dev_id) wake_up_interruptible(&dev->wait_q); DBG_PRINT("CPU%d is interrupted\n", dev->cpu); } else { - /* Some CPUs are offline, waking up agent */ - wake_up_process(agent_thread); - DBG_PRINT("Agent is interrupted\n"); + if (agent_thread->state != TASK_RUNNING) { + /* Some CPUs are offline, waking up agent */ + wake_up_process(agent_thread); + DBG_PRINT("Agent is interrupted\n"); + } } return IRQ_HANDLED; @@ -116,7 +123,6 @@ static irqreturn_t hardwood_handler(int irq, void *dev_id) static int hardwood_open(struct inode *inode, struct file *file) { - int i; int cpu; int found = 0; int minor = iminor(inode); @@ -126,6 +132,9 @@ static int hardwood_open(struct inode *inode, struct file *file) return -ENOENT; } + /* Lazy init */ + hardwood_late_init(); + for (cpu = 0; cpu < N_CPU; ++cpu) if (minor_map[cpu] == minor) { found = 1; @@ -133,13 +142,6 @@ static int hardwood_open(struct inode *inode, struct file *file) } BUG_ON(!found); - /* Initialize all CPUs at once */ - if (!hardwood_init_done) { - hardwood_init_agent(); - for (i = 0; i < N_CPU; i++) - hardwood_late_init(i); - } - file->private_data = &hardwood_devs[cpu]; return nonseekable_open(inode, file); } @@ -227,6 +229,7 @@ long hardwood_ioctl(struct file *file, unsigned int cmd, unsigned long arg) /* SW-only CMD */ case HARDWOOD_GET_PHYS_ADDR: op.data = hardwood_devs[op.core_id].bufs[op.buffer_id].pa; + op.data &= ~PHYS_NS_BIT; if (copy_to_user((void __user *)arg, &op, sizeof(op))) return -EFAULT; break; @@ -261,7 +264,8 @@ static bool is_buffer_ready(int cpu, int buf) status &= 0xff; if ((bytes_used > 0) && (status == 1)) - DBG_PRINT("buffer %d:%d is READY.", cpu, buf); + DBG_PRINT("buffer %d:%d is READY (used=%llu, status=%llu)..", + cpu, buf, bytes_used, status); else DBG_PRINT("buffer %d:%d is BUSY (used=%llu, status=%llu).", cpu, buf, bytes_used, status); @@ -336,6 +340,7 @@ ssize_t hardwood_read(struct file *file, char __user *p, size_t s, loff_t *r) if (dev->buf_status) { buf_id = find_first_bit(&dev->buf_status, sizeof(ulong)); clear_bit(buf_id, &dev->buf_status); + set_bit(buf_id, &dev->buf_occupied); } spin_unlock(&dev->buf_status_lock); @@ -412,6 +417,10 @@ static __init void init_one_buffer(int cpu, int buf_id) buf->pa = virt_to_phys(buf->va); BUG_ON(!buf->va || !buf->pa); + /* Set NS bit if kernel is non-secure */ + if (tegra_cpu_is_secure()) + buf->pa |= PHYS_NS_BIT; + /* Set buffer physical address */ trace_cmd = HW_CMD(cpu, buf_id, HARDWOOD_SET_PHYS_ADDR); hw_set_data(buf->pa); @@ -428,16 +437,60 @@ static __init void init_one_buffer(int cpu, int buf_id) *ptr++ = 0xdeadbeef; } -static void hardwood_late_init(int cpu) +static inline void hardwood_late_init(void) { - int i; - for (i = 0; i < N_BUFFER; i++) - init_one_buffer(cpu, i); - hardwood_init_done = 1; + int i, j; + + if (hardwood_init_done) + return; + + /* use mutex b/c below code might sleep */ + mutex_lock(&hardwood_init_lock); + if (!hardwood_init_done) { + hardwood_init_agent(); + + for (i = 0; i < N_CPU; i++) + for (j = 0; j < N_BUFFER; j++) + init_one_buffer(i, j); + + hardwood_init_done = 1; + } + mutex_unlock(&hardwood_init_lock); +} + +static int hardwood_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + long cpu = (long) hcpu; + long new_cpu; + + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + new_cpu = cpu; + break; + + case CPU_DEAD: + case CPU_DEAD_FROZEN: + new_cpu = cpu == 0 ? 1 : 0; + break; + + default: + return NOTIFY_OK; + } + + hw_run_cmd(HW_CMD(cpu, new_cpu, HARDWOOD_SET_IRQ_TARGET)); + + return NOTIFY_OK; } +static struct notifier_block hardwood_cpu_notifier = { + .notifier_call = hardwood_cpu_notify, +}; + static void hardwood_init_agent(void) { + register_hotcpu_notifier(&hardwood_cpu_notifier); agent_thread = kthread_create(agent_thread_fn, 0, "hardwood-agent"); } @@ -475,36 +528,6 @@ static void init_one_cpu(int cpu) spin_lock_init(&hdev->buf_status_lock); } -static int hardwood_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) -{ - long cpu = (long) hcpu; - long new_cpu; - - switch (action) { - case CPU_ONLINE: - case CPU_ONLINE_FROZEN: - new_cpu = cpu; - break; - - case CPU_DEAD: - case CPU_DEAD_FROZEN: - new_cpu = cpu == 0 ? 1 : 0; - break; - - default: - return NOTIFY_OK; - } - - hw_run_cmd(HW_CMD(cpu, new_cpu, HARDWOOD_SET_IRQ_TARGET)); - - return NOTIFY_OK; -} - -static struct notifier_block hardwood_cpu_notifier = { - .notifier_call = hardwood_cpu_notify, -}; - static __init int hardwood_init(void) { int cpu; @@ -514,11 +537,9 @@ static __init int hardwood_init(void) pr_info("Denver: hardwood is %ssupported.\n", hardwood_supported ? "" : "NOT "); - if (hardwood_supported) { + if (hardwood_supported) for (cpu = 0; cpu < N_CPU; ++cpu) init_one_cpu(cpu); - register_hotcpu_notifier(&hardwood_cpu_notifier); - } return 0; } |