This patch is applied to support the mbigen interrupt.

Change log:
--For irq_mbigen.c using,move some struct and function definition
  to a new head file arm-gic-its.h
--Add a irq_write_mbi_msg member for mbi interrupt using
--For mbi interrupt, the event id depends on the Hardware pin number on mbigen,
  so, the its_get_event_id is changed to calclulate the event id of mbi 
interrupt
--For mbigen, the device id information need to be carried with msg. So,
  its_irq_compose_msi_msg is changed.
--its_mask_msi_irq and its_unmaks_msi_irq are modifid for mbi interrupt using.
--before the irq_ack callback, check the irq_ack first(chip.c)


Signed-off-by: Ma Jun <[email protected]>
---
 drivers/irqchip/irq-gic-v3-its.c    |   71 +++++++++++-----------------------
 include/linux/irq.h                 |    1 +
 include/linux/irqchip/arm-gic-its.h |   68 +++++++++++++++++++++++++++++++++
 kernel/irq/chip.c                   |   12 ++++--
 4 files changed, 100 insertions(+), 52 deletions(-)
 mode change 100644 => 100755 drivers/irqchip/irq-gic-v3-its.c
 create mode 100755 include/linux/irqchip/arm-gic-its.h

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
old mode 100644
new mode 100755
index 9687f8a..21c36bf
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -22,6 +22,7 @@
 #include <linux/log2.h>
 #include <linux/mm.h>
 #include <linux/msi.h>
+#include <linux/mbi.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -30,7 +31,7 @@
 #include <linux/percpu.h>
 #include <linux/slab.h>

-#include <linux/irqchip/arm-gic-v3.h>
+#include <linux/irqchip/arm-gic-its.h>

 #include <asm/cacheflush.h>
 #include <asm/cputype.h>
@@ -42,36 +43,6 @@

 #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING    (1 << 0)

-/*
- * Collection structure - just an ID, and a redistributor address to
- * ping. We use one per CPU as a bag of interrupts assigned to this
- * CPU.
- */
-struct its_collection {
-       u64                     target_address;
-       u16                     col_id;
-};
-
-/*
- * The ITS structure - contains most of the infrastructure, with the
- * msi_controller, the command queue, the collections, and the list of
- * devices writing to it.
- */
-struct its_node {
-       raw_spinlock_t          lock;
-       struct list_head        entry;
-       struct msi_controller   msi_chip;
-       struct irq_domain       *domain;
-       void __iomem            *base;
-       unsigned long           phys_base;
-       struct its_cmd_block    *cmd_base;
-       struct its_cmd_block    *cmd_write;
-       void                    *tables[GITS_BASER_NR_REGS];
-       struct its_collection   *collections;
-       struct list_head        its_device_list;
-       u64                     flags;
-       u32                     ite_size;
-};

 #define ITS_ITT_ALIGN          SZ_256

@@ -79,17 +50,6 @@ struct its_node {
  * The ITS view of a device - belongs to an ITS, a collection, owns an
  * interrupt translation table, and a list of interrupts.
  */
-struct its_device {
-       struct list_head        entry;
-       struct its_node         *its;
-       struct its_collection   *collection;
-       void                    *itt;
-       unsigned long           *lpi_map;
-       irq_hw_number_t         lpi_base;
-       int                     nr_lpis;
-       u32                     nr_ites;
-       u32                     device_id;
-};

 static LIST_HEAD(its_nodes);
 static DEFINE_SPINLOCK(its_lock);
@@ -528,7 +488,11 @@ static void its_send_invall(struct its_node *its, struct 
its_collection *col)
 static inline u32 its_get_event_id(struct irq_data *d)
 {
        struct its_device *its_dev = irq_data_get_irq_chip_data(d);
-       return d->hwirq - its_dev->lpi_base;
+
+       if (!is_mbigen_domain(d))
+               return d->hwirq - its_dev->lpi_base;
+       else
+               return get_mbi_offset(d->irq);
 }

 static void lpi_set_config(struct irq_data *d, bool enable)
@@ -599,7 +563,13 @@ static void its_irq_compose_msi_msg(struct irq_data *d, 
struct msi_msg *msg)

        msg->address_lo         = addr & ((1UL << 32) - 1);
        msg->address_hi         = addr >> 32;
-       msg->data               = its_get_event_id(d);
+
+       /*for devices connect to mbigen, device id
+        *information is needed*/
+       if (!is_mbigen_domain(d))
+               msg->data = its_get_event_id(d);
+       else
+               msg->data = (its_dev->device_id << 16) | its_get_event_id(d);
 }

 static struct irq_chip its_irq_chip = {
@@ -613,13 +583,15 @@ static struct irq_chip its_irq_chip = {

 static void its_mask_msi_irq(struct irq_data *d)
 {
-       pci_msi_mask_irq(d);
+       if (!is_mbigen_domain(d))
+               pci_msi_mask_irq(d);
        irq_chip_mask_parent(d);
 }

 static void its_unmask_msi_irq(struct irq_data *d)
 {
-       pci_msi_unmask_irq(d);
+       if (!is_mbigen_domain(d))
+               pci_msi_unmask_irq(d);
        irq_chip_unmask_parent(d);
 }

@@ -629,6 +601,8 @@ static struct irq_chip its_msi_irq_chip = {
        .irq_mask               = its_mask_msi_irq,
        .irq_eoi                = irq_chip_eoi_parent,
        .irq_write_msi_msg      = pci_msi_domain_write_msg,
+       .irq_write_mbi_msg      = mbigen_write_msg,
+       .irq_ack                = irq_chip_ack_parent,
 };

 /*
@@ -721,6 +695,7 @@ static void its_lpi_free(unsigned long *bitmap, int base, 
int nr_ids)

        for (lpi = base; lpi < (base + nr_ids); lpi += IRQS_PER_CHUNK) {
                int chunk = its_lpi_to_chunk(lpi);
+
                BUG_ON(chunk > lpi_chunks);
                if (test_bit(chunk, lpi_bitmap)) {
                        clear_bit(chunk, lpi_bitmap);
@@ -1067,7 +1042,7 @@ static void its_cpu_init_collection(void)
        spin_unlock(&its_lock);
 }

-static struct its_device *its_find_device(struct its_node *its, u32 dev_id)
+struct its_device *its_find_device(struct its_node *its, u32 dev_id)
 {
        struct its_device *its_dev = NULL, *tmp;
        unsigned long flags;
@@ -1086,7 +1061,7 @@ static struct its_device *its_find_device(struct its_node 
*its, u32 dev_id)
        return its_dev;
 }

-static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
+struct its_device *its_create_device(struct its_node *its, u32 dev_id,
                                            int nvecs)
 {
        struct its_device *dev;
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 62c6901..9a745a8 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -365,6 +365,7 @@ struct irq_chip {

        void            (*irq_compose_msi_msg)(struct irq_data *data, struct 
msi_msg *msg);
        void            (*irq_write_msi_msg)(struct irq_data *data, struct 
msi_msg *msg);
+       void            (*irq_write_mbi_msg)(struct irq_data *irq_data, struct 
msi_msg *msg);

        int             (*irq_get_irqchip_state)(struct irq_data *data, enum 
irqchip_irq_state which, bool *state);
        int             (*irq_set_irqchip_state)(struct irq_data *data, enum 
irqchip_irq_state which, bool state);
diff --git a/include/linux/irqchip/arm-gic-its.h 
b/include/linux/irqchip/arm-gic-its.h
new file mode 100755
index 0000000..5677114
--- /dev/null
+++ b/include/linux/irqchip/arm-gic-its.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2013, 2014 ARM Limited, All Rights Reserved.
+ * Author: Marc Zyngier <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __LINUX_IRQCHIP_ARM_GIC_ITS_H
+#define __LINUX_IRQCHIP_ARM_GIC_ITS_H
+
+#include <linux/irqchip/arm-gic-v3.h>
+
+struct its_device {
+       struct list_head        entry;
+       struct its_node         *its;
+       struct its_collection   *collection;
+       void                    *itt;
+       unsigned long           *lpi_map;
+       irq_hw_number_t         lpi_base;
+       int                     nr_lpis;
+       u32                     nr_ites;
+       u32                     device_id;
+};
+/*
+ * Collection structure - just an ID, and a redistributor address to
+ * ping. We use one per CPU as a bag of interrupts assigned to this
+ * CPU.
+ */
+struct its_collection {
+       u64                     target_address;
+       u16                     col_id;
+};
+
+/*
+ * The ITS structure - contains most of the infrastructure, with the
+ * msi_controller, the command queue, the collections, and the list of
+ * devices writing to it.
+ */
+struct its_node {
+       raw_spinlock_t          lock;
+       struct list_head        entry;
+       struct msi_controller   msi_chip;
+       struct irq_domain       *domain;
+       void __iomem            *base;
+       unsigned long           phys_base;
+       struct its_cmd_block    *cmd_base;
+       struct its_cmd_block    *cmd_write;
+       void                    *tables[GITS_BASER_NR_REGS];
+       struct its_collection   *collections;
+       struct list_head        its_device_list;
+       u64                     flags;
+       u32                     ite_size;
+};
+
+struct its_device *its_find_device(struct its_node *its, u32 dev_id);
+struct its_device *its_create_device(struct its_node *its, u32 dev_id,
+                                           int nvecs);
+#endif
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index eb9a4ea..3020efc 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -882,7 +882,8 @@ void irq_cpu_offline(void)
 void irq_chip_ack_parent(struct irq_data *data)
 {
        data = data->parent_data;
-       data->chip->irq_ack(data);
+       if (data->chip->irq_ack)
+               data->chip->irq_ack(data);
 }

 /**
@@ -892,7 +893,8 @@ void irq_chip_ack_parent(struct irq_data *data)
 void irq_chip_mask_parent(struct irq_data *data)
 {
        data = data->parent_data;
-       data->chip->irq_mask(data);
+       if (data->chip->irq_mask)
+               data->chip->irq_mask(data);
 }

 /**
@@ -902,7 +904,8 @@ void irq_chip_mask_parent(struct irq_data *data)
 void irq_chip_unmask_parent(struct irq_data *data)
 {
        data = data->parent_data;
-       data->chip->irq_unmask(data);
+       if (data->chip->irq_unmask)
+               data->chip->irq_unmask(data);
 }

 /**
@@ -912,7 +915,8 @@ void irq_chip_unmask_parent(struct irq_data *data)
 void irq_chip_eoi_parent(struct irq_data *data)
 {
        data = data->parent_data;
-       data->chip->irq_eoi(data);
+       if (data->chip->irq_eoi)
+               data->chip->irq_eoi(data);
 }

 /**
-- 
1.7.1



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to