|
|
cd9d16 |
From 461473595d1dd1131cb060c460c87ca7b652939e Mon Sep 17 00:00:00 2001
|
|
|
cd9d16 |
From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
|
|
|
cd9d16 |
Date: Wed, 17 Aug 2011 11:03:14 +0200
|
|
|
cd9d16 |
Subject: [PATCH] e1000: use MII status register for link up/down
|
|
|
cd9d16 |
MIME-Version: 1.0
|
|
|
cd9d16 |
Content-Type: text/plain; charset=UTF-8
|
|
|
cd9d16 |
Content-Transfer-Encoding: 8bit
|
|
|
cd9d16 |
|
|
|
cd9d16 |
Some guests will use the standard MII status register
|
|
|
cd9d16 |
to verify link state. They will not notice link changes
|
|
|
cd9d16 |
unless this register is updated.
|
|
|
cd9d16 |
|
|
|
cd9d16 |
Verified with Linux 3.0 and Windows XP guests.
|
|
|
cd9d16 |
|
|
|
cd9d16 |
Without this patch, ethtool will report speed and duplex as
|
|
|
cd9d16 |
unknown when the link is down, but still report the link as
|
|
|
cd9d16 |
up. This is because the Linux e1000 driver checks the
|
|
|
cd9d16 |
mac_reg[STATUS] register link state before it checks speed
|
|
|
cd9d16 |
and duplex, but uses the phy_reg[PHY_STATUS] register for
|
|
|
cd9d16 |
the actual link state check. Fix by updating both registers
|
|
|
cd9d16 |
on link state changes.
|
|
|
cd9d16 |
|
|
|
cd9d16 |
Linux guest before:
|
|
|
cd9d16 |
|
|
|
cd9d16 |
(qemu) set_link e1000.0 off
|
|
|
cd9d16 |
|
|
|
cd9d16 |
kvm-sid:~# ethtool eth0
|
|
|
cd9d16 |
Settings for eth0:
|
|
|
cd9d16 |
Supported ports: [ TP ]
|
|
|
cd9d16 |
Supported link modes: 10baseT/Half 10baseT/Full
|
|
|
cd9d16 |
100baseT/Half 100baseT/Full
|
|
|
cd9d16 |
1000baseT/Full
|
|
|
cd9d16 |
Supports auto-negotiation: Yes
|
|
|
cd9d16 |
Advertised link modes: 10baseT/Half 10baseT/Full
|
|
|
cd9d16 |
100baseT/Half 100baseT/Full
|
|
|
cd9d16 |
1000baseT/Full
|
|
|
cd9d16 |
Advertised pause frame use: No
|
|
|
cd9d16 |
Advertised auto-negotiation: Yes
|
|
|
cd9d16 |
Speed: Unknown!
|
|
|
cd9d16 |
Duplex: Unknown! (255)
|
|
|
cd9d16 |
Port: Twisted Pair
|
|
|
cd9d16 |
PHYAD: 0
|
|
|
cd9d16 |
Transceiver: internal
|
|
|
cd9d16 |
Auto-negotiation: on
|
|
|
cd9d16 |
MDI-X: Unknown
|
|
|
cd9d16 |
Supports Wake-on: umbg
|
|
|
cd9d16 |
Wake-on: d
|
|
|
cd9d16 |
Current message level: 0x00000007 (7)
|
|
|
cd9d16 |
drv probe link
|
|
|
cd9d16 |
Link detected: yes
|
|
|
cd9d16 |
|
|
|
cd9d16 |
(qemu) set_link e1000.0 on
|
|
|
cd9d16 |
|
|
|
cd9d16 |
Linux guest after:
|
|
|
cd9d16 |
|
|
|
cd9d16 |
(qemu) set_link e1000.0 off
|
|
|
cd9d16 |
[ 63.384221] e1000: eth0 NIC Link is Down
|
|
|
cd9d16 |
|
|
|
cd9d16 |
kvm-sid:~# ethtool eth0
|
|
|
cd9d16 |
Settings for eth0:
|
|
|
cd9d16 |
Supported ports: [ TP ]
|
|
|
cd9d16 |
Supported link modes: 10baseT/Half 10baseT/Full
|
|
|
cd9d16 |
100baseT/Half 100baseT/Full
|
|
|
cd9d16 |
1000baseT/Full
|
|
|
cd9d16 |
Supports auto-negotiation: Yes
|
|
|
cd9d16 |
Advertised link modes: 10baseT/Half 10baseT/Full
|
|
|
cd9d16 |
100baseT/Half 100baseT/Full
|
|
|
cd9d16 |
1000baseT/Full
|
|
|
cd9d16 |
Advertised pause frame use: No
|
|
|
cd9d16 |
Advertised auto-negotiation: Yes
|
|
|
cd9d16 |
Speed: Unknown!
|
|
|
cd9d16 |
Duplex: Unknown! (255)
|
|
|
cd9d16 |
Port: Twisted Pair
|
|
|
cd9d16 |
PHYAD: 0
|
|
|
cd9d16 |
Transceiver: internal
|
|
|
cd9d16 |
Auto-negotiation: on
|
|
|
cd9d16 |
MDI-X: Unknown
|
|
|
cd9d16 |
Supports Wake-on: umbg
|
|
|
cd9d16 |
Wake-on: d
|
|
|
cd9d16 |
Current message level: 0x00000007 (7)
|
|
|
cd9d16 |
drv probe link
|
|
|
cd9d16 |
Link detected: no
|
|
|
cd9d16 |
|
|
|
cd9d16 |
(qemu) set_link e1000.0 on
|
|
|
cd9d16 |
[ 84.304582] e1000: eth0 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX
|
|
|
cd9d16 |
|
|
|
cd9d16 |
Signed-off-by: Bjørn Mork <bjorn@mork.no>
|
|
|
cd9d16 |
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
|
|
cd9d16 |
(cherry picked from commit d4044c2a6b9ba4a00dd653f515a4b0ebfcb7e125)
|
|
|
cd9d16 |
|
|
|
cd9d16 |
Signed-off-by: Andreas Färber <afaerber@suse.de>
|
|
|
cd9d16 |
---
|
|
|
cd9d16 |
hw/e1000.c | 7 +++++--
|
|
|
cd9d16 |
hw/e1000_hw.h | 17 +++++++++++++++++
|
|
|
cd9d16 |
2 files changed, 22 insertions(+), 2 deletions(-)
|
|
|
cd9d16 |
|
|
|
cd9d16 |
diff --git a/hw/e1000.c b/hw/e1000.c
|
|
|
cd9d16 |
index 96d84f9..e4d9ab5 100644
|
|
|
cd9d16 |
--- a/hw/e1000.c
|
|
|
cd9d16 |
+++ b/hw/e1000.c
|
|
|
cd9d16 |
@@ -624,10 +624,13 @@ e1000_set_link_status(VLANClientState *nc)
|
|
|
cd9d16 |
E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
|
|
|
cd9d16 |
uint32_t old_status = s->mac_reg[STATUS];
|
|
|
cd9d16 |
|
|
|
cd9d16 |
- if (nc->link_down)
|
|
|
cd9d16 |
+ if (nc->link_down) {
|
|
|
cd9d16 |
s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
|
|
|
cd9d16 |
- else
|
|
|
cd9d16 |
+ s->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
|
|
|
cd9d16 |
+ } else {
|
|
|
cd9d16 |
s->mac_reg[STATUS] |= E1000_STATUS_LU;
|
|
|
cd9d16 |
+ s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS;
|
|
|
cd9d16 |
+ }
|
|
|
cd9d16 |
|
|
|
cd9d16 |
if (s->mac_reg[STATUS] != old_status)
|
|
|
cd9d16 |
set_ics(s, 0, E1000_ICR_LSC);
|
|
|
cd9d16 |
diff --git a/hw/e1000_hw.h b/hw/e1000_hw.h
|
|
|
cd9d16 |
index 9bd8a4b..2e341ac 100644
|
|
|
cd9d16 |
--- a/hw/e1000_hw.h
|
|
|
cd9d16 |
+++ b/hw/e1000_hw.h
|
|
|
cd9d16 |
@@ -349,6 +349,23 @@
|
|
|
cd9d16 |
#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */
|
|
|
cd9d16 |
#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */
|
|
|
cd9d16 |
|
|
|
cd9d16 |
+/* PHY Status Register */
|
|
|
cd9d16 |
+#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
|
|
|
cd9d16 |
+#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
|
|
|
cd9d16 |
+#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
|
|
|
cd9d16 |
+#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
|
|
|
cd9d16 |
+#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
|
|
|
cd9d16 |
+#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
|
|
|
cd9d16 |
+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
|
|
|
cd9d16 |
+#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */
|
|
|
cd9d16 |
+#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
|
|
|
cd9d16 |
+#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
|
|
|
cd9d16 |
+#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
|
|
|
cd9d16 |
+#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
|
|
|
cd9d16 |
+#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
|
|
|
cd9d16 |
+#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
|
|
|
cd9d16 |
+#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
|
|
|
cd9d16 |
+
|
|
|
cd9d16 |
/* Interrupt Cause Read */
|
|
|
cd9d16 |
#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */
|
|
|
cd9d16 |
#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */
|
|
|
cd9d16 |
--
|
|
|
cd9d16 |
1.7.11.2
|
|
|
cd9d16 |
|