PERFORCE change 153777 for review
Sam Leffler
sam at FreeBSD.org
Sat Nov 29 10:41:13 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=153777
Change 153777 by sam at sam_ebb on 2008/11/29 18:40:51
Improve configuarability, add ixp435 support, and other fixups:
o change static configation state to use NPE id's instead of
port #'s; this allows board descriptions to be more portable
and more understandable (e.g. it's simpler to compare to the
IAL and linux code bases)
o add support for ixp435/Cambria boards
o change npe init setup to be done by npeid instead of unit#
so npe code doesn't need to translate
o add support for hints override of npeid and imageid
o add some error msgs for improbable conditions
o hack "fix rx q setup" issue; this was a reminder that if we
tried to map all 8 traffic classifications to our rx q the
npe firmware would hang; this looks to be dependent on the
firmware--if we're running vanilla Ethernet support it only
groks 4 classifications, 8 when QoS+VLAN support is present;
use the f/w image features id to decide how many to map
NB: the 2nd port on the Cambria board doesn't work but this is
likely because we have the wrong firmware; still working on that.
Affected files ...
.. //depot/projects/vap/sys/arm/xscale/ixp425/if_npe.c#6 edit
.. //depot/projects/vap/sys/arm/xscale/ixp425/if_npereg.h#3 edit
.. //depot/projects/vap/sys/arm/xscale/ixp425/ixp425_npe.c#3 edit
.. //depot/projects/vap/sys/arm/xscale/ixp425/ixp425_npevar.h#3 edit
Differences ...
==== //depot/projects/vap/sys/arm/xscale/ixp425/if_npe.c#6 (text+ko) ====
@@ -85,6 +85,8 @@
#include <dev/mii/miivar.h>
#include <arm/xscale/ixp425/if_npereg.h>
+#include <machine/armreg.h>
+
#include "miibus_if.h"
/*
@@ -121,6 +123,7 @@
bus_space_handle_t sc_ioh; /* MAC register window */
device_t sc_mii; /* child miibus */
bus_space_handle_t sc_miih; /* MII register window */
+ int sc_npeid;
struct ixpnpe_softc *sc_npe; /* NPE support */
int sc_debug; /* DPRINTF* control */
int sc_tickinterval;
@@ -143,7 +146,7 @@
};
/*
- * Per-unit static configuration for IXP425. The tx and
+ * Static configuration for IXP425. The tx and
* rx free Q id's are fixed by the NPE microcode. The
* rx Q id's are programmed to be separate to simplify
* multi-port processing. It may be better to handle
@@ -154,11 +157,9 @@
* assumptions probably need to be handled through hints.
*/
static const struct {
- const char *desc; /* device description */
- int npeid; /* NPE assignment */
- uint32_t imageid; /* NPE firmware image id */
- uint32_t regbase;
- int regsize;
+ uint32_t imageid; /* default fw image */
+ uint32_t macbase;
+ int macsize;
uint32_t miibase;
int miisize;
int phy; /* phy id */
@@ -166,12 +167,23 @@
uint8_t rx_freeqid;
uint8_t tx_qid;
uint8_t tx_doneqid;
-} npeconfig[NPE_PORTS_MAX] = {
- { .desc = "IXP NPE-B",
- .npeid = NPE_B,
+} npeconfig[NPE_MAX] = {
+ [NPE_A] = {
+ .imageid = IXP425_NPE_A_IMAGEID,
+ .macbase = IXP435_MAC_A_HWBASE,
+ .macsize = IXP435_MAC_A_SIZE,
+ .miibase = IXP435_MAC_A_HWBASE,
+ .miisize = IXP435_MAC_A_SIZE,
+ .phy = 2,
+ .rx_qid = 4,
+ .rx_freeqid = 27,
+ .tx_qid = 24,
+ .tx_doneqid = 31
+ },
+ [NPE_B] = {
.imageid = IXP425_NPE_B_IMAGEID,
- .regbase = IXP425_MAC_A_HWBASE,
- .regsize = IXP425_MAC_A_SIZE,
+ .macbase = IXP425_MAC_A_HWBASE,
+ .macsize = IXP425_MAC_A_SIZE,
.miibase = IXP425_MAC_A_HWBASE,
.miisize = IXP425_MAC_A_SIZE,
.phy = 0,
@@ -180,11 +192,10 @@
.tx_qid = 24,
.tx_doneqid = 31
},
- { .desc = "IXP NPE-C",
- .npeid = NPE_C,
+ [NPE_C] = {
.imageid = IXP425_NPE_C_IMAGEID,
- .regbase = IXP425_MAC_B_HWBASE,
- .regsize = IXP425_MAC_B_SIZE,
+ .macbase = IXP425_MAC_B_HWBASE,
+ .macsize = IXP425_MAC_B_SIZE,
.miibase = IXP425_MAC_A_HWBASE,
.miisize = IXP425_MAC_A_SIZE,
.phy = 1,
@@ -219,6 +230,7 @@
static devclass_t npe_devclass;
+static int override_npeid(device_t, const char *resname, int *val);
static int npe_activate(device_t dev);
static void npe_deactivate(device_t dev);
static int npe_ifmedia_update(struct ifnet *ifp);
@@ -275,16 +287,38 @@
TUNABLE_INT("hw.npe.txbuf", &npe_txbuf);
static int
+unit2npeid(int unit)
+{
+ static const int npeidmap[2][3] = {
+ /* on 425 A is for HSS, B & C are for Ethernet */
+ { NPE_B, NPE_C, -1 }, /* IXP425 */
+ /* 435 only has A & C, order C then A */
+ { NPE_C, NPE_A, -1 }, /* IXP435 */
+ };
+ /* XXX check feature register instead */
+ return (unit < 3 ? npeidmap[
+ (cpu_id() & CPU_ID_CPU_MASK) == CPU_ID_IXP435][unit] : -1);
+}
+
+static int
npe_probe(device_t dev)
{
- int unit = device_get_unit(dev);
+ static const char *desc[NPE_MAX] = {
+ [NPE_A] = "IXP NPE-A",
+ [NPE_B] = "IXP NPE-B",
+ [NPE_C] = "IXP NPE-C"
+ };
+ int npeid;
- if (unit >= NPE_PORTS_MAX) {
- device_printf(dev, "unit %d not supported\n", unit);
+ npeid = -1;
+ if (!override_npeid(dev, "npeid", &npeid))
+ npeid = unit2npeid(device_get_unit(dev));
+ if (npeid == -1) {
+ device_printf(dev, "unit not supported\n");
return EINVAL;
}
/* XXX check feature register to see if enabled */
- device_set_desc(dev, npeconfig[unit].desc);
+ device_set_desc(dev, desc[npeid]);
return 0;
}
@@ -306,22 +340,27 @@
sc->sc_debug = npe_debug;
sc->sc_tickinterval = npe_tickinterval;
- sc->sc_npe = ixpnpe_attach(dev);
+ if (!override_npeid(dev, "npeid", &sc->sc_npeid))
+ sc->sc_npeid = unit2npeid(device_get_unit(dev));
+ sc->sc_npe = ixpnpe_attach(dev, sc->sc_npeid);
if (sc->sc_npe == NULL) {
+ device_printf(dev, "cannot attach ixpnpe.\n");
error = EIO; /* XXX */
goto out;
}
error = npe_activate(dev);
- if (error)
+ if (error) {
+ device_printf(dev, "cannot activate npe.\n");
goto out;
+ }
npe_getmac(sc, eaddr);
/* NB: must be setup prior to invoking mii code */
sc->sc_ifp = ifp = if_alloc(IFT_ETHER);
if (mii_phy_probe(dev, &sc->sc_mii, npe_ifmedia_update, npe_ifmedia_status)) {
- device_printf(dev, "Cannot find my PHY.\n");
+ device_printf(dev, "cannot find my PHY.\n");
error = ENXIO;
goto out;
}
@@ -548,6 +587,34 @@
}
static int
+npe_macaddr(int npeid, int *base, int *size)
+{
+ if (npeid == NPE_A) {
+ if ((cpu_id() & CPU_ID_CPU_MASK) == CPU_ID_IXP435) {
+ *base = IXP435_MAC_A_HWBASE;
+ *size = IXP435_MAC_A_SIZE;
+ } else {
+ *base = IXP425_MAC_A_HWBASE;
+ *size = IXP425_MAC_A_SIZE;
+ }
+ return 0;
+ } else if (npeid == NPE_B) {
+ if ((cpu_id() & CPU_ID_CPU_MASK) != CPU_ID_IXP435) {
+ *base = IXP425_MAC_B_HWBASE;
+ *size = IXP425_MAC_B_SIZE;
+ return 0;
+ }
+ } else if (npeid == NPE_C) {
+ if ((cpu_id() & CPU_ID_CPU_MASK) == CPU_ID_IXP435) {
+ *base = IXP435_MAC_C_HWBASE;
+ *size = IXP435_MAC_C_SIZE;
+ return 0;
+ }
+ }
+ return EINVAL;
+}
+
+static int
override_addr(device_t dev, const char *resname, int *base, int *size)
{
int unit = device_get_unit(dev);
@@ -558,14 +625,42 @@
return 0;
switch (resval[0]) {
case 'A':
- *base = IXP425_MAC_A_HWBASE;
- *size = IXP425_MAC_A_SIZE;
+ npe_macaddr(NPE_A, base, size);
break;
case 'B':
- *base = IXP425_MAC_B_HWBASE;
- *size = IXP425_MAC_B_SIZE;
+ if (npe_macaddr(NPE_B, base, size) != 0)
+ goto bad;
+ break;
+ case 'C':
+ if (npe_macaddr(NPE_C, base, size) != 0)
+ goto bad;
break;
default:
+ bad:
+ device_printf(dev, "Warning, bad value %s for "
+ "npe.%d.%s ignored\n", resval, unit, resname);
+ return 0;
+ }
+ if (bootverbose)
+ device_printf(dev, "using npe.%d.%s=%s override\n",
+ unit, resname, resval);
+ return 1;
+}
+
+static int
+override_npeid(device_t dev, const char *resname, int *npeid)
+{
+ int unit = device_get_unit(dev);
+ const char *resval;
+
+ /* XXX warn for wrong hint type */
+ if (resource_string_value("npe", unit, resname, &resval) != 0)
+ return 0;
+ switch (resval[0]) {
+ case 'A': *npeid = NPE_A; break;
+ case 'B': *npeid = NPE_B; break;
+ case 'C': *npeid = NPE_C; break;
+ default:
device_printf(dev, "Warning, bad value %s for "
"npe.%d.%s ignored\n", resval, unit, resname);
return 0;
@@ -598,11 +693,26 @@
}
static int
+override_imageid(device_t dev, const char *resname, uint32_t *val)
+{
+ int unit = device_get_unit(dev);
+ int resval;
+
+ if (resource_int_value("npe", unit, resname, &resval) != 0)
+ return 0;
+ /* XXX validate */
+ if (bootverbose)
+ device_printf(dev, "using npe.%d.%s=0x%x override\n",
+ unit, resname, resval);
+ *val = resval;
+ return 1;
+}
+
+static int
npe_activate(device_t dev)
{
struct npe_softc * sc = device_get_softc(dev);
- int unit = device_get_unit(dev);
- int error, i, regbase, regsize, miibase, miisize;
+ int error, i, macbase, macsize, miibase, miisize;
uint32_t imageid;
/*
@@ -611,42 +721,49 @@
* the firmware image starting with the expected version
* and then bump the minor version up to the max.
*/
- imageid = npeconfig[unit].imageid;
+ if (!override_imageid(dev, "imageid", &imageid))
+ imageid = npeconfig[sc->sc_npeid].imageid;
for (;;) {
error = ixpnpe_init(sc->sc_npe, "npe_fw", imageid);
if (error == 0)
break;
/* ESRCH is returned when the requested image is not present */
- if (error != ESRCH)
+ if (error != ESRCH) {
+ device_printf(dev, "cannot init NPE (error %d)\n",
+ error);
return error;
+ }
/* bump the minor version up to the max possible */
- if (NPEIMAGE_MINOR(imageid) == 0xff)
+ if (NPEIMAGE_MINOR(imageid) == 0xff) {
+ device_printf(dev, "cannot locate firmware "
+ "(imageid 0x%08x)\n", imageid);
return error;
+ }
imageid++;
}
- if (!override_addr(dev, "mac", ®base, ®size)) {
- regbase = npeconfig[unit].regbase;
- regbase = npeconfig[unit].regsize;
+ if (!override_addr(dev, "mac", &macbase, &macsize)) {
+ macbase = npeconfig[sc->sc_npeid].macbase;
+ macsize = npeconfig[sc->sc_npeid].macsize;
}
- if (bus_space_map(sc->sc_iot, regbase, regsize, 0, &sc->sc_ioh)) {
- device_printf(dev, "Cannot map registers 0x%x:0x%x\n",
- regbase, regsize);
+ if (bus_space_map(sc->sc_iot, macbase, macsize, 0, &sc->sc_ioh)) {
+ device_printf(dev, "cannot map mac registers 0x%x:0x%x\n",
+ macbase, macsize);
return ENOMEM;
}
if (!override_addr(dev, "mii", &miibase, &miisize)) {
- miibase = npeconfig[unit].miibase;
- miisize = npeconfig[unit].miisize;
+ miibase = npeconfig[sc->sc_npeid].miibase;
+ miisize = npeconfig[sc->sc_npeid].miisize;
}
- if (miibase != regbase) {
+ if (miibase != macbase) {
/*
* PHY is mapped through a different MAC, setup an
* additional mapping for frobbing the PHY registers.
*/
if (bus_space_map(sc->sc_iot, miibase, miisize, 0, &sc->sc_miih)) {
device_printf(dev,
- "Cannot map MII registers 0x%x:0x%x\n",
+ "cannot map MII registers 0x%x:0x%x\n",
miibase, miisize);
return ENOMEM;
}
@@ -703,22 +820,21 @@
* when the rx q has at least one frame. These setings can
* changed at the time the q is configured.
*/
- sc->rx_qid = npeconfig[unit].rx_qid;
+ sc->rx_qid = npeconfig[sc->sc_npeid].rx_qid;
ixpqmgr_qconfig(sc->rx_qid, npe_rxbuf, 0, 1,
IX_QMGR_Q_SOURCE_ID_NOT_E, npe_rxdone, sc);
- sc->rx_freeqid = npeconfig[unit].rx_freeqid;
+ sc->rx_freeqid = npeconfig[sc->sc_npeid].rx_freeqid;
ixpqmgr_qconfig(sc->rx_freeqid, npe_rxbuf, 0, npe_rxbuf/2, 0, NULL, sc);
- /* tell the NPE to direct all traffic to rx_qid */
-#if 0
- for (i = 0; i < 8; i++)
-#else
-device_printf(sc->sc_dev, "remember to fix rx q setup\n");
- for (i = 0; i < 4; i++)
-#endif
+ /*
+ * Setup the NPE to direct all traffic to rx_qid.
+ * When QoS is enabled in the firmware there are
+ * 8 traffic classes; otherwise just 4.
+ */
+ for (i = 0; i < (imageid & 0xf0000 ? 8 : 4); i++)
npe_setrxqosentry(sc, i, 0, sc->rx_qid);
- sc->tx_qid = npeconfig[unit].tx_qid;
- sc->tx_doneqid = npeconfig[unit].tx_doneqid;
+ sc->tx_qid = npeconfig[sc->sc_npeid].tx_qid;
+ sc->tx_doneqid = npeconfig[sc->sc_npeid].tx_doneqid;
ixpqmgr_qconfig(sc->tx_qid, npe_txbuf, 0, npe_txbuf, 0, NULL, sc);
if (tx_doneqid == -1) {
ixpqmgr_qconfig(sc->tx_doneqid, npe_txbuf, 0, 2,
@@ -731,11 +847,11 @@
* to handle different board configs.
*/
if (!override_unit(dev, "phy", &sc->sc_phy, 0, MII_NPHY-1))
- sc->sc_phy = npeconfig[unit].phy;
+ sc->sc_phy = npeconfig[sc->sc_npeid].phy;
- KASSERT(npes[npeconfig[unit].npeid] == NULL,
- ("npe %u already setup", npeconfig[unit].npeid));
- npes[npeconfig[unit].npeid] = sc;
+ KASSERT(npes[sc->sc_npeid] == NULL,
+ ("npe %u already setup", sc->sc_npeid));
+ npes[sc->sc_npeid] = sc;
return 0;
}
@@ -744,9 +860,8 @@
npe_deactivate(device_t dev)
{
struct npe_softc *sc = device_get_softc(dev);
- int unit = device_get_unit(dev);
- npes[npeconfig[unit].npeid] = NULL;
+ npes[sc->sc_npeid] = NULL;
/* XXX disable q's */
if (sc->sc_npe != NULL)
@@ -1470,10 +1585,9 @@
static int
npe_setrxqosentry(struct npe_softc *sc, int classix, int trafclass, int qid)
{
- int npeid = npeconfig[device_get_unit(sc->sc_dev)].npeid;
uint32_t msg[2];
- msg[0] = (NPE_SETRXQOSENTRY << 24) | (npeid << 20) | classix;
+ msg[0] = (NPE_SETRXQOSENTRY << 24) | (sc->sc_npeid << 20) | classix;
msg[1] = (trafclass << 24) | (1 << 23) | (qid << 16) | (qid << 4);
return ixpnpe_sendandrecvmsg(sc->sc_npe, msg, msg);
}
==== //depot/projects/vap/sys/arm/xscale/ixp425/if_npereg.h#3 (text+ko) ====
@@ -84,12 +84,6 @@
} ix_ne[NPE_MAXSEG];
};
-/* NPE ID's */
-#define NPE_A 0
-#define NPE_B 1
-#define NPE_C 2
-#define NPE_MAX (NPE_C+1)
-
#define NPE_PORTS_MAX 2 /* logical ports */
#define NPE_FRAME_SIZE_DEFAULT 1536
#define NPE_FRAME_SIZE_MAX (65536-64)
==== //depot/projects/vap/sys/arm/xscale/ixp425/ixp425_npe.c#3 (text+ko) ====
@@ -246,12 +246,48 @@
}
struct ixpnpe_softc *
-ixpnpe_attach(device_t dev)
+ixpnpe_attach(device_t dev, int npeid)
{
+ struct npeconfig {
+ uint32_t base;
+ uint32_t size;
+ int irq;
+ uint32_t ins_memsize;
+ uint32_t data_memsize;
+ };
+ static const struct npeconfig npeconfigs[NPE_MAX] = {
+ [NPE_A] = {
+ .base = IXP425_NPE_A_HWBASE,
+ .size = IXP425_NPE_A_SIZE,
+ .irq = IXP425_INT_NPE_A,
+ .ins_memsize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEA,
+ .data_memsize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEA
+ },
+ [NPE_B] = {
+ .base = IXP425_NPE_B_HWBASE,
+ .size = IXP425_NPE_B_SIZE,
+ .irq = IXP425_INT_NPE_B,
+ .ins_memsize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEB,
+ .data_memsize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEB
+ },
+ [NPE_C] = {
+ .base = IXP425_NPE_C_HWBASE,
+ .size = IXP425_NPE_C_SIZE,
+ .irq = IXP425_INT_NPE_C,
+ .ins_memsize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEC,
+ .data_memsize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEC
+ },
+ };
struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
struct ixpnpe_softc *sc;
- bus_addr_t base;
- int rid, irq;
+ const struct npeconfig *config;
+ int rid;
+
+ if (npeid >= NPE_MAX) {
+ device_printf(dev, "bad npeid %d passed to %s\n", npeid, __func__);
+ return NULL;
+ }
+ config = &npeconfigs[npeid];
/* XXX M_BUS */
sc = malloc(sizeof(struct ixpnpe_softc), M_TEMP, M_WAITOK | M_ZERO);
@@ -259,26 +295,11 @@
sc->sc_iot = sa->sc_iot;
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), "npe driver", MTX_DEF);
- if (device_get_unit(dev) == 0) {
- base = IXP425_NPE_B_HWBASE;
- sc->sc_size = IXP425_NPE_B_SIZE;
- irq = IXP425_INT_NPE_B;
+ sc->sc_size = config->size;
+ sc->insMemSize = config->ins_memsize; /* size of instruction memory */
+ sc->dataMemSize = config->data_memsize; /* size of data memory */
- /* size of instruction memory */
- sc->insMemSize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEB;
- /* size of data memory */
- sc->dataMemSize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEB;
- } else {
- base = IXP425_NPE_C_HWBASE;
- sc->sc_size = IXP425_NPE_C_SIZE;
- irq = IXP425_INT_NPE_C;
-
- /* size of instruction memory */
- sc->insMemSize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEC;
- /* size of data memory */
- sc->dataMemSize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEC;
- }
- if (bus_space_map(sc->sc_iot, base, sc->sc_size, 0, &sc->sc_ioh))
+ if (bus_space_map(sc->sc_iot, config->base, sc->sc_size, 0, &sc->sc_ioh))
panic("%s: Cannot map registers", device_get_name(dev));
/*
@@ -286,9 +307,9 @@
*/
rid = 0;
sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
- irq, irq, 1, RF_ACTIVE);
+ config->irq, config->irq, 1, RF_ACTIVE);
if (!sc->sc_irq)
- panic("%s: Unable to allocate irq %u", device_get_name(dev), irq);
+ panic("%s: Unable to allocate irq %u", device_get_name(dev), config->irq);
/* XXX could be a source of entropy */
bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_NET | INTR_MPSAFE,
NULL, ixpnpe_intr, sc, &sc->sc_ih);
@@ -1326,7 +1347,7 @@
error = EIO;
if (error)
- device_printf(sc->sc_dev, "input FIFO timeout, msg [0x%x,0x%x]\n",
+ device_printf(sc->sc_dev, "input FIFO timeout, msg [0x%08x,0x%08x]\n",
msg[0], msg[1]);
return error;
}
==== //depot/projects/vap/sys/arm/xscale/ixp425/ixp425_npevar.h#3 (text+ko) ====
@@ -95,11 +95,18 @@
#define NPEFW_B_DMA 0x01020100 /* DMA only */
/* XXX ... more not include */
+/* NPE ID's */
+#define NPE_A 0
+#define NPE_B 1
+#define NPE_C 2
+#define NPE_MAX (NPE_C+1)
+
+#define IXP425_NPE_A_IMAGEID 0x10800200
#define IXP425_NPE_B_IMAGEID 0x01000200
#define IXP425_NPE_C_IMAGEID 0x02000200
struct ixpnpe_softc;
-struct ixpnpe_softc *ixpnpe_attach(device_t);
+struct ixpnpe_softc *ixpnpe_attach(device_t, int npeid);
void ixpnpe_detach(struct ixpnpe_softc *);
int ixpnpe_stopandreset(struct ixpnpe_softc *);
int ixpnpe_start(struct ixpnpe_softc *);
More information about the p4-projects
mailing list