Forum Discussion
Altera_Forum
Honored Contributor
16 years agoLinux with MMU on NEEK
Hi, all.
I'm testing Linux MMU version, on my NEEK. http://www.nioswiki.com/linux It works fine and I can use "bash" shell. This is the evident proof that we are using the true 'fork' instead of 'vfork'. May be this will depends on the version, but TSE driver claims an error and doesn't work on this design. The error is
ERROR: altera_tse.c:1666: request_mem_region() failed
I think that this error is caused by misunderstanding of the usage for the function request_mem_region(). Inside of the request_mem_region(), the function __request_region() is called. If the resource has been already registered, this function returns a non-NULL value, that is the pointer for its resource. But the resource 'sgdma_rx_base' is already registered in the initialization process, so this function returns the 'conflict' and
if (!request_mem_region(sgdma_rx_base, sgdma_rx_size, "altera_tse")) {
is always true. So I made a dirty patch,
if (!request_mem_region(sgdma_rx_base, sgdma_rx_size, "altera_tse")) {
reg_resource = __request_region(&iomem_resource, sgdma_rx_base, sgdma_rx_size, "altera_tse", 0);
if (reg_resource != NULL && reg_resource->flags & IORESOURCE_BUSY) {
printk(KERN_ERR "ERROR: %s:%d: request_mem_region() failed\n", __FILE__, __LINE__);
ret = -EBUSY;
goto out_sgdma_rx;
}
}
Moreover, the author is forgetting that the DMA is working in the physical address world, so we need to set the pointers of descripters like
// desc->source = read_addr;
desc->source = virt_to_phys(read_addr);
// desc->destination = write_addr;
desc->destination = virt_to_phys(write_addr);
// desc->next = (unsigned int *)next;
desc->next = (unsigned int *)((unsigned long)next & 0x1fffffffUL);
and so on. Also the frame buffer fb0 will not work well, because the driver 'altfb.c' is not implemented for Linux with MMU version. So I put some codes for altfb_mmap(), like
/* We implement our own mmap to set MAY_SHARE and add the correct size */
static int altfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
unsigned long phys_addr, phys_size;
unsigned long addr;
unsigned long size = vma->vm_end - vma->vm_start;
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
// vma->vm_flags |= VM_MAYSHARE | VM_SHARED;
// vma->vm_start = info->screen_base;
// vma->vm_end = vma->vm_start + info->fix.smem_len;
/* check range */
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return -EINVAL;
if (offset + size > altfb_fix.smem_len)
return -EINVAL;
vma->vm_flags |= VM_IO | VM_RESERVED;
addr = vma->vm_start;
phys_addr = altfb_fix.smem_start + offset;
if ((offset + size) < altfb_fix.smem_len)
phys_size = size;
else
phys_size = altfb_fix.smem_len - offset;
vma->vm_page_prot = __pgprot(_PAGE_PRESENT|_PAGE_READ|_PAGE_WRITE);
if (remap_pfn_range(vma, addr, phys_addr >> PAGE_SHIFT, phys_size, vma->vm_page_prot))
return -EAGAIN;
return 0;
}
and rewrite the DMA descripters like
desc->next = (void *)virt_to_phys((desc + 1));
So now, I can evoke telnetd and control NEEK through ethernet, and use Nano-X on Linux MMU version, but can't enter ftp session, because 'getservbyname()' function will not work well. I don't know the directory that the souce of 'getservbyname()' is included. Would anyone please tell me where is it? Thank you, in advance.95 Replies
- Altera_Forum
Honored Contributor
Hi,
--- Quote Start --- If this code does work why not upload it as a patch ? --- Quote End --- May I do such thing without permission? Of course, I'm using this patch in my NEEK without any trouble, e.g. telnet, ftp... but this is only a dirty and temporary patch and not well considered. It may be not robust. Kazu P.S. I'm a Japanese, hesitation and modesty are our key characters.:D - Altera_Forum
Honored Contributor
--- Quote Start --- May I do such thing without permission? --- Quote End --- AFAIK, you need a git server account, which Hippo might provide. --- Quote Start --- Of course, I'm using this patch in my NEEK without any trouble, e.g. telnet, ftp... but this is only a dirty and temporary patch and not well considered. It may be not robust. --- Quote End --- Git is specially created to handle this. There are appropriate branches for this purpose in Hippo's git database or you can create a new branch. --- Quote Start --- P.S. I'm a Japanese, hesitation and modesty are our key characters.:D --- Quote End --- Seemingly very different from (at least some) Chinese's which I met in several technical forums. I thought they are your close neighbors :p. -Michael - Altera_Forum
Honored Contributor
--- Quote Start --- Hi, Please see and try this. Kazu P.S. Why can't we attach *.c and *.h files directly? --- Quote End --- Thanks a lot! The driver seems to work at some level now. dhcpcd doesn't work, with either driver I get:
and it takes down eth0 if it was previously brought up with ifconfig. It's a SIGBUS so probably another incorrect memory access issue.dhcpcd: terminating on signal 7 - Altera_Forum
Honored Contributor
TO_BE_DONE
- Altera_Forum
Honored Contributor
Hi,
--- Quote Start --- dhcpcd doesn't work, with either driver I get:
and it takes down eth0 if it was previously brought up with ifconfig. It's a SIGBUS so probably another incorrect memory access issue. --- Quote End --- I think that you are using the dhcpcd of 'dhcpcd-new' directory(Mr.Yoichi Hariguchi's dhcpcd will claim 'ioctl SIOCSIFBRDADDR (ifConfig): Cannot assign requested address' and not work). So I debugged the new dhcpcd and found that the error is caused by calling a function ' memset' in the file 'client.c'dhcpcd: terminating on signal 7
This may be a dynamic linking error, but I don't know the reason exactly. Kazuvoid *dhcpReboot() { dhcpStart(); memset(&DhcpOptions,0,sizeof(DhcpOptions)); // <- This calling will generate a signal SIGSEGV in my debugger. memset(&DhcpIface,0,sizeof(dhcpInterface)); if ( readDhcpCache() ) { - Altera_Forum
Honored Contributor
--- Quote Start --- Hi, I think that you are using the dhcpcd of 'dhcpcd-new' directory(Mr.Yoichi Hariguchi's dhcpcd will claim 'ioctl SIOCSIFBRDADDR (ifConfig): Cannot assign requested address' and not work). So I debugged the new dhcpcd and found that the error is caused by calling a function ' memset' in the file 'client.c'
This may be a dynamic linking error, but I don't know the reason exactly. Kazu --- Quote End --- Actually, it (dhcpcd-new) wasn't crashing there, but in udpipgen.c in in_cksum. However, dhclient (ISC) works in this version (it didn't compile in the nommu version) so I am using that now. I was trying to get DHCP working because I thought maybe I was just misconfiguring something, but I am still not seeing any communication in or out of the device, so I am back to trying to debug the driver. This hardware design was working before the MMU was added. Now I get no errors or hangs, it's just not sending or receiving anything. Kazuyasu: in your altera_tse.c, you changed from using the .ndo functions to setting them somewhere else, was there a reason for that?void *dhcpReboot() { dhcpStart(); memset(&DhcpOptions,0,sizeof(DhcpOptions)); // <- This calling will generate a signal SIGSEGV in my debugger. memset(&DhcpIface,0,sizeof(dhcpInterface)); if ( readDhcpCache() ) { - Altera_Forum
Honored Contributor
Hi,
--- Quote Start --- I was trying to get DHCP working because I thought maybe I was just misconfiguring something, but I am still not seeing any communication in or out of the device, so I am back to trying to debug the driver. This hardware design was working before the MMU was added. Now I get no errors or hangs, it's just not sending or receiving anything. --- Quote End --- So I tested 'dhclient' and don't know whether it's fortunate or unfortunate, but it sends DHCP DISCOVER packets from my NEEK. The DHCP server returns an IP address. Of course, I encountered several bugs. 1) The compiler translates the function
in the file '/common/packet.c' to the next machine codememcpy (&from -> sin_addr, &ip -> ip_src, 4);
. Unfortunately, the address of 'from -> sin_addr' is word-aligned, so the code 'ldw r2,0(r21)' will evoke SIGBUS error. The detour is to rewrite the function as follows.0x0000aeb0 <decode_udp_ip_header+152>: ldw r2,0(r21) 0x0000aeb4 <decode_udp_ip_header+156>: add r17,r16,r19 0x0000aeb8 <decode_udp_ip_header+160>: stw r2,4(fp)
2) Also the checksum is wrong, I only comment the code out.{ int i; unsigned char *pd = &ip -> ip_src, *ps = &from -> sin_addr; for (i = 0; i < 4; i++) *pd++ = *ps++; }
Maybe , the function 'checksum' has some bugs. And 'dhclient-script' is not interpreted well. Maybe we need 'bash'. --- Quote Start --- in your altera_tse.c, you changed from using the .ndo functions to setting them somewhere else, was there a reason for that? --- Quote End --- I can't understand what you mean, but I think that these malfunctions are not caused by the driver. Kazu// if (usum && usum != sum) { // udp_packets_bad_checksum++; // if (udp_packets_seen > 4 && // (udp_packets_seen / udp_packets_bad_checksum) < 2) { // note ("%d bad udp checksums in %d packets", // udp_packets_bad_checksum, udp_packets_seen); // udp_packets_seen = udp_packets_bad_checksum = 0; // } // return -1; // } - Altera_Forum
Honored Contributor
Ooops ?!?!?!?
AFAIK, the memcpy() function/macro (builtin_memcpy)) is supposed to handle alignment issues automatically. If from->sin_addr is a long (or pointer) type, it can assume it is aligned correctly, Thus the compiled code might be correct. Maybe some erroneous memcpy() macro is active when the code sequence is compiled,. If it is not, I would give memcpy the correct alignment. e.g.: memcpy ((char*)&from -> sin_addr, (char*)&ip -> ip_src, 4); If the compiled code in fact is erroneous, we would need to have the library macro or compiler fixed.... -Michael - Altera_Forum
Honored Contributor
Hi,
--- Quote Start --- If from->sin_addr is a long (or pointer) type, it can assume it is aligned correctly, Thus the compiled code might be correct. --- Quote End --- Yes, you are right. And I think this source will not consider the machines that can not do unaligned-access. --- Quote Start --- If it is not, I would give memcpy the correct alignment. e.g.: memcpy ((char*)&from -> sin_addr, (char*)&ip -> ip_src, 4); --- Quote End --- Maybe, it's OK. And sorry, I made a mistake for the copy direction.
Kazu{ int i; //unsigned char *pd = &ip -> ip_src, *ps = &from -> sin_addr; unsigned char *ps = &ip -> ip_src, *pd = &from -> sin_addr; for (i = 0; i < 4; i++) *pd++ = *ps++; } - Altera_Forum
Honored Contributor
--- Quote Start --- Hi, So I tested 'dhclient' and don't know whether it's fortunate or unfortunate, but it sends DHCP DISCOVER packets from my NEEK. The DHCP server returns an IP address. Of course, I encountered several bugs. 1) The compiler translates the function
in the file '/common/packet.c' to the next machine codememcpy (&from -> sin_addr, &ip -> ip_src, 4);
. Unfortunately, the address of 'from -> sin_addr' is word-aligned, so the code 'ldw r2,0(r21)' will evoke SIGBUS error. The detour is to rewrite the function as follows.0x0000aeb0 <decode_udp_ip_header+152>: ldw r2,0(r21) 0x0000aeb4 <decode_udp_ip_header+156>: add r17,r16,r19 0x0000aeb8 <decode_udp_ip_header+160>: stw r2,4(fp)
2) Also the checksum is wrong, I only comment the code out.{ int i; unsigned char *pd = &ip -> ip_src, *ps = &from -> sin_addr; for (i = 0; i < 4; i++) *pd++ = *ps++; }
Maybe , the function 'checksum' has some bugs. And 'dhclient-script' is not interpreted well. Maybe we need 'bash'. I can't understand what you mean, but I think that these malfunctions are not caused by the driver. Kazu --- Quote End --- That's interesting, I didn't run into a SIGBUS or any crashes with dhclient. dhclient-script didn't get installed by uClinux-dist and I didn't see one there, so I just took the one from my desktop and changed bash to hush, so that could be causing problems. Networking does work on the NEEK using your driver patch and the design on the wiki, contrary to what the wiki says about that design! I can get an address with DHCP using dhcpcd (-new) if I comment out the checksum part that causes the SIGBUS. So it does seem that my problem on the custom hardware is not entirely caused by the driver -- though it did work before adding the MMU. Maybe it's the PHY driver.// if (usum && usum != sum) { // udp_packets_bad_checksum++; // if (udp_packets_seen > 4 && // (udp_packets_seen / udp_packets_bad_checksum) < 2) { // note ("%d bad udp checksums in %d packets", // udp_packets_bad_checksum, udp_packets_seen); // udp_packets_seen = udp_packets_bad_checksum = 0; // } // return -1; // }