summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorgallatin <gallatin@FreeBSD.org>2007-02-21 17:34:05 +0000
committergallatin <gallatin@FreeBSD.org>2007-02-21 17:34:05 +0000
commita5cba253f7c129dcf48fc6203b925b8ec7dad484 (patch)
tree6ba59864fd6554eebc08fb51894cdd4ef4c6ec97 /sys/dev
parent0b9339eb2e38480e601c158aa0556e4e7144a7de (diff)
downloadFreeBSD-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/dev')
-rw-r--r--sys/dev/mxge/if_mxge.c28
-rw-r--r--sys/dev/mxge/if_mxge_var.h4
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;
OpenPOWER on IntegriCloud