Kernel Newbies Archive on lore.kernel.org
 help / color / Atom feed
* Device file not appearing
@ 2021-03-17 15:52 Gregory Anders
  2021-03-17 15:59 ` Greg KH
  0 siblings, 1 reply; 9+ messages in thread
From: Gregory Anders @ 2021-03-17 15:52 UTC (permalink / raw)
  To: kernelnewbies

Hi all,

I'm writing a char device driver and am having trouble getting the file 
to appear under /dev.

This isn't my first rodeo: in fact, I've written a few other drivers in 
the past and they have all worked as expected. This driver is based on 
the source code of those other drivers, so I'm fairly confident I'm 
doing everything correctly. So I'm stumped and looking for help.

Here is what I have in my init function:

     #define DRIVER_NAME "foo"

     static int __init mod_init(void)
     {
         dev_t devno;
         my_class = class_create(THIS_MODULE, DRIVER_NAME);
         ret = alloc_chrdev_region(&devno, 0, MAX_DEVICES, DRIVER_NAME);

         my_major = MAJOR(devno);

         ...
     }

(Note that for brevity I'm omitting a lot of boilerplate/error handling, 
etc. But you can assume it's all there).

My driver is also a network driver; in fact, it's *primarily* a network 
driver and it provides a char device file that is used to configure the 
hardware. I am creating the char device whenever the network device is 
first opened (e.g. 'netdev_open' below is the 'ndo_open' field of the 
'struct netdev_ops'):

     struct private_data {
         struct cdev cdev;
         ...
     }

     static int netdev_open(struct net_device *dev)
     {
         struct private_data *priv = netdev_priv(dev);
         dev_t devno;
         int minor;
         struct device *d;

         minor = ida_alloc_max(&ida, MAX_DEVICES, GFP_KERNEL);

         devno = MKDEV(my_major, minor);
         cdev_init(&priv->cdev, &my_fops);
         cdev_add(&priv->cdev, devno, 1);

         /* This should create a device node with the same name as the
          * network interface, e.g. foo0
          */
         d = device_create(my_class, NULL, devno, priv, dev->name);
         if (IS_ERR(d)) {
             ...
         }

         ...
     }

Again, I'm omitting the error checking for the sake of brevity, but it 
is there in the actual code. This function runs successfully and the 
network device is successfully opened. The 'device_create' function does 
not return an error, but there is nothing beneath /dev as I would 
expect.

I'm really stumped here because everything I've been able to find online 
says that 'device_create' ought to create that device file. I can see my 
class under /sys/class/ and that directory contains a directory with the 
name of the device:

     $ ls -1 /sys/class/my_class/
     foo0

so it looks like the char device *is* being created, there's just no 
corresponding entry under /dev.

Anyway, I know that's a lot of info. If you've made it this far, thanks 
for reading. If you have any insight/advice/suggestions for me I'd 
greatly appreciate it!

Thanks,

Greg

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Device file not appearing
  2021-03-17 15:52 Device file not appearing Gregory Anders
@ 2021-03-17 15:59 ` Greg KH
  2021-03-17 16:13   ` Gregory Anders
  0 siblings, 1 reply; 9+ messages in thread
From: Greg KH @ 2021-03-17 15:59 UTC (permalink / raw)
  To: kernelnewbies

On Wed, Mar 17, 2021 at 09:52:32AM -0600, Gregory Anders wrote:
> Hi all,
> 
> I'm writing a char device driver and am having trouble getting the file to
> appear under /dev.
> 
> This isn't my first rodeo: in fact, I've written a few other drivers in the
> past and they have all worked as expected. This driver is based on the
> source code of those other drivers, so I'm fairly confident I'm doing
> everything correctly. So I'm stumped and looking for help.
> 
> Here is what I have in my init function:
> 
>     #define DRIVER_NAME "foo"
> 
>     static int __init mod_init(void)
>     {
>         dev_t devno;
>         my_class = class_create(THIS_MODULE, DRIVER_NAME);
>         ret = alloc_chrdev_region(&devno, 0, MAX_DEVICES, DRIVER_NAME);
> 
>         my_major = MAJOR(devno);
> 
>         ...
>     }
> 
> (Note that for brevity I'm omitting a lot of boilerplate/error handling,
> etc. But you can assume it's all there).
> 
> My driver is also a network driver; in fact, it's *primarily* a network
> driver and it provides a char device file that is used to configure the
> hardware. I am creating the char device whenever the network device is first
> opened (e.g. 'netdev_open' below is the 'ndo_open' field of the 'struct
> netdev_ops'):
> 
>     struct private_data {
>         struct cdev cdev;
>         ...
>     }
> 
>     static int netdev_open(struct net_device *dev)
>     {
>         struct private_data *priv = netdev_priv(dev);
>         dev_t devno;
>         int minor;
>         struct device *d;
> 
>         minor = ida_alloc_max(&ida, MAX_DEVICES, GFP_KERNEL);
> 
>         devno = MKDEV(my_major, minor);
>         cdev_init(&priv->cdev, &my_fops);
>         cdev_add(&priv->cdev, devno, 1);
> 
>         /* This should create a device node with the same name as the
>          * network interface, e.g. foo0
>          */
>         d = device_create(my_class, NULL, devno, priv, dev->name);
>         if (IS_ERR(d)) {
>             ...
>         }
> 
>         ...
>     }
> 
> Again, I'm omitting the error checking for the sake of brevity, but it is
> there in the actual code. This function runs successfully and the network
> device is successfully opened. The 'device_create' function does not return
> an error, but there is nothing beneath /dev as I would expect.
> 
> I'm really stumped here because everything I've been able to find online
> says that 'device_create' ought to create that device file. I can see my
> class under /sys/class/ and that directory contains a directory with the
> name of the device:
> 
>     $ ls -1 /sys/class/my_class/
>     foo0
> 
> so it looks like the char device *is* being created, there's just no
> corresponding entry under /dev.

Is your char device listed in /sys/dev/char/ ?

If not, then you have something wrong with your call to device_create().

If so, then you need to look at whatever tool is creating your device
nodes in /dev.  Usually the kernel handles this with devtmpfs, but I do
not know what your system uses for this.

Do you have a pointer to the real source code anywhere to be able to see
it better to see if you are doing something wrong with the call to
device_create()?

Also, why a full major?  Why not just use the misc_dev api instead that
does all of the above "housekeeping" for you automagically?

thanks,

greg k-h

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Device file not appearing
  2021-03-17 15:59 ` Greg KH
