Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc

Pull powerpc updates from Ben Herrenschmidt:
 "Here's the powerpc batch for this merge window.  Some of the
  highlights are:

   - A bunch of endian fixes ! We don't have full LE support yet in that
     release but this contains a lot of fixes all over arch/powerpc to
     use the proper accessors, call the firmware with the right endian
     mode, etc...

   - A few updates to our "powernv" platform (non-virtualized, the one
     to run KVM on), among other, support for bridging the P8 LPC bus
     for UARTs, support and some EEH fixes.

   - Some mpc51xx clock API cleanups in preparation for a clock API
     overhaul

   - A pile of cleanups of our old math emulation code, including better
     support for using it to emulate optional FP instructions on
     embedded chips that otherwise have a HW FPU.

   - Some infrastructure in selftest, for powerpc now, but could be
     generalized, initially used by some tests for our perf instruction
     counting code.

   - A pile of fixes for hotplug on pseries (that was seriously
     bitrotting)

   - The usual slew of freescale embedded updates, new boards, 64-bit
     hiberation support, e6500 core PMU support, etc..."

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (146 commits)
  powerpc: Correct FSCR bit definitions
  powerpc/xmon: Fix printing of set of CPUs in xmon
  powerpc/pseries: Move lparcfg.c to platforms/pseries
  powerpc/powernv: Return secondary CPUs to firmware on kexec
  powerpc/btext: Fix CONFIG_PPC_EARLY_DEBUG_BOOTX on ppc32
  powerpc: Cleanup handling of the DSCR bit in the FSCR register
  powerpc/pseries: Child nodes are not detached by dlpar_detach_node
  powerpc/pseries: Add mising of_node_put in delete_dt_node
  powerpc/pseries: Make dlpar_configure_connector parent node aware
  powerpc/pseries: Do all node initialization in dlpar_parse_cc_node
  powerpc/pseries: Fix parsing of initial node path in update_dt_node
  powerpc/pseries: Pack update_props_workarea to map correctly to rtas buffer header
  powerpc/pseries: Fix over writing of rtas return code in update_dt_node
  powerpc/pseries: Fix creation of loop in device node property list
  powerpc: Skip emulating & leave interrupts off for kernel program checks
  powerpc: Add more exception trampolines for hypervisor exceptions
  powerpc: Fix location and rename exception trampolines
  powerpc: Add more trap names to xmon
  powerpc/pseries: Add a warning in the case of cross-cpu VPA registration
  powerpc: Update the 00-Index in Documentation/powerpc
  ...
