From patchwork Sat May 30 03:19:14 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "majun (F)" X-Patchwork-Id: 6512301 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 7D18EC0020 for ; Sat, 30 May 2015 03:23:29 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0519F207C0 for ; Sat, 30 May 2015 03:23:28 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B8EF3207BE for ; Sat, 30 May 2015 03:23:26 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YyXJx-00020W-Kr; Sat, 30 May 2015 03:20:25 +0000 Received: from szxga01-in.huawei.com ([58.251.152.64]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YyXJi-0000nT-VN for linux-arm-kernel@lists.infradead.org; Sat, 30 May 2015 03:20:13 +0000 Received: from 172.24.2.119 (EHLO SZXEML429-HUB.china.huawei.com) ([172.24.2.119]) by szxrg01-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id COR93504; Sat, 30 May 2015 11:19:22 +0800 (CST) Received: from [127.0.0.1] (10.177.236.124) by SZXEML429-HUB.china.huawei.com (10.82.67.184) with Microsoft SMTP Server id 14.3.158.1; Sat, 30 May 2015 11:19:15 +0800 Message-ID: <55692C32.2050209@huawei.com> Date: Sat, 30 May 2015 11:19:14 +0800 From: "majun (F)" User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:31.0) Gecko/20100101 Thunderbird/31.2.0 MIME-Version: 1.0 To: catalin Marinas , LKML , linux-arm-kernel , Will Deacon , Mark Rutland , Marc Zyngier Subject: [PATCH 3/4]: Change arm-gic-its to support the Mbigen interrupt X-Originating-IP: [10.177.236.124] X-CFilter-Loop: Reflected X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150529_202011_835832_5266D5F9 X-CRM114-Status: GOOD ( 19.60 ) X-Spam-Score: -0.0 (/) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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 #include #include +#include #include #include #include @@ -30,7 +31,7 @@ #include #include -#include +#include #include #include @@ -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 + * + * + * 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 . + */ +#ifndef __LINUX_IRQCHIP_ARM_GIC_ITS_H +#define __LINUX_IRQCHIP_ARM_GIC_ITS_H + +#include + +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); } /**