All of lore.kernel.org
 help / color / mirror / Atom feed
From: Parav Pandit <parav@mellanox.com>
To: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	michal.lkml@markovi.net, davem@davemloft.net,
	gregkh@linuxfoundation.org, jiri@mellanox.com
Cc: parav@mellanox.com
Subject: [RFC net-next 1/8] subdev: Introducing subdev bus
Date: Thu, 28 Feb 2019 23:37:45 -0600	[thread overview]
Message-ID: <1551418672-12822-2-git-send-email-parav@mellanox.com> (raw)
In-Reply-To: <1551418672-12822-1-git-send-email-parav@mellanox.com>

Introduce a new subdev bus which holds sub devices created from a
primary device. These devices are named as 'subdev'.
A subdev is identified similarly to pci device using 16-bit vendor id
and device id.
Unlike PCI devices, scope of subdev is limited to Linux kernel.
A central entry that assigns unique subdev vendor and device id is:
include/linux/subdev_ids.h enums. Enum are chosen over define macro so
that two vendors do not end up with vendor id in kernel development
process.

subdev bus holds subdevices of multiple devices. A typical created
subdev for a PCI device in sysfs tree appears under their parent's
device as using core's default device naming scheme:

subdev<instance_id>.
i.e.
subdev0
subdev1

$ ls -l /sys/bus/pci/devices/0000:05:00.0
[..]
drwxr-xr-x 4 root root        0 Feb 13 15:57 subvdev0
drwxr-xr-x 4 root root        0 Feb 13 15:57 subvdev1

Device model view:
------------------
               +------+    +------+       +------+
               |subdev|    |subdev|       |subdev|
          -----|  1   |----|  2   |-------|  3   |----------
          |    +--|---+    +-|----+       +--|---+         |
          --------|----------|---subdev bus--|--------------
                  |          |               |
               +--+----+-----+           +---+---+
               |pcidev |                 |pcidev |
          -----|   A   |-----------------|   B   |----------
          |    +-------+                 +-------+         |
          -------------------pci bus------------------------

subdev are allocated and freed using subdev_alloc(), subdev_free() APIs.
A driver which wants to create actual class driver such as
net/block/infiniband need to use subdev_register_driver(),
subdev_unregister_driver() APIs.

Signed-off-by: Parav Pandit <parav@mellanox.com>
---
 drivers/Kconfig                 |   2 +
 drivers/Makefile                |   1 +
 drivers/subdev/Kconfig          |  12 ++++
 drivers/subdev/Makefile         |   8 +++
 drivers/subdev/subdev_main.c    | 153 ++++++++++++++++++++++++++++++++++++++++
 include/linux/mod_devicetable.h |  12 ++++
 include/linux/subdev_bus.h      |  63 +++++++++++++++++
 include/linux/subdev_ids.h      |  17 +++++
 8 files changed, 268 insertions(+)
 create mode 100644 drivers/subdev/Kconfig
 create mode 100644 drivers/subdev/Makefile
 create mode 100644 drivers/subdev/subdev_main.c
 create mode 100644 include/linux/subdev_bus.h
 create mode 100644 include/linux/subdev_ids.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 4f9f990..1818796 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -228,4 +228,6 @@ source "drivers/siox/Kconfig"
 
 source "drivers/slimbus/Kconfig"
 
+source "drivers/subdev/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index e1ce029..a040e96 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -186,3 +186,4 @@ obj-$(CONFIG_MULTIPLEXER)	+= mux/
 obj-$(CONFIG_UNISYS_VISORBUS)	+= visorbus/
 obj-$(CONFIG_SIOX)		+= siox/
 obj-$(CONFIG_GNSS)		+= gnss/
