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:
msaitoh 2009-03-11 16:30:20 +00:00
parent cf26bd22fc
commit 227ae4c962
4 changed files with 101 additions and 34 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}
/*

View File

@ -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 *);