* [PATCH 1/2] eth phy: add mdio bus char device interface
@ 2018-06-18 3:32 Wei Li
2018-06-18 3:32 ` [PATCH 2/2] " Wei Li
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Wei Li @ 2018-06-18 3:32 UTC (permalink / raw)
To: andrew, f.fainelli; +Cc: netdev
Add the char device interface of mdio bus, like what i2c-dev or spidev do.
They make it possible for user-space programs to access the bus directly.
Signed-off-by: Wei Li <liwei1412@163.com>
---
drivers/net/phy/Kconfig | 10 ++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/mdio-dev.c | 376 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/mdio-dev.h | 28 ++++
4 files changed, 415 insertions(+)
create mode 100644 drivers/net/phy/mdio-dev.c
create mode 100644 include/linux/mdio-dev.h
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index bdfbabb..cd688c5 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -158,6 +158,16 @@ config MDIO_XGENE
This module provides a driver for the MDIO busses found in the
APM X-Gene SoC's.
+config MDIO_CHARDEV
+ tristate "MDIO device interface"
+ help
+ Say Y here to use mdio-* device files, usually found in the /dev
+ directory on your system. They make it possible to have user-space
+ programs use the MDIO bus.
+
+ This support is also available as a module. If so, the module
+ will be called mdio-dev.
+
endif
config PHYLINK
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 01acbcb..a0566f8 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o
obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o
obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o
+obj-$(CONFIG_MDIO_CHARDEV) += mdio-dev.o
obj-$(CONFIG_SFP) += sfp.o
sfp-obj-$(CONFIG_SFP) += sfp-bus.o
diff --git a/drivers/net/phy/mdio-dev.c b/drivers/net/phy/mdio-dev.c
new file mode 100644
index 0000000..61487d2
--- /dev/null
+++ b/drivers/net/phy/mdio-dev.c
@@ -0,0 +1,376 @@
+/*
+ * mdio-dev.c - mdio-bus driver, char device interface
+ *
+ * Copyright (C) 2018 Wei Li <liwei1412@163.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/mdio-dev.h>
+#include <linux/mdio.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/slab.h>
+#include <linux/phy.h>
+
+/*
+ * An mdio_dev represents a mii_bus. It's coupled
+ * with a character special file which is accessed by user mode drivers.
+ *
+ * The list of mdio_dev structures is parallel to the mii_bus lists
+ * maintained by the driver model, and is updated using bus notifications.
+ */
+struct mdio_dev {
+ struct list_head list;
+ struct mii_bus *bus;
+ int nr;
+ struct device *dev;
+ struct cdev cdev;
+};
+
+static DEFINE_MUTEX(mdio_dev_lock);
+static DEFINE_IDR(mdio_dev_idr);
+static LIST_HEAD(mdio_dev_list);
+static DEFINE_SPINLOCK(mdio_dev_list_lock);
+
+static struct mdio_dev *mdio_dev_get_by_bus(struct mii_bus *bus)
+{
+ struct mdio_dev *mdio_dev;
+
+ if (!bus)
+ return NULL;
+
+ spin_lock(&mdio_dev_list_lock);
+ list_for_each_entry(mdio_dev, &mdio_dev_list, list) {
+ if (mdio_dev->bus == bus)
+ goto found;
+ }
+ mdio_dev = NULL;
+found:
+ spin_unlock(&mdio_dev_list_lock);
+ return mdio_dev;
+}
+
+static int alloc_mdio_dev_id(struct mdio_dev *mdio_dev)
+{
+ int id;
+
+ mutex_lock(&mdio_dev_lock);
+ id = idr_alloc(&mdio_dev_idr, mdio_dev, 0, MDIO_MINORS, GFP_KERNEL);
+ mutex_unlock(&mdio_dev_lock);
+ if (WARN(id < 0, "couldn't get idr"))
+ return id == -ENOSPC ? -EBUSY : id;
+
+ mdio_dev->nr = id;
+ return 0;
+}
+
+static void free_mdio_dev_id(struct mdio_dev *mdio_dev)
+{
+ mutex_lock(&mdio_dev_lock);
+ idr_remove(&mdio_dev_idr, mdio_dev->nr);
+ mutex_unlock(&mdio_dev_lock);
+ mdio_dev->nr = -1;
+}
+
+static struct mii_bus *mdiodev_get_bus(int nr)
+{
+ struct mdio_dev *found;
+
+ mutex_lock(&mdio_dev_lock);
+ found = idr_find(&mdio_dev_idr, nr);
+ if (!found)
+ goto exit;
+
+ if (try_module_get(found->bus->owner))
+ get_device(&found->bus->dev);
+ else
+ found = NULL;
+
+exit:
+ mutex_unlock(&mdio_dev_lock);
+ return found ? found->bus : NULL;
+}
+
+static void mdiodev_put_bus(struct mii_bus *bus)
+{
+ if (!bus)
+ return;
+
+ put_device(&bus->dev);
+ module_put(bus->owner);
+}
+
+static struct mdio_dev *get_free_mdio_dev(struct mii_bus *bus)
+{
+ struct mdio_dev *mdio_dev;
+
+ mdio_dev = kzalloc(sizeof(*mdio_dev), GFP_KERNEL);
+ if (!mdio_dev)
+ return ERR_PTR(-ENOMEM);
+ mdio_dev->bus = bus;
+
+ if (alloc_mdio_dev_id(mdio_dev)) {
+ printk(KERN_ERR "mdio-dev: Out of device minors\n");
+ kfree(mdio_dev);
+ return ERR_PTR(-ENODEV);
+ }
+
+ spin_lock(&mdio_dev_list_lock);
+ list_add_tail(&mdio_dev->list, &mdio_dev_list);
+ spin_unlock(&mdio_dev_list_lock);
+ return mdio_dev;
+}
+
+static void put_mdio_dev(struct mdio_dev *mdio_dev)
+{
+ spin_lock(&mdio_dev_list_lock);
+ list_del(&mdio_dev->list);
+ spin_unlock(&mdio_dev_list_lock);
+ free_mdio_dev_id(mdio_dev);
+ kfree(mdio_dev);
+}
+
+static ssize_t name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mii_bus *bus = mdiodev_get_bus(MINOR(dev->devt));
+
+ if (!bus)
+ return -ENODEV;
+ return sprintf(buf, "%s\n", bus->name);
+}
+static DEVICE_ATTR_RO(name);
+
+static struct attribute *mdio_attrs[] = {
+ &dev_attr_name.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(mdio);
+
+/*-------------------------------------------------------------------------*/
+
+static long mdiodev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct mii_bus *bus = file->private_data;
+ struct mii_ioctl_data data;
+ int res;
+
+ dev_dbg(&bus->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n", cmd, arg);
+
+ switch (cmd) {
+ case SIOCSMIIREG:
+ if (copy_from_user(&data,
+ (struct mii_ioctl_data __user *)arg, sizeof(data)))
+ return -EFAULT;
+
+ res = mdiobus_write(bus, data.phy_id, data.reg_num, data.val_in);
+ if (res < 0)
+ return -EIO;
+ return 0;
+
+ case SIOCGMIIREG:
+ if (copy_from_user(&data,
+ (struct mii_ioctl_data __user *)arg, sizeof(data)))
+ return -EFAULT;
+
+ res = mdiobus_read(bus, data.phy_id, data.reg_num);
+ if (res < 0)
+ return -EIO;
+
+ data.val_out = res;
+ if (copy_to_user((struct mii_ioctl_data __user *)arg,
+ &data, sizeof(data)))
+ return -EFAULT;
+ return 0;
+
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static int mdiodev_open(struct inode *inode, struct file *file)
+{
+ unsigned int minor = iminor(inode);
+ struct mii_bus *bus;
+
+ bus = mdiodev_get_bus(minor);
+ if (!bus)
+ return -ENODEV;
+
+ file->private_data = bus;
+
+ return 0;
+}
+
+static int mdiodev_release(struct inode *inode, struct file *file)
+{
+ struct mii_bus *bus = file->private_data;
+
+ mdiodev_put_bus(bus);
+ file->private_data = NULL;
+
+ return 0;
+}
+
+static const struct file_operations mdiodev_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .unlocked_ioctl = mdiodev_ioctl,
+ .open = mdiodev_open,
+ .release = mdiodev_release,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int mdio_major;
+static struct class *mdio_dev_class;
+
+static int mdiodev_attach_bus(struct device *dev, void *dummy)
+{
+ struct mii_bus *bus;
+ struct mdio_dev *mdio_dev;
+ int res;
+
+ if (dev->class != &mdio_bus_class)
+ return 0;
+ bus = to_mii_bus(dev);
+
+ mdio_dev = get_free_mdio_dev(bus);
+ if (IS_ERR(mdio_dev))
+ return PTR_ERR(mdio_dev);
+
+ cdev_init(&mdio_dev->cdev, &mdiodev_fops);
+ mdio_dev->cdev.owner = THIS_MODULE;
+ res = cdev_add(&mdio_dev->cdev, MKDEV(mdio_major, mdio_dev->nr), 1);
+ if (res)
+ goto error_cdev;
+
+ /* register this mdio device with the driver core */
+ mdio_dev->dev = device_create(mdio_dev_class, &bus->dev,
+ MKDEV(mdio_major, mdio_dev->nr), NULL,
+ "mdio-%d", mdio_dev->nr);
+ if (IS_ERR(mdio_dev->dev)) {
+ res = PTR_ERR(mdio_dev->dev);
+ goto error;
+ }
+
+ pr_debug("mdio-dev: bus [%s] registered as minor %d\n",
+ bus->name, mdio_dev->nr);
+ return 0;
+error:
+ cdev_del(&mdio_dev->cdev);
+error_cdev:
+ put_mdio_dev(mdio_dev);
+ return res;
+}
+
+static int mdiodev_detach_bus(struct device *dev, void *dummy)
+{
+ struct mii_bus *bus;
+ struct mdio_dev *mdio_dev;
+
+ if (dev->class != &mdio_bus_class)
+ return 0;
+ bus = to_mii_bus(dev);
+
+ mdio_dev = mdio_dev_get_by_bus(bus);
+ if (!mdio_dev) /* attach_bus must have failed */
+ return 0;
+
+ cdev_del(&mdio_dev->cdev);
+ device_destroy(mdio_dev_class, MKDEV(mdio_major, mdio_dev->nr));
+ put_mdio_dev(mdio_dev);
+
+ pr_debug("mdio-dev: bus [%s] unregistered\n", bus->name);
+ return 0;
+}
+
+static int mdiodev_notifier_call(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct device *dev = data;
+
+ switch (action) {
+ case BUS_NOTIFY_ADD_DEVICE:
+ return mdiodev_attach_bus(dev, NULL);
+ case BUS_NOTIFY_DEL_DEVICE:
+ return mdiodev_detach_bus(dev, NULL);
+ }
+
+ return 0;
+}
+
+static struct notifier_block mdiodev_notifier = {
+ .notifier_call = mdiodev_notifier_call,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init mdio_dev_init(void)
+{
+ int res;
+ dev_t devid;
+
+ printk(KERN_INFO "mdio /dev entries driver\n");
+
+ res = alloc_chrdev_region(&devid, 0, MDIO_MINORS, "mdio");
+ if (res)
+ goto out;
+
+ mdio_major = MAJOR(devid);
+ mdio_dev_class = class_create(THIS_MODULE, "mdio-dev");
+ if (IS_ERR(mdio_dev_class)) {
+ res = PTR_ERR(mdio_dev_class);
+ goto out_unreg_chrdev;
+ }
+ mdio_dev_class->dev_groups = mdio_groups;
+
+ /* Keep track of buses which will be added or removed later */
+ res = mdiobus_register_notifier(&mdiodev_notifier);
+ if (res)
+ goto out_unreg_class;
+
+ /* Bind to already existing buses right away */
+ class_for_each_device(&mdio_bus_class, NULL, NULL, mdiodev_attach_bus);
+
+ return 0;
+
+out_unreg_class:
+ class_destroy(mdio_dev_class);
+out_unreg_chrdev:
+ unregister_chrdev_region(MKDEV(mdio_major, 0), MDIO_MINORS);
+out:
+ printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__);
+ return res;
+}
+
+static void __exit mdio_dev_exit(void)
+{
+ mdiobus_unregister_notifier(&mdiodev_notifier);
+ class_for_each_device(&mdio_bus_class, NULL, NULL, mdiodev_detach_bus);
+ class_destroy(mdio_dev_class);
+ unregister_chrdev_region(MKDEV(mdio_major, 0), MDIO_MINORS);
+}
+
+MODULE_AUTHOR("Wei Li <liwei1412@163.com>");
+MODULE_DESCRIPTION("MDIO /dev entries driver");
+MODULE_LICENSE("GPL");
+
+module_init(mdio_dev_init);
+module_exit(mdio_dev_exit);
diff --git a/include/linux/mdio-dev.h b/include/linux/mdio-dev.h
new file mode 100644
index 0000000..cc4ed36
--- /dev/null
+++ b/include/linux/mdio-dev.h
@@ -0,0 +1,28 @@
+/*
+ * mdio-dev.h - mdio-bus driver, char device interface
+ *
+ * Copyright (C) 2018 Wei Li <liwei1412@163.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
+ */
+#ifndef _LINUX_MDIO_DEV_H
+#define _LINUX_MDIO_DEV_H
+
+#include <uapi/linux/mii.h>
+
+#define MDIO_MINORS MINORMASK
+
+#endif /* _LINUX_MDIO_DEV_H */
--
2.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] eth phy: add mdio bus char device interface
2018-06-18 3:32 [PATCH 1/2] eth phy: add mdio bus char device interface Wei Li
@ 2018-06-18 3:32 ` Wei Li
2018-06-18 6:52 ` kbuild test robot
2018-06-18 5:22 ` [PATCH 1/2] " kbuild test robot
2018-06-18 7:25 ` Andrew Lunn
2 siblings, 1 reply; 5+ messages in thread
From: Wei Li @ 2018-06-18 3:32 UTC (permalink / raw)
To: andrew, f.fainelli; +Cc: netdev
Add the notifier for the change of mdio bus, since i wanna that a char device
represents a mii_bus not a mdio_device.
Signed-off-by: Wei Li <liwei1412@163.com>
---
drivers/net/phy/mdio_bus.c | 21 ++++++++++++++++++++-
include/linux/mdio.h | 1 +
include/linux/phy.h | 2 ++
3 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 24b5511..3821dc8 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -240,10 +240,25 @@ static void mdiobus_release(struct device *d)
kfree(bus);
}
-static struct class mdio_bus_class = {
+struct class mdio_bus_class = {
.name = "mdio_bus",
.dev_release = mdiobus_release,
};
+EXPORT_SYMBOL_GPL(mdio_bus_class);
+
+static BLOCKING_NOTIFIER_HEAD(mdio_bus_notifier_list);
+
+int mdiobus_register_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(
+ &mdio_bus_notifier_list, nb);
+}
+
+int mdiobus_unregister_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(
+ &mdio_bus_notifier_list, nb);
+}
#if IS_ENABLED(CONFIG_OF_MDIO)
/* Helper function for of_mdio_find_bus */
@@ -418,6 +433,8 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
mdiobus_setup_mdiodev_from_board_info(bus, mdiobus_create_device);
bus->state = MDIOBUS_REGISTERED;
+ blocking_notifier_call_chain(&mdio_bus_notifier_list,
+ BUS_NOTIFY_ADD_DEVICE, &bus->dev);
pr_info("%s: probed\n", bus->name);
return 0;
@@ -446,6 +463,8 @@ void mdiobus_unregister(struct mii_bus *bus)
int i;
BUG_ON(bus->state != MDIOBUS_REGISTERED);
+ blocking_notifier_call_chain(&mdio_bus_notifier_list,
+ BUS_NOTIFY_DEL_DEVICE, &bus->dev);
bus->state = MDIOBUS_UNREGISTERED;
for (i = 0; i < PHY_MAX_ADDR; i++) {
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index 2cfffe5..29ab455 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -79,6 +79,7 @@ void mdio_device_reset(struct mdio_device *mdiodev, int value);
int mdio_driver_register(struct mdio_driver *drv);
void mdio_driver_unregister(struct mdio_driver *drv);
int mdio_device_bus_match(struct device *dev, struct device_driver *drv);
+extern struct class mdio_bus_class;
static inline bool mdio_phy_id_is_c45(int phy_id)
{
diff --git a/include/linux/phy.h b/include/linux/phy.h
index f0b5870..39f2609 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -246,6 +246,8 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner);
#define mdiobus_register(bus) __mdiobus_register(bus, THIS_MODULE)
void mdiobus_unregister(struct mii_bus *bus);
void mdiobus_free(struct mii_bus *bus);
+int mdiobus_register_notifier(struct notifier_block *nb);
+int mdiobus_unregister_notifier(struct notifier_block *nb);
struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv);
static inline struct mii_bus *devm_mdiobus_alloc(struct device *dev)
{
--
2.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] eth phy: add mdio bus char device interface
2018-06-18 3:32 [PATCH 1/2] eth phy: add mdio bus char device interface Wei Li
2018-06-18 3:32 ` [PATCH 2/2] " Wei Li
@ 2018-06-18 5:22 ` kbuild test robot
2018-06-18 7:25 ` Andrew Lunn
2 siblings, 0 replies; 5+ messages in thread
From: kbuild test robot @ 2018-06-18 5:22 UTC (permalink / raw)
To: Wei Li; +Cc: kbuild-all, andrew, f.fainelli, netdev
[-- Attachment #1: Type: text/plain, Size: 7227 bytes --]
Hi Wei,
I love your patch! Yet something to improve:
[auto build test ERROR on net-next/master]
[also build test ERROR on v4.18-rc1 next-20180615]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Wei-Li/eth-phy-add-mdio-bus-char-device-interface/20180618-115206
config: xtensa-allmodconfig (attached as .config)
compiler: xtensa-linux-gcc (GCC) 8.1.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=8.1.0 make.cross ARCH=xtensa
Note: the linux-review/Wei-Li/eth-phy-add-mdio-bus-char-device-interface/20180618-115206 HEAD 611497ceadd8527fc1e4aa0eb8936171906118dd builds fine.
It only hurts bisectibility.
All errors (new ones prefixed by >>):
drivers/net/phy/mdio-dev.c: In function 'mdiodev_attach_bus':
>> drivers/net/phy/mdio-dev.c:250:21: error: 'mdio_bus_class' undeclared (first use in this function); did you mean 'mdio_dev_class'?
if (dev->class != &mdio_bus_class)
^~~~~~~~~~~~~~
mdio_dev_class
drivers/net/phy/mdio-dev.c:250:21: note: each undeclared identifier is reported only once for each function it appears in
drivers/net/phy/mdio-dev.c: In function 'mdiodev_detach_bus':
drivers/net/phy/mdio-dev.c:288:21: error: 'mdio_bus_class' undeclared (first use in this function); did you mean 'mdio_dev_class'?
if (dev->class != &mdio_bus_class)
^~~~~~~~~~~~~~
mdio_dev_class
drivers/net/phy/mdio-dev.c: In function 'mdio_dev_init':
>> drivers/net/phy/mdio-dev.c:345:8: error: implicit declaration of function 'mdiobus_register_notifier'; did you mean 'bus_register_notifier'? [-Werror=implicit-function-declaration]
res = mdiobus_register_notifier(&mdiodev_notifier);
^~~~~~~~~~~~~~~~~~~~~~~~~
bus_register_notifier
drivers/net/phy/mdio-dev.c:350:25: error: 'mdio_bus_class' undeclared (first use in this function); did you mean 'mdio_dev_class'?
class_for_each_device(&mdio_bus_class, NULL, NULL, mdiodev_attach_bus);
^~~~~~~~~~~~~~
mdio_dev_class
drivers/net/phy/mdio-dev.c: In function 'mdio_dev_exit':
>> drivers/net/phy/mdio-dev.c:365:2: error: implicit declaration of function 'mdiobus_unregister_notifier'; did you mean 'bus_unregister_notifier'? [-Werror=implicit-function-declaration]
mdiobus_unregister_notifier(&mdiodev_notifier);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
bus_unregister_notifier
drivers/net/phy/mdio-dev.c:366:25: error: 'mdio_bus_class' undeclared (first use in this function); did you mean 'mdio_dev_class'?
class_for_each_device(&mdio_bus_class, NULL, NULL, mdiodev_detach_bus);
^~~~~~~~~~~~~~
mdio_dev_class
cc1: some warnings being treated as errors
vim +250 drivers/net/phy/mdio-dev.c
243
244 static int mdiodev_attach_bus(struct device *dev, void *dummy)
245 {
246 struct mii_bus *bus;
247 struct mdio_dev *mdio_dev;
248 int res;
249
> 250 if (dev->class != &mdio_bus_class)
251 return 0;
252 bus = to_mii_bus(dev);
253
254 mdio_dev = get_free_mdio_dev(bus);
255 if (IS_ERR(mdio_dev))
256 return PTR_ERR(mdio_dev);
257
258 cdev_init(&mdio_dev->cdev, &mdiodev_fops);
259 mdio_dev->cdev.owner = THIS_MODULE;
260 res = cdev_add(&mdio_dev->cdev, MKDEV(mdio_major, mdio_dev->nr), 1);
261 if (res)
262 goto error_cdev;
263
264 /* register this mdio device with the driver core */
265 mdio_dev->dev = device_create(mdio_dev_class, &bus->dev,
266 MKDEV(mdio_major, mdio_dev->nr), NULL,
267 "mdio-%d", mdio_dev->nr);
268 if (IS_ERR(mdio_dev->dev)) {
269 res = PTR_ERR(mdio_dev->dev);
270 goto error;
271 }
272
273 pr_debug("mdio-dev: bus [%s] registered as minor %d\n",
274 bus->name, mdio_dev->nr);
275 return 0;
276 error:
277 cdev_del(&mdio_dev->cdev);
278 error_cdev:
279 put_mdio_dev(mdio_dev);
280 return res;
281 }
282
283 static int mdiodev_detach_bus(struct device *dev, void *dummy)
284 {
285 struct mii_bus *bus;
286 struct mdio_dev *mdio_dev;
287
288 if (dev->class != &mdio_bus_class)
289 return 0;
290 bus = to_mii_bus(dev);
291
292 mdio_dev = mdio_dev_get_by_bus(bus);
293 if (!mdio_dev) /* attach_bus must have failed */
294 return 0;
295
296 cdev_del(&mdio_dev->cdev);
297 device_destroy(mdio_dev_class, MKDEV(mdio_major, mdio_dev->nr));
298 put_mdio_dev(mdio_dev);
299
300 pr_debug("mdio-dev: bus [%s] unregistered\n", bus->name);
301 return 0;
302 }
303
304 static int mdiodev_notifier_call(struct notifier_block *nb, unsigned long action,
305 void *data)
306 {
307 struct device *dev = data;
308
309 switch (action) {
310 case BUS_NOTIFY_ADD_DEVICE:
311 return mdiodev_attach_bus(dev, NULL);
312 case BUS_NOTIFY_DEL_DEVICE:
313 return mdiodev_detach_bus(dev, NULL);
314 }
315
316 return 0;
317 }
318
319 static struct notifier_block mdiodev_notifier = {
320 .notifier_call = mdiodev_notifier_call,
321 };
322
323 /*-------------------------------------------------------------------------*/
324
325 static int __init mdio_dev_init(void)
326 {
327 int res;
328 dev_t devid;
329
330 printk(KERN_INFO "mdio /dev entries driver\n");
331
332 res = alloc_chrdev_region(&devid, 0, MDIO_MINORS, "mdio");
333 if (res)
334 goto out;
335
336 mdio_major = MAJOR(devid);
337 mdio_dev_class = class_create(THIS_MODULE, "mdio-dev");
338 if (IS_ERR(mdio_dev_class)) {
339 res = PTR_ERR(mdio_dev_class);
340 goto out_unreg_chrdev;
341 }
342 mdio_dev_class->dev_groups = mdio_groups;
343
344 /* Keep track of buses which will be added or removed later */
> 345 res = mdiobus_register_notifier(&mdiodev_notifier);
346 if (res)
347 goto out_unreg_class;
348
349 /* Bind to already existing buses right away */
350 class_for_each_device(&mdio_bus_class, NULL, NULL, mdiodev_attach_bus);
351
352 return 0;
353
354 out_unreg_class:
355 class_destroy(mdio_dev_class);
356 out_unreg_chrdev:
357 unregister_chrdev_region(MKDEV(mdio_major, 0), MDIO_MINORS);
358 out:
359 printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__);
360 return res;
361 }
362
363 static void __exit mdio_dev_exit(void)
364 {
> 365 mdiobus_unregister_notifier(&mdiodev_notifier);
366 class_for_each_device(&mdio_bus_class, NULL, NULL, mdiodev_detach_bus);
367 class_destroy(mdio_dev_class);
368 unregister_chrdev_region(MKDEV(mdio_major, 0), MDIO_MINORS);
369 }
370
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 53907 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] eth phy: add mdio bus char device interface
2018-06-18 3:32 ` [PATCH 2/2] " Wei Li
@ 2018-06-18 6:52 ` kbuild test robot
0 siblings, 0 replies; 5+ messages in thread
From: kbuild test robot @ 2018-06-18 6:52 UTC (permalink / raw)
To: Wei Li; +Cc: kbuild-all, andrew, f.fainelli, netdev
[-- Attachment #1: Type: text/plain, Size: 1237 bytes --]
Hi Wei,
I love your patch! Yet something to improve:
[auto build test ERROR on net-next/master]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Wei-Li/eth-phy-add-mdio-bus-char-device-interface/20180618-115206
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 8.1.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=8.1.0 make.cross ARCH=ia64
All errors (new ones prefixed by >>):
ERROR: "ia64_delay_loop" [drivers/spi/spi-thunderx.ko] undefined!
ERROR: "__sw_hweight8" [drivers/net/wireless/mediatek/mt76/mt76.ko] undefined!
>> ERROR: "mdiobus_unregister_notifier" [drivers/net/phy/mdio-dev.ko] undefined!
>> ERROR: "mdiobus_register_notifier" [drivers/net/phy/mdio-dev.ko] undefined!
ERROR: "ia64_delay_loop" [drivers/net/phy/mdio-cavium.ko] undefined!
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 50794 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] eth phy: add mdio bus char device interface
2018-06-18 3:32 [PATCH 1/2] eth phy: add mdio bus char device interface Wei Li
2018-06-18 3:32 ` [PATCH 2/2] " Wei Li
2018-06-18 5:22 ` [PATCH 1/2] " kbuild test robot
@ 2018-06-18 7:25 ` Andrew Lunn
2 siblings, 0 replies; 5+ messages in thread
From: Andrew Lunn @ 2018-06-18 7:25 UTC (permalink / raw)
To: Wei Li; +Cc: f.fainelli, netdev
1;5202;0cOn Mon, Jun 18, 2018 at 11:32:12AM +0800, Wei Li wrote:
> Add the char device interface of mdio bus, like what i2c-dev or spidev do.
> They make it possible for user-space programs to access the bus directly.
>
Hi Wei
What is your real use case here?
What we don't want to do is add an easy to use API to allow vendors to
write user space binary blob propriatary Ethernet switch or PHY
drivers.
Also, it has been agreed that all new API's to the network stack need
to use netlink sockets, not IOCTLs.
The IOCTL interface you provide is very similar to what the stack
already has. Why cannot use you use that?
Andrew
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2018-06-18 7:25 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-06-18 3:32 [PATCH 1/2] eth phy: add mdio bus char device interface Wei Li
2018-06-18 3:32 ` [PATCH 2/2] " Wei Li
2018-06-18 6:52 ` kbuild test robot
2018-06-18 5:22 ` [PATCH 1/2] " kbuild test robot
2018-06-18 7:25 ` Andrew Lunn
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).