From patchwork Tue Nov 11 15:48:09 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Zyngier X-Patchwork-Id: 40585 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wg0-f72.google.com (mail-wg0-f72.google.com [74.125.82.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id B3F37241C9 for ; Tue, 11 Nov 2014 15:49:01 +0000 (UTC) Received: by mail-wg0-f72.google.com with SMTP id k14sf5530062wgh.7 for ; Tue, 11 Nov 2014 07:49:00 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=bveQHW5HesBcfYjVx0BKpy6HnsEW1p0QhOIF7miuXF8=; b=PNKzRT0oC0QX9686Z8PWCvfqnR0RN0tJ1to38Uc67HGN4mXHJjmYZxJR9d6er47xS+ ETWgNzpHsMzwDj64fIEUNbItqCKTSrtC0NDg2eSF07skq62822x1SM3XzPaCTwKI7nAL MjRyFHT2StZsKN2cOhDKdPfTO5blBycQful3/ApOS/y0nRKSxMhF+y/R9xSL8ir6TlbM r8duygb7Luv9QFmAq36EtjTFRxMk7NDrQvnKqparqWBgfeqAB1DBCmTDY+JVodbqvXYU jKTAf+jQ5GSCIc0nC1jUsMAjkX72aDPb1ZT8XI80EEcumikdPIgU+0JgNxH7iuMep68V eHUg== X-Gm-Message-State: ALoCoQkpHKVUu5ySFFIt+1sI2maKRNlkMqq31lI2Cxz52VOz946f0wnEqO0ORQ3P3L97O1hjScbk X-Received: by 10.180.19.226 with SMTP id i2mr5456826wie.5.1415720940932; Tue, 11 Nov 2014 07:49:00 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.8.68 with SMTP id p4ls600655laa.52.gmail; Tue, 11 Nov 2014 07:49:00 -0800 (PST) X-Received: by 10.113.5.7 with SMTP id ci7mr37646743lbd.9.1415720940625; Tue, 11 Nov 2014 07:49:00 -0800 (PST) Received: from mail-la0-f50.google.com (mail-la0-f50.google.com. [209.85.215.50]) by mx.google.com with ESMTPS id ll12si31865666lac.58.2014.11.11.07.49.00 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 11 Nov 2014 07:49:00 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.50 as permitted sender) client-ip=209.85.215.50; Received: by mail-la0-f50.google.com with SMTP id hs14so3527620lab.9 for ; Tue, 11 Nov 2014 07:49:00 -0800 (PST) X-Received: by 10.152.120.199 with SMTP id le7mr36245517lab.67.1415720940514; Tue, 11 Nov 2014 07:49:00 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.184.201 with SMTP id ew9csp277262lbc; Tue, 11 Nov 2014 07:48:59 -0800 (PST) X-Received: by 10.68.111.37 with SMTP id if5mr12542484pbb.140.1415720937321; Tue, 11 Nov 2014 07:48:57 -0800 (PST) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id cf17si18763750pdb.137.2014.11.11.07.48.56 for ; Tue, 11 Nov 2014 07:48:57 -0800 (PST) Received-SPF: none (google.com: linux-kernel-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751779AbaKKPsk (ORCPT + 25 others); Tue, 11 Nov 2014 10:48:40 -0500 Received: from foss-mx-na.foss.arm.com ([217.140.108.86]:56200 "EHLO foss-mx-na.foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751725AbaKKPsi (ORCPT ); Tue, 11 Nov 2014 10:48:38 -0500 Received: from foss-smtp-na-1.foss.arm.com (unknown [10.80.61.8]) by foss-mx-na.foss.arm.com (Postfix) with ESMTP id C4A514F4; Tue, 11 Nov 2014 09:48:33 -0600 (CST) Received: from collaborate-mta1.arm.com (highbank-bc01-b06.austin.arm.com [10.112.81.134]) by foss-smtp-na-1.foss.arm.com (Postfix) with ESMTP id 892AE5FAD8; Tue, 11 Nov 2014 09:48:31 -0600 (CST) Received: from e102391-lin.cambridge.arm.com (e102391-lin.cambridge.arm.com [10.1.209.143]) by collaborate-mta1.arm.com (Postfix) with ESMTP id 3DBBE13F78C; Tue, 11 Nov 2014 09:48:30 -0600 (CST) From: Marc Zyngier To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Jiang Liu , Thomas Gleixner Cc: Bjorn Helgaas , Yingjoe Chen , Will Deacon , Catalin marinas , Mark Rutland Subject: [PATCH 11/15] irqchip: GICv3: ITS: MSI support Date: Tue, 11 Nov 2014 15:48:09 +0000 Message-Id: <1415720893-13371-12-git-send-email-marc.zyngier@arm.com> X-Mailer: git-send-email 2.0.4 In-Reply-To: <1415720893-13371-1-git-send-email-marc.zyngier@arm.com> References: <1415720893-13371-1-git-send-email-marc.zyngier@arm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: marc.zyngier@arm.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.50 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Now, the bit of code that allow us to use the ITS as a MSI controller. Both MSI and MSI-X are supported. Signed-off-by: Marc Zyngier --- drivers/irqchip/irq-gic-v3-its.c | 131 +++++++++++++++++++++++++++++++++++++ include/linux/irqchip/arm-gic-v3.h | 6 ++ 2 files changed, 137 insertions(+) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 8d13012..0f51d23 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "irqchip.h" @@ -587,12 +588,27 @@ static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val, return IRQ_SET_MASK_OK; } +static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg) +{ + struct its_device *its_dev = irq_data_get_irq_chip_data(d); + struct its_node *its; + u64 addr; + + its = its_dev->its; + addr = its->phys_base + GITS_TRANSLATER; + + msg->address_lo = addr & ((1UL << 32) - 1); + msg->address_hi = addr >> 32; + msg->data = its_get_event_id(d); +} + static struct irq_chip its_irq_chip = { .name = "ITS", .irq_mask = its_mask_irq, .irq_unmask = its_unmask_irq, .irq_eoi = its_eoi_irq, .irq_set_affinity = its_set_affinity, + .irq_compose_msi_msg = its_irq_compose_msi_msg, }; /* @@ -1055,3 +1071,118 @@ static void its_free_device(struct its_device *its_dev) kfree(its_dev->itt); kfree(its_dev); } + +static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq) +{ + int idx; + + idx = find_first_zero_bit(dev->lpi_map, dev->nr_lpis); + if (idx == dev->nr_lpis) + return -ENOSPC; + + *hwirq = dev->lpi_base + idx; + set_bit(idx, dev->lpi_map); + + /* Map the GIC irq ID to the device */ + its_send_mapvi(dev, *hwirq, idx); + + return 0; +} + +static int its_irq_gic_domain_alloc(struct irq_domain *domain, + unsigned int virq, + irq_hw_number_t hwirq) +{ + struct of_phandle_args args; + + args.np = domain->parent->of_node; + args.args_count = 3; + args.args[0] = GIC_IRQ_TYPE_LPI; + args.args[1] = hwirq; + args.args[2] = IRQ_TYPE_EDGE_RISING; + + return irq_domain_alloc_irqs_parent(domain, virq, 1, &args); +} + +/* FIXME: Use proper API once it is available in the kernel... */ +#define PCI_REQUESTER_ID(dev) PCI_DEVID((dev)->bus->number, (dev)->devfn) + +static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, + unsigned int nr_irqs, void *arg) +{ + struct arm64_msi_info *info = arg; + struct pci_dev *pdev = info->pdev; + struct msi_chip *chip = pdev->bus->msi; + struct its_node *its = container_of(chip, struct its_node, msi_chip); + u32 dev_id = PCI_REQUESTER_ID(pdev); + struct its_device *its_dev; + irq_hw_number_t hwirq; + int err; + int i; + + its_dev = its_find_device(its, dev_id); + if (!its_dev) { + its_dev = its_create_device(its, dev_id, info->nvec); + dev_dbg(&pdev->dev, "ITT %d entries, %d bits\n", + info->nvec, ilog2(info->nvec)); + } + if (!its_dev) + return -ENOMEM; + + for (i = 0; i < nr_irqs; i++) { + err = its_alloc_device_irq(its_dev, &hwirq); + if (err) + return err; + + err = its_irq_gic_domain_alloc(domain, virq, hwirq); + if (err) + return err; + + irq_domain_set_hwirq_and_chip(lpi_domain, virq + i, + hwirq, &its_irq_chip, its_dev); + dev_dbg(&pdev->dev, "ID:%d pID:%d vID:%d\n", + (int)(hwirq - its_dev->lpi_base), + (int)hwirq, virq + i); + } + + return 0; +} + +static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq, + unsigned int nr_irqs) +{ + struct irq_data *d = irq_get_irq_data(virq); + struct its_device *its_dev = irq_data_get_irq_chip_data(d); + int i; + + for (i = 0; i < nr_irqs; i++) { + int event = its_get_event_id(d); + + /* Stop the delivery of interrupts */ + its_send_discard(its_dev, event); + + /* Mark interrupt index as unused, and clear the mapping */ + clear_bit(event, its_dev->lpi_map); + + irq_set_handler(virq + i, NULL); + irq_domain_set_hwirq_and_chip(domain, virq + i, 0, NULL, NULL); + } + + /* If all interrupts have been freed, start mopping the floor */ + if (bitmap_empty(its_dev->lpi_map, its_dev->nr_lpis)) { + its_lpi_free(its_dev->lpi_map, + its_dev->lpi_base, + its_dev->nr_lpis); + + /* Unmap device/itt */ + its_send_mapd(its_dev, 0); + its_free_device(its_dev); + } + + irq_domain_free_irqs_parent(domain, virq, nr_irqs); +} + +static const struct irq_domain_ops its_domain_ops = { + .alloc = its_irq_domain_alloc, + .free = its_irq_domain_free, +}; diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index 21c9d70..2a7486b 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -295,6 +295,12 @@ #include +/* + * We need a value to serve as a irq-type for LPIs. Choose one that will + * pick the interest of the reviewer. + */ +#define GIC_IRQ_TYPE_LPI 0xa110c8ed + struct rdists { struct { void __iomem *rd_base;