Re: alloc_chrdev_region/unregister_chrdev_region - Issue

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



May be at time itself the kernel confirms all the registered devices
and assign NULL to all remaining.
Not sure,  but will figure that out from  the code for sure.

On Sat, Dec 13, 2008 at 1:32 PM, Chetan Nanda <chetannanda@xxxxxxxxx> wrote:
>
>
> On Tue, Dec 9, 2008 at 11:34 AM, Chetan Nanda <chetannanda@xxxxxxxxx> wrote:
>>
>>
>> On Mon, Dec 8, 2008 at 9:35 PM, Sandeep K Sinha <sandeepksinha@xxxxxxxxx>
>> wrote:
>>>
>>> On Mon, Dec 8, 2008 at 7:45 PM, Chetan Nanda <chetannanda@xxxxxxxxx>
>>> wrote:
>>> > Hi,
>>> >
>>> > I am using 'alloc_chrdev_region' for registering char device range and
>>> > then
>>> > 'unregister_chrdev_region' for un-registering it.
>>> > But on each insmod I am getting MAJOR number as one less then that of
>>> > previous time.
>>>
>>>  /* temporary */
>>>  96         if (major == 0) {
>>>  97                 for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) {
>>>  98                         if (chrdevs[i] == NULL)
>>>  99                                 break;
>>> 100                 }
>>> 101
>>> 102                 if (i == 0) {
>>> 103                         ret = -EBUSY;
>>> 104                         goto out;
>>> 105                 }
>>> 106                 major = i;
>>> 107                 ret = major;
>>> 108         }
>>> 109
>>>
>>> REF: http://lxr.oss.org.cn/source/fs/char_dev.c#L80
>>> >
>>> > On seeing the code (unregister_chrdev_region) it seems that it just
>>> > kfree
>>> > the chrdevs[] entry but not set it to NULL which cause for new
>>> > entry in chrdevs[].
>>> >
>>>
>>> Thats right, it is like that.
>>> Dont have much idea regarding the same. I think we should assign a
>>> NULL to it for sure.
>>
>> I have tried with setting chrdevs entry to NULL after kfree but it didn't
>> help
>>
>> void unregister_chrdev_region(dev_t from, unsigned count)
>> {
>>   dev_t to = from + count;
>>   dev_t n, next;
>>
>>   for (n = from; n < to; n = next) {
>>     next = MKDEV(MAJOR(n)+1, 0);
>>     if (next > to)
>>       next = to;
>>     kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
>>   }
>>   /*I do it*/
>>   chrdevs[MAJOR(n)] = NULL; //<--- setting it to null here
>> }
>>
>> It seems that problem is in my test driver implementation.
>> Here are my init and clean-up function:
>>
>> int __init
>> cmos_init(void)
>> {
>>     int i;
>>
>>     /*Clear cmosdev_array struct*/
>>     memset((void *)&cmosdev_array, 0 , sizeof(struct cmos_dev*) *
>> NUM_CMOS_BANKS);
>>
>>     /* Request dynamic allocation of a device major number */
>>     if (alloc_chrdev_region(&cmos_dev_number, 0, NUM_CMOS_BANKS,
>> DEVICE_NAME) < 0)
>>     {
>>         printk(KERN_DEBUG "Can't register device\n"); return -1;
>>     }
>>
>>     /* Populate sysfs entries */
>>     cmos_class = class_create(THIS_MODULE, DEVICE_NAME);
>>
>>     for (i=0; i<NUM_CMOS_BANKS; i++)
>>     {
>>         /* Allocate memory for the per-device structure */
>>         cmos_devp = kmalloc(sizeof(struct cmos_dev), GFP_KERNEL);
>>         if (!cmos_devp)
>>         {
>>             printk("Bad Kmalloc\n"); return 1;
>>         }
>>         cmosdev_array[i] = cmos_devp;
>>
>>         /* Request I/O region */
>>         sprintf(cmos_devp->name, "cmos%d", i);
>>         if (!(request_region(addrports[i], 2, cmos_devp->name)))
>>         {
>>             printk("cmos: I/O port 0x%x is not free.\n", addrports[i]);
>>             return -EIO;
>>         }
>>
>>         /* Fill in the bank number to correlate this device
>>          *         with the corresponding CMOS bank */
>>         cmos_devp->bank_number = i;
>>
>>         /* Connect the file operations with the cdev */
>>         cdev_init(&cmos_devp->cdev, &cmos_fops);
>>         cmos_devp->cdev.owner = THIS_MODULE;
>>
>>         /* Connect the major/minor number to the cdev */
>>         if(cdev_add(&cmos_devp->cdev,(cmos_dev_number + i),1))
>>         {
>>             printk("Bad cdev\n");
>>             return 1;
>>         }
>>
>>         /* Send uevents to udev, so it'll create /dev nodes */
>>         class_device_create(cmos_class, NULL, (cmos_dev_number + i),NULL,
>> "cmos%d", i);
>>     }
>>     printk("CMOS Driver Initialized.\n");
>>     return 0;
>> }
>>
>> //clean-up function
>> /* Driver Exit */
>> void __exit
>> cmos_cleanup(void)
>> {
>>     int i;
>>
>>     /* Release the major number */
>>     unregister_chrdev_region(MAJOR(cmos_dev_number), NUM_CMOS_BANKS);
>>
>>     /* Release I/O region */
>>     for (i=0; i<NUM_CMOS_BANKS; i++)
>>     {
>>         /* Remove the cdev */
>>         cdev_del(&(cmosdev_array[i]->cdev));
>>         class_device_destroy(cmos_class, MKDEV(MAJOR(cmos_dev_number),
>> i));
>>         release_region(addrports[i], 2);
>>         kfree(cmosdev_array[i]);
>>     }
>>
>>     /* Destroy cmos_class */
>>     class_destroy(cmos_class);
>>     return;
>> }
>>
>> Please provide me any feedback on this piece of code.
>
> This issue is resolved, problem is indeed in my driver cleanup function.
> unregister_chrdev_region(
> MAJOR(cmos_dev_number), NUM_CMOS_BANKS);
> Instead of passing MAJOR(cmos_dev_number) passing 'cmod_dev_number' works.
>
> But still i an not able to figure out that how chrdevs[i] (in fs/char_dev.c)
> is getting NULL in unregister_chrdev_region
>>
>>
>>>
>>> > Thanks,
>>> > Chetan Nanda
>>> >
>>>
>>>
>>>
>>> --
>>> Regards,
>>> Sandeep.
>>>
>>>
>>>
>>>
>>>
>>>
>>> "To learn is to change. Education is a process that changes the learner."
>>
>
>



-- 
Regards,
Sandeep.





 	
"To learn is to change. Education is a process that changes the learner."

--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux