From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758183AbbKGBrU (ORCPT ); Fri, 6 Nov 2015 20:47:20 -0500 Received: from mail-bn1on0140.outbound.protection.outlook.com ([157.56.110.140]:2714 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1758156AbbKGBq0 (ORCPT ); Fri, 6 Nov 2015 20:46:26 -0500 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 v3 10/11] staging: fsl-mc: Added DPRC interrupt handler Date: Fri, 6 Nov 2015 19:30:26 -0600 Message-ID: <1446859827-6927-11-git-send-email-German.Rivera@freescale.com> X-Mailer: git-send-email 2.3.3 In-Reply-To: <1446859827-6927-1-git-send-email-German.Rivera@freescale.com> References: <1446859827-6927-1-git-send-email-German.Rivera@freescale.com> X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11FD031;1:q5AI9wJSID4AGcEWyKs9EQ7Ouf5oqyIzzRQf2KiuLvHmjzaXfYaESgMaloSCSnn0AOrGsMWRZ3W3aFRnpI0Imf7351CEuBr+e5M96aCNhbcNXER0WSJ3uIpQV+cBxxapYZXff5CTBiIdgSU+CUYKfGSzMTY3I0Apr5ZrprjXdtRDfEXU8em7b9t8A8IkfCxQnj6jeeyMn1Gz6RygVxLo5+GizP2Sh3y+gTfP3EeKzTx+FF6k2Lz7AK4U7opyjq4aUFr+8Ioa8WQKIyfJWKQvsrt/lYukpGGaPBuUgOpIIK3IhbiKoIQifLeNKbvSJUfGnmNJxuSlxtRt3aXGHYgEjLmjJRXcrKIJoF0TgocFA2CGGXS64yhEw/QnarLN2fpBY9mGjADPRiHgFM4YVIC8Eg== X-Forefront-Antispam-Report: CIP:192.88.168.50;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10019020)(6009001)(2980300002)(1109001)(1110001)(339900001)(199003)(189002)(19580405001)(5001770100001)(2201001)(5007970100001)(81156007)(50226001)(189998001)(19580395003)(48376002)(97736004)(106466001)(229853001)(107886002)(50986999)(76176999)(50466002)(5003940100001)(86362001)(105606002)(85426001)(87936001)(5001960100002)(47776003)(575784001)(2950100001)(5008740100001)(92566002)(4001430100002)(104016004)(36756003)(6806005)(77096005);DIR:OUT;SFP:1102;SCL:1;SRVR:BY1PR0301MB1302;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;BY1PR0301MB1302;2:Mepo3ZD2AKrtx7u/tOPMNUsltfYKGl2Dax9hVzA4gU+kxF464+t0vS8zKoeiFS0TYvQNTk3ltIOYgsCzbrbLowpm0oh5I+ykFJGutPw/bzIh1B+T3oNtL+0ey9CVaU4YF7H4KRo69BMtSfQxgNSgW+tC7L0nqg/RvhykokaUal4=;3:uXeSFGZOrLuQL3FMmpPMSiNJ032bh4VBNiwmBGQa/UqJc7QH58hcX0qntNsKZ1D2TyQhmjlfpsFUvpB8+w0TarNfoaqGmx+aLTgD6gDjNuyGXHSRjs/DVVqCJamgOLmihaD5PRMtBs7seM4STyEZAkySXI1n1fDP1A1mahOelDfW+K/X6XlKxRScZTjUAd68TLy+TOAccNUb00tbbo5Kq7oi3UWNE07fg0FwM1lfnV8=;25:rzumNJRspK0G1iV44HhCAPQCHdYgQLBwJX0juh9yOxaHXBibNcvKBDHk/BUXSPQmMKN8pi2OKD0Sdp9E/L+wqFRS0Sx1Y+VuBGcalrSuna4lUleiAE69sS8iFNWYMTQWKgzi0fwHDtJ84V1oqSAAcUZpXvV+Uf5dQUQFphFu0bQmiEm0SVFmn90eygb2n0cDkmWL/1SpCn5jdVHCz1pdcnFqPne/v91GnoMiGrsgmiBKYrJFwgKo+LO2hkda+3tViiugyqoCinsrX86dB7BC5w== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY1PR0301MB1302; X-Microsoft-Exchange-Diagnostics: 1;BY1PR0301MB1302;20:zU8ScRXKoFHqe6B2C0VvTJFMCqM5GbLZ6Kz+rlOqf4GR0VKeKEFq/LFjfcfke+Xlw8USU8rJnANpp4iYRg7UJKec6Q5iplzPtHXbJbSoCcaL0+ViHd1wz5oZV8NiPksBZm3eA9cnNn9E7o9+9P5EXoJoP7W25G/JDqZYPeRvQDZyP0yYlQV+l0VYf8zSDQsAzoesQPJcBK2pKvM8JpFaH+lhqB0z1XXDxtfYh2Xu3Z6IF6fu6iUtxBcA8mszzxzR5izMo2Y0a8kGP8HD9A3qS5UWtqlPDYWFTZ3EKeny7AT5xwVcANqW41Ls7uNQtRHYmwD+MDTXs5tF9ZAS9Foihysza/OpIS4o0Uvs058PGjg=;4:+kKfRcJ+C7+pOCvs/65FykFOTN2bOalCwLcvCRN69+YwVC+fb/x0R0n9hTfpbM0RmP5nPMay8Prm8Aqcsz6HVgUPp2SEUJbS6SqU155BD4oaGG51IRT4d11VOk834V+vsbXkX7YUJ3uboxNgL2GUhJDroF7pQrHO73nweazYZNc/TCYysdkaf6RMfJJ2/VmU8MYLpFvyPaqt2966M30qhxE0fH0vEE6eufBZ7LnXhkEpDKUpq4lH+MBOhv/XsftTiKvVqC2AnqRV6sd7btvZKvV6ayv3HXiORc8SPsGS0VvcNAoorZuDoBdSzJIMz8dNGMnPgltewt+atw4jRUoh01ReX+S6OPiCXVCeGWoAMbU75k1YciKFS9DDfcdX/obi X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(101931422205132); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(5005006)(520078)(8121501046)(10201501046)(3002001);SRVR:BY1PR0301MB1302;BCL:0;PCL:0;RULEID:;SRVR:BY1PR0301MB1302; X-Forefront-PRVS: 0753EA505A X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BY1PR0301MB1302;23:HejSwimhxAlUhld3arBXFdGzH+ilbyg+iUyUUo0?= =?us-ascii?Q?EyVOQ6VurF9MF9GETp5sy28Ne8ictPIuYwdN6LtfanU+jbWdR4x8mEbkI+6b?= =?us-ascii?Q?o48O5kro8eyO2C7lJH5eag3Ih4hJcAQPHDnrmFStp45AmxzuR6M3C7tVJab4?= =?us-ascii?Q?YWwDQ2k9na8l1FrL5lTSfolKKThJAlI6To2Ncw4esUvwvPfJtrnfy+5gp/xw?= =?us-ascii?Q?xsiW3xYjwjFnMXaddOsAIbRvR9OWvBE+MskwhZqN/q6hdKQ5Sj1fMnVFeJEh?= =?us-ascii?Q?b0LlmOUTu99gYoALl5xaxDKUqJ1IY3kBItJH+exOH+s8tnHnP0/0HQA40ehQ?= =?us-ascii?Q?JsHy1sx5kbgur6/fPDSVlHy+m4m28TKn4BzWan3Ax5b7va6thjsCqLg4+JLh?= =?us-ascii?Q?VD0xi6Fa6fTOv5VLuxAYL1Ju+/iaEGrsNoAgr6trWytMtlG+wjxBX0Gm50z8?= =?us-ascii?Q?fh5POVraRo147JiJlD+uvCEMa8WFfsl6TPuKmjPK3Bl+zlO3oV/hJgNYioYl?= =?us-ascii?Q?b8oQx2P/o0WgV5flOwR7EtkZP9q/Rwnyox7TY1BDAYxEUXweRHtYrHirwVga?= =?us-ascii?Q?8rvE4yzmI7gR7t/tyFGFkVAwOrVXp88IgUB59l449MzIMIiVDCsLLPXKx7xK?= =?us-ascii?Q?snZ2c82njohvkWgifQuOegV60DGC0YkeaARNw7Wh/WkU3vhboBG1fTpV77qt?= =?us-ascii?Q?QcOysgoUpHZl5bgIUm5rOplp5PwQ9v7fAqidrzoxzt2BrZcdiueRcZSmXxuv?= =?us-ascii?Q?qVNVB8x23Wfk6p7Kf61XAPyYZHeTz8KUuS4UYi2ldKTRKoQHbnJWABr7wqlm?= =?us-ascii?Q?Z9dwnRDuaMMGGAW4DJDOH3nVB34kkLOqUbhtBnpsK4jjdLEEF+g5AfZ7dMJo?= =?us-ascii?Q?4AGby6Gf/gmAfAmt0VUdzs1Cv8Mi6Q6vUtoDmiMKTJdstplWziB6fJr3vieA?= =?us-ascii?Q?O+qmFxLmZ4+7mKGdc/y5vARMKJOcnPGxNo3u6g1Q6Y/Q1Ho6d4SnxZgnWFn5?= =?us-ascii?Q?ZzLvGFTlDh56Oqc6/6EywOvlEsy2rd8rpMTWme/dLuEM5//iLKUHIp2hHOXv?= =?us-ascii?Q?l3qavyi1TamPt7xJf6aNTmP/63/Bv?= X-Microsoft-Exchange-Diagnostics: 1;BY1PR0301MB1302;5:9GnnKXdDbsoBWeZBy8aXGsvPBe/V71ySF1lii8n18iCBmHRMLeX83PY59oL3NTmLQlbGWk803y0EU23T+Ahp54as8pdMK1+KU3tbQ0zO/8XNxY77viN1sGQ6CsTIlETSTfXYYacJjyQUhL1WfPsfKA==;24:AYQ5wIV9FFmoQwNpOqRCHBUU84vnamqHMFOsPa+T1vGbjGb7phHxztRi85Ck+XHh9zk2Mdnh2cbaC7anWxC7NPB5d6gcPZeXR/zE18XRayk=;20:ktNZZXErbmRPp7SkMtmeeIMclO8k0yxiWA+yfhfyRVwtLWAOK/ZC0kYbCb6z0OG6v/drZZmklmwF1mCrGy54tA== X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Nov 2015 01:46:21.7103 (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: BY1PR0301MB1302 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 --- CHANGE HISTORY Changes in v3: none 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