lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-ID: <20100510185018.3478bcae@redhat.com> Date: Mon, 10 May 2010 18:50:18 -0600 From: Pete Zaitcev <zaitcev@...hat.com> To: netdev@...r.kernel.org Cc: zaitcev@...hat.com Subject: e1000e fails probe Dear All: I have a box where e1000e would refuse to probe the onboard interface with the following in dmesg: e1000e: Intel(R) PRO/1000 Network Driver - 1.0.2-k2 e1000e: Copyright (c) 1999 - 2009 Intel Corporation. e1000e 0000:00:19.0: PCI INT A -> GSI 20 (level, low) -> IRQ 20 e1000e 0000:00:19.0: setting latency timer to 64 e1000e 0000:00:19.0: irq 34 for MSI/MSI-X 0000:00:19.0: 0000:00:19.0: MDI Error e1000e 0000:00:19.0: PCI INT A disabled e1000e: probe of 0000:00:19.0 failed with error -2 The "MDI Error" seems to indicate a hardware failure, so I paid it no mind until I noticed that RHEL 5 works. So, I diffed the drivers between Linus' 2.6.34-rc5 and RHEL's 2.6.18-180.el5, with the following minimal patch working for me: diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 8b5e157..b97cd9f 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -276,19 +276,21 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) phy->id = e1000_phy_unknown; ret_val = e1000e_get_phy_id(hw); - if (ret_val) - goto out; - if ((phy->id == 0) || (phy->id == PHY_REVISION_MASK)) { +/* P3 */ printk("get_phy_id.fast ret %d id %d\n", ret_val, phy->id); + if (ret_val || (phy->id == 0) || (phy->id == PHY_REVISION_MASK)) { /* * In case the PHY needs to be in mdio slow mode (eg. 82577), * set slow mode and try to get the PHY id again. */ ret_val = e1000_set_mdio_slow_mode_hv(hw); - if (ret_val) - goto out; - ret_val = e1000e_get_phy_id(hw); - if (ret_val) - goto out; + if (ret_val) { +/* P3 */ printk("failed to set mdio slow mode %d\n", ret_val); + phy->id = e1000_phy_unknown; + } else { + ret_val = e1000e_get_phy_id(hw); +/* P3 */ printk("get_phy_id.slow ret %d id %d\n", ret_val, phy->id); + } + ret_val = 0; /* P3 */ } phy->type = e1000e_get_phy_type_from_id(phy->id); @@ -307,11 +309,10 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) phy->ops.get_info = e1000e_get_phy_info_m88; break; default: - ret_val = -E1000_ERR_PHY; +/* P3 */ printk("not doing anything for phy type %d\n", phy->type); break; } -out: return ret_val; } @@ -354,7 +355,10 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) msleep(1); ret_val = e1000e_get_phy_id(hw); if (ret_val) +{ +/* P3 */ printk("get_phy_id for params ret %d id %d\n", ret_val, phy->id); return ret_val; +} } /* Verify phy id */ @@ -777,6 +781,77 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) } /** + * e1000_phy_force_speed_duplex_ich8lan - Force PHY speed & duplex + * @hw: pointer to the HW structure + * + * Forces the speed and duplex settings of the PHY. + * This is a function pointer entry point only called by + * PHY setup routines. + **/ +static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data; + bool link; + + if (phy->type != e1000_phy_ife) { + ret_val = e1000e_phy_force_speed_duplex_igp(hw); + return ret_val; + } + + ret_val = e1e_rphy(hw, PHY_CONTROL, &data); + if (ret_val) + return ret_val; + + e1000e_phy_force_speed_duplex_setup(hw, &data); + + ret_val = e1e_wphy(hw, PHY_CONTROL, data); + if (ret_val) + return ret_val; + + /* Disable MDI-X support for 10/100 */ + ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data); + if (ret_val) + return ret_val; + + data &= ~IFE_PMC_AUTO_MDIX; + data &= ~IFE_PMC_FORCE_MDIX; + + ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, data); + if (ret_val) + return ret_val; + + e_dbg("IFE PMC: %X\n", data); + + udelay(1); + + if (phy->autoneg_wait_to_complete) { + e_dbg("Waiting for forced speed/duplex link on IFE phy.\n"); + + ret_val = e1000e_phy_has_link_generic(hw, + PHY_FORCE_LIMIT, + 100000, + &link); + if (ret_val) + return ret_val; + + if (!link) + e_dbg("Link taking longer than expected.\n"); + + /* Try once more */ + ret_val = e1000e_phy_has_link_generic(hw, + PHY_FORCE_LIMIT, + 100000, + &link); + if (ret_val) + return ret_val; + } + + return 0; +} + +/** * e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration * @hw: pointer to the HW structure * @@ -1273,6 +1348,87 @@ out: } /** + * e1000_get_phy_info_ife_ich8lan - Retrieves various IFE PHY states + * @hw: pointer to the HW structure + * + * Populates "phy" structure with various feature states. + * This function is only called by other family-specific + * routines. + **/ +static s32 e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data; + bool link; + + ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); + if (ret_val) + return ret_val; + + if (!link) { + e_dbg("Phy info is only valid if link is up\n"); + return -E1000_ERR_CONFIG; + } + + ret_val = e1e_rphy(hw, IFE_PHY_SPECIAL_CONTROL, &data); + if (ret_val) + return ret_val; + phy->polarity_correction = (!(data & IFE_PSC_AUTO_POLARITY_DISABLE)); + + if (phy->polarity_correction) { + ret_val = phy->ops.check_polarity(hw); + if (ret_val) + return ret_val; + } else { + /* Polarity is forced */ + phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY) + ? e1000_rev_polarity_reversed + : e1000_rev_polarity_normal; + } + + ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data); + if (ret_val) + return ret_val; + + phy->is_mdix = (data & IFE_PMC_MDIX_STATUS); + + /* The following parameters are undefined for 10/100 operation. */ + phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; + phy->local_rx = e1000_1000t_rx_status_undefined; + phy->remote_rx = e1000_1000t_rx_status_undefined; + + return 0; +} + +/** + * e1000_get_phy_info_ich8lan - Calls appropriate PHY type get_info + * @hw: pointer to the HW structure + * + * Wrapper for calling the get_info routines for the appropriate phy type. + * This is a function pointer entry point called by drivers + * or other shared routines. + **/ +static s32 e1000_get_phy_info_ich8lan(struct e1000_hw *hw) +{ + switch (hw->phy.type) { + case e1000_phy_ife: + return e1000_get_phy_info_ife_ich8lan(hw); + break; + case e1000_phy_igp_3: + case e1000_phy_bm: + case e1000_phy_82578: + case e1000_phy_82577: + return e1000e_get_phy_info_igp(hw); + break; + default: + break; + } + + return -E1000_ERR_PHY_TYPE; +} + +/** * e1000_set_lplu_state_pchlan - Set Low Power Link Up state * @hw: pointer to the HW structure * @active: true to enable LPLU, false to disable @@ -3394,8 +3550,10 @@ static struct e1000_phy_operations ich8_phy_ops = { .acquire = e1000_acquire_swflag_ich8lan, .check_reset_block = e1000_check_reset_block_ich8lan, .commit = NULL, + .force_speed_duplex = e1000_phy_force_speed_duplex_ich8lan, .get_cfg_done = e1000_get_cfg_done_ich8lan, .get_cable_length = e1000e_get_cable_length_igp_2, + .get_info = e1000_get_phy_info_ich8lan, .read_reg = e1000e_read_phy_reg_igp, .release = e1000_release_swflag_ich8lan, .reset = e1000_phy_hw_reset_ich8lan, What seems to be happening here is a persistent failure of e1000e_get_phy_id, in both "slow" and "fast" MDI modes. However, in RHEL 5, this failure triggers a chain of workaround and adjustments that bring up the interface with some default parameters... which appear to work with my 1Gbit/s Netgear switch. So the hardware is not dead, or not completely dead. Could someone come up with a fix here, please? I have no clue where to start even. Greetings, -- Pete -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists