linux-fpga.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Max Zhen <max.zhen@xilinx.com>
To: Tom Rix <trix@redhat.com>, Lizhi Hou <lizhi.hou@xilinx.com>,
	<linux-kernel@vger.kernel.org>
Cc: Lizhi Hou <lizhih@xilinx.com>, <linux-fpga@vger.kernel.org>,
	<sonal.santan@xilinx.com>, <michal.simek@xilinx.com>,
	<stefanos@xilinx.com>, <devicetree@vger.kernel.org>,
	<mdf@kernel.org>, <robh@kernel.org>,
	Max Zhen <max.zhen@xilinx.com>
Subject: Re: [PATCH V3 XRT Alveo 05/18] fpga: xrt: group platform driver
Date: Fri, 26 Feb 2021 13:57:22 -0800	[thread overview]
Message-ID: <4eb879cf-c2c3-5f85-79a4-73d02a9fa523@xilinx.com> (raw)
In-Reply-To: <ebf64992-4067-18c2-661d-6c3a3b64c7c0@redhat.com>

Hi Tom,


On 2/22/21 10:50 AM, Tom Rix wrote:
> CAUTION: This message has originated from an External Source. Please use proper judgment and caution when opening attachments, clicking links, or responding to this email.
>
>
> On 2/17/21 10:40 PM, Lizhi Hou wrote:
>> group driver that manages life cycle of a bunch of leaf driver instances
>> and bridges them with root.
>>
>> Signed-off-by: Sonal Santan <sonal.santan@xilinx.com>
>> Signed-off-by: Max Zhen <max.zhen@xilinx.com>
>> Signed-off-by: Lizhi Hou <lizhih@xilinx.com>
>> ---
>>   drivers/fpga/xrt/include/group.h |  27 ++++
>>   drivers/fpga/xrt/lib/group.c     | 265 +++++++++++++++++++++++++++++++
>>   2 files changed, 292 insertions(+)
>>   create mode 100644 drivers/fpga/xrt/include/group.h
>>   create mode 100644 drivers/fpga/xrt/lib/group.c
>>
>> diff --git a/drivers/fpga/xrt/include/group.h b/drivers/fpga/xrt/include/group.h
>> new file mode 100644
>> index 000000000000..1874cdd5120d
>> --- /dev/null
>> +++ b/drivers/fpga/xrt/include/group.h
>> @@ -0,0 +1,27 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Header file for Xilinx Runtime (XRT) driver
> A bit too generic, please add a description or remove.


Will remove.


>> + *
>> + * Copyright (C) 2020-2021 Xilinx, Inc.
>> + *
>> + * Authors:
>> + *   Cheng Zhen <maxz@xilinx.com>
>> + */
>> +
>> +#ifndef _XRT_GROUP_H_
>> +#define _XRT_GROUP_H_
>> +
>> +#include "xleaf.h"
> This is patch 6, consider comments on patch 4.


Will move this header to other patch.


>> +
>> +/*
>> + * Group driver IOCTL calls.
> Are these really ioctl calls?
>
> Seems more like messages between nodes in a tree.
>
> Consider changing to better jagon, maybe ioctl -> msg


You're right. They are not really ioctl calls. They are just calls b/w 
leaf nodes. I changed to leaf calls/commands.


>
>> + */
>> +enum xrt_group_ioctl_cmd {
>> +     XRT_GROUP_GET_LEAF = XRT_XLEAF_CUSTOM_BASE, /* See comments in xleaf.h */
> XRT_LEAF_CUSTOM_BASE is a #define, while these are enums. To be consistent, the XRT_LEAF_CUSTOM_BASE should be an enum in xleaf, you can initialize it to 64 there.


Will fix.


>> +     XRT_GROUP_PUT_LEAF,
>> +     XRT_GROUP_INIT_CHILDREN,
>> +     XRT_GROUP_FINI_CHILDREN,
>> +     XRT_GROUP_TRIGGER_EVENT,
>> +};
>> +
>> +#endif       /* _XRT_GROUP_H_ */
>> diff --git a/drivers/fpga/xrt/lib/group.c b/drivers/fpga/xrt/lib/group.c
>> new file mode 100644
>> index 000000000000..6ba56eea479b
>> --- /dev/null
>> +++ b/drivers/fpga/xrt/lib/group.c
>> @@ -0,0 +1,265 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Xilinx Alveo FPGA Group Driver
>> + *
>> + * Copyright (C) 2020-2021 Xilinx, Inc.
>> + *
>> + * Authors:
>> + *   Cheng Zhen <maxz@xilinx.com>
>> + */
>> +
>> +#include <linux/mod_devicetable.h>
>> +#include <linux/platform_device.h>
>> +#include "xleaf.h"
>> +#include "subdev_pool.h"
>> +#include "group.h"
>> +#include "metadata.h"
>> +#include "main.h"
>> +
>> +#define XRT_GRP "xrt_group"
>> +
>> +struct xrt_group {
>> +     struct platform_device *pdev;
>> +     struct xrt_subdev_pool leaves;
>> +     bool leaves_created;
>> +     struct mutex lock; /* lock for group */
>> +};
>> +
>> +static int xrt_grp_root_cb(struct device *dev, void *parg,
>> +                        u32 cmd, void *arg)
> could 'cmd' be some enum type ?


