Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46ba6d7d authored by David S. Miller's avatar David S. Miller
Browse files

[SPARC64]: Fix more of_device layer IRQ bugs, and correct PROMREG_MAX.



Sabre and Psycho PCI controllers can have partial interrupt-map
properties, meaning that on-board devices don't match up to any
entries.  Instead, they are fully specified from the beginning and
we should pass them directly to the IRQ translator as-is.

Also, fill in the necessary translator slots for the "graphics"
and "expansion UPA" interrupts on Sabre, Psycho, and SYSIO SBUS.

Increase PROMREG_MAX to 24, as seen on SUNW,ffb devices.

Finally, prevent accidentally writing past the end of the of_device
struct resource[] and irqs[] arrays.  Spit out a log message when
we ignore some entries because there are too many of them.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 00ab956f
Loading
Loading
Loading
Loading
+32 −2
Original line number Diff line number Diff line
@@ -542,9 +542,17 @@ static void __init build_device_resources(struct of_device *op,
	/* Convert to num-cells.  */
	num_reg /= 4;

	/* Conver to num-entries.  */
	/* Convert to num-entries.  */
	num_reg /= na + ns;

	/* Prevent overruning the op->resources[] array.  */
	if (num_reg > PROMREG_MAX) {
		printk(KERN_WARNING "%s: Too many regs (%d), "
		       "limiting to %d.\n",
		       op->node->full_name, num_reg, PROMREG_MAX);
		num_reg = PROMREG_MAX;
	}

	for (index = 0; index < num_reg; index++) {
		struct resource *r = &op->resource[index];
		u32 addr[OF_MAX_ADDR_CELLS];
@@ -650,8 +658,22 @@ apply_interrupt_map(struct device_node *dp, struct device_node *pp,
	next:
		imap += (na + 3);
	}
	if (i == imlen)
	if (i == imlen) {
		/* Psycho and Sabre PCI controllers can have 'interrupt-map'
		 * properties that do not include the on-board device
		 * interrupts.  Instead, the device's 'interrupts' property
		 * is already a fully specified INO value.
		 *
		 * Handle this by deciding that, if we didn't get a
		 * match in the parent's 'interrupt-map', and the
		 * parent is an IRQ translater, then use the parent as
		 * our IRQ controller.
		 */
		if (pp->irq_trans)
			return pp;

		return NULL;
	}

	*irq_p = irq;
	cp = of_find_node_by_phandle(handle);
@@ -803,6 +825,14 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
		op->num_irqs = 0;
	}

	/* Prevent overruning the op->irqs[] array.  */
	if (op->num_irqs > PROMINTR_MAX) {
		printk(KERN_WARNING "%s: Too many irqs (%d), "
		       "limiting to %d.\n",
		       dp->full_name, op->num_irqs, PROMINTR_MAX);
		op->num_irqs = PROMINTR_MAX;
	}

	build_device_resources(op, parent);
	for (i = 0; i < op->num_irqs; i++)
		op->irqs[i] = build_one_device_irq(op, parent, op->irqs[i]);
+10 −2
Original line number Diff line number Diff line
@@ -344,10 +344,12 @@ static unsigned long __psycho_onboard_imap_off[] = {
/*0x2f*/	PSYCHO_IMAP_CE,
/*0x30*/	PSYCHO_IMAP_A_ERR,
/*0x31*/	PSYCHO_IMAP_B_ERR,
/*0x32*/	PSYCHO_IMAP_PMGMT
/*0x32*/	PSYCHO_IMAP_PMGMT,
/*0x33*/	PSYCHO_IMAP_GFX,
/*0x34*/	PSYCHO_IMAP_EUPA,
};
#define PSYCHO_ONBOARD_IRQ_BASE		0x20
#define PSYCHO_ONBOARD_IRQ_LAST		0x32
#define PSYCHO_ONBOARD_IRQ_LAST		0x34
#define psycho_onboard_imap_offset(__ino) \
	__psycho_onboard_imap_off[(__ino) - PSYCHO_ONBOARD_IRQ_BASE]

@@ -529,6 +531,10 @@ static unsigned long __sabre_onboard_imap_off[] = {
/*0x2e*/	SABRE_IMAP_UE,
/*0x2f*/	SABRE_IMAP_CE,
/*0x30*/	SABRE_IMAP_PCIERR,
/*0x31*/	0 /* reserved */,
/*0x32*/	0 /* reserved */,
/*0x33*/	SABRE_IMAP_GFX,
/*0x34*/	SABRE_IMAP_EUPA,
};
#define SABRE_ONBOARD_IRQ_BASE		0x20
#define SABRE_ONBOARD_IRQ_LAST		0x30
@@ -895,6 +901,8 @@ static unsigned long sysio_irq_offsets[] = {
	SYSIO_IMAP_CE,
	SYSIO_IMAP_SBERR,
	SYSIO_IMAP_PMGMT,
	SYSIO_IMAP_GFX,
	SYSIO_IMAP_EUPA,
};

#undef bogon
+1 −1
Original line number Diff line number Diff line
@@ -175,7 +175,7 @@ struct linux_nodeops {
};

/* More fun PROM structures for device probing. */
#define PROMREG_MAX     16
#define PROMREG_MAX     24
#define PROMVADDR_MAX   16
#define PROMINTR_MAX    15