diff options
Diffstat (limited to 'drivers/irqchip/irq-gic-v3-its.c')
-rw-r--r-- | drivers/irqchip/irq-gic-v3-its.c | 43 |
1 files changed, 33 insertions, 10 deletions
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index e8d89343d613..e88395605e32 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c | |||
@@ -107,6 +107,10 @@ struct its_node { | |||
107 | 107 | ||
108 | #define ITS_ITT_ALIGN SZ_256 | 108 | #define ITS_ITT_ALIGN SZ_256 |
109 | 109 | ||
110 | /* The maximum number of VPEID bits supported by VLPI commands */ | ||
111 | #define ITS_MAX_VPEID_BITS (16) | ||
112 | #define ITS_MAX_VPEID (1 << (ITS_MAX_VPEID_BITS)) | ||
113 | |||
110 | /* Convert page order to size in bytes */ | 114 | /* Convert page order to size in bytes */ |
111 | #define PAGE_ORDER_TO_SIZE(o) (PAGE_SIZE << (o)) | 115 | #define PAGE_ORDER_TO_SIZE(o) (PAGE_SIZE << (o)) |
112 | 116 | ||
@@ -308,7 +312,7 @@ static void its_encode_size(struct its_cmd_block *cmd, u8 size) | |||
308 | 312 | ||
309 | static void its_encode_itt(struct its_cmd_block *cmd, u64 itt_addr) | 313 | static void its_encode_itt(struct its_cmd_block *cmd, u64 itt_addr) |
310 | { | 314 | { |
311 | its_mask_encode(&cmd->raw_cmd[2], itt_addr >> 8, 50, 8); | 315 | its_mask_encode(&cmd->raw_cmd[2], itt_addr >> 8, 51, 8); |
312 | } | 316 | } |
313 | 317 | ||
314 | static void its_encode_valid(struct its_cmd_block *cmd, int valid) | 318 | static void its_encode_valid(struct its_cmd_block *cmd, int valid) |
@@ -318,7 +322,7 @@ static void its_encode_valid(struct its_cmd_block *cmd, int valid) | |||
318 | 322 | ||
319 | static void its_encode_target(struct its_cmd_block *cmd, u64 target_addr) | 323 | static void its_encode_target(struct its_cmd_block *cmd, u64 target_addr) |
320 | { | 324 | { |
321 | its_mask_encode(&cmd->raw_cmd[2], target_addr >> 16, 50, 16); | 325 | its_mask_encode(&cmd->raw_cmd[2], target_addr >> 16, 51, 16); |
322 | } | 326 | } |
323 | 327 | ||
324 | static void its_encode_collection(struct its_cmd_block *cmd, u16 col) | 328 | static void its_encode_collection(struct its_cmd_block *cmd, u16 col) |
@@ -358,7 +362,7 @@ static void its_encode_its_list(struct its_cmd_block *cmd, u16 its_list) | |||
358 | 362 | ||
359 | static void its_encode_vpt_addr(struct its_cmd_block *cmd, u64 vpt_pa) | 363 | static void its_encode_vpt_addr(struct its_cmd_block *cmd, u64 vpt_pa) |
360 | { | 364 | { |
361 | its_mask_encode(&cmd->raw_cmd[3], vpt_pa >> 16, 50, 16); | 365 | its_mask_encode(&cmd->raw_cmd[3], vpt_pa >> 16, 51, 16); |
362 | } | 366 | } |
363 | 367 | ||
364 | static void its_encode_vpt_size(struct its_cmd_block *cmd, u8 vpt_size) | 368 | static void its_encode_vpt_size(struct its_cmd_block *cmd, u8 vpt_size) |
@@ -1478,9 +1482,9 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, | |||
1478 | u64 val = its_read_baser(its, baser); | 1482 | u64 val = its_read_baser(its, baser); |
1479 | u64 esz = GITS_BASER_ENTRY_SIZE(val); | 1483 | u64 esz = GITS_BASER_ENTRY_SIZE(val); |
1480 | u64 type = GITS_BASER_TYPE(val); | 1484 | u64 type = GITS_BASER_TYPE(val); |
1485 | u64 baser_phys, tmp; | ||
1481 | u32 alloc_pages; | 1486 | u32 alloc_pages; |
1482 | void *base; | 1487 | void *base; |
1483 | u64 tmp; | ||
1484 | 1488 | ||
1485 | retry_alloc_baser: | 1489 | retry_alloc_baser: |
1486 | alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz); | 1490 | alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz); |
@@ -1496,8 +1500,24 @@ retry_alloc_baser: | |||
1496 | if (!base) | 1500 | if (!base) |
1497 | return -ENOMEM; | 1501 | return -ENOMEM; |
1498 | 1502 | ||
1503 | baser_phys = virt_to_phys(base); | ||
1504 | |||
1505 | /* Check if the physical address of the memory is above 48bits */ | ||
1506 | if (IS_ENABLED(CONFIG_ARM64_64K_PAGES) && (baser_phys >> 48)) { | ||
1507 | |||
1508 | /* 52bit PA is supported only when PageSize=64K */ | ||
1509 | if (psz != SZ_64K) { | ||
1510 | pr_err("ITS: no 52bit PA support when psz=%d\n", psz); | ||
1511 | free_pages((unsigned long)base, order); | ||
1512 | return -ENXIO; | ||
1513 | } | ||
1514 | |||
1515 | /* Convert 52bit PA to 48bit field */ | ||
1516 | baser_phys = GITS_BASER_PHYS_52_to_48(baser_phys); | ||
1517 | } | ||
1518 | |||
1499 | retry_baser: | 1519 | retry_baser: |
1500 | val = (virt_to_phys(base) | | 1520 | val = (baser_phys | |
1501 | (type << GITS_BASER_TYPE_SHIFT) | | 1521 | (type << GITS_BASER_TYPE_SHIFT) | |
1502 | ((esz - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) | | 1522 | ((esz - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) | |
1503 | ((alloc_pages - 1) << GITS_BASER_PAGES_SHIFT) | | 1523 | ((alloc_pages - 1) << GITS_BASER_PAGES_SHIFT) | |
@@ -1582,13 +1602,12 @@ retry_baser: | |||
1582 | 1602 | ||
1583 | static bool its_parse_indirect_baser(struct its_node *its, | 1603 | static bool its_parse_indirect_baser(struct its_node *its, |
1584 | struct its_baser *baser, | 1604 | struct its_baser *baser, |
1585 | u32 psz, u32 *order) | 1605 | u32 psz, u32 *order, u32 ids) |
1586 | { | 1606 | { |
1587 | u64 tmp = its_read_baser(its, baser); | 1607 | u64 tmp = its_read_baser(its, baser); |
1588 | u64 type = GITS_BASER_TYPE(tmp); | 1608 | u64 type = GITS_BASER_TYPE(tmp); |
1589 | u64 esz = GITS_BASER_ENTRY_SIZE(tmp); | 1609 | u64 esz = GITS_BASER_ENTRY_SIZE(tmp); |
1590 | u64 val = GITS_BASER_InnerShareable | GITS_BASER_RaWaWb; | 1610 | u64 val = GITS_BASER_InnerShareable | GITS_BASER_RaWaWb; |
1591 | u32 ids = its->device_ids; | ||
1592 | u32 new_order = *order; | 1611 | u32 new_order = *order; |
1593 | bool indirect = false; | 1612 | bool indirect = false; |
1594 | 1613 | ||
@@ -1680,9 +1699,13 @@ static int its_alloc_tables(struct its_node *its) | |||
1680 | continue; | 1699 | continue; |
1681 | 1700 | ||
1682 | case GITS_BASER_TYPE_DEVICE: | 1701 | case GITS_BASER_TYPE_DEVICE: |
1702 | indirect = its_parse_indirect_baser(its, baser, | ||
1703 | psz, &order, | ||
1704 | its->device_ids); | ||
1683 | case GITS_BASER_TYPE_VCPU: | 1705 | case GITS_BASER_TYPE_VCPU: |
1684 | indirect = its_parse_indirect_baser(its, baser, | 1706 | indirect = its_parse_indirect_baser(its, baser, |
1685 | psz, &order); | 1707 | psz, &order, |
1708 | ITS_MAX_VPEID_BITS); | ||
1686 | break; | 1709 | break; |
1687 | } | 1710 | } |
1688 | 1711 | ||
@@ -2551,7 +2574,7 @@ static struct irq_chip its_vpe_irq_chip = { | |||
2551 | 2574 | ||
2552 | static int its_vpe_id_alloc(void) | 2575 | static int its_vpe_id_alloc(void) |
2553 | { | 2576 | { |
2554 | return ida_simple_get(&its_vpeid_ida, 0, 1 << 16, GFP_KERNEL); | 2577 | return ida_simple_get(&its_vpeid_ida, 0, ITS_MAX_VPEID, GFP_KERNEL); |
2555 | } | 2578 | } |
2556 | 2579 | ||
2557 | static void its_vpe_id_free(u16 id) | 2580 | static void its_vpe_id_free(u16 id) |
@@ -2851,7 +2874,7 @@ static int its_init_vpe_domain(void) | |||
2851 | return -ENOMEM; | 2874 | return -ENOMEM; |
2852 | } | 2875 | } |
2853 | 2876 | ||
2854 | BUG_ON(entries != vpe_proxy.dev->nr_ites); | 2877 | BUG_ON(entries > vpe_proxy.dev->nr_ites); |
2855 | 2878 | ||
2856 | raw_spin_lock_init(&vpe_proxy.lock); | 2879 | raw_spin_lock_init(&vpe_proxy.lock); |
2857 | vpe_proxy.next_victim = 0; | 2880 | vpe_proxy.next_victim = 0; |