diff options
author | Jason Cooper <jason@lakedaemon.net> | 2015-03-14 21:41:26 -0400 |
---|---|---|
committer | Jason Cooper <jason@lakedaemon.net> | 2015-03-14 21:41:26 -0400 |
commit | aaa95f74563a1c5a42db5fec43415b9a92ea7f7b (patch) | |
tree | 319e8916182a2cab4fa649213ab8b1b1b9d4d2f6 | |
parent | 5724be8464dceac047c1eaddaa3651cea0ec16ca (diff) | |
parent | 4559fbb3a9b1bde46afc739fa6c300826acdc19c (diff) |
Merge branch 'irqchip/urgent-gic' into irqchip/urgent
-rw-r--r-- | drivers/irqchip/irq-gic-v3-its.c | 157 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 2 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic.c | 20 | ||||
-rw-r--r-- | include/linux/irqchip/arm-gic-v3.h | 5 |
4 files changed, 146 insertions, 38 deletions
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index d8996bdf0f61..596b0a9eee99 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 | ||
443 | post: | 444 | post: |
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 | } |
@@ -799,21 +800,43 @@ static int its_alloc_tables(struct its_node *its) | |||
799 | { | 800 | { |
800 | int err; | 801 | int err; |
801 | int i; | 802 | int i; |
802 | int psz = PAGE_SIZE; | 803 | int psz = SZ_64K; |
803 | u64 shr = GITS_BASER_InnerShareable; | 804 | u64 shr = GITS_BASER_InnerShareable; |
804 | 805 | ||
805 | for (i = 0; i < GITS_BASER_NR_REGS; i++) { | 806 | for (i = 0; i < GITS_BASER_NR_REGS; i++) { |
806 | u64 val = readq_relaxed(its->base + GITS_BASER + i * 8); | 807 | u64 val = readq_relaxed(its->base + GITS_BASER + i * 8); |
807 | u64 type = GITS_BASER_TYPE(val); | 808 | u64 type = GITS_BASER_TYPE(val); |
808 | u64 entry_size = GITS_BASER_ENTRY_SIZE(val); | 809 | u64 entry_size = GITS_BASER_ENTRY_SIZE(val); |
810 | int order = get_order(psz); | ||
811 | int alloc_size; | ||
809 | u64 tmp; | 812 | u64 tmp; |
810 | void *base; | 813 | void *base; |
811 | 814 | ||
812 | if (type == GITS_BASER_TYPE_NONE) | 815 | if (type == GITS_BASER_TYPE_NONE) |
813 | continue; | 816 | continue; |
814 | 817 | ||
815 | /* We're lazy and only allocate a single page for now */ | 818 | /* |
816 | base = (void *)get_zeroed_page(GFP_KERNEL); | 819 | * Allocate as many entries as required to fit the |
820 | * range of device IDs that the ITS can grok... The ID | ||
821 | * space being incredibly sparse, this results in a | ||
822 | * massive waste of memory. | ||
823 | * | ||
824 | * For other tables, only allocate a single page. | ||
825 | */ | ||
826 | if (type == GITS_BASER_TYPE_DEVICE) { | ||
827 | u64 typer = readq_relaxed(its->base + GITS_TYPER); | ||
828 | u32 ids = GITS_TYPER_DEVBITS(typer); | ||
829 | |||
830 | order = get_order((1UL << ids) * entry_size); | ||
831 | if (order >= MAX_ORDER) { | ||
832 | order = MAX_ORDER - 1; | ||
833 | pr_warn("%s: Device Table too large, reduce its page order to %u\n", | ||
834 | its->msi_chip.of_node->full_name, order); | ||
835 | } | ||
836 | } | ||
837 | |||
838 | alloc_size = (1 << order) * PAGE_SIZE; | ||
839 | base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order); | ||
817 | if (!base) { | 840 | if (!base) { |
818 | err = -ENOMEM; | 841 | err = -ENOMEM; |
819 | goto out_free; | 842 | goto out_free; |
@@ -841,7 +864,7 @@ retry_baser: | |||
841 | break; | 864 | break; |
842 | } | 865 | } |
843 | 866 | ||
844 | val |= (PAGE_SIZE / psz) - 1; | 867 | val |= (alloc_size / psz) - 1; |
845 | 868 | ||
846 | writeq_relaxed(val, its->base + GITS_BASER + i * 8); | 869 | writeq_relaxed(val, its->base + GITS_BASER + i * 8); |
847 | tmp = readq_relaxed(its->base + GITS_BASER + i * 8); | 870 | tmp = readq_relaxed(its->base + GITS_BASER + i * 8); |
@@ -882,7 +905,7 @@ retry_baser: | |||
882 | } | 905 | } |
883 | 906 | ||
884 | pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n", | 907 | pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n", |
885 | (int)(PAGE_SIZE / entry_size), | 908 | (int)(alloc_size / entry_size), |
886 | its_base_type_string[type], | 909 | its_base_type_string[type], |
887 | (unsigned long)virt_to_phys(base), | 910 | (unsigned long)virt_to_phys(base), |
888 | psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT); | 911 | psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT); |
@@ -1020,8 +1043,9 @@ static void its_cpu_init_collection(void) | |||
1020 | static struct its_device *its_find_device(struct its_node *its, u32 dev_id) | 1043 | static struct its_device *its_find_device(struct its_node *its, u32 dev_id) |
1021 | { | 1044 | { |
1022 | struct its_device *its_dev = NULL, *tmp; | 1045 | struct its_device *its_dev = NULL, *tmp; |
1046 | unsigned long flags; | ||
1023 | 1047 | ||
1024 | raw_spin_lock(&its->lock); | 1048 | raw_spin_lock_irqsave(&its->lock, flags); |
1025 | 1049 | ||
1026 | list_for_each_entry(tmp, &its->its_device_list, entry) { | 1050 | list_for_each_entry(tmp, &its->its_device_list, entry) { |
1027 | if (tmp->device_id == dev_id) { | 1051 | if (tmp->device_id == dev_id) { |
@@ -1030,7 +1054,7 @@ static struct its_device *its_find_device(struct its_node *its, u32 dev_id) | |||
1030 | } | 1054 | } |
1031 | } | 1055 | } |
1032 | 1056 | ||
1033 | raw_spin_unlock(&its->lock); | 1057 | raw_spin_unlock_irqrestore(&its->lock, flags); |
1034 | 1058 | ||
1035 | return its_dev; | 1059 | return its_dev; |
1036 | } | 1060 | } |
@@ -1040,6 +1064,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, | |||
1040 | { | 1064 | { |
1041 | struct its_device *dev; | 1065 | struct its_device *dev; |
1042 | unsigned long *lpi_map; | 1066 | unsigned long *lpi_map; |
1067 | unsigned long flags; | ||
1043 | void *itt; | 1068 | void *itt; |
1044 | int lpi_base; | 1069 | int lpi_base; |
1045 | int nr_lpis; | 1070 | int nr_lpis; |
@@ -1056,7 +1081,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, | |||
1056 | nr_ites = max(2UL, roundup_pow_of_two(nvecs)); | 1081 | nr_ites = max(2UL, roundup_pow_of_two(nvecs)); |
1057 | sz = nr_ites * its->ite_size; | 1082 | sz = nr_ites * its->ite_size; |
1058 | sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1; | 1083 | sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1; |
1059 | itt = kmalloc(sz, GFP_KERNEL); | 1084 | itt = kzalloc(sz, GFP_KERNEL); |
1060 | lpi_map = its_lpi_alloc_chunks(nvecs, &lpi_base, &nr_lpis); | 1085 | lpi_map = its_lpi_alloc_chunks(nvecs, &lpi_base, &nr_lpis); |
1061 | 1086 | ||
1062 | if (!dev || !itt || !lpi_map) { | 1087 | if (!dev || !itt || !lpi_map) { |
@@ -1075,9 +1100,9 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, | |||
1075 | dev->device_id = dev_id; | 1100 | dev->device_id = dev_id; |
1076 | INIT_LIST_HEAD(&dev->entry); | 1101 | INIT_LIST_HEAD(&dev->entry); |
1077 | 1102 | ||
1078 | raw_spin_lock(&its->lock); | 1103 | raw_spin_lock_irqsave(&its->lock, flags); |
1079 | list_add(&dev->entry, &its->its_device_list); | 1104 | list_add(&dev->entry, &its->its_device_list); |
1080 | raw_spin_unlock(&its->lock); | 1105 | raw_spin_unlock_irqrestore(&its->lock, flags); |
1081 | 1106 | ||
1082 | /* Bind the device to the first possible CPU */ | 1107 | /* Bind the device to the first possible CPU */ |
1083 | cpu = cpumask_first(cpu_online_mask); | 1108 | cpu = cpumask_first(cpu_online_mask); |
@@ -1091,9 +1116,11 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, | |||
1091 | 1116 | ||
1092 | static void its_free_device(struct its_device *its_dev) | 1117 | static void its_free_device(struct its_device *its_dev) |
1093 | { | 1118 | { |
1094 | raw_spin_lock(&its_dev->its->lock); | 1119 | unsigned long flags; |
1120 | |||
1121 | raw_spin_lock_irqsave(&its_dev->its->lock, flags); | ||
1095 | list_del(&its_dev->entry); | 1122 | list_del(&its_dev->entry); |
1096 | raw_spin_unlock(&its_dev->its->lock); | 1123 | raw_spin_unlock_irqrestore(&its_dev->its->lock, flags); |
1097 | kfree(its_dev->itt); | 1124 | kfree(its_dev->itt); |
1098 | kfree(its_dev); | 1125 | kfree(its_dev); |
1099 | } | 1126 | } |
@@ -1112,31 +1139,69 @@ static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq) | |||
1112 | return 0; | 1139 | return 0; |
1113 | } | 1140 | } |
1114 | 1141 | ||
1142 | struct its_pci_alias { | ||
1143 | struct pci_dev *pdev; | ||
1144 | u32 dev_id; | ||
1145 | u32 count; | ||
1146 | }; | ||
1147 | |||
1148 | static int its_pci_msi_vec_count(struct pci_dev *pdev) | ||
1149 | { | ||
1150 | int msi, msix; | ||
1151 | |||
1152 | msi = max(pci_msi_vec_count(pdev), 0); | ||
1153 | msix = max(pci_msix_vec_count(pdev), 0); | ||
1154 | |||
1155 | return max(msi, msix); | ||
1156 | } | ||
1157 | |||
1158 | static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data) | ||
1159 | { | ||
1160 | struct its_pci_alias *dev_alias = data; | ||
1161 | |||
1162 | dev_alias->dev_id = alias; | ||
1163 | if (pdev != dev_alias->pdev) | ||
1164 | dev_alias->count += its_pci_msi_vec_count(dev_alias->pdev); | ||
1165 | |||
1166 | return 0; | ||
1167 | } | ||
1168 | |||
1115 | static int its_msi_prepare(struct irq_domain *domain, struct device *dev, | 1169 | static int its_msi_prepare(struct irq_domain *domain, struct device *dev, |
1116 | int nvec, msi_alloc_info_t *info) | 1170 | int nvec, msi_alloc_info_t *info) |
1117 | { | 1171 | { |
1118 | struct pci_dev *pdev; | 1172 | struct pci_dev *pdev; |
1119 | struct its_node *its; | 1173 | struct its_node *its; |
1120 | u32 dev_id; | ||
1121 | struct its_device *its_dev; | 1174 | struct its_device *its_dev; |
1175 | struct its_pci_alias dev_alias; | ||
1122 | 1176 | ||
1123 | if (!dev_is_pci(dev)) | 1177 | if (!dev_is_pci(dev)) |
1124 | return -EINVAL; | 1178 | return -EINVAL; |
1125 | 1179 | ||
1126 | pdev = to_pci_dev(dev); | 1180 | pdev = to_pci_dev(dev); |
1127 | dev_id = PCI_DEVID(pdev->bus->number, pdev->devfn); | 1181 | dev_alias.pdev = pdev; |
1182 | dev_alias.count = nvec; | ||
1183 | |||
1184 | pci_for_each_dma_alias(pdev, its_get_pci_alias, &dev_alias); | ||
1128 | its = domain->parent->host_data; | 1185 | its = domain->parent->host_data; |
1129 | 1186 | ||
1130 | its_dev = its_find_device(its, dev_id); | 1187 | its_dev = its_find_device(its, dev_alias.dev_id); |
1131 | if (WARN_ON(its_dev)) | 1188 | if (its_dev) { |
1132 | return -EINVAL; | 1189 | /* |
1190 | * We already have seen this ID, probably through | ||
1191 | * another alias (PCI bridge of some sort). No need to | ||
1192 | * create the device. | ||
1193 | */ | ||
1194 | dev_dbg(dev, "Reusing ITT for devID %x\n", dev_alias.dev_id); | ||
1195 | goto out; | ||
1196 | } | ||
1133 | 1197 | ||
1134 | its_dev = its_create_device(its, dev_id, nvec); | 1198 | its_dev = its_create_device(its, dev_alias.dev_id, dev_alias.count); |
1135 | if (!its_dev) | 1199 | if (!its_dev) |
1136 | return -ENOMEM; | 1200 | return -ENOMEM; |
1137 | 1201 | ||
1138 | dev_dbg(&pdev->dev, "ITT %d entries, %d bits\n", nvec, ilog2(nvec)); | 1202 | dev_dbg(&pdev->dev, "ITT %d entries, %d bits\n", |
1139 | 1203 | dev_alias.count, ilog2(dev_alias.count)); | |
1204 | out: | ||
1140 | info->scratchpad[0].ptr = its_dev; | 1205 | info->scratchpad[0].ptr = its_dev; |
1141 | info->scratchpad[1].ptr = dev; | 1206 | info->scratchpad[1].ptr = dev; |
1142 | return 0; | 1207 | return 0; |
@@ -1255,6 +1320,34 @@ static const struct irq_domain_ops its_domain_ops = { | |||
1255 | .deactivate = its_irq_domain_deactivate, | 1320 | .deactivate = its_irq_domain_deactivate, |
1256 | }; | 1321 | }; |
1257 | 1322 | ||
1323 | static int its_force_quiescent(void __iomem *base) | ||
1324 | { | ||
1325 | u32 count = 1000000; /* 1s */ | ||
1326 | u32 val; | ||
1327 | |||
1328 | val = readl_relaxed(base + GITS_CTLR); | ||
1329 | if (val & GITS_CTLR_QUIESCENT) | ||
1330 | return 0; | ||
1331 | |||
1332 | /* Disable the generation of all interrupts to this ITS */ | ||
1333 | val &= ~GITS_CTLR_ENABLE; | ||
1334 | writel_relaxed(val, base + GITS_CTLR); | ||
1335 | |||
1336 | /* Poll GITS_CTLR and wait until ITS becomes quiescent */ | ||
1337 | while (1) { | ||
1338 | val = readl_relaxed(base + GITS_CTLR); | ||
1339 | if (val & GITS_CTLR_QUIESCENT) | ||
1340 | return 0; | ||
1341 | |||
1342 | count--; | ||
1343 | if (!count) | ||
1344 | return -EBUSY; | ||
1345 | |||
1346 | cpu_relax(); | ||
1347 | udelay(1); | ||
1348 | } | ||
1349 | } | ||
1350 | |||
1258 | static int its_probe(struct device_node *node, struct irq_domain *parent) | 1351 | static int its_probe(struct device_node *node, struct irq_domain *parent) |
1259 | { | 1352 | { |
1260 | struct resource res; | 1353 | struct resource res; |
@@ -1283,6 +1376,13 @@ static int its_probe(struct device_node *node, struct irq_domain *parent) | |||
1283 | goto out_unmap; | 1376 | goto out_unmap; |
1284 | } | 1377 | } |
1285 | 1378 | ||
1379 | err = its_force_quiescent(its_base); | ||
1380 | if (err) { | ||
1381 | pr_warn("%s: failed to quiesce, giving up\n", | ||
1382 | node->full_name); | ||
1383 | goto out_unmap; | ||
1384 | } | ||
1385 | |||
1286 | pr_info("ITS: %s\n", node->full_name); | 1386 | pr_info("ITS: %s\n", node->full_name); |
1287 | 1387 | ||
1288 | its = kzalloc(sizeof(*its), GFP_KERNEL); | 1388 | its = kzalloc(sizeof(*its), GFP_KERNEL); |
@@ -1323,7 +1423,7 @@ static int its_probe(struct device_node *node, struct irq_domain *parent) | |||
1323 | writeq_relaxed(baser, its->base + GITS_CBASER); | 1423 | writeq_relaxed(baser, its->base + GITS_CBASER); |
1324 | tmp = readq_relaxed(its->base + GITS_CBASER); | 1424 | tmp = readq_relaxed(its->base + GITS_CBASER); |
1325 | writeq_relaxed(0, its->base + GITS_CWRITER); | 1425 | writeq_relaxed(0, its->base + GITS_CWRITER); |
1326 | writel_relaxed(1, its->base + GITS_CTLR); | 1426 | writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR); |
1327 | 1427 | ||
1328 | if ((tmp ^ baser) & GITS_BASER_SHAREABILITY_MASK) { | 1428 | if ((tmp ^ baser) & GITS_BASER_SHAREABILITY_MASK) { |
1329 | pr_info("ITS: using cache flushing for cmd queue\n"); | 1429 | pr_info("ITS: using cache flushing for cmd queue\n"); |
@@ -1382,12 +1482,11 @@ static bool gic_rdists_supports_plpis(void) | |||
1382 | 1482 | ||
1383 | int its_cpu_init(void) | 1483 | int its_cpu_init(void) |
1384 | { | 1484 | { |
1385 | if (!gic_rdists_supports_plpis()) { | ||
1386 | pr_info("CPU%d: LPIs not supported\n", smp_processor_id()); | ||
1387 | return -ENXIO; | ||
1388 | } | ||
1389 | |||
1390 | if (!list_empty(&its_nodes)) { | 1485 | if (!list_empty(&its_nodes)) { |
1486 | if (!gic_rdists_supports_plpis()) { | ||
1487 | pr_info("CPU%d: LPIs not supported\n", smp_processor_id()); | ||
1488 | return -ENXIO; | ||
1489 | } | ||
1391 | its_cpu_init_lpis(); | 1490 | its_cpu_init_lpis(); |
1392 | its_cpu_init_collection(); | 1491 | its_cpu_init_collection(); |
1393 | } | 1492 | } |
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 1c6dea2fbc34..fd8850def1b8 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c | |||
@@ -466,7 +466,7 @@ static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask, | |||
466 | tlist |= 1 << (mpidr & 0xf); | 466 | tlist |= 1 << (mpidr & 0xf); |
467 | 467 | ||
468 | cpu = cpumask_next(cpu, mask); | 468 | cpu = cpumask_next(cpu, mask); |
469 | if (cpu == nr_cpu_ids) | 469 | if (cpu >= nr_cpu_ids) |
470 | goto out; | 470 | goto out; |
471 | 471 | ||
472 | mpidr = cpu_logical_map(cpu); | 472 | mpidr = cpu_logical_map(cpu); |
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 4634cf7d0ec3..471e1cdc1933 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
@@ -154,23 +154,25 @@ static inline unsigned int gic_irq(struct irq_data *d) | |||
154 | static void gic_mask_irq(struct irq_data *d) | 154 | static void gic_mask_irq(struct irq_data *d) |
155 | { | 155 | { |
156 | u32 mask = 1 << (gic_irq(d) % 32); | 156 | u32 mask = 1 << (gic_irq(d) % 32); |
157 | unsigned long flags; | ||
157 | 158 | ||
158 | raw_spin_lock(&irq_controller_lock); | 159 | raw_spin_lock_irqsave(&irq_controller_lock, flags); |
159 | writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4); | 160 | writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4); |
160 | if (gic_arch_extn.irq_mask) | 161 | if (gic_arch_extn.irq_mask) |
161 | gic_arch_extn.irq_mask(d); | 162 | gic_arch_extn.irq_mask(d); |
162 | raw_spin_unlock(&irq_controller_lock); | 163 | raw_spin_unlock_irqrestore(&irq_controller_lock, flags); |
163 | } | 164 | } |
164 | 165 | ||
165 | static void gic_unmask_irq(struct irq_data *d) | 166 | static void gic_unmask_irq(struct irq_data *d) |
166 | { | 167 | { |
167 | u32 mask = 1 << (gic_irq(d) % 32); | 168 | u32 mask = 1 << (gic_irq(d) % 32); |
169 | unsigned long flags; | ||
168 | 170 | ||
169 | raw_spin_lock(&irq_controller_lock); | 171 | raw_spin_lock_irqsave(&irq_controller_lock, flags); |
170 | if (gic_arch_extn.irq_unmask) | 172 | if (gic_arch_extn.irq_unmask) |
171 | gic_arch_extn.irq_unmask(d); | 173 | gic_arch_extn.irq_unmask(d); |
172 | writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4); | 174 | writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4); |
173 | raw_spin_unlock(&irq_controller_lock); | 175 | raw_spin_unlock_irqrestore(&irq_controller_lock, flags); |
174 | } | 176 | } |
175 | 177 | ||
176 | static void gic_eoi_irq(struct irq_data *d) | 178 | static void gic_eoi_irq(struct irq_data *d) |
@@ -188,6 +190,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type) | |||
188 | { | 190 | { |
189 | void __iomem *base = gic_dist_base(d); | 191 | void __iomem *base = gic_dist_base(d); |
190 | unsigned int gicirq = gic_irq(d); | 192 | unsigned int gicirq = gic_irq(d); |
193 | unsigned long flags; | ||
191 | int ret; | 194 | int ret; |
192 | 195 | ||
193 | /* Interrupt configuration for SGIs can't be changed */ | 196 | /* Interrupt configuration for SGIs can't be changed */ |
@@ -199,14 +202,14 @@ static int gic_set_type(struct irq_data *d, unsigned int type) | |||
199 | type != IRQ_TYPE_EDGE_RISING) | 202 | type != IRQ_TYPE_EDGE_RISING) |
200 | return -EINVAL; | 203 | return -EINVAL; |
201 | 204 | ||
202 | raw_spin_lock(&irq_controller_lock); | 205 | raw_spin_lock_irqsave(&irq_controller_lock, flags); |
203 | 206 | ||
204 | if (gic_arch_extn.irq_set_type) | 207 | if (gic_arch_extn.irq_set_type) |
205 | gic_arch_extn.irq_set_type(d, type); | 208 | gic_arch_extn.irq_set_type(d, type); |
206 | 209 | ||
207 | ret = gic_configure_irq(gicirq, type, base, NULL); | 210 | ret = gic_configure_irq(gicirq, type, base, NULL); |
208 | 211 | ||
209 | raw_spin_unlock(&irq_controller_lock); | 212 | raw_spin_unlock_irqrestore(&irq_controller_lock, flags); |
210 | 213 | ||
211 | return ret; | 214 | return ret; |
212 | } | 215 | } |
@@ -227,6 +230,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, | |||
227 | void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3); | 230 | void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3); |
228 | unsigned int cpu, shift = (gic_irq(d) % 4) * 8; | 231 | unsigned int cpu, shift = (gic_irq(d) % 4) * 8; |
229 | u32 val, mask, bit; | 232 | u32 val, mask, bit; |
233 | unsigned long flags; | ||
230 | 234 | ||
231 | if (!force) | 235 | if (!force) |
232 | cpu = cpumask_any_and(mask_val, cpu_online_mask); | 236 | cpu = cpumask_any_and(mask_val, cpu_online_mask); |
@@ -236,12 +240,12 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, | |||
236 | if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids) | 240 | if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids) |
237 | return -EINVAL; | 241 | return -EINVAL; |
238 | 242 | ||
239 | raw_spin_lock(&irq_controller_lock); | 243 | raw_spin_lock_irqsave(&irq_controller_lock, flags); |
240 | mask = 0xff << shift; | 244 | mask = 0xff << shift; |
241 | bit = gic_cpu_map[cpu] << shift; | 245 | bit = gic_cpu_map[cpu] << shift; |
242 | val = readl_relaxed(reg) & ~mask; | 246 | val = readl_relaxed(reg) & ~mask; |
243 | writel_relaxed(val | bit, reg); | 247 | writel_relaxed(val | bit, reg); |
244 | raw_spin_unlock(&irq_controller_lock); | 248 | raw_spin_unlock_irqrestore(&irq_controller_lock, flags); |
245 | 249 | ||
246 | return IRQ_SET_MASK_OK; | 250 | return IRQ_SET_MASK_OK; |
247 | } | 251 | } |
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index 800544bc7bfd..781974afff9f 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h | |||
@@ -166,6 +166,11 @@ | |||
166 | 166 | ||
167 | #define GITS_TRANSLATER 0x10040 | 167 | #define GITS_TRANSLATER 0x10040 |
168 | 168 | ||
169 | #define GITS_CTLR_ENABLE (1U << 0) | ||
170 | #define GITS_CTLR_QUIESCENT (1U << 31) | ||
171 | |||
172 | #define GITS_TYPER_DEVBITS_SHIFT 13 | ||
173 | #define GITS_TYPER_DEVBITS(r) ((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1) | ||
169 | #define GITS_TYPER_PTA (1UL << 19) | 174 | #define GITS_TYPER_PTA (1UL << 19) |
170 | 175 | ||
171 | #define GITS_CBASER_VALID (1UL << 63) | 176 | #define GITS_CBASER_VALID (1UL << 63) |