aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2015-03-06 11:37:43 -0500
committerJason Cooper <jason@lakedaemon.net>2015-03-08 00:33:00 -0500
commit3e39e8f56c1c67cdd1e8f06da0d6b7c831818c76 (patch)
treeb7332e00d00a4e1f1a13b01b8da7237b644e5eb0
parente8137f4f5088d763ced1db82d3974336b76e1bd2 (diff)
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: Will Deacon <will.deacon@arm.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Link: https://lkml.kernel.org/r/1425659870-11832-5-git-send-email-marc.zyngier@arm.com Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 46b9441b36bd..6850141d6524 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -416,13 +416,14 @@ static void its_send_single_command(struct its_node *its,
416{ 416{
417 struct its_cmd_block *cmd, *sync_cmd, *next_cmd; 417 struct its_cmd_block *cmd, *sync_cmd, *next_cmd;
418 struct its_collection *sync_col; 418 struct its_collection *sync_col;
419 unsigned long flags;
419 420
420 raw_spin_lock(&its->lock); 421 raw_spin_lock_irqsave(&its->lock, flags);
421 422
422 cmd = its_allocate_entry(its); 423 cmd = its_allocate_entry(its);
423 if (!cmd) { /* We're soooooo screewed... */ 424 if (!cmd) { /* We're soooooo screewed... */
424 pr_err_ratelimited("ITS can't allocate, dropping command\n"); 425 pr_err_ratelimited("ITS can't allocate, dropping command\n");
425 raw_spin_unlock(&its->lock); 426 raw_spin_unlock_irqrestore(&its->lock, flags);
426 return; 427 return;
427 } 428 }
428 sync_col = builder(cmd, desc); 429 sync_col = builder(cmd, desc);
@@ -442,7 +443,7 @@ static void its_send_single_command(struct its_node *its,
442 443
443post: 444post:
444 next_cmd = its_post_commands(its); 445 next_cmd = its_post_commands(its);
445 raw_spin_unlock(&its->lock); 446 raw_spin_unlock_irqrestore(&its->lock, flags);
446 447
447 its_wait_for_range_completion(its, cmd, next_cmd); 448 its_wait_for_range_completion(its, cmd, next_cmd);
448} 449}
@@ -1037,8 +1038,9 @@ static void its_cpu_init_collection(void)
1037static struct its_device *its_find_device(struct its_node *its, u32 dev_id) 1038static struct its_device *its_find_device(struct its_node *its, u32 dev_id)
1038{ 1039{
1039 struct its_device *its_dev = NULL, *tmp; 1040 struct its_device *its_dev = NULL, *tmp;
1041 unsigned long flags;
1040 1042
1041 raw_spin_lock(&its->lock); 1043 raw_spin_lock_irqsave(&its->lock, flags);
1042 1044
1043 list_for_each_entry(tmp, &its->its_device_list, entry) { 1045 list_for_each_entry(tmp, &its->its_device_list, entry) {
1044 if (tmp->device_id == dev_id) { 1046 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 } 1049 }
1048 } 1050 }
1049 1051
1050 raw_spin_unlock(&its->lock); 1052 raw_spin_unlock_irqrestore(&its->lock, flags);
1051 1053
1052 return its_dev; 1054 return its_dev;
1053} 1055}
@@ -1057,6 +1059,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
1057{ 1059{
1058 struct its_device *dev; 1060 struct its_device *dev;
1059 unsigned long *lpi_map; 1061 unsigned long *lpi_map;
1062 unsigned long flags;
1060 void *itt; 1063 void *itt;
1061 int lpi_base; 1064 int lpi_base;
1062 int nr_lpis; 1065 int nr_lpis;
@@ -1092,9 +1095,9 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
1092 dev->device_id = dev_id; 1095 dev->device_id = dev_id;
1093 INIT_LIST_HEAD(&dev->entry); 1096 INIT_LIST_HEAD(&dev->entry);
1094 1097
1095 raw_spin_lock(&its->lock); 1098 raw_spin_lock_irqsave(&its->lock, flags);
1096 list_add(&dev->entry, &its->its_device_list); 1099 list_add(&dev->entry, &its->its_device_list);
1097 raw_spin_unlock(&its->lock); 1100 raw_spin_unlock_irqrestore(&its->lock, flags);
1098 1101
1099 /* Bind the device to the first possible CPU */ 1102 /* Bind the device to the first possible CPU */
1100 cpu = cpumask_first(cpu_online_mask); 1103 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 1111
1109static void its_free_device(struct its_device *its_dev) 1112static void its_free_device(struct its_device *its_dev)
1110{ 1113{
1111 raw_spin_lock(&its_dev->its->lock); 1114 unsigned long flags;
1115
1116 raw_spin_lock_irqsave(&its_dev->its->lock, flags);
1112 list_del(&its_dev->entry); 1117 list_del(&its_dev->entry);
1113 raw_spin_unlock(&its_dev->its->lock); 1118 raw_spin_unlock_irqrestore(&its_dev->its->lock, flags);
1114 kfree(its_dev->itt); 1119 kfree(its_dev->itt);
1115 kfree(its_dev); 1120 kfree(its_dev);
1116} 1121}