diff options
author | gallatin <gallatin@FreeBSD.org> | 2007-02-21 17:34:05 +0000 |
---|---|---|
committer | gallatin <gallatin@FreeBSD.org> | 2007-02-21 17:34:05 +0000 |
commit | a5cba253f7c129dcf48fc6203b925b8ec7dad484 (patch) | |
tree | 6ba59864fd6554eebc08fb51894cdd4ef4c6ec97 /sys | |
parent | 0b9339eb2e38480e601c158aa0556e4e7144a7de (diff) | |
download | FreeBSD-src-a5cba253f7c129dcf48fc6203b925b8ec7dad484.zip FreeBSD-src-a5cba253f7c129dcf48fc6203b925b8ec7dad484.tar.gz |
Work around a firmware bug where broadcast frames would be incorrectly
treated as multicast frames and filtered, but when only when "adopting"
running firmware. By "adopting", I mean using pre-existing firmware
loaded from eeprom at PCI reset, rather than firmware loaded by the
driver.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/mxge/if_mxge.c | 28 | ||||
-rw-r--r-- | sys/dev/mxge/if_mxge_var.h | 4 |
2 files changed, 27 insertions, 5 deletions
diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c index 52e64f0..6facddc 100644 --- a/sys/dev/mxge/if_mxge.c +++ b/sys/dev/mxge/if_mxge.c @@ -482,7 +482,7 @@ union qualhack static int mxge_validate_firmware(mxge_softc_t *sc, const mcp_gen_header_t *hdr) { - int major, minor; + if (be32toh(hdr->mcp_type) != MCP_TYPE_ETH) { device_printf(sc->dev, "Bad firmware type: 0x%x\n", @@ -495,10 +495,11 @@ mxge_validate_firmware(mxge_softc_t *sc, const mcp_gen_header_t *hdr) if (mxge_verbose) device_printf(sc->dev, "firmware id: %s\n", hdr->version); - sscanf(sc->fw_version, "%d.%d", &major, &minor); + sscanf(sc->fw_version, "%d.%d.%d", &sc->fw_ver_major, + &sc->fw_ver_minor, &sc->fw_ver_tiny); - if (!(major == MXGEFW_VERSION_MAJOR - && minor == MXGEFW_VERSION_MINOR)) { + if (!(sc->fw_ver_major == MXGEFW_VERSION_MAJOR + && sc->fw_ver_minor == MXGEFW_VERSION_MINOR)) { device_printf(sc->dev, "Found firmware version %s\n", sc->fw_version); device_printf(sc->dev, "Driver needs %d.%d\n", @@ -713,6 +714,21 @@ mxge_adopt_running_firmware(mxge_softc_t *sc) hdr_offset, (char *)hdr, bytes); status = mxge_validate_firmware(sc, hdr); free(hdr, M_DEVBUF); + + /* + * check to see if adopted firmware has bug where adopting + * it will cause broadcasts to be filtered unless the NIC + * is kept in ALLMULTI mode + */ + if (sc->fw_ver_major == 1 && sc->fw_ver_minor == 4 && + sc->fw_ver_tiny >= 4 && sc->fw_ver_tiny <= 11) { + sc->adopted_rx_filter_bug = 1; + device_printf(sc->dev, "Adopting fw %d.%d.%d: " + "working around rx filter bug\n", + sc->fw_ver_major, sc->fw_ver_minor, + sc->fw_ver_tiny); + } + return status; } @@ -875,7 +891,9 @@ mxge_set_multicast_list(mxge_softc_t *sc) " error status: %d\n", err); return; } - + + if (sc->adopted_rx_filter_bug) + return; if (ifp->if_flags & IFF_ALLMULTI) /* request to disable multicast filtering, so quit here */ diff --git a/sys/dev/mxge/if_mxge_var.h b/sys/dev/mxge/if_mxge_var.h index 9b5d3bc..61db27e 100644 --- a/sys/dev/mxge/if_mxge_var.h +++ b/sys/dev/mxge/if_mxge_var.h @@ -153,6 +153,10 @@ typedef struct { char *fw_name; char eeprom_strings[MXGE_EEPROM_STRINGS_SIZE]; char fw_version[128]; + int fw_ver_major; + int fw_ver_minor; + int fw_ver_tiny; + int adopted_rx_filter_bug; device_t dev; struct ifmedia media; int read_dma; |