how to allocate 9MB of memory in kernel ?
Hi all,
I need to allocate 9 MB of memory in to the kernel space which i need to mmap for the application to access.
I need to know what could be the best possible way of doing the same.
Please share your experience in this regard .
Thank you in advance
----Misbah <><
Signature · 2 lines
View this message in context: http://www.nabble.com/how-to-allocate-9MB-of-memory-in-kernel---tp18503022p18503022.html Sent from the linuxppc-embedded mailing list archive at Nabble.com.
Misbah khan ha scritto:
Quoted 5 lines
Hi all,
I need to allocate 9 MB of memory in to the kernel space which i need to mmap for the application to access.
Quoted 7 lines
I need to know what could be the best possible way of doing the same.
Please share your experience in this regard .
Thank you in advance
----Misbah <><
You can use the mem option to tell to the kernel that you've got less ram you really have. However you can read Linux device drivers chapter 8 "Obtaining Large Buffers" :).
Regards,
Signature · 7 lines
Marco Stornelli Embedded Software Engineer CoRiTeL - Consorzio di Ricerca sulle Telecomunicazioni http://www.coritel.it [email protected] +39 06 72582838
Quoted 3 lines
Quoted 3 lines
You can use the mem option to tell to the kernel that you've got less ram you really have.
I really didnt got the point you made. Can you please elaborate it for my understanding.
Quoted 1 line
Quoted 1 line
However you can read Linux device drivers chapter 8
i dont need to allocate large memory at the boot time also vmalloc and kmalloc i cant use as it can allocate free page up to 128kb, hence if you could suggest me a better technique i would really appriciate .
---Misbah <><
Quoted 34 lines · Marco Stornelli
Misbah khan ha scritto:
Quoted 5 lines
Hi all,
I need to allocate 9 MB of memory in to the kernel space which i need to mmap for the application to access.
Quoted 7 lines
I need to know what could be the best possible way of doing the same.
Please share your experience in this regard .
Thank you in advance
----Misbah <><
You can use the mem option to tell to the kernel that you've got less ram you really have. However you can read Linux device drivers chapter 8 "Obtaining Large Buffers" :).
Regards,
Signature · 11 lines
Marco Stornelli Embedded Software Engineer CoRiTeL - Consorzio di Ricerca sulle Telecomunicazioni http://www.coritel.it [email protected] +39 06 72582838 _______________________________________________ Linuxppc-embedded mailing list [email protected] https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Signature · 2 lines
View this message in context: http://www.nabble.com/how-to-allocate-9MB-of-memory-in-kernel---tp18503022p18503965.html Sent from the linuxppc-embedded mailing list archive at Nabble.com.
Misbah khan ha scritto:
Quoted 3 lines
Quoted 1 line
Quoted 1 line
You can use the mem option to tell to the kernel that you've got less ram you really have.
I really didnt got the point you made. Can you please elaborate it for my understanding.
If you've got 128MB of ram you can use the mem option to tell to the kernel the it can use only (128 - 9) MB of ram, after that you can use that chunk of ram, however I think it's not the case if your goal is to use a sdram as you said in the previous message.
Quoted 5 lines
Quoted 1 line
Quoted 1 line
However you can read Linux device drivers chapter 8
i dont need to allocate large memory at the boot time also vmalloc and kmalloc i cant use as it can allocate free page up to 128kb, hence if you could suggest me a better technique i would really appriciate .
The problem about 128KB is only for kmalloc. If I understood correctly you need only to remap the 9MB of your sdram.
Quoted 36 lines
---Misbah <><
Quoted 31 lines · Marco Stornelli
Misbah khan ha scritto:
Quoted 5 lines
Hi all,
I need to allocate 9 MB of memory in to the kernel space which i need to mmap for the application to access.
Quoted 7 lines
I need to know what could be the best possible way of doing the same.
Please share your experience in this regard .
Thank you in advance
----Misbah <><
You can use the mem option to tell to the kernel that you've got less ram you really have. However you can read Linux device drivers chapter 8 "Obtaining Large Buffers" :).
Regards,
Signature · 11 lines
Marco Stornelli Embedded Software Engineer CoRiTeL - Consorzio di Ricerca sulle Telecomunicazioni http://www.coritel.it [email protected] +39 06 72582838 _______________________________________________ Linuxppc-embedded mailing list [email protected] https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Signature · 7 lines
Marco Stornelli Embedded Software Engineer CoRiTeL - Consorzio di Ricerca sulle Telecomunicazioni http://www.coritel.it [email protected] +39 06 72582838
Quoted 5 lines · Misbah khan
I need to allocate 9 MB of memory in to the kernel space which i need to mmap for the application to access.
I need to know what could be the best possible way of doing the same.
If you don't need the memory to be physically contiguous, you can use vmalloc to get the memory, but then you need to use remap_vmalloc_range for mapping the memory into a user address space.
Arnd <><
vmalloc can only allocate 128k i guess where in i need 9MB allocated when driver is inserted and would be released only when its removed. mapping to user space is not a concern
--- Misbah <><
Quoted 19 lines · Arnd Bergmann
Quoted 5 lines · Misbah khan
I need to allocate 9 MB of memory in to the kernel space which i need to mmap for the application to access.
I need to know what could be the best possible way of doing the same.
If you don't need the memory to be physically contiguous, you can use vmalloc to get the memory, but then you need to use
remap_vmalloc_rangefor mapping the memory into a user address space.Arnd <><_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Signature · 2 lines
View this message in context: http://www.nabble.com/how-to-allocate-9MB-of-memory-in-kernel---tp18503022p18503765.html Sent from the linuxppc-embedded mailing list archive at Nabble.com.
Quoted 3 lines · Misbah khan
vmalloc can only allocate 128k i guess where in i need 9MB allocated when driver is inserted and would be released only when its removed. mapping to user space is not a concern
The 128kb limitation is in kmalloc, not vmalloc. The latter is specifically meant to have no limitations on the memory size (other than the available resources), at the expense of having to create a new virtual mapping.
Arnd <><
This i am not very sure with :-
Can we allocate 9MB using vmalloc and assure it to be low memory and not highmem ?
can we ioremap 9 MB SDRAM to kernel virtual ?
can we use vmalloc and do mmap to that allocated memory ,if the pages are not continues then is it going to concern mapping to user space ?
---Misbah <><
Quoted 19 lines · Arnd Bergmann
Quoted 5 lines · Misbah khan
I need to allocate 9 MB of memory in to the kernel space which i need to mmap for the application to access.
I need to know what could be the best possible way of doing the same.
If you don't need the memory to be physically contiguous, you can use vmalloc to get the memory, but then you need to use
remap_vmalloc_rangefor mapping the memory into a user address space.Arnd <><_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Signature · 2 lines
View this message in context: http://www.nabble.com/how-to-allocate-9MB-of-memory-in-kernel---tp18503022p18522535.html Sent from the linuxppc-embedded mailing list archive at Nabble.com.
Misbah khan ha scritto:
Quoted 3 lines
This i am not very sure with :-
Can we allocate 9MB using vmalloc and assure it to be low memory and not highmem ?
Why do you need only low memory? And why do you need to allocate memory? If I understood correctly you need only to "ioremap" a chunk of memory.
Quoted 1 line
can we ioremap 9 MB SDRAM to kernel virtual ?
Yep.
Quoted 2 lines
can we use vmalloc and do mmap to that allocated memory ,if the pages are not continues then is it going to concern mapping to user space ?
The "contiguous" problem is related only to DMA operations.
Quoted 24 lines
---Misbah <><
Quoted 17 lines · Arnd Bergmann
Quoted 5 lines · Misbah khan
I need to allocate 9 MB of memory in to the kernel space which i need to mmap for the application to access.
I need to know what could be the best possible way of doing the same.
If you don't need the memory to be physically contiguous, you can use vmalloc to get the memory, but then you need to use
remap_vmalloc_rangefor mapping the memory into a user address space.Arnd <><_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Signature · 7 lines
Marco Stornelli Embedded Software Engineer CoRiTeL - Consorzio di Ricerca sulle Telecomunicazioni http://www.coritel.it [email protected] +39 06 72582838
In our implimentation we have 9MB sdram which we want our application to directly access 3 MB at a time due to following reasons :-
1. We dont want our application to make a read call and copy to user 3 MB and go for context switching ?
2. We thought mmap could be a better solution to this as only one thread will act upon it and also we planed to have a circular buffer in the kernel having 3 frame of 3 MB size of the total 9MB ,each time we will block on read and get the read index and copy the frame of data for user application to process . We want our kernel circular buffer shared
3. In order to avoid switching we are going for circular buffer mapping to user space .
4. Now we want our 9MB SDRAM to point to the kernel circular buffer we want our circular buffer to be mapped to continues paged so that we could map it to user space.
Now my concern is How can i map SDRAM one to one to circular buffer of such a huge size ????
My idea is that i will ioreamp SDRAM and do memcpy_toio() when ever i am writing to the the circular buffer which is dma allocated and pages are set reserved . and read the frame from user space .
I may be totally wrong in the idea thats why i need your experience and suggession in this matter .
I hope i have answered to your concern including shiva's.
----- Misbah <><
Quoted 59 lines · Marco Stornelli
Misbah khan ha scritto:
Quoted 3 lines
This i am not very sure with :-
Can we allocate 9MB using vmalloc and assure it to be low memory and not highmem ?Why do you need only low memory? And why do you need to allocate memory? If I understood correctly you need only to "ioremap" a chunk of memory.
Quoted 1 line
can we ioremap 9 MB SDRAM to kernel virtual ?
Yep.
Quoted 2 lines
can we use vmalloc and do mmap to that allocated memory ,if the pages are not continues then is it going to concern mapping to user space ?
The "contiguous" problem is related only to DMA operations.
Quoted 25 lines
---Misbah <><
Quoted 18 lines · Arnd Bergmann
Quoted 6 lines · Misbah khan
I need to allocate 9 MB of memory in to the kernel space which i need to
mmap for the application to access.I need to know what could be the best possible way of doing the same.
If you don't need the memory to be physically contiguous, you can use vmalloc to get the memory, but then you need to use
remap_vmalloc_rangefor mapping the memory into a user address space.Arnd <><_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embeddedSignature · 11 lines
Marco Stornelli Embedded Software Engineer CoRiTeL - Consorzio di Ricerca sulle Telecomunicazioni http://www.coritel.it [email protected] +39 06 72582838 _______________________________________________ Linuxppc-embedded mailing list [email protected] https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Signature · 2 lines
View this message in context: http://www.nabble.com/how-to-allocate-9MB-of-memory-in-kernel---tp18503022p18525063.html Sent from the linuxppc-embedded mailing list archive at Nabble.com.
Quoted 3 lines · Misbah khan
4. Now we want our 9MB SDRAM to point to the kernel circular buffer we want our circular buffer to be mapped to continues paged so that we could map it to user space.
Physically contiguous or virtually contiguous? I think you only need the buffer to be virtually contiguous, which vmalloc gives you. You only need it to be physically contiguous if you are passing this buffer to hardware via DMA (and the hardware cannot handle scatter/gather).
If you need it to be physically contiguous, you'll have to use a function like alloc_pages() (or the new alloc_pages_exact, which will be in 2.6.27). To allocate 9MB, you'll need to increase CONFIG_FORCE_MAX_ZONEORDER to 12.
Signature · 2 lines
Timur Tabi Linux Kernel Developer @ Freescale
Quoted 2 lines · Misbah khan
Now my concern is How can i map SDRAM one to one to circular buffer of such a huge size ????
As I mentioned, use vmalloc to get the memory, and provide an mmap function that uses remap_vmalloc_range to put it into the user address space.
Quoted 3 lines
My idea is that i will ioreamp SDRAM and do
memcpy_toio()when ever i am writing to the the circular buffer which is dma allocated and pages are set reserved . and read the frame from user space .
ioremap and memcpy_toio style accesses only make sense for stuff that is *not* your main memory. Memory is alrady directly accessible in the kernel after allocating with get_free_pages, kmalloc or vmalloc. No need to play with __iomem pointers for this.
Arnd <><
Hi all,
I am getting kernel panic while trying these as suggested by you ,the following points will elaborate my concern :-
My circular buffer defination is this :-
/* Frame */
typedef struct
{
char buffer[SIZE_FRAME];
unsigned int count;
}frame_S;/* Circular Buffer Structured */
/* Mmaped area Structure */
typedef struct
{
frame_S fluke[NO_FRAMES]; unsigned int count_index; unsigned int read_index; unsigned int write_index;
}circularbuffer_S;
circularbuffer_S *buf_area=NULL;
i am allocating memory using vmalloc and remaping to the SDRAM area as :-
buf_area = vmalloc(sizeof(circularbuffer_S));
if(!buf_area)
{
printk(KERN_ALERT"vmalloc failed \n");
return -1;
}
buf_area = (circularbuffer_S *)ioremap(7700000,900000);
if(!buf_area)
{
printk(KERN_ALERT"ioremap failed \n");
return -1;
}mmap Implimentation is this :-
unsigned long start = vma->vm_start;
unsigned long size = vma->vm_end - vma->vm_start; //0x900000;
unsigned long phy_add = virt_to_phys(buf_area); //0x7700000;
int ret = 0;
/* Make the mmaped area noncacheable */
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
/* Set the Flags to give permissions to Mmaped area */
vma->vm_flags |=VM_RESERVED;
vma->vm_flags |=VM_READ;
vma->vm_flags |=VM_WRITE;
vma->vm_flags |=VM_IO;
//vma->vm_flags |=VM_SHARED;
//vma->vm_flags |=VM_LOCKED;
printk(KERN_DEBUG"In mmap function\n");
if(remap_vmalloc_range(vma,buf_area,(phy_add >> PAGE_SHIFT)))
{
printk(KERN_ALERT"remap_vmalloc_range failed\n");
goto mmap_exit;}
I am getting mmap failed .....
some times i am getting this error .......
/***************************************************/
insmod fluke_driver.ko
Ioremap mapped to virtual 0x0c7900e20
Unable to handle kernel paging request at virtual address c8200e34 pgd = c0444000 [c8200e34] *pgd=85c80011, *pte=00000000, *ppte=00000000 Internal error: Oops: 807 [#1] Modules linked in: fluke_driver tstamp sig_router mvci_spi mvci_sf_pcd
mvci_sci_unidir_s1 mvci_sci_diff mvci_sci_bidir_s
1 g_ether mvci_rtmd_s1 mvci_kwiso_s1 mvci_kw1281_s1 mvci_kh_s1 mvci_j1850 mvci_gm_sbc mvci_diagh_s1 mvci_dcl mvci_can1 fpga_conf arcotg_udc adc_dac keypad(F) splc501_lcd(F) cpld
CPU: 0 PC is at FlukeDriverInit+0xe4/0x140 [fluke_driver] LR is at preempt_schedule+0x48/0x58 pc : [<bf01c0e4>] lr : [<c0241e98>] Tainted: GF
sp : c69b9ed0 ip : c69b9e28 fp : c69b9eec
r10: c7862000 r9 : 00000015 r8 : 00000016
r7 : bf01aaa0 r6 : c682a5f0 r5 : bf01ac24 r4 : 00000000 r3 : 00900014 r2 : c7900e20 r1 : c69b8000 r0 : 00000000
Flags: nZCv IRQs on FIQs on Mode SVC_32 Segment user
Control: C5387F
Table: 80444000 DAC: 00000015
Process insmod (pid: 1089, stack limit = 0xc69b8250)
Stack: (0xc69b9ed0 to 0xc69ba000)
9ec0: 00000000 c682a5c4 c682a5c4c682a400
9ee0: c69b9fa4 c69b9ef0 c005ec78 bf01c00c 00000000 00000000 00011008 00000000
9f00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
9f20: 00000000 00000000 00000000 00000000 c78642e8 c6aad200 c7863820 c7863730
9f40: c7863848 00000000 0000006a 0000006a bf01aaac c00485d8 0000000a c69b8000
9f60: bf01aae8 c7863474 c7863870 00000013 00000000 c0282764 c69b9f9c 00008608
9f80: 00000003 00011018 00000080 c0020f64 c69b8000 00011008 00000000 c69b9fa8
9fa0: c0020de0 c005d7d4 00008608 00000003 00011018 000025e8 00011008 0000002d
9fc0: 00008608 00000003 00011018 00000080 bec38f5e 00000000 00011008 00000000
9fe0: 00004000 bec38d14 000088dc 400db334 60000010 00011018 48010000 00000000
Backtrace: [<bf01c000>] (FlukeDriverInit+0x0/0x140 [fluke_driver]) from [<c005ec78>] (sys_init_module+0x14b0/0x1698) r5 = C682A400 r4 = C682A5C4 [<c005d7c8>] (sys_init_module+0x0/0x1698) from [<c0020de0>] (ret_fast_syscall+0x0/0x2c) Code: eb408e00 e5952000 e59f3058 e1a00004 (e7824003) Segmentation fault
/****************************************************/
Please suggest me what could be the problem and how to overcome this and do my implimentation ....
------Misbah <><
Quoted 28 lines · Arnd Bergmann
Quoted 3 lines · Misbah khan
Now my concern is How can i map SDRAM one to one to circular buffer of such
a huge size ????As I mentioned, use vmalloc to get the memory, and provide an mmap function
that usesremap_vmalloc_rangeto put it into the user address space.Quoted 4 lines
My idea is that i will ioreamp SDRAM and do
memcpy_toio()when ever i am writing to the the circular buffer which is dma allocated and pages are set
reserved . and read the frame from user space .ioremap and
memcpy_toiostyle accesses only make sense for stuff that is *not* your main memory. Memory is alrady directly accessible in the kernel after allocating withget_free_pages, kmalloc or vmalloc. No need to play with__iomempointers for this.Arnd <><_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Signature · 2 lines
View this message in context: http://www.nabble.com/how-to-allocate-9MB-of-memory-in-kernel---tp18503022p18582612.html Sent from the linuxppc-embedded mailing list archive at Nabble.com.
Misbah khan ha scritto:
Quoted 29 lines
Hi all,
I am getting kernel panic while trying these as suggested by you ,the following points will elaborate my concern :-
My circular buffer defination is this :-
/* Frame */
typedef struct{ char buffer[SIZE_FRAME]; unsigned int count; }frame_S;/* Circular Buffer Structured */
/* Mmaped area Structure */
typedef struct
{frame_S fluke[NO_FRAMES]; unsigned int count_index; unsigned int read_index; unsigned int write_index;}circularbuffer_S;
circularbuffer_S*buf_area=NULL;i am allocating memory using vmalloc and remaping to the SDRAM area as :-
Quoted 8 lines
buf_area = vmalloc(sizeof(circularbuffer_S));
if(!buf_area)
{
printk(KERN_ALERT"vmalloc failed \n");
return -1;
}
buf_area = (circularbuffer_S *)ioremap(7700000,900000);Here you are overwriting buf_area!!!!!
Quoted 129 lines
if(!buf_area) { printk(KERN_ALERT"ioremap failed \n"); return -1; }mmap Implimentation is this :-
unsigned long start = vma->vm_start; unsigned long size = vma->vm_end - vma->vm_start; //0x900000; unsigned long phy_add = virt_to_phys(buf_area); //0x7700000; int ret = 0; /* Make the mmaped area noncacheable */ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* Set the Flags to give permissions to Mmaped area */ vma->vm_flags |=VM_RESERVED; vma->vm_flags |=VM_READ; vma->vm_flags |=VM_WRITE; vma->vm_flags |=VM_IO; //vma->vm_flags |=VM_SHARED; //vma->vm_flags |=VM_LOCKED; printk(KERN_DEBUG"In mmap function\n"); if(remap_vmalloc_range(vma,buf_area,(phy_add >> PAGE_SHIFT))) { printk(KERN_ALERT"remap_vmalloc_range failed\n"); goto mmap_exit;}I am getting mmap failed .....
some times i am getting this error .......
/***************************************************/
insmod fluke_driver.ko
Ioremap mapped to virtual0x0c7900e20Unable to handle kernel paging request at virtual address c8200e34 pgd = c0444000 [c8200e34] *pgd=85c80011, *pte=00000000, *ppte=00000000 Internal error: Oops: 807 [#1] Modules linked in: fluke_driver tstamp sig_router mvci_spi mvci_sf_pcd
mvci_sci_unidir_s1mvci_sci_diffmvci_sci_bidir_s
1g_ethermvci_rtmd_s1mvci_kwiso_s1mvci_kw1281_s1mvci_kh_s1mvci_j1850mvci_gm_sbcmvci_diagh_s1mvci_dclmvci_can1fpga_confarcotg_udcadc_dackeypad(F)splc501_lcd(F)cpldCPU: 0 PC is at FlukeDriverInit+0xe4/0x140 [fluke_driver] LR is at preempt_schedule+0x48/0x58 pc : [<bf01c0e4>] lr : [<c0241e98>] Tainted: GFsp :
c69b9ed0ip :c69b9e28fp :c69b9eec
r10:c7862000r9 : 00000015 r8 : 00000016
r7 :bf01aaa0r6 :c682a5f0r5 :bf01ac24r4 : 00000000 r3 : 00900014 r2 :c7900e20r1 :c69b8000r0 : 00000000
Flags: nZCv IRQs on FIQs on ModeSVC_32Segment user
Control: C5387F
Table: 80444000 DAC: 00000015
Process insmod (pid: 1089, stack limit =0xc69b8250)Stack: (0xc69b9ed0 to 0xc69ba000)9ec0: 00000000
c682a5c4c682a5c4c682a400
9ee0:c69b9fa4c69b9ef0c005ec78bf01c00c00000000 00000000 00011008 00000000
9f00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
9f20: 00000000 00000000 00000000 00000000c78642e8c6aad200c7863820c7863730
9f40:c7863848000000000000006a0000006abf01aaacc00485d80000000ac69b8000
9f60:bf01aae8c7863474c786387000000013 00000000c0282764c69b9f9c00008608
9f80: 00000003 00011018 00000080c0020f64c69b800000011008 00000000c69b9fa8
9fa0:c0020de0c005d7d400008608 00000003 00011018000025e8000110080000002d
9fc0: 00008608 00000003 00011018 00000080bec38f5e00000000 00011008 00000000
9fe0: 00004000bec38d14000088dc400db33460000010 00011018 48010000 00000000Backtrace: [<bf01c000>] (FlukeDriverInit+0x0/0x140 [fluke_driver]) from [<c005ec78>] (sys_init_module+0x14b0/0x1698) r5 = C682A400 r4 = C682A5C4 [<c005d7c8>] (sys_init_module+0x0/0x1698) from [<c0020de0>] (ret_fast_syscall+0x0/0x2c) Code: eb408e00 e5952000 e59f3058 e1a00004 (e7824003) Segmentation fault/****************************************************/
Please suggest me what could be the problem and how to overcome this and do my implimentation ....
------Misbah <><
Quoted 25 lines · Arnd Bergmann
Quoted 3 lines · Misbah khan
Now my concern is How can i map SDRAM one to one to circular buffer of such
a huge size ????As I mentioned, use vmalloc to get the memory, and provide an mmap function
that usesremap_vmalloc_rangeto put it into the user address space.Quoted 4 lines
My idea is that i will ioreamp SDRAM and do
memcpy_toio()when ever i am writing to the the circular buffer which is dma allocated and pages are set
reserved . and read the frame from user space .ioremap and
memcpy_toiostyle accesses only make sense for stuff that is *not* your main memory. Memory is alrady directly accessible in the kernel after allocating withget_free_pages, kmalloc or vmalloc. No need to play with__iomempointers for this.Arnd <><_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Signature · 7 lines
Marco Stornelli Embedded Software Engineer CoRiTeL - Consorzio di Ricerca sulle Telecomunicazioni http://www.coritel.it [email protected] +39 06 72582838
Quoted 2 lines · Misbah khan
I am getting kernel panic while trying these as suggested by you ,the following points will elaborate my concern :-
Please post the entire driver, when you only post fragments that don't compile, we can't really help you.
Quoted 6 lines
i am allocating memory using vmalloc and remaping to the SDRAM area as :- =20
buf_area=3D vmalloc(sizeof(circularbuffer_S)); =A0=A0=A0=A0=A0=A0=A0=A0if(!buf_area) =A0=A0=A0=A0=A0=A0=A0=A0{ =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0printk(KERN_ALERT"vmalloc=
failed \n");
Quoted 4 lines
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0return -1; =A0=A0=A0=A0=A0=A0=A0=A0}
=20
=A0=A0=A0=A0=A0=A0=A0=A0buf_area =3D (circularbuffer_S*)ioremap(7700000,=
900000);
Quoted 3 lines
=A0=A0=A0=A0=A0=A0=A0=A0if(!buf_area) =A0=A0=A0=A0=A0=A0=A0=A0{ =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0printk(KERN_ALERT"ioremap=
failed \n");
Quoted 2 lines
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0return -1; =A0=A0=A0=A0=A0=A0=A0=A0}
You really need to decide whether you want to allocate memory or want to remap an I/O range. ioremap is *only* for I/O ranges on SoC or similar devices, and when you have that, you don't allocate memory. Besides, the addresses you pass are really strange, e.g. 900,000 bytes are not 9MB. Normally, you would get the I/O address from the device tree, using of_iomap(), and then use of_translate_address/remap_pfn_range to map it to user space.
Arnd <><
Quoted 12 lines · Misbah khan
Quoted 11 lines
I am getting kernel panic while trying these as suggested by you ,the following points will elaborate my concern :-
i am allocating memory using vmalloc and remaping to the SDRAM area as :-buf_area = vmalloc(sizeof(circularbuffer_S)); if(!buf_area) { printk(KERN_ALERT"vmalloc failed \n"); return -1; }
Quoted 6 lines
Quoted 6 lines
buf_area = (circularbuffer_S *)ioremap(7700000,900000); if(!buf_area) { printk(KERN_ALERT"ioremap failed \n"); return -1; }
Misbah I suggest you, before to write in a Linux mailing list, to read Understanding the Linux kernel, Linux device drivers, Understanding the Linux virtual memory manager and so on, to study them very well, to think well about your problem and then ask for help in a mailing list.
Regards,
Signature · 7 lines
Marco Stornelli Embedded Software Engineer CoRiTeL - Consorzio di Ricerca sulle Telecomunicazioni http://www.coritel.it [email protected] +39 06 72582838
Hi All ...
First of all let me thank you for your valuable suggessions ...
1. I wanted to allocate 9MB in kernel and wanted that memory to be mapped to the physically continews SDRAM memory. but till now i could not found a way to do so ???
2. So i thought to use ioremap to map SDRAM and make it accessible to user using mmap technique but there is only one doubt and that is will it be secure and stable and whether it is a right way of doing ???
3. Now i have allocated 3MB of memory in kernel for simulation purpose in dma region and writing to 1 MB at a time in the driver and reading it in the application this works good in the Linux PC where as in the board i could just read '/0' char always .
4. When i do ioremap to a cpld memory mapped reg (as i am using simul board which does not have the actual SDRAM mapping ) i could read write to it but in the application i can read a value of '/0' always
5. Can i actually do ioremap to 9 MB SDRAM memory and map it to the user using function remap_pfn_range() ???
I am sorry Stornelli
--- Since there is a time criticality hence i am not able to look the driver books and documentation as of now and trying my little knowledge and your suggessions ....
------ Misbah <><
Quoted 42 lines · Marco Stornelli
Quoted 14 lines · Misbah khan
Quoted 12 lines
I am getting kernel panic while trying these as suggested by you ,the following points will elaborate my concern :-
i am allocating memory using vmalloc and remaping to the SDRAM area as :-buf_area = vmalloc(sizeof(circularbuffer_S)); if(!buf_area) { printk(KERN_ALERT"vmalloc failed \n"); return -1; }Quoted 6 lines
Quoted 6 lines
buf_area = (circularbuffer_S *)ioremap(7700000,900000); if(!buf_area) { printk(KERN_ALERT"ioremap failed \n"); return -1; }Misbah I suggest you, before to write in a Linux mailing list, to read Understanding the Linux kernel, Linux device drivers, Understanding the Linux virtual memory manager and so on, to study them very well, to think well about your problem and then ask for help in a mailing list.
Regards,
Signature · 11 lines
Marco Stornelli Embedded Software Engineer CoRiTeL - Consorzio di Ricerca sulle Telecomunicazioni http://www.coritel.it [email protected] +39 06 72582838 _______________________________________________ Linuxppc-embedded mailing list [email protected] https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Signature · 2 lines
View this message in context: http://www.nabble.com/how-to-allocate-9MB-of-memory-in-kernel---tp18503022p18587466.html Sent from the linuxppc-embedded mailing list archive at Nabble.com.
Quoted 9 lines · Misbah khan
First of all let me thank you for your valuable suggessions ...
1. I wanted to allocate 9MB in kernel and wanted that memory to be mapped to the physically continews SDRAM memory. but till now i could not found a way to do so ???
2. So i thought to use ioremap to map SDRAM and make it accessible to user using mmap technique but there is only one doubt and that is will it be secure and stable and whether it is a right way of doing ???
As I have told you a few times now, you *either* allocate the memory *or* ioremap it, NOT BOTH!!!
If you SDRAM is you main memory, you need vmalloc and remap_vmalloc_range. If the SDRAM is not your main memory but some I/O attached buffer, you need ioremap/of_iomap and remap_pfn_range.
Arnd <><
If you SDRAM is you main memory, you need vmalloc and remap_vmalloc_range. If the SDRAM is not your main memory but some I/O attached buffer, you need ioremap/of_iomap and remap_pfn_range.
My SDRAM is the main memory of which 9MB i have to allocate in the driver.
If i allocate 9BM using vmalloc and remap to user space how should it address to the 9MB
SDRAM contigues address which i need to map for user access ?
Quoted 30 lines · Arnd Bergmann
Quoted 8 lines · Misbah khan
First of all let me thank you for your valuable suggessions ...
1. I wanted to allocate 9MB in kernel and wanted that memory to be mapped to
the physically continews SDRAM memory. but till now i could not found a way
to do so ???Quoted 4 lines
2. So i thought to use ioremap to map SDRAM and make it accessible to user
using mmap technique but there is only one doubt and that is will it be secure and stable and whether it is a right way of doing ???As I have told you a few times now, you *either* allocate the memory *or* ioremap it, NOT BOTH!!!
If you SDRAM is you main memory, you need vmalloc and
remap_vmalloc_range. If the SDRAM is not your main memory but some I/O attached buffer, you need
ioremap/of_iomap andremap_pfn_range.Arnd <><_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Signature · 2 lines
View this message in context: http://www.nabble.com/how-to-allocate-9MB-of-memory-in-kernel---tp18503022p18605418.html Sent from the linuxppc-embedded mailing list archive at Nabble.com.
Quoted 4 lines
If i allocate 9BM using vmalloc and remap to user space how should it address to the 9MB
SDRAM contigues address which i need to map for user access ?
Use the nopage method and vmalloc_to_page in it.
I have an example in ftp://gnudd.com/pub/samplecode, in the smallsample26 package, the module is "smallmmap.c" (I'm sure there are simlilar examples elsewhere).
/alessandro
Hi all ...
I am uploading the source code which is doing the following :-
1. mapping cpld register using ioremap coping the data to circular buffer and remapping it to user space .
2. It can also map kernel virtual dma memory to user space if compiled conditionally .
following is the problem which i am facing ...
1. It is somitimes giving following kernel panic ....
nable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = c0004000
[00000000] *pgd=00000000
Internal error: Oops: 17 [#1] Modules linked in: fluke_driver tstamp sig_router mvci_spi mvci_sf_pcd
mvci_sci_unidir_s1 mvci_sci_diff mvci_sci_bidir_s
1 mvci_rtmd_s1 mvci_kwiso_s1 mvci_kw1281_s1 mvci_kh_s1 mvci_j1850 mvci_gm_sbc mvci_diagh_s1 g_ether mvci_dcl mvci_can1 f pga_conf arcotg_udc adc_dac keypad(F) splc501_lcd(F) cpld
CPU: 0 PC is at cascade+0x64/0x8c LR is at __init_begin+0x3fff8000/0x30 pc : [<c00484ac>] lr : [<00000000>] Tainted: GF
sp : c0293ea8 ip : 0040b000 fp : c0293ecc
r10: 8001d9f0 r9 : c0292000 r8 : 00000001
r7 : c0292000 r6 : 0000000c r5 : c02fa048 r4 : 00000000 r3 : c02fa2f8 r2 : 0000261a r1 : bf01ab70 r0 : c02fa2f8
Flags: Nzcv IRQs off FIQs on Mode SVC_32 Segment kernel
Control: C5387F
Table: 8698C000 DAC: 00000017
Process swapper (pid: 0, stack limit = 0xc0292250)
Stack: (0xc0293ea8 to 0xc0294000)
3ea0: bf01ab70 c02fb440 0000000a 00000000 c02fa0480000000a
3ec0: c0293efc c0293ed0 c0048810 c0048454 c0293eec c0293ee0 c002a30c 00000001
3ee0: c02f9e44 0000000a 00000002 00000001 c0293f1c c0293f00 c00442a0 c0048794
3f00: c0293f2c 0000001d c0294740 00000000 c0293f2c c0293f20 c00446d4 c0044254
3f20: c0293f4c c0293f30 c00217b0 c0044698 c0293f5c ffffffff 0000ffff 00000001
3f40: c0293fa4 c0293f50 c00209e4 c0021770 00000001 00000001 c0292000 00000000
3f60: c0022068 c0292000 c0298c44 c03121c0 8001da24 4107b364 8001d9f0 c0293fa4
3f80: c0293fa8 c0293f98 c0021d48 c002209c 60000013 ffffffff c0293fbc c0293fa8
3fa0: c0021d48 c0022074 c02faae0 c02f292c c0293fcc c0293fc0 c00202e0 c0021d24
3fc0: c0293ff4 c0293fd0 c0008848 c00202b4 c00083c4 00000000 00000000 c02f29a8
3fe0: 00000000 00c5387d 00000000 c0293ff8 80008030 c00086e0 00000000 00000000
Backtrace: [<c0048448>] (cascade+0x0/0x8c) from [<c0048810>] (run_timer_softirq+0x88/0x1e8) r6 = 0000000A r5 = C02FA048 r4 = 00000000 [<c0048788>] (run_timer_softirq+0x0/0x1e8) from [<c00442a0>] (__do_softirq+0x58/0xc8) r8 = 00000001 r7 = 00000002 r6 = 0000000A r5 = C02F9E44 r4 = 00000001 [<c0044248>] (__do_softirq+0x0/0xc8) from [<c00446d4>] (irq_exit+0x48/0x5c) r6 = 00000000 r5 = C0294740 r4 = 0000001D [<c004468c>] (irq_exit+0x0/0x5c) from [<c00217b0>] (asm_do_IRQ+0x4c/0x64) [<c0021764>] (asm_do_IRQ+0x0/0x64) from [<c00209e4>] (__irq_svc+0x44/0x80) r6 = 00000001 r5 = 0000FFFF r4 = FFFFFFFF [<c0022068>] (default_idle+0x0/0x3c) from [<c0021d48>] (cpu_idle+0x30/0x5c) [<c0021d18>] (cpu_idle+0x0/0x5c) from [<c00202e0>] (rest_init+0x38/0x40) r5 = C02F292C r4 = C02FAAE0 [<c00202a8>] (rest_init+0x0/0x40) from [<c0008848>] (start_kernel+0x174/0x1c0) [<c00086d4>] (start_kernel+0x0/0x1c0) from [<80008030>] (0x80008030) Code: e1530005 15822000 ebffffb6 e1a0e004 (e5944000) <0>Kernel panic - not syncing: Aiee, killing interrupt handler!
also when i run it on X86 PC i am able to get the data and no panic where in on the board it is giving the above error ....
2. I can raed the data using the user application when i run it on X86 PC where in i cant able to read the data when i run it on the board the data i was getting was always '/0' filled buffer .
Here is the compilete code .............
/******************************************************************************
* McBSP_Driver.c
*
* Fluke Driver
*
* Description:
*
* Libraries Used:
*
*
* Unit Test Drivers (Binary):
*
* <fix me >
*
*
* Special Compile Flags
* Nil
*
* Revision History:
* (17/July/2008) Misbah
* Created the file
*
* Copyright (C)
* ******************************************************************************/
/******************************************************************************
* Include Files
*****************************************************************************/
/* Standard linux files includes */
#include<linux/kernel.h>
//#include<linux/config.h>
#include<linux/ioctl.h>
#include<linux/types.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/delay.h>
#include<linux/init.h>
#include<linux/interrupt.h>
#include<linux/version.h>
#include<linux/wait.h>
#include<linux/poll.h>
#include<linux/timer.h>
#include<linux/irq.h>
#include<asm/uaccess.h>
#include<linux/time.h>
#include<asm/io.h>
#include<asm/bitops.h>
#include<linux/mm.h>
//#include<asm/mmzone.h>
#include<linux/bootmem.h>
#include <linux/dma-mapping.h>
#include <linux/vmalloc.h>
#include <asm/pgtable.h>
#include<asm/io.h>
#include<asm/bitops.h>
#include"fluke_driver.h"
static int McBSP_DriverOpen(struct inode *inode,struct file *file); static int McBSP_DriverInit(void);
static int McBSP_DriverIoctl(struct inode *inode, struct file *file,\
unsigned int cmd, unsigned long param); static ssize_t McBSP_DriverWrite(struct file *file, const char __user *buf, size_t len,loff_t *offset); static ssize_t McBSP_DriverRead(struct file *file,char __user *buf,size_t len, loff_t *offset);
static int McBSP_DriverMmap(struct file *file,struct vm_area_struct *vma); static void MmapOpen(struct vm_area_struct *vma);
static void MmapClose(struct vm_area_struct *vma);
static void McBSP_DriverExit(void);
static int McBSP_DriverClose(struct inode *inode,struct file *file); static int WriteBuf(void);
void timer_func(void);
static struct timer_list fluke_timer;
static dma_addr_t dma_addr;
static char *buf_ptr;
static struct file_operations fluke_fops =
{
.owner = THIS_MODULE,
.open = McBSP_DriverOpen,// .read = McBSP_DriverRead,
.ioctl = McBSP_DriverIoctl,
.mmap = McBSP_DriverMmap,
// .write = McBSP_DriverWrite,
.release = McBSP_DriverClose,
};
/* File operation structure for mmap system call */ static struct vm_operations_struct mmap_op=
{
.open = MmapOpen,
.close = MmapClose,
};static circularbuffer_S *buf_area = NULL;
static circularbuffer_index_S buf_index_area;
static int device_open_count = 0;
static int data_present_status = 0;
void *ioremap_ptr;
static int phy_addr ;
/* static declaration of wait queue */
static DECLARE_WAIT_QUEUE_HEAD(wait_queue);
static DECLARE_MUTEX(mutex);
module_init(McBSP_DriverInit);module_exit(McBSP_DriverExit);
MODULE_AUTHOR("Misbah U K");MODULE_LICENSE ("GPL");
#define SIMULATION /**************************************************************************** *
* Description: This function will open fluke device
*
* Input: File structure pointer and Inode structure pointer.
* ( passed by the kernel )
*
* output: Returns 0 on Success.
* ***************************************************************************/ static int McBSP_DriverOpen(struct inode *inode,struct file *file)
{
/* Reintialize file operation structure */
file->f_op=&fluke_fops;
printk(KERN_DEBUG" fluke driver open success \n");
if (device_open_count == 0)
{
device_open_count = 1;
/* Reset the read and write index*/
buf_index_area.write_index=0;
buf_index_area.read_index=-1;
buf_index_area.count_index=0;
#ifdef SIMULATION
/* Initialize the Timer */
init_timer(&fluke_timer);
fluke_timer.expires = jiffies + (HZ*10);//Timer will Expire after 60 sec
fluke_timer.data = 0;
fluke_timer.function = (void *)timer_func;
add_timer(&fluke_timer);
#endif
}
return 0;
}/******************************************************************************
*
* Description : Interrupt handler function.
*
* Input: NONE
*
* Output: NONE
*
*****************************************************************************/ irqreturn_t DataAcqIntHandler(int irq,void *dev_id, struct pt_regs *regs)
{
printk(KERN_ALERT" In Interrupt Handler\n");
/* Data present status is set to wake up the read call */
data_present_status=1;
/* Wake up the blocked Select call */
wake_up_interruptible(&wait_queue);
#ifndef SIMULATION
/* Clear the interrupt in the interrupt pending registor */
cpi->ic_scprrh |=DATA_ACQ_INT_CLEAR;
#endif
return IRQ_HANDLED;}/* End of PpsIntrHandler() */
#ifdef SIMULATION
void timer_func(void)
{
printk(KERN_ALERT" In the timer function \n"); /* Data present status is set to wake up the read call */ data_present_status=1; /* Wake up the blocked Read call */ wake_up_interruptible(&wait_queue);
}
#endif
/*************************************************************************** *
* Description: Register the device and perform Initialization.
*
* Input: NIL
*
* Output: Returns 0 on Success and -1 on failure
* **************************************************************************/ static int __init McBSP_DriverInit(void)
{
unsigned int virt_addr = 0;
int mem = 0;
//buf_area = vmalloc(sizeof(circularbuffer_S));
//if(!buf_area)
//{
// printk(KERN_ALERT"vmalloc failed \n");
// return -1;
//}#if 0
/*
* Allocate memory for the circular buffer in the DMA coherent area
* and algin it in the Cache
*/
mem = L1_CACHE_ALIGN(sizeof(circularbuffer_S));
buf_ptr = (char *)dma_alloc_coherent(NULL, mem, &dma_addr,GFP_KERNEL);
printk(KERN_INFO" buf_ptr = 0x%x \n",(int )buf_ptr);
if(NULL == buf_ptr )
{
printk(KERN_ALERT" Allocation of Memory failure ");
return -1;
}
buf_area = (circularbuffer_S *)(((unsigned int )buf_ptr + PAGE_SIZE - 1) \
& PAGE_MASK);
printk(KERN_INFO" buf_area = 0x%x \n",(int )buf_area);
if(NULL == buf_area)
{
printk(KERN_ALERT" Circular buffer memory not allocated \n");
return -1;
}
/* Marking the Pages as reserved */
for (virt_addr = (unsigned int)buf_area; \
virt_addr < (unsigned int )buf_area + sizeof(circularbuffer_S);\
virt_addr += PAGE_SIZE)
{
/* Set the pages as reserved */
SetPageReserved(virt_to_page(virt_addr));
//mem_map_reserve(virt_to_page(virt_addr));
}
phy_addr = virt_to_phys(buf_ptr);
printk(KERN_INFO"Allocated Memory for Circular Buffer at physical0x0%x\n",phy_addr);
#else
buf_area = ioremap(0xB2000000,0x4000); //(0xB2000000,0x4000);
//(7700000,900000);
if(!buf_area)
{
printk(KERN_ALERT"ioremap failed \n");
return -1;
}
printk(" Ioremap mapped to virtual 0x0%x \n",buf_area);
*((unsigned int *)buf_area) = 0xa5a5a5a5;
printk(" Ioremap data 0x0%x \n",*((unsigned int *)buf_area + 0));#endif
/* Device major number is registered to set the driver entry point */
if(register_chrdev(MAJOR_NO,MODULE_NAME, &fluke_fops)==0)
{
printk(KERN_DEBUG" Fluke driver registeration success \n");
}
else
{
printk(KERN_ALERT" Fluke driver registeration failed \n");
return -1;
}
/*
* Register Data Acq interrupt request with specified irq and install the
* handler
*/
if(request_irq(DATA_ACQ_INT,(void *)DataAcqIntHandler, SA_INTERRUPT,
MODULE_NAME, NULL)==0)
{
printk(KERN_DEBUG" Data Acq interrupt request returns success \n");
}
else
{
printk(KERN_DEBUG" Data Acq interrupt request failed \n");
unregister_chrdev(MAJOR_NO,MODULE_NAME);
return -1;
}
/* Reset the read and write index*/
buf_index_area.write_index=0;
buf_index_area.read_index=0;
buf_index_area.count_index=0;
return 0;}
/*************************************************************************** *
* Description: Input/Output entry point for driver.
*
* Input: Inode pointer, File pointer, command and parameter.
*
* Output: Returns 0 on success and -1 on failure.
* **************************************************************************/
static int McBSP_DriverIoctl(struct inode *inode, struct file *file,\
unsigned int cmd, unsigned long param)
{
int i;
daq_t daq_param;
printk(KERN_DEBUG"In ioctl command \n");
switch(cmd)
{
case START_ACQ_DATA:
if(copy_from_user(&daq_param,(void *)param,sizeof(daq_param)))
{
return -1;
}
/* For Simulation we are writing the data */
if(WriteBuf() < 0)
{
printk(" Writing to the memory failure \n");
return -1;
}
/* Wait for the Interrupt to occur */
wait_event_interruptible( wait_queue, data_present_status !=0);
printk("Read Index before read %d\n",buf_index_area.read_index);
data_present_status=0;
buf_index_area.read_index++;
buf_index_area.read_index%=NO_FRAMES;
if(buf_index_area.read_index ==((buf_index_area.write_index +1) %
NO_FRAMES))
//if(buf_index_area.read_index == buf_index_area.write_index )
{
printk("Read failure because read and write index are same\n");
return -1;
}
/* Decrement the count index to indicate the data availibility */
down(&mutex);
buf_index_area.count_index--;
up(&mutex);
/* copy the circular buffer read index */
daq_param.circular_index = buf_index_area.read_index;
/*for(i = 0;i < SIZE_FRAME; i++)
{
printk("%c",buf_area->fluke[buf_index_area.read_index].buffer[i]);
}
*/
/* Configure ADC unit for No of samples and period */
/* < To Dod > */
#ifdef SIMULATION
/* Reinitialize the timer and run it again */
init_timer(&fluke_timer);
fluke_timer.function=(void *)timer_func;
fluke_timer.data=0;
fluke_timer.expires=jiffies + (HZ*10);
del_timer(&fluke_timer);
printk(KERN_DEBUG"Timer reinitialize in ioctl \n");
add_timer(&fluke_timer);
#endif
printk("Read Index after read %d\n",buf_index_area.read_index);
if(copy_to_user((void *)param,&daq_param,sizeof(daq_param)))
{
return -1;
}
break;
default:
return(0);
}
return (0);
}/******************************************************************************
* Description: This function writes data to the device.
*
* Inputs: NONE
*
* Outputs: Returns No of bytes copied or -1 on failure. ******************************************************************************/ static ssize_t McBSP_DriverWrite(struct file *file,
const char __user *buf, size_t len,loff_t *offset)
{
int i,write_index;
write_index = buf_index_area.write_index;
if(buf_index_area.read_index ==((buf_index_area.write_index +1) %
NO_FRAMES))
//if(buf_index_area.read_index == buf_index_area.write_index )
{
printk(KERN_ALERT"Not able to write\n");
return -1;
}
printk(KERN_INFO" Before Write index = %d\n",buf_index_area.write_index);
for(i=0;i<len;i++)
{
buf_area->fluke[write_index].buffer[i]=buf[i];
//memset(buf_area->fluke[write_index].buffer,'A',SIZE_FRAME);
//for(i = 0;i < SIZE_FRAME; i++)
//{
// printk("%c",buf_area->fluke[write_index].buffer[i]);
//}
//printk(" %c",buf_area->fluke[write_index].buffer[i]);
}
for(i = 0;i < SIZE_FRAME; i++)
{
printk("%c",buf_area->fluke[write_index].buffer[i]);
}
//len = copy_from_user(buf_area->fluke[write_index].buffer,buf,len);
//memcpy_fromio(ioremap_ptr,buf_area->fluke[write_index].buffer,4);
buf_index_area.count_index++;
buf_index_area.write_index++;
buf_index_area.write_index%=3;
printk(KERN_INFO" After Write index = %d\n",buf_index_area.write_index);
return len;}
/******************************************************************************
* Description: This function writes data to the circular buffer.
*
* Inputs: NONE
*
* Outputs: Returns No of bytes copied or -1 on failure. ******************************************************************************/ static int WriteBuf(void)
{
int i;
printk(" write Index is %d \n",buf_index_area.write_index);
if(buf_index_area.read_index ==((buf_index_area.write_index +1) %
NO_FRAMES))
//if(buf_index_area.read_index == buf_index_area.write_index )
{
printk(KERN_ALERT"Not able to write\n");
return -1;
}
memset(buf_area->fluke[buf_index_area.write_index].buffer,'A',SIZE_FRAME);
/*for(i = 0;i < SIZE_FRAME; i++)
{
printk("%c",buf_index_area.fluke[buf_index_area.write_index].buffer[i]);
}
*/
buf_index_area.count_index++;
buf_index_area.write_index++;
buf_index_area.write_index%=3;
printk(" write Index incremented to %d \n",buf_index_area.write_index);
return 0;
}/******************************************************************************
* Description: This function reads data from the shared mmap area. *
* Inputs: file structuer,data buffer pointer and length of data. *
* Outputs: Return no of bytes read or -1 on failure.
* ******************************************************************************/ static ssize_t McBSP_DriverRead(struct file *file,char __user *buf,size_t len,
loff_t *offset)
{
int temp_read_index,i;
printk(KERN_INFO"Entering %s\n",__FUNCTION__);
/* Wait till timer Expires */
wait_event_interruptible( wait_queue, data_present_status !=0);
data_present_status=0;
buf_index_area.read_index++;
buf_index_area.read_index%=NO_FRAMES;
/* Decrement the count index to indicate the data availibility */
down(&mutex);
buf_index_area.count_index--;
up(&mutex);
temp_read_index = buf_index_area.read_index;
printk(KERN_INFO"Exting %s\n",__FUNCTION__);
printk(KERN_INFO"count_index=%d\n",buf_index_area.count_index);
printk(KERN_INFO"read_index=%d\n",buf_index_area.read_index);
/*for(i = 0 ;i < SIZE_FRAME ; i++)
{
printk("%c",buf_area->fluke[temp_read_index].buffer[i]);
}
*/
return((temp_read_index));
}/*****************************************************************************
* Description:This function is used to map the memory area to user application.
* There is a circular buffer which is created in the driver.
* This region is mmaped to the user application by this function.
* This fuction sets the permissions for that area accordingly.
*
* Inputs:file pointer, virtual memory area structure.
*
* Outputs: Returns 0 on success or -1 on failure. *******************************************************************************/ static int McBSP_DriverMmap(struct file *file,struct vm_area_struct *vma) {
unsigned long start = vma->vm_start;
unsigned long size = vma->vm_end - vma->vm_start; //0x900000;
unsigned long phy_add = virt_to_phys(buf_ptr); //0x7700000;
int ret = 0;
/* Make the mmaped area noncacheable */
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
/* Set the Flags to give permissions to Mmaped area */
vma->vm_flags |=VM_RESERVED;
vma->vm_flags |=VM_READ;
vma->vm_flags |=VM_WRITE;
vma->vm_flags |=VM_IO;
//vma->vm_flags |=VM_SHARED;
//vma->vm_flags |=VM_LOCKED;
printk(KERN_DEBUG"In mmap function\n");
/* Mmap the kernel buffer to user space */
if(remap_pfn_range(vma,start,(phy_add >>
PAGE_SHIFT),size,vma->vm_page_prot))
//if(remap_pfn_range(vma,start,vma->vm_pgoff,size,vma->vm_page_prot))
{
printk(KERN_ALERT"remap_pfn_range failed\n");
goto mmap_exit;}
printk(KERN_ALERT"phy addr 0x%08X mmapped to virt addr 0x%08X, size =
0x%08X\n",
(unsigned int)phy_add, (unsigned int)start, (unsigned int)size); /* Initialize the file operation structure of Mmaped area */ vma->vm_ops=&mmap_op; /* Open the Mmaped area */ MmapOpen(vma); mmap_exit: return ret; }
/******************************************************************************
* Description: This function opens mmaped area for the device.
*
* Inputs: Virtual memory area structure.
*
* Outputs: none ******************************************************************************/ static void MmapOpen(struct vm_area_struct *vma)
{
printk("Mmaped are is opened \n");
printk("Virtual= %lx, Physical=%lx \n",vma->vm_start,
(vma->vm_pgoff << PAGE_SHIFT));
return;
}/******************************************************************************
* Description: This function closes mmaped area for the device
*
* Inputs: Virtual Memory structure.
*
* Outputs: Return CASHEL_SUCCESS after closing the device. ******************************************************************************/ static void MmapClose(struct vm_area_struct *vma)
{
printk(KERN_DEBUG"Mmaped are is closed\n ");
return;
}/****************************************************************************** *
* Description : Unregisters the driver and makes the resources free.
*
* Input : NIL
*
* Output : NIL
* *****************************************************************************/ static void __exit McBSP_DriverExit(void)
{
unsigned int virt_addr;#if 0
/* Clear or Free the pages which are reserverd */
for (virt_addr=(unsigned int)buf_area; virt_addr < (unsigned int)buf_area
+ sizeof(circularbuffer_S);
virt_addr += PAGE_SIZE)
{
// clear all pages
ClearPageReserved(virt_to_page(virt_addr));
}
/* Free the mmaped buffer area */
dma_free_coherent(NULL,L1_CACHE_ALIGN(sizeof(circularbuffer_S)),
buf_ptr,dma_addr);#else
iounmap(buf_area);
#endif
/* Unregister the device */ if(unregister_chrdev(MAJOR_NO , MODULE_NAME)==0) printk(KERN_DEBUG" device cleanup success\n"); else printk(KERN_ALERT" device cleanup failed \n"); /* Free IRQ */ free_irq(DATA_ACQ_INT,NULL); //if(buf_area) // vfree(buf_area);
}
/******************************************************************************
* Description: This function closes the device
*
* Inputs: Inode structure pointer, File structure pointer
*
* Outputs: Return 0 on success and -1 on failure. ******************************************************************************/ static int McBSP_DriverClose(struct inode *inode,struct file *file)
{
device_open_count--;
if(device_open_count == 0)
{
/* Delete the timer */
del_timer(&fluke_timer);
}
printk(KERN_INFO" device closed %d\n",device_open_count);
return 0;
}/******************************************************************************
* File Ends
*****************************************************************************/
#define MODULE_NAME "fluke_driver"
#define MAJOR_NO 333
#define NO_FRAMES 3
#define SIZE_FRAME 1024*5//(1024*1024*1)/* 3MB */
#define DATA_ACQ_INT 23 /* To Do <for testing only > */
#define DATA_ACQ_INT_CLEAR 1 /* To Do <for testing only > */
#define MAGIC_NUM 'D'
#define START_ACQ_DATA _IOWR(MAGIC_NUM, 0,unsigned long)
/* Frame */
typedef struct
{
char buffer[SIZE_FRAME];}frame_S;
/* Circular Buffer Structured */
/* Mmaped area Structure */
typedef struct
{
frame_S fluke[NO_FRAMES];
}circularbuffer_S;
typedef struct
{
unsigned int count_index;
unsigned int read_index;
unsigned int write_index;
}circularbuffer_index_S;typedef struct
{
int test_period_ms; /*????? send to driver*/
int req_no_sample; /*send to driver*/
int acq_no_of_sample; /* return by driver*/
int circular_index; /* return by driver*/
int sampling_rate_hz; /*send to driver*/
}daq_t;
/******************************************************************************
* File Ends
*****************************************************************************/
/******************************************************************************
* McBSP_appl.c
*
* Fluke Driver
*
* Description:
*
* Libraries Used:
*
*
* Unit Test Drivers (Binary):
*
* <fix me >
*
*
* Special Compile Flags
* Nil
*
* Revision History:
* (17/July/2008) Misbah
* Created the file
*
* Copyright (C)
* ******************************************************************************/
/******************************************************************************
* Include Files
*****************************************************************************/ /* Standard linux files includes */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include "fluke_driver.h"
#define FLUKE_DRIVER "/dev/fluke"
int main (int argc ,char *argv[])
{
circularbuffer_S *mmap_ptr;
int fd = -1,i;
int size_mmap = sizeof(circularbuffer_S);
int read_index = -1,ret = -1 ;
FILE *fp1,*fp2,*fp3;
char buf[1024];
char *mmap_data;
daq_t daq_param;
/* Initialize the config param */
daq_param.test_period_ms = 60*1000 ;
daq_param.acq_no_of_sample = 0;
daq_param.req_no_sample =0;
daq_param.sampling_rate_hz = 0;
mmap_data = (char *)malloc(sizeof(circularbuffer_S));
/* creat files for frames */
fp1 = fopen("frame1.txt","w");
fp2 = fopen("frame2.txt","w");
fp3 = fopen("frame3.txt","w");
/* Open the device file */
fd = open(FLUKE_DRIVER , O_RDWR);
if (fd == -1)
{
printf(" Error in opening fluke device \n");
return -1;
}
/* map the kernel memory to user space */
mmap_ptr = mmap(NULL,size_mmap,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
printf(" Virtual addr of the pointer is 0x%x \n",(unsigned int)mmap_ptr);
if(mmap_ptr == NULL )
{
printf(" mapped ptr returns NULL from driver n");
return -1;
}
while(1)
{
/* Write to driver for testing only */
memset(buf,'Z',sizeof(buf));
printf(" Writing to driver \n");
//write(fd,buf,sizeof(buf));
/* Block on read to get the circular buffer read index */
//read_index = read(fd, buf , 1024);
//printf(" Here is the read for you %s\n",buf);
if (ioctl(fd , START_ACQ_DATA ,&daq_param) < 0)
{
printf(" ioctl failed \n");
return -1 ;
}
read_index = daq_param.circular_index;
printf(" read index from application %d \n",read_index);
/* Print the data read */
//for(i = 0;i <= 1024 ; i++)
printf(" %s \n",mmap_ptr->fluke[read_index].buffer);
/* Write the data read fron the driver to the file */
if(read_index >= 0)
{
ret = (SIZE_FRAME) ;
memcpy(mmap_data, \
mmap_ptr->fluke[read_index].buffer,SIZE_FRAME);
if(read_index == 0)
fwrite(mmap_ptr->fluke[read_index].buffer ,SIZE_FRAME , 1 ,fp1);
else if(read_index == 1)
fwrite(mmap_ptr->fluke[read_index].buffer ,SIZE_FRAME , 1 ,fp2);
else if(read_index == 2)
fwrite(mmap_ptr->fluke[read_index].buffer ,SIZE_FRAME , 1 ,fp3);
else
{
printf("Not able to write to file as read_index returns %d
\n",read_index );
return -1;
}
}
}
if(mmap_data)
free(mmap_data);
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 0;
}/******************************************************************************
* File Ends
*****************************************************************************/
please help me to resolve this issue .......
Thanks in advance ...
---- Misbah <><
Quoted 48 lines · Misbah khan
If you SDRAM is you main memory, you need vmalloc and
remap_vmalloc_range. If the SDRAM is not your main memory but some I/O attached buffer, you need
ioremap/of_iomap andremap_pfn_range.My SDRAM is the main memory of which 9MB i have to allocate in the driver.
If i allocate 9BM using vmalloc and remap to user space how should it address to the 9MB
SDRAM contigues address which i need to map for user access ?Quoted 31 lines · Arnd Bergmann
Quoted 8 lines · Misbah khan
First of all let me thank you for your valuable suggessions ...
1. I wanted to allocate 9MB in kernel and wanted that memory to be mapped to
the physically continews SDRAM memory. but till now i could not found a way
to do so ???Quoted 4 lines
2. So i thought to use ioremap to map SDRAM and make it accessible to user
using mmap technique but there is only one doubt and that is will it be secure and stable and whether it is a right way of doing ???As I have told you a few times now, you *either* allocate the memory *or* ioremap it, NOT BOTH!!!
If you SDRAM is you main memory, you need vmalloc and
remap_vmalloc_range.
If the SDRAM is not your main memory but some I/O attached buffer, you need
ioremap/of_iomap andremap_pfn_range.Arnd <><_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Signature · 2 lines
View this message in context: http://www.nabble.com/how-to-allocate-9MB-of-memory-in-kernel---tp18503022p18627544.html Sent from the linuxppc-embedded mailing list archive at Nabble.com.
Quoted 90 lines · Misbah khan
Hi all ...
I am uploading the source code which is doing the following :-
1. mapping cpld register using ioremap coping the data to circular buffer and remapping it to user space .
2. It can also map kernel virtual dma memory to user space if compiled conditionally .
following is the problem which i am facing ...
1. It is somitimes giving following kernel panic ....
nable to handle kernel NULL pointer dereference at virtual address 00000000 pgd =
c0004000
[00000000] *pgd=00000000Internal error: Oops: 17 [#1] Modules linked in: fluke_driver tstamp sig_router mvci_spi mvci_sf_pcd
mvci_sci_unidir_s1mvci_sci_diffmvci_sci_bidir_s
1mvci_rtmd_s1mvci_kwiso_s1mvci_kw1281_s1mvci_kh_s1mvci_j1850mvci_gm_sbcmvci_diagh_s1g_ethermvci_dclmvci_can1fpga_confarcotg_udcadc_dackeypad(F)splc501_lcd(F)cpldCPU: 0 PC is at cascade+0x64/0x8c LR is at __init_begin+0x3fff8000/0x30 pc : [<c00484ac>] lr : [<00000000>] Tainted: GFsp :
c0293ea8ip :0040b000fp :c0293ecc
r10:8001d9f0r9 :c0292000r8 : 00000001
r7 :c0292000r6 :0000000cr5 :c02fa048r4 : 00000000 r3 :c02fa2f8r2 :0000261ar1 :bf01ab70r0 :c02fa2f8
Flags: Nzcv IRQs off FIQs on ModeSVC_32Segment kernel
Control: C5387F
Table: 8698C000 DAC: 00000017
Process swapper (pid: 0, stack limit =0xc0292250)Stack: (0xc0293ea8 to 0xc0294000)3ea0:
bf01ab70c02fb4400000000a00000000c02fa0480000000a
3ec0:c0293efcc0293ed0c0048810c0048454c0293eecc0293ee0c002a30c00000001
3ee0:c02f9e440000000a00000002 00000001c0293f1cc0293f00c00442a0c0048794
3f00:c0293f2c0000001dc029474000000000c0293f2cc0293f20c00446d4c0044254
3f20:c0293f4cc0293f30c00217b0c0044698c0293f5cffffffff0000ffff00000001
3f40:c0293fa4c0293f50c00209e4c002177000000001 00000001c029200000000000
3f60:c0022068c0292000c0298c44c03121c08001da244107b3648001d9f0c0293fa4
3f80:c0293fa8c0293f98c0021d48c002209c60000013 ffffffffc0293fbcc0293fa8
3fa0:c0021d48c0022074c02faae0c02f292cc0293fccc0293fc0c00202e0c0021d24
3fc0:c0293ff4c0293fd0c0008848c00202b4c00083c400000000 00000000c02f29a8
3fe0: 0000000000c5387d00000000c0293ff880008030c00086e000000000 00000000Backtrace: [<c0048448>] (cascade+0x0/0x8c) from [<c0048810>] (run_timer_softirq+0x88/0x1e8) r6 = 0000000A r5 = C02FA048 r4 = 00000000 [<c0048788>] (run_timer_softirq+0x0/0x1e8) from [<c00442a0>] (__do_softirq+0x58/0xc8) r8 = 00000001 r7 = 00000002 r6 = 0000000A r5 = C02F9E44 r4 = 00000001 [<c0044248>] (__do_softirq+0x0/0xc8) from [<c00446d4>] (irq_exit+0x48/0x5c) r6 = 00000000 r5 = C0294740 r4 = 0000001D [<c004468c>] (irq_exit+0x0/0x5c) from [<c00217b0>] (asm_do_IRQ+0x4c/0x64) [<c0021764>] (asm_do_IRQ+0x0/0x64) from [<c00209e4>] (__irq_svc+0x44/0x80) r6 = 00000001 r5 = 0000FFFF r4 = FFFFFFFF [<c0022068>] (default_idle+0x0/0x3c) from [<c0021d48>] (cpu_idle+0x30/0x5c) [<c0021d18>] (cpu_idle+0x0/0x5c) from [<c00202e0>] (rest_init+0x38/0x40) r5 = C02F292C r4 = C02FAAE0 [<c00202a8>] (rest_init+0x0/0x40) from [<c0008848>] (start_kernel+0x174/0x1c0) [<c00086d4>] (start_kernel+0x0/0x1c0) from [<80008030>] (0x80008030) Code: e1530005 15822000 ebffffb6 e1a0e004 (e5944000) <0>Kernel panic - not syncing: Aiee, killing interrupt handler!also when i run it on X86 PC i am able to get the data and no panic where in on the board it is giving the above error ....
2. I can raed the data using the user application when i run it on X86 PC where in i cant able to read the data when i run it on the board the data i was getting was always '/0' filled buffer .
Quoted 8 lines
Here is the compilete code .............
static int
McBSP_DriverOpen(struct inode *inode,struct file *file){ /* Reintialize file operation structure */ file->f_op=&fluke_fops;
this is already set.
Quoted 15 lines
printk(KERN_DEBUG" fluke driver open success \n");
if (device_open_count == 0)
{
device_open_count = 1;
/* Reset the read and write index*/
buf_index_area.write_index=0;
buf_index_area.read_index=-1;
buf_index_area.count_index=0;
#ifdef SIMULATION
/* Initialize the Timer */
init_timer(&fluke_timer);
fluke_timer.expires = jiffies + (HZ*10);//Timer will Expire after 60 secQuoted 8 lines
fluke_timer.data = 0; fluke_timer.function = (void *)timer_func; add_timer(&fluke_timer); #endif } return 0; }
Using the count in this way is racy, best write the code so that it can allow multiple opens.
Quoted 16 lines
irqreturn_tDataAcqIntHandler(int irq,void *dev_id, struct pt_regs *regs){ printk(KERN_ALERT" In Interrupt Handler\n"); /* Data present status is set to wake up the read call */ data_present_status=1; /* Wake up the blocked Select call */ wake_up_interruptible(&wait_queue); #ifndef SIMULATION /* Clear the interrupt in the interrupt pending registor */ cpi->ic_scprrh |=DATA_ACQ_INT_CLEAR; #endif return IRQ_HANDLED;
Quoted 1 line
}/* End of
PpsIntrHandler()*/
The interrupt handler should be able to deal with shared interrupts, and needs to check if the interrupt came from this device, returning IRQ_NONE otherwise.
Quoted 12 lines
static int
__initMcBSP_DriverInit(void){ unsigned int virt_addr = 0; int mem = 0; //buf_area = vmalloc(sizeof(circularbuffer_S)); //if(!buf_area) //{ // printk(KERN_ALERT"vmalloc failed \n"); // return -1; //}
Quoted 8 lines
#if 0 /* * Allocate memory for the circular buffer in the DMA coherent area * and algin it in the Cache */ mem = L1_CACHE_ALIGN(sizeof(circularbuffer_S)); buf_ptr = (char *)dma_alloc_coherent(NULL, mem, &dma_addr,GFP_KERNEL);
no need for the cast.
Quoted 19 lines
printk(KERN_INFO" buf_ptr = 0x%x \n",(int )buf_ptr);
if(NULL == buf_ptr )
{
printk(KERN_ALERT" Allocation of Memory failure ");
return -1;
}
buf_area = (circularbuffer_S *)(((unsigned int )buf_ptr + PAGE_SIZE - 1) \
& PAGE_MASK);
printk(KERN_INFO" buf_area = 0x%x \n",(int )buf_area);
if(NULL == buf_area)
{
printk(KERN_ALERT" Circular buffer memory not allocated \n");
return -1;
}
/* Marking the Pages as reserved */Quoted 8 lines
for (virt_addr = (unsigned int)buf_area; \
virt_addr < (unsigned int )buf_area + sizeof(circularbuffer_S);\
virt_addr += PAGE_SIZE)
{
/* Set the pages as reserved */
SetPageReserved(virt_to_page(virt_addr));
//mem_map_reserve(virt_to_page(virt_addr));
}no need for SetPageReserved, it already is marked as in use through the allocation.
Quoted 1 line
phy_addr = virt_to_phys(buf_ptr);
You can't use virt_to_phys to get the dma address. You also don't need that because you already have it in dma_addr.
Quoted 5 lines
printk(KERN_INFO"Allocated Memory for Circular Buffer at physical
0x0%x\n",phy_addr);#else
Quoted 7 lines
buf_area = ioremap(0xB2000000,0x4000); //(0xB2000000,0x4000);
//(7700000,900000);
if(!buf_area)
{
printk(KERN_ALERT"ioremap failed \n");
return -1;
}Don't hardcode the numbers here, you should get the values from the device tree, and use of_iomap().
Quoted 6 lines
printk(" Ioremap mapped to virtual 0x0%x \n",buf_area); *((unsigned int *)buf_area) = 0xa5a5a5a5; printk(" Ioremap data 0x0%x \n",*((unsigned int *)buf_area + 0));#endif
Quoted 11 lines
/* Device major number is registered to set the driver entry point */
if(register_chrdev(MAJOR_NO,MODULE_NAME, &fluke_fops)==0)
{
printk(KERN_DEBUG" Fluke driver registeration success \n");
}
else
{
printk(KERN_ALERT" Fluke driver registeration failed \n");
return -1;
}Since it's just one device, it's easier to use a misc_device.
Quoted 8 lines
/*
* Register Data Acq interrupt request with specified irq and install the
* handler
*/
if(request_irq(DATA_ACQ_INT,(void *)DataAcqIntHandler, SA_INTERRUPT,
MODULE_NAME, NULL)==0)
{
printk(KERN_DEBUG" Data Acq interrupt request returns success \n");Quoted 8 lines
}
else
{
printk(KERN_DEBUG" Data Acq interrupt request failed \n");
unregister_chrdev(MAJOR_NO,MODULE_NAME);
return -1;
}hardcoding interrupt numbers is broken, interrupt numbers are relative to one interrupt controller. Use irq_of_parse_and_map.
Quoted 22 lines
static int McBSP_DriverIoctl(struct inode *inode, struct file *file,\
unsigned int cmd, unsigned long param){ int i; daq_t daq_param; printk(KERN_DEBUG"In ioctl command \n"); switch(cmd) { case START_ACQ_DATA: if(copy_from_user(&daq_param,(void *)param,sizeof(daq_param))) { return -1; } /* For Simulation we are writing the data */ if(WriteBuf() < 0) { printk(" Writing to the memory failure \n");
Quoted 8 lines
return -1;
}
/* Wait for the Interrupt to occur */
wait_event_interruptible( wait_queue, data_present_status !=0);
printk("Read Index before read %d\n",buf_index_area.read_index);
data_present_status=0;Racy, you could have multiple threads doing this ioctl. Moreover, you should not block in an ioctl but rather implement a poll() function for waiting.
Quoted 7 lines
buf_index_area.read_index++;
buf_index_area.read_index%=NO_FRAMES;
if(buf_index_area.read_index ==((buf_index_area.write_index +1) %
NO_FRAMES))
//if(buf_index_area.read_index == buf_index_area.write_index )
{Quoted 8 lines
printk("Read failure because read and write index are same\n");
return -1;
}
/* Decrement the count index to indicate the data availibility */
down(&mutex);
buf_index_area.count_index--;
up(&mutex);New drivers should not use semaphores (up/down) in places where they can use real mutexes (mutex_lock/mutex_unlock).
Quoted 6 lines
static int
McBSP_DriverMmap(struct file *file,struct vm_area_struct *vma){unsigned long start = vma->vm_start; unsigned long size = vma->vm_end - vma->vm_start; //0x900000; unsigned long phy_add = virt_to_phys(buf_ptr); //0x7700000;
virt_to_phys doesn't work on vmalloc memory.
Quoted 5 lines
int ret = 0; /* Make the mmaped area noncacheable */ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
Quoted 7 lines
/* Set the Flags to give permissions to Mmaped area */ vma->vm_flags |=VM_RESERVED; vma->vm_flags |=VM_READ; vma->vm_flags |=VM_WRITE; vma->vm_flags |=VM_IO; //vma->vm_flags |=VM_SHARED; //vma->vm_flags |=VM_LOCKED;
For memory, you typically want to set vm_page_prot to use non-guarded mapping, so that user space accesses are faster.
Not sure if VM_IO is right for vmalloc.
Arnd <><
Quoted 6 lines
printk(KERN_INFO"Allocated Memory for Circular Buffer at physical 0x0%x\n",phy_addr);#else
Quoted 7 lines
buf_area=ioremap(0xB2000000,0x4000); //(0xB2000000,0x4000); //(7700000,900000);if(!buf_area)
{printk(KERN_ALERT"ioremap failed \n");
return -1;
} ...[show rest of quote]
Don't hardcode the numbers here, you should get the values from the device tree, and use of_iomap().
I am really unaware of how can we get this physical address from the device tree which you have mentioned can you please explain this to me ???
Suppose there is one situation in which i have to map ram of the address 0x800000 to 9MB will it be good if i do this to map to user space
static int McBSP_DriverMmap(struct file *file,struct vm_area_struct *vma) {
unsigned long start = vma->vm_start ;
unsigned long size = 0x900000 ;
unsigned long phy_add = 0x800000;
int ret = 0;
/* Make the mmaped area noncacheable */
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
/* Set the Flags to give permissions to Mmaped area */
vma->vm_flags |=VM_RESERVED;
vma->vm_flags |=VM_READ;
vma->vm_flags |=VM_WRITE;
printk(KERN_DEBUG"In mmap function\n");
/* Mmap the kernel buffer to user space */
if(remap_pfn_range(vma,start,(phy_add >>
PAGE_SHIFT),size,vma->vm_page_prot))
{
printk(KERN_ALERT"remap_pfn_range failed\n");
goto mmap_exit;}
printk(KERN_ALERT"phy addr 0x%08X mmapped to virt addr 0x%08X, size =
0x%08X\n",
(unsigned int)phy_add, (unsigned int)start, (unsigned int)size); /* Initialize the file operation structure of Mmaped area */ vma->vm_ops=&mmap_op; /* Open the Mmaped area */ MmapOpen(vma); mmap_exit: return ret; }
suppose the same mapping i have to do using nopage method then shall i specify the RAM physical address and sixe in the same manner ???
There is one more concern that i have now is that i am writing a pattern (say 0xa5a5a5a5) to cpld by building the page using remap_pfn_range but when i try to read it its showing the pattern as a5a5a5a50000000a5a5a5a50000000 like with zeros in between is it a non aligned page problem.
----- Misbah <><
Quoted 370 lines · Arnd Bergmann
Quoted 96 lines · Misbah khan
Hi all ...
I am uploading the source code which is doing the following :-
1. mapping cpld register using ioremap coping the data to circular buffer and remapping it to user space .
2. It can also map kernel virtual dma memory to user space if compiled conditionally .
following is the problem which i am facing ...
1. It is somitimes giving following kernel panic ....
nable to handle kernel NULL pointer dereference at virtual address 00000000
pgd =c0004000
[00000000] *pgd=00000000Internal error: Oops: 17 [#1] Modules linked in: fluke_driver tstamp sig_router mvci_spi mvci_sf_pcd
mvci_sci_unidir_s1mvci_sci_diffmvci_sci_bidir_s
1mvci_rtmd_s1mvci_kwiso_s1mvci_kw1281_s1mvci_kh_s1mvci_j1850mvci_gm_sbcmvci_diagh_s1g_ethermvci_dclmvci_can1fpga_confarcotg_udcadc_dackeypad(F)splc501_lcd(F)cpldCPU: 0 PC is at cascade+0x64/0x8c LR is at __init_begin+0x3fff8000/0x30 pc : [<c00484ac>] lr : [<00000000>] Tainted: GFsp :
c0293ea8ip :0040b000fp :c0293ecc
r10:8001d9f0r9 :c0292000r8 : 00000001
r7 :c0292000r6 :0000000cr5 :c02fa048r4 : 00000000 r3 :c02fa2f8r2 :0000261ar1 :bf01ab70r0 :c02fa2f8
Flags: Nzcv IRQs off FIQs on ModeSVC_32Segment kernel
Control: C5387F
Table: 8698C000 DAC: 00000017
Process swapper (pid: 0, stack limit =0xc0292250)Stack: (0xc0293ea8 to 0xc0294000)3ea0:
bf01ab70c02fb4400000000a00000000c02fa0480000000a
3ec0:c0293efcc0293ed0c0048810c0048454c0293eecc0293ee0c002a30c00000001
3ee0:c02f9e440000000a00000002 00000001c0293f1cc0293f00c00442a0c0048794
3f00:c0293f2c0000001dc029474000000000c0293f2cc0293f20c00446d4c0044254
3f20:c0293f4cc0293f30c00217b0c0044698c0293f5cffffffff0000ffff00000001
3f40:c0293fa4c0293f50c00209e4c002177000000001 00000001c029200000000000
3f60:c0022068c0292000c0298c44c03121c08001da244107b3648001d9f0c0293fa4
3f80:c0293fa8c0293f98c0021d48c002209c60000013 ffffffffc0293fbcc0293fa8
3fa0:c0021d48c0022074c02faae0c02f292cc0293fccc0293fc0c00202e0c0021d24
3fc0:c0293ff4c0293fd0c0008848c00202b4c00083c400000000 00000000c02f29a8
3fe0: 0000000000c5387d00000000c0293ff880008030c00086e000000000 00000000Backtrace: [<c0048448>] (cascade+0x0/0x8c) from [<c0048810>] (run_timer_softirq+0x88/0x1e8) r6 = 0000000A r5 = C02FA048 r4 = 00000000 [<c0048788>] (run_timer_softirq+0x0/0x1e8) from [<c00442a0>] (__do_softirq+0x58/0xc8) r8 = 00000001 r7 = 00000002 r6 = 0000000A r5 = C02F9E44 r4 = 00000001 [<c0044248>] (__do_softirq+0x0/0xc8) from [<c00446d4>] (irq_exit+0x48/0x5c) r6 = 00000000 r5 = C0294740 r4 = 0000001D [<c004468c>] (irq_exit+0x0/0x5c) from [<c00217b0>] (asm_do_IRQ+0x4c/0x64) [<c0021764>] (asm_do_IRQ+0x0/0x64) from [<c00209e4>] (__irq_svc+0x44/0x80) r6 = 00000001 r5 = 0000FFFF r4 = FFFFFFFF [<c0022068>] (default_idle+0x0/0x3c) from [<c0021d48>] (cpu_idle+0x30/0x5c) [<c0021d18>] (cpu_idle+0x0/0x5c) from [<c00202e0>] (rest_init+0x38/0x40) r5 = C02F292C r4 = C02FAAE0 [<c00202a8>] (rest_init+0x0/0x40) from [<c0008848>] (start_kernel+0x174/0x1c0) [<c00086d4>] (start_kernel+0x0/0x1c0) from [<80008030>] (0x80008030) Code: e1530005 15822000 ebffffb6 e1a0e004 (e5944000) <0>Kernel panic - not syncing: Aiee, killing interrupt handler!also when i run it on X86 PC i am able to get the data and no panic where in
on the board it is giving the above error ....2. I can raed the data using the user application when i run it on X86 PC where in i cant able to read the data when i run it on the board the data i
was getting was always '/0' filled buffer .Quoted 8 lines
Here is the compilete code .............
static int
McBSP_DriverOpen(struct inode *inode,struct file *file){ /* Reintialize file operation structure */ file->f_op=&fluke_fops;this is already set.
Quoted 16 lines
printk(KERN_DEBUG" fluke driver open success \n"); if (device_open_count == 0) { device_open_count = 1; /* Reset the read and write index*/ buf_index_area.write_index=0; buf_index_area.read_index=-1; buf_index_area.count_index=0; #ifdef SIMULATION /* Initialize the Timer */ init_timer(&fluke_timer); fluke_timer.expires = jiffies + (HZ*10);//Timer will Expire after 60sec
Quoted 8 lines
fluke_timer.data = 0; fluke_timer.function = (void *)timer_func; add_timer(&fluke_timer); #endif } return 0; }Using the count in this way is racy, best write the code so that it can allow multiple opens.
Quoted 16 lines
irqreturn_tDataAcqIntHandler(int irq,void *dev_id, struct pt_regs *regs){ printk(KERN_ALERT" In Interrupt Handler\n"); /* Data present status is set to wake up the read call */ data_present_status=1; /* Wake up the blocked Select call */ wake_up_interruptible(&wait_queue); #ifndef SIMULATION /* Clear the interrupt in the interrupt pending registor */ cpi->ic_scprrh |=DATA_ACQ_INT_CLEAR; #endif return IRQ_HANDLED;Quoted 1 line
}/* End of
PpsIntrHandler()*/The interrupt handler should be able to deal with shared interrupts, and needs to check if the interrupt came from this device, returning
IRQ_NONEotherwise.Quoted 12 lines
static int
__initMcBSP_DriverInit(void){ unsigned int virt_addr = 0; int mem = 0; //buf_area = vmalloc(sizeof(circularbuffer_S)); //if(!buf_area) //{ // printk(KERN_ALERT"vmalloc failed \n"); // return -1; //}Quoted 8 lines
#if 0 /* * Allocate memory for the circular buffer in the DMA coherent area * and algin it in the Cache */ mem = L1_CACHE_ALIGN(sizeof(circularbuffer_S)); buf_ptr = (char *)dma_alloc_coherent(NULL, mem, &dma_addr,GFP_KERNEL);no need for the cast.
Quoted 20 lines
printk(KERN_INFO" buf_ptr = 0x%x \n",(int )buf_ptr); if(NULL == buf_ptr ) { printk(KERN_ALERT" Allocation of Memory failure "); return -1; } buf_area = (circularbuffer_S *)(((unsigned int )buf_ptr + PAGE_SIZE - 1) \ & PAGE_MASK); printk(KERN_INFO" buf_area = 0x%x \n",(int )buf_area); if(NULL == buf_area) { printk(KERN_ALERT" Circular buffer memory not allocated \n"); return -1; } /* Marking the Pages as reserved */Quoted 8 lines
for (virt_addr = (unsigned int)buf_area; \ virt_addr < (unsigned int )buf_area + sizeof(circularbuffer_S);\ virt_addr += PAGE_SIZE) { /* Set the pages as reserved */ SetPageReserved(virt_to_page(virt_addr)); //mem_map_reserve(virt_to_page(virt_addr)); }no need for SetPageReserved, it already is marked as in use through the allocation.
Quoted 1 line
phy_addr = virt_to_phys(buf_ptr);You can't use
virt_to_physto get the dma address. You also don't need that
because you already have it indma_addr.Quoted 5 lines
printk(KERN_INFO"Allocated Memory for Circular Buffer at physical
0x0%x\n",phy_addr);#else
Quoted 7 lines
buf_area = ioremap(0xB2000000,0x4000); //(0xB2000000,0x4000); //(7700000,900000); if(!buf_area) { printk(KERN_ALERT"ioremap failed \n"); return -1; }Don't hardcode the numbers here, you should get the values from the device tree, and use
of_iomap().Quoted 6 lines
printk(" Ioremap mapped to virtual 0x0%x \n",buf_area); *((unsigned int *)buf_area) = 0xa5a5a5a5; printk(" Ioremap data 0x0%x \n",*((unsigned int *)buf_area + 0));#endif
Quoted 11 lines
/* Device major number is registered to set the driver entry point */ if(register_chrdev(MAJOR_NO,MODULE_NAME, &fluke_fops)==0) { printk(KERN_DEBUG" Fluke driver registeration success \n"); } else { printk(KERN_ALERT" Fluke driver registeration failed \n"); return -1; }Since it's just one device, it's easier to use a
misc_device.Quoted 9 lines
/* * Register Data Acq interrupt request with specified irq and install the * handler */ if(request_irq(DATA_ACQ_INT,(void *)DataAcqIntHandler, SA_INTERRUPT, MODULE_NAME, NULL)==0) { printk(KERN_DEBUG" Data Acq interrupt request returns success \n");Quoted 8 lines
} else { printk(KERN_DEBUG" Data Acq interrupt request failed \n"); unregister_chrdev(MAJOR_NO,MODULE_NAME); return -1; }hardcoding interrupt numbers is broken, interrupt numbers are relative to one interrupt controller. Use
irq_of_parse_and_map.Quoted 22 lines
static int McBSP_DriverIoctl(struct inode *inode, struct file *file,\
unsigned int cmd, unsigned long param){ int i; daq_t daq_param; printk(KERN_DEBUG"In ioctl command \n"); switch(cmd) { case START_ACQ_DATA: if(copy_from_user(&daq_param,(void *)param,sizeof(daq_param))) { return -1; } /* For Simulation we are writing the data */ if(WriteBuf() < 0) { printk(" Writing to the memory failure \n");Quoted 8 lines
return -1; } /* Wait for the Interrupt to occur */ wait_event_interruptible( wait_queue, data_present_status !=0); printk("Read Index before read %d\n",buf_index_area.read_index); data_present_status=0;Racy, you could have multiple threads doing this ioctl. Moreover, you should not block in an ioctl but rather implement a
poll()function for waiting.Quoted 7 lines
buf_index_area.read_index++; buf_index_area.read_index%=NO_FRAMES; if(buf_index_area.read_index ==((buf_index_area.write_index +1) % NO_FRAMES)) //if(buf_index_area.read_index == buf_index_area.write_index ) {Quoted 8 lines
printk("Read failure because read and write index are same\n"); return -1; } /* Decrement the count index to indicate the data availibility */ down(&mutex); buf_index_area.count_index--; up(&mutex);New drivers should not use semaphores (up/down) in places where they can use real
mutexes (mutex_lock/mutex_unlock).Quoted 7 lines
static int
McBSP_DriverMmap(struct file *file,struct vm_area_struct *vma)
{unsigned long start = vma->vm_start; unsigned long size = vma->vm_end - vma->vm_start; //0x900000; unsigned long phy_add = virt_to_phys(buf_ptr); //0x7700000;
virt_to_physdoesn't work on vmalloc memory.Quoted 5 lines
int ret = 0; /* Make the mmaped area noncacheable */ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);Quoted 7 lines
/* Set the Flags to give permissions to Mmaped area */ vma->vm_flags |=VM_RESERVED; vma->vm_flags |=VM_READ; vma->vm_flags |=VM_WRITE; vma->vm_flags |=VM_IO; //vma->vm_flags |=VM_SHARED; //vma->vm_flags |=VM_LOCKED;For memory, you typically want to set
vm_page_protto use non-guarded mapping,
so that user space accesses are faster.Not sure if
VM_IOis right for vmalloc.Arnd <><_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Signature · 2 lines
View this message in context: http://www.nabble.com/how-to-allocate-9MB-of-memory-in-kernel---tp18503022p18647614.html Sent from the linuxppc-embedded mailing list archive at Nabble.com.
Quoted 3 lines · Misbah khan
I am really unaware of how can we get this physical address from the device tree which you have mentioned can you please explain this to me ???
With current Linux versions, all powerpc machines come with an open-firmware like device tree, which describes all devices that are part of the system. If your machine doesn't run an actual open firmware implementation, you most likely have the device tree source in arch/powerpc/boot/dts/, and that needs to describe your device.
Your init function should then not assume that the device is there, but register an of_platform_driver for that device.
When the driver is loaded, it is then bound to your hardware, and a struct of_device gets passed to a probe() function that does the actual initialization.
That is the device you pass to of_iomap in order to mmap the I/O range.
Arnd <><
Hi,
I also want to allocate 4MB space for DMA from external device. if possible, please let me know how did you overcome the problem of using mmap option from the userspace
Regards
Harish
Quoted 452 lines · Misbah khan
Quoted 6 lines
printk(KERN_INFO"Allocated Memory for Circular Buffer at physical 0x0%x\n",phy_addr);#else
Quoted 7 lines
buf_area=ioremap(0xB2000000,0x4000); //(0xB2000000,0x4000); //(7700000,900000);if(!buf_area)
{printk(KERN_ALERT"ioremap failed \n");
return -1;
} ...[show rest of quote]Don't hardcode the numbers here, you should get the values from the device tree, and use
of_iomap().I am really unaware of how can we get this physical address from the device tree which you have mentioned can you please explain this to me ???
Suppose there is one situation in which i have to map ram of the address
0x800000to 9MB will it be good if i do this to map to user spacestatic int
McBSP_DriverMmap(struct file *file,struct vm_area_struct *vma){unsigned long start = vma->vm_start ; unsigned long size = 0x900000 ; unsigned long phy_add = 0x800000; int ret = 0; /* Make the mmaped area noncacheable */ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* Set the Flags to give permissions to Mmaped area */ vma->vm_flags |=VM_RESERVED; vma->vm_flags |=VM_READ; vma->vm_flags |=VM_WRITE; printk(KERN_DEBUG"In mmap function\n"); /* Mmap the kernel buffer to user space */ if(remap_pfn_range(vma,start,(phy_add >> PAGE_SHIFT),size,vma->vm_page_prot)) { printk(KERN_ALERT"remap_pfn_range failed\n"); goto mmap_exit;}printk(KERN_ALERT"phy addr 0x%08X mmapped to virt addr 0x%08X, size =
0x%08X\n",(unsigned int)phy_add, (unsigned int)start, (unsigned int)size); /* Initialize the file operation structure of Mmaped area */ vma->vm_ops=&mmap_op; /* Open the Mmaped area */ MmapOpen(vma); mmap_exit: return ret; }suppose the same mapping i have to do using nopage method then shall i specify the RAM physical address and sixe in the same manner ???
There is one more concern that i have now is that i am writing a pattern (say
0xa5a5a5a5) to cpld by building the page usingremap_pfn_rangebut when i try to read it its showing the pattern asa5a5a5a50000000a5a5a5a50000000like with zeros in between is it a non aligned page problem.----- Misbah <><
Quoted 374 lines · Arnd Bergmann
Quoted 99 lines · Misbah khan
Hi all ...
I am uploading the source code which is doing the following :-
1. mapping cpld register using ioremap coping the data to circular buffer
and remapping it to user space .2. It can also map kernel virtual dma memory to user space if compiled conditionally .
following is the problem which i am facing ...
1. It is somitimes giving following kernel panic ....
nable to handle kernel NULL pointer dereference at virtual address 00000000
pgd =c0004000
[00000000] *pgd=00000000Internal error: Oops: 17 [#1] Modules linked in: fluke_driver tstamp sig_router mvci_spi mvci_sf_pcd
mvci_sci_unidir_s1mvci_sci_diffmvci_sci_bidir_s
1mvci_rtmd_s1mvci_kwiso_s1mvci_kw1281_s1mvci_kh_s1mvci_j1850mvci_gm_sbcmvci_diagh_s1g_ethermvci_dclmvci_can1fpga_confarcotg_udcadc_dackeypad(F)splc501_lcd(F)cpldCPU: 0 PC is at cascade+0x64/0x8c LR is at __init_begin+0x3fff8000/0x30 pc : [<c00484ac>] lr : [<00000000>] Tainted: GFsp :
c0293ea8ip :0040b000fp :c0293ecc
r10:8001d9f0r9 :c0292000r8 : 00000001
r7 :c0292000r6 :0000000cr5 :c02fa048r4 : 00000000 r3 :c02fa2f8r2 :0000261ar1 :bf01ab70r0 :c02fa2f8
Flags: Nzcv IRQs off FIQs on ModeSVC_32Segment kernel
Control: C5387F
Table: 8698C000 DAC: 00000017
Process swapper (pid: 0, stack limit =0xc0292250)Stack: (0xc0293ea8 to 0xc0294000)3ea0:
bf01ab70c02fb4400000000a00000000c02fa0480000000a
3ec0:c0293efcc0293ed0c0048810c0048454c0293eecc0293ee0c002a30c00000001
3ee0:c02f9e440000000a00000002 00000001c0293f1cc0293f00c00442a0c0048794
3f00:c0293f2c0000001dc029474000000000c0293f2cc0293f20c00446d4c0044254
3f20:c0293f4cc0293f30c00217b0c0044698c0293f5cffffffff0000ffff00000001
3f40:c0293fa4c0293f50c00209e4c002177000000001 00000001c029200000000000
3f60:c0022068c0292000c0298c44c03121c08001da244107b3648001d9f0c0293fa4
3f80:c0293fa8c0293f98c0021d48c002209c60000013 ffffffffc0293fbcc0293fa8
3fa0:c0021d48c0022074c02faae0c02f292cc0293fccc0293fc0c00202e0c0021d24
3fc0:c0293ff4c0293fd0c0008848c00202b4c00083c400000000 00000000c02f29a8
3fe0: 0000000000c5387d00000000c0293ff880008030c00086e000000000 00000000Backtrace: [<c0048448>] (cascade+0x0/0x8c) from [<c0048810>] (run_timer_softirq+0x88/0x1e8) r6 = 0000000A r5 = C02FA048 r4 = 00000000 [<c0048788>] (run_timer_softirq+0x0/0x1e8) from [<c00442a0>] (__do_softirq+0x58/0xc8) r8 = 00000001 r7 = 00000002 r6 = 0000000A r5 = C02F9E44 r4 = 00000001 [<c0044248>] (__do_softirq+0x0/0xc8) from [<c00446d4>] (irq_exit+0x48/0x5c) r6 = 00000000 r5 = C0294740 r4 = 0000001D [<c004468c>] (irq_exit+0x0/0x5c) from [<c00217b0>] (asm_do_IRQ+0x4c/0x64) [<c0021764>] (asm_do_IRQ+0x0/0x64) from [<c00209e4>] (__irq_svc+0x44/0x80) r6 = 00000001 r5 = 0000FFFF r4 = FFFFFFFF [<c0022068>] (default_idle+0x0/0x3c) from [<c0021d48>] (cpu_idle+0x30/0x5c) [<c0021d18>] (cpu_idle+0x0/0x5c) from [<c00202e0>] (rest_init+0x38/0x40) r5 = C02F292C r4 = C02FAAE0 [<c00202a8>] (rest_init+0x0/0x40) from [<c0008848>] (start_kernel+0x174/0x1c0) [<c00086d4>] (start_kernel+0x0/0x1c0) from [<80008030>] (0x80008030) Code: e1530005 15822000 ebffffb6 e1a0e004 (e5944000) <0>Kernel panic - not syncing: Aiee, killing interrupt handler!also when i run it on X86 PC i am able to get the data and no panic where in
on the board it is giving the above error ....2. I can raed the data using the user application when i run it on X86 PC
where in i cant able to read the data when i run it on the board the data i
was getting was always '/0' filled buffer .Quoted 8 lines
Here is the compilete code .............
static int
McBSP_DriverOpen(struct inode *inode,struct file *file){ /* Reintialize file operation structure */ file->f_op=&fluke_fops;this is already set.
Quoted 16 lines
printk(KERN_DEBUG" fluke driver open success \n"); if (device_open_count == 0) { device_open_count = 1; /* Reset the read and write index*/ buf_index_area.write_index=0; buf_index_area.read_index=-1; buf_index_area.count_index=0; #ifdef SIMULATION /* Initialize the Timer */ init_timer(&fluke_timer); fluke_timer.expires = jiffies + (HZ*10);//Timer will Expire after 60sec
Quoted 8 lines
fluke_timer.data = 0; fluke_timer.function = (void *)timer_func; add_timer(&fluke_timer); #endif } return 0; }Using the count in this way is racy, best write the code so that it can allow multiple opens.
Quoted 17 lines
irqreturn_tDataAcqIntHandler(int irq,void *dev_id, struct pt_regs *regs){ printk(KERN_ALERT" In Interrupt Handler\n"); /* Data present status is set to wake up the read call */ data_present_status=1; /* Wake up the blocked Select call */ wake_up_interruptible(&wait_queue); #ifndef SIMULATION /* Clear the interrupt in the interrupt pending registor */ cpi->ic_scprrh |=DATA_ACQ_INT_CLEAR; #endif return IRQ_HANDLED;Quoted 1 line
}/* End of
PpsIntrHandler()*/The interrupt handler should be able to deal with shared interrupts, and needs to check if the interrupt came from this device, returning
IRQ_NONEotherwise.Quoted 12 lines
static int
__initMcBSP_DriverInit(void){ unsigned int virt_addr = 0; int mem = 0; //buf_area = vmalloc(sizeof(circularbuffer_S)); //if(!buf_area) //{ // printk(KERN_ALERT"vmalloc failed \n"); // return -1; //}Quoted 8 lines
#if 0 /* * Allocate memory for the circular buffer in the DMA coherent area * and algin it in the Cache */ mem = L1_CACHE_ALIGN(sizeof(circularbuffer_S)); buf_ptr = (char *)dma_alloc_coherent(NULL, mem, &dma_addr,GFP_KERNEL);no need for the cast.
Quoted 20 lines
printk(KERN_INFO" buf_ptr = 0x%x \n",(int )buf_ptr); if(NULL == buf_ptr ) { printk(KERN_ALERT" Allocation of Memory failure "); return -1; } buf_area = (circularbuffer_S *)(((unsigned int )buf_ptr + PAGE_SIZE - 1) \ & PAGE_MASK); printk(KERN_INFO" buf_area = 0x%x \n",(int )buf_area); if(NULL == buf_area) { printk(KERN_ALERT" Circular buffer memory not allocated \n"); return -1; } /* Marking the Pages as reserved */Quoted 8 lines
for (virt_addr = (unsigned int)buf_area; \ virt_addr < (unsigned int )buf_area + sizeof(circularbuffer_S);\ virt_addr += PAGE_SIZE) { /* Set the pages as reserved */ SetPageReserved(virt_to_page(virt_addr)); //mem_map_reserve(virt_to_page(virt_addr)); }no need for SetPageReserved, it already is marked as in use through the allocation.
Quoted 1 line
phy_addr = virt_to_phys(buf_ptr);You can't use
virt_to_physto get the dma address. You also don't need that
because you already have it indma_addr.Quoted 5 lines
printk(KERN_INFO"Allocated Memory for Circular Buffer at physical
0x0%x\n",phy_addr);#else
Quoted 7 lines
buf_area = ioremap(0xB2000000,0x4000); //(0xB2000000,0x4000); //(7700000,900000); if(!buf_area) { printk(KERN_ALERT"ioremap failed \n"); return -1; }Don't hardcode the numbers here, you should get the values from the device tree, and use
of_iomap().Quoted 6 lines
printk(" Ioremap mapped to virtual 0x0%x \n",buf_area); *((unsigned int *)buf_area) = 0xa5a5a5a5; printk(" Ioremap data 0x0%x \n",*((unsigned int *)buf_area + 0));#endif
Quoted 11 lines
/* Device major number is registered to set the driver entry point */ if(register_chrdev(MAJOR_NO,MODULE_NAME, &fluke_fops)==0) { printk(KERN_DEBUG" Fluke driver registeration success \n"); } else { printk(KERN_ALERT" Fluke driver registeration failed \n"); return -1; }Since it's just one device, it's easier to use a
misc_device.Quoted 9 lines
/* * Register Data Acq interrupt request with specified irq and install the * handler */ if(request_irq(DATA_ACQ_INT,(void *)DataAcqIntHandler, SA_INTERRUPT, MODULE_NAME, NULL)==0) { printk(KERN_DEBUG" Data Acq interrupt request returns success \n");Quoted 8 lines
} else { printk(KERN_DEBUG" Data Acq interrupt request failed \n"); unregister_chrdev(MAJOR_NO,MODULE_NAME); return -1; }hardcoding interrupt numbers is broken, interrupt numbers are relative to one interrupt controller. Use
irq_of_parse_and_map.Quoted 22 lines
static int McBSP_DriverIoctl(struct inode *inode, struct file *file,\
unsigned int cmd, unsigned long param){ int i; daq_t daq_param; printk(KERN_DEBUG"In ioctl command \n"); switch(cmd) { case START_ACQ_DATA: if(copy_from_user(&daq_param,(void *)param,sizeof(daq_param))) { return -1; } /* For Simulation we are writing the data */ if(WriteBuf() < 0) { printk(" Writing to the memory failure \n");Quoted 8 lines
return -1; } /* Wait for the Interrupt to occur */ wait_event_interruptible( wait_queue, data_present_status !=0); printk("Read Index before read %d\n",buf_index_area.read_index); data_present_status=0;Racy, you could have multiple threads doing this ioctl. Moreover, you should not block in an ioctl but rather implement a
poll()function for waiting.Quoted 7 lines
buf_index_area.read_index++; buf_index_area.read_index%=NO_FRAMES; if(buf_index_area.read_index ==((buf_index_area.write_index +1) % NO_FRAMES)) //if(buf_index_area.read_index == buf_index_area.write_index ) {Quoted 8 lines
printk("Read failure because read and write index are same\n"); return -1; } /* Decrement the count index to indicate the data availibility */ down(&mutex); buf_index_area.count_index--; up(&mutex);New drivers should not use semaphores (up/down) in places where they can use real
mutexes (mutex_lock/mutex_unlock).Quoted 7 lines
static int
McBSP_DriverMmap(struct file *file,struct vm_area_struct *vma)
{unsigned long start = vma->vm_start; unsigned long size = vma->vm_end - vma->vm_start; //0x900000; unsigned long phy_add = virt_to_phys(buf_ptr); //0x7700000;
virt_to_physdoesn't work on vmalloc memory.Quoted 5 lines
int ret = 0; /* Make the mmaped area noncacheable */ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);Quoted 7 lines
/* Set the Flags to give permissions to Mmaped area */ vma->vm_flags |=VM_RESERVED; vma->vm_flags |=VM_READ; vma->vm_flags |=VM_WRITE; vma->vm_flags |=VM_IO; //vma->vm_flags |=VM_SHARED; //vma->vm_flags |=VM_LOCKED;For memory, you typically want to set
vm_page_protto use non-guarded mapping,
so that user space accesses are faster.Not sure if
VM_IOis right for vmalloc.Arnd <><_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Signature · 2 lines
View this message in context: http://www.nabble.com/how-to-allocate-9MB-of-memory-in-kernel---tp18503022p18792322.html Sent from the linuxppc-embedded mailing list archive at Nabble.com.
Misbah,
Please, give some more details about your application: the answer(s) heavily depends on the kind of memory you want to allocate: contiguous (implied in DMA purpose) or not (for process memory sharing only).
--
sj
2008/7/17 Misbah khan <[email protected]>:
Quoted 8 lines
Hi all,
I need to allocate 9 MB of memory in to the kernel space which i need to mmap for the application to access.
I need to know what could be the best possible way of doing the same.
Quoted 7 lines
Please share your experience in this regard .
Thank you in advance
----Misbah <><
--
View this message in context: http://www.nabble.com/how-to-allocate-9MB-o=
f-memory-in-kernel---tp18503022p18503022.html
Quoted 7 lines
Sent from the linuxppc-embedded mailing list archive at Nabble.com.
_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
--=20
------------------
Sylvain JOYEAU
Freelance Engineer
Software RT-OS R&D
[email protected]
T=E9l: +33-(0)667 477 052
"A good idea is one side of the coin. The other side is the practical usefulness". J. Liedke.
In have a sdram of size 9MB which i would map to kernel space (ioremap woul= d
do that ) the whole 9 MB kernel virtual memory i need to map to the application , the application would read when driver has complited writing and vice versa this implimentation would be in a circular buffer type. The size of my RAM is 128 MB=20
Quoted 4 lines · Sylvain Joyeau
=20
Misbah,
=20
Please, give some more details about your application: the answer(s)
Quoted 24 lines
heavily depends on the kind of memory you want to allocate: contiguous (implied in DMA purpose) or not (for process memory sharing only). =20
--
sj
=20
=20
2008/7/17 Misbah khan <[email protected]>:Quoted 16 lines
Hi all,
I need to allocate 9 MB of memory in to the kernel space which i need to mmap for the application to access.
I need to know what could be the best possible way of doing the same.
Please share your experience in this regard .
Thank you in advance
----Misbah <><
--
View this message in context:
http://www.nabble.com/how-to-allocate-9MB-of-memory-in-kernel---tp185030=
22p18503022.html
Quoted 17 lines
Quoted 7 lines
Sent from the linuxppc-embedded mailing list archive at Nabble.com.
_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded=20
=20
=20
--=20
------------------
Sylvain JOYEAU
Freelance Engineer
Software RT-OS R&D
[email protected]
T=C3=A9l: +33-(0)667 477 052
Quoted 8 lines
"A good idea is one side of the coin. The other side is the practical usefulness". J. Liedke.
_______________________________________________
Linuxppc-embedded mailing list [email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
=20
=20
--=20
View this message in context: http://www.nabble.com/how-to-allocate-9MB-of-=
memory-in-kernel---tp18503022p18504063.html
Sent from the linuxppc-embedded mailing list archive at Nabble.com.