Module Name: src
Committed By: martin
Date: Wed Aug 5 17:22:46 UTC 2020
Modified Files:
src/sys/dev/mii [netbsd-8]: igphy.c igphyreg.h makphy.c makphyreg.h
src/sys/dev/pci [netbsd-8]: if_wm.c if_wmreg.h if_wmvar.h
Log Message:
Pull up the following revisions, requested by msaitoh in ticket #1594:
sys/dev/pci/if_wm.c 1.655-1.658, 1.660,
1.662, 1.664-1.668,
1.671-1.674, 1.678,
1.680-1.685 via patch
sys/dev/pci/if_wmreg.c 1.118-1.119 via patch
sys/dev/pci/if_wmvar.c 1.45 via patch
sys/dev/mii/igphy.c 1.35-1.36 via patch
sys/dev/mii/igphyreg.h 1.12-1.13
sys/dev/mii/makphy.c 1.66 via patch
sys/dev/mii/makphyreg.h 1.11
- Add SFP support. Module insertion/removal is not supported yet.
Currently, SFP detection is only done in the driver's attach phase.
- Detect the Media Auto Sense feature. Not supported yet.
- Fix SFF_SFP_ETH_FLAGS_100FX. It's not 0x10 but 0x20.
- Add extra delay in wm_serdes_power_up_link_82575().
- Add Intel I219 LM10-LM15 and V10-V14.
- wm(4) can use workqueue as deferred Rx/Tx handler).
Set hw.wm*.txrx_workqueue=1 to use workqueue instead of softint.
The default value of hw.wm*.txrx_workqueue is 0 which use softint
as before.
- Unset RSS UDP flags like ixg(4) and other OSes. To handle IP
fragmented UDP, first packet and second packet should be processed
in the same Rx queue.
- It's useless to not to set PCI_PMCSR_PME_STS bit when writing because
the bit is W1C. Instead, always write PCI_PMCSR_PME_STS bit to clear
in case it's already set.
- Actually writing always the checksum offload context descriptor
makes the HW do extra processing, avoid doing that if possible.
- Fix a bug that the WMREG_EEARBC_I210 register is incorrectly set if
the system uses iNVM.
- "wmX: 0" on 82542 is difficult to understand, so don't print it.
- Explicitly cast from uint16_t to uint32_t before shifting 16bit left
when printing Image Unique ID to avoid undefined behavior.
- Set if_baudrate for non-MII device.
- Rename some macros and function.
- KNF. Add comment.
To generate a diff of this commit:
cvs rdiff -u -r1.26.10.1 -r1.26.10.2 src/sys/dev/mii/igphy.c
cvs rdiff -u -r1.10 -r1.10.8.1 src/sys/dev/mii/igphyreg.h
cvs rdiff -u -r1.42.8.4 -r1.42.8.5 src/sys/dev/mii/makphy.c
cvs rdiff -u -r1.6.20.2 -r1.6.20.3 src/sys/dev/mii/makphyreg.h
cvs rdiff -u -r1.508.4.38 -r1.508.4.39 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.98.6.11 -r1.98.6.12 src/sys/dev/pci/if_wmreg.h
cvs rdiff -u -r1.33.6.5 -r1.33.6.6 src/sys/dev/pci/if_wmvar.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/mii/igphy.c
diff -u src/sys/dev/mii/igphy.c:1.26.10.1 src/sys/dev/mii/igphy.c:1.26.10.2
--- src/sys/dev/mii/igphy.c:1.26.10.1 Tue Aug 1 23:33:18 2017
+++ src/sys/dev/mii/igphy.c Wed Aug 5 17:22:46 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: igphy.c,v 1.26.10.1 2017/08/01 23:33:18 snj Exp $ */
+/* $NetBSD: igphy.c,v 1.26.10.2 2020/08/05 17:22:46 martin Exp $ */
/*
* The Intel copyright applies to the analog register setup, and the
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.26.10.1 2017/08/01 23:33:18 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.26.10.2 2020/08/05 17:22:46 martin Exp $");
#ifdef _KERNEL_OPT
#include "opt_mii.h"
@@ -274,7 +274,7 @@ igphy_load_dspcode(struct mii_softc *sc)
delay(20000);
- PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000);
+ PHY_WRITE(sc, IGPHY_PAGE_SELECT, 0x0000);
PHY_WRITE(sc, 0x0000, 0x0140);
delay(5000);
@@ -282,7 +282,7 @@ igphy_load_dspcode(struct mii_softc *sc)
for (i = 0; !((code[i].reg == 0) && (code[i].val == 0)); i++)
IGPHY_WRITE(sc, code[i].reg, code[i].val);
- PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000);
+ PHY_WRITE(sc, IGPHY_PAGE_SELECT, 0x0000);
PHY_WRITE(sc, 0x0000, 0x3300);
delay(20000);
@@ -327,9 +327,9 @@ igphy_reset(struct mii_softc *sc)
}
if (igsc->sc_mactype == WM_T_82547) {
- fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_SPARE_FUSE_STATUS);
+ fused = IGPHY_READ(sc, IGPHY_ANALOG_SPARE_FUSE_STATUS);
if ((fused & ANALOG_SPARE_FUSE_ENABLED) == 0) {
- fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_FUSE_STATUS);
+ fused = IGPHY_READ(sc, IGPHY_ANALOG_FUSE_STATUS);
fine = fused & ANALOG_FUSE_FINE_MASK;
coarse = fused & ANALOG_FUSE_COARSE_MASK;
@@ -344,12 +344,12 @@ igphy_reset(struct mii_softc *sc)
(fine & ANALOG_FUSE_FINE_MASK) |
(coarse & ANALOG_FUSE_COARSE_MASK);
- IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_CONTROL, fused);
- IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_BYPASS,
+ IGPHY_WRITE(sc, IGPHY_ANALOG_FUSE_CONTROL, fused);
+ IGPHY_WRITE(sc, IGPHY_ANALOG_FUSE_BYPASS,
ANALOG_FUSE_ENABLE_SW_CONTROL);
}
}
- PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000);
+ PHY_WRITE(sc, IGPHY_PAGE_SELECT, 0x0000);
}
@@ -385,14 +385,14 @@ igphy_service(struct mii_softc *sc, stru
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- reg = PHY_READ(sc, MII_IGPHY_PORT_CTRL);
+ reg = PHY_READ(sc, IGPHY_PORT_CTRL);
if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
reg |= PSCR_AUTO_MDIX;
reg &= ~PSCR_FORCE_MDI_MDIX;
- PHY_WRITE(sc, MII_IGPHY_PORT_CTRL, reg);
+ PHY_WRITE(sc, IGPHY_PORT_CTRL, reg);
} else {
reg &= ~(PSCR_AUTO_MDIX | PSCR_FORCE_MDI_MDIX);
- PHY_WRITE(sc, MII_IGPHY_PORT_CTRL, reg);
+ PHY_WRITE(sc, IGPHY_PORT_CTRL, reg);
}
mii_phy_setmedia(sc);
@@ -435,9 +435,9 @@ igphy_status(struct mii_softc *sc)
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
- pssr = PHY_READ(sc, MII_IGPHY_PORT_STATUS);
+ pssr = PHY_READ(sc, IGPHY_PORT_STATUS);
- if (pssr & PSSR_LINK_UP)
+ if (pssr & IGPHY_PSSR_LINK_UP)
mii->mii_media_status |= IFM_ACTIVE;
bmcr = PHY_READ(sc, MII_BMCR);
@@ -461,19 +461,19 @@ igphy_status(struct mii_softc *sc)
mii->mii_media_active |= IFM_NONE;
return;
}
- switch (pssr & PSSR_SPEED_MASK) {
- case PSSR_SPEED_1000MBPS:
+ switch (pssr & IGPHY_PSSR_SPEED_MASK) {
+ case IGPHY_PSSR_SPEED_1000MBPS:
mii->mii_media_active |= IFM_1000_T;
gtsr = PHY_READ(sc, MII_100T2SR);
if (gtsr & GTSR_MS_RES)
mii->mii_media_active |= IFM_ETH_MASTER;
break;
- case PSSR_SPEED_100MBPS:
+ case IGPHY_PSSR_SPEED_100MBPS:
mii->mii_media_active |= IFM_100_TX;
break;
- case PSSR_SPEED_10MBPS:
+ case IGPHY_PSSR_SPEED_10MBPS:
mii->mii_media_active |= IFM_10_T;
break;
@@ -483,7 +483,7 @@ igphy_status(struct mii_softc *sc)
return;
}
- if (pssr & PSSR_FULL_DUPLEX)
+ if (pssr & IGPHY_PSSR_FULL_DUPLEX)
mii->mii_media_active |=
IFM_FDX | mii_phy_flowstatus(sc);
else
Index: src/sys/dev/mii/igphyreg.h
diff -u src/sys/dev/mii/igphyreg.h:1.10 src/sys/dev/mii/igphyreg.h:1.10.8.1
--- src/sys/dev/mii/igphyreg.h:1.10 Mon Nov 7 08:57:43 2016
+++ src/sys/dev/mii/igphyreg.h Wed Aug 5 17:22:46 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: igphyreg.h,v 1.10 2016/11/07 08:57:43 msaitoh Exp $ */
+/* $NetBSD: igphyreg.h,v 1.10.8.1 2020/08/05 17:22:46 martin Exp $ */
/*******************************************************************************
@@ -43,7 +43,7 @@
*/
/* IGP01E1000 Specific Port Config Register - R/W */
-#define MII_IGPHY_PORT_CONFIG 0x10 /* PHY specific config register */
+#define IGPHY_PORT_CONFIG 0x10 /* PHY specific config register */
#define PSCFR_AUTO_MDIX_PAR_DETECT 0x0010
#define PSCFR_PRE_EN 0x0020
#define PSCFR_SMART_SPEED 0x0080
@@ -52,22 +52,22 @@
#define PSCFR_DISABLE_TRANSMIT 0x2000
/* IGP01E1000 Specific Port Status Register - R/O */
-#define MII_IGPHY_PORT_STATUS 0x11
-#define PSSR_AUTONEG_FAILED 0x0001 /* RO LH SC */
-#define PSSR_POLARITY_REVERSED 0x0002
-#define PSSR_CABLE_LENGTH 0x007C
-#define PSSR_FULL_DUPLEX 0x0200
-#define PSSR_LINK_UP 0x0400
-#define PSSR_MDIX 0x0800
-#define PSSR_SPEED_MASK 0xC000 /* speed bits mask */
-#define PSSR_SPEED_10MBPS 0x4000
-#define PSSR_SPEED_100MBPS 0x8000
-#define PSSR_SPEED_1000MBPS 0xC000
-#define PSSR_CABLE_LENGTH_SHIFT 0x0002 /* shift right 2 */
-#define PSSR_MDIX_SHIFT 0x000B /* shift right 11 */
+#define IGPHY_PORT_STATUS 0x11
+#define IGPHY_PSSR_AUTONEG_FAILED 0x0001 /* RO LH SC */
+#define IGPHY_PSSR_POLARITY_REVERSED 0x0002
+#define IGPHY_PSSR_CABLE_LENGTH 0x007C
+#define IGPHY_PSSR_FULL_DUPLEX 0x0200
+#define IGPHY_PSSR_LINK_UP 0x0400
+#define IGPHY_PSSR_MDIX 0x0800
+#define IGPHY_PSSR_SPEED_MASK 0xC000 /* speed bits mask */
+#define IGPHY_PSSR_SPEED_10MBPS 0x4000
+#define IGPHY_PSSR_SPEED_100MBPS 0x8000
+#define IGPHY_PSSR_SPEED_1000MBPS 0xC000
+#define IGPHY_PSSR_CABLE_LENGTH_SHIFT 0x0002 /* shift right 2 */
+#define IGPHY_PSSR_MDIX_SHIFT 0x000B /* shift right 11 */
/* IGP01E1000 Specific Port Control Register - R/W */
-#define MII_IGPHY_PORT_CTRL 0x12
+#define IGPHY_PORT_CTRL 0x12
#define PSCR_TP_LOOPBACK 0x0010
#define PSCR_CORRECT_NC_SCMBLR 0x0200
#define PSCR_TEN_CRS_SELECT 0x0400
@@ -76,7 +76,7 @@
#define PSCR_FORCE_MDI_MDIX 0x2000 /* 0-MDI, 1-MDIX */
/* IGP01E1000 Specific Port Link Health Register */
-#define MII_IGPHY_LINK_HEALTH 0x13
+#define IGPHY_LINK_HEALTH 0x13
#define PLHR_VALID_CHANNEL_A 0x0001
#define PLHR_VALID_CHANNEL_B 0x0002
#define PLHR_VALID_CHANNEL_C 0x0004
@@ -96,61 +96,61 @@
#define GMII_SPD 0x20 /* Enable SPD */
/* IGP01E1000 Channel Quality Register */
-#define MII_IGPHY_CHANNEL_QUALITY 0x15
+#define IGPHY_CHANNEL_QUALITY 0x15
#define MSE_CHANNEL_A 0x000F
#define MSE_CHANNEL_B 0x00F0
#define MSE_CHANNEL_C 0x0F00
#define MSE_CHANNEL_D 0xF000
/* IGP01E1000 Power Management */
-#define MII_IGPHY_POWER_MGMT 0x19
+#define IGPHY_POWER_MGMT 0x19
#define PMR_SPD_EN 0x0001
#define PMR_D0_LPLU 0x0002
#define PMR_D3_LPLU 0x0004
#define PMR_DIS_1000 0x0040
-#define MII_IGPHY_PAGE_SELECT 0x1F
+#define IGPHY_PAGE_SELECT 0x1F
#define IGPHY_MAXREGADDR 0x1F
#define IGPHY_PAGEMASK (~IGPHY_MAXREGADDR)
/* IGP01E1000 AGC Registers - stores the cable length values*/
-#define MII_IGPHY_AGC_A 0x1172
-#define MII_IGPHY_AGC_PARAM_A 0x1171
-#define MII_IGPHY_AGC_B 0x1272
-#define MII_IGPHY_AGC_PARAM_B 0x1271
-#define MII_IGPHY_AGC_C 0x1472
-#define MII_IGPHY_AGC_PARAM_C 0x1471
-#define MII_IGPHY_AGC_D 0x1872
-#define MII_IGPHY_AGC_PARAM_D 0x1871
+#define IGPHY_AGC_A 0x1172
+#define IGPHY_AGC_PARAM_A 0x1171
+#define IGPHY_AGC_B 0x1272
+#define IGPHY_AGC_PARAM_B 0x1271
+#define IGPHY_AGC_C 0x1472
+#define IGPHY_AGC_PARAM_C 0x1471
+#define IGPHY_AGC_D 0x1872
+#define IGPHY_AGC_PARAM_D 0x1871
#define AGC_LENGTH_SHIFT 7 /* Coarse - 13:11, Fine - 10:7 */
#define AGC_LENGTH_TABLE_SIZE 128
#define AGC_RANGE 10
/* IGP01E1000 DSP Reset Register */
-#define MII_IGPHY_DSP_RESET 0x1F33
-#define MII_IGPHY_DSP_SET 0x1F71
-#define MII_IGPHY_DSP_FFE 0x1F35
-#define MII_IGPHY_CHANNEL_NUM 4
-#define MII_IGPHY_EDAC_MU_INDEX 0xC000
-#define MII_IGPHY_EDAC_SIGN_EXT_9_BITS 0x8000
-#define MII_IGPHY_ANALOG_TX_STATE 0x2890
-#define MII_IGPHY_ANALOG_CLASS_A 0x2000
-#define MII_IGPHY_FORCE_ANALOG_ENABLE 0x0004
-#define MII_IGPHY_DSP_FFE_CM_CP 0x0069
-#define MII_IGPHY_DSP_FFE_DEFAULT 0x002A
+#define IGPHY_DSP_RESET 0x1F33
+#define IGPHY_DSP_SET 0x1F71
+#define IGPHY_DSP_FFE 0x1F35
+#define IGPHY_CHANNEL_NUM 4
+#define IGPHY_EDAC_MU_INDEX 0xC000
+#define IGPHY_EDAC_SIGN_EXT_9_BITS 0x8000
+#define IGPHY_ANALOG_TX_STATE 0x2890
+#define IGPHY_ANALOG_CLASS_A 0x2000
+#define IGPHY_FORCE_ANALOG_ENABLE 0x0004
+#define IGPHY_DSP_FFE_CM_CP 0x0069
+#define IGPHY_DSP_FFE_DEFAULT 0x002A
/* IGP01E1000 PCS Initialization register - stores the polarity status */
-#define MII_IGPHY_PCS_INIT_REG 0x00B4
-#define MII_IGPHY_PCS_CTRL_REG 0x00B5
+#define IGPHY_PCS_INIT_REG 0x00B4
+#define IGPHY_PCS_CTRL_REG 0x00B5
-#define MII_IGPHY_ANALOG_REGS_PAGE 0x20C0
+#define IGPHY_ANALOG_REGS_PAGE 0x20C0
#define PHY_POLARITY_MASK 0x0078
/* IGP01E1000 Analog Register */
-#define MII_IGPHY_ANALOG_SPARE_FUSE_STATUS 0x20D1
-#define MII_IGPHY_ANALOG_FUSE_STATUS 0x20D0
-#define MII_IGPHY_ANALOG_FUSE_CONTROL 0x20DC
-#define MII_IGPHY_ANALOG_FUSE_BYPASS 0x20DE
+#define IGPHY_ANALOG_SPARE_FUSE_STATUS 0x20D1
+#define IGPHY_ANALOG_FUSE_STATUS 0x20D0
+#define IGPHY_ANALOG_FUSE_CONTROL 0x20DC
+#define IGPHY_ANALOG_FUSE_BYPASS 0x20DE
#define ANALOG_FUSE_POLY_MASK 0xF000
#define ANALOG_FUSE_FINE_MASK 0x0F80
#define ANALOG_FUSE_COARSE_MASK 0x0070
@@ -177,12 +177,12 @@
#define IGPHY_READ(sc, reg) \
- (PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, (reg) & ~0x1f), \
+ (PHY_WRITE(sc, IGPHY_PAGE_SELECT, (reg) & ~0x1f), \
PHY_READ(sc, (reg) & 0x1f))
#define IGPHY_WRITE(sc, reg, val) \
do { \
- PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, (reg) & ~0x1f); \
+ PHY_WRITE(sc, IGPHY_PAGE_SELECT, (reg) & ~0x1f); \
PHY_WRITE(sc, (reg) & 0x1f, val); \
} while (/*CONSTCOND*/0)
Index: src/sys/dev/mii/makphy.c
diff -u src/sys/dev/mii/makphy.c:1.42.8.4 src/sys/dev/mii/makphy.c:1.42.8.5
--- src/sys/dev/mii/makphy.c:1.42.8.4 Tue Jan 28 09:34:29 2020
+++ src/sys/dev/mii/makphy.c Wed Aug 5 17:22:46 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: makphy.c,v 1.42.8.4 2020/01/28 09:34:29 martin Exp $ */
+/* $NetBSD: makphy.c,v 1.42.8.5 2020/08/05 17:22:46 martin Exp $ */
/*-
* Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -59,7 +59,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: makphy.c,v 1.42.8.4 2020/01/28 09:34:29 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: makphy.c,v 1.42.8.5 2020/08/05 17:22:46 martin Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -469,7 +469,7 @@ makphy_status(struct mii_softc *sc)
/* XXX FIXME: Use different page for Fiber on newer chips */
pssr = PHY_READ(sc, MAKPHY_PSSR);
- if (pssr & PSSR_LINK)
+ if (pssr & MAKPHY_PSSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
if (bmcr & BMCR_LOOP)
@@ -486,13 +486,13 @@ makphy_status(struct mii_softc *sc)
* Check Speed and Duplex Resolved bit.
* Note that this bit is always 1 when autonego is not enabled.
*/
- if (!(pssr & PSSR_RESOLVED)) {
+ if (!(pssr & MAKPHY_PSSR_RESOLVED)) {
/* Erg, still trying, I guess... */
mii->mii_media_active |= IFM_NONE;
return;
}
} else {
- if ((pssr & PSSR_LINK) == 0) {
+ if ((pssr & MAKPHY_PSSR_LINK) == 0) {
mii->mii_media_active |= IFM_NONE;
return;
}
@@ -520,10 +520,10 @@ makphy_status(struct mii_softc *sc)
/* Fiber/Copper auto select mode */
pssr = PHY_READ(sc, MAKPHY_PSSR);
- if ((pssr & PSSR_RESOLUTION_FIBER) == 0)
+ if ((pssr & MAKPHY_PSSR_RESOLUTION_FIBER) == 0)
goto copper;
- switch (PSSR_SPEED_get(pssr)) {
+ switch (MAKPHY_PSSR_SPEED_get(pssr)) {
case SPEED_1000:
mii->mii_media_active |= IFM_1000_SX;
break;
@@ -537,7 +537,7 @@ makphy_status(struct mii_softc *sc)
}
} else {
copper:
- switch (PSSR_SPEED_get(pssr)) {
+ switch (MAKPHY_PSSR_SPEED_get(pssr)) {
case SPEED_1000:
mii->mii_media_active |= IFM_1000_T;
break;
@@ -554,7 +554,7 @@ copper:
}
}
- if (pssr & PSSR_DUPLEX)
+ if (pssr & MAKPHY_PSSR_DUPLEX)
mii->mii_media_active |= mii_phy_flowstatus(sc) | IFM_FDX;
else
mii->mii_media_active |= IFM_HDX;
Index: src/sys/dev/mii/makphyreg.h
diff -u src/sys/dev/mii/makphyreg.h:1.6.20.2 src/sys/dev/mii/makphyreg.h:1.6.20.3
--- src/sys/dev/mii/makphyreg.h:1.6.20.2 Tue Jan 28 09:34:29 2020
+++ src/sys/dev/mii/makphyreg.h Wed Aug 5 17:22:46 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: makphyreg.h,v 1.6.20.2 2020/01/28 09:34:29 martin Exp $ */
+/* $NetBSD: makphyreg.h,v 1.6.20.3 2020/08/05 17:22:46 martin Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -92,15 +92,15 @@
#define MSCR_ENHANCED_SGMII 0x0004 /* Enhanced SGMII */
#define MAKPHY_PSSR 0x11 /* PHY specific status register */
-#define PSSR_JABBER (1U << 0) /* jabber indication */
-#define PSSR_POLARITY (1U << 1) /* polarity indiciation */
-#define PSSR_MDIX (1U << 6) /* 1 = MIDX, 0 = MDI */
-#define PSSR_CABLE_LENGTH_get(x) (((x) >> 7) & 0x3)
-#define PSSR_LINK (1U << 10) /* link indication */
-#define PSSR_RESOLVED (1U << 11) /* speed and duplex resolved */
-#define PSSR_PAGE_RECEIVED (1U << 12) /* page received */
-#define PSSR_DUPLEX (1U << 13) /* 1 = FDX */
-#define PSSR_SPEED_get(x) (((x) >> 14) & 0x3)
+#define MAKPHY_PSSR_JABBER (1U << 0) /* jabber indication */
+#define MAKPHY_PSSR_POLARITY (1U << 1) /* polarity indiciation */
+#define MAKPHY_PSSR_MDIX (1U << 6) /* 1 = MIDX, 0 = MDI */
+#define MAKPHY_PSSR_CABLE_LENGTH_get(x) (((x) >> 7) & 0x3)
+#define MAKPHY_PSSR_LINK (1U << 10) /* link indication */
+#define MAKPHY_PSSR_RESOLVED (1U << 11) /* speed and duplex resolved */
+#define MAKPHY_PSSR_PAGE_RECEIVED (1U << 12) /* page received */
+#define MAKPHY_PSSR_DUPLEX (1U << 13) /* 1 = FDX */
+#define MAKPHY_PSSR_SPEED_get(x) (((x) >> 14) & 0x3)
#define SPEED_10 0
#define SPEED_100 1
@@ -108,10 +108,10 @@
#define SPEED_reserved 3
/* For 88E1112 */
-#define PSSR_RESOLUTION_FIBER (1U << 7) /*
- * Fiber/Copper resolution
- * 1 = Fiber, 0 = Copper
- */
+#define MAKPHY_PSSR_RESOLUTION_FIBER (1U << 7) /*
+ * Fiber/Copper resolution
+ * 1 = Fiber, 0 = Copper
+ */
#define MAKPHY_IE 0x12 /* Interrupt enable */
#define IE_JABBER (1U << 0) /* jabber indication */
Index: src/sys/dev/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.508.4.38 src/sys/dev/pci/if_wm.c:1.508.4.39
--- src/sys/dev/pci/if_wm.c:1.508.4.38 Fri Jan 24 18:43:35 2020
+++ src/sys/dev/pci/if_wm.c Wed Aug 5 17:22:45 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wm.c,v 1.508.4.38 2020/01/24 18:43:35 martin Exp $ */
+/* $NetBSD: if_wm.c,v 1.508.4.39 2020/08/05 17:22:45 martin Exp $ */
/*
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -82,7 +82,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.508.4.38 2020/01/24 18:43:35 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.508.4.39 2020/08/05 17:22:45 martin Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -105,6 +105,8 @@ __KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.
#include <sys/interrupt.h>
#include <sys/cpu.h>
#include <sys/pcq.h>
+#include <sys/sysctl.h>
+#include <sys/workqueue.h>
#include <sys/rndsource.h>
@@ -136,6 +138,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.
#include <dev/mii/igphyvar.h>
#include <dev/mii/inbmphyreg.h>
#include <dev/mii/ihphyreg.h>
+#include <dev/mii/makphyreg.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
@@ -155,7 +158,6 @@ __KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.
#define WM_DEBUG_LOCK __BIT(7)
int wm_debug = WM_DEBUG_TX | WM_DEBUG_RX | WM_DEBUG_LINK | WM_DEBUG_GMII
| WM_DEBUG_MANAGE | WM_DEBUG_NVM | WM_DEBUG_INIT | WM_DEBUG_LOCK;
-
#define DPRINTF(x, y) do { if (wm_debug & (x)) printf y; } while (0)
#else
#define DPRINTF(x, y) __nothing
@@ -163,11 +165,17 @@ int wm_debug = WM_DEBUG_TX | WM_DEBUG_RX
#ifdef NET_MPSAFE
#define WM_MPSAFE 1
-#define CALLOUT_FLAGS CALLOUT_MPSAFE
+#define WM_CALLOUT_FLAGS CALLOUT_MPSAFE
+#define WM_SOFTINT_FLAGS SOFTINT_MPSAFE
+#define WM_WORKQUEUE_FLAGS WQ_PERCPU | WQ_MPSAFE
#else
-#define CALLOUT_FLAGS 0
+#define WM_CALLOUT_FLAGS 0
+#define WM_SOFTINT_FLAGS 0
+#define WM_WORKQUEUE_FLAGS WQ_PERCPU
#endif
+#define WM_WORKQUEUE_PRI PRI_SOFTNET
+
/*
* This device driver's max interrupt numbers.
*/
@@ -373,6 +381,12 @@ struct wm_txqueue {
bool txq_sending;
time_t txq_lastsent;
+ /* Checksum flags used for previous packet */
+ uint32_t txq_last_hw_cmd;
+ uint8_t txq_last_hw_fields;
+ uint16_t txq_last_hw_ipcs;
+ uint16_t txq_last_hw_tucs;
+
uint32_t txq_packets; /* for AIM */
uint32_t txq_bytes; /* for AIM */
#ifdef WM_EVENT_COUNTERS
@@ -397,6 +411,7 @@ struct wm_txqueue {
WM_Q_EVCNT_DEFINE(txq, toomanyseg) /* Pkt dropped(toomany DMA segs) */
WM_Q_EVCNT_DEFINE(txq, defrag) /* m_defrag() */
WM_Q_EVCNT_DEFINE(txq, underrun) /* Tx underrun */
+ WM_Q_EVCNT_DEFINE(txq, skipcontext) /* Tx skip wring cksum context */
char txq_txseg_evcnt_names[WM_NTXSEGS][sizeof("txqXXtxsegXXX")];
struct evcnt txq_ev_txseg[WM_NTXSEGS]; /* Tx packets w/ N segments */
@@ -456,6 +471,8 @@ struct wm_queue {
struct wm_txqueue wmq_txq;
struct wm_rxqueue wmq_rxq;
+ bool wmq_txrx_use_workqueue;
+ struct work wmq_cookie;
void *wmq_si;
krndsource_t rnd_source; /* random source */
};
@@ -466,6 +483,7 @@ struct wm_phyop {
int (*readreg_locked)(device_t, int, int, uint16_t *);
int (*writereg_locked)(device_t, int, int, uint16_t);
int reset_delay_us;
+ bool no_errprint;
};
struct wm_nvmop {
@@ -506,6 +524,7 @@ struct wm_softc {
wm_chip_type sc_type; /* MAC type */
int sc_rev; /* MAC revision */
wm_phy_type sc_phytype; /* PHY type */
+ uint8_t sc_sfptype; /* SFP type */
uint32_t sc_mediatype; /* Media type (Copper, Fiber, SERDES)*/
#define WM_MEDIATYPE_UNKNOWN 0x00
#define WM_MEDIATYPE_FIBER 0x01
@@ -548,6 +567,8 @@ struct wm_softc {
u_int sc_tx_intr_process_limit; /* Tx proc. repeat limit in H/W intr */
u_int sc_rx_process_limit; /* Rx proc. repeat limit in softint */
u_int sc_rx_intr_process_limit; /* Rx proc. repeat limit in H/W intr */
+ struct workqueue *sc_queue_wq;
+ bool sc_txrx_use_workqueue;
int sc_affinity_offset;
@@ -563,6 +584,8 @@ struct wm_softc {
struct evcnt sc_ev_rx_macctl; /* Rx Unsupported */
#endif /* WM_EVENT_COUNTERS */
+ struct sysctllog *sc_sysctllog;
+
/* This variable are used only on the 82547. */
callout_t sc_txfifo_ch; /* Tx FIFO stall work-around timer */
@@ -734,11 +757,12 @@ static void wm_init_rss(struct wm_softc
static void wm_adjust_qnum(struct wm_softc *, int);
static inline bool wm_is_using_msix(struct wm_softc *);
static inline bool wm_is_using_multiqueue(struct wm_softc *);
-static int wm_softint_establish(struct wm_softc *, int, int);
+static int wm_softint_establish_queue(struct wm_softc *, int, int);
static int wm_setup_legacy(struct wm_softc *);
static int wm_setup_msix(struct wm_softc *);
static int wm_init(struct ifnet *);
static int wm_init_locked(struct ifnet *);
+static void wm_init_sysctls(struct wm_softc *);
static void wm_unset_stopping_flags(struct wm_softc *);
static void wm_set_stopping_flags(struct wm_softc *);
static void wm_stop(struct ifnet *, int);
@@ -771,7 +795,7 @@ static int wm_alloc_txrx_queues(struct w
static void wm_free_txrx_queues(struct wm_softc *);
static int wm_init_txrx_queues(struct wm_softc *);
/* Start */
-static int wm_tx_offload(struct wm_softc *, struct wm_txqueue *,
+static void wm_tx_offload(struct wm_softc *, struct wm_txqueue *,
struct wm_txsoft *, uint32_t *, uint8_t *);
static inline int wm_select_txqueue(struct ifnet *, struct mbuf *);
static void wm_start(struct ifnet *);
@@ -780,7 +804,7 @@ static int wm_transmit(struct ifnet *, s
static void wm_transmit_locked(struct ifnet *, struct wm_txqueue *);
static void wm_send_common_locked(struct ifnet *, struct wm_txqueue *,
bool);
-static int wm_nq_tx_offload(struct wm_softc *, struct wm_txqueue *,
+static void wm_nq_tx_offload(struct wm_softc *, struct wm_txqueue *,
struct wm_txsoft *, uint32_t *, uint32_t *, bool *);
static void wm_nq_start(struct ifnet *);
static void wm_nq_start_locked(struct ifnet *);
@@ -790,6 +814,7 @@ static void wm_nq_send_common_locked(str
bool);
static void wm_deferred_start_locked(struct wm_txqueue *);
static void wm_handle_queue(void *);
+static void wm_handle_queue_work(struct work *, void *);
/* Interrupt */
static bool wm_txeof(struct wm_txqueue *, u_int);
static bool wm_rxeof(struct wm_rxqueue *, u_int);
@@ -855,6 +880,7 @@ static int wm_kmrn_writereg(struct wm_so
static int wm_kmrn_writereg_locked(struct wm_softc *, int, uint16_t);
/* SGMII */
static bool wm_sgmii_uses_mdio(struct wm_softc *);
+static void wm_sgmii_sfp_preconfig(struct wm_softc *);
static int wm_sgmii_readreg(device_t, int, int);
static void wm_sgmii_writereg(device_t, int, int, int);
/* TBI related */
@@ -1173,23 +1199,23 @@ static const struct wm_product {
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571GB_QUAD_COPPER,
"Intel PRO/1000 PT Quad Port Server Adapter",
- WM_T_82571, WMP_F_COPPER, },
+ WM_T_82571, WMP_F_COPPER },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571PT_QUAD_COPPER,
"Intel Gigabit PT Quad Port Server ExpressModule",
- WM_T_82571, WMP_F_COPPER, },
+ WM_T_82571, WMP_F_COPPER },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571EB_DUAL_SERDES,
"Intel 82571EB Dual Gigabit Ethernet (SERDES)",
- WM_T_82571, WMP_F_SERDES, },
+ WM_T_82571, WMP_F_SERDES },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571EB_QUAD_SERDES,
"Intel 82571EB Quad Gigabit Ethernet (SERDES)",
- WM_T_82571, WMP_F_SERDES, },
+ WM_T_82571, WMP_F_SERDES },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571EB_QUAD_FIBER,
"Intel 82571EB Quad 1000baseX Ethernet",
- WM_T_82571, WMP_F_FIBER, },
+ WM_T_82571, WMP_F_FIBER },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82572EI_COPPER,
"Intel i82572EI 1000baseT Ethernet",
@@ -1543,6 +1569,24 @@ static const struct wm_product {
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM9,
"I219 LM Ethernet Connection",
WM_T_PCH_CNP, WMP_F_COPPER },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM10,
+ "I219 LM Ethernet Connection",
+ WM_T_PCH_CNP, WMP_F_COPPER },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM11,
+ "I219 LM Ethernet Connection",
+ WM_T_PCH_CNP, WMP_F_COPPER },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM12,
+ "I219 LM Ethernet Connection",
+ WM_T_PCH_SPT, WMP_F_COPPER },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM13,
+ "I219 LM Ethernet Connection",
+ WM_T_PCH_CNP, WMP_F_COPPER },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM14,
+ "I219 LM Ethernet Connection",
+ WM_T_PCH_CNP, WMP_F_COPPER },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM15,
+ "I219 LM Ethernet Connection",
+ WM_T_PCH_CNP, WMP_F_COPPER },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V,
"I219 V Ethernet Connection",
WM_T_PCH_SPT, WMP_F_COPPER },
@@ -1567,6 +1611,21 @@ static const struct wm_product {
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V9,
"I219 V Ethernet Connection",
WM_T_PCH_CNP, WMP_F_COPPER },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V10,
+ "I219 V Ethernet Connection",
+ WM_T_PCH_CNP, WMP_F_COPPER },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V11,
+ "I219 V Ethernet Connection",
+ WM_T_PCH_CNP, WMP_F_COPPER },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V12,
+ "I219 V Ethernet Connection",
+ WM_T_PCH_SPT, WMP_F_COPPER },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V13,
+ "I219 V Ethernet Connection",
+ WM_T_PCH_CNP, WMP_F_COPPER },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V14,
+ "I219 V Ethernet Connection",
+ WM_T_PCH_CNP, WMP_F_COPPER },
{ 0, 0,
NULL,
0, 0 },
@@ -1763,6 +1822,7 @@ wm_attach(device_t parent, device_t self
prop_number_t pn;
uint8_t enaddr[ETHER_ADDR_LEN];
char buf[256];
+ char wqname[MAXCOMLEN];
uint16_t cfg1, cfg2, swdpin, nvmword;
pcireg_t preg, memtype;
uint16_t eeprom_data, apme_mask;
@@ -1771,7 +1831,7 @@ wm_attach(device_t parent, device_t self
uint32_t reg;
sc->sc_dev = self;
- callout_init(&sc->sc_tick_ch, CALLOUT_FLAGS);
+ callout_init(&sc->sc_tick_ch, WM_CALLOUT_FLAGS);
sc->sc_core_stopping = false;
wmp = wm_lookup(pa);
@@ -1996,6 +2056,16 @@ alloc_retry:
}
}
+ snprintf(wqname, sizeof(wqname), "%sTxRx", device_xname(sc->sc_dev));
+ error = workqueue_create(&sc->sc_queue_wq, wqname,
+ wm_handle_queue_work, sc, WM_WORKQUEUE_PRI, IPL_NET,
+ WM_WORKQUEUE_FLAGS);
+ if (error) {
+ aprint_error_dev(sc->sc_dev,
+ "unable to create workqueue\n");
+ goto out;
+ }
+
/*
* Check the function ID (unit number of the chip).
*/
@@ -2025,7 +2095,7 @@ alloc_retry:
aprint_verbose_dev(sc->sc_dev,
"Communication Streaming Architecture\n");
if (sc->sc_type == WM_T_82547) {
- callout_init(&sc->sc_txfifo_ch, CALLOUT_FLAGS);
+ callout_init(&sc->sc_txfifo_ch, WM_CALLOUT_FLAGS);
callout_setfunc(&sc->sc_txfifo_ch,
wm_82547_txfifo_stall, sc);
aprint_verbose_dev(sc->sc_dev,
@@ -2593,11 +2663,22 @@ alloc_retry:
break;
}
- if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)) {
- /* Check NVM for autonegotiation */
+ if (sc->sc_type >= WM_T_82575) {
if (wm_nvm_read(sc, NVM_OFF_COMPAT, 1, &nvmword) == 0) {
- if ((nvmword & NVM_COMPAT_SERDES_FORCE_MODE) != 0)
- sc->sc_flags |= WM_F_PCS_DIS_AUTONEGO;
+ aprint_debug_dev(sc->sc_dev, "COMPAT = %hx\n",
+ nvmword);
+ if ((sc->sc_type == WM_T_82575) ||
+ (sc->sc_type == WM_T_82576)) {
+ /* Check NVM for autonegotiation */
+ if ((nvmword & NVM_COMPAT_SERDES_FORCE_MODE)
+ != 0)
+ sc->sc_flags |= WM_F_PCS_DIS_AUTONEGO;
+ }
+ if ((sc->sc_type == WM_T_82575) ||
+ (sc->sc_type == WM_T_I350)) {
+ if (nvmword & NVM_COMPAT_MAS_EN(sc->sc_funcid))
+ sc->sc_flags |= WM_F_MAS;
+ }
}
}
@@ -2705,12 +2786,12 @@ alloc_retry:
link_mode = reg & CTRL_EXT_LINK_MODE_MASK;
switch (link_mode) {
case CTRL_EXT_LINK_MODE_1000KX:
- aprint_verbose_dev(sc->sc_dev, "1000KX\n");
+ aprint_normal_dev(sc->sc_dev, "1000KX\n");
sc->sc_mediatype = WM_MEDIATYPE_SERDES;
break;
case CTRL_EXT_LINK_MODE_SGMII:
if (wm_sgmii_uses_mdio(sc)) {
- aprint_verbose_dev(sc->sc_dev,
+ aprint_normal_dev(sc->sc_dev,
"SGMII(MDIO)\n");
sc->sc_flags |= WM_F_SGMII;
sc->sc_mediatype = WM_MEDIATYPE_COPPER;
@@ -2725,6 +2806,8 @@ alloc_retry:
== CTRL_EXT_LINK_MODE_SGMII) {
sc->sc_mediatype = WM_MEDIATYPE_COPPER;
sc->sc_flags |= WM_F_SGMII;
+ aprint_verbose_dev(sc->sc_dev,
+ "SGMII\n");
} else {
sc->sc_mediatype = WM_MEDIATYPE_SERDES;
aprint_verbose_dev(sc->sc_dev,
@@ -2733,25 +2816,26 @@ alloc_retry:
break;
}
if (sc->sc_mediatype == WM_MEDIATYPE_SERDES)
- aprint_verbose_dev(sc->sc_dev, "SERDES\n");
+ aprint_normal_dev(sc->sc_dev, "SERDES(SFP)\n");
+ else if (sc->sc_mediatype == WM_MEDIATYPE_COPPER) {
+ aprint_normal_dev(sc->sc_dev, "SGMII(SFP)\n");
+ sc->sc_flags |= WM_F_SGMII;
+ }
+ /* Do not change link mode for 100BaseFX */
+ if (sc->sc_sfptype == SFF_SFP_ETH_FLAGS_100FX)
+ break;
/* Change current link mode setting */
reg &= ~CTRL_EXT_LINK_MODE_MASK;
- switch (sc->sc_mediatype) {
- case WM_MEDIATYPE_COPPER:
+ if (sc->sc_mediatype == WM_MEDIATYPE_COPPER)
reg |= CTRL_EXT_LINK_MODE_SGMII;
- break;
- case WM_MEDIATYPE_SERDES:
+ else
reg |= CTRL_EXT_LINK_MODE_PCIE_SERDES;
- break;
- default:
- break;
- }
CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
break;
case CTRL_EXT_LINK_MODE_GMII:
default:
- aprint_verbose_dev(sc->sc_dev, "Copper\n");
+ aprint_normal_dev(sc->sc_dev, "Copper\n");
sc->sc_mediatype = WM_MEDIATYPE_COPPER;
break;
}
@@ -2762,6 +2846,10 @@ alloc_retry:
else
reg &= ~CTRL_EXT_I2C_ENA;
CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
+ if ((sc->sc_flags & WM_F_SGMII) != 0) {
+ wm_gmii_setup_phytype(sc, 0, 0);
+ wm_reset_mdicnfg_82580(sc);
+ }
} else if (sc->sc_type < WM_T_82543 ||
(CSR_READ(sc, WMREG_STATUS) & STATUS_TBIMODE) != 0) {
if (sc->sc_mediatype == WM_MEDIATYPE_COPPER) {
@@ -2776,8 +2864,10 @@ alloc_retry:
sc->sc_mediatype = WM_MEDIATYPE_COPPER;
}
}
- snprintb(buf, sizeof(buf), WM_FLAGS, sc->sc_flags);
- aprint_verbose_dev(sc->sc_dev, "%s\n", buf);
+ if (sc->sc_flags != 0) {
+ snprintb(buf, sizeof(buf), WM_FLAGS, sc->sc_flags);
+ aprint_verbose_dev(sc->sc_dev, "%s\n", buf);
+ }
/* Set device properties (macflags) */
prop_dictionary_set_uint32(dict, "macflags", sc->sc_flags);
@@ -2948,6 +3038,10 @@ alloc_retry:
NULL, xname, "rx_macctl");
#endif /* WM_EVENT_COUNTERS */
+ sc->sc_txrx_use_workqueue = false;
+
+ wm_init_sysctls(sc);
+
if (pmf_device_register(self, wm_suspend, wm_resume))
pmf_class_network_register(self, ifp);
else
@@ -2974,6 +3068,8 @@ wm_detach(device_t self, int flags __unu
pmf_device_deregister(self);
+ sysctl_teardown(&sc->sc_sysctllog);
+
#ifdef WM_EVENT_COUNTERS
evcnt_detach(&sc->sc_ev_linkintr);
@@ -3018,6 +3114,9 @@ wm_detach(device_t self, int flags __unu
}
pci_intr_release(sc->sc_pc, sc->sc_intrs, sc->sc_nintrs);
+ /* wm_stop() ensure workqueue is stopped. */
+ workqueue_destroy(sc->sc_queue_wq);
+
for (i = 0; i < sc->sc_nqueues; i++)
softint_disestablish(sc->sc_queue[i].wmq_si);
@@ -4153,7 +4252,7 @@ wm_init_lcd_from_nvm(struct wm_softc *sc
if (wm_nvm_read(sc, (word_addr + i * 2 + 1), 1, ®_addr) !=0)
goto release;
- if (reg_addr == MII_IGPHY_PAGE_SELECT)
+ if (reg_addr == IGPHY_PAGE_SELECT)
phy_page = reg_data;
reg_addr &= IGPHY_MAXREGADDR;
@@ -5175,8 +5274,11 @@ wm_init_rss(struct wm_softc *sc)
*/
mrqc |= (MRQC_RSS_FIELD_IPV4 | MRQC_RSS_FIELD_IPV4_TCP);
mrqc |= (MRQC_RSS_FIELD_IPV6 | MRQC_RSS_FIELD_IPV6_TCP);
+#if 0
mrqc |= (MRQC_RSS_FIELD_IPV4_UDP | MRQC_RSS_FIELD_IPV6_UDP);
- mrqc |= (MRQC_RSS_FIELD_IPV6_UDP_EX | MRQC_RSS_FIELD_IPV6_TCP_EX);
+ mrqc |= MRQC_RSS_FIELD_IPV6_UDP_EX;
+#endif
+ mrqc |= MRQC_RSS_FIELD_IPV6_TCP_EX;
CSR_WRITE(sc, WMREG_MRQC, mrqc);
}
@@ -5281,22 +5383,19 @@ wm_is_using_multiqueue(struct wm_softc *
}
static int
-wm_softint_establish(struct wm_softc *sc, int qidx, int intr_idx)
+wm_softint_establish_queue(struct wm_softc *sc, int qidx, int intr_idx)
{
struct wm_queue *wmq = &sc->sc_queue[qidx];
+
wmq->wmq_id = qidx;
wmq->wmq_intr_idx = intr_idx;
- wmq->wmq_si = softint_establish(SOFTINT_NET
-#ifdef WM_MPSAFE
- | SOFTINT_MPSAFE
-#endif
- , wm_handle_queue, wmq);
+ wmq->wmq_si = softint_establish(SOFTINT_NET | WM_SOFTINT_FLAGS,
+ wm_handle_queue, wmq);
if (wmq->wmq_si != NULL)
return 0;
aprint_error_dev(sc->sc_dev, "unable to establish queue[%d] handler\n",
wmq->wmq_id);
-
pci_intr_disestablish(sc->sc_pc, sc->sc_ihs[wmq->wmq_intr_idx]);
sc->sc_ihs[wmq->wmq_intr_idx] = NULL;
return ENOMEM;
@@ -5336,7 +5435,7 @@ wm_setup_legacy(struct wm_softc *sc)
aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr);
sc->sc_nintrs = 1;
- return wm_softint_establish(sc, 0, 0);
+ return wm_softint_establish_queue(sc, 0, 0);
}
static int
@@ -5414,7 +5513,7 @@ wm_setup_msix(struct wm_softc *sc)
"for TX and RX interrupting at %s\n", intrstr);
}
sc->sc_ihs[intr_idx] = vih;
- if (wm_softint_establish(sc, qidx, intr_idx) != 0)
+ if (wm_softint_establish_queue(sc, qidx, intr_idx) != 0)
goto fail;
txrx_established++;
intr_idx++;
@@ -5608,6 +5707,40 @@ out:
#endif
}
+static void
+wm_init_sysctls(struct wm_softc *sc)
+{
+ struct sysctllog **log;
+ const struct sysctlnode *rnode, *cnode;
+ int rv;
+ const char *dvname;
+
+ log = &sc->sc_sysctllog;
+ dvname = device_xname(sc->sc_dev);
+
+ rv = sysctl_createv(log, 0, NULL, &rnode,
+ 0, CTLTYPE_NODE, dvname,
+ SYSCTL_DESCR("wm information and settings"),
+ NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
+ if (rv != 0)
+ goto err;
+
+ rv = sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
+ CTLTYPE_BOOL, "txrx_workqueue", SYSCTL_DESCR("Use workqueue for packet processing"),
+ NULL, 0, &sc->sc_txrx_use_workqueue, 0, CTL_CREATE, CTL_EOL);
+ if (rv != 0)
+ goto teardown;
+
+ return;
+
+teardown:
+ sysctl_teardown(log);
+err:
+ sc->sc_sysctllog = NULL;
+ device_printf(sc->sc_dev, "%s: sysctl_createv failed, rv = %d\n",
+ __func__, rv);
+}
+
/*
* wm_init: [ifnet interface function]
*
@@ -5631,7 +5764,7 @@ wm_init_locked(struct ifnet *ifp)
{
struct wm_softc *sc = ifp->if_softc;
int i, j, trynum, error = 0;
- uint32_t reg;
+ uint32_t reg, sfp_mask = 0;
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
device_xname(sc->sc_dev), __func__));
@@ -5701,6 +5834,7 @@ wm_init_locked(struct ifnet *ifp)
reg &= ~GCR_NO_SNOOP_ALL;
CSR_WRITE(sc, WMREG_GCR, reg);
}
+
if ((sc->sc_type >= WM_T_ICH8)
|| (sc->sc_pcidevid == PCI_PRODUCT_INTEL_82546GB_QUAD_COPPER)
|| (sc->sc_pcidevid == PCI_PRODUCT_INTEL_82546GB_QUAD_COPPER_KSP3)) {
@@ -5750,6 +5884,11 @@ wm_init_locked(struct ifnet *ifp)
if (error)
goto out;
+ if (((sc->sc_flags & WM_F_SGMII) == 0) &&
+ (sc->sc_mediatype == WM_MEDIATYPE_SERDES) &&
+ (sc->sc_type >= WM_T_82575))
+ wm_serdes_power_up_link_82575(sc);
+
/* Clear out the VLAN table -- we don't use it (yet). */
CSR_WRITE(sc, WMREG_VET, 0);
if ((sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354))
@@ -5983,6 +6122,13 @@ wm_init_locked(struct ifnet *ifp)
/* Set up the interrupt registers. */
CSR_WRITE(sc, WMREG_IMC, 0xffffffffU);
+ /* Enable SFP module insertion interrupt if it's required */
+ if ((sc->sc_flags & WM_F_SFP) != 0) {
+ sc->sc_ctrl |= CTRL_EXTLINK_EN;
+ CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+ sfp_mask = ICR_GPI(0);
+ }
+
if (wm_is_using_msix(sc)) {
uint32_t mask;
struct wm_queue *wmq;
@@ -6019,12 +6165,14 @@ wm_init_locked(struct ifnet *ifp)
CSR_WRITE(sc, WMREG_EIAC, mask);
CSR_WRITE(sc, WMREG_EIAM, mask);
CSR_WRITE(sc, WMREG_EIMS, mask);
- CSR_WRITE(sc, WMREG_IMS, ICR_LSC);
+
+ /* For other interrupts */
+ CSR_WRITE(sc, WMREG_IMS, ICR_LSC | sfp_mask);
break;
}
} else {
sc->sc_icr = ICR_TXDW | ICR_LSC | ICR_RXSEQ | ICR_RXDMT0 |
- ICR_RXO | ICR_RXT0;
+ ICR_RXO | ICR_RXT0 | sfp_mask;
CSR_WRITE(sc, WMREG_IMS, sc->sc_icr);
}
@@ -6205,6 +6353,16 @@ wm_stop(struct ifnet *ifp, int disable)
WM_CORE_LOCK(sc);
wm_stop_locked(ifp, disable);
WM_CORE_UNLOCK(sc);
+
+ /*
+ * After wm_set_stopping_flags(), it is guaranteed
+ * wm_handle_queue_work() does not call workqueue_enqueue().
+ * However, workqueue_wait() cannot call in wm_stop_locked()
+ * because it can sleep...
+ * so, call workqueue_wait() here.
+ */
+ for (int i = 0; i < sc->sc_nqueues; i++)
+ workqueue_wait(sc->sc_queue_wq, &sc->sc_queue[i].wmq_cookie);
}
static void
@@ -6720,6 +6878,7 @@ wm_alloc_txrx_queues(struct wm_softc *sc
WM_Q_MISC_EVCNT_ATTACH(txq, toomanyseg, txq, i, xname);
WM_Q_MISC_EVCNT_ATTACH(txq, defrag, txq, i, xname);
WM_Q_MISC_EVCNT_ATTACH(txq, underrun, txq, i, xname);
+ WM_Q_MISC_EVCNT_ATTACH(txq, skipcontext, txq, i, xname);
#endif /* WM_EVENT_COUNTERS */
tx_done++;
@@ -6852,6 +7011,7 @@ wm_free_txrx_queues(struct wm_softc *sc)
WM_Q_EVCNT_DETACH(txq, toomanyseg, txq, i);
WM_Q_EVCNT_DETACH(txq, defrag, txq, i);
WM_Q_EVCNT_DETACH(txq, underrun, txq, i);
+ WM_Q_EVCNT_DETACH(txq, skipcontext, txq, i);
#endif /* WM_EVENT_COUNTERS */
/* Drain txq_interq */
@@ -7137,7 +7297,7 @@ wm_init_txrx_queues(struct wm_softc *sc)
* Set up TCP/IP checksumming parameters for the
* specified packet.
*/
-static int
+static void
wm_tx_offload(struct wm_softc *sc, struct wm_txqueue *txq,
struct wm_txsoft *txs, uint32_t *cmdp, uint8_t *fieldsp)
{
@@ -7167,9 +7327,12 @@ wm_tx_offload(struct wm_softc *sc, struc
default:
/* Don't support this protocol or encapsulation. */
+ txq->txq_last_hw_cmd = txq->txq_last_hw_fields = 0;
+ txq->txq_last_hw_ipcs = 0;
+ txq->txq_last_hw_tucs = 0;
*fieldsp = 0;
*cmdp = 0;
- return 0;
+ return;
}
if ((m0->m_pkthdr.csum_flags &
@@ -7306,13 +7469,51 @@ wm_tx_offload(struct wm_softc *sc, struc
WTX_TCPIP_TUCSE(0) /* Rest of packet */;
}
+ *cmdp = cmd;
+ *fieldsp = fields;
+
/*
* We don't have to write context descriptor for every packet
* except for 82574. For 82574, we must write context descriptor
* for every packet when we use two descriptor queues.
- * It would be overhead to write context descriptor for every packet,
- * however it does not cause problems.
- */
+ *
+ * The 82574L can only remember the *last* context used
+ * regardless of queue that it was use for. We cannot reuse
+ * contexts on this hardware platform and must generate a new
+ * context every time. 82574L hardware spec, section 7.2.6,
+ * second note.
+ */
+ if (sc->sc_nqueues < 2) {
+ /*
+ *
+ * Setting up new checksum offload context for every
+ * frames takes a lot of processing time for hardware.
+ * This also reduces performance a lot for small sized
+ * frames so avoid it if driver can use previously
+ * configured checksum offload context.
+ * For TSO, in theory we can use the same TSO context only if
+ * frame is the same type(IP/TCP) and the same MSS. However
+ * checking whether a frame has the same IP/TCP structure is
+ * hard thing so just ignore that and always restablish a
+ * new TSO context.
+ */
+ if ((m0->m_pkthdr.csum_flags & (M_CSUM_TSOv4 | M_CSUM_TSOv6))
+ == 0) {
+ if (txq->txq_last_hw_cmd == cmd &&
+ txq->txq_last_hw_fields == fields &&
+ txq->txq_last_hw_ipcs == (ipcs & 0xffff) &&
+ txq->txq_last_hw_tucs == (tucs & 0xffff)) {
+ WM_Q_EVCNT_INCR(txq, skipcontext);
+ return;
+ }
+ }
+
+ txq->txq_last_hw_cmd = cmd;
+ txq->txq_last_hw_fields = fields;
+ txq->txq_last_hw_ipcs = (ipcs & 0xffff);
+ txq->txq_last_hw_tucs = (tucs & 0xffff);
+ }
+
/* Fill in the context descriptor. */
t = (struct livengood_tcpip_ctxdesc *)
&txq->txq_descs[txq->txq_next];
@@ -7324,11 +7525,6 @@ wm_tx_offload(struct wm_softc *sc, struc
txq->txq_next = WM_NEXTTX(txq, txq->txq_next);
txs->txs_ndesc++;
-
- *cmdp = cmd;
- *fieldsp = fields;
-
- return 0;
}
static inline int
@@ -7610,13 +7806,10 @@ retry:
(M_CSUM_TSOv4 | M_CSUM_TSOv6 |
M_CSUM_IPv4 | M_CSUM_TCPv4 | M_CSUM_UDPv4 |
M_CSUM_TCPv6 | M_CSUM_UDPv6)) {
- if (wm_tx_offload(sc, txq, txs, &cksumcmd,
- &cksumfields) != 0) {
- /* Error message already displayed. */
- bus_dmamap_unload(sc->sc_dmat, dmamap);
- continue;
- }
+ wm_tx_offload(sc, txq, txs, &cksumcmd, &cksumfields);
} else {
+ txq->txq_last_hw_cmd = txq->txq_last_hw_fields = 0;
+ txq->txq_last_hw_ipcs = txq->txq_last_hw_tucs = 0;
cksumcmd = 0;
cksumfields = 0;
}
@@ -7751,7 +7944,7 @@ retry:
* Set up TCP/IP checksumming parameters for the
* specified packet, for NEWQUEUE devices
*/
-static int
+static void
wm_nq_tx_offload(struct wm_softc *sc, struct wm_txqueue *txq,
struct wm_txsoft *txs, uint32_t *cmdlenp, uint32_t *fieldsp, bool *do_csum)
{
@@ -7781,7 +7974,7 @@ wm_nq_tx_offload(struct wm_softc *sc, st
default:
/* Don't support this protocol or encapsulation. */
*do_csum = false;
- return 0;
+ return;
}
*do_csum = true;
*cmdlenp = NQTX_DTYP_D | NQTX_CMD_DEXT | NQTX_CMD_IFCS;
@@ -7947,7 +8140,6 @@ wm_nq_tx_offload(struct wm_softc *sc, st
DPRINTF(WM_DEBUG_TX, ("\t0x%08x%08x\n", mssidx, cmdc));
txq->txq_next = WM_NEXTTX(txq, txq->txq_next);
txs->txs_ndesc++;
- return 0;
}
/*
@@ -8184,12 +8376,8 @@ retry:
(M_CSUM_TSOv4 | M_CSUM_TSOv6 |
M_CSUM_IPv4 | M_CSUM_TCPv4 | M_CSUM_UDPv4 |
M_CSUM_TCPv6 | M_CSUM_UDPv6)) {
- if (wm_nq_tx_offload(sc, txq, txs, &cmdlen, &fields,
- &do_csum) != 0) {
- /* Error message already displayed. */
- bus_dmamap_unload(sc->sc_dmat, dmamap);
- continue;
- }
+ wm_nq_tx_offload(sc, txq, txs, &cmdlen, &fields,
+ &do_csum);
} else {
do_csum = false;
cmdlen = 0;
@@ -8225,7 +8413,7 @@ retry:
htole64(dmamap->dm_segs[0].ds_addr);
KASSERT((dmamap->dm_segs[0].ds_len & cmdlen) == 0);
txq->txq_nq_descs[nexttx].nqtx_data.nqtxd_cmdlen =
- htole32(dmamap->dm_segs[0].ds_len | cmdlen );
+ htole32(dmamap->dm_segs[0].ds_len | cmdlen);
txq->txq_nq_descs[nexttx].nqtx_data.nqtxd_fields =
htole32(fields);
DPRINTF(WM_DEBUG_TX,
@@ -9186,6 +9374,17 @@ wm_linkintr(struct wm_softc *sc, uint32_
wm_linkintr_tbi(sc, icr);
}
+
+static inline void
+wm_sched_handle_queue(struct wm_softc *sc, struct wm_queue *wmq)
+{
+
+ if (wmq->wmq_txrx_use_workqueue)
+ workqueue_enqueue(sc->sc_queue_wq, &wmq->wmq_cookie, curcpu());
+ else
+ softint_schedule(wmq->wmq_si);
+}
+
/*
* wm_intr_legacy:
*
@@ -9270,6 +9469,8 @@ wm_intr_legacy(void *arg)
WM_EVCNT_INCR(&sc->sc_ev_linkintr);
wm_linkintr(sc, icr);
}
+ if ((icr & ICR_GPI(0)) != 0)
+ device_printf(sc->sc_dev, "got module interrupt\n");
WM_CORE_UNLOCK(sc);
@@ -9285,7 +9486,8 @@ wm_intr_legacy(void *arg)
if (handled) {
/* Try to get more packets going. */
- softint_schedule(wmq->wmq_si);
+ wmq->wmq_txrx_use_workqueue = sc->sc_txrx_use_workqueue;
+ wm_sched_handle_queue(sc, wmq);
}
return handled;
@@ -9388,9 +9590,10 @@ wm_txrxintr_msix(void *arg)
if (rndval != 0)
rnd_add_uint32(&sc->sc_queue[wmq->wmq_id].rnd_source, rndval);
- if (txmore || rxmore)
- softint_schedule(wmq->wmq_si);
- else
+ if (txmore || rxmore) {
+ wmq->wmq_txrx_use_workqueue = sc->sc_txrx_use_workqueue;
+ wm_sched_handle_queue(sc, wmq);
+ } else
wm_txrxintr_enable(wmq);
return 1;
@@ -9426,12 +9629,24 @@ wm_handle_queue(void *arg)
rxmore = wm_rxeof(rxq, rxlimit);
mutex_exit(rxq->rxq_lock);
- if (txmore || rxmore)
- softint_schedule(wmq->wmq_si);
- else
+ if (txmore || rxmore) {
+ wmq->wmq_txrx_use_workqueue = sc->sc_txrx_use_workqueue;
+ wm_sched_handle_queue(sc, wmq);
+ } else
wm_txrxintr_enable(wmq);
}
+static void
+wm_handle_queue_work(struct work *wk, void *context)
+{
+ struct wm_queue *wmq = container_of(wk, struct wm_queue, wmq_cookie);
+
+ /*
+ * "enqueued flag" is not required here.
+ */
+ wm_handle_queue(wmq);
+}
+
/*
* wm_linkintr_msix:
*
@@ -9457,6 +9672,8 @@ wm_linkintr_msix(void *arg)
WM_EVCNT_INCR(&sc->sc_ev_linkintr);
wm_linkintr(sc, ICR_LSC);
}
+ if ((reg & ICR_GPI(0)) != 0)
+ device_printf(sc->sc_dev, "got module interrupt\n");
/*
* XXX 82574 MSI-X mode workaround
@@ -9728,10 +9945,18 @@ wm_gmii_setup_phytype(struct wm_softc *s
uint16_t doubt_phytype = WMPHY_UNKNOWN;
mii_readreg_t new_readreg;
mii_writereg_t new_writereg;
+ bool dodiag = true;
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
device_xname(sc->sc_dev), __func__));
+ /*
+ * 1000BASE-T SFP uses SGMII and the first asumed PHY type is always
+ * incorrect. So don't print diag output when it's 2nd call.
+ */
+ if ((sc->sc_sfptype != 0) && (phy_oui == 0) && (phy_model == 0))
+ dodiag = false;
+
if (mii->mii_readreg == NULL) {
/*
* This is the first call of this function. For ICH and PCH
@@ -9848,16 +10073,20 @@ wm_gmii_setup_phytype(struct wm_softc *s
default:
break;
}
- if (new_phytype == WMPHY_UNKNOWN)
- aprint_verbose_dev(dev,
- "%s: unknown PHY model. OUI=%06x, model=%04x\n",
- __func__, phy_oui, phy_model);
- if ((sc->sc_phytype != WMPHY_UNKNOWN)
- && (sc->sc_phytype != new_phytype )) {
- aprint_error_dev(dev, "Previously assumed PHY type(%u)"
- "was incorrect. PHY type from PHY ID = %u\n",
- sc->sc_phytype, new_phytype);
+ if (dodiag) {
+ if (new_phytype == WMPHY_UNKNOWN)
+ aprint_verbose_dev(dev,
+ "%s: Unknown PHY model. OUI=%06x, "
+ "model=%04x\n", __func__, phy_oui,
+ phy_model);
+
+ if ((sc->sc_phytype != WMPHY_UNKNOWN)
+ && (sc->sc_phytype != new_phytype)) {
+ aprint_error_dev(dev, "Previously assumed PHY "
+ "type(%u) was incorrect. PHY type from PHY"
+ "ID = %u\n", sc->sc_phytype, new_phytype);
+ }
}
}
@@ -9926,22 +10155,26 @@ wm_gmii_setup_phytype(struct wm_softc *s
}
/* Diag output */
- if (doubt_phytype != WMPHY_UNKNOWN)
- aprint_error_dev(dev, "Assumed new PHY type was "
- "incorrect. old = %u, new = %u\n", sc->sc_phytype,
- new_phytype);
- else if ((sc->sc_phytype != WMPHY_UNKNOWN)
- && (sc->sc_phytype != new_phytype ))
- aprint_error_dev(dev, "Previously assumed PHY type(%u)"
- "was incorrect. New PHY type = %u\n",
- sc->sc_phytype, new_phytype);
-
- if ((mii->mii_readreg != NULL) && (new_phytype == WMPHY_UNKNOWN))
- aprint_error_dev(dev, "PHY type is still unknown.\n");
-
- if ((mii->mii_readreg != NULL) && (mii->mii_readreg != new_readreg))
- aprint_error_dev(dev, "Previously assumed PHY read/write "
- "function was incorrect.\n");
+ if (dodiag) {
+ if (doubt_phytype != WMPHY_UNKNOWN)
+ aprint_error_dev(dev, "Assumed new PHY type was "
+ "incorrect. old = %u, new = %u\n", sc->sc_phytype,
+ new_phytype);
+ else if ((sc->sc_phytype != WMPHY_UNKNOWN)
+ && (sc->sc_phytype != new_phytype))
+ aprint_error_dev(dev, "Previously assumed PHY type(%u)"
+ "was incorrect. New PHY type = %u\n",
+ sc->sc_phytype, new_phytype);
+
+ if ((mii->mii_readreg != NULL) &&
+ (new_phytype == WMPHY_UNKNOWN))
+ aprint_error_dev(dev, "PHY type is still unknown.\n");
+
+ if ((mii->mii_readreg != NULL) &&
+ (mii->mii_readreg != new_readreg))
+ aprint_error_dev(dev, "Previously assumed PHY "
+ "read/write function was incorrect.\n");
+ }
/* Update now */
sc->sc_phytype = new_phytype;
@@ -9994,7 +10227,6 @@ wm_get_phy_id_82575(struct wm_softc *sc)
return phyid;
}
-
/*
* wm_gmii_mediainit:
*
@@ -10006,7 +10238,6 @@ wm_gmii_mediainit(struct wm_softc *sc, p
device_t dev = sc->sc_dev;
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
struct mii_data *mii = &sc->sc_mii;
- uint32_t reg;
DPRINTF(WM_DEBUG_GMII, ("%s: %s called\n",
device_xname(sc->sc_dev), __func__));
@@ -10019,15 +10250,6 @@ wm_gmii_mediainit(struct wm_softc *sc, p
else
sc->sc_tipg = TIPG_1000T_DFLT;
- /* XXX Not for I354? FreeBSD's e1000_82575.c doesn't include it */
- if ((sc->sc_type == WM_T_82580)
- || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I210)
- || (sc->sc_type == WM_T_I211)) {
- reg = CSR_READ(sc, WMREG_PHPM);
- reg &= ~PHPM_GO_LINK_D;
- CSR_WRITE(sc, WMREG_PHPM, reg);
- }
-
/*
* Let the chip set speed/duplex on its own based on
* signals from the PHY.
@@ -10054,6 +10276,9 @@ wm_gmii_mediainit(struct wm_softc *sc, p
ifmedia_init(&mii->mii_media, IFM_IMASK, wm_gmii_mediachange,
wm_gmii_mediastatus);
+ /* Setup internal SGMII PHY for SFP */
+ wm_sgmii_sfp_preconfig(sc);
+
if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)
|| (sc->sc_type == WM_T_82580)
|| (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I354)
@@ -10080,11 +10305,19 @@ wm_gmii_mediainit(struct wm_softc *sc, p
CSR_WRITE_FLUSH(sc);
delay(300*1000); /* XXX too long */
- /* From 1 to 8 */
+ /*
+ * From 1 to 8.
+ *
+ * I2C access fails with I2C register's ERROR
+ * bit set, so prevent error message while
+ * scanning.
+ */
+ sc->phy.no_errprint = true;
for (i = 1; i < 8; i++)
mii_attach(sc->sc_dev, &sc->sc_mii,
0xffffffff, i, MII_OFFSET_ANY,
MIIF_DOPAUSE);
+ sc->phy.no_errprint = false;
/* Restore previous sfp cage power state */
CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext);
@@ -10153,6 +10386,7 @@ wm_gmii_mediachange(struct ifnet *ifp)
{
struct wm_softc *sc = ifp->if_softc;
struct ifmedia_entry *ife = sc->sc_mii.mii_media.ifm_cur;
+ uint32_t reg;
int rc;
DPRINTF(WM_DEBUG_GMII, ("%s: %s called\n",
@@ -10160,6 +10394,15 @@ wm_gmii_mediachange(struct ifnet *ifp)
if ((ifp->if_flags & IFF_UP) == 0)
return 0;
+ /* XXX Not for I354? FreeBSD's e1000_82575.c doesn't include it */
+ if ((sc->sc_type == WM_T_82580)
+ || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I210)
+ || (sc->sc_type == WM_T_I211)) {
+ reg = CSR_READ(sc, WMREG_PHPM);
+ reg &= ~PHPM_GO_LINK_D;
+ CSR_WRITE(sc, WMREG_PHPM, reg);
+ }
+
/* Disable D0 LPLU. */
wm_lplu_d0_disable(sc);
@@ -10193,8 +10436,18 @@ wm_gmii_mediachange(struct ifnet *ifp)
}
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
CSR_WRITE_FLUSH(sc);
+
+ if ((sc->sc_type >= WM_T_82575) && (sc->sc_type <= WM_T_I211))
+ wm_serdes_mediachange(ifp);
+
if (sc->sc_type <= WM_T_82543)
wm_gmii_reset(sc);
+ else if ((sc->sc_type >= WM_T_82575) && (sc->sc_type <= WM_T_I211)
+ && ((sc->sc_flags & WM_F_SGMII) != 0)) {
+ /* allow time for SFP cage time to power up phy */
+ delay(300 * 1000);
+ wm_gmii_reset(sc);
+ }
if ((rc = mii_mediachg(&sc->sc_mii)) == ENXIO)
return 0;
@@ -10464,7 +10717,7 @@ wm_gmii_i82544_readreg_locked(device_t d
case WMPHY_IGP:
case WMPHY_IGP_2:
case WMPHY_IGP_3:
- wm_gmii_mdic_writereg(dev, phy, MII_IGPHY_PAGE_SELECT,
+ wm_gmii_mdic_writereg(dev, phy, IGPHY_PAGE_SELECT,
reg);
break;
default:
@@ -10510,7 +10763,7 @@ wm_gmii_i82544_writereg_locked(device_t
case WMPHY_IGP:
case WMPHY_IGP_2:
case WMPHY_IGP_3:
- wm_gmii_mdic_writereg(dev, phy, MII_IGPHY_PAGE_SELECT,
+ wm_gmii_mdic_writereg(dev, phy, IGPHY_PAGE_SELECT,
reg);
break;
default:
@@ -10666,7 +10919,7 @@ wm_gmii_bm_readreg(device_t dev, int phy
if ((phy == 1) && (sc->sc_type != WM_T_82574)
&& (sc->sc_type != WM_T_82583))
wm_gmii_mdic_writereg(dev, phy,
- MII_IGPHY_PAGE_SELECT, page << BME1000_PAGE_SHIFT);
+ IGPHY_PAGE_SELECT, page << BME1000_PAGE_SHIFT);
else
wm_gmii_mdic_writereg(dev, phy,
BME1000_PHY_PAGE_SELECT, page);
@@ -10713,7 +10966,7 @@ wm_gmii_bm_writereg(device_t dev, int ph
if ((phy == 1) && (sc->sc_type != WM_T_82574)
&& (sc->sc_type != WM_T_82583))
wm_gmii_mdic_writereg(dev, phy,
- MII_IGPHY_PAGE_SELECT, page << BME1000_PAGE_SHIFT);
+ IGPHY_PAGE_SELECT, page << BME1000_PAGE_SHIFT);
else
wm_gmii_mdic_writereg(dev, phy,
BME1000_PHY_PAGE_SELECT, page);
@@ -10747,7 +11000,7 @@ wm_enable_phy_wakeup_reg_access_bm(devic
/* All page select, port ctrl and wakeup registers use phy address 1 */
/* Select Port Control Registers page */
- wm_gmii_mdic_writereg(dev, 1, MII_IGPHY_PAGE_SELECT,
+ wm_gmii_mdic_writereg(dev, 1, IGPHY_PAGE_SELECT,
BM_PORT_CTRL_PAGE << IGP3_PAGE_SHIFT);
/* Read WUCE and save it */
@@ -10765,7 +11018,7 @@ wm_enable_phy_wakeup_reg_access_bm(devic
/* Select Host Wakeup Registers page - caller now able to write
* registers on the Wakeup registers page
*/
- wm_gmii_mdic_writereg(dev, 1, MII_IGPHY_PAGE_SELECT,
+ wm_gmii_mdic_writereg(dev, 1, IGPHY_PAGE_SELECT,
BM_WUC_PAGE << IGP3_PAGE_SHIFT);
return 0;
@@ -10793,7 +11046,7 @@ wm_disable_phy_wakeup_reg_access_bm(devi
return -1;
/* Select Port Control Registers page */
- wm_gmii_mdic_writereg(dev, 1, MII_IGPHY_PAGE_SELECT,
+ wm_gmii_mdic_writereg(dev, 1, IGPHY_PAGE_SELECT,
BM_PORT_CTRL_PAGE << IGP3_PAGE_SHIFT);
/* Restore 769.17 to its original value */
@@ -10935,7 +11188,7 @@ wm_gmii_hv_readreg_locked(device_t dev,
page = 0;
if (regnum > BME1000_MAX_MULTI_PAGE_REG) {
- wm_gmii_mdic_writereg(dev, 1, MII_IGPHY_PAGE_SELECT,
+ wm_gmii_mdic_writereg(dev, 1, IGPHY_PAGE_SELECT,
page << BME1000_PAGE_SHIFT);
}
@@ -11020,7 +11273,7 @@ wm_gmii_hv_writereg_locked(device_t dev,
}
if (regnum > BME1000_MAX_MULTI_PAGE_REG) {
- wm_gmii_mdic_writereg(dev, 1, MII_IGPHY_PAGE_SELECT,
+ wm_gmii_mdic_writereg(dev, 1, IGPHY_PAGE_SELECT,
page << BME1000_PAGE_SHIFT);
}
}
@@ -11337,6 +11590,38 @@ wm_sgmii_uses_mdio(struct wm_softc *sc)
return ismdio;
}
+/* Setup internal SGMII PHY for SFP */
+static void
+wm_sgmii_sfp_preconfig(struct wm_softc *sc)
+{
+ uint16_t id1, id2, phyreg;
+ int i, rv;
+
+ if (((sc->sc_flags & WM_F_SGMII) == 0)
+ || ((sc->sc_flags & WM_F_SFP) == 0))
+ return;
+
+ for (i = 0; i < MII_NPHY; i++) {
+ sc->phy.no_errprint = true;
+ rv = sc->phy.readreg_locked(sc->sc_dev, i, MII_PHYIDR1, &id1);
+ if (rv != 0)
+ continue;
+ rv = sc->phy.readreg_locked(sc->sc_dev, i, MII_PHYIDR2, &id2);
+ if (rv != 0)
+ continue;
+ if (MII_OUI(id1, id2) != MII_OUI_xxMARVELL)
+ continue;
+ sc->phy.no_errprint = false;
+
+ sc->phy.readreg_locked(sc->sc_dev, i, MAKPHY_ESSR, &phyreg);
+ phyreg &= ~(ESSR_SER_ANEG_BYPASS | ESSR_HWCFG_MODE);
+ phyreg |= ESSR_SGMII_WOC_COPPER;
+ sc->phy.writereg_locked(sc->sc_dev, i, MAKPHY_ESSR, phyreg);
+ break;
+ }
+
+}
+
/*
* wm_sgmii_readreg: [mii interface function]
*
@@ -11349,7 +11634,7 @@ wm_sgmii_readreg(device_t dev, int phy,
{
struct wm_softc *sc = device_private(dev);
uint32_t i2ccmd;
- int i, rv;
+ int i, rv = 0;
if (sc->phy.acquire(sc)) {
device_printf(dev, "%s: failed to get semaphore\n", __func__);
@@ -11367,13 +11652,20 @@ wm_sgmii_readreg(device_t dev, int phy,
if (i2ccmd & I2CCMD_READY)
break;
}
- if ((i2ccmd & I2CCMD_READY) == 0)
+ if ((i2ccmd & I2CCMD_READY) == 0) {
device_printf(dev, "I2CCMD Read did not complete\n");
- if ((i2ccmd & I2CCMD_ERROR) != 0)
- device_printf(dev, "I2CCMD Error bit set\n");
+ goto out;
+ }
+ if ((i2ccmd & I2CCMD_ERROR) != 0) {
+ if (!sc->phy.no_errprint)
+ device_printf(dev, "%s: I2CCMD Error bit set\n",
+ __func__);
+ goto out;
+ }
rv = ((i2ccmd >> 8) & 0x00ff) | ((i2ccmd << 8) & 0xff00);
+out:
sc->phy.release(sc);
return rv;
}
@@ -11413,7 +11705,7 @@ wm_sgmii_writereg(device_t dev, int phy,
if ((i2ccmd & I2CCMD_READY) == 0)
device_printf(dev, "I2CCMD Write did not complete\n");
if ((i2ccmd & I2CCMD_ERROR) != 0)
- device_printf(dev, "I2CCMD Error bit set\n");
+ device_printf(dev, "%s: I2CCMD Error bit set\n", __func__);
sc->phy.release(sc);
}
@@ -11459,6 +11751,7 @@ wm_tbi_mediainit(struct wm_softc *sc)
sc->sc_mii.mii_ifp = ifp;
sc->sc_ethercom.ec_mii = &sc->sc_mii;
+ ifp->if_baudrate = IF_Gbps(1);
if (((sc->sc_type >= WM_T_82575) && (sc->sc_type <= WM_T_I211))
&& (sc->sc_mediatype == WM_MEDIATYPE_SERDES))
ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK,
@@ -11506,6 +11799,31 @@ do { \
/* Only 82545 is LX (XXX except SFP) */
ADD("1000baseLX", IFM_1000_LX, ANAR_X_HD);
ADD("1000baseLX-FDX", IFM_1000_LX | IFM_FDX, ANAR_X_FD);
+ } else if (sc->sc_sfptype != 0) {
+ /* XXX wm(4) fiber/serdes don't use ifm_data */
+ switch (sc->sc_sfptype) {
+ default:
+ case SFF_SFP_ETH_FLAGS_1000SX:
+ ADD("1000baseSX", IFM_1000_SX, ANAR_X_HD);
+ ADD("1000baseSX-FDX", IFM_1000_SX | IFM_FDX, ANAR_X_FD);
+ break;
+ case SFF_SFP_ETH_FLAGS_1000LX:
+ ADD("1000baseLX", IFM_1000_LX, ANAR_X_HD);
+ ADD("1000baseLX-FDX", IFM_1000_LX | IFM_FDX, ANAR_X_FD);
+ break;
+ case SFF_SFP_ETH_FLAGS_1000CX:
+ ADD("1000baseCX", IFM_1000_CX, ANAR_X_HD);
+ ADD("1000baseCX-FDX", IFM_1000_CX | IFM_FDX, ANAR_X_FD);
+ break;
+ case SFF_SFP_ETH_FLAGS_1000T:
+ ADD("1000baseT", IFM_1000_T, 0);
+ ADD("1000baseT-FDX", IFM_1000_T | IFM_FDX, 0);
+ break;
+ case SFF_SFP_ETH_FLAGS_100FX:
+ ADD("100baseFX", IFM_100_FX, ANAR_TX);
+ ADD("100baseFX-FDX", IFM_100_FX | IFM_FDX, ANAR_TX_FD);
+ break;
+ }
} else {
ADD("1000baseSX", IFM_1000_SX, ANAR_X_HD);
ADD("1000baseSX-FDX", IFM_1000_SX | IFM_FDX, ANAR_X_FD);
@@ -11823,14 +12141,19 @@ wm_serdes_power_up_link_82575(struct wm_
&& ((sc->sc_flags & WM_F_SGMII) == 0))
return;
+ /* Enable PCS to turn on link */
reg = CSR_READ(sc, WMREG_PCS_CFG);
reg |= PCS_CFG_PCS_EN;
CSR_WRITE(sc, WMREG_PCS_CFG, reg);
+ /* Power up the laser */
reg = CSR_READ(sc, WMREG_CTRL_EXT);
reg &= ~CTRL_EXT_SWDPIN(3);
CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
+
+ /* Flush the write to verify completion */
CSR_WRITE_FLUSH(sc);
+ delay(1000);
}
static int
@@ -11840,23 +12163,37 @@ wm_serdes_mediachange(struct ifnet *ifp)
bool pcs_autoneg = true; /* XXX */
uint32_t ctrl_ext, pcs_lctl, reg;
+ if ((sc->sc_mediatype != WM_MEDIATYPE_SERDES)
+ && ((sc->sc_flags & WM_F_SGMII) == 0))
+ return 0;
+
/* XXX Currently, this function is not called on 8257[12] */
if ((sc->sc_type == WM_T_82571) || (sc->sc_type == WM_T_82572)
|| (sc->sc_type >= WM_T_82575))
CSR_WRITE(sc, WMREG_SCTL, SCTL_DISABLE_SERDES_LOOPBACK);
- wm_serdes_power_up_link_82575(sc);
+ /* Power on the sfp cage if present */
+ ctrl_ext = CSR_READ(sc, WMREG_CTRL_EXT);
+ ctrl_ext &= ~CTRL_EXT_SWDPIN(3);
+ ctrl_ext |= CTRL_EXT_I2C_ENA;
+ CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext);
sc->sc_ctrl |= CTRL_SLU;
- if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576))
+ if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)) {
sc->sc_ctrl |= CTRL_SWDPIN(0) | CTRL_SWDPIN(1);
- ctrl_ext = CSR_READ(sc, WMREG_CTRL_EXT);
+ reg = CSR_READ(sc, WMREG_CONNSW);
+ reg |= CONNSW_ENRGSRC;
+ CSR_WRITE(sc, WMREG_CONNSW, reg);
+ }
+
pcs_lctl = CSR_READ(sc, WMREG_PCS_LCTL);
switch (ctrl_ext & CTRL_EXT_LINK_MODE_MASK) {
case CTRL_EXT_LINK_MODE_SGMII:
+ /* SGMII mode lets the phy handle forcing speed/duplex */
pcs_autoneg = true;
+ /* Autoneg time out should be disabled for SGMII mode */
pcs_lctl &= ~PCS_LCTL_AN_TIMEOUT;
break;
case CTRL_EXT_LINK_MODE_1000KX:
@@ -11870,14 +12207,23 @@ wm_serdes_mediachange(struct ifnet *ifp)
}
sc->sc_ctrl |= CTRL_SPEED_1000 | CTRL_FRCSPD | CTRL_FD
| CTRL_FRCFDX;
+
+ /* Set speed of 1000/Full if speed/duplex is forced */
pcs_lctl |= PCS_LCTL_FSV_1000 | PCS_LCTL_FDV_FULL;
}
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
+ pcs_lctl &= ~(PCS_LCTL_AN_ENABLE | PCS_LCTL_FLV_LINK_UP |
+ PCS_LCTL_FSD | PCS_LCTL_FORCE_LINK);
+
if (pcs_autoneg) {
+ /* Set PCS register for autoneg */
pcs_lctl |= PCS_LCTL_AN_ENABLE | PCS_LCTL_AN_RESTART;
+
+ /* Disable force flow control for autoneg */
pcs_lctl &= ~PCS_LCTL_FORCE_FC;
+ /* Configure flow control advertisement for autoneg */
reg = CSR_READ(sc, WMREG_PCS_ANADV);
reg &= ~(TXCW_ASYM_PAUSE | TXCW_SYM_PAUSE);
reg |= TXCW_ASYM_PAUSE | TXCW_SYM_PAUSE;
@@ -11887,7 +12233,6 @@ wm_serdes_mediachange(struct ifnet *ifp)
CSR_WRITE(sc, WMREG_PCS_LCTL, pcs_lctl);
-
return 0;
}
@@ -11938,6 +12283,7 @@ wm_serdes_mediastatus(struct ifnet *ifp,
break;
}
}
+ ifp->if_baudrate = ifmedia_baudrate(ifmr->ifm_active);
if ((reg & PCS_LSTS_FDX) != 0)
ifmr->ifm_active |= IFM_FDX;
else
@@ -12084,7 +12430,7 @@ wm_sfp_get_media_type(struct wm_softc *s
"Module/Connector soldered to board\n");
break;
case SFF_SFP_ID_SFP:
- aprint_normal_dev(sc->sc_dev, "SFP\n");
+ sc->sc_flags |= WM_F_SFP;
break;
case SFF_SFP_ID_UNKNOWN:
goto out;
@@ -12096,6 +12442,7 @@ wm_sfp_get_media_type(struct wm_softc *s
if (rv != 0)
goto out;
+ sc->sc_sfptype = val;
if ((val & (SFF_SFP_ETH_FLAGS_1000SX | SFF_SFP_ETH_FLAGS_1000LX)) != 0)
mediatype = WM_MEDIATYPE_SERDES;
else if ((val & SFF_SFP_ETH_FLAGS_1000T) != 0) {
@@ -12104,6 +12451,10 @@ wm_sfp_get_media_type(struct wm_softc *s
} else if ((val & SFF_SFP_ETH_FLAGS_100FX) != 0) {
sc->sc_flags |= WM_F_SGMII;
mediatype = WM_MEDIATYPE_SERDES;
+ } else {
+ device_printf(sc->sc_dev, "%s: unknown media type? (0x%hhx)\n",
+ __func__, sc->sc_sfptype);
+ sc->sc_sfptype = 0; /* XXX unknown */
}
out:
@@ -13005,6 +13356,13 @@ wm_nvm_read_invm(struct wm_softc *sc, in
rv = -1;
}
break;
+ case NVM_OFF_CFG1: /* == INVM_AUTOLOAD */
+ rv = wm_nvm_read_word_invm(sc, offset, data);
+ if (rv != 0) {
+ *data = INVM_DEFAULT_AL;
+ rv = 0;
+ }
+ break;
case NVM_OFF_CFG2:
rv = wm_nvm_read_word_invm(sc, offset, data);
if (rv != 0) {
@@ -13320,7 +13678,8 @@ printver:
}
if (have_uid && (wm_nvm_read(sc, NVM_OFF_IMAGE_UID0, 1, &uid0) == 0))
- aprint_verbose(", Image Unique ID %08x", (uid1 << 16) | uid0);
+ aprint_verbose(", Image Unique ID %08x",
+ ((uint32_t)uid1 << 16) | uid0);
}
/*
@@ -14757,12 +15116,13 @@ wm_enable_wakeup(struct wm_softc *sc)
pme:
/* Request PME */
pmode = pci_conf_read(sc->sc_pc, sc->sc_pcitag, pmreg + PCI_PMCSR);
+ pmode |= PCI_PMCSR_PME_STS; /* in case it's already set (W1C) */
if ((rv == 0) && (sc->sc_flags & WM_F_WOL) != 0) {
/* For WOL */
- pmode |= PCI_PMCSR_PME_STS | PCI_PMCSR_PME_EN;
+ pmode |= PCI_PMCSR_PME_EN;
} else {
/* Disable WOL */
- pmode &= ~(PCI_PMCSR_PME_STS | PCI_PMCSR_PME_EN);
+ pmode &= ~PCI_PMCSR_PME_EN;
}
pci_conf_write(sc->sc_pc, sc->sc_pcitag, pmreg + PCI_PMCSR, pmode);
}
@@ -14846,9 +15206,9 @@ wm_lplu_d0_disable(struct wm_softc *sc)
case WM_T_82573:
case WM_T_82575:
case WM_T_82576:
- reg = mii->mii_readreg(sc->sc_dev, 1, MII_IGPHY_POWER_MGMT);
+ reg = mii->mii_readreg(sc->sc_dev, 1, IGPHY_POWER_MGMT);
reg &= ~PMR_D0_LPLU;
- mii->mii_writereg(sc->sc_dev, 1, MII_IGPHY_POWER_MGMT, reg);
+ mii->mii_writereg(sc->sc_dev, 1, IGPHY_POWER_MGMT, reg);
break;
case WM_T_82580:
case WM_T_I350:
@@ -15030,7 +15390,7 @@ wm_hv_phy_workarounds_ich8lan(struct wm_
/* Select page 0 */
sc->phy.acquire(sc);
- wm_gmii_mdic_writereg(sc->sc_dev, 1, MII_IGPHY_PAGE_SELECT, 0);
+ wm_gmii_mdic_writereg(sc->sc_dev, 1, IGPHY_PAGE_SELECT, 0);
sc->phy.release(sc);
/*
@@ -15633,6 +15993,8 @@ wm_platform_pm_pch_lpt(struct wm_softc *
/*
* I210 Errata 25 and I211 Errata 10
* Slow System Clock.
+ *
+ * Note that this function is called on both FLASH and iNVM case on NetBSD.
*/
static void
wm_pll_workaround_i210(struct wm_softc *sc)
@@ -15658,8 +16020,13 @@ wm_pll_workaround_i210(struct wm_softc *
reg = mdicnfg & ~MDICNFG_DEST;
CSR_WRITE(sc, WMREG_MDICNFG, reg);
- if (wm_nvm_read(sc, INVM_AUTOLOAD, 1, &nvmword) != 0)
+ if (wm_nvm_read(sc, INVM_AUTOLOAD, 1, &nvmword) != 0) {
+ /*
+ * The default value of the Initialization Control Word 1
+ * is the same on both I210's FLASH_HW and I21[01]'s iNVM.
+ */
nvmword = INVM_DEFAULT_AL;
+ }
tmp_nvmword = nvmword | INVM_PLL_WO_VAL;
for (i = 0; i < WM_MAX_PLL_TRIES; i++) {
Index: src/sys/dev/pci/if_wmreg.h
diff -u src/sys/dev/pci/if_wmreg.h:1.98.6.11 src/sys/dev/pci/if_wmreg.h:1.98.6.12
--- src/sys/dev/pci/if_wmreg.h:1.98.6.11 Fri Jan 24 18:43:35 2020
+++ src/sys/dev/pci/if_wmreg.h Wed Aug 5 17:22:46 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wmreg.h,v 1.98.6.11 2020/01/24 18:43:35 martin Exp $ */
+/* $NetBSD: if_wmreg.h,v 1.98.6.12 2020/08/05 17:22:46 martin Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -694,7 +694,7 @@ struct livengood_tcpip_ctxdesc {
#define ICR_RXT0 (1U << 7) /* Rx ring 0 timer */
#define ICR_MDAC (1U << 9) /* MDIO access complete */
#define ICR_RXCFG (1U << 10) /* Receiving /C/ */
-#define ICR_GPI(x) (1U << (x)) /* general purpose interrupts */
+#define ICR_GPI(x) __BIT(11+(x)) /* general purpose interrupts */
#define ICR_RXQ(x) __BIT(20+(x)) /* 82574: Rx queue x interrupt x=0,1 */
#define ICR_TXQ(x) __BIT(22+(x)) /* 82574: Tx queue x interrupt x=0,1 */
#define ICR_OTHER __BIT(24) /* 82574: Other interrupt */
@@ -1474,6 +1474,7 @@ struct livengood_tcpip_ctxdesc {
#define NVM_CFG2_MNGM_NCSI 1
#define NVM_CFG2_MNGM_PT 2
+#define NVM_COMPAT_MAS_EN(x) __BIT(x) /* Media Auto Sense Enable */
#define NVM_COMPAT_SERDES_FORCE_MODE __BIT(14) /* Don't use autonego */
#define NVM_FUTURE_INIT_WORD1_VALID_CHECKSUM 0x0040
@@ -1618,7 +1619,8 @@ struct livengood_tcpip_ctxdesc {
#define SFF_SFP_ETH_FLAGS_1000LX 0x02
#define SFF_SFP_ETH_FLAGS_1000CX 0x04
#define SFF_SFP_ETH_FLAGS_1000T 0x08
-#define SFF_SFP_ETH_FLAGS_100FX 0x10
+#define SFF_SFP_ETH_FLAGS_100LX 0x10
+#define SFF_SFP_ETH_FLAGS_100FX 0x20
/* I21[01] PHY related definitions */
#define GS40G_PAGE_SELECT 0x16
Index: src/sys/dev/pci/if_wmvar.h
diff -u src/sys/dev/pci/if_wmvar.h:1.33.6.5 src/sys/dev/pci/if_wmvar.h:1.33.6.6
--- src/sys/dev/pci/if_wmvar.h:1.33.6.5 Thu Mar 7 17:11:53 2019
+++ src/sys/dev/pci/if_wmvar.h Wed Aug 5 17:22:46 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wmvar.h,v 1.33.6.5 2019/03/07 17:11:53 martin Exp $ */
+/* $NetBSD: if_wmvar.h,v 1.33.6.6 2020/08/05 17:22:46 martin Exp $ */
/*
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -97,6 +97,8 @@
#define WM_F_PCS_DIS_AUTONEGO 0x02000000 /* PCS Disable Autonego */
#define WM_F_PLL_WA_I210 0x04000000 /* I21[01] PLL workaround */
#define WM_F_WA_I210_CLSEM 0x08000000 /* I21[01] Semaphore workaround */
+#define WM_F_SFP 0x10000000 /* SFP */
+#define WM_F_MAS 0x20000000 /* Media Auto Sense */
#define WM_FLAGS "\20" \
"\1" "HAS_MII" "\2" "LOCK_EECD" "\3" "_B02" "\4" "_B03" \
@@ -105,7 +107,8 @@
"\15" "PCIX" "\16" "CSA" "\17" "PCIE" "\20" "SGMII" \
"\21" "NEWQUEUE" "\22" "ASF_FIRM" "\23" "ARC_SUBSYS" "\24" "AMT" \
"\25" "MANAGE" "\26" "WOL" "\27" "EEE" "\30" "ATTACHED" \
- "\31" "MDIC_WA" "\32" "PCS_DIS_AUTONEGO" "\33" "PLLWA" "\34" "CLSEMWA"
+ "\31" "MDIC_WA" "\32" "PCS_DIS_AUTONEGO" "\33" "PLLWA" "\34" "CLSEMWA" \
+ "\35" "SFP" "\36" "MAS"
/*
* Variations of Intel gigabit Ethernet controller: