Re: [PATCH V3 XRT Alveo 04/18] fpga: xrt: xrt-lib platform driver manager

2021-03-03 Thread Max Zhen



On 2/22/21 7:05 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:

xrt-lib kernel module infrastructure code to register and manage all
leaf driver modules.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
  drivers/fpga/xrt/lib/main.c | 274 
  drivers/fpga/xrt/lib/main.h |  17 +++
  2 files changed, 291 insertions(+)
  create mode 100644 drivers/fpga/xrt/lib/main.c
  create mode 100644 drivers/fpga/xrt/lib/main.h

Not sure if 'main' is a good base name for something going into a lib.



These files are the main file for xrt-lib.ko. I'm not sure what name you 
prefer, but I've changed them to lib-drv.[c|h]. Let me know if you don't 
like them...






diff --git a/drivers/fpga/xrt/lib/main.c b/drivers/fpga/xrt/lib/main.c
new file mode 100644
index ..36fb62710843
--- /dev/null
+++ b/drivers/fpga/xrt/lib/main.c
@@ -0,0 +1,274 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for Xilinx Alveo FPGA Support
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *   Cheng Zhen 
+ */
+
+#include 
+#include "xleaf.h"
+#include "xroot.h"
+#include "main.h"
+
+#define XRT_IPLIB_MODULE_NAME"xrt-lib"
+#define XRT_IPLIB_MODULE_VERSION "4.0.0"
+#define XRT_MAX_DEVICE_NODES 128
+#define XRT_DRVNAME(drv) ((drv)->driver.name)
+
+/*
+ * Subdev driver is known by ID to others. We map the ID to it's

by it's ID



Sure.



+ * struct platform_driver, which contains it's binding name and driver/file 
ops.
+ * We also map it to the endpoint name in DTB as well, if it's different
+ * than the driver's binding name.
+ */
+struct xrt_drv_map {
+ struct list_head list;
+ enum xrt_subdev_id id;
+ struct platform_driver *drv;
+ struct xrt_subdev_endpoints *eps;
+ struct ida ida; /* manage driver instance and char dev minor */
+};
+
+static DEFINE_MUTEX(xrt_lib_lock); /* global lock protecting xrt_drv_maps list 
*/
+static LIST_HEAD(xrt_drv_maps);
+struct class *xrt_class;
+
+static inline struct xrt_subdev_drvdata *
+xrt_drv_map2drvdata(struct xrt_drv_map *map)
+{
+ return (struct xrt_subdev_drvdata *)map->drv->id_table[0].driver_data;
+}
+
+static struct xrt_drv_map *
+xrt_drv_find_map_by_id_nolock(enum xrt_subdev_id id)

name could be by convention

__xrt_drv_find_map_id



Sure.





