Commit 20818d45 authored by Philippe Gerum's avatar Philippe Gerum

net: create sysfs nodes for net devices

Each rtnet device registered with the stack is represented by a node
into /sys/devices/virtual/rtnet/.

Setting the address of the real device probed by the kernel into the
rtnet_device.sysbind field before calling rt_register_rtnetdev(),
causes the "adapter" symlink to be installed in the newly created
attribute directory, pointing at that device.

e.g.

static int probe_handler(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	...
	rtdev->sysbind = &pdev->dev;
	...
	ret = rt_register_rtnetdev(rtdev);
	...
}

$ ls -l /sys/devices/virtual/rtnet/
total 0
drwxr-xr-x    2 root     root             0 Mar 30 12:50 enp1s0
drwxr-xr-x    2 root     root             0 Mar 30 12:50 rtlo

$ ls -l /sys/devices/virtual/rtnet/enp1s0/
total 0
lrwxrwxrwx    1 root     root             0 Mar 30 12:51 adapter -> ../../../pci0000:00/0000:00:13.0/0000:01:00.0
lrwxrwxrwx    1 root     root             0 Mar 30 12:51 subsystem -> ../../../../class/rtnet
-rw-r--r--    1 root     root          4096 Mar 30 12:50 uevent
parent f75baabc
......@@ -70,6 +70,7 @@ struct rtnet_device {
unsigned int vers;
char name[IFNAMSIZ];
struct device *sysbind; /* device bound in sysfs (optional) */
unsigned long rmem_end; /* shmem "recv" end */
unsigned long rmem_start; /* shmem "recv" start */
......@@ -90,6 +91,7 @@ struct rtnet_device {
int ifindex;
atomic_t refcount;
struct device *sysdev; /* node in driver model for sysfs */
struct module *rt_owner; /* like classic owner, but *
* forces correct macro usage */
......
......@@ -28,10 +28,9 @@
#define __RTNET_INTERNAL_H_
#include <linux/module.h>
#include <linux/mutex.h>
#include <rtdm/driver.h>
#ifdef CONFIG_XENO_DRIVERS_NET_CHECKED
#define RTNET_ASSERT(expr, func) \
if (!(expr)) \
......@@ -76,6 +75,6 @@ extern const char rtnet_rtdm_provider_name[];
extern struct xnvfile_directory rtnet_proc_root;
#endif /* CONFIG_XENO_OPT_VFILE */
#include <linux/mutex.h>
extern struct class *rtnet_class;
#endif /* __RTNET_INTERNAL_H_ */
......@@ -507,8 +507,8 @@ int rt_register_rtnetdev(struct rtnet_device *rtdev)
ifindex = __rtdev_new_index();
if (ifindex < 0) {
mutex_unlock(&rtnet_devices_nrt_lock);
return ifindex;
err = ifindex;
goto fail;
}
rtdev->ifindex = ifindex;
......@@ -516,15 +516,27 @@ int rt_register_rtnetdev(struct rtnet_device *rtdev)
rtdev_alloc_name(rtdev, rtdev->name);
if (__rtdev_get_by_name(rtdev->name) != NULL) {
mutex_unlock(&rtnet_devices_nrt_lock);
return -EEXIST;
err = -EEXIST;
goto fail;
}
err = rtdev_map_all_rtskbs(rtdev);
if (err) {
mutex_unlock(&rtnet_devices_nrt_lock);
return err;
rtdev->sysdev = device_create(rtnet_class, NULL,
MKDEV(0, rtdev->ifindex), rtdev, rtdev->name);
if (rtdev->sysdev == NULL) {
err = PTR_ERR(rtdev->sysdev);
goto fail;
}
if (rtdev->sysbind) {
err = sysfs_create_link(&rtdev->sysdev->kobj,
&rtdev->sysbind->kobj, "adapter");
if (err)
goto fail_link;
}
err = rtdev_map_all_rtskbs(rtdev);
if (err)
goto fail_map;
rtdm_lock_get_irqsave(&rtnet_devices_rt_lock, context);
......@@ -532,8 +544,8 @@ int rt_register_rtnetdev(struct rtnet_device *rtdev)
/* allow only one loopback device */
if (loopback_device) {
rtdm_lock_put_irqrestore(&rtnet_devices_rt_lock, context);
mutex_unlock(&rtnet_devices_nrt_lock);
return -EEXIST;
err = -EEXIST;
goto fail_loopback;
}
loopback_device = rtdev;
}
......@@ -555,6 +567,18 @@ int rt_register_rtnetdev(struct rtnet_device *rtdev)
printk("RTnet: registered %s\n", rtdev->name);
return 0;
fail_loopback:
rtdev_unmap_all_rtskbs(rtdev);
fail_map:
if (rtdev->sysbind)
sysfs_remove_link(&rtdev->sysdev->kobj, "adapter");
fail_link:
device_destroy(rtnet_class, MKDEV(0, rtdev->ifindex));
fail:
mutex_unlock(&rtnet_devices_nrt_lock);
return err;
}
......@@ -569,11 +593,15 @@ int rt_unregister_rtnetdev(struct rtnet_device *rtdev)
struct rtdev_event_hook *hook;
rtdm_lockctx_t context;
RTNET_ASSERT(rtdev->ifindex != 0,
printk("RTnet: device %s/%p was not registered\n", rtdev->name, rtdev);
return -ENODEV;);
if (rtdev->sysbind)
sysfs_remove_link(&rtdev->sysdev->kobj, "adapter");
device_destroy(rtnet_class, MKDEV(0, rtdev->ifindex));
mutex_lock(&rtnet_devices_nrt_lock);
rtdm_lock_get_irqsave(&rtnet_devices_rt_lock, context);
......
......@@ -39,6 +39,8 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("RTnet stack core");
struct class *rtnet_class;
struct rtnet_mgr STACK_manager;
struct rtnet_mgr RTDEV_manager;
......@@ -323,6 +325,10 @@ int __init rtnet_init(void)
printk("\n*** RTnet for Xenomai v" XENO_VERSION_STRING " ***\n\n");
printk("RTnet: initialising real-time networking\n");
rtnet_class = class_create(THIS_MODULE, "rtnet");
if (IS_ERR(rtnet_class))
return PTR_ERR(rtnet_class);
if ((err = rtskb_pools_init()) != 0)
goto err_out1;
......@@ -371,6 +377,8 @@ err_out2:
rtskb_pools_release();
err_out1:
class_destroy(rtnet_class);
return err;
}
......@@ -397,6 +405,8 @@ void __exit rtnet_release(void)
rtnet_proc_unregister();
#endif
class_destroy(rtnet_class);
printk("RTnet: unloaded\n");
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment