diff options
author | Brice Goglin <brice@myri.com> | 2007-02-21 12:05:17 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-02-27 04:16:04 -0500 |
commit | 9dc6f0e789ac8cdd4a7912a9c27027d937a6e784 (patch) | |
tree | 57308095e448d1642c678e9acd63bf0633d5470b /drivers/net/myri10ge/myri10ge.c | |
parent | b1adf031a1325bd85eef0313e42d0189d89cece0 (diff) |
myri10ge: workaround buggy adopted firmwares
Work around a bug which occurs when adopting firmware versions
1.4.4 though 1.4.11 where broadcasts are filtered as if they
were multicasts.
Signed-off-by: Brice Goglin <brice@myri.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/myri10ge/myri10ge.c')
-rw-r--r-- | drivers/net/myri10ge/myri10ge.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 030924fb1ab3..954842e85ab9 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
@@ -195,6 +195,10 @@ struct myri10ge_priv { | |||
195 | char *fw_name; | 195 | char *fw_name; |
196 | char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE]; | 196 | char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE]; |
197 | char fw_version[128]; | 197 | char fw_version[128]; |
198 | int fw_ver_major; | ||
199 | int fw_ver_minor; | ||
200 | int fw_ver_tiny; | ||
201 | int adopted_rx_filter_bug; | ||
198 | u8 mac_addr[6]; /* eeprom mac address */ | 202 | u8 mac_addr[6]; /* eeprom mac address */ |
199 | unsigned long serial_number; | 203 | unsigned long serial_number; |
200 | int vendor_specific_offset; | 204 | int vendor_specific_offset; |
@@ -447,7 +451,6 @@ myri10ge_validate_firmware(struct myri10ge_priv *mgp, | |||
447 | struct mcp_gen_header *hdr) | 451 | struct mcp_gen_header *hdr) |
448 | { | 452 | { |
449 | struct device *dev = &mgp->pdev->dev; | 453 | struct device *dev = &mgp->pdev->dev; |
450 | int major, minor; | ||
451 | 454 | ||
452 | /* check firmware type */ | 455 | /* check firmware type */ |
453 | if (ntohl(hdr->mcp_type) != MCP_TYPE_ETH) { | 456 | if (ntohl(hdr->mcp_type) != MCP_TYPE_ETH) { |
@@ -458,9 +461,11 @@ myri10ge_validate_firmware(struct myri10ge_priv *mgp, | |||
458 | /* save firmware version for ethtool */ | 461 | /* save firmware version for ethtool */ |
459 | strncpy(mgp->fw_version, hdr->version, sizeof(mgp->fw_version)); | 462 | strncpy(mgp->fw_version, hdr->version, sizeof(mgp->fw_version)); |
460 | 463 | ||
461 | sscanf(mgp->fw_version, "%d.%d", &major, &minor); | 464 | sscanf(mgp->fw_version, "%d.%d.%d", &mgp->fw_ver_major, |
465 | &mgp->fw_ver_minor, &mgp->fw_ver_tiny); | ||
462 | 466 | ||
463 | if (!(major == MXGEFW_VERSION_MAJOR && minor == MXGEFW_VERSION_MINOR)) { | 467 | if (!(mgp->fw_ver_major == MXGEFW_VERSION_MAJOR |
468 | && mgp->fw_ver_minor == MXGEFW_VERSION_MINOR)) { | ||
464 | dev_err(dev, "Found firmware version %s\n", mgp->fw_version); | 469 | dev_err(dev, "Found firmware version %s\n", mgp->fw_version); |
465 | dev_err(dev, "Driver needs %d.%d\n", MXGEFW_VERSION_MAJOR, | 470 | dev_err(dev, "Driver needs %d.%d\n", MXGEFW_VERSION_MAJOR, |
466 | MXGEFW_VERSION_MINOR); | 471 | MXGEFW_VERSION_MINOR); |
@@ -561,6 +566,18 @@ static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp) | |||
561 | memcpy_fromio(hdr, mgp->sram + hdr_offset, bytes); | 566 | memcpy_fromio(hdr, mgp->sram + hdr_offset, bytes); |
562 | status = myri10ge_validate_firmware(mgp, hdr); | 567 | status = myri10ge_validate_firmware(mgp, hdr); |
563 | kfree(hdr); | 568 | kfree(hdr); |
569 | |||
570 | /* check to see if adopted firmware has bug where adopting | ||
571 | * it will cause broadcasts to be filtered unless the NIC | ||
572 | * is kept in ALLMULTI mode */ | ||
573 | if (mgp->fw_ver_major == 1 && mgp->fw_ver_minor == 4 && | ||
574 | mgp->fw_ver_tiny >= 4 && mgp->fw_ver_tiny <= 11) { | ||
575 | mgp->adopted_rx_filter_bug = 1; | ||
576 | dev_warn(dev, "Adopting fw %d.%d.%d: " | ||
577 | "working around rx filter bug\n", | ||
578 | mgp->fw_ver_major, mgp->fw_ver_minor, | ||
579 | mgp->fw_ver_tiny); | ||
580 | } | ||
564 | return status; | 581 | return status; |
565 | } | 582 | } |
566 | 583 | ||
@@ -794,6 +811,8 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) | |||
794 | status = myri10ge_update_mac_address(mgp, mgp->dev->dev_addr); | 811 | status = myri10ge_update_mac_address(mgp, mgp->dev->dev_addr); |
795 | myri10ge_change_promisc(mgp, 0, 0); | 812 | myri10ge_change_promisc(mgp, 0, 0); |
796 | myri10ge_change_pause(mgp, mgp->pause); | 813 | myri10ge_change_pause(mgp, mgp->pause); |
814 | if (mgp->adopted_rx_filter_bug) | ||
815 | (void)myri10ge_send_cmd(mgp, MXGEFW_ENABLE_ALLMULTI, &cmd, 1); | ||
797 | return status; | 816 | return status; |
798 | } | 817 | } |
799 | 818 | ||
@@ -2239,7 +2258,7 @@ static void myri10ge_set_multicast_list(struct net_device *dev) | |||
2239 | myri10ge_change_promisc(mgp, dev->flags & IFF_PROMISC, 1); | 2258 | myri10ge_change_promisc(mgp, dev->flags & IFF_PROMISC, 1); |
2240 | 2259 | ||
2241 | /* This firmware is known to not support multicast */ | 2260 | /* This firmware is known to not support multicast */ |
2242 | if (!mgp->fw_multicast_support) | 2261 | if (!mgp->fw_multicast_support || mgp->adopted_rx_filter_bug) |
2243 | return; | 2262 | return; |
2244 | 2263 | ||
2245 | /* Disable multicast filtering */ | 2264 | /* Disable multicast filtering */ |