Page MenuHomeFreeBSD

D59228.diff
No OneTemporary

D59228.diff

diff --git a/sys/dev/alc/if_alc.c b/sys/dev/alc/if_alc.c
--- a/sys/dev/alc/if_alc.c
+++ b/sys/dev/alc/if_alc.c
@@ -167,6 +167,7 @@
static void alc_int_task(void *, int);
static int alc_intr(void *);
static int alc_ioctl(if_t, u_long, caddr_t);
+static void alc_link_change(struct alc_softc *);
static void alc_mac_config(struct alc_softc *);
static uint32_t alc_mii_readreg_813x(struct alc_softc *, int, int);
static uint32_t alc_mii_readreg_816x(struct alc_softc *, int, int);
@@ -182,6 +183,8 @@
static int alc_mediachange(if_t);
static int alc_mediachange_locked(struct alc_softc *);
static void alc_mediastatus(if_t, struct ifmediareq *);
+static int alc_mt_link_check(struct alc_softc *);
+static uint32_t alc_mt_media_subtype(uint32_t);
static int alc_newbuf(struct alc_softc *, struct alc_rxdesc *);
static void alc_osc_reset(struct alc_softc *);
static void alc_phy_down(struct alc_softc *);
@@ -412,7 +415,6 @@
struct alc_softc *sc;
struct mii_data *mii;
if_t ifp;
- uint32_t reg;
sc = device_get_softc(dev);
@@ -438,6 +440,19 @@
break;
}
}
+ alc_link_change(sc);
+ alc_aspm(sc, 0, IFM_SUBTYPE(mii->mii_media_active));
+ alc_dsp_fixup(sc, IFM_SUBTYPE(mii->mii_media_active));
+}
+
+/* Reprogram the MACs after ALC_FLAG_LINK was updated. */
+static void
+alc_link_change(struct alc_softc *sc)
+{
+ uint32_t reg;
+
+ ALC_LOCK_ASSERT(sc);
+
/* Stop Rx/Tx MACs. */
alc_stop_mac(sc);
@@ -450,8 +465,61 @@
reg |= MAC_CFG_TX_ENB | MAC_CFG_RX_ENB;
CSR_WRITE_4(sc, ALC_MAC_CFG, reg);
}
- alc_aspm(sc, 0, IFM_SUBTYPE(mii->mii_media_active));
- alc_dsp_fixup(sc, IFM_SUBTYPE(mii->mii_media_active));
+}
+
+/*
+ * Take link state from ALC_MT_SPEED, as the Mikrotik NIC has no PHY and its
+ * MDIO emulation is incomplete. Returns non-zero if it reinitialized.
+ */
+static int
+alc_mt_link_check(struct alc_softc *sc)
+{
+ if_t ifp;
+ uint32_t speed;
+
+ ALC_LOCK_ASSERT(sc);
+
+ ifp = sc->alc_ifp;
+ speed = CSR_READ_4(sc, ALC_MT_SPEED);
+ if (speed == sc->alc_mt_speed)
+ return (0);
+ sc->alc_mt_speed = speed;
+ if (speed == 0) {
+ /*
+ * Frames queued when the link went down never complete and
+ * the Tx indices only resynchronize on a reset, so do that
+ * rather than wait for the watchdog.
+ */
+ sc->alc_flags &= ~ALC_FLAG_LINK;
+ if_setbaudrate(ifp, 0);
+ if_link_state_change(ifp, LINK_STATE_DOWN);
+ if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING);
+ alc_init_locked(sc);
+ return (1);
+ }
+ sc->alc_flags |= ALC_FLAG_LINK;
+ if_setbaudrate(ifp, IF_Mbps((uint64_t)speed));
+ alc_link_change(sc);
+ alc_aspm(sc, 0, IFM_UNKNOWN);
+ if_link_state_change(ifp, LINK_STATE_UP);
+
+ return (0);
+}
+
+static uint32_t
+alc_mt_media_subtype(uint32_t speed)
+{
+
+ switch (speed) {
+ case 1000:
+ return (IFM_1000_SX);
+ case 10000:
+ return (IFM_10G_SR);
+ case 25000:
+ return (IFM_25G_SR);
+ default:
+ return (IFM_OTHER);
+ }
}
static uint32_t
@@ -617,6 +685,18 @@
ALC_UNLOCK(sc);
return;
}
+ if ((sc->alc_flags & ALC_FLAG_MT) != 0) {
+ ifmr->ifm_status = IFM_AVALID;
+ ifmr->ifm_active = IFM_ETHER;
+ if (sc->alc_mt_speed != 0) {
+ ifmr->ifm_status |= IFM_ACTIVE;
+ ifmr->ifm_active |= IFM_FDX |
+ alc_mt_media_subtype(sc->alc_mt_speed);
+ } else
+ ifmr->ifm_active |= IFM_NONE;
+ ALC_UNLOCK(sc);
+ return;
+ }
mii = device_get_softc(sc->alc_miibus);
mii_pollstat(mii);
@@ -648,6 +728,10 @@
ALC_LOCK_ASSERT(sc);
+ /* There is no media to select on controllers without a PHY. */
+ if ((sc->alc_flags & ALC_FLAG_MT) != 0)
+ return (0);
+
mii = device_get_softc(sc->alc_miibus);
LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
PHY_RESET(miisc);
@@ -1601,12 +1685,19 @@
if_setcapenable(ifp, if_getcapabilities(ifp));
/* Set up MII bus. */
- error = mii_attach(dev, &sc->alc_miibus, ifp, alc_mediachange,
- alc_mediastatus, BMSR_DEFCAPMASK, sc->alc_phyaddr, MII_OFFSET_ANY,
- MIIF_DOPAUSE);
- if (error != 0) {
- device_printf(dev, "attaching PHYs failed\n");
- goto fail;
+ if ((sc->alc_flags & ALC_FLAG_MT) == 0) {
+ error = mii_attach(dev, &sc->alc_miibus, ifp, alc_mediachange,
+ alc_mediastatus, BMSR_DEFCAPMASK, sc->alc_phyaddr,
+ MII_OFFSET_ANY, MIIF_DOPAUSE);
+ if (error != 0) {
+ device_printf(dev, "attaching PHYs failed\n");
+ goto fail;
+ }
+ } else {
+ ifmedia_init(&sc->alc_ifmedia, 0, alc_mediachange,
+ alc_mediastatus);
+ ifmedia_add(&sc->alc_ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL);
+ ifmedia_set(&sc->alc_ifmedia, IFM_ETHER | IFM_AUTO);
}
ether_ifattach(ifp, sc->alc_eaddr);
@@ -1701,6 +1792,9 @@
bus_generic_detach(dev);
alc_dma_free(sc);
+ if ((sc->alc_flags & ALC_FLAG_MT) != 0)
+ ifmedia_removeall(&sc->alc_ifmedia);
+
if (ifp != NULL) {
if_free(ifp);
sc->alc_ifp = NULL;
@@ -2457,6 +2551,10 @@
struct mii_data *mii;
int aneg, i;
+ /* The Mikrotik NIC has no PHY to renegotiate with. */
+ if ((sc->alc_flags & ALC_FLAG_MT) != 0)
+ return;
+
mii = device_get_softc(sc->alc_miibus);
mii_pollstat(mii);
aneg = 0;
@@ -3069,6 +3167,10 @@
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
+ if ((sc->alc_flags & ALC_FLAG_MT) != 0) {
+ error = ifmedia_ioctl(ifp, ifr, &sc->alc_ifmedia, cmd);
+ break;
+ }
mii = device_get_softc(sc->alc_miibus);
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
break;
@@ -3135,7 +3237,6 @@
ALC_LOCK_ASSERT(sc);
- mii = device_get_softc(sc->alc_miibus);
reg = CSR_READ_4(sc, ALC_MAC_CFG);
reg &= ~(MAC_CFG_FULL_DUPLEX | MAC_CFG_TX_FC | MAC_CFG_RX_FC |
MAC_CFG_SPEED_MASK);
@@ -3144,6 +3245,13 @@
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151_V2 ||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B2)
reg |= MAC_CFG_HASH_ALG_CRC32 | MAC_CFG_SPEED_MODE_SW;
+ if ((sc->alc_flags & ALC_FLAG_MT) != 0) {
+ /* No encoding for 10G/25G; it is ignored, and always FDX. */
+ reg |= MAC_CFG_SPEED_10_100 | MAC_CFG_FULL_DUPLEX;
+ CSR_WRITE_4(sc, ALC_MAC_CFG, reg);
+ return;
+ }
+ mii = device_get_softc(sc->alc_miibus);
/* Reprogram MAC with resolved speed/duplex. */
switch (IFM_SUBTYPE(mii->mii_media_active)) {
case IFM_10_T:
@@ -3753,8 +3861,12 @@
ALC_LOCK_ASSERT(sc);
- mii = device_get_softc(sc->alc_miibus);
- mii_tick(mii);
+ if ((sc->alc_flags & ALC_FLAG_MT) != 0)
+ alc_mt_link_check(sc);
+ else {
+ mii = device_get_softc(sc->alc_miibus);
+ mii_tick(mii);
+ }
alc_stats_update(sc);
/*
* alc(4) does not rely on Tx completion interrupts to reclaim
@@ -4288,7 +4400,10 @@
sc->alc_flags &= ~ALC_FLAG_LINK;
/* Switch to the current media. */
- alc_mediachange_locked(sc);
+ if ((sc->alc_flags & ALC_FLAG_MT) != 0)
+ alc_mt_link_check(sc);
+ else
+ alc_mediachange_locked(sc);
callout_reset(&sc->alc_tick_ch, hz, alc_tick, sc);
}
@@ -4309,6 +4424,7 @@
ifp = sc->alc_ifp;
if_setdrvflagbits(ifp, 0, (IFF_DRV_RUNNING | IFF_DRV_OACTIVE));
sc->alc_flags &= ~ALC_FLAG_LINK;
+ sc->alc_mt_speed = 0;
callout_stop(&sc->alc_tick_ch);
sc->alc_watchdog_timer = 0;
alc_stats_update(sc);
diff --git a/sys/dev/alc/if_alcvar.h b/sys/dev/alc/if_alcvar.h
--- a/sys/dev/alc/if_alcvar.h
+++ b/sys/dev/alc/if_alcvar.h
@@ -238,6 +238,10 @@
#define ALC_FLAG_LINK 0x10000
#define ALC_FLAG_MT 0x20000
+ /* Media state of controllers that have no PHY. */
+ struct ifmedia alc_ifmedia;
+ uint32_t alc_mt_speed;
+
struct callout alc_tick_ch;
struct alc_hw_stats alc_stats;
struct alc_chain_data alc_cdata;

File Metadata

Mime Type
text/plain
Expires
Fri, Sep 4, 9:19 AM (13 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38207688
Default Alt Text
D59228.diff (7 KB)

Event Timeline