lkml.org 
[lkml]   [2017]   [Oct]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[GIT pull] irq fixes for 4.14
    Linus,

    please pull the latest irq-urgent-for-linus git tree from:

    git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq-urgent-for-linus

    A set of small fixes mostly in the irq drivers area:

    - Make the tango irq chip work correctly, which requires a new function in
    the generiq irq chip implementation

    - A set of updates to the GIC-V3 ITS driver removing a bogus BUG_ON() and
    parsing the VCPU table size correctly.

    Thanks,

    tglx

    ------------------>
    Doug Berger (2):
    genirq: generic chip: Add irq_gc_mask_disable_and_ack_set()
    genirq: generic chip: remove irq_gc_mask_disable_reg_and_ack()

    Florian Fainelli (1):
    irqchip/tango: Use irq_gc_mask_disable_and_ack_set

    Julien Grall (1):
    DT: arm,gic-v3: Update the ITS size in the examples

    Shanker Donthineni (3):
    irqchip/gic-v3-its: Fix the incorrect BUG_ON in its_init_vpe_domain()
    irqchip/gic-v3-its: Fix the incorrect parsing of VCPU table size
    irqchip/gic-v3-its: Add missing changes to support 52bit physical address


    .../bindings/interrupt-controller/arm,gic-v3.txt | 6 +--
    drivers/irqchip/irq-gic-v3-its.c | 43 +++++++++++++++++-----
    drivers/irqchip/irq-tango.c | 2 +-
    include/linux/irq.h | 2 +-
    include/linux/irqchip/arm-gic-v3.h | 2 +
    kernel/irq/generic-chip.c | 15 ++++++--
    6 files changed, 52 insertions(+), 18 deletions(-)

    diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
    index 4c29cdab0ea5..5eb108e180fa 100644
    --- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
    +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
    @@ -99,7 +99,7 @@ Examples:
    compatible = "arm,gic-v3-its";
    msi-controller;
    #msi-cells = <1>;
    - reg = <0x0 0x2c200000 0 0x200000>;
    + reg = <0x0 0x2c200000 0 0x20000>;
    };
    };

    @@ -124,14 +124,14 @@ Examples:
    compatible = "arm,gic-v3-its";
    msi-controller;
    #msi-cells = <1>;
    - reg = <0x0 0x2c200000 0 0x200000>;
    + reg = <0x0 0x2c200000 0 0x20000>;
    };

    gic-its@2c400000 {
    compatible = "arm,gic-v3-its";
    msi-controller;
    #msi-cells = <1>;
    - reg = <0x0 0x2c400000 0 0x200000>;
    + reg = <0x0 0x2c400000 0 0x20000>;
    };

    ppi-partitions {
    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 {

    #define ITS_ITT_ALIGN SZ_256

    +/* The maximum number of VPEID bits supported by VLPI commands */
    +#define ITS_MAX_VPEID_BITS (16)
    +#define ITS_MAX_VPEID (1 << (ITS_MAX_VPEID_BITS))
    +
    /* Convert page order to size in bytes */
    #define PAGE_ORDER_TO_SIZE(o) (PAGE_SIZE << (o))

    @@ -308,7 +312,7 @@ static void its_encode_size(struct its_cmd_block *cmd, u8 size)

    static void its_encode_itt(struct its_cmd_block *cmd, u64 itt_addr)
    {
    - its_mask_encode(&cmd->raw_cmd[2], itt_addr >> 8, 50, 8);
    + its_mask_encode(&cmd->raw_cmd[2], itt_addr >> 8, 51, 8);
    }

    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)

    static void its_encode_target(struct its_cmd_block *cmd, u64 target_addr)
    {
    - its_mask_encode(&cmd->raw_cmd[2], target_addr >> 16, 50, 16);
    + its_mask_encode(&cmd->raw_cmd[2], target_addr >> 16, 51, 16);
    }

    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)

    static void its_encode_vpt_addr(struct its_cmd_block *cmd, u64 vpt_pa)
    {
    - its_mask_encode(&cmd->raw_cmd[3], vpt_pa >> 16, 50, 16);
    + its_mask_encode(&cmd->raw_cmd[3], vpt_pa >> 16, 51, 16);
    }

    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,
    u64 val = its_read_baser(its, baser);
    u64 esz = GITS_BASER_ENTRY_SIZE(val);
    u64 type = GITS_BASER_TYPE(val);
    + u64 baser_phys, tmp;
    u32 alloc_pages;
    void *base;
    - u64 tmp;

    retry_alloc_baser:
    alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
    @@ -1496,8 +1500,24 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser,
    if (!base)
    return -ENOMEM;

    + baser_phys = virt_to_phys(base);
    +
    + /* Check if the physical address of the memory is above 48bits */
    + if (IS_ENABLED(CONFIG_ARM64_64K_PAGES) && (baser_phys >> 48)) {
    +
    + /* 52bit PA is supported only when PageSize=64K */
    + if (psz != SZ_64K) {
    + pr_err("ITS: no 52bit PA support when psz=%d\n", psz);
    + free_pages((unsigned long)base, order);
    + return -ENXIO;
    + }
    +
    + /* Convert 52bit PA to 48bit field */
    + baser_phys = GITS_BASER_PHYS_52_to_48(baser_phys);
    + }
    +
    retry_baser:
    - val = (virt_to_phys(base) |
    + val = (baser_phys |
    (type << GITS_BASER_TYPE_SHIFT) |
    ((esz - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) |
    ((alloc_pages - 1) << GITS_BASER_PAGES_SHIFT) |
    @@ -1582,13 +1602,12 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser,

    static bool its_parse_indirect_baser(struct its_node *its,
    struct its_baser *baser,
    - u32 psz, u32 *order)
    + u32 psz, u32 *order, u32 ids)
    {
    u64 tmp = its_read_baser(its, baser);
    u64 type = GITS_BASER_TYPE(tmp);
    u64 esz = GITS_BASER_ENTRY_SIZE(tmp);
    u64 val = GITS_BASER_InnerShareable | GITS_BASER_RaWaWb;
    - u32 ids = its->device_ids;
    u32 new_order = *order;
    bool indirect = false;

    @@ -1680,9 +1699,13 @@ static int its_alloc_tables(struct its_node *its)
    continue;

    case GITS_BASER_TYPE_DEVICE:
    + indirect = its_parse_indirect_baser(its, baser,
    + psz, &order,
    + its->device_ids);
    case GITS_BASER_TYPE_VCPU:
    indirect = its_parse_indirect_baser(its, baser,
    - psz, &order);
    + psz, &order,
    + ITS_MAX_VPEID_BITS);
    break;
    }

    @@ -2551,7 +2574,7 @@ static struct irq_chip its_vpe_irq_chip = {

    static int its_vpe_id_alloc(void)
    {
    - return ida_simple_get(&its_vpeid_ida, 0, 1 << 16, GFP_KERNEL);
    + return ida_simple_get(&its_vpeid_ida, 0, ITS_MAX_VPEID, GFP_KERNEL);
    }

    static void its_vpe_id_free(u16 id)
    @@ -2851,7 +2874,7 @@ static int its_init_vpe_domain(void)
    return -ENOMEM;
    }

    - BUG_ON(entries != vpe_proxy.dev->nr_ites);
    + BUG_ON(entries > vpe_proxy.dev->nr_ites);

    raw_spin_lock_init(&vpe_proxy.lock);
    vpe_proxy.next_victim = 0;
    diff --git a/drivers/irqchip/irq-tango.c b/drivers/irqchip/irq-tango.c
    index bdbb5c0ff7fe..0c085303a583 100644
    --- a/drivers/irqchip/irq-tango.c
    +++ b/drivers/irqchip/irq-tango.c
    @@ -141,7 +141,7 @@ static void __init tangox_irq_init_chip(struct irq_chip_generic *gc,
    for (i = 0; i < 2; i++) {
    ct[i].chip.irq_ack = irq_gc_ack_set_bit;
    ct[i].chip.irq_mask = irq_gc_mask_disable_reg;
    - ct[i].chip.irq_mask_ack = irq_gc_mask_disable_reg_and_ack;
    + ct[i].chip.irq_mask_ack = irq_gc_mask_disable_and_ack_set;
    ct[i].chip.irq_unmask = irq_gc_unmask_enable_reg;
    ct[i].chip.irq_set_type = tangox_irq_set_type;
    ct[i].chip.name = gc->domain->name;
    diff --git a/include/linux/irq.h b/include/linux/irq.h
    index d4728bf6a537..5ad10948ea95 100644
    --- a/include/linux/irq.h
    +++ b/include/linux/irq.h
    @@ -1009,7 +1009,7 @@ void irq_gc_mask_clr_bit(struct irq_data *d);
    void irq_gc_unmask_enable_reg(struct irq_data *d);
    void irq_gc_ack_set_bit(struct irq_data *d);
    void irq_gc_ack_clr_bit(struct irq_data *d);
    -void irq_gc_mask_disable_reg_and_ack(struct irq_data *d);
    +void irq_gc_mask_disable_and_ack_set(struct irq_data *d);
    void irq_gc_eoi(struct irq_data *d);
    int irq_gc_set_wake(struct irq_data *d, unsigned int on);

    diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
    index 1ea576c8126f..14b74f22d43c 100644
    --- a/include/linux/irqchip/arm-gic-v3.h
    +++ b/include/linux/irqchip/arm-gic-v3.h
    @@ -372,6 +372,8 @@
    #define GITS_BASER_ENTRY_SIZE_SHIFT (48)
    #define GITS_BASER_ENTRY_SIZE(r) ((((r) >> GITS_BASER_ENTRY_SIZE_SHIFT) & 0x1f) + 1)
    #define GITS_BASER_ENTRY_SIZE_MASK GENMASK_ULL(52, 48)
    +#define GITS_BASER_PHYS_52_to_48(phys) \
    + (((phys) & GENMASK_ULL(47, 16)) | (((phys) >> 48) & 0xf) << 12)
    #define GITS_BASER_SHAREABILITY_SHIFT (10)
    #define GITS_BASER_InnerShareable \
    GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable)
    diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c
    index 5270a54b9fa4..c26c5bb6b491 100644
    --- a/kernel/irq/generic-chip.c
    +++ b/kernel/irq/generic-chip.c
    @@ -135,17 +135,26 @@ void irq_gc_ack_clr_bit(struct irq_data *d)
    }

    /**
    - * irq_gc_mask_disable_reg_and_ack - Mask and ack pending interrupt
    + * irq_gc_mask_disable_and_ack_set - Mask and ack pending interrupt
    * @d: irq_data
    + *
    + * This generic implementation of the irq_mask_ack method is for chips
    + * with separate enable/disable registers instead of a single mask
    + * register and where a pending interrupt is acknowledged by setting a
    + * bit.
    + *
    + * Note: This is the only permutation currently used. Similar generic
    + * functions should be added here if other permutations are required.
    */
    -void irq_gc_mask_disable_reg_and_ack(struct irq_data *d)
    +void irq_gc_mask_disable_and_ack_set(struct irq_data *d)
    {
    struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
    struct irq_chip_type *ct = irq_data_get_chip_type(d);
    u32 mask = d->mask;

    irq_gc_lock(gc);
    - irq_reg_writel(gc, mask, ct->regs.mask);
    + irq_reg_writel(gc, mask, ct->regs.disable);
    + *ct->mask_cache &= ~mask;
    irq_reg_writel(gc, mask, ct->regs.ack);
    irq_gc_unlock(gc);
    }
    \
     
     \ /
      Last update: 2017-10-22 17:53    [W:4.049 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site