* Re: Intel P6 vs P7 system call performance
From: Rogier Wolff @ 2002-12-18 12:57 UTC (permalink / raw)
To: Linus Torvalds
Cc: Ulrich Drepper, Alan Cox, Matti Aarnio, Hugh Dickins, Dave Jones,
Ingo Molnar, Linux Kernel Mailing List, hpa
In-Reply-To: <Pine.LNX.4.44.0212171106210.1095-100000@home.transmeta.com>
On Tue, Dec 17, 2002 at 11:10:20AM -0800, Linus Torvalds wrote:
>
>
> On Tue, 17 Dec 2002, Ulrich Drepper wrote:
> >
> > But this is exactly what I expect to happen. If you want to implement
> > gettimeofday() at user-level you need to modify the page.
>
> Note that I really don't think we ever want to do the user-level
> gettimeofday(). The complexity just argues against it, it's better to try
> to make system calls be cheap enough that you really don't care.
I'd say that this should not be "fixed" from userspace, but from the
kernel. Thus if the kernel knows that the "gettimeofday" can be made
faster by doing it completely in userspace, then that system call
should be "patched" by the kernel to do it faster for everybody.
Next, someone might find a faster (full-userspace) way to do some
"reads"(*). Then it might pay to check for that specific
filedescriptor in userspace, and only call into the kernel for the
other filedescriptors. The idea is that the kernel knows best when
optimizations are possible.
Thus that ONE magic address is IMHO not the right way to do it. By
demultiplexing the stuff in userspace, you can do "sane" things with
specific syscalls.
So for example, the code at 0xffff80000 would be:
mov 0x00,%eax
int $80
ret
(in the case where sysenter & friends is not available)
moving the "load syscall number into the register" into the
kernel-modifiable area does not cost a thing, but because we have
demultiplexed the code, we can easily replace the gettimeofday call by
something that (when it's easy) doesn't require the 600-cycle call
into kernel mode.
The "syscall _NR" would then become:
call 0xffff8000 + _NR * 0x80
allowing for up to 0x80 bytes of "patchup code" or "do it quickly"
code, but also for a jump to some other "magic page", that has more
extensive code.
(Oh, I'm showing a base of 0xffff8000: A bit lower than previous
suggestions: allowing for a per-syscall entrypoint, and up to 0x80
bytes of fixup or "do it really quickly" code.)
P.S. People might argue that using this large "stride" would have a
larger cache-footprint. I think that all "where it matters" programs
will have a very small working-set of system calls. It might pay to
use a stride of say 0xa0 to spread the different
system-call-code-points over different cache-lines whenever possible.
Roger.
(*) I was trying to pick a particularly unlikely case, but I can even
see a case where this is useful. For example, a kernel might be
compiled with "high performance pipes", which would move most of the
pipe reads and writes into userspace, through a shared-memory window.
--
** R.E.Wolff@BitWizard.nl ** http://www.BitWizard.nl/ ** +31-15-2600998 **
*-- BitWizard writes Linux device drivers for any device you may have! --*
* The Worlds Ecosystem is a stable system. Stable systems may experience *
* excursions from the stable situation. We are currently in such an *
* excursion: The stable situation does not include humans. ***************
^ permalink raw reply
* Re: Intel P6 vs P7 system call performance
From: Terje Eggestad @ 2002-12-18 12:55 UTC (permalink / raw)
To: Linus Torvalds
Cc: Ulrich Drepper, Matti Aarnio, Hugh Dickins, Dave Jones,
Ingo Molnar, linux-kernel, hpa
what about:
int (*_vsyscall) (int, ...);
_vsyscall = mmap(NULL, getpagesize(), PROT_READ|PROT_EXEC,
MAP_VSYSCALL, , );
or if you're afraid of running out of MAP_* flags:
fd = open("/dev/vsyscall", );
_vsyscall = mmap(NULL, getpagesize(), PROT_READ|PROT_EXEC, MAP_SHARED,
fd, 0);
Then you can leisurely map it in just after the programs text segment.
TJ
On tir, 2002-12-17 at 18:55, Linus Torvalds wrote:
> On Tue, 17 Dec 2002, Matti Aarnio wrote:
> >
> > On Tue, Dec 17, 2002 at 09:07:21AM -0800, Linus Torvalds wrote:
> > > On Tue, 17 Dec 2002, Hugh Dickins wrote:
> > > > I thought that last page was intentionally left invalid?
> > >
> > > It was. But I thought it made sense to use, as it's the only really
> > > "special" page.
> >
> > In couple of occasions I have caught myself from pre-decrementing
> > a char pointer which "just happened" to be NULL.
> >
> > Please keep the last page, as well as a few of the first pages as
> > NULL-pointer poisons.
>
> I think I have a good clean solution to this, that not only avoids the
> need for any hard-coded address _at_all_, but also solves Uli's problem
> quite cleanly.
>
> Uli, how about I just add one ne warchitecture-specific ELF AT flag, which
> is the "base of sysinfo page". Right now that page is all zeroes except
> for the system call trampoline at the beginning, but we might want to add
> other system information to the page in the future (it is readable, after
> all).
>
> So we'd have an AT_SYSINFO entry, that with the current implementation
> would just get the value 0xfffff000. And then the glibc startup code could
> easily be backwards compatible with the suggestion I had in the previous
> email. Since we basically want to do an indirect jump anyway (because of
> the lack of absolute jumps in the instruction set), this looks like the
> natural way to do it.
>
> That also allows the kernel to move around the SYSINFO page at will, and
> even makes it possible to avoid it altogether (ie this will solve the
> inevitable problems with UML - UML just wouldn't set AT_SYSINFO, so user
> level just wouldn't even _try_ to use it).
>
> With that, there's nothing "special" about the vsyscall page, and I'd just
> go back to having the very last page unmapped (and have the vsyscall page
> in some other fixmap location that might even depend on kernel
> configuration).
>
> Whaddaya think?
>
> Linus
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
--
_________________________________________________________________________
Terje Eggestad mailto:terje.eggestad@scali.no
Scali Scalable Linux Systems http://www.scali.com
Olaf Helsets Vei 6 tel: +47 22 62 89 61 (OFFICE)
P.O.Box 150, Oppsal +47 975 31 574 (MOBILE)
N-0619 Oslo fax: +47 22 62 89 51
NORWAY
_________________________________________________________________________
^ permalink raw reply
* RE: Intel sez: Synchronous Flash and XIP is the future -- thought s?
From: Paul Nash @ 2002-12-18 13:13 UTC (permalink / raw)
To: 'manningc2@actrix.gen.nz', Russ Dill, linux-mtd
So what are people out there using in their designs for NAND primarily? Raw
NAND? NAND plus some bootable sector? DiskOnChip?
-----Original Message-----
From: Charles Manning [mailto:manningc2@actrix.gen.nz]
Sent: Monday, December 16, 2002 3:19 PM
To: Russ Dill; linux-mtd@lists.infradead.org
Subject: Re: Intel sez: Synchronous Flash and XIP is the future -- thoughts?
On Tue, 17 Dec 2002 10:21, you wrote:
> On Mon, 2002-12-16 at 14:02, Charles Manning wrote:
> > Intel's flash is expensive. Figure somwhere over $1 per MB. NAND
> > costs approx 30c/MB + SDRAM approx 20c/MB. Intel's flash thus costs
> > approx twice what a NAND/RAM image does.
> >
> > One NAND flash footprint can give you up to 256MB of storage.
> >
> > NOR fully sucks for any sort of writeable file system performance.
> > NAND runs a very usable fs with YAFFS or JFFS2.
> >
> > The only benefit I can see in NOR is a faster boot. This is becoming
> > less of an issue as more designs switch to sleep/resume models.
>
> It really depends on how much data you store, and how you use that
> data. Sure, for you, with a dynamic file system, and 256M of storage,
> NAND is an easy choice. But many designs out there have static file
> systems, use 2M or 4M of flash, and for such designs, NOR offers a lot
> more simplicity for around the same cost as a NAND + boot logic. With
> NOR flash, I can put a couple cramfs filesystems on there, and use the
> boot block for storing a simple journalled config, reliably. I don't
> have to worry about setting aside blocks in case one goes bad.
>
> I think this is the market intel is targeting, just change 2M or 4M to
> 4M or 8M (no more compressed fs).
True, flexibility is the key. If 2-4MB with a static fs is all you need,
then
no need to take on all the extra drama.
However, to get back to the start of this thread, Intels big push is for the
larger sizes (8MB+) where NOR is less palatable.
-- CHarles
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply
* iptables accounting problem
From: ITM CS Ruslan O. Nesterov @ 2002-12-18 12:41 UTC (permalink / raw)
To: netfilter
Hello netfilter list,
I'm sorry for asking this question, I red all the documentation
and still got no clue how to make ip accounting work.
I got a pc with 2 ethernet cards all traffics goes through it.
i created a rule like
iptables -N xxx.xxx.xxx.xxx
iptables -A input -d xxx.xxx.xxx.xxx -j xxx.xxx.xxx.xxx
when i type
iptables -L xxx.xxx.xxx.xxx -n -v
i get 0 traffic information. How could be? Or whereis my
mistake?
--
Best regards,
ITM mailto:ruslan@complexsystem.ru
^ permalink raw reply
* New style dpalloc/hostalloc routines (diff).
From: Pantelis Antoniou @ 2002-12-18 12:39 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 35 bytes --]
Sorry forgot to attach the patch.
[-- Attachment #2: new_cpm_alloc.patch --]
[-- Type: text/plain, Size: 32901 bytes --]
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux 2.4 for PowerPC development tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.1190 -> 1.1191
# arch/ppc/8xx_io/Makefile 1.8 -> 1.9
# arch/ppc/8xx_io/commproc.c 1.19 -> 1.20
# arch/ppc/kernel/ppc_ksyms.c 1.106 -> 1.107
# include/asm-ppc/commproc.h 1.4 -> 1.5
# arch/ppc/8xx_io/Config.in 1.10 -> 1.11
# (new) -> 1.1 arch/ppc/8xx_io/rheap.c
# (new) -> 1.1 arch/ppc/8xx_io/rheap.h
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/12/18 panto@macpanto.intranet.gr 1.1191
# Add support for new style dpalloc/hostalloc routines
# which properly manage memory, and permit their use in modules.
# --------------------------------------------
#
diff -Nru a/arch/ppc/8xx_io/Config.in b/arch/ppc/8xx_io/Config.in
--- a/arch/ppc/8xx_io/Config.in Wed Dec 18 14:27:45 2002
+++ b/arch/ppc/8xx_io/Config.in Wed Dec 18 14:27:45 2002
@@ -36,5 +36,11 @@
bool 'Copy-Back Data Cache (else Writethrough)' CONFIG_8xx_COPYBACK
bool 'CPU6 Silicon Errata (860 Pre Rev. C)' CONFIG_8xx_CPU6
bool 'I2C/SPI Microcode Patch' CONFIG_UCODE_PATCH
+# Support new type of routines, usable from modules
+bool 'Use new type dpalloc routines()' CONFIG_NEW_DPALLOC
+bool 'Use new type hostalloc routines()' CONFIG_NEW_HOSTALLOC
+if [ "$CONFIG_NEW_DPALLOC" = "y" -o "$CONFIG_NEW_HOSTALLOC" = "y" ]; then
+ define_bool CONFIG_CPM_RHEAP y
+fi
endmenu
diff -Nru a/arch/ppc/8xx_io/Makefile b/arch/ppc/8xx_io/Makefile
--- a/arch/ppc/8xx_io/Makefile Wed Dec 18 14:27:45 2002
+++ b/arch/ppc/8xx_io/Makefile Wed Dec 18 14:27:45 2002
@@ -17,5 +17,6 @@
obj-$(CONFIG_SCC_ENET) += enet.o
obj-$(CONFIG_UCODE_PATCH) += micropatch.o
obj-$(CONFIG_HTDMSOUND) += cs4218_tdm.o
+obj-$(CONFIG_CPM_RHEAP) += rheap.o
include $(TOPDIR)/Rules.make
diff -Nru a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c
--- a/arch/ppc/8xx_io/commproc.c Wed Dec 18 14:27:45 2002
+++ b/arch/ppc/8xx_io/commproc.c Wed Dec 18 14:27:45 2002
@@ -38,12 +38,27 @@
#include <asm/8xx_immap.h>
#include <asm/commproc.h>
+#include <linux/slab.h>
+#include "rheap.h"
+
extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep);
+#ifndef CONFIG_NEW_DPALLOC
static uint dp_alloc_base; /* Starting offset in DP ram */
static uint dp_alloc_top; /* Max offset + 1 */
+#else
+/* needed for dpalloc_index */
+static uint faked_dp_alloc_base;
+void new_m8xx_cpm_dpinit(void);
+#endif
+
+#ifndef CONFIG_NEW_HOSTALLOC
static uint host_buffer; /* One page of host buffer */
static uint host_end; /* end + 1 */
+#else
+void new_m8xx_cpm_hostinit(uint bootpage);
+#endif
+
cpm8xx_t *cpmp; /* Pointer to comm processor space */
/* CPM interrupt vector functions.
@@ -59,11 +74,10 @@
#if 1
void
-m8xx_cpm_reset()
+m8xx_cpm_reset(uint page)
{
volatile immap_t *imp;
volatile cpm8xx_t *commproc;
- pte_t *pte;
imp = (immap_t *)IMAP_ADDR;
commproc = (cpm8xx_t *)&imp->im_cpm;
@@ -88,16 +102,26 @@
*/
imp->im_siu_conf.sc_sdcr = 1;
+#ifndef CONFIG_NEW_DPALLOC
/* Reclaim the DP memory for our use.
*/
dp_alloc_base = CPM_DATAONLY_BASE;
dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE;
+#else
+ faked_dp_alloc_base = CPM_DATAONLY_BASE;
+ new_m8xx_cpm_dpinit();
+#endif
+
+#ifdef CONFIG_NEW_HOSTALLOC
+ new_m8xx_cpm_hostinit(0);
+#endif
/* Tell everyone where the comm processor resides.
*/
cpmp = (cpm8xx_t *)commproc;
}
+#ifndef CONFIG_NEW_HOSTALLOC
/* We used to do this earlier, but have to postpone as long as possible
* to ensure the kernel VM is now running.
*/
@@ -111,13 +135,17 @@
host_buffer = (uint)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &physaddr);
host_end = host_buffer + PAGE_SIZE;
}
+#endif
+
#else
void
m8xx_cpm_reset(uint host_page_addr)
{
volatile immap_t *imp;
volatile cpm8xx_t *commproc;
+#ifndef CONFIG_NEW_HOSTALLOC
pte_t *pte;
+#endif
imp = (immap_t *)IMAP_ADDR;
commproc = (cpm8xx_t *)&imp->im_cpm;
@@ -142,11 +170,16 @@
*/
imp->im_siu_conf.sc_sdcr = 1;
+#ifndef CONFIG_NEW_DPALLOC
/* Reclaim the DP memory for our use.
*/
dp_alloc_base = CPM_DATAONLY_BASE;
dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE;
+#else
+ new_m8xx_cpm_dpinit();
+#endif
+#ifndef CONFIG_NEW_HOSTALLOC
/* Set the host page for allocation.
*/
host_buffer = host_page_addr; /* Host virtual page address */
@@ -162,6 +195,9 @@
else {
panic("Huh? No CPM host page?");
}
+#else
+ new_m8xx_cpm_hostinit(host_page_addr);
+#endif
/* Tell everyone where the comm processor resides.
*/
@@ -261,6 +297,7 @@
((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec);
}
+#ifndef CONFIG_NEW_DPALLOC
/* Allocate some memory from the dual ported ram. We may want to
* enforce alignment restrictions, but right now everyone is a good
* citizen.
@@ -285,6 +322,9 @@
return dp_alloc_base;
}
+#endif
+
+#ifndef CONFIG_NEW_HOSTALLOC
/* We also own one page of host buffer space for the allocation of
* UART "fifos" and the like.
*/
@@ -306,6 +346,7 @@
return(retloc);
}
+#endif
/* Set a baud rate generator. This needs lots of work. There are
* four BRGs, any of which can be wired to any channel.
@@ -334,3 +375,352 @@
*bp = (((BRG_UART_CLK_DIV16 / rate) - 1) << 1) |
CPM_BRG_EN | CPM_BRG_DIV16;
}
+
+#ifdef CONFIG_NEW_DPALLOC
+
+/********************************************************************************
+
+ dpalloc
+
+********************************************************************************/
+
+uint
+m8xx_cpm_dpalloc(uint size)
+{
+ volatile cpm8xx_t *cp = &((volatile immap_t *)IMAP_ADDR)->im_cpm;
+ u_char *start;
+ uint ret;
+
+ start = new_m8xx_cpm_dpalloc(size, "commproc");
+ if (start == NULL)
+ return(CPM_DP_NOSPACE);
+
+ ret = start - (u_char *)cp->cp_dpmem;
+
+ if (ret + size > faked_dp_alloc_base)
+ faked_dp_alloc_base = ret + size;
+
+ return ret;
+}
+
+/* XXX this is really weird, not called from anywhere in the kernel. */
+uint
+m8xx_cpm_dpalloc_index(void)
+{
+ return faked_dp_alloc_base;
+}
+
+
+static spinlock_t cpm_dpmem_lock;
+static rh_block_t cpm_boot_dpmem_rh_block[16]; /* start with 16 blocks */
+static rh_info_t cpm_dpmem_info;
+
+/********************************************************************************/
+
+#define CPM_DPMEM_ALIGNMENT 8
+
+void new_m8xx_cpm_dpinit(void)
+{
+ volatile cpm8xx_t *cp = &((volatile immap_t *)IMAP_ADDR)->im_cpm;
+
+ spin_lock_init(&cpm_dpmem_lock);
+
+ /* initialize the info header */
+ rh_init(&cpm_dpmem_info, CPM_DPMEM_ALIGNMENT,
+ sizeof(cpm_boot_dpmem_rh_block)/sizeof(cpm_boot_dpmem_rh_block[0]),
+ cpm_boot_dpmem_rh_block);
+
+ /* attach the usable dpmem area */
+ rh_attach_region(&cpm_dpmem_info, (u_char *)cp->cp_dpmem + CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
+}
+
+void *new_m8xx_cpm_dpalloc(unsigned int size, const char *owner)
+{
+ void *start;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cpm_dpmem_lock, flags);
+ start = rh_alloc(&cpm_dpmem_info, size, owner);
+ spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+ return start;
+}
+
+int new_m8xx_cpm_dpfree(void *start)
+{
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cpm_dpmem_lock, flags);
+ ret = rh_free(&cpm_dpmem_info, start);
+ spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+ return ret;
+}
+
+void *new_m8xx_cpm_dpalloc_fixed(void *start, int size, const char *owner)
+{
+ void *ret = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cpm_dpmem_lock, flags);
+ ret = rh_alloc_fixed(&cpm_dpmem_info, start, size, owner);
+ spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+ return ret;
+}
+
+void new_m8xx_cpm_dpdump(void)
+{
+ rh_dump(&cpm_dpmem_info);
+}
+
+#endif
+
+#ifdef CONFIG_NEW_HOSTALLOC
+
+/********************************************************************************
+
+ hostalloc
+
+********************************************************************************/
+
+uint
+m8xx_cpm_hostalloc(uint size)
+{
+ return (uint)new_m8xx_cpm_hostalloc(size, "commproc");
+}
+
+typedef struct cpm_hostmem_block {
+ struct list_head list;
+ int order;
+ int num_pages;
+ int size;
+ int allocated;
+ ulong va;
+ pte_t pte[1]; /* at least one */
+ /* more follow */
+} cpm_hostmem_block_t;
+
+static uint cpm_bootpage;
+static rh_block_t cpm_boot_hostmem_rh_block[8]; /* start with 8 blocks */
+static rh_info_t cpm_hostmem_info;
+
+static spinlock_t cpm_hostmem_lock;
+static struct list_head cpm_hostmem_list;
+
+/********************************************************************************/
+
+static cpm_hostmem_block_t *hostmem_block_create(int reqsize)
+{
+ int i, order, num_pages, size;
+ ulong va;
+ pte_t *pte;
+ cpm_hostmem_block_t *hb;
+
+ order = get_order(reqsize);
+ num_pages = 1 << order;
+ size = num_pages << PAGE_SHIFT;
+
+ hb = kmalloc(sizeof(*hb) + sizeof(pte_t) * num_pages, GFP_KERNEL);
+ if (hb == NULL)
+ return NULL;
+
+ /* now get the actual pages */
+ va = __get_dma_pages(GFP_KERNEL, order);
+ if (va == 0) {
+ kfree(hb);
+ return NULL;
+ }
+
+ INIT_LIST_HEAD(&hb->list);
+ hb->order = order;
+ hb->num_pages = num_pages;
+ hb->size = size;
+ hb->allocated = 0;
+ hb->va = va;
+
+ /* ensure no cache lines in use */
+ invalidate_dcache_range(va, va + size);
+
+ /* chase the PTEs and mark them uncached. */
+ for (i = 0; i < num_pages; i++, va += PAGE_SIZE) {
+ if (get_pteptr(&init_mm, va, &pte) == 0) {
+ BUG();
+ return NULL;
+ }
+ /* save old pte value */
+ pte_val(hb->pte[i]) = pte_val(*pte);
+
+ /* and make it uncachable */
+ pte_val(*pte) |= _PAGE_NO_CACHE;
+
+ flush_tlb_page(find_vma(&init_mm, va), va);
+ }
+
+ return hb;
+}
+
+static int hostmem_block_destroy(cpm_hostmem_block_t *hb)
+{
+ int i;
+ ulong va;
+ pte_t *pte;
+
+ if (hb == NULL)
+ return -EINVAL;
+
+ if (in_interrupt())
+ BUG();
+
+ /* restore PTEs to former values */
+ for (i = 0, va = hb->va; i < hb->num_pages; i++, va += PAGE_SIZE) {
+ if (get_pteptr(&init_mm, va, &pte) == 0) {
+ BUG();
+ return -EINVAL;
+ }
+ /* restore previous pte value */
+ pte_val(*pte) = pte_val(hb->pte[i]);
+ flush_tlb_page(find_vma(&init_mm, va), va);
+ }
+
+ free_pages(hb->va, hb->order);
+
+ kfree(hb);
+
+ return 0;
+}
+
+/********************************************************************************/
+
+#define CPM_HOSTMEM_ALIGNMENT 16
+
+void new_m8xx_cpm_hostinit(uint bootpage)
+{
+ pte_t *pte;
+
+ if (bootpage != 0) {
+ /* get the PTE for the bootpage */
+ if (!get_pteptr(&init_mm, bootpage, &pte))
+ panic("get_pteptr failed\n");
+
+ /* and make it uncachable */
+ pte_val(*pte) |= _PAGE_NO_CACHE;
+ flush_tlb_page(init_mm.mmap, bootpage);
+ }
+
+ spin_lock_init(&cpm_hostmem_lock);
+ INIT_LIST_HEAD(&cpm_hostmem_list);
+
+ /* initialize the info header */
+ rh_init(&cpm_hostmem_info, CPM_HOSTMEM_ALIGNMENT,
+ sizeof(cpm_boot_hostmem_rh_block)/sizeof(cpm_boot_hostmem_rh_block[0]),
+ cpm_boot_hostmem_rh_block);
+
+ /* attach as free memory the bootpage to satisfy early allocations */
+ if (bootpage != 0)
+ rh_attach_region(&cpm_hostmem_info, (void *)bootpage, PAGE_SIZE);
+
+ /* please note that the initial bootpage is NOT in the hostmem block list */
+ /* so keep it around just in case */
+ cpm_bootpage = bootpage;
+}
+
+void *new_m8xx_cpm_hostalloc(unsigned int size, const char *owner)
+{
+ void *ret;
+ static cpm_hostmem_block_t *hb;
+ struct list_head *l;
+ unsigned long flags;
+
+ /* align size */
+ /* size = (size + CPM_HOSTMEM_ALIGNMENT - 1) & ~(CPM_HOSTMEM_ALIGNMENT - 1); */
+
+ spin_lock_irqsave(&cpm_hostmem_lock, flags);
+
+ /* try to get it from already present free list */
+ ret = rh_alloc(&cpm_hostmem_info, size, owner);
+ if (ret != NULL)
+ goto out;
+ spin_unlock_irqrestore(&cpm_hostmem_lock, flags);
+
+ /* no memory, grow hostmem list */
+ hb = hostmem_block_create(size);
+ if (hb == NULL)
+ return NULL;
+
+ spin_lock_irqsave(&cpm_hostmem_lock, flags);
+
+ /* attach free memory region */
+ if (rh_attach_region(&cpm_hostmem_info, (void *)hb->va, hb->size) < 0) {
+ hostmem_block_destroy(hb);
+ goto out;
+ }
+
+ /* append to list */
+ list_add(&hb->list, &cpm_hostmem_list);
+
+ /* and retry, hopefully this will succeed */
+ ret = rh_alloc(&cpm_hostmem_info, size, owner);
+out:
+ if (ret != NULL) {
+ list_for_each(l, &cpm_hostmem_list) {
+ hb = list_entry(l, cpm_hostmem_block_t, list);
+ if (hb->va <= (uint)ret && hb->va + size > (uint)ret) {
+ hb->allocated += size;
+ break;
+ }
+ }
+ }
+
+ spin_unlock_irqrestore(&cpm_hostmem_lock, flags);
+
+ return ret;
+}
+
+int new_m8xx_cpm_hostfree(void *start)
+{
+ int size;
+ static cpm_hostmem_block_t *hb, *hbfound;
+ struct list_head *l;
+ unsigned long flags;
+
+ hbfound = NULL;
+
+ spin_lock_irqsave(&cpm_hostmem_lock, flags);
+
+ size = rh_free(&cpm_hostmem_info, start);
+ if (size > 0) {
+ /* update allocated space counter, and destroy page(s) if zero */
+ list_for_each(l, &cpm_hostmem_list) {
+ hb = list_entry(l, cpm_hostmem_block_t, list);
+ if (hb->va <= (uint)start && hb->va + size > (uint)start) {
+ hb->allocated -= size;
+ if (hb->allocated == 0) {
+ list_del(&hb->list);
+ rh_detach_region(&cpm_hostmem_info, (void *)hb->va, hb->size);
+ hbfound = hb;
+ }
+ break;
+ }
+ }
+ }
+
+ spin_unlock_irqrestore(&cpm_hostmem_lock, flags);
+
+ /* if the block was detached destroy it */
+ if (hbfound != NULL)
+ hostmem_block_destroy(hbfound);
+
+ return size;
+}
+
+void new_m8xx_cpm_hostdump(void)
+{
+ extern void rh_dump(rh_info_t *info);
+
+ rh_dump(&cpm_hostmem_info);
+}
+
+#endif
+
diff -Nru a/arch/ppc/8xx_io/rheap.c b/arch/ppc/8xx_io/rheap.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/8xx_io/rheap.c Wed Dec 18 14:27:45 2002
@@ -0,0 +1,657 @@
+/*
+ * Remote Heap
+ *
+ * Pantelis Antoniou <panto@intracom.gr>
+ * INTRACOM S.A. Greece
+ *
+ */
+
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include "rheap.h"
+
+/********************************************************************************/
+
+/* fixup a list_head, needed when copying lists */
+/* if the pointers fall between s and e, apply the delta */
+/* assumes that sizeof(struct list_head *) == sizeof(unsigned long *) */
+static inline void fixup(unsigned long s, unsigned long e, int d, struct list_head *l)
+{
+ unsigned long *pp;
+
+ pp = (unsigned long *)&l->next;
+ if (*pp >= s && *pp < e)
+ *pp += d;
+
+ pp = (unsigned long *)&l->prev;
+ if (*pp >= s && *pp < e)
+ *pp += d;
+}
+
+/* grow the allocated blocks */
+static int grow(rh_info_t *info, int max_blocks)
+{
+ rh_block_t *block, *blk;
+ int i, new_blocks;
+ int delta;
+ unsigned long blks, blke;
+
+ if (max_blocks <= info->max_blocks)
+ return -EINVAL;
+
+ new_blocks = max_blocks - info->max_blocks;
+
+ block = kmalloc(sizeof(rh_block_t) * max_blocks, GFP_KERNEL);
+ if (block == NULL)
+ return -ENOMEM;
+
+ if (info->max_blocks > 0) {
+
+ /* copy old block area */
+ memcpy(block, info->block, sizeof(rh_block_t) * info->max_blocks);
+
+ delta = (char *)block - (char *)info->block;
+
+ /* and fixup list pointers */
+ blks = (unsigned long)info->block;
+ blke = (unsigned long)(info->block + info->max_blocks);
+
+ for (i = 0, blk = block; i < info->max_blocks; i++, blk++)
+ fixup(blks, blke, delta, &blk->list);
+
+ fixup(blks, blke, delta, &info->empty_list);
+ fixup(blks, blke, delta, &info->free_list);
+ fixup(blks, blke, delta, &info->taken_list);
+
+ /* free the old allocated memory */
+ if ((info->flags & RHIF_STATIC_BLOCK) == 0)
+ kfree(info->block);
+ }
+
+ info->block = block;
+ info->empty_slots += new_blocks;
+ info->max_blocks = max_blocks;
+ info->flags &= ~RHIF_STATIC_BLOCK;
+
+ /* add all new blocks to the free list */
+ for (i = 0, blk = block + info->max_blocks; i < new_blocks; i++, blk++)
+ list_add(&blk->list, &info->empty_list);
+
+ return 0;
+}
+
+/* assure at least the required amount of empty slots
+ if this function causes a grow in the block area
+ the all pointers kept to the block area are invalid!
+*/
+static int assure_empty(rh_info_t *info, int slots)
+{
+ int max_blocks;
+
+ /* this function is not meant to be used to grow uncontrollably */
+ if (slots >= 4)
+ return -EINVAL;
+
+ /* enough space */
+ if (info->empty_slots >= slots)
+ return 0;
+
+ /* next 16 sized block */
+ max_blocks = ((info->max_blocks + slots) + 15) & ~15;
+
+ return grow(info, max_blocks);
+}
+
+static rh_block_t *get_slot(rh_info_t *info)
+{
+ rh_block_t *blk;
+
+ /* if no more free slots, and failure to extend */
+ /* XXX you should have called assure_empty before */
+ if (info->empty_slots == 0) {
+ printk(KERN_ERR "rh: out of slots; crash is imminent.\n");
+ return NULL;
+ }
+
+ /* get empty slot to use */
+ blk = list_entry(info->empty_list.next, rh_block_t, list);
+ list_del_init(&blk->list);
+ info->empty_slots--;
+
+ /* initialize */
+ blk->start = NULL;
+ blk->size = 0;
+ blk->owner = NULL;
+
+ return blk;
+}
+
+static inline void release_slot(rh_info_t *info, rh_block_t *blk)
+{
+ list_add(&blk->list, &info->empty_list);
+ info->empty_slots++;
+}
+
+static void attach_free_block(rh_info_t *info, rh_block_t *blkn)
+{
+ rh_block_t *blk;
+ rh_block_t *before;
+ rh_block_t *after;
+ rh_block_t *next;
+ int size;
+ unsigned long s, e, bs, be;
+ struct list_head *l;
+
+ /* we assume that they are aligned properly */
+ size = blkn->size;
+ s = (unsigned long)blkn->start;
+ e = s + size;
+
+ /* find the blocks immediately before and after the given one (if any) */
+ before = NULL;
+ after = NULL;
+ next = NULL;
+
+ list_for_each(l, &info->free_list) {
+ blk = list_entry(l, rh_block_t, list);
+
+ bs = (unsigned long)blk->start;
+ be = bs + blk->size;
+
+ if (next == NULL && s >= bs)
+ next = blk;
+
+ if (be == s)
+ before = blk;
+
+ if (e == bs)
+ after = blk;
+
+ /* if both are not null, break now */
+ if (before != NULL && after != NULL)
+ break;
+ }
+
+ /* now check if they are really adjacent */
+ if (before != NULL && s != (unsigned long)before->start + before->size)
+ before = NULL;
+
+ if (after != NULL && e != (unsigned long)after->start)
+ after = NULL;
+
+ /* no coalescing; list insert and return */
+ if (before == NULL && after == NULL) {
+
+ if (next != NULL)
+ list_add(&blkn->list, &next->list);
+ else
+ list_add(&blkn->list, &info->free_list);
+
+ return;
+ }
+
+ /* we don't need it anymore */
+ release_slot(info, blkn);
+
+ /* grow the before block */
+ if (before != NULL && after == NULL) {
+ before->size += size;
+ return;
+ }
+
+ /* grow the after block backwards */
+ if (before == NULL && after != NULL) {
+ (int8_t *)after->start -= size;
+ after->size += size;
+ return;
+ }
+
+ /* grow the before block, and release the after block */
+ before->size += size + after->size;
+ list_del(&after->list);
+ release_slot(info, after);
+}
+
+static void attach_taken_block(rh_info_t *info, rh_block_t *blkn)
+{
+ rh_block_t *blk;
+ struct list_head *l;
+
+ /* find the block immediately before the given one (if any) */
+ list_for_each(l, &info->taken_list) {
+ blk = list_entry(l, rh_block_t, list);
+ if (blk->start > blkn->start) {
+ list_add_tail(&blkn->list, &blk->list);
+ return;
+ }
+ }
+
+ list_add_tail(&blkn->list, &info->taken_list);
+}
+
+/**********************************************************************/
+
+/* Create a remote heap dynamically.
+ Note that no memory for the blocks are allocated.
+ It will upon the first allocation
+*/
+rh_info_t *rh_create(unsigned int alignment)
+{
+ rh_info_t *info;
+
+ /* alignment must be a power of two */
+ if ((alignment & (alignment - 1)) != 0)
+ return NULL;
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (info == NULL)
+ return NULL;
+
+ info->alignment = alignment;
+
+ /* initially everything is empty */
+ info->block = NULL;
+ info->max_blocks = 0;
+ info->empty_slots = 0;
+ info->flags = 0;
+
+ INIT_LIST_HEAD(&info->empty_list);
+ INIT_LIST_HEAD(&info->free_list);
+ INIT_LIST_HEAD(&info->taken_list);
+
+ return info;
+}
+
+/* Destroy a dynamically created remote heap
+ Deallocate only if the areas are not static
+*/
+void rh_destroy(rh_info_t *info)
+{
+ if ((info->flags & RHIF_STATIC_BLOCK) == 0 && info->block != NULL)
+ kfree(info->block);
+
+ if ((info->flags & RHIF_STATIC_INFO) == 0)
+ kfree(info);
+}
+
+/********************************************************************************/
+
+/* Initialize in place a remote heap info block.
+ This is needed to support operation very early in the startup of the
+ kernel, when it is not yet safe to call kmalloc.
+*/
+void rh_init(rh_info_t *info, unsigned int alignment, int max_blocks, rh_block_t *block)
+{
+ int i;
+ rh_block_t *blk;
+
+ /* alignment must be a power of two */
+ if ((alignment & (alignment - 1)) != 0)
+ return;
+
+ info->alignment = alignment;
+
+ /* initially everything is empty */
+ info->block = block;
+ info->max_blocks = max_blocks;
+ info->empty_slots = max_blocks;
+ info->flags = RHIF_STATIC_INFO | RHIF_STATIC_BLOCK;
+
+ INIT_LIST_HEAD(&info->empty_list);
+ INIT_LIST_HEAD(&info->free_list);
+ INIT_LIST_HEAD(&info->taken_list);
+
+ /* add all new blocks to the free list */
+ for (i = 0, blk = block; i < max_blocks; i++, blk++)
+ list_add(&blk->list, &info->empty_list);
+}
+
+/********************************************************************************/
+
+/* Attach a free memory region, coalesces regions if adjuscent */
+int rh_attach_region(rh_info_t *info, void *start, int size)
+{
+ rh_block_t *blk;
+ unsigned long s, e, m;
+ int r;
+
+ /* the region must be aligned */
+ s = (unsigned long)start;
+ e = s + size;
+ m = info->alignment - 1;
+
+ /* round start up */
+ s = (s + m) & ~m;
+
+ /* round end down */
+ e = e & ~m;
+
+ /* take final values */
+ start = (void *)s;
+ size = (int)(e - s);
+
+ /* grow the blocks, if needed */
+ r = assure_empty(info, 1);
+ if (r < 0)
+ return r;
+
+ blk = get_slot(info);
+ blk->start = start;
+ blk->size = size;
+ blk->owner = NULL;
+
+ attach_free_block(info, blk);
+
+ return 0;
+}
+
+/* Detatch given address range, splits free block if needed. */
+void *rh_detach_region(rh_info_t *info, void *start, int size)
+{
+ struct list_head *l;
+ rh_block_t *blk, *newblk;
+ unsigned long s, e, m, bs, be;
+
+ /* validate size */
+ if (size <= 0)
+ return NULL;
+
+ /* the region must be aligned */
+ s = (unsigned long)start;
+ e = s + size;
+ m = info->alignment - 1;
+
+ /* round start up */
+ s = (s + m) & ~m;
+
+ /* round end down */
+ e = e & ~m;
+
+ if (assure_empty(info, 1) < 0)
+ return NULL;
+
+ blk = NULL;
+ list_for_each(l, &info->free_list) {
+ blk = list_entry(l, rh_block_t, list);
+ /* the range must lie entirely inside one free block */
+ bs = (unsigned long)blk->start;
+ be = (unsigned long)blk->start + blk->size;
+ if (s >= bs && e <= be)
+ break;
+ blk = NULL;
+ }
+
+ if (blk == NULL)
+ return NULL;
+
+ /* perfect fit */
+ if (bs == s && be == e) {
+ /* delete from free list, release slot */
+ list_del(&blk->list);
+ release_slot(info, blk);
+ return (void *)s;
+ }
+
+ /* blk still in free list, with updated start and/or size */
+ if (bs == s || be == e) {
+ if (bs == s)
+ (int8_t *)blk->start += size;
+ blk->size -= size;
+
+ } else {
+ /* the front free fragment */
+ blk->size = s - bs;
+
+ /* the back free fragment */
+ newblk = get_slot(info);
+ newblk->start = (void *)e;
+ newblk->size = be - e;
+
+ list_add(&newblk->list, &blk->list);
+ }
+
+ return (void *)s;
+}
+
+/********************************************************************************/
+
+void *rh_alloc(rh_info_t *info, int size, const char *owner)
+{
+ struct list_head *l;
+ rh_block_t *blk;
+ rh_block_t *newblk;
+ void *start;
+
+ /* validate size */
+ if (size <= 0)
+ return NULL;
+
+ /* align to configured alignment */
+ size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
+
+ if (assure_empty(info, 1) < 0)
+ return NULL;
+
+ blk = NULL;
+ list_for_each(l, &info->free_list) {
+ blk = list_entry(l, rh_block_t, list);
+ if (size <= blk->size)
+ break;
+ blk = NULL;
+ }
+
+ if (blk == NULL)
+ return NULL;
+
+ /* just fits */
+ if (blk->size == size) {
+ /* move from free list to taken list */
+ list_del(&blk->list);
+ blk->owner = owner;
+ start = blk->start;
+
+ attach_taken_block(info, blk);
+
+ return start;
+ }
+
+ newblk = get_slot(info);
+ newblk->start = blk->start;
+ newblk->size = size;
+ newblk->owner = owner;
+
+ /* blk still in free list, with updated start, size */
+ (int8_t *)blk->start += size;
+ blk->size -= size;
+
+ start = newblk->start;
+
+ attach_taken_block(info, newblk);
+
+ return start;
+}
+
+/* allocate at precisely the given address */
+void *rh_alloc_fixed(rh_info_t *info, void *start, int size, const char *owner)
+{
+ struct list_head *l;
+ rh_block_t *blk, *newblk1, *newblk2;
+ unsigned long s, e, m, bs, be;
+
+ /* validate size */
+ if (size <= 0)
+ return NULL;
+
+ /* the region must be aligned */
+ s = (unsigned long)start;
+ e = s + size;
+ m = info->alignment - 1;
+
+ /* round start up */
+ s = (s + m) & ~m;
+
+ /* round end down */
+ e = e & ~m;
+
+ if (assure_empty(info, 2) < 0)
+ return NULL;
+
+ blk = NULL;
+ list_for_each(l, &info->free_list) {
+ blk = list_entry(l, rh_block_t, list);
+ /* the range must lie entirely inside one free block */
+ bs = (unsigned long)blk->start;
+ be = (unsigned long)blk->start + blk->size;
+ if (s >= bs && e <= be)
+ break;
+ }
+
+ if (blk == NULL)
+ return NULL;
+
+ /* perfect fit */
+ if (bs == s && be == e) {
+ /* move from free list to taken list */
+ list_del(&blk->list);
+ blk->owner = owner;
+
+ start = blk->start;
+ attach_taken_block(info, blk);
+
+ return start;
+
+ }
+
+ /* blk still in free list, with updated start and/or size */
+ if (bs == s || be == e) {
+ if (bs == s)
+ (int8_t *)blk->start += size;
+ blk->size -= size;
+
+ } else {
+ /* the front free fragment */
+ blk->size = s - bs;
+
+ /* the back free fragment */
+ newblk2 = get_slot(info);
+ newblk2->start = (void *)e;
+ newblk2->size = be - e;
+
+ list_add(&newblk2->list, &blk->list);
+ }
+
+ newblk1 = get_slot(info);
+ newblk1->start = (void *)s;
+ newblk1->size = e - s;
+ newblk1->owner = owner;
+
+ start = newblk1->start;
+ attach_taken_block(info, newblk1);
+
+ return start;
+}
+
+int rh_free(rh_info_t *info, void *start)
+{
+ rh_block_t *blk, *blk2;
+ struct list_head *l;
+ int size;
+
+ /* linear search for block */
+
+ blk = NULL;
+ list_for_each(l, &info->taken_list) {
+ blk2 = list_entry(l, rh_block_t, list);
+ if (start < blk2->start)
+ break;
+ blk = blk2;
+ }
+
+ if (blk == NULL || start > (blk->start + blk->size))
+ return -EINVAL;
+
+ /* remove from taken list */
+ list_del(&blk->list);
+
+ /* get size of freed block */
+ size = blk->size;
+ attach_free_block(info, blk);
+
+ return size;
+}
+
+int rh_get_stats(rh_info_t *info, int what, int max_stats, rh_stats_t *stats)
+{
+ rh_block_t *blk;
+ struct list_head *l;
+ struct list_head *h;
+ int nr;
+
+ switch (what) {
+
+ case RHGS_FREE:
+ h = &info->free_list;
+ break;
+
+ case RHGS_TAKEN:
+ h = &info->taken_list;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* linear search for block */
+ nr = 0;
+ list_for_each(l, h) {
+ blk = list_entry(l, rh_block_t, list);
+ if (stats != NULL && nr < max_stats) {
+ stats->start = blk->start;
+ stats->size = blk->size;
+ stats->owner = blk->owner;
+ stats++;
+ }
+ nr++;
+ }
+
+ return nr;
+}
+
+/********************************************************************************/
+
+void rh_dump(rh_info_t *info)
+{
+ static rh_stats_t st[32]; /* XXX maximum 32 blocks */
+ int maxnr;
+ int i, nr;
+
+ maxnr = sizeof(st) / sizeof(st[0]);
+
+ printk(KERN_INFO "info @0x%p (%d slots empty / %d max)\n", info, info->empty_slots, info->max_blocks);
+
+ printk(KERN_INFO " Free:\n");
+ nr = rh_get_stats(info, RHGS_FREE, maxnr, st);
+ if (nr > maxnr)
+ nr = maxnr;
+ for (i = 0; i < nr; i++)
+ printk(KERN_INFO " 0x%p-0x%p (%u)\n", st[i].start, (int8_t *)st[i].start + st[i].size, st[i].size);
+ printk(KERN_INFO "\n");
+
+ printk(KERN_INFO " Taken:\n");
+ nr = rh_get_stats(info, RHGS_TAKEN, maxnr, st);
+ if (nr > maxnr)
+ nr = maxnr;
+ for (i = 0; i < nr; i++)
+ printk(KERN_INFO " 0x%p-0x%p (%u) %s\n", st[i].start, (int8_t *)st[i].start + st[i].size, st[i].size,
+ st[i].owner != NULL ? st[i].owner : "");
+ printk(KERN_INFO "\n");
+}
+
+void rh_dump_blk(rh_info_t *info, rh_block_t *blk)
+{
+ printk(KERN_INFO "blk @0x%p: 0x%p-0x%p (%u)\n", blk, blk->start, (int8_t *)blk->start + blk->size, blk->size);
+}
diff -Nru a/arch/ppc/8xx_io/rheap.h b/arch/ppc/8xx_io/rheap.h
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/8xx_io/rheap.h Wed Dec 18 14:27:45 2002
@@ -0,0 +1,89 @@
+/*
+ * Remote Heap
+ *
+ * Pantelis Antoniou <panto@intracom.gr>
+ * INTRACOM S.A. Greece
+ *
+ * Header file for the implementation of a remote heap.
+ *
+ * Remote means that we don't touch the memory that the heap
+ * points to. Normal heap implementations use the memory
+ * they manage to place their list. We cannot do that
+ * because the memory we manage may have special
+ * properties, for example it is uncachable or of
+ * different endianess.
+ *
+ */
+
+#ifndef RHEAP_H
+#define RHEAP_H
+
+#include <linux/list.h>
+
+/********************************************************************************/
+
+typedef struct _rh_block {
+ struct list_head list;
+ void *start;
+ int size;
+ const char *owner;
+} rh_block_t;
+
+typedef struct _rh_info {
+ unsigned int alignment;
+ int max_blocks;
+ int empty_slots;
+ rh_block_t *block;
+ struct list_head empty_list;
+ struct list_head free_list;
+ struct list_head taken_list;
+ unsigned int flags;
+} rh_info_t;
+
+#define RHIF_STATIC_INFO 0x1
+#define RHIF_STATIC_BLOCK 0x2
+
+typedef struct rh_stats_t {
+ void *start;
+ int size;
+ const char *owner;
+} rh_stats_t;
+
+#define RHGS_FREE 0
+#define RHGS_TAKEN 1
+
+/********************************************************************************/
+
+/* create a remote heap dynamically */
+rh_info_t *rh_create(unsigned int alignment);
+
+/* destroy a remote heap, created by rh_create() */
+void rh_destroy(rh_info_t *info);
+
+/* initialize in place a remote info block */
+void rh_init(rh_info_t *info, unsigned int alignment, int max_blocks, rh_block_t *block);
+
+/* attach a free region to manage */
+int rh_attach_region(rh_info_t *info, void *start, int size);
+
+/* detach a free region */
+void *rh_detach_region(rh_info_t *info, void *start, int size);
+
+/* allocate the given size from the remote heap */
+void *rh_alloc(rh_info_t *info, int size, const char *owner);
+
+/* allocate the given size from the given address */
+void *rh_alloc_fixed(rh_info_t *info, void *start, int size, const char *owner);
+
+/* free the allocated area */
+int rh_free(rh_info_t *info, void *start);
+
+/* get stats for debugging purposes */
+int rh_get_stats(rh_info_t *info, int what, int max_stats, rh_stats_t *stats);
+
+/* simple dump of remote heap info */
+void rh_dump(rh_info_t *info);
+
+/********************************************************************************/
+
+#endif
diff -Nru a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
--- a/arch/ppc/kernel/ppc_ksyms.c Wed Dec 18 14:27:45 2002
+++ b/arch/ppc/kernel/ppc_ksyms.c Wed Dec 18 14:27:45 2002
@@ -357,6 +357,17 @@
EXPORT_SYMBOL(__res);
EXPORT_SYMBOL(cpm_install_handler);
EXPORT_SYMBOL(cpm_free_handler);
+#ifdef CONFIG_NEW_DPALLOC
+EXPORT_SYMBOL(new_m8xx_cpm_dpalloc);
+EXPORT_SYMBOL(new_m8xx_cpm_dpfree);
+EXPORT_SYMBOL(new_m8xx_cpm_dpalloc_fixed);
+EXPORT_SYMBOL(new_m8xx_cpm_dpdump);
+#endif
+#ifdef CONFIG_NEW_HOSTALLOC
+EXPORT_SYMBOL(new_m8xx_cpm_hostalloc);
+EXPORT_SYMBOL(new_m8xx_cpm_hostfree);
+EXPORT_SYMBOL(new_m8xx_cpm_hostdump);
+#endif
#endif /* CONFIG_8xx */
#if defined(CONFIG_8xx) || defined(CONFIG_8260)
EXPORT_SYMBOL(request_8xxirq);
diff -Nru a/include/asm-ppc/commproc.h b/include/asm-ppc/commproc.h
--- a/include/asm-ppc/commproc.h Wed Dec 18 14:27:45 2002
+++ b/include/asm-ppc/commproc.h Wed Dec 18 14:27:45 2002
@@ -797,4 +797,17 @@
void (*handler)(void *, struct pt_regs *regs), void *dev_id);
extern void cpm_free_handler(int vec);
+#ifdef CONFIG_NEW_DPALLOC
+extern void *new_m8xx_cpm_dpalloc(unsigned int size, const char *owner);
+extern int new_m8xx_cpm_dpfree(void *start);
+extern void *new_m8xx_cpm_dpalloc_fixed(void *start, int size, const char *owner);
+extern void new_m8xx_cpm_dpdump(void);
+#endif
+
+#ifdef CONFIG_NEW_HOSTALLOC
+extern void *new_m8xx_cpm_hostalloc(unsigned int size, const char *owner);
+extern int new_m8xx_cpm_hostfree(void *start);
+extern void new_m8xx_cpm_hostdump(void);
+#endif
+
#endif /* __CPM_8XX__ */
^ permalink raw reply
* New style dpalloc/hostalloc routines (diff).
From: Pantelis Antoniou @ 2002-12-18 12:38 UTC (permalink / raw)
To: linuxppc-embedded
This is the gnu-style diff patch.
This patch is against the current linuxppc_2_4_devel tree.
** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/
^ permalink raw reply
* how to delete a piece of rule in iptables?
From: bobo @ 2002-12-18 12:38 UTC (permalink / raw)
To: netfilter-devel@lists.netfilter.org; +Cc: bobowd@sohu.com
i have insert some rules to iptables firewall.now,i would
like to delete it .
but i only know to use iptalbes -L to empty them.
but it lead to delete all the rules in it.
how to do ??
^ permalink raw reply
* New style dpalloc/hostalloc routines. (bitkeeper)
From: Pantelis Antoniou @ 2002-12-18 12:37 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 312 bytes --]
Hi
Here are my patches adding support
for better allocation of dual ported memory and uncached
host memory for the 8xx family of processors.
The memory ranges allocated are tracked properly
and the functions are exported for use in modules.
This patch is against the current linuxppc_2_4_devel tree.
Regards
[-- Attachment #2: new_cpm_alloc.bitkeeper.patch --]
[-- Type: text/plain, Size: 33216 bytes --]
# User: panto
# Host: macpanto.intranet.gr
# Root: /archives/bk/linuxppc_2_4_devel-alloc_patch
# Patch vers: 1.3
# Patch type: REGULAR
== ChangeSet ==
cort@ftsoj.fsmlabs.com|ChangeSet|20010106071759|19793|5c81b698cda31832
dgibson@zax.zax|ChangeSet|20021217041010|26004
D 1.1191 02/12/18 14:13:21+02:00 panto@macpanto.intranet.gr +8 -0
B cort@ftsoj.fsmlabs.com|ChangeSet|20010106071759|19793|5c81b698cda31832
C
c Add support for new style dpalloc/hostalloc routines
c which properly manage memory, and permit their use in modules.
K 59218
P ChangeSet
------------------------------------------------
0a0
> cort@ftsoj.fsmlabs.com|arch/ppc/8xx_io/Config.in|20010106073019|32642|b93de5be3809f14b panto@macpanto.intranet.gr|arch/ppc/8xx_io/Config.in|20021218121130|48369
> panto@macpanto.intranet.gr|arch/ppc/8xx_io/rheap.c|20021218110152|22702|dc008764c8bd3605 panto@macpanto.intranet.gr|arch/ppc/8xx_io/rheap.c|20021218110153|65298
> patch@bill-the-cat.bloom.county|include/asm-ppc/commproc.h|20011008234020|17681|bb192d8bed8005fd panto@macpanto.intranet.gr|include/asm-ppc/commproc.h|20021218121130|40673
> cort@ftsoj.fsmlabs.com|arch/ppc/kernel/ppc_ksyms.c|20010106073009|44721|924fea448d6377b3 panto@macpanto.intranet.gr|arch/ppc/kernel/ppc_ksyms.c|20021218121130|62557
> panto@macpanto.intranet.gr|arch/ppc/8xx_io/rheap.h|20021218110153|06128|b08dd5e21d4baa75 panto@macpanto.intranet.gr|arch/ppc/8xx_io/rheap.h|20021218110154|58254
> cort@ftsoj.fsmlabs.com|arch/ppc/8xx_io/commproc.c|20010106073019|23718|f798ec524203928f panto@macpanto.intranet.gr|arch/ppc/8xx_io/commproc.c|20021218121130|27033
> cort@ftsoj.fsmlabs.com|arch/ppc/8xx_io/Makefile|20010106073019|12217|f81e3795cac36eb3 panto@macpanto.intranet.gr|arch/ppc/8xx_io/Makefile|20021218121130|49428
> cort@ftsoj.fsmlabs.com|BitKeeper/etc/logging_ok|20010106073834|64358|2442203aaaa98f panto@macpanto.intranet.gr|BitKeeper/etc/logging_ok|20021218121321|19637
== BitKeeper/etc/logging_ok ==
cort@ftsoj.fsmlabs.com|BitKeeper/etc/logging_ok|20010106073834|64358|2442203aaaa98f
porter@cox.net|BitKeeper/etc/logging_ok|20021121144656|16988
D 1.78 02/12/18 14:13:21+02:00 panto@macpanto.intranet.gr +2 -1
B cort@ftsoj.fsmlabs.com|ChangeSet|20010106071759|19793|5c81b698cda31832
C
c Logging to logging@openlogging.org accepted
K 19637
O -rw-rw-r--
P BitKeeper/etc/logging_ok
------------------------------------------------
I40 1
panto@macpanto.intranet.gr
I53 1
porter@cox.net
D66 1
== arch/ppc/8xx_io/Config.in ==
cort@ftsoj.fsmlabs.com|arch/ppc/8xx_io/Config.in|20010106073019|32642|b93de5be3809f14b
dan@dp500.netx4.com|arch/ppc/8xx_io/Config.in|20020120091435|25577
D 1.11 02/12/18 14:11:30+02:00 panto@macpanto.intranet.gr +6 -0
B cort@ftsoj.fsmlabs.com|ChangeSet|20010106071759|19793|5c81b698cda31832
C
c Add an option for the new hostalloc/dpalloc routines.
K 48369
O -rw-rw-r--
P arch/ppc/8xx_io/Config.in
------------------------------------------------
I38 6
# Support new type of routines, usable from modules
bool 'Use new type dpalloc routines()' CONFIG_NEW_DPALLOC
bool 'Use new type hostalloc routines()' CONFIG_NEW_HOSTALLOC
if [ "$CONFIG_NEW_DPALLOC" = "y" -o "$CONFIG_NEW_HOSTALLOC" = "y" ]; then
define_bool CONFIG_CPM_RHEAP y
fi
== arch/ppc/8xx_io/Makefile ==
cort@ftsoj.fsmlabs.com|arch/ppc/8xx_io/Makefile|20010106073019|12217|f81e3795cac36eb3
dan@dp500.netx4.com|arch/ppc/8xx_io/Makefile|20020120091435|46882
D 1.9 02/12/18 14:11:30+02:00 panto@macpanto.intranet.gr +1 -0
B cort@ftsoj.fsmlabs.com|ChangeSet|20010106071759|19793|5c81b698cda31832
C
c Built rheap if required
K 49428
O -rw-rw-r--
P arch/ppc/8xx_io/Makefile
------------------------------------------------
I19 1
obj-$(CONFIG_CPM_RHEAP) += rheap.o
== arch/ppc/8xx_io/commproc.c ==
cort@ftsoj.fsmlabs.com|arch/ppc/8xx_io/commproc.c|20010106073019|23718|f798ec524203928f
dan@dp500.netx4.com|arch/ppc/8xx_io/commproc.c|20020119080714|57650
D 1.20 02/12/18 14:11:30+02:00 panto@macpanto.intranet.gr +392 -2
B cort@ftsoj.fsmlabs.com|ChangeSet|20010106071759|19793|5c81b698cda31832
C
c New style dpalloc/hostalloc.
K 27033
O -rw-rw-r--
P arch/ppc/8xx_io/commproc.c
------------------------------------------------
I40 3
#include <linux/slab.h>
#include "rheap.h"
\
I42 1
#ifndef CONFIG_NEW_DPALLOC
I44 7
#else
/* needed for dpalloc_index */
static uint faked_dp_alloc_base;
void new_m8xx_cpm_dpinit(void);
#endif
\
#ifndef CONFIG_NEW_HOSTALLOC
I46 4
#else
void new_m8xx_cpm_hostinit(uint bootpage);
#endif
\
D62 1
I62 1
m8xx_cpm_reset(uint page)
D66 1
I90 1
#ifndef CONFIG_NEW_DPALLOC
I94 8
#else
faked_dp_alloc_base = CPM_DATAONLY_BASE;
new_m8xx_cpm_dpinit();
#endif
\
#ifdef CONFIG_NEW_HOSTALLOC
new_m8xx_cpm_hostinit(0);
#endif
I100 1
#ifndef CONFIG_NEW_HOSTALLOC
I113 2
#endif
\
I119 1
#ifndef CONFIG_NEW_HOSTALLOC
I120 1
#endif
I144 1
#ifndef CONFIG_NEW_DPALLOC
I148 3
#else
new_m8xx_cpm_dpinit();
#endif
I149 1
#ifndef CONFIG_NEW_HOSTALLOC
I164 3
#else
new_m8xx_cpm_hostinit(host_page_addr);
#endif
I263 1
#ifndef CONFIG_NEW_DPALLOC
I287 3
#endif
\
#ifndef CONFIG_NEW_HOSTALLOC
I308 1
#endif
I336 349
\
#ifdef CONFIG_NEW_DPALLOC
\
/********************************************************************************
\
dpalloc
\
********************************************************************************/
\
uint
m8xx_cpm_dpalloc(uint size)
{
volatile cpm8xx_t *cp = &((volatile immap_t *)IMAP_ADDR)->im_cpm;
u_char *start;
uint ret;
\
start = new_m8xx_cpm_dpalloc(size, "commproc");
if (start == NULL)
return(CPM_DP_NOSPACE);
\
ret = start - (u_char *)cp->cp_dpmem;
\
if (ret + size > faked_dp_alloc_base)
faked_dp_alloc_base = ret + size;
\
return ret;
}
\
/* XXX this is really weird, not called from anywhere in the kernel. */
uint
m8xx_cpm_dpalloc_index(void)
{
return faked_dp_alloc_base;
}
\
\
static spinlock_t cpm_dpmem_lock;
static rh_block_t cpm_boot_dpmem_rh_block[16]; /* start with 16 blocks */
static rh_info_t cpm_dpmem_info;
\
/********************************************************************************/
\
#define CPM_DPMEM_ALIGNMENT 8
\
void new_m8xx_cpm_dpinit(void)
{
volatile cpm8xx_t *cp = &((volatile immap_t *)IMAP_ADDR)->im_cpm;
\
spin_lock_init(&cpm_dpmem_lock);
\
/* initialize the info header */
rh_init(&cpm_dpmem_info, CPM_DPMEM_ALIGNMENT,
sizeof(cpm_boot_dpmem_rh_block)/sizeof(cpm_boot_dpmem_rh_block[0]),
cpm_boot_dpmem_rh_block);
\
/* attach the usable dpmem area */
rh_attach_region(&cpm_dpmem_info, (u_char *)cp->cp_dpmem + CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
}
\
void *new_m8xx_cpm_dpalloc(unsigned int size, const char *owner)
{
void *start;
unsigned long flags;
\
spin_lock_irqsave(&cpm_dpmem_lock, flags);
start = rh_alloc(&cpm_dpmem_info, size, owner);
spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
\
return start;
}
\
int new_m8xx_cpm_dpfree(void *start)
{
int ret;
unsigned long flags;
\
spin_lock_irqsave(&cpm_dpmem_lock, flags);
ret = rh_free(&cpm_dpmem_info, start);
spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
\
return ret;
}
\
void *new_m8xx_cpm_dpalloc_fixed(void *start, int size, const char *owner)
{
void *ret = NULL;
unsigned long flags;
\
spin_lock_irqsave(&cpm_dpmem_lock, flags);
ret = rh_alloc_fixed(&cpm_dpmem_info, start, size, owner);
spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
\
return ret;
}
\
void new_m8xx_cpm_dpdump(void)
{
rh_dump(&cpm_dpmem_info);
}
\
#endif
\
#ifdef CONFIG_NEW_HOSTALLOC
\
/********************************************************************************
\
hostalloc
\
********************************************************************************/
\
uint
m8xx_cpm_hostalloc(uint size)
{
return (uint)new_m8xx_cpm_hostalloc(size, "commproc");
}
\
typedef struct cpm_hostmem_block {
struct list_head list;
int order;
int num_pages;
int size;
int allocated;
ulong va;
pte_t pte[1]; /* at least one */
/* more follow */
} cpm_hostmem_block_t;
\
static uint cpm_bootpage;
static rh_block_t cpm_boot_hostmem_rh_block[8]; /* start with 8 blocks */
static rh_info_t cpm_hostmem_info;
\
static spinlock_t cpm_hostmem_lock;
static struct list_head cpm_hostmem_list;
\
/********************************************************************************/
\
static cpm_hostmem_block_t *hostmem_block_create(int reqsize)
{
int i, order, num_pages, size;
ulong va;
pte_t *pte;
cpm_hostmem_block_t *hb;
\
order = get_order(reqsize);
num_pages = 1 << order;
size = num_pages << PAGE_SHIFT;
\
hb = kmalloc(sizeof(*hb) + sizeof(pte_t) * num_pages, GFP_KERNEL);
if (hb == NULL)
return NULL;
\
/* now get the actual pages */
va = __get_dma_pages(GFP_KERNEL, order);
if (va == 0) {
kfree(hb);
return NULL;
}
\
INIT_LIST_HEAD(&hb->list);
hb->order = order;
hb->num_pages = num_pages;
hb->size = size;
hb->allocated = 0;
hb->va = va;
\
/* ensure no cache lines in use */
invalidate_dcache_range(va, va + size);
\
/* chase the PTEs and mark them uncached. */
for (i = 0; i < num_pages; i++, va += PAGE_SIZE) {
if (get_pteptr(&init_mm, va, &pte) == 0) {
BUG();
return NULL;
}
/* save old pte value */
pte_val(hb->pte[i]) = pte_val(*pte);
\
/* and make it uncachable */
pte_val(*pte) |= _PAGE_NO_CACHE;
\
flush_tlb_page(find_vma(&init_mm, va), va);
}
\
return hb;
}
\
static int hostmem_block_destroy(cpm_hostmem_block_t *hb)
{
int i;
ulong va;
pte_t *pte;
\
if (hb == NULL)
return -EINVAL;
\
if (in_interrupt())
BUG();
\
/* restore PTEs to former values */
for (i = 0, va = hb->va; i < hb->num_pages; i++, va += PAGE_SIZE) {
if (get_pteptr(&init_mm, va, &pte) == 0) {
BUG();
return -EINVAL;
}
/* restore previous pte value */
pte_val(*pte) = pte_val(hb->pte[i]);
flush_tlb_page(find_vma(&init_mm, va), va);
}
\
free_pages(hb->va, hb->order);
\
kfree(hb);
\
return 0;
}
\
/********************************************************************************/
\
#define CPM_HOSTMEM_ALIGNMENT 16
\
void new_m8xx_cpm_hostinit(uint bootpage)
{
pte_t *pte;
\
if (bootpage != 0) {
/* get the PTE for the bootpage */
if (!get_pteptr(&init_mm, bootpage, &pte))
panic("get_pteptr failed\n");
\
/* and make it uncachable */
pte_val(*pte) |= _PAGE_NO_CACHE;
flush_tlb_page(init_mm.mmap, bootpage);
}
\
spin_lock_init(&cpm_hostmem_lock);
INIT_LIST_HEAD(&cpm_hostmem_list);
\
/* initialize the info header */
rh_init(&cpm_hostmem_info, CPM_HOSTMEM_ALIGNMENT,
sizeof(cpm_boot_hostmem_rh_block)/sizeof(cpm_boot_hostmem_rh_block[0]),
cpm_boot_hostmem_rh_block);
\
/* attach as free memory the bootpage to satisfy early allocations */
if (bootpage != 0)
rh_attach_region(&cpm_hostmem_info, (void *)bootpage, PAGE_SIZE);
\
/* please note that the initial bootpage is NOT in the hostmem block list */
/* so keep it around just in case */
cpm_bootpage = bootpage;
}
\
void *new_m8xx_cpm_hostalloc(unsigned int size, const char *owner)
{
void *ret;
static cpm_hostmem_block_t *hb;
struct list_head *l;
unsigned long flags;
\
/* align size */
/* size = (size + CPM_HOSTMEM_ALIGNMENT - 1) & ~(CPM_HOSTMEM_ALIGNMENT - 1); */
\
spin_lock_irqsave(&cpm_hostmem_lock, flags);
\
/* try to get it from already present free list */
ret = rh_alloc(&cpm_hostmem_info, size, owner);
if (ret != NULL)
goto out;
spin_unlock_irqrestore(&cpm_hostmem_lock, flags);
\
/* no memory, grow hostmem list */
hb = hostmem_block_create(size);
if (hb == NULL)
return NULL;
\
spin_lock_irqsave(&cpm_hostmem_lock, flags);
\
/* attach free memory region */
if (rh_attach_region(&cpm_hostmem_info, (void *)hb->va, hb->size) < 0) {
hostmem_block_destroy(hb);
goto out;
}
\
/* append to list */
list_add(&hb->list, &cpm_hostmem_list);
\
/* and retry, hopefully this will succeed */
ret = rh_alloc(&cpm_hostmem_info, size, owner);
out:
if (ret != NULL) {
list_for_each(l, &cpm_hostmem_list) {
hb = list_entry(l, cpm_hostmem_block_t, list);
if (hb->va <= (uint)ret && hb->va + size > (uint)ret) {
hb->allocated += size;
break;
}
}
}
\
spin_unlock_irqrestore(&cpm_hostmem_lock, flags);
\
return ret;
}
\
int new_m8xx_cpm_hostfree(void *start)
{
int size;
static cpm_hostmem_block_t *hb, *hbfound;
struct list_head *l;
unsigned long flags;
\
hbfound = NULL;
\
spin_lock_irqsave(&cpm_hostmem_lock, flags);
\
size = rh_free(&cpm_hostmem_info, start);
if (size > 0) {
/* update allocated space counter, and destroy page(s) if zero */
list_for_each(l, &cpm_hostmem_list) {
hb = list_entry(l, cpm_hostmem_block_t, list);
if (hb->va <= (uint)start && hb->va + size > (uint)start) {
hb->allocated -= size;
if (hb->allocated == 0) {
list_del(&hb->list);
rh_detach_region(&cpm_hostmem_info, (void *)hb->va, hb->size);
hbfound = hb;
}
break;
}
}
}
\
spin_unlock_irqrestore(&cpm_hostmem_lock, flags);
\
/* if the block was detached destroy it */
if (hbfound != NULL)
hostmem_block_destroy(hbfound);
\
return size;
}
\
void new_m8xx_cpm_hostdump(void)
{
extern void rh_dump(rh_info_t *info);
\
rh_dump(&cpm_hostmem_info);
}
\
#endif
\
== arch/ppc/kernel/ppc_ksyms.c ==
cort@ftsoj.fsmlabs.com|arch/ppc/kernel/ppc_ksyms.c|20010106073009|44721|924fea448d6377b3
paulus@au1.ibm.com|arch/ppc/kernel/ppc_ksyms.c|20021217012142|33492
D 1.107 02/12/18 14:11:30+02:00 panto@macpanto.intranet.gr +11 -0
B cort@ftsoj.fsmlabs.com|ChangeSet|20010106071759|19793|5c81b698cda31832
C
c Export the dpalloc/hostalloc routines for use in modules.
K 62557
O -rw-rw-r--
P arch/ppc/kernel/ppc_ksyms.c
------------------------------------------------
I359 11
#ifdef CONFIG_NEW_DPALLOC
EXPORT_SYMBOL(new_m8xx_cpm_dpalloc);
EXPORT_SYMBOL(new_m8xx_cpm_dpfree);
EXPORT_SYMBOL(new_m8xx_cpm_dpalloc_fixed);
EXPORT_SYMBOL(new_m8xx_cpm_dpdump);
#endif
#ifdef CONFIG_NEW_HOSTALLOC
EXPORT_SYMBOL(new_m8xx_cpm_hostalloc);
EXPORT_SYMBOL(new_m8xx_cpm_hostfree);
EXPORT_SYMBOL(new_m8xx_cpm_hostdump);
#endif
== arch/ppc/8xx_io/rheap.c ==
New file: arch/ppc/8xx_io/rheap.c
V 4
panto@macpanto.intranet.gr|arch/ppc/8xx_io/rheap.c|20021218110152|22702|dc008764c8bd3605
D 1.0 02/12/18 13:01:52+02:00 panto@macpanto.intranet.gr +0 -0
B cort@ftsoj.fsmlabs.com|ChangeSet|20010106071759|19793|5c81b698cda31832
c BitKeeper file /archives/bk/linuxppc_2_4_devel-alloc_patch/arch/ppc/8xx_io/rheap.c
K 22702
P arch/ppc/8xx_io/rheap.c
R dc008764c8bd3605
X 0x821
------------------------------------------------
panto@macpanto.intranet.gr|arch/ppc/8xx_io/rheap.c|20021218110152|22702|dc008764c8bd3605
D 1.1 02/12/18 13:01:52+02:00 panto@macpanto.intranet.gr +657 -0
B cort@ftsoj.fsmlabs.com|ChangeSet|20010106071759|19793|5c81b698cda31832
C
F 1
K 65298
O -rw-rw-r--
P arch/ppc/8xx_io/rheap.c
------------------------------------------------
I0 657
/*
* Remote Heap
*
* Pantelis Antoniou <panto@intracom.gr>
* INTRACOM S.A. Greece
*
*/
\
\
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/slab.h>
\
#include "rheap.h"
\
/********************************************************************************/
\
/* fixup a list_head, needed when copying lists */
/* if the pointers fall between s and e, apply the delta */
/* assumes that sizeof(struct list_head *) == sizeof(unsigned long *) */
static inline void fixup(unsigned long s, unsigned long e, int d, struct list_head *l)
{
unsigned long *pp;
\
pp = (unsigned long *)&l->next;
if (*pp >= s && *pp < e)
*pp += d;
\
pp = (unsigned long *)&l->prev;
if (*pp >= s && *pp < e)
*pp += d;
}
\
/* grow the allocated blocks */
static int grow(rh_info_t *info, int max_blocks)
{
rh_block_t *block, *blk;
int i, new_blocks;
int delta;
unsigned long blks, blke;
\
if (max_blocks <= info->max_blocks)
return -EINVAL;
\
new_blocks = max_blocks - info->max_blocks;
\
block = kmalloc(sizeof(rh_block_t) * max_blocks, GFP_KERNEL);
if (block == NULL)
return -ENOMEM;
\
if (info->max_blocks > 0) {
\
/* copy old block area */
memcpy(block, info->block, sizeof(rh_block_t) * info->max_blocks);
\
delta = (char *)block - (char *)info->block;
\
/* and fixup list pointers */
blks = (unsigned long)info->block;
blke = (unsigned long)(info->block + info->max_blocks);
\
for (i = 0, blk = block; i < info->max_blocks; i++, blk++)
fixup(blks, blke, delta, &blk->list);
\
fixup(blks, blke, delta, &info->empty_list);
fixup(blks, blke, delta, &info->free_list);
fixup(blks, blke, delta, &info->taken_list);
\
/* free the old allocated memory */
if ((info->flags & RHIF_STATIC_BLOCK) == 0)
kfree(info->block);
}
\
info->block = block;
info->empty_slots += new_blocks;
info->max_blocks = max_blocks;
info->flags &= ~RHIF_STATIC_BLOCK;
\
/* add all new blocks to the free list */
for (i = 0, blk = block + info->max_blocks; i < new_blocks; i++, blk++)
list_add(&blk->list, &info->empty_list);
\
return 0;
}
\
/* assure at least the required amount of empty slots
if this function causes a grow in the block area
the all pointers kept to the block area are invalid!
*/
static int assure_empty(rh_info_t *info, int slots)
{
int max_blocks;
\
/* this function is not meant to be used to grow uncontrollably */
if (slots >= 4)
return -EINVAL;
\
/* enough space */
if (info->empty_slots >= slots)
return 0;
\
/* next 16 sized block */
max_blocks = ((info->max_blocks + slots) + 15) & ~15;
\
return grow(info, max_blocks);
}
\
static rh_block_t *get_slot(rh_info_t *info)
{
rh_block_t *blk;
\
/* if no more free slots, and failure to extend */
/* XXX you should have called assure_empty before */
if (info->empty_slots == 0) {
printk(KERN_ERR "rh: out of slots; crash is imminent.\n");
return NULL;
}
\
/* get empty slot to use */
blk = list_entry(info->empty_list.next, rh_block_t, list);
list_del_init(&blk->list);
info->empty_slots--;
\
/* initialize */
blk->start = NULL;
blk->size = 0;
blk->owner = NULL;
\
return blk;
}
\
static inline void release_slot(rh_info_t *info, rh_block_t *blk)
{
list_add(&blk->list, &info->empty_list);
info->empty_slots++;
}
\
static void attach_free_block(rh_info_t *info, rh_block_t *blkn)
{
rh_block_t *blk;
rh_block_t *before;
rh_block_t *after;
rh_block_t *next;
int size;
unsigned long s, e, bs, be;
struct list_head *l;
\
/* we assume that they are aligned properly */
size = blkn->size;
s = (unsigned long)blkn->start;
e = s + size;
\
/* find the blocks immediately before and after the given one (if any) */
before = NULL;
after = NULL;
next = NULL;
\
list_for_each(l, &info->free_list) {
blk = list_entry(l, rh_block_t, list);
\
bs = (unsigned long)blk->start;
be = bs + blk->size;
\
if (next == NULL && s >= bs)
next = blk;
\
if (be == s)
before = blk;
\
if (e == bs)
after = blk;
\
/* if both are not null, break now */
if (before != NULL && after != NULL)
break;
}
\
/* now check if they are really adjacent */
if (before != NULL && s != (unsigned long)before->start + before->size)
before = NULL;
\
if (after != NULL && e != (unsigned long)after->start)
after = NULL;
\
/* no coalescing; list insert and return */
if (before == NULL && after == NULL) {
\
if (next != NULL)
list_add(&blkn->list, &next->list);
else
list_add(&blkn->list, &info->free_list);
\
return;
}
\
/* we don't need it anymore */
release_slot(info, blkn);
\
/* grow the before block */
if (before != NULL && after == NULL) {
before->size += size;
return;
}
\
/* grow the after block backwards */
if (before == NULL && after != NULL) {
(int8_t *)after->start -= size;
after->size += size;
return;
}
\
/* grow the before block, and release the after block */
before->size += size + after->size;
list_del(&after->list);
release_slot(info, after);
}
\
static void attach_taken_block(rh_info_t *info, rh_block_t *blkn)
{
rh_block_t *blk;
struct list_head *l;
\
/* find the block immediately before the given one (if any) */
list_for_each(l, &info->taken_list) {
blk = list_entry(l, rh_block_t, list);
if (blk->start > blkn->start) {
list_add_tail(&blkn->list, &blk->list);
return;
}
}
\
list_add_tail(&blkn->list, &info->taken_list);
}
\
/**********************************************************************/
\
/* Create a remote heap dynamically.
Note that no memory for the blocks are allocated.
It will upon the first allocation
*/
rh_info_t *rh_create(unsigned int alignment)
{
rh_info_t *info;
\
/* alignment must be a power of two */
if ((alignment & (alignment - 1)) != 0)
return NULL;
\
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (info == NULL)
return NULL;
\
info->alignment = alignment;
\
/* initially everything is empty */
info->block = NULL;
info->max_blocks = 0;
info->empty_slots = 0;
info->flags = 0;
\
INIT_LIST_HEAD(&info->empty_list);
INIT_LIST_HEAD(&info->free_list);
INIT_LIST_HEAD(&info->taken_list);
\
return info;
}
\
/* Destroy a dynamically created remote heap
Deallocate only if the areas are not static
*/
void rh_destroy(rh_info_t *info)
{
if ((info->flags & RHIF_STATIC_BLOCK) == 0 && info->block != NULL)
kfree(info->block);
\
if ((info->flags & RHIF_STATIC_INFO) == 0)
kfree(info);
}
\
/********************************************************************************/
\
/* Initialize in place a remote heap info block.
This is needed to support operation very early in the startup of the
kernel, when it is not yet safe to call kmalloc.
*/
void rh_init(rh_info_t *info, unsigned int alignment, int max_blocks, rh_block_t *block)
{
int i;
rh_block_t *blk;
\
/* alignment must be a power of two */
if ((alignment & (alignment - 1)) != 0)
return;
\
info->alignment = alignment;
\
/* initially everything is empty */
info->block = block;
info->max_blocks = max_blocks;
info->empty_slots = max_blocks;
info->flags = RHIF_STATIC_INFO | RHIF_STATIC_BLOCK;
\
INIT_LIST_HEAD(&info->empty_list);
INIT_LIST_HEAD(&info->free_list);
INIT_LIST_HEAD(&info->taken_list);
\
/* add all new blocks to the free list */
for (i = 0, blk = block; i < max_blocks; i++, blk++)
list_add(&blk->list, &info->empty_list);
}
\
/********************************************************************************/
\
/* Attach a free memory region, coalesces regions if adjuscent */
int rh_attach_region(rh_info_t *info, void *start, int size)
{
rh_block_t *blk;
unsigned long s, e, m;
int r;
\
/* the region must be aligned */
s = (unsigned long)start;
e = s + size;
m = info->alignment - 1;
\
/* round start up */
s = (s + m) & ~m;
\
/* round end down */
e = e & ~m;
\
/* take final values */
start = (void *)s;
size = (int)(e - s);
\
/* grow the blocks, if needed */
r = assure_empty(info, 1);
if (r < 0)
return r;
\
blk = get_slot(info);
blk->start = start;
blk->size = size;
blk->owner = NULL;
\
attach_free_block(info, blk);
\
return 0;
}
\
/* Detatch given address range, splits free block if needed. */
void *rh_detach_region(rh_info_t *info, void *start, int size)
{
struct list_head *l;
rh_block_t *blk, *newblk;
unsigned long s, e, m, bs, be;
\
/* validate size */
if (size <= 0)
return NULL;
\
/* the region must be aligned */
s = (unsigned long)start;
e = s + size;
m = info->alignment - 1;
\
/* round start up */
s = (s + m) & ~m;
\
/* round end down */
e = e & ~m;
\
if (assure_empty(info, 1) < 0)
return NULL;
\
blk = NULL;
list_for_each(l, &info->free_list) {
blk = list_entry(l, rh_block_t, list);
/* the range must lie entirely inside one free block */
bs = (unsigned long)blk->start;
be = (unsigned long)blk->start + blk->size;
if (s >= bs && e <= be)
break;
blk = NULL;
}
if (blk == NULL)
return NULL;
\
/* perfect fit */
if (bs == s && be == e) {
/* delete from free list, release slot */
list_del(&blk->list);
release_slot(info, blk);
return (void *)s;
}
\
/* blk still in free list, with updated start and/or size */
if (bs == s || be == e) {
if (bs == s)
(int8_t *)blk->start += size;
blk->size -= size;
\
} else {
/* the front free fragment */
blk->size = s - bs;
\
/* the back free fragment */
newblk = get_slot(info);
newblk->start = (void *)e;
newblk->size = be - e;
\
list_add(&newblk->list, &blk->list);
}
\
return (void *)s;
}
\
/********************************************************************************/
\
void *rh_alloc(rh_info_t *info, int size, const char *owner)
{
struct list_head *l;
rh_block_t *blk;
rh_block_t *newblk;
void *start;
\
/* validate size */
if (size <= 0)
return NULL;
\
/* align to configured alignment */
size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
\
if (assure_empty(info, 1) < 0)
return NULL;
\
blk = NULL;
list_for_each(l, &info->free_list) {
blk = list_entry(l, rh_block_t, list);
if (size <= blk->size)
break;
blk = NULL;
}
if (blk == NULL)
return NULL;
\
/* just fits */
if (blk->size == size) {
/* move from free list to taken list */
list_del(&blk->list);
blk->owner = owner;
start = blk->start;
\
attach_taken_block(info, blk);
\
return start;
}
\
newblk = get_slot(info);
newblk->start = blk->start;
newblk->size = size;
newblk->owner = owner;
\
/* blk still in free list, with updated start, size */
(int8_t *)blk->start += size;
blk->size -= size;
\
start = newblk->start;
\
attach_taken_block(info, newblk);
\
return start;
}
\
/* allocate at precisely the given address */
void *rh_alloc_fixed(rh_info_t *info, void *start, int size, const char *owner)
{
struct list_head *l;
rh_block_t *blk, *newblk1, *newblk2;
unsigned long s, e, m, bs, be;
\
/* validate size */
if (size <= 0)
return NULL;
\
/* the region must be aligned */
s = (unsigned long)start;
e = s + size;
m = info->alignment - 1;
\
/* round start up */
s = (s + m) & ~m;
\
/* round end down */
e = e & ~m;
\
if (assure_empty(info, 2) < 0)
return NULL;
\
blk = NULL;
list_for_each(l, &info->free_list) {
blk = list_entry(l, rh_block_t, list);
/* the range must lie entirely inside one free block */
bs = (unsigned long)blk->start;
be = (unsigned long)blk->start + blk->size;
if (s >= bs && e <= be)
break;
}
if (blk == NULL)
return NULL;
\
/* perfect fit */
if (bs == s && be == e) {
/* move from free list to taken list */
list_del(&blk->list);
blk->owner = owner;
\
start = blk->start;
attach_taken_block(info, blk);
\
return start;
\
}
\
/* blk still in free list, with updated start and/or size */
if (bs == s || be == e) {
if (bs == s)
(int8_t *)blk->start += size;
blk->size -= size;
\
} else {
/* the front free fragment */
blk->size = s - bs;
\
/* the back free fragment */
newblk2 = get_slot(info);
newblk2->start = (void *)e;
newblk2->size = be - e;
\
list_add(&newblk2->list, &blk->list);
}
\
newblk1 = get_slot(info);
newblk1->start = (void *)s;
newblk1->size = e - s;
newblk1->owner = owner;
\
start = newblk1->start;
attach_taken_block(info, newblk1);
\
return start;
}
\
int rh_free(rh_info_t *info, void *start)
{
rh_block_t *blk, *blk2;
struct list_head *l;
int size;
\
/* linear search for block */
\
blk = NULL;
list_for_each(l, &info->taken_list) {
blk2 = list_entry(l, rh_block_t, list);
if (start < blk2->start)
break;
blk = blk2;
}
\
if (blk == NULL || start > (blk->start + blk->size))
return -EINVAL;
\
/* remove from taken list */
list_del(&blk->list);
\
/* get size of freed block */
size = blk->size;
attach_free_block(info, blk);
\
return size;
}
\
int rh_get_stats(rh_info_t *info, int what, int max_stats, rh_stats_t *stats)
{
rh_block_t *blk;
struct list_head *l;
struct list_head *h;
int nr;
\
switch (what) {
\
case RHGS_FREE:
h = &info->free_list;
break;
\
case RHGS_TAKEN:
h = &info->taken_list;
break;
\
default:
return -EINVAL;
}
\
/* linear search for block */
nr = 0;
list_for_each(l, h) {
blk = list_entry(l, rh_block_t, list);
if (stats != NULL && nr < max_stats) {
stats->start = blk->start;
stats->size = blk->size;
stats->owner = blk->owner;
stats++;
}
nr++;
}
return nr;
}
\
/********************************************************************************/
\
void rh_dump(rh_info_t *info)
{
static rh_stats_t st[32]; /* XXX maximum 32 blocks */
int maxnr;
int i, nr;
\
maxnr = sizeof(st) / sizeof(st[0]);
\
printk(KERN_INFO "info @0x%p (%d slots empty / %d max)\n", info, info->empty_slots, info->max_blocks);
\
printk(KERN_INFO " Free:\n");
nr = rh_get_stats(info, RHGS_FREE, maxnr, st);
if (nr > maxnr)
nr = maxnr;
for (i = 0; i < nr; i++)
printk(KERN_INFO " 0x%p-0x%p (%u)\n", st[i].start, (int8_t *)st[i].start + st[i].size, st[i].size);
printk(KERN_INFO "\n");
\
printk(KERN_INFO " Taken:\n");
nr = rh_get_stats(info, RHGS_TAKEN, maxnr, st);
if (nr > maxnr)
nr = maxnr;
for (i = 0; i < nr; i++)
printk(KERN_INFO " 0x%p-0x%p (%u) %s\n", st[i].start, (int8_t *)st[i].start + st[i].size, st[i].size,
st[i].owner != NULL ? st[i].owner : "");
printk(KERN_INFO "\n");
}
\
void rh_dump_blk(rh_info_t *info, rh_block_t *blk)
{
printk(KERN_INFO "blk @0x%p: 0x%p-0x%p (%u)\n", blk, blk->start, (int8_t *)blk->start + blk->size, blk->size);
}
== arch/ppc/8xx_io/rheap.h ==
New file: arch/ppc/8xx_io/rheap.h
V 4
panto@macpanto.intranet.gr|arch/ppc/8xx_io/rheap.h|20021218110153|06128|b08dd5e21d4baa75
D 1.0 02/12/18 13:01:53+02:00 panto@macpanto.intranet.gr +0 -0
B cort@ftsoj.fsmlabs.com|ChangeSet|20010106071759|19793|5c81b698cda31832
c BitKeeper file /archives/bk/linuxppc_2_4_devel-alloc_patch/arch/ppc/8xx_io/rheap.h
K 6128
P arch/ppc/8xx_io/rheap.h
R b08dd5e21d4baa75
X 0x821
------------------------------------------------
panto@macpanto.intranet.gr|arch/ppc/8xx_io/rheap.h|20021218110153|06128|b08dd5e21d4baa75
D 1.1 02/12/18 13:01:53+02:00 panto@macpanto.intranet.gr +89 -0
B cort@ftsoj.fsmlabs.com|ChangeSet|20010106071759|19793|5c81b698cda31832
C
F 1
K 58254
O -rw-rw-r--
P arch/ppc/8xx_io/rheap.h
------------------------------------------------
I0 89
/*
* Remote Heap
*
* Pantelis Antoniou <panto@intracom.gr>
* INTRACOM S.A. Greece
*
* Header file for the implementation of a remote heap.
*
* Remote means that we don't touch the memory that the heap
* points to. Normal heap implementations use the memory
* they manage to place their list. We cannot do that
* because the memory we manage may have special
* properties, for example it is uncachable or of
* different endianess.
*
*/
\
#ifndef RHEAP_H
#define RHEAP_H
\
#include <linux/list.h>
\
/********************************************************************************/
\
typedef struct _rh_block {
struct list_head list;
void *start;
int size;
const char *owner;
} rh_block_t;
\
typedef struct _rh_info {
unsigned int alignment;
int max_blocks;
int empty_slots;
rh_block_t *block;
struct list_head empty_list;
struct list_head free_list;
struct list_head taken_list;
unsigned int flags;
} rh_info_t;
\
#define RHIF_STATIC_INFO 0x1
#define RHIF_STATIC_BLOCK 0x2
\
typedef struct rh_stats_t {
void *start;
int size;
const char *owner;
} rh_stats_t;
\
#define RHGS_FREE 0
#define RHGS_TAKEN 1
\
/********************************************************************************/
\
/* create a remote heap dynamically */
rh_info_t *rh_create(unsigned int alignment);
\
/* destroy a remote heap, created by rh_create() */
void rh_destroy(rh_info_t *info);
\
/* initialize in place a remote info block */
void rh_init(rh_info_t *info, unsigned int alignment, int max_blocks, rh_block_t *block);
\
/* attach a free region to manage */
int rh_attach_region(rh_info_t *info, void *start, int size);
\
/* detach a free region */
void *rh_detach_region(rh_info_t *info, void *start, int size);
\
/* allocate the given size from the remote heap */
void *rh_alloc(rh_info_t *info, int size, const char *owner);
\
/* allocate the given size from the given address */
void *rh_alloc_fixed(rh_info_t *info, void *start, int size, const char *owner);
\
/* free the allocated area */
int rh_free(rh_info_t *info, void *start);
\
/* get stats for debugging purposes */
int rh_get_stats(rh_info_t *info, int what, int max_stats, rh_stats_t *stats);
\
/* simple dump of remote heap info */
void rh_dump(rh_info_t *info);
\
/********************************************************************************/
\
#endif
== include/asm-ppc/commproc.h ==
patch@bill-the-cat.bloom.county|include/asm-ppc/commproc.h|20011008234020|17681|bb192d8bed8005fd
paulus@samba.org|include/asm-ppc/commproc.h|20020625143811|62769
D 1.5 02/12/18 14:11:30+02:00 panto@macpanto.intranet.gr +13 -0
B cort@ftsoj.fsmlabs.com|ChangeSet|20010106071759|19793|5c81b698cda31832
C
c Prototypes for the new style dpalloc/hostalloc functions.
K 40673
O -rw-rw-r--
P include/asm-ppc/commproc.h
------------------------------------------------
I799 13
#ifdef CONFIG_NEW_DPALLOC
extern void *new_m8xx_cpm_dpalloc(unsigned int size, const char *owner);
extern int new_m8xx_cpm_dpfree(void *start);
extern void *new_m8xx_cpm_dpalloc_fixed(void *start, int size, const char *owner);
extern void new_m8xx_cpm_dpdump(void);
#endif
\
#ifdef CONFIG_NEW_HOSTALLOC
extern void *new_m8xx_cpm_hostalloc(unsigned int size, const char *owner);
extern int new_m8xx_cpm_hostfree(void *start);
extern void new_m8xx_cpm_hostdump(void);
#endif
\
# Patch checksum=133cfdf6
^ permalink raw reply
* Re: 2.5.52-mm1
From: Ed Tomlinson @ 2002-12-18 12:26 UTC (permalink / raw)
To: Andrew Morton, linux-kernel
In-Reply-To: <3DFD908D.14D7F6E7@digeo.com>
Hi
Got this oops this morning reading news:
Dec 18 07:15:29 oscar kernel: printing eip:
Dec 18 07:15:29 oscar kernel: c0140317
Dec 18 07:15:29 oscar kernel: Oops: 0002
Dec 18 07:15:29 oscar kernel: CPU: 0
Dec 18 07:15:29 oscar kernel: EIP: 0060:[remove_inode_buffers+67/116] Not tainted
Dec 18 07:15:29 oscar kernel: EFLAGS: 00010246
Dec 18 07:15:29 oscar kernel: EIP is at remove_inode_buffers+0x43/0x74
Dec 18 07:15:29 oscar kernel: eax: 0dc4c344 ebx: c3440dc4 ecx: c3440dc6 edx: 0000c344
Dec 18 07:15:29 oscar kernel: esi: c3440cd4 edi: 00000001 ebp: dfdb9ebc esp: dfdb9e8c
Dec 18 07:15:29 oscar kernel: ds: 0068 es: 0068 ss: 0068
Dec 18 07:15:29 oscar kernel: Process kswapd0 (pid: 7, threadinfo=dfdb8000 task=dfdcb860)
Dec 18 07:15:29 oscar kernel: Stack: c3440cd4 c3440cdc dfdb8000 c0152ff7 c3440cd4 00000080 00000923 d
Dec 18 07:15:29 oscar kernel: 00000036 00000036 c3440b5c d76876dc 00000000 c01530db 00000080 c
Dec 18 07:15:29 oscar kernel: 00000080 000001d0 00000221 c02a5374 fffffe27 0000000c 0d024a92 0
Dec 18 07:15:29 oscar kernel: Call Trace:
Dec 18 07:15:29 oscar kernel: [prune_icache+191/396] prune_icache+0xbf/0x18c
Dec 18 07:15:29 oscar kernel: [shrink_icache_memory+23/32] shrink_icache_memory+0x17/0x20
Dec 18 07:15:29 oscar kernel: [shrink_slab+245/320] shrink_slab+0xf5/0x140
Dec 18 07:15:29 oscar kernel: [balance_pgdat+212/316] balance_pgdat+0xd4/0x13c
Dec 18 07:15:29 oscar kernel: [kswapd+256/264] kswapd+0x100/0x108
Dec 18 07:15:29 oscar kernel: [kswapd+0/264] kswapd+0x0/0x108
Dec 18 07:15:29 oscar kernel: [autoremove_wake_function+0/56] autoremove_wake_function+0x0/0x38
Dec 18 07:15:29 oscar kernel: [autoremove_wake_function+0/56] autoremove_wake_function+0x0/0x38
Dec 18 07:15:29 oscar kernel: [kernel_thread_helper+5/12] kernel_thread_helper+0x5/0xc
Dec 18 07:15:29 oscar kernel:
Dec 18 07:15:29 oscar kernel: Code: 89 50 04 89 02 89 09 89 49 04 39 1b 75 e0 b8 00 e0 ff ff 21
followed by
Dec 18 07:15:29 oscar kernel: <6>note: kswapd0[7] exited with preempt_count 1
Dec 18 07:15:29 oscar kernel: Call Trace:
Dec 18 07:15:29 oscar kernel: [__might_sleep+82/88] __might_sleep+0x52/0x58
Dec 18 07:15:29 oscar kernel: [profile_exit_task+23/72] profile_exit_task+0x17/0x48
Dec 18 07:15:29 oscar kernel: [do_exit+149/964] do_exit+0x95/0x3c4
Dec 18 07:15:29 oscar kernel: [die+111/112] die+0x6f/0x70
Dec 18 07:15:29 oscar kernel: [do_page_fault+757/1076] do_page_fault+0x2f5/0x434
Dec 18 07:15:29 oscar kernel: [do_page_fault+0/1076] do_page_fault+0x0/0x434
Dec 18 07:15:29 oscar kernel: [x86_profile_hook+28/56] x86_profile_hook+0x1c/0x38
Dec 18 07:15:29 oscar kernel: [timer_interrupt+42/272] timer_interrupt+0x2a/0x110
Dec 18 07:15:29 oscar kernel: [free_hot_page+7/8] free_hot_page+0x7/0x8
Dec 18 07:15:29 oscar kernel: [__free_pages+49/64] __free_pages+0x31/0x40
Dec 18 07:15:29 oscar kernel: [free_pages+48/52] free_pages+0x30/0x34
Dec 18 07:15:29 oscar kernel: [slab_destroy+154/180] slab_destroy+0x9a/0xb4
Dec 18 07:15:29 oscar kernel: [cache_flusharray+161/292] cache_flusharray+0xa1/0x124
Dec 18 07:15:29 oscar kernel: [error_code+45/64] error_code+0x2d/0x40
Dec 18 07:15:29 oscar kernel: [remove_inode_buffers+67/116] remove_inode_buffers+0x43/0x74
Dec 18 07:15:29 oscar kernel: [prune_icache+191/396] prune_icache+0xbf/0x18c
Dec 18 07:15:29 oscar kernel: [shrink_icache_memory+23/32] shrink_icache_memory+0x17/0x20
Dec 18 07:15:29 oscar kernel: [shrink_slab+245/320] shrink_slab+0xf5/0x140
Dec 18 07:15:29 oscar kernel: [balance_pgdat+212/316] balance_pgdat+0xd4/0x13c
Dec 18 07:15:29 oscar kernel: [kswapd+256/264] kswapd+0x100/0x108
Dec 18 07:15:29 oscar kernel: [kswapd+0/264] kswapd+0x0/0x108
Dec 18 07:15:29 oscar kernel: [autoremove_wake_function+0/56] autoremove_wake_function+0x0/0x38
Dec 18 07:15:29 oscar kernel: [autoremove_wake_function+0/56] autoremove_wake_function+0x0/0x38
Dec 18 07:15:29 oscar kernel: [kernel_thread_helper+5/12] kernel_thread_helper+0x5/0xc
Dec 18 07:15:29 oscar kernel:
Ideas?
^ permalink raw reply
* Re: Help: Auto login
From: Paul Nasrat @ 2002-12-18 12:35 UTC (permalink / raw)
To: linux-8086
In-Reply-To: <Pine.LNX.4.30.0212180621300.1088-100000@Vachuska.localdomain>
On Wed, Dec 18, 2002 at 06:24:08AM -0600, Peter L. Vachuska wrote:
> I am trying to set up ELKS running on a 286 laptop in a display case. In
> case of power failure, I don't want to have to login and start the program
> running. So how do I automatically login user1 and start my program?
> (Basically the program would print digits of pi to the screen.)
If you are happy running as root you can use /etc/inittab.
Looks like setuid is in dev86 so you may be able to write a c wrapper to
setuid to user1.
hth
Paul
^ permalink raw reply
* Re: kmalloc and startup process
From: Pantelis Antoniou @ 2002-12-18 12:34 UTC (permalink / raw)
To: Dan Malek; +Cc: linuxppc-embedded
In-Reply-To: <3DFF5466.3050606@embeddededge.com>
Dan Malek wrote:
> Pantelis Antoniou wrote:
>
>
>> At what point in the startup process is it OK to call
>> kmalloc?
>
>
> Before you start hacking up things that are "broken", you
> should probably take a moment to understand why they are
> currently implemented the way they are.
>
> The CPM support functions are called _very_ early in the
> kernel to support such features as KGDB on the serial ports.
> Currently, the host memory allocator uses bootmem pages
> because they are only option for allocating memory that early.
Yes I'm perfectly aware of that. My solution is to use this
memory first, and then fallback to using dynamic memory
later. Since my routines don't impose any memory overhead
to the allocated space, anyone counting at the old behaviour
is unaffected.
>
>
> There are three host memory allocators that are used to
> support CPM functions. One is the 'cpm_hostalloc()' space,
> which is available early and used for small objects like
> uart fifos. Second is the consistent DMA functions which
> are used in the places like the Ethernet driver. Third is
> the kernel kmalloc() function which must be futher managed
> with the cache coherency functions. They all have advantages
> and features that meet various driver requirements. You may
> need to use several layers of initialization to make this
> happen, just like any other Linux driver. Some must be
> done at kernel initialization, others can be postponed until
> later. When you think driver support functions are "broken"
> you may want to stop and consider that maybe your driver
> writing techniques are broken and investigate how these
> functions are working successfully for others.
What I'm dealing here is the requirement to use modules
for my proprietary hardware. I am perfectly willing to
contibute whatever changes I make to the kernel to the places
not dealing with my hardware. But I cannot open source my
hardware.
>
>
> I would strongly suggest that the only thing to "fix" is to
> add a trivial space manager to some statically configurable
> number of bootmem pages. The old UNIX resouce map allocator
> would be a perfect algorithm to manage this space.
Well, patch follows.
>
>
> Thanks.
>
>
> -- Dan
>
>
>
Regards
Pantelis
** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/
^ permalink raw reply
* how to delete a piece of rule in iptables?
From: bobo @ 2002-12-18 12:30 UTC (permalink / raw)
To: netfilter@lists.netfilter.org; +Cc: bobowd@sohu.com
i have insert some rules to iptables firewall.now,i would
like to delete it .
but i only know to use iptalbes -L to empty them.
but it lead to delete all the rules in it.
how to do ??
^ permalink raw reply
* Thank you (Re: How do I see all my partitions?)
From: Chris @ 2002-12-18 12:27 UTC (permalink / raw)
To: linux-newbie
In-Reply-To: <20021218104722.GA3850@neon.pearbough.net>
Thank you...
Now I feel like I should have known to look there 1st. Duh.
Hopefully I won't be a newbie too long...
Chris
At 11:47 AM Wednesday 12/18/2002, you wrote:
>Hi Chris!
>
>On Tue, 17 Dec 2002, Chris wrote:
>
> > my winxp partition. How do I display all the
> > partitions, Win/Dos/Linux, in one place so I can
> > give mount the correct partition name?
>
>You might already have heard of fdisk. It is a tool to partition your hard
>disks and also in fact the easiest way to see what partition is of what
>type and has what number/name.
>To call fdisk for your primary IDE slave call "fdisk /dev/hda" and you
>will get something like this:
>
> Device Boot Start End Blocks Id System
>/dev/hda1 1 9688 4882720+ 83 Linux
>/dev/hda2 * 9689 48440 19531008 7 HPFS/NTFS
>/dev/hda3 48441 158816 55629504 83 Linux
>
>(For example for your second SCSI disk it would be "fdisk /dev/sdb")
>
>Here you can see that my windows partition is /dev/hda2 is of type NTFS.
>To mount it you'll need an empty directory (e.g. /windows or /mnt/win) and
>the necessary file system support for you kernel (in my case NTFS).
>
>Then "mount <device> <mount directory>". In my case this looks like:
> "mount /dev/hda2 /windows"
>
>
>Have fun,
>Axel
-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs
^ permalink raw reply
* Help: Auto login
From: Peter L. Vachuska @ 2002-12-18 12:24 UTC (permalink / raw)
To: linux-8086
Hello-
I am trying to set up ELKS running on a 286 laptop in a display case. In
case of power failure, I don't want to have to login and start the program
running. So how do I automatically login user1 and start my program?
(Basically the program would print digits of pi to the screen.)
-Peter Vachuska
^ permalink raw reply
* [LARTC] Traffic is exceeding limits
From: Mindaugas Riauba @ 2002-12-18 12:23 UTC (permalink / raw)
To: lartc
I'm trying to setup traffic shaping for a customer.
Machine is RedHat 7.3 with kernel-smp-2.4.18-18.7.x.
HZQ2.
But when I try to load link (using netcat and discard /
chargen services) bytes count (tc -s qdisc show, sfq qdisc)
goes quite well over 512kbit (~560kbit). With UDP I can
even go over 1mbit.
What can be done to ensure tighter limits?
Thanks,
Mindaugas
burst and cburst were set by tc and equals 2175b. r2q = 10.
No more tc rules exists now.
$TC qdisc del dev eth0 root
$TC qdisc del dev eth1 root
$TC qdisc add dev eth0 root handle 1: htb
$TC qdisc add dev eth1 root handle 1: htb
$TC class add dev eth0 parent 1: classid 1:200 htb rate 512kbit
$TC class add dev eth1 parent 1: classid 1:200 htb rate 512kbit
$TC qdisc add dev eth0 parent 1:200 handle 200: sfq perturb 10
$TC qdisc add dev eth1 parent 1:200 handle 200: sfq perturb 10
$TC filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip src $ip
flowid 1:200
$TC filter add dev eth1 parent 1: protocol ip prio 1 u32 match ip dst $ip
flowid 1:200
_______________________________________________
LARTC mailing list / LARTC@mailman.ds9a.nl
http://mailman.ds9a.nl/mailman/listinfo/lartc HOWTO: http://lartc.org/
^ permalink raw reply
* Re: buggy scsi_register behaviour in 2.5.51
From: Douglas Gilbert @ 2002-12-18 12:14 UTC (permalink / raw)
To: wrlk; +Cc: linux-scsi
In-Reply-To: <20021217114730.GE7990@linnie.riede.org>
Willem Riede wrote:
> <snip/>
>
> I'll also see if I can find what the remaining problems are. I'd also be
> prepared do do "cleaning up" of ide-scsi -- what in your opinion needs
> taking care of?
Willem,
ide-scsi in lk 2.5 ...
a) needs .eh_bus_reset_handler defined in idescsi_template
and implemented. It probably would be a dummy unless there
is a clean way to do an ATAPI bus (or device) reset.
b) replace .detect and .release in idescsi_template with the
slave_alloc, slave_configure and slave_destroy interface
These are documented in Documentation/scsi/scsi_mid_low_api.txt .
If you find mistakes or the explanation is not clear then
complain to me. For an example of the use of these new
interfaces see scsi_debug.c or aic7xxx_old.c
Good to see that you have fixed the ide sysfs de-registration
problem.
Doug Gilbert
^ permalink raw reply
* 24-bit 3byte formats
From: Jaroslav Kysela @ 2002-12-18 12:07 UTC (permalink / raw)
To: ALSA development
Hi,
it is possible with latest changes in CVS use 24-bit 3byte
formats (at least for playback direction). I've fixed remaining bugs in
driver/library/aplay.
Jaroslav
-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SuSE Labs
-------------------------------------------------------
This sf.net email is sponsored by:
With Great Power, Comes Great Responsibility
Learn to use your power at OSDN's High Performance Computing Channel
http://hpc.devchannel.org/
^ permalink raw reply
* Re: USB PCI
From: Korosi Akos @ 2002-12-18 12:04 UTC (permalink / raw)
To: dashielljt; +Cc: Newbie
In-Reply-To: <Pine.LNX.4.50.0212172225140.2352-100000@athame.gmpexpress.net>
dashielljt <dashielljt@gmpexpress.net> wrote
>Correction on that date. The bios needs to be no younger than july 1,
> 1999. Anything newer actually does support at least usb 1 and maybe
usb
> 2.
Thank you.
Sadly it's date is almost certainly before july 1, 1999, but I will
check it anyway.
Akos
________________________________________________
http://mailbox.hu - Már SMS értesítéssel is!
-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs
^ permalink raw reply
* [PATCH] Yet another new option for ROUTE target
From: Cedric de Launois @ 2002-12-18 11:58 UTC (permalink / raw)
To: Netfilter Development Mailinglist
[-- Attachment #1: Type: text/plain, Size: 889 bytes --]
Hi,
I added yet another new option (--iif option) for the ROUTE target.
This option lets you change the incoming interface of a packet.
This can be useful for testing purposes or unusual routing needs (see
http://lists.netfilter.org/pipermail/netfilter-devel/2002-December/010026.html)
I also cleaned up the code and somewhat standardized the option names.
The ROUTE target options are now:
--oif ifname Send the packet out using `ifname' network interface.
--iif ifname Change the packet's incoming interface to `ifname'.
--gw ip Route the packet via this gateway.
Besides, the target can now apply on all five hooks.
I tried to do my best to test this target but it is quite hard to test
the different configurations, even with the help of user-mode linux.
Please tell me how this target works (or not) for you !
The patch is against the current cvs tree.
Cedric
[-- Attachment #2: ROUTE.cvs.patch --]
[-- Type: text/x-patch, Size: 19309 bytes --]
diff -Nru netfilter.orig/patch-o-matic/extra/ROUTE.patch netfilter/patch-o-matic/extra/ROUTE.patch
--- netfilter.orig/patch-o-matic/extra/ROUTE.patch Thu Dec 5 21:44:38 2002
+++ netfilter/patch-o-matic/extra/ROUTE.patch Wed Dec 18 12:53:02 2002
@@ -1,7 +1,7 @@
diff -Nru linux.orig/include/linux/netfilter_ipv4/ipt_ROUTE.h linux/include/linux/netfilter_ipv4/ipt_ROUTE.h
--- linux.orig/include/linux/netfilter_ipv4/ipt_ROUTE.h Thu Jan 1 01:00:00 1970
-+++ linux/include/linux/netfilter_ipv4/ipt_ROUTE.h Thu Nov 21 10:36:35 2002
-@@ -0,0 +1,17 @@
++++ linux/include/linux/netfilter_ipv4/ipt_ROUTE.h Tue Dec 17 16:49:04 2002
+@@ -0,0 +1,18 @@
+/* Header file for iptables ipt_ROUTE target
+ *
+ * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
@@ -14,22 +14,19 @@
+#define IPT_ROUTE_IFNAMSIZ 16
+
+struct ipt_route_target_info {
-+ char ifname[IPT_ROUTE_IFNAMSIZ];
-+ unsigned int ipto;
++ char oif[IPT_ROUTE_IFNAMSIZ];
++ char iif[IPT_ROUTE_IFNAMSIZ];
++ unsigned int gw;
+};
+
+#endif /*_IPT_ROUTE_H_target*/
diff -Nru linux.orig/net/ipv4/netfilter/ipt_ROUTE.c linux/net/ipv4/netfilter/ipt_ROUTE.c
--- linux.orig/net/ipv4/netfilter/ipt_ROUTE.c Thu Jan 1 01:00:00 1970
-+++ linux/net/ipv4/netfilter/ipt_ROUTE.c Fri Nov 22 14:53:06 2002
-@@ -0,0 +1,317 @@
++++ linux/net/ipv4/netfilter/ipt_ROUTE.c Wed Dec 18 12:40:26 2002
+@@ -0,0 +1,365 @@
+/*
-+ * This is a module which is used for directly sending a received packet to
-+ * an interface or a host specified by the user. This target NEVER modifies
-+ * packets but allows a different routing scheme than the one provided by
-+ * the standard kernel routing table.
-+ *
-+ * Based on code from: ipt_MIRROR.c and various sources.
++ * This implements the ROUTE target, which enables you to setup unusual
++ * routes not supported by the standard kernel routing table.
+ *
+ * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
+ *
@@ -44,6 +41,7 @@
+#include <linux/netdevice.h>
+#include <linux/route.h>
+#include <net/ip.h>
++#include <net/route.h>
+#include <net/icmp.h>
+
+#if 0
@@ -58,7 +56,7 @@
+ * - ifindex :
+ * 0 if no oif prefered,
+ * otherwise set to the index of the desired oif
-+ * - route_info->ipto :
++ * - route_info->gw :
+ * 0 if no gateway specified,
+ * otherwise set to the next host to which the pkt must be routed
+ * If success, skb->dev is the output device to which the packet must
@@ -76,24 +74,24 @@
+{
+ int err;
+ struct rtable *rt;
-+ struct iphdr *iph = skb->nh.iph;
++ struct iphdr *iph = skb->nh.iph;
+ struct rt_key key = {
+ dst:iph->daddr,
+ src:0,
+ oif:ifindex,
+ tos:RT_TOS(iph->tos)
+ };
-+
++
+ /* The destination address may be overloaded by the target */
-+ if (route_info->ipto)
-+ key.dst = route_info->ipto;
-+
++ if (route_info->gw)
++ key.dst = route_info->gw;
++
+ /* Trying to route the packet with the standard routing table. */
+ if ((err = ip_route_output_key(&rt, &key))) {
+ DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
+ return -1;
+ }
-+
++
+ /* Success if no oif specified or if the oif correspond to the
+ * one desired */
+ if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
@@ -103,7 +101,7 @@
+ skb->dev = skb->dst->dev;
+ return 1;
+ }
-+
++
+ /* The interface selected by the routing table is not the one
+ * specified by the user. This may happen because the dst address
+ * is one of our own addresses. This module makes it possible to
@@ -111,7 +109,7 @@
+ */
+ DEBUGP("ipt_ROUTE: failed to route as desired (oif: %i)",
+ rt->u.dst.dev->ifindex);
-+
++
+ return 0;
+}
+
@@ -154,22 +152,120 @@
+}
+
+
-+static unsigned int ipt_route_target(struct sk_buff **pskb,
-+ unsigned int hooknum,
-+ const struct net_device *in,
-+ const struct net_device *out,
-+ const void *targinfo,
-+ void *userinfo)
++static unsigned int route_oif(const struct ipt_route_target_info *route_info,
++ struct sk_buff *skb)
+{
-+ const struct ipt_route_target_info *route_info = targinfo;
+ struct net_device *dev_out = NULL;
-+ struct sk_buff *skb = *pskb;
+ unsigned int ifindex = 0;
+
-+ if (!route_info->ipto && !route_info->ifname[0]) {
-+ DEBUGP(KERN_DEBUG "ipt_ROUTE: missing argument!\n");
-+ return NF_ACCEPT;
++ /* The user set the interface name to use.
++ * Getting the current interface index.
++ */
++ if ((dev_out = dev_get_by_name(route_info->oif)))
++ ifindex = dev_out->ifindex;
++ else
++ /* Unknown interface name : packet dropped */
++ return NF_DROP;
++
++ DEBUGP(KERN_DEBUG "oif index of %s is %i\n", route_info->oif, ifindex);
++
++
++ /* Trying the standard way of routing packets */
++ if (route(skb, ifindex, route_info)==1) {
++ DEBUGP(KERN_DEBUG "ROUTE oif ok, skb->dev->index=%i\n",
++ skb->dev->ifindex);
++
++ dev_put(dev_out);
++ if (ip_direct_send(skb) == -EINVAL)
++ return NF_DROP;
++ else
++ return NF_STOLEN;
++ }
++
++ /* Failed to send to oif. Trying the hard way */
++
++ DEBUGP(KERN_DEBUG "HARD ROUTING\n");
++
++ /* Drop old route. */
++ dst_release(skb->dst);
++ skb->dst = NULL;
++
++ /* We have to force the use of an interface.
++ * This interface must be a tunnel interface since
++ * otherwise we can't guess the hw address for
++ * the packet. For a tunnel interface, no hw address
++ * is needed.
++ */
++ if ((dev_out->type != ARPHRD_TUNNEL)
++ && (dev_out->type != ARPHRD_IPGRE)) {
++ DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
++ dev_put(dev_out);
++ return NF_DROP;
+ }
++
++ /* Send the packet. This will also free skb !
++ * Do not go through the POST_ROUTING hook because
++ * skb->dst is not set and because it will probably
++ * get confused by the destination IP address.
++ */
++ skb->dev = dev_out;
++ dev_direct_send(skb);
++ dev_put(dev_out);
++
++ return NF_STOLEN;
++}
++
++
++static unsigned int route_iif(const struct ipt_route_target_info *route_info,
++ struct sk_buff *skb)
++{
++ struct net_device *dev_out = NULL;
++ unsigned int ifindex = 0;
++
++ /* Getting the current interface index. */
++ if ((dev_out = dev_get_by_name(route_info->iif)))
++ ifindex = dev_out->ifindex;
++ else
++ /* Unknown interface name : packet dropped */
++ return NF_DROP;
++
++ DEBUGP(KERN_DEBUG "iif index of %s is %i\n", route_info->iif, ifindex);
++
++ skb->dev = dev_out;
++ dst_release(skb->dst);
++ skb->dst = NULL;
++
++ netif_rx(skb);
++
++ return NF_STOLEN;
++}
++
++
++static unsigned int route_gw(const struct ipt_route_target_info *route_info,
++ struct sk_buff *skb)
++{
++ if (route(skb, 0, route_info)!=1)
++ return NF_DROP;
++
++ DEBUGP(KERN_DEBUG "ROUTE gw ok, skb->dev->index=%i\n",
++ skb->dev->ifindex);
++
++ if (ip_direct_send(skb) == -EINVAL)
++ return NF_DROP;
++
++ return NF_STOLEN;
++}
++
++
++static unsigned int ipt_route_target(struct sk_buff **pskb,
++ unsigned int hooknum,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *targinfo,
++ void *userinfo)
++{
++ const struct ipt_route_target_info *route_info = targinfo;
++ struct sk_buff *skb = *pskb;
+
+ /* raw socket (tcpdump) may have clone of incoming
+ * skb: don't disturb it
@@ -225,74 +321,25 @@
+ skb->nf_debug = 0;
+#endif
+
-+ if (route_info->ifname[0]) {
-+ /* The user set the interface name to use.
-+ * Getting the current interface index.
-+ */
-+ if ((dev_out = dev_get_by_name(route_info->ifname)))
-+ ifindex = dev_out->ifindex;
-+ else
-+ /* Unknown interface name : packet dropped */
-+ return NF_DROP;
-+
-+ }
-+
-+ DEBUGP(KERN_DEBUG "Index of %s is %i\n", route_info->ifname, ifindex);
-+
-+ /* Trying the standard way of routing packets */
-+ if (route(skb, ifindex, route_info)==1) {
-+ DEBUGP(KERN_DEBUG "ROUTE ok, skb->dev->index=%i\n",
-+ skb->dev->ifindex);
-+
-+ if (dev_out) dev_put(dev_out);
-+ if (ip_direct_send(skb) == -EINVAL) return NF_DROP;
-+ return NF_STOLEN;
-+ }
-+
-+ if (!route_info->ifname[0]) {
-+ if (dev_out) dev_put(dev_out);
-+ return NF_DROP;
-+ }
-+
-+ /* Failed to correctly route. Trying the hard way */
-+
-+ DEBUGP(KERN_DEBUG "HARD ROUTING\n");
++ if (route_info->oif[0])
++ return route_oif(route_info, skb);
++
++ if (route_info->iif[0])
++ return route_iif(route_info, skb);
+
-+ /* Drop old route. */
-+ dst_release(skb->dst);
-+ skb->dst = NULL;
++ if (route_info->gw)
++ return route_gw(route_info, skb);
+
-+ /* We have to force the use of an interface.
-+ * This interface must be a tunnel interface since
-+ * otherwise we can't guess the hw address for
-+ * the packet. For a tunnel interface, no hw address
-+ * is needed.
-+ */
-+ if ((dev_out->type != ARPHRD_TUNNEL)
-+ && (dev_out->type != ARPHRD_IPGRE)) {
-+ DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
-+ dev_put(dev_out);
-+ return NF_DROP;
-+ }
-+
-+ /* Send the packet. This will also free skb !
-+ * Do not go through the POST_ROUTING hook because
-+ * skb->dst is not set and because it will probably
-+ * get confused by the destination IP address.
-+ */
-+ skb->dev = dev_out;
-+ dev_direct_send(skb);
-+ dev_put(dev_out);
-+
-+ return NF_STOLEN;
++ DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
++ return NF_ACCEPT;
+}
+
+
+static int ipt_route_checkentry(const char *tablename,
-+ const struct ipt_entry *e,
-+ void *targinfo,
-+ unsigned int targinfosize,
-+ unsigned int hook_mask)
++ const struct ipt_entry *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
+{
+ if (strcmp(tablename, "mangle") != 0) {
+ printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
@@ -301,8 +348,10 @@
+ }
+
+ if (hook_mask & ~( (1 << NF_IP_PRE_ROUTING)
-+ | (1 << NF_IP_FORWARD)
-+ | (1 << NF_IP_POST_ROUTING))) {
++ | (1 << NF_IP_LOCAL_IN)
++ | (1 << NF_IP_FORWARD)
++ | (1 << NF_IP_LOCAL_OUT)
++ | (1 << NF_IP_POST_ROUTING))) {
+ printk("ipt_ROUTE: bad hook\n");
+ return 0;
+ }
diff -Nru netfilter.orig/patch-o-matic/extra/ROUTE.patch.configure.help netfilter/patch-o-matic/extra/ROUTE.patch.configure.help
--- netfilter.orig/patch-o-matic/extra/ROUTE.patch.configure.help Thu Dec 5 21:44:38 2002
+++ netfilter/patch-o-matic/extra/ROUTE.patch.configure.help Wed Dec 18 12:19:19 2002
@@ -1,14 +1,18 @@
CONFIG_IP_NF_TARGET_LOG
ROUTE target support
CONFIG_IP_NF_TARGET_ROUTE
- This option adds a `ROUTE' target, which allows you to directly route
- a received packet through a specified interface or towards a host, even
- if the regular destination of the packet is the router itself.
- This target never modifies packets but allows a different routing scheme
- than the one provided by the standard kernel routing table.
+ This option adds a `ROUTE' target, which enables you to setup unusual
+ routes not supported by the standard kernel routing table.
+ For example, the ROUTE lets you directly route a received packet through
+ an interface or towards a host, even if the regular destination of the
+ packet is the router itself. The ROUTE target is also able to change the
+ incoming interface of a packet.
+
+ This target does never modify the packet and is a final target.
+ It has to be used inside the mangle table.
+
If you want to compile it as a module, say M here and read
Documentation/modules.txt. The module will be called ipt_ROUTE.o.
If unsure, say `N'.
-
diff -Nru netfilter.orig/patch-o-matic/extra/ROUTE.patch.help netfilter/patch-o-matic/extra/ROUTE.patch.help
--- netfilter.orig/patch-o-matic/extra/ROUTE.patch.help Thu Dec 5 21:44:38 2002
+++ netfilter/patch-o-matic/extra/ROUTE.patch.help Wed Dec 18 12:51:37 2002
@@ -1,28 +1,32 @@
Author: Cédric de Launois <delaunois@info.ucl.ac.be>
Status: In Development/Works for me
- This option adds a `ROUTE' target, which allows you to directly route
- a received packet through a specified interface or towards a host, even
- if the regular destination of the packet is the router itself.
- This target never modifies packets but allows a different routing scheme
- than the one provided by the standard kernel routing table.
-
- This target is to be used inside the mangle table, in the PREROUTING,
- POSTROUTING or FORWARD hooks.
+ This option adds a `ROUTE' target, which enables you to setup unusual
+ routes not supported by the standard kernel routing table.
+ For example, the ROUTE lets you directly route a received packet through
+ an interface or towards a host, even if the regular destination of the
+ packet is the router itself. The ROUTE target is also able to change the
+ incoming interface of a packet.
+
+ This target does never modify the packet and is a final target.
+ It has to be used inside the mangle table.
ROUTE target options:
- --iface name Send the packet directly through this interface.
- --to ip Route the packet as if its destination address was ip.
+ --oif ifname Send the packet out using `ifname' network interface.
+ --iif ifname Change the packet's incoming interface to `ifname'.
+ --gw ip Route the packet via this gateway.
Examples :
To redirect all outgoing icmp packet to the eth1 interface :
- # iptables -A POSTROUTING -t mangle -p icmp -j ROUTE --iface eth1
+ # iptables -A POSTROUTING -t mangle -p icmp -j ROUTE --oif eth1
- To tunnel all incoming http packets
- # iptables -A PREROUTING -t mangle -p tcp --dport 80 -j ROUTE --iface tunl1
+ To tunnel all incoming http packets :
+ # iptables -A PREROUTING -t mangle -p tcp --dport 80 -j ROUTE --oif tunl1
- To force the next-hop used for ssh packets
- # iptables -A PREROUTING -t mangle -p tcp --dport 22 -j ROUTE --to w.x.y.z
+ To force the next-hop used for ssh packets :
+ # iptables -A PREROUTING -t mangle -p tcp --dport 22 -j ROUTE --gw w.x.y.z
+ To change the incoming network interface from eth0 to eth1 for icmp packets :
+ # iptables -A PREROUTING -t mangle -p icmp -i eth0 -j ROUTE --iif eth1
diff -Nru netfilter.orig/userspace/extensions/libipt_ROUTE.c netfilter/userspace/extensions/libipt_ROUTE.c
--- netfilter.orig/userspace/extensions/libipt_ROUTE.c Thu Dec 5 21:44:38 2002
+++ netfilter/userspace/extensions/libipt_ROUTE.c Wed Dec 18 12:26:37 2002
@@ -20,15 +20,17 @@
{
printf(
"ROUTE target v%s options:\n"
-" --iface name Send the packet directly through this interface.\n"
-" --to ip Route the packet as if its destination address was ip.\n"
+" --oif \tifname \t\tSend the packet out using `ifname' network interface\n"
+" --iif \tifname \t\tChange the packet's incoming interface to `ifname'\n"
+" --gw \tip \t\tRoute the packet via this gateway\n"
"\n",
IPTABLES_VERSION);
}
static struct option opts[] = {
- { "iface", 1, 0, '1' },
- { "to", 1, 0, '2' },
+ { "oif", 1, 0, '1' },
+ { "iif", 1, 0, '2' },
+ { "gw", 1, 0, '3' },
{ 0 }
};
@@ -39,12 +41,14 @@
struct ipt_route_target_info *route_info =
(struct ipt_route_target_info*)t->data;
- route_info->ifname[0] = '\0';
- route_info->ipto = 0;
+ route_info->oif[0] = '\0';
+ route_info->iif[0] = '\0';
+ route_info->gw = 0;
}
-#define IPT_ROUTE_OPT_IF 0x01
-#define IPT_ROUTE_OPT_TO 0x02
+
+#define IPT_ROUTE_OPT_IF 0x01
+#define IPT_ROUTE_OPT_GW 0x02
/* Function which parses command options; returns true if it
ate an option */
@@ -60,33 +64,51 @@
case '1':
if (*flags & IPT_ROUTE_OPT_IF)
exit_error(PARAMETER_PROBLEM,
- "Can't specify --iface twice");
+ "Can't specify --oif twice or --oif with --iif");
if (check_inverse(optarg, &invert, NULL, 0))
exit_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --iface");
+ "Unexpected `!' after --oif");
- if (strlen(optarg) > sizeof(route_info->ifname) - 1)
+ if (strlen(optarg) > sizeof(route_info->oif) - 1)
exit_error(PARAMETER_PROBLEM,
"Maximum interface name length %u",
- sizeof(route_info->ifname) - 1);
+ sizeof(route_info->oif) - 1);
- strcpy(route_info->ifname, optarg);
+ strcpy(route_info->oif, optarg);
*flags |= IPT_ROUTE_OPT_IF;
break;
case '2':
- if (*flags & IPT_ROUTE_OPT_TO)
+ if (*flags & IPT_ROUTE_OPT_IF)
+ exit_error(PARAMETER_PROBLEM,
+ "Can't specify --iif twice or --iif with --oif");
+
+ if (check_inverse(optarg, &invert, NULL, 0))
+ exit_error(PARAMETER_PROBLEM,
+ "Unexpected `!' after --iif");
+
+ if (strlen(optarg) > sizeof(route_info->iif) - 1)
exit_error(PARAMETER_PROBLEM,
- "Can't specify --to twice");
+ "Maximum interface name length %u",
+ sizeof(route_info->iif) - 1);
+
+ strcpy(route_info->iif, optarg);
+ *flags |= IPT_ROUTE_OPT_IF;
+ break;
- if (!inet_aton(optarg, (struct in_addr*)&route_info->ipto)) {
+ case '3':
+ if (*flags & IPT_ROUTE_OPT_GW)
+ exit_error(PARAMETER_PROBLEM,
+ "Can't specify --gw twice");
+
+ if (!inet_aton(optarg, (struct in_addr*)&route_info->gw)) {
exit_error(PARAMETER_PROBLEM,
"Invalid IP address %s",
optarg);
}
- *flags |= IPT_ROUTE_OPT_TO;
+ *flags |= IPT_ROUTE_OPT_GW;
break;
default:
@@ -96,14 +118,16 @@
return 1;
}
+
static void
final_check(unsigned int flags)
{
if (!flags)
exit_error(PARAMETER_PROBLEM,
- "ROUTE target: minimum 1 parameter is required");
+ "ROUTE target: one parameter is required");
}
+
/* Prints out the targinfo. */
static void
print(const struct ipt_ip *ip,
@@ -115,15 +139,38 @@
printf("ROUTE ");
- if (route_info->ifname[0])
- printf("iface %s ", route_info->ifname);
+ if (route_info->oif[0])
+ printf("oif %s ", route_info->oif);
+
+ if (route_info->iif[0])
+ printf("iif %s ", route_info->iif);
- if (route_info->ipto) {
- struct in_addr ip = { route_info->ipto };
- printf("to %s ", inet_ntoa(ip));
+ if (route_info->gw) {
+ struct in_addr ip = { route_info->gw };
+ printf("gw %s ", inet_ntoa(ip));
}
}
+
+static void save(const struct ipt_ip *ip,
+ const struct ipt_entry_target *target)
+{
+ const struct ipt_route_target_info *route_info
+ = (const struct ipt_route_target_info *)target->data;
+
+ if (route_info->oif[0])
+ printf("--oif %s ", route_info->oif);
+
+ if (route_info->iif[0])
+ printf("--iif %s ", route_info->iif);
+
+ if (route_info->gw) {
+ struct in_addr ip = { route_info->gw };
+ printf("--gw %s ", inet_ntoa(ip));
+ }
+}
+
+
static
struct iptables_target route
= { NULL,
@@ -136,7 +183,7 @@
&parse,
&final_check,
&print,
- NULL, /* save */
+ &save,
opts
};
^ permalink raw reply
* FORWARD chain and local interfaces
From: Carlos Carvalho @ 2002-12-18 11:31 UTC (permalink / raw)
To: netfilter
Hi netfilter users,
I have a doubt/problem with this since kernel 2.2. Suppose you have a
box with two interfaces, for example eth0=192.168.1.0/24 and
eth1=192.168.2.0/24, and the box addresses are 192.168.1.1 and
192.168.2.1 respectively. The machine is a firewall and has ip_forward
activated. If you ping 192.168.2.1 from a machine connected to eth0,
say 192.168.1.5, you get an answer, which is normal because of the
forwarding.
Now let's block the FORWARD chain, say with iptables -P FORWARD DROP
and no rules in the chain. I'd expect to not get any answers to the
ping above, because the echo-request's are arriving on an interface
and are destined to the other, so they should go through the FORWARD
chain which is blocked. However I still get the normal echo-reply's...
This means that the kernel sees the interface is local and doesn't
route them through the FORWARD chain.
I'd like to know if this is expected or an unwanted side-effect. For
me it's annoying because I use SNAT and I don't want the internal
(192.168.2.1 in this example) visible from outside. I also find it
conceptually strange. Is there a way to avoid this without filtering
these packets at the INPUT chain?
^ permalink raw reply
* Re: how to delete a piece of rule in iptables?
From: Marcello Scacchetti @ 2002-12-18 11:18 UTC (permalink / raw)
To: bobo; +Cc: netfilter@lists.netfilter.org, bobowd@sohu.com
In-Reply-To: <200212181222.UAA02783@email.whu.edu.cn>
Hi,
you can use iptables -D or -X or -F. -D to delete a single rule, -X do
detele a chain and -F to flush all rules from a chain.
Refer to man 8 iptables for details and examples.
Marcello
Il mer, 2002-12-18 alle 13:30, bobo ha scritto:
> i have insert some rules to iptables firewall.now,i would
> like to delete it .
> but i only know to use iptalbes -L to empty them.
> but it lead to delete all the rules in it.
> how to do ??
>
--
Marcello Scacchetti <marcello.scacchetti@nextrem.it>
^ permalink raw reply
* Re: alsasound init script (Re: possible problems with rc6 aplay )
From: Takashi Iwai @ 2002-12-18 11:17 UTC (permalink / raw)
To: Fernando Pablo Lopez-Lezcano; +Cc: Mark Knecht, Paul Davis, Alsa-Devel
In-Reply-To: <s5h1y4fwqne.wl@alsa2.suse.de>
At Wed, 18 Dec 2002 11:46:45 +0100,
I wrote:
>
> > It would be better to make the alsasound script more robust (and
> > independent of the startup order) and able to deal with partially loaded
> > modules, so instead of just checking for the /proc/asound directory it
> > would actually see what modules are already loaded and only load those
> > that are not. It does not look too easy, it seems that /proc/asound does
> > not provide a list of loaded modules (rather a list of cards that are
> > not associated with module names).
>
> agreed. a scenario i can imagine now is that the script just takes a
> look at /proc/asound/cards and checks the numbers at the first column.
> this should correspond to the card indices which have been already
> loaded. then the script will try to load the modules snd-card-X but
> skip the numbers listed in the above...
> i'll try to rewrite as this way.
after reconsideration: it would be much simpler to create a new proc
file which shows the modules already loaded.
Takashi
-------------------------------------------------------
This sf.net email is sponsored by:
With Great Power, Comes Great Responsibility
Learn to use your power at OSDN's High Performance Computing Channel
http://hpc.devchannel.org/
^ permalink raw reply
* question
From: franck Jolimay @ 2002-12-18 11:14 UTC (permalink / raw)
To: linux-smp
Hello,
I send you an email because I have the following message
during my reboot on a redhat7.2 server:
WARNING: unexpected IO-APIC, please mail
Dec 17 16:12:08 L1_CRUNCH03 kernel: to linux-smp@vger.kernel.org
Can you tell me the meaning of this message and is there something to do ?
Franck Jolimay
Senior Unix Administrator
Oracle dba administrator
RealMedia
Route de la Pierre
1024 Ecublens-Lausanne
Email : fjolimay@realmedia.com
Tel : 00 41 21.69.59.743
Fax : 00 41 21.69.59.701
Web : http://www.realmedia.com
24/7 Real Media, Inc. provides marketing solutions to the digital
advertising industry. Through a suite of online marketing and technologies
services, 24/7 Real Media connects media buyers and media sellers across
multiple digital platforms and works closely with individual clients to
develop a comprehensive, customized, value-enhancing solution. The Company's
business is organized into two principal lines of business: Technology
Solutions and Integrated Media Solutions. Technology Solutions includes Open
Adstream, the Company's proprietary advertising delivery and management
suite. 24/7 Real Media also partners with other companies to offer
complementary plug-ins and modules. 24/7 Real Media connects advertisers to
high-quality audiences through its Integrated Media Solutions, which include
four products: the 24/7 Network of marquee branded Websites and niche
Websites; permission-based e-mail databases; a comprehensive promotions
suite; and a search engine results listings service.
^ permalink raw reply
* Re: [parisc-linux] problems with PCI IDE controller
From: Joerg Steindlberger @ 2002-12-17 21:04 UTC (permalink / raw)
To: parisc-linux; +Cc: Alan Cox
In-Reply-To: <1040050989.13786.23.camel@irongate.swansea.linux.org.uk>
Hi Alan! Great things happened!
I could sweare, that a few weeks ago nothing worked, neither with the nat=
ive=20
IDE drivers nor with PDC20268 options. (That kernel was 2.4.19-pa14). Now=
it=20
only doesn't work with the special IDE options for this card. Is there a=20
roadmap to fix that prolem? ;-)
Thanks to all who helped me!
Joerg
hp-c240:~# modprobe -k ide-mod
Uniform Multi-Platform E-IDE driver Revision: 6.31
ide: Assuming 33MHz system bus speed for PIO modes; override with idebus=3D=
xx
PDC20268: IDE controller on PCI bus 00 dev 08
PDC20268: chipset revision 2
PDC20268: not 100% native mode: will probe irqs later
ide0: BM-DMA at 0xfd00-0xfd07, BIOS settings: hda:pio, hdb:pio
ide1: BM-DMA at 0xfd08-0xfd0f, BIOS settings: hdc:pio, hdd:pio
hp-c240:~# modprobe -k ide-probe-mod
hdd: IBM-DTTA-351680, ATA DISK drive
ide1 at 0xfb00-0xfb07,0xfc02 on irq 97
hp-c240:~# modprobe -k ide-disk
hdd: 33022080 sectors (16907 MB) w/462KiB Cache, CHS=3D32760/16/63
/dev/ide/host0/bus1/target1/lun0: [PTBL] [2055/255/63] p1
hp-c240:~# mount /dev/ide/host0/bus1/target1/lun0/part1 /mnt/tmp
(works with and without devfs)
On Monday 16 December 2002 16:03, you wrote:
> In legacy mode the PCI BAR registers are ignored, the I/O decode is at
> 0x170 etc and interrupts are flagged by the ISA legacy not by the PCI
> bus.
> That isnt going to work very well on your average PA-RISC box. Most
> probably you want to force the chip into native mode on pa-risc
> hardware.
^ permalink raw reply
* Re: Alcatel speedtouch USB driver and SMP.
From: Oliver Neukum @ 2002-12-18 11:13 UTC (permalink / raw)
To: romieu, Colin Paul Adams; +Cc: linux-kernel
In-Reply-To: <20021217232010.A19613@electric-eye.fr.zoreil.com>
Am Dienstag, 17. Dezember 2002 23:20 schrieb romieu@fr.zoreil.com:
> Colin Paul Adams <colin@colina.demon.co.uk> :
> [...]
>
> > So, is anyone using it on SMP?
>
> drivers/usb/misc/speedtouch.c::udsl_atm_ioctl() calls put_user() and
> atm ioctls are issued with spinlock held (see
> net/atm/common.c::atm_ioctl()).
Correct. As far as that is concerned the ATM layer is utter crap.
Regards
Oliver
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.