@ 2021-03-17 16:13   ` Gregory Anders
  2021-03-17 16:16     ` Greg KH
  0 siblings, 1 reply; 9+ messages in thread
From: Gregory Anders @ 2021-03-17 16:13 UTC (permalink / raw)
  To: Greg KH; +Cc: kernelnewbies

On Wed, 17 Mar 2021 16:59:08 +0100, Greg KH <greg@kroah.com> wrote:
>Is your char device listed in /sys/dev/char/ ?
>
>If not, then you have something wrong with your call to device_create().
>
>If so, then you need to look at whatever tool is creating your device
>nodes in /dev.  Usually the kernel handles this with devtmpfs, but I do
>not know what your system uses for this.

Indeed it is. I am working with a fairly minimal system on a Xilinx 
Microblaze soft-core CPU. I have udev installed, but I'm not sure about 
devtmpfs. I'll start digging in that direction and see what I find.

>Also, why a full major?  Why not just use the misc_dev api instead that
>does all of the above "housekeeping" for you automagically?

Simply because I wasn't aware of the misc_dev API :) But that does look 
like a nice abstraction that will save me some boilerplate, so thanks 
for pointing that out.

Thanks,

Greg

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Device file not appearing
  2021-03-17 16:13   ` Gregory Anders
@ 2021-03-17 16:16     ` Greg KH
  2021-03-17 16:56       ` Gregory Anders
  0 siblings, 1 reply; 9+ messages in thread
From: Greg KH @ 2021-03-17 16:16 UTC (permalink / raw)
  To: kernelnewbies

On Wed, Mar 17, 2021 at 10:13:22AM -0600, Gregory Anders wrote:
> On Wed, 17 Mar 2021 16:59:08 +0100, Greg KH <greg@kroah.com> wrote:
> > Is your char device listed in /sys/dev/char/ ?
> > 
> > If not, then you have something wrong with your call to device_create().
> > 
> > If so, then you need to look at whatever tool is creating your device
> > nodes in /dev.  Usually the kernel handles this with devtmpfs, but I do
> > not know what your system uses for this.
> 
> Indeed it is. I am working with a fairly minimal system on a Xilinx
> Microblaze soft-core CPU. I have udev installed, but I'm not sure about
> devtmpfs. I'll start digging in that direction and see what I find.

udev does not do device node creation anymore (as of a decade or so),
you should make sure devtmpfs is mounted at /dev/ in order for this to
work properly.

good luck!

greg k-h

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Device file not appearing
  2021-03-17 16:16     ` Greg KH
