LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel
User Name
Password
Linux - Kernel This forum is for all discussion relating to the Linux kernel.

Notices


Reply
  Search this Thread
Old 08-16-2018, 09:28 AM   #1
ezaluzec
LQ Newbie
 
Registered: Jun 2017
Posts: 3

Rep: Reputation: Disabled
Modified Linux kernel driver to use a virtual address instead of a physical address


I've modified a Linux kernel sound driver to use a new virtual address instead of a physical address when receiving data. When the driver is called on, it reports that the data is 0. I'm looking for any input or feedback on what I may be missing in my process and implementation. If my descriptions below are too vague to give proper feedback, I am happy to expand and provide more details.

I have a physical register at address 0xc0056014. The hardware register is readable and is correctly initialized in the device tree and Linux kernel(4.4.71). The register holds audio data input from a microphone.

The bits in the physical register are not mapped correctly for playback. This causes audio playback to be filled with white-noise and hissing. I've made a user-space program that will take a raw audio sample and remap the data bits to new raw/wav sample where playback quality is as expected.

My goal is to have this data remapping done in the kernel space. Example data in physical register: 0x4000f965 Example data remapped : 0xf9654000

In the kernel sound driver written for the hardware's audio interface, I've done the following:
  1. Initialized a new virtual address with
    Code:
    vzalloc(data_size)
  2. Started a thread.
  3. In thread, mapped physical register with
    Code:
    __iomem *regs = ioremap(0xc0056014, 4);
  4. Read the register values into temp buffers & remap the 32bits.
  5. Write remap value to virtual address with
    Code:
    memcpy(dst_addr, src_addr, data_size);
  6. Lastly, outside of thread where driver was setting address of physical register, I changed to the virtual address.
    Code:
    dma->peri_addr = dst_addr;

I'm able to do kernel prints that read the values in my virtual address. The kernel prints show correct values in virtual address, but when calling on the kernel sound driver by use of alsa recording tools, the audio data is being reported as 0.

The kernel reports no errors or warnings and I'm a little stumped at what I'm missing or what to do next. Any pointers, tips, feedback, or questions is welcome!

Cheers.


Driver setting address:

Code:
		if (phy_base == 0xC0056000 && dma == &par->capt)
		{
			void *p;
			size_t data_size;
			data_size = sizeof(unsigned long);	
			p = vzalloc(data_size);
			void *dst_addr = (void *)(p);
			printk(KERN_INFO "Virtual Address is : 0x%p\n", p);
			
			char our_thread[8]="thread1";
			thread1 = kthread_create(thread_fn,dst_addr,our_thread);
	
			if((thread1))
			{
				printk(KERN_INFO "Hit thread1");
				wake_up_process(thread1);
			}			
			dma->peri_addr = dst_addr;
			printk(KERN_INFO "snd i2s1: %s dma peri addr is 0x%p and virtual addr is 0x%p\n", STREAM_STR(i), (void *)dma->peri_addr, p);
		}
Thread:

Code:
		int thread_fn(void *dst_addr) {
			printk(KERN_INFO "Hit inside thread1\n");

			size_t data_size;
			data_size = sizeof(unsigned long);	

			int k = 0;
			
			while (1) {
				
				//printk(KERN_INFO "Virtual Address is : 0x%p\n", p);
					
				unsigned long read_result;
				void __iomem *regs = ioremap(0xc0056014, 4);	
			
				read_result = *((unsigned long *) regs);	

				
				uint32_t sample = read_result;
				uint32_t sample1, sample1buf1, sample1buf2, sample1buf3, sample1buf4;
					 
				sample1buf1 = (sample >> (8*0)) & 0xff; 
				sample1buf2 = (sample >> (8*1)) & 0xff;  
				sample1buf3 = (sample >> (8*2)) & 0xff;			
				sample1buf4 = (sample >> (8*3)) & 0xff;		
				
				/* Shift bytes from s16le format bit order to s32le format bit order
				 [  L   |   R  ]    [          L]
				 [  L   |   R  ]    [          R]
					 MSB     MSB              MSB
				 [99 f9 | 00 40] -> [00 40 99 f9]
				 [cf f9 | 00 40] -> [00 40 cf f9]
				 [12 34 | 56 78] -> [56 78 12 34]
				*/
				sample1buf1 = sample1buf1 << 16;
				sample1buf2 = sample1buf2 << 24;
				sample1buf4 = sample1buf4 << 8;		
				
				sample1 = sample1 & 0x00000000;
				sample1 = sample1 | sample1buf3;
				sample1 = sample1 | sample1buf4;
				sample1 = sample1 | sample1buf1;
				sample1 = sample1 | sample1buf2;
				sample = sample1;

				void *src_addr;
				src_addr = &sample;
				memcpy(dst_addr, src_addr, data_size);
						
				iounmap(regs);	
			}

			return 0;
		}

Last edited by ezaluzec; 08-16-2018 at 09:44 AM. Reason: Add code
 
Old 08-25-2018, 10:01 AM   #2
Mara
Moderator
 
Registered: Feb 2002
Location: Grenoble
Distribution: Debian
Posts: 9,696

Rep: Reputation: 232Reputation: 232Reputation: 232
Hello ezaluzec, where do you use the virtual address? Do you pass it directly to other kernel modules, to user space? Virtual memory is usable in its' context only, if you use it in differnet one, the address may point to completely different space. This happens if it's associated with another process/thread for example. I'm wondering if it's your case.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
linux kernel is running in physical address or virtual address? clp510 Linux - Kernel 8 06-04-2014 06:53 AM
linux kernel is running in physical address or virtual address? clp510 Linux - Newbie 3 06-03-2014 06:59 AM
When IOMMU is enabled, how to get the Kernel Virtual Address from a Physical address leechaotang Linux - Kernel 1 11-10-2011 12:21 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel

All times are GMT -5. The time now is 12:16 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration