diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2018-08-06 06:45:42 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2018-08-06 06:45:42 -0400 |
commit | 9e90c7985229430428dc9ba0ec7fe422901b456d (patch) | |
tree | cae2072feba8cc433a32d96568bbcf36070bd6e5 /drivers/irqchip | |
parent | 4f7799d96e6621ce584df60739e1480a6fd89f0a (diff) | |
parent | a8db74564b0c634667e1722264bde303d296f566 (diff) |
Merge tag 'irqchip-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/core
Pull irqchip updates from Marc Zyngier:
- GICv3 ITS LPI allocation revamp
- GICv3 support for hypervisor-enforced LPI range
- GICv3 ITS conversion to raw spinlock
Diffstat (limited to 'drivers/irqchip')
-rw-r--r-- | drivers/irqchip/irq-gic-v2m.c | 2 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 3 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3-its-pci-msi.c | 16 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3-its-platform-msi.c | 2 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3-its.c | 305 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 4 | ||||
-rw-r--r-- | drivers/irqchip/irq-ls-scfg-msi.c | 10 |
7 files changed, 234 insertions, 108 deletions
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c index 0f52d44b3f69..f5fe0100f9ff 100644 --- a/drivers/irqchip/irq-gic-v2m.c +++ b/drivers/irqchip/irq-gic-v2m.c | |||
@@ -199,7 +199,7 @@ static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, | |||
199 | 199 | ||
200 | fail: | 200 | fail: |
201 | irq_domain_free_irqs_parent(domain, virq, nr_irqs); | 201 | irq_domain_free_irqs_parent(domain, virq, nr_irqs); |
202 | gicv2m_unalloc_msi(v2m, hwirq, get_count_order(nr_irqs)); | 202 | gicv2m_unalloc_msi(v2m, hwirq, nr_irqs); |
203 | return err; | 203 | return err; |
204 | } | 204 | } |
205 | 205 | ||
diff --git a/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c index 4eca5c763766..606efa64adff 100644 --- a/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c +++ b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | |||
@@ -45,6 +45,9 @@ static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain, | |||
45 | */ | 45 | */ |
46 | info->scratchpad[0].ul = mc_bus_dev->icid; | 46 | info->scratchpad[0].ul = mc_bus_dev->icid; |
47 | msi_info = msi_get_domain_info(msi_domain->parent); | 47 | msi_info = msi_get_domain_info(msi_domain->parent); |
48 | |||
49 | /* Allocate at least 32 MSIs, and always as a power of 2 */ | ||
50 | nvec = max_t(int, 32, roundup_pow_of_two(nvec)); | ||
48 | return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info); | 51 | return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info); |
49 | } | 52 | } |
50 | 53 | ||
diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c index 25a98de5cfb2..8d6d009d1d58 100644 --- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c +++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c | |||
@@ -66,7 +66,7 @@ static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev, | |||
66 | { | 66 | { |
67 | struct pci_dev *pdev, *alias_dev; | 67 | struct pci_dev *pdev, *alias_dev; |
68 | struct msi_domain_info *msi_info; | 68 | struct msi_domain_info *msi_info; |
69 | int alias_count = 0; | 69 | int alias_count = 0, minnvec = 1; |
70 | 70 | ||
71 | if (!dev_is_pci(dev)) | 71 | if (!dev_is_pci(dev)) |
72 | return -EINVAL; | 72 | return -EINVAL; |
@@ -86,8 +86,18 @@ static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev, | |||
86 | /* ITS specific DeviceID, as the core ITS ignores dev. */ | 86 | /* ITS specific DeviceID, as the core ITS ignores dev. */ |
87 | info->scratchpad[0].ul = pci_msi_domain_get_msi_rid(domain, pdev); | 87 | info->scratchpad[0].ul = pci_msi_domain_get_msi_rid(domain, pdev); |
88 | 88 | ||
89 | return msi_info->ops->msi_prepare(domain->parent, | 89 | /* |
90 | dev, max(nvec, alias_count), info); | 90 | * Always allocate a power of 2, and special case device 0 for |
91 | * broken systems where the DevID is not wired (and all devices | ||
92 | * appear as DevID 0). For that reason, we generously allocate a | ||
93 | * minimum of 32 MSIs for DevID 0. If you want more because all | ||
94 | * your devices are aliasing to DevID 0, consider fixing your HW. | ||
95 | */ | ||
96 | nvec = max(nvec, alias_count); | ||
97 | if (!info->scratchpad[0].ul) | ||
98 | minnvec = 32; | ||
99 | nvec = max_t(int, minnvec, roundup_pow_of_two(nvec)); | ||
100 | return msi_info->ops->msi_prepare(domain->parent, dev, nvec, info); | ||
91 | } | 101 | } |
92 | 102 | ||
93 | static struct msi_domain_ops its_pci_msi_ops = { | 103 | static struct msi_domain_ops its_pci_msi_ops = { |
diff --git a/drivers/irqchip/irq-gic-v3-its-platform-msi.c b/drivers/irqchip/irq-gic-v3-its-platform-msi.c index 8881a053c173..7b8e87b493fe 100644 --- a/drivers/irqchip/irq-gic-v3-its-platform-msi.c +++ b/drivers/irqchip/irq-gic-v3-its-platform-msi.c | |||
@@ -73,6 +73,8 @@ static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev, | |||
73 | /* ITS specific DeviceID, as the core ITS ignores dev. */ | 73 | /* ITS specific DeviceID, as the core ITS ignores dev. */ |
74 | info->scratchpad[0].ul = dev_id; | 74 | info->scratchpad[0].ul = dev_id; |
75 | 75 | ||
76 | /* Allocate at least 32 MSIs, and always as a power of 2 */ | ||
77 | nvec = max_t(int, 32, roundup_pow_of_two(nvec)); | ||
76 | return msi_info->ops->msi_prepare(domain->parent, | 78 | return msi_info->ops->msi_prepare(domain->parent, |
77 | dev, nvec, info); | 79 | dev, nvec, info); |
78 | } | 80 | } |
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 5377d7e2afba..316a57530f6d 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/dma-iommu.h> | 23 | #include <linux/dma-iommu.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/irqdomain.h> | 25 | #include <linux/irqdomain.h> |
26 | #include <linux/list.h> | ||
27 | #include <linux/list_sort.h> | ||
26 | #include <linux/log2.h> | 28 | #include <linux/log2.h> |
27 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
28 | #include <linux/msi.h> | 30 | #include <linux/msi.h> |
@@ -160,7 +162,7 @@ static struct { | |||
160 | } vpe_proxy; | 162 | } vpe_proxy; |
161 | 163 | ||
162 | static LIST_HEAD(its_nodes); | 164 | static LIST_HEAD(its_nodes); |
163 | static DEFINE_SPINLOCK(its_lock); | 165 | static DEFINE_RAW_SPINLOCK(its_lock); |
164 | static struct rdists *gic_rdists; | 166 | static struct rdists *gic_rdists; |
165 | static struct irq_domain *its_parent; | 167 | static struct irq_domain *its_parent; |
166 | 168 | ||
@@ -182,6 +184,22 @@ static struct its_collection *dev_event_to_col(struct its_device *its_dev, | |||
182 | return its->collections + its_dev->event_map.col_map[event]; | 184 | return its->collections + its_dev->event_map.col_map[event]; |
183 | } | 185 | } |
184 | 186 | ||
187 | static struct its_collection *valid_col(struct its_collection *col) | ||
188 | { | ||
189 | if (WARN_ON_ONCE(col->target_address & GENMASK_ULL(0, 15))) | ||
190 | return NULL; | ||
191 | |||
192 | return col; | ||
193 | } | ||
194 | |||
195 | static struct its_vpe *valid_vpe(struct its_node *its, struct its_vpe *vpe) | ||
196 | { | ||
197 | if (valid_col(its->collections + vpe->col_idx)) | ||
198 | return vpe; | ||
199 | |||
200 | return NULL; | ||
201 | } | ||
202 | |||
185 | /* | 203 | /* |
186 | * ITS command descriptors - parameters to be encoded in a command | 204 | * ITS command descriptors - parameters to be encoded in a command |
187 | * block. | 205 | * block. |
@@ -439,7 +457,7 @@ static struct its_collection *its_build_mapti_cmd(struct its_node *its, | |||
439 | 457 | ||
440 | its_fixup_cmd(cmd); | 458 | its_fixup_cmd(cmd); |
441 | 459 | ||
442 | return col; | 460 | return valid_col(col); |
443 | } | 461 | } |
444 | 462 | ||
445 | static struct its_collection *its_build_movi_cmd(struct its_node *its, | 463 | static struct its_collection *its_build_movi_cmd(struct its_node *its, |
@@ -458,7 +476,7 @@ static struct its_collection *its_build_movi_cmd(struct its_node *its, | |||
458 | 476 | ||
459 | its_fixup_cmd(cmd); | 477 | its_fixup_cmd(cmd); |
460 | 478 | ||
461 | return col; | 479 | return valid_col(col); |
462 | } | 480 | } |
463 | 481 | ||
464 | static struct its_collection *its_build_discard_cmd(struct its_node *its, | 482 | static struct its_collection *its_build_discard_cmd(struct its_node *its, |
@@ -476,7 +494,7 @@ static struct its_collection *its_build_discard_cmd(struct its_node *its, | |||
476 | 494 | ||
477 | its_fixup_cmd(cmd); | 495 | its_fixup_cmd(cmd); |
478 | 496 | ||
479 | return col; | 497 | return valid_col(col); |
480 | } | 498 | } |
481 | 499 | ||
482 | static struct its_collection *its_build_inv_cmd(struct its_node *its, | 500 | static struct its_collection *its_build_inv_cmd(struct its_node *its, |
@@ -494,7 +512,7 @@ static struct its_collection *its_build_inv_cmd(struct its_node *its, | |||
494 | 512 | ||
495 | its_fixup_cmd(cmd); | 513 | its_fixup_cmd(cmd); |
496 | 514 | ||
497 | return col; | 515 | return valid_col(col); |
498 | } | 516 | } |
499 | 517 | ||
500 | static struct its_collection *its_build_int_cmd(struct its_node *its, | 518 | static struct its_collection *its_build_int_cmd(struct its_node *its, |
@@ -512,7 +530,7 @@ static struct its_collection *its_build_int_cmd(struct its_node *its, | |||
512 | 530 | ||
513 | its_fixup_cmd(cmd); | 531 | its_fixup_cmd(cmd); |
514 | 532 | ||
515 | return col; | 533 | return valid_col(col); |
516 | } | 534 | } |
517 | 535 | ||
518 | static struct its_collection *its_build_clear_cmd(struct its_node *its, | 536 | static struct its_collection *its_build_clear_cmd(struct its_node *its, |
@@ -530,7 +548,7 @@ static struct its_collection *its_build_clear_cmd(struct its_node *its, | |||
530 | 548 | ||
531 | its_fixup_cmd(cmd); | 549 | its_fixup_cmd(cmd); |
532 | 550 | ||
533 | return col; | 551 | return valid_col(col); |
534 | } | 552 | } |
535 | 553 | ||
536 | static struct its_collection *its_build_invall_cmd(struct its_node *its, | 554 | static struct its_collection *its_build_invall_cmd(struct its_node *its, |
@@ -554,7 +572,7 @@ static struct its_vpe *its_build_vinvall_cmd(struct its_node *its, | |||
554 | 572 | ||
555 | its_fixup_cmd(cmd); | 573 | its_fixup_cmd(cmd); |
556 | 574 | ||
557 | return desc->its_vinvall_cmd.vpe; | 575 | return valid_vpe(its, desc->its_vinvall_cmd.vpe); |
558 | } | 576 | } |
559 | 577 | ||
560 | static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, | 578 | static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, |
@@ -576,7 +594,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, | |||
576 | 594 | ||
577 | its_fixup_cmd(cmd); | 595 | its_fixup_cmd(cmd); |
578 | 596 | ||
579 | return desc->its_vmapp_cmd.vpe; | 597 | return valid_vpe(its, desc->its_vmapp_cmd.vpe); |
580 | } | 598 | } |
581 | 599 | ||
582 | static struct its_vpe *its_build_vmapti_cmd(struct its_node *its, | 600 | static struct its_vpe *its_build_vmapti_cmd(struct its_node *its, |
@@ -599,7 +617,7 @@ static struct its_vpe *its_build_vmapti_cmd(struct its_node *its, | |||
599 | 617 | ||
600 | its_fixup_cmd(cmd); | 618 | its_fixup_cmd(cmd); |
601 | 619 | ||
602 | return desc->its_vmapti_cmd.vpe; | 620 | return valid_vpe(its, desc->its_vmapti_cmd.vpe); |
603 | } | 621 | } |
604 | 622 | ||
605 | static struct its_vpe *its_build_vmovi_cmd(struct its_node *its, | 623 | static struct its_vpe *its_build_vmovi_cmd(struct its_node *its, |
@@ -622,7 +640,7 @@ static struct its_vpe *its_build_vmovi_cmd(struct its_node *its, | |||
622 | 640 | ||
623 | its_fixup_cmd(cmd); | 641 | its_fixup_cmd(cmd); |
624 | 642 | ||
625 | return desc->its_vmovi_cmd.vpe; | 643 | return valid_vpe(its, desc->its_vmovi_cmd.vpe); |
626 | } | 644 | } |
627 | 645 | ||
628 | static struct its_vpe *its_build_vmovp_cmd(struct its_node *its, | 646 | static struct its_vpe *its_build_vmovp_cmd(struct its_node *its, |
@@ -640,7 +658,7 @@ static struct its_vpe *its_build_vmovp_cmd(struct its_node *its, | |||
640 | 658 | ||
641 | its_fixup_cmd(cmd); | 659 | its_fixup_cmd(cmd); |
642 | 660 | ||
643 | return desc->its_vmovp_cmd.vpe; | 661 | return valid_vpe(its, desc->its_vmovp_cmd.vpe); |
644 | } | 662 | } |
645 | 663 | ||
646 | static u64 its_cmd_ptr_to_offset(struct its_node *its, | 664 | static u64 its_cmd_ptr_to_offset(struct its_node *its, |
@@ -1405,112 +1423,176 @@ static struct irq_chip its_irq_chip = { | |||
1405 | .irq_set_vcpu_affinity = its_irq_set_vcpu_affinity, | 1423 | .irq_set_vcpu_affinity = its_irq_set_vcpu_affinity, |
1406 | }; | 1424 | }; |
1407 | 1425 | ||
1426 | |||
1408 | /* | 1427 | /* |
1409 | * How we allocate LPIs: | 1428 | * How we allocate LPIs: |
1410 | * | 1429 | * |
1411 | * The GIC has id_bits bits for interrupt identifiers. From there, we | 1430 | * lpi_range_list contains ranges of LPIs that are to available to |
1412 | * must subtract 8192 which are reserved for SGIs/PPIs/SPIs. Then, as | 1431 | * allocate from. To allocate LPIs, just pick the first range that |
1413 | * we allocate LPIs by chunks of 32, we can shift the whole thing by 5 | 1432 | * fits the required allocation, and reduce it by the required |
1414 | * bits to the right. | 1433 | * amount. Once empty, remove the range from the list. |
1415 | * | 1434 | * |
1416 | * This gives us (((1UL << id_bits) - 8192) >> 5) possible allocations. | 1435 | * To free a range of LPIs, add a free range to the list, sort it and |
1436 | * merge the result if the new range happens to be adjacent to an | ||
1437 | * already free block. | ||
1438 | * | ||
1439 | * The consequence of the above is that allocation is cost is low, but | ||
1440 | * freeing is expensive. We assumes that freeing rarely occurs. | ||
1417 | */ | 1441 | */ |
1418 | #define IRQS_PER_CHUNK_SHIFT 5 | ||
1419 | #define IRQS_PER_CHUNK (1UL << IRQS_PER_CHUNK_SHIFT) | ||
1420 | #define ITS_MAX_LPI_NRBITS 16 /* 64K LPIs */ | ||
1421 | 1442 | ||
1422 | static unsigned long *lpi_bitmap; | 1443 | static DEFINE_MUTEX(lpi_range_lock); |
1423 | static u32 lpi_chunks; | 1444 | static LIST_HEAD(lpi_range_list); |
1424 | static DEFINE_SPINLOCK(lpi_lock); | 1445 | |
1446 | struct lpi_range { | ||
1447 | struct list_head entry; | ||
1448 | u32 base_id; | ||
1449 | u32 span; | ||
1450 | }; | ||
1451 | |||
1452 | static struct lpi_range *mk_lpi_range(u32 base, u32 span) | ||
1453 | { | ||
1454 | struct lpi_range *range; | ||
1455 | |||
1456 | range = kzalloc(sizeof(*range), GFP_KERNEL); | ||
1457 | if (range) { | ||
1458 | INIT_LIST_HEAD(&range->entry); | ||
1459 | range->base_id = base; | ||
1460 | range->span = span; | ||
1461 | } | ||
1425 | 1462 | ||
1426 | static int its_lpi_to_chunk(int lpi) | 1463 | return range; |
1464 | } | ||
1465 | |||
1466 | static int lpi_range_cmp(void *priv, struct list_head *a, struct list_head *b) | ||
1427 | { | 1467 | { |
1428 | return (lpi - 8192) >> IRQS_PER_CHUNK_SHIFT; | 1468 | struct lpi_range *ra, *rb; |
1469 | |||
1470 | ra = container_of(a, struct lpi_range, entry); | ||
1471 | rb = container_of(b, struct lpi_range, entry); | ||
1472 | |||
1473 | return rb->base_id - ra->base_id; | ||
1429 | } | 1474 | } |
1430 | 1475 | ||
1431 | static int its_chunk_to_lpi(int chunk) | 1476 | static void merge_lpi_ranges(void) |
1432 | { | 1477 | { |
1433 | return (chunk << IRQS_PER_CHUNK_SHIFT) + 8192; | 1478 | struct lpi_range *range, *tmp; |
1479 | |||
1480 | list_for_each_entry_safe(range, tmp, &lpi_range_list, entry) { | ||
1481 | if (!list_is_last(&range->entry, &lpi_range_list) && | ||
1482 | (tmp->base_id == (range->base_id + range->span))) { | ||
1483 | tmp->base_id = range->base_id; | ||
1484 | tmp->span += range->span; | ||
1485 | list_del(&range->entry); | ||
1486 | kfree(range); | ||
1487 | } | ||
1488 | } | ||
1434 | } | 1489 | } |
1435 | 1490 | ||
1436 | static int __init its_lpi_init(u32 id_bits) | 1491 | static int alloc_lpi_range(u32 nr_lpis, u32 *base) |
1437 | { | 1492 | { |
1438 | lpi_chunks = its_lpi_to_chunk(1UL << id_bits); | 1493 | struct lpi_range *range, *tmp; |
1494 | int err = -ENOSPC; | ||
1439 | 1495 | ||
1440 | lpi_bitmap = kcalloc(BITS_TO_LONGS(lpi_chunks), sizeof(long), | 1496 | mutex_lock(&lpi_range_lock); |
1441 | GFP_KERNEL); | 1497 | |
1442 | if (!lpi_bitmap) { | 1498 | list_for_each_entry_safe(range, tmp, &lpi_range_list, entry) { |
1443 | lpi_chunks = 0; | 1499 | if (range->span >= nr_lpis) { |
1444 | return -ENOMEM; | 1500 | *base = range->base_id; |
1501 | range->base_id += nr_lpis; | ||
1502 | range->span -= nr_lpis; | ||
1503 | |||
1504 | if (range->span == 0) { | ||
1505 | list_del(&range->entry); | ||
1506 | kfree(range); | ||
1507 | } | ||
1508 | |||
1509 | err = 0; | ||
1510 | break; | ||
1511 | } | ||
1445 | } | 1512 | } |
1446 | 1513 | ||
1447 | pr_info("ITS: Allocated %d chunks for LPIs\n", (int)lpi_chunks); | 1514 | mutex_unlock(&lpi_range_lock); |
1448 | return 0; | 1515 | |
1516 | pr_debug("ITS: alloc %u:%u\n", *base, nr_lpis); | ||
1517 | return err; | ||
1449 | } | 1518 | } |
1450 | 1519 | ||
1451 | static unsigned long *its_lpi_alloc_chunks(int nr_irqs, int *base, int *nr_ids) | 1520 | static int free_lpi_range(u32 base, u32 nr_lpis) |
1452 | { | 1521 | { |
1453 | unsigned long *bitmap = NULL; | 1522 | struct lpi_range *new; |
1454 | int chunk_id; | 1523 | int err = 0; |
1455 | int nr_chunks; | ||
1456 | int i; | ||
1457 | 1524 | ||
1458 | nr_chunks = DIV_ROUND_UP(nr_irqs, IRQS_PER_CHUNK); | 1525 | mutex_lock(&lpi_range_lock); |
1459 | 1526 | ||
1460 | spin_lock(&lpi_lock); | 1527 | new = mk_lpi_range(base, nr_lpis); |
1528 | if (!new) { | ||
1529 | err = -ENOMEM; | ||
1530 | goto out; | ||
1531 | } | ||
1532 | |||
1533 | list_add(&new->entry, &lpi_range_list); | ||
1534 | list_sort(NULL, &lpi_range_list, lpi_range_cmp); | ||
1535 | merge_lpi_ranges(); | ||
1536 | out: | ||
1537 | mutex_unlock(&lpi_range_lock); | ||
1538 | return err; | ||
1539 | } | ||
1540 | |||
1541 | static int __init its_lpi_init(u32 id_bits) | ||
1542 | { | ||
1543 | u32 lpis = (1UL << id_bits) - 8192; | ||
1544 | u32 numlpis; | ||
1545 | int err; | ||
1546 | |||
1547 | numlpis = 1UL << GICD_TYPER_NUM_LPIS(gic_rdists->gicd_typer); | ||
1548 | |||
1549 | if (numlpis > 2 && !WARN_ON(numlpis > lpis)) { | ||
1550 | lpis = numlpis; | ||
1551 | pr_info("ITS: Using hypervisor restricted LPI range [%u]\n", | ||
1552 | lpis); | ||
1553 | } | ||
1554 | |||
1555 | /* | ||
1556 | * Initializing the allocator is just the same as freeing the | ||
1557 | * full range of LPIs. | ||
1558 | */ | ||
1559 | err = free_lpi_range(8192, lpis); | ||
1560 | pr_debug("ITS: Allocator initialized for %u LPIs\n", lpis); | ||
1561 | return err; | ||
1562 | } | ||
1563 | |||
1564 | static unsigned long *its_lpi_alloc(int nr_irqs, u32 *base, int *nr_ids) | ||
1565 | { | ||
1566 | unsigned long *bitmap = NULL; | ||
1567 | int err = 0; | ||
1461 | 1568 | ||
1462 | do { | 1569 | do { |
1463 | chunk_id = bitmap_find_next_zero_area(lpi_bitmap, lpi_chunks, | 1570 | err = alloc_lpi_range(nr_irqs, base); |
1464 | 0, nr_chunks, 0); | 1571 | if (!err) |
1465 | if (chunk_id < lpi_chunks) | ||
1466 | break; | 1572 | break; |
1467 | 1573 | ||
1468 | nr_chunks--; | 1574 | nr_irqs /= 2; |
1469 | } while (nr_chunks > 0); | 1575 | } while (nr_irqs > 0); |
1470 | 1576 | ||
1471 | if (!nr_chunks) | 1577 | if (err) |
1472 | goto out; | 1578 | goto out; |
1473 | 1579 | ||
1474 | bitmap = kcalloc(BITS_TO_LONGS(nr_chunks * IRQS_PER_CHUNK), | 1580 | bitmap = kcalloc(BITS_TO_LONGS(nr_irqs), sizeof (long), GFP_ATOMIC); |
1475 | sizeof(long), | ||
1476 | GFP_ATOMIC); | ||
1477 | if (!bitmap) | 1581 | if (!bitmap) |
1478 | goto out; | 1582 | goto out; |
1479 | 1583 | ||
1480 | for (i = 0; i < nr_chunks; i++) | 1584 | *nr_ids = nr_irqs; |
1481 | set_bit(chunk_id + i, lpi_bitmap); | ||
1482 | |||
1483 | *base = its_chunk_to_lpi(chunk_id); | ||
1484 | *nr_ids = nr_chunks * IRQS_PER_CHUNK; | ||
1485 | 1585 | ||
1486 | out: | 1586 | out: |
1487 | spin_unlock(&lpi_lock); | ||
1488 | |||
1489 | if (!bitmap) | 1587 | if (!bitmap) |
1490 | *base = *nr_ids = 0; | 1588 | *base = *nr_ids = 0; |
1491 | 1589 | ||
1492 | return bitmap; | 1590 | return bitmap; |
1493 | } | 1591 | } |
1494 | 1592 | ||
1495 | static void its_lpi_free_chunks(unsigned long *bitmap, int base, int nr_ids) | 1593 | static void its_lpi_free(unsigned long *bitmap, u32 base, u32 nr_ids) |
1496 | { | 1594 | { |
1497 | int lpi; | 1595 | WARN_ON(free_lpi_range(base, nr_ids)); |
1498 | |||
1499 | spin_lock(&lpi_lock); | ||
1500 | |||
1501 | for (lpi = base; lpi < (base + nr_ids); lpi += IRQS_PER_CHUNK) { | ||
1502 | int chunk = its_lpi_to_chunk(lpi); | ||
1503 | |||
1504 | BUG_ON(chunk > lpi_chunks); | ||
1505 | if (test_bit(chunk, lpi_bitmap)) { | ||
1506 | clear_bit(chunk, lpi_bitmap); | ||
1507 | } else { | ||
1508 | pr_err("Bad LPI chunk %d\n", chunk); | ||
1509 | } | ||
1510 | } | ||
1511 | |||
1512 | spin_unlock(&lpi_lock); | ||
1513 | |||
1514 | kfree(bitmap); | 1596 | kfree(bitmap); |
1515 | } | 1597 | } |
1516 | 1598 | ||
@@ -1543,7 +1625,7 @@ static int __init its_alloc_lpi_tables(void) | |||
1543 | { | 1625 | { |
1544 | phys_addr_t paddr; | 1626 | phys_addr_t paddr; |
1545 | 1627 | ||
1546 | lpi_id_bits = min_t(u32, gic_rdists->id_bits, ITS_MAX_LPI_NRBITS); | 1628 | lpi_id_bits = GICD_TYPER_ID_BITS(gic_rdists->gicd_typer); |
1547 | gic_rdists->prop_page = its_allocate_prop_table(GFP_NOWAIT); | 1629 | gic_rdists->prop_page = its_allocate_prop_table(GFP_NOWAIT); |
1548 | if (!gic_rdists->prop_page) { | 1630 | if (!gic_rdists->prop_page) { |
1549 | pr_err("Failed to allocate PROPBASE\n"); | 1631 | pr_err("Failed to allocate PROPBASE\n"); |
@@ -1824,11 +1906,16 @@ static int its_alloc_tables(struct its_node *its) | |||
1824 | 1906 | ||
1825 | static int its_alloc_collections(struct its_node *its) | 1907 | static int its_alloc_collections(struct its_node *its) |
1826 | { | 1908 | { |
1909 | int i; | ||
1910 | |||
1827 | its->collections = kcalloc(nr_cpu_ids, sizeof(*its->collections), | 1911 | its->collections = kcalloc(nr_cpu_ids, sizeof(*its->collections), |
1828 | GFP_KERNEL); | 1912 | GFP_KERNEL); |
1829 | if (!its->collections) | 1913 | if (!its->collections) |
1830 | return -ENOMEM; | 1914 | return -ENOMEM; |
1831 | 1915 | ||
1916 | for (i = 0; i < nr_cpu_ids; i++) | ||
1917 | its->collections[i].target_address = ~0ULL; | ||
1918 | |||
1832 | return 0; | 1919 | return 0; |
1833 | } | 1920 | } |
1834 | 1921 | ||
@@ -1976,12 +2063,12 @@ static void its_cpu_init_collections(void) | |||
1976 | { | 2063 | { |
1977 | struct its_node *its; | 2064 | struct its_node *its; |
1978 | 2065 | ||
1979 | spin_lock(&its_lock); | 2066 | raw_spin_lock(&its_lock); |
1980 | 2067 | ||
1981 | list_for_each_entry(its, &its_nodes, entry) | 2068 | list_for_each_entry(its, &its_nodes, entry) |
1982 | its_cpu_init_collection(its); | 2069 | its_cpu_init_collection(its); |
1983 | 2070 | ||
1984 | spin_unlock(&its_lock); | 2071 | raw_spin_unlock(&its_lock); |
1985 | } | 2072 | } |
1986 | 2073 | ||
1987 | static struct its_device *its_find_device(struct its_node *its, u32 dev_id) | 2074 | static struct its_device *its_find_device(struct its_node *its, u32 dev_id) |
@@ -2113,17 +2200,20 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, | |||
2113 | if (!its_alloc_device_table(its, dev_id)) | 2200 | if (!its_alloc_device_table(its, dev_id)) |
2114 | return NULL; | 2201 | return NULL; |
2115 | 2202 | ||
2203 | if (WARN_ON(!is_power_of_2(nvecs))) | ||
2204 | nvecs = roundup_pow_of_two(nvecs); | ||
2205 | |||
2116 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 2206 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
2117 | /* | 2207 | /* |
2118 | * We allocate at least one chunk worth of LPIs bet device, | 2208 | * Even if the device wants a single LPI, the ITT must be |
2119 | * and thus that many ITEs. The device may require less though. | 2209 | * sized as a power of two (and you need at least one bit...). |
2120 | */ | 2210 | */ |
2121 | nr_ites = max(IRQS_PER_CHUNK, roundup_pow_of_two(nvecs)); | 2211 | nr_ites = max(2, nvecs); |
2122 | sz = nr_ites * its->ite_size; | 2212 | sz = nr_ites * its->ite_size; |
2123 | sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1; | 2213 | sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1; |
2124 | itt = kzalloc(sz, GFP_KERNEL); | 2214 | itt = kzalloc(sz, GFP_KERNEL); |
2125 | if (alloc_lpis) { | 2215 | if (alloc_lpis) { |
2126 | lpi_map = its_lpi_alloc_chunks(nvecs, &lpi_base, &nr_lpis); | 2216 | lpi_map = its_lpi_alloc(nvecs, &lpi_base, &nr_lpis); |
2127 | if (lpi_map) | 2217 | if (lpi_map) |
2128 | col_map = kcalloc(nr_lpis, sizeof(*col_map), | 2218 | col_map = kcalloc(nr_lpis, sizeof(*col_map), |
2129 | GFP_KERNEL); | 2219 | GFP_KERNEL); |
@@ -2310,7 +2400,14 @@ static int its_irq_domain_activate(struct irq_domain *domain, | |||
2310 | cpu_mask = cpumask_of_node(its_dev->its->numa_node); | 2400 | cpu_mask = cpumask_of_node(its_dev->its->numa_node); |
2311 | 2401 | ||
2312 | /* Bind the LPI to the first possible CPU */ | 2402 | /* Bind the LPI to the first possible CPU */ |
2313 | cpu = cpumask_first(cpu_mask); | 2403 | cpu = cpumask_first_and(cpu_mask, cpu_online_mask); |
2404 | if (cpu >= nr_cpu_ids) { | ||
2405 | if (its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) | ||
2406 | return -EINVAL; | ||
2407 | |||
2408 | cpu = cpumask_first(cpu_online_mask); | ||
2409 | } | ||
2410 | |||
2314 | its_dev->event_map.col_map[event] = cpu; | 2411 | its_dev->event_map.col_map[event] = cpu; |
2315 | irq_data_update_effective_affinity(d, cpumask_of(cpu)); | 2412 | irq_data_update_effective_affinity(d, cpumask_of(cpu)); |
2316 | 2413 | ||
@@ -2351,9 +2448,9 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq, | |||
2351 | /* If all interrupts have been freed, start mopping the floor */ | 2448 | /* If all interrupts have been freed, start mopping the floor */ |
2352 | if (bitmap_empty(its_dev->event_map.lpi_map, | 2449 | if (bitmap_empty(its_dev->event_map.lpi_map, |
2353 | its_dev->event_map.nr_lpis)) { | 2450 | its_dev->event_map.nr_lpis)) { |
2354 | its_lpi_free_chunks(its_dev->event_map.lpi_map, | 2451 | its_lpi_free(its_dev->event_map.lpi_map, |
2355 | its_dev->event_map.lpi_base, | 2452 | its_dev->event_map.lpi_base, |
2356 | its_dev->event_map.nr_lpis); | 2453 | its_dev->event_map.nr_lpis); |
2357 | kfree(its_dev->event_map.col_map); | 2454 | kfree(its_dev->event_map.col_map); |
2358 | 2455 | ||
2359 | /* Unmap device/itt */ | 2456 | /* Unmap device/itt */ |
@@ -2752,7 +2849,7 @@ static void its_vpe_irq_domain_free(struct irq_domain *domain, | |||
2752 | } | 2849 | } |
2753 | 2850 | ||
2754 | if (bitmap_empty(vm->db_bitmap, vm->nr_db_lpis)) { | 2851 | if (bitmap_empty(vm->db_bitmap, vm->nr_db_lpis)) { |
2755 | its_lpi_free_chunks(vm->db_bitmap, vm->db_lpi_base, vm->nr_db_lpis); | 2852 | its_lpi_free(vm->db_bitmap, vm->db_lpi_base, vm->nr_db_lpis); |
2756 | its_free_prop_table(vm->vprop_page); | 2853 | its_free_prop_table(vm->vprop_page); |
2757 | } | 2854 | } |
2758 | } | 2855 | } |
@@ -2767,18 +2864,18 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq | |||
2767 | 2864 | ||
2768 | BUG_ON(!vm); | 2865 | BUG_ON(!vm); |
2769 | 2866 | ||
2770 | bitmap = its_lpi_alloc_chunks(nr_irqs, &base, &nr_ids); | 2867 | bitmap = its_lpi_alloc(roundup_pow_of_two(nr_irqs), &base, &nr_ids); |
2771 | if (!bitmap) | 2868 | if (!bitmap) |
2772 | return -ENOMEM; | 2869 | return -ENOMEM; |
2773 | 2870 | ||
2774 | if (nr_ids < nr_irqs) { | 2871 | if (nr_ids < nr_irqs) { |
2775 | its_lpi_free_chunks(bitmap, base, nr_ids); | 2872 | its_lpi_free(bitmap, base, nr_ids); |
2776 | return -ENOMEM; | 2873 | return -ENOMEM; |
2777 | } | 2874 | } |
2778 | 2875 | ||
2779 | vprop_page = its_allocate_prop_table(GFP_KERNEL); | 2876 | vprop_page = its_allocate_prop_table(GFP_KERNEL); |
2780 | if (!vprop_page) { | 2877 | if (!vprop_page) { |
2781 | its_lpi_free_chunks(bitmap, base, nr_ids); | 2878 | its_lpi_free(bitmap, base, nr_ids); |
2782 | return -ENOMEM; | 2879 | return -ENOMEM; |
2783 | } | 2880 | } |
2784 | 2881 | ||
@@ -2805,7 +2902,7 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq | |||
2805 | if (i > 0) | 2902 | if (i > 0) |
2806 | its_vpe_irq_domain_free(domain, virq, i - 1); | 2903 | its_vpe_irq_domain_free(domain, virq, i - 1); |
2807 | 2904 | ||
2808 | its_lpi_free_chunks(bitmap, base, nr_ids); | 2905 | its_lpi_free(bitmap, base, nr_ids); |
2809 | its_free_prop_table(vprop_page); | 2906 | its_free_prop_table(vprop_page); |
2810 | } | 2907 | } |
2811 | 2908 | ||
@@ -3042,7 +3139,7 @@ static int its_save_disable(void) | |||
3042 | struct its_node *its; | 3139 | struct its_node *its; |
3043 | int err = 0; | 3140 | int err = 0; |
3044 | 3141 | ||
3045 | spin_lock(&its_lock); | 3142 | raw_spin_lock(&its_lock); |
3046 | list_for_each_entry(its, &its_nodes, entry) { | 3143 | list_for_each_entry(its, &its_nodes, entry) { |
3047 | void __iomem *base; | 3144 | void __iomem *base; |
3048 | 3145 | ||
@@ -3074,7 +3171,7 @@ err: | |||
3074 | writel_relaxed(its->ctlr_save, base + GITS_CTLR); | 3171 | writel_relaxed(its->ctlr_save, base + GITS_CTLR); |
3075 | } | 3172 | } |
3076 | } | 3173 | } |
3077 | spin_unlock(&its_lock); | 3174 | raw_spin_unlock(&its_lock); |
3078 | 3175 | ||
3079 | return err; | 3176 | return err; |
3080 | } | 3177 | } |
@@ -3084,7 +3181,7 @@ static void its_restore_enable(void) | |||
3084 | struct its_node *its; | 3181 | struct its_node *its; |
3085 | int ret; | 3182 | int ret; |
3086 | 3183 | ||
3087 | spin_lock(&its_lock); | 3184 | raw_spin_lock(&its_lock); |
3088 | list_for_each_entry(its, &its_nodes, entry) { | 3185 | list_for_each_entry(its, &its_nodes, entry) { |
3089 | void __iomem *base; | 3186 | void __iomem *base; |
3090 | int i; | 3187 | int i; |
@@ -3136,7 +3233,7 @@ static void its_restore_enable(void) | |||
3136 | GITS_TYPER_HCC(gic_read_typer(base + GITS_TYPER))) | 3233 | GITS_TYPER_HCC(gic_read_typer(base + GITS_TYPER))) |
3137 | its_cpu_init_collection(its); | 3234 | its_cpu_init_collection(its); |
3138 | } | 3235 | } |
3139 | spin_unlock(&its_lock); | 3236 | raw_spin_unlock(&its_lock); |
3140 | } | 3237 | } |
3141 | 3238 | ||
3142 | static struct syscore_ops its_syscore_ops = { | 3239 | static struct syscore_ops its_syscore_ops = { |
@@ -3370,9 +3467,9 @@ static int __init its_probe_one(struct resource *res, | |||
3370 | if (err) | 3467 | if (err) |
3371 | goto out_free_tables; | 3468 | goto out_free_tables; |
3372 | 3469 | ||
3373 | spin_lock(&its_lock); | 3470 | raw_spin_lock(&its_lock); |
3374 | list_add(&its->entry, &its_nodes); | 3471 | list_add(&its->entry, &its_nodes); |
3375 | spin_unlock(&its_lock); | 3472 | raw_spin_unlock(&its_lock); |
3376 | 3473 | ||
3377 | return 0; | 3474 | return 0; |
3378 | 3475 | ||
@@ -3399,6 +3496,16 @@ static int redist_disable_lpis(void) | |||
3399 | u64 timeout = USEC_PER_SEC; | 3496 | u64 timeout = USEC_PER_SEC; |
3400 | u64 val; | 3497 | u64 val; |
3401 | 3498 | ||
3499 | /* | ||
3500 | * If coming via a CPU hotplug event, we don't need to disable | ||
3501 | * LPIs before trying to re-enable them. They are already | ||
3502 | * configured and all is well in the world. Detect this case | ||
3503 | * by checking the allocation of the pending table for the | ||
3504 | * current CPU. | ||
3505 | */ | ||
3506 | if (gic_data_rdist()->pend_page) | ||
3507 | return 0; | ||
3508 | |||
3402 | if (!gic_rdists_supports_plpis()) { | 3509 | if (!gic_rdists_supports_plpis()) { |
3403 | pr_info("CPU%d: LPIs not supported\n", smp_processor_id()); | 3510 | pr_info("CPU%d: LPIs not supported\n", smp_processor_id()); |
3404 | return -ENXIO; | 3511 | return -ENXIO; |
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 76ea56d779a1..e214181b77b7 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c | |||
@@ -877,7 +877,7 @@ static struct irq_chip gic_eoimode1_chip = { | |||
877 | .flags = IRQCHIP_SET_TYPE_MASKED, | 877 | .flags = IRQCHIP_SET_TYPE_MASKED, |
878 | }; | 878 | }; |
879 | 879 | ||
880 | #define GIC_ID_NR (1U << gic_data.rdists.id_bits) | 880 | #define GIC_ID_NR (1U << GICD_TYPER_ID_BITS(gic_data.rdists.gicd_typer)) |
881 | 881 | ||
882 | static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, | 882 | static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, |
883 | irq_hw_number_t hw) | 883 | irq_hw_number_t hw) |
@@ -1091,7 +1091,7 @@ static int __init gic_init_bases(void __iomem *dist_base, | |||
1091 | * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI) | 1091 | * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI) |
1092 | */ | 1092 | */ |
1093 | typer = readl_relaxed(gic_data.dist_base + GICD_TYPER); | 1093 | typer = readl_relaxed(gic_data.dist_base + GICD_TYPER); |
1094 | gic_data.rdists.id_bits = GICD_TYPER_ID_BITS(typer); | 1094 | gic_data.rdists.gicd_typer = typer; |
1095 | gic_irqs = GICD_TYPER_IRQS(typer); | 1095 | gic_irqs = GICD_TYPER_IRQS(typer); |
1096 | if (gic_irqs > 1020) | 1096 | if (gic_irqs > 1020) |
1097 | gic_irqs = 1020; | 1097 | gic_irqs = 1020; |
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c index 1ec3bfe56693..c671b3212010 100644 --- a/drivers/irqchip/irq-ls-scfg-msi.c +++ b/drivers/irqchip/irq-ls-scfg-msi.c | |||
@@ -93,8 +93,12 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg) | |||
93 | msg->address_lo = lower_32_bits(msi_data->msiir_addr); | 93 | msg->address_lo = lower_32_bits(msi_data->msiir_addr); |
94 | msg->data = data->hwirq; | 94 | msg->data = data->hwirq; |
95 | 95 | ||
96 | if (msi_affinity_flag) | 96 | if (msi_affinity_flag) { |
97 | msg->data |= cpumask_first(data->common->affinity); | 97 | const struct cpumask *mask; |
98 | |||
99 | mask = irq_data_get_effective_affinity_mask(data); | ||
100 | msg->data |= cpumask_first(mask); | ||
101 | } | ||
98 | 102 | ||
99 | iommu_dma_map_msi_msg(data->irq, msg); | 103 | iommu_dma_map_msi_msg(data->irq, msg); |
100 | } | 104 | } |
@@ -121,7 +125,7 @@ static int ls_scfg_msi_set_affinity(struct irq_data *irq_data, | |||
121 | return -EINVAL; | 125 | return -EINVAL; |
122 | } | 126 | } |
123 | 127 | ||
124 | cpumask_copy(irq_data->common->affinity, mask); | 128 | irq_data_update_effective_affinity(irq_data, cpumask_of(cpu)); |
125 | 129 | ||
126 | return IRQ_SET_MASK_OK; | 130 | return IRQ_SET_MASK_OK; |
127 | } | 131 | } |