Date: Sat, 29 Nov 2008 18:41:12 GMT From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 153777 for review Message-ID: <200811291841.mATIfCpc082190@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=153777 Change 153777 by sam@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 *);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200811291841.mATIfCpc082190>