Received: by 2002:ab2:1347:0:b0:1f4:ac9d:b246 with SMTP id g7csp450673lqg; Thu, 11 Apr 2024 07:48:37 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCUg2DavLVi5yfQGglQ5Jh9ACoHrWQ1FBdt5ZdY6YZC0t58VBX5w5CHsE0RfNZFQqGeyvpYr/rr05N57d+JwSZyeU0EadVTWF5URyPEeSw== X-Google-Smtp-Source: AGHT+IGoAwHY6bMafHytBDf0DTo895T4dDLGW7u8e5xAAYfaexlGTx073KuJzO2xHd5F/wvSZ/dk X-Received: by 2002:a17:90a:4747:b0:2a3:f005:982a with SMTP id y7-20020a17090a474700b002a3f005982amr5336053pjg.24.1712846917620; Thu, 11 Apr 2024 07:48:37 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1712846917; cv=pass; d=google.com; s=arc-20160816; b=SNqCLnw6rwU1cgg1JFCvVeboY0H3oslm/w5ECjSOfuryUCK4ou37vehK6dHvwwz0yP 6LpRTpRAqjEfPZi043EAACWvsKVN+6OrqZI1OMOvlABGcKKL6FYM3nuL+Rn9kmfm2dV/ 4R6vMEF0RyUIeCmKikHSGy5riBVFGOqR3OK0JY+2fhaHwgX6zwagDgNZwK8DlZH2+vff 2VBnPN+3GiOEhXGW3lNDCrIrjBsZLPmjUaWxxCCkGUPv7GyLGLrxcPorvBttZF8zpTJc vLWgcsM7PYr6RDFvZFmrVjxuEOyIpXicQ0xCsuxGr2Wi267kpzpo1MHfvcLShPHdWr+B yooA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:message-id:date:subject:cc:to :from:dkim-signature; bh=5jHQyB0DALNKMopR2MDBXCeG1jJE0vxzfU8Bvd08rQ8=; fh=b3pLwzNJBBMsKVHYXn6YyJdU2zldUjgT1ow30KApt70=; b=atT6gh8wwpmzVYe7rPZ0qiamn7EV4VwiqKsTZfo3ZvFWnfoUo2OPKwmZpwHHY3iOrD I9+OED1WUtlQqkTF0+JZvNElLG6k1viC5P/8RHSXnfMIqllQzpn6MiCeGB8bmRsJxTPl 32oBOZ55YSVZ/awlOwPF6JQRfdHjbjPagZ7o6VYt8JmTn2enKMlJKHabDYD8NqkPTKAp iT0ipePlFWgwt4/PyZQouYkXLtROV+Ks869YIiQWFYfRizD+Rex9wCbntB6pWvb9s3Oj N30d+IKLpJDrNmtAr1gZwH0QRl8YZJuciQBe/nCM4DqxhJg3Kh0OvxR3nvFXOZ4dsWqW vbvQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=RnjOmShM; arc=pass (i=1 spf=pass spfdomain=redhat.com dkim=pass dkdomain=redhat.com dmarc=pass fromdomain=redhat.com); spf=pass (google.com: domain of linux-kernel+bounces-140693-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-140693-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id l11-20020a17090ac58b00b002a2e545eac4si3623574pjt.87.2024.04.11.07.48.37 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Apr 2024 07:48:37 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-140693-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=RnjOmShM; arc=pass (i=1 spf=pass spfdomain=redhat.com dkim=pass dkdomain=redhat.com dmarc=pass fromdomain=redhat.com); spf=pass (google.com: domain of linux-kernel+bounces-140693-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-140693-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 44739283C4F for ; Thu, 11 Apr 2024 14:48:37 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 6234412E74; Thu, 11 Apr 2024 14:48:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="RnjOmShM" Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8A6C010799 for ; Thu, 11 Apr 2024 14:48:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712846909; cv=none; b=GmFsw3CGt13jn0jv4cBXMHKCZGjsv1pD6+86zl4QX+ei2uO0m/WFbl5YCha47Q1l81n4/M5iV8GTrzbLJIWK7vTXdCnWu7071D2xvsDzL/KRfTd4R6kQB9vXq6D7SZ/eUMMluQwnbn4U9fhYRt3KTpGweo6XmF39FIFDgJQzJbs= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712846909; c=relaxed/simple; bh=xdvDHEbiuJUGM57iynqCZ38yFaZXfSHSPEafF7pHVc0=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=b7y43p0mMUk1DjyF925FA+d9BVVtgud9oyfVBgCegi7AJHKgHq5AyJCKUdgdiyFgXiqdRKwH7wT82Er/DUHev5og6GotVUTCl/2FkCHfXNsQHguYoum/a32foRQQk9ojNzDLrUCJ2c2phY8pc3H6Bjrc7BkqUfA+yaKOdY3Sdnc= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=RnjOmShM; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712846906; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=5jHQyB0DALNKMopR2MDBXCeG1jJE0vxzfU8Bvd08rQ8=; b=RnjOmShMMdcUN46kTM1FMXomdNgWA2//O7PUKFgKC0nyWhMZX9hC16eIWj/Ezdxn/G6eD7 UsVp5+oX+NcpyRu9kcbOlHf5mOE5f/Ls/9bgciA97LypFSm7QTPhRZlm9dSVmMeSpYWlZZ dR9723zxjNaotK/DSjGNHm6ECFQC3Jk= Received: from mail-qk1-f198.google.com (mail-qk1-f198.google.com [209.85.222.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-480-zFRUZmCPNfG6TDvN6HwMXw-1; Thu, 11 Apr 2024 10:48:25 -0400 X-MC-Unique: zFRUZmCPNfG6TDvN6HwMXw-1 Received: by mail-qk1-f198.google.com with SMTP id af79cd13be357-78d6b7d1f4fso275293885a.1 for ; Thu, 11 Apr 2024 07:48:24 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712846904; x=1713451704; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=5jHQyB0DALNKMopR2MDBXCeG1jJE0vxzfU8Bvd08rQ8=; b=j9W9TsfNgoAjXDoT/ntI5Be7h8KnIkEgnJo5OPULujqzaBGVihgPGvBraVMa/aKuR8 vZMitC8B/KfDfccSF+/Er+6S7zgrS3P1MXMppGTTna1G+R2ZL2Iwu4wV9NXmybo5Hh+c Oe3nHfJEXuGdVRYVP3Ydu8nFIXGbOAhaCRKiaD7zaeDsNT1MA/frFAt4su9TW30cDXaM kwVEUGPvs9dgIM9PAzBONkWrYBhM5g0bLmrQfWl3Iup+p3lMCFslVesPkvMvi/MiC8En qvVUGLZmnOgFzD1+ud9uakvcF6I1If2seQl7If9t8660D1OpmCLA+Sa/e3YsQxizssM7 R20Q== X-Forwarded-Encrypted: i=1; AJvYcCWAvdrczFqeBI/h2iki86e/RcHlU3eGb3GJCCFnpTTdlY6IB6Dj3G8/9K0q5iBYrpTiQ0tiC27hVmCqw3eSgIt5aN5dGLGvnpX0Z9DJ X-Gm-Message-State: AOJu0YzJ4xgLv6GZcsVbfAAKU8uBQ+Thc3LU7qLYbOA0nAqgZ8C0S4FO iqIyFP1C3uZ5Stp92YPTU4CnHLnFTVd4Z6aM7o71rAgrMBOXHYpvMpPtWP+qkF3ULuoE2FulJvI ItIYCLGcOm5nt4F7ExlzwoE8KCo6jounI/usJJNHlYaOCeoSl4Uxu0H9Obx+p X-Received: by 2002:a05:620a:1019:b0:78d:6bc5:167a with SMTP id z25-20020a05620a101900b0078d6bc5167amr6458939qkj.24.1712846904399; Thu, 11 Apr 2024 07:48:24 -0700 (PDT) X-Received: by 2002:a05:620a:1019:b0:78d:6bc5:167a with SMTP id z25-20020a05620a101900b0078d6bc5167amr6458917qkj.24.1712846904013; Thu, 11 Apr 2024 07:48:24 -0700 (PDT) Received: from klayman.redhat.com (net-2-34-25-239.cust.vodafonedsl.it. [2.34.25.239]) by smtp.gmail.com with ESMTPSA id bi10-20020a05620a318a00b0078d623428c5sm1106815qkb.88.2024.04.11.07.48.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Apr 2024 07:48:23 -0700 (PDT) From: Marco Pagani To: Moritz Fischer , Wu Hao , Xu Yilun , Tom Rix , Jonathan Corbet , Greg Kroah-Hartman , Alan Tull Cc: Marco Pagani , Russ Weight , linux-fpga@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5] fpga: region: add owner module and take its refcount Date: Thu, 11 Apr 2024 16:48:10 +0200 Message-ID: <20240411144811.121500-1-marpagan@redhat.com> X-Mailer: git-send-email 2.44.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit The current implementation of the fpga region assumes that the low-level module registers a driver for the parent device and uses its owner pointer to take the module's refcount. This approach is problematic since it can lead to a null pointer dereference while attempting to get the region during programming if the parent device does not have a driver. To address this problem, add a module owner pointer to the fpga_region struct and use it to take the module's refcount. Modify the functions for registering a region to take an additional owner module parameter and rename them to avoid conflicts. Use the old function names for helper macros that automatically set the module that registers the region as the owner. This ensures compatibility with existing low-level control modules and reduces the chances of registering a region without setting the owner. Also, update the documentation to keep it consistent with the new interface for registering an fpga region. Fixes: 0fa20cdfcc1f ("fpga: fpga-region: device tree control for FPGA") Suggested-by: Greg Kroah-Hartman Suggested-by: Xu Yilun Reviewed-by: Russ Weight Signed-off-by: Marco Pagani --- v5: - Reverted function names swap in the documentation - Renamed owner module pointer br_owner -> ops_owner v4: - Split out the swap between put_device() and mutex_unlock() while releasing the region to avoid potential use after release issues v3: - Add reviewed-by Russ Weight v2: - Fixed typo in the documentation sets -> set - Renamed owner module pointer get_br_owner -> br_owner --- Documentation/driver-api/fpga/fpga-region.rst | 13 ++++++---- drivers/fpga/fpga-region.c | 24 +++++++++++-------- include/linux/fpga/fpga-region.h | 13 +++++++--- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/Documentation/driver-api/fpga/fpga-region.rst b/Documentation/driver-api/fpga/fpga-region.rst index dc55d60a0b4a..2d03b5fb7657 100644 --- a/Documentation/driver-api/fpga/fpga-region.rst +++ b/Documentation/driver-api/fpga/fpga-region.rst @@ -46,13 +46,16 @@ API to add a new FPGA region ---------------------------- * struct fpga_region - The FPGA region struct -* struct fpga_region_info - Parameter structure for fpga_region_register_full() -* fpga_region_register_full() - Create and register an FPGA region using the +* struct fpga_region_info - Parameter structure for __fpga_region_register_full() +* __fpga_region_register_full() - Create and register an FPGA region using the fpga_region_info structure to provide the full flexibility of options -* fpga_region_register() - Create and register an FPGA region using standard +* __fpga_region_register() - Create and register an FPGA region using standard arguments * fpga_region_unregister() - Unregister an FPGA region +Helper macros ``fpga_region_register()`` and ``fpga_region_register_full()`` +automatically set the module that registers the FPGA region as the owner. + The FPGA region's probe function will need to get a reference to the FPGA Manager it will be using to do the programming. This usually would happen during the region's probe function. @@ -82,10 +85,10 @@ following APIs to handle building or tearing down that list. :functions: fpga_region_info .. kernel-doc:: drivers/fpga/fpga-region.c - :functions: fpga_region_register_full + :functions: __fpga_region_register_full .. kernel-doc:: drivers/fpga/fpga-region.c - :functions: fpga_region_register + :functions: __fpga_region_register .. kernel-doc:: drivers/fpga/fpga-region.c :functions: fpga_region_unregister diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index b364a929425c..cb446dc68fca 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -53,7 +53,7 @@ static struct fpga_region *fpga_region_get(struct fpga_region *region) } get_device(dev); - if (!try_module_get(dev->parent->driver->owner)) { + if (!try_module_get(region->ops_owner)) { put_device(dev); mutex_unlock(®ion->mutex); return ERR_PTR(-ENODEV); @@ -75,7 +75,7 @@ static void fpga_region_put(struct fpga_region *region) dev_dbg(dev, "put\n"); - module_put(dev->parent->driver->owner); + module_put(region->ops_owner); put_device(dev); mutex_unlock(®ion->mutex); } @@ -181,14 +181,16 @@ static struct attribute *fpga_region_attrs[] = { ATTRIBUTE_GROUPS(fpga_region); /** - * fpga_region_register_full - create and register an FPGA Region device + * __fpga_region_register_full - create and register an FPGA Region device * @parent: device parent * @info: parameters for FPGA Region + * @owner: owner module containing the get_bridges function * * Return: struct fpga_region or ERR_PTR() */ struct fpga_region * -fpga_region_register_full(struct device *parent, const struct fpga_region_info *info) +__fpga_region_register_full(struct device *parent, const struct fpga_region_info *info, + struct module *owner) { struct fpga_region *region; int id, ret = 0; @@ -213,6 +215,7 @@ fpga_region_register_full(struct device *parent, const struct fpga_region_info * region->compat_id = info->compat_id; region->priv = info->priv; region->get_bridges = info->get_bridges; + region->ops_owner = owner; mutex_init(®ion->mutex); INIT_LIST_HEAD(®ion->bridge_list); @@ -241,13 +244,14 @@ fpga_region_register_full(struct device *parent, const struct fpga_region_info * return ERR_PTR(ret); } -EXPORT_SYMBOL_GPL(fpga_region_register_full); +EXPORT_SYMBOL_GPL(__fpga_region_register_full); /** - * fpga_region_register - create and register an FPGA Region device + * __fpga_region_register - create and register an FPGA Region device * @parent: device parent * @mgr: manager that programs this region * @get_bridges: optional function to get bridges to a list + * @owner: owner module containing get_bridges function * * This simple version of the register function should be sufficient for most users. * The fpga_region_register_full() function is available for users that need to @@ -256,17 +260,17 @@ EXPORT_SYMBOL_GPL(fpga_region_register_full); * Return: struct fpga_region or ERR_PTR() */ struct fpga_region * -fpga_region_register(struct device *parent, struct fpga_manager *mgr, - int (*get_bridges)(struct fpga_region *)) +__fpga_region_register(struct device *parent, struct fpga_manager *mgr, + int (*get_bridges)(struct fpga_region *), struct module *owner) { struct fpga_region_info info = { 0 }; info.mgr = mgr; info.get_bridges = get_bridges; - return fpga_region_register_full(parent, &info); + return __fpga_region_register_full(parent, &info, owner); } -EXPORT_SYMBOL_GPL(fpga_region_register); +EXPORT_SYMBOL_GPL(__fpga_region_register); /** * fpga_region_unregister - unregister an FPGA region diff --git a/include/linux/fpga/fpga-region.h b/include/linux/fpga/fpga-region.h index 9d4d32909340..5fbc05fe70a6 100644 --- a/include/linux/fpga/fpga-region.h +++ b/include/linux/fpga/fpga-region.h @@ -36,6 +36,7 @@ struct fpga_region_info { * @mgr: FPGA manager * @info: FPGA image info * @compat_id: FPGA region id for compatibility check. + * @ops_owner: module containing the get_bridges function * @priv: private data * @get_bridges: optional function to get bridges to a list */ @@ -46,6 +47,7 @@ struct fpga_region { struct fpga_manager *mgr; struct fpga_image_info *info; struct fpga_compat_id *compat_id; + struct module *ops_owner; void *priv; int (*get_bridges)(struct fpga_region *region); }; @@ -58,12 +60,17 @@ fpga_region_class_find(struct device *start, const void *data, int fpga_region_program_fpga(struct fpga_region *region); +#define fpga_region_register_full(parent, info) \ + __fpga_region_register_full(parent, info, THIS_MODULE) struct fpga_region * -fpga_region_register_full(struct device *parent, const struct fpga_region_info *info); +__fpga_region_register_full(struct device *parent, const struct fpga_region_info *info, + struct module *owner); +#define fpga_region_register(parent, mgr, get_bridges) \ + __fpga_region_register(parent, mgr, get_bridges, THIS_MODULE) struct fpga_region * -fpga_region_register(struct device *parent, struct fpga_manager *mgr, - int (*get_bridges)(struct fpga_region *)); +__fpga_region_register(struct device *parent, struct fpga_manager *mgr, + int (*get_bridges)(struct fpga_region *), struct module *owner); void fpga_region_unregister(struct fpga_region *region); #endif /* _FPGA_REGION_H */ base-commit: 5d04660b29fb31e88e945c8b3eb658976824d0fa -- 2.44.0