summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/ffec
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-08-07 14:56:50 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-21 10:29:37 +0200
commitc37f9fba70085fedc8eede7559489d2321393005 (patch)
tree042455ebf1fa89a277a825f72e1ed805d0b4d296 /freebsd/sys/dev/ffec
parentUpdate to FreeBSD head 2017-06-01 (diff)
downloadrtems-libbsd-c37f9fba70085fedc8eede7559489d2321393005.tar.bz2
Update to FreeBSD head 2017-08-01
Git mirror commit f5002f5e5f78cae9f0269d812dc0aedb0339312c. Update #3472.
Diffstat (limited to 'freebsd/sys/dev/ffec')
-rw-r--r--freebsd/sys/dev/ffec/if_ffec.c122
1 files changed, 58 insertions, 64 deletions
diff --git a/freebsd/sys/dev/ffec/if_ffec.c b/freebsd/sys/dev/ffec/if_ffec.c
index b9a0d668..22b2cdfc 100644
--- a/freebsd/sys/dev/ffec/if_ffec.c
+++ b/freebsd/sys/dev/ffec/if_ffec.c
@@ -90,6 +90,7 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
+#include <dev/mii/mii_fdt.h>
#include <rtems/bsd/local/miibus_if.h>
/*
@@ -140,7 +141,6 @@ static struct ofw_compat_data compat_data[] = {
#define TX_MAX_DMA_SEGS 8
#define WATCHDOG_TIMEOUT_SECS 5
-#define STATS_HARVEST_INTERVAL 3
#define MAX_IRQ_COUNT 3
@@ -153,13 +153,6 @@ struct ffec_bufmap {
bus_dmamap_t map;
};
-enum {
- PHY_CONN_UNKNOWN,
- PHY_CONN_MII,
- PHY_CONN_RMII,
- PHY_CONN_RGMII
-};
-
struct ffec_softc {
device_t dev;
device_t miibus;
@@ -172,15 +165,14 @@ struct ffec_softc {
struct resource *mem_res;
void * intr_cookie[MAX_IRQ_COUNT];
struct callout ffec_callout;
- uint8_t phy_conn_type;
+ mii_contype_t phy_conn_type;
uintptr_t fectype;
boolean_t link_is_up;
boolean_t is_attached;
boolean_t is_detaching;
int tx_watchdog_count;
- int stats_harvest_count;
- int rxbuf_align;
- int txbuf_align;
+ int rxbuf_align;
+ int txbuf_align;
bus_dma_tag_t rxdesc_tag;
bus_dmamap_t rxdesc_map;
@@ -320,10 +312,10 @@ ffec_miigasket_setup(struct ffec_softc *sc)
switch (sc->phy_conn_type)
{
- case PHY_CONN_MII:
+ case MII_CONTYPE_MII:
ifmode = 0;
break;
- case PHY_CONN_RMII:
+ case MII_CONTYPE_RMII:
ifmode = FEC_MIIGSK_CFGR_IF_MODE_RMII;
break;
default:
@@ -435,14 +427,17 @@ ffec_miibus_statchg(device_t dev)
rcr |= FEC_RCR_MII_MODE; /* Must always be on even for R[G]MII. */
switch (sc->phy_conn_type) {
- case PHY_CONN_MII:
- break;
- case PHY_CONN_RMII:
+ case MII_CONTYPE_RMII:
rcr |= FEC_RCR_RMII_MODE;
break;
- case PHY_CONN_RGMII:
+ case MII_CONTYPE_RGMII:
+ case MII_CONTYPE_RGMII_ID:
+ case MII_CONTYPE_RGMII_RXID:
+ case MII_CONTYPE_RGMII_TXID:
rcr |= FEC_RCR_RGMII_EN;
break;
+ default:
+ break;
}
switch (IFM_SUBTYPE(mii->mii_media_active)) {
@@ -518,22 +513,41 @@ ffec_media_change(struct ifnet * ifp)
static void ffec_clear_stats(struct ffec_softc *sc)
{
+ uint32_t mibc;
- WR4(sc, FEC_RMON_R_PACKETS, 0);
- WR4(sc, FEC_RMON_R_MC_PKT, 0);
- WR4(sc, FEC_RMON_R_CRC_ALIGN, 0);
- WR4(sc, FEC_RMON_R_UNDERSIZE, 0);
- WR4(sc, FEC_RMON_R_OVERSIZE, 0);
- WR4(sc, FEC_RMON_R_FRAG, 0);
- WR4(sc, FEC_RMON_R_JAB, 0);
- WR4(sc, FEC_RMON_T_PACKETS, 0);
- WR4(sc, FEC_RMON_T_MC_PKT, 0);
- WR4(sc, FEC_RMON_T_CRC_ALIGN, 0);
- WR4(sc, FEC_RMON_T_UNDERSIZE, 0);
- WR4(sc, FEC_RMON_T_OVERSIZE , 0);
- WR4(sc, FEC_RMON_T_FRAG, 0);
- WR4(sc, FEC_RMON_T_JAB, 0);
- WR4(sc, FEC_RMON_T_COL, 0);
+ mibc = RD4(sc, FEC_MIBC_REG);
+
+ /*
+ * On newer hardware the statistic regs are cleared by toggling a bit in
+ * the mib control register. On older hardware the clear procedure is
+ * to disable statistics collection, zero the regs, then re-enable.
+ */
+ if (sc->fectype == FECTYPE_IMX6 || sc->fectype == FECTYPE_MVF) {
+ WR4(sc, FEC_MIBC_REG, mibc | FEC_MIBC_CLEAR);
+ WR4(sc, FEC_MIBC_REG, mibc & ~FEC_MIBC_CLEAR);
+ } else {
+ WR4(sc, FEC_MIBC_REG, mibc | FEC_MIBC_DIS);
+
+ WR4(sc, FEC_IEEE_R_DROP, 0);
+ WR4(sc, FEC_IEEE_R_MACERR, 0);
+ WR4(sc, FEC_RMON_R_CRC_ALIGN, 0);
+ WR4(sc, FEC_RMON_R_FRAG, 0);
+ WR4(sc, FEC_RMON_R_JAB, 0);
+ WR4(sc, FEC_RMON_R_MC_PKT, 0);
+ WR4(sc, FEC_RMON_R_OVERSIZE, 0);
+ WR4(sc, FEC_RMON_R_PACKETS, 0);
+ WR4(sc, FEC_RMON_R_UNDERSIZE, 0);
+ WR4(sc, FEC_RMON_T_COL, 0);
+ WR4(sc, FEC_RMON_T_CRC_ALIGN, 0);
+ WR4(sc, FEC_RMON_T_FRAG, 0);
+ WR4(sc, FEC_RMON_T_JAB, 0);
+ WR4(sc, FEC_RMON_T_MC_PKT, 0);
+ WR4(sc, FEC_RMON_T_OVERSIZE , 0);
+ WR4(sc, FEC_RMON_T_PACKETS, 0);
+ WR4(sc, FEC_RMON_T_UNDERSIZE, 0);
+
+ WR4(sc, FEC_MIBC_REG, mibc);
+ }
}
static void
@@ -541,28 +555,21 @@ ffec_harvest_stats(struct ffec_softc *sc)
{
struct ifnet *ifp;
- /* We don't need to harvest too often. */
- if (++sc->stats_harvest_count < STATS_HARVEST_INTERVAL)
- return;
+ ifp = sc->ifp;
/*
- * Try to avoid harvesting unless the IDLE flag is on, but if it has
- * been too long just go ahead and do it anyway, the worst that'll
- * happen is we'll lose a packet count or two as we clear at the end.
+ * - FEC_IEEE_R_DROP is "dropped due to invalid start frame delimiter"
+ * so it's really just another type of input error.
+ * - FEC_IEEE_R_MACERR is "no receive fifo space"; count as input drops.
*/
- if (sc->stats_harvest_count < (2 * STATS_HARVEST_INTERVAL) &&
- ((RD4(sc, FEC_MIBC_REG) & FEC_MIBC_IDLE) == 0))
- return;
-
- sc->stats_harvest_count = 0;
- ifp = sc->ifp;
-
if_inc_counter(ifp, IFCOUNTER_IPACKETS, RD4(sc, FEC_RMON_R_PACKETS));
if_inc_counter(ifp, IFCOUNTER_IMCASTS, RD4(sc, FEC_RMON_R_MC_PKT));
if_inc_counter(ifp, IFCOUNTER_IERRORS,
RD4(sc, FEC_RMON_R_CRC_ALIGN) + RD4(sc, FEC_RMON_R_UNDERSIZE) +
RD4(sc, FEC_RMON_R_OVERSIZE) + RD4(sc, FEC_RMON_R_FRAG) +
- RD4(sc, FEC_RMON_R_JAB));
+ RD4(sc, FEC_RMON_R_JAB) + RD4(sc, FEC_IEEE_R_DROP));
+
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, RD4(sc, FEC_IEEE_R_MACERR));
if_inc_counter(ifp, IFCOUNTER_OPACKETS, RD4(sc, FEC_RMON_T_PACKETS));
if_inc_counter(ifp, IFCOUNTER_OMCASTS, RD4(sc, FEC_RMON_T_MC_PKT));
@@ -1132,7 +1139,6 @@ ffec_stop_locked(struct ffec_softc *sc)
ifp = sc->ifp;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->tx_watchdog_count = 0;
- sc->stats_harvest_count = 0;
/*
* Stop the hardware, mask all interrupts, and clear all current
@@ -1311,7 +1317,8 @@ ffec_init_locked(struct ffec_softc *sc)
WR4(sc, FEC_IEM_REG, FEC_IER_TXF | FEC_IER_RXF | FEC_IER_EBERR);
/*
- * MIBC - MIB control (hardware stats).
+ * MIBC - MIB control (hardware stats); clear all statistics regs, then
+ * enable collection of statistics.
*/
regval = RD4(sc, FEC_MIBC_REG);
WR4(sc, FEC_MIBC_REG, regval | FEC_MIBC_DIS);
@@ -1708,7 +1715,6 @@ ffec_attach(device_t dev)
phandle_t ofw_node;
int error, phynum, rid, irq;
uint8_t eaddr[ETHER_ADDR_LEN];
- char phy_conn_name[32];
uint32_t idx, mscr;
sc = device_get_softc(dev);
@@ -1739,20 +1745,8 @@ ffec_attach(device_t dev)
error = ENXIO;
goto out;
}
- if (OF_searchprop(ofw_node, "phy-mode",
- phy_conn_name, sizeof(phy_conn_name)) != -1) {
- if (strcasecmp(phy_conn_name, "mii") == 0)
- sc->phy_conn_type = PHY_CONN_MII;
- else if (strcasecmp(phy_conn_name, "rmii") == 0)
- sc->phy_conn_type = PHY_CONN_RMII;
-#ifndef __rtems__
- else if (strcasecmp(phy_conn_name, "rgmii") == 0)
-#else /* __rtems__ */
- else if (strncasecmp(phy_conn_name, "rgmii", 5) == 0)
-#endif /* __rtems__ */
- sc->phy_conn_type = PHY_CONN_RGMII;
- }
- if (sc->phy_conn_type == PHY_CONN_UNKNOWN) {
+ sc->phy_conn_type = mii_fdt_get_contype(ofw_node);
+ if (sc->phy_conn_type == MII_CONTYPE_UNKNOWN) {
device_printf(sc->dev, "No valid 'phy-mode' "
"property found in FDT data for device.\n");
#ifndef __rtems__