From patchwork Mon Jul 6 05:47:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gavin Shan X-Patchwork-Id: 11644889 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D3D4860D for ; Mon, 6 Jul 2020 05:50:53 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9F8AD2074F for ; Mon, 6 Jul 2020 05:50:53 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="AXtGHwU/"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="aGmeDeOQ" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9F8AD2074F Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=SmLH9tYU6KgBOud7kfAzkzfVd7MLsMeEjFRDoO2NlK0=; b=AXtGHwU/x60mhPJD7OFNEbrKL AhU/9etsqDSHVot/krse2K6X1XR2V32fDkYefd76SBcyNMnkIDcY60Vq6j0Z45JMKu6tyN6UC5QVs IAhydtJwm/YI6avSWxVqKAY7pcp2RIAXMoEgozR1Np9vcK/qUL6mkwGNIyPddLCsMm8rox0uvb3G6 11qznUbGAq2w1vTE5HuDJHqwy3P0tpvqR4aGzHkslKXcQr2CYsUJBquFj6UlI5Ndva24VOfIKEpOH AO4KwY+0NE7GszBQLEk/x0iqelhmhDODxm09vxQ6RUex+FGTp74CNuIBS7yOWy1HcXOUCGsQIgb4i uOZYmzPQg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jsK02-0003z7-TH; Mon, 06 Jul 2020 05:49:06 +0000 Received: from us-smtp-1.mimecast.com ([207.211.31.81] helo=us-smtp-delivery-1.mimecast.com) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jsJzO-0003fI-Cf for linux-arm-kernel@lists.infradead.org; Mon, 06 Jul 2020 05:48:31 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1594014505; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bQduMedDUMkgcn7HYQv7Wm36k5Mvj7BS+DErp3vKYbI=; b=aGmeDeOQvZ75iGnm+whNq3B5IyK9P9XuueUHTDPG2cZAo10Ck45oD56FnMDgKvK91WQdgc 25N0hpX90wyOtUuUcPVThnx3AxRbZg/8D3/OOccxD2Vp5QcKD+6AcySiuJ5gRFGW2oB7la z3ZmeDPsX8utSPtbNj+A4+63Wiphje0= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-349-55R1ug2cOhGySx-qe-DrZg-1; Mon, 06 Jul 2020 01:48:23 -0400 X-MC-Unique: 55R1ug2cOhGySx-qe-DrZg-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1716119067E0; Mon, 6 Jul 2020 05:48:22 +0000 (UTC) Received: from localhost.localdomain.com (vpn2-54-159.bne.redhat.com [10.64.54.159]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7CD4FC0DBA; Mon, 6 Jul 2020 05:48:19 +0000 (UTC) From: Gavin Shan To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 12/14] drivers/firmware/sdei: Identify event by struct sdei_event Date: Mon, 6 Jul 2020 15:47:30 +1000 Message-Id: <20200706054732.99387-13-gshan@redhat.com> In-Reply-To: <20200706054732.99387-1-gshan@redhat.com> References: <20200706054732.99387-1-gshan@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=gshan@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200706_014826_613408_6DFAEA6A X-CRM114-Status: GOOD ( 23.40 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [207.211.31.81 listed in list.dnswl.org] 0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [207.211.31.81 listed in wl.mailspike.net] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders -0.0 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, will@kernel.org, james.morse@arm.com, shan.gavin@gmail.com, catalin.marinas@arm.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org There are 4 APIs exported by the driver as below. They are using the event number as the identifier to the event. It's conflicting with the requirement to dereference the event by struct sdei_event instance when SDEI virtualization is supported. So this reworks on the APIs according to dereference the event by struct sdei_event instance: * sdei_event_register() returns the struct sdei_event instance. * sdei_event_unregister() and sdei_event_{enable, disable}() accepts struct sdei_event instance as the parameter. * Rework sdei_{register,unregister}_ghes() to use the modified APIs. Signed-off-by: Gavin Shan --- drivers/firmware/arm_sdei.c | 145 +++++++++++++++++------------------- include/linux/arm_sdei.h | 71 ++++++++++-------- 2 files changed, 108 insertions(+), 108 deletions(-) diff --git a/drivers/firmware/arm_sdei.c b/drivers/firmware/arm_sdei.c index 8f53bef88379..8e5f6683c155 100644 --- a/drivers/firmware/arm_sdei.c +++ b/drivers/firmware/arm_sdei.c @@ -44,26 +44,6 @@ static asmlinkage void (*sdei_firmware_call)(unsigned long function_id, /* entry point from firmware to arch asm code */ static unsigned long sdei_entry_point; -struct sdei_event { - /* These three are protected by the sdei_list_lock */ - struct list_head list; - bool reregister; - bool reenable; - - u32 event_num; - u8 type; - u8 priority; - - /* This pointer is handed to firmware as the event argument. */ - union { - /* Shared events */ - struct sdei_registered_event *registered; - - /* CPU private events */ - struct sdei_registered_event __percpu *private_registered; - }; -}; - /* Take the mutex for any API call or modification. Take the mutex first. */ static DEFINE_MUTEX(sdei_events_lock); @@ -393,30 +373,26 @@ static void _local_event_enable(void *data) sdei_cross_call_return(arg, err); } -int sdei_event_enable(u32 event_num) +int sdei_event_enable(struct sdei_event *event) { int err = -EINVAL; - struct sdei_event *event; mutex_lock(&sdei_events_lock); - event = sdei_event_find(event_num); - if (!event) { - mutex_unlock(&sdei_events_lock); - return -ENOENT; - } - - cpus_read_lock(); + if (event->type == SDEI_EVENT_TYPE_SHARED) err = sdei_api_event_enable(event->event_num); else err = sdei_do_cross_call(_local_event_enable, event); - if (!err) { - spin_lock(&sdei_list_lock); - event->reenable = true; - spin_unlock(&sdei_list_lock); - } + if (err) + goto cpu_unlock; + + spin_lock(&sdei_list_lock); + event->reenable = true; + spin_unlock(&sdei_list_lock); + +cpu_unlock: cpus_read_unlock(); mutex_unlock(&sdei_events_lock); @@ -439,28 +415,26 @@ static void _ipi_event_disable(void *data) sdei_cross_call_return(arg, err); } -int sdei_event_disable(u32 event_num) +int sdei_event_disable(struct sdei_event *event) { int err = -EINVAL; - struct sdei_event *event; mutex_lock(&sdei_events_lock); - event = sdei_event_find(event_num); - if (!event) { - mutex_unlock(&sdei_events_lock); - return -ENOENT; - } - - spin_lock(&sdei_list_lock); - event->reenable = false; - spin_unlock(&sdei_list_lock); if (event->type == SDEI_EVENT_TYPE_SHARED) err = sdei_api_event_disable(event->event_num); else err = sdei_do_cross_call(_ipi_event_disable, event); - mutex_unlock(&sdei_events_lock); + if (err) + goto out; + + spin_lock(&sdei_list_lock); + event->reenable = false; + spin_unlock(&sdei_list_lock); + +out: + mutex_unlock(&sdei_events_lock); return err; } @@ -483,25 +457,13 @@ static void _local_event_unregister(void *data) sdei_cross_call_return(arg, err); } -int sdei_event_unregister(u32 event_num) +int sdei_event_unregister(struct sdei_event *event) { int err; - struct sdei_event *event; WARN_ON(in_nmi()); mutex_lock(&sdei_events_lock); - event = sdei_event_find(event_num); - if (!event) { - pr_warn("Event %u not registered\n", event_num); - err = -ENOENT; - goto out; - } - - spin_lock(&sdei_list_lock); - event->reregister = false; - event->reenable = false; - spin_unlock(&sdei_list_lock); if (event->type == SDEI_EVENT_TYPE_SHARED) err = sdei_api_event_unregister(event->event_num); @@ -511,6 +473,11 @@ int sdei_event_unregister(u32 event_num) if (err) goto out; + spin_lock(&sdei_list_lock); + event->reregister = false; + event->reenable = false; + spin_unlock(&sdei_list_lock); + sdei_event_destroy(event); out: @@ -567,17 +534,18 @@ static void _local_event_register(void *data) sdei_cross_call_return(arg, err); } -int sdei_event_register(u32 event_num, sdei_event_callback *cb, void *arg) +struct sdei_event *sdei_event_register(u32 event_num, + sdei_event_callback *cb, void *arg) { + struct sdei_event *event = NULL; int err; - struct sdei_event *event; WARN_ON(in_nmi()); mutex_lock(&sdei_events_lock); if (sdei_event_find(event_num)) { pr_warn("Event %u already registered\n", event_num); - err = -EBUSY; + event = ERR_PTR(-EBUSY); goto out; } @@ -603,6 +571,7 @@ int sdei_event_register(u32 event_num, sdei_event_callback *cb, void *arg) if (err) { sdei_event_destroy(event); + event = ERR_PTR(err); pr_warn("Failed to register event %u: %d\n", event_num, err); goto cpu_unlock; @@ -616,7 +585,7 @@ int sdei_event_register(u32 event_num, sdei_event_callback *cb, void *arg) cpus_read_unlock(); out: mutex_unlock(&sdei_events_lock); - return err; + return event; } static int sdei_reregister_shared(void) @@ -857,13 +826,16 @@ NOKPROBE_SYMBOL(sdei_smccc_hvc); int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb, sdei_event_callback *critical_cb) { - int err; + struct sdei_event *event; u64 result; u32 event_num; sdei_event_callback *cb; + int err; - if (!IS_ENABLED(CONFIG_ACPI_APEI_GHES)) - return -EOPNOTSUPP; + if (!IS_ENABLED(CONFIG_ACPI_APEI_GHES)) { + err = -EOPNOTSUPP; + goto out; + } event_num = ghes->generic->notify.vector; if (event_num == 0) { @@ -871,53 +843,70 @@ int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb, * Event 0 is reserved by the specification for * SDEI_EVENT_SIGNAL. */ - return -EINVAL; + err = -EINVAL; + goto out; } err = sdei_api_event_get_info(event_num, SDEI_EVENT_INFO_EV_PRIORITY, &result); if (err) - return err; + goto out; if (result == SDEI_EVENT_PRIORITY_CRITICAL) cb = critical_cb; else cb = normal_cb; - err = sdei_event_register(event_num, cb, ghes); - if (!err) - err = sdei_event_enable(event_num); + event = sdei_event_register(event_num, cb, ghes); + if (IS_ERR(event)) { + err = PTR_ERR(event); + goto out; + } + err = sdei_event_enable(event); + +out: return err; } int sdei_unregister_ghes(struct ghes *ghes) { - int i; - int err; + struct sdei_event *event; u32 event_num = ghes->generic->notify.vector; + int err, i; might_sleep(); - if (!IS_ENABLED(CONFIG_ACPI_APEI_GHES)) - return -EOPNOTSUPP; + if (!IS_ENABLED(CONFIG_ACPI_APEI_GHES)) { + err = -EOPNOTSUPP; + goto out; + } + + mutex_lock(&sdei_events_lock); + event = sdei_event_find(event_num); + mutex_unlock(&sdei_events_lock); + if (!event) { + err = -ENOENT; + goto out; + } /* * The event may be running on another CPU. Disable it * to stop new events, then try to unregister a few times. */ - err = sdei_event_disable(event_num); + err = sdei_event_disable(event); if (err) - return err; + goto out; for (i = 0; i < 3; i++) { - err = sdei_event_unregister(event_num); + err = sdei_event_unregister(event); if (err != -EINPROGRESS) break; schedule(); } +out: return err; } diff --git a/include/linux/arm_sdei.h b/include/linux/arm_sdei.h index 0a241c5c911d..fb6aa455e51d 100644 --- a/include/linux/arm_sdei.h +++ b/include/linux/arm_sdei.h @@ -22,36 +22,6 @@ */ typedef int (sdei_event_callback)(u32 event, struct pt_regs *regs, void *arg); -/* - * Register your callback to claim an event. The event must be described - * by firmware. - */ -int sdei_event_register(u32 event_num, sdei_event_callback *cb, void *arg); - -/* - * Calls to sdei_event_unregister() may return EINPROGRESS. Keep calling - * it until it succeeds. - */ -int sdei_event_unregister(u32 event_num); - -int sdei_event_enable(u32 event_num); -int sdei_event_disable(u32 event_num); - -/* GHES register/unregister helpers */ -int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb, - sdei_event_callback *critical_cb); -int sdei_unregister_ghes(struct ghes *ghes); - -#ifdef CONFIG_ARM_SDE_INTERFACE -/* For use by arch code when CPU hotplug notifiers are not appropriate. */ -int sdei_mask_local_cpu(void); -int sdei_unmask_local_cpu(void); -#else -static inline int sdei_mask_local_cpu(void) { return 0; } -static inline int sdei_unmask_local_cpu(void) { return 0; } -#endif /* CONFIG_ARM_SDE_INTERFACE */ - - /* * This struct represents an event that has been registered. The driver * maintains a list of all events, and which ones are registered. (Private @@ -72,6 +42,47 @@ struct sdei_registered_event { u8 priority; }; +struct sdei_event { + /* These three are protected by the sdei_list_lock */ + struct list_head list; + bool reregister; + bool reenable; + + u32 event_num; + u8 type; + u8 priority; + + /* This pointer is handed to firmware as the event argument. */ + union { + /* Shared events */ + struct sdei_registered_event *registered; + + /* CPU private events */ + struct sdei_registered_event __percpu *private_registered; + }; +}; + +/* APIs */ +struct sdei_event *sdei_event_register(u32 event_num, + sdei_event_callback *cb, void *arg); +int sdei_event_unregister(struct sdei_event *event); +int sdei_event_enable(struct sdei_event *event); +int sdei_event_disable(struct sdei_event *event); + +/* GHES register/unregister helpers */ +int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb, + sdei_event_callback *critical_cb); +int sdei_unregister_ghes(struct ghes *ghes); + +#ifdef CONFIG_ARM_SDE_INTERFACE +/* For use by arch code when CPU hotplug notifiers are not appropriate. */ +int sdei_mask_local_cpu(void); +int sdei_unmask_local_cpu(void); +#else +static inline int sdei_mask_local_cpu(void) { return 0; } +static inline int sdei_unmask_local_cpu(void) { return 0; } +#endif /* CONFIG_ARM_SDE_INTERFACE */ + /* The arch code entry point should then call this when an event arrives. */ int notrace sdei_event_handler(struct pt_regs *regs, struct sdei_registered_event *arg);