From patchwork Fri Jan 8 23:22:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alex Deucher X-Patchwork-Id: 7991161 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id B4869BEEE5 for ; Fri, 8 Jan 2016 23:23:43 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8C0E4201C8 for ; Fri, 8 Jan 2016 23:23:42 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 16C42201C0 for ; Fri, 8 Jan 2016 23:23:41 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 766452660B4; Sat, 9 Jan 2016 00:23:39 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, NO_DNS_FOR_FROM, RCVD_IN_DNSWL_NONE, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id A0CEB265A7F; Sat, 9 Jan 2016 00:22:33 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 9CFCA265AB3; Sat, 9 Jan 2016 00:22:32 +0100 (CET) Received: from mail-qg0-f66.google.com (mail-qg0-f66.google.com [209.85.192.66]) by alsa0.perex.cz (Postfix) with ESMTP id E2B91260502 for ; Sat, 9 Jan 2016 00:22:21 +0100 (CET) Received: by mail-qg0-f66.google.com with SMTP id 94so43227934qgt.1 for ; Fri, 08 Jan 2016 15:22:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=s6AfHHcVq8MHEOBOmHAiRwNRWmG7BDtAkzMF5XZoh8s=; b=J4+JuN85r3Ysj3qVNAK4MNv91QeYidK/hMcAERORnVBe0JOoFaXFyMc2f23jmYMP9A dyKq1kpdHe26HlmgULgETC79+ib5w29/V43caJQUTMu2qvXo5yKaf4E8+Vy12yGfVNLY ojSQRH6P+AoeiWdPAL+X8mzY/i3/9azH6V5EKhOKUc5z902Znn5JscsKpZQPqKzdoiyl g7hZKLX8ehs1F2oq9jpRvPCy0ej/MWXBDtjQbDYLOV/lNcwjEpTJ/w8uM8jXIFchtpUI yKb2NLiRaHNoZeomc3Lu1s01HjDf8Av8I7uXRjqQYDD6Ia3Hiz2mzaFNzKQUL3RHEuaV XD+w== X-Received: by 10.140.42.139 with SMTP id c11mr85821585qga.5.1452295341238; Fri, 08 Jan 2016 15:22:21 -0800 (PST) Received: from cm.localdomain (static-74-96-105-49.washdc.fios.verizon.net. [74.96.105.49]) by smtp.gmail.com with ESMTPSA id f83sm43834730qkb.25.2016.01.08.15.22.20 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 08 Jan 2016 15:22:20 -0800 (PST) From: Alex Deucher X-Google-Original-From: Alex Deucher To: airlied@gmail.com, dri-devel@lists.freedesktop.org, broonie@kernel.org, alsa-devel@alsa-project.org, maruthi.bayyavarapu@amd.com, rajeevkumar.linux@gmail.com Date: Fri, 8 Jan 2016 18:22:04 -0500 Message-Id: <1452295331-28476-3-git-send-email-alexander.deucher@amd.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1452295331-28476-1-git-send-email-alexander.deucher@amd.com> References: <1452295331-28476-1-git-send-email-alexander.deucher@amd.com> MIME-Version: 1.0 Cc: tiwai@suse.de, Alex Deucher , lgirdwood@gmail.com Subject: [alsa-devel] [PATCH 2/9] drm/amdgpu: add irq domain support X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP Hardware blocks on the GPU like ACP generate interrupts in the GPU interrupt controller, but are driven by a separate driver. Add an irq domain to the GPU driver so that blocks like ACP can register a Linux interrupt. Acked-by: Dave Airlie Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 108 +++++++++++++++++++++++++++++--- drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h | 9 +++ drivers/gpu/drm/amd/amdgpu/cik_ih.c | 6 ++ drivers/gpu/drm/amd/amdgpu/cz_ih.c | 7 +++ drivers/gpu/drm/amd/amdgpu/iceland_ih.c | 7 +++ drivers/gpu/drm/amd/amdgpu/tonga_ih.c | 7 +++ 6 files changed, 136 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 7c42ff6..3006182 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -312,6 +312,7 @@ int amdgpu_irq_add_id(struct amdgpu_device *adev, unsigned src_id, } adev->irq.sources[src_id] = source; + return 0; } @@ -335,15 +336,19 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev, return; } - src = adev->irq.sources[src_id]; - if (!src) { - DRM_DEBUG("Unhandled interrupt src_id: %d\n", src_id); - return; - } + if (adev->irq.virq[src_id]) { + generic_handle_irq(irq_find_mapping(adev->irq.domain, src_id)); + } else { + src = adev->irq.sources[src_id]; + if (!src) { + DRM_DEBUG("Unhandled interrupt src_id: %d\n", src_id); + return; + } - r = src->funcs->process(adev, src, entry); - if (r) - DRM_ERROR("error processing interrupt (%d)\n", r); + r = src->funcs->process(adev, src, entry); + if (r) + DRM_ERROR("error processing interrupt (%d)\n", r); + } } /** @@ -461,3 +466,90 @@ bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src, return !!atomic_read(&src->enabled_types[type]); } + +/* gen irq */ +static void amdgpu_irq_mask(struct irq_data *irqd) +{ + /* XXX */ +} + +static void amdgpu_irq_unmask(struct irq_data *irqd) +{ + /* XXX */ +} + +static struct irq_chip amdgpu_irq_chip = { + .name = "amdgpu-ih", + .irq_mask = amdgpu_irq_mask, + .irq_unmask = amdgpu_irq_unmask, +}; + +static int amdgpu_irqdomain_map(struct irq_domain *d, + unsigned int irq, irq_hw_number_t hwirq) +{ + if (hwirq >= AMDGPU_MAX_IRQ_SRC_ID) + return -EPERM; + + irq_set_chip_and_handler(irq, + &amdgpu_irq_chip, handle_simple_irq); + return 0; +} + +static struct irq_domain_ops amdgpu_hw_irqdomain_ops = { + .map = amdgpu_irqdomain_map, +}; + +/** + * amdgpu_irq_add_domain - create a linear irq domain + * + * @adev: amdgpu device pointer + * + * Create an irq domain for GPU interrupt sources + * that may be driven by another driver (e.g., ACP). + */ +int amdgpu_irq_add_domain(struct amdgpu_device *adev) +{ + adev->irq.domain = irq_domain_add_linear(NULL, AMDGPU_MAX_IRQ_SRC_ID, + &amdgpu_hw_irqdomain_ops, adev); + if (!adev->irq.domain) { + DRM_ERROR("GPU irq add domain failed\n"); + return -ENODEV; + } + + return 0; +} + +/** + * amdgpu_irq_remove_domain - remove the irq domain + * + * @adev: amdgpu device pointer + * + * Remove the irq domain for GPU interrupt sources + * that may be driven by another driver (e.g., ACP). + */ +void amdgpu_irq_remove_domain(struct amdgpu_device *adev) +{ + if (adev->irq.domain) { + irq_domain_remove(adev->irq.domain); + adev->irq.domain = NULL; + } +} + +/** + * amdgpu_irq_create_mapping - create a mapping between a domain irq and a + * Linux irq + * + * @adev: amdgpu device pointer + * @src_id: IH source id + * + * Create a mapping between a domain irq (GPU IH src id) and a Linux irq + * Use this for components that generate a GPU interrupt, but are driven + * by a different driver (e.g., ACP). + * Returns the Linux irq. + */ +unsigned amdgpu_irq_create_mapping(struct amdgpu_device *adev, unsigned src_id) +{ + adev->irq.virq[src_id] = irq_create_mapping(adev->irq.domain, src_id); + + return adev->irq.virq[src_id]; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h index 17b01aef..e124b59 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h @@ -24,6 +24,7 @@ #ifndef __AMDGPU_IRQ_H__ #define __AMDGPU_IRQ_H__ +#include #include "amdgpu_ih.h" #define AMDGPU_MAX_IRQ_SRC_ID 0x100 @@ -65,6 +66,10 @@ struct amdgpu_irq { /* interrupt ring */ struct amdgpu_ih_ring ih; const struct amdgpu_ih_funcs *ih_funcs; + + /* gen irq stuff */ + struct irq_domain *domain; /* GPU irq controller domain */ + unsigned virq[AMDGPU_MAX_IRQ_SRC_ID]; }; void amdgpu_irq_preinstall(struct drm_device *dev); @@ -90,4 +95,8 @@ int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src, bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type); +int amdgpu_irq_add_domain(struct amdgpu_device *adev); +void amdgpu_irq_remove_domain(struct amdgpu_device *adev); +unsigned amdgpu_irq_create_mapping(struct amdgpu_device *adev, unsigned src_id); + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/cik_ih.c b/drivers/gpu/drm/amd/amdgpu/cik_ih.c index 8993c50..30c9b3be 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_ih.c @@ -274,6 +274,11 @@ static void cik_ih_set_rptr(struct amdgpu_device *adev) static int cik_ih_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int ret; + + ret = amdgpu_irq_add_domain(adev); + if (ret) + return ret; cik_ih_set_interrupt_funcs(adev); @@ -300,6 +305,7 @@ static int cik_ih_sw_fini(void *handle) amdgpu_irq_fini(adev); amdgpu_ih_ring_fini(adev); + amdgpu_irq_remove_domain(adev); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ih.c b/drivers/gpu/drm/amd/amdgpu/cz_ih.c index bc751bf..c79638f 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_ih.c @@ -253,8 +253,14 @@ static void cz_ih_set_rptr(struct amdgpu_device *adev) static int cz_ih_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int ret; + + ret = amdgpu_irq_add_domain(adev); + if (ret) + return ret; cz_ih_set_interrupt_funcs(adev); + return 0; } @@ -278,6 +284,7 @@ static int cz_ih_sw_fini(void *handle) amdgpu_irq_fini(adev); amdgpu_ih_ring_fini(adev); + amdgpu_irq_remove_domain(adev); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c index 779532d..679e739 100644 --- a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c @@ -253,8 +253,14 @@ static void iceland_ih_set_rptr(struct amdgpu_device *adev) static int iceland_ih_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int ret; + + ret = amdgpu_irq_add_domain(adev); + if (ret) + return ret; iceland_ih_set_interrupt_funcs(adev); + return 0; } @@ -278,6 +284,7 @@ static int iceland_ih_sw_fini(void *handle) amdgpu_irq_fini(adev); amdgpu_ih_ring_fini(adev); + amdgpu_irq_remove_domain(adev); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c index 743c372..b6f7d7b 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c @@ -273,8 +273,14 @@ static void tonga_ih_set_rptr(struct amdgpu_device *adev) static int tonga_ih_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int ret; + + ret = amdgpu_irq_add_domain(adev); + if (ret) + return ret; tonga_ih_set_interrupt_funcs(adev); + return 0; } @@ -301,6 +307,7 @@ static int tonga_ih_sw_fini(void *handle) amdgpu_irq_fini(adev); amdgpu_ih_ring_fini(adev); + amdgpu_irq_add_domain(adev); return 0; }