x86_64 SGI UV: Fix writes to led registers on remote uv hubs.
[sfrench/cifs-2.6.git] / arch / x86 / include / asm / uv / uv_hub.h
index d1414af9855961ff52a1a952908995eacfb57b69..bcdb708993d249540a2d27ab6d21ab511c7f51b4 100644 (file)
@@ -172,6 +172,8 @@ DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
 #define UV_LOCAL_MMR_SIZE              (64UL * 1024 * 1024)
 #define UV_GLOBAL_MMR32_SIZE           (64UL * 1024 * 1024)
 
+#define UV_GLOBAL_GRU_MMR_BASE         0x4000000
+
 #define UV_GLOBAL_MMR32_PNODE_SHIFT    15
 #define UV_GLOBAL_MMR64_PNODE_SHIFT    26
 
@@ -232,6 +234,26 @@ static inline unsigned long uv_gpa(void *v)
        return uv_soc_phys_ram_to_gpa(__pa(v));
 }
 
+/* Top two bits indicate the requested address is in MMR space.  */
+static inline int
+uv_gpa_in_mmr_space(unsigned long gpa)
+{
+       return (gpa >> 62) == 0x3UL;
+}
+
+/* UV global physical address --> socket phys RAM */
+static inline unsigned long uv_gpa_to_soc_phys_ram(unsigned long gpa)
+{
+       unsigned long paddr = gpa & uv_hub_info->gpa_mask;
+       unsigned long remap_base = uv_hub_info->lowmem_remap_base;
+       unsigned long remap_top =  uv_hub_info->lowmem_remap_top;
+
+       if (paddr >= remap_base && paddr < remap_base + remap_top)
+               paddr -= remap_base;
+       return paddr;
+}
+
+
 /* gnode -> pnode */
 static inline unsigned long uv_gpa_to_gnode(unsigned long gpa)
 {
@@ -307,6 +329,27 @@ static inline unsigned long uv_read_global_mmr64(int pnode,
        return readq(uv_global_mmr64_address(pnode, offset));
 }
 
+/*
+ * Global MMR space addresses when referenced by the GRU. (GRU does
+ * NOT use socket addressing).
+ */
+static inline unsigned long uv_global_gru_mmr_address(int pnode, unsigned long offset)
+{
+       return UV_GLOBAL_GRU_MMR_BASE | offset | (pnode << uv_hub_info->m_val);
+}
+
+static inline void uv_write_global_mmr8(int pnode, unsigned long offset,
+                               unsigned char val)
+{
+       writeb(val, uv_global_mmr64_address(pnode, offset));
+}
+
+static inline unsigned char uv_read_global_mmr8(int pnode,
+                                                unsigned long offset)
+{
+       return readb(uv_global_mmr64_address(pnode, offset));
+}
+
 /*
  * Access hub local MMRs. Faster than using global space but only local MMRs
  * are accessible.
@@ -426,14 +469,28 @@ static inline void uv_set_scir_bits(unsigned char value)
        }
 }
 
+static inline unsigned long uv_scir_offset(int apicid)
+{
+       return SCIR_LOCAL_MMR_BASE | (apicid & 0x3f);
+}
+
 static inline void uv_set_cpu_scir_bits(int cpu, unsigned char value)
 {
        if (uv_cpu_hub_info(cpu)->scir.state != value) {
+               uv_write_global_mmr8(uv_cpu_to_pnode(cpu),
+                               uv_cpu_hub_info(cpu)->scir.offset, value);
                uv_cpu_hub_info(cpu)->scir.state = value;
-               uv_write_local_mmr8(uv_cpu_hub_info(cpu)->scir.offset, value);
        }
 }
 
+static unsigned long uv_hub_ipi_value(int apicid, int vector, int mode)
+{
+       return (1UL << UVH_IPI_INT_SEND_SHFT) |
+                       ((apicid) << UVH_IPI_INT_APIC_ID_SHFT) |
+                       (mode << UVH_IPI_INT_DELIVERY_MODE_SHFT) |
+                       (vector << UVH_IPI_INT_VECTOR_SHFT);
+}
+
 static inline void uv_hub_send_ipi(int pnode, int apicid, int vector)
 {
        unsigned long val;
@@ -442,10 +499,7 @@ static inline void uv_hub_send_ipi(int pnode, int apicid, int vector)
        if (vector == NMI_VECTOR)
                dmode = dest_NMI;
 
-       val = (1UL << UVH_IPI_INT_SEND_SHFT) |
-                       ((apicid) << UVH_IPI_INT_APIC_ID_SHFT) |
-                       (dmode << UVH_IPI_INT_DELIVERY_MODE_SHFT) |
-                       (vector << UVH_IPI_INT_VECTOR_SHFT);
+       val = uv_hub_ipi_value(apicid, vector, dmode);
        uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
 }