Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F170053378
D59228.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D59228.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D59228: alc(4): correctly detect link speed/state for CCR2004-1G-2XS-PCIe
Attached
Detach File
Event Timeline
Log In to Comment