Will fix.


>> +{
>> +     int rc;
>> +     struct platform_device *pdev =
>> +             container_of(dev, struct platform_device, dev);
>> +     struct xrt_group *xg = (struct xrt_group *)parg;
>> +
>> +     switch (cmd) {
>> +     case XRT_ROOT_GET_LEAF_HOLDERS: {
>> +             struct xrt_root_ioctl_get_holders *holders =
>> +                     (struct xrt_root_ioctl_get_holders *)arg;
>> +             rc = xrt_subdev_pool_get_holders(&xg->leaves,
>> +                                              holders->xpigh_pdev,
>> +                                              holders->xpigh_holder_buf,
>> +                                              holders->xpigh_holder_buf_len);
>> +             break;
>> +     }
>> +     default:
>> +             /* Forward parent call to root. */
>> +             rc = xrt_subdev_root_request(pdev, cmd, arg);
>> +             break;
>> +     }
>> +
>> +     return rc;
>> +}
>> +
>> +static int xrt_grp_create_leaves(struct xrt_group *xg)
>> +{
>> +     struct xrt_subdev_platdata *pdata = DEV_PDATA(xg->pdev);
>> +     enum xrt_subdev_id did;
>> +     struct xrt_subdev_endpoints *eps = NULL;
>> +     int ep_count = 0, i, ret = 0, failed = 0;
>> +     unsigned long mlen;
>> +     char *dtb, *grp_dtb = NULL;
>> +     const char *ep_name;
>> +
>> +     mutex_lock(&xg->lock);
>> +
>> +     if (xg->leaves_created) {
>> +             mutex_unlock(&xg->lock);
> This happens should be programming error, so print out some error message


The root driver does not remember which group has created leaves or not. 
It'll just blindly make the call. The group driver itself should 
remember and tell the root that it's done already or not. So, this is 
not considered as an error.


>> +             return -EEXIST;
>> +     }
>> +
>> +     xrt_info(xg->pdev, "bringing up leaves...");
>> +
>> +     /* Create all leaves based on dtb. */
>> +     if (!pdata)
>> +             goto bail;
> move to above the lock and fail with something like -EINVAL


Will fix.


>> +
>> +     mlen = xrt_md_size(DEV(xg->pdev), pdata->xsp_dtb);
>> +     if (mlen == XRT_MD_INVALID_LENGTH) {
>> +             xrt_err(xg->pdev, "invalid dtb, len %ld", mlen);
>> +             goto bail;
>> +     }
>> +
>> +     grp_dtb = vmalloc(mlen);
>> +     if (!grp_dtb)
>> +             goto bail;
> failed is only set in the loop. This is an unreported -ENOMEM


Will fix.


>> +
>> +     memcpy(grp_dtb, pdata->xsp_dtb, mlen);
>> +     for (did = 0; did < XRT_SUBDEV_NUM;) {
> why isn't the did incremented ?


This is not a bug, but I will fix it by rewriting this function so that 
it'll be easier to follow (hopefully :-)).


>> +             eps = eps ? eps + 1 : xrt_drv_get_endpoints(did);
> this assumes the enpoints are in an array and accessed serially.
>
> this is fragile.
>
> convert to using just the xrt_drv_get_endpoints() call


It does not seem to be fragile? The endpoint data structure is private 
data structure so it has to be an array as defined. It's usage is just 
like an ID table as we have in other PCIE drivers.


>
>> +             if (!eps || !eps->xse_names) {
>> +                     did++;
>> +                     eps = NULL;
>> +                     continue;
>> +             }
>> +             ret = xrt_md_create(DEV(xg->pdev), &dtb);
>> +             if (ret) {
>> +                     xrt_err(xg->pdev, "create md failed, drv %s",
>> +                             xrt_drv_name(did));
>> +                     failed++;
> failed but no cleanup of earier successes


The leaves already created will still be there until the group is 
destroyed. This is not considered as fatal error.


>> +                     continue;
>> +             }
>> +             for (i = 0; eps->xse_names[i].ep_name ||
> this assumes that xse_names[] always has a guard.
>
> why not use xse_min_ep ?


xse_min_ep is to tell caller the minimum number of end points needs to 
be collected before instantiate the leaf driver. it does not indicate 
exactly how many end points this leaf can handle (it might be able to 
handle more). So, the guard is necessary to tell caller total number of 
end points it can handle.


>
>> +                  eps->xse_names[i].regmap_name; i++) {
>> +                     ep_name = (char *)eps->xse_names[i].ep_name;
>> +                     if (!ep_name) {
>> +                             xrt_md_get_compatible_endpoint(DEV(xg->pdev),
>> +                                                            grp_dtb,
>> +                                                            eps->xse_names[i].regmap_name,
>> +                                                            &ep_name);
>> +                     }
>> +                     if (!ep_name)
>> +                             continue;
>> +
>> +                     ret = xrt_md_copy_endpoint(DEV(xg->pdev),
>> +                                                dtb, grp_dtb, ep_name,
>> +                                                (char *)eps->xse_names[i].regmap_name,
>> +                                                NULL);
>> +                     if (ret)
>> +                             continue;
>> +                     xrt_md_del_endpoint(DEV(xg->pdev), grp_dtb, ep_name,
>> +                                         (char *)eps->xse_names[i].regmap_name);
>> +                     ep_count++;
>> +             }
>> +             if (ep_count >= eps->xse_min_ep) {
> This only happens if all additions are successful.


This happens if the minimum number of end points has been collected. 
Anyway, the function is going to be rewritten.


>> +                     ret = xrt_subdev_pool_add(&xg->leaves, did,
>> +                                               xrt_grp_root_cb, xg, dtb);
>> +                     eps = NULL;
>> +                     if (ret < 0) {
>> +                             failed++;
>> +                             xrt_err(xg->pdev, "failed to create %s: %d",
>> +                                     xrt_drv_name(did), ret);
>> +                     }
>> +             } else if (ep_count > 0) {
>> +                     xrt_md_copy_all_endpoints(DEV(xg->pdev), grp_dtb, dtb);
>> +             }
>> +             vfree(dtb);
>> +             ep_count = 0;
>> +     }
>> +
>> +     xg->leaves_created = true;
> This is true even if some failed ?


Yes, this is OK. Some functionality may be missing if some leaves can be 
instantiated, but the group will be in leaves created state now.


>> +
>> +bail:
>> +     vfree(grp_dtb);
>> +     mutex_unlock(&xg->lock);
>> +
>> +     return failed == 0 ? 0 : -ECHILD;
>> +}
>> +
>> +static void xrt_grp_remove_leaves(struct xrt_group *xg)
>> +{
>> +     mutex_lock(&xg->lock);
>> +
>> +     if (!xg->leaves_created) {
>> +             mutex_unlock(&xg->lock);
>> +             return;
>> +     }
>> +
>> +     xrt_info(xg->pdev, "tearing down leaves...");
>> +     xrt_subdev_pool_fini(&xg->leaves);
> partial failure above and the subdev_pool is not created ?


It is still created, just not fully populated.


>> +     xg->leaves_created = false;
>> +
>> +     mutex_unlock(&xg->lock);
>> +}
>> +
>> +static int xrt_grp_probe(struct platform_device *pdev)
>> +{
>> +     struct xrt_group *xg;
>> +
>> +     xrt_info(pdev, "probing...");
>> +
>> +     xg = devm_kzalloc(&pdev->dev, sizeof(*xg), GFP_KERNEL);
>> +     if (!xg)
>> +             return -ENOMEM;
>> +
>> +     xg->pdev = pdev;
>> +     mutex_init(&xg->lock);
>> +     xrt_subdev_pool_init(DEV(pdev), &xg->leaves);
>> +     platform_set_drvdata(pdev, xg);
>> +
>> +     return 0;
>> +}
>> +
>> +static int xrt_grp_remove(struct platform_device *pdev)
>> +{
>> +     struct xrt_group *xg = platform_get_drvdata(pdev);
>> +
>> +     xrt_info(pdev, "leaving...");
>> +     xrt_grp_remove_leaves(xg);
> lock ?


xrt_grp_remove_leaves() takes lock internally.


Thanks,

Max

>
> Tom
>
>> +     return 0;
>> +}
>> +
>> +static int xrt_grp_ioctl(struct platform_device *pdev, u32 cmd, void *arg)
>> +{
>> +     int rc = 0;
>> +     struct xrt_group *xg = platform_get_drvdata(pdev);
>> +
>> +     switch (cmd) {
>> +     case XRT_XLEAF_EVENT:
>> +             /* Simply forward to every child. */
>> +             xrt_subdev_pool_handle_event(&xg->leaves,
>> +                                          (struct xrt_event *)arg);
>> +             break;
>> +     case XRT_GROUP_GET_LEAF: {
>> +             struct xrt_root_ioctl_get_leaf *get_leaf =
>> +                     (struct xrt_root_ioctl_get_leaf *)arg;
>> +
>> +             rc = xrt_subdev_pool_get(&xg->leaves, get_leaf->xpigl_match_cb,
>> +                                      get_leaf->xpigl_match_arg,
>> +                                      DEV(get_leaf->xpigl_pdev),
>> +                                      &get_leaf->xpigl_leaf);
>> +             break;
>> +     }
>> +     case XRT_GROUP_PUT_LEAF: {
>> +             struct xrt_root_ioctl_put_leaf *put_leaf =
>> +                     (struct xrt_root_ioctl_put_leaf *)arg;
>> +
>> +             rc = xrt_subdev_pool_put(&xg->leaves, put_leaf->xpipl_leaf,
>> +                                      DEV(put_leaf->xpipl_pdev));
>> +             break;
>> +     }
>> +     case XRT_GROUP_INIT_CHILDREN:
>> +             rc = xrt_grp_create_leaves(xg);
>> +             break;
>> +     case XRT_GROUP_FINI_CHILDREN:
>> +             xrt_grp_remove_leaves(xg);
>> +             break;
>> +     case XRT_GROUP_TRIGGER_EVENT:
>> +             xrt_subdev_pool_trigger_event(&xg->leaves, (enum xrt_events)(uintptr_t)arg);
>> +             break;
>> +     default:
>> +             xrt_err(pdev, "unknown IOCTL cmd %d", cmd);
>> +             rc = -EINVAL;
>> +             break;
>> +     }
>> +     return rc;
>> +}
>> +
>> +static struct xrt_subdev_drvdata xrt_grp_data = {
>> +     .xsd_dev_ops = {
>> +             .xsd_ioctl = xrt_grp_ioctl,
>> +     },
>> +};
>> +
>> +static const struct platform_device_id xrt_grp_id_table[] = {
>> +     { XRT_GRP, (kernel_ulong_t)&xrt_grp_data },
>> +     { },
>> +};
>> +
>> +static struct platform_driver xrt_group_driver = {
>> +     .driver = {
>> +             .name    = XRT_GRP,
>> +     },
>> +     .probe   = xrt_grp_probe,
>> +     .remove  = xrt_grp_remove,
>> +     .id_table = xrt_grp_id_table,
>> +};
>> +
>> +void group_leaf_init_fini(bool init)
>> +{
>> +     if (init)
>> +             xleaf_register_driver(XRT_SUBDEV_GRP, &xrt_group_driver, NULL);
>> +     else
>> +             xleaf_unregister_driver(XRT_SUBDEV_GRP);
>> +}

  reply	other threads:[~2021-02-26 21:58 UTC|newest]

