From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.1 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C29D3C2BB85 for ; Fri, 10 Apr 2020 03:57:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9946E2063A for ; Fri, 10 Apr 2020 03:57:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1586491044; bh=uq4hJNtqFZPJMrmWI/E4aG4wnFS/dFvqaSP8vydg5S0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=kAa7fT1CekwAef/PLp6UD1Ys3G+NVQ5Y1beFARbqW18mgXBsrjDbttmIgdZA9QqWu W24xvR7FaYekp3akliQQNBmjjqLjHrUt9Imy6aNtOoq0L10j1G82vhV4TZwZ/x6ORa oys6VNgiBJvhhjdUXMyDZ3X3BZXvenRgV0VN1m0A= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728918AbgDJD5X (ORCPT ); Thu, 9 Apr 2020 23:57:23 -0400 Received: from mail.kernel.org ([198.145.29.99]:33082 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726670AbgDJDtP (ORCPT ); Thu, 9 Apr 2020 23:49:15 -0400 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 9ADF8214DB; Fri, 10 Apr 2020 03:49:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1586490555; bh=uq4hJNtqFZPJMrmWI/E4aG4wnFS/dFvqaSP8vydg5S0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ayq10PwTTa3BHpR1+TGt2gKx+OVxbBbc66qBToEHXuqQg5cS52IHkWJWIPa9c6itn HKLlmkVR4GIX3lGurdxaGyfO4WlQLfM1MkVCfNFqDT79aILFpofsVVO/z5MJjIGFmx 2epRvwhpGE/UaPIywuYIWcUYl53g8zWtle5FR2Zk= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: James Morse , Liguang Zhang , Catalin Marinas , Sasha Levin , linux-arm-kernel@lists.infradead.org Subject: [PATCH AUTOSEL 5.4 04/46] firmware: arm_sdei: fix double-lock on hibernate with shared events Date: Thu, 9 Apr 2020 23:48:27 -0400 Message-Id: <20200410034909.8922-4-sashal@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200410034909.8922-1-sashal@kernel.org> References: <20200410034909.8922-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: James Morse [ Upstream commit 6ded0b61cf638bf9f8efe60ab8ba23db60ea9763 ] SDEI has private events that must be registered on each CPU. When CPUs come and go they must re-register and re-enable their private events. Each event has flags to indicate whether this should happen to protect against an event being registered on a CPU coming online, while all the others are unregistering the event. These flags are protected by the sdei_list_lock spinlock, because the cpuhp callbacks can't take the mutex. Hibernate needs to unregister all events, but keep the in-memory re-register and re-enable as they are. sdei_unregister_shared() takes the spinlock to walk the list, then calls _sdei_event_unregister() on each shared event. _sdei_event_unregister() tries to take the same spinlock to update re-register and re-enable. This doesn't go so well. Push the re-register and re-enable updates out to their callers. sdei_unregister_shared() doesn't want these values updated, so doesn't need to do anything. This also fixes shared events getting lost over hibernate as this path made them look unregistered. Fixes: da351827240e ("firmware: arm_sdei: Add support for CPU and system power states") Reported-by: Liguang Zhang Signed-off-by: James Morse Signed-off-by: Catalin Marinas Signed-off-by: Sasha Levin --- drivers/firmware/arm_sdei.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/drivers/firmware/arm_sdei.c b/drivers/firmware/arm_sdei.c index 9cd70d1a56221..eb2df89d4924f 100644 --- a/drivers/firmware/arm_sdei.c +++ b/drivers/firmware/arm_sdei.c @@ -491,11 +491,6 @@ static int _sdei_event_unregister(struct sdei_event *event) { lockdep_assert_held(&sdei_events_lock); - spin_lock(&sdei_list_lock); - event->reregister = false; - event->reenable = false; - spin_unlock(&sdei_list_lock); - if (event->type == SDEI_EVENT_TYPE_SHARED) return sdei_api_event_unregister(event->event_num); @@ -518,6 +513,11 @@ int sdei_event_unregister(u32 event_num) break; } + spin_lock(&sdei_list_lock); + event->reregister = false; + event->reenable = false; + spin_unlock(&sdei_list_lock); + err = _sdei_event_unregister(event); if (err) break; @@ -585,26 +585,15 @@ static int _sdei_event_register(struct sdei_event *event) lockdep_assert_held(&sdei_events_lock); - spin_lock(&sdei_list_lock); - event->reregister = true; - spin_unlock(&sdei_list_lock); - if (event->type == SDEI_EVENT_TYPE_SHARED) return sdei_api_event_register(event->event_num, sdei_entry_point, event->registered, SDEI_EVENT_REGISTER_RM_ANY, 0); - err = sdei_do_cross_call(_local_event_register, event); - if (err) { - spin_lock(&sdei_list_lock); - event->reregister = false; - event->reenable = false; - spin_unlock(&sdei_list_lock); - + if (err) sdei_do_cross_call(_local_event_unregister, event); - } return err; } @@ -632,8 +621,17 @@ int sdei_event_register(u32 event_num, sdei_event_callback *cb, void *arg) break; } + spin_lock(&sdei_list_lock); + event->reregister = true; + spin_unlock(&sdei_list_lock); + err = _sdei_event_register(event); if (err) { + spin_lock(&sdei_list_lock); + event->reregister = false; + event->reenable = false; + spin_unlock(&sdei_list_lock); + sdei_event_destroy(event); pr_warn("Failed to register event %u: %d\n", event_num, err); -- 2.20.1