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; |
