Subject: kern/27379: flow control support for ex(4)
To: None <gnats-bugs@gnats.NetBSD.org>
From: HITOSHI Osada <QFH02545@nifty.com>
List: netbsd-bugs
Date: 10/23/2004 17:27:58
>Number: 27379
>Category: kern
>Synopsis: flow control support for ex(4)
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: kern-bug-people
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sat Oct 23 08:29:00 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator: HITOSHI Osada
>Release: NetBSD 2.99.10 (2004/10/23)
>Organization:
>Environment:
System: NetBSD that 2.99.10 NetBSD 2.99.10 (TIGERMPX) #0: Fri Oct 22 17:43:14 JST 2004 that@that:/sys/arch/i386/compile/TIGERMPX i386
Architecture: i386
Machine: i386
>Description:
I wrote a patch for ex(4) to support flow control(RXPAUSE only).
Tested on my TigerMPX(3c920).
>How-To-Repeat:
>Fix:
Here is a patch.
Index: elinkxl.c
===================================================================
RCS file: /Sources/NetBSD-rep/netbsd/src/sys/dev/ic/elinkxl.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 elinkxl.c
--- elinkxl.c 30 Sep 2004 07:38:42 -0000 1.1.1.3
+++ elinkxl.c 23 Oct 2004 08:20:40 -0000
@@ -407,7 +407,8 @@
ex_set_xcvr(sc, val);
mii_attach(&sc->sc_dev, &sc->ex_mii, 0xffffffff,
- MII_PHY_ANY, MII_OFFSET_ANY, 0);
+ MII_PHY_ANY, MII_OFFSET_ANY,
+ (sc->ex_conf & EX_CONF_90XB) ? MIIF_DOPAUSE : 0 );
if (LIST_FIRST(&sc->ex_mii.mii_phys) == NULL) {
ifmedia_add(&sc->ex_mii.mii_media, IFM_ETHER|IFM_NONE,
0, NULL);
@@ -858,16 +859,18 @@
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
u_int32_t configreg;
+ u_int16_t mctl = 0;
- if (((sc->ex_conf & EX_CONF_MII) &&
- (sc->ex_mii.mii_media_active & IFM_FDX))
- || (!(sc->ex_conf & EX_CONF_MII) &&
- (sc->ex_mii.mii_media.ifm_media & IFM_FDX))) {
- bus_space_write_2(iot, ioh, ELINK_W3_MAC_CONTROL,
- MAC_CONTROL_FDX);
+ if (sc->ex_conf & EX_CONF_MII) {
+ if (sc->ex_mii.mii_media_active & IFM_FDX)
+ mctl |= MAC_CONTROL_FDX;
+ if (sc->ex_flowflags & (IFM_FLOW|IFM_ETH_RXPAUSE))
+ mctl |= ELINK_MAC_FLOWENABLE;
} else {
- bus_space_write_2(iot, ioh, ELINK_W3_MAC_CONTROL, 0);
+ if (sc->ex_mii.mii_media.ifm_media & IFM_FDX)
+ mctl |= MAC_CONTROL_FDX;
}
+ bus_space_write_2(iot, ioh, ELINK_W3_MAC_CONTROL, mctl);
/*
* If the device has MII, select it, and then tell the
@@ -951,7 +954,12 @@
if (sc->ex_conf & EX_CONF_MII) {
mii_pollstat(&sc->ex_mii);
req->ifm_status = sc->ex_mii.mii_media_status;
- req->ifm_active = sc->ex_mii.mii_media_active;
+ if (sc->ex_conf & EX_CONF_90XB) {
+ req->ifm_active = (sc->ex_mii.mii_media_active & ~IFM_ETH_FMASK) |
+ sc->ex_flowflags;
+ } else {
+ req->ifm_active = sc->ex_mii.mii_media_active;
+ }
} else {
GO_WINDOW(4);
req->ifm_status = IFM_AVALID;
@@ -1379,6 +1387,25 @@
switch (cmd) {
case SIOCSIFMEDIA:
+ if ((sc->ex_conf & EX_CONF_MII) && (sc->ex_conf & EX_CONF_90XB)) {
+ if (IFM_SUBTYPE(ifr->ifr_media) == IFM_AUTO ||
+ (ifr->ifr_media & IFM_FDX) == 0) {
+ ifr->ifr_media &= ~IFM_ETH_FMASK;
+ }
+ if (IFM_SUBTYPE(ifr->ifr_media) != IFM_AUTO) {
+ if ((ifr->ifr_media & IFM_ETH_FMASK) == IFM_FLOW) {
+ /* RXPAUSE only */
+ ifr->ifr_media |= IFM_ETH_RXPAUSE;
+ }
+ if (ifr->ifr_media & IFM_FLOW) {
+ sc->ex_flowflags =
+ ifr->ifr_media & (IFM_FLOW|IFM_ETH_RXPAUSE);
+ } else {
+ sc->ex_flowflags = 0;
+ }
+ }
+ }
+ /* FALLTHROUGH */
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &sc->ex_mii.mii_media, cmd);
break;
@@ -1887,16 +1914,32 @@
struct device *v;
{
struct ex_softc *sc = (struct ex_softc *)v;
+ struct mii_data *mii = &sc->ex_mii;
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
- int mctl;
+ u_int16_t mctl;
+ u_int phy_flowflags;
GO_WINDOW(3);
mctl = bus_space_read_2(iot, ioh, ELINK_W3_MAC_CONTROL);
- if (sc->ex_mii.mii_media_active & IFM_FDX)
+ if (mii->mii_media_active & IFM_FDX)
mctl |= MAC_CONTROL_FDX;
else
mctl &= ~MAC_CONTROL_FDX;
+ /* 802.3x flow control */
+ if ((sc->ex_conf & EX_CONF_MII) && (sc->ex_conf & EX_CONF_90XB)) {
+ phy_flowflags = mii->mii_media_active & (IFM_FLOW|IFM_ETH_RXPAUSE);
+ mii->mii_media_active &= ~IFM_ETH_FMASK;
+ if ((IFM_SUBTYPE(mii->mii_media.ifm_cur->ifm_media) == IFM_AUTO) &&
+ (phy_flowflags != sc->ex_flowflags)) {
+ sc->ex_flowflags = phy_flowflags;
+ }
+ if (sc->ex_flowflags & (IFM_FLOW|IFM_ETH_RXPAUSE))
+ mctl |= ELINK_MAC_FLOWENABLE;
+ else
+ mctl &= ~ELINK_MAC_FLOWENABLE;
+ }
+
bus_space_write_2(iot, ioh, ELINK_W3_MAC_CONTROL, mctl);
GO_WINDOW(1); /* back to operating window */
}
Index: elinkxlreg.h
===================================================================
RCS file: /Sources/NetBSD-rep/netbsd/src/sys/dev/ic/elinkxlreg.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- elinkxlreg.h 10 May 2004 09:07:43 -0000 1.1.1.1
+++ elinkxlreg.h 18 Oct 2004 16:12:58 -0000 1.2
@@ -327,3 +327,6 @@
#define EX_UPD_ERR 0x001f4000 /* Errors we check for */
#define EX_UPD_ERR_VLAN 0x000f0000 /* same for 802.1q */
+
+/* 802.3x flow control flag (in MAC Control Register) */
+#define ELINK_MAC_FLOWENABLE 0x100
Index: elinkxlvar.h
===================================================================
RCS file: /Sources/NetBSD-rep/netbsd/src/sys/dev/ic/elinkxlvar.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- elinkxlvar.h 10 May 2004 09:07:43 -0000 1.1.1.1
+++ elinkxlvar.h 18 Oct 2004 16:12:58 -0000 1.2
@@ -122,6 +122,8 @@
#if NRND > 0
rndsource_element_t rnd_source;
#endif
+ /* 802.3x flow control (90xB and later, CONF_MII) */
+ int ex_flowflags;
/* power management hooks */
int (*enable) __P((struct ex_softc *));
>Release-Note:
>Audit-Trail:
>Unformatted: