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.
Note: I did not change the signature of bcma_core_mips_irq to return
negative values; as this would conflict with the printing logic
in bcma_core_mips_print_irq. If you still think I should change
this, that function will need to be updated to accomodate it as
well. The first three patches in this series should be OK to
accept without this change if more updates are required.
Signed-off-by: Nathan Hintz <[email protected]>
--- /dev/null
+++ target/linux/brcm47xx/patches-3.6/239-bcma-fix-irq-assignment.patch
@@ -0,0 +1,131 @@
+--- a/drivers/bcma/driver_mips.c
++++ b/drivers/bcma/driver_mips.c
+@@ -65,7 +65,10 @@ static const u32 ipsflag_irq_shift[] = {
+ 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,31 +78,39 @@ static u32 bcma_core_mips_irqflag(struct
+ 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, 5 is returned; if no IRQ is required, 6 is returned
+ */
++#define IRQ_NOT_ASSIGNED 5
++#define IRQ_NOT_REQUIRED 6
+ static unsigned int bcma_core_mips_irq(struct bcma_device *dev)
+ {
+ struct bcma_device *mdev = dev->bus->drv_mips.core;
+- u32 irqflag;
++ s32 irqflag;
+ unsigned int irq;
+
+ irqflag = bcma_core_mips_irqflag(dev);
++ if (irqflag == -EINVALID_IRQ_FLAG)
++ return IRQ_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 IRQ_NOT_ASSIGNED;
+ }
+
+ unsigned int bcma_core_irq(struct bcma_device *dev)
+ {
+- return bcma_core_mips_irq(dev) + 2;
++ unsigned int irq = bcma_core_mips_irq(dev);
++ return (irq <= 4) ? (irq + 2) : 0;
+ }
+ EXPORT_SYMBOL(bcma_core_irq);
+
+@@ -108,10 +119,11 @@ static void bcma_core_mips_set_irq(struc
+ unsigned 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 @@ static void bcma_core_mips_set_irq(struc
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
+ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
+ ~(1 << irqflag));
+- else
++ else if (oldirq <= 4)
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0);
+
+ /* assign the new one */
+@@ -129,17 +141,18 @@ static void bcma_core_mips_set_irq(struc
+ 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,7 +163,7 @@ static void bcma_core_mips_set_irq(struc
+ }
+
+ bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n",
+- dev->id.id, oldirq + 2, irq + 2);
++ dev->id.id, (oldirq <= 4) ? (oldirq + 2) : 0, irq + 2);
+ }
+
+ static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int
irq)
+@@ -294,11 +307,11 @@ void bcma_core_mips_init(struct bcma_drv
+
+ /* Assign IRQs to all cores on the bus */
+ list_for_each_entry(core, &bus->cores, list) {
+- int mips_irq;
+- if (core->irq)
++ unsigned int mips_irq = bcma_core_mips_irq(core);
++
++ if (mips_irq == IRQ_NOT_REQUIRED || core->irq)
+ continue;
+
+- mips_irq = bcma_core_mips_irq(core);
+ if (mips_irq > 4)
+ core->irq = 0;
+ else
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel