From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1030407AbbJ3UAr (ORCPT ); Fri, 30 Oct 2015 16:00:47 -0400 Received: from mail-by2on0131.outbound.protection.outlook.com ([207.46.100.131]:52448 "EHLO na01-by2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1760241AbbJ3T7Q (ORCPT ); Fri, 30 Oct 2015 15:59:16 -0400 Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=freescale.com; freescale.mail.onmicrosoft.com; dkim=none (message not signed) header.d=none;freescale.mail.onmicrosoft.com; dmarc=none action=none header.from=freescale.com; From: "J. German Rivera" To: , , , CC: , , , , , , , , , , , , , , "J. German Rivera" Subject: [PATCH v2 10/11] staging: fsl-mc: Added DPRC interrupt handler Date: Fri, 30 Oct 2015 14:43:36 -0500 Message-ID: <1446234217-25512-11-git-send-email-German.Rivera@freescale.com> X-Mailer: git-send-email 2.3.3 In-Reply-To: <1446234217-25512-1-git-send-email-German.Rivera@freescale.com> References: <1446234217-25512-1-git-send-email-German.Rivera@freescale.com> X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BN1BFFO11FD050;1:T0BsjkWVKYHgaABC5EjPYMuqTHLs7EVHwIYQgJ8vGbj9EunBeiYr2o6rhXSrvxzr9+DX3KWHyQ6ii7NuIjTXEuodO1ykiG5nc26VmfEvSEIPSsjEflYx7sN90daHvIlA6xJMrRQ6yB/ujjOQhYrKN63tsHJyZjsT75Eeq+lI/VFEk5HX4Z56Sf/PT4FxaW0obmw25LHD1WyuiHCWcucml/X5cT+rTBKwmt4AaZs/PD1UvGPKxg5km6rF5QKSUoZr0Vsws6QlTAxMOEcd8SbQ3gOEyLcvE09axPN9vzkDSMWhkT4IZlkBgRWgvsFORNQ4+Hvn5bHfDr1qHFCCerVXdAfw4yCMF5q8kWBsObSe4FadxbOzMPd8q2WM1xLzO59gFXGZpbQvCZCMoz+8aMbs0A== X-Forefront-Antispam-Report: CIP:192.88.168.50;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10019020)(6009001)(2980300002)(1110001)(1109001)(339900001)(199003)(189002)(4001430100002)(5003940100001)(229853001)(36756003)(105606002)(106466001)(5008740100001)(2201001)(76176999)(50986999)(104016004)(92566002)(6806005)(86362001)(575784001)(2950100001)(77096005)(81156007)(85426001)(50466002)(87936001)(5001960100002)(19580395003)(5007970100001)(11100500001)(97736004)(5001770100001)(5001920100001)(19580405001)(50226001)(189998001)(47776003)(48376002)(107886002);DIR:OUT;SFP:1102;SCL:1;SRVR:BN3PR03MB1478;H:tx30smr01.am.freescale.net;FPR:;SPF:Fail;PTR:InfoDomainNonexistent;A:1;MX:1;LANG:en; MIME-Version: 1.0 Content-Type: text/plain X-Microsoft-Exchange-Diagnostics: 1;BN3PR03MB1478;2:brVE2kU4zaDsI+ScxCz12u78SXvbDzvY9W9hfppUhGJJp9AALM8nfZf/kdF7RgXhzVBJfjvhlJCmIoKzAc1LARj9Ms8hxHe5Elrd5LKPtTQ3Rh7dHVzVJE041CcxMv4xsAVhOjAfO7nFDdXuAV6mnwE3SUV0efs4E66gyJMzMHw=;3:6LmS91rZwVrwrPk0v3QCMKjaJ0BiN91GBE5TsaDljKZn0wcxfbCLicL/8RVQsOaMFkWWL7e+BbYzIaOI9mLQaDJzyAv90G/E1qimsNHkT87qFauVAeiOmynMt3/ubsO77I450pUdW7g81o/KkoralBJ3/en9r2RDN2cRbfcv6VfTYuHCVVmhAdKEXHIgNi/DAQ3QRacJyI4/5CnwIw0BIPZQM0TGiBCDtwhR8JzaoHs=;25:OSVg8lcW0Yb7bIbHUdwR6wO+euC7/ADlxNnxjT1Ds16g64RzWFy1scFMkIqDGwMWM4BC01VfY/ifVJUGJPuykl3fnReHRNgK8oMAB/xSGzxHkXnr0lo1tlUz98/imffz7g7oA3jdeoOJ/AXeGdwgd1xeW1FQAQPR+ggsmC7CAfpxyu99Sy9hjq3m+sGf1y2dT1GlG8o7Or4mA+A/p2XsO86UZ6rUW21aLZrxprl2KobwgxB1UzalduYJl8lTtzvQbXD6vCF9j6Czenb3Gq+EGg== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BN3PR03MB1478; X-Microsoft-Exchange-Diagnostics: 1;BN3PR03MB1478;20:T2WQzmOtGkASEFdcg0gZ7tA5ud/OKyUxu5pLtJO/NeMc8O0+ckzT3c7UygEnRbyZlswbTxClIN5wsGqjba3xahxAO3HwibL+DwfDbekED4KehE9s5ib9wthLFvb1hXKzadkDENIH7+AIg8zkPk67/C3Inl5VrMOHGe/uWGef5fWhAoc4KqDqqGJ6b5UyCBTwRH35+fxEdm2cywdyNiCeZ1FyEr1XYYmg68w67nd23Py0wrEqrd/40EyehDbOBfuSqD5shmYMyYm/rxDZCW08re+WFQiowg+ZrraZ1voEcjVe+dlxwIbpmcOt8tiQH8oAe+pegvruXaas41q2dic9jNsHWNW2/VOA69PPHFyhmhI=;4:64DJRjqcSw1IcSEX5l1gT7gWtj9YyFIISDM0KklWMm5vCLWsBuM4yZiIDi/bQgAF1ApF23OX+Ut1EvTBHbJJT4Wmu73avta50dkJ53TeawpXN3xFsJT9ZbKmYPi7CUA3wot6kLpHOLqDXy5STmxL63HEEeck4on9hGZ3AO9rfY07e1xHFWvOSjzxOnFTcXlXY0FDjZoGif7E6xPdlehTapzIPZtHr3TcqmWCnZQpfK0MepQANh9uEL1Jl0AkXI5S0TTAdVtYi2BehFSprJqF76sST0+h5A2FAR6x5TZU5K9UBCiSpvYqxkisVyF8WwIXfTooeinxtv4cw+3r0DZJnN0KhKMoN0q9Z1yU3vilBV0NkYhntUoA6nopIdGqcDvkUwV+n6LnAwZqJM3lDOuTcQ== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(101931422205132); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(8121501046)(520078)(5005006)(10201501046)(3002001)(102215026);SRVR:BN3PR03MB1478;BCL:0;PCL:0;RULEID:;SRVR:BN3PR03MB1478; X-Forefront-PRVS: 07459438AA X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BN3PR03MB1478;23:XQtXh0NylTjOYySUS51Z6mg9eFpUGdR8Cd13b4G18?= =?us-ascii?Q?DKmU86CffOz97xwhjLQGJIQr6CePpkARYo2jpfZL82BUU2uMCGDTXOE+5FsM?= =?us-ascii?Q?jbUPyx0a3qELAnTuiDqw7u4w4zlSzHMWyFDRG13ShL5hcGRrYpb0HqHcY9K9?= =?us-ascii?Q?qVzvEVvrzfOgtcC2T1K4jmHjueag2VPvhOmMq9AmF7rfOa0qn3vBrvS4UPhh?= =?us-ascii?Q?w3EK/i/UsusWvxiRflYu94wAaJHy/jA9/7z8pDhK4mZfnewL9xUCKqI+Zf4A?= =?us-ascii?Q?928Pcgr6LRyP6nJ0/Z6mIdRR+9yhsHVOtcsKSwGiGolm/TScXI07AobTGH1R?= =?us-ascii?Q?gcOIWXj3N3MsUdVg+pf/rHTIyofm4Q0HPKTGQRkEImjaCZpF/91XgIDdxhYI?= =?us-ascii?Q?YFwwC3+3Gcg342CvkGm24SN8+qjk2MrS5J95RoUvu7cRQRI5I3nA+0LfP5ED?= =?us-ascii?Q?+aOlfofLM5j1IZI+QPxzA5vKoV3uBoBQocsE0D3OOM412XIo63OQqyyeaRhm?= =?us-ascii?Q?X6tgx1UZRduF8iDR7lfItGtMy61mPlGYrr6scMCWrpBe3muXxTpx4gc3kaRh?= =?us-ascii?Q?uszNk6nGyzkNcy9JMeqkCIp6fPDdfQheMnlvyWayQpbynKRE/+Ebm/tETDpt?= =?us-ascii?Q?iiFv/i51WttSEtcJCg/ZR6097kBXEMTaov+6JPiaZz/aYvtR3mU+/LfvDLVs?= =?us-ascii?Q?QehhwClm38plj7qaVQp8QhrIyvz+m9H6shgwUnoComoymUUWjfquChVQ6IZ/?= =?us-ascii?Q?sz5M3O8NWr+Oe/5fmYPv7tPb3m4T2jFXCOa0sQ3bThr97LjYNmSkvqxzLSjD?= =?us-ascii?Q?EMt5pJXTr1QUa99MJvQDHc6fLJHmqB6/ukR7hQQkm49RVNtbUNnJuAtvaBHb?= =?us-ascii?Q?Tl7cXXSI5talvSgMEAZdCSjcM8KVewFLqfHmKUKtfbBZzrvWBpPz4V2oubvc?= =?us-ascii?Q?iSUlJL454w5meGKv9efwgpjOXxFRgObxjPoR30hTGJOHS2ZMAqCDb6KLgzqK?= =?us-ascii?Q?6le3EQWSQy9Vt3LmDoNdHkYZbBFmqv5OpsHTuRu+9OH1HSq7nsCOqwGlnLKg?= =?us-ascii?Q?DVP8hzR1ib/+utE3YZgDWjUplAKTITP4znEtx80sBqbQad/BFwYKqC7I3BYR?= =?us-ascii?Q?4+ljKHAvVnsP45g5YA5A9bCwGOd2hC0?= X-Microsoft-Exchange-Diagnostics: 1;BN3PR03MB1478;5:YLJ7C/g9Lwfs/EhAlSR6pvHfzH8+A0RfD/ZPvHSFLK/42EfGpH1+6BL15vB7bdgFCKeBxPAd4hRb+lVnp9chLzIh2COwkxwyvXw9smiVLGFZxwqmQMhEL+ce8fa3x/OkdMmQAbpSHTMuVtwC2YWUDQ==;24:2JruVuC1zCXDTE3qWVl836c38UJwVcUwXSXFeruJrRiIQU0ZxL4FY4kmyAoolgtsjAYxY7IVdupowKa+FUIJkoixUzQhu34dOtfMPAgri60=;20:pDBEL+4YICH75oB9ChldZlfHYEe+4zweCFJtOCg68DF15XyxAvOnTqCOiXZ6Qrpc8Tk36RCT4rZOcMt5ImefAg== X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 30 Oct 2015 19:59:13.0792 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d;Ip=[192.88.168.50];Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR03MB1478 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The interrupt handler for DPRC IRQs is added. DPRC IRQs are generated for hot plug events related to DPAA2 objects in a given DPRC. These events include, creating/destroying DPAA2 objects in the DPRC, changing the "plugged" state of DPAA2 objects and moving objects between DPRCs. Signed-off-by: J. German Rivera --- Changes in v2: none drivers/staging/fsl-mc/bus/dprc-driver.c | 247 +++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 7f1ceb5..0bd2e63 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "dprc-cmd.h" struct dprc_child_objs { @@ -386,6 +387,230 @@ error: EXPORT_SYMBOL_GPL(dprc_scan_container); /** + * dprc_irq0_handler - Regular ISR for DPRC interrupt 0 + * + * @irq: IRQ number of the interrupt being handled + * @arg: Pointer to device structure + */ +static irqreturn_t dprc_irq0_handler(int irq_num, void *arg) +{ + return IRQ_WAKE_THREAD; +} + +/** + * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0 + * + * @irq: IRQ number of the interrupt being handled + * @arg: Pointer to device structure + */ +static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg) +{ + int error; + u32 status; + struct device *dev = (struct device *)arg; + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); + struct fsl_mc_io *mc_io = mc_dev->mc_io; + struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc; + + dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n", + irq_num, smp_processor_id()); + + if (WARN_ON(!(mc_dev->flags & FSL_MC_IS_DPRC))) + return IRQ_HANDLED; + + mutex_lock(&mc_bus->scan_mutex); + if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num)) + goto out; + + error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0, + &status); + if (error < 0) { + dev_err(dev, + "dprc_get_irq_status() failed: %d\n", error); + goto out; + } + + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, + status); + if (error < 0) { + dev_err(dev, + "dprc_clear_irq_status() failed: %d\n", error); + goto out; + } + + if (status & (DPRC_IRQ_EVENT_OBJ_ADDED | + DPRC_IRQ_EVENT_OBJ_REMOVED | + DPRC_IRQ_EVENT_CONTAINER_DESTROYED | + DPRC_IRQ_EVENT_OBJ_DESTROYED | + DPRC_IRQ_EVENT_OBJ_CREATED)) { + unsigned int irq_count; + + error = dprc_scan_objects(mc_dev, &irq_count); + if (error < 0) { + /* + * If the error is -ENXIO, we ignore it, as it indicates + * that the object scan was aborted, as we detected that + * an object was removed from the DPRC in the MC, while + * we were scanning the DPRC. + */ + if (error != -ENXIO) { + dev_err(dev, "dprc_scan_objects() failed: %d\n", + error); + } + + goto out; + } + + if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { + dev_warn(dev, + "IRQs needed (%u) exceed IRQs preallocated (%u)\n", + irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); + } + } + +out: + mutex_unlock(&mc_bus->scan_mutex); + return IRQ_HANDLED; +} + +/* + * Disable and clear interrupt for a given DPRC object + */ +static int disable_dprc_irq(struct fsl_mc_device *mc_dev) +{ + int error; + struct fsl_mc_io *mc_io = mc_dev->mc_io; + + WARN_ON(mc_dev->obj_desc.irq_count != 1); + + /* + * Disable generation of interrupt, while we configure it: + */ + error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0); + if (error < 0) { + dev_err(&mc_dev->dev, + "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", + error); + return error; + } + + /* + * Disable all interrupt causes for the interrupt: + */ + error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0); + if (error < 0) { + dev_err(&mc_dev->dev, + "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", + error); + return error; + } + + /* + * Clear any leftover interrupts: + */ + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U); + if (error < 0) { + dev_err(&mc_dev->dev, + "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n", + error); + return error; + } + + return 0; +} + +static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev) +{ + int error; + struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; + + WARN_ON(mc_dev->obj_desc.irq_count != 1); + + /* + * NOTE: devm_request_threaded_irq() invokes the device-specific + * function that programs the MSI physically in the device + */ + error = devm_request_threaded_irq(&mc_dev->dev, + irq->msi_desc->irq, + dprc_irq0_handler, + dprc_irq0_handler_thread, + IRQF_NO_SUSPEND | IRQF_ONESHOT, + "FSL MC DPRC irq0", + &mc_dev->dev); + if (error < 0) { + dev_err(&mc_dev->dev, + "devm_request_threaded_irq() failed: %d\n", + error); + return error; + } + + return 0; +} + +static int enable_dprc_irq(struct fsl_mc_device *mc_dev) +{ + int error; + + /* + * Enable all interrupt causes for the interrupt: + */ + error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, + ~0x0u); + if (error < 0) { + dev_err(&mc_dev->dev, + "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", + error); + + return error; + } + + /* + * Enable generation of the interrupt: + */ + error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1); + if (error < 0) { + dev_err(&mc_dev->dev, + "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", + error); + + return error; + } + + return 0; +} + +/* + * Setup interrupt for a given DPRC device + */ +static int dprc_setup_irq(struct fsl_mc_device *mc_dev) +{ + int error; + + error = fsl_mc_allocate_irqs(mc_dev); + if (error < 0) + return error; + + error = disable_dprc_irq(mc_dev); + if (error < 0) + goto error_free_irqs; + + error = register_dprc_irq_handler(mc_dev); + if (error < 0) + goto error_free_irqs; + + error = enable_dprc_irq(mc_dev); + if (error < 0) + goto error_free_irqs; + + return 0; + +error_free_irqs: + fsl_mc_free_irqs(mc_dev); + return error; +} + +/** * dprc_probe - callback invoked when a DPRC is being bound to this driver * * @mc_dev: Pointer to fsl-mc device representing a DPRC @@ -476,6 +701,13 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) if (error < 0) goto error_cleanup_open; + /* + * Configure interrupt for the DPRC object associated with this MC bus: + */ + error = dprc_setup_irq(mc_dev); + if (error < 0) + goto error_cleanup_open; + dev_info(&mc_dev->dev, "DPRC device bound to driver"); return 0; @@ -494,6 +726,15 @@ error_cleanup_msi_domain: return error; } +/* + * Tear down interrupt for a given DPRC object + */ +static void dprc_teardown_irq(struct fsl_mc_device *mc_dev) +{ + (void)disable_dprc_irq(mc_dev); + fsl_mc_free_irqs(mc_dev); +} + /** * dprc_remove - callback invoked when a DPRC is being unbound from this driver * @@ -514,6 +755,12 @@ static int dprc_remove(struct fsl_mc_device *mc_dev) if (WARN_ON(!mc_dev->mc_io)) return -EINVAL; + if (WARN_ON(!mc_bus->irq_resources)) + return -EINVAL; + + if (dev_get_msi_domain(&mc_dev->dev)) + dprc_teardown_irq(mc_dev); + device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove); dprc_cleanup_all_resource_pools(mc_dev); error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); -- 2.3.3