|
@@ -26,6 +26,7 @@
|
|
|
#include <linux/delay.h>
|
|
|
#include <linux/crash_dump.h>
|
|
|
#include <linux/reboot.h>
|
|
|
+#include <linux/memory.h>
|
|
|
|
|
|
#include <asm/uv/uv_mmrs.h>
|
|
|
#include <asm/uv/uv_hub.h>
|
|
@@ -392,6 +393,51 @@ extern int uv_hub_info_version(void)
|
|
|
}
|
|
|
EXPORT_SYMBOL(uv_hub_info_version);
|
|
|
|
|
|
+/* Default UV memory block size is 2GB */
|
|
|
+static unsigned long mem_block_size = (2UL << 30);
|
|
|
+
|
|
|
+/* Kernel parameter to specify UV mem block size */
|
|
|
+static int parse_mem_block_size(char *ptr)
|
|
|
+{
|
|
|
+ unsigned long size = memparse(ptr, NULL);
|
|
|
+
|
|
|
+ /* Size will be rounded down by set_block_size() below */
|
|
|
+ mem_block_size = size;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+early_param("uv_memblksize", parse_mem_block_size);
|
|
|
+
|
|
|
+static __init int adj_blksize(u32 lgre)
|
|
|
+{
|
|
|
+ unsigned long base = (unsigned long)lgre << UV_GAM_RANGE_SHFT;
|
|
|
+ unsigned long size;
|
|
|
+
|
|
|
+ for (size = mem_block_size; size > MIN_MEMORY_BLOCK_SIZE; size >>= 1)
|
|
|
+ if (IS_ALIGNED(base, size))
|
|
|
+ break;
|
|
|
+
|
|
|
+ if (size >= mem_block_size)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ mem_block_size = size;
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+static __init void set_block_size(void)
|
|
|
+{
|
|
|
+ unsigned int order = ffs(mem_block_size);
|
|
|
+
|
|
|
+ if (order) {
|
|
|
+ /* adjust for ffs return of 1..64 */
|
|
|
+ set_memory_block_size_order(order - 1);
|
|
|
+ pr_info("UV: mem_block_size set to 0x%lx\n", mem_block_size);
|
|
|
+ } else {
|
|
|
+ /* bad or zero value, default to 1UL << 31 (2GB) */
|
|
|
+ pr_err("UV: mem_block_size error with 0x%lx\n", mem_block_size);
|
|
|
+ set_memory_block_size_order(31);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/* Build GAM range lookup table: */
|
|
|
static __init void build_uv_gr_table(void)
|
|
|
{
|
|
@@ -1180,23 +1226,30 @@ static void __init decode_gam_rng_tbl(unsigned long ptr)
|
|
|
<< UV_GAM_RANGE_SHFT);
|
|
|
int order = 0;
|
|
|
char suffix[] = " KMGTPE";
|
|
|
+ int flag = ' ';
|
|
|
|
|
|
while (size > 9999 && order < sizeof(suffix)) {
|
|
|
size /= 1024;
|
|
|
order++;
|
|
|
}
|
|
|
|
|
|
+ /* adjust max block size to current range start */
|
|
|
+ if (gre->type == 1 || gre->type == 2)
|
|
|
+ if (adj_blksize(lgre))
|
|
|
+ flag = '*';
|
|
|
+
|
|
|
if (!index) {
|
|
|
pr_info("UV: GAM Range Table...\n");
|
|
|
- pr_info("UV: # %20s %14s %5s %4s %5s %3s %2s\n", "Range", "", "Size", "Type", "NASID", "SID", "PN");
|
|
|
+ pr_info("UV: # %20s %14s %6s %4s %5s %3s %2s\n", "Range", "", "Size", "Type", "NASID", "SID", "PN");
|
|
|
}
|
|
|
- pr_info("UV: %2d: 0x%014lx-0x%014lx %5lu%c %3d %04x %02x %02x\n",
|
|
|
+ pr_info("UV: %2d: 0x%014lx-0x%014lx%c %5lu%c %3d %04x %02x %02x\n",
|
|
|
index++,
|
|
|
(unsigned long)lgre << UV_GAM_RANGE_SHFT,
|
|
|
(unsigned long)gre->limit << UV_GAM_RANGE_SHFT,
|
|
|
- size, suffix[order],
|
|
|
+ flag, size, suffix[order],
|
|
|
gre->type, gre->nasid, gre->sockid, gre->pnode);
|
|
|
|
|
|
+ /* update to next range start */
|
|
|
lgre = gre->limit;
|
|
|
if (sock_min > gre->sockid)
|
|
|
sock_min = gre->sockid;
|
|
@@ -1427,6 +1480,7 @@ static void __init uv_system_init_hub(void)
|
|
|
|
|
|
build_socket_tables();
|
|
|
build_uv_gr_table();
|
|
|
+ set_block_size();
|
|
|
uv_init_hub_info(&hub_info);
|
|
|
uv_possible_blades = num_possible_nodes();
|
|
|
if (!_node_to_pnode)
|