Re: [PATCH v4 3/4] fpga: dfl: create a dfl bus type to support DFL devices

2020-08-10 Thread Xu Yilun
On Mon, Aug 10, 2020 at 02:36:44PM +0800, Wu, Hao wrote:
> >
> > A new bus type "dfl" is introduced for private features which are not
> > initialized by DFL feature drivers (dfl-fme & dfl-afu drivers). So these
> > private features could be handled by separate driver modules.
> >
> > DFL feature drivers (dfl-fme, dfl-port) will create DFL devices on
> > enumeration. DFL drivers could be registered on this bus to match these
> > DFL devices. They are matched by dfl type & feature_id.
> >
> > Signed-off-by: Xu Yilun 
> > Signed-off-by: Wu Hao 
> > Signed-off-by: Matthew Gerlach 
> > Signed-off-by: Russ Weight 
> > Reviewed-by: Tom Rix 
> > ---
> > v2: change the bus uevent format.
> > change the dfl device's sysfs name format.
> > refactor dfl_dev_add().
> > minor fixes for comments from Hao and Tom.
> > v3: no change.
> > v4: improve the uevent format, 4 bits for type & 12 bits for id.
> > change dfl_device->type to u8.
> > A dedicate field in struct dfl_feature for dfl device instance.
> > error out if dfl_device already exist on dfl_devs_init().
> > ---
> >  Documentation/ABI/testing/sysfs-bus-dfl |  15 ++
> >  drivers/fpga/dfl.c  | 263 
> > +++-
> >  drivers/fpga/dfl.h  |  85 +++
> >  3 files changed, 355 insertions(+), 8 deletions(-)
> >  create mode 100644 Documentation/ABI/testing/sysfs-bus-dfl
> >
> > diff --git a/Documentation/ABI/testing/sysfs-bus-dfl
> > b/Documentation/ABI/testing/sysfs-bus-dfl
> > new file mode 100644
> > index 000..4d74cc0
> > --- /dev/null
> > +++ b/Documentation/ABI/testing/sysfs-bus-dfl
> > @@ -0,0 +1,15 @@
> > +What:/sys/bus/dfl/devices/dfl_dev.X/type
> > +Date:July 2020
> > +KernelVersion:5.10
> > +Contact:Xu Yilun 
> > +Description:Read-only. It returns type of DFL FIU of the device. Now DFL
> > +supports 2 FIU types, 0 for FME, 1 for PORT.
> > +Format: 0x%x
> > +
> > +What:/sys/bus/dfl/devices/dfl_dev.X/feature_id
> > +Date:July 2020
> > +KernelVersion:5.10
> > +Contact:Xu Yilun 
> > +Description:Read-only. It returns feature identifier local to its DFL FIU
> > +type.
> > +Format: 0x%x
> > diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
> > index b5257d7..51cef85 100644
> > --- a/drivers/fpga/dfl.c
> > +++ b/drivers/fpga/dfl.c
> > @@ -30,12 +30,6 @@ static DEFINE_MUTEX(dfl_id_mutex);
> >   * index to dfl_chardevs table. If no chardev support just set devt_type
> >   * as one invalid index (DFL_FPGA_DEVT_MAX).
> >   */
> > -enum dfl_id_type {
> > -FME_ID,/* fme id allocation and mapping */
> > -PORT_ID,/* port id allocation and mapping */
> > -DFL_ID_MAX,
> > -};
> > -
> >  enum dfl_fpga_devt_type {
> >  DFL_FPGA_DEVT_FME,
> >  DFL_FPGA_DEVT_PORT,
> > @@ -250,6 +244,245 @@ int dfl_fpga_check_port_id(struct platform_device
> > *pdev, void *pport_id)
> >  }
> >  EXPORT_SYMBOL_GPL(dfl_fpga_check_port_id);
> >
> > +static DEFINE_IDA(dfl_device_ida);
> > +
> > +static const struct dfl_device_id *
> > +dfl_match_one_device(const struct dfl_device_id *id, struct dfl_device
> > *ddev)
> > +{
> > +if (id->type == ddev->type && id->feature_id == ddev->feature_id)
> > +return id;
> > +
> > +return NULL;
> > +}
> > +
> > +static int dfl_bus_match(struct device *dev, struct device_driver *drv)
> > +{
> > +struct dfl_device *ddev = to_dfl_dev(dev);
> > +struct dfl_driver *ddrv = to_dfl_drv(drv);
> > +const struct dfl_device_id *id_entry = ddrv->id_table;
> > +
> > +if (id_entry) {
> > +while (id_entry->feature_id) {
> > +if (dfl_match_one_device(id_entry, ddev)) {
> > +ddev->id_entry = id_entry;
> > +return 1;
> > +}
> > +id_entry++;
> > +}
> > +}
> > +
> > +return 0;
> > +}
> > +
> > +static int dfl_bus_probe(struct device *dev)
> > +{
> > +struct dfl_device *ddev = to_dfl_dev(dev);
> > +struct dfl_driver *ddrv = to_dfl_drv(dev->driver);
> > +
> > +return ddrv->probe(ddev);
> > +}
> > +
> > +static int dfl_bus_remove(struct device *dev)
> > +{
> > +struct dfl_device *ddev = to_dfl_dev(dev);
> > +struct dfl_driver *ddrv = to_dfl_drv(dev->driver);
> > +
> > +if (ddrv->remove)
> > +ddrv->remove(ddev);
> > +
> > +return 0;
> > +}
> > +
> > +static int dfl_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
> > +{
> > +struct dfl_device *ddev = to_dfl_dev(dev);
> > +
> > +/* The type has 4 valid bits and feature_id has 12 valid bits */
> > +return add_uevent_var(env, "MODALIAS=dfl:t%01Xf%03X",
> > +  ddev->type, ddev->feature_id);
> > +}
> > +
> > +/* show dfl info fields */
> > +#define dfl_info_attr(field, format_string)\
> > +static ssize_t\
> > +field##_show(struct device *dev, struct device_attribute *attr,
> > \
> > + char *buf)\
> > +{\
> > +struct dfl_device *ddev = to_dfl_dev(dev);\
> > +\
> > +return sprintf(buf, format_string, ddev->field);\
> > +}\
> > +static DEVICE_ATTR_RO(field)
> > +
> > +dfl_info_attr(type, "0x%x\n");
> > +dfl_info_attr(feature_id, "0x%x\n");
> > +
> > +static struct attribute *dfl_dev_attrs[] = {
> > +_attr_type.attr,
> > 

RE: [PATCH v4 3/4] fpga: dfl: create a dfl bus type to support DFL devices

2020-08-10 Thread Wu, Hao
> 
> A new bus type "dfl" is introduced for private features which are not
> initialized by DFL feature drivers (dfl-fme & dfl-afu drivers). So these
> private features could be handled by separate driver modules.
> 
> DFL feature drivers (dfl-fme, dfl-port) will create DFL devices on
> enumeration. DFL drivers could be registered on this bus to match these
> DFL devices. They are matched by dfl type & feature_id.
> 
> Signed-off-by: Xu Yilun 
> Signed-off-by: Wu Hao 
> Signed-off-by: Matthew Gerlach 
> Signed-off-by: Russ Weight 
> Reviewed-by: Tom Rix 
> ---
> v2: change the bus uevent format.
> change the dfl device's sysfs name format.
> refactor dfl_dev_add().
> minor fixes for comments from Hao and Tom.
> v3: no change.
> v4: improve the uevent format, 4 bits for type & 12 bits for id.
> change dfl_device->type to u8.
> A dedicate field in struct dfl_feature for dfl device instance.
> error out if dfl_device already exist on dfl_devs_init().
> ---
>  Documentation/ABI/testing/sysfs-bus-dfl |  15 ++
>  drivers/fpga/dfl.c  | 263 
> +++-
>  drivers/fpga/dfl.h  |  85 +++
>  3 files changed, 355 insertions(+), 8 deletions(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-dfl
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-dfl
> b/Documentation/ABI/testing/sysfs-bus-dfl
> new file mode 100644
> index 000..4d74cc0
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-dfl
> @@ -0,0 +1,15 @@
> +What:/sys/bus/dfl/devices/dfl_dev.X/type
> +Date:July 2020
> +KernelVersion:   5.10
> +Contact: Xu Yilun 
> +Description: Read-only. It returns type of DFL FIU of the device. Now DFL
> + supports 2 FIU types, 0 for FME, 1 for PORT.
> + Format: 0x%x
> +
> +What:/sys/bus/dfl/devices/dfl_dev.X/feature_id
> +Date:July 2020
> +KernelVersion:   5.10
> +Contact: Xu Yilun 
> +Description: Read-only. It returns feature identifier local to its DFL FIU
> + type.
> + Format: 0x%x
> diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
> index b5257d7..51cef85 100644
> --- a/drivers/fpga/dfl.c
> +++ b/drivers/fpga/dfl.c
> @@ -30,12 +30,6 @@ static DEFINE_MUTEX(dfl_id_mutex);
>   * index to dfl_chardevs table. If no chardev support just set devt_type
>   * as one invalid index (DFL_FPGA_DEVT_MAX).
>   */
> -enum dfl_id_type {
> - FME_ID, /* fme id allocation and mapping */
> - PORT_ID,/* port id allocation and mapping */
> - DFL_ID_MAX,
> -};
> -
>  enum dfl_fpga_devt_type {
>   DFL_FPGA_DEVT_FME,
>   DFL_FPGA_DEVT_PORT,
> @@ -250,6 +244,245 @@ int dfl_fpga_check_port_id(struct platform_device
> *pdev, void *pport_id)
>  }
>  EXPORT_SYMBOL_GPL(dfl_fpga_check_port_id);
> 
> +static DEFINE_IDA(dfl_device_ida);
> +
> +static const struct dfl_device_id *
> +dfl_match_one_device(const struct dfl_device_id *id, struct dfl_device
> *ddev)
> +{
> + if (id->type == ddev->type && id->feature_id == ddev->feature_id)
> + return id;
> +
> + return NULL;
> +}
> +
> +static int dfl_bus_match(struct device *dev, struct device_driver *drv)
> +{
> + struct dfl_device *ddev = to_dfl_dev(dev);
> + struct dfl_driver *ddrv = to_dfl_drv(drv);
> + const struct dfl_device_id *id_entry = ddrv->id_table;
> +
> + if (id_entry) {
> + while (id_entry->feature_id) {
> + if (dfl_match_one_device(id_entry, ddev)) {
> + ddev->id_entry = id_entry;
> + return 1;
> + }
> + id_entry++;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int dfl_bus_probe(struct device *dev)
> +{
> + struct dfl_device *ddev = to_dfl_dev(dev);
> + struct dfl_driver *ddrv = to_dfl_drv(dev->driver);
> +
> + return ddrv->probe(ddev);
> +}
> +
> +static int dfl_bus_remove(struct device *dev)
> +{
> + struct dfl_device *ddev = to_dfl_dev(dev);
> + struct dfl_driver *ddrv = to_dfl_drv(dev->driver);
> +
> + if (ddrv->remove)
> + ddrv->remove(ddev);
> +
> + return 0;
> +}
> +
> +static int dfl_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
> +{
> + struct dfl_device *ddev = to_dfl_dev(dev);
> +
> + /* The type has 4 valid bits and feature_id has 12 valid bits */
> + return add_uevent_var(env, "MODALIAS=dfl:t%01Xf%03X",
> +   ddev->type, ddev->feature_id);
> +}
> +
> +/* show dfl info fields */
> +#define dfl_info_attr(field, format_string)  \
> +static ssize_t   
> \
> +field##_show(struct device *dev, struct device_attribute *attr,
>   \
> +  char *buf) \
> +{  

[PATCH v4 3/4] fpga: dfl: create a dfl bus type to support DFL devices

2020-08-09 Thread Xu Yilun
A new bus type "dfl" is introduced for private features which are not
initialized by DFL feature drivers (dfl-fme & dfl-afu drivers). So these
private features could be handled by separate driver modules.

DFL feature drivers (dfl-fme, dfl-port) will create DFL devices on
enumeration. DFL drivers could be registered on this bus to match these
DFL devices. They are matched by dfl type & feature_id.

Signed-off-by: Xu Yilun 
Signed-off-by: Wu Hao 
Signed-off-by: Matthew Gerlach 
Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v2: change the bus uevent format.
change the dfl device's sysfs name format.
refactor dfl_dev_add().
minor fixes for comments from Hao and Tom.
v3: no change.
v4: improve the uevent format, 4 bits for type & 12 bits for id.
change dfl_device->type to u8.
A dedicate field in struct dfl_feature for dfl device instance.
error out if dfl_device already exist on dfl_devs_init().
---
 Documentation/ABI/testing/sysfs-bus-dfl |  15 ++
 drivers/fpga/dfl.c  | 263 +++-
 drivers/fpga/dfl.h  |  85 +++
 3 files changed, 355 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-dfl

diff --git a/Documentation/ABI/testing/sysfs-bus-dfl 
b/Documentation/ABI/testing/sysfs-bus-dfl
new file mode 100644
index 000..4d74cc0
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-dfl
@@ -0,0 +1,15 @@
+What:  /sys/bus/dfl/devices/dfl_dev.X/type
+Date:  July 2020
+KernelVersion: 5.10
+Contact:   Xu Yilun 
+Description:   Read-only. It returns type of DFL FIU of the device. Now DFL
+   supports 2 FIU types, 0 for FME, 1 for PORT.
+   Format: 0x%x
+
+What:  /sys/bus/dfl/devices/dfl_dev.X/feature_id
+Date:  July 2020
+KernelVersion: 5.10
+Contact:   Xu Yilun 
+Description:   Read-only. It returns feature identifier local to its DFL FIU
+   type.
+   Format: 0x%x
diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
index b5257d7..51cef85 100644
--- a/drivers/fpga/dfl.c
+++ b/drivers/fpga/dfl.c
@@ -30,12 +30,6 @@ static DEFINE_MUTEX(dfl_id_mutex);
  * index to dfl_chardevs table. If no chardev support just set devt_type
  * as one invalid index (DFL_FPGA_DEVT_MAX).
  */
-enum dfl_id_type {
-   FME_ID, /* fme id allocation and mapping */
-   PORT_ID,/* port id allocation and mapping */
-   DFL_ID_MAX,
-};
-
 enum dfl_fpga_devt_type {
DFL_FPGA_DEVT_FME,
DFL_FPGA_DEVT_PORT,
@@ -250,6 +244,245 @@ int dfl_fpga_check_port_id(struct platform_device *pdev, 
void *pport_id)
 }
 EXPORT_SYMBOL_GPL(dfl_fpga_check_port_id);
 
+static DEFINE_IDA(dfl_device_ida);
+
+static const struct dfl_device_id *
+dfl_match_one_device(const struct dfl_device_id *id, struct dfl_device *ddev)
+{
+   if (id->type == ddev->type && id->feature_id == ddev->feature_id)
+   return id;
+
+   return NULL;
+}
+
+static int dfl_bus_match(struct device *dev, struct device_driver *drv)
+{
+   struct dfl_device *ddev = to_dfl_dev(dev);
+   struct dfl_driver *ddrv = to_dfl_drv(drv);
+   const struct dfl_device_id *id_entry = ddrv->id_table;
+
+   if (id_entry) {
+   while (id_entry->feature_id) {
+   if (dfl_match_one_device(id_entry, ddev)) {
+   ddev->id_entry = id_entry;
+   return 1;
+   }
+   id_entry++;
+   }
+   }
+
+   return 0;
+}
+
+static int dfl_bus_probe(struct device *dev)
+{
+   struct dfl_device *ddev = to_dfl_dev(dev);
+   struct dfl_driver *ddrv = to_dfl_drv(dev->driver);
+
+   return ddrv->probe(ddev);
+}
+
+static int dfl_bus_remove(struct device *dev)
+{
+   struct dfl_device *ddev = to_dfl_dev(dev);
+   struct dfl_driver *ddrv = to_dfl_drv(dev->driver);
+
+   if (ddrv->remove)
+   ddrv->remove(ddev);
+
+   return 0;
+}
+
+static int dfl_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+   struct dfl_device *ddev = to_dfl_dev(dev);
+
+   /* The type has 4 valid bits and feature_id has 12 valid bits */
+   return add_uevent_var(env, "MODALIAS=dfl:t%01Xf%03X",
+ ddev->type, ddev->feature_id);
+}
+
+/* show dfl info fields */
+#define dfl_info_attr(field, format_string)\
+static ssize_t \
+field##_show(struct device *dev, struct device_attribute *attr,
\
+char *buf) \
+{  \
+   struct dfl_device *ddev = to_dfl_dev(dev);  \
+   \
+   return sprintf(buf, format_string, ddev->field);