Module Name: src
Committed By: matt
Date: Thu Mar 18 00:16:18 UTC 2010
Modified Files:
src/sys/arch/mips/sibyte/dev [matt-nb5-mips64]: sbmac.c
Log Message:
Convert to using mutex instead of spl.
To generate a diff of this commit:
cvs rdiff -u -r1.28.24.3 -r1.28.24.4 src/sys/arch/mips/sibyte/dev/sbmac.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/mips/sibyte/dev/sbmac.c
diff -u src/sys/arch/mips/sibyte/dev/sbmac.c:1.28.24.3 src/sys/arch/mips/sibyte/dev/sbmac.c:1.28.24.4
--- src/sys/arch/mips/sibyte/dev/sbmac.c:1.28.24.3 Mon Nov 23 18:46:50 2009
+++ src/sys/arch/mips/sibyte/dev/sbmac.c Thu Mar 18 00:16:17 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: sbmac.c,v 1.28.24.3 2009/11/23 18:46:50 matt Exp $ */
+/* $NetBSD: sbmac.c,v 1.28.24.4 2010/03/18 00:16:17 matt Exp $ */
/*
* Copyright 2000, 2001, 2004
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sbmac.c,v 1.28.24.3 2009/11/23 18:46:50 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sbmac.c,v 1.28.24.4 2010/03/18 00:16:17 matt Exp $");
#include "bpfilter.h"
#include "opt_inet.h"
@@ -45,6 +45,7 @@
#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
+#include <sys/mutex.h>
#include <sys/socket.h>
#include <sys/queue.h>
#include <sys/device.h>
@@ -64,11 +65,6 @@
#include <netinet/if_inarp.h>
#endif
-#ifdef NS
-#include <netns/ns.h>
-#include <netns/ns_if.h>
-#endif
-
#include <machine/locore.h>
#include "sbobiovar.h"
@@ -114,7 +110,7 @@
#define KVTOPHYS(x) kvtophys((vaddr_t)(x))
#ifdef SBMACDEBUG
-#define dprintf(x) printf x
+#define dprintf(x) aprint_debug x
#else
#define dprintf(x)
#endif
@@ -176,12 +172,13 @@
/*
* NetBSD-specific things
*/
- struct device sc_dev; /* base device (must be first) */
+ device_t sc_dev; /* base device (must be first) */
struct ethercom sc_ethercom; /* Ethernet common part */
struct mii_data sc_mii;
struct callout sc_tick_ch;
- int sbm_if_flags;
+ kmutex_t sc_intrlock __aligned(CACHELINESIZE);
+
void *sbm_intrhand;
/*
@@ -209,7 +206,9 @@
sbmacdma_t sbm_txdma; /* for now, only use channel 0 */
sbmacdma_t sbm_rxdma;
- int sbm_pass3_dma; /* chip has pass3 SOC DMA features */
+ bool sbm_pass3_dma; /* chip has pass3 SOC DMA features */
+ bool sbm_promisc; /* chip is in promiscious mode */
+ u_int sbm_mtu; /* last mtu used */
#ifdef SBMAC_EVENT_COUNTERS
struct evcnt sbm_ev_rxintr; /* Rx interrupts */
@@ -235,7 +234,7 @@
/* Prototypes */
-static void sbdma_initctx(sbmacdma_t *d, struct sbmac_softc *s, int chan,
+static void sbdma_initctx(sbmacdma_t *d, struct sbmac_softc *sc, int chan,
int txrx, int maxdescr);
static void sbdma_channel_start(sbmacdma_t *d);
static int sbdma_add_rcvbuffer(sbmacdma_t *d, struct mbuf *m);
@@ -244,52 +243,54 @@
static void sbdma_fillring(sbmacdma_t *d);
static void sbdma_rx_process(struct sbmac_softc *sc, sbmacdma_t *d);
static void sbdma_tx_process(struct sbmac_softc *sc, sbmacdma_t *d);
-static void sbmac_initctx(struct sbmac_softc *s);
-static void sbmac_channel_start(struct sbmac_softc *s);
-static void sbmac_channel_stop(struct sbmac_softc *s);
+static void sbmac_initctx(struct sbmac_softc *sc);
+static void sbmac_channel_start(struct sbmac_softc *sc);
+static void sbmac_channel_stop(struct sbmac_softc *sc);
static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *,
sbmac_state_t);
-static void sbmac_promiscuous_mode(struct sbmac_softc *sc, int onoff);
+static void sbmac_promiscuous_mode(struct sbmac_softc *sc, bool onoff);
static void sbmac_init_and_start(struct sbmac_softc *sc);
static uint64_t sbmac_addr2reg(u_char *ptr);
static void sbmac_intr(void *xsc, uint32_t status, vaddr_t pc);
-static void sbmac_start(struct ifnet *ifp);
+static void sbmac_start(struct sbmac_softc *sc);
static void sbmac_setmulti(struct sbmac_softc *sc);
-static int sbmac_ether_ioctl(struct ifnet *ifp, u_long cmd, void *data);
-static int sbmac_ioctl(struct ifnet *ifp, u_long command, void *data);
-static void sbmac_watchdog(struct ifnet *ifp);
-static int sbmac_match(struct device *parent, struct cfdata *match, void *aux);
-static void sbmac_attach(struct device *parent, struct device *self, void *aux);
-static int sbmac_set_speed(struct sbmac_softc *s, sbmac_speed_t speed);
-static int sbmac_set_duplex(struct sbmac_softc *s, sbmac_duplex_t duplex,
+static void sbmac_ifstart(struct ifnet *ifp);
+static int sbmac_ifinit(struct ifnet *ifp);
+static void sbmac_ifstop(struct ifnet *ifp, int disable);
+static int sbmac_ifioctl(struct ifnet *ifp, u_long command, void *data);
+static void sbmac_ifwatchdog(struct ifnet *ifp);
+static int sbmac_match(device_t parent, cfdata_t match, void *aux);
+static void sbmac_attach(device_t parent, device_t self, void *aux);
+static int sbmac_set_speed(struct sbmac_softc *sc, sbmac_speed_t speed);
+static int sbmac_set_duplex(struct sbmac_softc *sc, sbmac_duplex_t duplex,
sbmac_fc_t fc);
static void sbmac_tick(void *arg);
/* Globals */
-CFATTACH_DECL(sbmac, sizeof(struct sbmac_softc),
+CFATTACH_DECL_NEW(sbmac, sizeof(struct sbmac_softc),
sbmac_match, sbmac_attach, NULL, NULL);
-static uint32_t sbmac_mii_bitbang_read(struct device *self);
-static void sbmac_mii_bitbang_write(struct device *self, uint32_t val);
+static uint32_t sbmac_mii_bitbang_read(device_t self);
+static void sbmac_mii_bitbang_write(device_t self, uint32_t val);
static const struct mii_bitbang_ops sbmac_mii_bitbang_ops = {
- sbmac_mii_bitbang_read,
- sbmac_mii_bitbang_write,
- {
- (uint32_t)M_MAC_MDIO_OUT, /* MII_BIT_MDO */
- (uint32_t)M_MAC_MDIO_IN, /* MII_BIT_MDI */
- (uint32_t)M_MAC_MDC, /* MII_BIT_MDC */
- 0, /* MII_BIT_DIR_HOST_PHY */
- (uint32_t)M_MAC_MDIO_DIR /* MII_BIT_DIR_PHY_HOST */
- }
+ .mbo_read = sbmac_mii_bitbang_read,
+ .mbo_write = sbmac_mii_bitbang_write,
+ .mbo_bits = {
+ [MII_BIT_MDO] = (uint32_t)M_MAC_MDIO_OUT,
+ [MII_BIT_MDI] = (uint32_t)M_MAC_MDIO_IN,
+ [MII_BIT_MDC] = (uint32_t)M_MAC_MDC,
+ [MII_BIT_DIR_HOST_PHY] = 0,
+ [MII_BIT_DIR_PHY_HOST] = (uint32_t)M_MAC_MDIO_DIR,
+ },
};
static uint32_t
-sbmac_mii_bitbang_read(struct device *self)
+sbmac_mii_bitbang_read(device_t self)
{
- struct sbmac_softc *sc = (void *) self;
+ struct sbmac_softc *sc = device_private(self);
sbmac_port_t reg;
reg = PKSEG1(sc->sbm_base + R_MAC_MDIO);
@@ -297,9 +298,9 @@
}
static void
-sbmac_mii_bitbang_write(struct device *self, uint32_t val)
+sbmac_mii_bitbang_write(device_t self, uint32_t val)
{
- struct sbmac_softc *sc = (void *) self;
+ struct sbmac_softc *sc = device_private(self);
sbmac_port_t reg;
reg = PKSEG1(sc->sbm_base + R_MAC_MDIO);
@@ -312,26 +313,26 @@
* Read an PHY register through the MII.
*/
static int
-sbmac_mii_readreg(struct device *self, int phy, int reg)
+sbmac_mii_readreg(device_t self, int phy, int reg)
{
- return (mii_bitbang_readreg(self, &sbmac_mii_bitbang_ops, phy, reg));
+ return mii_bitbang_readreg(self, &sbmac_mii_bitbang_ops, phy, reg);
}
/*
* Write to a PHY register through the MII.
*/
static void
-sbmac_mii_writereg(struct device *self, int phy, int reg, int val)
+sbmac_mii_writereg(device_t self, int phy, int reg, int val)
{
mii_bitbang_writereg(self, &sbmac_mii_bitbang_ops, phy, reg, val);
}
static void
-sbmac_mii_statchg(struct device *self)
+sbmac_mii_statchg(device_t self)
{
- struct sbmac_softc *sc = (struct sbmac_softc *)self;
+ struct sbmac_softc *sc = device_private(self);
sbmac_state_t oldstate;
/* Stop the MAC in preparation for changing all of the parameters. */
@@ -367,7 +368,7 @@
}
/*
- * SBDMA_INITCTX(d, s, chan, txrx, maxdescr)
+ * SBDMA_INITCTX(d, sc, chan, txrx, maxdescr)
*
* Initialize a DMA channel context. Since there are potentially
* eight DMA channels per MAC, it's nice to do this in a standard
@@ -385,14 +386,14 @@
*/
static void
-sbdma_initctx(sbmacdma_t *d, struct sbmac_softc *s, int chan, int txrx,
+sbdma_initctx(sbmacdma_t *d, struct sbmac_softc *sc, int chan, int txrx,
int maxdescr)
{
/*
* Save away interesting stuff in the structure
*/
- d->sbdma_eth = s;
+ d->sbdma_eth = sc;
d->sbdma_channel = chan;
d->sbdma_txdir = txrx;
@@ -400,15 +401,15 @@
* initialize register pointers
*/
- d->sbdma_config0 = PKSEG1(s->sbm_base +
+ d->sbdma_config0 = PKSEG1(sc->sbm_base +
R_MAC_DMA_REGISTER(txrx, chan, R_MAC_DMA_CONFIG0));
- d->sbdma_config1 = PKSEG1(s->sbm_base +
+ d->sbdma_config1 = PKSEG1(sc->sbm_base +
R_MAC_DMA_REGISTER(txrx, chan, R_MAC_DMA_CONFIG1));
- d->sbdma_dscrbase = PKSEG1(s->sbm_base +
+ d->sbdma_dscrbase = PKSEG1(sc->sbm_base +
R_MAC_DMA_REGISTER(txrx, chan, R_MAC_DMA_DSCR_BASE));
- d->sbdma_dscrcnt = PKSEG1(s->sbm_base +
+ d->sbdma_dscrcnt = PKSEG1(sc->sbm_base +
R_MAC_DMA_REGISTER(txrx, chan, R_MAC_DMA_DSCR_CNT));
- d->sbdma_curdscr = PKSEG1(s->sbm_base +
+ d->sbdma_curdscr = PKSEG1(sc->sbm_base +
R_MAC_DMA_REGISTER(txrx, chan, R_MAC_DMA_CUR_DSCRADDR));
/*
@@ -511,15 +512,15 @@
if (m == NULL) {
MGETHDR(m_new, M_DONTWAIT, MT_DATA);
if (m_new == NULL) {
- printf("%s: mbuf allocation failed\n",
- d->sbdma_eth->sc_dev.dv_xname);
+ aprint_error_dev(d->sbdma_eth->sc_dev,
+ "mbuf allocation failed\n");
return ENOBUFS;
}
MCLGET(m_new, M_DONTWAIT);
if (!(m_new->m_flags & M_EXT)) {
- printf("%s: mbuf cluster allocation failed\n",
- d->sbdma_eth->sc_dev.dv_xname);
+ aprint_error_dev(d->sbdma_eth->sc_dev,
+ "mbuf cluster allocation failed\n");
m_freem(m_new);
return ENOBUFS;
}
@@ -724,16 +725,16 @@
MGETHDR(m_new,M_DONTWAIT,MT_DATA);
if (m_new == NULL) {
- printf("%s: mbuf allocation failed\n",
- d->sbdma_eth->sc_dev.dv_xname);
+ aprint_error_dev(d->sbdma_eth->sc_dev,
+ "mbuf allocation failed\n");
SBMAC_EVCNT_INCR(sc->sbm_ev_txdrop);
return ENOBUFS;
}
MCLGET(m_new,M_DONTWAIT);
if (!(m_new->m_flags & M_EXT)) {
- printf("%s: mbuf cluster allocation failed\n",
- d->sbdma_eth->sc_dev.dv_xname);
+ aprint_error_dev(d->sbdma_eth->sc_dev,
+ "mbuf cluster allocation failed\n");
m_freem(m_new);
SBMAC_EVCNT_INCR(sc->sbm_ev_txdrop);
return ENOBUFS;
@@ -1051,7 +1052,7 @@
}
/*
- * SBMAC_INITCTX(s)
+ * SBMAC_INITCTX(sc)
*
* Initialize an Ethernet context structure - this is called
* once per MAC on the 1250. Memory is allocated here, so don't
@@ -1066,7 +1067,7 @@
*/
static void
-sbmac_initctx(struct sbmac_softc *s)
+sbmac_initctx(struct sbmac_softc *sc)
{
uint64_t sysrev;
@@ -1074,65 +1075,66 @@
* figure out the addresses of some ports
*/
- s->sbm_macenable = PKSEG1(s->sbm_base + R_MAC_ENABLE);
- s->sbm_maccfg = PKSEG1(s->sbm_base + R_MAC_CFG);
- s->sbm_fifocfg = PKSEG1(s->sbm_base + R_MAC_THRSH_CFG);
- s->sbm_framecfg = PKSEG1(s->sbm_base + R_MAC_FRAMECFG);
- s->sbm_rxfilter = PKSEG1(s->sbm_base + R_MAC_ADFILTER_CFG);
- s->sbm_isr = PKSEG1(s->sbm_base + R_MAC_STATUS);
- s->sbm_imr = PKSEG1(s->sbm_base + R_MAC_INT_MASK);
+ sc->sbm_macenable = PKSEG1(sc->sbm_base + R_MAC_ENABLE);
+ sc->sbm_maccfg = PKSEG1(sc->sbm_base + R_MAC_CFG);
+ sc->sbm_fifocfg = PKSEG1(sc->sbm_base + R_MAC_THRSH_CFG);
+ sc->sbm_framecfg = PKSEG1(sc->sbm_base + R_MAC_FRAMECFG);
+ sc->sbm_rxfilter = PKSEG1(sc->sbm_base + R_MAC_ADFILTER_CFG);
+ sc->sbm_isr = PKSEG1(sc->sbm_base + R_MAC_STATUS);
+ sc->sbm_imr = PKSEG1(sc->sbm_base + R_MAC_INT_MASK);
/*
* Initialize the DMA channels. Right now, only one per MAC is used
* Note: Only do this _once_, as it allocates memory from the kernel!
*/
- sbdma_initctx(&(s->sbm_txdma), s, 0, DMA_TX, SBMAC_MAX_TXDESCR);
- sbdma_initctx(&(s->sbm_rxdma), s, 0, DMA_RX, SBMAC_MAX_RXDESCR);
+ sbdma_initctx(&(sc->sbm_txdma), sc, 0, DMA_TX, SBMAC_MAX_TXDESCR);
+ sbdma_initctx(&(sc->sbm_rxdma), sc, 0, DMA_RX, SBMAC_MAX_RXDESCR);
/*
* initial state is OFF
*/
- s->sbm_state = sbmac_state_off;
+ sc->sbm_state = sbmac_state_off;
/*
* Initial speed is (XXX TEMP) 10MBit/s HDX no FC
*/
- s->sbm_speed = sbmac_speed_10;
- s->sbm_duplex = sbmac_duplex_half;
- s->sbm_fc = sbmac_fc_disabled;
+ sc->sbm_speed = sbmac_speed_10;
+ sc->sbm_duplex = sbmac_duplex_half;
+ sc->sbm_fc = sbmac_fc_disabled;
/*
* Determine SOC type. 112x has Pass3 SOC features.
*/
sysrev = SBMAC_READCSR( PKSEG1(A_SCD_SYSTEM_REVISION) );
- s->sbm_pass3_dma = (SYS_SOC_TYPE(sysrev) == K_SYS_SOC_TYPE_BCM1120 ||
+ sc->sbm_pass3_dma = (SYS_SOC_TYPE(sysrev) == K_SYS_SOC_TYPE_BCM1120 ||
SYS_SOC_TYPE(sysrev) == K_SYS_SOC_TYPE_BCM1125 ||
SYS_SOC_TYPE(sysrev) == K_SYS_SOC_TYPE_BCM1125H ||
(SYS_SOC_TYPE(sysrev) == K_SYS_SOC_TYPE_BCM1250 &&
G_SYS_REVISION(sysrev) >= K_SYS_REVISION_BCM1250_PASS3));
#ifdef SBMAC_EVENT_COUNTERS
- evcnt_attach_dynamic(&s->sbm_ev_rxintr, EVCNT_TYPE_INTR,
- NULL, s->sc_dev.dv_xname, "rxintr");
- evcnt_attach_dynamic(&s->sbm_ev_txintr, EVCNT_TYPE_INTR,
- NULL, s->sc_dev.dv_xname, "txintr");
- evcnt_attach_dynamic(&s->sbm_ev_txdrop, EVCNT_TYPE_MISC,
- NULL, s->sc_dev.dv_xname, "txdrop");
- evcnt_attach_dynamic(&s->sbm_ev_txstall, EVCNT_TYPE_MISC,
- NULL, s->sc_dev.dv_xname, "txstall");
- if (s->sbm_pass3_dma) {
- evcnt_attach_dynamic(&s->sbm_ev_txsplit, EVCNT_TYPE_MISC,
- NULL, s->sc_dev.dv_xname, "pass3tx-split");
- evcnt_attach_dynamic(&s->sbm_ev_txkeep, EVCNT_TYPE_MISC,
- NULL, s->sc_dev.dv_xname, "pass3tx-keep");
+ const char * const xname = device_xname(sc->sc_dev);
+ evcnt_attach_dynamic(&sc->sbm_ev_rxintr, EVCNT_TYPE_INTR,
+ NULL, xname, "rxintr");
+ evcnt_attach_dynamic(&sc->sbm_ev_txintr, EVCNT_TYPE_INTR,
+ NULL, xname, "txintr");
+ evcnt_attach_dynamic(&sc->sbm_ev_txdrop, EVCNT_TYPE_MISC,
+ NULL, xname, "txdrop");
+ evcnt_attach_dynamic(&sc->sbm_ev_txstall, EVCNT_TYPE_MISC,
+ NULL, xname, "txstall");
+ if (sc->sbm_pass3_dma) {
+ evcnt_attach_dynamic(&sc->sbm_ev_txsplit, EVCNT_TYPE_MISC,
+ NULL, xname, "pass3tx-split");
+ evcnt_attach_dynamic(&sc->sbm_ev_txkeep, EVCNT_TYPE_MISC,
+ NULL, xname, "pass3tx-keep");
}
#endif
}
/*
- * SBMAC_CHANNEL_START(s)
+ * SBMAC_CHANNEL_START(sc)
*
* Start packet processing on this MAC.
*
@@ -1144,7 +1146,7 @@
*/
static void
-sbmac_channel_start(struct sbmac_softc *s)
+sbmac_channel_start(struct sbmac_softc *sc)
{
uint64_t reg;
sbmac_port_t port;
@@ -1157,20 +1159,20 @@
* Don't do this if running
*/
- if (s->sbm_state == sbmac_state_on)
+ if (sc->sbm_state == sbmac_state_on)
return;
/*
* Bring the controller out of reset, but leave it off.
*/
- SBMAC_WRITECSR(s->sbm_macenable, 0);
+ SBMAC_WRITECSR(sc->sbm_macenable, 0);
/*
* Ignore all received packets
*/
- SBMAC_WRITECSR(s->sbm_rxfilter, 0);
+ SBMAC_WRITECSR(sc->sbm_rxfilter, 0);
/*
* Calculate values for various control registers.
@@ -1192,15 +1194,17 @@
V_MAC_RX_RL_THRSH(8) |
0;
+ sc->sbm_mtu = sc->sc_ethercom.ec_if.if_mtu;
framecfg = V_MAC_MIN_FRAMESZ_DEFAULT |
- V_MAC_MAX_FRAMESZ_DEFAULT |
+ V_MAC_MAX_FRAMESZ(sc->sbm_mtu +
+ ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN) |
V_MAC_BACKOFF_SEL(1);
/*
* Clear out the hash address map
*/
- port = PKSEG1(s->sbm_base + R_MAC_HASH_BASE);
+ port = PKSEG1(sc->sbm_base + R_MAC_HASH_BASE);
for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
SBMAC_WRITECSR(port, 0);
port += sizeof(uint64_t);
@@ -1210,7 +1214,7 @@
* Clear out the exact-match table
*/
- port = PKSEG1(s->sbm_base + R_MAC_ADDR_BASE);
+ port = PKSEG1(sc->sbm_base + R_MAC_ADDR_BASE);
for (idx = 0; idx < MAC_ADDR_COUNT; idx++) {
SBMAC_WRITECSR(port, 0);
port += sizeof(uint64_t);
@@ -1220,13 +1224,13 @@
* Clear out the DMA Channel mapping table registers
*/
- port = PKSEG1(s->sbm_base + R_MAC_CHUP0_BASE);
+ port = PKSEG1(sc->sbm_base + R_MAC_CHUP0_BASE);
for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
SBMAC_WRITECSR(port, 0);
port += sizeof(uint64_t);
}
- port = PKSEG1(s->sbm_base + R_MAC_CHLO0_BASE);
+ port = PKSEG1(sc->sbm_base + R_MAC_CHLO0_BASE);
for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
SBMAC_WRITECSR(port, 0);
port += sizeof(uint64_t);
@@ -1237,11 +1241,11 @@
* register as well as the first filter register.
*/
- reg = sbmac_addr2reg(s->sbm_hwaddr);
+ reg = sbmac_addr2reg(sc->sbm_hwaddr);
- port = PKSEG1(s->sbm_base + R_MAC_ADDR_BASE);
+ port = PKSEG1(sc->sbm_base + R_MAC_ADDR_BASE);
SBMAC_WRITECSR(port, reg);
- port = PKSEG1(s->sbm_base + R_MAC_ETHERNET_ADDR);
+ port = PKSEG1(sc->sbm_base + R_MAC_ETHERNET_ADDR);
SBMAC_WRITECSR(port, 0); // pass1 workaround
/*
@@ -1249,44 +1253,44 @@
* to the various config registers
*/
- SBMAC_WRITECSR(s->sbm_rxfilter, 0);
- SBMAC_WRITECSR(s->sbm_imr, 0);
- SBMAC_WRITECSR(s->sbm_framecfg, framecfg);
- SBMAC_WRITECSR(s->sbm_fifocfg, fifo);
- SBMAC_WRITECSR(s->sbm_maccfg, cfg);
+ SBMAC_WRITECSR(sc->sbm_rxfilter, 0);
+ SBMAC_WRITECSR(sc->sbm_imr, 0);
+ SBMAC_WRITECSR(sc->sbm_framecfg, framecfg);
+ SBMAC_WRITECSR(sc->sbm_fifocfg, fifo);
+ SBMAC_WRITECSR(sc->sbm_maccfg, cfg);
/*
* Initialize DMA channels (rings should be ok now)
*/
- sbdma_channel_start(&(s->sbm_rxdma));
- sbdma_channel_start(&(s->sbm_txdma));
+ sbdma_channel_start(&(sc->sbm_rxdma));
+ sbdma_channel_start(&(sc->sbm_txdma));
/*
* Configure the speed, duplex, and flow control
*/
- sbmac_set_speed(s, s->sbm_speed);
- sbmac_set_duplex(s, s->sbm_duplex, s->sbm_fc);
+ sbmac_set_speed(sc, sc->sbm_speed);
+ sbmac_set_duplex(sc, sc->sbm_duplex, sc->sbm_fc);
/*
* Fill the receive ring
*/
- sbdma_fillring(&(s->sbm_rxdma));
+ sbdma_fillring(&(sc->sbm_rxdma));
/*
* Turn on the rest of the bits in the enable register
*/
- SBMAC_WRITECSR(s->sbm_macenable, M_MAC_RXDMA_EN0 | M_MAC_TXDMA_EN0 |
+ SBMAC_WRITECSR(sc->sbm_macenable, M_MAC_RXDMA_EN0 | M_MAC_TXDMA_EN0 |
M_MAC_RX_ENABLE | M_MAC_TX_ENABLE);
/*
* Accept any kind of interrupt on TX and RX DMA channel 0
*/
- SBMAC_WRITECSR(s->sbm_imr,
+ SBMAC_WRITECSR(sc->sbm_imr,
(M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
(M_MAC_INT_CHANNEL << S_MAC_RX_CH0));
@@ -1294,55 +1298,55 @@
* Enable receiving unicasts and broadcasts
*/
- SBMAC_WRITECSR(s->sbm_rxfilter, M_MAC_UCAST_EN | M_MAC_BCAST_EN);
+ SBMAC_WRITECSR(sc->sbm_rxfilter, M_MAC_UCAST_EN | M_MAC_BCAST_EN);
/*
* On chips which support unaligned DMA features, set the descriptor
* ring for transmit channels to use the unaligned buffer format.
*/
- txdma = &(s->sbm_txdma);
+ txdma = &(sc->sbm_txdma);
- if (s->sbm_pass3_dma) {
+ if (sc->sbm_pass3_dma) {
dma_cfg0 = SBMAC_READCSR(txdma->sbdma_config0);
dma_cfg0 |= V_DMA_DESC_TYPE(K_DMA_DESC_TYPE_RING_UAL_RMW) |
M_DMA_TBX_EN | M_DMA_TDX_EN;
SBMAC_WRITECSR(txdma->sbdma_config0,dma_cfg0);
- fifo_cfg = SBMAC_READCSR(s->sbm_fifocfg);
+ fifo_cfg = SBMAC_READCSR(sc->sbm_fifocfg);
fifo_cfg |= V_MAC_TX_WR_THRSH(8) |
V_MAC_TX_RD_THRSH(8) | V_MAC_TX_RL_THRSH(8);
- SBMAC_WRITECSR(s->sbm_fifocfg,fifo_cfg);
+ SBMAC_WRITECSR(sc->sbm_fifocfg,fifo_cfg);
}
/*
* we're running now.
*/
- s->sbm_state = sbmac_state_on;
- s->sc_ethercom.ec_if.if_flags |= IFF_RUNNING;
+ sc->sbm_state = sbmac_state_on;
+ sc->sc_ethercom.ec_if.if_flags |= IFF_RUNNING;
/*
* Program multicast addresses
*/
- sbmac_setmulti(s);
+ sbmac_setmulti(sc);
/*
* If channel was in promiscuous mode before, turn that on
*/
- if (s->sc_ethercom.ec_if.if_flags & IFF_PROMISC)
- sbmac_promiscuous_mode(s, 1);
+ if (sc->sc_ethercom.ec_if.if_flags & IFF_PROMISC)
+ sbmac_promiscuous_mode(sc, true);
/*
* Turn on the once-per-second timer
*/
- callout_reset(&(s->sc_tick_ch), hz, sbmac_tick, s);
+ callout_reset(&(sc->sc_tick_ch), hz, sbmac_tick, sc);
}
/*
- * SBMAC_CHANNEL_STOP(s)
+ * SBMAC_CHANNEL_STOP(sc)
*
* Stop packet processing on this MAC.
*
@@ -1354,39 +1358,39 @@
*/
static void
-sbmac_channel_stop(struct sbmac_softc *s)
+sbmac_channel_stop(struct sbmac_softc *sc)
{
uint64_t ctl;
/* don't do this if already stopped */
- if (s->sbm_state == sbmac_state_off)
+ if (sc->sbm_state == sbmac_state_off)
return;
/* don't accept any packets, disable all interrupts */
- SBMAC_WRITECSR(s->sbm_rxfilter, 0);
- SBMAC_WRITECSR(s->sbm_imr, 0);
+ SBMAC_WRITECSR(sc->sbm_rxfilter, 0);
+ SBMAC_WRITECSR(sc->sbm_imr, 0);
/* Turn off ticker */
- callout_stop(&(s->sc_tick_ch));
+ callout_stop(&(sc->sc_tick_ch));
/* turn off receiver and transmitter */
- ctl = SBMAC_READCSR(s->sbm_macenable);
+ ctl = SBMAC_READCSR(sc->sbm_macenable);
ctl &= ~(M_MAC_RXDMA_EN0 | M_MAC_TXDMA_EN0);
- SBMAC_WRITECSR(s->sbm_macenable, ctl);
+ SBMAC_WRITECSR(sc->sbm_macenable, ctl);
/* We're stopped now. */
- s->sbm_state = sbmac_state_off;
- s->sc_ethercom.ec_if.if_flags &= ~IFF_RUNNING;
+ sc->sbm_state = sbmac_state_off;
+ sc->sc_ethercom.ec_if.if_flags &= ~IFF_RUNNING;
/* Empty the receive and transmit rings */
- sbdma_emptyring(&(s->sbm_rxdma));
- sbdma_emptyring(&(s->sbm_txdma));
+ sbdma_emptyring(&(sc->sbm_rxdma));
+ sbdma_emptyring(&(sc->sbm_txdma));
}
/*
@@ -1443,7 +1447,7 @@
*/
static void
-sbmac_promiscuous_mode(struct sbmac_softc *sc, int onoff)
+sbmac_promiscuous_mode(struct sbmac_softc *sc, bool onoff)
{
uint64_t reg;
@@ -1459,6 +1463,7 @@
reg &= ~M_MAC_ALLPKT_EN;
SBMAC_WRITECSR(sc->sbm_rxfilter, reg);
}
+ sc->sbm_promisc = onoff;
}
/*
@@ -1475,15 +1480,10 @@
static void
sbmac_init_and_start(struct sbmac_softc *sc)
{
- int s;
-
- s = splnet();
mii_pollstat(&sc->sc_mii); /* poll phy for current speed */
- sbmac_mii_statchg((struct device *) sc); /* set state to new speed */
+ sbmac_mii_statchg(sc->sc_dev); /* set state to new speed */
sbmac_set_channel_state(sc, sbmac_state_on);
-
- splx(s);
}
/*
@@ -1522,7 +1522,7 @@
}
/*
- * SBMAC_SET_SPEED(s, speed)
+ * SBMAC_SET_SPEED(sc, speed)
*
* Configure LAN speed for the specified MAC.
* Warning: must be called when MAC is off!
@@ -1537,7 +1537,7 @@
*/
static int
-sbmac_set_speed(struct sbmac_softc *s, sbmac_speed_t speed)
+sbmac_set_speed(struct sbmac_softc *sc, sbmac_speed_t speed)
{
uint64_t cfg;
uint64_t framecfg;
@@ -1546,17 +1546,17 @@
* Save new current values
*/
- s->sbm_speed = speed;
+ sc->sbm_speed = speed;
- if (s->sbm_state != sbmac_state_off)
+ if (sc->sbm_state != sbmac_state_off)
panic("sbmac_set_speed while MAC not off");
/*
* Read current register values
*/
- cfg = SBMAC_READCSR(s->sbm_maccfg);
- framecfg = SBMAC_READCSR(s->sbm_framecfg);
+ cfg = SBMAC_READCSR(sc->sbm_maccfg);
+ framecfg = SBMAC_READCSR(sc->sbm_framecfg);
/*
* Mask out the stuff we want to change
@@ -1605,14 +1605,14 @@
* Send the bits back to the hardware
*/
- SBMAC_WRITECSR(s->sbm_framecfg, framecfg);
- SBMAC_WRITECSR(s->sbm_maccfg, cfg);
+ SBMAC_WRITECSR(sc->sbm_framecfg, framecfg);
+ SBMAC_WRITECSR(sc->sbm_maccfg, cfg);
return 1;
}
/*
- * SBMAC_SET_DUPLEX(s, duplex, fc)
+ * SBMAC_SET_DUPLEX(sc, duplex, fc)
*
* Set Ethernet duplex and flow control options for this MAC
* Warning: must be called when MAC is off!
@@ -1628,7 +1628,7 @@
*/
static int
-sbmac_set_duplex(struct sbmac_softc *s, sbmac_duplex_t duplex, sbmac_fc_t fc)
+sbmac_set_duplex(struct sbmac_softc *sc, sbmac_duplex_t duplex, sbmac_fc_t fc)
{
uint64_t cfg;
@@ -1636,17 +1636,17 @@
* Save new current values
*/
- s->sbm_duplex = duplex;
- s->sbm_fc = fc;
+ sc->sbm_duplex = duplex;
+ sc->sbm_fc = fc;
- if (s->sbm_state != sbmac_state_off)
+ if (sc->sbm_state != sbmac_state_off)
panic("sbmac_set_duplex while MAC not off");
/*
* Read current register values
*/
- cfg = SBMAC_READCSR(s->sbm_maccfg);
+ cfg = SBMAC_READCSR(sc->sbm_maccfg);
/*
* Mask off the stuff we're about to change
@@ -1674,7 +1674,7 @@
case sbmac_fc_frame: /* not valid in half duplex */
default: /* invalid selection */
panic("%s: invalid half duplex fc selection %d",
- s->sc_dev.dv_xname, fc);
+ device_xname(sc->sc_dev), fc);
return 0;
}
break;
@@ -1695,7 +1695,7 @@
/* fall through */
default:
panic("%s: invalid full duplex fc selection %d",
- s->sc_dev.dv_xname, fc);
+ device_xname(sc->sc_dev), fc);
return 0;
}
break;
@@ -1703,7 +1703,7 @@
default:
/* fall through */
case sbmac_duplex_auto:
- panic("%s: bad duplex %d", s->sc_dev.dv_xname, duplex);
+ panic("%s: bad duplex %d", device_xname(sc->sc_dev), duplex);
/* XXX not implemented */
break;
}
@@ -1712,7 +1712,7 @@
* Send the bits back to the hardware
*/
- SBMAC_WRITECSR(s->sbm_maccfg, cfg);
+ SBMAC_WRITECSR(sc->sbm_maccfg, cfg);
return 1;
}
@@ -1734,9 +1734,9 @@
sbmac_intr(void *xsc, uint32_t status, vaddr_t pc)
{
struct sbmac_softc *sc = (struct sbmac_softc *) xsc;
- struct ifnet *ifp = &sc->sc_ethercom.ec_if;
uint64_t isr;
+ mutex_spin_enter(&sc->sc_intrlock);
for (;;) {
/*
@@ -1768,7 +1768,8 @@
}
/* try to get more packets going */
- sbmac_start(ifp);
+ sbmac_start(sc);
+ mutex_spin_exit(&sc->sc_intrlock);
}
@@ -1787,16 +1788,28 @@
*/
static void
-sbmac_start(struct ifnet *ifp)
+sbmac_ifstart(struct ifnet *ifp)
{
- struct sbmac_softc *sc;
- struct mbuf *m_head = NULL;
- int rv;
+ struct sbmac_softc * const sc = ifp->if_softc;
if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
return;
- sc = ifp->if_softc;
+ if (mutex_tryenter(&sc->sc_intrlock)) {
+ sbmac_start(sc);
+ mutex_spin_exit(&sc->sc_intrlock);
+ }
+}
+
+static void
+sbmac_start(struct sbmac_softc *sc)
+{
+ struct ifnet * const ifp = &sc->sc_ethercom.ec_if;
+ struct mbuf *m_head = NULL;
+ int rv;
+
+ if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
+ return;
for (;;) {
@@ -1854,14 +1867,13 @@
static void
sbmac_setmulti(struct sbmac_softc *sc)
{
- struct ifnet *ifp;
+ struct ifnet * const ifp = &sc->sc_ethercom.ec_if;
uint64_t reg;
sbmac_port_t port;
int idx;
struct ether_multi *enm;
struct ether_multistep step;
- ifp = &sc->sc_ethercom.ec_if;
/*
* Clear out entire multicast table. We do this by nuking
@@ -1934,66 +1946,35 @@
}
}
-/*
- * SBMAC_ETHER_IOCTL(ifp, cmd, data)
- *
- * Generic IOCTL requests for this interface. The basic
- * stuff is handled here for bringing the interface up,
- * handling multicasts, etc.
- *
- * Input parameters:
- * ifp - interface structure
- * cmd - command code
- * data - pointer to data
- *
- * Return value:
- * return value (0 is success)
- */
-
-static int
-sbmac_ether_ioctl(struct ifnet *ifp, u_long cmd, void *data)
+int
+sbmac_ifinit(struct ifnet *ifp)
{
- struct ifaddr *ifa = (struct ifaddr *) data;
- struct sbmac_softc *sc = ifp->if_softc;
+ struct sbmac_softc * const sc = ifp->if_softc;
- switch (cmd) {
- case SIOCSIFADDR:
- ifp->if_flags |= IFF_UP;
-
- switch (ifa->ifa_addr->sa_family) {
-#ifdef INET
- case AF_INET:
- sbmac_init_and_start(sc);
- arp_ifinit(ifp, ifa);
- break;
-#endif
-#ifdef NS
- case AF_NS:
- {
- struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
-
- if (ns_nullhost(*ina))
- ina->x_host =
- *(union ns_host *)LLADDR(ifp->if_sadl);
- else
- bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
- ifp->if_addrlen);
- /* Set new address. */
- sbmac_init_and_start(sc);
- break;
- }
-#endif
- default:
+ /*
+ * If MTU change, whack it hard otherwise if only the state of the
+ * PROMISC flag changed, just tweak the hardware registers.
+ */
+ if (sc->sbm_state == sbmac_state_on) {
+ bool promisc = (ifp->if_flags & IFF_PROMISC) != 0;
+ if (sc->sbm_mtu != ifp->if_mtu)
sbmac_init_and_start(sc);
- break;
- }
- break;
-
- default:
- return (EINVAL);
+ else if (promisc != sc->sbm_promisc)
+ sbmac_promiscuous_mode(sc, promisc);
+ } else {
+ sbmac_set_channel_state(sc, sbmac_state_on);
}
- return (0);
+ return 0;
+}
+
+void
+sbmac_ifstop(struct ifnet *ifp, int disable)
+{
+ struct sbmac_softc * const sc = ifp->if_softc;
+
+ if (ifp->if_flags & IFF_RUNNING)
+ sbmac_set_channel_state(sc, sbmac_state_off);
}
/*
@@ -2013,69 +1994,33 @@
*/
static int
-sbmac_ioctl(struct ifnet *ifp, u_long command, void *data)
+sbmac_ifioctl(struct ifnet *ifp, u_long command, void *data)
{
struct sbmac_softc *sc = ifp->if_softc;
- struct ifreq *ifr = (struct ifreq *) data;
- int s, error = 0;
-
- s = splnet();
- switch(command) {
+ switch (command) {
case SIOCSIFADDR:
case SIOCGIFADDR:
- error = sbmac_ether_ioctl(ifp, command, data);
- break;
case SIOCSIFMTU:
- if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU)
- error = EINVAL;
- else if ((error = ifioctl_common(ifp, command, data)) == ENETRESET)
- /* XXX Program new MTU here */
- error = 0;
- break;
- case SIOCSIFFLAGS:
- if (ifp->if_flags & IFF_UP) {
- /*
- * If only the state of the PROMISC flag changed,
- * just tweak the hardware registers.
- */
- if ((ifp->if_flags & IFF_RUNNING) &&
- (ifp->if_flags & IFF_PROMISC)) {
- /* turn on promiscuous mode */
- sbmac_promiscuous_mode(sc, 1);
- } else if (ifp->if_flags & IFF_RUNNING &&
- !(ifp->if_flags & IFF_PROMISC)) {
- /* turn off promiscuous mode */
- sbmac_promiscuous_mode(sc, 0);
- } else
- sbmac_set_channel_state(sc, sbmac_state_on);
- } else {
- if (ifp->if_flags & IFF_RUNNING)
- sbmac_set_channel_state(sc, sbmac_state_off);
- }
-
- sc->sbm_if_flags = ifp->if_flags;
- error = 0;
- break;
-
case SIOCADDMULTI:
case SIOCDELMULTI:
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
- if ((error = ether_ioctl(ifp, command, data)) == ENETRESET) {
+ case SIOCSIFFLAGS:
+ mutex_spin_enter(&sc->sc_intrlock);
+ int error = ether_ioctl(ifp, command, data);
+ if (error == ENETRESET) {
error = 0;
if (ifp->if_flags & IFF_RUNNING)
sbmac_setmulti(sc);
}
- break;
+ if (error == 0 && !IF_IS_EMPTY(&ifp->if_snd))
+ sbmac_start(sc);
+ mutex_spin_exit(&sc->sc_intrlock);
+ return error;
default:
- error = EINVAL;
- break;
+ return EINVAL;
}
-
- (void)splx(s);
-
- return(error);
}
/*
@@ -2118,7 +2063,7 @@
*/
static void
-sbmac_watchdog(struct ifnet *ifp)
+sbmac_ifwatchdog(struct ifnet *ifp)
{
/* XXX do something */
@@ -2131,11 +2076,10 @@
sbmac_tick(void *arg)
{
struct sbmac_softc *sc = arg;
- int s;
- s = splnet();
+ mutex_spin_enter(&sc->sc_intrlock);
mii_tick(&sc->sc_mii);
- splx(s);
+ mutex_spin_exit(&sc->sc_intrlock);
callout_reset(&sc->sc_tick_ch, hz, sbmac_tick, sc);
}
@@ -2158,7 +2102,7 @@
*/
static int
-sbmac_match(struct device *parent, struct cfdata *match, void *aux)
+sbmac_match(device_t parent, cfdata_t match, void *aux)
{
struct sbobio_attach_args *sap = aux;
@@ -2269,17 +2213,19 @@
*/
static void
-sbmac_attach(struct device *parent, struct device *self, void *aux)
+sbmac_attach(device_t parent, device_t self, void *aux)
{
- struct ifnet *ifp;
- struct sbmac_softc *sc;
- struct sbobio_attach_args *sap = aux;
+ struct sbmac_softc * const sc = device_private(self);
+ struct ifnet * const ifp = &sc->sc_ethercom.ec_if;
+ struct sbobio_attach_args * const sap = aux;
u_char *eaddr;
static int unit = 0; /* XXX */
uint64_t ea_reg;
int idx;
- sc = (struct sbmac_softc *)self;
+ sc->sc_dev = self;
+
+ mutex_init(&sc->sc_intrlock, MUTEX_DEFAULT, IPL_VM);
/* Determine controller base address */
@@ -2332,9 +2278,9 @@
* Display Ethernet address (this is called during the config process
* so we need to finish off the config message that was being displayed)
*/
- printf(": Ethernet%s\n",
+ aprint_normal(": Ethernet%s\n",
sc->sbm_pass3_dma ? ", using unaligned tx DMA" : "");
- printf("%s: Ethernet address: %s\n", self->dv_xname,
+ aprint_normal_dev(self, "Ethernet address: %s\n",
ether_sprintf(eaddr));
@@ -2342,14 +2288,15 @@
* Set up ifnet structure
*/
- ifp = &sc->sc_ethercom.ec_if;
ifp->if_softc = sc;
- bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+ memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
IFF_NOTRAILERS;
- ifp->if_ioctl = sbmac_ioctl;
- ifp->if_start = sbmac_start;
- ifp->if_watchdog = sbmac_watchdog;
+ ifp->if_init = sbmac_ifinit;
+ ifp->if_ioctl = sbmac_ifioctl;
+ ifp->if_start = sbmac_ifstart;
+ ifp->if_stop = sbmac_ifstop;
+ ifp->if_watchdog = sbmac_ifwatchdog;
ifp->if_snd.ifq_maxlen = SBMAC_MAX_TXDESCR - 1;
/*
@@ -2366,7 +2313,7 @@
sc->sc_ethercom.ec_mii = &sc->sc_mii;
ifmedia_init(&sc->sc_mii.mii_media, 0, ether_mediachange,
ether_mediastatus);
- mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
+ mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
MII_OFFSET_ANY, 0);
if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {