PSAS/ usbfs/ majorNumbersPatch

Background

Before the 2.6 kernel, major numbers were allocated like so:

error = register_chrdev(USB_MAJOR, "usb", &usb_fops);
        if (error)
                err("unable to get major %d for usb devices", USB_MAJOR);

However, register_chrdev only allocates 256 minor numbers. The 2.6 kernel allows for 2^20 or 1,048,576 minor numbers. The 2.6 kernel also breaks up the register_chrdev function into three calls.

1a) Dynamic Major Number Allocation

To allocate a major number dynamically using the 2.6 API, you must call alloc_chrdev_region. This specifies the major number, the first minor number that will be used, the count of minor numbers to allocate, and the name for the device driver:

int alloc_chrdev_region(dev_t *dev, unsigned int firstminor,
                        unsigned int count, char *name);

dev is an output only parameter.

1b) Static Major Number Allocation

To allocate a major number statically using the 2.6 API, you must call register_chrdev_region. This is very similar to alloc_chrdev_region, but should only be used when a driver has been assigned a static major number (as the USB driver is):

int register_chrdev_region(dev_t first, unsigned int count,
                           char *name);

2a) Stand-alone cdev Structures

To obtain a standalone cdev structure at runtime:

struct cdev *my_cdev = cdev_alloc( );
my_cdev->ops = &my_fops;

2b) Embedded cdev Structures

If you want to embed the cdev structure in another device-specific structure, you can initialize that pointer with a call to cdev_init:

void cdev_init(struct cdev *cdev, struct file_operations *fops);

Whichever way you initialize the cdev, you should also set the owner field in the structure to THIS_MODULE

3) Registering the Character Device

To tell the kernel about your character device, you need to register it with cdev_add:

int cdev_add(struct cdev *dev, dev_t num, unsigned int count);

Unregistering the Character Device

With the old call register_chrdev, you need to call unregister_chrdev to remove your character devices from the file system. The new method has a similar call:

void cdev_del(struct cdev *dev);

This method should be called in the device's cleanup fuctions.

Why do I care?

Some of the USB core files still use register_chrdev, and this patch will update them. The older register_chrdev method allocates 256 minor numbers (starting at zero). The patch will update the code with the new function calls, but keep the same behavior (i.e. only request 256 minor numbers). It will also create character devices for the 256 minor numbers using cdev_add.

References

Linux Device Drivers 3rd edition - Chapter 3 (Character Devices) explains the change in allocating minor numbers and initializing character devices (pp. 45-57).

Kernel Janitors has a post about replacing register_chrdev.