Commit 3e39e8f5 authored by Marc Zyngier's avatar Marc Zyngier Committed by Jason Cooper

irqchip: gicv3-its: Fix unsafe locking reported by lockdep

When compiled with CONFIG_LOCKDEP, the kernel shouts badly, saying
that my locking is unsafe. I'm afraid the kernel is right:

       CPU0                    CPU1
       ----                    ----
  lock(&its->lock);
                               local_irq_disable();
                               lock(&irq_desc_lock_class);
                               lock(&its->lock);
  <Interrupt>
    lock(&irq_desc_lock_class);

 *** DEADLOCK ***

The fix is to always take its->lock with interrupts disabled.
Reported-by: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Link: https://lkml.kernel.org/r/1425659870-11832-5-git-send-email-marc.zyngier@arm.comSigned-off-by: default avatarJason Cooper <jason@lakedaemon.net>
parent e8137f4f
...@@ -416,13 +416,14 @@ static void its_send_single_command(struct its_node *its, ...@@ -416,13 +416,14 @@ static void its_send_single_command(struct its_node *its,
{ {
struct its_cmd_block *cmd, *sync_cmd, *next_cmd; struct its_cmd_block *cmd, *sync_cmd, *next_cmd;
struct its_collection *sync_col; struct its_collection *sync_col;
unsigned long flags;
raw_spin_lock(&its->lock); raw_spin_lock_irqsave(&its->lock, flags);
cmd = its_allocate_entry(its); cmd = its_allocate_entry(its);
if (!cmd) { /* We're soooooo screewed... */ if (!cmd) { /* We're soooooo screewed... */
pr_err_ratelimited("ITS can't allocate, dropping command\n"); pr_err_ratelimited("ITS can't allocate, dropping command\n");
raw_spin_unlock(&its->lock); raw_spin_unlock_irqrestore(&its->lock, flags);
return; return;
} }
sync_col = builder(cmd, desc); sync_col = builder(cmd, desc);
...@@ -442,7 +443,7 @@ static void its_send_single_command(struct its_node *its, ...@@ -442,7 +443,7 @@ static void its_send_single_command(struct its_node *its,
post: post:
next_cmd = its_post_commands(its); next_cmd = its_post_commands(its);
raw_spin_unlock(&its->lock); raw_spin_unlock_irqrestore(&its->lock, flags);
its_wait_for_range_completion(its, cmd, next_cmd); its_wait_for_range_completion(its, cmd, next_cmd);
} }
...@@ -1037,8 +1038,9 @@ static void its_cpu_init_collection(void) ...@@ -1037,8 +1038,9 @@ static void its_cpu_init_collection(void)
static struct its_device *its_find_device(struct its_node *its, u32 dev_id) static struct its_device *its_find_device(struct its_node *its, u32 dev_id)
{ {
struct its_device *its_dev = NULL, *tmp; struct its_device *its_dev = NULL, *tmp;
unsigned long flags;
raw_spin_lock(&its->lock); raw_spin_lock_irqsave(&its->lock, flags);
list_for_each_entry(tmp, &its->its_device_list, entry) { list_for_each_entry(tmp, &its->its_device_list, entry) {
if (tmp->device_id == dev_id) { if (tmp->device_id == dev_id) {
...@@ -1047,7 +1049,7 @@ static struct its_device *its_find_device(struct its_node *its, u32 dev_id) ...@@ -1047,7 +1049,7 @@ static struct its_device *its_find_device(struct its_node *its, u32 dev_id)
} }
} }
raw_spin_unlock(&its->lock); raw_spin_unlock_irqrestore(&its->lock, flags);
return its_dev; return its_dev;
} }
...@@ -1057,6 +1059,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, ...@@ -1057,6 +1059,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
{ {
struct its_device *dev; struct its_device *dev;
unsigned long *lpi_map; unsigned long *lpi_map;
unsigned long flags;
void *itt; void *itt;
int lpi_base; int lpi_base;
int nr_lpis; int nr_lpis;
...@@ -1092,9 +1095,9 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, ...@@ -1092,9 +1095,9 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
dev->device_id = dev_id; dev->device_id = dev_id;
INIT_LIST_HEAD(&dev->entry); INIT_LIST_HEAD(&dev->entry);
raw_spin_lock(&its->lock); raw_spin_lock_irqsave(&its->lock, flags);
list_add(&dev->entry, &its->its_device_list); list_add(&dev->entry, &its->its_device_list);
raw_spin_unlock(&its->lock); raw_spin_unlock_irqrestore(&its->lock, flags);
/* Bind the device to the first possible CPU */ /* Bind the device to the first possible CPU */
cpu = cpumask_first(cpu_online_mask); cpu = cpumask_first(cpu_online_mask);
...@@ -1108,9 +1111,11 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, ...@@ -1108,9 +1111,11 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
static void its_free_device(struct its_device *its_dev) static void its_free_device(struct its_device *its_dev)
{ {
raw_spin_lock(&its_dev->its->lock); unsigned long flags;
raw_spin_lock_irqsave(&its_dev->its->lock, flags);
list_del(&its_dev->entry); list_del(&its_dev->entry);
raw_spin_unlock(&its_dev->its->lock); raw_spin_unlock_irqrestore(&its_dev->its->lock, flags);
kfree(its_dev->itt); kfree(its_dev->itt);
kfree(its_dev); kfree(its_dev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment