mirror of https://gitee.com/openkylin/linux.git
x86, UV: Add support for SGI UV2 hub chip
This patch adds support for a new version of the SGI UV hub chip. The hub chip is the node controller that connects multiple blades into a larger coherent SSI. For the most part, UV2 is compatible with UV1. The majority of the changes are in the addresses of MMRs and in a few cases, the contents of MMRs. These changes are the result in changes in the system topology such as node configuration, processor types, maximum nodes, physical address sizes, etc. Signed-off-by: Jack Steiner <steiner@sgi.com> Link: http://lkml.kernel.org/r/20110511175028.GA18006@sgi.com Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
7ccafc5f75
commit
2a919596c1
|
@ -44,7 +44,10 @@
|
|||
#define UV_ACT_STATUS_SIZE 2
|
||||
#define UV_DISTRIBUTION_SIZE 256
|
||||
#define UV_SW_ACK_NPENDING 8
|
||||
#define UV_NET_ENDPOINT_INTD 0x38
|
||||
#define UV1_NET_ENDPOINT_INTD 0x38
|
||||
#define UV2_NET_ENDPOINT_INTD 0x28
|
||||
#define UV_NET_ENDPOINT_INTD (is_uv1_hub() ? \
|
||||
UV1_NET_ENDPOINT_INTD : UV2_NET_ENDPOINT_INTD)
|
||||
#define UV_DESC_BASE_PNODE_SHIFT 49
|
||||
#define UV_PAYLOADQ_PNODE_SHIFT 49
|
||||
#define UV_PTC_BASENAME "sgi_uv/ptc_statistics"
|
||||
|
@ -53,10 +56,22 @@
|
|||
#define UV_BAU_TUNABLES_FILE "bau_tunables"
|
||||
#define WHITESPACE " \t\n"
|
||||
#define uv_physnodeaddr(x) ((__pa((unsigned long)(x)) & uv_mmask))
|
||||
#define UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT 15
|
||||
#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT 16
|
||||
#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 0x0000000009UL
|
||||
|
||||
|
||||
/* [19:16] SOFT_ACK timeout period 19: 1 is urgency 7 17:16 1 is multiplier */
|
||||
/*
|
||||
* UV2: Bit 19 selects between
|
||||
* (0): 10 microsecond timebase and
|
||||
* (1): 80 microseconds
|
||||
* we're using 655us, similar to UV1: 65 units of 10us
|
||||
*/
|
||||
#define UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD (9UL)
|
||||
#define UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD (65*10UL)
|
||||
|
||||
#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD (is_uv1_hub() ? \
|
||||
UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD : \
|
||||
UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD)
|
||||
|
||||
#define BAU_MISC_CONTROL_MULT_MASK 3
|
||||
|
||||
#define UVH_AGING_PRESCALE_SEL 0x000000b000UL
|
||||
|
@ -76,6 +91,16 @@
|
|||
#define DESC_STATUS_ACTIVE 1
|
||||
#define DESC_STATUS_DESTINATION_TIMEOUT 2
|
||||
#define DESC_STATUS_SOURCE_TIMEOUT 3
|
||||
/*
|
||||
* bits put together from HRP_LB_BAU_SB_ACTIVATION_STATUS_0/1/2
|
||||
* values 1 and 5 will not occur
|
||||
*/
|
||||
#define UV2H_DESC_IDLE 0
|
||||
#define UV2H_DESC_DEST_TIMEOUT 2
|
||||
#define UV2H_DESC_DEST_STRONG_NACK 3
|
||||
#define UV2H_DESC_BUSY 4
|
||||
#define UV2H_DESC_SOURCE_TIMEOUT 6
|
||||
#define UV2H_DESC_DEST_PUT_ERR 7
|
||||
|
||||
/*
|
||||
* delay for 'plugged' timeout retries, in microseconds
|
||||
|
@ -96,6 +121,15 @@
|
|||
|
||||
#define UV_LB_SUBNODEID 0x10
|
||||
|
||||
/* these two are the same for UV1 and UV2: */
|
||||
#define UV_SA_SHFT UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT
|
||||
#define UV_SA_MASK UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK
|
||||
/* 4 bits of software ack period */
|
||||
#define UV2_ACK_MASK 0x7UL
|
||||
#define UV2_ACK_UNITS_SHFT 3
|
||||
#define UV2_LEG_SHFT UV2H_LB_BAU_MISC_CONTROL_USE_LEGACY_DESCRIPTOR_FORMATS_SHFT
|
||||
#define UV2_EXT_SHFT UV2H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_SHFT
|
||||
|
||||
/*
|
||||
* number of entries in the destination side payload queue
|
||||
*/
|
||||
|
|
|
@ -77,8 +77,9 @@
|
|||
*
|
||||
* 1111110000000000
|
||||
* 5432109876543210
|
||||
* pppppppppplc0cch Nehalem-EX
|
||||
* ppppppppplcc0cch Westmere-EX
|
||||
* pppppppppplc0cch Nehalem-EX (12 bits in hdw reg)
|
||||
* ppppppppplcc0cch Westmere-EX (12 bits in hdw reg)
|
||||
* pppppppppppcccch SandyBridge (15 bits in hdw reg)
|
||||
* sssssssssss
|
||||
*
|
||||
* p = pnode bits
|
||||
|
@ -87,7 +88,7 @@
|
|||
* h = hyperthread
|
||||
* s = bits that are in the SOCKET_ID CSR
|
||||
*
|
||||
* Note: Processor only supports 12 bits in the APICID register. The ACPI
|
||||
* Note: Processor may support fewer bits in the APICID register. The ACPI
|
||||
* tables hold all 16 bits. Software needs to be aware of this.
|
||||
*
|
||||
* Unless otherwise specified, all references to APICID refer to
|
||||
|
@ -138,6 +139,8 @@ struct uv_hub_info_s {
|
|||
unsigned long global_mmr_base;
|
||||
unsigned long gpa_mask;
|
||||
unsigned int gnode_extra;
|
||||
unsigned char hub_revision;
|
||||
unsigned char apic_pnode_shift;
|
||||
unsigned long gnode_upper;
|
||||
unsigned long lowmem_remap_top;
|
||||
unsigned long lowmem_remap_base;
|
||||
|
@ -149,13 +152,31 @@ struct uv_hub_info_s {
|
|||
unsigned char m_val;
|
||||
unsigned char n_val;
|
||||
struct uv_scir_s scir;
|
||||
unsigned char apic_pnode_shift;
|
||||
};
|
||||
|
||||
DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
|
||||
#define uv_hub_info (&__get_cpu_var(__uv_hub_info))
|
||||
#define uv_cpu_hub_info(cpu) (&per_cpu(__uv_hub_info, cpu))
|
||||
|
||||
/*
|
||||
* Hub revisions less than UV2_HUB_REVISION_BASE are UV1 hubs. All UV2
|
||||
* hubs have revision numbers greater than or equal to UV2_HUB_REVISION_BASE.
|
||||
* This is a software convention - NOT the hardware revision numbers in
|
||||
* the hub chip.
|
||||
*/
|
||||
#define UV1_HUB_REVISION_BASE 1
|
||||
#define UV2_HUB_REVISION_BASE 3
|
||||
|
||||
static inline int is_uv1_hub(void)
|
||||
{
|
||||
return uv_hub_info->hub_revision < UV2_HUB_REVISION_BASE;
|
||||
}
|
||||
|
||||
static inline int is_uv2_hub(void)
|
||||
{
|
||||
return uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE;
|
||||
}
|
||||
|
||||
union uvh_apicid {
|
||||
unsigned long v;
|
||||
struct uvh_apicid_s {
|
||||
|
@ -180,11 +201,25 @@ union uvh_apicid {
|
|||
#define UV_PNODE_TO_GNODE(p) ((p) |uv_hub_info->gnode_extra)
|
||||
#define UV_PNODE_TO_NASID(p) (UV_PNODE_TO_GNODE(p) << 1)
|
||||
|
||||
#define UV_LOCAL_MMR_BASE 0xf4000000UL
|
||||
#define UV_GLOBAL_MMR32_BASE 0xf8000000UL
|
||||
#define UV1_LOCAL_MMR_BASE 0xf4000000UL
|
||||
#define UV1_GLOBAL_MMR32_BASE 0xf8000000UL
|
||||
#define UV1_LOCAL_MMR_SIZE (64UL * 1024 * 1024)
|
||||
#define UV1_GLOBAL_MMR32_SIZE (64UL * 1024 * 1024)
|
||||
|
||||
#define UV2_LOCAL_MMR_BASE 0xfa000000UL
|
||||
#define UV2_GLOBAL_MMR32_BASE 0xfc000000UL
|
||||
#define UV2_LOCAL_MMR_SIZE (32UL * 1024 * 1024)
|
||||
#define UV2_GLOBAL_MMR32_SIZE (32UL * 1024 * 1024)
|
||||
|
||||
#define UV_LOCAL_MMR_BASE (is_uv1_hub() ? UV1_LOCAL_MMR_BASE \
|
||||
: UV2_LOCAL_MMR_BASE)
|
||||
#define UV_GLOBAL_MMR32_BASE (is_uv1_hub() ? UV1_GLOBAL_MMR32_BASE \
|
||||
: UV2_GLOBAL_MMR32_BASE)
|
||||
#define UV_LOCAL_MMR_SIZE (is_uv1_hub() ? UV1_LOCAL_MMR_SIZE : \
|
||||
UV2_LOCAL_MMR_SIZE)
|
||||
#define UV_GLOBAL_MMR32_SIZE (is_uv1_hub() ? UV1_GLOBAL_MMR32_SIZE :\
|
||||
UV2_GLOBAL_MMR32_SIZE)
|
||||
#define UV_GLOBAL_MMR64_BASE (uv_hub_info->global_mmr_base)
|
||||
#define UV_LOCAL_MMR_SIZE (64UL * 1024 * 1024)
|
||||
#define UV_GLOBAL_MMR32_SIZE (64UL * 1024 * 1024)
|
||||
|
||||
#define UV_GLOBAL_GRU_MMR_BASE 0x4000000
|
||||
|
||||
|
@ -300,6 +335,17 @@ static inline int uv_apicid_to_pnode(int apicid)
|
|||
return (apicid >> uv_hub_info->apic_pnode_shift);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an apicid to the socket number on the blade
|
||||
*/
|
||||
static inline int uv_apicid_to_socket(int apicid)
|
||||
{
|
||||
if (is_uv1_hub())
|
||||
return (apicid >> (uv_hub_info->apic_pnode_shift - 1)) & 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Access global MMRs using the low memory MMR32 space. This region supports
|
||||
* faster MMR access but not all MMRs are accessible in this space.
|
||||
|
@ -519,14 +565,13 @@ static inline void uv_hub_send_ipi(int pnode, int apicid, int vector)
|
|||
|
||||
/*
|
||||
* Get the minimum revision number of the hub chips within the partition.
|
||||
* 1 - initial rev 1.0 silicon
|
||||
* 2 - rev 2.0 production silicon
|
||||
* 1 - UV1 rev 1.0 initial silicon
|
||||
* 2 - UV1 rev 2.0 production silicon
|
||||
* 3 - UV2 rev 1.0 initial silicon
|
||||
*/
|
||||
static inline int uv_get_min_hub_revision_id(void)
|
||||
{
|
||||
extern int uv_min_hub_revision_id;
|
||||
|
||||
return uv_min_hub_revision_id;
|
||||
return uv_hub_info->hub_revision;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_X86_64 */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -91,6 +91,10 @@ static int __init early_get_pnodeid(void)
|
|||
m_n_config.v = uv_early_read_mmr(UVH_RH_GAM_CONFIG_MMR);
|
||||
uv_min_hub_revision_id = node_id.s.revision;
|
||||
|
||||
if (node_id.s.part_number == UV2_HUB_PART_NUMBER)
|
||||
uv_min_hub_revision_id += UV2_HUB_REVISION_BASE - 1;
|
||||
|
||||
uv_hub_info->hub_revision = uv_min_hub_revision_id;
|
||||
pnode = (node_id.s.node_id >> 1) & ((1 << m_n_config.s.n_skt) - 1);
|
||||
return pnode;
|
||||
}
|
||||
|
@ -112,17 +116,25 @@ static void __init early_get_apic_pnode_shift(void)
|
|||
*/
|
||||
static void __init uv_set_apicid_hibit(void)
|
||||
{
|
||||
union uvh_lb_target_physical_apic_id_mask_u apicid_mask;
|
||||
union uv1h_lb_target_physical_apic_id_mask_u apicid_mask;
|
||||
|
||||
apicid_mask.v = uv_early_read_mmr(UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK);
|
||||
uv_apicid_hibits = apicid_mask.s.bit_enables & UV_APICID_HIBIT_MASK;
|
||||
if (is_uv1_hub()) {
|
||||
apicid_mask.v =
|
||||
uv_early_read_mmr(UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK);
|
||||
uv_apicid_hibits =
|
||||
apicid_mask.s1.bit_enables & UV_APICID_HIBIT_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
{
|
||||
int pnodeid;
|
||||
int pnodeid, is_uv1, is_uv2;
|
||||
|
||||
if (!strcmp(oem_id, "SGI")) {
|
||||
is_uv1 = !strcmp(oem_id, "SGI");
|
||||
is_uv2 = !strcmp(oem_id, "SGI2");
|
||||
if (is_uv1 || is_uv2) {
|
||||
uv_hub_info->hub_revision =
|
||||
is_uv1 ? UV1_HUB_REVISION_BASE : UV2_HUB_REVISION_BASE;
|
||||
pnodeid = early_get_pnodeid();
|
||||
early_get_apic_pnode_shift();
|
||||
x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range;
|
||||
|
@ -484,13 +496,20 @@ static __init void map_mmr_high(int max_pnode)
|
|||
static __init void map_mmioh_high(int max_pnode)
|
||||
{
|
||||
union uvh_rh_gam_mmioh_overlay_config_mmr_u mmioh;
|
||||
int shift = UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT;
|
||||
int shift;
|
||||
|
||||
mmioh.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR);
|
||||
if (mmioh.s.enable)
|
||||
map_high("MMIOH", mmioh.s.base, shift, mmioh.s.m_io,
|
||||
if (is_uv1_hub() && mmioh.s1.enable) {
|
||||
shift = UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT;
|
||||
map_high("MMIOH", mmioh.s1.base, shift, mmioh.s1.m_io,
|
||||
max_pnode, map_uc);
|
||||
}
|
||||
if (is_uv2_hub() && mmioh.s2.enable) {
|
||||
shift = UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT;
|
||||
map_high("MMIOH", mmioh.s2.base, shift, mmioh.s2.m_io,
|
||||
max_pnode, map_uc);
|
||||
}
|
||||
}
|
||||
|
||||
static __init void map_low_mmrs(void)
|
||||
{
|
||||
|
@ -736,13 +755,14 @@ void __init uv_system_init(void)
|
|||
unsigned long mmr_base, present, paddr;
|
||||
unsigned short pnode_mask, pnode_io_mask;
|
||||
|
||||
printk(KERN_INFO "UV: Found %s hub\n", is_uv1_hub() ? "UV1" : "UV2");
|
||||
map_low_mmrs();
|
||||
|
||||
m_n_config.v = uv_read_local_mmr(UVH_RH_GAM_CONFIG_MMR );
|
||||
m_val = m_n_config.s.m_skt;
|
||||
n_val = m_n_config.s.n_skt;
|
||||
mmioh.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR);
|
||||
n_io = mmioh.s.n_io;
|
||||
n_io = is_uv1_hub() ? mmioh.s1.n_io : mmioh.s2.n_io;
|
||||
mmr_base =
|
||||
uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) &
|
||||
~UV_MMR_ENABLE;
|
||||
|
@ -811,6 +831,8 @@ void __init uv_system_init(void)
|
|||
*/
|
||||
uv_cpu_hub_info(cpu)->pnode_mask = pnode_mask;
|
||||
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;
|
||||
|
||||
pnode = uv_apicid_to_pnode(apicid);
|
||||
blade = boot_pnode_to_blade(pnode);
|
||||
lcpu = uv_blade_info[blade].nr_possible_cpus;
|
||||
|
|
|
@ -397,16 +397,13 @@ end_uvhub_quiesce(struct bau_control *hmaster)
|
|||
* Wait for completion of a broadcast software ack message
|
||||
* return COMPLETE, RETRY(PLUGGED or TIMEOUT) or GIVEUP
|
||||
*/
|
||||
static int uv_wait_completion(struct bau_desc *bau_desc,
|
||||
static int uv1_wait_completion(struct bau_desc *bau_desc,
|
||||
unsigned long mmr_offset, int right_shift, int this_cpu,
|
||||
struct bau_control *bcp, struct bau_control *smaster, long try)
|
||||
{
|
||||
unsigned long descriptor_status;
|
||||
cycles_t ttime;
|
||||
struct ptc_stats *stat = bcp->statp;
|
||||
struct bau_control *hmaster;
|
||||
|
||||
hmaster = bcp->uvhub_master;
|
||||
|
||||
/* spin on the status MMR, waiting for it to go idle */
|
||||
while ((descriptor_status = (((unsigned long)
|
||||
|
@ -414,10 +411,10 @@ static int uv_wait_completion(struct bau_desc *bau_desc,
|
|||
right_shift) & UV_ACT_STATUS_MASK)) !=
|
||||
DESC_STATUS_IDLE) {
|
||||
/*
|
||||
* Our software ack messages may be blocked because there are
|
||||
* no swack resources available. As long as none of them
|
||||
* has timed out hardware will NACK our message and its
|
||||
* state will stay IDLE.
|
||||
* Our software ack messages may be blocked because
|
||||
* there are no swack resources available. As long
|
||||
* as none of them has timed out hardware will NACK
|
||||
* our message and its state will stay IDLE.
|
||||
*/
|
||||
if (descriptor_status == DESC_STATUS_SOURCE_TIMEOUT) {
|
||||
stat->s_stimeout++;
|
||||
|
@ -452,6 +449,86 @@ static int uv_wait_completion(struct bau_desc *bau_desc,
|
|||
return FLUSH_COMPLETE;
|
||||
}
|
||||
|
||||
static int uv2_wait_completion(struct bau_desc *bau_desc,
|
||||
unsigned long mmr_offset, int right_shift, int this_cpu,
|
||||
struct bau_control *bcp, struct bau_control *smaster, long try)
|
||||
{
|
||||
unsigned long descriptor_status;
|
||||
unsigned long descriptor_status2;
|
||||
int cpu;
|
||||
cycles_t ttime;
|
||||
struct ptc_stats *stat = bcp->statp;
|
||||
|
||||
/* UV2 has an extra bit of status */
|
||||
cpu = bcp->uvhub_cpu;
|
||||
/* spin on the status MMR, waiting for it to go idle */
|
||||
descriptor_status = (((unsigned long)(uv_read_local_mmr
|
||||
(mmr_offset)) >> right_shift) & UV_ACT_STATUS_MASK);
|
||||
descriptor_status2 = (((unsigned long)uv_read_local_mmr
|
||||
(UV2H_LB_BAU_SB_ACTIVATION_STATUS_2) >> cpu) & 0x1UL);
|
||||
descriptor_status = (descriptor_status << 1) |
|
||||
descriptor_status2;
|
||||
while (descriptor_status != UV2H_DESC_IDLE) {
|
||||
/*
|
||||
* Our software ack messages may be blocked because
|
||||
* there are no swack resources available. As long
|
||||
* as none of them has timed out hardware will NACK
|
||||
* our message and its state will stay IDLE.
|
||||
*/
|
||||
if ((descriptor_status == UV2H_DESC_SOURCE_TIMEOUT) ||
|
||||
(descriptor_status == UV2H_DESC_DEST_STRONG_NACK) ||
|
||||
(descriptor_status == UV2H_DESC_DEST_PUT_ERR)) {
|
||||
stat->s_stimeout++;
|
||||
return FLUSH_GIVEUP;
|
||||
} else if (descriptor_status == UV2H_DESC_DEST_TIMEOUT) {
|
||||
stat->s_dtimeout++;
|
||||
ttime = get_cycles();
|
||||
|
||||
/*
|
||||
* Our retries may be blocked by all destination
|
||||
* swack resources being consumed, and a timeout
|
||||
* pending. In that case hardware returns the
|
||||
* ERROR that looks like a destination timeout.
|
||||
*/
|
||||
if (cycles_2_us(ttime - bcp->send_message) <
|
||||
timeout_us) {
|
||||
bcp->conseccompletes = 0;
|
||||
return FLUSH_RETRY_PLUGGED;
|
||||
}
|
||||
|
||||
bcp->conseccompletes = 0;
|
||||
return FLUSH_RETRY_TIMEOUT;
|
||||
} else {
|
||||
/*
|
||||
* descriptor_status is still BUSY
|
||||
*/
|
||||
cpu_relax();
|
||||
}
|
||||
descriptor_status = (((unsigned long)(uv_read_local_mmr
|
||||
(mmr_offset)) >> right_shift) &
|
||||
UV_ACT_STATUS_MASK);
|
||||
descriptor_status2 = (((unsigned long)uv_read_local_mmr
|
||||
(UV2H_LB_BAU_SB_ACTIVATION_STATUS_2) >> cpu) &
|
||||
0x1UL);
|
||||
descriptor_status = (descriptor_status << 1) |
|
||||
descriptor_status2;
|
||||
}
|
||||
bcp->conseccompletes++;
|
||||
return FLUSH_COMPLETE;
|
||||
}
|
||||
|
||||
static int uv_wait_completion(struct bau_desc *bau_desc,
|
||||
unsigned long mmr_offset, int right_shift, int this_cpu,
|
||||
struct bau_control *bcp, struct bau_control *smaster, long try)
|
||||
{
|
||||
if (is_uv1_hub())
|
||||
return uv1_wait_completion(bau_desc, mmr_offset, right_shift,
|
||||
this_cpu, bcp, smaster, try);
|
||||
else
|
||||
return uv2_wait_completion(bau_desc, mmr_offset, right_shift,
|
||||
this_cpu, bcp, smaster, try);
|
||||
}
|
||||
|
||||
static inline cycles_t
|
||||
sec_2_cycles(unsigned long sec)
|
||||
{
|
||||
|
@ -585,7 +662,8 @@ int uv_flush_send_and_wait(struct bau_desc *bau_desc,
|
|||
struct bau_control *smaster = bcp->socket_master;
|
||||
struct bau_control *hmaster = bcp->uvhub_master;
|
||||
|
||||
if (!atomic_inc_unless_ge(&hmaster->uvhub_lock,
|
||||
if (is_uv1_hub() &&
|
||||
!atomic_inc_unless_ge(&hmaster->uvhub_lock,
|
||||
&hmaster->active_descriptor_count,
|
||||
hmaster->max_bau_concurrent)) {
|
||||
stat->s_throttles++;
|
||||
|
@ -899,12 +977,17 @@ static void __init uv_enable_timeouts(void)
|
|||
uv_write_global_mmr64
|
||||
(pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image);
|
||||
/*
|
||||
* UV1:
|
||||
* Subsequent reversals of the timebase bit (3) cause an
|
||||
* immediate timeout of one or all INTD resources as
|
||||
* indicated in bits 2:0 (7 causes all of them to timeout).
|
||||
*/
|
||||
mmr_image |= ((unsigned long)1 <<
|
||||
UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT);
|
||||
if (is_uv2_hub()) {
|
||||
mmr_image |= ((unsigned long)1 << UV2_LEG_SHFT);
|
||||
mmr_image |= ((unsigned long)1 << UV2_EXT_SHFT);
|
||||
}
|
||||
uv_write_global_mmr64
|
||||
(pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image);
|
||||
}
|
||||
|
@ -1486,7 +1569,9 @@ calculate_destination_timeout(void)
|
|||
int ret;
|
||||
unsigned long ts_ns;
|
||||
|
||||
mult1 = UV_INTD_SOFT_ACK_TIMEOUT_PERIOD & BAU_MISC_CONTROL_MULT_MASK;
|
||||
if (is_uv1_hub()) {
|
||||
mult1 = UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD &
|
||||
BAU_MISC_CONTROL_MULT_MASK;
|
||||
mmr_image = uv_read_local_mmr(UVH_AGING_PRESCALE_SEL);
|
||||
index = (mmr_image >> BAU_URGENCY_7_SHIFT) & BAU_URGENCY_7_MASK;
|
||||
mmr_image = uv_read_local_mmr(UVH_TRANSACTION_TIMEOUT);
|
||||
|
@ -1494,6 +1579,17 @@ calculate_destination_timeout(void)
|
|||
base = timeout_base_ns[index];
|
||||
ts_ns = base * mult1 * mult2;
|
||||
ret = ts_ns / 1000;
|
||||
} else {
|
||||
/* 4 bits 0/1 for 10/80us, 3 bits of multiplier */
|
||||
mmr_image = uv_read_local_mmr(UVH_AGING_PRESCALE_SEL);
|
||||
mmr_image = (mmr_image & UV_SA_MASK) >> UV_SA_SHFT;
|
||||
if (mmr_image & ((unsigned long)1 << UV2_ACK_UNITS_SHFT))
|
||||
mult1 = 80;
|
||||
else
|
||||
mult1 = 10;
|
||||
base = mmr_image & UV2_ACK_MASK;
|
||||
ret = mult1 * base;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -99,8 +99,12 @@ static void uv_rtc_send_IPI(int cpu)
|
|||
/* Check for an RTC interrupt pending */
|
||||
static int uv_intr_pending(int pnode)
|
||||
{
|
||||
if (is_uv1_hub())
|
||||
return uv_read_global_mmr64(pnode, UVH_EVENT_OCCURRED0) &
|
||||
UVH_EVENT_OCCURRED0_RTC1_MASK;
|
||||
UV1H_EVENT_OCCURRED0_RTC1_MASK;
|
||||
else
|
||||
return uv_read_global_mmr64(pnode, UV2H_EVENT_OCCURRED2) &
|
||||
UV2H_EVENT_OCCURRED2_RTC_1_MASK;
|
||||
}
|
||||
|
||||
/* Setup interrupt and return non-zero if early expiration occurred. */
|
||||
|
@ -114,8 +118,12 @@ static int uv_setup_intr(int cpu, u64 expires)
|
|||
UVH_RTC1_INT_CONFIG_M_MASK);
|
||||
uv_write_global_mmr64(pnode, UVH_INT_CMPB, -1L);
|
||||
|
||||
if (is_uv1_hub())
|
||||
uv_write_global_mmr64(pnode, UVH_EVENT_OCCURRED0_ALIAS,
|
||||
UVH_EVENT_OCCURRED0_RTC1_MASK);
|
||||
UV1H_EVENT_OCCURRED0_RTC1_MASK);
|
||||
else
|
||||
uv_write_global_mmr64(pnode, UV2H_EVENT_OCCURRED2_ALIAS,
|
||||
UV2H_EVENT_OCCURRED2_RTC_1_MASK);
|
||||
|
||||
val = (X86_PLATFORM_IPI_VECTOR << UVH_RTC1_INT_CONFIG_VECTOR_SHFT) |
|
||||
((u64)apicid << UVH_RTC1_INT_CONFIG_APIC_ID_SHFT);
|
||||
|
|
Loading…
Reference in New Issue