+{
+ const struct list_head *ptr;
+
+ list_for_each(ptr, _drv_maps) {
+ struct xrt_drv_map *tmap = list_entry(ptr, struct xrt_drv_map, 
list);
+
+ if (tmap->id == id)
+ return tmap;
+ }
+ return NULL;
+}
+
+static struct xrt_drv_map *
+xrt_drv_find_map_by_id(enum xrt_subdev_id id)
+{
+ struct xrt_drv_map *map;
+
+ mutex_lock(_lib_lock);
+ map = xrt_drv_find_map_by_id_nolock(id);
+ mutex_unlock(_lib_lock);
+ /*
+  * map should remain valid even after lock is dropped since a registered

even after the lock



Sure.



+  * driver should only be unregistered when driver module is being 
unloaded,
+  * which means that the driver should not be used by then.
+  */
+ return map;
+}
+
+static int xrt_drv_register_driver(struct xrt_drv_map *map)
+{
+ struct xrt_subdev_drvdata *drvdata;
+ int rc = 0;
+ const char *drvname = XRT_DRVNAME(map->drv);
+
+ rc = platform_driver_register(map->drv);
+ if (rc) {
+ pr_err("register %s platform driver failed\n", drvname);
+ return rc;
+ }
+
+ drvdata = xrt_drv_map2drvdata(map);
+ if (drvdata) {
+ /* Initialize dev_t for char dev node. */
+ if (xleaf_devnode_enabled(drvdata)) {
+ rc = 
alloc_chrdev_region(>xsd_file_ops.xsf_dev_t, 0,
+  XRT_MAX_DEVICE_NODES, drvname);
+ if (rc) {
+ platform_driver_unregister(map->drv);
+ pr_err("failed to alloc dev minor for %s: %d\n", 
drvname, rc);
+ return rc;
+ }
+ } else {
+ drvdata->xsd_file_ops.xsf_dev_t = (dev_t)-1;
+ }
+ }
+
+ ida_init(>ida);
+
+ pr_info("%s registered successfully\n", drvname);
+
+ return 0;
+}
+
+static void xrt_drv_unregister_driver(struct xrt_drv_map *map)
+{
+ const char *drvname = XRT_DRVNAME(map->drv);
+ struct xrt_subdev_drvdata *drvdata;
+
+ ida_destroy(>ida);
+
+ drvdata = xrt_drv_map2drvdata(map);
+ if (drvdata && drvdata->xsd_file_ops.xsf_dev_t != (dev_t)-1) {
+ unregister_chrdev_region(drvdata->xsd_file_ops.xsf_dev_t,
+  XRT_MAX_DEVICE_NODES);
+ }
+
+ platform_driver_unregister(map->drv);
+
+ pr_info("%s 

Re: [PATCH V3 XRT Alveo 04/18] fpga: xrt: xrt-lib platform driver manager

2021-03-01 Thread Max Zhen

Hi Moritz,


On 2/21/21 12:39 PM, Moritz Fischer 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.


Lizhi,

On Wed, Feb 17, 2021 at 10:40:05PM -0800, Lizhi Hou wrote:

xrt-lib kernel module infrastructure code to register and manage all
leaf driver modules.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
  drivers/fpga/xrt/lib/main.c | 274 
  drivers/fpga/xrt/lib/main.h |  17 +++
  2 files changed, 291 insertions(+)
  create mode 100644 drivers/fpga/xrt/lib/main.c
  create mode 100644 drivers/fpga/xrt/lib/main.h

diff --git a/drivers/fpga/xrt/lib/main.c b/drivers/fpga/xrt/lib/main.c
new file mode 100644
index ..36fb62710843
--- /dev/null
+++ b/drivers/fpga/xrt/lib/main.c
@@ -0,0 +1,274 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for Xilinx Alveo FPGA Support
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *   Cheng Zhen 
+ */
+
+#include 
+#include "xleaf.h"
+#include "xroot.h"
+#include "main.h"
+
+#define XRT_IPLIB_MODULE_NAME"xrt-lib"
+#define XRT_IPLIB_MODULE_VERSION "4.0.0"
+#define XRT_MAX_DEVICE_NODES 128
+#define XRT_DRVNAME(drv) ((drv)->driver.name)
+
+/*
+ * Subdev driver is known by ID to others. We map the ID to it's
+ * struct platform_driver, which contains it's binding name and driver/file 
ops.
+ * We also map it to the endpoint name in DTB as well, if it's different
+ * than the driver's binding name.
+ */
+struct xrt_drv_map {
+ struct list_head list;
+ enum xrt_subdev_id id;
+ struct platform_driver *drv;
+ struct xrt_subdev_endpoints *eps;
+ struct ida ida; /* manage driver instance and char dev minor */
+};
+
+static DEFINE_MUTEX(xrt_lib_lock); /* global lock protecting xrt_drv_maps list 
*/
+static LIST_HEAD(xrt_drv_maps);
+struct class *xrt_class;
+
+static inline struct xrt_subdev_drvdata *
+xrt_drv_map2drvdata(struct xrt_drv_map *map)
+{
+ return (struct xrt_subdev_drvdata *)map->drv->id_table[0].driver_data;
+}
+
+static struct xrt_drv_map *
+xrt_drv_find_map_by_id_nolock(enum xrt_subdev_id id)
+{
+ const struct list_head *ptr;
+
+ list_for_each(ptr, _drv_maps) {
+ struct xrt_drv_map *tmap = list_entry(ptr, struct xrt_drv_map, 
list);

list_for_each_entry, maybe?



Yes!



+
+ if (tmap->id == id)
+ return tmap;
+ }
+ return NULL;
+}
+
+static struct xrt_drv_map *
+xrt_drv_find_map_by_id(enum xrt_subdev_id id)
+{
+ struct xrt_drv_map *map;
+
+ mutex_lock(_lib_lock);
+ map = xrt_drv_find_map_by_id_nolock(id);
+ mutex_unlock(_lib_lock);
+ /*
+  * map should remain valid even after lock is dropped since a registered
+  * driver should only be unregistered when driver module is being 
unloaded,
+  * which means that the driver should not be used by then.
+  */
+ return map;
+}
+
+static int xrt_drv_register_driver(struct xrt_drv_map *map)
+{
+ struct xrt_subdev_drvdata *drvdata;
+ int rc = 0;
+ const char *drvname = XRT_DRVNAME(map->drv);
+
+ rc = platform_driver_register(map->drv);
+ if (rc) {
+ pr_err("register %s platform driver failed\n", drvname);
+ return rc;
+ }
+
+ drvdata = xrt_drv_map2drvdata(map);
+ if (drvdata) {
+ /* Initialize dev_t for char dev node. */
+ if (xleaf_devnode_enabled(drvdata)) {
+ rc = 
alloc_chrdev_region(>xsd_file_ops.xsf_dev_t, 0,
+  XRT_MAX_DEVICE_NODES, drvname);
+ if (rc) {
+ platform_driver_unregister(map->drv);
+ pr_err("failed to alloc dev minor for %s: %d\n", 
drvname, rc);
+ return rc;
+ }
+ } else {
+ drvdata->xsd_file_ops.xsf_dev_t = (dev_t)-1;
+ }
+ }
+
+ ida_init(>ida);
+
+ pr_info("%s registered successfully\n", drvname);

Is this not xrt_info() then?



xrt_info() is meant for leaf driver to call where struct platform_device 
is available. We are initializing the drivers here, so can't call 
xrt_info().




+
+ return 0;
+}
+
+static void xrt_drv_unregister_driver(struct xrt_drv_map *map)
+{
+ const char *drvname = XRT_DRVNAME(map->drv);
+ struct xrt_subdev_drvdata *drvdata;
+
+ ida_destroy(>ida);
+
+ drvdata = xrt_drv_map2drvdata(map);
+ if (drvdata && drvdata->xsd_file_ops.xsf_dev_t != (dev_t)-1) {
+ unregister_chrdev_region(drvdata->xsd_file_ops.xsf_dev_t,
+  XRT_MAX_DEVICE_NODES);
+ }
+
+ platform_driver_unregister(map->drv);
+
+ pr_info("%s unregistered successfully\n", drvname);
+}
+
+int xleaf_register_driver(enum xrt_subdev_id 

Re: [PATCH V3 XRT Alveo 04/18] fpga: xrt: xrt-lib platform driver manager

2021-02-22 Thread Moritz Fischer
On Mon, Feb 22, 2021 at 07:05:29AM -0800, Tom Rix wrote:
> 
> On 2/17/21 10:40 PM, Lizhi Hou wrote:
> > xrt-lib kernel module infrastructure code to register and manage all
> > leaf driver modules.
> >
> > Signed-off-by: Sonal Santan 
> > Signed-off-by: Max Zhen 
> > Signed-off-by: Lizhi Hou 
> > ---
> >  drivers/fpga/xrt/lib/main.c | 274 
> >  drivers/fpga/xrt/lib/main.h |  17 +++
> >  2 files changed, 291 insertions(+)
> >  create mode 100644 drivers/fpga/xrt/lib/main.c
> >  create mode 100644 drivers/fpga/xrt/lib/main.h
> 
> Not sure if 'main' is a good base name for something going into a lib.
> 
> >
> > diff --git a/drivers/fpga/xrt/lib/main.c b/drivers/fpga/xrt/lib/main.c
> > new file mode 100644
> > index ..36fb62710843
> > --- /dev/null
> > +++ b/drivers/fpga/xrt/lib/main.c
> > @@ -0,0 +1,274 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Driver for Xilinx Alveo FPGA Support
> > + *
> > + * Copyright (C) 2020-2021 Xilinx, Inc.
> > + *
> > + * Authors:
> > + * Cheng Zhen 
> > + */
> > +
> > +#include 
> > +#include "xleaf.h"
> > +#include "xroot.h"
> > +#include "main.h"
> > +
> > +#define XRT_IPLIB_MODULE_NAME  "xrt-lib"
> > +#define XRT_IPLIB_MODULE_VERSION   "4.0.0"
> > +#define XRT_MAX_DEVICE_NODES   128
> > +#define XRT_DRVNAME(drv)   ((drv)->driver.name)
> > +
> > +/*
> > + * Subdev driver is known by ID to others. We map the ID to it's
> by it's ID
> > + * struct platform_driver, which contains it's binding name and 
> > driver/file ops.
> > + * We also map it to the endpoint name in DTB as well, if it's different
> > + * than the driver's binding name.
> > + */
> > +struct xrt_drv_map {
> > +   struct list_head list;
> > +   enum xrt_subdev_id id;
> > +   struct platform_driver *drv;
> > +   struct xrt_subdev_endpoints *eps;
> > +   struct ida ida; /* manage driver instance and char dev minor */
> > +};
> > +
> > +static DEFINE_MUTEX(xrt_lib_lock); /* global lock protecting xrt_drv_maps 
> > list */
> > +static LIST_HEAD(xrt_drv_maps);
> > +struct class *xrt_class;
> > +
> > +static inline struct xrt_subdev_drvdata *
> > +xrt_drv_map2drvdata(struct xrt_drv_map *map)
> > +{
> > +   return (struct xrt_subdev_drvdata *)map->drv->id_table[0].driver_data;
> > +}
> > +
> > +static struct xrt_drv_map *
> > +xrt_drv_find_map_by_id_nolock(enum xrt_subdev_id id)
> 
> name could be by convention
> 
> __xrt_drv_find_map_id
> 
> > +{
> > +   const struct list_head *ptr;
> > +
> > +   list_for_each(ptr, _drv_maps) {
> > +   struct xrt_drv_map *tmap = list_entry(ptr, struct xrt_drv_map, 
> > list);
> > +
> > +   if (tmap->id == id)
> > +   return tmap;
> > +   }
> > +   return NULL;
> > +}
> > +
> > +static struct xrt_drv_map *
> > +xrt_drv_find_map_by_id(enum xrt_subdev_id id)
> > +{
> > +   struct xrt_drv_map *map;
> > +
> > +   mutex_lock(_lib_lock);
> > +   map = xrt_drv_find_map_by_id_nolock(id);
> > +   mutex_unlock(_lib_lock);
> > +   /*
> > +* map should remain valid even after lock is dropped since a registered
> even after the lock
> > +* driver should only be unregistered when driver module is being 
> > unloaded,
> > +* which means that the driver should not be used by then.
> > +*/
> > +   return map;
> > +}
> > +
> > +static int xrt_drv_register_driver(struct xrt_drv_map *map)
> > +{
> > +   struct xrt_subdev_drvdata *drvdata;
> > +   int rc = 0;
> > +   const char *drvname = XRT_DRVNAME(map->drv);
> > +
> > +   rc = platform_driver_register(map->drv);
> > +   if (rc) {
> > +   pr_err("register %s platform driver failed\n", drvname);
> > +   return rc;
> > +   }
> > +
> > +   drvdata = xrt_drv_map2drvdata(map);
> > +   if (drvdata) {
> > +   /* Initialize dev_t for char dev node. */
> > +   if (xleaf_devnode_enabled(drvdata)) {
> > +   rc = 
> > alloc_chrdev_region(>xsd_file_ops.xsf_dev_t, 0,
> > +XRT_MAX_DEVICE_NODES, drvname);
> > +   if (rc) {
> > +   platform_driver_unregister(map->drv);
> > +   pr_err("failed to alloc dev minor for %s: 
> > %d\n", drvname, rc);
> > +   return rc;
> > +   }
> > +   } else {
> > +   drvdata->xsd_file_ops.xsf_dev_t = (dev_t)-1;
> > +   }
> > +   }
> > +
> > +   ida_init(>ida);
> > +
> > +   pr_info("%s registered successfully\n", drvname);
> > +
> > +   return 0;
> > +}
> > +
> > +static void xrt_drv_unregister_driver(struct xrt_drv_map *map)
> > +{
> > +   const char *drvname = XRT_DRVNAME(map->drv);
> > +   struct xrt_subdev_drvdata *drvdata;
> > +
> > +   ida_destroy(>ida);
> > +
> > +   drvdata = xrt_drv_map2drvdata(map);
> > +   if (drvdata && drvdata->xsd_file_ops.xsf_dev_t != (dev_t)-1) {
> > +   unregister_chrdev_region(drvdata->xsd_file_ops.xsf_dev_t,
> > +  

Re: [PATCH V3 XRT Alveo 04/18] fpga: xrt: xrt-lib platform driver manager

2021-02-22 Thread Tom Rix


On 2/17/21 10:40 PM, Lizhi Hou wrote:
> xrt-lib kernel module infrastructure code to register and manage all
> leaf driver modules.
>
> Signed-off-by: Sonal Santan 
> Signed-off-by: Max Zhen 
> Signed-off-by: Lizhi Hou 
> ---
>  drivers/fpga/xrt/lib/main.c | 274 
>  drivers/fpga/xrt/lib/main.h |  17 +++
>  2 files changed, 291 insertions(+)
>  create mode 100644 drivers/fpga/xrt/lib/main.c
>  create mode 100644 drivers/fpga/xrt/lib/main.h

Not sure if 'main' is a good base name for something going into a lib.

>
> diff --git a/drivers/fpga/xrt/lib/main.c b/drivers/fpga/xrt/lib/main.c
> new file mode 100644
> index ..36fb62710843
> --- /dev/null
> +++ b/drivers/fpga/xrt/lib/main.c
> @@ -0,0 +1,274 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Driver for Xilinx Alveo FPGA Support
> + *
> + * Copyright (C) 2020-2021 Xilinx, Inc.
> + *
> + * Authors:
> + *   Cheng Zhen 
> + */
> +
> +#include 
> +#include "xleaf.h"
> +#include "xroot.h"
> +#include "main.h"
> +
> +#define XRT_IPLIB_MODULE_NAME"xrt-lib"
> +#define XRT_IPLIB_MODULE_VERSION "4.0.0"
> +#define XRT_MAX_DEVICE_NODES 128
> +#define XRT_DRVNAME(drv) ((drv)->driver.name)
> +
> +/*
> + * Subdev driver is known by ID to others. We map the ID to it's
by it's ID
> + * struct platform_driver, which contains it's binding name and driver/file 
> ops.
> + * We also map it to the endpoint name in DTB as well, if it's different
> + * than the driver's binding name.
> + */
> +struct xrt_drv_map {
> + struct list_head list;
> + enum xrt_subdev_id id;
> + struct platform_driver *drv;
> + struct xrt_subdev_endpoints *eps;
> + struct ida ida; /* manage driver instance and char dev minor */
> +};
> +
> +static DEFINE_MUTEX(xrt_lib_lock); /* global lock protecting xrt_drv_maps 
> list */
> +static LIST_HEAD(xrt_drv_maps);
> +struct class *xrt_class;
> +
> +static inline struct xrt_subdev_drvdata *
> +xrt_drv_map2drvdata(struct xrt_drv_map *map)
> +{
> + return (struct xrt_subdev_drvdata *)map->drv->id_table[0].driver_data;
> +}
> +
> +static struct xrt_drv_map *
> +xrt_drv_find_map_by_id_nolock(enum xrt_subdev_id id)

name could be by convention

__xrt_drv_find_map_id

> +{
> + const struct list_head *ptr;
> +
> + list_for_each(ptr, _drv_maps) {
> + struct xrt_drv_map *tmap = list_entry(ptr, struct xrt_drv_map, 
> list);
> +
> + if (tmap->id == id)
> + return tmap;
> + }
> + return NULL;
> +}
> +
> +static struct xrt_drv_map *
> +xrt_drv_find_map_by_id(enum xrt_subdev_id id)
> +{
> + struct xrt_drv_map *map;
> +
> + mutex_lock(_lib_lock);
> + map = xrt_drv_find_map_by_id_nolock(id);
> + mutex_unlock(_lib_lock);
> + /*
> +  * map should remain valid even after lock is dropped since a registered
even after the lock
> +  * driver should only be unregistered when driver module is being 
> unloaded,
> +  * which means that the driver should not be used by then.
> +  */
> + return map;
> +}
> +
> +static int xrt_drv_register_driver(struct xrt_drv_map *map)
> +{
> + struct xrt_subdev_drvdata *drvdata;
> + int rc = 0;
> + const char *drvname = XRT_DRVNAME(map->drv);
> +
> + rc = platform_driver_register(map->drv);
> + if (rc) {
> + pr_err("register %s platform driver failed\n", drvname);
> + return rc;
> + }
> +
> + drvdata = xrt_drv_map2drvdata(map);
> + if (drvdata) {
> + /* Initialize dev_t for char dev node. */
> + if (xleaf_devnode_enabled(drvdata)) {
> + rc = 
> alloc_chrdev_region(>xsd_file_ops.xsf_dev_t, 0,
> +  XRT_MAX_DEVICE_NODES, drvname);
> + if (rc) {
> + platform_driver_unregister(map->drv);
> + pr_err("failed to alloc dev minor for %s: 
> %d\n", drvname, rc);
> + return rc;
> + }
> + } else {
> + drvdata->xsd_file_ops.xsf_dev_t = (dev_t)-1;
> + }
> + }
> +
> + ida_init(>ida);
> +
> + pr_info("%s registered successfully\n", drvname);
> +
> + return 0;
> +}
> +
> +static void xrt_drv_unregister_driver(struct xrt_drv_map *map)
> +{
> + const char *drvname = XRT_DRVNAME(map->drv);
> + struct xrt_subdev_drvdata *drvdata;
> +
> + ida_destroy(>ida);
> +
> + drvdata = xrt_drv_map2drvdata(map);
> + if (drvdata && drvdata->xsd_file_ops.xsf_dev_t != (dev_t)-1) {
> + unregister_chrdev_region(drvdata->xsd_file_ops.xsf_dev_t,
> +  XRT_MAX_DEVICE_NODES);
> + }
> +
> + platform_driver_unregister(map->drv);
> +
> + pr_info("%s unregistered successfully\n", drvname);
> +}
> +
> +int xleaf_register_driver(enum xrt_subdev_id id,
> +   struct 

Re: [PATCH V3 XRT Alveo 04/18] fpga: xrt: xrt-lib platform driver manager

2021-02-21 Thread Moritz Fischer
Lizhi,

On Wed, Feb 17, 2021 at 10:40:05PM -0800, Lizhi Hou wrote:
> xrt-lib kernel module infrastructure code to register and manage all
> leaf driver modules.
> 
> Signed-off-by: Sonal Santan 
> Signed-off-by: Max Zhen 
> Signed-off-by: Lizhi Hou 
> ---
>  drivers/fpga/xrt/lib/main.c | 274 
>  drivers/fpga/xrt/lib/main.h |  17 +++
>  2 files changed, 291 insertions(+)
>  create mode 100644 drivers/fpga/xrt/lib/main.c
>  create mode 100644 drivers/fpga/xrt/lib/main.h
> 
> diff --git a/drivers/fpga/xrt/lib/main.c b/drivers/fpga/xrt/lib/main.c
> new file mode 100644
> index ..36fb62710843
> --- /dev/null
> +++ b/drivers/fpga/xrt/lib/main.c
> @@ -0,0 +1,274 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Driver for Xilinx Alveo FPGA Support
> + *
> + * Copyright (C) 2020-2021 Xilinx, Inc.
> + *
> + * Authors:
> + *   Cheng Zhen 
> + */
> +
> +#include 
> +#include "xleaf.h"
> +#include "xroot.h"
> +#include "main.h"
> +
> +#define XRT_IPLIB_MODULE_NAME"xrt-lib"
> +#define XRT_IPLIB_MODULE_VERSION "4.0.0"
> +#define XRT_MAX_DEVICE_NODES 128
> +#define XRT_DRVNAME(drv) ((drv)->driver.name)
> +
> +/*
> + * Subdev driver is known by ID to others. We map the ID to it's
> + * struct platform_driver, which contains it's binding name and driver/file 
> ops.
> + * We also map it to the endpoint name in DTB as well, if it's different
> + * than the driver's binding name.
> + */
> +struct xrt_drv_map {
> + struct list_head list;
> + enum xrt_subdev_id id;
> + struct platform_driver *drv;
> + struct xrt_subdev_endpoints *eps;
> + struct ida ida; /* manage driver instance and char dev minor */
> +};
> +
> +static DEFINE_MUTEX(xrt_lib_lock); /* global lock protecting xrt_drv_maps 
> list */
> +static LIST_HEAD(xrt_drv_maps);
> +struct class *xrt_class;
> +
> +static inline struct xrt_subdev_drvdata *
> +xrt_drv_map2drvdata(struct xrt_drv_map *map)
> +{
> + return (struct xrt_subdev_drvdata *)map->drv->id_table[0].driver_data;
> +}
> +
> +static struct xrt_drv_map *
> +xrt_drv_find_map_by_id_nolock(enum xrt_subdev_id id)
> +{
> + const struct list_head *ptr;
> +
> + list_for_each(ptr, _drv_maps) {
> + struct xrt_drv_map *tmap = list_entry(ptr, struct xrt_drv_map, 
> list);
list_for_each_entry, maybe?
> +
> + if (tmap->id == id)
> + return tmap;
> + }
> + return NULL;
> +}
> +
> +static struct xrt_drv_map *
> +xrt_drv_find_map_by_id(enum xrt_subdev_id id)
> +{
> + struct xrt_drv_map *map;
> +
> + mutex_lock(_lib_lock);
> + map = xrt_drv_find_map_by_id_nolock(id);
> + mutex_unlock(_lib_lock);
> + /*
> +  * map should remain valid even after lock is dropped since a registered
> +  * driver should only be unregistered when driver module is being 
> unloaded,
> +  * which means that the driver should not be used by then.
> +  */
> + return map;
> +}
> +
> +static int xrt_drv_register_driver(struct xrt_drv_map *map)
> +{
> + struct xrt_subdev_drvdata *drvdata;
> + int rc = 0;
> + const char *drvname = XRT_DRVNAME(map->drv);
> +
> + rc = platform_driver_register(map->drv);
> + if (rc) {
> + pr_err("register %s platform driver failed\n", drvname);
> + return rc;
> + }
> +
> + drvdata = xrt_drv_map2drvdata(map);
> + if (drvdata) {
> + /* Initialize dev_t for char dev node. */
> + if (xleaf_devnode_enabled(drvdata)) {
> + rc = 
> alloc_chrdev_region(>xsd_file_ops.xsf_dev_t, 0,
> +  XRT_MAX_DEVICE_NODES, drvname);
> + if (rc) {
> + platform_driver_unregister(map->drv);
> + pr_err("failed to alloc dev minor for %s: 
> %d\n", drvname, rc);
> + return rc;
> + }
> + } else {
> + drvdata->xsd_file_ops.xsf_dev_t = (dev_t)-1;
> + }
> + }
> +
> + ida_init(>ida);
> +
> + pr_info("%s registered successfully\n", drvname);
Is this not xrt_info() then?
> +
> + return 0;
> +}
> +
> +static void xrt_drv_unregister_driver(struct xrt_drv_map *map)
> +{
> + const char *drvname = XRT_DRVNAME(map->drv);
> + struct xrt_subdev_drvdata *drvdata;
> +
> + ida_destroy(>ida);
> +
> + drvdata = xrt_drv_map2drvdata(map);
> + if (drvdata && drvdata->xsd_file_ops.xsf_dev_t != (dev_t)-1) {
> + unregister_chrdev_region(drvdata->xsd_file_ops.xsf_dev_t,
> +  XRT_MAX_DEVICE_NODES);
> + }
> +
> + platform_driver_unregister(map->drv);
> +
> + pr_info("%s unregistered successfully\n", drvname);
> +}
> +
> +int xleaf_register_driver(enum xrt_subdev_id id,
> +   struct platform_driver *drv,
> +   struct 

[PATCH V3 XRT Alveo 04/18] fpga: xrt: xrt-lib platform driver manager

2021-02-17 Thread Lizhi Hou
xrt-lib kernel module infrastructure code to register and manage all
leaf driver modules.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/lib/main.c | 274 
 drivers/fpga/xrt/lib/main.h |  17 +++
 2 files changed, 291 insertions(+)
 create mode 100644 drivers/fpga/xrt/lib/main.c
 create mode 100644 drivers/fpga/xrt/lib/main.h

diff --git a/drivers/fpga/xrt/lib/main.c b/drivers/fpga/xrt/lib/main.c
new file mode 100644
index ..36fb62710843
--- /dev/null
+++ b/drivers/fpga/xrt/lib/main.c
@@ -0,0 +1,274 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for Xilinx Alveo FPGA Support
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Cheng Zhen 
+ */
+
+#include 
+#include "xleaf.h"
+#include "xroot.h"
+#include "main.h"
+
+#define XRT_IPLIB_MODULE_NAME  "xrt-lib"
+#define XRT_IPLIB_MODULE_VERSION   "4.0.0"
+#define XRT_MAX_DEVICE_NODES   128
+#define XRT_DRVNAME(drv)   ((drv)->driver.name)
+
+/*
+ * Subdev driver is known by ID to others. We map the ID to it's
+ * struct platform_driver, which contains it's binding name and driver/file 
ops.
+ * We also map it to the endpoint name in DTB as well, if it's different
+ * than the driver's binding name.
+ */
+struct xrt_drv_map {
+   struct list_head list;
+   enum xrt_subdev_id id;
+   struct platform_driver *drv;
+   struct xrt_subdev_endpoints *eps;
+   struct ida ida; /* manage driver instance and char dev minor */
+};
+
+static DEFINE_MUTEX(xrt_lib_lock); /* global lock protecting xrt_drv_maps list 
*/
+static LIST_HEAD(xrt_drv_maps);
+struct class *xrt_class;
+
+static inline struct xrt_subdev_drvdata *
+xrt_drv_map2drvdata(struct xrt_drv_map *map)
+{
+   return (struct xrt_subdev_drvdata *)map->drv->id_table[0].driver_data;
+}
+
+static struct xrt_drv_map *
+xrt_drv_find_map_by_id_nolock(enum xrt_subdev_id id)
+{
+   const struct list_head *ptr;
+
+   list_for_each(ptr, _drv_maps) {
+   struct xrt_drv_map *tmap = list_entry(ptr, struct xrt_drv_map, 
list);
+
+   if (tmap->id == id)
+   return tmap;
+   }
+   return NULL;
+}
+
+static struct xrt_drv_map *
+xrt_drv_find_map_by_id(enum xrt_subdev_id id)
+{
+   struct xrt_drv_map *map;
+
+   mutex_lock(_lib_lock);
+   map = xrt_drv_find_map_by_id_nolock(id);
+   mutex_unlock(_lib_lock);
+   /*
+* map should remain valid even after lock is dropped since a registered
+* driver should only be unregistered when driver module is being 
unloaded,
+* which means that the driver should not be used by then.
+*/
+   return map;
+}
+
+static int xrt_drv_register_driver(struct xrt_drv_map *map)
+{
+   struct xrt_subdev_drvdata *drvdata;
+   int rc = 0;
+   const char *drvname = XRT_DRVNAME(map->drv);
+
+   rc = platform_driver_register(map->drv);
+   if (rc) {
+   pr_err("register %s platform driver failed\n", drvname);
+   return rc;
+   }
+
+   drvdata = xrt_drv_map2drvdata(map);
+   if (drvdata) {
+   /* Initialize dev_t for char dev node. */
+   if (xleaf_devnode_enabled(drvdata)) {
+   rc = 
alloc_chrdev_region(>xsd_file_ops.xsf_dev_t, 0,
+XRT_MAX_DEVICE_NODES, drvname);
+   if (rc) {
+   platform_driver_unregister(map->drv);
+   pr_err("failed to alloc dev minor for %s: 
%d\n", drvname, rc);
+   return rc;
+   }
+   } else {
+   drvdata->xsd_file_ops.xsf_dev_t = (dev_t)-1;
+   }
+   }
+
+   ida_init(>ida);
+
+   pr_info("%s registered successfully\n", drvname);
+
+   return 0;
+}
+
+static void xrt_drv_unregister_driver(struct xrt_drv_map *map)
+{
+   const char *drvname = XRT_DRVNAME(map->drv);
+   struct xrt_subdev_drvdata *drvdata;
+
+   ida_destroy(>ida);
+
+   drvdata = xrt_drv_map2drvdata(map);
+   if (drvdata && drvdata->xsd_file_ops.xsf_dev_t != (dev_t)-1) {
+   unregister_chrdev_region(drvdata->xsd_file_ops.xsf_dev_t,
+XRT_MAX_DEVICE_NODES);
+   }
+
+   platform_driver_unregister(map->drv);
+
+   pr_info("%s unregistered successfully\n", drvname);
+}
+
+int xleaf_register_driver(enum xrt_subdev_id id,
+ struct platform_driver *drv,
+ struct xrt_subdev_endpoints *eps)
+{
+   struct xrt_drv_map *map;
+
+   mutex_lock(_lib_lock);
+
+   map = xrt_drv_find_map_by_id_nolock(id);
+   if (map) {
+   mutex_unlock(_lib_lock);
+   pr_err("Id %d already has a registered driver, 0x%p\n",
+  id, map->drv);
+