Merge branch 'x86-uv-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
* 'x86-uv-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86: uv2: Workaround for UV2 Hub bug (system global address format)
This commit is contained in:
commit
d630ba565f
|
@ -55,6 +55,7 @@
|
||||||
#define UV_BAU_TUNABLES_DIR "sgi_uv"
|
#define UV_BAU_TUNABLES_DIR "sgi_uv"
|
||||||
#define UV_BAU_TUNABLES_FILE "bau_tunables"
|
#define UV_BAU_TUNABLES_FILE "bau_tunables"
|
||||||
#define WHITESPACE " \t\n"
|
#define WHITESPACE " \t\n"
|
||||||
|
#define uv_mmask ((1UL << uv_hub_info->m_val) - 1)
|
||||||
#define uv_physnodeaddr(x) ((__pa((unsigned long)(x)) & uv_mmask))
|
#define uv_physnodeaddr(x) ((__pa((unsigned long)(x)) & uv_mmask))
|
||||||
#define cpubit_isset(cpu, bau_local_cpumask) \
|
#define cpubit_isset(cpu, bau_local_cpumask) \
|
||||||
test_bit((cpu), (bau_local_cpumask).bits)
|
test_bit((cpu), (bau_local_cpumask).bits)
|
||||||
|
|
|
@ -46,6 +46,13 @@
|
||||||
* PNODE - the low N bits of the GNODE. The PNODE is the most useful variant
|
* PNODE - the low N bits of the GNODE. The PNODE is the most useful variant
|
||||||
* of the nasid for socket usage.
|
* of the nasid for socket usage.
|
||||||
*
|
*
|
||||||
|
* GPA - (global physical address) a socket physical address converted
|
||||||
|
* so that it can be used by the GRU as a global address. Socket
|
||||||
|
* physical addresses 1) need additional NASID (node) bits added
|
||||||
|
* to the high end of the address, and 2) unaliased if the
|
||||||
|
* partition does not have a physical address 0. In addition, on
|
||||||
|
* UV2 rev 1, GPAs need the gnode left shifted to bits 39 or 40.
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* NumaLink Global Physical Address Format:
|
* NumaLink Global Physical Address Format:
|
||||||
* +--------------------------------+---------------------+
|
* +--------------------------------+---------------------+
|
||||||
|
@ -141,6 +148,8 @@ struct uv_hub_info_s {
|
||||||
unsigned int gnode_extra;
|
unsigned int gnode_extra;
|
||||||
unsigned char hub_revision;
|
unsigned char hub_revision;
|
||||||
unsigned char apic_pnode_shift;
|
unsigned char apic_pnode_shift;
|
||||||
|
unsigned char m_shift;
|
||||||
|
unsigned char n_lshift;
|
||||||
unsigned long gnode_upper;
|
unsigned long gnode_upper;
|
||||||
unsigned long lowmem_remap_top;
|
unsigned long lowmem_remap_top;
|
||||||
unsigned long lowmem_remap_base;
|
unsigned long lowmem_remap_base;
|
||||||
|
@ -177,6 +186,16 @@ static inline int is_uv2_hub(void)
|
||||||
return uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE;
|
return uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int is_uv2_1_hub(void)
|
||||||
|
{
|
||||||
|
return uv_hub_info->hub_revision == UV2_HUB_REVISION_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int is_uv2_2_hub(void)
|
||||||
|
{
|
||||||
|
return uv_hub_info->hub_revision == UV2_HUB_REVISION_BASE + 1;
|
||||||
|
}
|
||||||
|
|
||||||
union uvh_apicid {
|
union uvh_apicid {
|
||||||
unsigned long v;
|
unsigned long v;
|
||||||
struct uvh_apicid_s {
|
struct uvh_apicid_s {
|
||||||
|
@ -276,7 +295,10 @@ static inline unsigned long uv_soc_phys_ram_to_gpa(unsigned long paddr)
|
||||||
{
|
{
|
||||||
if (paddr < uv_hub_info->lowmem_remap_top)
|
if (paddr < uv_hub_info->lowmem_remap_top)
|
||||||
paddr |= uv_hub_info->lowmem_remap_base;
|
paddr |= uv_hub_info->lowmem_remap_base;
|
||||||
return paddr | uv_hub_info->gnode_upper;
|
paddr |= uv_hub_info->gnode_upper;
|
||||||
|
paddr = ((paddr << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
|
||||||
|
((paddr >> uv_hub_info->m_val) << uv_hub_info->n_lshift);
|
||||||
|
return paddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -300,16 +322,19 @@ static inline unsigned long uv_gpa_to_soc_phys_ram(unsigned long gpa)
|
||||||
unsigned long remap_base = uv_hub_info->lowmem_remap_base;
|
unsigned long remap_base = uv_hub_info->lowmem_remap_base;
|
||||||
unsigned long remap_top = uv_hub_info->lowmem_remap_top;
|
unsigned long remap_top = uv_hub_info->lowmem_remap_top;
|
||||||
|
|
||||||
|
gpa = ((gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
|
||||||
|
((gpa >> uv_hub_info->n_lshift) << uv_hub_info->m_val);
|
||||||
|
gpa = gpa & uv_hub_info->gpa_mask;
|
||||||
if (paddr >= remap_base && paddr < remap_base + remap_top)
|
if (paddr >= remap_base && paddr < remap_base + remap_top)
|
||||||
paddr -= remap_base;
|
paddr -= remap_base;
|
||||||
return paddr;
|
return paddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* gnode -> pnode */
|
/* gpa -> pnode */
|
||||||
static inline unsigned long uv_gpa_to_gnode(unsigned long gpa)
|
static inline unsigned long uv_gpa_to_gnode(unsigned long gpa)
|
||||||
{
|
{
|
||||||
return gpa >> uv_hub_info->m_val;
|
return gpa >> uv_hub_info->n_lshift;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gpa -> pnode */
|
/* gpa -> pnode */
|
||||||
|
@ -320,6 +345,12 @@ static inline int uv_gpa_to_pnode(unsigned long gpa)
|
||||||
return uv_gpa_to_gnode(gpa) & n_mask;
|
return uv_gpa_to_gnode(gpa) & n_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* gpa -> node offset*/
|
||||||
|
static inline unsigned long uv_gpa_to_offset(unsigned long gpa)
|
||||||
|
{
|
||||||
|
return (gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift;
|
||||||
|
}
|
||||||
|
|
||||||
/* pnode, offset --> socket virtual */
|
/* pnode, offset --> socket virtual */
|
||||||
static inline void *uv_pnode_offset_to_vaddr(int pnode, unsigned long offset)
|
static inline void *uv_pnode_offset_to_vaddr(int pnode, unsigned long offset)
|
||||||
{
|
{
|
||||||
|
|
|
@ -820,6 +820,10 @@ void __init uv_system_init(void)
|
||||||
uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift;
|
uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift;
|
||||||
uv_cpu_hub_info(cpu)->hub_revision = uv_hub_info->hub_revision;
|
uv_cpu_hub_info(cpu)->hub_revision = uv_hub_info->hub_revision;
|
||||||
|
|
||||||
|
uv_cpu_hub_info(cpu)->m_shift = 64 - m_val;
|
||||||
|
uv_cpu_hub_info(cpu)->n_lshift = is_uv2_1_hub() ?
|
||||||
|
(m_val == 40 ? 40 : 39) : m_val;
|
||||||
|
|
||||||
pnode = uv_apicid_to_pnode(apicid);
|
pnode = uv_apicid_to_pnode(apicid);
|
||||||
blade = boot_pnode_to_blade(pnode);
|
blade = boot_pnode_to_blade(pnode);
|
||||||
lcpu = uv_blade_info[blade].nr_possible_cpus;
|
lcpu = uv_blade_info[blade].nr_possible_cpus;
|
||||||
|
@ -850,8 +854,7 @@ void __init uv_system_init(void)
|
||||||
if (uv_node_to_blade[nid] >= 0)
|
if (uv_node_to_blade[nid] >= 0)
|
||||||
continue;
|
continue;
|
||||||
paddr = node_start_pfn(nid) << PAGE_SHIFT;
|
paddr = node_start_pfn(nid) << PAGE_SHIFT;
|
||||||
paddr = uv_soc_phys_ram_to_gpa(paddr);
|
pnode = uv_gpa_to_pnode(uv_soc_phys_ram_to_gpa(paddr));
|
||||||
pnode = (paddr >> m_val) & pnode_mask;
|
|
||||||
blade = boot_pnode_to_blade(pnode);
|
blade = boot_pnode_to_blade(pnode);
|
||||||
uv_node_to_blade[nid] = blade;
|
uv_node_to_blade[nid] = blade;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,9 +115,6 @@ early_param("nobau", setup_nobau);
|
||||||
|
|
||||||
/* base pnode in this partition */
|
/* base pnode in this partition */
|
||||||
static int uv_base_pnode __read_mostly;
|
static int uv_base_pnode __read_mostly;
|
||||||
/* position of pnode (which is nasid>>1): */
|
|
||||||
static int uv_nshift __read_mostly;
|
|
||||||
static unsigned long uv_mmask __read_mostly;
|
|
||||||
|
|
||||||
static DEFINE_PER_CPU(struct ptc_stats, ptcstats);
|
static DEFINE_PER_CPU(struct ptc_stats, ptcstats);
|
||||||
static DEFINE_PER_CPU(struct bau_control, bau_control);
|
static DEFINE_PER_CPU(struct bau_control, bau_control);
|
||||||
|
@ -1435,7 +1432,7 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int cpu;
|
int cpu;
|
||||||
unsigned long pa;
|
unsigned long gpa;
|
||||||
unsigned long m;
|
unsigned long m;
|
||||||
unsigned long n;
|
unsigned long n;
|
||||||
size_t dsize;
|
size_t dsize;
|
||||||
|
@ -1451,9 +1448,9 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
|
||||||
bau_desc = kmalloc_node(dsize, GFP_KERNEL, node);
|
bau_desc = kmalloc_node(dsize, GFP_KERNEL, node);
|
||||||
BUG_ON(!bau_desc);
|
BUG_ON(!bau_desc);
|
||||||
|
|
||||||
pa = uv_gpa(bau_desc); /* need the real nasid*/
|
gpa = uv_gpa(bau_desc);
|
||||||
n = pa >> uv_nshift;
|
n = uv_gpa_to_gnode(gpa);
|
||||||
m = pa & uv_mmask;
|
m = uv_gpa_to_offset(gpa);
|
||||||
|
|
||||||
/* the 14-bit pnode */
|
/* the 14-bit pnode */
|
||||||
write_mmr_descriptor_base(pnode, (n << UV_DESC_PSHIFT | m));
|
write_mmr_descriptor_base(pnode, (n << UV_DESC_PSHIFT | m));
|
||||||
|
@ -1525,9 +1522,9 @@ static void pq_init(int node, int pnode)
|
||||||
bcp->queue_last = pqp + (DEST_Q_SIZE - 1);
|
bcp->queue_last = pqp + (DEST_Q_SIZE - 1);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* need the pnode of where the memory was really allocated
|
* need the gnode of where the memory was really allocated
|
||||||
*/
|
*/
|
||||||
pn = uv_gpa(pqp) >> uv_nshift;
|
pn = uv_gpa_to_gnode(uv_gpa(pqp));
|
||||||
first = uv_physnodeaddr(pqp);
|
first = uv_physnodeaddr(pqp);
|
||||||
pn_first = ((unsigned long)pn << UV_PAYLOADQ_PNODE_SHIFT) | first;
|
pn_first = ((unsigned long)pn << UV_PAYLOADQ_PNODE_SHIFT) | first;
|
||||||
last = uv_physnodeaddr(pqp + (DEST_Q_SIZE - 1));
|
last = uv_physnodeaddr(pqp + (DEST_Q_SIZE - 1));
|
||||||
|
@ -1837,8 +1834,6 @@ static int __init uv_bau_init(void)
|
||||||
zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu));
|
zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu));
|
||||||
}
|
}
|
||||||
|
|
||||||
uv_nshift = uv_hub_info->m_val;
|
|
||||||
uv_mmask = (1UL << uv_hub_info->m_val) - 1;
|
|
||||||
nuvhubs = uv_num_possible_blades();
|
nuvhubs = uv_num_possible_blades();
|
||||||
spin_lock_init(&disable_lock);
|
spin_lock_init(&disable_lock);
|
||||||
congested_cycles = usec_2_cycles(congested_respns_us);
|
congested_cycles = usec_2_cycles(congested_respns_us);
|
||||||
|
|
Loading…
Reference in New Issue