From patchwork Tue Jan 14 08:28:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Hao X-Patchwork-Id: 1222566 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=lqRJaG4F; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xkRZ0RKfz9sPn for ; Tue, 14 Jan 2020 19:40:10 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728746AbgANIkD (ORCPT ); Tue, 14 Jan 2020 03:40:03 -0500 Received: from mail-pl1-f194.google.com ([209.85.214.194]:41554 "EHLO mail-pl1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727083AbgANIkD (ORCPT ); Tue, 14 Jan 2020 03:40:03 -0500 Received: by mail-pl1-f194.google.com with SMTP id bd4so4953315plb.8 for ; Tue, 14 Jan 2020 00:40:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=cmRHW7xaszw0z6LuO2XN1PiyQlaOyRn78JrJJ835zUo=; b=lqRJaG4F68zMDE8katwfrw4uiIH3fHDrp3sIgQju+KkYIUfU33GbhifajwwGHR/aVH 4iJzfJOJrY1v1VPTaSz2kjl80JJyzrAS/IDMPkMtMnqHa+t0hgDUZLODWobwOZncufJ9 9bL/kAAKeYbsICmR5mn8z4LAGsISK3pY5DtUgHkHdXnqC9pW1s87A8Qq8A0nTYphQTJl 4GC+nFmsy2Hfk7vGDCwOYOT95FKPy6IV005QAbCQSZjeNDbnw0h7x1roe36ix0M5MbZN uY2pAjq8rA9VSFvWN25J4UjH+TgUds43IA8ECe1d92rCOyCu7D5X+0yFLidMsN7NMkAq nRAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=cmRHW7xaszw0z6LuO2XN1PiyQlaOyRn78JrJJ835zUo=; b=Uyw+7hvMMAKUKwK+k0Xi6dZ091FmtVZYPq58tmNAxYjJ3sM6VZcnCTgA/1FjM+hNcb 2moGQpWTiO3VYJSEWHjupeo1t/k4eiHTD7/17OqQIAesSALd0izbNSP8epSdzx5YjBD4 v4Ta5RBxl6l7j6aAIaTedWeGRWxPzdNucKEggsItcw9yueSLreuCUpOAux97UXFQ49DI YxW3i6QEKYR3quNGkO8YBGw6k4Rph5tjjoL3OO4OLVptPAIcopi06KZwdW6QzkIZE4DB MoWnnE3zp9DmPI28GIMnWhVg17IDxBnLneO7OX+7HTMDfo73VOzCONaKdGj7AyYSAQxa mLDA== X-Gm-Message-State: APjAAAWR9mG74UG/B4al+psl1ydZ9jdCzZo2WOcRcH3TT8GepvcugN9s MDClY6g17TBB2sbi21/h8eX5FpjlEro= X-Google-Smtp-Source: APXvYqw1hy+uiU8UrFNPl6vMUcamBwna3jCkdBTxilevbU1LYMqAIB0IGzaygRvqTGTpRESZR0ZRdA== X-Received: by 2002:a17:90a:db48:: with SMTP id u8mr27409045pjx.54.1578991202066; Tue, 14 Jan 2020 00:40:02 -0800 (PST) Received: from pek-lpggp6.wrs.com (unknown-105-123.windriver.com. [147.11.105.123]) by smtp.gmail.com with ESMTPSA id o16sm16284910pgl.58.2020.01.14.00.39.56 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 14 Jan 2020 00:40:01 -0800 (PST) From: Kevin Hao To: linux-gpio@vger.kernel.org Cc: Linus Walleij , Bartosz Golaszewski , Robert Richter , Kevin Hao Subject: [PATCH 1/4] Revert "gpio: thunderx: Switch to GPIOLIB_IRQCHIP" Date: Tue, 14 Jan 2020 16:28:18 +0800 Message-Id: <20200114082821.14015-2-haokexin@gmail.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20200114082821.14015-1-haokexin@gmail.com> References: <20200114082821.14015-1-haokexin@gmail.com> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org This reverts commit a7fc89f9d5fcc10a5474cfe555f5a9e5df8b0f1f because there are some bugs in this commit, and we don't have a simple way to fix these bugs. So revert this commit to make the thunderx gpio work on the stable kernel at least. We will switch to GPIOLIB_IRQCHIP for thunderx gpio by following patches. Fixes: a7fc89f9d5fc ("gpio: thunderx: Switch to GPIOLIB_IRQCHIP") Signed-off-by: Kevin Hao --- drivers/gpio/Kconfig | 1 - drivers/gpio/gpio-thunderx.c | 163 ++++++++++++++++++++++++++++--------------- 2 files changed, 107 insertions(+), 57 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 9e99d09a64c6..ce65919dee12 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -571,7 +571,6 @@ config GPIO_THUNDERX tristate "Cavium ThunderX/OCTEON-TX GPIO" depends on ARCH_THUNDER || (64BIT && COMPILE_TEST) depends on PCI_MSI - select GPIOLIB_IRQCHIP select IRQ_DOMAIN_HIERARCHY select IRQ_FASTEOI_HIERARCHY_HANDLERS help diff --git a/drivers/gpio/gpio-thunderx.c b/drivers/gpio/gpio-thunderx.c index d08d86a22b1f..462770479045 100644 --- a/drivers/gpio/gpio-thunderx.c +++ b/drivers/gpio/gpio-thunderx.c @@ -53,6 +53,7 @@ struct thunderx_line { struct thunderx_gpio { struct gpio_chip chip; u8 __iomem *register_base; + struct irq_domain *irqd; struct msix_entry *msix_entries; /* per line MSI-X */ struct thunderx_line *line_entries; /* per line irq info */ raw_spinlock_t lock; @@ -285,60 +286,54 @@ static void thunderx_gpio_set_multiple(struct gpio_chip *chip, } } -static void thunderx_gpio_irq_ack(struct irq_data *d) +static void thunderx_gpio_irq_ack(struct irq_data *data) { - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct thunderx_gpio *txgpio = gpiochip_get_data(gc); + struct thunderx_line *txline = irq_data_get_irq_chip_data(data); writeq(GPIO_INTR_INTR, - txgpio->register_base + intr_reg(irqd_to_hwirq(d))); + txline->txgpio->register_base + intr_reg(txline->line)); } -static void thunderx_gpio_irq_mask(struct irq_data *d) +static void thunderx_gpio_irq_mask(struct irq_data *data) { - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct thunderx_gpio *txgpio = gpiochip_get_data(gc); + struct thunderx_line *txline = irq_data_get_irq_chip_data(data); writeq(GPIO_INTR_ENA_W1C, - txgpio->register_base + intr_reg(irqd_to_hwirq(d))); + txline->txgpio->register_base + intr_reg(txline->line)); } -static void thunderx_gpio_irq_mask_ack(struct irq_data *d) +static void thunderx_gpio_irq_mask_ack(struct irq_data *data) { - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct thunderx_gpio *txgpio = gpiochip_get_data(gc); + struct thunderx_line *txline = irq_data_get_irq_chip_data(data); writeq(GPIO_INTR_ENA_W1C | GPIO_INTR_INTR, - txgpio->register_base + intr_reg(irqd_to_hwirq(d))); + txline->txgpio->register_base + intr_reg(txline->line)); } -static void thunderx_gpio_irq_unmask(struct irq_data *d) +static void thunderx_gpio_irq_unmask(struct irq_data *data) { - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct thunderx_gpio *txgpio = gpiochip_get_data(gc); + struct thunderx_line *txline = irq_data_get_irq_chip_data(data); writeq(GPIO_INTR_ENA_W1S, - txgpio->register_base + intr_reg(irqd_to_hwirq(d))); + txline->txgpio->register_base + intr_reg(txline->line)); } -static int thunderx_gpio_irq_set_type(struct irq_data *d, +static int thunderx_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type) { - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct thunderx_gpio *txgpio = gpiochip_get_data(gc); - struct thunderx_line *txline = - &txgpio->line_entries[irqd_to_hwirq(d)]; + struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + struct thunderx_gpio *txgpio = txline->txgpio; u64 bit_cfg; - irqd_set_trigger_type(d, flow_type); + irqd_set_trigger_type(data, flow_type); bit_cfg = txline->fil_bits | GPIO_BIT_CFG_INT_EN; if (flow_type & IRQ_TYPE_EDGE_BOTH) { - irq_set_handler_locked(d, handle_fasteoi_ack_irq); + irq_set_handler_locked(data, handle_fasteoi_ack_irq); bit_cfg |= GPIO_BIT_CFG_INT_TYPE; } else { - irq_set_handler_locked(d, handle_fasteoi_mask_irq); + irq_set_handler_locked(data, handle_fasteoi_mask_irq); } raw_spin_lock(&txgpio->lock); @@ -367,6 +362,33 @@ static void thunderx_gpio_irq_disable(struct irq_data *data) irq_chip_disable_parent(data); } +static int thunderx_gpio_irq_request_resources(struct irq_data *data) +{ + struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + struct thunderx_gpio *txgpio = txline->txgpio; + int r; + + r = gpiochip_lock_as_irq(&txgpio->chip, txline->line); + if (r) + return r; + + r = irq_chip_request_resources_parent(data); + if (r) + gpiochip_unlock_as_irq(&txgpio->chip, txline->line); + + return r; +} + +static void thunderx_gpio_irq_release_resources(struct irq_data *data) +{ + struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + struct thunderx_gpio *txgpio = txline->txgpio; + + irq_chip_release_resources_parent(data); + + gpiochip_unlock_as_irq(&txgpio->chip, txline->line); +} + /* * Interrupts are chained from underlying MSI-X vectors. We have * these irq_chip functions to be able to handle level triggering @@ -383,24 +405,50 @@ static struct irq_chip thunderx_gpio_irq_chip = { .irq_unmask = thunderx_gpio_irq_unmask, .irq_eoi = irq_chip_eoi_parent, .irq_set_affinity = irq_chip_set_affinity_parent, + .irq_request_resources = thunderx_gpio_irq_request_resources, + .irq_release_resources = thunderx_gpio_irq_release_resources, .irq_set_type = thunderx_gpio_irq_set_type, .flags = IRQCHIP_SET_TYPE_MASKED }; -static int thunderx_gpio_child_to_parent_hwirq(struct gpio_chip *gc, - unsigned int child, - unsigned int child_type, - unsigned int *parent, - unsigned int *parent_type) +static int thunderx_gpio_irq_translate(struct irq_domain *d, + struct irq_fwspec *fwspec, + irq_hw_number_t *hwirq, + unsigned int *type) { - struct thunderx_gpio *txgpio = gpiochip_get_data(gc); - - *parent = txgpio->base_msi + (2 * child); - *parent_type = IRQ_TYPE_LEVEL_HIGH; + struct thunderx_gpio *txgpio = d->host_data; + + if (WARN_ON(fwspec->param_count < 2)) + return -EINVAL; + if (fwspec->param[0] >= txgpio->chip.ngpio) + return -EINVAL; + *hwirq = fwspec->param[0]; + *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; return 0; } +static int thunderx_gpio_irq_alloc(struct irq_domain *d, unsigned int virq, + unsigned int nr_irqs, void *arg) +{ + struct thunderx_line *txline = arg; + + return irq_domain_set_hwirq_and_chip(d, virq, txline->line, + &thunderx_gpio_irq_chip, txline); +} + +static const struct irq_domain_ops thunderx_gpio_irqd_ops = { + .alloc = thunderx_gpio_irq_alloc, + .translate = thunderx_gpio_irq_translate +}; + +static int thunderx_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) +{ + struct thunderx_gpio *txgpio = gpiochip_get_data(chip); + + return irq_find_mapping(txgpio->irqd, offset); +} + static int thunderx_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -408,7 +456,6 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, struct device *dev = &pdev->dev; struct thunderx_gpio *txgpio; struct gpio_chip *chip; - struct gpio_irq_chip *girq; int ngpio, i; int err = 0; @@ -453,8 +500,8 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, } txgpio->msix_entries = devm_kcalloc(dev, - ngpio, sizeof(struct msix_entry), - GFP_KERNEL); + ngpio, sizeof(struct msix_entry), + GFP_KERNEL); if (!txgpio->msix_entries) { err = -ENOMEM; goto out; @@ -495,6 +542,27 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, if (err < 0) goto out; + /* + * Push GPIO specific irqdomain on hierarchy created as a side + * effect of the pci_enable_msix() + */ + txgpio->irqd = irq_domain_create_hierarchy(irq_get_irq_data(txgpio->msix_entries[0].vector)->domain, + 0, 0, of_node_to_fwnode(dev->of_node), + &thunderx_gpio_irqd_ops, txgpio); + if (!txgpio->irqd) { + err = -ENOMEM; + goto out; + } + + /* Push on irq_data and the domain for each line. */ + for (i = 0; i < ngpio; i++) { + err = irq_domain_push_irq(txgpio->irqd, + txgpio->msix_entries[i].vector, + &txgpio->line_entries[i]); + if (err < 0) + dev_err(dev, "irq_domain_push_irq: %d\n", err); + } + chip->label = KBUILD_MODNAME; chip->parent = dev; chip->owner = THIS_MODULE; @@ -509,28 +577,11 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, chip->set = thunderx_gpio_set; chip->set_multiple = thunderx_gpio_set_multiple; chip->set_config = thunderx_gpio_set_config; - girq = &chip->irq; - girq->chip = &thunderx_gpio_irq_chip; - girq->fwnode = of_node_to_fwnode(dev->of_node); - girq->parent_domain = - irq_get_irq_data(txgpio->msix_entries[0].vector)->domain; - girq->child_to_parent_hwirq = thunderx_gpio_child_to_parent_hwirq; - girq->handler = handle_bad_irq; - girq->default_type = IRQ_TYPE_NONE; - + chip->to_irq = thunderx_gpio_to_irq; err = devm_gpiochip_add_data(dev, chip, txgpio); if (err) goto out; - /* Push on irq_data and the domain for each line. */ - for (i = 0; i < ngpio; i++) { - err = irq_domain_push_irq(chip->irq.domain, - txgpio->msix_entries[i].vector, - chip); - if (err < 0) - dev_err(dev, "irq_domain_push_irq: %d\n", err); - } - dev_info(dev, "ThunderX GPIO: %d lines with base %d.\n", ngpio, chip->base); return 0; @@ -545,10 +596,10 @@ static void thunderx_gpio_remove(struct pci_dev *pdev) struct thunderx_gpio *txgpio = pci_get_drvdata(pdev); for (i = 0; i < txgpio->chip.ngpio; i++) - irq_domain_pop_irq(txgpio->chip.irq.domain, + irq_domain_pop_irq(txgpio->irqd, txgpio->msix_entries[i].vector); - irq_domain_remove(txgpio->chip.irq.domain); + irq_domain_remove(txgpio->irqd); pci_set_drvdata(pdev, NULL); } From patchwork Tue Jan 14 08:28:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Hao X-Patchwork-Id: 1222567 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=oo06eeV7; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xkRl0QhSz9sPn for ; Tue, 14 Jan 2020 19:40:19 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728810AbgANIkO (ORCPT ); Tue, 14 Jan 2020 03:40:14 -0500 Received: from mail-pj1-f65.google.com ([209.85.216.65]:40243 "EHLO mail-pj1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727083AbgANIkO (ORCPT ); Tue, 14 Jan 2020 03:40:14 -0500 Received: by mail-pj1-f65.google.com with SMTP id bg7so5538813pjb.5 for ; Tue, 14 Jan 2020 00:40:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=d88RijQwAj4cV7alegR9skygE3HHGfexf/vhPhy3XvA=; b=oo06eeV7Y3kT0c0QKn1DoVFrD+y5tWdVf3G9Jh43CFR0LGkfmi+fKOqiQfK44137UG mqxUVHt4LJTbhmLLo7rfwnl/BQYfN8Y7wd4huShXZleGj59FHcIXn3KKUE7XQZqX5nRz 09bHKWmS/fX2Sd7uN3rrH+UNf49WX5jVSj5pC/F8XQv10Erode21JnDmeHEfo2Gpd09A /Ausz0DnbtKo3GTh48BnoSeB2uHNC5x+Cgh51irBolNIUNrplbIZyOb8dKy8UiPL+LvO 2Qgf5UfLfAFMLOJ4NX/lShc37+jl8YI+6u6jG+n5YmrUIkiFxyzX0bOYxu21x51r9teW /lww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=d88RijQwAj4cV7alegR9skygE3HHGfexf/vhPhy3XvA=; b=ugrInYo9EeO1345wsooZPgO4pRwXU8k8RStbQxqpyEBHdGb6dn0XwKoIyWxwCmymV4 d+FvHgV2LsURjwCpPxwtVu3efrj+kN5nv8W16fSCOkNhC9nJiXNOR269pKn+WS7ReHkW 4zUJGqFp5oM5hSkhshNsMWx3vdZ9XJ/0UoxInPpPVXtgA37Qtfm6jP3OtJzxlqclsnwS B0a8dLXIkDHc1+bqpbsjeusvPhPUvkhd9LlvCbhq2il0vwa17wt+B4t3cTg+Ui8F2LMM xsim2eNSo3EHPAfDyPQ8S2FGPCrUkyt7QmfmaEDrMU0norYwe1Dfw2EHMFSEYj+QTVt8 Ei8A== X-Gm-Message-State: APjAAAXHmtE68WjNVkwDLdNESSYlNJ08x32S8SZK7oWBQ1+fRsKBqrgj DbaLb4VWsDoChztHdAQG0f50HmJqLmI= X-Google-Smtp-Source: APXvYqw7KMvmtm8HoeXSTl0dwE0rcxf37G1C41rq3dQ4aCTLup0Ap2e/DCttMB6g7QjETC5qTrw4vQ== X-Received: by 2002:a17:902:7c95:: with SMTP id y21mr24809942pll.150.1578991213239; Tue, 14 Jan 2020 00:40:13 -0800 (PST) Received: from pek-lpggp6.wrs.com (unknown-105-123.windriver.com. [147.11.105.123]) by smtp.gmail.com with ESMTPSA id o16sm16284910pgl.58.2020.01.14.00.40.06 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 14 Jan 2020 00:40:12 -0800 (PST) From: Kevin Hao To: linux-gpio@vger.kernel.org Cc: Linus Walleij , Bartosz Golaszewski , Thierry Reding , Jonathan Hunter , Andy Gross , Bjorn Andersson , Kevin Hao Subject: [PATCH 2/4] gpiolib: Add support for the irqdomain which doesn't use irq_fwspec as arg Date: Tue, 14 Jan 2020 16:28:19 +0800 Message-Id: <20200114082821.14015-3-haokexin@gmail.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20200114082821.14015-1-haokexin@gmail.com> References: <20200114082821.14015-1-haokexin@gmail.com> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Some gpio's parent irqdomain may not use the struct irq_fwspec as argument, such as msi irqdomain. So rename the callback populate_parent_fwspec() to populate_parent_alloc_arg() and make it allocate and populate the specific struct which is needed by the parent irqdomain. Signed-off-by: Kevin Hao --- drivers/gpio/gpio-tegra186.c | 13 ++++++--- drivers/gpio/gpiolib.c | 45 ++++++++++++++++++++------------ drivers/pinctrl/qcom/pinctrl-spmi-gpio.c | 2 +- drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c | 2 +- include/linux/gpio/driver.h | 21 ++++++--------- 5 files changed, 49 insertions(+), 34 deletions(-) diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index 55b43b7ce88d..de241263d4be 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -448,17 +448,24 @@ static int tegra186_gpio_irq_domain_translate(struct irq_domain *domain, return 0; } -static void tegra186_gpio_populate_parent_fwspec(struct gpio_chip *chip, - struct irq_fwspec *fwspec, +static void *tegra186_gpio_populate_parent_fwspec(struct gpio_chip *chip, unsigned int parent_hwirq, unsigned int parent_type) { struct tegra_gpio *gpio = gpiochip_get_data(chip); + struct irq_fwspec *fwspec; + fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); + if (!fwspec) + return NULL; + + fwspec->fwnode = chip->irq.parent_domain->fwnode; fwspec->param_count = 3; fwspec->param[0] = gpio->soc->instance; fwspec->param[1] = parent_hwirq; fwspec->param[2] = parent_type; + + return fwspec; } static int tegra186_gpio_child_to_parent_hwirq(struct gpio_chip *chip, @@ -621,7 +628,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev) irq->chip = &gpio->intc; irq->fwnode = of_node_to_fwnode(pdev->dev.of_node); irq->child_to_parent_hwirq = tegra186_gpio_child_to_parent_hwirq; - irq->populate_parent_fwspec = tegra186_gpio_populate_parent_fwspec; + irq->populate_parent_alloc_arg = tegra186_gpio_populate_parent_fwspec; irq->child_offset_to_irq = tegra186_gpio_child_offset_to_irq; irq->child_irq_domain_ops.translate = tegra186_gpio_irq_domain_translate; irq->handler = handle_simple_irq; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 967371377a9d..bedf611a7c9e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1990,7 +1990,7 @@ static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d, irq_hw_number_t hwirq; unsigned int type = IRQ_TYPE_NONE; struct irq_fwspec *fwspec = data; - struct irq_fwspec parent_fwspec; + void *parent_arg; unsigned int parent_hwirq; unsigned int parent_type; struct gpio_irq_chip *girq = &gc->irq; @@ -2029,23 +2029,20 @@ static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d, NULL, NULL); irq_set_probe(irq); - /* - * Create a IRQ fwspec to send up to the parent irqdomain: - * specify the hwirq we address on the parent and tie it - * all together up the chain. - */ - parent_fwspec.fwnode = d->parent->fwnode; /* This parent only handles asserted level IRQs */ - girq->populate_parent_fwspec(gc, &parent_fwspec, parent_hwirq, - parent_type); + parent_arg = girq->populate_parent_alloc_arg(gc, parent_hwirq, parent_type); + if (!parent_arg) + return -ENOMEM; + chip_info(gc, "alloc_irqs_parent for %d parent hwirq %d\n", irq, parent_hwirq); - ret = irq_domain_alloc_irqs_parent(d, irq, 1, &parent_fwspec); + ret = irq_domain_alloc_irqs_parent(d, irq, 1, parent_arg); if (ret) chip_err(gc, "failed to allocate parent hwirq %d for hwirq %lu\n", parent_hwirq, hwirq); + kfree(parent_arg); return ret; } @@ -2082,8 +2079,8 @@ static int gpiochip_hierarchy_add_domain(struct gpio_chip *gc) if (!gc->irq.child_offset_to_irq) gc->irq.child_offset_to_irq = gpiochip_child_offset_to_irq_noop; - if (!gc->irq.populate_parent_fwspec) - gc->irq.populate_parent_fwspec = + if (!gc->irq.populate_parent_alloc_arg) + gc->irq.populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_twocell; gpiochip_hierarchy_setup_domain_ops(&gc->irq.child_irq_domain_ops); @@ -2109,27 +2106,43 @@ static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc) return !!gc->irq.parent_domain; } -void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, - struct irq_fwspec *fwspec, +void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, unsigned int parent_hwirq, unsigned int parent_type) { + struct irq_fwspec *fwspec; + + fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); + if (!fwspec) + return NULL; + + fwspec->fwnode = chip->irq.parent_domain->fwnode; fwspec->param_count = 2; fwspec->param[0] = parent_hwirq; fwspec->param[1] = parent_type; + + return fwspec; } EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_twocell); -void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, - struct irq_fwspec *fwspec, +void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, unsigned int parent_hwirq, unsigned int parent_type) { + struct irq_fwspec *fwspec; + + fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); + if (!fwspec) + return NULL; + + fwspec->fwnode = chip->irq.parent_domain->fwnode; fwspec->param_count = 4; fwspec->param[0] = 0; fwspec->param[1] = parent_hwirq; fwspec->param[2] = 0; fwspec->param[3] = parent_type; + + return fwspec; } EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_fourcell); diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index 653d1095bfea..fe0be8a6ebb7 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -1060,7 +1060,7 @@ static int pmic_gpio_probe(struct platform_device *pdev) girq->fwnode = of_node_to_fwnode(state->dev->of_node); girq->parent_domain = parent_domain; girq->child_to_parent_hwirq = pmic_gpio_child_to_parent_hwirq; - girq->populate_parent_fwspec = gpiochip_populate_parent_fwspec_fourcell; + girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_fourcell; girq->child_offset_to_irq = pmic_gpio_child_offset_to_irq; girq->child_irq_domain_ops.translate = pmic_gpio_domain_translate; diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c index c7912135bbfb..fba1d41d20ec 100644 --- a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c @@ -794,7 +794,7 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev) girq->fwnode = of_node_to_fwnode(pctrl->dev->of_node); girq->parent_domain = parent_domain; girq->child_to_parent_hwirq = pm8xxx_child_to_parent_hwirq; - girq->populate_parent_fwspec = gpiochip_populate_parent_fwspec_fourcell; + girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_fourcell; girq->child_offset_to_irq = pm8xxx_child_offset_to_irq; girq->child_irq_domain_ops.translate = pm8xxx_domain_translate; diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 4f032de10bae..ea6e615ad7fc 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -94,16 +94,15 @@ struct gpio_irq_chip { unsigned int *parent_type); /** - * @populate_parent_fwspec: + * @populate_parent_alloc_arg : * - * This optional callback populates the &struct irq_fwspec for the - * parent's IRQ domain. If this is not specified, then + * This optional callback allocates and populates the specific struct + * for the parent's IRQ domain. If this is not specified, then * &gpiochip_populate_parent_fwspec_twocell will be used. A four-cell * variant named &gpiochip_populate_parent_fwspec_fourcell is also * available. */ - void (*populate_parent_fwspec)(struct gpio_chip *chip, - struct irq_fwspec *fwspec, + void *(*populate_parent_alloc_arg)(struct gpio_chip *chip, unsigned int parent_hwirq, unsigned int parent_type); @@ -537,26 +536,22 @@ struct bgpio_pdata { #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY -void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, - struct irq_fwspec *fwspec, +void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, unsigned int parent_hwirq, unsigned int parent_type); -void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, - struct irq_fwspec *fwspec, +void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, unsigned int parent_hwirq, unsigned int parent_type); #else -static inline void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, - struct irq_fwspec *fwspec, +static inline void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, unsigned int parent_hwirq, unsigned int parent_type) { } -static inline void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, - struct irq_fwspec *fwspec, +static inline void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, unsigned int parent_hwirq, unsigned int parent_type) { From patchwork Tue Jan 14 08:28:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Hao X-Patchwork-Id: 1222568 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=aXVhTQaO; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xkRp2kTZz9sPn for ; Tue, 14 Jan 2020 19:40:22 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727102AbgANIkV (ORCPT ); Tue, 14 Jan 2020 03:40:21 -0500 Received: from mail-pf1-f193.google.com ([209.85.210.193]:34340 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727083AbgANIkV (ORCPT ); Tue, 14 Jan 2020 03:40:21 -0500 Received: by mail-pf1-f193.google.com with SMTP id i6so6248374pfc.1 for ; Tue, 14 Jan 2020 00:40:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ZR7iL6rDkWI9c3J40FqEWMz9/qBe7v556TrmI33+1s4=; b=aXVhTQaO67ykw8tnN0eJMPN1TybFUSmbtAxtR1vhR+TAtJOAQStOwltVWt8pHJIa7r l7wDjoff48zmYXr1enbyVeWp5HNq43oO0dSQVcBvfWGna7knRzsCJKmySfejuhjWFPws GsJ0l7kRtcIui7hQLvJcTWWaf5a6l2DpVvmvxIpGskDW2Dy2D/6tmJnl54RpKHteF6Tz 6UsuCmkdRI3kSJugBF4vmseZOsZOr+cD8m8iiIs2TQDXIYf8zuSsLy7DMXGyYDZG8D9D LVdd6E0iODG7OyBeEy1hvBXqkZzgZ+NimqDdZr0AjQutU6CEsh8oV4jgfUhbeNZnYVps tsFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ZR7iL6rDkWI9c3J40FqEWMz9/qBe7v556TrmI33+1s4=; b=l/m1sHuyKog8Dpr6uyC6MBL7F3zL/M+l2h5h1G4VJ9iadoyrE8U5ttYfLi4l6JOrlU BgVZRFoDlBazPoSFHtMV3ySKsmuZ3aeoyPnS41QPiTKU12s79S0E3fRkvKGbG6qtvn3e oNJLdN5F876Ig8vcmdq4mK/zKX0R8b1EzuDUUpIsdsaKB57wwUk9elhgrhuyIr/yTfi6 V5N8JzxRsJcb3M4au7yrfS8B7jjqGSjjfG7KwzXZO4bupjpAh0PUjjPbyeZ07VK4nP1h 6QqRBfhWUr1RqefgvAXhBKW5i5ZSok4L469nnWjn8YbSzyNszRQmgsSzVTiDwxxsQ9xr igKQ== X-Gm-Message-State: APjAAAVkDUlGdojVANQKlB6/OapQ8hJiTFxoJJjZxJ5iuq1pD9UF//yD pg4uLN3uXmZzrf2EY90IDLer+EaDwkk= X-Google-Smtp-Source: APXvYqwP6ThoBjPemdGvaxpS4kUjjYEkYfytsN5aBmw8XQlPuG4AGj+dPe3JyZFhPZwBfNlIdh8D9A== X-Received: by 2002:a62:342:: with SMTP id 63mr24243118pfd.19.1578991220608; Tue, 14 Jan 2020 00:40:20 -0800 (PST) Received: from pek-lpggp6.wrs.com (unknown-105-123.windriver.com. [147.11.105.123]) by smtp.gmail.com with ESMTPSA id o16sm16284910pgl.58.2020.01.14.00.40.16 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 14 Jan 2020 00:40:20 -0800 (PST) From: Kevin Hao To: linux-gpio@vger.kernel.org Cc: Linus Walleij , Bartosz Golaszewski , Kevin Hao Subject: [PATCH 3/4] gpiolib: Add the support for the msi parent domain Date: Tue, 14 Jan 2020 16:28:20 +0800 Message-Id: <20200114082821.14015-4-haokexin@gmail.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20200114082821.14015-1-haokexin@gmail.com> References: <20200114082821.14015-1-haokexin@gmail.com> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org If the gpio's parent irqdomain is a msi irqdomain, we should ignore the EEXIST error returned by the msi irqdomain because all the msi interrupts have already been allocated. Signed-off-by: Kevin Hao --- drivers/gpio/gpiolib.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index bedf611a7c9e..1cca9ab61923 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2037,6 +2037,12 @@ static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d, chip_info(gc, "alloc_irqs_parent for %d parent hwirq %d\n", irq, parent_hwirq); ret = irq_domain_alloc_irqs_parent(d, irq, 1, parent_arg); + /* + * If the parent irqdomain is msi, the interrupts have already + * been allocated, so the EEXIST is good. + */ + if (irq_domain_is_msi(d->parent) && (ret == -EEXIST)) + ret = 0; if (ret) chip_err(gc, "failed to allocate parent hwirq %d for hwirq %lu\n", From patchwork Tue Jan 14 08:28:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Hao X-Patchwork-Id: 1222569 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=caBZG7DI; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xkRw34c2z9s29 for ; Tue, 14 Jan 2020 19:40:28 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728820AbgANIk2 (ORCPT ); Tue, 14 Jan 2020 03:40:28 -0500 Received: from mail-pl1-f196.google.com ([209.85.214.196]:39323 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728819AbgANIk1 (ORCPT ); Tue, 14 Jan 2020 03:40:27 -0500 Received: by mail-pl1-f196.google.com with SMTP id g6so4958755plp.6 for ; Tue, 14 Jan 2020 00:40:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=LW23/JMCyQEMDTbvdZaUJMd36ZXaQbBxWazIzMf6tFc=; b=caBZG7DIymtLJAJG+6Du6bJjrMFnThLb3p4gIJvyx8mRyf/8Kswd/lbmgwrsDzHphK YlsKWtg1HjGWNrfYHEvOpGUCB/jT3f4DlbTbUEgK3GLQe0xTEE40AvHtAa8uv9SstlCK waVUXhzav7UFuJuzdEwwGtthIPskC2xb8xkkFJuV694qxxpcAf95WpQJ7dnchIuIfMoW Dp3SwzevLhsBcNkMML3mThqCaziiO2eDxowCKHcDkFEHaTAb6CpdO6uKVew9itXJq6zq d1Zss3CzLovfLidrOl5xio4PtHwJZ9dlB0xKkSDyPKx8RJK6l/ZKB15a/Wwf/BjMxlWn Ne9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=LW23/JMCyQEMDTbvdZaUJMd36ZXaQbBxWazIzMf6tFc=; b=kGiMXd0V+k5p9Xq3teqUNeeCsq8loDRiOK50H9oHzHeiN/fyCMJdA3E4DeMnLuQ8P9 iOzHeVdHhMH6iy9UcdDT+4vPPMAFJ6HNyvpCfNd7kj9E/Jnbqhp44LI4ogSN0j/h/s3z Wv7mIsgHtGK0OUclL8/GewPCQIpZpEL+6+GSm+44akbPvJMkSzz/waMdH/Yq0b50GyRf akW4+r61UmqBkAIFjAUF0xvxmLtm/CjenElvHhbb2nknGezmRKQFGJQRCB2mVGwvOG17 w+fjRDAwxxX6jNt9C2gzKLtjb3BE0G7jICjCDWP31HdAFM2HySAaZadSc3BzdMAuZmPg 4t7g== X-Gm-Message-State: APjAAAXFmfwqWa5tJG9yzgTeU1WAsoyyE0yH+9Z0v+gDvoaf+W5NbwPW nlQaX5q0jiyDZ3Tum9hHATH1HGY93rg= X-Google-Smtp-Source: APXvYqwQIgxQ+r1mPiriNAktyR310vLVPibr2bqTQizGb1i+jlwIpk3EoXjqoB7Nn1G1XAYrpFg6/Q== X-Received: by 2002:a17:902:7292:: with SMTP id d18mr16647751pll.205.1578991226971; Tue, 14 Jan 2020 00:40:26 -0800 (PST) Received: from pek-lpggp6.wrs.com (unknown-105-123.windriver.com. [147.11.105.123]) by smtp.gmail.com with ESMTPSA id o16sm16284910pgl.58.2020.01.14.00.40.21 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 14 Jan 2020 00:40:26 -0800 (PST) From: Kevin Hao To: linux-gpio@vger.kernel.org Cc: Linus Walleij , Bartosz Golaszewski , Robert Richter , Kevin Hao Subject: [PATCH 4/4] gpio: thunderx: Switch to GPIOLIB_IRQCHIP Date: Tue, 14 Jan 2020 16:28:21 +0800 Message-Id: <20200114082821.14015-5-haokexin@gmail.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20200114082821.14015-1-haokexin@gmail.com> References: <20200114082821.14015-1-haokexin@gmail.com> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org The main parts of this patch are from commit a7fc89f9d5fc ("gpio: thunderx: Switch to GPIOLIB_IRQCHIP") and patch [1]. And also adjust thunderx_gpio_child_to_parent_hwirq() and add thunderx_gpio_populate_parent_alloc_info() to make sure that the correct hwirq are passed to the parent msi irqdomain. [1] https://patchwork.ozlabs.org/patch/1210180/ Signed-off-by: Kevin Hao --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-thunderx.c | 177 +++++++++++++++++++------------------------ 2 files changed, 78 insertions(+), 100 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index ce65919dee12..9e99d09a64c6 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -571,6 +571,7 @@ config GPIO_THUNDERX tristate "Cavium ThunderX/OCTEON-TX GPIO" depends on ARCH_THUNDER || (64BIT && COMPILE_TEST) depends on PCI_MSI + select GPIOLIB_IRQCHIP select IRQ_DOMAIN_HIERARCHY select IRQ_FASTEOI_HIERARCHY_HANDLERS help diff --git a/drivers/gpio/gpio-thunderx.c b/drivers/gpio/gpio-thunderx.c index 462770479045..9f66deab46ea 100644 --- a/drivers/gpio/gpio-thunderx.c +++ b/drivers/gpio/gpio-thunderx.c @@ -15,6 +15,7 @@ #include #include #include +#include #define GPIO_RX_DAT 0x0 @@ -53,7 +54,6 @@ struct thunderx_line { struct thunderx_gpio { struct gpio_chip chip; u8 __iomem *register_base; - struct irq_domain *irqd; struct msix_entry *msix_entries; /* per line MSI-X */ struct thunderx_line *line_entries; /* per line irq info */ raw_spinlock_t lock; @@ -286,54 +286,60 @@ static void thunderx_gpio_set_multiple(struct gpio_chip *chip, } } -static void thunderx_gpio_irq_ack(struct irq_data *data) +static void thunderx_gpio_irq_ack(struct irq_data *d) { - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); writeq(GPIO_INTR_INTR, - txline->txgpio->register_base + intr_reg(txline->line)); + txgpio->register_base + intr_reg(irqd_to_hwirq(d))); } -static void thunderx_gpio_irq_mask(struct irq_data *data) +static void thunderx_gpio_irq_mask(struct irq_data *d) { - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); writeq(GPIO_INTR_ENA_W1C, - txline->txgpio->register_base + intr_reg(txline->line)); + txgpio->register_base + intr_reg(irqd_to_hwirq(d))); } -static void thunderx_gpio_irq_mask_ack(struct irq_data *data) +static void thunderx_gpio_irq_mask_ack(struct irq_data *d) { - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); writeq(GPIO_INTR_ENA_W1C | GPIO_INTR_INTR, - txline->txgpio->register_base + intr_reg(txline->line)); + txgpio->register_base + intr_reg(irqd_to_hwirq(d))); } -static void thunderx_gpio_irq_unmask(struct irq_data *data) +static void thunderx_gpio_irq_unmask(struct irq_data *d) { - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); writeq(GPIO_INTR_ENA_W1S, - txline->txgpio->register_base + intr_reg(txline->line)); + txgpio->register_base + intr_reg(irqd_to_hwirq(d))); } -static int thunderx_gpio_irq_set_type(struct irq_data *data, +static int thunderx_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) { - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); - struct thunderx_gpio *txgpio = txline->txgpio; + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); + struct thunderx_line *txline = + &txgpio->line_entries[irqd_to_hwirq(d)]; u64 bit_cfg; - irqd_set_trigger_type(data, flow_type); + irqd_set_trigger_type(d, flow_type); bit_cfg = txline->fil_bits | GPIO_BIT_CFG_INT_EN; if (flow_type & IRQ_TYPE_EDGE_BOTH) { - irq_set_handler_locked(data, handle_fasteoi_ack_irq); + irq_set_handler_locked(d, handle_fasteoi_ack_irq); bit_cfg |= GPIO_BIT_CFG_INT_TYPE; } else { - irq_set_handler_locked(data, handle_fasteoi_mask_irq); + irq_set_handler_locked(d, handle_fasteoi_mask_irq); } raw_spin_lock(&txgpio->lock); @@ -362,33 +368,6 @@ static void thunderx_gpio_irq_disable(struct irq_data *data) irq_chip_disable_parent(data); } -static int thunderx_gpio_irq_request_resources(struct irq_data *data) -{ - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); - struct thunderx_gpio *txgpio = txline->txgpio; - int r; - - r = gpiochip_lock_as_irq(&txgpio->chip, txline->line); - if (r) - return r; - - r = irq_chip_request_resources_parent(data); - if (r) - gpiochip_unlock_as_irq(&txgpio->chip, txline->line); - - return r; -} - -static void thunderx_gpio_irq_release_resources(struct irq_data *data) -{ - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); - struct thunderx_gpio *txgpio = txline->txgpio; - - irq_chip_release_resources_parent(data); - - gpiochip_unlock_as_irq(&txgpio->chip, txline->line); -} - /* * Interrupts are chained from underlying MSI-X vectors. We have * these irq_chip functions to be able to handle level triggering @@ -405,48 +384,42 @@ static struct irq_chip thunderx_gpio_irq_chip = { .irq_unmask = thunderx_gpio_irq_unmask, .irq_eoi = irq_chip_eoi_parent, .irq_set_affinity = irq_chip_set_affinity_parent, - .irq_request_resources = thunderx_gpio_irq_request_resources, - .irq_release_resources = thunderx_gpio_irq_release_resources, .irq_set_type = thunderx_gpio_irq_set_type, .flags = IRQCHIP_SET_TYPE_MASKED }; -static int thunderx_gpio_irq_translate(struct irq_domain *d, - struct irq_fwspec *fwspec, - irq_hw_number_t *hwirq, - unsigned int *type) +static int thunderx_gpio_child_to_parent_hwirq(struct gpio_chip *gc, + unsigned int child, + unsigned int child_type, + unsigned int *parent, + unsigned int *parent_type) { - struct thunderx_gpio *txgpio = d->host_data; + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); + struct irq_data *irqd; + unsigned int irq; - if (WARN_ON(fwspec->param_count < 2)) + irq = txgpio->msix_entries[child].vector; + irqd = irq_domain_get_irq_data(gc->irq.parent_domain, irq); + if (!irqd) return -EINVAL; - if (fwspec->param[0] >= txgpio->chip.ngpio) - return -EINVAL; - *hwirq = fwspec->param[0]; - *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; + *parent = irqd_to_hwirq(irqd); + *parent_type = IRQ_TYPE_LEVEL_HIGH; return 0; } -static int thunderx_gpio_irq_alloc(struct irq_domain *d, unsigned int virq, - unsigned int nr_irqs, void *arg) +static void *thunderx_gpio_populate_parent_alloc_info(struct gpio_chip *chip, + unsigned int parent_hwirq, + unsigned int parent_type) { - struct thunderx_line *txline = arg; - - return irq_domain_set_hwirq_and_chip(d, virq, txline->line, - &thunderx_gpio_irq_chip, txline); -} - -static const struct irq_domain_ops thunderx_gpio_irqd_ops = { - .alloc = thunderx_gpio_irq_alloc, - .translate = thunderx_gpio_irq_translate -}; + msi_alloc_info_t *info; -static int thunderx_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) -{ - struct thunderx_gpio *txgpio = gpiochip_get_data(chip); + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return NULL; - return irq_find_mapping(txgpio->irqd, offset); + info->hwirq = parent_hwirq; + return info; } static int thunderx_gpio_probe(struct pci_dev *pdev, @@ -456,6 +429,7 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, struct device *dev = &pdev->dev; struct thunderx_gpio *txgpio; struct gpio_chip *chip; + struct gpio_irq_chip *girq; int ngpio, i; int err = 0; @@ -500,8 +474,8 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, } txgpio->msix_entries = devm_kcalloc(dev, - ngpio, sizeof(struct msix_entry), - GFP_KERNEL); + ngpio, sizeof(struct msix_entry), + GFP_KERNEL); if (!txgpio->msix_entries) { err = -ENOMEM; goto out; @@ -542,27 +516,6 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, if (err < 0) goto out; - /* - * Push GPIO specific irqdomain on hierarchy created as a side - * effect of the pci_enable_msix() - */ - txgpio->irqd = irq_domain_create_hierarchy(irq_get_irq_data(txgpio->msix_entries[0].vector)->domain, - 0, 0, of_node_to_fwnode(dev->of_node), - &thunderx_gpio_irqd_ops, txgpio); - if (!txgpio->irqd) { - err = -ENOMEM; - goto out; - } - - /* Push on irq_data and the domain for each line. */ - for (i = 0; i < ngpio; i++) { - err = irq_domain_push_irq(txgpio->irqd, - txgpio->msix_entries[i].vector, - &txgpio->line_entries[i]); - if (err < 0) - dev_err(dev, "irq_domain_push_irq: %d\n", err); - } - chip->label = KBUILD_MODNAME; chip->parent = dev; chip->owner = THIS_MODULE; @@ -577,11 +530,35 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, chip->set = thunderx_gpio_set; chip->set_multiple = thunderx_gpio_set_multiple; chip->set_config = thunderx_gpio_set_config; - chip->to_irq = thunderx_gpio_to_irq; + girq = &chip->irq; + girq->chip = &thunderx_gpio_irq_chip; + girq->fwnode = of_node_to_fwnode(dev->of_node); + girq->parent_domain = + irq_get_irq_data(txgpio->msix_entries[0].vector)->domain; + girq->child_to_parent_hwirq = thunderx_gpio_child_to_parent_hwirq; + girq->populate_parent_alloc_arg = thunderx_gpio_populate_parent_alloc_info; + girq->handler = handle_bad_irq; + girq->default_type = IRQ_TYPE_NONE; + err = devm_gpiochip_add_data(dev, chip, txgpio); if (err) goto out; + /* Push on irq_data and the domain for each line. */ + for (i = 0; i < ngpio; i++) { + struct irq_fwspec fwspec; + + fwspec.fwnode = of_node_to_fwnode(dev->of_node); + fwspec.param_count = 2; + fwspec.param[0] = i; + fwspec.param[1] = IRQ_TYPE_NONE; + err = irq_domain_push_irq(girq->domain, + txgpio->msix_entries[i].vector, + &fwspec); + if (err < 0) + dev_err(dev, "irq_domain_push_irq: %d\n", err); + } + dev_info(dev, "ThunderX GPIO: %d lines with base %d.\n", ngpio, chip->base); return 0; @@ -596,10 +573,10 @@ static void thunderx_gpio_remove(struct pci_dev *pdev) struct thunderx_gpio *txgpio = pci_get_drvdata(pdev); for (i = 0; i < txgpio->chip.ngpio; i++) - irq_domain_pop_irq(txgpio->irqd, + irq_domain_pop_irq(txgpio->chip.irq.domain, txgpio->msix_entries[i].vector); - irq_domain_remove(txgpio->irqd); + irq_domain_remove(txgpio->chip.irq.domain); pci_set_drvdata(pdev, NULL); }