Bug fixes phase5.
- Catch NPE_NOTIFYMACRECOVERYDONE from NPE, reset MAC and send NPE_MACRECOVERYSTART to NPE. This sequence is very important :-| (It's easy to reproduce) - Don't call tsleep() in interrupt context. - Add randomness of the transmit deferwhen a collision occured (like CSR) - fix DPRINTFn() in npe_cpu_reset()
This commit is contained in:
parent
cf26bd22fc
commit
227ae4c962
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ixp425_if_npe.c,v 1.15 2009/03/11 14:51:19 msaitoh Exp $ */
|
||||
/* $NetBSD: ixp425_if_npe.c,v 1.16 2009/03/11 16:30:20 msaitoh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 Sam Leffler. All rights reserved.
|
||||
|
@ -28,7 +28,7 @@
|
|||
#if 0
|
||||
__FBSDID("$FreeBSD: src/sys/arm/xscale/ixp425/if_npe.c,v 1.1 2006/11/19 23:55:23 sam Exp $");
|
||||
#endif
|
||||
__KERNEL_RCSID(0, "$NetBSD: ixp425_if_npe.c,v 1.15 2009/03/11 14:51:19 msaitoh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ixp425_if_npe.c,v 1.16 2009/03/11 16:30:20 msaitoh Exp $");
|
||||
|
||||
/*
|
||||
* Intel XScale NPE Ethernet driver.
|
||||
|
@ -140,6 +140,7 @@ struct npe_softc {
|
|||
static const struct {
|
||||
const char *desc; /* device description */
|
||||
int npeid; /* NPE assignment */
|
||||
int macport; /* Port number of the MAC */
|
||||
uint32_t imageid; /* NPE firmware image id */
|
||||
uint32_t regbase;
|
||||
int regsize;
|
||||
|
@ -152,6 +153,7 @@ static const struct {
|
|||
} npeconfig[NPE_PORTS_MAX] = {
|
||||
{ .desc = "IXP NPE-B",
|
||||
.npeid = NPE_B,
|
||||
.macport = 0x10,
|
||||
.imageid = IXP425_NPE_B_IMAGEID,
|
||||
.regbase = IXP425_MAC_A_HWBASE,
|
||||
.regsize = IXP425_MAC_A_SIZE,
|
||||
|
@ -164,6 +166,7 @@ static const struct {
|
|||
},
|
||||
{ .desc = "IXP NPE-C",
|
||||
.npeid = NPE_C,
|
||||
.macport = 0x20,
|
||||
.imageid = IXP425_NPE_C_IMAGEID,
|
||||
.regbase = IXP425_MAC_B_HWBASE,
|
||||
.regsize = IXP425_MAC_B_SIZE,
|
||||
|
@ -202,6 +205,7 @@ static int npe_rxbuf_init(struct npe_softc *, struct npebuf *,
|
|||
static void npe_rxdone(int qid, void *arg);
|
||||
static void npeinit_macreg(struct npe_softc *);
|
||||
static int npeinit(struct ifnet *);
|
||||
static void npeinit_resetcb(void *);
|
||||
static void npeinit_locked(void *);
|
||||
static void npestart(struct ifnet *);
|
||||
static void npestop(struct ifnet *, int);
|
||||
|
@ -267,6 +271,7 @@ npe_attach(struct device *parent, struct device *self, void *arg)
|
|||
{
|
||||
struct npe_softc *sc = (void *)self;
|
||||
struct ixpnpe_attach_args *na = arg;
|
||||
struct ixpnpe_softc *isc = (struct ixpnpe_softc *)parent;
|
||||
struct ifnet *ifp;
|
||||
|
||||
aprint_naive("\n");
|
||||
|
@ -328,6 +333,10 @@ npe_attach(struct device *parent, struct device *self, void *arg)
|
|||
|
||||
if_attach(ifp);
|
||||
ether_ifattach(ifp, sc->sc_enaddr);
|
||||
|
||||
/* callback function to reset MAC */
|
||||
isc->macresetcbfunc = npeinit_resetcb;
|
||||
isc->macresetcbarg = sc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -339,6 +348,7 @@ npe_setmcast(struct npe_softc *sc)
|
|||
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
|
||||
uint8_t mask[ETHER_ADDR_LEN], addr[ETHER_ADDR_LEN];
|
||||
uint32_t reg;
|
||||
uint32_t msg[2];
|
||||
int i;
|
||||
|
||||
/* Always use filter. Is here a correct position? */
|
||||
|
@ -390,6 +400,13 @@ npe_setmcast(struct npe_softc *sc)
|
|||
WR4(sc, NPE_MAC_ADDR_MASK(i), mask[i]);
|
||||
WR4(sc, NPE_MAC_ADDR(i), addr[i]);
|
||||
}
|
||||
|
||||
msg[0] = NPE_ADDRESSFILTERCONFIG << NPE_MAC_MSGID_SHL
|
||||
| (npeconfig[sc->sc_unit].macport << NPE_MAC_PORTID_SHL);
|
||||
msg[1] = ((ifp->if_flags & IFF_PROMISC) ? 1 : 0) << 24
|
||||
| ((RD4(sc, NPE_MAC_UNI_ADDR_6) & 0xff) << 16)
|
||||
| (addr[5] << 8) | mask[5];
|
||||
ixpnpe_sendandrecvmsg(sc->sc_npe, msg, msg);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1127,6 +1144,22 @@ npeinit_macreg(struct npe_softc *sc)
|
|||
WR4(sc, NPE_MAC_RX_CNTRL2, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
npeinit_resetcb(void *xsc)
|
||||
{
|
||||
struct npe_softc *sc = xsc;
|
||||
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
|
||||
uint32_t msg[2];
|
||||
|
||||
ifp->if_oerrors++;
|
||||
npeinit_locked(sc);
|
||||
|
||||
msg[0] = NPE_NOTIFYMACRECOVERYDONE << NPE_MAC_MSGID_SHL
|
||||
| (npeconfig[sc->sc_unit].macport << NPE_MAC_PORTID_SHL);
|
||||
msg[1] = 0;
|
||||
ixpnpe_sendandrecvmsg(sc->sc_npe, msg, msg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset and initialize the chip
|
||||
*/
|
||||
|
@ -1618,14 +1651,22 @@ npe_miibus_statchg(struct device *self)
|
|||
{
|
||||
struct npe_softc *sc = (void *)self;
|
||||
uint32_t tx1, rx1;
|
||||
uint32_t randoff;
|
||||
|
||||
/* sync MAC duplex state */
|
||||
tx1 = RD4(sc, NPE_MAC_TX_CNTRL1);
|
||||
rx1 = RD4(sc, NPE_MAC_RX_CNTRL1);
|
||||
if (sc->sc_mii.mii_media_active & IFM_FDX) {
|
||||
WR4(sc, NPE_MAC_SLOT_TIME, NPE_MAC_SLOT_TIME_MII_DEFAULT);
|
||||
tx1 &= ~NPE_TX_CNTRL1_DUPLEX;
|
||||
rx1 |= NPE_RX_CNTRL1_PAUSE_EN;
|
||||
} else {
|
||||
struct timeval now;
|
||||
getmicrotime(&now);
|
||||
randoff = (RD4(sc, NPE_MAC_UNI_ADDR_6) ^ now.tv_usec)
|
||||
& 0x7f;
|
||||
WR4(sc, NPE_MAC_SLOT_TIME, NPE_MAC_SLOT_TIME_MII_DEFAULT
|
||||
+ randoff);
|
||||
tx1 |= NPE_TX_CNTRL1_DUPLEX;
|
||||
rx1 &= ~NPE_RX_CNTRL1_PAUSE_EN;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ixp425_if_npereg.h,v 1.2 2009/03/11 11:36:33 msaitoh Exp $ */
|
||||
/* $NetBSD: ixp425_if_npereg.h,v 1.3 2009/03/11 16:30:20 msaitoh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 Sam Leffler, Errno Consulting
|
||||
|
@ -124,6 +124,9 @@ struct npehwbuf {
|
|||
#define NPE_SETRXQOSENTRY 0x0b /* map user pri -> QoS class+rx qid */
|
||||
#define NPE_SETFIREWALLMODE 0x0e /* config firewall services */
|
||||
#define NPE_SETLOOPBACK 0x12 /* enable/disable loopback */
|
||||
#define NPE_ADDRESSFILTERCONFIG 0x14 /* update multicast filter */
|
||||
#define NPE_NOTIFYMACRECOVERYDONE 0x16 /* MAC has been recovered */
|
||||
#define NPE_MACRECOVERYSTART 0x17 /* message from NPE to recover MAC*/
|
||||
/* ... XXX more */
|
||||
|
||||
#define NPE_MAC_MSGID_SHL 24
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ixp425_npe.c,v 1.3 2008/01/08 02:07:53 matt Exp $ */
|
||||
/* $NetBSD: ixp425_npe.c,v 1.4 2009/03/11 16:30:20 msaitoh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 Sam Leffler, Errno Consulting
|
||||
|
@ -62,7 +62,7 @@
|
|||
#if 0
|
||||
__FBSDID("$FreeBSD: src/sys/arm/xscale/ixp425/ixp425_npe.c,v 1.1 2006/11/19 23:55:23 sam Exp $");
|
||||
#endif
|
||||
__KERNEL_RCSID(0, "$NetBSD: ixp425_npe.c,v 1.3 2008/01/08 02:07:53 matt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ixp425_npe.c,v 1.4 2009/03/11 16:30:20 msaitoh Exp $");
|
||||
|
||||
/*
|
||||
* Intel XScale Network Processing Engine (NPE) support.
|
||||
|
@ -102,30 +102,10 @@ __KERNEL_RCSID(0, "$NetBSD: ixp425_npe.c,v 1.3 2008/01/08 02:07:53 matt Exp $");
|
|||
|
||||
#include <arm/xscale/ixp425_npereg.h>
|
||||
#include <arm/xscale/ixp425_npevar.h>
|
||||
#include <arm/xscale/ixp425_if_npereg.h>
|
||||
|
||||
#include "locators.h"
|
||||
|
||||
struct ixpnpe_softc {
|
||||
struct device sc_dev;
|
||||
bus_dma_tag_t sc_dt;
|
||||
bus_space_tag_t sc_iot;
|
||||
bus_space_handle_t sc_ioh;
|
||||
bus_size_t sc_size; /* size of mapped register window */
|
||||
int sc_unit;
|
||||
void *sc_ih; /* interrupt handler */
|
||||
struct simplelock sc_lock; /* mailbox lock */
|
||||
uint32_t sc_msg[2]; /* reply msg collected in ixpnpe_intr */
|
||||
int sc_msgwaiting; /* sc_msg holds valid data */
|
||||
|
||||
int validImage; /* valid ucode image loaded */
|
||||
int started; /* NPE is started */
|
||||
uint8_t functionalityId;/* ucode functionality ID */
|
||||
int insMemSize; /* size of instruction memory */
|
||||
int dataMemSize; /* size of data memory */
|
||||
uint32_t savedExecCount;
|
||||
uint32_t savedEcsDbgCtxtReg2;
|
||||
};
|
||||
|
||||
/*
|
||||
* IXP425_NPE_MICROCODE will be defined by ixp425-fw.mk IFF the
|
||||
* microcode object file exists in sys/arch/arm/xscale.
|
||||
|
@ -876,7 +856,7 @@ npe_cpu_reset(struct ixpnpe_softc *sc)
|
|||
|
||||
/* un-fuse and un-reset the NPE & coprocessor */
|
||||
DPRINTFn(2, sc->sc_dev, "%s: FCTRL unfuse parity, write 0x%x\n",
|
||||
__func__, regVal & resetNpeParity);
|
||||
__func__, regVal & ~resetNpeParity);
|
||||
EXP_BUS_WRITE_4(ixp425_softc, EXP_FCTRL_OFFSET, regVal &~ resetNpeParity);
|
||||
|
||||
/*
|
||||
|
@ -1347,7 +1327,20 @@ ixpnpe_intr(void *arg)
|
|||
sc->sc_msgwaiting = 1; /* successful fetch */
|
||||
}
|
||||
}
|
||||
if (sc->sc_msg[0] == (NPE_MACRECOVERYSTART << NPE_MAC_MSGID_SHL)) {
|
||||
int s;
|
||||
|
||||
s = splnet();
|
||||
delay(100); /* delay 100usec */
|
||||
if (sc->macresetcbfunc != NULL)
|
||||
sc->macresetcbfunc(sc->macresetcbarg);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* XXX Too dangerous! see ixpnpe_recvmsg_locked() */
|
||||
wakeup(sc);
|
||||
#endif
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
@ -1390,11 +1383,20 @@ static int
|
|||
ixpnpe_recvmsg_locked(struct ixpnpe_softc *sc, uint32_t msg[2])
|
||||
{
|
||||
|
||||
if (!sc->sc_msgwaiting)
|
||||
ltsleep(sc, 0, "npemh", 0, &sc->sc_lock);
|
||||
bcopy(sc->sc_msg, msg, sizeof(sc->sc_msg));
|
||||
/* NB: sc_msgwaiting != 1 means the ack fetch failed */
|
||||
return sc->sc_msgwaiting != 1 ? EIO : 0;
|
||||
if (!sc->sc_msgwaiting) {
|
||||
#if 0
|
||||
/*
|
||||
* This ltsleep() is dangerous because this function may be
|
||||
* called under interrupt context.
|
||||
*/
|
||||
ltsleep(sc, 0, "npemh", 0, &sc->sc_lock);
|
||||
#else
|
||||
delay(1000); /* wait 1ms (is it ok?)*/
|
||||
#endif
|
||||
}
|
||||
bcopy(sc->sc_msg, msg, sizeof(sc->sc_msg));
|
||||
/* NB: sc_msgwaiting != 1 means the ack fetch failed */
|
||||
return sc->sc_msgwaiting != 1 ? EIO : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ixp425_npevar.h,v 1.2 2009/03/10 17:09:48 msaitoh Exp $ */
|
||||
/* $NetBSD: ixp425_npevar.h,v 1.3 2009/03/11 16:30:20 msaitoh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 Sam Leffler. All rights reserved.
|
||||
|
@ -81,7 +81,28 @@
|
|||
#define IXP425_NPE_B_IMAGEID 0x01000201
|
||||
#define IXP425_NPE_C_IMAGEID 0x02000201
|
||||
|
||||
struct ixpnpe_softc;
|
||||
struct ixpnpe_softc {
|
||||
struct device sc_dev;
|
||||
bus_dma_tag_t sc_dt;
|
||||
bus_space_tag_t sc_iot;
|
||||
bus_space_handle_t sc_ioh;
|
||||
bus_size_t sc_size; /* size of mapped register window */
|
||||
int sc_unit;
|
||||
void *sc_ih; /* interrupt handler */
|
||||
struct simplelock sc_lock; /* mailbox lock */
|
||||
uint32_t sc_msg[2]; /* reply msg collected in ixpnpe_intr */
|
||||
int sc_msgwaiting; /* sc_msg holds valid data */
|
||||
|
||||
int validImage; /* valid ucode image loaded */
|
||||
int started; /* NPE is started */
|
||||
uint8_t functionalityId;/* ucode functionality ID */
|
||||
int insMemSize; /* size of instruction memory */
|
||||
int dataMemSize; /* size of data memory */
|
||||
uint32_t savedExecCount;
|
||||
uint32_t savedEcsDbgCtxtReg2;
|
||||
void (*macresetcbfunc)(void *);
|
||||
void *macresetcbarg;
|
||||
};
|
||||
|
||||
int ixpnpe_stopandreset(struct ixpnpe_softc *);
|
||||
int ixpnpe_start(struct ixpnpe_softc *);
|
||||
|
|
Loading…
Reference in New Issue