From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752212AbbJZQF4 (ORCPT ); Mon, 26 Oct 2015 12:05:56 -0400 Received: from mail-bn1bn0103.outbound.protection.outlook.com ([157.56.110.103]:44400 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751761AbbJZQEv (ORCPT ); Mon, 26 Oct 2015 12:04:51 -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 09/10] staging: fsl-mc: Added DPRC interrupt handler Date: Mon, 26 Oct 2015 10:49:20 -0500 Message-ID: <1445874561-14761-10-git-send-email-German.Rivera@freescale.com> X-Mailer: git-send-email 2.3.3 In-Reply-To: <1445874561-14761-1-git-send-email-German.Rivera@freescale.com> References: <1445874561-14761-1-git-send-email-German.Rivera@freescale.com> X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BN1BFFO11FD051;1:R9HiVwK4ZIsVznMnGV44W1zGQ4lbDYzBOCpvHGeD7J8OQJz9sL3DeqqRIYTzpa6ObTXqTkIQ9nW3lwirZUnX9za6d3kOXjCMNK1rO7Li5E0yGzct0iKfXBENiOJvrv3rYoTh+8ap+k2iukIxzfaQXU5SXr37KLRw0mk42jpOBMB82nzyRuk6wEyhCy89QHHCTnaqxzhsTWFo/k+IoAf0XPmWgrUPkPek62/EsPjXUCTxEO0Jup7BVEzI2NgtfuTVbuN4nPfNRV9mqGKc5FHfgEG1zFrYKCnFykJuBLA+DDwsmXL6x8HY4nXXfNVuSr4sj+fDdi9f8xGamVqExFVxPCwXM5qK7n/u9UwiOC92aZ+j5GThqG1FwNpuZ9acv4ZPKK0e8J+0NexSW3Zju0yyWw== 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)(48376002)(50466002)(92566002)(50226001)(47776003)(2950100001)(6806005)(104016004)(77096005)(11100500001)(189998001)(5007970100001)(229853001)(107886002)(5008740100001)(5003940100001)(5001960100002)(5001770100001)(87936001)(97736004)(86362001)(81156007)(5001920100001)(19580395003)(19580405001)(105606002)(85426001)(76176999)(106466001)(575784001)(50986999)(2201001)(36756003)(4001430100002);DIR:OUT;SFP:1102;SCL:1;SRVR:BL2PR03MB497;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;BL2PR03MB497;2:FpEDnFUhv7dM8Pexnaxv0nGbru+g55fTY35LB2aA4Cl83Wuf7D/ewBWk5RaaM3Y3FGbjhQ5ykE6VieEpVW3wrGSBXEXz18qPb3OFrzvf0n9R+VPYHSrhMTtWZDvRwgkySNEv40IK5feMbYNzxZaMKI8jGOoCxRxpD3W1YxvAKzo=;3:xc4n3hNOfw3LtThCzkMYv1Q1c9bJndQvANXCOw2P7fxX4mx1Mtu9EaEMUl9m+aw6xIbOocUpmynv/dviB2yJYy4Mdfn85NB9NjraHuvnWUdeK85fF/H4oIAW+9ptnS2MvB8/14KneqZPyeR8EaPbMQMtC6QQydsCTb5diUBihct3MkTtTpCwH5SQviKbfOzndrGoRhX3W8hZXXsj/T1i4G540qC0Sr6yw+IRa6JhKWk=;25:IOomXhNx77NSptO8fmYIOi6TKqCqWcl7EKb7lt3MF8Bhl4miML3HISLcKKHxw6HI2+RYQBxpwjSnxM1ud0Q68S1lfLrbWNd7aE2xraAF+YBT7lSbzgcw7EZMeSCDfYxgRcN9yWviflYpnKOmJjB0F9VjK6dl6Qncuz4vLC7YfzaFdqbn93+hR7vaDDFZQ3Iq6taUgK5hEs8VLgqiKu7pYt6EvPEhnkmiNbUO35jY8sNFEIG8nPv+Kzn0upWcoV0wT6+/kYDrUUz0lGBSBOQKZg== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BL2PR03MB497; X-Microsoft-Exchange-Diagnostics: 1;BL2PR03MB497;20:TrOW5KsBxf9IyV3s2PXfRQ/Au2c3EK5HuJkGpZ3TvDvl/buVn4+oQdoR7HQ6nErjK/6jj0uDdTjV5xsYV7V8jBqQFPqdpoFrgO6+8GBGh6p56VJPmSL4NPyUg22E77+b1Oo4gEoNHXowaEXyKkHceC9N7ItOo06GMaExpt+XxutNd5mVCGWi3IgOHmJG/xD2YQhy5zhihOq8YMuWEWw3uX8UZLy9KGU671eHNIe9jOYf06/GOIB98TSgkCOZJo/+a3iJhkkQdpPug5ejEr2lPf88F850nFsjwxtWV0pJJ6OldEb59rRTtxeW8ZtvZqbJ1Wy7a/kWmHmBqzihcp0hlKCBrwzbX14PhiSfT8qzyDA=;4:38AJ92dWgyHiZrivb/Y55OhG5pyja8RbdVU1irE/e8QBYZW6y1O+jnTgYdojosbf6UD6omZbIXA9lG9/wZz20yfTV/41B/An9FgOb7SKmlo1SkB3+p3umg0qHtOLHqlvwbOtxYCWjlN9OpAhgzhcfxKOSIKztPafR26u69xEkbHDNGj4ceh3EQn2a+DoM4ZI/m6zueqLczoPQ0JcQkbJxC3lm/sdluiv6Y+spt7b5ST6PwEZD1ulMeo3+xmCF9NjQXs06xoTw9ZH6BGDIbR5yvzwHELyCajhkTOu/B30j+6hAg4ldtoC4yQwYxBJGgsc6dPo4F1nUjFqrP+sPCV7Gw4q0Awbpa4osrBxjIG9ohhRSHV36pjR0hZTSWhFIXg/ 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)(3002001)(102215026);SRVR:BL2PR03MB497;BCL:0;PCL:0;RULEID:;SRVR:BL2PR03MB497; X-Forefront-PRVS: 0741C77572 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BL2PR03MB497;23:2/btE0++1BTU19mGtxZh0k84V645K9VMJ/Km/ln29x?= =?us-ascii?Q?P0yPXN/yeRwkH/ugjyDxQseFXYm63ofOXlM44daIfMJvZEpzYpUiu95vHUJe?= =?us-ascii?Q?ndDrX30j3YMFsWiof+w89jA5pRo+Szqkg1ScMhve0yhgQrhYEWmlN1eW80VF?= =?us-ascii?Q?nc2eJYhDCnKc9kxSVGFT4bnLK8k2dV/SvsmJhDRl0vdJHzNMbRDjFNRVoZzc?= =?us-ascii?Q?N1+SbKPJn4HzkAlyeG4jWLX2NvtVPcWmR9O0ya8537Lhnyhqq7PsG5o1Uhah?= =?us-ascii?Q?NBG03jCfhjjZyyB3si+dLah/AZMlx31BUdtkxmJ5HZIkj/MePa+zx4Be2Z6X?= =?us-ascii?Q?RknKMsI1hy4ZwrWNu6uJpFkP8FoCqCA9BFAb7zfxl77k2kTxVZIa7obUQeMC?= =?us-ascii?Q?aF5r9Z12EkeJjh4hZWPtKgySl3zsQ7wKvXie72bEbTX7sA1cNOt3X5sg8BYq?= =?us-ascii?Q?kCAwybnRHXrfwM2LZwS9D1h8amm6jM6UJv6x2kzUvRqr6Ak6MBQSFOXq60ZT?= =?us-ascii?Q?07Wl1mnRcib5y9oXprDlOOoZJWpLLUwwcnHbRZ8ZV50VeByJ58ZWnOn/+qnT?= =?us-ascii?Q?pY75QHRRnNh0I7CSYA2cgQSmyOhIKziKR7sXMhDz7Sm6VU1SFTk7legF9Rd2?= =?us-ascii?Q?Q+llbCpZZhjzW9GVx8nJZ+p502sPfqm8VdSsrkMHgfYnVUj4UX+TBAniENEd?= =?us-ascii?Q?wM/3/ijpqdHc72ibAz6utnGGhwPQryOhnNx+7Qv6ictvLtDKZeTrnQxA/Xx3?= =?us-ascii?Q?o8MPy2vJeT9RS8NYWZsI7ns1VYN9Chdo8bmySJPNXbe7WDG2QiMj5kI6XD0a?= =?us-ascii?Q?0bqoRel01lznOE5Ou+X6jkW84c/eQr8QOC/DAIBhEFtXyvDsh809FAYduB2a?= =?us-ascii?Q?Y+z3hX19T+R5kaA/kiAX+r5T1xnVkH3RXX//TjzYnTC4wgte2kSfvvvMnE1D?= =?us-ascii?Q?/WrglBufgnOsQcHgGfKE4dWL5eGtf0oQi0/ashAHgImxMCyqCmbRQLdixrOz?= =?us-ascii?Q?Xb0C9mSKiB+zsFVkxY5Sql1ERCKj5Vk7jSChc2oQQKe5Iz2Cng1l3Y/nfvxF?= =?us-ascii?Q?2UTBIsachRJIvaBRHJsS91ZP95velZR+DG905HKfjRXn0G5uJWgo5MmyUUTs?= =?us-ascii?Q?W6w5+TZMCiNoXAimhnnclwEheHdLHG?= X-Microsoft-Exchange-Diagnostics: 1;BL2PR03MB497;5:f4P/QFk4qYaPVMpV4RkoMi79Qc2Sm9TNKdnh8NuHRwDgI8pGaPHWokrleME0EH8ftjceXOEAL1BhLXsswfii5L5zoHWtbpVvd9pdIBvdNbiEps9ZcilqXCQM1eV/S+C1GeLHqpSS3dfKDL29biGZnA==;24:o+ptsKVP//k6wRRlGgyK83HPMC7Z9k3wFhrKvSm/CdPgrE91KZN4Fjc+JnzLrORae/cH0wInpqUaaguqZwcBdTXXDaUN1e8My8kAyk2/K9w=;20:rLXdKBpZp2fJ5HWG0Vex9Y4GEj8YWr034MvJ66Slkm5cAs9KEpicmDDM+aavPrei3P1z3ySNWiigb4myqPfZFQ== X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Oct 2015 16:04:48.3315 (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: BL2PR03MB497 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 --- 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 3eeafaa..38ec2b2 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,10 +701,17 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) if (error < 0) goto dprc_scan_container_error; + /* + * Configure interrupt for the DPRC object associated with this MC bus: + */ + error = dprc_setup_irq(mc_dev); + if (error < 0) + goto dprc_setup_irqs_error; dev_info(&mc_dev->dev, "DPRC device bound to driver"); return 0; +dprc_setup_irqs_error: dprc_scan_container_error: (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); dprc_open_error: @@ -494,6 +726,15 @@ dprc_open_error: 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