This commit is contained in:
Linus Torvalds
2013-09-06 10:49:42 -07:00
192 changed files with 4881 additions and 1775 deletions
+96 -41
View File
@@ -28,6 +28,18 @@
#include "fsl_msi.h"
#include "fsl_pci.h"
#define MSIIR_OFFSET_MASK 0xfffff
#define MSIIR_IBS_SHIFT 0
#define MSIIR_SRS_SHIFT 5
#define MSIIR1_IBS_SHIFT 4
#define MSIIR1_SRS_SHIFT 0
#define MSI_SRS_MASK 0xf
#define MSI_IBS_MASK 0x1f
#define msi_hwirq(msi, msir_index, intr_index) \
((msir_index) << (msi)->srs_shift | \
((intr_index) << (msi)->ibs_shift))
static LIST_HEAD(msi_head);
struct fsl_msi_feature {
@@ -80,18 +92,19 @@ static const struct irq_domain_ops fsl_msi_host_ops = {
static int fsl_msi_init_allocator(struct fsl_msi *msi_data)
{
int rc;
int rc, hwirq;
rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS,
rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS_MAX,
msi_data->irqhost->of_node);
if (rc)
return rc;
rc = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap);
if (rc < 0) {
msi_bitmap_free(&msi_data->bitmap);
return rc;
}
/*
* Reserve all the hwirqs
* The available hwirqs will be released in fsl_msi_setup_hwirq()
*/
for (hwirq = 0; hwirq < NR_MSI_IRQS_MAX; hwirq++)
msi_bitmap_reserve_hwirq(&msi_data->bitmap, hwirq);
return 0;
}
@@ -144,8 +157,9 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
msg->data = hwirq;
pr_debug("%s: allocated srs: %d, ibs: %d\n",
__func__, hwirq / IRQS_PER_MSI_REG, hwirq % IRQS_PER_MSI_REG);
pr_debug("%s: allocated srs: %d, ibs: %d\n", __func__,
(hwirq >> msi_data->srs_shift) & MSI_SRS_MASK,
(hwirq >> msi_data->ibs_shift) & MSI_IBS_MASK);
}
static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
@@ -255,7 +269,7 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
msir_index = cascade_data->index;
if (msir_index >= NR_MSI_REG)
if (msir_index >= NR_MSI_REG_MAX)
cascade_irq = NO_IRQ;
irqd_set_chained_irq_inprogress(idata);
@@ -285,8 +299,8 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
intr_index = ffs(msir_value) - 1;
cascade_irq = irq_linear_revmap(msi_data->irqhost,
msir_index * IRQS_PER_MSI_REG +
intr_index + have_shift);
msi_hwirq(msi_data, msir_index,
intr_index + have_shift));
if (cascade_irq != NO_IRQ)
generic_handle_irq(cascade_irq);
have_shift += intr_index + 1;
@@ -316,7 +330,7 @@ static int fsl_of_msi_remove(struct platform_device *ofdev)
if (msi->list.prev != NULL)
list_del(&msi->list);
for (i = 0; i < NR_MSI_REG; i++) {
for (i = 0; i < NR_MSI_REG_MAX; i++) {
virq = msi->msi_virqs[i];
if (virq != NO_IRQ) {
cascade_data = irq_get_handler_data(virq);
@@ -339,7 +353,7 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev,
int offset, int irq_index)
{
struct fsl_msi_cascade_data *cascade_data = NULL;
int virt_msir;
int virt_msir, i;
virt_msir = irq_of_parse_and_map(dev->dev.of_node, irq_index);
if (virt_msir == NO_IRQ) {
@@ -360,6 +374,11 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev,
irq_set_handler_data(virt_msir, cascade_data);
irq_set_chained_handler(virt_msir, fsl_msi_cascade);
/* Release the hwirqs corresponding to this MSI register */
for (i = 0; i < IRQS_PER_MSI_REG; i++)
msi_bitmap_free_hwirqs(&msi->bitmap,
msi_hwirq(msi, offset, i), 1);
return 0;
}
@@ -368,14 +387,12 @@ static int fsl_of_msi_probe(struct platform_device *dev)
{
const struct of_device_id *match;
struct fsl_msi *msi;
struct resource res;
struct resource res, msiir;
int err, i, j, irq_index, count;
int rc;
const u32 *p;
const struct fsl_msi_feature *features;
int len;
u32 offset;
static const u32 all_avail[] = { 0, NR_MSI_IRQS };
match = of_match_device(fsl_of_msi_ids, &dev->dev);
if (!match)
@@ -392,7 +409,7 @@ static int fsl_of_msi_probe(struct platform_device *dev)
platform_set_drvdata(dev, msi);
msi->irqhost = irq_domain_add_linear(dev->dev.of_node,
NR_MSI_IRQS, &fsl_msi_host_ops, msi);
NR_MSI_IRQS_MAX, &fsl_msi_host_ops, msi);
if (msi->irqhost == NULL) {
dev_err(&dev->dev, "No memory for MSI irqhost\n");
@@ -421,6 +438,16 @@ static int fsl_of_msi_probe(struct platform_device *dev)
}
msi->msiir_offset =
features->msiir_offset + (res.start & 0xfffff);
/*
* First read the MSIIR/MSIIR1 offset from dts
* On failure use the hardcode MSIIR offset
*/
if (of_address_to_resource(dev->dev.of_node, 1, &msiir))
msi->msiir_offset = features->msiir_offset +
(res.start & MSIIR_OFFSET_MASK);
else
msi->msiir_offset = msiir.start & MSIIR_OFFSET_MASK;
}
msi->feature = features->fsl_pic_ip;
@@ -431,42 +458,66 @@ static int fsl_of_msi_probe(struct platform_device *dev)
*/
msi->phandle = dev->dev.of_node->phandle;
rc = fsl_msi_init_allocator(msi);
if (rc) {
err = fsl_msi_init_allocator(msi);
if (err) {
dev_err(&dev->dev, "Error allocating MSI bitmap\n");
goto error_out;
}
p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len);
if (p && len % (2 * sizeof(u32)) != 0) {
dev_err(&dev->dev, "%s: Malformed msi-available-ranges property\n",
__func__);
err = -EINVAL;
goto error_out;
}
if (!p) {
p = all_avail;
len = sizeof(all_avail);
}
if (of_device_is_compatible(dev->dev.of_node, "fsl,mpic-msi-v4.3")) {
msi->srs_shift = MSIIR1_SRS_SHIFT;
msi->ibs_shift = MSIIR1_IBS_SHIFT;
if (p)
dev_warn(&dev->dev, "%s: dose not support msi-available-ranges property\n",
__func__);
for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) {
if (p[i * 2] % IRQS_PER_MSI_REG ||
p[i * 2 + 1] % IRQS_PER_MSI_REG) {
printk(KERN_WARNING "%s: %s: msi available range of %u at %u is not IRQ-aligned\n",
__func__, dev->dev.of_node->full_name,
p[i * 2 + 1], p[i * 2]);
for (irq_index = 0; irq_index < NR_MSI_REG_MSIIR1;
irq_index++) {
err = fsl_msi_setup_hwirq(msi, dev,
irq_index, irq_index);
if (err)
goto error_out;
}
} else {
static const u32 all_avail[] =
{ 0, NR_MSI_REG_MSIIR * IRQS_PER_MSI_REG };
msi->srs_shift = MSIIR_SRS_SHIFT;
msi->ibs_shift = MSIIR_IBS_SHIFT;
if (p && len % (2 * sizeof(u32)) != 0) {
dev_err(&dev->dev, "%s: Malformed msi-available-ranges property\n",
__func__);
err = -EINVAL;
goto error_out;
}
offset = p[i * 2] / IRQS_PER_MSI_REG;
count = p[i * 2 + 1] / IRQS_PER_MSI_REG;
if (!p) {
p = all_avail;
len = sizeof(all_avail);
}
for (j = 0; j < count; j++, irq_index++) {
err = fsl_msi_setup_hwirq(msi, dev, offset + j, irq_index);
if (err)
for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) {
if (p[i * 2] % IRQS_PER_MSI_REG ||
p[i * 2 + 1] % IRQS_PER_MSI_REG) {
pr_warn("%s: %s: msi available range of %u at %u is not IRQ-aligned\n",
__func__, dev->dev.of_node->full_name,
p[i * 2 + 1], p[i * 2]);
err = -EINVAL;
goto error_out;
}
offset = p[i * 2] / IRQS_PER_MSI_REG;
count = p[i * 2 + 1] / IRQS_PER_MSI_REG;
for (j = 0; j < count; j++, irq_index++) {
err = fsl_msi_setup_hwirq(msi, dev, offset + j,
irq_index);
if (err)
goto error_out;
}
}
}
@@ -508,6 +559,10 @@ static const struct of_device_id fsl_of_msi_ids[] = {
.compatible = "fsl,mpic-msi",
.data = &mpic_msi_feature,
},
{
.compatible = "fsl,mpic-msi-v4.3",
.data = &mpic_msi_feature,
},
{
.compatible = "fsl,ipic-msi",
.data = &ipic_msi_feature,
+7 -3
View File
@@ -16,9 +16,11 @@
#include <linux/of.h>
#include <asm/msi_bitmap.h>
#define NR_MSI_REG 8
#define NR_MSI_REG_MSIIR 8 /* MSIIR can index 8 MSI registers */
#define NR_MSI_REG_MSIIR1 16 /* MSIIR1 can index 16 MSI registers */
#define NR_MSI_REG_MAX NR_MSI_REG_MSIIR1
#define IRQS_PER_MSI_REG 32
#define NR_MSI_IRQS (NR_MSI_REG * IRQS_PER_MSI_REG)
#define NR_MSI_IRQS_MAX (NR_MSI_REG_MAX * IRQS_PER_MSI_REG)
#define FSL_PIC_IP_MASK 0x0000000F
#define FSL_PIC_IP_MPIC 0x00000001
@@ -31,9 +33,11 @@ struct fsl_msi {
unsigned long cascade_irq;
u32 msiir_offset; /* Offset of MSIIR, relative to start of CCSR */
u32 ibs_shift; /* Shift of interrupt bit select */
u32 srs_shift; /* Shift of the shared interrupt register select */
void __iomem *msi_regs;
u32 feature;
int msi_virqs[NR_MSI_REG];
int msi_virqs[NR_MSI_REG_MAX];
struct msi_bitmap bitmap;
+163 -21
View File
@@ -26,11 +26,15 @@
#include <linux/memblock.h>
#include <linux/log2.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <asm/ppc-pci.h>
#include <asm/machdep.h>
#include <asm/disassemble.h>
#include <asm/ppc-opcode.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
@@ -64,7 +68,7 @@ static int fsl_pcie_check_link(struct pci_controller *hose)
if (hose->indirect_type & PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) {
if (hose->ops->read == fsl_indirect_read_config) {
struct pci_bus bus;
bus.number = 0;
bus.number = hose->first_busno;
bus.sysdata = hose;
bus.ops = hose->ops;
indirect_read_config(&bus, 0, PCIE_LTSSM, 4, &val);
@@ -297,10 +301,10 @@ static void setup_pci_atmu(struct pci_controller *hose)
if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
/* Size window to exact size if power-of-two or one size up */
if ((1ull << mem_log) != mem) {
mem_log++;
if ((1ull << mem_log) > mem)
pr_info("%s: Setting PCI inbound window "
"greater than memory size\n", name);
mem_log++;
}
piwar |= ((mem_log - 1) & PIWAR_SZ_MASK);
@@ -373,7 +377,9 @@ static void setup_pci_atmu(struct pci_controller *hose)
}
if (hose->dma_window_size < mem) {
#ifndef CONFIG_SWIOTLB
#ifdef CONFIG_SWIOTLB
ppc_swiotlb_enable = 1;
#else
pr_err("%s: ERROR: Memory size exceeds PCI ATMU ability to "
"map - enable CONFIG_SWIOTLB to avoid dma errors.\n",
name);
@@ -868,6 +874,160 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose)
return 0;
}
#ifdef CONFIG_E500
static int mcheck_handle_load(struct pt_regs *regs, u32 inst)
{
unsigned int rd, ra, rb, d;
rd = get_rt(inst);
ra = get_ra(inst);
rb = get_rb(inst);
d = get_d(inst);
switch (get_op(inst)) {
case 31:
switch (get_xop(inst)) {
case OP_31_XOP_LWZX:
case OP_31_XOP_LWBRX:
regs->gpr[rd] = 0xffffffff;
break;
case OP_31_XOP_LWZUX:
regs->gpr[rd] = 0xffffffff;
regs->gpr[ra] += regs->gpr[rb];
break;
case OP_31_XOP_LBZX:
regs->gpr[rd] = 0xff;
break;
case OP_31_XOP_LBZUX:
regs->gpr[rd] = 0xff;
regs->gpr[ra] += regs->gpr[rb];
break;
case OP_31_XOP_LHZX:
case OP_31_XOP_LHBRX:
regs->gpr[rd] = 0xffff;
break;
case OP_31_XOP_LHZUX:
regs->gpr[rd] = 0xffff;
regs->gpr[ra] += regs->gpr[rb];
break;
case OP_31_XOP_LHAX:
regs->gpr[rd] = ~0UL;
break;
case OP_31_XOP_LHAUX:
regs->gpr[rd] = ~0UL;
regs->gpr[ra] += regs->gpr[rb];
break;
default:
return 0;
}
break;
case OP_LWZ:
regs->gpr[rd] = 0xffffffff;
break;
case OP_LWZU:
regs->gpr[rd] = 0xffffffff;
regs->gpr[ra] += (s16)d;
break;
case OP_LBZ:
regs->gpr[rd] = 0xff;
break;
case OP_LBZU:
regs->gpr[rd] = 0xff;
regs->gpr[ra] += (s16)d;
break;
case OP_LHZ:
regs->gpr[rd] = 0xffff;
break;
case OP_LHZU:
regs->gpr[rd] = 0xffff;
regs->gpr[ra] += (s16)d;
break;
case OP_LHA:
regs->gpr[rd] = ~0UL;
break;
case OP_LHAU:
regs->gpr[rd] = ~0UL;
regs->gpr[ra] += (s16)d;
break;
default:
return 0;
}
return 1;
}
static int is_in_pci_mem_space(phys_addr_t addr)
{
struct pci_controller *hose;
struct resource *res;
int i;
list_for_each_entry(hose, &hose_list, list_node) {
if (!(hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG))
continue;
for (i = 0; i < 3; i++) {
res = &hose->mem_resources[i];
if ((res->flags & IORESOURCE_MEM) &&
addr >= res->start && addr <= res->end)
return 1;
}
}
return 0;
}
int fsl_pci_mcheck_exception(struct pt_regs *regs)
{
u32 inst;
int ret;
phys_addr_t addr = 0;
/* Let KVM/QEMU deal with the exception */
if (regs->msr & MSR_GS)
return 0;
#ifdef CONFIG_PHYS_64BIT
addr = mfspr(SPRN_MCARU);
addr <<= 32;
#endif
addr += mfspr(SPRN_MCAR);
if (is_in_pci_mem_space(addr)) {
if (user_mode(regs)) {
pagefault_disable();
ret = get_user(regs->nip, &inst);
pagefault_enable();
} else {
ret = probe_kernel_address(regs->nip, inst);
}
if (mcheck_handle_load(regs, inst)) {
regs->nip += 4;
return 1;
}
}
return 0;
}
#endif
#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
static const struct of_device_id pci_ids[] = {
{ .compatible = "fsl,mpc8540-pci", },
@@ -928,28 +1088,10 @@ static int fsl_pci_probe(struct platform_device *pdev)
{
int ret;
struct device_node *node;
#ifdef CONFIG_SWIOTLB
struct pci_controller *hose;
#endif
node = pdev->dev.of_node;
ret = fsl_add_bridge(pdev, fsl_pci_primary == node);
#ifdef CONFIG_SWIOTLB
if (ret == 0) {
hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
/*
* if we couldn't map all of DRAM via the dma windows
* we need SWIOTLB to handle buffers located outside of
* dma capable memory region
*/
if (memblock_end_of_DRAM() - 1 > hose->dma_window_base_cur +
hose->dma_window_size)
ppc_swiotlb_enable = 1;
}
#endif
mpc85xx_pci_err_probe(pdev);
return 0;
+6
View File
@@ -126,5 +126,11 @@ static inline int mpc85xx_pci_err_probe(struct platform_device *op)
}
#endif
#ifdef CONFIG_FSL_PCI
extern int fsl_pci_mcheck_exception(struct pt_regs *);
#else
static inline int fsl_pci_mcheck_exception(struct pt_regs *regs) {return 0; }
#endif
#endif /* __POWERPC_FSL_PCI_H */
#endif /* __KERNEL__ */
+1 -1
View File
@@ -216,7 +216,7 @@ static int __init icp_native_init_one_node(struct device_node *np,
unsigned int *indx)
{
unsigned int ilen;
const u32 *ireg;
const __be32 *ireg;
int i;
int reg_tuple_size;
int num_servers = 0;
+5 -5
View File
@@ -49,7 +49,7 @@ void xics_update_irq_servers(void)
int i, j;
struct device_node *np;
u32 ilen;
const u32 *ireg;
const __be32 *ireg;
u32 hcpuid;
/* Find the server numbers for the boot cpu. */
@@ -75,8 +75,8 @@ void xics_update_irq_servers(void)
* default distribution server
*/
for (j = 0; j < i; j += 2) {
if (ireg[j] == hcpuid) {
xics_default_distrib_server = ireg[j+1];
if (be32_to_cpu(ireg[j]) == hcpuid) {
xics_default_distrib_server = be32_to_cpu(ireg[j+1]);
break;
}
}
@@ -383,7 +383,7 @@ void __init xics_register_ics(struct ics *ics)
static void __init xics_get_server_size(void)
{
struct device_node *np;
const u32 *isize;
const __be32 *isize;
/* We fetch the interrupt server size from the first ICS node
* we find if any
@@ -394,7 +394,7 @@ static void __init xics_get_server_size(void)
isize = of_get_property(np, "ibm,interrupt-server#-size", NULL);
if (!isize)
return;
xics_interrupt_server_size = *isize;
xics_interrupt_server_size = be32_to_cpu(*isize);
of_node_put(np);
}