Message ID | d85c7441b96ce387d9010142efc3469d53b6aedc.1671898144.git.drv@mailo.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:4e01:0:0:0:0:0 with SMTP id p1csp223458wrt; Sat, 24 Dec 2022 08:36:36 -0800 (PST) X-Google-Smtp-Source: AMrXdXuaejlpeHIESeZ8T1gwThH+N2DWpxu69G9BoqVA7nyj5TBu6Zm3eEmE0EDiEkzFwAMfy+dj X-Received: by 2002:a17:907:9d0b:b0:78d:f455:30db with SMTP id kt11-20020a1709079d0b00b0078df45530dbmr11188147ejc.3.1671899796213; Sat, 24 Dec 2022 08:36:36 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1671899796; cv=none; d=google.com; s=arc-20160816; b=FugDRN8ZQS/Z5cPI48+ee7MQTlORxdFyCCh3ihrdSy2sEOIsWCVrhO5nKK3U2SBOS9 ZHQUsKzxRgWr/n1hMxmeRj5QAgvz853BR5HVvFyHG8TQsMf3MNM329JA598B/Bud47lw 8c1kErP2C8J4DwevVz2h5VNljsHTNIv9xDqn87+Rvd5B/4iFEuD3tqd63JQ7u8wHd/Pq qyNYJxkO6nSuvOQYX4aEMCd8d+peyT448mW0MGjPVWoKHjTNPtcHhrt+mFuDrHMMntPV rjhUlKYT4QjZJaIqhXrxg2xhQ7hg52gelkRGQqq8VSFCXp5XZZal8PGw0ckgryZfSir4 2l2w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date:dkim-signature; bh=nw83YWXMrMVmsMep9YogcVzbm09s5Dw1YdlvKFb/PYI=; b=S7/oCE9WTVi523kFbARNpsCKZYi4d2mGp9zvgu3DUFweSI5igHp0juKqBchQ9UoyCi 7USMg3CLwXL16OtWqE7FuaeHwDU5E7ktlxDHp13feiHS72ExJng4nhuH2nPLKCwpu5Iy yY0IanOF4GhqeICkXMsIc5/PIudXubAyIva3wbVsD8a5dsRswlXjj4ag/Hs5wZB+bhga r1WsY5gC4nX67eHhTpWhfIuFBuSEYLIQUi2tYNyb/1B25Qn8CSnazeTHxjzY5zXW7IAS qRVnpKcWmQSucfNZNyAvbmnu/0/miV5d8mH4WvuJA/IJ9103wmWydwUzoyD/Hg9vf5iM 3jqg== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@mailo.com header.s=mailo header.b=PEQeobYk; 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=fail (p=NONE sp=NONE dis=NONE) header.from=mailo.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ds3-20020a170907724300b0078cdba56108si4658467ejc.296.2022.12.24.08.36.13; Sat, 24 Dec 2022 08:36:36 -0800 (PST) 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=fail header.i=@mailo.com header.s=mailo header.b=PEQeobYk; 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=fail (p=NONE sp=NONE dis=NONE) header.from=mailo.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231293AbiLXQeJ (ORCPT <rfc822;eddaouddi.ayoub@gmail.com> + 99 others); Sat, 24 Dec 2022 11:34:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50440 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229688AbiLXQeH (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Sat, 24 Dec 2022 11:34:07 -0500 Received: from msg-1.mailo.com (msg-1.mailo.com [213.182.54.11]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 67242BC24; Sat, 24 Dec 2022 08:34:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=mailo.com; s=mailo; t=1671899635; bh=lZPFgAklaDMM/Nar0joqKweC5S5QgeTAOuf+S5eqA54=; h=X-EA-Auth:Date:From:To:Cc:Subject:Message-ID:References: MIME-Version:Content-Type:In-Reply-To; b=PEQeobYkPHBvsQf1uYxPjVZCr5MDrzYQbm30/dqzXCxDsDshfAYWe/8YKPTKh5r+H ML+EvdZCkgfCpFwY5UNGsY+Sm5hg36YyH9d++1KS7SAW+qArwjQWDBnQQ+NcoMZo9C 4U9QHm8dpR+tHec57wRWfIT1nfaQdI4Ts6+yKnTs= Received: by b-4.in.mailobj.net [192.168.90.14] with ESMTP via ip-206.mailobj.net [213.182.55.206] Sat, 24 Dec 2022 17:33:55 +0100 (CET) X-EA-Auth: KoErFyzIxepLC6/uiq781G29rTyZ7tEIEuiqF35jeYbUL5AI27FCTgRYKDO1jWYUk5i2hvlmx46SY09VhqDEcSR4FSyBbACE Date: Sat, 24 Dec 2022 22:03:48 +0530 From: Deepak R Varma <drv@mailo.com> To: "Maciej W. Rozycki" <macro@orcam.me.uk>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Jiri Slaby <jirislaby@kernel.org>, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Saurabh Singh Sengar <ssengar@microsoft.com>, Praveen Kumar <kumarpraveen@linux.microsoft.com>, Deepak R Varma <drv@mailo.com> Subject: [PATCH v3 1/2] tty: serial: dz: convert atomic_* to refcount_* APIs for map_guard Message-ID: <d85c7441b96ce387d9010142efc3469d53b6aedc.1671898144.git.drv@mailo.com> References: <cover.1671898144.git.drv@mailo.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <cover.1671898144.git.drv@mailo.com> X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS 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: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1753114000484655642?= X-GMAIL-MSGID: =?utf-8?q?1753114000484655642?= |
Series |
tty: serial: dz: convert atomic_* to refcount_*
|
|
Commit Message
Deepak R Varma
Dec. 24, 2022, 4:33 p.m. UTC
The refcount_* APIs are designed to address known issues with the
atomic_t APIs for reference counting. They provide following distinct
advantages
- protect the reference counters from overflow/underflow
- avoid use-after-free errors
- provide improved memory ordering guarantee schemes
- neater and safer.
Hence, replace the atomic_* APIs by their equivalent refcount_t
API functions.
This patch proposal address the following warnings generated by
the atomic_as_refcounter.cocci coccinelle script
atomic_add_return(-1, ...)
Signed-off-by: Deepak R Varma <drv@mailo.com>
---
Please Note:
1. The patch is compile tested using dec_station.defconfig for MIPS architecture.
2. This patch should be applied before patch 2/2 of this series due to
dependency.
Changes in v3:
1. Include the individual patches in a series and highlight dependency.
Feedback provided by gregkh@linuxfoundation.org
Changes in v2:
1. Separate the combined change into one variable per patch as
suggested by gregkh@linuxfoundation.org
2. There was additional feedback on validating the change as it appeared to
modify the existing logic. However, I found that the logic does not
change with the proposed refcount_* APIs used in this change. Hence that
feedback is not applied in this version.
drivers/tty/serial/dz.c | 23 +++++++++--------------
1 file changed, 9 insertions(+), 14 deletions(-)
--
2.34.1
Comments
On 26. 12. 22, 7:21, Deepak R Varma wrote: > The refcount_* APIs are designed to address known issues with the > atomic_t APIs for reference counting. They provide following distinct > advantages > - protect the reference counters from overflow/underflow > - avoid use-after-free errors > - provide improved memory ordering guarantee schemes > - neater and safer. Really? (see below) > --- a/drivers/tty/serial/dz.c > +++ b/drivers/tty/serial/dz.c ... > @@ -687,23 +686,19 @@ static int dz_map_port(struct uart_port *uport) > static int dz_request_port(struct uart_port *uport) > { > struct dz_mux *mux = to_dport(uport)->mux; > - int map_guard; > int ret; > > - map_guard = atomic_add_return(1, &mux->map_guard); > - if (map_guard == 1) { > - if (!request_mem_region(uport->mapbase, dec_kn_slot_size, > - "dz")) { > - atomic_add(-1, &mux->map_guard); > - printk(KERN_ERR > - "dz: Unable to reserve MMIO resource\n"); > + refcount_inc(&mux->map_guard); > + if (refcount_read(&mux->map_guard) == 1) { This is now racy, right? thanks,
On Tue, Jan 03, 2023 at 09:59:52AM +0100, Jiri Slaby wrote: > On 26. 12. 22, 7:21, Deepak R Varma wrote: > > The refcount_* APIs are designed to address known issues with the > > atomic_t APIs for reference counting. They provide following distinct > > advantages > > - protect the reference counters from overflow/underflow > > - avoid use-after-free errors > > - provide improved memory ordering guarantee schemes > > - neater and safer. > > Really? (see below) > > > --- a/drivers/tty/serial/dz.c > > +++ b/drivers/tty/serial/dz.c > ... > > @@ -687,23 +686,19 @@ static int dz_map_port(struct uart_port *uport) > > static int dz_request_port(struct uart_port *uport) > > { > > struct dz_mux *mux = to_dport(uport)->mux; > > - int map_guard; > > int ret; > > > > - map_guard = atomic_add_return(1, &mux->map_guard); > > - if (map_guard == 1) { > > - if (!request_mem_region(uport->mapbase, dec_kn_slot_size, > > - "dz")) { > > - atomic_add(-1, &mux->map_guard); > > - printk(KERN_ERR > > - "dz: Unable to reserve MMIO resource\n"); > > + refcount_inc(&mux->map_guard); > > + if (refcount_read(&mux->map_guard) == 1) { > > This is now racy, right? Hello Jiri, Thank you for the feedback. You are correct. I have split a single instruction in two (or more?) instructions potentially resulting in race conditions. I looked through the refcount_* APIs but did not find a direct match. Can you please comment if the the following variation will avoid race condition? if (!refcount_add_not_zero(1, &mux->map_guard)) { refcount_inc(&mux->map_guard); ... } Here, refcount_add_not_zero would return false if &mux->map_guard is already 0. Which means, incrementing it by 1 would have met the earlier if evaluation. Whereas, if &mux->map_guard is something other than 0, refcount_add_not_zero will increment it by 1 and return true, in which case the if condition will fail, similar to the previous if evaluation. Hope that helps clarify my revised thought. Can you please let me know if this revision looks safe? Thank you, ./drv > > thanks, > -- > js > suse labs >
On Tue, Jan 03, 2023 at 03:35:15PM +0530, Deepak R Varma wrote: > On Tue, Jan 03, 2023 at 09:59:52AM +0100, Jiri Slaby wrote: > > On 26. 12. 22, 7:21, Deepak R Varma wrote: > > > The refcount_* APIs are designed to address known issues with the > > > atomic_t APIs for reference counting. They provide following distinct > > > advantages > > > - protect the reference counters from overflow/underflow > > > - avoid use-after-free errors > > > - provide improved memory ordering guarantee schemes > > > - neater and safer. > > > > Really? (see below) > > > > > --- a/drivers/tty/serial/dz.c > > > +++ b/drivers/tty/serial/dz.c > > ... > > > @@ -687,23 +686,19 @@ static int dz_map_port(struct uart_port *uport) > > > static int dz_request_port(struct uart_port *uport) > > > { > > > struct dz_mux *mux = to_dport(uport)->mux; > > > - int map_guard; > > > int ret; > > > > > > - map_guard = atomic_add_return(1, &mux->map_guard); > > > - if (map_guard == 1) { > > > - if (!request_mem_region(uport->mapbase, dec_kn_slot_size, > > > - "dz")) { > > > - atomic_add(-1, &mux->map_guard); > > > - printk(KERN_ERR > > > - "dz: Unable to reserve MMIO resource\n"); > > > + refcount_inc(&mux->map_guard); > > > + if (refcount_read(&mux->map_guard) == 1) { > > > > This is now racy, right? > > Hello Jiri, > Thank you for the feedback. You are correct. I have split a single instruction > in two (or more?) instructions potentially resulting in race conditions. I > looked through the refcount_* APIs but did not find a direct match. > > > Can you please comment if the the following variation will avoid race condition? > > if (!refcount_add_not_zero(1, &mux->map_guard)) { > refcount_inc(&mux->map_guard); > ... > } What do you think? The onus is on you to prove the conversion is correct, otherwise, why do the conversion at all? Actually, why do this at all, what is the goal here? And how was this tested? thanks, greg k-h
On Wed, Jan 04, 2023 at 09:28:13AM +0100, Greg Kroah-Hartman wrote: > On Tue, Jan 03, 2023 at 03:35:15PM +0530, Deepak R Varma wrote: > > > > - printk(KERN_ERR > > > > - "dz: Unable to reserve MMIO resource\n"); > > > > + refcount_inc(&mux->map_guard); > > > > + if (refcount_read(&mux->map_guard) == 1) { > > > > > > This is now racy, right? > > > > Hello Jiri, > > Thank you for the feedback. You are correct. I have split a single instruction > > in two (or more?) instructions potentially resulting in race conditions. I > > looked through the refcount_* APIs but did not find a direct match. > > > > > > Can you please comment if the the following variation will avoid race condition? > > > > if (!refcount_add_not_zero(1, &mux->map_guard)) { > > refcount_inc(&mux->map_guard); > > ... > > } > > What do you think? The onus is on you to prove the conversion is > correct, otherwise, why do the conversion at all? Hello Greg, Okay. Sounds good. I think the revised approach should be safer. I will work on finding a means to prove that. > > Actually, why do this at all, what is the goal here? And how was this > tested? The objective here is to migrate to specific and improved APIs that are already proved to be better for different reasons as mentioned in the patch log messages. This is as per the Linux Kernel documentation. In terms of testing, First, I did a compile and build test of the changes. I also wrote separate small dummy modules and tested the API transformation. However, these modules were standalone and limited in complexity and intensity. I will try to make these more intense, multithreaded and run the test again. Thank you as always :) ./drv > > thanks, > > greg k-h
On Tue, Jan 03, 2023 at 09:59:52AM +0100, Jiri Slaby wrote: > On 26. 12. 22, 7:21, Deepak R Varma wrote: > > The refcount_* APIs are designed to address known issues with the > > atomic_t APIs for reference counting. They provide following distinct > > advantages > > - protect the reference counters from overflow/underflow > > - avoid use-after-free errors > > - provide improved memory ordering guarantee schemes > > - neater and safer. > > Really? (see below) > > > --- a/drivers/tty/serial/dz.c > > +++ b/drivers/tty/serial/dz.c > ... > > @@ -687,23 +686,19 @@ static int dz_map_port(struct uart_port *uport) > > static int dz_request_port(struct uart_port *uport) > > { > > struct dz_mux *mux = to_dport(uport)->mux; > > - int map_guard; > > int ret; > > > > - map_guard = atomic_add_return(1, &mux->map_guard); > > - if (map_guard == 1) { > > - if (!request_mem_region(uport->mapbase, dec_kn_slot_size, > > - "dz")) { > > - atomic_add(-1, &mux->map_guard); > > - printk(KERN_ERR > > - "dz: Unable to reserve MMIO resource\n"); > > + refcount_inc(&mux->map_guard); > > + if (refcount_read(&mux->map_guard) == 1) { > > This is now racy, right? Hello Jiri, I found this [1] commit which introduced similar transformation in a neighbouring driver. Can you please comment how is this different from the current patch proposal? [1] commit ID: 22a33651a56f ("convert sbd_duart.map_guard from atomic_t to refcount_t") On a side note, I have not been able to find an exact 1:1 map to the atomic_add_result API. I am wondering should we have one? Thank you, ./drv Thank you, ./drv > > thanks, > -- > js > suse labs >
> On Tue, Jan 03, 2023 at 09:59:52AM +0100, Jiri Slaby wrote: > > On 26. 12. 22, 7:21, Deepak R Varma wrote: > > > The refcount_* APIs are designed to address known issues with the > > > atomic_t APIs for reference counting. They provide following distinct > > > advantages > > > - protect the reference counters from overflow/underflow > > > - avoid use-after-free errors > > > - provide improved memory ordering guarantee schemes > > > - neater and safer. > > > > Really? (see below) > > > > > --- a/drivers/tty/serial/dz.c > > > +++ b/drivers/tty/serial/dz.c > > ... > > > @@ -687,23 +686,19 @@ static int dz_map_port(struct uart_port *uport) > > > static int dz_request_port(struct uart_port *uport) > > > { > > > struct dz_mux *mux = to_dport(uport)->mux; > > > - int map_guard; > > > int ret; > > > > > > - map_guard = atomic_add_return(1, &mux->map_guard); > > > - if (map_guard == 1) { > > > - if (!request_mem_region(uport->mapbase, dec_kn_slot_size, > > > - "dz")) { > > > - atomic_add(-1, &mux->map_guard); > > > - printk(KERN_ERR > > > - "dz: Unable to reserve MMIO resource\n"); > > > + refcount_inc(&mux->map_guard); > > > + if (refcount_read(&mux->map_guard) == 1) { > > > > This is now racy, right? > > Hello Jiri, > I found this [1] commit which introduced similar transformation in a > neighbouring driver. Can you please comment how is this different from the > current patch proposal? > > [1] commit ID: 22a33651a56f ("convert sbd_duart.map_guard from atomic_t to > refcount_t") > > On a side note, I have not been able to find an exact 1:1 map to the > atomic_add_result API. I am wondering should we have one? In past we have decided not to provide this API for refcount_t because for truly correctly behaving reference counters it should not be needed (vs atomics that cover a broader range of use cases). Can you use !refcount_inc_not_zero in the above case? Best Regards, Elena.
On Tue, Jan 10, 2023 at 07:27:44AM +0000, Reshetova, Elena wrote: > > > On Tue, Jan 03, 2023 at 09:59:52AM +0100, Jiri Slaby wrote: > > > On 26. 12. 22, 7:21, Deepak R Varma wrote: > > > > The refcount_* APIs are designed to address known issues with the > > > > atomic_t APIs for reference counting. They provide following distinct > > > > advantages > > > > - protect the reference counters from overflow/underflow > > > > - avoid use-after-free errors > > > > - provide improved memory ordering guarantee schemes > > > > - neater and safer. > > > > > > Really? (see below) > > > > > > > --- a/drivers/tty/serial/dz.c > > > > +++ b/drivers/tty/serial/dz.c > > > ... > > > > @@ -687,23 +686,19 @@ static int dz_map_port(struct uart_port *uport) > > > > static int dz_request_port(struct uart_port *uport) > > > > { > > > > struct dz_mux *mux = to_dport(uport)->mux; > > > > - int map_guard; > > > > int ret; > > > > > > > > - map_guard = atomic_add_return(1, &mux->map_guard); > > > > - if (map_guard == 1) { > > > > - if (!request_mem_region(uport->mapbase, dec_kn_slot_size, > > > > - "dz")) { > > > > - atomic_add(-1, &mux->map_guard); > > > > - printk(KERN_ERR > > > > - "dz: Unable to reserve MMIO resource\n"); > > > > + refcount_inc(&mux->map_guard); > > > > + if (refcount_read(&mux->map_guard) == 1) { > > > > > > This is now racy, right? > > > > Hello Jiri, > > I found this [1] commit which introduced similar transformation in a > > neighbouring driver. Can you please comment how is this different from the > > current patch proposal? > > > > [1] commit ID: 22a33651a56f ("convert sbd_duart.map_guard from atomic_t to > > refcount_t") > > > > On a side note, I have not been able to find an exact 1:1 map to the > > atomic_add_result API. I am wondering should we have one? > Hello Elena, > In past we have decided not to provide this API for refcount_t > because for truly correctly behaving reference counters it should not be needed > (vs atomics that cover a broader range of use cases). So, there is no FAA refcount wrapper? I think this is a pretty common need. Please correct me if I am wrong. > Can you use !refcount_inc_not_zero in the above case? I actually did try that but was not sure if truly addresses the objection. Please attached and let me know if you have a feedback on the alternate approach. Thank you, ./drv > > Best Regards, > Elena. ############## ORIGINAL CODE ################################## - map_guard = atomic_add_return(1, &mux->map_guard); - if (map_guard == 1) { - if (!request_mem_region(uport->mapbase, dec_kn_slot_size, - "dz")) { - atomic_add(-1, &mux->map_guard); - printk(KERN_ERR - "dz: Unable to reserve MMIO resource\n"); return -EBUSY; } } ############## INITIAL APPROACH ################################## + refcount_inc(&mux->map_guard); + if (refcount_read(&mux->map_guard) == 1) { + if (!request_mem_region(uport->mapbase, dec_kn_slot_size, "dz")) { + refcount_dec(&mux->map_guard); + printk(KERN_ERR "dz: Unable to reserve MMIO resource\n"); return -EBUSY; } } ############## ALTERNATE APPROACH ################################## + if (!refcount_inc_not_zero(&mux->map_guard)) { + refcount_inc(&mux->map_guard); + if (!request_mem_region(uport->mapbase, dec_kn_slot_size, "dz")) { + refcount_dec(&mux->map_guard); + printk(KERN_ERR "dz: Unable to reserve MMIO resource\n"); return -EBUSY; } }
On Tue, Jan 10, 2023 at 01:17:54PM +0530, Deepak R Varma wrote: > On Tue, Jan 10, 2023 at 07:27:44AM +0000, Reshetova, Elena wrote: > > > > > On Tue, Jan 03, 2023 at 09:59:52AM +0100, Jiri Slaby wrote: > > > > On 26. 12. 22, 7:21, Deepak R Varma wrote: > > > > > The refcount_* APIs are designed to address known issues with the > > > > > atomic_t APIs for reference counting. They provide following distinct > > > > > advantages > > > > > - protect the reference counters from overflow/underflow > > > > > - avoid use-after-free errors > > > > > - provide improved memory ordering guarantee schemes > > > > > - neater and safer. > > > > > > > > Really? (see below) > > > > > > > > > --- a/drivers/tty/serial/dz.c > > > > > +++ b/drivers/tty/serial/dz.c > > > > ... > > > > > @@ -687,23 +686,19 @@ static int dz_map_port(struct uart_port *uport) > > > > > static int dz_request_port(struct uart_port *uport) > > > > > { > > > > > struct dz_mux *mux = to_dport(uport)->mux; > > > > > - int map_guard; > > > > > int ret; > > > > > > > > > > - map_guard = atomic_add_return(1, &mux->map_guard); > > > > > - if (map_guard == 1) { > > > > > - if (!request_mem_region(uport->mapbase, dec_kn_slot_size, > > > > > - "dz")) { > > > > > - atomic_add(-1, &mux->map_guard); > > > > > - printk(KERN_ERR > > > > > - "dz: Unable to reserve MMIO resource\n"); > > > > > + refcount_inc(&mux->map_guard); > > > > > + if (refcount_read(&mux->map_guard) == 1) { > > > > > > > > This is now racy, right? > > > > > > Hello Jiri, > > > I found this [1] commit which introduced similar transformation in a > > > neighbouring driver. Can you please comment how is this different from the > > > current patch proposal? > > > > > > [1] commit ID: 22a33651a56f ("convert sbd_duart.map_guard from atomic_t to > > > refcount_t") > > > > > > On a side note, I have not been able to find an exact 1:1 map to the > > > atomic_add_result API. I am wondering should we have one? > > > > Hello Elena, > > > In past we have decided not to provide this API for refcount_t > > because for truly correctly behaving reference counters it should not be needed > > (vs atomics that cover a broader range of use cases). > > So, there is no FAA refcount wrapper? I think this is a pretty common need. > Please correct me if I am wrong. > > > Can you use !refcount_inc_not_zero in the above case? > > I actually did try that but was not sure if truly addresses the objection. > Please attached and let me know if you have a feedback on the alternate > approach. > > Thank you, > ./drv > > > > > > Best Regards, > > Elena. > ############## ORIGINAL CODE ################################## > - map_guard = atomic_add_return(1, &mux->map_guard); > - if (map_guard == 1) { > - if (!request_mem_region(uport->mapbase, dec_kn_slot_size, > - "dz")) { > - atomic_add(-1, &mux->map_guard); > - printk(KERN_ERR > - "dz: Unable to reserve MMIO resource\n"); > return -EBUSY; > } > } > > ############## INITIAL APPROACH ################################## > + refcount_inc(&mux->map_guard); > + if (refcount_read(&mux->map_guard) == 1) { > + if (!request_mem_region(uport->mapbase, dec_kn_slot_size, "dz")) { > + refcount_dec(&mux->map_guard); > + printk(KERN_ERR "dz: Unable to reserve MMIO resource\n"); > return -EBUSY; > } > } > > ############## ALTERNATE APPROACH ################################## > > + if (!refcount_inc_not_zero(&mux->map_guard)) { > + refcount_inc(&mux->map_guard); > + if (!request_mem_region(uport->mapbase, dec_kn_slot_size, "dz")) { > + refcount_dec(&mux->map_guard); > + printk(KERN_ERR "dz: Unable to reserve MMIO resource\n"); > return -EBUSY; > } > } > This feels odd to me, why not just use a normal lock instead? thanks, greg k-h
diff --git a/drivers/tty/serial/dz.c b/drivers/tty/serial/dz.c index 6b7ed7f2f3ca..b70edc248f8b 100644 --- a/drivers/tty/serial/dz.c +++ b/drivers/tty/serial/dz.c @@ -47,6 +47,7 @@ #include <linux/tty_flip.h> #include <linux/atomic.h> +#include <linux/refcount.h> #include <linux/io.h> #include <asm/bootinfo.h> @@ -75,7 +76,7 @@ struct dz_port { struct dz_mux { struct dz_port dport[DZ_NB_PORT]; - atomic_t map_guard; + refcount_t map_guard; atomic_t irq_guard; int initialised; }; @@ -662,13 +663,11 @@ static const char *dz_type(struct uart_port *uport) static void dz_release_port(struct uart_port *uport) { struct dz_mux *mux = to_dport(uport)->mux; - int map_guard; iounmap(uport->membase); uport->membase = NULL; - map_guard = atomic_add_return(-1, &mux->map_guard); - if (!map_guard) + if (refcount_dec_and_test(&mux->map_guard)) release_mem_region(uport->mapbase, dec_kn_slot_size); } @@ -687,23 +686,19 @@ static int dz_map_port(struct uart_port *uport) static int dz_request_port(struct uart_port *uport) { struct dz_mux *mux = to_dport(uport)->mux; - int map_guard; int ret; - map_guard = atomic_add_return(1, &mux->map_guard); - if (map_guard == 1) { - if (!request_mem_region(uport->mapbase, dec_kn_slot_size, - "dz")) { - atomic_add(-1, &mux->map_guard); - printk(KERN_ERR - "dz: Unable to reserve MMIO resource\n"); + refcount_inc(&mux->map_guard); + if (refcount_read(&mux->map_guard) == 1) { + if (!request_mem_region(uport->mapbase, dec_kn_slot_size, "dz")) { + refcount_dec(&mux->map_guard); + printk(KERN_ERR "dz: Unable to reserve MMIO resource\n"); return -EBUSY; } } ret = dz_map_port(uport); if (ret) { - map_guard = atomic_add_return(-1, &mux->map_guard); - if (!map_guard) + if (refcount_dec_and_test(&mux->map_guard)) release_mem_region(uport->mapbase, dec_kn_slot_size); return ret; }