Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754012AbdHRAyk (ORCPT ); Thu, 17 Aug 2017 20:54:40 -0400 Received: from mail-cys01nam02on0075.outbound.protection.outlook.com ([104.47.37.75]:46231 "EHLO NAM02-CY1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753875AbdHRAxv (ORCPT ); Thu, 17 Aug 2017 20:53:51 -0400 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=David.Daney@cavium.com; From: David Daney To: Linus Walleij , Alexandre Courbot , Mark Rutland , Marc Zyngier , Thomas Gleixner , linux-gpio@vger.kernel.org Cc: linux-kernel@vger.kernel.org, David Daney Subject: [PATCH v8 5/7] irqdomain: Add irq_domain_{push,pop}_irq() functions. Date: Thu, 17 Aug 2017 17:53:34 -0700 Message-Id: <1503017616-3252-6-git-send-email-david.daney@cavium.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1503017616-3252-1-git-send-email-david.daney@cavium.com> References: <1503017616-3252-1-git-send-email-david.daney@cavium.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [50.233.148.156] X-ClientProxiedBy: CO2PR07CA0061.namprd07.prod.outlook.com (10.174.192.29) To CY4PR07MB3493.namprd07.prod.outlook.com (10.171.252.150) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: c158160d-d292-412b-9224-08d4e5d39527 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(300000500095)(300135000095)(300000501095)(300135300095)(22001)(300000502095)(300135100095)(2017030254152)(300000503095)(300135400095)(201703131423075)(201703031133081)(201702281549075)(300000504095)(300135200095)(300000505095)(300135600095)(300000506095)(300135500095);SRVR:CY4PR07MB3493; X-Microsoft-Exchange-Diagnostics: 1;CY4PR07MB3493;3:3MIuuPxBsssQm0tQajxLKbbGmoaEGNtrq61p3arviriju5W3Hvs+r1+1YlDbgkq7OTWn6rNWAb24q1+1u3b5YmUZwc0P9K3G4rhJl9kCEvKRj6I8G/X+m9MDloomN56lnvZUvGE8AuUd5jrkdqU5cwA5DaZX4HGzvnAUZyDoUc6C+FpudRxtIHZb/VEF9m/Z34QxMTd5Zx3YbPbVmU5QPd2Nw6KvbrZL/xgSKZHbs/EIgAV9SQxszfw3gZ1LcBLV;25:RuAxXbkTqqm+jwkaEBrcvuhZL22NwcamdNxLRIIQejRIHN9LeIucq4YBJyITRchjzFTyIFFhskXoMFoXYF9Cekh5ardkTr7E/bsDtVcUAJQhTtCejNNWg0QF2NF4dB9ochGH4cuk4AHtRUUlG8Vk7d/Vm9vg2MhL8T6Gsvog2d4fkXRyBZQmvv33PRIZxDkUFx+F+wBij2b7pwidGqXI9l+Ovu0V6GfxFY6zZuGNFYhJ226J0Gqa6ai4So6WGQJFhcqC+MKxJDLBmeYw6qagTf2e7biV/wjenNMw17TH06Afq1OTrlpBAeiu0yPfOwmUaWxjwDth/GJW+Bq48woflQ==;31:PqFGvh2ZCUgMEmrE4lMVkshTxlZ/7pFpRFrF1U/GvArteINq1EwLup4diAWKJ62njm45jyylqd4ox/ilzUiZrpDvqkzDnUUD/LDQBLSe4VcbB0T7Cs6F3tEJoGi+scqIaHSBMUF5vyLmZlThbXUNSukiR0fhKUw/nzq6UzCE0I0JzCuKX47vJVLOKHbtgmkmhQVWJZZIZ2SgE2PS1QJi0I9siUYFzoI7smjEo9yOxIY= X-MS-TrafficTypeDiagnostic: CY4PR07MB3493: X-Microsoft-Exchange-Diagnostics: 1;CY4PR07MB3493;20:cqPDTh/H+GlFfNRB/5h9EZwBSvYuZMzGakvpkAGNDtYJ4zFnFF+ONr2k4BDZJt7N9aQC4U65TsPtkPThef6/g6wF8fyaPlW/7emrapp4blDUmDLmpeuIvlLqVgu0zNfZaSNUZplQzLVjSReeA28yH9f9OAbBIXiQZhP+ey4dkkfct0BDlb/emKUuE2/Yq46J7fDGsBxeDAQuyMRLnKa9DjvfMOzm3QhZIpQcbmjGXRw2iya+frS9k0Hopw9IWYAtqfBGeZwqcF5b+7QKKe6iJuaUHPuQYMxh8IGDz8mXOFUQ0tie1iBQNEMWQTNxevRR1b2CckpMm4/2YROiINJoeOCZu+Ypx/EwZXiZqaFmZNLCFyRl8ZiUTrT6zU5yMDBI9EPw7XIlbaRUDGhYK3IhqMebBugyPaqcOBsbCIA0iZesxeWLaD1o2u3OPGUg6drElcFy/uJdpa3gxkg7sg2UIOE/wlgXSjXiUB3YRC8a7tmxQheqeFD4WA5oMtICcKY8;4:pQm9PTjcKiZUcqOWhM7ZIesZHglvFRTVAZOJw6kzh4KU53tJW/lnT6MoU4a2ihNNPyWEpdACIXPfECw52gNqLrBExZfuc1Laf1nr1Py+W7HuHjctKm0JUnB1og0EMGRv6N06/FNx741wTFa6/1OBjVTxwrHPkAq5r/VEXCE7aTvvzo7dt6gH9EAyRD7mTndpqoEeqhsgYypk96Z/WLHM3wrZ9R0ehFryQRx86uVX302Xct5VtsS+91iD4jHyVcQB X-Exchange-Antispam-Report-Test: UriScan:; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(601004)(2401047)(5005006)(8121501046)(10201501046)(3002001)(100000703101)(100105400095)(93006095)(93001095)(6041248)(20161123562025)(20161123564025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123555025)(20161123560025)(20161123558100)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095);SRVR:CY4PR07MB3493;BCL:0;PCL:0;RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095);SRVR:CY4PR07MB3493; X-Forefront-PRVS: 040359335D X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(4630300001)(7370300001)(6009001)(189002)(199003)(69596002)(72206003)(50226002)(6116002)(3846002)(4326008)(105586002)(42186005)(2950100002)(6666003)(5003940100001)(4720700003)(76176999)(50986999)(5660300001)(189998001)(7350300001)(53416004)(33646002)(101416001)(53936002)(478600001)(6512007)(50466002)(2906002)(48376002)(7736002)(68736007)(107886003)(66066001)(25786009)(86362001)(47776003)(97736004)(36756003)(106356001)(6486002)(6506006)(305945005)(81156014)(81166006)(8676002)(142933001);DIR:OUT;SFP:1101;SCL:1;SRVR:CY4PR07MB3493;H:ubuntu.caveonetworks.com;FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;CY4PR07MB3493;23:uGJjkICRE4hjTzVPt+tvgjEgTw4G9aqyLclH7BRJp?= =?us-ascii?Q?Thgkclx7/Y5s7HjEBH2R9qkPw08oE0SgCh7Qqwyl9vPIfmlmNaHfQQ8O/bN0?= =?us-ascii?Q?aPw7+Y2pYMEKxLh5oMqM/QXakoKNT7xA2UFnMpq42W/D14QNsx1SrJqlVteA?= =?us-ascii?Q?a7cmiLAWyB50c+QLbv1AUIfeY1nLu1DaIJCp9UReaHXfUkMsub6BM/f/Iz7H?= =?us-ascii?Q?APBomPFkey4eTT0cWj+X7ps/V5Drne706X7SuwibpkP1qPtr4jm6LNmyUErG?= =?us-ascii?Q?xO26yBkAi9QGt2P2WDIIM3AjVpmsgZZuol6m8Dh6D3MYhpSnlIBNBfC7XR0N?= =?us-ascii?Q?nJZy2kyNXBL2Jfv98Z2kDHi3CvnGRTcSamYQHK0G46HhBgT1mHfWkcnYoQeb?= =?us-ascii?Q?ctMnAOzHit8k+mRzGIMBCTMyb/uquMKfAODZOYklrdWBaNKalQMB8TszccL6?= =?us-ascii?Q?dzV4j01hw1sUvTlyiTgkxnzj7qNmqngiBHErZKNw3LpsB0uVnFPoklcw2BYR?= =?us-ascii?Q?XpBlOVuY5xt5n+b6y/7SQ1ouassxDFAKF2ucSLG2WgBR4IuK5/mainYAnDX+?= =?us-ascii?Q?9brP/T23XsJuc5Anfxntzpa+fbozHKa0xRC8+JC1UkK9jF5D2fIX47/+1e0c?= =?us-ascii?Q?fn8n/u/CKY7yBEQa3C/oC2cWne2ZJGZqfcavJC9nsLbtUOHHRGrD5w8rzN2w?= =?us-ascii?Q?oR19c0wxMFTgA/hZq9NmbBh7b/rCwXATM/aCdPG4It437XLSC2F1CSqM167I?= =?us-ascii?Q?w9rcdwq593ihg4gJUurwkkZj20JbNm85S+ArJQufzVeMudptRoZ7MnEKGii4?= =?us-ascii?Q?u+GLz3u/XsNqFhAjwMu+BkyGxQIa3GBGN7GuDsU4i6vWIbfD9NC5zjqDXNQL?= =?us-ascii?Q?h1qI2jmHxw6hO82e25Jpd6NrH0HbZZdT/G4QTTvGRwe+70lfhjIVcJypphxg?= =?us-ascii?Q?clLcpm/kaSiWbjifvF3Rt8XPDILsK8lRwDc9egqFaS6gm58ehQbqpamDlCtz?= =?us-ascii?Q?yslHPiWD702z/L8z9syL/EYYa9QXbL+x+UFeaHkxh3Lfe+yzFofCBhnCUHoh?= =?us-ascii?Q?5jNBeViof0rAhxULuaVrvKCgGAym5oy2VB9WVgz3uq51v9j5IopBsbOEMYAe?= =?us-ascii?Q?R8r+c3zHnoxxKl6dJJun/DTZuT0zazi3W6W0LkpMaF0O25Jb92VMaFTi3sLa?= =?us-ascii?Q?MrQxMm3bitWizI=3D?= X-Microsoft-Exchange-Diagnostics: 1;CY4PR07MB3493;6:WjDAr3kTSwaAFXdtszJs0YzZyfuN4fP5FW3Rg4IdEi6WnUskiZl3vVRgrESHdUHrOIiB0B/JacmdmSJDbOoozrSvG3tSKRKH+GMYWZg9jUF5CG9i42u7PFmrZqHlkqbBhLzE+MjviqZVxwLTBV6iHHKA0uDRXKWMT/xU4bfIfHOiuMBxJoovtt64uBV5+QSBMcq2Yg2YpJkBqRUzWMf692EA8k5zGFjHhiDNORPGrZPU/oa2/H0pF1nyOMjt0lQ+mM3+SVmoOoAo2Cwn/X94wVkMBhywb/DNJAdzZjRto5sm6ETWvbbI41LnocE/urbPIBhhRAgfXZ3et2ZMzr2Clg==;5:L9ErQkjjPBlTsTMh0b/qB8zvbo2vYkhT52e02IZDc2PX8L4QPlnhf50w/S+EY3qZuHq7clkXk64xRD4Utlpan9pINW9AEJIWe9WWWKYs9wXT+BmggKky14IYSRE4XZ1gKuCVFyly7z8v86GUCCj7Kg==;24:JDdu66A0DYCESI7nlJJsrpyp6jUG9SQSCxsRQnk2aneNK/9P2OUeVzWuZbpkT+80xBLB+bdyLrOBo20LO/8YHjpr6FOLDaDYL7o7iin9A+I=;7:xI3AVzqeUt0kYE2NsEB+bQRuCRHRSzpR0c3BgVUubndQElJsawudICn3PlBj4vx5gfGcgtUwgF8fFGv/ou6hjexFSRqRingtjP4Ojoy89zh9IaiqKIqb+0UuXfN7KNmcHe+iX+4ZQtgPHGJZJmLk9oYfZdd+wZb5RIujUERW43f4UsBuGmzOJDJq2NsyUxJ086xNdBOsCNslA2jNa6u5lhS8kaxoNZSKqQfvgp3qjlI= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Aug 2017 00:53:46.4687 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY4PR07MB3493 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6687 Lines: 213 For an already existing irqdomain hierarchy, as might be obtained via a call to pci_enable_msix_range(), a PCI driver wishing to add an additional irqdomain to the hierarchy needs to be able to insert the irqdomain to that already initialized hierarchy. Calling irq_domain_create_hierarchy() allows the new irqdomain to be created, but no existing code allows for initializing the associated irq_data. Add a couple of helper functions (irq_domain_push_irq() and irq_domain_pop_irq()) to initialize the irq_data for the new irqdomain added to an existing hierarchy. Signed-off-by: David Daney --- include/linux/irqdomain.h | 3 + kernel/irq/irqdomain.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index cac77a5..2318f29 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -460,6 +460,9 @@ extern void irq_domain_free_irqs_common(struct irq_domain *domain, extern void irq_domain_free_irqs_top(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs); +extern int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg); +extern int irq_domain_pop_irq(struct irq_domain *domain, int virq); + extern int irq_domain_alloc_irqs_parent(struct irq_domain *domain, unsigned int irq_base, unsigned int nr_irqs, void *arg); diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 24fda75..1ff9912 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -1449,6 +1449,175 @@ int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base, return ret; } +/* The irq_data was moved, fix the revmap to refer to the new location */ +static void irq_domain_fix_revmap(struct irq_data *d) +{ + void **slot; + + if (d->hwirq < d->domain->revmap_size) + return; /* Not using radix tree. */ + + /* Fix up the revmap. */ + mutex_lock(&revmap_trees_mutex); + slot = radix_tree_lookup_slot(&d->domain->revmap_tree, d->hwirq); + if (slot) + radix_tree_replace_slot(&d->domain->revmap_tree, slot, d); + mutex_unlock(&revmap_trees_mutex); +} + +/** + * irq_domain_push_irq() - Push a domain in to the top of a hierarchy. + * @domain: Domain to push. + * @virq: Irq to push the domain in to. + * @arg: Passed to the irq_domain_ops alloc() function. + * + * For an already existing irqdomain hierarchy, as might be obtained + * via a call to pci_enable_msix(), add an additional domain to the + * head of the processing chain. Must be called before request_irq() + * has been called. + */ +int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg) +{ + struct irq_data *child_irq_data; + struct irq_data *root_irq_data = irq_get_irq_data(virq); + struct irq_desc *desc; + int rv = 0; + + /* + * Check that no action has been set, which indicates the virq + * is in a state where this function doesn't have to deal with + * races between interrupt handling and maintaining the + * hierarchy. This will catch gross misuse. Attempting to + * make the check race free would require holding locks across + * calls to struct irq_domain_ops->alloc(), which could lead + * to deadlock, so we just do a simple check before starting. + */ + desc = irq_to_desc(virq); + if (!desc) + return -EINVAL; + if (WARN_ON(desc->action)) + return -EBUSY; + + if (domain == NULL) + return -EINVAL; + + if (WARN_ON(!irq_domain_is_hierarchy(domain))) + return -EINVAL; + + if (domain->parent != root_irq_data->domain) + return -EINVAL; + + if (!root_irq_data) + return -EINVAL; + + child_irq_data = kzalloc_node(sizeof(*child_irq_data), GFP_KERNEL, + irq_data_get_node(root_irq_data)); + if (!child_irq_data) + return -ENOMEM; + + mutex_lock(&irq_domain_mutex); + + /* Copy the original irq_data. */ + *child_irq_data = *root_irq_data; + + /* + * Overwrite the root_irq_data, which is embedded in struct + * irq_desc, with values for this domain. + */ + root_irq_data->parent_data = child_irq_data; + root_irq_data->domain = domain; + root_irq_data->mask = 0; + root_irq_data->hwirq = 0; + root_irq_data->chip = NULL; + root_irq_data->chip_data = NULL; + + /* May (probably does) set hwirq, chip, etc. */ + rv = irq_domain_alloc_irqs_hierarchy(domain, virq, 1, arg); + if (rv) { + /* Restore the original irq_data. */ + *root_irq_data = *child_irq_data; + goto error; + } + + irq_domain_fix_revmap(child_irq_data); + irq_domain_set_mapping(domain, root_irq_data->hwirq, root_irq_data); + +error: + mutex_unlock(&irq_domain_mutex); + + return rv; +} +EXPORT_SYMBOL_GPL(irq_domain_push_irq); + +/** + * irq_domain_pop_irq() - Remove a domain from the top of a hierarchy. + * @domain: Domain to remove. + * @virq: Irq to remove the domain from. + * + * Undo the effects of a call to irq_domain_push_irq(). Must be + * called either before request_irq() or after free_irq(). + */ +int irq_domain_pop_irq(struct irq_domain *domain, int virq) +{ + struct irq_data *root_irq_data = irq_get_irq_data(virq); + struct irq_data *child_irq_data; + struct irq_data *tmp_irq_data; + struct irq_desc *desc; + + /* + * Check that no action is set, which indicates the virq is in + * a state where this function doesn't have to deal with races + * between interrupt handling and maintaining the hierarchy. + * This will catch gross misuse. Attempting to make the check + * race free would require holding locks across calls to + * struct irq_domain_ops->free(), which could lead to + * deadlock, so we just do a simple check before starting. + */ + desc = irq_to_desc(virq); + if (!desc) + return -EINVAL; + if (WARN_ON(desc->action)) + return -EBUSY; + + if (domain == NULL) + return -EINVAL; + + if (!root_irq_data) + return -EINVAL; + + tmp_irq_data = irq_domain_get_irq_data(domain, virq); + + /* We can only "pop" if this domain is at the top of the list */ + if (WARN_ON(root_irq_data != tmp_irq_data)) + return -EINVAL; + + if (WARN_ON(root_irq_data->domain != domain)) + return -EINVAL; + + child_irq_data = root_irq_data->parent_data; + if (WARN_ON(!child_irq_data)) + return -EINVAL; + + mutex_lock(&irq_domain_mutex); + + root_irq_data->parent_data = NULL; + + irq_domain_clear_mapping(domain, root_irq_data->hwirq); + irq_domain_free_irqs_hierarchy(domain, virq, 1); + + /* Restore the original irq_data. */ + *root_irq_data = *child_irq_data; + + irq_domain_fix_revmap(root_irq_data); + + mutex_unlock(&irq_domain_mutex); + + kfree(child_irq_data); + + return 0; +} +EXPORT_SYMBOL_GPL(irq_domain_pop_irq); + /** * irq_domain_free_irqs - Free IRQ number and associated data structures * @virq: base IRQ number -- 1.8.3.1