+obj-$(CONFIG_SUBDEV)		+= subdev/
diff --git a/drivers/subdev/Kconfig b/drivers/subdev/Kconfig
new file mode 100644
index 0000000..8ce3acc
--- /dev/null
+++ b/drivers/subdev/Kconfig
@@ -0,0 +1,12 @@
+#
+# subdev configuration
+#
+
+config SUBDEV
+	tristate "subdev bus driver"
+	help
+	The subdev bus driver allows creating hardware based sub devices
+	from a parent device. The subdev bus driver is required to create,
+	discover devices and to attach device drivers to this subdev
+	devices. These subdev devices are created using devlink tool by
+	user.
diff --git a/drivers/subdev/Makefile b/drivers/subdev/Makefile
new file mode 100644
index 0000000..405b74a
--- /dev/null
+++ b/drivers/subdev/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for subdev bus driver
+#
+
+obj-$(CONFIG_SUBDEV)	+= subdev.o
+
+subdev-y := subdev_main.o
diff --git a/drivers/subdev/subdev_main.c b/drivers/subdev/subdev_main.c
new file mode 100644
index 0000000..4aabcaa
--- /dev/null
+++ b/drivers/subdev/subdev_main.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/subdev_bus.h>
+
+static DEFINE_XARRAY_FLAGS(subdev_ids, XA_FLAGS_ALLOC);
+
+static int subdev_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct subdev_driver *subdev_drv = to_subdev_driver(drv);
+	const struct subdev_id *ids = subdev_drv->id_table;
+	const struct subdev *subdev = to_subdev_device(dev);
+
+	while (ids) {
+		if (ids->vendor_id == subdev->dev_id.vendor_id &&
+		    ids->device_id == subdev->dev_id.device_id)
+			return 1;
+
+		ids++;
+	}
+	return 0;
+}
+
+static struct bus_type subdev_bus_type = {
+	.dev_name = "subdev",
+	.name = "subdev",
+	.match = subdev_bus_match,
+};
+
+int __subdev_register_driver(struct subdev_driver *drv, struct module *owner,
+			     const char *mod_name)
+{
+	drv->driver.name = mod_name;
+	drv->driver.bus = &subdev_bus_type;
+	drv->driver.owner = owner;
+	drv->driver.mod_name = mod_name;
+
+	return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL(__subdev_register_driver);
+
+void subdev_unregister_driver(struct subdev_driver *drv)
+{
+	driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(subdev_unregister_driver);
+
+static void subdev_release(struct device *dev)
+{
+	struct subdev *subdev = to_subdev_device(dev);
+
+	kfree(subdev);
+}
+
+/**
+ * _subdev_alloc_subdev - Allocate a subdev device.
+ * @size:	Size of the device that to allocate that contains subdev
+ *		device as the first element.
+ * Returns pointer to a valid subdev structure or returns ERR_PTR.
+ *
+ */
+struct subdev *_subdev_alloc_dev(size_t size)
+{
+	struct subdev *subdev;
+
+	subdev = kzalloc(size, GFP_KERNEL);
+	if (!subdev)
+		return ERR_PTR(-ENOMEM);
+	subdev->dev.release = subdev_release;
+	device_initialize(&subdev->dev);
+	return subdev;
+}
+EXPORT_SYMBOL(_subdev_alloc_dev);
+
+/**
+ * subdev_free_dev - Free allocated subdev device.
+ * @subdev:	Pointer to subdev
+ *
+ */
+void subdev_free_dev(struct subdev *subdev)
+{
+	put_device(&subdev->dev);
+}
+EXPORT_SYMBOL(subdev_free_dev);
+
+/**
+ * subdev_add_dev - Add a sub device to bus.
+ * @subdev:	subdev devie to be placed on the bus
+ * @parent_dev:	Parent device of the subdev
+ * @vid:	Vendor ID of the device
+ * @did:	Device ID of the device
+ *
+ * Returns 0 on successfully adding subdev to bus or error code on failure.
+ * Once the device is added, it can be probed by the device driver who
+ * wish to match it.
+ *
+ */
+int subdev_add_dev(struct subdev *subdev, struct device *parent_dev,
+		   enum subdev_vendor_id vid, enum subdev_device_id did)
+{
+	u32 id = 0;
+	int ret;
+
+	if (!parent_dev)
+		return -EINVAL;
+
+	ret = xa_alloc(&subdev_ids, &id, UINT_MAX, NULL, GFP_KERNEL);
+	if (ret < 0)
+		return ret;
+
+	subdev->dev.id = id;
+	subdev->dev_id.vendor_id = vid;
+	subdev->dev_id.device_id = did;
+	subdev->dev.parent = parent_dev;
+	subdev->dev.bus = &subdev_bus_type;
+	subdev->dev.dma_mask = parent_dev->dma_mask;
+	subdev->dev.dma_parms = parent_dev->dma_parms;
+	subdev->dev.coherent_dma_mask = parent_dev->coherent_dma_mask;
+	ret = device_add(&subdev->dev);
+	if (ret)
+		xa_erase(&subdev_ids, id);
+	return ret;
+}
+EXPORT_SYMBOL(subdev_add_dev);
+
+/**
+ * subdev_delete_dev - Delete previously added subdev device
+ *
+ * @subdev:	Pointer to subdev device to delete
+ */
+void subdev_delete_dev(struct subdev *subdev)
+{
+	device_del(&subdev->dev);
+	xa_erase(&subdev_ids, subdev->dev.id);
+}
+EXPORT_SYMBOL(subdev_delete_dev);
+
+static int __init subdev_init(void)
+{
+	return bus_register(&subdev_bus_type);
+}
+
+static void __exit subdev_exit(void)
+{
+	bus_unregister(&subdev_bus_type);
+}
+
+module_init(subdev_init);
+module_exit(subdev_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index f9bd2f3..f271dab 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -779,4 +779,16 @@ struct typec_device_id {
 	kernel_ulong_t driver_data;
 };
 
+/**
+ * struct subdev_id - subdev device identifiers defined in
+ *		      include/linux/subdev_ids.h
+ *
+ * @vendor_id: Vendor ID
+ * @device_id: Device ID
+ */
+struct subdev_id {
+	__u16 vendor_id;
+	__u16 device_id;
+};
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/subdev_bus.h b/include/linux/subdev_bus.h
new file mode 100644
index 0000000..c6410e3
--- /dev/null
+++ b/include/linux/subdev_bus.h
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#ifndef SUBDEV_BUS_H
+#define SUBDEV_BUS_H
+
+#include <linux/mod_devicetable.h>
+#include <linux/device.h>
+#include <linux/subdev_ids.h>
+
+struct subdev_driver {
+	const struct subdev_id *id_table;
+	struct device_driver driver;
+	struct list_head list;
+};
+
+#define to_subdev_driver(x) container_of(x, struct subdev_driver, driver)
+
+int __subdev_register_driver(struct subdev_driver *drv, struct module *owner,
+			     const char *mod_name);
+#define subdev_register_driver(driver)		\
+	__subdev_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
+
+void subdev_unregister_driver(struct subdev_driver *dev);
+
+/**
+ * subdev - A subdev device representation
+ *
+ * @dev:	device struct that represent subdev device in core device model
+ * @dev_id:	Unique vendor id, device id that subdev device drivers match
+ *		against. A unique id that defines this subdev assigned in
+ *		include/linux/subdev_ids.h
+ */
+struct subdev {
+	struct device dev;
+	struct subdev_id dev_id;
+};
+
+#define to_subdev_device(x) container_of(x, struct subdev, dev)
+
+struct subdev *_subdev_alloc_dev(size_t size);
+
+/**
+ * subdev_alloc_dev -	allocate memory for driver structure which holds
+ *			subdev structure and other driver's device specific
+ *			fields.
+ * @drv_struct:		Driver's device structure which defines subdev device
+ *			as the first member in the structure.
+ * @member:		Name of the subdev instance name in drivers device
+ *			structure.
+ */
+#define subdev_alloc_dev(drv_struct, member)                                \
+	container_of(_subdev_alloc_dev(sizeof(struct drv_struct) +          \
+				      BUILD_BUG_ON_ZERO(offsetof(           \
+					      struct drv_struct, member))), \
+		     struct drv_struct, member)
+
+void subdev_free_dev(struct subdev *subdev);
+
+int subdev_add_dev(struct subdev *subdev, struct device *parent_dev,
+		   enum subdev_vendor_id vid, enum subdev_device_id did);
+void subdev_delete_dev(struct subdev *subdev);
+
+#endif
diff --git a/include/linux/subdev_ids.h b/include/linux/subdev_ids.h
new file mode 100644
index 0000000..361faa3
--- /dev/null
+++ b/include/linux/subdev_ids.h
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#ifndef SUBDEV_IDS_H
+#define SUBDEV_IDS_H
+
+enum subdev_vendor_id {
+	SUBDEV_VENDOR_ID_MELLANOX,
+
+	/* new device id must be added above at the end */
+};
+
+enum subdev_device_id {
+	SUBDEV_DEVICE_ID_MELLANOX_SF,
+
+	/* new device id mst be added above at the end */
+};
+#endif
-- 
1.8.3.1


  reply	other threads:[~2019-03-01  5:38 UTC|newest]

Thread overview: 72+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-01  5:37 [RFC net-next 0/8] Introducing subdev bus and devlink extension Parav Pandit
2019-03-01  5:37 ` Parav Pandit [this message]
2019-03-01  7:17   ` [RFC net-next 1/8] subdev: Introducing subdev bus Greg KH
2019-03-01 16:35     ` Parav Pandit
2019-03-01 17:00       ` Greg KH
2019-03-26 11:48     ` Lorenzo Pieralisi
2019-03-01  5:37 ` [RFC net-next 2/8] subdev: Introduce pm callbacks Parav Pandit
2019-03-01  5:37 ` [RFC net-next 3/8] modpost: Add support for subdev device id table Parav Pandit
2019-03-01  5:37 ` [RFC net-next 4/8] devlink: Introduce and use devlink_init/cleanup() in alloc/free Parav Pandit
2019-03-01  5:37 ` [RFC net-next 5/8] devlink: Add variant of devlink_register/unregister Parav Pandit
2019-03-01  5:37 ` [RFC net-next 6/8] devlink: Add support for devlink subdev lifecycle Parav Pandit
2019-03-01  5:37 ` [RFC net-next 7/8] net/mlx5: Add devlink subdev life cycle command support Parav Pandit
2019-03-01  7:18   ` Greg KH
2019-03-01 16:04     ` Parav Pandit
2019-03-01  5:37 ` [RFC net-next 8/8] net/mlx5: Add subdev driver to bind to subdev devices Parav Pandit
2019-03-01  7:21   ` Greg KH
2019-03-01 17:21     ` Parav Pandit
2019-03-05  7:13       ` Greg KH
2019-03-05 17:57         ` Parav Pandit
2019-03-05 19:27           ` Greg KH
2019-03-05 21:37             ` Parav Pandit
2019-03-01 22:12   ` Saeed Mahameed
2019-03-04 16:45     ` Parav Pandit
2019-03-01 20:03 ` [RFC net-next 0/8] Introducing subdev bus and devlink extension Jakub Kicinski
2019-03-04  4:41   ` Parav Pandit
2019-03-05  1:35     ` Jakub Kicinski
2019-03-05 19:46       ` Parav Pandit
2019-03-05 22:39         ` Kirti Wankhede
2019-03-05 23:17           ` Parav Pandit
2019-03-05 23:44             ` Parav Pandit
2019-03-06  0:44               ` Parav Pandit
2019-03-06  3:51                 ` Kirti Wankhede
2019-03-06  5:42                   ` Parav Pandit
2019-03-07 19:04                     ` Kirti Wankhede
2019-03-07 20:27                       ` Parav Pandit
2019-03-07 20:53                         ` Kirti Wankhede
2019-03-07 21:02                           ` Parav Pandit
2019-03-07 21:07                             ` Kirti Wankhede
2019-03-07 21:21                               ` Parav Pandit
2019-03-07 22:01                                 ` Kirti Wankhede
2019-03-07 22:31                                   ` Parav Pandit
2019-03-08 12:19                                     ` Kirti Wankhede
2019-03-08 17:09                                       ` Parav Pandit
2019-03-05  1:45     ` Jakub Kicinski
2019-03-05 16:52       ` Parav Pandit
2021-05-31 10:36         ` moyufeng
2021-06-01  5:37           ` Jakub Kicinski
2021-06-01  7:33             ` Yunsheng Lin
2021-06-01 21:34               ` Jakub Kicinski
2021-06-02  2:24                 ` Yunsheng Lin
2021-06-02 16:34                   ` Jakub Kicinski
2021-06-03  3:46                     ` Yunsheng Lin
2021-06-03 17:53                       ` Jakub Kicinski
2021-06-04  1:18                         ` Yunsheng Lin
2021-06-04 18:41                           ` Jakub Kicinski
2021-06-07  1:36                             ` Yunsheng Lin
2021-06-07 19:46                               ` Jakub Kicinski
2021-06-08 12:10                                 ` Yunsheng Lin
2021-06-08 17:29                                   ` Jakub Kicinski
2021-06-09  9:16                                     ` Yunsheng Lin
2021-06-09  9:38                                       ` Parav Pandit
2021-06-09 11:05                                         ` Yunsheng Lin
2021-06-09 11:59                                           ` Parav Pandit
2021-06-09 12:30                                             ` Yunsheng Lin
2021-06-09 13:45                                               ` Parav Pandit
2021-06-10  7:04                                                 ` Yunsheng Lin
2021-06-10  7:17                                                   ` Parav Pandit
2021-06-09 16:40                                       ` Jakub Kicinski
2021-06-10  6:52                                         ` Yunsheng Lin
2021-06-09  9:52                                   ` Parav Pandit
2021-06-09 11:16                                     ` Yunsheng Lin
2021-06-09 12:00                                       ` Parav Pandit

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=1551418672-12822-2-git-send-email-parav@mellanox.com \
    --to=parav@mellanox.com \
    --cc=davem@davemloft.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=jiri@mellanox.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=michal.lkml@markovi.net \
    --cc=netdev@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.