* [PATCH] Use SLB size from the device tree
From: Michael Neuling @ 2007-12-06 6:24 UTC (permalink / raw)
To: Paul Mackerras; +Cc: Olof Johansson, linuxppc-dev, Will Schmidt
In-Reply-To: <18263.27999.950921.122870@cargo.ozlabs.ibm.com>
Currently we hardwire the number of SLBs but PAPR says we export an
ibm,slb-size property to specify the number of SLB entries. This
patch uses this property instead of assuming 64. If no property is
found, we assume 64 entries as before.
This soft patches the SLB handler, so it won't change performance at
all.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
> On 32-bit platforms (e.g. powermac) I get:
>
> /home/paulus/kernel/powerpc/arch/powerpc/kernel/prom.c: In function 'check_cp
u_slb_size':
> /home/paulus/kernel/powerpc/arch/powerpc/kernel/prom.c:592: error: 'mmu_slb_s
ize' undeclared (first use in this function)
> /home/paulus/kernel/powerpc/arch/powerpc/kernel/prom.c:592: error: (Each unde
clared identifier is reported only once
> /home/paulus/kernel/powerpc/arch/powerpc/kernel/prom.c:592: error: for each f
unction it appears in.)
> make[2]: *** [arch/powerpc/kernel/prom.o] Error 1
Here's a nickel kid, buy yourself another 32bits! :-)
Or in other words.... Sorry about that! Below should fix it.
arch/powerpc/kernel/prom.c | 15 +++++++++++++++
arch/powerpc/mm/hash_utils_64.c | 1 +
arch/powerpc/mm/slb.c | 3 +++
arch/powerpc/mm/slb_low.S | 5 +++--
arch/powerpc/platforms/pasemi/setup.c | 3 ++-
arch/powerpc/xmon/xmon.c | 2 +-
include/asm-powerpc/mmu-hash64.h | 1 +
include/asm-powerpc/reg.h | 6 ------
8 files changed, 26 insertions(+), 10 deletions(-)
Index: linux-2.6-ozlabs/arch/powerpc/kernel/prom.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/prom.c
+++ linux-2.6-ozlabs/arch/powerpc/kernel/prom.c
@@ -583,6 +583,20 @@ static void __init check_cpu_pa_features
ibm_pa_features, ARRAY_SIZE(ibm_pa_features));
}
+#ifdef CONFIG_PPC64
+static void __init check_cpu_slb_size(unsigned long node)
+{
+ u32 *slb_size_ptr;
+
+ slb_size_ptr = of_get_flat_dt_prop(node, "ibm,slb-size", NULL);
+ if (slb_size_ptr != NULL) {
+ mmu_slb_size = *slb_size_ptr;
+ }
+}
+#else
+#define check_cpu_slb_size(node) do { } while(0)
+#endif
+
static struct feature_property {
const char *name;
u32 min_value;
@@ -713,6 +727,7 @@ static int __init early_init_dt_scan_cpu
check_cpu_feature_properties(node);
check_cpu_pa_features(node);
+ check_cpu_slb_size(node);
#ifdef CONFIG_PPC_PSERIES
if (nthreads > 1)
Index: linux-2.6-ozlabs/arch/powerpc/mm/hash_utils_64.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/mm/hash_utils_64.c
+++ linux-2.6-ozlabs/arch/powerpc/mm/hash_utils_64.c
@@ -96,6 +96,7 @@ int mmu_vmalloc_psize = MMU_PAGE_4K;
int mmu_io_psize = MMU_PAGE_4K;
int mmu_kernel_ssize = MMU_SEGSIZE_256M;
int mmu_highuser_ssize = MMU_SEGSIZE_256M;
+u16 mmu_slb_size = 64;
#ifdef CONFIG_HUGETLB_PAGE
int mmu_huge_psize = MMU_PAGE_16M;
unsigned int HPAGE_SHIFT;
Index: linux-2.6-ozlabs/arch/powerpc/mm/slb.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/mm/slb.c
+++ linux-2.6-ozlabs/arch/powerpc/mm/slb.c
@@ -256,6 +256,7 @@ void slb_initialize(void)
static int slb_encoding_inited;
extern unsigned int *slb_miss_kernel_load_linear;
extern unsigned int *slb_miss_kernel_load_io;
+ extern unsigned int *slb_compare_rr_to_size;
/* Prepare our SLB miss handler based on our page size */
linear_llp = mmu_psize_defs[mmu_linear_psize].sllp;
@@ -269,6 +270,8 @@ void slb_initialize(void)
SLB_VSID_KERNEL | linear_llp);
patch_slb_encoding(slb_miss_kernel_load_io,
SLB_VSID_KERNEL | io_llp);
+ patch_slb_encoding(slb_compare_rr_to_size,
+ mmu_slb_size);
DBG("SLB: linear LLP = %04x\n", linear_llp);
DBG("SLB: io LLP = %04x\n", io_llp);
Index: linux-2.6-ozlabs/arch/powerpc/mm/slb_low.S
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/mm/slb_low.S
+++ linux-2.6-ozlabs/arch/powerpc/mm/slb_low.S
@@ -227,8 +227,9 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISER
7: ld r10,PACASTABRR(r13)
addi r10,r10,1
- /* use a cpu feature mask if we ever change our slb size */
- cmpldi r10,SLB_NUM_ENTRIES
+ /* This gets soft patched on boot. */
+_GLOBAL(slb_compare_rr_to_size)
+ cmpldi r10,0
blt+ 4f
li r10,SLB_NUM_BOLTED
Index: linux-2.6-ozlabs/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/platforms/pasemi/setup.c
+++ linux-2.6-ozlabs/arch/powerpc/platforms/pasemi/setup.c
@@ -36,6 +36,7 @@
#include <asm/smp.h>
#include <asm/time.h>
#include <asm/of_platform.h>
+#include <asm/mmu.h>
#include <pcmcia/ss.h>
#include <pcmcia/cistpl.h>
@@ -295,7 +296,7 @@ static int pas_machine_check_handler(str
int i;
printk(KERN_ERR "slb contents:\n");
- for (i = 0; i < SLB_NUM_ENTRIES; i++) {
+ for (i = 0; i < mmu_slb_size; i++) {
asm volatile("slbmfee %0,%1" : "=r" (e) : "r" (i));
asm volatile("slbmfev %0,%1" : "=r" (v) : "r" (i));
printk(KERN_ERR "%02d %016lx %016lx\n", i, e, v);
Index: linux-2.6-ozlabs/arch/powerpc/xmon/xmon.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/xmon/xmon.c
+++ linux-2.6-ozlabs/arch/powerpc/xmon/xmon.c
@@ -2543,7 +2543,7 @@ static void dump_slb(void)
printf("SLB contents of cpu %x\n", smp_processor_id());
- for (i = 0; i < SLB_NUM_ENTRIES; i++) {
+ for (i = 0; i < mmu_slb_size; i++) {
asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i));
printf("%02d %016lx ", i, tmp);
Index: linux-2.6-ozlabs/include/asm-powerpc/mmu-hash64.h
===================================================================
--- linux-2.6-ozlabs.orig/include/asm-powerpc/mmu-hash64.h
+++ linux-2.6-ozlabs/include/asm-powerpc/mmu-hash64.h
@@ -180,6 +180,7 @@ extern int mmu_vmalloc_psize;
extern int mmu_io_psize;
extern int mmu_kernel_ssize;
extern int mmu_highuser_ssize;
+extern u16 mmu_slb_size;
/*
* If the processor supports 64k normal pages but not 64k cache
Index: linux-2.6-ozlabs/include/asm-powerpc/reg.h
===================================================================
--- linux-2.6-ozlabs.orig/include/asm-powerpc/reg.h
+++ linux-2.6-ozlabs/include/asm-powerpc/reg.h
@@ -691,12 +691,6 @@
#define PV_BE 0x0070
#define PV_PA6T 0x0090
-/*
- * Number of entries in the SLB. If this ever changes we should handle
- * it with a use a cpu feature fixup.
- */
-#define SLB_NUM_ENTRIES 64
-
/* Macros for setting and retrieving special purpose registers */
#ifndef __ASSEMBLY__
#define mfmsr() ({unsigned long rval; \
^ permalink raw reply
* Re: Link up/down messages from 5200 ethernet driver
From: Jon Smirl @ 2007-12-06 6:19 UTC (permalink / raw)
To: Grant Likely, Matt Sealey; +Cc: PowerPC dev list, Domen Puncer
In-Reply-To: <fa686aa40712052208o3722cf60qfcac9b56ecc6184f@mail.gmail.com>
T24gMTIvNi8wNywgR3JhbnQgTGlrZWx5IDxncmFudC5saWtlbHlAc2VjcmV0bGFiLmNhPiB3cm90
ZToKPiBPbiAxMi81LzA3LCBKb24gU21pcmwgPGpvbnNtaXJsQGdtYWlsLmNvbT4gd3JvdGU6Cj4g
PiBPbiAxMi82LzA3LCBKb24gU21pcmwgPGpvbnNtaXJsQGdtYWlsLmNvbT4gd3JvdGU6Cj4gPiA+
IE9uIDEyLzUvMDcsIEdyYW50IExpa2VseSA8Z3JhbnQubGlrZWx5QHNlY3JldGxhYi5jYT4gd3Jv
dGU6Cj4gPiA+ID4gT24gMTIvNS8wNywgSm9uIFNtaXJsIDxqb25zbWlybEBnbWFpbC5jb20+IHdy
b3RlOgo+ID4gPiA+ID4gV2h5IGRvZXMgdGhlIGZlYzUyMDAgZHJpdmVyIHNvbWV0aW1lcyBub3Qg
cHJpbnQgJ1BIWScgY29ycmVjdGx5Pwo+ID4gPiA+ID4KPiA+ID4gPiA+IHBoeUNPUkUtTVBDNTIw
MEItdGlueSBsb2dpbjogVNikVu+/vSBmMDAwMzAwMDoxMCAtIExpbmsgaXMgRG93bgo+ID4gPiA+
ID4gVO+/vVk6IGYwMDAzMDAwOjEwIC0gTGluayBpcyBVcCAtIDEwMC9GdWxsCj4gPiA+ID4gPiBU
77+9WTogZjAwMDMwMDA6MTAgLSBMaW5rIGlzIERvd24KPiA+ID4gPiA+IFBIWTogZjAwMDMwMDA6
MTAgLSBMaW5rIGlzIFVwIC0gMTAwL0Z1bGwKPiA+ID4gPgo+ID4gPiA+IFdlaXJkOyB0aGF0IGxp
bmUgY29tZXMgZnJvbSBkcml2ZXJzL25ldC9waHkvcGh5LmMgaW4KPiA+ID4gPiBwaHlfcHJpbnRf
c3RhdHVzKCksIGFuZCBpdCdzIGp1c3QgYSBhIHByX2luZm8gc3RhdGVtZW50LiAgSSBzdXBwb3Nl
IGl0Cj4gPiA+ID4gbWlnaHQgYmUgYSBzdGFjayBvdmVycnVuLCBidXQgSSdkIGV4cGVjdCBtb3Jl
IHNldmVyZSBzeW1wdG9tcyBpZiB0aGF0Cj4gPiA+ID4gd2FzIHRoZSBjYXNlLgo+ID4gPiA+Cj4g
PiA+ID4gVGhhdCAqbG9va3MqIGxpa2UgYSBzZXJpYWwgc3RyZWFtIGNvcnJ1cHRpb24uICBJcyB0
aGF0IHRoZSBvdXRwdXQgb2YKPiA+ID4gPiB5b3VyIHNlcmlhbCBwb3J0PyAgRG9lcyBkbWVzZyBz
aG93IHRoZSBzYW1lIGNvcnJ1cHRpb24/Cj4gPiA+Cj4gPiA+IFRoYXQncyB0aGUgc2VyaWFsIHBv
cnQgb3V0cHV0Lgo+ID4gPiBkbWVzZyBpcyBvay4KPiA+ID4KPiA+ID4gTm90aGluZyBlbHNlIEkg
ZG8gY2FuIG1lc3MgdXAgdGhlIHNlcmlhbCBwb3J0Lgo+ID4KPiA+IE1heWJlIHRoZSBLRVJOX0lO
Rk8gcHJlZml4IGlzIHNlbmRpbmcgb3V0IGNvbnRyb2wgY2hhcmFjdGVycyB0aGF0IG1lc3MKPiA+
IHVwIHRoZSBzZXJpYWwgb3V0cHV0Pwo+Cj4gTW9yZSBsaWtlbHkgdGhlIEV0aGVybmV0IGxpbmsg
c3RhdGUgY2hhbmdlIGlzIGludGVyZmVyaW5nIHdpdGggdGhlCj4gc2VyaWFsIGxpbmUgYXQgdGhl
IGVsZWN0cmljYWwgbGV2ZWwuICBUcnkgdHdlYWtpbmcgdGhlIHNlcmlhbCBjbG9jayB1cAo+IG9y
IGRvd24gYSB0aW55IGJpdCwgdGhhdCBtaWdodCBtYWtlIGl0IG1vcmUgc3RhYmxlLiAgKEkndmUg
aGFkIHRvIGRvCj4gdGhhdCBvbiBvbmUgb2YgbXkgYm9hcmRzIGhlcmUgdG8gZ2V0IHN0YWJsZSBz
ZXJpYWwgb3V0cHV0KS4KClRoYXQgYXBwZWFycyB0byBiZSB0aGUgcHJvYmxlbS4gSXQncyBteSBF
ZmlrYSB0aGF0IGlzIGNvcnJ1cHRpbmcgdGhlCm1lc3NhZ2UuIE9uIHRoZSBFZmlrYSBFdGhlcm5l
dCBhbmQgc2VyaWFsIGFyZSByaWdodCBuZXh0IHRvIGVhY2gKb3RoZXIuIE15IFBoeXRlYyBzeXN0
ZW0gaXMgb2ssIHNlcmlhbCBhbmQgRXRoZXJuZXQgYXJlIGF0IG9wcG9zaXRlCmVuZHMgb2YgdGhl
IGJvYXJkLgoKPgo+IENoZWVycywKPiBnLgo+Cj4KPiAtLQo+IEdyYW50IExpa2VseSwgQi5TYy4s
IFAuRW5nLgo+IFNlY3JldCBMYWIgVGVjaG5vbG9naWVzIEx0ZC4KPiBncmFudC5saWtlbHlAc2Vj
cmV0bGFiLmNhCj4gKDQwMykgMzk5LTAxOTUKPgoKCi0tIApKb24gU21pcmwKam9uc21pcmxAZ21h
aWwuY29tCg==
^ permalink raw reply
* Re: Link up/down messages from 5200 ethernet driver
From: Grant Likely @ 2007-12-06 6:08 UTC (permalink / raw)
To: Jon Smirl; +Cc: PowerPC dev list, Domen Puncer
In-Reply-To: <9e4733910712052143l581207d4l163b7d1be8b27e1d@mail.gmail.com>
T24gMTIvNS8wNywgSm9uIFNtaXJsIDxqb25zbWlybEBnbWFpbC5jb20+IHdyb3RlOgo+IE9uIDEy
LzYvMDcsIEpvbiBTbWlybCA8am9uc21pcmxAZ21haWwuY29tPiB3cm90ZToKPiA+IE9uIDEyLzUv
MDcsIEdyYW50IExpa2VseSA8Z3JhbnQubGlrZWx5QHNlY3JldGxhYi5jYT4gd3JvdGU6Cj4gPiA+
IE9uIDEyLzUvMDcsIEpvbiBTbWlybCA8am9uc21pcmxAZ21haWwuY29tPiB3cm90ZToKPiA+ID4g
PiBXaHkgZG9lcyB0aGUgZmVjNTIwMCBkcml2ZXIgc29tZXRpbWVzIG5vdCBwcmludCAnUEhZJyBj
b3JyZWN0bHk/Cj4gPiA+ID4KPiA+ID4gPiBwaHlDT1JFLU1QQzUyMDBCLXRpbnkgbG9naW46IFTY
pFbvv70gZjAwMDMwMDA6MTAgLSBMaW5rIGlzIERvd24KPiA+ID4gPiBU77+9WTogZjAwMDMwMDA6
MTAgLSBMaW5rIGlzIFVwIC0gMTAwL0Z1bGwKPiA+ID4gPiBU77+9WTogZjAwMDMwMDA6MTAgLSBM
aW5rIGlzIERvd24KPiA+ID4gPiBQSFk6IGYwMDAzMDAwOjEwIC0gTGluayBpcyBVcCAtIDEwMC9G
dWxsCj4gPiA+Cj4gPiA+IFdlaXJkOyB0aGF0IGxpbmUgY29tZXMgZnJvbSBkcml2ZXJzL25ldC9w
aHkvcGh5LmMgaW4KPiA+ID4gcGh5X3ByaW50X3N0YXR1cygpLCBhbmQgaXQncyBqdXN0IGEgYSBw
cl9pbmZvIHN0YXRlbWVudC4gIEkgc3VwcG9zZSBpdAo+ID4gPiBtaWdodCBiZSBhIHN0YWNrIG92
ZXJydW4sIGJ1dCBJJ2QgZXhwZWN0IG1vcmUgc2V2ZXJlIHN5bXB0b21zIGlmIHRoYXQKPiA+ID4g
d2FzIHRoZSBjYXNlLgo+ID4gPgo+ID4gPiBUaGF0ICpsb29rcyogbGlrZSBhIHNlcmlhbCBzdHJl
YW0gY29ycnVwdGlvbi4gIElzIHRoYXQgdGhlIG91dHB1dCBvZgo+ID4gPiB5b3VyIHNlcmlhbCBw
b3J0PyAgRG9lcyBkbWVzZyBzaG93IHRoZSBzYW1lIGNvcnJ1cHRpb24/Cj4gPgo+ID4gVGhhdCdz
IHRoZSBzZXJpYWwgcG9ydCBvdXRwdXQuCj4gPiBkbWVzZyBpcyBvay4KPiA+Cj4gPiBOb3RoaW5n
IGVsc2UgSSBkbyBjYW4gbWVzcyB1cCB0aGUgc2VyaWFsIHBvcnQuCj4KPiBNYXliZSB0aGUgS0VS
Tl9JTkZPIHByZWZpeCBpcyBzZW5kaW5nIG91dCBjb250cm9sIGNoYXJhY3RlcnMgdGhhdCBtZXNz
Cj4gdXAgdGhlIHNlcmlhbCBvdXRwdXQ/CgpNb3JlIGxpa2VseSB0aGUgRXRoZXJuZXQgbGluayBz
dGF0ZSBjaGFuZ2UgaXMgaW50ZXJmZXJpbmcgd2l0aCB0aGUKc2VyaWFsIGxpbmUgYXQgdGhlIGVs
ZWN0cmljYWwgbGV2ZWwuICBUcnkgdHdlYWtpbmcgdGhlIHNlcmlhbCBjbG9jayB1cApvciBkb3du
IGEgdGlueSBiaXQsIHRoYXQgbWlnaHQgbWFrZSBpdCBtb3JlIHN0YWJsZS4gIChJJ3ZlIGhhZCB0
byBkbwp0aGF0IG9uIG9uZSBvZiBteSBib2FyZHMgaGVyZSB0byBnZXQgc3RhYmxlIHNlcmlhbCBv
dXRwdXQpLgoKQ2hlZXJzLApnLgoKCi0tIApHcmFudCBMaWtlbHksIEIuU2MuLCBQLkVuZy4KU2Vj
cmV0IExhYiBUZWNobm9sb2dpZXMgTHRkLgpncmFudC5saWtlbHlAc2VjcmV0bGFiLmNhCig0MDMp
IDM5OS0wMTk1Cg==
^ permalink raw reply
* dtc: Remove obsolete check_properties() function
From: David Gibson @ 2007-12-06 6:04 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
After the last couple of patches converting various old-style semantic
checks to the new framework, the only thing that the old-style
check_properties() function still checks is that the size of "reg"
properties is a multiple of the cell size.
This patch removes check_properties() and all related code and data.
The check on the size of reg properties is folded into the existing
check for the format of "reg" properties (still old-style for the time
being).
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Index: dtc/checks.c
===================================================================
--- dtc.orig/checks.c 2007-12-05 11:08:45.000000000 +1100
+++ dtc/checks.c 2007-12-05 11:08:48.000000000 +1100
@@ -412,46 +412,6 @@
#define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0)
-static int must_be_cells(struct property *prop, struct node *node)
-{
- if ((prop->val.len % sizeof(cell_t)) != 0) {
- ERRMSG("\"%s\" property in %s is not a multiple of cell size\n",
- prop->name, node->fullpath);
- return 0;
- }
-
- return 1;
-}
-
-static struct {
- char *propname;
- int (*check_fn)(struct property *prop, struct node *node);
-} prop_checker_table[] = {
- {"reg", must_be_cells},
-};
-
-static int check_properties(struct node *node)
-{
- struct property *prop;
- struct node *child;
- int i;
- int ok = 1;
-
- for_each_property(node, prop)
- for (i = 0; i < ARRAY_SIZE(prop_checker_table); i++)
- if (streq(prop->name, prop_checker_table[i].propname))
- if (! prop_checker_table[i].check_fn(prop, node)) {
- ok = 0;
- break;
- }
-
- for_each_child(node, child)
- if (! check_properties(child))
- ok = 0;
-
- return ok;
-}
-
#define CHECK_HAVE(node, propname) \
do { \
if (! (prop = get_property((node), (propname)))) \
@@ -672,10 +632,9 @@
prop = get_property(node, "reg");
if (prop) {
- int len = prop->val.len / 4;
-
- if ((len % (addr_cells+size_cells)) != 0)
- DO_ERR("\"reg\" property in %s has invalid length (%d) for given #address-cells (%d) and #size-cells (%d)\n",
+ int reg_entry_len = (addr_cells + size_cells) * sizeof(cell_t);
+ if ((prop->val.len % reg_entry_len) != 0)
+ DO_ERR("\"reg\" property in %s has invalid length (%d bytes) for given #address-cells (%d) and #size-cells (%d)\n",
node->fullpath, prop->val.len,
addr_cells, size_cells);
}
@@ -699,7 +658,6 @@
{
int ok = 1;
- ok = ok && check_properties(dt);
ok = ok && check_addr_size_reg(dt, -1, -1);
ok = ok && check_root(dt);
ok = ok && check_cpus(dt, outversion, boot_cpuid_phys);
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* dtc: Migrate "string property" checks to new framework
From: David Gibson @ 2007-12-06 6:01 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
This patch converts to the new tree checking framework those checks
which verify that certain properties (device_type, model) have a
string value, when present.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Index: dtc/checks.c
===================================================================
--- dtc.orig/checks.c 2007-12-06 16:57:02.000000000 +1100
+++ dtc/checks.c 2007-12-06 16:59:54.000000000 +1100
@@ -351,6 +351,10 @@
CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN);
CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN);
+CHECK_IS_STRING(device_type_is_string, "device_type", WARN);
+CHECK_IS_STRING(model_is_string, "model", WARN);
+CHECK_IS_STRING(status_is_string, "status", WARN);
+
static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names,
&name_is_string, &name_properties,
@@ -358,6 +362,7 @@
&phandle_references, &path_references,
&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
+ &device_type_is_string, &model_is_string, &status_is_string,
};
int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys);
@@ -418,24 +423,11 @@
return 1;
}
-static int must_be_string(struct property *prop, struct node *node)
-{
- if (! data_is_one_string(prop->val)) {
- ERRMSG("\"%s\" property in %s is not a string\n",
- prop->name, node->fullpath);
- return 0;
- }
-
- return 1;
-}
-
static struct {
char *propname;
int (*check_fn)(struct property *prop, struct node *node);
} prop_checker_table[] = {
{"reg", must_be_cells},
- {"model", must_be_string},
- {"device_type", must_be_string},
};
static int check_properties(struct node *node)
Index: dtc/tests/bad-string-props.dts
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dtc/tests/bad-string-props.dts 2007-12-06 16:59:54.000000000 +1100
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+ device_type = <0xdeadbeef>;
+ model = <0xdeadbeef>;
+ status = <0xdeadbeef>;
+};
Index: dtc/tests/run_tests.sh
===================================================================
--- dtc.orig/tests/run_tests.sh 2007-12-06 16:57:02.000000000 +1100
+++ dtc/tests/run_tests.sh 2007-12-06 16:59:54.000000000 +1100
@@ -169,6 +169,8 @@
run_test dtc-checkfails.sh name_properties -- -I dts -O dtb bad-name-property.dts
run_test dtc-checkfails.sh address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell -- -I dts -O dtb bad-ncells.dts
+ run_test dtc-checkfails.sh device_type_is_string model_is_string status_is_string -- -I dts -O dtb bad-string-props.dts
+
}
while getopts "vt:m" ARG ; do
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* dtc: Migrate "one cell" checks to new framework
From: David Gibson @ 2007-12-06 5:59 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
This patch converts to the new tree checking framework those checks
which verify that certain properties (#address-cells and #size-cells)
are exactly one cell in size, when present.
We also drop the old-style check for "linux,phandle" being one cell,
since that is already implied in the the existing new-style checks on
the linux,phandle property.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Index: dtc/checks.c
===================================================================
--- dtc.orig/checks.c 2007-12-06 16:52:00.000000000 +1100
+++ dtc/checks.c 2007-12-06 16:57:02.000000000 +1100
@@ -190,6 +190,23 @@
#define CHECK_IS_STRING(nm, propname, lvl) \
CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl))
+static void check_is_cell(struct check *c, struct node *root,
+ struct node *node)
+{
+ struct property *prop;
+ char *propname = c->data;
+
+ prop = get_property(node, propname);
+ if (!prop)
+ return; /* Not present, assumed ok */
+
+ if (prop->val.len != sizeof(cell_t))
+ FAIL(c, "\"%s\" property in %s is not a single cell",
+ propname, node->fullpath);
+}
+#define CHECK_IS_CELL(nm, propname, lvl) \
+ CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl))
+
/*
* Structural check functions
*/
@@ -327,11 +344,20 @@
CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR,
&duplicate_node_names);
+/*
+ * Semantic checks
+ */
+CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN);
+CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN);
+CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN);
+
static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names,
&name_is_string, &name_properties,
&explicit_phandles,
&phandle_references, &path_references,
+
+ &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
};
int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys);
@@ -381,17 +407,6 @@
#define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0)
-static int must_be_one_cell(struct property *prop, struct node *node)
-{
- if (prop->val.len != sizeof(cell_t)) {
- ERRMSG("\"%s\" property in %s has the wrong length (should be 1 cell)\n",
- prop->name, node->fullpath);
- return 0;
- }
-
- return 1;
-}
-
static int must_be_cells(struct property *prop, struct node *node)
{
if ((prop->val.len % sizeof(cell_t)) != 0) {
@@ -418,9 +433,6 @@
char *propname;
int (*check_fn)(struct property *prop, struct node *node);
} prop_checker_table[] = {
- {"linux,phandle", must_be_one_cell},
- {"#address-cells", must_be_one_cell},
- {"#size-cells", must_be_one_cell},
{"reg", must_be_cells},
{"model", must_be_string},
{"device_type", must_be_string},
Index: dtc/tests/bad-ncells.dts
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dtc/tests/bad-ncells.dts 2007-12-06 16:57:02.000000000 +1100
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+ #address-cells = "badthing";
+ #size-cells = "badthing";
+ #interrupt-cells = "badthing";
+};
Index: dtc/tests/run_tests.sh
===================================================================
--- dtc.orig/tests/run_tests.sh 2007-12-06 16:57:01.000000000 +1100
+++ dtc/tests/run_tests.sh 2007-12-06 16:57:02.000000000 +1100
@@ -167,6 +167,8 @@
run_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-node-ref.dts
run_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-label-ref.dts
run_test dtc-checkfails.sh name_properties -- -I dts -O dtb bad-name-property.dts
+
+ run_test dtc-checkfails.sh address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell -- -I dts -O dtb bad-ncells.dts
}
while getopts "vt:m" ARG ; do
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* dtc: More detailed testing of tree checks
From: David Gibson @ 2007-12-06 5:56 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
This patch modifies the dtc-checkfails.sh testcase wrapper so that
instead of testing just that dtc fails with a particular error code on
the sample input, it scans dtc's stderr output looking for a message
that dtc failed a specific check or checks. This has several advantages:
- It means we more precisely check dtc's checking behaviour
- It means we can check for generation of warnings using the
same script
- It means we can test cases where dtc should generate
multiple errors or warnings from different checks
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Index: dtc/tests/dtc-checkfails.sh
===================================================================
--- dtc.orig/tests/dtc-checkfails.sh 2007-12-06 16:33:21.000000000 +1100
+++ dtc/tests/dtc-checkfails.sh 2007-12-06 16:48:28.000000000 +1100
@@ -2,21 +2,27 @@
. tests.sh
-TMPFILE="tmp.out.$$"
+for x; do
+ shift
+ if [ "$x" = "--" ]; then
+ break;
+ fi
+ CHECKS="$CHECKS $x"
+done
-rm -f $TMPFILE
+LOG="tmp.log.$$"
-verbose_run "$DTC" -o $TMPFILE "$@"
+rm -f $TMPFILE $LOG
+
+verbose_run_log "$LOG" "$DTC" -o /dev/null "$@"
ret="$?"
-if [ -f $TMPFILE ]; then
- FAIL "output file was created despite bad input"
-fi
-
-if [ "$ret" = "2" ]; then
- PASS
-else
- FAIL "dtc returned error code $ret instead of 2 (check failed)"
-fi
+for c in $CHECKS; do
+ if ! grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then
+ FAIL "Failed to trigger check \"%c\""
+ fi
+done
+
+rm -f $LOG
-rm -f $TMPFILE
+PASS
Index: dtc/tests/run_tests.sh
===================================================================
--- dtc.orig/tests/run_tests.sh 2007-12-06 16:33:21.000000000 +1100
+++ dtc/tests/run_tests.sh 2007-12-06 16:47:15.000000000 +1100
@@ -159,14 +159,14 @@
done
# Check some checks
- run_test dtc-checkfails.sh -I dts -O dtb dup-nodename.dts
- run_test dtc-checkfails.sh -I dts -O dtb dup-propname.dts
- run_test dtc-checkfails.sh -I dts -O dtb dup-phandle.dts
- run_test dtc-checkfails.sh -I dts -O dtb zero-phandle.dts
- run_test dtc-checkfails.sh -I dts -O dtb minusone-phandle.dts
- run_test dtc-checkfails.sh -I dts -O dtb nonexist-node-ref.dts
- run_test dtc-checkfails.sh -I dts -O dtb nonexist-label-ref.dts
- run_test dtc-checkfails.sh -I dts -O dtb bad-name-property.dts
+ run_test dtc-checkfails.sh duplicate_node_names -- -I dts -O dtb dup-nodename.dts
+ run_test dtc-checkfails.sh duplicate_property_names -- -I dts -O dtb dup-propname.dts
+ run_test dtc-checkfails.sh explicit_phandles -- -I dts -O dtb dup-phandle.dts
+ run_test dtc-checkfails.sh explicit_phandles -- -I dts -O dtb zero-phandle.dts
+ run_test dtc-checkfails.sh explicit_phandles -- -I dts -O dtb minusone-phandle.dts
+ run_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-node-ref.dts
+ run_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-label-ref.dts
+ run_test dtc-checkfails.sh name_properties -- -I dts -O dtb bad-name-property.dts
}
while getopts "vt:m" ARG ; do
Index: dtc/tests/tests.sh
===================================================================
--- dtc.orig/tests/tests.sh 2007-12-06 16:33:21.000000000 +1100
+++ dtc/tests/tests.sh 2007-12-06 16:35:12.000000000 +1100
@@ -19,3 +19,14 @@
"$@" > /dev/null 2> /dev/null
fi
}
+
+verbose_run_log () {
+ LOG="$1"
+ shift
+ "$@" &> "$LOG"
+ ret=$?
+ if [ -z "$QUIET_TEST" ]; then
+ cat "$LOG" >&2
+ fi
+ return $ret
+}
Index: dtc/tests/Makefile.tests
===================================================================
--- dtc.orig/tests/Makefile.tests 2007-12-06 16:48:35.000000000 +1100
+++ dtc/tests/Makefile.tests 2007-12-06 16:48:39.000000000 +1100
@@ -26,7 +26,7 @@
TESTS_DEPFILES = $(TESTS:%=%.d) \
$(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d)
-TESTS_CLEANFILES_L = *.output vglog.* vgcore.* *.dtb *.test.dts
+TESTS_CLEANFILES_L = *.output vglog.* vgcore.* *.dtb *.test.dts tmp.*
TESTS_CLEANFILES = $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%)
BIN += $(TESTS) $(TESTS_PREFIX)dumptrees
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: Link up/down messages from 5200 ethernet driver
From: Jon Smirl @ 2007-12-06 5:43 UTC (permalink / raw)
To: Grant Likely; +Cc: PowerPC dev list, Domen Puncer
In-Reply-To: <9e4733910712052140j70f48f05qbbf9af082ba4747c@mail.gmail.com>
T24gMTIvNi8wNywgSm9uIFNtaXJsIDxqb25zbWlybEBnbWFpbC5jb20+IHdyb3RlOgo+IE9uIDEy
LzUvMDcsIEdyYW50IExpa2VseSA8Z3JhbnQubGlrZWx5QHNlY3JldGxhYi5jYT4gd3JvdGU6Cj4g
PiBPbiAxMi81LzA3LCBKb24gU21pcmwgPGpvbnNtaXJsQGdtYWlsLmNvbT4gd3JvdGU6Cj4gPiA+
IFdoeSBkb2VzIHRoZSBmZWM1MjAwIGRyaXZlciBzb21ldGltZXMgbm90IHByaW50ICdQSFknIGNv
cnJlY3RseT8KPiA+ID4KPiA+ID4gcGh5Q09SRS1NUEM1MjAwQi10aW55IGxvZ2luOiBU2KRW77+9
IGYwMDAzMDAwOjEwIC0gTGluayBpcyBEb3duCj4gPiA+IFTvv71ZOiBmMDAwMzAwMDoxMCAtIExp
bmsgaXMgVXAgLSAxMDAvRnVsbAo+ID4gPiBU77+9WTogZjAwMDMwMDA6MTAgLSBMaW5rIGlzIERv
d24KPiA+ID4gUEhZOiBmMDAwMzAwMDoxMCAtIExpbmsgaXMgVXAgLSAxMDAvRnVsbAo+ID4KPiA+
IFdlaXJkOyB0aGF0IGxpbmUgY29tZXMgZnJvbSBkcml2ZXJzL25ldC9waHkvcGh5LmMgaW4KPiA+
IHBoeV9wcmludF9zdGF0dXMoKSwgYW5kIGl0J3MganVzdCBhIGEgcHJfaW5mbyBzdGF0ZW1lbnQu
ICBJIHN1cHBvc2UgaXQKPiA+IG1pZ2h0IGJlIGEgc3RhY2sgb3ZlcnJ1biwgYnV0IEknZCBleHBl
Y3QgbW9yZSBzZXZlcmUgc3ltcHRvbXMgaWYgdGhhdAo+ID4gd2FzIHRoZSBjYXNlLgo+ID4KPiA+
IFRoYXQgKmxvb2tzKiBsaWtlIGEgc2VyaWFsIHN0cmVhbSBjb3JydXB0aW9uLiAgSXMgdGhhdCB0
aGUgb3V0cHV0IG9mCj4gPiB5b3VyIHNlcmlhbCBwb3J0PyAgRG9lcyBkbWVzZyBzaG93IHRoZSBz
YW1lIGNvcnJ1cHRpb24/Cj4KPiBUaGF0J3MgdGhlIHNlcmlhbCBwb3J0IG91dHB1dC4KPiBkbWVz
ZyBpcyBvay4KPgo+IE5vdGhpbmcgZWxzZSBJIGRvIGNhbiBtZXNzIHVwIHRoZSBzZXJpYWwgcG9y
dC4KCk1heWJlIHRoZSBLRVJOX0lORk8gcHJlZml4IGlzIHNlbmRpbmcgb3V0IGNvbnRyb2wgY2hh
cmFjdGVycyB0aGF0IG1lc3MKdXAgdGhlIHNlcmlhbCBvdXRwdXQ/Cgo+Cj4gPgo+ID4gQ2hlZXJz
LAo+ID4gZy4KPiA+Cj4gPiAtLQo+ID4gR3JhbnQgTGlrZWx5LCBCLlNjLiwgUC5FbmcuCj4gPiBT
ZWNyZXQgTGFiIFRlY2hub2xvZ2llcyBMdGQuCj4gPiBncmFudC5saWtlbHlAc2VjcmV0bGFiLmNh
Cj4gPiAoNDAzKSAzOTktMDE5NQo+ID4KPgo+Cj4gLS0KPiBKb24gU21pcmwKPiBqb25zbWlybEBn
bWFpbC5jb20KPgoKCi0tIApKb24gU21pcmwKam9uc21pcmxAZ21haWwuY29tCg==
^ permalink raw reply
* Re: Link up/down messages from 5200 ethernet driver
From: Jon Smirl @ 2007-12-06 5:40 UTC (permalink / raw)
To: Grant Likely; +Cc: PowerPC dev list, Domen Puncer
In-Reply-To: <fa686aa40712052046s5887c9fewa61c2921a22f5c80@mail.gmail.com>
T24gMTIvNS8wNywgR3JhbnQgTGlrZWx5IDxncmFudC5saWtlbHlAc2VjcmV0bGFiLmNhPiB3cm90
ZToKPiBPbiAxMi81LzA3LCBKb24gU21pcmwgPGpvbnNtaXJsQGdtYWlsLmNvbT4gd3JvdGU6Cj4g
PiBXaHkgZG9lcyB0aGUgZmVjNTIwMCBkcml2ZXIgc29tZXRpbWVzIG5vdCBwcmludCAnUEhZJyBj
b3JyZWN0bHk/Cj4gPgo+ID4gcGh5Q09SRS1NUEM1MjAwQi10aW55IGxvZ2luOiBU2KRW77+9IGYw
MDAzMDAwOjEwIC0gTGluayBpcyBEb3duCj4gPiBU77+9WTogZjAwMDMwMDA6MTAgLSBMaW5rIGlz
IFVwIC0gMTAwL0Z1bGwKPiA+IFTvv71ZOiBmMDAwMzAwMDoxMCAtIExpbmsgaXMgRG93bgo+ID4g
UEhZOiBmMDAwMzAwMDoxMCAtIExpbmsgaXMgVXAgLSAxMDAvRnVsbAo+Cj4gV2VpcmQ7IHRoYXQg
bGluZSBjb21lcyBmcm9tIGRyaXZlcnMvbmV0L3BoeS9waHkuYyBpbgo+IHBoeV9wcmludF9zdGF0
dXMoKSwgYW5kIGl0J3MganVzdCBhIGEgcHJfaW5mbyBzdGF0ZW1lbnQuICBJIHN1cHBvc2UgaXQK
PiBtaWdodCBiZSBhIHN0YWNrIG92ZXJydW4sIGJ1dCBJJ2QgZXhwZWN0IG1vcmUgc2V2ZXJlIHN5
bXB0b21zIGlmIHRoYXQKPiB3YXMgdGhlIGNhc2UuCj4KPiBUaGF0ICpsb29rcyogbGlrZSBhIHNl
cmlhbCBzdHJlYW0gY29ycnVwdGlvbi4gIElzIHRoYXQgdGhlIG91dHB1dCBvZgo+IHlvdXIgc2Vy
aWFsIHBvcnQ/ICBEb2VzIGRtZXNnIHNob3cgdGhlIHNhbWUgY29ycnVwdGlvbj8KClRoYXQncyB0
aGUgc2VyaWFsIHBvcnQgb3V0cHV0LgpkbWVzZyBpcyBvay4KCk5vdGhpbmcgZWxzZSBJIGRvIGNh
biBtZXNzIHVwIHRoZSBzZXJpYWwgcG9ydC4KCj4KPiBDaGVlcnMsCj4gZy4KPgo+IC0tCj4gR3Jh
bnQgTGlrZWx5LCBCLlNjLiwgUC5FbmcuCj4gU2VjcmV0IExhYiBUZWNobm9sb2dpZXMgTHRkLgo+
IGdyYW50Lmxpa2VseUBzZWNyZXRsYWIuY2EKPiAoNDAzKSAzOTktMDE5NQo+CgoKLS0gCkpvbiBT
bWlybApqb25zbWlybEBnbWFpbC5jb20K
^ permalink raw reply
* Re: Link up/down messages from 5200 ethernet driver
From: Grant Likely @ 2007-12-06 4:46 UTC (permalink / raw)
To: Jon Smirl; +Cc: PowerPC dev list, Domen Puncer
In-Reply-To: <9e4733910712051755l76c0403bo4a60834928a35c2@mail.gmail.com>
T24gMTIvNS8wNywgSm9uIFNtaXJsIDxqb25zbWlybEBnbWFpbC5jb20+IHdyb3RlOgo+IFdoeSBk
b2VzIHRoZSBmZWM1MjAwIGRyaXZlciBzb21ldGltZXMgbm90IHByaW50ICdQSFknIGNvcnJlY3Rs
eT8KPgo+IHBoeUNPUkUtTVBDNTIwMEItdGlueSBsb2dpbjogVNikVu+/vSBmMDAwMzAwMDoxMCAt
IExpbmsgaXMgRG93bgo+IFTvv71ZOiBmMDAwMzAwMDoxMCAtIExpbmsgaXMgVXAgLSAxMDAvRnVs
bAo+IFTvv71ZOiBmMDAwMzAwMDoxMCAtIExpbmsgaXMgRG93bgo+IFBIWTogZjAwMDMwMDA6MTAg
LSBMaW5rIGlzIFVwIC0gMTAwL0Z1bGwKCldlaXJkOyB0aGF0IGxpbmUgY29tZXMgZnJvbSBkcml2
ZXJzL25ldC9waHkvcGh5LmMgaW4KcGh5X3ByaW50X3N0YXR1cygpLCBhbmQgaXQncyBqdXN0IGEg
YSBwcl9pbmZvIHN0YXRlbWVudC4gIEkgc3VwcG9zZSBpdAptaWdodCBiZSBhIHN0YWNrIG92ZXJy
dW4sIGJ1dCBJJ2QgZXhwZWN0IG1vcmUgc2V2ZXJlIHN5bXB0b21zIGlmIHRoYXQKd2FzIHRoZSBj
YXNlLgoKVGhhdCAqbG9va3MqIGxpa2UgYSBzZXJpYWwgc3RyZWFtIGNvcnJ1cHRpb24uICBJcyB0
aGF0IHRoZSBvdXRwdXQgb2YKeW91ciBzZXJpYWwgcG9ydD8gIERvZXMgZG1lc2cgc2hvdyB0aGUg
c2FtZSBjb3JydXB0aW9uPwoKQ2hlZXJzLApnLgoKLS0gCkdyYW50IExpa2VseSwgQi5TYy4sIFAu
RW5nLgpTZWNyZXQgTGFiIFRlY2hub2xvZ2llcyBMdGQuCmdyYW50Lmxpa2VseUBzZWNyZXRsYWIu
Y2EKKDQwMykgMzk5LTAxOTUK
^ permalink raw reply
* Re: drivers/net/iseries_veth.c dubious sysfs usage
From: Michael Ellerman @ 2007-12-06 3:48 UTC (permalink / raw)
To: Greg KH; +Cc: linuxppc-dev, Kyle A. Lucke, paulus, linux-kernel, David Gibson
In-Reply-To: <20071205214103.GA7074@kroah.com>
[-- Attachment #1: Type: text/plain, Size: 4596 bytes --]
On Wed, 2007-12-05 at 13:41 -0800, Greg KH wrote:
> On Wed, Dec 05, 2007 at 10:10:31PM +1100, Michael Ellerman wrote:
> > On Wed, 2007-12-05 at 01:30 -0800, Greg KH wrote:
> > > In doing a massive kobject cleanup of the kernel tree, I ran across the
> > > iseries_veth.c driver.
> > >
> > > It looks like the driver is creating a number of subdirectories under
> > > the driver sysfs directory. This is odd and probably wrong. You want
> > > these virtual connections to show up in the main sysfs device tree, not
> > > under the driver directory.
> > >
> > > I'll be glad to totally guess and try to move it around in the sysfs
> > > tree, but odds are I'll get it all wrong as I can't really test this
> > > out :)
> > >
> > > Any hints on what this driver is trying to do in this sysfs directories?
> >
> > I wrote the code, I think, but it's been a while - I'll have a look at
> > it tomorrow.
>
> Yes, can you send me the sysfs tree output of the driver directory, and
> what exactly the different files in there are supposed to be used for?
Sure. My version of tar (1.15.1) doesn't seem to be able to tar up /sys,
so hopefully this is sufficient:
igoeast:~# cd /sys/class/net/eth1/
igoeast:/sys/class/net/eth1# ls -la
total 0
drwxr-xr-x 4 root root 0 Dec 6 10:22 .
drwxr-xr-x 6 root root 0 Dec 6 10:21 ..
-r--r--r-- 1 root root 4096 Dec 6 10:30 addr_len
-r--r--r-- 1 root root 4096 Dec 6 10:30 address
-r--r--r-- 1 root root 4096 Dec 6 10:30 broadcast
-r--r--r-- 1 root root 4096 Dec 6 10:30 carrier
lrwxrwxrwx 1 root root 0 Dec 6 10:22 device -> ../../../devices/vio/3
-r--r--r-- 1 root root 4096 Dec 6 10:30 dormant
-r--r--r-- 1 root root 4096 Dec 6 10:30 features
-rw-r--r-- 1 root root 4096 Dec 6 10:30 flags
-r--r--r-- 1 root root 4096 Dec 6 10:30 ifindex
-r--r--r-- 1 root root 4096 Dec 6 10:30 iflink
-r--r--r-- 1 root root 4096 Dec 6 10:30 link_mode
-rw-r--r-- 1 root root 4096 Dec 6 10:30 mtu
-r--r--r-- 1 root root 4096 Dec 6 10:30 operstate
drwxr-xr-x 2 root root 0 Dec 6 10:30 statistics
lrwxrwxrwx 1 root root 0 Dec 6 10:30 subsystem -> ../../../class/net
-rw-r--r-- 1 root root 4096 Dec 6 10:30 tx_queue_len
-r--r--r-- 1 root root 4096 Dec 6 10:30 type
-rw-r--r-- 1 root root 4096 Dec 6 10:30 uevent
drwxr-xr-x 2 root root 0 Dec 6 10:30 veth_port
Each net device has a port structure associated with it, the fields
should be fairly self explanatory, they're all read only I think.
igoeast:/sys/class/net/eth1# find veth_port/
veth_port/
veth_port/mac_addr
veth_port/lpar_map
veth_port/stopped_map
veth_port/promiscuous
veth_port/num_mcast
igoeast:/sys/class/net/eth1# cd device/driver
igoeast:/sys/class/net/eth1/device/driver# ls -l
total 0
lrwxrwxrwx 1 root root 0 Dec 6 10:21 2 -> ../../../../devices/vio/2
lrwxrwxrwx 1 root root 0 Dec 6 10:21 3 -> ../../../../devices/vio/3
--w------- 1 root root 4096 Dec 6 10:21 bind
drwxr-xr-x 2 root root 0 Dec 6 10:21 cnx00
drwxr-xr-x 2 root root 0 Dec 6 10:21 cnx02
drwxr-xr-x 2 root root 0 Dec 6 10:21 cnx03
drwxr-xr-x 2 root root 0 Dec 6 10:21 cnx04
lrwxrwxrwx 1 root root 0 Dec 6 10:21 module -> ../../../../module/iseries_veth
--w------- 1 root root 4096 Dec 6 10:21 uevent
--w------- 1 root root 4096 Dec 6 10:21 unbind
The driver has a connection to all the other lpars, this is entirely
independent of the net devices.
igoeast:/sys/class/net/eth1/device/driver# find cnx00/
cnx00/
cnx00/outstanding_tx
cnx00/remote_lp
cnx00/num_events
cnx00/reset_timeout
cnx00/last_contact
cnx00/state
cnx00/src_inst
cnx00/dst_inst
cnx00/num_pending_acks
cnx00/num_ack_events
cnx00/ack_timeout
> > Why is it "odd and probably wrong" to create subdirectories under the
> > driver in sysfs?
>
> Because a driver does not have "devices" under it in the sysfs tree.
> All devices liven in the /sys/devices/ tree so we can properly manage
> them that way. A driver will then bind to a device, and the driver core
> will set up the linkages in sysfs properly so that everthing looks
> uniform.
OK. They're not "devices" that we create under the driver, they're just
attributes of the driver, and they happen to be in groups so I put them
in subdirectories.
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH] Use SLB size from the device tree
From: Paul Mackerras @ 2007-12-06 3:32 UTC (permalink / raw)
To: Michael Neuling; +Cc: Olof Johansson, linuxppc-dev, Will Schmidt
In-Reply-To: <510.1194565218@neuling.org>
Michael Neuling writes:
> Currently we hardwire the number of SLBs but the PAPR says we export an
> ibm,slb-size property to specify the number of SLB entries. This patch
> uses this property instead of assuming 64 always. If no property is
> found, we assume 64 entries as before.
On 32-bit platforms (e.g. powermac) I get:
/home/paulus/kernel/powerpc/arch/powerpc/kernel/prom.c: In function 'check_cpu_slb_size':
/home/paulus/kernel/powerpc/arch/powerpc/kernel/prom.c:592: error: 'mmu_slb_size' undeclared (first use in this function)
/home/paulus/kernel/powerpc/arch/powerpc/kernel/prom.c:592: error: (Each undeclared identifier is reported only once
/home/paulus/kernel/powerpc/arch/powerpc/kernel/prom.c:592: error: for each function it appears in.)
make[2]: *** [arch/powerpc/kernel/prom.o] Error 1
Paul.
^ permalink raw reply
* Re: [PATCH] pci: Fix bus resource assignment on 32 bits with 64b resources
From: Benjamin Herrenschmidt @ 2007-12-06 3:22 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: linuxppc-dev, linux-pci, linux-kernel
In-Reply-To: <20071205064116.D849BDE10A@ozlabs.org>
On Wed, 2007-12-05 at 17:40 +1100, Benjamin Herrenschmidt wrote:
> The current pci_assign_unassigned_resources() code doesn't work properly
> on 32 bits platforms with 64 bits resources. The main reason is the use
> of unsigned long in various places instead of resource_size_t.
>
> This fixes it, along with some tricks to avoid casting to 64 bits on
> platforms that don't need it in every printk around.
>
> This is a pre-requisite for making powerpc use the generic code instead of
> its own half-useful implementation.
>
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
>
> This version fixes some stupid warnings when using 32 bits resources
... and has warnings on 64 bits platforms... GRRRR
This whole issue of printk vs. resource_size_t is a terrible mess :-(
Part of the problem is that resource_size_t can be either u32 or u64..
that is it can be either unsigned int, unsigned long or unsigned long
long... and we have no way to reliably printk that.
Any clever idea before I start pushing filthy macros up linux/types.h ?
Cheers,
Ben.
^ permalink raw reply
* [PATCH 2/2] [POWERPC] pSeries: remove dependency on pci_dn bussubno
From: Stephen Rothwell @ 2007-12-06 2:40 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20071206133919.9c609f17.sfr@canb.auug.org.au>
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/platforms/pseries/iommu.c | 24 +++++++-----------------
1 files changed, 7 insertions(+), 17 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index d4e9d85..ebb9313 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -296,11 +296,12 @@ static void iommu_table_setparms(struct pci_controller *phb,
static void iommu_table_setparms_lpar(struct pci_controller *phb,
struct device_node *dn,
struct iommu_table *tbl,
- const void *dma_window)
+ const void *dma_window,
+ int bussubno)
{
unsigned long offset, size;
- tbl->it_busno = PCI_DN(dn)->bussubno;
+ tbl->it_busno = bussubno;
of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size);
tbl->it_base = 0;
@@ -420,17 +421,10 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
pdn->full_name, ppci->iommu_table);
if (!ppci->iommu_table) {
- /* Bussubno hasn't been copied yet.
- * Do it now because iommu_table_setparms_lpar needs it.
- */
-
- ppci->bussubno = bus->number;
-
tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
ppci->phb->node);
-
- iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
-
+ iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window,
+ bus->number);
ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node);
DBG(" created table: %p\n", ppci->iommu_table);
}
@@ -523,14 +517,10 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
pci = PCI_DN(pdn);
if (!pci->iommu_table) {
- /* iommu_table_setparms_lpar needs bussubno. */
- pci->bussubno = pci->phb->bus->number;
-
tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
pci->phb->node);
-
- iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window);
-
+ iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window,
+ pci->phb->bus->number);
pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
DBG(" created table: %p\n", pci->iommu_table);
} else {
--
1.5.3.7
^ permalink raw reply related
* [PATCH 1/2] [POWERPC] iommu_free_table doesn't need the device_node
From: Stephen Rothwell @ 2007-12-06 2:39 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
It only needs the iommu_table address. It also makes use of the node
name to print error messages. So just pass it the things it needs.
This reduces the places that know about the pci_dn by one.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/kernel/iommu.c | 8 +++-----
arch/powerpc/platforms/pseries/iommu.c | 2 +-
include/asm-powerpc/iommu.h | 3 +--
3 files changed, 5 insertions(+), 8 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 2d0c9ef..47c3fe5 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -526,16 +526,14 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
return tbl;
}
-void iommu_free_table(struct device_node *dn)
+void iommu_free_table(struct iommu_table *tbl, const char *node_name)
{
- struct pci_dn *pdn = dn->data;
- struct iommu_table *tbl = pdn->iommu_table;
unsigned long bitmap_sz, i;
unsigned int order;
if (!tbl || !tbl->it_map) {
printk(KERN_ERR "%s: expected TCE map for %s\n", __FUNCTION__,
- dn->full_name);
+ node_name);
return;
}
@@ -544,7 +542,7 @@ void iommu_free_table(struct device_node *dn)
for (i = 0; i < (tbl->it_size/64); i++) {
if (tbl->it_map[i] != 0) {
printk(KERN_WARNING "%s: Unexpected TCEs for %s\n",
- __FUNCTION__, dn->full_name);
+ __FUNCTION__, node_name);
break;
}
}
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index be17d23..d4e9d85 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -556,7 +556,7 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti
case PSERIES_RECONFIG_REMOVE:
if (pci && pci->iommu_table &&
of_get_property(np, "ibm,dma-window", NULL))
- iommu_free_table(np);
+ iommu_free_table(pci->iommu_table, np->full_name);
break;
default:
err = NOTIFY_DONE;
diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h
index 4a82fdc..7a3cef7 100644
--- a/include/asm-powerpc/iommu.h
+++ b/include/asm-powerpc/iommu.h
@@ -69,10 +69,9 @@ struct iommu_table {
};
struct scatterlist;
-struct device_node;
/* Frees table for an individual device node */
-extern void iommu_free_table(struct device_node *dn);
+extern void iommu_free_table(struct iommu_table *tbl, const char *node_name);
/* Initializes an iommu_table based in values set in the passed-in
* structure
--
1.5.3.7
^ permalink raw reply related
* dtc: Remove space from flex command line
From: David Gibson @ 2007-12-06 2:07 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
Author: Geoff Levand <geoffrey.levand@am.sony.com>
Apparently some versions of flex don't correctly parse the -o
parameter, if there's a space between the -o and its argument. So,
this patch removes it.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Index: dtc/Makefile
===================================================================
--- dtc.orig/Makefile 2007-12-06 13:03:41.000000000 +1100
+++ dtc/Makefile 2007-12-06 13:03:45.000000000 +1100
@@ -206,7 +206,7 @@
%.lex.c: %.l
@$(VECHO) LEX $@
- $(LEX) -o $@ $<
+ $(LEX) -o$@ $<
%.tab.c %.tab.h %.output: %.y
@$(VECHO) BISON $@
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Link up/down messages from 5200 ethernet driver
From: Jon Smirl @ 2007-12-06 1:55 UTC (permalink / raw)
To: Grant Likely, Domen Puncer, PowerPC dev list
V2h5IGRvZXMgdGhlIGZlYzUyMDAgZHJpdmVyIHNvbWV0aW1lcyBub3QgcHJpbnQgJ1BIWScgY29y
cmVjdGx5PwoKcGh5Q09SRS1NUEM1MjAwQi10aW55IGxvZ2luOiBU2KRW77+9IGYwMDAzMDAwOjEw
IC0gTGluayBpcyBEb3duClTvv71ZOiBmMDAwMzAwMDoxMCAtIExpbmsgaXMgVXAgLSAxMDAvRnVs
bApU77+9WTogZjAwMDMwMDA6MTAgLSBMaW5rIGlzIERvd24KUEhZOiBmMDAwMzAwMDoxMCAtIExp
bmsgaXMgVXAgLSAxMDAvRnVsbAoKLS0gCkpvbiBTbWlybApqb25zbWlybEBnbWFpbC5jb20K
^ permalink raw reply
* Re: Regarding MPC8641D
From: sivaji @ 2007-12-06 1:45 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <D83235F0F3C86D4D889D8B9A0DA8C6D7011A75D5@corpexc01.corp.networkrobots.com>
Hi,
We need only SMP mode, asper ur idea let me disable the Low
memory offset mode. We face some issues when ioremap in the kernel, we guess
the problem is related to Low memory offset mode so only we go for that.
Consider now the Low memory offset is disable the bootargs (root=/dev/ram
console=ttyS0, mem=504M). When mem=504 or greater than we are not able to
ioremap, if mem is less than 500 there was no issues on ioremap. We can't
understand why ioremap was failed for 504M?
Thanks and Regards
S.Balamurugan
Siva Prasad-3 wrote:
>
> Hi,
>
> If you want to use SMP, do not enable low memory offset mode. That is
> only and only for AMP, not for SMP. All the exception vectors go into a
> different address range for core1, once you enable that, resulting in a
> need for entirely different copy of OS (be it Linux, or any other OS).
>
> You are in the right path. Just don't enable low memory offset mode,
> unless you are looking for Assymetric multi-processing.
>
> - siva
>
>
>
>
> Message: 6
> Date: Wed, 5 Dec 2007 16:45:31 -0800 (PST)
> From: sivaji <rameshmrm@gmail.com>
> Subject: Re: Regarding MPC8641D
> To: linuxppc-dev@ozlabs.org
> Message-ID: <14184234.post@talk.nabble.com>
> Content-Type: text/plain; charset=us-ascii
>
>
> Hai,
> The kernel was compiled in SMP mode. The low memory offset
> mode
> is only for AMP mode means, then how we test both the core 0 and 1 in
> the
> linux kernel ?. Asper my understanding if we enable the Low Memory
> Offset
> mode, then only the core1 translation is enabled. If we disalbed the Low
> Memory offset mode, Only Core 0 will work in SMP mode and Core 1 will
> idle.
> If we want to test the efficient of Dual core means we need to enable
> both
> the core and Low Memory Offset Mode. For this configuration linux kernel
> was
> not up.
> ( Please correct me if I am wrong )
>
> Thanks and Regards
> Sivaji
>
>
> Chris Fester wrote:
>>
>> On Tue, 2007-12-04 at 23:51 -0800, sivaji wrote:
>>> We have designed a MPC8641D based AMC card. We are using
> the
>>> kernel (2.6.23-rc4) and uboot (1.2.0). When we disable the core1 Low
>>> Memory
>>> offset mode the kernel was up and when we enable this core1 Low
> Memory
>>> offset mode kernel was not up, It was hang after MPIC initialization.
>> [snip!]
>>> After this the kernel was hang, i want to know
> why
>>> kernel was hang when we enalbe Low memory Offset mode. Please help me
> to
>>> fix
>>> this issue.
>>
>> Have you compiled your kernel for SMP mode? I believe the Low memory
>> offset mode is only for AMP mode (vxworks can use this, probably other
>> OSes). I don't know if the kernel has support for any multiprocessing
>> mode other than SMP.
>>
>> Hope that helps,
>> Chris
>>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
>
--
View this message in context: http://www.nabble.com/Regarding-MPC8641D-tf4948004.html#a14184891
Sent from the linuxppc-dev mailing list archive at Nabble.com.
^ permalink raw reply
* [PATCH] windfarm: add PowerMac 12,1 support
From: Étienne Bersac @ 2007-12-06 1:20 UTC (permalink / raw)
To: linuxppc-dev
From: Étienne Bersac <bersace@gmail.com>
Implement a new driver named windfarm_pm121 which drive fans on PowerMac
12,1 machine : iMac G5 iSight (rev C) 17" and 20". It's based on
windfarm_pm81 driver from Benjamin Herrenschmidt.
Signed-off-by: Étienne Bersac <bersace@gmail.com>
---
Implement fan control for PowerMac 12,1 machines. This needs update to
windfarm_lm75 and windfarm_max6690 sensors drivers in order to properly
match sensors by their location. The code is based on windfarm_pm81
driver, adapted to the complexity of PowerMac 12,1 : 4 system control
loops instead of one, per-control target correction and per-model
control rubber-banding.
All the data are copied from Darwin 8.10 AppleMacRISC4PE-185.0.0 module
as well as correction formula.
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 0a6fa1f..7125837 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -656,6 +656,7 @@ CONFIG_WINDFARM=y
CONFIG_WINDFARM_PM81=y
CONFIG_WINDFARM_PM91=y
CONFIG_WINDFARM_PM112=y
+CONFIG_WINDFARM_PM121=y
# CONFIG_PMAC_RACKMETER is not set
CONFIG_NETDEVICES=y
# CONFIG_NETDEVICES_MULTIQUEUE is not set
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 77f50b6..2d028e6 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -234,6 +234,14 @@ config WINDFARM_PM112
which are the recent dual and quad G5 machines using the
970MP dual-core processor.
+config WINDFARM_PM121
+ tristate "Support for thermal management on PowerMac12,1"
+ depends on WINDFARM && I2C && PMAC_SMU
+ select I2C_POWERMAC
+ help
+ This driver provides thermal control for the PowerMac12,1
+ which is the iMac G5 (iSight) 970MP
+
config ANSLCD
tristate "Support for ANS LCD display"
depends on ADB_CUDA && PPC_PMAC
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
index 2dfc3f4..e3132ef 100644
--- a/drivers/macintosh/Makefile
+++ b/drivers/macintosh/Makefile
@@ -42,4 +42,9 @@ obj-$(CONFIG_WINDFARM_PM112) += windfarm_pm112.o windfarm_smu_sat.o \
windfarm_smu_sensors.o \
windfarm_max6690_sensor.o \
windfarm_lm75_sensor.o windfarm_pid.o
+obj-$(CONFIG_WINDFARM_PM121) += windfarm_pm121.o windfarm_smu_sat.o \
+ windfarm_smu_controls.o \
+ windfarm_smu_sensors.o \
+ windfarm_max6690_sensor.o \
+ windfarm_lm75_sensor.o windfarm_pid.o
obj-$(CONFIG_PMAC_RACKMETER) += rack-meter.o
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
index 7e10c3a..b92b959 100644
--- a/drivers/macintosh/windfarm_lm75_sensor.c
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
@@ -127,6 +127,12 @@ static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter,
*/
if (!strcmp(loc, "Hard drive") || !strcmp(loc, "DRIVE BAY"))
lm->sens.name = "hd-temp";
+ else if (!strcmp(loc, "Incoming Air Temp"))
+ lm->sens.name = "incoming-air-temp";
+ else if (!strcmp(loc, "ODD Temp"))
+ lm->sens.name = "optical-drive-temp";
+ else if (!strcmp(loc, "HD Temp"))
+ lm->sens.name = "hard-drive-temp";
else
goto fail;
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
index 5f03aab..c2b6d1c 100644
--- a/drivers/macintosh/windfarm_max6690_sensor.c
+++ b/drivers/macintosh/windfarm_max6690_sensor.c
@@ -77,10 +77,11 @@ static struct wf_sensor_ops wf_max6690_ops = {
.owner = THIS_MODULE,
};
-static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr)
+static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr,
+ const char *loc)
{
struct wf_6690_sensor *max;
- char *name = "backside-temp";
+ char *name = NULL;
max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
if (max == NULL) {
@@ -89,6 +90,15 @@ static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr)
return;
}
+ if (!strcmp(loc, "BACKSIDE"))
+ name = "backside-temp";
+ else if (!strcmp(loc, "NB Ambient"))
+ name = "north-bridge-temp";
+ else if (!strcmp(loc, "GPU Ambient"))
+ name = "gpu-temp";
+ else
+ goto fail;
+
max->sens.ops = &wf_max6690_ops;
max->sens.name = name;
max->i2c.addr = addr >> 1;
@@ -138,9 +148,7 @@ static int wf_max6690_attach(struct i2c_adapter *adapter)
if (loc == NULL || addr == 0)
continue;
printk("found max6690, loc=%s addr=0x%02x\n", loc, addr);
- if (strcmp(loc, "BACKSIDE"))
- continue;
- wf_max6690_create(adapter, addr);
+ wf_max6690_create(adapter, addr, loc);
}
return 0;
diff --git a/drivers/macintosh/windfarm_pm121.c b/drivers/macintosh/windfarm_pm121.c
new file mode 100644
index 0000000..0cb4b3e
--- /dev/null
+++ b/drivers/macintosh/windfarm_pm121.c
@@ -0,0 +1,1052 @@
+/*
+ * Windfarm PowerMac thermal control. iMac G5 iSight
+ *
+ * (c) Copyright 2007 Étienne Bersac <bersace@gmail.com>
+ *
+ * Bits & pieces from windfarm_pm81.c by (c) Copyright 2005 Benjamin
+ * Herrenschmidt, IBM Corp. <benh@kernel.crashing.org>
+ *
+ * Released under the term of the GNU GPL v2.
+ *
+ *
+ *
+ * PowerMac12,1
+ * ============
+ *
+ *
+ * The algorithm used is the PID control algorithm, used the same way
+ * the published Darwin code does, using the same values that are
+ * present in the Darwin 8.10 snapshot property lists (note however
+ * that none of the code has been re-used, it's a complete
+ * re-implementation
+ *
+ * There is two models using PowerMac12,1. Model 2 is iMac G5 iSight
+ * 17" while Model 3 is iMac G5 20". They do have both the same
+ * controls with a tiny difference. The control-ids of hard-drive-fan
+ * and cpu-fan is swapped.
+ *
+ *
+ * Target Correction :
+ *
+ * controls have a target correction calculated as :
+ *
+ * new_min = ((((average_power * slope) >> 16) + offset) >> 16) + min_value
+ * new_value = max(new_value, max(new_min, 0))
+ *
+ * OD Fan control correction.
+ *
+ * # model_id: 2
+ * offset : -19563152
+ * slope : 1956315
+ *
+ * # model_id: 3
+ * offset : -15650652
+ * slope : 1565065
+ *
+ * HD Fan control correction.
+ *
+ * # model_id: 2
+ * offset : -15650652
+ * slope : 1565065
+ *
+ * # model_id: 3
+ * offset : -19563152
+ * slope : 1956315
+ *
+ * CPU Fan control correction.
+ *
+ * # model_id: 2
+ * offset : -25431900
+ * slope : 2543190
+ *
+ * # model_id: 3
+ * offset : -15650652
+ * slope : 1565065
+ *
+ *
+ * Target rubber-banding :
+ *
+ * Some controls have a target correction which depends on another
+ * control value. The correction is computed in the following way :
+ *
+ * new_min = ref_value * slope + offset
+ *
+ * ref_value is the value of the reference control. If new_min is
+ * greater than 0, then we correct the target value using :
+ *
+ * new_target = max (new_target, new_min >> 16)
+ *
+ *
+ * # model_id : 2
+ * control : cpu-fan
+ * ref : optical-drive-fan
+ * offset : -15650652
+ * slope : 1565065
+ *
+ * # model_id : 3
+ * control : optical-drive-fan
+ * ref : hard-drive-fan
+ * offset : -32768000
+ * slope : 65536
+ *
+ *
+ * In order to have the moste efficient correction with those
+ * dependencies, we must trigger HD loop before OD loop before CPU
+ * loop.
+ *
+ *
+ * The various control loops found in Darwin config file are:
+ *
+ * HD Fan control loop.
+ *
+ * # model_id: 2
+ * control : hard-drive-fan
+ * sensor : hard-drive-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x002D70A3
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x370000
+ * Interval = 5s
+ *
+ * # model_id: 3
+ * control : hard-drive-fan
+ * sensor : hard-drive-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x002170A3
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x370000
+ * Interval = 5s
+ *
+ * OD Fan control loop.
+ *
+ * # model_id: 2
+ * control : optical-drive-fan
+ * sensor : optical-drive-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x001FAE14
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x320000
+ * Interval = 5s
+ *
+ * # model_id: 3
+ * control : optical-drive-fan
+ * sensor : optical-drive-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x001FAE14
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x320000
+ * Interval = 5s
+ *
+ * GPU Fan control loop.
+ *
+ * # model_id: 2
+ * control : hard-drive-fan
+ * sensor : gpu-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x002A6666
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x5A0000
+ * Interval = 5s
+ *
+ * # model_id: 3
+ * control : cpu-fan
+ * sensor : gpu-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x0010CCCC
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x500000
+ * Interval = 5s
+ *
+ * KODIAK (aka northbridge) Fan control loop.
+ *
+ * # model_id: 2
+ * control : optical-drive-fan
+ * sensor : north-bridge-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x003BD70A
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x550000
+ * Interval = 5s
+ *
+ * # model_id: 3
+ * control : hard-drive-fan
+ * sensor : north-bridge-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x0030F5C2
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x550000
+ * Interval = 5s
+ *
+ * CPU Fan control loop.
+ *
+ * control : cpu-fan
+ * sensors : cpu-temp, cpu-power
+ * PID params : from SDB partition
+ *
+ *
+ * CPU Slew control loop.
+ *
+ * control : cpufreq-clamp
+ * sensor : cpu-temp
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/kmod.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/sections.h>
+#include <asm/smu.h>
+
+#include "windfarm.h"
+#include "windfarm_pid.h"
+
+#define VERSION "0.1"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(args...) printk(args)
+#else
+#define DBG(args...) do { } while (0)
+#endif
+
+static int pm121_mach_model; /* machine model id */
+
+/* Controls & sensors */
+static struct wf_sensor *sensor_cpu_power;
+static struct wf_sensor *sensor_cpu_temp;
+static struct wf_sensor *sensor_cpu_voltage;
+static struct wf_sensor *sensor_cpu_current;
+static struct wf_sensor *sensor_gpu_temp;
+static struct wf_sensor *sensor_north_bridge_temp;
+static struct wf_sensor *sensor_hard_drive_temp;
+static struct wf_sensor *sensor_optical_drive_temp;
+static struct wf_sensor *sensor_incoming_air_temp; /* unused ! */
+
+enum {
+ FAN_CPU,
+ FAN_HD,
+ FAN_OD,
+ CPUFREQ,
+ N_CONTROLS
+};
+static struct wf_control *controls[N_CONTROLS] = {};
+
+/* Set to kick the control loop into life */
+static int pm121_all_controls_ok, pm121_all_sensors_ok, pm121_started;
+
+enum {
+ FAILURE_FAN = 1 << 0,
+ FAILURE_SENSOR = 1 << 1,
+ FAILURE_OVERTEMP = 1 << 2
+};
+
+/* All sys loops. Note the HD before the OD loop in order to have it
+ run before. */
+enum {
+ LOOP_GPU, /* control = hd or cpu, but luckily,
+ it doesn't matter */
+ LOOP_HD, /* control = hd */
+ LOOP_KODIAK, /* control = hd or od */
+ LOOP_OD, /* control = od */
+ N_LOOPS
+};
+
+static const char *loop_names[N_LOOPS] = {
+ "GPU",
+ "HD",
+ "KODIAK",
+ "OD",
+};
+
+#define PM121_NUM_CONFIGS 2
+
+static unsigned int pm121_failure_state;
+static int pm121_readjust, pm121_skipping;
+static s32 average_power;
+
+struct pm121_correction {
+ int offset;
+ int slope;
+};
+
+struct pm121_correction corrections[N_CONTROLS][PM121_NUM_CONFIGS] = {
+ /* FAN_OD */
+ {
+ /* MODEL 2 */
+ { .offset = -19563152,
+ .slope = 1956315
+ },
+ /* MODEL 3 */
+ { .offset = -15650652,
+ .slope = 1565065
+ },
+ },
+ /* FAN_HD */
+ {
+ /* MODEL 2 */
+ { .offset = -15650652,
+ .slope = 1565065
+ },
+ /* MODEL 3 */
+ { .offset = -19563152,
+ .slope = 1956315
+ },
+ },
+ /* FAN_CPU */
+ {
+ /* MODEL 2 */
+ { .offset = -25431900,
+ .slope = 2543190
+ },
+ /* MODEL 3 */
+ { .offset = -15650652,
+ .slope = 1565065
+ },
+ },
+ /* CPUFREQ has no correction (and is not implemented at all) */
+};
+
+struct pm121_connection {
+ unsigned int control_id;
+ unsigned int ref_id;
+ struct pm121_correction correction;
+};
+
+static struct pm121_connection pm121_connections[] = {
+ /* MODEL 2 */
+ { .control_id = FAN_CPU,
+ .ref_id = FAN_OD,
+ { .offset = -32768000,
+ .slope = 65536
+ }
+ },
+ /* MODEL 3 */
+ { .control_id = FAN_OD,
+ .ref_id = FAN_HD,
+ { .offset = -32768000,
+ .slope = 65536
+ }
+ },
+};
+
+/* pointer to the current model connection */
+static struct pm121_connection *pm121_connection;
+
+/*
+ * ****** System Fans Control Loop ******
+ *
+ */
+
+/* Since each loop handles only one control and we want to avoid
+ * writing virtual control, we store the control correction with the
+ * loop params. Some data are not set, there are common to all loop
+ * and thus, hardcoded.
+ */
+struct pm121_sys_param {
+ /* purely informative since we use mach_model-2 as index */
+ int model_id;
+ struct wf_sensor **sensor; /* use sensor_id instead ? */
+ s32 gp, itarget;
+ unsigned int control_id;
+};
+
+static struct pm121_sys_param
+pm121_sys_all_params[N_LOOPS][PM121_NUM_CONFIGS] = {
+ /* GPU Fan control loop */
+ {
+ { .model_id = 2,
+ .sensor = &sensor_gpu_temp,
+ .gp = 0x002A6666,
+ .itarget = 0x5A0000,
+ .control_id = FAN_HD,
+ },
+ { .model_id = 3,
+ .sensor = &sensor_gpu_temp,
+ .gp = 0x0010CCCC,
+ .itarget = 0x500000,
+ .control_id = FAN_CPU,
+ },
+ },
+ /* HD Fan control loop */
+ {
+ { .model_id = 2,
+ .sensor = &sensor_hard_drive_temp,
+ .gp = 0x002D70A3,
+ .itarget = 0x370000,
+ .control_id = FAN_HD,
+ },
+ { .model_id = 3,
+ .sensor = &sensor_hard_drive_temp,
+ .gp = 0x002170A3,
+ .itarget = 0x370000,
+ .control_id = FAN_HD,
+ },
+ },
+ /* KODIAK Fan control loop */
+ {
+ { .model_id = 2,
+ .sensor = &sensor_north_bridge_temp,
+ .gp = 0x003BD70A,
+ .itarget = 0x550000,
+ .control_id = FAN_OD,
+ },
+ { .model_id = 3,
+ .sensor = &sensor_north_bridge_temp,
+ .gp = 0x0030F5C2,
+ .itarget = 0x550000,
+ .control_id = FAN_HD,
+ },
+ },
+ /* OD Fan control loop */
+ {
+ { .model_id = 2,
+ .sensor = &sensor_optical_drive_temp,
+ .gp = 0x001FAE14,
+ .itarget = 0x320000,
+ .control_id = FAN_OD,
+ },
+ { .model_id = 3,
+ .sensor = &sensor_optical_drive_temp,
+ .gp = 0x001FAE14,
+ .itarget = 0x320000,
+ .control_id = FAN_OD,
+ },
+ },
+};
+
+/* the hardcoded values */
+#define PM121_SYS_GD 0x00000000
+#define PM121_SYS_GR 0x00019999
+#define PM121_SYS_HISTORY_SIZE 2
+#define PM121_SYS_INTERVAL 5
+
+/* State data used by the system fans control loop
+ */
+struct pm121_sys_state {
+ int ticks;
+ s32 setpoint;
+ struct wf_pid_state pid;
+};
+
+struct pm121_sys_state *pm121_sys_state[N_LOOPS] = {};
+
+/*
+ * ****** CPU Fans Control Loop ******
+ *
+ */
+
+#define PM121_CPU_INTERVAL 1
+
+/* State data used by the cpu fans control loop
+ */
+struct pm121_cpu_state {
+ int ticks;
+ s32 setpoint;
+ struct wf_cpu_pid_state pid;
+};
+
+static struct pm121_cpu_state *pm121_cpu_state;
+
+
+
+/*
+ * ***** Implementation *****
+ *
+ */
+
+/* correction the value using the output-low-bound correction algo */
+static s32 pm121_correct(s32 new_setpoint,
+ unsigned int control_id,
+ s32 min)
+{
+ s32 new_min;
+ struct pm121_correction *correction;
+ correction = &corrections[control_id][pm121_mach_model - 2];
+
+ new_min = (average_power * correction->slope) >> 16;
+ new_min += correction->offset;
+ new_min = (new_min >> 16) + min;
+
+ return max(new_setpoint, max(new_min, 0));
+}
+
+static s32 pm121_connect(unsigned int control_id, s32 setpoint)
+{
+ s32 new_min, value, new_setpoint;
+
+ if (pm121_connection->control_id == control_id) {
+ controls[control_id]->ops->get_value(controls[control_id],
+ &value);
+ new_min = value * pm121_connection->correction.slope;
+ new_min += pm121_connection->correction.offset;
+ if (new_min > 0) {
+ new_setpoint = max(setpoint, (new_min >> 16));
+ if (new_setpoint != setpoint) {
+ DBG("pm121: %s depending on %s, "
+ "corrected from %d to %d RPM\n",
+ controls[control_id]->name,
+ controls[pm121_connection->ref_id]->name,
+ (int) setpoint, (int) new_setpoint);
+ }
+ } else
+ new_setpoint = setpoint;
+ }
+ /* no connection */
+ else
+ new_setpoint = setpoint;
+
+ return new_setpoint;
+}
+
+/* FAN LOOPS */
+static void pm121_create_sys_fans(int loop_id)
+{
+ struct pm121_sys_param *param = NULL;
+ struct wf_pid_param pid_param;
+ struct wf_control *control = NULL;
+ int i;
+
+ /* First, locate the params for this model */
+ for (i = 0; i < PM121_NUM_CONFIGS; i++) {
+ param = &(pm121_sys_all_params[loop_id][i]);
+ if (param->model_id == pm121_mach_model)
+ break;
+ }
+
+ /* No params found, put fans to max */
+ if (param == NULL) {
+ printk(KERN_WARNING "pm121: %s fan config not found "
+ " for this machine model\n",
+ loop_names[loop_id]);
+ goto fail;
+ }
+
+ control = controls[param->control_id];
+
+ /* Alloc & initialize state */
+ pm121_sys_state[loop_id] = kmalloc(sizeof(struct pm121_sys_state),
+ GFP_KERNEL);
+ if (pm121_sys_state[loop_id] == NULL) {
+ printk(KERN_WARNING "pm121: Memory allocation error\n");
+ goto fail;
+ }
+ pm121_sys_state[loop_id]->ticks = 1;
+
+ /* Fill PID params */
+ pid_param.gd = PM121_SYS_GD;
+ pid_param.gp = param->gp;
+ pid_param.gr = PM121_SYS_GR;
+ pid_param.interval = PM121_SYS_INTERVAL;
+ pid_param.history_len = PM121_SYS_HISTORY_SIZE;
+ pid_param.itarget = param->itarget;
+ pid_param.min = control->ops->get_min(control);
+ pid_param.max = control->ops->get_max(control);
+
+ wf_pid_init(&pm121_sys_state[loop_id]->pid, &pid_param);
+
+ DBG("pm121: %s Fan control loop initialized.\n"
+ " itarged=%d.%03d, min=%d RPM, max=%d RPM\n",
+ loop_names[loop_id], FIX32TOPRINT(pid_param.itarget),
+ pid_param.min, pid_param.max);
+ return;
+
+ fail:
+ /* note that this is not optimal since another loop may still
+ control the same control */
+ printk(KERN_WARNING "pm121: failed to set up %s loop "
+ "setting \"%s\" to max speed.\n",
+ loop_names[loop_id], control->name);
+
+ if (control)
+ wf_control_set_max(control);
+}
+
+static void pm121_sys_fans_tick(int loop_id)
+{
+ struct pm121_sys_param *param;
+ struct pm121_sys_state *st;
+ struct wf_sensor *sensor;
+ struct wf_control *control;
+ s32 temp, new_setpoint;
+ int rc;
+
+ param = &(pm121_sys_all_params[loop_id][pm121_mach_model-2]);
+ st = pm121_sys_state[loop_id];
+ sensor = *(param->sensor);
+ control = controls[param->control_id];
+
+ if (--st->ticks != 0) {
+ if (pm121_readjust)
+ goto readjust;
+ return;
+ }
+ st->ticks = PM121_SYS_INTERVAL;
+
+ rc = sensor->ops->get_value(sensor, &temp);
+ if (rc) {
+ printk(KERN_WARNING "windfarm: %s sensor error %d\n",
+ sensor->name, rc);
+ pm121_failure_state |= FAILURE_SENSOR;
+ return;
+ }
+
+ DBG("pm121: %s Fan tick ! %s: %d.%03d\n",
+ loop_names[loop_id], sensor->name,
+ FIX32TOPRINT(temp));
+
+ new_setpoint = wf_pid_run(&st->pid, temp);
+
+ /* correction */
+ new_setpoint = pm121_correct(new_setpoint,
+ param->control_id,
+ st->pid.param.min);
+ /* linked corretion */
+ new_setpoint = pm121_connect(param->control_id, new_setpoint);
+
+ if (new_setpoint == st->setpoint)
+ return;
+ st->setpoint = new_setpoint;
+ DBG("pm121: %s corrected setpoint: %d RPM\n",
+ control->name, (int)new_setpoint);
+ readjust:
+ if (control && pm121_failure_state == 0) {
+ rc = control->ops->set_value(control, st->setpoint);
+ if (rc) {
+ printk(KERN_WARNING "windfarm: %s fan error %d\n",
+ control->name, rc);
+ pm121_failure_state |= FAILURE_FAN;
+ }
+ }
+}
+
+
+/* CPU LOOP */
+static void pm121_create_cpu_fans(void)
+{
+ struct wf_cpu_pid_param pid_param;
+ const struct smu_sdbp_header *hdr;
+ struct smu_sdbp_cpupiddata *piddata;
+ struct smu_sdbp_fvt *fvt;
+ struct wf_control *fan_cpu;
+ s32 tmax, tdelta, maxpow, powadj;
+
+ fan_cpu = controls[FAN_CPU];
+
+ /* First, locate the PID params in SMU SBD */
+ hdr = smu_get_sdb_partition(SMU_SDB_CPUPIDDATA_ID, NULL);
+ if (hdr == 0) {
+ printk(KERN_WARNING "pm121: CPU PID fan config not found.\n");
+ goto fail;
+ }
+ piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
+
+ /* Get the FVT params for operating point 0 (the only supported one
+ * for now) in order to get tmax
+ */
+ hdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL);
+ if (hdr) {
+ fvt = (struct smu_sdbp_fvt *)&hdr[1];
+ tmax = ((s32)fvt->maxtemp) << 16;
+ } else
+ tmax = 0x5e0000; /* 94 degree default */
+
+ /* Alloc & initialize state */
+ pm121_cpu_state = kmalloc(sizeof(struct pm121_cpu_state),
+ GFP_KERNEL);
+ if (pm121_cpu_state == NULL)
+ goto fail;
+ pm121_cpu_state->ticks = 1;
+
+ /* Fill PID params */
+ pid_param.interval = PM121_CPU_INTERVAL;
+ pid_param.history_len = piddata->history_len;
+ if (pid_param.history_len > WF_CPU_PID_MAX_HISTORY) {
+ printk(KERN_WARNING "pm121: History size overflow on "
+ "CPU control loop (%d)\n", piddata->history_len);
+ pid_param.history_len = WF_CPU_PID_MAX_HISTORY;
+ }
+ pid_param.gd = piddata->gd;
+ pid_param.gp = piddata->gp;
+ pid_param.gr = piddata->gr / pid_param.history_len;
+
+ tdelta = ((s32)piddata->target_temp_delta) << 16;
+ maxpow = ((s32)piddata->max_power) << 16;
+ powadj = ((s32)piddata->power_adj) << 16;
+
+ pid_param.tmax = tmax;
+ pid_param.ttarget = tmax - tdelta;
+ pid_param.pmaxadj = maxpow - powadj;
+
+ pid_param.min = fan_cpu->ops->get_min(fan_cpu);
+ pid_param.max = fan_cpu->ops->get_max(fan_cpu);
+
+ wf_cpu_pid_init(&pm121_cpu_state->pid, &pid_param);
+
+ DBG("pm121: CPU Fan control initialized.\n");
+ DBG(" ttarged=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM,\n",
+ FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax),
+ pid_param.min, pid_param.max);
+
+ return;
+
+ fail:
+ printk(KERN_WARNING "pm121: CPU fan config not found, max fan speed\n");
+
+ if (controls[CPUFREQ])
+ wf_control_set_max(controls[CPUFREQ]);
+ if (fan_cpu)
+ wf_control_set_max(fan_cpu);
+}
+
+
+static void pm121_cpu_fans_tick(struct pm121_cpu_state *st)
+{
+ s32 new_setpoint, temp, power;
+ struct wf_control *fan_cpu = NULL;
+ int rc;
+
+ if (--st->ticks != 0) {
+ if (pm121_readjust)
+ goto readjust;
+ return;
+ }
+ st->ticks = PM121_CPU_INTERVAL;
+
+ fan_cpu = controls[FAN_CPU];
+
+ rc = sensor_cpu_temp->ops->get_value(sensor_cpu_temp, &temp);
+ if (rc) {
+ printk(KERN_WARNING "pm121: CPU temp sensor error %d\n",
+ rc);
+ pm121_failure_state |= FAILURE_SENSOR;
+ return;
+ }
+
+ rc = sensor_cpu_power->ops->get_value(sensor_cpu_power, &power);
+ if (rc) {
+ printk(KERN_WARNING "pm121: CPU power sensor error %d\n",
+ rc);
+ pm121_failure_state |= FAILURE_SENSOR;
+ return;
+ }
+
+ DBG("pm121: CPU Fans tick ! CPU temp: %d.%03d°C, power: %d.%03d\n",
+ FIX32TOPRINT(temp), FIX32TOPRINT(power));
+
+#ifdef HACKED_OVERTEMP
+#define MAX 0x4a0000
+#else
+#define MAX st->pid.param.tmax
+#endif
+ if (temp > MAX)
+ pm121_failure_state |= FAILURE_OVERTEMP;
+
+#undef MAX
+
+ new_setpoint = wf_cpu_pid_run(&st->pid, power, temp);
+
+ /* correction */
+ new_setpoint = pm121_correct(new_setpoint,
+ FAN_CPU,
+ st->pid.param.min);
+
+ /* connected correction */
+ new_setpoint = pm121_connect(FAN_CPU, new_setpoint);
+
+ if (st->setpoint == new_setpoint)
+ return;
+ st->setpoint = new_setpoint;
+ DBG("pm121: CPU corrected setpoint: %d RPM\n", (int)new_setpoint);
+
+ readjust:
+ if (fan_cpu && pm121_failure_state == 0) {
+ rc = fan_cpu->ops->set_value(fan_cpu, st->setpoint);
+ if (rc) {
+ printk(KERN_WARNING "pm121: %s fan error %d\n",
+ fan_cpu->name, rc);
+ pm121_failure_state |= FAILURE_FAN;
+ }
+ }
+}
+
+/*
+ * ****** Common ******
+ *
+ */
+
+static void pm121_tick(void)
+{
+ unsigned int last_failure = pm121_failure_state;
+ unsigned int new_failure;
+ s32 total_power;
+ int i;
+
+ if (!pm121_started) {
+ DBG("pm121: creating control loops !\n");
+ for (i = 0; i < N_LOOPS; i++)
+ pm121_create_sys_fans(i);
+
+ pm121_create_cpu_fans();
+ pm121_started = 1;
+ }
+
+ /* skipping ticks */
+ if (pm121_skipping && --pm121_skipping)
+ return;
+
+ /* compute average power */
+ total_power = 0;
+ for (i = 0; i < pm121_cpu_state->pid.param.history_len; i++)
+ total_power += pm121_cpu_state->pid.powers[i];
+
+ average_power = total_power / pm121_cpu_state->pid.param.history_len;
+
+
+ pm121_failure_state = 0;
+ for (i = 0 ; i < N_LOOPS; i++) {
+ if (pm121_sys_state[i])
+ pm121_sys_fans_tick(i);
+ }
+
+ if (pm121_cpu_state)
+ pm121_cpu_fans_tick(pm121_cpu_state);
+
+ pm121_readjust = 0;
+ new_failure = pm121_failure_state & ~last_failure;
+
+ /* If entering failure mode, clamp cpufreq and ramp all
+ * fans to full speed.
+ */
+ if (pm121_failure_state && !last_failure) {
+ for (i = 0; i < N_CONTROLS; i++) {
+ if (controls[i])
+ wf_control_set_max(controls[i]);
+ }
+ }
+
+ /* If leaving failure mode, unclamp cpufreq and readjust
+ * all fans on next iteration
+ */
+ if (!pm121_failure_state && last_failure) {
+ if (controls[CPUFREQ])
+ wf_control_set_min(controls[CPUFREQ]);
+ pm121_readjust = 1;
+ }
+
+ /* Overtemp condition detected, notify and start skipping a couple
+ * ticks to let the temperature go down
+ */
+ if (new_failure & FAILURE_OVERTEMP) {
+ wf_set_overtemp();
+ pm121_skipping = 2;
+ }
+
+ /* We only clear the overtemp condition if overtemp is cleared
+ * _and_ no other failure is present. Since a sensor error will
+ * clear the overtemp condition (can't measure temperature) at
+ * the control loop levels, but we don't want to keep it clear
+ * here in this case
+ */
+ if (new_failure == 0 && last_failure & FAILURE_OVERTEMP)
+ wf_clear_overtemp();
+}
+
+
+
+
+#define pm121_register_control(control, match, id) \
+ if (controls[id] == NULL && !strcmp(control->name,match)) { \
+ if (wf_get_control(control) == 0) \
+ controls[id] = control; \
+ } \
+ all = all && controls[id];
+
+static void pm121_new_control(struct wf_control *ct)
+{
+ int all = 1;
+
+ if (pm121_all_controls_ok)
+ return;
+
+ pm121_register_control(ct, "optical-drive-fan", FAN_OD);
+ pm121_register_control(ct, "hard-drive-fan", FAN_HD);
+ pm121_register_control(ct, "cpu-fan", FAN_CPU);
+ pm121_register_control(ct, "cpufreq-clamp", CPUFREQ);
+
+ if (all)
+ pm121_all_controls_ok = 1;
+}
+#undef pm121_register_control
+
+
+
+
+#define pm121_register_sensor(sensor, match, var) \
+ if (var == NULL && !strcmp(sensor->name,match)) { \
+ if (wf_get_sensor(sensor) == 0) \
+ var = sensor; \
+ } \
+ all = all && var;
+
+static void pm121_new_sensor(struct wf_sensor *sr)
+{
+ int all = 1;
+
+ if (pm121_all_sensors_ok)
+ return;
+
+ pm121_register_sensor(sr, "cpu-temp",
+ sensor_cpu_temp);
+ pm121_register_sensor(sr, "cpu-current",
+ sensor_cpu_current);
+ pm121_register_sensor(sr, "cpu-voltage",
+ sensor_cpu_voltage);
+ pm121_register_sensor(sr, "cpu-power",
+ sensor_cpu_power);
+ pm121_register_sensor(sr, "hard-drive-temp",
+ sensor_hard_drive_temp);
+ pm121_register_sensor(sr, "optical-drive-temp",
+ sensor_optical_drive_temp);
+ pm121_register_sensor(sr, "incoming-air-temp",
+ sensor_incoming_air_temp);
+ pm121_register_sensor(sr, "north-bridge-temp",
+ sensor_north_bridge_temp);
+ pm121_register_sensor(sr, "gpu-temp",
+ sensor_gpu_temp);
+
+ if (all)
+ pm121_all_sensors_ok = 1;
+}
+
+#undef pm121_register_sensor
+
+
+
+static int pm121_notify(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ switch (event) {
+ case WF_EVENT_NEW_CONTROL:
+ DBG("pm121: new control %s detected\n",
+ ((struct wf_control *)data)->name);
+ pm121_new_control(data);
+ break;
+ case WF_EVENT_NEW_SENSOR:
+ DBG("pm121: new sensor %s detected\n",
+ ((struct wf_sensor *)data)->name);
+ pm121_new_sensor(data);
+ break;
+ case WF_EVENT_TICK:
+ if (pm121_all_controls_ok && pm121_all_sensors_ok)
+ pm121_tick();
+ break;
+ }
+
+ return 0;
+}
+
+static struct notifier_block pm121_events = {
+ .notifier_call = pm121_notify,
+};
+
+static int pm121_init_pm(void)
+{
+ const struct smu_sdbp_header *hdr;
+
+ hdr = smu_get_sdb_partition(SMU_SDB_SENSORTREE_ID, NULL);
+ if (hdr != 0) {
+ struct smu_sdbp_sensortree *st =
+ (struct smu_sdbp_sensortree *)&hdr[1];
+ pm121_mach_model = st->model_id;
+ }
+
+ pm121_connection = &pm121_connections[pm121_mach_model - 2];
+
+ printk(KERN_INFO "pm121: Initializing for iMac G5 iSight model ID %d\n",
+ pm121_mach_model);
+
+ return 0;
+}
+
+
+static int pm121_probe(struct platform_device *ddev)
+{
+ wf_register_client(&pm121_events);
+
+ return 0;
+}
+
+static int __devexit pm121_remove(struct platform_device *ddev)
+{
+ wf_unregister_client(&pm121_events);
+ return 0;
+}
+
+static struct platform_driver pm121_driver = {
+ .probe = pm121_probe,
+ .remove = __devexit_p(pm121_remove),
+ .driver = {
+ .name = "windfarm",
+ .bus = &platform_bus_type,
+ },
+};
+
+
+static int __init pm121_init(void)
+{
+ int rc = -ENODEV;
+
+ if (machine_is_compatible("PowerMac12,1"))
+ rc = pm121_init_pm();
+
+ if (rc == 0) {
+#ifdef MODULE
+ request_module("windfarm_smu_controls");
+ request_module("windfarm_smu_sensors");
+ request_module("windfarm_smu_sat");
+ request_module("windfarm_lm75_sensor");
+ request_module("windfarm_max6690_sensor");
+ request_module("windfarm_cpufreq_clamp");
+
+#endif /* MODULE */
+ platform_driver_register(&pm121_driver);
+ }
+
+ return rc;
+}
+
+static void __exit pm121_exit(void)
+{
+
+ platform_driver_unregister(&pm121_driver);
+}
+
+
+module_init(pm121_init);
+module_exit(pm121_exit);
+
+MODULE_AUTHOR("Étienne Bersac <bersace@gmail.com>");
+MODULE_DESCRIPTION("Thermal control logic for iMac G5 (iSight)");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c
index 58c2590..961fa0e 100644
--- a/drivers/macintosh/windfarm_smu_controls.c
+++ b/drivers/macintosh/windfarm_smu_controls.c
@@ -218,6 +218,10 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node,
fct->ctrl.name = "cpu-fan";
else if (!strcmp(l, "Hard Drive") || !strcmp(l, "Hard drive"))
fct->ctrl.name = "drive-bay-fan";
+ else if (!strcmp(l, "HDD Fan")) /* seen on iMac G5 iSight */
+ fct->ctrl.name = "hard-drive-fan";
+ else if (!strcmp(l, "ODD Fan")) /* same */
+ fct->ctrl.name = "optical-drive-fan";
/* Unrecognized fan, bail out */
if (fct->ctrl.name == NULL)
^ permalink raw reply related
* RE: Regarding MPC8641D
From: Siva Prasad @ 2007-12-06 1:14 UTC (permalink / raw)
To: rameshmrm; +Cc: linuxppc-dev
In-Reply-To: <mailman.9.1196902804.16874.linuxppc-dev@ozlabs.org>
BTW... it is not true that core1 is idle when low memory offset mode is
disabled. Taking core1 out of reset will enable core1 to start booting.
These two are two different things.
- Siva
-----Original Message-----
From: Siva Prasad=20
Sent: Wednesday, December 05, 2007 5:06 PM
To: 'linuxppc-dev@ozlabs.org'
Cc: 'rameshmrm@gmail.com'
Subject: Regarding MPC8641D
Hi,
If you want to use SMP, do not enable low memory offset mode. That is
only and only for AMP, not for SMP. All the exception vectors go into a
different address range for core1, once you enable that, resulting in a
need for entirely different copy of OS (be it Linux, or any other OS).
You are in the right path. Just don't enable low memory offset mode,
unless you are looking for Assymetric multi-processing.
- siva
Message: 6
Date: Wed, 5 Dec 2007 16:45:31 -0800 (PST)
From: sivaji <rameshmrm@gmail.com>
Subject: Re: Regarding MPC8641D
To: linuxppc-dev@ozlabs.org
Message-ID: <14184234.post@talk.nabble.com>
Content-Type: text/plain; charset=3Dus-ascii
Hai,
The kernel was compiled in SMP mode. The low memory offset
mode
is only for AMP mode means, then how we test both the core 0 and 1 in
the
linux kernel ?. Asper my understanding if we enable the Low Memory
Offset
mode, then only the core1 translation is enabled. If we disalbed the Low
Memory offset mode, Only Core 0 will work in SMP mode and Core 1 will
idle.
If we want to test the efficient of Dual core means we need to enable
both
the core and Low Memory Offset Mode. For this configuration linux kernel
was
not up.
( Please correct me if I am wrong )
Thanks and Regards
Sivaji
Chris Fester wrote:
>=20
> On Tue, 2007-12-04 at 23:51 -0800, sivaji wrote:
>> We have designed a MPC8641D based AMC card. We are using
the
>> kernel (2.6.23-rc4) and uboot (1.2.0). When we disable the core1 Low
>> Memory
>> offset mode the kernel was up and when we enable this core1 Low
Memory
>> offset mode kernel was not up, It was hang after MPIC initialization.
> [snip!]
>> After this the kernel was hang, i want to know
why
>> kernel was hang when we enalbe Low memory Offset mode. Please help me
to
>> fix
>> this issue.
>=20
> Have you compiled your kernel for SMP mode? I believe the Low memory
> offset mode is only for AMP mode (vxworks can use this, probably other
> OSes). I don't know if the kernel has support for any multiprocessing
> mode other than SMP.
>=20
> Hope that helps,
> Chris
>=20
^ permalink raw reply
* Regarding MPC8641D
From: Siva Prasad @ 2007-12-06 1:05 UTC (permalink / raw)
To: linuxppc-dev; +Cc: rameshmrm
In-Reply-To: <mailman.9.1196902804.16874.linuxppc-dev@ozlabs.org>
Hi,
If you want to use SMP, do not enable low memory offset mode. That is
only and only for AMP, not for SMP. All the exception vectors go into a
different address range for core1, once you enable that, resulting in a
need for entirely different copy of OS (be it Linux, or any other OS).
You are in the right path. Just don't enable low memory offset mode,
unless you are looking for Assymetric multi-processing.
- siva
Message: 6
Date: Wed, 5 Dec 2007 16:45:31 -0800 (PST)
From: sivaji <rameshmrm@gmail.com>
Subject: Re: Regarding MPC8641D
To: linuxppc-dev@ozlabs.org
Message-ID: <14184234.post@talk.nabble.com>
Content-Type: text/plain; charset=3Dus-ascii
Hai,
The kernel was compiled in SMP mode. The low memory offset
mode
is only for AMP mode means, then how we test both the core 0 and 1 in
the
linux kernel ?. Asper my understanding if we enable the Low Memory
Offset
mode, then only the core1 translation is enabled. If we disalbed the Low
Memory offset mode, Only Core 0 will work in SMP mode and Core 1 will
idle.
If we want to test the efficient of Dual core means we need to enable
both
the core and Low Memory Offset Mode. For this configuration linux kernel
was
not up.
( Please correct me if I am wrong )
Thanks and Regards
Sivaji
Chris Fester wrote:
>=20
> On Tue, 2007-12-04 at 23:51 -0800, sivaji wrote:
>> We have designed a MPC8641D based AMC card. We are using
the
>> kernel (2.6.23-rc4) and uboot (1.2.0). When we disable the core1 Low
>> Memory
>> offset mode the kernel was up and when we enable this core1 Low
Memory
>> offset mode kernel was not up, It was hang after MPIC initialization.
> [snip!]
>> After this the kernel was hang, i want to know
why
>> kernel was hang when we enalbe Low memory Offset mode. Please help me
to
>> fix
>> this issue.
>=20
> Have you compiled your kernel for SMP mode? I believe the Low memory
> offset mode is only for AMP mode (vxworks can use this, probably other
> OSes). I don't know if the kernel has support for any multiprocessing
> mode other than SMP.
>=20
> Hope that helps,
> Chris
>=20
^ permalink raw reply
* Re: Regarding MPC8641D
From: sivaji @ 2007-12-06 0:45 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1196874416.32356.3.camel@kaboom.lisle.iphase.com>
Hai,
The kernel was compiled in SMP mode. The low memory offset mode
is only for AMP mode means, then how we test both the core 0 and 1 in the
linux kernel ?. Asper my understanding if we enable the Low Memory Offset
mode, then only the core1 translation is enabled. If we disalbed the Low
Memory offset mode, Only Core 0 will work in SMP mode and Core 1 will idle.
If we want to test the efficient of Dual core means we need to enable both
the core and Low Memory Offset Mode. For this configuration linux kernel was
not up.
( Please correct me if I am wrong )
Thanks and Regards
Sivaji
Chris Fester wrote:
>
> On Tue, 2007-12-04 at 23:51 -0800, sivaji wrote:
>> We have designed a MPC8641D based AMC card. We are using the
>> kernel (2.6.23-rc4) and uboot (1.2.0). When we disable the core1 Low
>> Memory
>> offset mode the kernel was up and when we enable this core1 Low Memory
>> offset mode kernel was not up, It was hang after MPIC initialization.
> [snip!]
>> After this the kernel was hang, i want to know why
>> kernel was hang when we enalbe Low memory Offset mode. Please help me to
>> fix
>> this issue.
>
> Have you compiled your kernel for SMP mode? I believe the Low memory
> offset mode is only for AMP mode (vxworks can use this, probably other
> OSes). I don't know if the kernel has support for any multiprocessing
> mode other than SMP.
>
> Hope that helps,
> Chris
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
--
View this message in context: http://www.nabble.com/Regarding-MPC8641D-tf4948004.html#a14184234
Sent from the linuxppc-dev mailing list archive at Nabble.com.
^ permalink raw reply
* Re: [patch] Windfarm plateform module for PowerMac12,1
From: Étienne Bersac @ 2007-12-06 0:18 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1196897863.7132.5.camel@thilivren>
Sorry for my noobness, i though i wasn't allowed to sign my own
patches /o\
So …
Signed-off-by: Étienne Bersac <bersace@gmail.com>
If you want a re-submission, please tell me so.
Regards,
Étienne.
--
E Ultreïa !
^ permalink raw reply
* Re: [PATCH v2] qe: add ability to upload QE firmware
From: Arnd Bergmann @ 2007-12-06 0:17 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Timur Tabi
In-Reply-To: <47573CCE.4000606@freescale.com>
On Thursday 06 December 2007, Timur Tabi wrote:
> > In that case, I think it
> > would really be better to just put the blob into the tree and only
> > have the fw loading code in the kernel instead of duplicating it in the=
boot
> > loader.
>=20
> That would require the firmware to present in RAM for all time, since the=
device=20
> tree cannot be unloaded.
Yes, that's a backdraw of my approach, but in the case of spidernet, it was=
only
an insignificant amount of RAM. Don't know what sizes of RAM and QE firmware
to expect typically on the machines you care about.
> Besides, you might need to have the firmware loaded in =20
> U-Boot anyway. =A0If your console is connected to the QE, then you'll nee=
d the=20
> UART firmware loaded before you can see anything. =A0That's why U-Boot ne=
eds its=20
> own version.
Right, so you can't really get around having it in some boot loaders at lea=
st.
IIRC you said that the firmware is only needed for serial output on some ch=
ips
but not on others. What about the case where you don't need it for serial b=
ut
still want to provide it by the firmware, and perhaps use something other t=
han
U-boot? Is that relevant?
I'm not trying to convince you of this if it's completely pointless for
all your systems, just want to make sure you're aware of this option,
because spending a few extra code lines on it now may save you some trouble
if you need this later.
> > Regarding the question whether the firmware should be a device node or
> > a property of another node, I'd prefer a simple property, because the
> > firmware itself is not really a device you can access, but I don't care
> > much about that.
>=20
> Technically, the firmware could be considered a device on the QE, because=
it's=20
> loaded into I-RAM and it can significantly alter the behavior of the devi=
ce.=20
Well, it doesn't have any of the standard properties like registers or inte=
rrupts
though.
> Having it its own node also lets me compartmentalize it. =A0If I want to =
expand=20
> the node and add more properties, it's cleaner.
Yes, that makes a lot of sense.
Arnd <><
^ permalink raw reply
* Re: [PATCH v2] qe: add ability to upload QE firmware
From: Timur Tabi @ 2007-12-06 0:05 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: linuxppc-dev
In-Reply-To: <200712060056.39368.arnd@arndb.de>
Arnd Bergmann wrote:
> What does the firmware node contain then? The way I read it, you only put
> metadata about the uploaded firmware in there, but not the blob itself, right?
That's correct. The meta-data is only the information that a device driver
would need to identify and interact with the microcode.
> Is there a case where you don't need the firmware in order to start the
> kernel, but still want to provide it in flash?
I don't think you'll ever need the firmware to *start* the kernel.
> In that case, I think it
> would really be better to just put the blob into the tree and only
> have the fw loading code in the kernel instead of duplicating it in the boot
> loader.
That would require the firmware to present in RAM for all time, since the device
tree cannot be unloaded. Besides, you might need to have the firmware loaded in
U-Boot anyway. If your console is connected to the QE, then you'll need the
UART firmware loaded before you can see anything. That's why U-Boot needs its
own version.
> Regarding the question whether the firmware should be a device node or
> a property of another node, I'd prefer a simple property, because the
> firmware itself is not really a device you can access, but I don't care
> much about that.
Technically, the firmware could be considered a device on the QE, because it's
loaded into I-RAM and it can significantly alter the behavior of the device.
Having it its own node also lets me compartmentalize it. If I want to expand
the node and add more properties, it's cleaner.
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox