All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [RFC/PATCH] Makefile: allow boards to check file size limits
From: Mike Frysinger @ 2010-10-20  5:16 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <AANLkTimcki1vN0Hy5tXixytNaWYQkrgKfO=i9wM4GTch@mail.gmail.com>

On Wednesday, October 20, 2010 00:38:08 Vaibhav Bedia wrote:

please do not top post

> The size of other sections like the bss section also need to be accounted
> for when doing a size check.

that really cannot be checked at compile time.  it certainly cannot be done 
easily or with a few lines of shell code.

> Insufficient space for bss when doing something like a MMC read which
> requires large buffers causes system hangs for no apparent reason.

that doesnt make much sense.  bss is statically allocated.  either it exists, 
or it doesnt.  if bss doesnt work, your system/build is fundamentally screwed.  
either way, none of this is related to my patch.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20101020/19afb5c9/attachment.pgp 

^ permalink raw reply

* Re: [PATCH 2/2]x86: spread tlb flush vector between nodes
From: Eric Dumazet @ 2010-10-20  5:16 UTC (permalink / raw)
  To: Shaohua Li; +Cc: lkml, Ingo Molnar, hpa@zytor.com, Andi Kleen, Chen, Tim C
In-Reply-To: <1287544023.4571.8.camel@sli10-conroe.sh.intel.com>

Le mercredi 20 octobre 2010 à 11:07 +0800, Shaohua Li a écrit :
> Currently flush tlb vector allocation is based on below equation:
> 	sender = smp_processor_id() % 8
> This isn't optimal, CPUs from different node can have the same vector, this
> causes a lot of lock contention. Instead, we can assign the same vectors to
> CPUs from the same node, while different node has different vectors. This has
> below advantages:
> a. if there is lock contention, the lock contention is between CPUs from one
> node. This should be much cheaper than the contention between nodes.
> b. completely avoid lock contention between nodes. This especially benefits
> kswapd, which is the biggest user of tlb flush, since kswapd sets its affinity
> to specific node.
> 
> In my test, this could reduce > 20% CPU overhead in extreme case.The test
> machine has 4 nodes and each node has 16 CPUs. I then bind each node's kswapd
> to the first CPU of the node. I run a workload with 4 sequential mmap file
> read thread. The files are empty sparse file. This workload will trigger a
> lot of page reclaim and tlbflush. The kswapd bind is to easy trigger the
> extreme tlb flush lock contention because otherwise kswapd keeps migrating
> between CPUs of a node and I can't get stable result. Sure in real workload,
> we can't always see so big tlb flush lock contention, but it's possible.
> 
> Signed-off-by: Shaohua Li <shaohua.li@intel.com>
> ---
>  arch/x86/mm/tlb.c |   48 +++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 47 insertions(+), 1 deletion(-)
> 
> Index: linux/arch/x86/mm/tlb.c
> ===================================================================
> --- linux.orig/arch/x86/mm/tlb.c	2010-10-20 10:07:53.000000000 +0800
> +++ linux/arch/x86/mm/tlb.c	2010-10-20 10:09:26.000000000 +0800
> @@ -5,6 +5,7 @@
>  #include <linux/smp.h>
>  #include <linux/interrupt.h>
>  #include <linux/module.h>
> +#include <linux/cpu.h>
>  
>  #include <asm/tlbflush.h>
>  #include <asm/mmu_context.h>
> @@ -52,6 +53,8 @@ union smp_flush_state {
>     want false sharing in the per cpu data segment. */
>  static union smp_flush_state flush_state[NUM_INVALIDATE_TLB_VECTORS];
>  
> +static DEFINE_PER_CPU_READ_MOSTLY(int, tlb_vector_offset);
> +
>  /*
>   * We cannot call mmdrop() because we are in interrupt context,
>   * instead update mm->cpu_vm_mask.
> @@ -173,7 +176,7 @@ static void flush_tlb_others_ipi(const s
>  	union smp_flush_state *f;
>  
>  	/* Caller has disabled preemption */
> -	sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
> +	sender = per_cpu(tlb_vector_offset, smp_processor_id());

	sender = this_cpu_read(tlb_vector_offset);

>  	f = &flush_state[sender];
>  
>  	/*
> @@ -218,6 +221,47 @@ void native_flush_tlb_others(const struc
>  	flush_tlb_others_ipi(cpumask, mm, va);
>  }
>  


Thats a pretty good patch, thanks !

Maybe we should have a per_node memory infrastructure, so that we can
lower memory needs of currently per_cpu objects.




^ permalink raw reply

* [PATCH] msix: fix irqchip breakage
From: Michael S. Tsirkin @ 2010-10-20  5:09 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

msix.c doesn't include linux kvm header anymore, so
IRQCHIP macro is never defined, which resulted in
a broken msix support. As a fix, stub out kvm_set_irq
and remove the remaining ifdefs.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/msix.c  |    2 --
 kvm-stub.c |    6 ++++++
 kvm.h      |    2 ++
 qemu-kvm.h |    1 -
 4 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/hw/msix.c b/hw/msix.c
index f12e4aa..4b6133d 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -509,12 +509,10 @@ void msix_notify(PCIDevice *dev, unsigned vector)
         return;
     }
 
-#ifdef KVM_CAP_IRQCHIP
     if (kvm_enabled() && kvm_irqchip_in_kernel()) {
         kvm_set_irq(dev->msix_irq_entries[vector].gsi, 1, NULL);
         return;
     }
-#endif
 
     address = pci_get_long(table_entry + MSIX_MSG_UPPER_ADDR);
     address = (address << 32) | pci_get_long(table_entry + MSIX_MSG_ADDR);
diff --git a/kvm-stub.c b/kvm-stub.c
index 3c2deec..aeee3c0 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -176,3 +176,9 @@ int kvm_commit_irq_routes(void)
 {
     return -ENOSYS;
 }
+
+int kvm_set_irq(int irq, int level, int *status)
+{
+    assert(0);
+    return -ENOSYS;
+}
diff --git a/kvm.h b/kvm.h
index d484a3f..74dfa48 100644
--- a/kvm.h
+++ b/kvm.h
@@ -214,4 +214,6 @@ int kvm_commit_irq_routes(void);
 
 int kvm_irqchip_in_kernel(void);
 
+int kvm_set_irq(int irq, int level, int *status);
+
 #endif
diff --git a/qemu-kvm.h b/qemu-kvm.h
index 9c08ab4..c6f5632 100644
--- a/qemu-kvm.h
+++ b/qemu-kvm.h
@@ -785,7 +785,6 @@ void kvm_load_lapic(CPUState *env);
 
 void kvm_hpet_enable_kpit(void);
 void kvm_hpet_disable_kpit(void);
-int kvm_set_irq(int irq, int level, int *status);
 
 int kvm_physical_memory_set_dirty_tracking(int enable);
 
-- 
1.7.3-rc1

^ permalink raw reply related

* + kfifo-disable-__kfifo_must_check_helper.patch added to -mm tree
From: akpm @ 2010-10-20  5:14 UTC (permalink / raw)
  To: mm-commits; +Cc: akpm, randy.dunlap, stefani


The patch titled
     kfifo: disable __kfifo_must_check_helper()
has been added to the -mm tree.  Its filename is
     kfifo-disable-__kfifo_must_check_helper.patch

Before you just go and hit "reply", please:
   a) Consider who else should be cc'ed
   b) Prefer to cc a suitable mailing list as well
   c) Ideally: find the original patch on the mailing list and do a
      reply-to-all to that, adding suitable additional cc's

*** Remember to use Documentation/SubmitChecklist when testing your code ***

See http://userweb.kernel.org/~akpm/stuff/added-to-mm.txt to find
out what to do about this

The current -mm tree may be found at http://userweb.kernel.org/~akpm/mmotm/

------------------------------------------------------
Subject: kfifo: disable __kfifo_must_check_helper()
From: Andrew Morton <akpm@linux-foundation.org>

This helper is wrong: it coerces signed values into unsigned ones, so code
such as

	if (kfifo_alloc(...) < 0) {
		error
	}

will fail to detect the error.

So let's disable __kfifo_must_check_helper() for 2.6.37.

Cc: Randy Dunlap <randy.dunlap@oracle.com>
Cc: Stefani Seibold <stefani@seibold.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 include/linux/kfifo.h |    6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff -puN include/linux/kfifo.h~kfifo-disable-__kfifo_must_check_helper include/linux/kfifo.h
--- a/include/linux/kfifo.h~kfifo-disable-__kfifo_must_check_helper
+++ a/include/linux/kfifo.h
@@ -171,11 +171,7 @@ struct kfifo_rec_ptr_2 __STRUCT_KFIFO_PT
 	}
 
 
-static inline unsigned int __must_check
-__kfifo_must_check_helper(unsigned int val)
-{
-	return val;
-}
+#define __kfifo_must_check_helper(x) (x)
 
 /**
  * kfifo_initialized - Check if the fifo is initialized
_

Patches currently in -mm which might be from akpm@linux-foundation.org are

origin.patch
typesh-move-misplaced-comment.patch
kfifo-disable-__kfifo_must_check_helper.patch
linux-next.patch
next-remove-localversion.patch
fs-inodec-work-around-bug.patch
arch-x86-kernel-entry_64s-fix-build-with-gas-2161.patch
arch-x86-kernel-entry_32s-i386-too.patch
i-need-old-gcc.patch
arch-alpha-kernel-systblss-remove-debug-check.patch
mm-vmap-area-cache.patch
arch-mips-include-asm-fcntlh-needs-typesh.patch
gcc-46-btrfs-clean-up-unused-variables-bugs.patch
drivers-gpu-drm-radeon-atomc-fix-warning.patch
fs-notify-fanotify-fanotify_userc-fix-warnings.patch
leds-route-kbd-leds-through-the-generic-leds-layer.patch
leds-add-led-trigger-for-input-subsystem-led-events-checkpatch-fixes.patch
backlight-add-low-threshold-to-pwm-backlight.patch
serial8250-ratelimit-too-much-work-error-fix.patch
serial8250-ratelimit-too-much-work-error-fix-fix.patch
sched-make-sched_param-argument-static-variables-in-some-sched_setscheduler-caller.patch
drivers-message-fusion-mptsasc-fix-warning.patch
drivers-block-aoe-aoeblkc-ratelimit-a-warning-printk.patch
vfs-allow-mnt_want_write-to-sleep-fix.patch
mm.patch
oom-kill-all-threads-sharing-oom-killed-tasks-mm-fix.patch
oom-kill-all-threads-sharing-oom-killed-tasks-mm-fix-fix.patch
oom-rewrite-error-handling-for-oom_adj-and-oom_score_adj-tunables.patch
oom-fix-locking-for-oom_adj-and-oom_score_adj.patch
mm-only-build-per-node-scan_unevictable-functions-when-numa-is-enabled-cleanup.patch
memory-hotplug-unify-is_removable-and-offline-detection-code-checkpatch-fixes.patch
mm-stack-based-kmap_atomic-checkpatch-fixes.patch
mm-stack-based-kmap_atomic-fix.patch
mm-retry-page-fault-when-blocking-on-disk-transfer.patch
mm-retry-page-fault-when-blocking-on-disk-transfer-update-fix.patch
rmap-make-anon_vma_free-static-fix.patch
vmstat-include-compactionh-when-config_compaction-fix.patch
fs-fs-writebackc-restore-lost-comment.patch
mm-memory_hotplugc-make-scan_lru_pages-static.patch
proc-swaps-support-polling-fix.patch
frv-duplicate-output_buffer-of-e03-checkpatch-fixes.patch
hpet-factor-timer-allocate-from-open.patch
hpet-factor-timer-allocate-from-open-fix.patch
kernelh-add-minmax3-macros-fix.patch
include-linux-kernelh-add-__must_check-to-strict_strto.patch
printk-declare-printk_ratelimit_state-in-ratelimith-fix.patch
vsprintfc-use-default-pointer-field-size-for-null-strings-fix.patch
scripts-get_maintainerpl-add-git-blame-rolestats-authored-lines-information.patch
idr-fix-idr_pre_get-locking-description-fix.patch
checkpatch-returning-errno-typically-should-be-negative.patch
select-rename-estimate_accuracy-to-select_estimate_accuracy.patch
vcs-add-poll-fasync-support-fix-fix.patch
rtc-rtc-s3c-fix-access-unit-from-byte-to-word-on-rtccon-checkpatch-fixes.patch
gpio-add-support-for-74x164-serial-in-parallel-out-8-bit-shift-register-fix.patch
cgroup_freezer-update_freezer_state-does-incorrect-state-transitions-checkpatch-fixes.patch
memcg-cpu-hotplug-aware-quick-acount_move-detection-checkpatch-fixes.patch
core_pattern-fix-long-parameters-was-truncated-by-core_pattern-handler-update.patch
core_pattern-fix-long-parameters-was-truncated-by-core_pattern-handler-update-2.patch
core_pattern-fix-long-parameters-was-truncated-by-core_pattern-handler-update-2-checkpatch-fixes.patch
drivers-char-hvc_consolec-remove-unneeded-__set_current_statetask_running.patch
delay-accounting-re-implement-c-for-getdelaysc-to-report-information-on-a-target-command-checkpatch-fixes.patch
fuse-use-release_pages.patch
pps-add-async-pps-event-handler-fix.patch
memstick-add-driver-for-ricoh-r5c592-card-reader-fix.patch
kernel-resourcec-handle-reinsertion-of-an-already-inserted-resource.patch
ramoops-use-the-platform-data-structure-instead-of-module-params-fix.patch
journal_add_journal_head-debug.patch
slab-leaks3-default-y.patch
put_bh-debug.patch
getblk-handle-2tb-devices.patch
memblock-add-input-size-checking-to-memblock_find_region.patch
memblock-add-input-size-checking-to-memblock_find_region-fix.patch


^ permalink raw reply

* RE: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common to elbc devices
From: Zang Roy-R61911 @ 2010-10-20  5:12 UTC (permalink / raw)
  To: Kumar Gala
  Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
	linux-mtd, akpm, dwmw2, Gala Kumar-B11780
In-Reply-To: <2D2A6B88-DA17-467D-BB43-919C1CAAB894@kernel.crashing.org>



> -----Original Message-----
> From: Kumar Gala [mailto:galak@kernel.crashing.org]
> Sent: Tuesday, October 19, 2010 21:19 PM
> To: Zang Roy-R61911
> Cc: linux-mtd@lists.infradead.org; Wood Scott-B07421;
dedekind1@gmail.com; Lan
> Chunhe-B25806; linuxppc-dev@ozlabs.org; akpm@linux-foundation.org;
> dwmw2@infradead.org; Gala Kumar-B11780
> Subject: Re: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt
common to
> elbc devices
>=20
>=20
> On Oct 18, 2010, at 2:22 AM, Roy Zang wrote:
>=20
> > Move Freescale elbc interrupt from nand dirver to elbc driver.
> > Then all elbc devices can use the interrupt instead of ONLY nand.
> >
> > For former nand driver, it had the two functions:
> >
> > 1. detecting nand flash partitions;
> > 2. registering elbc interrupt.
> >
> > Now, second function is removed to fsl_lbc.c.
> >
> > Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
> > Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
> > Reviewed-by: Anton Vorontsov <cbouatmailru@gmail.com>
> > Cc: Wood Scott-B07421 <B07421@freescale.com>
> > ---
>=20
> Roy, this is a nit, but are these really p4080 specific?  just
wondering why
> the subject is P4080/eLBC:...
We start these code in P4080 project. Some customer want to track eLBC
error on P4080, but some of the code is limited in nand driver only ...
That is why P4080/eLBC ...
Roy

^ permalink raw reply

* RE: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common to elbc devices
From: Zang Roy-R61911 @ 2010-10-20  5:12 UTC (permalink / raw)
  To: Kumar Gala
  Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
	linux-mtd, akpm, dwmw2, Gala Kumar-B11780
In-Reply-To: <2D2A6B88-DA17-467D-BB43-919C1CAAB894@kernel.crashing.org>



> -----Original Message-----
> From: Kumar Gala [mailto:galak@kernel.crashing.org]
> Sent: Tuesday, October 19, 2010 21:19 PM
> To: Zang Roy-R61911
> Cc: linux-mtd@lists.infradead.org; Wood Scott-B07421;
dedekind1@gmail.com; Lan
> Chunhe-B25806; linuxppc-dev@ozlabs.org; akpm@linux-foundation.org;
> dwmw2@infradead.org; Gala Kumar-B11780
> Subject: Re: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt
common to
> elbc devices
> 
> 
> On Oct 18, 2010, at 2:22 AM, Roy Zang wrote:
> 
> > Move Freescale elbc interrupt from nand dirver to elbc driver.
> > Then all elbc devices can use the interrupt instead of ONLY nand.
> >
> > For former nand driver, it had the two functions:
> >
> > 1. detecting nand flash partitions;
> > 2. registering elbc interrupt.
> >
> > Now, second function is removed to fsl_lbc.c.
> >
> > Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
> > Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
> > Reviewed-by: Anton Vorontsov <cbouatmailru@gmail.com>
> > Cc: Wood Scott-B07421 <B07421@freescale.com>
> > ---
> 
> Roy, this is a nit, but are these really p4080 specific?  just
wondering why
> the subject is P4080/eLBC:...
We start these code in P4080 project. Some customer want to track eLBC
error on P4080, but some of the code is limited in nand driver only ...
That is why P4080/eLBC ...
Roy

^ permalink raw reply

* Re: kfifo must_check warning
From: Andrew Morton @ 2010-10-20  5:12 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: lkml, Stefani Seibold
In-Reply-To: <20101019151048.ae79bb25.randy.dunlap@oracle.com>

On Tue, 19 Oct 2010 15:10:48 -0700 Randy Dunlap <randy.dunlap@oracle.com> wrote:

> In 2.6.36-rc8, I see this build warning:
> 
> drivers/char/n_gsm.c: In function 'gsm_dlci_alloc':
> drivers/char/n_gsm.c:1580: warning: ignoring return value of '__kfifo_must_check_helper', declared with attribute warn_unused_result
> 
> The helper seems to be getting in the way (?).  The driver code does this:
> 
> 	if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL) < 0) {
> 		kfree(dlci);
> 		return NULL;
> 	}
> 
> Should the driver code be doing something else?
> or should the kfifo_alloc() macro be checking the result of the helper?
> 

A gcc bug, I'd say.  The code looks OK and my gcc doesn't warn.

Perhaps see if you can find some code transformation in n_gsm.c which
makes it go away?  Add a new local variable or something.


I did see a probably unrelated bug in there though. 
__kfifo_must_check_helper() coerces its arg into an `unsigned int' and
returns an unsigned int.  Consequently if kfifo_alloc() tries to return
-EINVAL, the above-quoted code won't detect the error: it will see
-EINVAL as a large, positive unsigned value.

I don't see a simple fix for that apart from creating several flavours
of __kfifo_must_check_helper() and carefully going through each
instance and using the one which takes (and returns) the correct type.

A suitable temporary 2.6.37 patch would bee to just disable
__kfifo_must_check_helper():

--- a/include/linux/kfifo.h~a
+++ a/include/linux/kfifo.h
@@ -171,11 +171,7 @@ struct kfifo_rec_ptr_2 __STRUCT_KFIFO_PT
 	}
 
 
-static inline unsigned int __must_check
-__kfifo_must_check_helper(unsigned int val)
-{
-	return val;
-}
+#define __kfifo_must_check_helper(x) (x)
 
 /**
  * kfifo_initialized - Check if the fifo is initialized
_


^ permalink raw reply

* linux-next: build failure after merge of the final tree (security-testing tree related)
From: Stephen Rothwell @ 2010-10-20  5:10 UTC (permalink / raw)
  To: James Morris; +Cc: linux-next, linux-kernel, Eric Paris

Hi James,

After merging the final tree, today's linux-next build (powerpc
allyesconfig) failed like this:

security/selinux/ss/services.c: In function 'security_read_policy':
security/selinux/ss/services.c:3172: error: implicit declaration of function 'vmalloc_user'
security/selinux/ss/services.c:3172: warning: assignment makes pointer from integer without a cast

Caused by commit ed167abda544bb7f8cf09dc3d3608c79e1cfb25f ("SELinux:
allow userspace to read policy back out of the kernel") and
bb17427490e1e295f3c0550c308684bd952a585d ("selinux: implement mmap
on /selinux/policy").

Please see Rule 1 (in Documentation/SubmitChecklist).

I applied the following patch for today:

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Wed, 20 Oct 2010 16:08:00 +1100
Subject: [PATCH] selinux: include vmalloc.h for vmalloc_user

---
 security/selinux/ss/services.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 3a1739b..223c1ff 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -51,6 +51,7 @@
 #include <linux/mutex.h>
 #include <linux/selinux.h>
 #include <linux/flex_array.h>
+#include <linux/vmalloc.h>
 #include <net/netlabel.h>
 
 #include "flask.h"
-- 
1.7.1

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

^ permalink raw reply related

* Re: [PATCH] net: make ctl_path local and const
From: Changli Gao @ 2010-10-20  5:10 UTC (permalink / raw)
  To: Joe Perches
  Cc: Andy Grover, linux-sctp, rds-devel, Pekka Savola (ipv6),
	linux-x25, dccp, bridge, James Morris, coreteam,
	Arnaldo Carvalho de Melo, Alexey Kuznetsov, Joerg Reuter,
	Sridhar Samudrala, Samuel Ortiz, Vlad Yasevich, netfilter,
	Remi Denis-Courmont, linux-hams, Hideaki YOSHIFUJI, netdev,
	linux-decnet-user, linux-kernel, Ralf Baechle <ralf
In-Reply-To: <1287550779.10409.620.camel@Joe-Laptop>

On Wed, Oct 20, 2010 at 12:59 PM, Joe Perches <joe@perches.com> wrote:
>
> Not using static requires the compiler to emit
> initialization code for any use of the routine
> that otherwise would only be done once.
>

If the code isn't performance critical, I think we can afford.
Otherwise, we have to reserve the memory used to save the static data,
if we don't specify it as initial data.

-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

^ permalink raw reply

* Re: [PATCH] net: make ctl_path local and const
From: Changli Gao @ 2010-10-20  5:10 UTC (permalink / raw)
  To: Joe Perches
  Cc: Andy Grover, linux-sctp, rds-devel, Pekka Savola (ipv6),
	linux-x25, dccp, bridge, James Morris, coreteam,
	Arnaldo Carvalho de Melo, Alexey Kuznetsov, Joerg Reuter,
	Sridhar Samudrala, Samuel Ortiz, Vlad Yasevich, netfilter,
	Remi Denis-Courmont, linux-hams, Hideaki YOSHIFUJI, netdev,
	linux-decnet-user, linux-kernel, Ralf Baechle <ralf>
In-Reply-To: <1287550779.10409.620.camel@Joe-Laptop>

On Wed, Oct 20, 2010 at 12:59 PM, Joe Perches <joe@perches.com> wrote:
>
> Not using static requires the compiler to emit
> initialization code for any use of the routine
> that otherwise would only be done once.
>

If the code isn't performance critical, I think we can afford.
Otherwise, we have to reserve the memory used to save the static data,
if we don't specify it as initial data.

-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

^ permalink raw reply

* Re: [Bridge] [PATCH] net: make ctl_path local and const
From: Changli Gao @ 2010-10-20  5:10 UTC (permalink / raw)
  To: Joe Perches
  Cc: Andy Grover, linux-sctp, rds-devel, Pekka Savola (ipv6),
	linux-x25, dccp, bridge, James Morris, coreteam,
	Arnaldo Carvalho de Melo, Alexey Kuznetsov, Joerg Reuter,
	Sridhar Samudrala, Samuel Ortiz, Vlad Yasevich, netfilter,
	Remi Denis-Courmont, linux-hams, Hideaki YOSHIFUJI, netdev,
	linux-decnet-user, linux-kernel, Ralf Baechle, David S. Miller,
	netfilter-devel, Andrew Hendry
In-Reply-To: <1287550779.10409.620.camel@Joe-Laptop>

On Wed, Oct 20, 2010 at 12:59 PM, Joe Perches <joe@perches.com> wrote:
>
> Not using static requires the compiler to emit
> initialization code for any use of the routine
> that otherwise would only be done once.
>

If the code isn't performance critical, I think we can afford.
Otherwise, we have to reserve the memory used to save the static data,
if we don't specify it as initial data.

-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

^ permalink raw reply

* [PATCH v2][memcg+dirtylimit] Fix  overwriting global vm dirty limit setting by memcg (Re: [PATCH v3 00/11] memcg: per cgroup dirty page accounting
From: KAMEZAWA Hiroyuki @ 2010-10-20  5:02 UTC (permalink / raw)
  To: KAMEZAWA Hiroyuki
  Cc: Greg Thelen, Andrew Morton, linux-kernel, linux-mm, containers,
	Andrea Righi, Balbir Singh, Daisuke Nishimura, Minchan Kim,
	Ciju Rajan K, David Rientjes
In-Reply-To: <20101020122144.47f2b60b.kamezawa.hiroyu@jp.fujitsu.com>

Fixed one here.
==
From: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>

Now, at calculating dirty limit, vm_dirty_param() is called.
This function returns dirty-limit related parameters considering
memory cgroup settings.

Now, assume that vm_dirty_bytes=100M (global dirty limit) and
memory cgroup has 1G of pages and 40 dirty_ratio, dirtyable memory is
500MB.

In this case, global_dirty_limits will consider dirty_limt as
500 *0.4 = 200MB. This is bad...memory cgroup is not back door.

This patch limits the return value of vm_dirty_param() considring
global settings.

Changelog:
 - fixed an argument "mem" int to u64
 - fixed to use global available memory to cap memcg's value.

Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
---
 include/linux/memcontrol.h |    5 +++--
 mm/memcontrol.c            |   30 +++++++++++++++++++++++++++++-
 mm/page-writeback.c        |    3 ++-
 3 files changed, 34 insertions(+), 4 deletions(-)

Index: dirty_limit_new/mm/memcontrol.c
===================================================================
--- dirty_limit_new.orig/mm/memcontrol.c
+++ dirty_limit_new/mm/memcontrol.c
@@ -1171,9 +1171,11 @@ static void __mem_cgroup_dirty_param(str
  * can be moved after our access and writeback tends to take long time.  At
  * least, "memcg" will not be freed while holding rcu_read_lock().
  */
-void vm_dirty_param(struct vm_dirty_param *param)
+void vm_dirty_param(struct vm_dirty_param *param,
+	 u64 mem, u64 global)
 {
 	struct mem_cgroup *memcg;
+	u64 limit, bglimit;
 
 	if (mem_cgroup_disabled()) {
 		global_vm_dirty_param(param);
@@ -1183,6 +1185,32 @@ void vm_dirty_param(struct vm_dirty_para
 	rcu_read_lock();
 	memcg = mem_cgroup_from_task(current);
 	__mem_cgroup_dirty_param(param, memcg);
+	/*
+	 * A limitation under memory cgroup is under global vm, too.
+	 */
+	if (vm_dirty_ratio)
+		limit = global * vm_dirty_ratio / 100;
+	else
+		limit = vm_dirty_bytes;
+	if (param->dirty_ratio) {
+		param->dirty_bytes = mem * param->dirty_ratio / 100;
+		param->dirty_ratio = 0;
+	}
+	if (param->dirty_bytes > limit)
+		param->dirty_bytes = limit;
+
+	if (dirty_background_ratio)
+		bglimit = global * dirty_background_ratio / 100;
+	else
+		bglimit = dirty_background_bytes;
+
+	if (param->dirty_background_ratio) {
+		param->dirty_background_bytes =
+			mem * param->dirty_background_ratio / 100;
+		param->dirty_background_ratio = 0;
+	}
+	if (param->dirty_background_bytes > bglimit)
+		param->dirty_background_bytes = bglimit;
 	rcu_read_unlock();
 }
 
Index: dirty_limit_new/include/linux/memcontrol.h
===================================================================
--- dirty_limit_new.orig/include/linux/memcontrol.h
+++ dirty_limit_new/include/linux/memcontrol.h
@@ -171,7 +171,7 @@ static inline void mem_cgroup_dec_page_s
 }
 
 bool mem_cgroup_has_dirty_limit(void);
-void vm_dirty_param(struct vm_dirty_param *param);
+void vm_dirty_param(struct vm_dirty_param *param, u64 mem, u64 global);
 s64 mem_cgroup_page_stat(enum mem_cgroup_nr_pages_item item);
 
 unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
@@ -360,7 +360,8 @@ static inline bool mem_cgroup_has_dirty_
 	return false;
 }
 
-static inline void vm_dirty_param(struct vm_dirty_param *param)
+static inline void vm_dirty_param(struct vm_dirty_param *param,
+		u64 mem, u64 global)
 {
 	global_vm_dirty_param(param);
 }
Index: dirty_limit_new/mm/page-writeback.c
===================================================================
--- dirty_limit_new.orig/mm/page-writeback.c
+++ dirty_limit_new/mm/page-writeback.c
@@ -466,7 +466,8 @@ void global_dirty_limits(unsigned long *
 	struct task_struct *tsk;
 	struct vm_dirty_param dirty_param;
 
-	vm_dirty_param(&dirty_param);
+	vm_dirty_param(&dirty_param,
+		available_memory, global_dirtyable_memory());
 
 	if (dirty_param.dirty_bytes)
 		dirty = DIV_ROUND_UP(dirty_param.dirty_bytes, PAGE_SIZE);


^ permalink raw reply

* net{space,xbig} TCLK determination
From: Lennert Buytenhek @ 2010-10-20  5:08 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

The net{space,xbig} board support files have this:

	static void netspace_v2_timer_init(void)
	{
		kirkwood_tclk = 166666667;
		orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
	}

This is a pretty ugly hack -- if kirkwood_find_tclk() is not
determining the right TCLK on these boards, then that would be the
real bug, and it should be fixed there, and not by putting hacks
like these in board support files.


thanks,
Lennert

^ permalink raw reply

* [PATCH 1/2] MIPS: fix/enrich 34K APRP (APSP) functionalities
From: Deng-Cheng Zhu @ 2010-10-20  5:10 UTC (permalink / raw)
  To: linux-mips, ralf, kevink; +Cc: eyal, dengcheng.zhu
In-Reply-To: <1287551431-15737-1-git-send-email-dengcheng.zhu@gmail.com>

This patch makes 34K APRP (also known as APSP) works. Also, it allows the
RP side to run floating point heavy jobs and uses interrupt to wake up RP
side read. These functionalities need proper RP code to work correctly.

For a 34Kf core, currently we simply disable the FPU on the AP side. And RP
will init it and use it exclusively.

Sample programs were created and tests had been done sucessfully.

Signed-off-by: Deng-Cheng Zhu <dengcheng.zhu@gmail.com>
---
 arch/mips/Kconfig                                  |    8 +++++
 .../include/asm/mach-malta/cpu-feature-overrides.h |    3 ++
 arch/mips/kernel/rtlx.c                            |   34 +++++++++++++++++---
 arch/mips/kernel/vpe.c                             |    4 +-
 arch/mips/mti-malta/malta-int.c                    |   22 ++++++++++++-
 5 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index fbaf08e..c73a07d 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1756,6 +1756,14 @@ config MIPS_VPE_LOADER_TOM
 	  you to ensure the amount you put in the option and the space your
 	  program requires is less or equal to the amount physically present.
 
+config MIPS_SP_FP_INTENSIVE
+	bool "SP is used for running FP-intensive jobs"
+	depends on MIPS_VPE_LOADER
+	help
+	  If you intend to use the SP to run FP-intensive jobs, you probably
+	  want to say yes here. Your FPU will then be exclusively used by the
+	  SP, and the Linux on the AP side will not see the FPU.
+
 # this should possibly be in drivers/char, but it is rather cpu related. Hmmm
 config MIPS_VPE_APSP_API
 	bool "Enable support for AP/SP API (RTLX)"
diff --git a/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h b/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h
index 2848cea..26cc064 100644
--- a/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h
@@ -17,6 +17,9 @@
 #define cpu_has_tlb		1
 #define cpu_has_4kex		1
 #define cpu_has_4k_cache	1
+#ifdef CONFIG_MIPS_SP_FP_INTENSIVE
+#define cpu_has_fpu		0
+#endif
 /* #define cpu_has_fpu		? */
 /* #define cpu_has_32fpr	? */
 #define cpu_has_counter		1
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 26f9b9a..1c2e156 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2005, 2010 MIPS Technologies, Inc.  All rights reserved.
  * Copyright (C) 2005, 06 Ralf Baechle (ralf@linux-mips.org)
  *
  *  This program is free software; you can distribute it and/or modify it
@@ -56,12 +56,15 @@ static struct chan_waitqueues {
 
 static struct vpe_notifications notify;
 static int sp_stopping;
+static void (*save_aprp_dispatch)(void);
 
 extern void *vpe_get_shared(int index);
+extern void (*aprp_dispatch)(void);
 
 static void rtlx_dispatch(void)
 {
-	do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ);
+	if (read_c0_cause() & read_c0_status() & C_SW0)
+		do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ);
 }
 
 
@@ -345,6 +348,18 @@ out:
 	return count;
 }
 
+static void _interrupt_sp(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	dvpe();
+	settc(1);
+	write_vpe_c0_cause(read_vpe_c0_cause() | C_SW0);
+	evpe(EVPE_ENABLE);
+	local_irq_restore(flags);
+}
+
 ssize_t rtlx_write(int index, const void __user *buffer, size_t count)
 {
 	struct rtlx_channel *rt;
@@ -385,6 +400,8 @@ out:
 	smp_wmb();
 	mutex_unlock(&channel_wqs[index].mutex);
 
+	_interrupt_sp();
+
 	return count;
 }
 
@@ -526,9 +543,15 @@ static int __init rtlx_module_init(void)
 	notify.stop = stopping;
 	vpe_notify(tclimit, &notify);
 
-	if (cpu_has_vint)
-		set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch);
-	else {
+	if (cpu_has_vint) {
+		/*
+		 * set_vi_handler() doesn't work in some cases: When sw0
+		 * gets set, a hw interrupt is signaled as well. Here we
+		 * are hooking it into platform specific dispatch.
+		 */
+		save_aprp_dispatch = aprp_dispatch;
+		aprp_dispatch = rtlx_dispatch;
+	} else {
 		pr_err("APRP RTLX init on non-vectored-interrupt processor\n");
 		err = -ENODEV;
 		goto out_chrdev;
@@ -554,6 +577,7 @@ static void __exit rtlx_module_exit(void)
 		device_destroy(mt_class, MKDEV(major, i));
 
 	unregister_chrdev(major, module_name);
+	aprp_dispatch = save_aprp_dispatch;
 }
 
 module_init(rtlx_module_init);
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 2bd2151..d0e757a 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2004, 2005, 2010 MIPS Technologies, Inc.  All rights reserved.
  *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
@@ -192,7 +192,7 @@ static struct tc *get_tc(int index)
 	}
 	spin_unlock(&vpecontrol.tc_list_lock);
 
-	return NULL;
+	return res;
 }
 
 /* allocate a vpe and associate it with this minor (or index) */
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index b79b24a..0fec7b2 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -1,6 +1,6 @@
 /*
  * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
+ * Copyright (C) 2000, 2001, 2004, 2010 MIPS Technologies, Inc.
  * Copyright (C) 2001 Ralf Baechle
  *
  *  This program is free software; you can distribute it and/or modify it
@@ -30,6 +30,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/kernel.h>
 #include <linux/random.h>
+#include <linux/module.h>
 
 #include <asm/traps.h>
 #include <asm/i8259.h>
@@ -117,6 +118,16 @@ static inline int get_int(void)
 	return irq;
 }
 
+#ifdef CONFIG_MIPS_VPE_APSP_API
+static void null_aprp_dispatch(void)
+{
+}
+
+void (*aprp_dispatch)(void) = null_aprp_dispatch;
+
+EXPORT_SYMBOL(aprp_dispatch);
+#endif
+
 static void malta_hw0_irqdispatch(void)
 {
 	int irq;
@@ -128,6 +139,15 @@ static void malta_hw0_irqdispatch(void)
 	}
 
 	do_IRQ(MALTA_INT_BASE + irq);
+
+#ifdef CONFIG_MIPS_VPE_APSP_API
+	/*
+	 * When sw0 gets set, a spurious hw interrupt is signaled as well.
+	 * The sw0 will not be handled until the hw interrupt is cleared.
+	 * We use the hook to handle sw0 and the hw interrupt gets cleared.
+	 */
+	aprp_dispatch();
+#endif
 }
 
 static void malta_ipi_irqdispatch(void)
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH 2/2] MIPS: enable CPS multicore APRP (APSP)
From: Deng-Cheng Zhu @ 2010-10-20  5:10 UTC (permalink / raw)
  To: linux-mips, ralf, kevink; +Cc: eyal, dengcheng.zhu
In-Reply-To: <1287551431-15737-1-git-send-email-dengcheng.zhu@gmail.com>

Now CPS such as 1004K can run programs in APRP (APSP) model. For example, a
3 core 1004K CPU can run SMVP Linux on the first 2 cores and leave a VPE of
the 3rd core to run RTOS or signal processing program. The kernel command
line option "maxcpus=" needs to be appointed.

Basically I think the way we are doing with rtlx/kspd/vpe_loader can be
extended to other architectures, despite of the low-level register details.

To handle the AP/RP communication interrupt, we hook our ISR into the ipi
resched interrupt.

Known issue: When we define CONFIG_MIPS_CMP to let 1004K run SMVP Linux and
RP program, currently we can only load the RP program 1 time. Loading it
multiple times won't affect the kernel, but only the 1st time works as
expected. This is not a top priority issue I suppose, since normally we
build RP programs to keep alive as kind of server programs -- They wait
for requests in the CPU "wait" mode.

Signed-off-by: Deng-Cheng Zhu <dengcheng.zhu@gmail.com>
---
 arch/mips/include/asm/rtlx.h    |    3 +
 arch/mips/kernel/kspd.c         |   26 ++++-
 arch/mips/kernel/rtlx.c         |  129 +++++++++++++++++++++---
 arch/mips/kernel/vpe.c          |  213 ++++++++++++++++++++++++++++++++++++++-
 arch/mips/mti-malta/malta-int.c |   14 ++-
 5 files changed, 356 insertions(+), 29 deletions(-)

diff --git a/arch/mips/include/asm/rtlx.h b/arch/mips/include/asm/rtlx.h
index 4ca3063..adddffe 100644
--- a/arch/mips/include/asm/rtlx.h
+++ b/arch/mips/include/asm/rtlx.h
@@ -58,6 +58,9 @@ struct rtlx_channel {
 struct rtlx_info {
 	unsigned long id;
 	enum rtlx_state state;
+#ifdef CONFIG_MIPS_CMP
+	int ap_int_pending;
+#endif
 
 	struct rtlx_channel channel[RTLX_CHANNELS];
 };
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
index 29811f0..c76a5d9 100644
--- a/arch/mips/kernel/kspd.c
+++ b/arch/mips/kernel/kspd.c
@@ -31,6 +31,9 @@
 #include <asm/rtlx.h>
 #include <asm/kspd.h>
 
+#ifdef CONFIG_MIPS_CMP
+static int cpu_idx;
+#endif
 static struct workqueue_struct *workqueue;
 static struct work_struct work;
 
@@ -208,6 +211,7 @@ void sp_work_handle_request(void)
 
 	char *vcwd;
 	int size;
+	int index;
 
 	ret.retval = -1;
 
@@ -230,11 +234,16 @@ void sp_work_handle_request(void)
 		}
 	}
 
+#ifdef CONFIG_MIPS_CMP
+	index = cpu_idx;
+#else
+	index = tclimit;
+#endif
 	/* Run the syscall at the privilege of the user who loaded the
 	   SP program */
 
-	if (vpe_getuid(tclimit)) {
-		err = sp_setfsuidgid(vpe_getuid(tclimit), vpe_getgid(tclimit));
+	if (vpe_getuid(index)) {
+		err = sp_setfsuidgid(vpe_getuid(index), vpe_getgid(index));
 		if (!err)
 			pr_err("Change of creds failed\n");
 	}
@@ -256,7 +265,7 @@ void sp_work_handle_request(void)
 
  	case MTSP_SYSCALL_EXIT:
 		list_for_each_entry(n, &kspd_notifylist, list)
-			n->kspd_sp_exit(tclimit);
+			n->kspd_sp_exit(index);
 		sp_stopping = 1;
 
 		printk(KERN_DEBUG "KSPD got exit syscall from SP exitcode %d\n",
@@ -266,7 +275,7 @@ void sp_work_handle_request(void)
  	case MTSP_SYSCALL_OPEN:
  		generic.arg1 = translate_open_flags(generic.arg1);
 
-		vcwd = vpe_getcwd(tclimit);
+		vcwd = vpe_getcwd(index);
 
 		/* change to cwd of the process that loaded the SP program */
 		old_fs = get_fs();
@@ -294,7 +303,7 @@ void sp_work_handle_request(void)
 		break;
  	} /* switch */
 
-	if (vpe_getuid(tclimit)) {
+	if (vpe_getuid(index)) {
 		err = sp_setfsuidgid(0, 0);
 		if (!err)
 			pr_err("restoring old creds failed\n");
@@ -399,13 +408,18 @@ void kspd_notify(struct kspd_notifications *notify)
 }
 
 static struct vpe_notifications notify;
-static int kspd_module_init(void)
+static int __init kspd_module_init(void)
 {
 	INIT_LIST_HEAD(&kspd_notifylist);
 
 	notify.start = startwork;
 	notify.stop = stopwork;
+#ifdef CONFIG_MIPS_CMP
+	cpu_idx = setup_max_cpus;
+	vpe_notify(cpu_idx, &notify);
+#else
 	vpe_notify(tclimit, &notify);
+#endif
 
 	return 0;
 }
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 1c2e156..308190e 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -56,18 +56,39 @@ static struct chan_waitqueues {
 
 static struct vpe_notifications notify;
 static int sp_stopping;
-static void (*save_aprp_dispatch)(void);
+static void (*save_aprp_hook)(void);
 
 extern void *vpe_get_shared(int index);
-extern void (*aprp_dispatch)(void);
+extern void (*aprp_hook)(void);
 
+#ifdef CONFIG_MIPS_CMP
+static int cpu_idx;
+static void rtlx_interrupt(void)
+{
+	int i;
+	struct rtlx_info *info;
+	struct rtlx_info **p = vpe_get_shared(cpu_idx);
+
+	if (p == NULL || *p == NULL)
+		return;
+
+	info = *p;
+
+	if (info->ap_int_pending == 1 && smp_processor_id() == 0) {
+		for (i = 0; i < RTLX_CHANNELS; i++) {
+			wake_up(&channel_wqs[i].lx_queue);
+			wake_up(&channel_wqs[i].rt_queue);
+		}
+		info->ap_int_pending = 0;
+	}
+}
+#else
 static void rtlx_dispatch(void)
 {
 	if (read_c0_cause() & read_c0_status() & C_SW0)
 		do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ);
 }
 
-
 /* Interrupt handler may be called before rtlx_init has otherwise had
    a chance to run.
 */
@@ -86,12 +107,13 @@ static irqreturn_t rtlx_interrupt(int irq, void *dev_id)
 	local_irq_restore(flags);
 
 	for (i = 0; i < RTLX_CHANNELS; i++) {
-			wake_up(&channel_wqs[i].lx_queue);
-			wake_up(&channel_wqs[i].rt_queue);
+		wake_up(&channel_wqs[i].lx_queue);
+		wake_up(&channel_wqs[i].rt_queue);
 	}
 
 	return IRQ_HANDLED;
 }
+#endif
 
 static void __used dump_rtlx(void)
 {
@@ -160,6 +182,7 @@ int rtlx_open(int index, int can_sleep)
 	struct rtlx_channel *chan;
 	enum rtlx_state state;
 	int ret = 0;
+	int cpu_index;
 
 	if (index >= RTLX_CHANNELS) {
 		printk(KERN_DEBUG "rtlx_open index out of range\n");
@@ -173,11 +196,17 @@ int rtlx_open(int index, int can_sleep)
 		goto out_fail;
 	}
 
+#ifdef CONFIG_MIPS_CMP
+	cpu_index = cpu_idx;
+#else
+	cpu_index = tclimit;
+#endif
+
 	if (rtlx == NULL) {
-		if( (p = vpe_get_shared(tclimit)) == NULL) {
+		if( (p = vpe_get_shared(cpu_index)) == NULL) {
 		    if (can_sleep) {
 			__wait_event_interruptible(channel_wqs[index].lx_queue,
-				(p = vpe_get_shared(tclimit)), ret);
+				(p = vpe_get_shared(cpu_index)), ret);
 			if (ret)
 				goto out_fail;
 		    } else {
@@ -348,6 +377,12 @@ out:
 	return count;
 }
 
+#ifdef CONFIG_MIPS_CMP
+static void _interrupt_sp(void)
+{
+	cmp_send_ipi_single(cpu_idx, SMP_RESCHEDULE_YOURSELF);
+}
+#else
 static void _interrupt_sp(void)
 {
 	unsigned long flags;
@@ -359,6 +394,7 @@ static void _interrupt_sp(void)
 	evpe(EVPE_ENABLE);
 	local_irq_restore(flags);
 }
+#endif
 
 ssize_t rtlx_write(int index, const void __user *buffer, size_t count)
 {
@@ -488,6 +524,75 @@ static const struct file_operations rtlx_fops = {
 	.poll =    file_poll
 };
 
+static char register_chrdev_failed[] __initdata =
+	KERN_ERR "rtlx_module_init: unable to register device\n";
+
+#ifdef CONFIG_MIPS_CMP
+static int __init rtlx_module_init(void)
+{
+	struct device *dev;
+	int i, err;
+
+	if (!cpu_has_mipsmt) {
+		printk("VPE loader: not a MIPS MT capable processor\n");
+		return -ENODEV;
+	}
+
+	cpu_idx = setup_max_cpus;
+
+	if (num_possible_cpus() - cpu_idx < 1) {
+		printk(KERN_WARNING "No TCs reserved for AP/SP, not "
+		       "initializing RTLX.\nPass maxcpus=<n> argument as kernel "
+		       "argument\n");
+
+		return -ENODEV;
+	}
+
+	major = register_chrdev(0, module_name, &rtlx_fops);
+	if (major < 0) {
+		printk(register_chrdev_failed);
+		return major;
+	}
+
+	/* initialise the wait queues */
+	for (i = 0; i < RTLX_CHANNELS; i++) {
+		init_waitqueue_head(&channel_wqs[i].rt_queue);
+		init_waitqueue_head(&channel_wqs[i].lx_queue);
+		atomic_set(&channel_wqs[i].in_open, 0);
+		mutex_init(&channel_wqs[i].mutex);
+
+		dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
+				    "%s%d", module_name, i);
+		if (IS_ERR(dev)) {
+			err = PTR_ERR(dev);
+			goto out_chrdev;
+		}
+	}
+
+	/* set up notifiers */
+	notify.start = starting;
+	notify.stop = stopping;
+	vpe_notify(cpu_idx, &notify);
+
+	if (cpu_has_vint) {
+		save_aprp_hook = aprp_hook;
+		aprp_hook = rtlx_interrupt;
+	}
+	else {
+		pr_err("APRP RTLX init on non-vectored-interrupt processor\n");
+		err = -ENODEV;
+		goto out_chrdev;
+	}
+
+	return 0;
+
+out_chrdev:
+	for (i = 0; i < RTLX_CHANNELS; i++)
+		device_destroy(mt_class, MKDEV(major, i));
+
+	return err;
+}
+#else
 static struct irqaction rtlx_irq = {
 	.handler	= rtlx_interrupt,
 	.flags		= IRQF_DISABLED,
@@ -496,9 +601,6 @@ static struct irqaction rtlx_irq = {
 
 static int rtlx_irq_num = MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ;
 
-static char register_chrdev_failed[] __initdata =
-	KERN_ERR "rtlx_module_init: unable to register device\n";
-
 static int __init rtlx_module_init(void)
 {
 	struct device *dev;
@@ -549,8 +651,8 @@ static int __init rtlx_module_init(void)
 		 * gets set, a hw interrupt is signaled as well. Here we
 		 * are hooking it into platform specific dispatch.
 		 */
-		save_aprp_dispatch = aprp_dispatch;
-		aprp_dispatch = rtlx_dispatch;
+		save_aprp_hook = aprp_hook;
+		aprp_hook = rtlx_dispatch;
 	} else {
 		pr_err("APRP RTLX init on non-vectored-interrupt processor\n");
 		err = -ENODEV;
@@ -568,6 +670,7 @@ out_chrdev:
 
 	return err;
 }
+#endif
 
 static void __exit rtlx_module_exit(void)
 {
@@ -577,7 +680,7 @@ static void __exit rtlx_module_exit(void)
 		device_destroy(mt_class, MKDEV(major, i));
 
 	unregister_chrdev(major, module_name);
-	aprp_dispatch = save_aprp_dispatch;
+	aprp_hook = save_aprp_hook;
 }
 
 module_init(rtlx_module_init);
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index d0e757a..b2e8640 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -53,6 +53,10 @@
 #include <asm/system.h>
 #include <asm/vpe.h>
 #include <asm/kspd.h>
+#ifdef CONFIG_MIPS_CMP
+#include <asm/amon.h>
+#include <asm/mips-boards/launch.h>
+#endif
 
 typedef void *vpe_handle;
 
@@ -66,7 +70,11 @@ typedef void *vpe_handle;
 /*
  * The number of TCs and VPEs physically available on the core
  */
+#ifdef CONFIG_MIPS_CMP
+static int cpu_idx;
+#else
 static int hw_tcs, hw_vpes;
+#endif
 static char module_name[] = "vpe";
 static int major;
 static const int minor = 1;	/* fixed for now  */
@@ -178,7 +186,7 @@ static struct vpe *get_vpe(int minor)
 }
 
 /* get the vpe associated with this minor */
-static struct tc *get_tc(int index)
+static __attribute__((__unused__)) struct tc *get_tc(int index)
 {
 	struct tc *res, *t;
 
@@ -683,6 +691,43 @@ static void dump_elfsymbols(Elf_Shdr * sechdrs, unsigned int symindex,
 }
 #endif
 
+#ifdef CONFIG_MIPS_CMP
+static int vpe_run(struct vpe *v)
+{
+	struct vpe_notifications *n;
+	volatile struct cpulaunch *launch =
+		(struct cpulaunch  *)CKSEG0ADDR(CPULAUNCH);
+
+	if (!amon_cpu_avail(cpu_idx))
+		return -1;
+	if (cpu_idx == smp_processor_id()) {
+		printk(KERN_WARNING "launch: I am cpu%d!\n", cpu_idx);
+		return -1;
+	}
+	launch += cpu_idx;
+
+	printk(KERN_INFO "launch: starting cpu%d\n", cpu_idx);
+
+	launch->pc = v->__start;
+	launch->gp = 0;
+	launch->sp = 0;
+	launch->a0 = 0;
+
+	smp_wmb();
+	launch->flags |= LAUNCH_FGO;
+	smp_wmb();
+
+	while ((launch->flags & LAUNCH_FGONE) == 0)
+		;
+	smp_rmb();
+	printk(KERN_INFO "launch: cpu%d gone!\n", cpu_idx);
+
+	list_for_each_entry(n, &v->notify, list)
+		n->start(minor);
+
+	return 0;
+}
+#else
 /* We are prepared so configure and start the VPE... */
 static int vpe_run(struct vpe * v)
 {
@@ -812,6 +857,7 @@ static int vpe_run(struct vpe * v)
 
 	return 0;
 }
+#endif /* CONFIG_MIPS_CMP */
 
 static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
 				      unsigned int symindex, const char *strtab,
@@ -1010,6 +1056,7 @@ static int vpe_elfload(struct vpe * v)
 	return 0;
 }
 
+#ifndef CONFIG_MIPS_CMP
 static void cleanup_tc(struct tc *tc)
 {
 	unsigned long flags;
@@ -1041,6 +1088,7 @@ static void cleanup_tc(struct tc *tc)
 	emt(mtflags);
 	local_irq_restore(flags);
 }
+#endif
 
 static int getcwd(char *buff, int size)
 {
@@ -1063,7 +1111,13 @@ static int vpe_open(struct inode *inode, struct file *filp)
 	enum vpe_state state;
 	struct vpe_notifications *not;
 	struct vpe *v;
-	int ret;
+	int ret, index;
+
+#ifdef CONFIG_MIPS_CMP
+	index = cpu_idx;
+#else
+	index = tclimit;
+#endif
 
 	if (minor != iminor(inode)) {
 		/* assume only 1 device at the moment. */
@@ -1072,7 +1126,7 @@ static int vpe_open(struct inode *inode, struct file *filp)
 		return -ENODEV;
 	}
 
-	if ((v = get_vpe(tclimit)) == NULL) {
+	if ((v = get_vpe(index)) == NULL) {
 		pr_warning("VPE loader: unable to get vpe\n");
 
 		return -ENODEV;
@@ -1083,11 +1137,13 @@ static int vpe_open(struct inode *inode, struct file *filp)
 		printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n");
 
 		list_for_each_entry(not, &v->notify, list) {
-			not->stop(tclimit);
+			not->stop(index);
 		}
 
 		release_progmem(v->load_addr);
-		cleanup_tc(get_tc(tclimit));
+#ifndef CONFIG_MIPS_CMP
+		cleanup_tc(get_tc(index));
+#endif
 	}
 
 	/* this of-course trashes what was there before... */
@@ -1124,7 +1180,11 @@ static int vpe_release(struct inode *inode, struct file *filp)
 	Elf_Ehdr *hdr;
 	int ret = 0;
 
+#ifdef CONFIG_MIPS_CMP
+	v = get_vpe(cpu_idx);
+#else
 	v = get_vpe(tclimit);
+#endif
 	if (v == NULL)
 		return -ENODEV;
 
@@ -1165,7 +1225,11 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,
 	if (iminor(file->f_path.dentry->d_inode) != minor)
 		return -ENODEV;
 
+#ifdef CONFIG_MIPS_CMP
+	v = get_vpe(cpu_idx);
+#else
 	v = get_vpe(tclimit);
+#endif
 	if (v == NULL)
 		return -ENODEV;
 
@@ -1195,6 +1259,7 @@ static const struct file_operations vpe_fops = {
 	.write = vpe_write
 };
 
+#ifndef CONFIG_MIPS_CMP
 /* module wrapper entry points */
 /* give me a vpe */
 vpe_handle vpe_alloc(void)
@@ -1282,6 +1347,7 @@ int vpe_free(vpe_handle vpe)
 }
 
 EXPORT_SYMBOL(vpe_free);
+#endif /* CONFIG_MIPS_CMP */
 
 void *vpe_get_shared(int index)
 {
@@ -1344,6 +1410,60 @@ char *vpe_getcwd(int index)
 
 EXPORT_SYMBOL(vpe_getcwd);
 
+#ifdef CONFIG_MIPS_CMP
+#ifdef CONFIG_MIPS_APSP_KSPD
+static void kspd_sp_exit( int sp_id)
+{
+	/* Do nothing to the SP core. */
+}
+#endif
+
+static ssize_t store_kill(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t len)
+{
+	struct vpe *vpe = get_vpe(cpu_idx);
+	struct vpe_notifications *not;
+
+	list_for_each_entry(not, &vpe->notify, list) {
+		not->stop(cpu_idx);
+	}
+
+	release_progmem(vpe->load_addr);
+	vpe->state = VPE_STATE_UNUSED;
+
+	return len;
+}
+
+static ssize_t show_ntcs(struct device *cd, struct device_attribute *attr,
+			 char *buf)
+{
+	struct vpe *vpe = get_vpe(cpu_idx);
+
+	return sprintf(buf, "%d\n", vpe->ntcs);
+}
+
+static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t len)
+{
+	struct vpe *vpe = get_vpe(cpu_idx);
+	unsigned long new;
+	char *endp;
+
+	new = simple_strtoul(buf, &endp, 0);
+	if (endp == buf)
+		goto out_einval;
+
+	if (new != 1)
+		goto out_einval;
+
+	vpe->ntcs = new;
+
+	return len;
+
+out_einval:
+	return -EINVAL;
+}
+#else
 #ifdef CONFIG_MIPS_APSP_KSPD
 static void kspd_sp_exit( int sp_id)
 {
@@ -1398,6 +1518,7 @@ static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr,
 out_einval:
 	return -EINVAL;
 }
+#endif /* CONFIG_MIPS_CMP */
 
 static struct device_attribute vpe_class_attributes[] = {
 	__ATTR(kill, S_IWUSR, NULL, store_kill),
@@ -1419,6 +1540,87 @@ struct class vpe_class = {
 
 struct device vpe_device;
 
+#ifdef CONFIG_MIPS_CMP
+static int __init vpe_module_init(void)
+{
+	struct vpe *v = NULL;
+	struct tc *t;
+	int err;
+
+	if (!cpu_has_mipsmt) {
+		printk("VPE loader: not a MIPS MT capable processor\n");
+		return -ENODEV;
+	}
+
+	cpu_idx = setup_max_cpus;
+
+	if (num_possible_cpus() - cpu_idx < 1) {
+		printk (KERN_WARNING "No VPEs reserved for AP/SP in "
+				"CPS, not initializing VPE loader.\nPass maxcpus=<n> "
+				"argument as kernel argument\n");
+		return -ENODEV;
+	}
+
+	major = register_chrdev(0, module_name, &vpe_fops);
+	if (major < 0) {
+		printk("VPE loader: unable to register character device\n");
+		return major;
+	}
+
+	err = class_register(&vpe_class);
+	if (err) {
+		printk(KERN_ERR "vpe_class registration failed\n");
+		goto out_chrdev;
+	}
+
+	device_initialize(&vpe_device);
+	vpe_device.class	= &vpe_class,
+	vpe_device.parent	= NULL,
+	dev_set_name(&vpe_device, "vpe_sp");
+	vpe_device.devt = MKDEV(major, minor);
+	err = device_add(&vpe_device);
+	if (err) {
+		printk(KERN_ERR "Adding vpe_device failed\n");
+		goto out_class;
+	}
+
+	t = alloc_tc(cpu_idx);
+	if (!t) {
+		printk(KERN_WARNING "VPE: unable to allocate TC\n");
+		err = -ENOMEM;
+		goto out;
+	}
+
+	/* VPE */
+	if ((v = alloc_vpe(cpu_idx)) == NULL) {
+		printk(KERN_WARNING "VPE: unable to allocate VPE\n");
+		kfree(t);
+		err = -ENOMEM;
+		goto out;
+	}
+
+	v->ntcs = 1;
+
+	/* add the tc to the list of this vpe's tc's. */
+	list_add(&t->tc, &v->tc);
+
+	/* TC */
+	t->pvpe = v;	/* set the parent vpe */
+
+#ifdef CONFIG_MIPS_APSP_KSPD
+	kspd_events.kspd_sp_exit = kspd_sp_exit;
+#endif
+	return 0;
+
+out_class:
+	class_unregister(&vpe_class);
+out_chrdev:
+	unregister_chrdev(major, module_name);
+
+out:
+	return err;
+}
+#else
 static int __init vpe_module_init(void)
 {
 	unsigned int mtflags, vpflags;
@@ -1601,6 +1803,7 @@ out_chrdev:
 out:
 	return err;
 }
+#endif /* CONFIG_MIPS_CMP */
 
 static void __exit vpe_module_exit(void)
 {
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index 0fec7b2..2f44421 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -119,13 +119,13 @@ static inline int get_int(void)
 }
 
 #ifdef CONFIG_MIPS_VPE_APSP_API
-static void null_aprp_dispatch(void)
+static void null_aprp_hook(void)
 {
 }
 
-void (*aprp_dispatch)(void) = null_aprp_dispatch;
+void (*aprp_hook)(void) = null_aprp_hook;
 
-EXPORT_SYMBOL(aprp_dispatch);
+EXPORT_SYMBOL(aprp_hook);
 #endif
 
 static void malta_hw0_irqdispatch(void)
@@ -140,13 +140,13 @@ static void malta_hw0_irqdispatch(void)
 
 	do_IRQ(MALTA_INT_BASE + irq);
 
-#ifdef CONFIG_MIPS_VPE_APSP_API
+#if defined(CONFIG_MIPS_VPE_APSP_API) && !defined(CONFIG_MIPS_CMP)
 	/*
 	 * When sw0 gets set, a spurious hw interrupt is signaled as well.
 	 * The sw0 will not be handled until the hw interrupt is cleared.
 	 * We use the hook to handle sw0 and the hw interrupt gets cleared.
 	 */
-	aprp_dispatch();
+	aprp_hook();
 #endif
 }
 
@@ -329,6 +329,10 @@ static void ipi_call_dispatch(void)
 
 static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
 {
+#if defined(CONFIG_MIPS_VPE_APSP_API) && defined(CONFIG_MIPS_CMP)
+	aprp_hook();
+#endif
+
 	return IRQ_HANDLED;
 }
 
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH 0/2] MIPS: enable APRP (APSP) and add features
From: Deng-Cheng Zhu @ 2010-10-20  5:10 UTC (permalink / raw)
  To: linux-mips, ralf, kevink; +Cc: eyal, dengcheng.zhu

The APRP model makes it possible that one or more CPUs run the Linux
kernel whereas a dedicated CPU runs special real-time or signal processing
program.

This patchset adds the following to the current APRP support:
1. Several bug fixes;
2. Running floating point heavy jobs on the RP side;
3. Waking up RP side read by interrupt;
4. CPS multicore APRP support.

A mp3 player program was ported to run in the APRP (APSP exactly) model.
Considerable performance benefits were observed on the player program.
Since I encountered a sound card support issue on the current linux-mips
kernel, I rebased this patchset onto mti-2.6.29.4-1. And for the current
kernel, I used a simple test program to validate this work.

Deng-Cheng Zhu (2):
  MIPS: fix/enrich 34K APRP (APSP) functionalities
  MIPS: enable CPS multicore APRP (APSP)

 arch/mips/Kconfig                                  |    8 +
 .../include/asm/mach-malta/cpu-feature-overrides.h |    3 +
 arch/mips/include/asm/rtlx.h                       |    3 +
 arch/mips/kernel/kspd.c                            |   26 ++-
 arch/mips/kernel/rtlx.c                            |  153 +++++++++++++--
 arch/mips/kernel/vpe.c                             |  217 +++++++++++++++++++-
 arch/mips/mti-malta/malta-int.c                    |   26 +++-
 7 files changed, 409 insertions(+), 27 deletions(-)

^ permalink raw reply

* [U-Boot] [PATCH] cmd_mii: localize & constify local funcs/data
From: Mike Frysinger @ 2010-10-20  5:06 UTC (permalink / raw)
  To: u-boot

No need for these structures to be writable or global.

While we're here, also drop local versions of the ARRAY_SIZE macro.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
---
 common/cmd_mii.c |   68 +++++++++++++++++++++++------------------------------
 1 files changed, 30 insertions(+), 38 deletions(-)

diff --git a/common/cmd_mii.c b/common/cmd_mii.c
index 3ea493b..3fb0795 100644
--- a/common/cmd_mii.c
+++ b/common/cmd_mii.c
@@ -34,7 +34,7 @@ typedef struct _MII_reg_desc_t {
 	char * name;
 } MII_reg_desc_t;
 
-MII_reg_desc_t reg_0_5_desc_tbl[] = {
+static const MII_reg_desc_t reg_0_5_desc_tbl[] = {
 	{ 0,   "PHY control register"                },
 	{ 1,   "PHY status register"                 },
 	{ 2,   "PHY ID 1 register"                   },
@@ -50,7 +50,7 @@ typedef struct _MII_field_desc_t {
 	char * name;
 } MII_field_desc_t;
 
-MII_field_desc_t reg_0_desc_tbl[] = {
+static const MII_field_desc_t reg_0_desc_tbl[] = {
 	{ 15, 15, 0x01, "reset"                        },
 	{ 14, 14, 0x01, "loopback"                     },
 	{ 13,  6, 0x81, "speed selection"              }, /* special */
@@ -63,7 +63,7 @@ MII_field_desc_t reg_0_desc_tbl[] = {
 	{  5,  0, 0x3f, "(reserved)"                   }
 };
 
-MII_field_desc_t reg_1_desc_tbl[] = {
+static const MII_field_desc_t reg_1_desc_tbl[] = {
 	{ 15, 15, 0x01, "100BASE-T4 able"              },
 	{ 14, 14, 0x01, "100BASE-X  full duplex able"  },
 	{ 13, 13, 0x01, "100BASE-X  half duplex able"  },
@@ -82,17 +82,17 @@ MII_field_desc_t reg_1_desc_tbl[] = {
 	{  0,  0, 0x01, "extended capabilities"        },
 };
 
-MII_field_desc_t reg_2_desc_tbl[] = {
+static const MII_field_desc_t reg_2_desc_tbl[] = {
 	{ 15,  0, 0xffff, "OUI portion"                },
 };
 
-MII_field_desc_t reg_3_desc_tbl[] = {
+static const MII_field_desc_t reg_3_desc_tbl[] = {
 	{ 15, 10, 0x3f, "OUI portion"                },
 	{  9,  4, 0x3f, "manufacturer part number"   },
 	{  3,  0, 0x0f, "manufacturer rev. number"   },
 };
 
-MII_field_desc_t reg_4_desc_tbl[] = {
+static const MII_field_desc_t reg_4_desc_tbl[] = {
 	{ 15, 15, 0x01, "next page able"               },
 	{ 14, 14, 0x01, "reserved"                     },
 	{ 13, 13, 0x01, "remote fault"                 },
@@ -107,7 +107,7 @@ MII_field_desc_t reg_4_desc_tbl[] = {
 	{  4,  0, 0x1f, "xxx to do"                    },
 };
 
-MII_field_desc_t reg_5_desc_tbl[] = {
+static const MII_field_desc_t reg_5_desc_tbl[] = {
 	{ 15, 15, 0x01, "next page able"               },
 	{ 14, 14, 0x01, "acknowledge"                  },
 	{ 13, 13, 0x01, "remote fault"                 },
@@ -121,39 +121,31 @@ MII_field_desc_t reg_5_desc_tbl[] = {
 	{  5,  5, 0x01, "10BASE-T able"                },
 	{  4,  0, 0x1f, "xxx to do"                    },
 };
-
-#define DESC0LEN (sizeof(reg_0_desc_tbl)/sizeof(reg_0_desc_tbl[0]))
-#define DESC1LEN (sizeof(reg_1_desc_tbl)/sizeof(reg_1_desc_tbl[0]))
-#define DESC2LEN (sizeof(reg_2_desc_tbl)/sizeof(reg_2_desc_tbl[0]))
-#define DESC3LEN (sizeof(reg_3_desc_tbl)/sizeof(reg_3_desc_tbl[0]))
-#define DESC4LEN (sizeof(reg_4_desc_tbl)/sizeof(reg_4_desc_tbl[0]))
-#define DESC5LEN (sizeof(reg_5_desc_tbl)/sizeof(reg_5_desc_tbl[0]))
-
 typedef struct _MII_field_desc_and_len_t {
-	MII_field_desc_t * pdesc;
+	const MII_field_desc_t *pdesc;
 	ushort len;
 } MII_field_desc_and_len_t;
 
-MII_field_desc_and_len_t desc_and_len_tbl[] = {
-	{ reg_0_desc_tbl, DESC0LEN },
-	{ reg_1_desc_tbl, DESC1LEN },
-	{ reg_2_desc_tbl, DESC2LEN },
-	{ reg_3_desc_tbl, DESC3LEN },
-	{ reg_4_desc_tbl, DESC4LEN },
-	{ reg_5_desc_tbl, DESC5LEN },
+static const MII_field_desc_and_len_t desc_and_len_tbl[] = {
+	{ reg_0_desc_tbl, ARRAY_SIZE(reg_0_desc_tbl)   },
+	{ reg_1_desc_tbl, ARRAY_SIZE(reg_1_desc_tbl)   },
+	{ reg_2_desc_tbl, ARRAY_SIZE(reg_2_desc_tbl)   },
+	{ reg_3_desc_tbl, ARRAY_SIZE(reg_3_desc_tbl)   },
+	{ reg_4_desc_tbl, ARRAY_SIZE(reg_4_desc_tbl)   },
+	{ reg_5_desc_tbl, ARRAY_SIZE(reg_5_desc_tbl)   },
 };
 
 static void dump_reg(
 	ushort             regval,
-	MII_reg_desc_t   * prd,
-	MII_field_desc_and_len_t * pdl);
+	const MII_reg_desc_t *prd,
+	const MII_field_desc_and_len_t *pdl);
 
 static int special_field(
 	ushort regno,
-	MII_field_desc_t * pdesc,
+	const MII_field_desc_t *pdesc,
 	ushort regval);
 
-void MII_dump_0_to_5(
+static void MII_dump_0_to_5(
 	ushort regvals[6],
 	uchar reglo,
 	uchar reghi)
@@ -169,12 +161,12 @@ void MII_dump_0_to_5(
 
 static void dump_reg(
 	ushort             regval,
-	MII_reg_desc_t   * prd,
-	MII_field_desc_and_len_t * pdl)
+	const MII_reg_desc_t *prd,
+	const MII_field_desc_and_len_t *pdl)
 {
 	ulong i;
 	ushort mask_in_place;
-	MII_field_desc_t * pdesc;
+	const MII_field_desc_t *pdesc;
 
 	printf("%u.     (%04hx)                 -- %s --\n",
 		prd->regno, regval, prd->name);
@@ -217,7 +209,7 @@ static void dump_reg(
 
 static int special_field(
 	ushort regno,
-	MII_field_desc_t * pdesc,
+	const MII_field_desc_t *pdesc,
 	ushort regval)
 {
 	if ((regno == 0) && (pdesc->lo == 6)) {
@@ -268,12 +260,12 @@ static int special_field(
 	return 0;
 }
 
-char last_op[2];
-uint last_data;
-uint last_addr_lo;
-uint last_addr_hi;
-uint last_reg_lo;
-uint last_reg_hi;
+static char last_op[2];
+static uint last_data;
+static uint last_addr_lo;
+static uint last_addr_hi;
+static uint last_reg_lo;
+static uint last_reg_hi;
 
 static void extract_range(
 	char * input,
@@ -292,7 +284,7 @@ static void extract_range(
 }
 
 /* ---------------------------------------------------------------- */
-int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
+static int do_mii(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	char		op[2];
 	unsigned char	addrlo, addrhi, reglo, reghi;
-- 
1.7.3.1

^ permalink raw reply related

* How to build the driver for old OS (RHEL4.2)
From: Scott @ 2010-10-20  5:05 UTC (permalink / raw)
  To: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 388 bytes --]

Hi friends,

I am having a Intel box with 945GSE chipset.
And I have a legacy application which runs on RHEL4.2 / GNOME.
The standard (in-built) Intel driver is working fine for GNOME
But I found the (dual) display is not operating successfully.

Please advise how to re-build the driver 'cause I couldn't find the rpm or make files from the forum.

Thanks!!

Scott @ India


[-- Attachment #1.2: Type: text/html, Size: 1323 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply

* Re: oom_killer crash linux system
From: Adam Jiang @ 2010-10-20  5:05 UTC (permalink / raw)
  To: Figo.zhang
  Cc: KOSAKI Motohiro, Wu Fengguang, KAMEZAWA Hiroyuki, Minchan Kim,
	linux-kernel@vger.kernel.org, rientjes@google.com, figo1802,
	linux-mm@kvack.org
In-Reply-To: <1287546225.2121.14.camel@myhost>

On Wed, Oct 20, 2010 at 11:43:45AM +0800, Figo.zhang wrote:
> 
> > > active_anon:398375 inactive_anon:82967 isolated_anon:0 
> > >  active_file:81 inactive_file:429 isolated_file:32
> > >  unevictable:13 dirty:2 writeback:14 unstable:0
> > >  free:11942 slab_reclaimable:2391 slab_unreclaimable:3303
> > >  mapped:5617 shmem:33909 pagetables:2280 bounce:0
> > 
> > active_anon + inactive_anon + isolated_anon = 481342 pages ~= 1.8GB
> > Um, this oom doesn't makes accounting lost.
> > 
> > >              total	    515071     2011
> > 
> > page-types show similar result.
> > 
> > 
> > The big difference is, previous and current are showing some different processes.
> > only previous has VirtualBox, only current has vmware-usbarbit, etc..
> > 
> > Can you use same test environment?
> yes, it is the same desktop, and i open some pdf files and applications
> by random. 
> 
> but when my desktop eat up to 1.8GB RAM (active_anon + inactive_anon +
> isolated_anon = 481342 pages >= 1.8GB), the system became extraordinary
> slow. when i move the mouse, the mouse cant move a little on screen. i
> deem it have "crashed", but i ping it's ip by other desktop, it is ok.
> 
> so what is apect affect the system seem to "crashed", page-writeback?
> page-reclaimed?  and the oom-killer seem to be very conservative? in
> that condition , oom_killer must kill some process to release memory for
> new process.

I think it just simply the test caused system *almost* dead but not
really trigger oom-killer. You have 2GB RAM, right. 0.2G is a huge
amount of memory for Linux kernel.

If you do want to test the new oom-killer, you can just right a simple
program to allocate memory continues but make different instances to
eat memory in different paces. Then, you can find out who will be killed
first eventually.

/Adam
> 
> 
> --
> 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/

^ permalink raw reply

* Re: oom_killer crash linux system
From: Adam Jiang @ 2010-10-20  5:05 UTC (permalink / raw)
  To: Figo.zhang
  Cc: KOSAKI Motohiro, Wu Fengguang, KAMEZAWA Hiroyuki, Minchan Kim,
	linux-kernel@vger.kernel.org, rientjes@google.com, figo1802,
	linux-mm@kvack.org
In-Reply-To: <1287546225.2121.14.camel@myhost>

On Wed, Oct 20, 2010 at 11:43:45AM +0800, Figo.zhang wrote:
> 
> > > active_anon:398375 inactive_anon:82967 isolated_anon:0 
> > >  active_file:81 inactive_file:429 isolated_file:32
> > >  unevictable:13 dirty:2 writeback:14 unstable:0
> > >  free:11942 slab_reclaimable:2391 slab_unreclaimable:3303
> > >  mapped:5617 shmem:33909 pagetables:2280 bounce:0
> > 
> > active_anon + inactive_anon + isolated_anon = 481342 pages ~= 1.8GB
> > Um, this oom doesn't makes accounting lost.
> > 
> > >              total	    515071     2011
> > 
> > page-types show similar result.
> > 
> > 
> > The big difference is, previous and current are showing some different processes.
> > only previous has VirtualBox, only current has vmware-usbarbit, etc..
> > 
> > Can you use same test environment?
> yes, it is the same desktop, and i open some pdf files and applications
> by random. 
> 
> but when my desktop eat up to 1.8GB RAM (active_anon + inactive_anon +
> isolated_anon = 481342 pages >= 1.8GB), the system became extraordinary
> slow. when i move the mouse, the mouse cant move a little on screen. i
> deem it have "crashed", but i ping it's ip by other desktop, it is ok.
> 
> so what is apect affect the system seem to "crashed", page-writeback?
> page-reclaimed?  and the oom-killer seem to be very conservative? in
> that condition , oom_killer must kill some process to release memory for
> new process.

I think it just simply the test caused system *almost* dead but not
really trigger oom-killer. You have 2GB RAM, right. 0.2G is a huge
amount of memory for Linux kernel.

If you do want to test the new oom-killer, you can just right a simple
program to allocate memory continues but make different instances to
eat memory in different paces. Then, you can find out who will be killed
first eventually.

/Adam
> 
> 
> --
> 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/

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* [PATCH v2][memcg+dirtylimit] Fix  overwriting global vm dirty limit setting by memcg (Re: [PATCH v3 00/11] memcg: per cgroup dirty page accounting
From: KAMEZAWA Hiroyuki @ 2010-10-20  5:02 UTC (permalink / raw)
  To: KAMEZAWA Hiroyuki
  Cc: Greg Thelen, Andrew Morton, linux-kernel, linux-mm, containers,
	Andrea Righi, Balbir Singh, Daisuke Nishimura, Minchan Kim,
	Ciju Rajan K, David Rientjes
In-Reply-To: <20101020122144.47f2b60b.kamezawa.hiroyu@jp.fujitsu.com>

Fixed one here.
==
From: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>

Now, at calculating dirty limit, vm_dirty_param() is called.
This function returns dirty-limit related parameters considering
memory cgroup settings.

Now, assume that vm_dirty_bytes=100M (global dirty limit) and
memory cgroup has 1G of pages and 40 dirty_ratio, dirtyable memory is
500MB.

In this case, global_dirty_limits will consider dirty_limt as
500 *0.4 = 200MB. This is bad...memory cgroup is not back door.

This patch limits the return value of vm_dirty_param() considring
global settings.

Changelog:
 - fixed an argument "mem" int to u64
 - fixed to use global available memory to cap memcg's value.

Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
---
 include/linux/memcontrol.h |    5 +++--
 mm/memcontrol.c            |   30 +++++++++++++++++++++++++++++-
 mm/page-writeback.c        |    3 ++-
 3 files changed, 34 insertions(+), 4 deletions(-)

Index: dirty_limit_new/mm/memcontrol.c
===================================================================
--- dirty_limit_new.orig/mm/memcontrol.c
+++ dirty_limit_new/mm/memcontrol.c
@@ -1171,9 +1171,11 @@ static void __mem_cgroup_dirty_param(str
  * can be moved after our access and writeback tends to take long time.  At
  * least, "memcg" will not be freed while holding rcu_read_lock().
  */
-void vm_dirty_param(struct vm_dirty_param *param)
+void vm_dirty_param(struct vm_dirty_param *param,
+	 u64 mem, u64 global)
 {
 	struct mem_cgroup *memcg;
+	u64 limit, bglimit;
 
 	if (mem_cgroup_disabled()) {
 		global_vm_dirty_param(param);
@@ -1183,6 +1185,32 @@ void vm_dirty_param(struct vm_dirty_para
 	rcu_read_lock();
 	memcg = mem_cgroup_from_task(current);
 	__mem_cgroup_dirty_param(param, memcg);
+	/*
+	 * A limitation under memory cgroup is under global vm, too.
+	 */
+	if (vm_dirty_ratio)
+		limit = global * vm_dirty_ratio / 100;
+	else
+		limit = vm_dirty_bytes;
+	if (param->dirty_ratio) {
+		param->dirty_bytes = mem * param->dirty_ratio / 100;
+		param->dirty_ratio = 0;
+	}
+	if (param->dirty_bytes > limit)
+		param->dirty_bytes = limit;
+
+	if (dirty_background_ratio)
+		bglimit = global * dirty_background_ratio / 100;
+	else
+		bglimit = dirty_background_bytes;
+
+	if (param->dirty_background_ratio) {
+		param->dirty_background_bytes =
+			mem * param->dirty_background_ratio / 100;
+		param->dirty_background_ratio = 0;
+	}
+	if (param->dirty_background_bytes > bglimit)
+		param->dirty_background_bytes = bglimit;
 	rcu_read_unlock();
 }
 
Index: dirty_limit_new/include/linux/memcontrol.h
===================================================================
--- dirty_limit_new.orig/include/linux/memcontrol.h
+++ dirty_limit_new/include/linux/memcontrol.h
@@ -171,7 +171,7 @@ static inline void mem_cgroup_dec_page_s
 }
 
 bool mem_cgroup_has_dirty_limit(void);
-void vm_dirty_param(struct vm_dirty_param *param);
+void vm_dirty_param(struct vm_dirty_param *param, u64 mem, u64 global);
 s64 mem_cgroup_page_stat(enum mem_cgroup_nr_pages_item item);
 
 unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
@@ -360,7 +360,8 @@ static inline bool mem_cgroup_has_dirty_
 	return false;
 }
 
-static inline void vm_dirty_param(struct vm_dirty_param *param)
+static inline void vm_dirty_param(struct vm_dirty_param *param,
+		u64 mem, u64 global)
 {
 	global_vm_dirty_param(param);
 }
Index: dirty_limit_new/mm/page-writeback.c
===================================================================
--- dirty_limit_new.orig/mm/page-writeback.c
+++ dirty_limit_new/mm/page-writeback.c
@@ -466,7 +466,8 @@ void global_dirty_limits(unsigned long *
 	struct task_struct *tsk;
 	struct vm_dirty_param dirty_param;
 
-	vm_dirty_param(&dirty_param);
+	vm_dirty_param(&dirty_param,
+		available_memory, global_dirtyable_memory());
 
 	if (dirty_param.dirty_bytes)
 		dirty = DIV_ROUND_UP(dirty_param.dirty_bytes, PAGE_SIZE);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* [tip:irq/core] apic, x86: Use BIOS settings for IBS and MCE threshold interrupt LVT offsets
From: tip-bot for Robert Richter @ 2010-10-20  5:01 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, robert.richter, tglx, mingo
In-Reply-To: <1286360874-1471-3-git-send-email-robert.richter@amd.com>

Commit-ID:  27afdf2008da0b8878a73e32e4eb12381b84e224
Gitweb:     http://git.kernel.org/tip/27afdf2008da0b8878a73e32e4eb12381b84e224
Author:     Robert Richter <robert.richter@amd.com>
AuthorDate: Wed, 6 Oct 2010 12:27:54 +0200
Committer:  Ingo Molnar <mingo@elte.hu>
CommitDate: Wed, 20 Oct 2010 04:42:13 +0200

apic, x86: Use BIOS settings for IBS and MCE threshold interrupt LVT offsets

We want the BIOS to setup the EILVT APIC registers. The offsets
were hardcoded and BIOS settings were overwritten by the OS.
Now, the subsystems for MCE threshold and IBS determine the LVT
offset from the registers the BIOS has setup. If the BIOS setup
is buggy on a family 10h system, a workaround enables IBS. If
the OS determines an invalid register setup, a "[Firmware Bug]:
" error message is reported.

We need this change also for upcomming cpu families.

Signed-off-by: Robert Richter <robert.richter@amd.com>
LKML-Reference: <1286360874-1471-3-git-send-email-robert.richter@amd.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/include/asm/apic.h          |    4 +-
 arch/x86/kernel/apic/apic.c          |   19 +----
 arch/x86/kernel/cpu/mcheck/mce_amd.c |   27 ++++++-
 arch/x86/oprofile/op_model_amd.c     |  145 +++++++++++++++++++++++++++++----
 4 files changed, 154 insertions(+), 41 deletions(-)

diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 1fa03e0..286de34 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -252,9 +252,7 @@ static inline int apic_is_clustered_box(void)
 }
 #endif
 
-extern u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask);
-extern u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask);
-
+extern int setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask);
 
 #else /* !CONFIG_X86_LOCAL_APIC */
 static inline void lapic_shutdown(void) { }
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 2bfeafd..850657d 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -390,9 +390,6 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
  * necessarily a BIOS bug.
  */
 
-#define APIC_EILVT_LVTOFF_MCE 0
-#define APIC_EILVT_LVTOFF_IBS 1
-
 static atomic_t eilvt_offsets[APIC_EILVT_NR_MAX];
 
 static inline int eilvt_entry_is_changeable(unsigned int old, unsigned int new)
@@ -426,7 +423,7 @@ static unsigned int reserve_eilvt_offset(int offset, unsigned int new)
  * enables the vector. See also the BKDGs.
  */
 
-static int setup_APIC_eilvt(u8 offset, u8 vector, u8 msg_type, u8 mask)
+int setup_APIC_eilvt(u8 offset, u8 vector, u8 msg_type, u8 mask)
 {
 	unsigned long reg = APIC_EILVTn(offset);
 	unsigned int new, old, reserved;
@@ -454,19 +451,7 @@ static int setup_APIC_eilvt(u8 offset, u8 vector, u8 msg_type, u8 mask)
 
 	return 0;
 }
-
-u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask)
-{
-	setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask);
-	return APIC_EILVT_LVTOFF_MCE;
-}
-
-u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask)
-{
-	setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask);
-	return APIC_EILVT_LVTOFF_IBS;
-}
-EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs);
+EXPORT_SYMBOL_GPL(setup_APIC_eilvt);
 
 /*
  * Program the next event, relative to now
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 39aaee5..80c4823 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -131,7 +131,8 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
 	u32 low = 0, high = 0, address = 0;
 	unsigned int bank, block;
 	struct thresh_restart tr;
-	u8 lvt_off;
+	int lvt_off = -1;
+	u8 offset;
 
 	for (bank = 0; bank < NR_BANKS; ++bank) {
 		for (block = 0; block < NR_BLOCKS; ++block) {
@@ -162,8 +163,28 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
 			if (shared_bank[bank] && c->cpu_core_id)
 				break;
 #endif
-			lvt_off = setup_APIC_eilvt_mce(THRESHOLD_APIC_VECTOR,
-						       APIC_EILVT_MSG_FIX, 0);
+			offset = (high & MASK_LVTOFF_HI) >> 20;
+			if (lvt_off < 0) {
+				if (setup_APIC_eilvt(offset,
+						     THRESHOLD_APIC_VECTOR,
+						     APIC_EILVT_MSG_FIX, 0)) {
+					pr_err(FW_BUG "cpu %d, failed to "
+					       "setup threshold interrupt "
+					       "for bank %d, block %d "
+					       "(MSR%08X=0x%x%08x)",
+					       smp_processor_id(), bank, block,
+					       address, high, low);
+					continue;
+				}
+				lvt_off = offset;
+			} else if (lvt_off != offset) {
+				pr_err(FW_BUG "cpu %d, invalid threshold "
+				       "interrupt offset %d for bank %d,"
+				       "block %d (MSR%08X=0x%x%08x)",
+				       smp_processor_id(), lvt_off, bank,
+				       block, address, high, low);
+				continue;
+			}
 
 			high &= ~MASK_LVTOFF_HI;
 			high |= lvt_off << 20;
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
index b67a6b5..42fb46f 100644
--- a/arch/x86/oprofile/op_model_amd.c
+++ b/arch/x86/oprofile/op_model_amd.c
@@ -64,15 +64,22 @@ static u64 ibs_op_ctl;
  * IBS cpuid feature detection
  */
 
-#define IBS_CPUID_FEATURES      0x8000001b
+#define IBS_CPUID_FEATURES		0x8000001b
 
 /*
  * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but
  * bit 0 is used to indicate the existence of IBS.
  */
-#define IBS_CAPS_AVAIL			(1LL<<0)
-#define IBS_CAPS_RDWROPCNT		(1LL<<3)
-#define IBS_CAPS_OPCNT			(1LL<<4)
+#define IBS_CAPS_AVAIL			(1U<<0)
+#define IBS_CAPS_RDWROPCNT		(1U<<3)
+#define IBS_CAPS_OPCNT			(1U<<4)
+
+/*
+ * IBS APIC setup
+ */
+#define IBSCTL				0x1cc
+#define IBSCTL_LVT_OFFSET_VALID		(1ULL<<8)
+#define IBSCTL_LVT_OFFSET_MASK		0x0F
 
 /*
  * IBS randomization macros
@@ -266,6 +273,74 @@ static void op_amd_stop_ibs(void)
 		wrmsrl(MSR_AMD64_IBSOPCTL, 0);
 }
 
+static inline int eilvt_is_available(int offset)
+{
+	/* check if we may assign a vector */
+	return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1);
+}
+
+static inline int ibs_eilvt_valid(void)
+{
+	u64 val;
+	int offset;
+
+	rdmsrl(MSR_AMD64_IBSCTL, val);
+	if (!(val & IBSCTL_LVT_OFFSET_VALID)) {
+		pr_err(FW_BUG "cpu %d, invalid IBS "
+		       "interrupt offset %d (MSR%08X=0x%016llx)",
+		       smp_processor_id(), offset,
+		       MSR_AMD64_IBSCTL, val);
+		return 0;
+	}
+
+	offset = val & IBSCTL_LVT_OFFSET_MASK;
+
+	if (eilvt_is_available(offset))
+		return !0;
+
+	pr_err(FW_BUG "cpu %d, IBS interrupt offset %d "
+	       "not available (MSR%08X=0x%016llx)",
+	       smp_processor_id(), offset,
+	       MSR_AMD64_IBSCTL, val);
+
+	return 0;
+}
+
+static inline int get_ibs_offset(void)
+{
+	u64 val;
+
+	rdmsrl(MSR_AMD64_IBSCTL, val);
+	if (!(val & IBSCTL_LVT_OFFSET_VALID))
+		return -EINVAL;
+
+	return val & IBSCTL_LVT_OFFSET_MASK;
+}
+
+static void setup_APIC_ibs(void)
+{
+	int offset;
+
+	offset = get_ibs_offset();
+	if (offset < 0)
+		goto failed;
+
+	if (!setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 0))
+		return;
+failed:
+	pr_warn("oprofile: IBS APIC setup failed on cpu #%d\n",
+		smp_processor_id());
+}
+
+static void clear_APIC_ibs(void)
+{
+	int offset;
+
+	offset = get_ibs_offset();
+	if (offset >= 0)
+		setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
+}
+
 #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
 
 static void op_mux_switch_ctrl(struct op_x86_model_spec const *model,
@@ -376,13 +451,13 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
 	}
 
 	if (ibs_caps)
-		setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0);
+		setup_APIC_ibs();
 }
 
 static void op_amd_cpu_shutdown(void)
 {
 	if (ibs_caps)
-		setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
+		clear_APIC_ibs();
 }
 
 static int op_amd_check_ctrs(struct pt_regs * const regs,
@@ -445,16 +520,11 @@ static void op_amd_stop(struct op_msrs const * const msrs)
 	op_amd_stop_ibs();
 }
 
-static int __init_ibs_nmi(void)
+static int setup_ibs_ctl(int ibs_eilvt_off)
 {
-#define IBSCTL_LVTOFFSETVAL		(1 << 8)
-#define IBSCTL				0x1cc
 	struct pci_dev *cpu_cfg;
 	int nodes;
 	u32 value = 0;
-	u8 ibs_eilvt_off;
-
-	ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
 
 	nodes = 0;
 	cpu_cfg = NULL;
@@ -466,21 +536,60 @@ static int __init_ibs_nmi(void)
 			break;
 		++nodes;
 		pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
-				       | IBSCTL_LVTOFFSETVAL);
+				       | IBSCTL_LVT_OFFSET_VALID);
 		pci_read_config_dword(cpu_cfg, IBSCTL, &value);
-		if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) {
+		if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) {
 			pci_dev_put(cpu_cfg);
 			printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
-				"IBSCTL = 0x%08x", value);
-			return 1;
+			       "IBSCTL = 0x%08x\n", value);
+			return -EINVAL;
 		}
 	} while (1);
 
 	if (!nodes) {
-		printk(KERN_DEBUG "No CPU node configured for IBS");
-		return 1;
+		printk(KERN_DEBUG "No CPU node configured for IBS\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int force_ibs_eilvt_setup(void)
+{
+	int i;
+	int ret;
+
+	/* find the next free available EILVT entry */
+	for (i = 1; i < 4; i++) {
+		if (!eilvt_is_available(i))
+			continue;
+		ret = setup_ibs_ctl(i);
+		if (ret)
+			return ret;
+		return 0;
 	}
 
+	printk(KERN_DEBUG "No EILVT entry available\n");
+
+	return -EBUSY;
+}
+
+static int __init_ibs_nmi(void)
+{
+	int ret;
+
+	if (ibs_eilvt_valid())
+		return 0;
+
+	ret = force_ibs_eilvt_setup();
+	if (ret)
+		return ret;
+
+	if (!ibs_eilvt_valid())
+		return -EFAULT;
+
+	pr_err(FW_BUG "workaround enabled for IBS LVT offset\n");
+
 	return 0;
 }
 

^ permalink raw reply related

* [Xenomai-core] hostrt broken on ARM.
From: Gilles Chanteperdrix @ 2010-10-20  5:02 UTC (permalink / raw)
  To: xenomai-core


Hi,

the hostrt stuff did not compile on ARM, at this chance, I had a look 
and found a few things which I did not like:
- the kernel-space and user-space did not use seqcount implementations 
from the same header, and what is more, seqcount is not available on 2.4
kernels. Since we provide an implementation anyway, I changed the code 
so that only this implementation is used both in kernel-space and 
user-space. Prefixing everything with xn to avoid namespace clashes.
- the xnarch_hostrt_data also had two different definitions, one for 
user-space, one for kernel-space, since this definition is supposed to 
come from newer I-pipe in kernel-space, the code did not compile with 
older I-pipe patches. I separated xnarch_hostrt_data, the structure 
passed by the I-pipe to do_hostrt_event, from xnvdso_hostrt_data, the 
structure, part of the vdso used for exchanges between user-space and 
kernel-space. We can now get xnvdso_hostrt_data defined all the time. We
can probably even move xnvdso_hostrt_data definition to vdso.h
- avoided cycle_t and u32 in order to avoid user-space namespace 
pollution and need for many typedefs with 2.4 kernels. Using unsigned 
long long directly instead of cycle_t revealed a bug in clocktest.c.

Here is the patch.

diff --git a/include/nucleus/Makefile.am b/include/nucleus/Makefile.am
index 9a72b24..5fc1c21 100644
diff --git a/include/nucleus/Makefile.in b/include/nucleus/Makefile.in
index 5e93dc9..a6fa801 100644
diff --git a/include/nucleus/hostrt.h b/include/nucleus/hostrt.h
index 70ffbfe..85b8e88 100644
--- a/include/nucleus/hostrt.h
+++ b/include/nucleus/hostrt.h
@@ -23,32 +23,24 @@
  * 02111-1307, USA.
  */
 
-#include <nucleus/types.h>
-#ifdef __KERNEL__
-#include <asm-generic/xenomai/system.h>
-#else /* !__KERNEL__ */
+#ifndef __KERNEL__
 #include <time.h>
 #include <sys/types.h>
-#include <nucleus/seqlock_user.h>
-typedef u_int32_t u32;
-typedef u_int64_t cycle_t;
+#else /* __KERNEL__ */
+#include <asm-generic/xenomai/system.h>
+#endif /* __KERNEL__ */
+#include <nucleus/seqlock.h>
 
-/*
- * xnarch_hostrt_data must be kept in sync with the corresponding ipipe
- * definitions in ipipe_tickdev.h We cannot directly include the file
- * here because the definitions are also required in Xenomai userland.
- */
-struct xnarch_hostrt_data {
+struct xnvdso_hostrt_data {
 	short live;
-	seqcount_t seqcount;
+	xnseqcount_t seqcount;
 	time_t wall_time_sec;
-	u32 wall_time_nsec;
+	unsigned wall_time_nsec;
 	struct timespec wall_to_monotonic;
-	cycle_t cycle_last;
-	cycle_t mask;
-	u32 mult;
-	u32 shift;
+	unsigned long long cycle_last;
+	unsigned long long mask;
+	unsigned mult;
+	unsigned shift;
 };
-#endif /* !__KERNEL__ */
 
 #endif
diff --git a/include/nucleus/seqlock.h b/include/nucleus/seqlock.h
new file mode 100644
index 0000000..897d411
--- /dev/null
+++ b/include/nucleus/seqlock.h
@@ -0,0 +1,57 @@
+#ifndef __SEQLOCK_H
+#define __SEQLOCK_H
+
+/* Originally from the linux kernel, adapted for userland and Xenomai */
+
+#include <asm/xenomai/atomic.h>
+
+typedef struct xnseqcount {
+	unsigned sequence;
+} xnseqcount_t;
+
+#define XNSEQCNT_ZERO { 0 }
+#define xnseqcount_init(x) do { *(x) = (xnseqcount_t) SEQCNT_ZERO; } while (0)
+
+/* Start of read using pointer to a sequence counter only.  */
+static inline unsigned xnread_seqcount_begin(const xnseqcount_t *s)
+{
+	unsigned ret;
+
+repeat:
+	ret = s->sequence;
+	xnarch_read_memory_barrier();
+	if (unlikely(ret & 1)) {
+		cpu_relax();
+		goto repeat;
+	}
+	return ret;
+}
+
+/*
+ * Test if reader processed invalid data because sequence number has changed.
+ */
+static inline int xnread_seqcount_retry(const xnseqcount_t *s, unsigned start)
+{
+	xnarch_read_memory_barrier();
+
+	return s->sequence != start;
+}
+
+
+/*
+ * The sequence counter only protects readers from concurrent writers.
+ * Writers must use their own locking.
+ */
+static inline void xnwrite_seqcount_begin(xnseqcount_t *s)
+{
+	s->sequence++;
+	xnarch_write_memory_barrier();
+}
+
+static inline void xnwrite_seqcount_end(xnseqcount_t *s)
+{
+	xnarch_write_memory_barrier();
+	s->sequence++;
+}
+
+#endif /* __SEQLOCK_H */
diff --git a/include/nucleus/seqlock_user.h b/include/nucleus/seqlock_user.h
deleted file mode 100644
index 598d4da..0000000
--- a/include/nucleus/seqlock_user.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef __SEQLOCK_USER_H
-#define __SEQLOCK_USER_H
-
-/* Originally from the linux kernel, adapted for userland and Xenomai */
-
-#include <asm/xenomai/atomic.h>
-
-typedef struct seqcount {
-	unsigned sequence;
-} seqcount_t;
-
-#define SEQCNT_ZERO { 0 }
-#define seqcount_init(x) do { *(x) = (seqcount_t) SEQCNT_ZERO; } while (0)
-
-/* Start of read using pointer to a sequence counter only.  */
-static inline unsigned read_seqcount_begin(const seqcount_t *s)
-{
-	unsigned ret;
-
-repeat:
-	ret = s->sequence;
-	xnarch_read_memory_barrier();
-	if (unlikely(ret & 1)) {
-		cpu_relax();
-		goto repeat;
-	}
-	return ret;
-}
-
-/*
- * Test if reader processed invalid data because sequence number has changed.
- */
-static inline int read_seqcount_retry(const seqcount_t *s, unsigned start)
-{
-	xnarch_read_memory_barrier();
-
-	return s->sequence != start;
-}
-
-
-/*
- * The sequence counter only protects readers from concurrent writers.
- * Writers must use their own locking.
- */
-static inline void write_seqcount_begin(seqcount_t *s)
-{
-	s->sequence++;
-	xnarch_write_memory_barrier();
-}
-
-static inline void write_seqcount_end(seqcount_t *s)
-{
-	xnarch_write_memory_barrier();
-	s->sequence++;
-}
-
-#endif
diff --git a/include/nucleus/vdso.h b/include/nucleus/vdso.h
index bce4c5a..279574b 100644
--- a/include/nucleus/vdso.h
+++ b/include/nucleus/vdso.h
@@ -34,7 +34,7 @@
 struct xnvdso {
 	unsigned long long features;
 
-	struct xnarch_hostrt_data hostrt_data;
+	struct xnvdso_hostrt_data hostrt_data;
 	/*
 	 * Embed further domain specific structures that
 	 * describe the shared data here
@@ -61,7 +61,7 @@ struct xnvdso {
 
 extern struct xnvdso *nkvdso;
 
-static inline struct xnarch_hostrt_data *get_hostrt_data(void)
+static inline struct xnvdso_hostrt_data *get_hostrt_data(void)
 {
 	return &nkvdso->hostrt_data;
 }
diff --git a/ksrc/nucleus/module.c b/ksrc/nucleus/module.c
index 3f962ba..fc8ceac 100644
--- a/ksrc/nucleus/module.c
+++ b/ksrc/nucleus/module.c
@@ -69,7 +69,7 @@ static inline void do_hostrt_event(struct xnarch_hostrt_data *hostrt)
 	 */
 
 	spin_lock_irqsave(&__hostrtlock, flags);
-	write_seqcount_begin(&nkvdso->hostrt_data.seqcount);
+	xnwrite_seqcount_begin(&nkvdso->hostrt_data.seqcount);
 
 	nkvdso->hostrt_data.live = 1;
 	nkvdso->hostrt_data.cycle_last = hostrt->cycle_last;
@@ -80,7 +80,7 @@ static inline void do_hostrt_event(struct xnarch_hostrt_data *hostrt)
 	nkvdso->hostrt_data.wall_time_nsec = hostrt->wall_time_nsec;
 	nkvdso->hostrt_data.wall_to_monotonic = hostrt->wall_to_monotonic;
 
-	write_seqcount_end(&nkvdso->hostrt_data.seqcount);
+	xnwrite_seqcount_end(&nkvdso->hostrt_data.seqcount);
 	spin_unlock_irqrestore(&__hostrtlock, flags);
 }
 
diff --git a/src/skins/posix/clock.c b/src/skins/posix/clock.c
index 7232c48..4f2171b 100644
--- a/src/skins/posix/clock.c
+++ b/src/skins/posix/clock.c
@@ -25,7 +25,6 @@
 #include <time.h>
 #include <asm/xenomai/arith.h>
 #include <asm-generic/xenomai/timeconv.h>
-#include <nucleus/seqlock_user.h>
 #include <sys/types.h>
 #include <nucleus/vdso.h>
 
@@ -63,9 +62,9 @@ int __do_clock_host_realtime(struct timespec *ts, void *tzp)
 {
 #ifdef XNARCH_HAVE_NONPRIV_TSC
 	unsigned int seq;
-	cycle_t now, base, mask, cycle_delta;
+	unsigned long long now, base, mask, cycle_delta;
 	unsigned long mult, shift, nsec, rem;
-	struct xnarch_hostrt_data *hostrt_data;
+	struct xnvdso_hostrt_data *hostrt_data;
 
 	if (!xnvdso_test_feature(XNVDSO_FEAT_HOST_REALTIME))
 		return -1;
@@ -80,7 +79,7 @@ int __do_clock_host_realtime(struct timespec *ts, void *tzp)
 	 * mechanism in the kernel.
 	 */
 retry:
-	seq = read_seqcount_begin(&hostrt_data->seqcount);
+	seq = xnread_seqcount_begin(&hostrt_data->seqcount);
 
 	now = __xn_rdtsc();
 	base = hostrt_data->cycle_last;
@@ -92,7 +91,7 @@ retry:
 
 	/* If the data changed during the read, try the
 	   alternative data element */
-	if (read_seqcount_retry(&hostrt_data->seqcount, seq))
+	if (xnread_seqcount_retry(&hostrt_data->seqcount, seq))
 		goto retry;
 
 	cycle_delta = (now - base) & mask;
diff --git a/src/testsuite/clocktest/clocktest.c b/src/testsuite/clocktest/clocktest.c
index bf4feb6..038cfbc 100644
--- a/src/testsuite/clocktest/clocktest.c
+++ b/src/testsuite/clocktest/clocktest.c
@@ -99,8 +99,8 @@ static void show_hostrt_diagnostics(void)
 	       (intmax_t)nkvdso->hostrt_data.wall_to_monotonic.tv_sec);
 	printf("         tv_nsec : %ld\n",
 	       nkvdso->hostrt_data.wall_to_monotonic.tv_nsec);
-	printf("cycle_last       : %lu\n", nkvdso->hostrt_data.cycle_last);
-	printf("mask             : 0x%lx\n", nkvdso->hostrt_data.mask);
+	printf("cycle_last       : %Lu\n", nkvdso->hostrt_data.cycle_last);
+	printf("mask             : 0x%Lx\n", nkvdso->hostrt_data.mask);
 	printf("mult             : %u\n", nkvdso->hostrt_data.mult);
 	printf("shift            : %u\n\n", nkvdso->hostrt_data.shift);
 }

Everybody OK?

-- 
                                                                Gilles.


^ permalink raw reply related

* [tip:irq/core] apic, x86: Check if EILVT APIC registers are available (AMD only)
From: tip-bot for Robert Richter @ 2010-10-20  5:01 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, robert.richter, tglx, mingo
In-Reply-To: <1286360874-1471-2-git-send-email-robert.richter@amd.com>

Commit-ID:  a68c439b1966c91f0ef474e2bf275d6792312726
Gitweb:     http://git.kernel.org/tip/a68c439b1966c91f0ef474e2bf275d6792312726
Author:     Robert Richter <robert.richter@amd.com>
AuthorDate: Wed, 6 Oct 2010 12:27:53 +0200
Committer:  Ingo Molnar <mingo@elte.hu>
CommitDate: Wed, 20 Oct 2010 04:42:13 +0200

apic, x86: Check if EILVT APIC registers are available (AMD only)

This patch implements checks for the availability of LVT entries
(APIC500-530) and reserves it if used. The check becomes
necessary since we want to let the BIOS provide the LVT offsets.
 The offsets should be determined by the subsystems using it
like those for MCE threshold or IBS.  On K8 only offset 0
(APIC500) and MCE interrupts are supported. Beginning with
family 10h at least 4 offsets are available.

Since offsets must be consistent for all cores, we keep track of
the LVT offsets in software and reserve the offset for the same
vector also to be used on other cores. An offset is freed by
setting the entry to APIC_EILVT_MASKED.

If the BIOS is right, there should be no conflicts. Otherwise a
"[Firmware Bug]: ..." error message is generated. However, if
software does not properly determines the offsets, it is not
necessarily a BIOS bug.

Signed-off-by: Robert Richter <robert.richter@amd.com>
LKML-Reference: <1286360874-1471-2-git-send-email-robert.richter@amd.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/include/asm/apicdef.h |    1 +
 arch/x86/kernel/apic/apic.c    |   83 +++++++++++++++++++++++++++++++++++----
 2 files changed, 75 insertions(+), 9 deletions(-)

diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
index 7fe3b30..a859ca4 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -131,6 +131,7 @@
 #define APIC_EILVTn(n)	(0x500 + 0x10 * n)
 #define		APIC_EILVT_NR_AMD_K8	1	/* # of extended interrupts */
 #define		APIC_EILVT_NR_AMD_10H	4
+#define		APIC_EILVT_NR_MAX	APIC_EILVT_NR_AMD_10H
 #define		APIC_EILVT_LVTOFF(x)	(((x) >> 4) & 0xF)
 #define		APIC_EILVT_MSG_FIX	0x0
 #define		APIC_EILVT_MSG_SMI	0x2
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 8cf86fb..2bfeafd 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -52,6 +52,7 @@
 #include <asm/mce.h>
 #include <asm/kvm_para.h>
 #include <asm/tsc.h>
+#include <asm/atomic.h>
 
 unsigned int num_processors;
 
@@ -370,24 +371,88 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
 }
 
 /*
- * Setup extended LVT, AMD specific (K8, family 10h)
+ * Setup extended LVT, AMD specific
  *
- * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and
- * MCE interrupts are supported. Thus MCE offset must be set to 0.
+ * Software should use the LVT offsets the BIOS provides.  The offsets
+ * are determined by the subsystems using it like those for MCE
+ * threshold or IBS.  On K8 only offset 0 (APIC500) and MCE interrupts
+ * are supported. Beginning with family 10h at least 4 offsets are
+ * available.
  *
- * If mask=1, the LVT entry does not generate interrupts while mask=0
- * enables the vector. See also the BKDGs.
+ * Since the offsets must be consistent for all cores, we keep track
+ * of the LVT offsets in software and reserve the offset for the same
+ * vector also to be used on other cores. An offset is freed by
+ * setting the entry to APIC_EILVT_MASKED.
+ *
+ * If the BIOS is right, there should be no conflicts. Otherwise a
+ * "[Firmware Bug]: ..." error message is generated. However, if
+ * software does not properly determines the offsets, it is not
+ * necessarily a BIOS bug.
  */
 
 #define APIC_EILVT_LVTOFF_MCE 0
 #define APIC_EILVT_LVTOFF_IBS 1
 
-static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask)
+static atomic_t eilvt_offsets[APIC_EILVT_NR_MAX];
+
+static inline int eilvt_entry_is_changeable(unsigned int old, unsigned int new)
+{
+	return (old & APIC_EILVT_MASKED)
+		|| (new == APIC_EILVT_MASKED)
+		|| ((new & ~APIC_EILVT_MASKED) == old);
+}
+
+static unsigned int reserve_eilvt_offset(int offset, unsigned int new)
+{
+	unsigned int rsvd;			/* 0: uninitialized */
+
+	if (offset >= APIC_EILVT_NR_MAX)
+		return ~0;
+
+	rsvd = atomic_read(&eilvt_offsets[offset]) & ~APIC_EILVT_MASKED;
+	do {
+		if (rsvd &&
+		    !eilvt_entry_is_changeable(rsvd, new))
+			/* may not change if vectors are different */
+			return rsvd;
+		rsvd = atomic_cmpxchg(&eilvt_offsets[offset], rsvd, new);
+	} while (rsvd != new);
+
+	return new;
+}
+
+/*
+ * If mask=1, the LVT entry does not generate interrupts while mask=0
+ * enables the vector. See also the BKDGs.
+ */
+
+static int setup_APIC_eilvt(u8 offset, u8 vector, u8 msg_type, u8 mask)
 {
-	unsigned long reg = (lvt_off << 4) + APIC_EILVTn(0);
-	unsigned int  v   = (mask << 16) | (msg_type << 8) | vector;
+	unsigned long reg = APIC_EILVTn(offset);
+	unsigned int new, old, reserved;
+
+	new = (mask << 16) | (msg_type << 8) | vector;
+	old = apic_read(reg);
+	reserved = reserve_eilvt_offset(offset, new);
 
-	apic_write(reg, v);
+	if (reserved != new) {
+		pr_err(FW_BUG "cpu %d, try to setup vector 0x%x, but "
+		       "vector 0x%x was already reserved by another core, "
+		       "APIC%lX=0x%x\n",
+		       smp_processor_id(), new, reserved, reg, old);
+		return -EINVAL;
+	}
+
+	if (!eilvt_entry_is_changeable(old, new)) {
+		pr_err(FW_BUG "cpu %d, try to setup vector 0x%x but "
+		       "register already in use, APIC%lX=0x%x\n",
+		       smp_processor_id(), new, reg, old);
+		return -EBUSY;
+	}
+
+	apic_write(reg, new);
+
+	return 0;
 }
 
 u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask)

^ permalink raw reply related

* [PATCH, RFC] Remove dependency of plat-orion time code on mach directory includes.
From: Lennert Buytenhek @ 2010-10-20  5:01 UTC (permalink / raw)
  To: linux-arm-kernel

This patch makes the various mach dirs that use plat-orion pass in
timer and bridge addresses into orion_time_init() explicitly, instead
of having plat-orion get those values by including a mach dir include
file -- the latter mechanism is problematic if you want to support
multiple ARM platforms in the same kernel image.

Signed-off-by: Lennert Buytenhek <buytenh@secretlab.ca>

diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index f7a1258..7ea13ef 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -540,7 +540,10 @@ static int get_tclk(void)
 
 static void dove_timer_init(void)
 {
-	orion_time_init(IRQ_DOVE_BRIDGE, get_tclk());
+	orion_time_init((void __iomem *)BRIDGE_VIRT_BASE,
+			BRIDGE_INT_TIMER1_CLR,
+			(void __iomem *)TIMER_VIRT_BASE,
+			IRQ_DOVE_BRIDGE, get_tclk());
 }
 
 struct sys_timer dove_timer = {
diff --git a/arch/arm/mach-dove/include/mach/bridge-regs.h b/arch/arm/mach-dove/include/mach/bridge-regs.h
index 214a4c3..226949d 100644
--- a/arch/arm/mach-dove/include/mach/bridge-regs.h
+++ b/arch/arm/mach-dove/include/mach/bridge-regs.h
@@ -26,10 +26,6 @@
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE | 0x010c)
 #define  SOFT_RESET		0x00000001
 
-#define BRIDGE_CAUSE		(BRIDGE_VIRT_BASE | 0x0110)
-#define BRIDGE_MASK		(BRIDGE_VIRT_BASE | 0x0114)
-#define  BRIDGE_INT_TIMER0	0x0002
-#define  BRIDGE_INT_TIMER1	0x0004
 #define  BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
 #define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index 1c82d42..bebc0c5 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -865,7 +865,11 @@ int __init kirkwood_find_tclk(void)
 static void __init kirkwood_timer_init(void)
 {
 	kirkwood_tclk = kirkwood_find_tclk();
-	orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
+
+	orion_time_init((void __iomem *)BRIDGE_VIRT_BASE,
+			BRIDGE_INT_TIMER1_CLR,
+			(void __iomem *)TIMER_VIRT_BASE,
+			IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
 }
 
 struct sys_timer kirkwood_timer = {
diff --git a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
index aff0e13..957bd79 100644
--- a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
+++ b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
@@ -29,9 +29,6 @@
 #define BRIDGE_CAUSE		(BRIDGE_VIRT_BASE | 0x0110)
 #define WDT_INT_REQ		0x0008
 
-#define BRIDGE_MASK		(BRIDGE_VIRT_BASE | 0x0114)
-#define BRIDGE_INT_TIMER0	0x0002
-#define BRIDGE_INT_TIMER1	0x0004
 #define BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
 #define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
diff --git a/arch/arm/mach-kirkwood/netspace_v2-setup.c b/arch/arm/mach-kirkwood/netspace_v2-setup.c
index d26bf32..269677c 100644
--- a/arch/arm/mach-kirkwood/netspace_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netspace_v2-setup.c
@@ -39,6 +39,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <mach/kirkwood.h>
+#include <mach/bridge-regs.h>
 #include <mach/leds-ns2.h>
 #include <plat/time.h>
 #include "common.h"
@@ -230,7 +231,11 @@ static struct platform_device netspace_v2_leds = {
 static void netspace_v2_timer_init(void)
 {
 	kirkwood_tclk = 166666667;
-	orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
+
+	orion_time_init((void __iomem *)BRIDGE_VIRT_BASE,
+			BRIDGE_INT_TIMER1_CLR,
+			(void __iomem *)TIMER_VIRT_BASE,
+			IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
 }
 
 struct sys_timer netspace_v2_timer = {
diff --git a/arch/arm/mach-kirkwood/netxbig_v2-setup.c b/arch/arm/mach-kirkwood/netxbig_v2-setup.c
index 2bd14c5..5f41e14 100644
--- a/arch/arm/mach-kirkwood/netxbig_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netxbig_v2-setup.c
@@ -38,6 +38,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <mach/kirkwood.h>
+#include <mach/bridge-regs.h>
 #include <plat/time.h>
 #include "common.h"
 #include "mpp.h"
@@ -252,7 +253,11 @@ static struct platform_device netxbig_v2_gpio_buttons = {
 static void netxbig_v2_timer_init(void)
 {
 	kirkwood_tclk = 166666667;
-	orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
+
+	orion_time_init((void __iomem *)BRIDGE_VIRT_BASE,
+			BRIDGE_INT_TIMER1_CLR,
+			(void __iomem *)TIMER_VIRT_BASE,
+			IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
 }
 
 struct sys_timer netxbig_v2_timer = {
diff --git a/arch/arm/mach-loki/common.c b/arch/arm/mach-loki/common.c
index 818f19d..26aba6c 100644
--- a/arch/arm/mach-loki/common.c
+++ b/arch/arm/mach-loki/common.c
@@ -18,6 +18,7 @@
 #include <asm/timex.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
+#include <mach/bridge-regs.h>
 #include <mach/loki.h>
 #include <plat/orion_nand.h>
 #include <plat/time.h>
@@ -292,7 +293,10 @@ void __init loki_uart1_init(void)
  ****************************************************************************/
 static void loki_timer_init(void)
 {
-	orion_time_init(IRQ_LOKI_BRIDGE, LOKI_TCLK);
+	orion_time_init((void __iomem *)BRIDGE_VIRT_BASE,
+			BRIDGE_INT_TIMER1_CLR,
+			(void __iomem *)TIMER_VIRT_BASE,
+			IRQ_LOKI_BRIDGE, LOKI_TCLK);
 }
 
 struct sys_timer loki_timer = {
diff --git a/arch/arm/mach-loki/include/mach/bridge-regs.h b/arch/arm/mach-loki/include/mach/bridge-regs.h
index a3fabf7..fd87732 100644
--- a/arch/arm/mach-loki/include/mach/bridge-regs.h
+++ b/arch/arm/mach-loki/include/mach/bridge-regs.h
@@ -17,11 +17,6 @@
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE | 0x010c)
 #define SOFT_RESET		0x00000001
 
-#define BRIDGE_CAUSE		(BRIDGE_VIRT_BASE | 0x0110)
-
-#define BRIDGE_MASK		(BRIDGE_VIRT_BASE | 0x0114)
-#define BRIDGE_INT_TIMER0	0x0002
-#define BRIDGE_INT_TIMER1	0x0004
 #define BRIDGE_INT_TIMER1_CLR	0x0004
 
 #define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c
index 08465eb..db926b2 100644
--- a/arch/arm/mach-mv78xx0/common.c
+++ b/arch/arm/mach-mv78xx0/common.c
@@ -820,7 +820,10 @@ void __init mv78xx0_uart3_init(void)
  ****************************************************************************/
 static void mv78xx0_timer_init(void)
 {
-	orion_time_init(IRQ_MV78XX0_TIMER_1, get_tclk());
+	orion_time_init((void __iomem *)BRIDGE_VIRT_BASE,
+			BRIDGE_INT_TIMER1_CLR,
+			(void __iomem *)TIMER_VIRT_BASE,
+			IRQ_MV78XX0_TIMER_1, get_tclk());
 }
 
 struct sys_timer mv78xx0_timer = {
diff --git a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
index 2d14c4f..c64dbb9 100644
--- a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
+++ b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
@@ -20,10 +20,6 @@
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE | 0x010c)
 #define SOFT_RESET		0x00000001
 
-#define BRIDGE_CAUSE		(BRIDGE_VIRT_BASE | 0x0110)
-#define BRIDGE_MASK		(BRIDGE_VIRT_BASE | 0x0114)
-#define BRIDGE_INT_TIMER0	0x0002
-#define BRIDGE_INT_TIMER1	0x0004
 #define BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
 #define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index 8dc2c76..682653b 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -26,6 +26,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
+#include <mach/bridge-regs.h>
 #include <mach/hardware.h>
 #include <mach/orion5x.h>
 #include <plat/ehci-orion.h>
@@ -616,7 +617,11 @@ int __init orion5x_find_tclk(void)
 static void orion5x_timer_init(void)
 {
 	orion5x_tclk = orion5x_find_tclk();
-	orion_time_init(IRQ_ORION5X_BRIDGE, orion5x_tclk);
+
+	orion_time_init((void __iomem *)ORION5X_BRIDGE_VIRT_BASE,
+			BRIDGE_INT_TIMER1_CLR,
+			(void __iomem *)TIMER_VIRT_BASE,
+			IRQ_ORION5X_BRIDGE, orion5x_tclk);
 }
 
 struct sys_timer orion5x_timer = {
diff --git a/arch/arm/mach-orion5x/include/mach/bridge-regs.h b/arch/arm/mach-orion5x/include/mach/bridge-regs.h
index 5c9744c..e15a8e0 100644
--- a/arch/arm/mach-orion5x/include/mach/bridge-regs.h
+++ b/arch/arm/mach-orion5x/include/mach/bridge-regs.h
@@ -24,12 +24,8 @@
 
 #define POWER_MNG_CTRL_REG	(ORION5X_BRIDGE_VIRT_BASE | 0x11C)
 
-#define BRIDGE_CAUSE		(ORION5X_BRIDGE_VIRT_BASE | 0x110)
 #define WDT_INT_REQ		0x0008
 
-#define BRIDGE_MASK		(ORION5X_BRIDGE_VIRT_BASE | 0x114)
-#define BRIDGE_INT_TIMER0	0x0002
-#define BRIDGE_INT_TIMER1	0x0004
 #define BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
 #define MAIN_IRQ_CAUSE		(ORION5X_BRIDGE_VIRT_BASE | 0x200)
diff --git a/arch/arm/plat-orion/include/plat/time.h b/arch/arm/plat-orion/include/plat/time.h
index c06ca35..2cf3f4d 100644
--- a/arch/arm/plat-orion/include/plat/time.h
+++ b/arch/arm/plat-orion/include/plat/time.h
@@ -11,7 +11,9 @@
 #ifndef __PLAT_TIME_H
 #define __PLAT_TIME_H
 
-void orion_time_init(unsigned int irq, unsigned int tclk);
+void
+orion_time_init(void __iomem *_bridge_base, u32 _bridge_timer1_clr_mask,
+		void __iomem *_timer_base, unsigned int irq, unsigned int tclk);
 
 
 #endif
diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c
index 715a301..914b88f 100644
--- a/arch/arm/plat-orion/time.c
+++ b/arch/arm/plat-orion/time.c
@@ -18,28 +18,42 @@
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <asm/mach/time.h>
-#include <mach/bridge-regs.h>
-#include <mach/hardware.h>
 
 /*
- * Number of timer ticks per jiffy.
+ * MBus bridge block registers.
  */
-static u32 ticks_per_jiffy;
+#define BRIDGE_CAUSE_OFF	0x0110
+#define BRIDGE_MASK_OFF		0x0114
+#define  BRIDGE_INT_TIMER0	 0x0002
+#define  BRIDGE_INT_TIMER1	 0x0004
 
 
 /*
  * Timer block registers.
  */
-#define TIMER_CTRL		(TIMER_VIRT_BASE + 0x0000)
-#define  TIMER0_EN		0x0001
-#define  TIMER0_RELOAD_EN	0x0002
-#define  TIMER1_EN		0x0004
-#define  TIMER1_RELOAD_EN	0x0008
-#define TIMER0_RELOAD		(TIMER_VIRT_BASE + 0x0010)
-#define TIMER0_VAL		(TIMER_VIRT_BASE + 0x0014)
-#define TIMER1_RELOAD		(TIMER_VIRT_BASE + 0x0018)
-#define TIMER1_VAL		(TIMER_VIRT_BASE + 0x001c)
+#define TIMER_CTRL_OFF		0x0000
+#define  TIMER0_EN		 0x0001
+#define  TIMER0_RELOAD_EN	 0x0002
+#define  TIMER1_EN		 0x0004
+#define  TIMER1_RELOAD_EN	 0x0008
+#define TIMER0_RELOAD_OFF	0x0010
+#define TIMER0_VAL_OFF		0x0014
+#define TIMER1_RELOAD_OFF	0x0018
+#define TIMER1_VAL_OFF		0x001c
+
+
+/*
+ * SoC-specific data.
+ */
+static void __iomem *bridge_base;
+static u32 bridge_timer1_clr_mask;
+static void __iomem *timer_base;
+
+
+/*
+ * Number of timer ticks per jiffy.
+ */
+static u32 ticks_per_jiffy;
 
 
 /*
@@ -57,7 +71,8 @@ static unsigned long tclk2ns_scale;
 
 unsigned long long sched_clock(void)
 {
-	unsigned long long v = cnt32_to_63(0xffffffff - readl(TIMER0_VAL));
+	unsigned long val = readl(timer_base + TIMER0_VAL_OFF);
+	unsigned long long v = cnt32_to_63(0xffffffff - val);
 	return (v * tclk2ns_scale) >> TCLK2NS_SCALE_FACTOR;
 }
 
@@ -78,6 +93,7 @@ static void __init setup_sched_clock(unsigned long tclk)
 	v <<= TCLK2NS_SCALE_FACTOR;
 	v += tclk/2;
 	do_div(v, tclk);
+
 	/*
 	 * We want an even value to automatically clear the top bit
 	 * returned by cnt32_to_63() without an additional run time
@@ -97,7 +113,7 @@ static void __init setup_sched_clock(unsigned long tclk)
  */
 static cycle_t orion_clksrc_read(struct clocksource *cs)
 {
-	return 0xffffffff - readl(TIMER0_VAL);
+	return 0xffffffff - readl(timer_base + TIMER0_VAL_OFF);
 }
 
 static struct clocksource orion_clksrc = {
@@ -128,23 +144,23 @@ orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev)
 	/*
 	 * Clear and enable clockevent timer interrupt.
 	 */
-	writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
+	writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
 
-	u = readl(BRIDGE_MASK);
+	u = readl(bridge_base + BRIDGE_MASK_OFF);
 	u |= BRIDGE_INT_TIMER1;
-	writel(u, BRIDGE_MASK);
+	writel(u, bridge_base + BRIDGE_MASK_OFF);
 
 	/*
 	 * Setup new clockevent timer value.
 	 */
-	writel(delta, TIMER1_VAL);
+	writel(delta, timer_base + TIMER1_VAL_OFF);
 
 	/*
 	 * Enable the timer.
 	 */
-	u = readl(TIMER_CTRL);
+	u = readl(timer_base + TIMER_CTRL_OFF);
 	u = (u & ~TIMER1_RELOAD_EN) | TIMER1_EN;
-	writel(u, TIMER_CTRL);
+	writel(u, timer_base + TIMER_CTRL_OFF);
 
 	local_irq_restore(flags);
 
@@ -162,37 +178,38 @@ orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
 		/*
 		 * Setup timer to fire@1/HZ intervals.
 		 */
-		writel(ticks_per_jiffy - 1, TIMER1_RELOAD);
-		writel(ticks_per_jiffy - 1, TIMER1_VAL);
+		writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD_OFF);
+		writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL_OFF);
 
 		/*
 		 * Enable timer interrupt.
 		 */
-		u = readl(BRIDGE_MASK);
-		writel(u | BRIDGE_INT_TIMER1, BRIDGE_MASK);
+		u = readl(bridge_base + BRIDGE_MASK_OFF);
+		writel(u | BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF);
 
 		/*
 		 * Enable timer.
 		 */
-		u = readl(TIMER_CTRL);
-		writel(u | TIMER1_EN | TIMER1_RELOAD_EN, TIMER_CTRL);
+		u = readl(timer_base + TIMER_CTRL_OFF);
+		writel(u | TIMER1_EN | TIMER1_RELOAD_EN,
+		       timer_base + TIMER_CTRL_OFF);
 	} else {
 		/*
 		 * Disable timer.
 		 */
-		u = readl(TIMER_CTRL);
-		writel(u & ~TIMER1_EN, TIMER_CTRL);
+		u = readl(timer_base + TIMER_CTRL_OFF);
+		writel(u & ~TIMER1_EN, timer_base + TIMER_CTRL_OFF);
 
 		/*
 		 * Disable timer interrupt.
 		 */
-		u = readl(BRIDGE_MASK);
-		writel(u & ~BRIDGE_INT_TIMER1, BRIDGE_MASK);
+		u = readl(bridge_base + BRIDGE_MASK_OFF);
+		writel(u & ~BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF);
 
 		/*
 		 * ACK pending timer interrupt.
 		 */
-		writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
+		writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
 
 	}
 	local_irq_restore(flags);
@@ -212,7 +229,7 @@ static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
 	/*
 	 * ACK timer interrupt and call event handler.
 	 */
-	writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
+	writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
 	orion_clkevt.event_handler(&orion_clkevt);
 
 	return IRQ_HANDLED;
@@ -224,32 +241,41 @@ static struct irqaction orion_timer_irq = {
 	.handler	= orion_timer_interrupt
 };
 
-void __init orion_time_init(unsigned int irq, unsigned int tclk)
+void __init
+orion_time_init(void __iomem *_bridge_base, u32 _bridge_timer1_clr_mask,
+		void __iomem *_timer_base, unsigned int irq, unsigned int tclk)
 {
 	u32 u;
 
+	/*
+	 * Set SoC-specific data.
+	 */
+	bridge_base = _bridge_base;
+	bridge_timer1_clr_mask = _bridge_timer1_clr_mask;
+	timer_base = _timer_base;
+
 	ticks_per_jiffy = (tclk + HZ/2) / HZ;
 
 	/*
-	 * Set scale and timer for sched_clock
+	 * Set scale and timer for sched_clock.
 	 */
 	setup_sched_clock(tclk);
 
 	/*
 	 * Setup free-running clocksource timer (interrupts
-	 * disabled.)
+	 * disabled).
 	 */
-	writel(0xffffffff, TIMER0_VAL);
-	writel(0xffffffff, TIMER0_RELOAD);
-	u = readl(BRIDGE_MASK);
-	writel(u & ~BRIDGE_INT_TIMER0, BRIDGE_MASK);
-	u = readl(TIMER_CTRL);
-	writel(u | TIMER0_EN | TIMER0_RELOAD_EN, TIMER_CTRL);
+	writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
+	writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
+	u = readl(bridge_base + BRIDGE_MASK_OFF);
+	writel(u & ~BRIDGE_INT_TIMER0, bridge_base + BRIDGE_MASK_OFF);
+	u = readl(timer_base + TIMER_CTRL_OFF);
+	writel(u | TIMER0_EN | TIMER0_RELOAD_EN, timer_base + TIMER_CTRL_OFF);
 	orion_clksrc.mult = clocksource_hz2mult(tclk, orion_clksrc.shift);
 	clocksource_register(&orion_clksrc);
 
 	/*
-	 * Setup clockevent timer (interrupt-driven.)
+	 * Setup clockevent timer (interrupt-driven).
 	 */
 	setup_irq(irq, &orion_timer_irq);
 	orion_clkevt.mult = div_sc(tclk, NSEC_PER_SEC, orion_clkevt.shift);
-- 

^ permalink raw reply related


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.