Thread overview: 86+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-18  6:40 [PATCH V3 XRT Alveo 00/18] XRT Alveo driver overview Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 01/18] Documentation: fpga: Add a document describing XRT Alveo drivers Lizhi Hou
2021-02-19 22:26   ` Tom Rix
2021-03-01  6:48     ` Sonal Santan
2021-03-06 17:19       ` Moritz Fischer
2021-03-08 20:12         ` Sonal Santan
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 02/18] fpga: xrt: driver metadata helper functions Lizhi Hou
2021-02-20 17:07   ` Tom Rix
2021-02-23  6:05     ` Lizhi Hou
2021-02-23  1:23   ` Fernando Pacheco
2021-02-25 20:27     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 03/18] fpga: xrt: xclbin file " Lizhi Hou
2021-02-21 17:12   ` Tom Rix
2021-02-21 18:33     ` Moritz Fischer
2021-03-06  1:13       ` Lizhi Hou
2021-02-26 21:23     ` Lizhi Hou
2021-02-28 16:54       ` Tom Rix
2021-03-02  0:25         ` Lizhi Hou
2021-03-02 15:14           ` Moritz Fischer
2021-03-04 18:53             ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 04/18] fpga: xrt: xrt-lib platform driver manager Lizhi Hou
2021-02-21 20:39   ` Moritz Fischer
2021-03-01 20:34     ` Max Zhen
2021-02-22 15:05   ` Tom Rix
2021-02-23  3:35     ` Moritz Fischer
2021-03-03 17:20     ` Max Zhen
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 05/18] fpga: xrt: group platform driver Lizhi Hou
2021-02-22 18:50   ` Tom Rix
2021-02-26 21:57     ` Max Zhen [this message]
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 06/18] fpga: xrt: platform driver infrastructure Lizhi Hou
2021-02-25 21:59   ` Tom Rix
     [not found]     ` <13e9a311-2d04-ba65-3ed2-f9f1834c37de@xilinx.com>
2021-03-08 20:36       ` Max Zhen
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 07/18] fpga: xrt: management physical function driver (root) Lizhi Hou
2021-02-26 15:01   ` Tom Rix
2021-02-26 17:56     ` Moritz Fischer
2021-03-16 20:29     ` Max Zhen
2021-03-17 21:08       ` Tom Rix
2021-03-18  0:44         ` Max Zhen
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 08/18] fpga: xrt: main platform driver for management function device Lizhi Hou
2021-02-26 17:22   ` Tom Rix
2021-03-16 21:23     ` Lizhi Hou
2021-03-17 21:12       ` Tom Rix
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 09/18] fpga: xrt: fpga-mgr and region implementation for xclbin download Lizhi Hou
2021-02-28 16:36   ` Tom Rix
2021-03-04 17:50     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 10/18] fpga: xrt: VSEC platform driver Lizhi Hou
2021-03-01 19:01   ` Tom Rix
2021-03-05 19:58     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 11/18] fpga: xrt: UCS " Lizhi Hou
2021-03-02 16:09   ` Tom Rix
2021-03-10 20:24     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 12/18] fpga: xrt: ICAP " Lizhi Hou
2021-02-21 20:24   ` Moritz Fischer
2021-03-02 18:26     ` Lizhi Hou
2021-03-03 15:12   ` Tom Rix
2021-03-17 20:56     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 13/18] fpga: xrt: devctl " Lizhi Hou
2021-03-04 13:39   ` Tom Rix
2021-03-16 23:54     ` Lizhi Hou
2021-03-17 21:16       ` Tom Rix
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 14/18] fpga: xrt: clock " Lizhi Hou
2021-03-05 15:23   ` Tom Rix
2021-03-11  0:12     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 15/18] fpga: xrt: clock frequence counter " Lizhi Hou
2021-03-06 15:25   ` Tom Rix
2021-03-12 23:43     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 16/18] fpga: xrt: DDR calibration " Lizhi Hou
2021-02-21 20:21   ` Moritz Fischer
2021-03-06 15:34   ` Tom Rix
2021-03-13  0:45     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 17/18] fpga: xrt: partition isolation " Lizhi Hou
2021-02-21 20:36   ` Moritz Fischer
2021-03-16 20:38     ` Lizhi Hou
2021-03-06 15:54   ` Tom Rix
2021-03-13  6:53     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 18/18] fpga: xrt: Kconfig and Makefile updates for XRT drivers Lizhi Hou
2021-02-18  9:02   ` kernel test robot
2021-02-21 14:57   ` Tom Rix
2021-02-21 18:39     ` Moritz Fischer
2021-02-28 20:52       ` Sonal Santan
2021-02-18 13:52 ` [PATCH V3 XRT Alveo 00/18] XRT Alveo driver overview Tom Rix
2021-02-19  5:15   ` Lizhi Hou
2021-02-21 20:43 ` Moritz Fischer
2021-03-01 18:29   ` Lizhi Hou
2021-03-03  6:49   ` Joe Perches
2021-03-03 23:15     ` Moritz Fischer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4eb879cf-c2c3-5f85-79a4-73d02a9fa523@xilinx.com \
    --to=max.zhen@xilinx.com \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-fpga@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lizhi.hou@xilinx.com \
    --cc=lizhih@xilinx.com \
    --cc=mdf@kernel.org \
    --cc=michal.simek@xilinx.com \
    --cc=robh@kernel.org \
    --cc=sonal.santan@xilinx.com \
    --cc=stefanos@xilinx.com \
    --cc=trix@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).