* [PATCH 1/3] msi vector targeting abstractions
From: Mark Maule @ 2006-03-21 14:34 UTC (permalink / raw)
To: linuxppc64-dev, linux-pci, linux-ia64, linux-kernel
Cc: j-nomura, Mark Maule, Tony Luck, gregkh
In-Reply-To: <20060321143444.9913.48372.11324@lnx-maule.americas.sgi.com>
Abstract portions of the MSI core for platforms that do not use standard
APIC interrupt controllers. This is implemented through a new arch-specific
msi setup routine, and a set of msi ops which can be set on a per platform
basis.
Signed-off-by: Mark Maule <maule@sgi.com>
Index: linux-2.6.16/drivers/pci/msi.c
===================================================================
--- linux-2.6.16.orig/drivers/pci/msi.c 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/drivers/pci/msi.c 2006-03-21 07:17:39.987000963 -0600
@@ -23,8 +23,6 @@
#include "pci.h"
#include "msi.h"
-#define MSI_TARGET_CPU first_cpu(cpu_online_map)
-
static DEFINE_SPINLOCK(msi_lock);
static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL };
static kmem_cache_t* msi_cachep;
@@ -40,6 +38,15 @@
u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
#endif
+static struct msi_ops *msi_ops;
+
+int
+msi_register(struct msi_ops *ops)
+{
+ msi_ops = ops;
+ return 0;
+}
+
static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags)
{
memset(p, 0, NR_IRQS * sizeof(struct msi_desc));
@@ -92,7 +99,7 @@
static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
{
struct msi_desc *entry;
- struct msg_address address;
+ u32 address_hi, address_lo;
unsigned int irq = vector;
unsigned int dest_cpu = first_cpu(cpu_mask);
@@ -108,28 +115,36 @@
if (!(pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI)))
return;
+ pci_read_config_dword(entry->dev, msi_upper_address_reg(pos),
+ &address_hi);
pci_read_config_dword(entry->dev, msi_lower_address_reg(pos),
- &address.lo_address.value);
- address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
- address.lo_address.value |= (cpu_physical_id(dest_cpu) <<
- MSI_TARGET_CPU_SHIFT);
- entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu);
+ &address_lo);
+
+ msi_ops->target(vector, dest_cpu, &address_hi, &address_lo);
+
+ pci_write_config_dword(entry->dev, msi_upper_address_reg(pos),
+ address_hi);
pci_write_config_dword(entry->dev, msi_lower_address_reg(pos),
- address.lo_address.value);
+ address_lo);
set_native_irq_info(irq, cpu_mask);
break;
}
case PCI_CAP_ID_MSIX:
{
- int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
- PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET;
+ int offset_hi =
+ entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET;
+ int offset_lo =
+ entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET;
+
+ address_hi = readl(entry->mask_base + offset_hi);
+ address_lo = readl(entry->mask_base + offset_lo);
- address.lo_address.value = readl(entry->mask_base + offset);
- address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
- address.lo_address.value |= (cpu_physical_id(dest_cpu) <<
- MSI_TARGET_CPU_SHIFT);
- entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu);
- writel(address.lo_address.value, entry->mask_base + offset);
+ msi_ops->target(vector, dest_cpu, &address_hi, &address_lo);
+
+ writel(address_hi, entry->mask_base + offset_hi);
+ writel(address_lo, entry->mask_base + offset_lo);
set_native_irq_info(irq, cpu_mask);
break;
}
@@ -251,30 +266,6 @@
.set_affinity = set_msi_affinity
};
-static void msi_data_init(struct msg_data *msi_data,
- unsigned int vector)
-{
- memset(msi_data, 0, sizeof(struct msg_data));
- msi_data->vector = (u8)vector;
- msi_data->delivery_mode = MSI_DELIVERY_MODE;
- msi_data->level = MSI_LEVEL_MODE;
- msi_data->trigger = MSI_TRIGGER_MODE;
-}
-
-static void msi_address_init(struct msg_address *msi_address)
-{
- unsigned int dest_id;
- unsigned long dest_phys_id = cpu_physical_id(MSI_TARGET_CPU);
-
- memset(msi_address, 0, sizeof(struct msg_address));
- msi_address->hi_address = (u32)0;
- dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT);
- msi_address->lo_address.u.dest_mode = MSI_PHYSICAL_MODE;
- msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE;
- msi_address->lo_address.u.dest_id = dest_id;
- msi_address->lo_address.value |= (dest_phys_id << MSI_TARGET_CPU_SHIFT);
-}
-
static int msi_free_vector(struct pci_dev* dev, int vector, int reassign);
static int assign_msi_vector(void)
{
@@ -369,6 +360,20 @@
return status;
}
+ if ((status = msi_arch_init()) < 0) {
+ pci_msi_enable = 0;
+ printk(KERN_WARNING
+ "PCI: MSI arch init failed. MSI disabled.\n");
+ return status;
+ }
+
+ if (! msi_ops) {
+ printk(KERN_WARNING
+ "PCI: MSI ops not registered. MSI disabled.\n");
+ status = -EINVAL;
+ return status;
+ }
+
if ((status = msi_cache_init()) < 0) {
pci_msi_enable = 0;
printk(KERN_WARNING "PCI: MSI cache init failed\n");
@@ -514,9 +519,11 @@
**/
static int msi_capability_init(struct pci_dev *dev)
{
+ int status;
struct msi_desc *entry;
- struct msg_address address;
- struct msg_data data;
+ u32 address_lo;
+ u32 address_hi;
+ u32 data;
int pos, vector;
u16 control;
@@ -543,23 +550,27 @@
entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
is_64bit_address(control));
}
+ /* Configure MSI capability structure */
+ status = msi_ops->setup(dev, vector,
+ &address_hi,
+ &address_lo,
+ &data);
+ if (status < 0) {
+ dev->irq = entry->msi_attrib.default_vector;
+ kmem_cache_free(msi_cachep, entry);
+ return status;
+ }
/* Replace with MSI handler */
irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit);
- /* Configure MSI capability structure */
- msi_address_init(&address);
- msi_data_init(&data, vector);
- entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
- MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
- pci_write_config_dword(dev, msi_lower_address_reg(pos),
- address.lo_address.value);
+
+ pci_write_config_dword(dev, msi_lower_address_reg(pos), address_lo);
if (is_64bit_address(control)) {
pci_write_config_dword(dev,
- msi_upper_address_reg(pos), address.hi_address);
- pci_write_config_word(dev,
- msi_data_reg(pos, 1), *((u32*)&data));
+ msi_upper_address_reg(pos), address_hi);
+ pci_write_config_word(dev, msi_data_reg(pos, 1), data);
} else
- pci_write_config_word(dev,
- msi_data_reg(pos, 0), *((u32*)&data));
+ pci_write_config_word(dev, msi_data_reg(pos, 0), data);
+
if (entry->msi_attrib.maskbit) {
unsigned int maskbits, temp;
/* All MSIs are unmasked by default, Mask them all */
@@ -594,13 +605,15 @@
struct msix_entry *entries, int nvec)
{
struct msi_desc *head = NULL, *tail = NULL, *entry = NULL;
- struct msg_address address;
- struct msg_data data;
+ u32 address_hi;
+ u32 address_lo;
+ u32 data;
int vector, pos, i, j, nr_entries, temp = 0;
u32 phys_addr, table_offset;
u16 control;
u8 bir;
void __iomem *base;
+ int status;
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
/* Request & Map MSI-X table region */
@@ -647,18 +660,20 @@
/* Replace with MSI-X handler */
irq_handler_init(PCI_CAP_ID_MSIX, vector, 1);
/* Configure MSI-X capability structure */
- msi_address_init(&address);
- msi_data_init(&data, vector);
- entry->msi_attrib.current_cpu =
- ((address.lo_address.u.dest_id >>
- MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
- writel(address.lo_address.value,
+ status = msi_ops->setup(dev, vector,
+ &address_hi,
+ &address_lo,
+ &data);
+ if (status < 0)
+ break;
+
+ writel(address_lo,
base + j * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
- writel(address.hi_address,
+ writel(address_hi,
base + j * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
- writel(*(u32*)&data,
+ writel(data,
base + j * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_DATA_OFFSET);
attach_msi_entry(entry, vector);
@@ -793,6 +808,8 @@
void __iomem *base;
unsigned long flags;
+ msi_ops->teardown(vector);
+
spin_lock_irqsave(&msi_lock, flags);
entry = msi_desc[vector];
if (!entry || entry->dev != dev) {
Index: linux-2.6.16/include/asm-i386/msi.h
===================================================================
--- linux-2.6.16.orig/include/asm-i386/msi.h 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/include/asm-i386/msi.h 2006-03-20 14:45:09.540950385 -0600
@@ -12,4 +12,12 @@
#define LAST_DEVICE_VECTOR 232
#define MSI_TARGET_CPU_SHIFT 12
+extern struct msi_ops msi_apic_ops;
+
+static inline int msi_arch_init(void)
+{
+ msi_register(&msi_apic_ops);
+ return 0;
+}
+
#endif /* ASM_MSI_H */
Index: linux-2.6.16/include/asm-x86_64/msi.h
===================================================================
--- linux-2.6.16.orig/include/asm-x86_64/msi.h 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/include/asm-x86_64/msi.h 2006-03-20 14:45:09.542903318 -0600
@@ -13,4 +13,12 @@
#define LAST_DEVICE_VECTOR 232
#define MSI_TARGET_CPU_SHIFT 12
+extern struct msi_ops msi_apic_ops;
+
+static inline int msi_arch_init(void)
+{
+ msi_register(&msi_apic_ops);
+ return 0;
+}
+
#endif /* ASM_MSI_H */
Index: linux-2.6.16/include/asm-ia64/machvec.h
===================================================================
--- linux-2.6.16.orig/include/asm-ia64/machvec.h 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/include/asm-ia64/machvec.h 2006-03-20 14:49:38.415888062 -0600
@@ -74,6 +74,7 @@
typedef unsigned short ia64_mv_readw_relaxed_t (const volatile void __iomem *);
typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *);
typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *);
+typedef int ia64_mv_msi_init_t (void);
static inline void
machvec_noop (void)
@@ -146,6 +147,7 @@
# define platform_readw_relaxed ia64_mv.readw_relaxed
# define platform_readl_relaxed ia64_mv.readl_relaxed
# define platform_readq_relaxed ia64_mv.readq_relaxed
+# define platform_msi_init ia64_mv.msi_init
# endif
/* __attribute__((__aligned__(16))) is required to make size of the
@@ -194,6 +196,7 @@
ia64_mv_readw_relaxed_t *readw_relaxed;
ia64_mv_readl_relaxed_t *readl_relaxed;
ia64_mv_readq_relaxed_t *readq_relaxed;
+ ia64_mv_msi_init_t *msi_init;
} __attribute__((__aligned__(16))); /* align attrib? see above comment */
#define MACHVEC_INIT(name) \
@@ -238,6 +241,7 @@
platform_readw_relaxed, \
platform_readl_relaxed, \
platform_readq_relaxed, \
+ platform_msi_init, \
}
extern struct ia64_machine_vector ia64_mv;
@@ -386,5 +390,8 @@
#ifndef platform_readq_relaxed
# define platform_readq_relaxed __ia64_readq_relaxed
#endif
+#ifndef platform_msi_init
+# define platform_msi_init NULL
+#endif
#endif /* _ASM_IA64_MACHVEC_H */
Index: linux-2.6.16/include/asm-ia64/machvec_sn2.h
===================================================================
--- linux-2.6.16.orig/include/asm-ia64/machvec_sn2.h 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/include/asm-ia64/machvec_sn2.h 2006-03-20 14:45:09.548762117 -0600
@@ -66,6 +66,7 @@
extern ia64_mv_dma_sync_sg_for_device sn_dma_sync_sg_for_device;
extern ia64_mv_dma_mapping_error sn_dma_mapping_error;
extern ia64_mv_dma_supported sn_dma_supported;
+extern ia64_mv_msi_init_t sn_msi_init;
/*
* This stuff has dual use!
@@ -115,6 +116,11 @@
#define platform_dma_sync_sg_for_device sn_dma_sync_sg_for_device
#define platform_dma_mapping_error sn_dma_mapping_error
#define platform_dma_supported sn_dma_supported
+#ifdef CONFIG_PCI_MSI
+#define platform_msi_init sn_msi_init
+#else
+#define platform_msi_init NULL
+#endif
#include <asm/sn/io.h>
Index: linux-2.6.16/include/asm-ia64/msi.h
===================================================================
--- linux-2.6.16.orig/include/asm-ia64/msi.h 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/include/asm-ia64/msi.h 2006-03-20 14:50:53.331368084 -0600
@@ -14,4 +14,16 @@
#define ack_APIC_irq ia64_eoi
#define MSI_TARGET_CPU_SHIFT 4
+extern struct msi_ops msi_apic_ops;
+
+static inline int msi_arch_init(void)
+{
+ if (platform_msi_init)
+ return platform_msi_init();
+
+ /* default ops for most ia64 platforms */
+ msi_register(&msi_apic_ops);
+ return 0;
+}
+
#endif /* ASM_MSI_H */
Index: linux-2.6.16/drivers/pci/Makefile
===================================================================
--- linux-2.6.16.orig/drivers/pci/Makefile 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/drivers/pci/Makefile 2006-03-20 22:00:54.079057888 -0600
@@ -26,7 +26,11 @@
obj-$(CONFIG_PPC64) += setup-bus.o
obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
obj-$(CONFIG_X86_VISWS) += setup-irq.o
-obj-$(CONFIG_PCI_MSI) += msi.o
+
+msiobj-y := msi.o msi-apic.o
+msiobj-$(CONFIG_IA64_GENERIC) += msi-altix.o
+msiobj-$(CONFIG_IA64_SGI_SN2) += msi-altix.o
+obj-$(CONFIG_PCI_MSI) += $(msiobj-y)
#
# ACPI Related PCI FW Functions
Index: linux-2.6.16/drivers/pci/msi-apic.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16/drivers/pci/msi-apic.c 2006-03-20 22:01:01.802923681 -0600
@@ -0,0 +1,100 @@
+/*
+ * MSI hooks for standard x86 apic
+ */
+
+#include <linux/pci.h>
+#include <linux/irq.h>
+
+#include "msi.h"
+
+/*
+ * Shifts for APIC-based data
+ */
+
+#define MSI_DATA_VECTOR_SHIFT 0
+#define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT)
+
+#define MSI_DATA_DELIVERY_SHIFT 8
+#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT)
+#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_SHIFT)
+
+#define MSI_DATA_LEVEL_SHIFT 14
+#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT)
+#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT)
+
+#define MSI_DATA_TRIGGER_SHIFT 15
+#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT)
+#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT)
+
+/*
+ * Shift/mask fields for APIC-based bus address
+ */
+
+#define MSI_ADDR_HEADER 0xfee00000
+
+#define MSI_ADDR_DESTID_MASK 0xfff0000f
+#define MSI_ADDR_DESTID_CPU(cpu) ((cpu) << MSI_TARGET_CPU_SHIFT)
+
+#define MSI_ADDR_DESTMODE_SHIFT 2
+#define MSI_ADDR_DESTMODE_PHYS (0 << MSI_ADDR_DESTMODE_SHIFT)
+#define MSI_ADDR_DESTMODE_LOGIC (1 << MSI_ADDR_DESTMODE_SHIFT)
+
+#define MSI_ADDR_REDIRECTION_SHIFT 3
+#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT)
+#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT)
+
+
+static void
+msi_target_apic(unsigned int vector,
+ unsigned int dest_cpu,
+ u32 *address_hi, /* in/out */
+ u32 *address_lo) /* in/out */
+{
+ u32 addr = *address_lo;
+
+ addr &= MSI_ADDR_DESTID_MASK;
+ addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(dest_cpu));
+
+ *address_lo = addr;
+}
+
+static int
+msi_setup_apic(struct pci_dev *pdev, /* unused in generic */
+ unsigned int vector,
+ u32 *address_hi,
+ u32 *address_lo,
+ u32 *data)
+{
+ unsigned long dest_phys_id;
+
+ dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
+
+ *address_hi = 0;
+ *address_lo = MSI_ADDR_HEADER |
+ MSI_ADDR_DESTMODE_PHYS |
+ MSI_ADDR_REDIRECTION_CPU |
+ MSI_ADDR_DESTID_CPU(dest_phys_id);
+
+ *data = MSI_DATA_TRIGGER_EDGE |
+ MSI_DATA_LEVEL_ASSERT |
+ MSI_DATA_DELIVERY_FIXED |
+ MSI_DATA_VECTOR(vector);
+
+ return 0;
+}
+
+static void
+msi_teardown_apic(unsigned int vector)
+{
+ return; /* no-op */
+}
+
+/*
+ * Generic ops used on most IA archs/platforms. Set with msi_register()
+ */
+
+struct msi_ops msi_apic_ops = {
+ .setup = msi_setup_apic,
+ .teardown = msi_teardown_apic,
+ .target = msi_target_apic,
+};
Index: linux-2.6.16/drivers/pci/msi.h
===================================================================
--- linux-2.6.16.orig/drivers/pci/msi.h 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/drivers/pci/msi.h 2006-03-20 14:55:40.935888578 -0600
@@ -6,6 +6,68 @@
#ifndef MSI_H
#define MSI_H
+/*
+ * MSI operation vector. Used by the msi core code (drivers/pci/msi.c)
+ * to abstract platform-specific tasks relating to MSI address generation
+ * and resource management.
+ */
+struct msi_ops {
+ /**
+ * setup - generate an MSI bus address and data for a given vector
+ * @pdev: PCI device context (in)
+ * @vector: vector allocated by the msi core (in)
+ * @addr_hi: upper 32 bits of PCI bus MSI address (out)
+ * @addr_lo: lower 32 bits of PCI bus MSI address (out)
+ * @data: MSI data payload (out)
+ *
+ * Description: The setup op is used to generate a PCI bus addres and
+ * data which the msi core will program into the card MSI capability
+ * registers. The setup routine is responsible for picking an initial
+ * cpu to target the MSI at. The setup routine is responsible for
+ * examining pdev to determine the MSI capabilities of the card and
+ * generating a suitable address/data. The setup routine is
+ * responsible for allocating and tracking any system resources it
+ * needs to route the MSI to the cpu it picks, and for associating
+ * those resources with the passed in vector.
+ *
+ * Returns 0 if the MSI address/data was successfully setup.
+ **/
+
+ int (*setup) (struct pci_dev *pdev, unsigned int vector,
+ u32 *addr_hi, u32 *addr_lo, u32 *data);
+
+ /**
+ * teardown - release resources allocated by setup
+ * @vector: vector context for resources (in)
+ *
+ * Description: The teardown op is used to release any resources
+ * that were allocated in the setup routine associated with the passed
+ * in vector.
+ **/
+
+ void (*teardown) (unsigned int vector);
+
+ /**
+ * target - retarget an MSI at a different cpu
+ * @vector: vector context for resources (in)
+ * @cpu: new cpu to direct vector at (in)
+ * @addr_hi: new value of PCI bus upper 32 bits (in/out)
+ * @addr_lo: new value of PCI bus lower 32 bits (in/out)
+ *
+ * Description: The target op is used to redirect an MSI vector
+ * at a different cpu. addr_hi/addr_lo coming in are the existing
+ * values that the MSI core has programmed into the card. The
+ * target code is responsible for freeing any resources (if any)
+ * associated with the old address, and generating a new PCI bus
+ * addr_hi/addr_lo that will redirect the vector at the indicated cpu.
+ **/
+
+ void (*target) (unsigned int vector, unsigned int cpu,
+ u32 *addr_hi, u32 *addr_lo);
+};
+
+extern int msi_register(struct msi_ops *ops);
+
#include <asm/msi.h>
/*
@@ -63,67 +125,6 @@
#define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK)
#define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK)
-/*
- * MSI Defined Data Structures
- */
-#define MSI_ADDRESS_HEADER 0xfee
-#define MSI_ADDRESS_HEADER_SHIFT 12
-#define MSI_ADDRESS_HEADER_MASK 0xfff000
-#define MSI_ADDRESS_DEST_ID_MASK 0xfff0000f
-#define MSI_TARGET_CPU_MASK 0xff
-#define MSI_DELIVERY_MODE 0
-#define MSI_LEVEL_MODE 1 /* Edge always assert */
-#define MSI_TRIGGER_MODE 0 /* MSI is edge sensitive */
-#define MSI_PHYSICAL_MODE 0
-#define MSI_LOGICAL_MODE 1
-#define MSI_REDIRECTION_HINT_MODE 0
-
-struct msg_data {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- __u32 vector : 8;
- __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */
- __u32 reserved_1 : 3;
- __u32 level : 1; /* 0: deassert | 1: assert */
- __u32 trigger : 1; /* 0: edge | 1: level */
- __u32 reserved_2 : 16;
-#elif defined(__BIG_ENDIAN_BITFIELD)
- __u32 reserved_2 : 16;
- __u32 trigger : 1; /* 0: edge | 1: level */
- __u32 level : 1; /* 0: deassert | 1: assert */
- __u32 reserved_1 : 3;
- __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */
- __u32 vector : 8;
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
-} __attribute__ ((packed));
-
-struct msg_address {
- union {
- struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- __u32 reserved_1 : 2;
- __u32 dest_mode : 1; /*0:physic | 1:logic */
- __u32 redirection_hint: 1; /*0: dedicated CPU
- 1: lowest priority */
- __u32 reserved_2 : 4;
- __u32 dest_id : 24; /* Destination ID */
-#elif defined(__BIG_ENDIAN_BITFIELD)
- __u32 dest_id : 24; /* Destination ID */
- __u32 reserved_2 : 4;
- __u32 redirection_hint: 1; /*0: dedicated CPU
- 1: lowest priority */
- __u32 dest_mode : 1; /*0:physic | 1:logic */
- __u32 reserved_1 : 2;
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
- }u;
- __u32 value;
- }lo_address;
- __u32 hi_address;
-} __attribute__ ((packed));
-
struct msi_desc {
struct {
__u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */
@@ -132,7 +133,7 @@
__u8 reserved: 1; /* reserved */
__u8 entry_nr; /* specific enabled entry */
__u8 default_vector; /* default pre-assigned vector */
- __u8 current_cpu; /* current destination cpu */
+ __u8 unused; /* formerly unused destination cpu*/
}msi_attrib;
struct {
Index: linux-2.6.16/drivers/pci/msi-altix.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16/drivers/pci/msi-altix.c 2006-03-21 07:17:34.077424014 -0600
@@ -0,0 +1,18 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
+ */
+
+#include <asm/errno.h>
+
+int
+sn_msi_init(void)
+{
+ /*
+ * return error until MSI is supported on altix platforms
+ */
+ return -EINVAL;
+}
^ permalink raw reply
* [PATCH 0/3] msi abstractions and support for altix
From: Mark Maule @ 2006-03-21 14:34 UTC (permalink / raw)
To: linuxppc64-dev, linux-pci, linux-ia64, linux-kernel
Cc: j-nomura, Mark Maule, Tony Luck, gregkh
Resend #6: resubmit against 2.6.16 base
Patch set to abstract portions of the MSI core so that it can be used on
architectures which don't use standard interrupt controllers.
Changes from Resend #5
+ Move altix msi ops down into drivers/pci/msi-altix.c
+ Simplify ia64 platform_msi_init machvec
Changes from Resend #4
+ Fix an x86_64 build problem
+ Fix an ia64 CONFIG_IA64_GENERIC build problem
+ Fix a bug in the new ia64 reserve_irq_vector()
+ Restore dev->irq if msi_ops->setup fails
+ Redo msi-altix.patch so it applies on 2.6.16-rc1
Changes from Resend #3
+ Move external declarations of msi_apic_ops out of routines, and up earlier
in the respective .h files.
+ Add comments to the msi_ops structure declaration
Changes from Resend #2
+ Cleanup the ia64 platform_msi_init macro so it works on non-altix ia64
Changes from initial version
+ Change uintXX_t to uXX
+ Change _callouts to _ops
+ Renamed the _generic routines to _apic and moved them to a new file
msi-apic.c
+ Have each msi_arch_init() routine call msi_register() with the desired
msi ops for that platform.
+ Moved msi_address, msi_data, and related defs out of msi.h and into
msi-apic.c, replaced by shifts/masks.
+ Rolled msi-arch-init.patch and msi-callouts.patch into a single msi-ops.patch
Mark
1/3 msi-ops.patch
Add an msi_arch_init() hook which can be used to perform platform
specific setup prior to msi use.
Define a set of msi ops to implement the platform-specific tasks:
setup - set up plumbing to get a vector directed at a default
cpu, and return the corresponding MSI bus address and data.
teardown - inverse of msi_setup
target - retarget a vector to a given cpu
Define the routine msi_register() called from msi_arch_init()
to set the desired ops.
Move a bunch of apic-specific code out of the msi core .h/.c and
into a new msi-apic.c file.
2/3 ia64-per-platform-device-vector.patch
For the ia64 arch, allow per-platform definitions of
IA64_FIRST_DEVICE_VECTOR and IA64_LAST_DEVICE_VECTOR.
3/3 msi-altix.patch
Altix specific callouts to implement MSI.
^ permalink raw reply
* VLAN support on TSEC for MPC8541
From: Bizhan Gholikhamseh (bgholikh) @ 2006-03-21 14:04 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 178 bytes --]
Hi All,
I have asked this question in past with no response. Are there any VLAN
implementation of TSEC driver for MPC8541 (with CPM core)?
Many thanks in advance,
Bizhan
[-- Attachment #2: Type: text/html, Size: 826 bytes --]
^ permalink raw reply
* [PATCH 11/11] powerpc: Remove calculation of io hole
From: Michael Ellerman @ 2006-03-21 9:46 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
In mm_init_ppc64() we calculate the location of the "IO hole", but then
no one ever looks at the value. So don't bother.
That's actually all mm_init_ppc64() does, so get rid of it too.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/setup_64.c | 2 -
arch/powerpc/mm/init_64.c | 48 -----------------------------------------
include/asm-powerpc/lmb.h | 2 -
include/asm-powerpc/mmu.h | 1
4 files changed, 53 deletions(-)
Index: to-merge/arch/powerpc/kernel/setup_64.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/setup_64.c
+++ to-merge/arch/powerpc/kernel/setup_64.c
@@ -497,8 +497,6 @@ void __init setup_system(void)
#endif
printk("-----------------------------------------------------\n");
- mm_init_ppc64();
-
DBG(" <- setup_system()\n");
}
Index: to-merge/arch/powerpc/mm/init_64.c
===================================================================
--- to-merge.orig/arch/powerpc/mm/init_64.c
+++ to-merge/arch/powerpc/mm/init_64.c
@@ -84,54 +84,6 @@
/* max amount of RAM to use */
unsigned long __max_memory;
-/* info on what we think the IO hole is */
-unsigned long io_hole_start;
-unsigned long io_hole_size;
-
-/*
- * Do very early mm setup.
- */
-void __init mm_init_ppc64(void)
-{
-#ifndef CONFIG_PPC_ISERIES
- unsigned long i;
-#endif
-
- ppc64_boot_msg(0x100, "MM Init");
-
- /* This is the story of the IO hole... please, keep seated,
- * unfortunately, we are out of oxygen masks at the moment.
- * So we need some rough way to tell where your big IO hole
- * is. On pmac, it's between 2G and 4G, on POWER3, it's around
- * that area as well, on POWER4 we don't have one, etc...
- * We need that as a "hint" when sizing the TCE table on POWER3
- * So far, the simplest way that seem work well enough for us it
- * to just assume that the first discontinuity in our physical
- * RAM layout is the IO hole. That may not be correct in the future
- * (and isn't on iSeries but then we don't care ;)
- */
-
-#ifndef CONFIG_PPC_ISERIES
- for (i = 1; i < lmb.memory.cnt; i++) {
- unsigned long base, prevbase, prevsize;
-
- prevbase = lmb.memory.region[i-1].base;
- prevsize = lmb.memory.region[i-1].size;
- base = lmb.memory.region[i].base;
- if (base > (prevbase + prevsize)) {
- io_hole_start = prevbase + prevsize;
- io_hole_size = base - (prevbase + prevsize);
- break;
- }
- }
-#endif /* CONFIG_PPC_ISERIES */
- if (io_hole_start)
- printk("IO Hole assumed to be %lx -> %lx\n",
- io_hole_start, io_hole_start + io_hole_size - 1);
-
- ppc64_boot_msg(0x100, "MM Init Done");
-}
-
void free_initmem(void)
{
unsigned long addr;
Index: to-merge/include/asm-powerpc/lmb.h
===================================================================
--- to-merge.orig/include/asm-powerpc/lmb.h
+++ to-merge/include/asm-powerpc/lmb.h
@@ -54,8 +54,6 @@ extern void __init lmb_enforce_memory_li
extern void lmb_dump_all(void);
-extern unsigned long io_hole_start;
-
static inline unsigned long
lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)
{
Index: to-merge/include/asm-powerpc/mmu.h
===================================================================
--- to-merge.orig/include/asm-powerpc/mmu.h
+++ to-merge/include/asm-powerpc/mmu.h
@@ -236,7 +236,6 @@ extern void htab_initialize_secondary(vo
extern void hpte_init_native(void);
extern void hpte_init_lpar(void);
extern void hpte_init_iSeries(void);
-extern void mm_init_ppc64(void);
extern long pSeries_lpar_hpte_insert(unsigned long hpte_group,
unsigned long va, unsigned long prpn,
^ permalink raw reply
* [PATCH 10/11] powerpc: iseries: Add bootargs to /chosen
From: Michael Ellerman @ 2006-03-21 9:46 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
Add the command line args to the device tree as /chosen/bootargs.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/iseries/setup.c | 1 +
1 files changed, 1 insertion(+)
Index: to-merge/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/setup.c
+++ to-merge/arch/powerpc/platforms/iseries/setup.c
@@ -931,6 +931,7 @@ void build_flat_dt(struct iseries_flat_d
/* /chosen */
dt_start_node(dt, "chosen");
dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR);
+ dt_prop_str(dt, "bootargs", cmd_line);
if (cmd_mem_limit)
dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit);
dt_end_node(dt);
^ permalink raw reply
* [PATCH 9/11] powerpc: iseries: Add /system-id, /model and /compatible
From: Michael Ellerman @ 2006-03-21 9:46 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
Add /system-id, /model and /compatible to the iSeries device tree.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/iseries/setup.c | 20 ++++++++++++++++++++
1 files changed, 20 insertions(+)
Index: to-merge/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/setup.c
+++ to-merge/arch/powerpc/platforms/iseries/setup.c
@@ -50,6 +50,7 @@
#include <asm/iseries/hv_call_xm.h>
#include <asm/iseries/it_lp_queue.h>
#include <asm/iseries/mf.h>
+#include <asm/iseries/it_exp_vpd_panel.h>
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/lpar_map.h>
#include <asm/udbg.h>
@@ -888,6 +889,24 @@ void dt_cpus(struct iseries_flat_dt *dt)
dt_end_node(dt);
}
+void dt_model(struct iseries_flat_dt *dt)
+{
+ char buf[16] = "IBM,";
+
+ /* "IBM," + mfgId[2:3] + systemSerial[1:5] */
+ strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
+ strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
+ buf[11] = '\0';
+ dt_prop_str(dt, "system-id", buf);
+
+ /* "IBM," + machineType[0:4] */
+ strne2a(buf + 4, xItExtVpdPanel.machineType, 4);
+ buf[8] = '\0';
+ dt_prop_str(dt, "model", buf);
+
+ dt_prop_str(dt, "compatible", "IBM,iSeries");
+}
+
void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
{
u64 tmp[2];
@@ -898,6 +917,7 @@ void build_flat_dt(struct iseries_flat_d
dt_prop_u32(dt, "#address-cells", 2);
dt_prop_u32(dt, "#size-cells", 2);
+ dt_model(dt);
/* /memory */
dt_start_node(dt, "memory@0");
^ permalink raw reply
* [PATCH 8/11] powerpc: Add strne2a() to convert a string from EBCDIC to ASCII
From: Michael Ellerman @ 2006-03-21 9:46 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
Add strne2a() which converts a string from EBCDIC to ASCII.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/lib/e2a.c | 10 ++++++++++
include/asm-powerpc/system.h | 2 ++
2 files changed, 12 insertions(+)
Index: to-merge/arch/powerpc/lib/e2a.c
===================================================================
--- to-merge.orig/arch/powerpc/lib/e2a.c
+++ to-merge/arch/powerpc/lib/e2a.c
@@ -103,4 +103,14 @@ unsigned char e2a(unsigned char x)
}
EXPORT_SYMBOL(e2a);
+unsigned char* strne2a(unsigned char *dest, const unsigned char *src, size_t n)
+{
+ int i;
+ n = strnlen(src, n);
+
+ for (i = 0; i < n; i++)
+ dest[i] = e2a(src[i]);
+
+ return dest;
+}
Index: to-merge/include/asm-powerpc/system.h
===================================================================
--- to-merge.orig/include/asm-powerpc/system.h
+++ to-merge/include/asm-powerpc/system.h
@@ -171,6 +171,8 @@ extern u32 booke_wdt_period;
/* EBCDIC -> ASCII conversion for [0-9A-Z] on iSeries */
extern unsigned char e2a(unsigned char);
+extern unsigned char* strne2a(unsigned char *dest,
+ const unsigned char *src, size_t n);
struct device_node;
extern void note_scsi_host(struct device_node *, void *);
^ permalink raw reply
* [PATCH 7/11] powerpc: iseries: Make more stuff static in platforms/iseries/mf.c
From: Michael Ellerman @ 2006-03-21 9:46 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
Make mf_get_rtc(), mf_get_boot_rtc() and mf_set_rtc() static, cause they can
be. We need to move mf_set_rtc() to avoid a forward declaration.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/iseries/mf.c | 78 ++++++++++++++++++------------------
include/asm-powerpc/iseries/mf.h | 4 -
2 files changed, 39 insertions(+), 43 deletions(-)
Index: to-merge/arch/powerpc/platforms/iseries/mf.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/mf.c
+++ to-merge/arch/powerpc/platforms/iseries/mf.c
@@ -706,6 +706,43 @@ static void get_rtc_time_complete(void *
complete(&rtc->com);
}
+static int mf_set_rtc(struct rtc_time *tm)
+{
+ char ce_time[12];
+ u8 day, mon, hour, min, sec, y1, y2;
+ unsigned year;
+
+ year = 1900 + tm->tm_year;
+ y1 = year / 100;
+ y2 = year % 100;
+
+ sec = tm->tm_sec;
+ min = tm->tm_min;
+ hour = tm->tm_hour;
+ day = tm->tm_mday;
+ mon = tm->tm_mon + 1;
+
+ BIN_TO_BCD(sec);
+ BIN_TO_BCD(min);
+ BIN_TO_BCD(hour);
+ BIN_TO_BCD(mon);
+ BIN_TO_BCD(day);
+ BIN_TO_BCD(y1);
+ BIN_TO_BCD(y2);
+
+ memset(ce_time, 0, sizeof(ce_time));
+ ce_time[3] = 0x41;
+ ce_time[4] = y1;
+ ce_time[5] = y2;
+ ce_time[6] = sec;
+ ce_time[7] = min;
+ ce_time[8] = hour;
+ ce_time[10] = day;
+ ce_time[11] = mon;
+
+ return signal_ce_msg(ce_time, NULL);
+}
+
static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm)
{
tm->tm_wday = 0;
@@ -761,7 +798,7 @@ static int rtc_set_tm(int rc, u8 *ce_msg
return 0;
}
-int mf_get_rtc(struct rtc_time *tm)
+static int mf_get_rtc(struct rtc_time *tm)
{
struct ce_msg_comp_data ce_complete;
struct rtc_time_data rtc_data;
@@ -794,7 +831,7 @@ static void get_boot_rtc_time_complete(v
rtc->busy = 0;
}
-int mf_get_boot_rtc(struct rtc_time *tm)
+static int mf_get_boot_rtc(struct rtc_time *tm)
{
struct ce_msg_comp_data ce_complete;
struct boot_rtc_time_data rtc_data;
@@ -816,43 +853,6 @@ int mf_get_boot_rtc(struct rtc_time *tm)
return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
}
-int mf_set_rtc(struct rtc_time *tm)
-{
- char ce_time[12];
- u8 day, mon, hour, min, sec, y1, y2;
- unsigned year;
-
- year = 1900 + tm->tm_year;
- y1 = year / 100;
- y2 = year % 100;
-
- sec = tm->tm_sec;
- min = tm->tm_min;
- hour = tm->tm_hour;
- day = tm->tm_mday;
- mon = tm->tm_mon + 1;
-
- BIN_TO_BCD(sec);
- BIN_TO_BCD(min);
- BIN_TO_BCD(hour);
- BIN_TO_BCD(mon);
- BIN_TO_BCD(day);
- BIN_TO_BCD(y1);
- BIN_TO_BCD(y2);
-
- memset(ce_time, 0, sizeof(ce_time));
- ce_time[3] = 0x41;
- ce_time[4] = y1;
- ce_time[5] = y2;
- ce_time[6] = sec;
- ce_time[7] = min;
- ce_time[8] = hour;
- ce_time[10] = day;
- ce_time[11] = mon;
-
- return signal_ce_msg(ce_time, NULL);
-}
-
#ifdef CONFIG_PROC_FS
static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
Index: to-merge/include/asm-powerpc/iseries/mf.h
===================================================================
--- to-merge.orig/include/asm-powerpc/iseries/mf.h
+++ to-merge/include/asm-powerpc/iseries/mf.h
@@ -48,8 +48,4 @@ extern void mf_display_progress(u16 valu
extern void mf_init(void);
-extern int mf_get_rtc(struct rtc_time *tm);
-extern int mf_get_boot_rtc(struct rtc_time *tm);
-extern int mf_set_rtc(struct rtc_time *tm);
-
#endif /* _ASM_POWERPC_ISERIES_MF_H */
^ permalink raw reply
* [PATCH 6/11] powerpc: iseries: Remove pointless iSeries_(restart|power_off|halt)
From: Michael Ellerman @ 2006-03-21 9:46 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
These routines just call through to the mf routines, so point ppc_md straight
at the mf routines. We need to pass the cmd through to mf_reboot to make it
work, but that seems reasonable.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/iseries/mf.c | 2 +-
arch/powerpc/platforms/iseries/setup.c | 30 +++---------------------------
include/asm-powerpc/iseries/mf.h | 2 +-
3 files changed, 5 insertions(+), 29 deletions(-)
Index: to-merge/arch/powerpc/platforms/iseries/mf.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/mf.c
+++ to-merge/arch/powerpc/platforms/iseries/mf.c
@@ -599,7 +599,7 @@ void mf_power_off(void)
* Global kernel interface to tell the VSP object in the primary
* partition to reboot this partition.
*/
-void mf_reboot(void)
+void mf_reboot(char *cmd)
{
printk(KERN_INFO "mf.c: Preparing to bounce...\n");
signal_ce_msg_simple(0x4e, NULL);
Index: to-merge/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/setup.c
+++ to-merge/arch/powerpc/platforms/iseries/setup.c
@@ -554,30 +554,6 @@ static void iSeries_show_cpuinfo(struct
seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n");
}
-/*
- * Document me.
- */
-static void iSeries_restart(char *cmd)
-{
- mf_reboot();
-}
-
-/*
- * Document me.
- */
-static void iSeries_power_off(void)
-{
- mf_power_off();
-}
-
-/*
- * Document me.
- */
-static void iSeries_halt(void)
-{
- mf_power_off();
-}
-
static void __init iSeries_progress(char * st, unsigned short code)
{
printk("Progress: [%04x] - %s\n", (unsigned)code, st);
@@ -716,9 +692,9 @@ struct machdep_calls __initdata iseries_
.get_irq = iSeries_get_irq,
.init_early = iSeries_init_early,
.pcibios_fixup = iSeries_pci_final_fixup,
- .restart = iSeries_restart,
- .power_off = iSeries_power_off,
- .halt = iSeries_halt,
+ .restart = mf_reboot,
+ .power_off = mf_power_off,
+ .halt = mf_power_off,
.get_boot_time = iSeries_get_boot_time,
.set_rtc_time = iSeries_set_rtc_time,
.get_rtc_time = iSeries_get_rtc_time,
Index: to-merge/include/asm-powerpc/iseries/mf.h
===================================================================
--- to-merge.orig/include/asm-powerpc/iseries/mf.h
+++ to-merge/include/asm-powerpc/iseries/mf.h
@@ -41,7 +41,7 @@ extern void mf_deallocate_lp_events(HvLp
unsigned count, MFCompleteHandler hdlr, void *userToken);
extern void mf_power_off(void);
-extern void mf_reboot(void);
+extern void mf_reboot(char *cmd);
extern void mf_display_src(u32 word);
extern void mf_display_progress(u16 value);
^ permalink raw reply
* [PATCH 5/11] powerpc: iseries: mf related cleanups
From: Michael Ellerman @ 2006-03-21 9:46 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
Some cleanups in the iSeries code.
- Make mf_display_progress() check mf_initialized rather than the caller.
- Set mf_initialized in mf_init() rather than in setup.c
- Then move mf_initialized into mf.c, the only place it's used.
- Move the mf related logic from iSeries_progress() to mf_display_progress()
- Use a #define to size the pending_event_prealloc array
- Use that define in the initialsation loop rather than sizeof jiggery pokery
- Remove stupid comment(s)
- Mark stuff static and/or __init
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/iseries/mf.c | 32 +++++++++++++++++++++++---------
arch/powerpc/platforms/iseries/setup.c | 11 +----------
include/asm-powerpc/iseries/mf.h | 1 -
3 files changed, 24 insertions(+), 20 deletions(-)
Index: to-merge/arch/powerpc/platforms/iseries/mf.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/mf.c
+++ to-merge/arch/powerpc/platforms/iseries/mf.c
@@ -46,6 +46,7 @@
#include "setup.h"
extern int piranha_simulator;
+static int mf_initialized = 0;
/*
* This is the structure layout for the Machine Facilites LPAR event
@@ -143,7 +144,8 @@ static spinlock_t pending_event_spinlock
static struct pending_event *pending_event_head;
static struct pending_event *pending_event_tail;
static struct pending_event *pending_event_avail;
-static struct pending_event pending_event_prealloc[16];
+#define PENDING_EVENT_PREALLOC_LEN 16
+static struct pending_event pending_event_prealloc[PENDING_EVENT_PREALLOC_LEN];
/*
* Put a pending event onto the available queue, so it can get reused.
@@ -625,7 +627,7 @@ void mf_display_src(u32 word)
/*
* Display a single word SRC of the form "PROGXXXX" on the VSP control panel.
*/
-void mf_display_progress(u16 value)
+static __init void mf_display_progress_src(u16 value)
{
u8 ce[12];
u8 src[72];
@@ -649,30 +651,42 @@ void mf_display_progress(u16 value)
* Clear the VSP control panel. Used to "erase" an SRC that was
* previously displayed.
*/
-void mf_clear_src(void)
+static void mf_clear_src(void)
{
signal_ce_msg_simple(0x4b, NULL);
}
+void __init mf_display_progress(u16 value)
+{
+ if (piranha_simulator || !mf_initialized)
+ return;
+
+ if (0xFFFF == value)
+ mf_clear_src();
+ else
+ mf_display_progress_src(value);
+}
+
/*
* Initialization code here.
*/
-void mf_init(void)
+void __init mf_init(void)
{
int i;
- /* initialize */
spin_lock_init(&pending_event_spinlock);
- for (i = 0;
- i < sizeof(pending_event_prealloc) / sizeof(*pending_event_prealloc);
- ++i)
+
+ for (i = 0; i < PENDING_EVENT_PREALLOC_LEN; i++)
free_pending_event(&pending_event_prealloc[i]);
+
HvLpEvent_registerHandler(HvLpEvent_Type_MachineFac, &hv_handler);
/* virtual continue ack */
signal_ce_msg_simple(0x57, NULL);
- /* initialization complete */
+ mf_initialized = 1;
+ mb();
+
printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities "
"initialized\n");
}
Index: to-merge/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/setup.c
+++ to-merge/arch/powerpc/platforms/iseries/setup.c
@@ -89,8 +89,6 @@ extern unsigned long embedded_sysmap_end
extern unsigned long iSeries_recal_tb;
extern unsigned long iSeries_recal_titan;
-static int mf_initialized;
-
static unsigned long cmd_mem_limit;
struct MemoryBlock {
@@ -347,8 +345,6 @@ static void __init iSeries_init_early(vo
HvCallEvent_setLpEventQueueInterruptProc(0, 0);
mf_init();
- mf_initialized = 1;
- mb();
/* If we were passed an initrd, set the ROOT_DEV properly if the values
* look sensible. If not, clear initrd reference.
@@ -585,12 +581,7 @@ static void iSeries_halt(void)
static void __init iSeries_progress(char * st, unsigned short code)
{
printk("Progress: [%04x] - %s\n", (unsigned)code, st);
- if (!piranha_simulator && mf_initialized) {
- if (code != 0xffff)
- mf_display_progress(code);
- else
- mf_clear_src();
- }
+ mf_display_progress(code);
}
static void __init iSeries_fixup_klimit(void)
Index: to-merge/include/asm-powerpc/iseries/mf.h
===================================================================
--- to-merge.orig/include/asm-powerpc/iseries/mf.h
+++ to-merge/include/asm-powerpc/iseries/mf.h
@@ -45,7 +45,6 @@ extern void mf_reboot(void);
extern void mf_display_src(u32 word);
extern void mf_display_progress(u16 value);
-extern void mf_clear_src(void);
extern void mf_init(void);
^ permalink raw reply
* [PATCH 4/11] powerpc: Replace platform_is_lpar() with a firmware feature
From: Michael Ellerman @ 2006-03-21 9:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
It has been decreed that platform numbers are evil, so as a step in that
direction, replace platform_is_lpar() with a FW_FEATURE_LPAR bit.
Currently FW_FEATURE_LPAR really means i/pSeries LPAR, in the future we might
have to clean that up if we need to be more specific about what LPAR actually
means. But that's another patch ...
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/mm/hash_utils_64.c | 4 ++--
arch/powerpc/oprofile/op_model_power4.c | 3 ++-
arch/powerpc/platforms/iseries/setup.c | 10 +++++++---
arch/powerpc/platforms/pseries/iommu.c | 2 +-
arch/powerpc/platforms/pseries/setup.c | 11 +++++++----
arch/powerpc/platforms/pseries/smp.c | 2 +-
arch/powerpc/platforms/pseries/xics.c | 3 ++-
include/asm-powerpc/firmware.h | 7 ++++---
include/asm-powerpc/processor.h | 1 -
9 files changed, 26 insertions(+), 17 deletions(-)
Index: to-merge/arch/powerpc/mm/hash_utils_64.c
===================================================================
--- to-merge.orig/arch/powerpc/mm/hash_utils_64.c
+++ to-merge/arch/powerpc/mm/hash_utils_64.c
@@ -422,7 +422,7 @@ void __init htab_initialize(void)
htab_hash_mask = pteg_count - 1;
- if (platform_is_lpar()) {
+ if (firmware_has_feature(FW_FEATURE_LPAR)) {
/* Using a hypervisor which owns the htab */
htab_address = NULL;
_SDR1 = 0;
@@ -517,7 +517,7 @@ void __init htab_initialize(void)
void htab_initialize_secondary(void)
{
- if (!platform_is_lpar())
+ if (!firmware_has_feature(FW_FEATURE_LPAR))
mtspr(SPRN_SDR1, _SDR1);
}
Index: to-merge/arch/powerpc/oprofile/op_model_power4.c
===================================================================
--- to-merge.orig/arch/powerpc/oprofile/op_model_power4.c
+++ to-merge/arch/powerpc/oprofile/op_model_power4.c
@@ -10,6 +10,7 @@
#include <linux/oprofile.h>
#include <linux/init.h>
#include <linux/smp.h>
+#include <asm/firmware.h>
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/processor.h>
@@ -232,7 +233,7 @@ static unsigned long get_pc(struct pt_re
mmcra = mfspr(SPRN_MMCRA);
/* Were we in the hypervisor? */
- if (platform_is_lpar() && (mmcra & MMCRA_SIHV))
+ if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & MMCRA_SIHV))
/* function descriptor madness */
return *((unsigned long *)hypervisor_bucket);
Index: to-merge/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/setup.c
+++ to-merge/arch/powerpc/platforms/iseries/setup.c
@@ -303,8 +303,6 @@ static void __init iSeries_init_early(vo
{
DBG(" -> iSeries_init_early()\n");
- ppc64_firmware_features = FW_FEATURE_ISERIES;
-
ppc64_interrupt_controller = IC_ISERIES;
#if defined(CONFIG_BLK_DEV_INITRD)
@@ -711,7 +709,13 @@ void __init iSeries_init_IRQ(void) { }
static int __init iseries_probe(int platform)
{
- return PLATFORM_ISERIES_LPAR == platform;
+ if (PLATFORM_ISERIES_LPAR != platform)
+ return 0;
+
+ ppc64_firmware_features |= FW_FEATURE_ISERIES;
+ ppc64_firmware_features |= FW_FEATURE_LPAR;
+
+ return 1;
}
struct machdep_calls __initdata iseries_md = {
Index: to-merge/arch/powerpc/platforms/pseries/iommu.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/pseries/iommu.c
+++ to-merge/arch/powerpc/platforms/pseries/iommu.c
@@ -580,7 +580,7 @@ void iommu_init_early_pSeries(void)
return;
}
- if (platform_is_lpar()) {
+ if (firmware_has_feature(FW_FEATURE_LPAR)) {
if (firmware_has_feature(FW_FEATURE_MULTITCE)) {
ppc_md.tce_build = tce_buildmulti_pSeriesLP;
ppc_md.tce_free = tce_freemulti_pSeriesLP;
Index: to-merge/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/pseries/setup.c
+++ to-merge/arch/powerpc/platforms/pseries/setup.c
@@ -246,7 +246,7 @@ static void __init pSeries_setup_arch(vo
ppc_md.idle_loop = default_idle;
}
- if (platform_is_lpar())
+ if (firmware_has_feature(FW_FEATURE_LPAR))
ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
else
ppc_md.enable_pmcs = power4_enable_pmcs;
@@ -324,12 +324,12 @@ static void __init pSeries_init_early(vo
fw_feature_init();
- if (platform_is_lpar())
+ if (firmware_has_feature(FW_FEATURE_LPAR))
hpte_init_lpar();
else
hpte_init_native();
- if (platform_is_lpar())
+ if (firmware_has_feature(FW_FEATURE_LPAR))
find_udbg_vterm();
if (firmware_has_feature(FW_FEATURE_DABR))
@@ -385,6 +385,9 @@ static int __init pSeries_probe(int plat
* it here ...
*/
+ if (platform == PLATFORM_PSERIES_LPAR)
+ ppc64_firmware_features |= FW_FEATURE_LPAR;
+
return 1;
}
@@ -524,7 +527,7 @@ static void pseries_shared_idle(void)
static int pSeries_pci_probe_mode(struct pci_bus *bus)
{
- if (platform_is_lpar())
+ if (firmware_has_feature(FW_FEATURE_LPAR))
return PCI_PROBE_DEVTREE;
return PCI_PROBE_NORMAL;
}
Index: to-merge/arch/powerpc/platforms/pseries/smp.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/pseries/smp.c
+++ to-merge/arch/powerpc/platforms/pseries/smp.c
@@ -443,7 +443,7 @@ void __init smp_init_pSeries(void)
smp_ops->cpu_die = pSeries_cpu_die;
/* Processors can be added/removed only on LPAR */
- if (platform_is_lpar())
+ if (firmware_has_feature(FW_FEATURE_LPAR))
pSeries_reconfig_notifier_register(&pSeries_smp_nb);
#endif
Index: to-merge/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/pseries/xics.c
+++ to-merge/arch/powerpc/platforms/pseries/xics.c
@@ -20,6 +20,7 @@
#include <linux/gfp.h>
#include <linux/radix-tree.h>
#include <linux/cpu.h>
+#include <asm/firmware.h>
#include <asm/prom.h>
#include <asm/io.h>
#include <asm/pgtable.h>
@@ -536,7 +537,7 @@ nextnode:
of_node_put(np);
}
- if (platform_is_lpar())
+ if (firmware_has_feature(FW_FEATURE_LPAR))
ops = &pSeriesLP_ops;
else {
#ifdef CONFIG_SMP
Index: to-merge/include/asm-powerpc/firmware.h
===================================================================
--- to-merge.orig/include/asm-powerpc/firmware.h
+++ to-merge/include/asm-powerpc/firmware.h
@@ -41,6 +41,7 @@
#define FW_FEATURE_MULTITCE (1UL<<19)
#define FW_FEATURE_SPLPAR (1UL<<20)
#define FW_FEATURE_ISERIES (1UL<<21)
+#define FW_FEATURE_LPAR (1UL<<22)
enum {
#ifdef CONFIG_PPC64
@@ -51,10 +52,10 @@ enum {
FW_FEATURE_MIGRATE | FW_FEATURE_PERFMON | FW_FEATURE_CRQ |
FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN |
FW_FEATURE_BULK | FW_FEATURE_XDABR | FW_FEATURE_MULTITCE |
- FW_FEATURE_SPLPAR,
+ FW_FEATURE_SPLPAR | FW_FEATURE_LPAR,
FW_FEATURE_PSERIES_ALWAYS = 0,
- FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES,
- FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES,
+ FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
+ FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
FW_FEATURE_POSSIBLE =
#ifdef CONFIG_PPC_PSERIES
FW_FEATURE_PSERIES_POSSIBLE |
Index: to-merge/include/asm-powerpc/processor.h
===================================================================
--- to-merge.orig/include/asm-powerpc/processor.h
+++ to-merge/include/asm-powerpc/processor.h
@@ -52,7 +52,6 @@
#ifdef __KERNEL__
#define platform_is_pseries() (_machine == PLATFORM_PSERIES || \
_machine == PLATFORM_PSERIES_LPAR)
-#define platform_is_lpar() (!!(_machine & PLATFORM_LPAR))
#if defined(CONFIG_PPC_MULTIPLATFORM)
extern int _machine;
^ permalink raw reply
* [PATCH 3/11] powerpc: trivial: Cleanup whitespace in cputable.h
From: Michael Ellerman @ 2006-03-21 9:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
Remove redundant whitespace in include/asm-powerpc/cputable.h
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
include/asm-powerpc/cputable.h | 34 +++++++++++++++++-----------------
1 files changed, 17 insertions(+), 17 deletions(-)
Index: to-merge/include/asm-powerpc/cputable.h
===================================================================
--- to-merge.orig/include/asm-powerpc/cputable.h
+++ to-merge/include/asm-powerpc/cputable.h
@@ -102,19 +102,19 @@ extern void do_cpu_ftr_fixups(unsigned l
#define CPU_FTR_NEED_COHERENT ASM_CONST(0x0000000000020000)
#define CPU_FTR_NO_BTIC ASM_CONST(0x0000000000040000)
#define CPU_FTR_BIG_PHYS ASM_CONST(0x0000000000080000)
-#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000000000100000)
+#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000000000100000)
#ifdef __powerpc64__
/* Add the 64b processor unique features in the top half of the word */
-#define CPU_FTR_SLB ASM_CONST(0x0000000100000000)
-#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000)
-#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000)
-#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000)
-#define CPU_FTR_IABR ASM_CONST(0x0000002000000000)
-#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000)
+#define CPU_FTR_SLB ASM_CONST(0x0000000100000000)
+#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000)
+#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000)
+#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000)
+#define CPU_FTR_IABR ASM_CONST(0x0000002000000000)
+#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000)
#define CPU_FTR_CTRL ASM_CONST(0x0000008000000000)
-#define CPU_FTR_SMT ASM_CONST(0x0000010000000000)
-#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000)
+#define CPU_FTR_SMT ASM_CONST(0x0000010000000000)
+#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000)
#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000)
#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000)
#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0000100000000000)
@@ -123,15 +123,15 @@ extern void do_cpu_ftr_fixups(unsigned l
#else
/* ensure on 32b processors the flags are available for compiling but
* don't do anything */
-#define CPU_FTR_SLB ASM_CONST(0x0)
-#define CPU_FTR_16M_PAGE ASM_CONST(0x0)
-#define CPU_FTR_TLBIEL ASM_CONST(0x0)
-#define CPU_FTR_NOEXECUTE ASM_CONST(0x0)
-#define CPU_FTR_IABR ASM_CONST(0x0)
-#define CPU_FTR_MMCRA ASM_CONST(0x0)
+#define CPU_FTR_SLB ASM_CONST(0x0)
+#define CPU_FTR_16M_PAGE ASM_CONST(0x0)
+#define CPU_FTR_TLBIEL ASM_CONST(0x0)
+#define CPU_FTR_NOEXECUTE ASM_CONST(0x0)
+#define CPU_FTR_IABR ASM_CONST(0x0)
+#define CPU_FTR_MMCRA ASM_CONST(0x0)
#define CPU_FTR_CTRL ASM_CONST(0x0)
-#define CPU_FTR_SMT ASM_CONST(0x0)
-#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0)
+#define CPU_FTR_SMT ASM_CONST(0x0)
+#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0)
#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0)
#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0)
#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0)
^ permalink raw reply
* [PATCH 2/11] powerpc: Remove unused iommu_off logic from pSeries_init_early()
From: Michael Ellerman @ 2006-03-21 9:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
When iommu_init_early_pSeries() was added, ages ago, we forgot to remove
the code that checks /chosen/linux,iommu-off in pSeries_init_early(). We
do it now in iommu_init_early_pSeries().
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/pseries/setup.c | 7 +------
1 files changed, 1 insertion(+), 6 deletions(-)
Index: to-merge/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/pseries/setup.c
+++ to-merge/arch/powerpc/platforms/pseries/setup.c
@@ -320,19 +320,14 @@ static int pseries_set_xdabr(unsigned lo
*/
static void __init pSeries_init_early(void)
{
- int iommu_off = 0;
-
DBG(" -> pSeries_init_early()\n");
fw_feature_init();
if (platform_is_lpar())
hpte_init_lpar();
- else {
+ else
hpte_init_native();
- iommu_off = (of_chosen &&
- get_property(of_chosen, "linux,iommu-off", NULL));
- }
if (platform_is_lpar())
find_udbg_vterm();
^ permalink raw reply
* [PATCH 1/11] powerpc: Unconfuse htab_bolt_mapping() callers
From: Michael Ellerman @ 2006-03-21 9:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
htab_bolt_mapping() takes a vstart and pstart parameter, but all but one of
its callers actually pass it vstart and vstart. Luckily before it passes
paddr (calculated from paddr) to the hpte_insert routines it calls
virt_to_abs() (aka. __pa()) on the address, so there isn't actually a bug.
map_io_page() however does pass pstart properly, so currently it's broken
AFAICT because we're calling __pa(paddr) which will get us something very
large. Presumably no one's calling map_io_page() in the right context.
Anyway, change htab_bolt_mapping() callers to properly pass pstart, and then
use it properly in htab_bolt_mapping(), ie. don't call __pa() on it again.
Booted on p5 LPAR, iSeries and Power3.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/mm/hash_utils_64.c | 27 ++++++++++++++-------------
1 files changed, 14 insertions(+), 13 deletions(-)
Index: to-merge/arch/powerpc/mm/hash_utils_64.c
===================================================================
--- to-merge.orig/arch/powerpc/mm/hash_utils_64.c
+++ to-merge/arch/powerpc/mm/hash_utils_64.c
@@ -169,7 +169,7 @@ int htab_bolt_mapping(unsigned long vsta
#ifdef CONFIG_PPC_ISERIES
if (_machine == PLATFORM_ISERIES_LPAR)
ret = iSeries_hpte_insert(hpteg, va,
- __pa(vaddr),
+ paddr,
tmp_mode,
HPTE_V_BOLTED,
psize);
@@ -178,7 +178,7 @@ int htab_bolt_mapping(unsigned long vsta
#ifdef CONFIG_PPC_PSERIES
if (_machine & PLATFORM_LPAR)
ret = pSeries_lpar_hpte_insert(hpteg, va,
- virt_to_abs(paddr),
+ paddr,
tmp_mode,
HPTE_V_BOLTED,
psize);
@@ -186,7 +186,7 @@ int htab_bolt_mapping(unsigned long vsta
#endif
#ifdef CONFIG_PPC_MULTIPLATFORM
ret = native_hpte_insert(hpteg, va,
- virt_to_abs(paddr),
+ paddr,
tmp_mode, HPTE_V_BOLTED,
psize);
#endif
@@ -392,7 +392,7 @@ static unsigned long __init htab_get_tab
#ifdef CONFIG_MEMORY_HOTPLUG
void create_section_mapping(unsigned long start, unsigned long end)
{
- BUG_ON(htab_bolt_mapping(start, end, start,
+ BUG_ON(htab_bolt_mapping(start, end, __pa(start),
_PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX,
mmu_linear_psize));
}
@@ -473,21 +473,22 @@ void __init htab_initialize(void)
if (dart_tablebase != 0 && dart_tablebase >= base
&& dart_tablebase < (base + size)) {
+ unsigned long dart_table_end = dart_tablebase + 16 * MB;
if (base != dart_tablebase)
BUG_ON(htab_bolt_mapping(base, dart_tablebase,
- base, mode_rw,
- mmu_linear_psize));
- if ((base + size) > (dart_tablebase + 16*MB))
+ __pa(base), mode_rw,
+ mmu_linear_psize));
+ if ((base + size) > dart_table_end)
BUG_ON(htab_bolt_mapping(dart_tablebase+16*MB,
- base + size,
- dart_tablebase+16*MB,
+ base + size,
+ __pa(dart_table_end),
mode_rw,
mmu_linear_psize));
continue;
}
#endif /* CONFIG_U3_DART */
- BUG_ON(htab_bolt_mapping(base, base + size, base,
- mode_rw, mmu_linear_psize));
+ BUG_ON(htab_bolt_mapping(base, base + size, __pa(base),
+ mode_rw, mmu_linear_psize));
}
/*
@@ -504,8 +505,8 @@ void __init htab_initialize(void)
if (base + size >= tce_alloc_start)
tce_alloc_start = base + size + 1;
- BUG_ON(htab_bolt_mapping(tce_alloc_start, tce_alloc_end,
- tce_alloc_start, mode_rw,
+ BUG_ON(htab_bolt_mapping(tce_alloc_start, tce_alloc_end,
+ __pa(tce_alloc_start), mode_rw,
mmu_linear_psize));
}
^ permalink raw reply
* Re: [RFC] powerpc: cell interrupt controller updates
From: Benjamin Herrenschmidt @ 2006-03-21 6:27 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Jens Osterkamp, stk, Milton Miller, Paul Mackerras, hpenner,
linuxppc64-dev
In-Reply-To: <200601180020.17301.arnd@arndb.de>
On Wed, 2006-01-18 at 00:20 +0100, Arnd Bergmann wrote:
> The interrupt-parent relationship between the spider and iic controllers
> is just an approximation, each spider pic can also send interrupts to any
> other interrupt controller in the system (all six of them, if you count
> the SMT threads as separate interrupt targets), but for best performance, it
> is usually wise to use local interrupt delivery.
We could either express that by having a new property that we could call
"multiple-parents" or something like that with a list of parents... or
we could have a "virtual" iic that is a single controller in the
device-tree (the later makes a lot of sense I think) with sub-nodes for
the actual iic's to be used maybe by the iic driver for probing... I
still need to think about that one though..
Ben.
^ permalink raw reply
* [RFC/PATCH] powerpc: Make BUG_ON & WARN_ON play nice with compile-time optimisations
From: Michael Ellerman @ 2006-03-21 5:51 UTC (permalink / raw)
To: Paul Mackerras, linuxppc-dev
In-Reply-To: <200603211445.32454.michael@ellerman.id.au>
Although we could do this. It relys on firmware_has_feature() being a macro,
but perhaps that's ok. This isn't exactly ideal, as it encourages us to use
macros where we could otherwise use static inlines, but perhaps it's ok.
Given this:
void test(void)
{
constant_false();
BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
constant_true();
BUG_ON(!firmware_has_feature(FW_FEATURE_ISERIES));
non_constant();
BUG_ON(firmware_has_feature(FW_FEATURE_SPLPAR));
constant_false();
WARN_ON(firmware_has_feature(FW_FEATURE_ISERIES));
constant_true();
WARN_ON(!firmware_has_feature(FW_FEATURE_ISERIES));
non_constant();
WARN_ON(firmware_has_feature(FW_FEATURE_SPLPAR));
}
I get assembly like so, which looks good to me:
bl .constant_false
bl .constant_true
1: twi 31,0,0
.section __bug_table,"a"
.llong 1b,400,.LC12,__func__.21353
.previous
bl .non_constant
ld 9,.LC13@toc(2)
ld 0,0(9)
rldicl 0,0,44,63
1: tdnei 0,0
.section __bug_table,"a"
.llong 1b,403,.LC12,__func__.21353
.previous
bl .constant_false
bl .constant_true
1: twi 31,0,0
.section __bug_table,"a"
.llong 1b,16777625,.LC12,__func__.21353
.previous
bl .non_constant
ld 9,.LC13@toc(2)
ld 0,0(9)
rldicl 0,0,44,63
1: tdnei 0,0
.section __bug_table,"a"
.llong 1b,16777628,.LC12,__func__.21353
.previous
include/asm-powerpc/bug.h | 24 ++++++++++++++++++++++--
include/asm-powerpc/firmware.h | 8 +++-----
2 files changed, 25 insertions(+), 7 deletions(-)
Index: to-merge/include/asm-powerpc/bug.h
===================================================================
--- to-merge.orig/include/asm-powerpc/bug.h
+++ to-merge/include/asm-powerpc/bug.h
@@ -40,17 +40,36 @@ struct bug_entry *find_bug(unsigned long
} while (0)
#define BUG_ON(x) do { \
- __asm__ __volatile__( \
+ if (__builtin_constant_p(x)) { \
+ if (x) \
+ BUG(); \
+ } else { \
+ __asm__ __volatile__( \
"1: "PPC_TLNEI" %0,0\n" \
".section __bug_table,\"a\"\n" \
"\t"PPC_LONG" 1b,%1,%2,%3\n" \
".previous" \
: : "r" ((long)(x)), "i" (__LINE__), \
"i" (__FILE__), "i" (__FUNCTION__)); \
+ } \
} while (0)
-#define WARN_ON(x) do { \
+#define WARN() do { \
__asm__ __volatile__( \
+ "1: twi 31,0,0\n" \
+ ".section __bug_table,\"a\"\n" \
+ "\t"PPC_LONG" 1b,%0,%1,%2\n" \
+ ".previous" \
+ : : "i" (__LINE__ + BUG_WARNING_TRAP), \
+ "i" (__FILE__), "i" (__FUNCTION__)); \
+} while (0)
+
+#define WARN_ON(x) do { \
+ if (__builtin_constant_p(x)) { \
+ if (x) \
+ WARN(); \
+ } else { \
+ __asm__ __volatile__( \
"1: "PPC_TLNEI" %0,0\n" \
".section __bug_table,\"a\"\n" \
"\t"PPC_LONG" 1b,%1,%2,%3\n" \
@@ -58,6 +77,7 @@ struct bug_entry *find_bug(unsigned long
: : "r" ((long)(x)), \
"i" (__LINE__ + BUG_WARNING_TRAP), \
"i" (__FILE__), "i" (__FUNCTION__)); \
+ } \
} while (0)
#define HAVE_ARCH_BUG
Index: to-merge/include/asm-powerpc/firmware.h
===================================================================
--- to-merge.orig/include/asm-powerpc/firmware.h
+++ to-merge/include/asm-powerpc/firmware.h
@@ -83,11 +83,9 @@ enum {
*/
extern unsigned long ppc64_firmware_features;
-static inline unsigned long firmware_has_feature(unsigned long feature)
-{
- return (FW_FEATURE_ALWAYS & feature) ||
- (FW_FEATURE_POSSIBLE & ppc64_firmware_features & feature);
-}
+#define firmware_has_feature(feature) \
+ ((FW_FEATURE_ALWAYS & (feature)) || \
+ (FW_FEATURE_POSSIBLE & ppc64_firmware_features & (feature)))
extern void system_reset_fwnmi(void);
extern void machine_check_fwnmi(void);
^ permalink raw reply
* Re: [PATCH 5/7] powerpc numa: Consolidate handling of Power4 special case
From: Jon Mason @ 2006-03-21 3:54 UTC (permalink / raw)
To: Nathan Lynch; +Cc: linuxppc-dev
In-Reply-To: <11429013752643-git-send-email-nathanl@austin.ibm.com>
On Mon, Mar 20, 2006 at 06:36:15PM -0600, Nathan Lynch wrote:
> Code to handle Power4's invalid node id (0xffff) is duplicated for cpu
> and memory. Better to handle this case in one place --
> of_node_to_nid. Overall behavior should be unchanged.
>
> Signed-off-by: Nathan Lynch <nathanl@austin.ibm.com>
>
> ---
>
> arch/powerpc/mm/numa.c | 23 +++++++++++------------
> 1 files changed, 11 insertions(+), 12 deletions(-)
>
> d9dd3889e58eeb34d1130d2514fea905ca2cab6a
> diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
> index e511ca1..4a6cbb0 100644
> --- a/arch/powerpc/mm/numa.c
> +++ b/arch/powerpc/mm/numa.c
> @@ -207,6 +207,11 @@ static int of_node_to_nid(struct device_
> device->full_name);
> nid = 0;
> }
> +
> + /* POWER4 LPAR uses 0xffff as invalid node */
> + if (nid == 0xffff)
A #define for 0xffff would make the code much nicer. Something like
POWER4_LPAR_INVALID_NODEID could also enable you to remove the above
comment.
Thanks,
Jon
> + nid = 0;
> +
> return nid;
> }
>
> @@ -297,14 +302,9 @@ static int __cpuinit numa_setup_cpu(unsi
> nid = of_node_to_nid(cpu);
>
> if (nid >= num_online_nodes()) {
> - /*
> - * POWER4 LPAR uses 0xffff as invalid node,
> - * dont warn in this case.
> - */
> - if (nid != 0xffff)
> - printk(KERN_ERR "WARNING: cpu %ld "
> - "maps to invalid NUMA node %d\n",
> - lcpu, nid);
> + printk(KERN_ERR "WARNING: cpu %ld "
> + "maps to invalid NUMA node %d\n",
> + lcpu, nid);
> nid = 0;
> }
> out:
> @@ -442,10 +442,9 @@ new_range:
> nid = of_node_to_nid(memory);
>
> if (nid >= MAX_NUMNODES) {
> - if (nid != 0xffff)
> - printk(KERN_ERR "WARNING: memory at %lx maps "
> - "to invalid NUMA node %d\n", start,
> - nid);
> + printk(KERN_ERR "WARNING: memory at %lx maps "
> + "to invalid NUMA node %d\n", start,
> + nid);
> nid = 0;
> }
>
> --
> 1.2.4
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH] powerpc: Make BUG_ON & WARN_ON play nice with compile-time optimisations
From: Michael Ellerman @ 2006-03-21 3:45 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20060207052220.917C668A92@ozlabs.org>
[-- Attachment #1: Type: text/plain, Size: 1698 bytes --]
On Tue, 7 Feb 2006 16:22, Michael Ellerman wrote:
> Currently if you do BUG_ON(0) you'll still get a trap instruction in your
> object, although it'll never trigger. That's ok, but a bit ugly, it'd be
> nice if the compiler could completely eliminate any trace of the BUG_ON.
>
> So update the BUG_ON & WARN_ON macros to make this possible. From the
> comment in the patch:
>
> The if statement in BUG_ON and WARN_ON gives the compiler a chance to do
> compile-time optimisation and possibly elide the entire block. The check
> for !__builtin_constant(x) has the oppposite effect, if we must do the
> test at runtime then we avoid a spurious compare and branch by ensuring
> the if condition is always true.
>
> I've confirmed it works in both cases, if the condition is false at compile
> time we get no code emitted for the BUG statement. If the condition needs
> to be evaluated at runtime we get the same code we used to, ie. only one
> test in the trap instruction.
Turns out this doesn't always do what we want, depending on what the condition
for the BUG_ON() is. Specifically the __builtin_constant_p() sometimes fails
to recognise that the condition will be constant, and so we end up with:
558: 38 00 00 00 li r0,0
55c: 0b 00 00 00 tdnei r0,0
Which is harmless but not really good enough. When gcc gets fixed
(http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26724) we can think about this
again.
cheers
--
Michael Ellerman
IBM OzLabs
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH] powerpc: Add FSL SEC node to documentation
From: Hollis Blanchard @ 2006-03-21 2:14 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20060320195945.004fdf26.kim.phillips@freescale.com>
On Monday 20 March 2006 19:59, Kim Phillips wrote:
> diff --git a/Documentation/powerpc/booting-without-of.txt=20
b/Documentation/powerpc/booting-without-of.txt
> index d02c649..72f3241 100644
> --- a/Documentation/powerpc/booting-without-of.txt
> +++ b/Documentation/powerpc/booting-without-of.txt
> @@ -1365,6 +1365,79 @@ platforms are moved over to use the flat
> =A0=A0=A0=A0=A0=A0};
> =A0
> =A0
> + =A0 g) Freescale SOC SEC Security Engines
> +
> + =A0 Required properties:
> +
> + =A0 =A0- device_type : Should be "crypto"
> + =A0 =A0- model : Model of the device. =A0Should be "SEC1" or "SEC2"
> + =A0 =A0- compatible : Should be "talitos"
[snip]
Have you consulted with any other vendors regarding these properties? I kno=
w=20
there is no IEEE1275 binding for these sorts of devices, but we can at leas=
t=20
attempt to standardize it (even in the absence of the Open Firmware Working=
=20
Group)...
=2DHollis
^ permalink raw reply
* [PATCH 0/7] powerpc numa updates and fixes
From: Nathan Lynch @ 2006-03-21 0:33 UTC (permalink / raw)
To: linuxppc-dev
The following series has some minor bugfixes and updates for numa for
2.6.17.
Tested on Power4 (lpar and non-) and Power5.
numa.c | 156 +++++++++++++++++++++--------------------------
1 files changed, 72 insertions(+), 84 deletions(-)
^ permalink raw reply
* [PATCH] powerpc: Add FSL SEC node to documentation
From: Kim Phillips @ 2006-03-21 1:59 UTC (permalink / raw)
To: linuxppc-dev
Documentation: Added FSL SOC SEC node definition
Updated the documentation to include the definition of the SEC device
node format for Freescale SOC devices.
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
---
commit 97d971c1d30e77a453cacaef72c32e00381ab02a
tree 4b815caece1c05b33309f8852eeccd90f020ca49
parent c4a1745aa09fc110afdefea0e5d025043e348bae
author Kim Phillips <kim.phillips@freescale.com> Mon, 20 Mar 2006 19:31:21 -0600
committer Kim Phillips <kim.phillips@freescale.com> Mon, 20 Mar 2006 19:31:21 -0600
Documentation/powerpc/booting-without-of.txt | 73 ++++++++++++++++++++++++++
1 files changed, 73 insertions(+), 0 deletions(-)
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index d02c649..72f3241 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -1365,6 +1365,79 @@ platforms are moved over to use the flat
};
+ g) Freescale SOC SEC Security Engines
+
+ Required properties:
+
+ - device_type : Should be "crypto"
+ - model : Model of the device. Should be "SEC1" or "SEC2"
+ - compatible : Should be "talitos"
+ - reg : Offset and length of the register set for the device
+ - interrupts : <a b> where a is the interrupt number and b is a
+ field that represents an encoding of the sense and level
+ information for the interrupt. This should be encoded based on
+ the information in section 2) depending on the type of interrupt
+ controller you have.
+ - interrupt-parent : the phandle for the interrupt controller that
+ services interrupts for this device.
+ - num-channels : An integer representing the number of channels
+ available. Most modern SEC's have 4 channels.
+ - channel-fifo-len : An integer representing the number of descriptor
+ pointers each channel fetch fifo can hold. Most modern SEC channel
+ fetch fifos can hold 24 descriptor pointers.
+ - exec-units-mask : The bitmask representing what execution units (EUs)
+ are available. It's a single 32 bit cell. EU information should be
+ encoded following the SEC's Descriptor Header Dword EU_SEL0 field
+ documentation, i.e. as follows:
+
+ bit 0 = reserved - should be 0
+ bit 1 = set if SEC has the ARC4 EU (AFEU)
+ bit 2 = set if SEC has the DES/3DES EU (DEU)
+ bit 3 = set if SEC has the message digest EU (MDEU)
+ bit 4 = set if SEC has the random number generator EU (RNG)
+ bit 5 = set if SEC has the public key EU (PKEU)
+ bit 6 = set if SEC has the AES EU (AESU)
+ bit 7 = set if SEC has the Kasumi EU (KEU)
+
+ bits 8 through 31 are reserved for future SEC EUs.
+
+ - descriptor-types-mask : The bitmask representing what descriptors
+ are available. It's a single 32 bit cell. Descriptor type information
+ should be encoded as follows:
+
+ bit 0 = set if SEC supports the aesu_ctr_nonsnoop descriptor type
+ bit 1 = set if SEC supports the ipsec_esp descriptor type
+ bit 2 = set if SEC supports the common_nonsnoop descriptor type
+ bit 3 = set if SEC supports the 802.11i AES ccmp descriptor type
+ bit 4 = set if SEC supports the hmac_snoop_no_afeu descriptor type
+ bit 5 = set if SEC supports the srtp descriptor type
+ bit 6 = reserved - should be 0
+ bit 7 = set if SEC supports the pkeu_assemble descriptor type
+ bit 8 = reserved - should be 0
+ bit 9 = set if SEC supports the pkeu_ptmul descriptor type
+ bit 10 = set if SEC supports the common_nonsnoop_afeu descriptor type
+ bit 11 = set if SEC supports the pkeu_ptadd_dbl descriptor type
+
+ ..and so on and so forth, following the SEC's Descriptor Header Dword
+ DESC_TYPE field definition in reference documentation.
+
+ Example:
+
+ /* MPC8548E */
+ crypto@30000 {
+ device_type = "crypto";
+ model = "SEC2";
+ compatible = "talitos";
+ reg = <30000 10000>;
+ interrupts = <1d 3>;
+ interrupt-parent = <40000>;
+ num-channels = <4>;
+ channel-fifo-len = <24>;
+ exec-units-mask = <000000fe>;
+ descriptor-types-mask = <073f1127>;
+ };
+
+
More devices will be defined as this spec matures.
--
^ permalink raw reply related
* [PATCH 1/7] powerpc numa: fix boot_cpuid always assigned to node 0
From: Nathan Lynch @ 2006-03-21 0:34 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nathan Lynch
In-Reply-To: <1142901225978-git-send-email-nathanl@austin.ibm.com>
At boot, the numa code is assigning boot_cpuid to node 0
unconditionally. Basically, numa_setup_cpu is being stupid about it,
but this is the minimal fix -- just call numa_setup_cpu(boot_cpuid)
later, after all nodes have been set online.
Signed-off-by: Nathan Lynch <nathanl@austin.ibm.com>
---
arch/powerpc/mm/numa.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
d5ecb195c3b93cb954264e075c7fe29a0bdc6db7
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 2863a91..b813bad 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -375,7 +375,7 @@ static int __init parse_numa_properties(
{
struct device_node *cpu = NULL;
struct device_node *memory = NULL;
- int max_domain;
+ int max_domain = 0;
unsigned long i;
if (numa_enabled == 0) {
@@ -389,8 +389,6 @@ static int __init parse_numa_properties(
if (min_common_depth < 0)
return min_common_depth;
- max_domain = numa_setup_cpu(boot_cpuid);
-
/*
* Even though we connect cpus to numa domains later in SMP init,
* we need to know the maximum node id now. This is because each
@@ -469,6 +467,8 @@ new_range:
for (i = 0; i <= max_domain; i++)
node_set_online(i);
+ max_domain = numa_setup_cpu(boot_cpuid);
+
return 0;
}
--
1.2.4
^ permalink raw reply related
* [PATCH 5/7] powerpc numa: Consolidate handling of Power4 special case
From: Nathan Lynch @ 2006-03-21 0:36 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nathan Lynch
In-Reply-To: <1142901225978-git-send-email-nathanl@austin.ibm.com>
Code to handle Power4's invalid node id (0xffff) is duplicated for cpu
and memory. Better to handle this case in one place --
of_node_to_nid. Overall behavior should be unchanged.
Signed-off-by: Nathan Lynch <nathanl@austin.ibm.com>
---
arch/powerpc/mm/numa.c | 23 +++++++++++------------
1 files changed, 11 insertions(+), 12 deletions(-)
d9dd3889e58eeb34d1130d2514fea905ca2cab6a
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index e511ca1..4a6cbb0 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -207,6 +207,11 @@ static int of_node_to_nid(struct device_
device->full_name);
nid = 0;
}
+
+ /* POWER4 LPAR uses 0xffff as invalid node */
+ if (nid == 0xffff)
+ nid = 0;
+
return nid;
}
@@ -297,14 +302,9 @@ static int __cpuinit numa_setup_cpu(unsi
nid = of_node_to_nid(cpu);
if (nid >= num_online_nodes()) {
- /*
- * POWER4 LPAR uses 0xffff as invalid node,
- * dont warn in this case.
- */
- if (nid != 0xffff)
- printk(KERN_ERR "WARNING: cpu %ld "
- "maps to invalid NUMA node %d\n",
- lcpu, nid);
+ printk(KERN_ERR "WARNING: cpu %ld "
+ "maps to invalid NUMA node %d\n",
+ lcpu, nid);
nid = 0;
}
out:
@@ -442,10 +442,9 @@ new_range:
nid = of_node_to_nid(memory);
if (nid >= MAX_NUMNODES) {
- if (nid != 0xffff)
- printk(KERN_ERR "WARNING: memory at %lx maps "
- "to invalid NUMA node %d\n", start,
- nid);
+ printk(KERN_ERR "WARNING: memory at %lx maps "
+ "to invalid NUMA node %d\n", start,
+ nid);
nid = 0;
}
--
1.2.4
^ permalink raw reply related
* [PATCH 3/7] powerpc numa: Minor cpu hotplug-related cleanups
From: Nathan Lynch @ 2006-03-21 0:35 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nathan Lynch
In-Reply-To: <1142901225978-git-send-email-nathanl@austin.ibm.com>
map_cpu_to_node does not need to be inline, it is never called in a
hot path.
map_cpu_to_node, numa_setup_cpu, and find_cpu_node can be marked
__cpuinit, as they are never used after boot if CONFIG_HOTPLUG_CPU=n.
Signed-off-by: Nathan Lynch <nathanl@austin.ibm.com>
---
arch/powerpc/mm/numa.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
5685935151d9ed413571e03b8e7c9b4673bd5e88
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index de99e47..1c3df1d 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -129,7 +129,7 @@ void __init get_region(unsigned int nid,
*start_pfn = 0;
}
-static inline void map_cpu_to_node(int cpu, int node)
+static void __cpuinit map_cpu_to_node(int cpu, int node)
{
numa_cpu_lookup_table[cpu] = node;
@@ -155,7 +155,7 @@ static void unmap_cpu_from_node(unsigned
}
#endif /* CONFIG_HOTPLUG_CPU */
-static struct device_node *find_cpu_node(unsigned int cpu)
+static struct device_node * __cpuinit find_cpu_node(unsigned int cpu)
{
unsigned int hw_cpuid = get_hard_smp_processor_id(cpu);
struct device_node *cpu_node = NULL;
@@ -284,7 +284,7 @@ static unsigned long __devinit read_n_ce
* Figure out to which domain a cpu belongs and stick it there.
* Return the id of the domain used.
*/
-static int numa_setup_cpu(unsigned long lcpu)
+static int __cpuinit numa_setup_cpu(unsigned long lcpu)
{
int numa_domain = 0;
struct device_node *cpu = find_cpu_node(lcpu);
--
1.2.4
^ permalink raw reply related
* [PATCH 6/7] powerpc numa: Support sparse online node map
From: Nathan Lynch @ 2006-03-21 0:36 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nathan Lynch
In-Reply-To: <1142901225978-git-send-email-nathanl@austin.ibm.com>
The powerpc numa code unconditionally onlines all nodes from 0 to the
highest node id found, regardless of whether cpus or memory are
present in the nodes. This wastes 8K per node and complicates some
cpu and memory hotplug situations, such as adding a resource that
doesn't map to one of the nodes discovered at boot.
Set nodes online as resources are scanned. Fall back to node 0 only
when we're sure this isn't a NUMA machine.
Instead of defaulting to node 0 for cases of hot-adding a resource
which doesn't belong to any initialized node, assign it to the first
online node.
Signed-off-by: Nathan Lynch <nathanl@austin.ibm.com>
---
arch/powerpc/mm/numa.c | 95 ++++++++++++++++++++++--------------------------
1 files changed, 43 insertions(+), 52 deletions(-)
d49f5d199a1939ebf55c9554caf78fbe7e32c598
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 4a6cbb0..fe0ee6d 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -191,27 +191,28 @@ static int *of_get_associativity(struct
return (unsigned int *)get_property(dev, "ibm,associativity", NULL);
}
+/* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa
+ * info is found.
+ */
static int of_node_to_nid(struct device_node *device)
{
- int nid;
+ int nid = -1;
unsigned int *tmp;
if (min_common_depth == -1)
- return 0;
+ goto out;
tmp = of_get_associativity(device);
- if (tmp && (tmp[0] >= min_common_depth)) {
+ if (!tmp)
+ goto out;
+
+ if (tmp[0] >= min_common_depth)
nid = tmp[min_common_depth];
- } else {
- dbg("WARNING: no NUMA information for %s\n",
- device->full_name);
- nid = 0;
- }
/* POWER4 LPAR uses 0xffff as invalid node */
- if (nid == 0xffff)
- nid = 0;
-
+ if (nid == 0xffff || nid >= MAX_NUMNODES)
+ nid = -1;
+out:
return nid;
}
@@ -301,15 +302,9 @@ static int __cpuinit numa_setup_cpu(unsi
nid = of_node_to_nid(cpu);
- if (nid >= num_online_nodes()) {
- printk(KERN_ERR "WARNING: cpu %ld "
- "maps to invalid NUMA node %d\n",
- lcpu, nid);
- nid = 0;
- }
+ if (nid < 0 || !node_online(nid))
+ nid = any_online_node(NODE_MASK_ALL);
out:
- node_set_online(nid);
-
map_cpu_to_node(lcpu, nid);
of_node_put(cpu);
@@ -376,7 +371,7 @@ static int __init parse_numa_properties(
{
struct device_node *cpu = NULL;
struct device_node *memory = NULL;
- int max_domain = 0;
+ int default_nid = 0;
unsigned long i;
if (numa_enabled == 0) {
@@ -392,25 +387,26 @@ static int __init parse_numa_properties(
dbg("NUMA associativity depth for CPU/Memory: %d\n", min_common_depth);
/*
- * Even though we connect cpus to numa domains later in SMP init,
- * we need to know the maximum node id now. This is because each
- * node id must have NODE_DATA etc backing it.
- * As a result of hotplug we could still have cpus appear later on
- * with larger node ids. In that case we force the cpu into node 0.
+ * Even though we connect cpus to numa domains later in SMP
+ * init, we need to know the node ids now. This is because
+ * each node to be onlined must have NODE_DATA etc backing it.
*/
- for_each_cpu(i) {
+ for_each_present_cpu(i) {
int nid;
cpu = find_cpu_node(i);
+ BUG_ON(!cpu);
+ nid = of_node_to_nid(cpu);
+ of_node_put(cpu);
- if (cpu) {
- nid = of_node_to_nid(cpu);
- of_node_put(cpu);
-
- if (nid < MAX_NUMNODES &&
- max_domain < nid)
- max_domain = nid;
- }
+ /*
+ * Don't fall back to default_nid yet -- we will plug
+ * cpus into nodes once the memory scan has discovered
+ * the topology.
+ */
+ if (nid < 0)
+ continue;
+ node_set_online(nid);
}
get_n_mem_cells(&n_mem_addr_cells, &n_mem_size_cells);
@@ -439,17 +435,15 @@ new_range:
start = read_n_cells(n_mem_addr_cells, &memcell_buf);
size = read_n_cells(n_mem_size_cells, &memcell_buf);
+ /*
+ * Assumption: either all memory nodes or none will
+ * have associativity properties. If none, then
+ * everything goes to default_nid.
+ */
nid = of_node_to_nid(memory);
-
- if (nid >= MAX_NUMNODES) {
- printk(KERN_ERR "WARNING: memory at %lx maps "
- "to invalid NUMA node %d\n", start,
- nid);
- nid = 0;
- }
-
- if (max_domain < nid)
- max_domain = nid;
+ if (nid < 0)
+ nid = default_nid;
+ node_set_online(nid);
if (!(size = numa_enforce_memory_limit(start, size))) {
if (--ranges)
@@ -465,10 +459,7 @@ new_range:
goto new_range;
}
- for (i = 0; i <= max_domain; i++)
- node_set_online(i);
-
- max_domain = numa_setup_cpu(boot_cpuid);
+ numa_setup_cpu(boot_cpuid);
return 0;
}
@@ -768,10 +759,10 @@ int hot_add_scn_to_nid(unsigned long scn
{
struct device_node *memory = NULL;
nodemask_t nodes;
- int nid = 0;
+ int default_nid = any_online_node(NODE_MASK_ALL);
if (!numa_enabled || (min_common_depth < 0))
- return nid;
+ return default_nid;
while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
unsigned long start, size;
@@ -791,8 +782,8 @@ ha_new_range:
nid = of_node_to_nid(memory);
/* Domains not present at boot default to 0 */
- if (!node_online(nid))
- nid = any_online_node(NODE_MASK_ALL);
+ if (nid < 0 || !node_online(nid))
+ nid = default_nid;
if ((scn_addr >= start) && (scn_addr < (start + size))) {
of_node_put(memory);
--
1.2.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox