summaryrefslogtreecommitdiffstats
path: root/hw/net/imx_fec.c
diff options
context:
space:
mode:
authorPeter Maydell2018-03-19 20:20:45 +0100
committerPeter Maydell2018-03-19 20:20:45 +0100
commitc26ef39204f3200efe89470f6b21ac783edadd29 (patch)
tree092ec87be2c37ebc77edf4c5cb59751c78c3839f /hw/net/imx_fec.c
parentMerge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (diff)
parenthw/arm/raspi: Provide spin-loop code for AArch64 CPUs (diff)
downloadqemu-c26ef39204f3200efe89470f6b21ac783edadd29.tar.gz
qemu-c26ef39204f3200efe89470f6b21ac783edadd29.tar.xz
qemu-c26ef39204f3200efe89470f6b21ac783edadd29.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180319' into staging
target-arm queue: * fsl-imx6: Fix incorrect Ethernet interrupt defines * dump: Update correct kdump phys_base field for AArch64 * char: i.MX: Add support for "TX complete" interrupt * bcm2836/raspi: Fix various bugs resulting in panics trying to boot a Debian Linux kernel on raspi3 # gpg: Signature made Mon 19 Mar 2018 18:30:33 GMT # gpg: using RSA key 3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20180319: hw/arm/raspi: Provide spin-loop code for AArch64 CPUs hw/arm/bcm2836: Hardcode correct CPU type hw/arm/bcm2836: Use correct affinity values for BCM2837 hw/arm/bcm2836: Create proper bcm2837 device hw/arm/bcm2836: Rename bcm2836 type/struct to bcm283x hw/arm/bcm2386: Fix parent type of bcm2386 hw/arm/boot: If booting a kernel in EL2, set SCR_EL3.HCE hw/arm/boot: assert that secure_boot and secure_board_setup are false for AArch64 hw/arm/raspi: Don't do board-setup or secure-boot for raspi3 char: i.MX: Add support for "TX complete" interrupt char: i.MX: Simplify imx_update() dump: Update correct kdump phys_base field for AArch64 fsl-imx6: Swap Ethernet interrupt defines Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/net/imx_fec.c')
-rw-r--r--hw/net/imx_fec.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 9506f9b69f..6e297c5480 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -417,7 +417,33 @@ static void imx_enet_write_bd(IMXENETBufDesc *bd, dma_addr_t addr)
static void imx_eth_update(IMXFECState *s)
{
- if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] & ENET_INT_TS_TIMER) {
+ /*
+ * Previous versions of qemu had the ENET_INT_MAC and ENET_INT_TS_TIMER
+ * interrupts swapped. This worked with older versions of Linux (4.14
+ * and older) since Linux associated both interrupt lines with Ethernet
+ * MAC interrupts. Specifically,
+ * - Linux 4.15 and later have separate interrupt handlers for the MAC and
+ * timer interrupts. Those versions of Linux fail with versions of QEMU
+ * with swapped interrupt assignments.
+ * - In linux 4.14, both interrupt lines were registered with the Ethernet
+ * MAC interrupt handler. As a result, all versions of qemu happen to
+ * work, though that is accidental.
+ * - In Linux 4.9 and older, the timer interrupt was registered directly
+ * with the Ethernet MAC interrupt handler. The MAC interrupt was
+ * redirected to a GPIO interrupt to work around erratum ERR006687.
+ * This was implemented using the SOC's IOMUX block. In qemu, this GPIO
+ * interrupt never fired since IOMUX is currently not supported in qemu.
+ * Linux instead received MAC interrupts on the timer interrupt.
+ * As a result, qemu versions with the swapped interrupt assignment work,
+ * albeit accidentally, but qemu versions with the correct interrupt
+ * assignment fail.
+ *
+ * To ensure that all versions of Linux work, generate ENET_INT_MAC
+ * interrrupts on both interrupt lines. This should be changed if and when
+ * qemu supports IOMUX.
+ */
+ if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] &
+ (ENET_INT_MAC | ENET_INT_TS_TIMER)) {
qemu_set_irq(s->irq[1], 1);
} else {
qemu_set_irq(s->irq[1], 0);