~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to arch/powerpc/platforms/pseries/hotplug-memory.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#include <linux/of.h>
13
13
#include <linux/memblock.h>
14
14
#include <linux/vmalloc.h>
 
15
#include <linux/memory.h>
 
16
 
15
17
#include <asm/firmware.h>
16
18
#include <asm/machdep.h>
17
19
#include <asm/pSeries_reconfig.h>
18
20
#include <asm/sparsemem.h>
19
21
 
 
22
static unsigned long get_memblock_size(void)
 
23
{
 
24
        struct device_node *np;
 
25
        unsigned int memblock_size = MIN_MEMORY_BLOCK_SIZE;
 
26
        struct resource r;
 
27
 
 
28
        np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
 
29
        if (np) {
 
30
                const __be64 *size;
 
31
 
 
32
                size = of_get_property(np, "ibm,lmb-size", NULL);
 
33
                if (size)
 
34
                        memblock_size = be64_to_cpup(size);
 
35
                of_node_put(np);
 
36
        } else  if (machine_is(pseries)) {
 
37
                /* This fallback really only applies to pseries */
 
38
                unsigned int memzero_size = 0;
 
39
 
 
40
                np = of_find_node_by_path("/memory@0");
 
41
                if (np) {
 
42
                        if (!of_address_to_resource(np, 0, &r))
 
43
                                memzero_size = resource_size(&r);
 
44
                        of_node_put(np);
 
45
                }
 
46
 
 
47
                if (memzero_size) {
 
48
                        /* We now know the size of memory@0, use this to find
 
49
                         * the first memoryblock and get its size.
 
50
                         */
 
51
                        char buf[64];
 
52
 
 
53
                        sprintf(buf, "/memory@%x", memzero_size);
 
54
                        np = of_find_node_by_path(buf);
 
55
                        if (np) {
 
56
                                if (!of_address_to_resource(np, 0, &r))
 
57
                                        memblock_size = resource_size(&r);
 
58
                                of_node_put(np);
 
59
                        }
 
60
                }
 
61
        }
 
62
        return memblock_size;
 
63
}
 
64
 
 
65
/* WARNING: This is going to override the generic definition whenever
 
66
 * pseries is built-in regardless of what platform is active at boot
 
67
 * time. This is fine for now as this is the only "option" and it
 
68
 * should work everywhere. If not, we'll have to turn this into a
 
69
 * ppc_md. callback
 
70
 */
 
71
unsigned long memory_block_size_bytes(void)
 
72
{
 
73
        return get_memblock_size();
 
74
}
 
75
 
20
76
static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
21
77
{
22
78
        unsigned long start, start_pfn;
127
183
 
128
184
static int pseries_drconf_memory(unsigned long *base, unsigned int action)
129
185
{
130
 
        struct device_node *np;
131
 
        const unsigned long *lmb_size;
 
186
        unsigned long memblock_size;
132
187
        int rc;
133
188
 
134
 
        np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
135
 
        if (!np)
136
 
                return -EINVAL;
137
 
 
138
 
        lmb_size = of_get_property(np, "ibm,lmb-size", NULL);
139
 
        if (!lmb_size) {
140
 
                of_node_put(np);
141
 
                return -EINVAL;
142
 
        }
 
189
        memblock_size = get_memblock_size();
 
190
        if (!memblock_size)
 
191
                return -EINVAL;
143
192
 
144
193
        if (action == PSERIES_DRCONF_MEM_ADD) {
145
 
                rc = memblock_add(*base, *lmb_size);
 
194
                rc = memblock_add(*base, memblock_size);
146
195
                rc = (rc < 0) ? -EINVAL : 0;
147
196
        } else if (action == PSERIES_DRCONF_MEM_REMOVE) {
148
 
                rc = pseries_remove_memblock(*base, *lmb_size);
 
197
                rc = pseries_remove_memblock(*base, memblock_size);
149
198
        } else {
150
199
                rc = -EINVAL;
151
200
        }
152
201
 
153
 
        of_node_put(np);
154
202
        return rc;
155
203
}
156
204