The existing IRQ logic incorrectly indicates cores that have no IRQ
assignment as being assigned to the shared IRQ; this includes setting
the "irq" field in the bcma_device struct to "2". This is evidenced by
output of bcma_core_mips_print_irq, which is as follows:
[ 0.112000] bcma: bus0: Initializing MIPS core...
[ 0.112000] bcma: bus0: Moved i2s interrupt to oob line 7 instead of 8
[ 0.112000] bcma: bus0: set_irq: core 0x0800, irq 2 => 2
[ 0.112000] bcma: bus0: set_irq: core 0x0812, irq 3 => 3
[ 0.112000] bcma: bus0: set_irq: core 0x082d, irq 4 => 4
[ 0.112000] bcma: bus0: set_irq: core 0x0819, irq 5 => 5
[ 0.112000] bcma: bus0: set_irq: core 0x0820, irq 6 => 6
[ 0.112000] bcma: bus0: set_irq: core 0x0834, irq 2 => 2
[ 0.112000] bcma: bus0: IRQ reconfiguration done
[ 0.112000] bcma: core 0x0800, irq : 2(S)* 3 4 5 6 D I
[ 0.112000] bcma: core 0x082c, irq : 2(S)* 3 4 5 6 D I <-- Incorrect
[ 0.112000] bcma: core 0x0812, irq : 2(S) 3* 4 5 6 D I
[ 0.112000] bcma: core 0x082d, irq : 2(S) 3 4* 5 6 D I
[ 0.112000] bcma: core 0x0819, irq : 2(S) 3 4 5* 6 D I
[ 0.112000] bcma: core 0x0820, irq : 2(S) 3 4 5 6* D I
[ 0.112000] bcma: core 0x082e, irq : 2(S)* 3 4 5 6 D I <-- Incorrect
[ 0.112000] bcma: core 0x080e, irq : 2(S)* 3 4 5 6 D I <-- Incorrect
[ 0.112000] bcma: core 0x0834, irq : 2(S)* 3 4 5 6 D I
[ 0.116000] bcma: bus0: PCIEcore in host mode found
This is corrected by the following patch.
v2: Modified the signature of bcma_core_mips_irq to return negative values
as was suggested, and adjusted the logic accordingly. Modified output
of bcma_core_mips_print_irq slightly to accomodate the change. Please
disregard the previous version of this patch (4/4); patches 1 through
3 of the series still apply.
Signed-off-by: Nathan Hintz <[email protected]>
--- /dev/null
+++ target/linux/brcm47xx/patches-3.6/239-bcma-fix-irq-assignment.patch
@@ -0,0 +1,150 @@
+--- a/drivers/bcma/driver_mips.c
++++ b/drivers/bcma/driver_mips.c
+@@ -65,7 +65,10 @@
+ BCMA_MIPS_IPSFLAG_IRQ4_SHIFT,
+ };
+
+-static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
++#define IRQ_FLAG_VALIDITY_MASK 0x80
++#define IRQ_FLAG_MASK 0x1F
++#define EINVALID_IRQ_FLAG 1
++static s32 bcma_core_mips_irqflag(struct bcma_device *dev)
+ {
+ u32 flag;
+
+@@ -75,43 +78,52 @@
+ return dev->core_index;
+ flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
+
+- return flag & 0x1F;
++ if (flag & IRQ_FLAG_VALIDITY_MASK)
++ return (flag & IRQ_FLAG_MASK);
++ else
++ return -EINVALID_IRQ_FLAG;
+ }
+
+ /* Get the MIPS IRQ assignment for a specified device.
+- * If unassigned, 0 is returned.
++ * If unassigned, -1 is returned; if no IRQ is required, -2 is returned
+ */
+-static unsigned int bcma_core_mips_irq(struct bcma_device *dev)
++#define EIRQ_NOT_ASSIGNED 1
++#define EIRQ_NOT_REQUIRED 2
++static int bcma_core_mips_irq(struct bcma_device *dev)
+ {
+ struct bcma_device *mdev = dev->bus->drv_mips.core;
+- u32 irqflag;
+- unsigned int irq;
++ s32 irqflag;
++ int irq;
+
+ irqflag = bcma_core_mips_irqflag(dev);
++ if (irqflag == -EINVALID_IRQ_FLAG)
++ return -EIRQ_NOT_REQUIRED;
+
+- for (irq = 1; irq <= 4; irq++)
++ for (irq = 0; irq <= 4; irq++)
+ if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
+ (1 << irqflag))
+ return irq;
+
+- return 0;
++ return -EIRQ_NOT_ASSIGNED;
+ }
+
+ unsigned int bcma_core_irq(struct bcma_device *dev)
+ {
+- return bcma_core_mips_irq(dev) + 2;
++ int irq = bcma_core_mips_irq(dev);
++ return (irq >= 0) ? (irq + 2) : 0;
+ }
+ EXPORT_SYMBOL(bcma_core_irq);
+
+ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
+ {
+- unsigned int oldirq = bcma_core_mips_irq(dev);
++ int oldirq = bcma_core_mips_irq(dev);
+ struct bcma_bus *bus = dev->bus;
+ struct bcma_device *mdev = bus->drv_mips.core;
+- u32 irqflag;
++ s32 irqflag;
+
+ irqflag = bcma_core_mips_irqflag(dev);
+- BUG_ON(oldirq == 6);
++ if (irqflag == -EINVALID_IRQ_FLAG)
++ return;
+
+ dev->irq = irq + 2;
+
+@@ -120,7 +132,7 @@
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
+ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
+ ~(1 << irqflag));
+- else
++ else if (oldirq > 0)
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0);
+
+ /* assign the new one */
+@@ -129,17 +141,18 @@
+ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
+ (1 << irqflag));
+ } else {
+- u32 oldirqflag = bcma_read32(mdev,
+- BCMA_MIPS_MIPS74K_INTMASK(irq));
+- if (oldirqflag) {
++ u32 intmask = bcma_read32(mdev,
++ BCMA_MIPS_MIPS74K_INTMASK(irq));
++ if (intmask) {
+ struct bcma_device *core;
+
+ /* backplane irq line is in use, find out who uses
+ * it and set user to irq 0
+ */
+ list_for_each_entry(core, &bus->cores, list) {
+- if ((1 << bcma_core_mips_irqflag(core)) ==
+- oldirqflag) {
++ s32 oldirqflag = bcma_core_mips_irqflag(core);
++ if (oldirqflag != -EINVALID_IRQ_FLAG &&
++ (1 << oldirqflag) == intmask) {
+ bcma_core_mips_set_irq(core, 0);
+ break;
+ }
+@@ -150,16 +163,16 @@
+ }
+
+ bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n",
+- dev->id.id, oldirq + 2, irq + 2);
++ dev->id.id, (oldirq >= 0) ? (oldirq + 2) : 0, irq + 2);
+ }
+
+-static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int
irq)
++static void bcma_core_mips_print_irq(struct bcma_device *dev, int irq)
+ {
+ int i;
+- static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
++ static const char *irq_name[] = {"I", "D", "2(S)", "3", "4", "5", "6"};
+ printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
+- for (i = 0; i <= 6; i++)
+- printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
++ for (i = -EIRQ_NOT_REQUIRED; i <= 4; i++)
++ printk(" %s%s", irq_name[i + EIRQ_NOT_REQUIRED], i == irq ? "*"
: " ");
+ printk("\n");
+ }
+
+@@ -294,12 +307,12 @@
+
+ /* Assign IRQs to all cores on the bus */
+ list_for_each_entry(core, &bus->cores, list) {
+- int mips_irq;
+- if (core->irq)
++ int mips_irq = bcma_core_mips_irq(core);
++
++ if (mips_irq == -EIRQ_NOT_REQUIRED || core->irq)
+ continue;
+
+- mips_irq = bcma_core_mips_irq(core);
+- if (mips_irq > 4)
++ if (mips_irq < 0)
+ core->irq = 0;
+ else
+ core->irq = mips_irq + 2;
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel