aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c242
-rw-r--r--include/linux/irqchip/arm-gic-v3.h1
2 files changed, 127 insertions, 116 deletions
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 5cfa29991eed..146189b1b587 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -56,13 +56,14 @@ struct its_collection {
56}; 56};
57 57
58/* 58/*
59 * The ITS_BASER structure - contains memory information and cached 59 * The ITS_BASER structure - contains memory information, cached
60 * value of BASER register configuration. 60 * value of BASER register configuration and ITS page size.
61 */ 61 */
62struct its_baser { 62struct its_baser {
63 void *base; 63 void *base;
64 u64 val; 64 u64 val;
65 u32 order; 65 u32 order;
66 u32 psz;
66}; 67};
67 68
68/* 69/*
@@ -840,6 +841,110 @@ static void its_write_baser(struct its_node *its, struct its_baser *baser,
840 baser->val = its_read_baser(its, baser); 841 baser->val = its_read_baser(its, baser);
841} 842}
842 843
844static int its_setup_baser(struct its_node *its, struct its_baser *baser,
845 u64 cache, u64 shr, u32 psz, u32 order)
846{
847 u64 val = its_read_baser(its, baser);
848 u64 esz = GITS_BASER_ENTRY_SIZE(val);
849 u64 type = GITS_BASER_TYPE(val);
850 u32 alloc_pages;
851 void *base;
852 u64 tmp;
853
854retry_alloc_baser:
855 alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
856 if (alloc_pages > GITS_BASER_PAGES_MAX) {
857 pr_warn("ITS@%pa: %s too large, reduce ITS pages %u->%u\n",
858 &its->phys_base, its_base_type_string[type],
859 alloc_pages, GITS_BASER_PAGES_MAX);
860 alloc_pages = GITS_BASER_PAGES_MAX;
861 order = get_order(GITS_BASER_PAGES_MAX * psz);
862 }
863
864 base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
865 if (!base)
866 return -ENOMEM;
867
868retry_baser:
869 val = (virt_to_phys(base) |
870 (type << GITS_BASER_TYPE_SHIFT) |
871 ((esz - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) |
872 ((alloc_pages - 1) << GITS_BASER_PAGES_SHIFT) |
873 cache |
874 shr |
875 GITS_BASER_VALID);
876
877 switch (psz) {
878 case SZ_4K:
879 val |= GITS_BASER_PAGE_SIZE_4K;
880 break;
881 case SZ_16K:
882 val |= GITS_BASER_PAGE_SIZE_16K;
883 break;
884 case SZ_64K:
885 val |= GITS_BASER_PAGE_SIZE_64K;
886 break;
887 }
888
889 its_write_baser(its, baser, val);
890 tmp = baser->val;
891
892 if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) {
893 /*
894 * Shareability didn't stick. Just use
895 * whatever the read reported, which is likely
896 * to be the only thing this redistributor
897 * supports. If that's zero, make it
898 * non-cacheable as well.
899 */
900 shr = tmp & GITS_BASER_SHAREABILITY_MASK;
901 if (!shr) {
902 cache = GITS_BASER_nC;
903 __flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order));
904 }
905 goto retry_baser;
906 }
907
908 if ((val ^ tmp) & GITS_BASER_PAGE_SIZE_MASK) {
909 /*
910 * Page size didn't stick. Let's try a smaller
911 * size and retry. If we reach 4K, then
912 * something is horribly wrong...
913 */
914 free_pages((unsigned long)base, order);
915 baser->base = NULL;
916
917 switch (psz) {
918 case SZ_16K:
919 psz = SZ_4K;
920 goto retry_alloc_baser;
921 case SZ_64K:
922 psz = SZ_16K;
923 goto retry_alloc_baser;
924 }
925 }
926
927 if (val != tmp) {
928 pr_err("ITS@%pa: %s doesn't stick: %lx %lx\n",
929 &its->phys_base, its_base_type_string[type],
930 (unsigned long) val, (unsigned long) tmp);
931 free_pages((unsigned long)base, order);
932 return -ENXIO;
933 }
934
935 baser->order = order;
936 baser->base = base;
937 baser->psz = psz;
938
939 pr_info("ITS@%pa: allocated %d %s @%lx (psz %dK, shr %d)\n",
940 &its->phys_base, (int)(PAGE_ORDER_TO_SIZE(order) / esz),
941 its_base_type_string[type],
942 (unsigned long)virt_to_phys(base),
943 psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
944
945 return 0;
946}
947
843static void its_parse_baser_device(struct its_node *its, struct its_baser *baser, 948static void its_parse_baser_device(struct its_node *its, struct its_baser *baser,
844 u32 *order) 949 u32 *order)
845{ 950{
@@ -879,25 +984,20 @@ static void its_free_tables(struct its_node *its)
879 984
880static int its_alloc_tables(const char *node_name, struct its_node *its) 985static int its_alloc_tables(const char *node_name, struct its_node *its)
881{ 986{
882 int err; 987 u64 typer = readq_relaxed(its->base + GITS_TYPER);
883 int i; 988 u32 ids = GITS_TYPER_DEVBITS(typer);
884 int psz = SZ_64K;
885 u64 shr = GITS_BASER_InnerShareable; 989 u64 shr = GITS_BASER_InnerShareable;
886 u64 cache; 990 u64 cache = GITS_BASER_WaWb;
887 u64 typer; 991 u32 psz = SZ_64K;
888 u32 ids; 992 int err, i;
889 993
890 if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_22375) { 994 if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_22375) {
891 /* 995 /*
892 * erratum 22375: only alloc 8MB table size 996 * erratum 22375: only alloc 8MB table size
893 * erratum 24313: ignore memory access type 997 * erratum 24313: ignore memory access type
894 */ 998 */
895 cache = 0; 999 cache = GITS_BASER_nCnB;
896 ids = 0x14; /* 20 bits, 8MB */ 1000 ids = 0x14; /* 20 bits, 8MB */
897 } else {
898 cache = GITS_BASER_WaWb;
899 typer = readq_relaxed(its->base + GITS_TYPER);
900 ids = GITS_TYPER_DEVBITS(typer);
901 } 1001 }
902 1002
903 its->device_ids = ids; 1003 its->device_ids = ids;
@@ -906,11 +1006,7 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
906 struct its_baser *baser = its->tables + i; 1006 struct its_baser *baser = its->tables + i;
907 u64 val = its_read_baser(its, baser); 1007 u64 val = its_read_baser(its, baser);
908 u64 type = GITS_BASER_TYPE(val); 1008 u64 type = GITS_BASER_TYPE(val);
909 u64 entry_size = GITS_BASER_ENTRY_SIZE(val); 1009 u32 order = get_order(psz);
910 int order = get_order(psz);
911 int alloc_pages;
912 u64 tmp;
913 void *base;
914 1010
915 if (type == GITS_BASER_TYPE_NONE) 1011 if (type == GITS_BASER_TYPE_NONE)
916 continue; 1012 continue;
@@ -918,105 +1014,19 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
918 if (type == GITS_BASER_TYPE_DEVICE) 1014 if (type == GITS_BASER_TYPE_DEVICE)
919 its_parse_baser_device(its, baser, &order); 1015 its_parse_baser_device(its, baser, &order);
920 1016
921retry_alloc_baser: 1017 err = its_setup_baser(its, baser, cache, shr, psz, order);
922 alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz); 1018 if (err < 0) {
923 if (alloc_pages > GITS_BASER_PAGES_MAX) { 1019 its_free_tables(its);
924 alloc_pages = GITS_BASER_PAGES_MAX; 1020 return err;
925 order = get_order(GITS_BASER_PAGES_MAX * psz);
926 pr_warn("%s: Device Table too large, reduce its page order to %u (%u pages)\n",
927 node_name, order, alloc_pages);
928 }
929
930 base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
931 if (!base) {
932 err = -ENOMEM;
933 goto out_free;
934 }
935
936 its->tables[i].base = base;
937 its->tables[i].order = order;
938
939retry_baser:
940 val = (virt_to_phys(base) |
941 (type << GITS_BASER_TYPE_SHIFT) |
942 ((entry_size - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) |
943 cache |
944 shr |
945 GITS_BASER_VALID);
946
947 switch (psz) {
948 case SZ_4K:
949 val |= GITS_BASER_PAGE_SIZE_4K;
950 break;
951 case SZ_16K:
952 val |= GITS_BASER_PAGE_SIZE_16K;
953 break;
954 case SZ_64K:
955 val |= GITS_BASER_PAGE_SIZE_64K;
956 break;
957 }
958
959 val |= alloc_pages - 1;
960
961 its_write_baser_cache(its, baser, val);
962 tmp = baser->val;
963
964 if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) {
965 /*
966 * Shareability didn't stick. Just use
967 * whatever the read reported, which is likely
968 * to be the only thing this redistributor
969 * supports. If that's zero, make it
970 * non-cacheable as well.
971 */
972 shr = tmp & GITS_BASER_SHAREABILITY_MASK;
973 if (!shr) {
974 cache = GITS_BASER_nC;
975 __flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order));
976 }
977 goto retry_baser;
978 }
979
980 if ((val ^ tmp) & GITS_BASER_PAGE_SIZE_MASK) {
981 /*
982 * Page size didn't stick. Let's try a smaller
983 * size and retry. If we reach 4K, then
984 * something is horribly wrong...
985 */
986 free_pages((unsigned long)base, order);
987 its->tables[i].base = NULL;
988
989 switch (psz) {
990 case SZ_16K:
991 psz = SZ_4K;
992 goto retry_alloc_baser;
993 case SZ_64K:
994 psz = SZ_16K;
995 goto retry_alloc_baser;
996 }
997 }
998
999 if (val != tmp) {
1000 pr_err("ITS: %s: GITS_BASER%d doesn't stick: %lx %lx\n",
1001 node_name, i,
1002 (unsigned long) val, (unsigned long) tmp);
1003 err = -ENXIO;
1004 goto out_free;
1005 } 1021 }
1006 1022
1007 pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n", 1023 /* Update settings which will be used for next BASERn */
1008 (int)(PAGE_ORDER_TO_SIZE(order) / entry_size), 1024 psz = baser->psz;
1009 its_base_type_string[type], 1025 cache = baser->val & GITS_BASER_CACHEABILITY_MASK;
1010 (unsigned long)virt_to_phys(base), 1026 shr = baser->val & GITS_BASER_SHAREABILITY_MASK;
1011 psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
1012 } 1027 }
1013 1028
1014 return 0; 1029 return 0;
1015
1016out_free:
1017 its_free_tables(its);
1018
1019 return err;
1020} 1030}
1021 1031
1022static int its_alloc_collections(struct its_node *its) 1032static int its_alloc_collections(struct its_node *its)
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index dc493e0f0ff7..01cf171ef97d 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -228,6 +228,7 @@
228#define GITS_BASER_PAGE_SIZE_64K (2UL << GITS_BASER_PAGE_SIZE_SHIFT) 228#define GITS_BASER_PAGE_SIZE_64K (2UL << GITS_BASER_PAGE_SIZE_SHIFT)
229#define GITS_BASER_PAGE_SIZE_MASK (3UL << GITS_BASER_PAGE_SIZE_SHIFT) 229#define GITS_BASER_PAGE_SIZE_MASK (3UL << GITS_BASER_PAGE_SIZE_SHIFT)
230#define GITS_BASER_PAGES_MAX 256 230#define GITS_BASER_PAGES_MAX 256
231#define GITS_BASER_PAGES_SHIFT (0)
231 232
232#define GITS_BASER_TYPE_NONE 0 233#define GITS_BASER_TYPE_NONE 0
233#define GITS_BASER_TYPE_DEVICE 1 234#define GITS_BASER_TYPE_DEVICE 1