More ioremap trouble (sock_recvmsg)

Stephen Cameron steve.cameron at hp.com
Tue Jul 23 04:45:25 EST 2002


Hello,

Hmm, I'm *still* having trouble with ioremap on powerpc,
but at least it's different trouble.  (It still works fine on x86).

Here's the situation:  IBM ebony (440) board w/ 128Mb RAM.
Boot kernel with "mem=64M", then use ioremap to access the
unused 64M RAM.

	ioremapped_buffer = ioremap(1024*1024*64, 1024*1024*64);

I'm able to DMA between this memory and a PCI device, although
I have to do virtual-physical address translation myself (pci_map_single
won't do it, virt_to_phys just subtracts C-zillion, turns out wrong, since
I ioremapped the memory myself, the translation is trivial.)

I can also memset()/memcpy() to/from this ioremapped_buffer just fine.

I'm trying to use sock_recvmsg to receive into this ioremapped buffer.
It works, sometimes, but crashes inside __copy_tofrom_user eventually.
It does not appear to always do the exact same thing.  This could be due to
the network making things behave differently, I suppose.)  The iovec
that I used with sock_recvmsg has just one entry, the address, which is
ioremapped_buffer (or some offset from it) and a length.

I tried a sledgehammer approach, replacing copy_to_user with memcpy
when I know the address in question can work that way.

Index: iovec.c
===================================================================
RCS file: /linuxcvs/slipstream/sslinux/net/core/iovec.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 iovec.c
--- iovec.c	28 May 2002 16:03:31 -0000	1.1.1.1
+++ iovec.c	22 Jul 2002 16:04:48 -0000
@@ -78,7 +78,7 @@
  *
  *	Note: this modifies the original iovec.
  */
-
+extern unsigned char *ioremapped_buffer;
 int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
 {
 	int err = -EFAULT;
@@ -88,8 +88,14 @@
 		if(iov->iov_len)
 		{
 			int copy = min_t(unsigned int, iov->iov_len, len);
-			if (copy_to_user(iov->iov_base, kdata, copy))
+			if (ioremapped_buffer != NULL &&
+				iov->iov_base >= ioremapped_buffer &&
+				iov->iov_base <=
+					(ioremapped_buffer + 64*1024*1024))
+				memcpy(iov->iov_base, kdata, copy);
+			else if (copy_to_user(iov->iov_base, kdata, copy)) {
 				goto out;
+			}
 			kdata+=copy;
 			len-=copy;
 			iov->iov_len-=copy;

(not sure why it's using copy_to_user anyway... I guess probably
normally this is entered from user context via a recv() system call,
in my case, not so, I come here from a kernel thread in a module...):

So this patch makes it work considerably longer.  However, again it crashes
inside __copy_tofrom_user, eventually (in a different call).  I'm
thinking maybe I can continue in a similar vein, replacing more
copy_to_user() calls with memcpy, but this strikes me as being
inelegant, and I wonder if I'm doing something wrong with my ioremap...

or, is sock_recvmsg designed to be called only from process context
(e.g. not a kernel thread)?  If so, then why does it work on x86
but not powerpc?

Thanks,

-- steve


** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/





More information about the Linuxppc-embedded mailing list