@ 2021-03-17 16:56       ` Gregory Anders
  2021-03-17 17:05         ` Gregory Anders
  2021-03-17 17:15         ` Greg KH
  0 siblings, 2 replies; 9+ messages in thread
From: Gregory Anders @ 2021-03-17 16:56 UTC (permalink / raw)
  To: Greg KH; +Cc: kernelnewbies

On Wed, 17 Mar 2021 17:16:04 +0100, Greg KH <greg@kroah.com> wrote:
>udev does not do device node creation anymore (as of a decade or so),
>you should make sure devtmpfs is mounted at /dev/ in order for this to
>work properly.
>
>good luck!
>
>greg k-h

I switched over to using the miscdevice API and the situation is the 
same. Nothing under /dev, but I can see my device under /sys/dev/char 
(it now also exists under /sys/devices/virtual/misc/, as expected).

I verified that devtmpfs is enabled in the kernel config 
(CONFIG_DEVTMPFS=y and CONFIG_DEVTMPFS_MOUNT=y) and also see that it is 
mounted on /dev:

     # cat /proc/mounts
     root@xilinx-kcu105-2020_2:~# cat /proc/mounts
     192.168.0.116:/data/nfs/root / nfs rw,relatime,vers=3,rsize=4096,wsize=4096,namlen=255,hard,nolock,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=192.168.0.116,mountvers=3,mountproto=tcp,local_lock=all,addr=192.168.0.116 0 0
     devtmpfs /dev devtmpfs rw,relatime,size=1026312k,nr_inodes=185478,mode=755 0 0
     proc /proc proc rw,relatime 0 0
     sysfs /sys sysfs rw,relatime 0 0
     tmpfs /run tmpfs rw,nosuid,nodev,mode=755 0 0
     tmpfs /var/volatile tmpfs rw,relatime 0 0
     tmpfs /dev tmpfs rw,relatime,size=64k,mode=755 0 0
     devpts /dev/pts devpts rw,relatime,mode=600,ptmxmode=000 0 0

I notice that it lists /dev as both devtmpfs (line 2) as well as tmpfs 
(the second line from the bottom). Could that be an issue? I'm not sure 
how or why /dev is being mounted as tmpfs in addition to devtmpfs.

Thanks,

Greg

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Device file not appearing
  2021-03-17 16:56       ` Gregory Anders
@ 2021-03-17 17:05         ` Gregory Anders
  2021-03-17 17:15         ` Greg KH
  1 sibling, 0 replies; 9+ messages in thread
From: Gregory Anders @ 2021-03-17 17:05 UTC (permalink / raw)
  To: Greg KH, kernelnewbies

On Wed, 17 Mar 2021 10:56:34 -0600, Gregory Anders <greg@gpanders.com> wrote:
>I switched over to using the miscdevice API and the situation is the 
>same. Nothing under /dev, but I can see my device under /sys/dev/char 
>(it now also exists under /sys/devices/virtual/misc/, as expected).
>
>I verified that devtmpfs is enabled in the kernel config 
>(CONFIG_DEVTMPFS=y and CONFIG_DEVTMPFS_MOUNT=y) and also see that it 
>is mounted on /dev:
>
>    # cat /proc/mounts
>    root@xilinx-kcu105-2020_2:~# cat /proc/mounts
>    192.168.0.116:/data/nfs/root / nfs rw,relatime,vers=3,rsize=4096,wsize=4096,namlen=255,hard,nolock,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=192.168.0.116,mountvers=3,mountproto=tcp,local_lock=all,addr=192.168.0.116 0 0
>    devtmpfs /dev devtmpfs rw,relatime,size=1026312k,nr_inodes=185478,mode=755 0 0
>    proc /proc proc rw,relatime 0 0
>    sysfs /sys sysfs rw,relatime 0 0
>    tmpfs /run tmpfs rw,nosuid,nodev,mode=755 0 0
>    tmpfs /var/volatile tmpfs rw,relatime 0 0
>    tmpfs /dev tmpfs rw,relatime,size=64k,mode=755 0 0
>    devpts /dev/pts devpts rw,relatime,mode=600,ptmxmode=000 0 0
>
>I notice that it lists /dev as both devtmpfs (line 2) as well as tmpfs 
>(the second line from the bottom). Could that be an issue? I'm not 
>sure how or why /dev is being mounted as tmpfs in addition to 
>devtmpfs.
>
>Thanks,
>
>Greg

One other data point: there are 3 other misc devices on the system, and 
all of them are correctly listed under /dev:

     # ls -1 /sys/class/misc
     cpu_dma_latency
     loop-control
     foo0
     vga_arbiter

     # ls -1 /dev/{cpu_dma_latency,loop-control,vga_arbiter}
     /dev/cpu_dma_latency
     /dev/loop-control
     /dev/vga_arbiter

Greg

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Device file not appearing
  2021-03-17 16:56       ` Gregory Anders
  2021-03-17 17:05         ` Gregory Anders
@ 2021-03-17 17:15         ` Greg KH
  2021-03-17 18:26           ` Gregory Anders
  1 sibling, 1 reply; 9+ messages in thread
From: Greg KH @ 2021-03-17 17:15 UTC (permalink / raw)
  To: kernelnewbies

On Wed, Mar 17, 2021 at 10:56:34AM -0600, Gregory Anders wrote:
> On Wed, 17 Mar 2021 17:16:04 +0100, Greg KH <greg@kroah.com> wrote:
> > udev does not do device node creation anymore (as of a decade or so),
> > you should make sure devtmpfs is mounted at /dev/ in order for this to
> > work properly.
> > 
> > good luck!
> > 
> > greg k-h
> 
> I switched over to using the miscdevice API and the situation is the same.
> Nothing under /dev, but I can see my device under /sys/dev/char (it now also
> exists under /sys/devices/virtual/misc/, as expected).

Then this is a userspace issue, not the kernel :)

> I verified that devtmpfs is enabled in the kernel config (CONFIG_DEVTMPFS=y
> and CONFIG_DEVTMPFS_MOUNT=y) and also see that it is mounted on /dev:
> 
>     # cat /proc/mounts
>     root@xilinx-kcu105-2020_2:~# cat /proc/mounts
>     192.168.0.116:/data/nfs/root / nfs rw,relatime,vers=3,rsize=4096,wsize=4096,namlen=255,hard,nolock,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=192.168.0.116,mountvers=3,mountproto=tcp,local_lock=all,addr=192.168.0.116 0 0
>     devtmpfs /dev devtmpfs rw,relatime,size=1026312k,nr_inodes=185478,mode=755 0 0
>     proc /proc proc rw,relatime 0 0
>     sysfs /sys sysfs rw,relatime 0 0
>     tmpfs /run tmpfs rw,nosuid,nodev,mode=755 0 0
>     tmpfs /var/volatile tmpfs rw,relatime 0 0
>     tmpfs /dev tmpfs rw,relatime,size=64k,mode=755 0 0
>     devpts /dev/pts devpts rw,relatime,mode=600,ptmxmode=000 0 0
> 
> I notice that it lists /dev as both devtmpfs (line 2) as well as tmpfs (the
> second line from the bottom). Could that be an issue? I'm not sure how or
> why /dev is being mounted as tmpfs in addition to devtmpfs.

Looks like you have mounted tmpfs on top of devtmpfs, which seems very
odd.  Try unmounting the tmpfs instance and see if the node really is
there in devtmpfs.

Or better yet, mount devtmpfs somewhere else right now to see if the
node is there.

Good luck with your userspace mount maze!

greg k-h

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Device file not appearing
  2021-03-17 17:15         ` Greg KH
@ 2021-03-17 18:26           ` Gregory Anders
  0 siblings, 0 replies; 9+ messages in thread
From: Gregory Anders @ 2021-03-17 18:26 UTC (permalink / raw)
  To: Greg KH; +Cc: kernelnewbies

On Wed, 17 Mar 2021 18:15:27 +0100, Greg KH <greg@kroah.com> wrote:
>Looks like you have mounted tmpfs on top of devtmpfs, which seems very
>odd.  Try unmounting the tmpfs instance and see if the node really is
>there in devtmpfs.
>
>Or better yet, mount devtmpfs somewhere else right now to see if the
>node is there.
>
>Good luck with your userspace mount maze!
>
>greg k-h

Ok I finally tracked down what was going on. The embedded distribution I 
am using uses mdev. mdev has an init script that mounts tmpfs on /dev, 
which is why devtmpfs wasn't working as expected.

mdev requires the kernel option CONFIG_UEVENT_HELPER=y which was not 
enabled in my configuration (it even has a scary help description, 
something along the lines of "this should not be used", so I didn't 
think to enable it until I saw it mentioned somewhere else). After 
enabling that, the device file appears under /dev.

Thanks for your help Greg!

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Device file not appearing
@ 2021-03-16 20:25 Gregory Anders
  0 siblings, 0 replies; 9+ messages in thread
From: Gregory Anders @ 2021-03-16 20:25 UTC (permalink / raw)
  To: kernelnewbies

Hi all,

I'm writing a char device driver and am having trouble getting the file 
to appear under /dev.

This isn't my first rodeo: in fact, I've written a few other drivers in 
the past and they have all worked as expected. This driver is based on 
the source code of those other drivers, so I'm fairly confident I'm 
doing everything correctly. So I'm stumped and looking for help.

Here is what I have in my init function:

     #define DRIVER_NAME "foo"

     static int __init mod_init(void)
     {
         dev_t devno;
         my_class = class_create(THIS_MODULE, DRIVER_NAME);
         ret = alloc_chrdev_region(&devno, 0, MAX_DEVICES, DRIVER_NAME);

         my_major = MAJOR(devno);

         ...
     }

(Note that for brevity I'm omitting a lot of boilerplate/error handling, 
etc. But you can assume it's all there).

My driver is also a network driver; in fact, it's *primarily* a network 
driver and it provides a char device file that is used to configure the 
hardware. I am creating the char device whenever the network device is 
first opened (e.g. 'netdev_open' below is the 'ndo_open' field of the 
'struct netdev_ops'):

     struct private_data {
         struct cdev cdev;
         ...
     }

     static int netdev_open(struct net_device *dev)
     {
         struct private_data *priv = netdev_priv(dev);
         dev_t devno;
         int minor;
         struct device *d;

         minor = ida_alloc_max(&ida, MAX_DEVICES, GFP_KERNEL);

         devno = MKDEV(my_major, minor);
         cdev_init(&priv->cdev, &my_fops);
         cdev_add(&priv->cdev, devno, 1);

         /* This should create a device node with the same name as the
          * network interface, e.g. foo0
          */
         d = device_create(my_class, NULL, devno, priv, dev->name);
         if (IS_ERR(d)) {
             ...
         }

         ...
     }

Again, I'm omitting the error checking for the sake of brevity, but it 
is there in the actual code. This function runs successfully and the 
network device is successfully opened. The 'device_create' function does 
not return an error, but there is nothing beneath /dev as I would 
expect.

I'm really stumped here because everything I've been able to find online 
says that 'device_create' ought to create that device file. I can see my 
class under /sys/class/ and that directory contains a directory with the 
name of the device:

     $ ls -1 /sys/class/my_class/
     foo0

so it looks like the char device *is* being created, there's just no 
corresponding entry under /dev.

Anyway, I know that's a lot of info. If you've made it this far, thanks 
for reading. If you have any insight/advice/suggestions for me I'd 
greatly appreciate it!

Thanks,

Greg

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, back to index

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-17 15:52 Device file not appearing Gregory Anders
2021-03-17 15:59 ` Greg KH
2021-03-17 16:13   ` Gregory Anders
2021-03-17 16:16     ` Greg KH
2021-03-17 16:56       ` Gregory Anders
2021-03-17 17:05         ` Gregory Anders
2021-03-17 17:15         ` Greg KH
2021-03-17 18:26           ` Gregory Anders
  -- strict thread matches above, loose matches on Subject: below --
2021-03-16 20:25 Gregory Anders

Kernel Newbies Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/kernelnewbies/0 kernelnewbies/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 kernelnewbies kernelnewbies/ https://lore.kernel.org/kernelnewbies \
		kernelnewbies@kernelnewbies.org
	public-inbox-index kernelnewbies

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernelnewbies.kernelnewbies


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git