Received: by 2002:a05:6358:bb9e:b0:b9:5105:a5b4 with SMTP id df30csp3056946rwb; Mon, 5 Sep 2022 05:59:36 -0700 (PDT) X-Google-Smtp-Source: AA6agR4B2UOgW0ck0ORdUufHPp/+tbysQLuGOcV/bmfxATR91rBApI8fT6clpgazPZ9ZpyMj8tFO X-Received: by 2002:a17:902:e744:b0:176:a57f:4566 with SMTP id p4-20020a170902e74400b00176a57f4566mr6056300plf.96.1662382776721; Mon, 05 Sep 2022 05:59:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1662382776; cv=none; d=google.com; s=arc-20160816; b=SwO5L18r1IGQPWWjFGqEnPVBm0fNsjYQI/WtgIJZ1JBKk6Cw/GBVcZd9dUasPvm9r+ upBptulwv6aXaa1SXmsD2D/7HjJ7NaQI7P9gg3rGJ+Kts9xbdJ8pffUqdJ/zH18kYh5i CLBOmIpSF+cj4JsFYI1z8+fAbsTYQ2SMNOaGa3UnFvVYqXM1DyeArBowDbXpiY64lAMw vLr7WWOftTQA9M3DgOzoyXmtz/Mn1SbeFjff+dzU33BUxGSyGvzLLxesPCuTpfHwiAAe tdpmj71cRy5OW29YvPSMViDW7c3leLMFmsDcXXZK7yHTDNl+g02VAeyDJCZ6vKm10Ksr rYag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:user-agent:references:in-reply-to :subject:cc:to:from:message-id:date:dkim-signature:dkim-signature; bh=yd11dLSAJEXEEwZ6RhMzIdRuDebb2LyGE84VSu1zZoY=; b=cM7UB5VClIabhd2mLuHwbdX+YtTOQ5ht+UITN7PxQ5bpdMJ5JXGVbAt5O45jsYbGVK s1wlO9k9M26rtCYDx253b5ujh8M5Esq0GXnFU7C4k0MFAAfRqGTaN70cipORq23oCQiV xg20Ykw/waW+yn4gLCE/jhKl00H3iZuTRU8JvLO0K+6CqFj/E2oP+oNYf0sfSdQzRfDo C/0sqwT/eN1QKQLK4F620eQXRTOLQSsoRjlKa6uD9FBNRAeROPkah8w4HvouPJQowrOY DmX7E1nBLO78093j5DJ2BeyPw/5mnfCHzS8MwfWvlWcJzTov/ALSf0pqvPMmbIHwuRCW 8DJg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@suse.de header.s=susede2_rsa header.b=FncgLmX0; dkim=neutral (no key) header.i=@suse.de; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=suse.de Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id b128-20020a621b86000000b0052eb81ff734si10640488pfb.113.2022.09.05.05.59.24; Mon, 05 Sep 2022 05:59:36 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@suse.de header.s=susede2_rsa header.b=FncgLmX0; dkim=neutral (no key) header.i=@suse.de; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=suse.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237400AbiIEM4v (ORCPT + 99 others); Mon, 5 Sep 2022 08:56:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34694 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237075AbiIEM4n (ORCPT ); Mon, 5 Sep 2022 08:56:43 -0400 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 996A720F47 for ; Mon, 5 Sep 2022 05:56:41 -0700 (PDT) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 427C9388A6; Mon, 5 Sep 2022 12:56:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1662382600; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=yd11dLSAJEXEEwZ6RhMzIdRuDebb2LyGE84VSu1zZoY=; b=FncgLmX0EjrYzuObYeeFbfEeRBOyIQRghMHMa/M1TbWZ04lNH1va/HufyKfogIVqmnqy3e Jv3bLSfbY+5tZ7pHnsTboapJkqKt+r68aY7ho6IPK8+Cbb9yFbLwDyKRpPO5MD+8KOF26W yyuNkMAaLdIoWhhc4YgLhUpox7G1PaE= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1662382600; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=yd11dLSAJEXEEwZ6RhMzIdRuDebb2LyGE84VSu1zZoY=; b=c2DOdEnbT6A7m89Mzy2R6IFJIwwz/AobJEZ10fnjiPAW6lOD4AJV9Ienkv5aAfrp0d0ElS 07cgTuQXmzmT2hAg== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 2349A13A66; Mon, 5 Sep 2022 12:56:40 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id Co/sBwjyFWPaEAAAMHmgww (envelope-from ); Mon, 05 Sep 2022 12:56:40 +0000 Date: Mon, 05 Sep 2022 14:56:39 +0200 Message-ID: <87k06ij7y0.wl-tiwai@suse.de> From: Takashi Iwai To: Thomas Zimmermann Cc: Takashi Iwai , dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH 10/12] drm/udl: Fix inconsistent urbs.count value during udl_free_urb_list() In-Reply-To: <5730ea32-caea-03db-c37c-658484c2f8f0@suse.de> References: <20220816153655.27526-1-tiwai@suse.de> <20220816153655.27526-11-tiwai@suse.de> <5730ea32-caea-03db-c37c-658484c2f8f0@suse.de> User-Agent: Wanderlust/2.15.9 (Almost Unreal) Emacs/27.2 Mule/6.0 MIME-Version: 1.0 (generated by SEMI-EPG 1.14.7 - "Harue") Content-Type: text/plain; charset=US-ASCII X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, 05 Sep 2022 10:32:55 +0200, Thomas Zimmermann wrote: > > Hi > > Am 16.08.22 um 17:36 schrieb Takashi Iwai: > > In the current design, udl_get_urb() may be called asynchronously > > during the driver freeing its URL list via udl_free_urb_list(). > > The problem is that the sync is determined by comparing the urbs.count > > and urbs.available fields, while we clear urbs.count field only once > > after udl_free_urb_list() finishes, i.e. during udl_free_urb_list(), > > the state becomes inconsistent. > > > > For fixing this inconsistency and also for hardening the locking > > scheme, this patch does a slight refactoring of the code around > > udl_get_urb() and udl_free_urb_list(). Now urbs.count is updated in > > the same spinlock at extracting a URB from the list in > > udl_free_url_list(). > > > > Signed-off-by: Takashi Iwai > > --- > > drivers/gpu/drm/udl/udl_drv.h | 8 +------- > > drivers/gpu/drm/udl/udl_main.c | 37 ++++++++++++++++++++++++---------- > > 2 files changed, 27 insertions(+), 18 deletions(-) > > > > diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h > > index 5923d2e02bc8..d943684b5bbb 100644 > > --- a/drivers/gpu/drm/udl/udl_drv.h > > +++ b/drivers/gpu/drm/udl/udl_drv.h > > @@ -74,13 +74,7 @@ static inline struct usb_device *udl_to_usb_device(struct udl_device *udl) > > int udl_modeset_init(struct drm_device *dev); > > struct drm_connector *udl_connector_init(struct drm_device *dev); > > -struct urb *udl_get_urb_timeout(struct drm_device *dev, long > > timeout); > > - > > -#define GET_URB_TIMEOUT HZ > > -static inline struct urb *udl_get_urb(struct drm_device *dev) > > -{ > > - return udl_get_urb_timeout(dev, GET_URB_TIMEOUT); > > -} > > +struct urb *udl_get_urb(struct drm_device *dev); > > int udl_submit_urb(struct drm_device *dev, struct urb *urb, > > size_t len); > > int udl_sync_pending_urbs(struct drm_device *dev); > > diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c > > index 8bbb4e2861fb..19dc8317e843 100644 > > --- a/drivers/gpu/drm/udl/udl_main.c > > +++ b/drivers/gpu/drm/udl/udl_main.c > > @@ -28,6 +28,8 @@ > > static uint udl_num_urbs = WRITES_IN_FLIGHT; > > module_param_named(numurbs, udl_num_urbs, uint, 0600); > > +static struct urb *__udl_get_urb(struct udl_device *udl, long > > timeout); > > + > > static int udl_parse_vendor_descriptor(struct udl_device *udl) > > { > > struct usb_device *udev = udl_to_usb_device(udl); > > @@ -151,15 +153,17 @@ void udl_urb_completion(struct urb *urb) > > static void udl_free_urb_list(struct drm_device *dev) > > { > > struct udl_device *udl = to_udl(dev); > > - int count = udl->urbs.count; > > struct urb_node *unode; > > struct urb *urb; > > DRM_DEBUG("Waiting for completes and freeing all render > > urbs\n"); > > /* keep waiting and freeing, until we've got 'em all */ > > - while (count--) { > > - urb = udl_get_urb_timeout(dev, MAX_SCHEDULE_TIMEOUT); > > + while (udl->urbs.count) { > > + spin_lock_irq(&udl->urbs.lock); > > + urb = __udl_get_urb(udl, MAX_SCHEDULE_TIMEOUT); > > + udl->urbs.count--; > > + spin_unlock_irq(&udl->urbs.lock); > > if (WARN_ON(!urb)) > > break; > > unode = urb->context; > > @@ -169,7 +173,8 @@ static void udl_free_urb_list(struct drm_device *dev) > > usb_free_urb(urb); > > kfree(unode); > > } > > - udl->urbs.count = 0; > > + > > + wake_up(&udl->urbs.sleep); > > There's just one waiter, but it's the shutdown code. Maybe > wake_up_all() would more clearly communicate the intention. OK. > > } > > static int udl_alloc_urb_list(struct drm_device *dev, int count, > > size_t size) > > @@ -233,33 +238,43 @@ static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) > > return udl->urbs.count; > > } > > -struct urb *udl_get_urb_timeout(struct drm_device *dev, long > > timeout) > > +static struct urb *__udl_get_urb(struct udl_device *udl, long timeout) > > I think in DRM, the correct name for this function would be > udl_get_urb_locked(). OK. > > { > > - struct udl_device *udl = to_udl(dev); > > - struct urb_node *unode = NULL; > > + struct urb_node *unode; > > + > > + assert_spin_locked(&udl->urbs.lock); > > if (!udl->urbs.count) > > return NULL; > > /* Wait for an in-flight buffer to complete and get re-queued > > */ > > - spin_lock_irq(&udl->urbs.lock); > > if (!wait_event_lock_irq_timeout(udl->urbs.sleep, > > !list_empty(&udl->urbs.list), > > The urb-free function will wake up this code, but the urb list should > be empty then. Should we update the condition to something like > 'udl->urbs.count && !list_empty()' ? This must not happen as this function itself is the only one who takes out the element from the list. But it's OK to add the zero check there just to be sure... thanks, Takashi