diff options
author | Dariusz Swiderski <dms@cvs.openbsd.org> | 2010-03-02 22:09:58 +0000 |
---|---|---|
committer | Dariusz Swiderski <dms@cvs.openbsd.org> | 2010-03-02 22:09:58 +0000 |
commit | 0eb3412bfe7b5053f2a4705348499fbde8221e93 (patch) | |
tree | 700d87afcb949d6bc499b42ef5fd09e657b4a2c7 /sys | |
parent | b9c4e2ed8e8350aa2c6fdbb8e673148e5f0b93a4 (diff) |
Fix support for Intel PRO/1000 QP 82575-based devices. This changes the way
PHY is recognized on 82575 based cards, now they are autodetected.
Patch originaly form Atte Peltomaki, minor changes by me.
ok by sthen@, claudio@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/if_em_hw.c | 100 | ||||
-rw-r--r-- | sys/dev/pci/if_em_hw.h | 10 |
2 files changed, 103 insertions, 7 deletions
diff --git a/sys/dev/pci/if_em_hw.c b/sys/dev/pci/if_em_hw.c index be7a9be4104..db3c4caa44b 100644 --- a/sys/dev/pci/if_em_hw.c +++ b/sys/dev/pci/if_em_hw.c @@ -31,7 +31,7 @@ *******************************************************************************/ -/* $OpenBSD: if_em_hw.c,v 1.45 2010/01/09 22:56:24 dms Exp $ */ +/* $OpenBSD: if_em_hw.c,v 1.46 2010/03/02 22:09:57 dms Exp $ */ /* * if_em_hw.c Shared functions for accessing and configuring the MAC */ @@ -162,6 +162,7 @@ static int32_t em_host_if_read_cookie(struct em_hw *, uint8_t *); static uint8_t em_calculate_mng_checksum(char *, uint32_t); static int32_t em_configure_kmrn_for_10_100(struct em_hw *, uint16_t); static int32_t em_configure_kmrn_for_1000(struct em_hw *); +static int32_t em_set_pciex_completion_timeout(struct em_hw *hw); /* IGP cable length table */ static const uint16_t @@ -639,6 +640,15 @@ em_reset_hw(struct em_hw *hw) DEBUGOUT("PCI-E Master disable polling has failed.\n"); } } + + /* Set the completion timeout for 82575 chips */ + if (hw->mac_type == em_82575) { + ret_val = em_set_pciex_completion_timeout(hw); + if (ret_val) { + DEBUGOUT("PCI-E Set completion timeout has failed.\n"); + } + } + /* Clear interrupt mask to stop board from generating interrupts */ DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, IMC, 0xffffffff); @@ -3859,8 +3869,12 @@ em_read_phy_reg_ex(struct em_hw *hw, uint32_t reg_addr, uint16_t *phy_data) E1000_WRITE_REG(hw, MDIC, mdic); - /* Poll the ready bit to see if the MDI read completed */ - for (i = 0; i < 64; i++) { + /* + * Poll the ready bit to see if the MDI read completed + * Increasing the time out as testing showed failures with + * the lower time out (from FreeBSD driver) + */ + for (i = 0; i < 1960; i++) { usec_delay(50); mdic = E1000_READ_REG(hw, MDIC); if (mdic & E1000_MDIC_READY) @@ -4378,6 +4392,14 @@ em_match_gig_phy(struct em_hw *hw) if (hw->phy_id == BME1000_E_PHY_ID) match = TRUE; break; + case em_82575: + if (hw->phy_id == M88E1000_E_PHY_ID) + match = TRUE; + if (hw->phy_id == IGP01E1000_I_PHY_ID) + match = TRUE; + if (hw->phy_id == IGP03E1000_E_PHY_ID) + match = TRUE; + break; case em_80003es2lan: if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE; @@ -4440,12 +4462,12 @@ em_detect_gig_phy(struct em_hw *hw) * So we explicitly set the PHY values. */ if (hw->mac_type == em_82571 || - hw->mac_type == em_82572 || - hw->mac_type == em_82575) { + hw->mac_type == em_82572) { hw->phy_id = IGP01E1000_I_PHY_ID; hw->phy_type = em_phy_igp_2; return E1000_SUCCESS; } + /* * Some of the fiber cards dont have a phy, so we must exit cleanly * here @@ -4599,7 +4621,6 @@ em_init_eeprom_params(struct em_hw *hw) break; case em_82571: case em_82572: - case em_82575: eeprom->type = em_eeprom_spi; eeprom->opcode_bits = 8; eeprom->delay_usec = 1; @@ -4615,6 +4636,7 @@ em_init_eeprom_params(struct em_hw *hw) break; case em_82573: case em_82574: + case em_82575: eeprom->type = em_eeprom_spi; eeprom->opcode_bits = 8; eeprom->delay_usec = 1; @@ -8792,3 +8814,69 @@ em_init_lcd_from_nvm(struct em_hw *hw) } return E1000_SUCCESS; } + +/****************************************************************************** + * em_set_pciex_completion_timeout - set pci-e completion timeout + * + * The defaults for 82575 and 82576 should be in the range of 50us to 50ms, + * however the hardware default for these parts is 500us to 1ms which is less + * than the 10ms recommended by the pci-e spec. To address this we need to + * increase the value to either 10ms to 200ms for capability version 1 config, + * or 16ms to 55ms for version 2. + * + * * hw - pointer to em_hw structure + *****************************************************************************/ +int32_t +em_set_pciex_completion_timeout(struct em_hw *hw) +{ + uint32_t gcr = E1000_READ_REG(hw, GCR); + int32_t ret_val = E1000_SUCCESS; + + /* Only take action if timeout value is not set by system BIOS */ + if (gcr & E1000_GCR_CMPL_TMOUT_MASK) + goto out; + + DEBUGOUT("PCIe completion timeout not set by system BIOS."); + + /* + * If capababilities version is type 1 we can write the + * timeout of 10ms to 200ms through the GCR register + */ + + if (!(gcr & E1000_GCR_CAP_VER2)) { + gcr |= E1000_GCR_CMPL_TMOUT_10ms; + DEBUGOUT("PCIe capability version 1 detected, setting \ + completion timeout to 10ms."); + goto out; + } + + /* + * For version 2 capabilities we need to write the config space + * directly in order to set the completion timeout value for + * 16ms to 55ms + * + * XXX: Implement em_*_pcie_cap_reg() first. + */ +#if 0 + ret_val = em_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, + &pciex_devctl2); + + if (ret_val) + goto out; + + pciex_devctl2 |= PCIE_DEVICE_CONTROL2_16ms; + + ret_val = em_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, + &pciex_devctl2); +#endif + +out: + + /* Disable completion timeout resend */ + gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND; + + DEBUGOUT("PCIe completion timeout resend disabled."); + + E1000_WRITE_REG(hw, GCR, gcr); + return ret_val; +} diff --git a/sys/dev/pci/if_em_hw.h b/sys/dev/pci/if_em_hw.h index 4511dd2cd88..20bd3ab0816 100644 --- a/sys/dev/pci/if_em_hw.h +++ b/sys/dev/pci/if_em_hw.h @@ -31,7 +31,7 @@ *******************************************************************************/ -/* $OpenBSD: if_em_hw.h,v 1.35 2009/11/25 13:28:13 dms Exp $ */ +/* $OpenBSD: if_em_hw.h,v 1.36 2010/03/02 22:09:57 dms Exp $ */ /* $FreeBSD: if_em_hw.h,v 1.15 2005/05/26 23:32:02 tackerman Exp $ */ /* if_em_hw.h @@ -2238,6 +2238,11 @@ struct em_host_command_info { #define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010 #define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020 +#define E1000_GCR_CMPL_TMOUT_MASK 0x0000F000 +#define E1000_GCR_CMPL_TMOUT_10ms 0x00001000 +#define E1000_GCR_CMPL_TMOUT_RESEND 0x00010000 +#define E1000_GCR_CAP_VER2 0x00040000 + #define PCI_EX_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \ E1000_GCR_RXDSCW_NO_SNOOP | \ E1000_GCR_RXDSCR_NO_SNOOP | \ @@ -2277,6 +2282,9 @@ struct em_host_command_info { #define PCI_EX_LINK_WIDTH_MASK 0x3F0 #define PCI_EX_LINK_WIDTH_SHIFT 4 +#define PCI_EX_DEVICE_CONTROL2 0x28 +#define PCI_EX_DEVICE_CONTROL2_16ms 0x0005 + /* EEPROM Commands - Microwire */ #define EEPROM_READ_OPCODE_MICROWIRE 0x6 /* EEPROM read opcode */ #define EEPROM_WRITE_OPCODE_MICROWIRE 0x5 /* EEPROM write opcode */ |