Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp4388034pxf; Tue, 30 Mar 2021 06:47:36 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy7ciecGA8wDpD1ym/Ovz06d9/NTAzSZaiBBIrfGmpmXEAqtLcIjt0OSep5gh/5JcQQIjsO X-Received: by 2002:a05:6402:17e9:: with SMTP id t9mr33708346edy.211.1617112055832; Tue, 30 Mar 2021 06:47:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617112055; cv=none; d=google.com; s=arc-20160816; b=oQRiAJ4sNY7x7X1GVYl/lU/YmOcPpBYiukNJLZE2fqhCZYZHpYypvKALJZV3TyeDtz VJA78B4sElumCuT3K8um+hx15JUHfd4pwHzFgPs6/8Fw4s0ysRqcZirNye8VygNnQmm+ UeTUx8h9rPlXuZumoxoLwuH+imEVYbf8BCwJi7+hvK+BV4FI2zM6czmsKUS4q9caX4ff yP03u1u4dJoSAdQd09WML4RID1e4UB3/wkBRZijRKE8W1mHAZ96AhJW6vE5Uc4sXK3cH n1ybhLwkRFFhnU85dxptv+kwRNPJuKd7nS5VfMo2EKjqFfUI2cqzcfSlHK8WK++r2QNC TrTw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-language:content-transfer-encoding :in-reply-to:mime-version:user-agent:date:message-id:from:references :cc:to:subject:dkim-signature; bh=TvixdV6Zx7/AWSYPQxJ6x7+mxKn8oXSTnyruFM7nqLc=; b=sgVCB2sJgnzrhfwTmmLhpgGa0e3nxpbWxejXlvS6ALU2HiQ1qRs0/ApGZvN6KFdM6d IXMj6Nnm9WaJ+GVIzIloH034N9EZvnHvfj7dCPilZf3tKn6AaeW8lhjtZVPIBlMTSu2p jbq7u/glrHrfdVzQl++eXU0PD1Aix/FvQzbTCJedUaKRz7OMsPQ6nxUCY5kMWiybCFf1 dwKxBPZ61/5jKWqqMvysPRMBwM8YFQ92OnfY6hnaZzvKKIbwGgsrOMzmkuWt+bWc5UNl IfQeJGEp44oHoFiWL966PUe6QdOoaxHASyG+tPqJ9Nt5sCqUzWx0W6yRlhqr+fGGQy6n 3USA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=La+Nj0m3; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id p8si15612639edm.44.2021.03.30.06.47.10; Tue, 30 Mar 2021 06:47:35 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=La+Nj0m3; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231910AbhC3Npn (ORCPT + 99 others); Tue, 30 Mar 2021 09:45:43 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:57905 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231574AbhC3NpR (ORCPT ); Tue, 30 Mar 2021 09:45:17 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1617111916; 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=TvixdV6Zx7/AWSYPQxJ6x7+mxKn8oXSTnyruFM7nqLc=; b=La+Nj0m3eYrpEmUzLAmthvur7RgDbqtUw13NFFhNx5MjuZ0hLnFbFeIB5Uy5Dukv/ogvWz EBv2p5b99SbMDF32poDOPNcIj/QPL5r6wiv2Ybp2RL7Bjdg1ZPC9UELbij16nrbAVAKLPH ga2S+1wDqvxtGtdHo/IYlzwKdkAtkz8= Received: from mail-qk1-f198.google.com (mail-qk1-f198.google.com [209.85.222.198]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-288-0KQpFX-RNWylaWlrF6Z8Pw-1; Tue, 30 Mar 2021 09:45:14 -0400 X-MC-Unique: 0KQpFX-RNWylaWlrF6Z8Pw-1 Received: by mail-qk1-f198.google.com with SMTP id b127so14472462qkf.19 for ; Tue, 30 Mar 2021 06:45:14 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding :content-language; bh=TvixdV6Zx7/AWSYPQxJ6x7+mxKn8oXSTnyruFM7nqLc=; b=W3fhhLX5wC0bA90p7jORRiQOI71l7OyciAmnE49ZkBqO8dX6a45TyXErEi/H9Kgnnp tpzpQXYe5OeMOLC36SlTmxSFrfz+PGJE3Ae/ZpoMMl1yWHFtzgULKQXz9tV3jhICUP6J W3X2dnrRFWuI+B0UrDed80ZVspQz2XhjcfXZ36l0390R1zmMBzxAfcbWaEnLZ+WGU41K NmONIGeNfarKycnSV2bNji9OJZ/c4/jjzqDXJ9u/3Au+V4j0Vyjs7gyw6IOfWNclNA5I tQjWJMtkE7epRf5dWPQXbwZrJ7W0tsTA8TZo9eB0AcI/WsqzYz64u83ffSNkvEUPssh4 CvaA== X-Gm-Message-State: AOAM532YIm+814lhvFEwLNX+seljEEo8wc4mdGNgKcWh32LFxZ9TbGeV xD+er76fDyxVvTTHDB76EGKcumhbNS5lgxRYd+xlrEEKbT1OU/Ug8A+IsygRebWsxHz3R509A8p 24M78aGX+kNLr7bWsX9+ttr9a X-Received: by 2002:a05:6214:21a5:: with SMTP id t5mr30882341qvc.23.1617111914305; Tue, 30 Mar 2021 06:45:14 -0700 (PDT) X-Received: by 2002:a05:6214:21a5:: with SMTP id t5mr30882305qvc.23.1617111914067; Tue, 30 Mar 2021 06:45:14 -0700 (PDT) Received: from trix.remote.csb (075-142-250-213.res.spectrum.com. [75.142.250.213]) by smtp.gmail.com with ESMTPSA id g11sm15745881qkk.5.2021.03.30.06.45.12 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 30 Mar 2021 06:45:13 -0700 (PDT) Subject: Re: [PATCH V4 XRT Alveo 06/20] fpga: xrt: char dev node helper functions To: Lizhi Hou , linux-kernel@vger.kernel.org Cc: linux-fpga@vger.kernel.org, maxz@xilinx.com, sonal.santan@xilinx.com, yliu@xilinx.com, michal.simek@xilinx.com, stefanos@xilinx.com, devicetree@vger.kernel.org, mdf@kernel.org, robh@kernel.org, Max Zhen References: <20210324052947.27889-1-lizhi.hou@xilinx.com> <20210324052947.27889-7-lizhi.hou@xilinx.com> From: Tom Rix Message-ID: <755d73b9-1e23-c2e9-1502-15df14b9ed35@redhat.com> Date: Tue, 30 Mar 2021 06:45:11 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.8.0 MIME-Version: 1.0 In-Reply-To: <20210324052947.27889-7-lizhi.hou@xilinx.com> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Content-Language: en-US Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org It is unclear from the changelog if this new patch was split from an existing patch or new content. the file ops seem to come from mgmnt/main.c, which call what could be file ops here.  why is this complicated redirection needed ? On 3/23/21 10:29 PM, Lizhi Hou wrote: > Helper functions for char device node creation / removal for platform > drivers. This is part of platform driver infrastructure. > > Signed-off-by: Sonal Santan > Signed-off-by: Max Zhen > Signed-off-by: Lizhi Hou > --- > drivers/fpga/xrt/lib/cdev.c | 232 ++++++++++++++++++++++++++++++++++++ > 1 file changed, 232 insertions(+) > create mode 100644 drivers/fpga/xrt/lib/cdev.c > > diff --git a/drivers/fpga/xrt/lib/cdev.c b/drivers/fpga/xrt/lib/cdev.c > new file mode 100644 > index 000000000000..38efd24b6e10 > --- /dev/null > +++ b/drivers/fpga/xrt/lib/cdev.c > @@ -0,0 +1,232 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Xilinx Alveo FPGA device node helper functions. > + * > + * Copyright (C) 2020-2021 Xilinx, Inc. > + * > + * Authors: > + * Cheng Zhen > + */ > + > +#include "xleaf.h" > + > +extern struct class *xrt_class; > + > +#define XRT_CDEV_DIR "xfpga" maybe "xrt_fpga" or just "xrt" > +#define INODE2PDATA(inode) \ > + container_of((inode)->i_cdev, struct xrt_subdev_platdata, xsp_cdev) > +#define INODE2PDEV(inode) \ > + to_platform_device(kobj_to_dev((inode)->i_cdev->kobj.parent)) > +#define CDEV_NAME(sysdev) (strchr((sysdev)->kobj.name, '!') + 1) > + > +/* Allow it to be accessed from cdev. */ > +static void xleaf_devnode_allowed(struct platform_device *pdev) > +{ > + struct xrt_subdev_platdata *pdata = DEV_PDATA(pdev); > + > + /* Allow new opens. */ > + mutex_lock(&pdata->xsp_devnode_lock); > + pdata->xsp_devnode_online = true; > + mutex_unlock(&pdata->xsp_devnode_lock); > +} > + > +/* Turn off access from cdev and wait for all existing user to go away. */ > +static int xleaf_devnode_disallowed(struct platform_device *pdev) > +{ > + int ret = 0; > + struct xrt_subdev_platdata *pdata = DEV_PDATA(pdev); > + > + mutex_lock(&pdata->xsp_devnode_lock); > + > + /* Prevent new opens. */ > + pdata->xsp_devnode_online = false; > + /* Wait for existing user to close. */ > + while (!ret && pdata->xsp_devnode_ref) { > + int rc; > + > + mutex_unlock(&pdata->xsp_devnode_lock); > + rc = wait_for_completion_killable(&pdata->xsp_devnode_comp); > + mutex_lock(&pdata->xsp_devnode_lock); > + > + if (rc == -ERESTARTSYS) { > + /* Restore online state. */ > + pdata->xsp_devnode_online = true; > + xrt_err(pdev, "%s is in use, ref=%d", > + CDEV_NAME(pdata->xsp_sysdev), > + pdata->xsp_devnode_ref); > + ret = -EBUSY; > + } > + } > + > + mutex_unlock(&pdata->xsp_devnode_lock); > + > + return ret; > +} > + > +static struct platform_device * > +__xleaf_devnode_open(struct inode *inode, bool excl) > +{ > + struct xrt_subdev_platdata *pdata = INODE2PDATA(inode); > + struct platform_device *pdev = INODE2PDEV(inode); > + bool opened = false; > + > + mutex_lock(&pdata->xsp_devnode_lock); > + > + if (pdata->xsp_devnode_online) { > + if (excl && pdata->xsp_devnode_ref) { > + xrt_err(pdev, "%s has already been opened exclusively", > + CDEV_NAME(pdata->xsp_sysdev)); > + } else if (!excl && pdata->xsp_devnode_excl) { > + xrt_err(pdev, "%s has been opened exclusively", > + CDEV_NAME(pdata->xsp_sysdev)); > + } else { > + pdata->xsp_devnode_ref++; > + pdata->xsp_devnode_excl = excl; > + opened = true; > + xrt_info(pdev, "opened %s, ref=%d", > + CDEV_NAME(pdata->xsp_sysdev), > + pdata->xsp_devnode_ref); > + } > + } else { > + xrt_err(pdev, "%s is offline", CDEV_NAME(pdata->xsp_sysdev)); > + } > + > + mutex_unlock(&pdata->xsp_devnode_lock); > + > + pdev = opened ? pdev : NULL; > + return pdev; > +} > + > +struct platform_device * > +xleaf_devnode_open_excl(struct inode *inode) > +{ > + return __xleaf_devnode_open(inode, true); > +} This function is unused, remove. > + > +struct platform_device * > +xleaf_devnode_open(struct inode *inode) > +{ > + return __xleaf_devnode_open(inode, false); > +} > +EXPORT_SYMBOL_GPL(xleaf_devnode_open); does this really need to be exported ? > + > +void xleaf_devnode_close(struct inode *inode) > +{ > + struct xrt_subdev_platdata *pdata = INODE2PDATA(inode); > + struct platform_device *pdev = INODE2PDEV(inode); > + bool notify = false; > + > + mutex_lock(&pdata->xsp_devnode_lock); > + > + WARN_ON(pdata->xsp_devnode_ref == 0); > + pdata->xsp_devnode_ref--; > + if (pdata->xsp_devnode_ref == 0) { > + pdata->xsp_devnode_excl = false; > + notify = true; > + } > + if (notify) { > + xrt_info(pdev, "closed %s, ref=%d", > + CDEV_NAME(pdata->xsp_sysdev), pdata->xsp_devnode_ref); xsp_devnode_ref will always be 0, so no need to report it. > + } else { > + xrt_info(pdev, "closed %s, notifying waiter", > + CDEV_NAME(pdata->xsp_sysdev)); > + } > + > + mutex_unlock(&pdata->xsp_devnode_lock); > + > + if (notify) > + complete(&pdata->xsp_devnode_comp); > +} > +EXPORT_SYMBOL_GPL(xleaf_devnode_close); > + > +static inline enum xrt_subdev_file_mode > +devnode_mode(struct xrt_subdev_drvdata *drvdata) > +{ > + return drvdata->xsd_file_ops.xsf_mode; > +} > + > +int xleaf_devnode_create(struct platform_device *pdev, const char *file_name, > + const char *inst_name) > +{ > + struct xrt_subdev_drvdata *drvdata = DEV_DRVDATA(pdev); > + struct xrt_subdev_file_ops *fops = &drvdata->xsd_file_ops; > + struct xrt_subdev_platdata *pdata = DEV_PDATA(pdev); > + struct cdev *cdevp; > + struct device *sysdev; > + int ret = 0; > + char fname[256]; > + > + mutex_init(&pdata->xsp_devnode_lock); > + init_completion(&pdata->xsp_devnode_comp); > + > + cdevp = &DEV_PDATA(pdev)->xsp_cdev; > + cdev_init(cdevp, &fops->xsf_ops); > + cdevp->owner = fops->xsf_ops.owner; > + cdevp->dev = MKDEV(MAJOR(fops->xsf_dev_t), pdev->id); > + > + /* > + * Set pdev as parent of cdev so that when pdev (and its platform > + * data) will not be freed when cdev is not freed. > + */ > + cdev_set_parent(cdevp, &DEV(pdev)->kobj); > + > + ret = cdev_add(cdevp, cdevp->dev, 1); > + if (ret) { > + xrt_err(pdev, "failed to add cdev: %d", ret); > + goto failed; > + } > + if (!file_name) > + file_name = pdev->name; > + if (!inst_name) { > + if (devnode_mode(drvdata) == XRT_SUBDEV_FILE_MULTI_INST) { > + snprintf(fname, sizeof(fname), "%s/%s/%s.%u", > + XRT_CDEV_DIR, DEV_PDATA(pdev)->xsp_root_name, > + file_name, pdev->id); > + } else { > + snprintf(fname, sizeof(fname), "%s/%s/%s", > + XRT_CDEV_DIR, DEV_PDATA(pdev)->xsp_root_name, > + file_name); > + } > + } else { > + snprintf(fname, sizeof(fname), "%s/%s/%s.%s", XRT_CDEV_DIR, > + DEV_PDATA(pdev)->xsp_root_name, file_name, inst_name); > + } > + sysdev = device_create(xrt_class, NULL, cdevp->dev, NULL, "%s", fname); > + if (IS_ERR(sysdev)) { > + ret = PTR_ERR(sysdev); > + xrt_err(pdev, "failed to create device node: %d", ret); > + goto failed_cdev_add; > + } > + pdata->xsp_sysdev = sysdev; > + > + xleaf_devnode_allowed(pdev); > + > + xrt_info(pdev, "created (%d, %d): /dev/%s", > + MAJOR(cdevp->dev), pdev->id, fname); > + return 0; > + > +failed_cdev_add: > + cdev_del(cdevp); > +failed: > + cdevp->owner = NULL; > + return ret; > +} > + > +int xleaf_devnode_destroy(struct platform_device *pdev) > +{ > + struct xrt_subdev_platdata *pdata = DEV_PDATA(pdev); > + struct cdev *cdevp = &pdata->xsp_cdev; > + dev_t dev = cdevp->dev; > + int rc; > + > + rc = xleaf_devnode_disallowed(pdev); > + if (rc) > + return rc; Failure of one leaf to be destroyed is not handled well. could a able to destroy check be done over the whole group ? Tom > + > + xrt_info(pdev, "removed (%d, %d): /dev/%s/%s", MAJOR(dev), MINOR(dev), > + XRT_CDEV_DIR, CDEV_NAME(pdata->xsp_sysdev)); > + device_destroy(xrt_class, cdevp->dev); > + pdata->xsp_sysdev = NULL; > + cdev_del(cdevp); > + return 0; > +}