Add a sysctl to control the interrupt pacing on AM335x integrated switch.

The hardware can be set to limit the number of interrupts from 2 to 63
interrupts per ms.

To keep the compatibility with the TI documentation the sysctl take the
interval between the interrupts pulses: 16~500 us.

Sponsored by:	Rubicon Communications, LLC (Netgate)
This commit is contained in:
Luiz Otavio O Souza 2016-09-27 18:19:29 +00:00
parent f987297fc9
commit feeb22f34a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=306376
3 changed files with 73 additions and 0 deletions

View File

@ -583,6 +583,11 @@ cpsw_init(struct cpsw_softc *sc)
struct cpsw_slot *slot;
uint32_t reg;
/* Disable the interrupt pacing. */
reg = cpsw_read_4(sc, CPSW_WR_INT_CONTROL);
reg &= ~(CPSW_WR_INT_PACE_EN | CPSW_WR_INT_PRESCALE_MASK);
cpsw_write_4(sc, CPSW_WR_INT_CONTROL, reg);
/* Clear ALE */
cpsw_write_4(sc, CPSW_ALE_CONTROL, CPSW_ALE_CTL_CLEAR_TBL);
@ -2491,6 +2496,51 @@ cpsw_stat_attached(SYSCTL_HANDLER_ARGS)
return (sysctl_handle_int(oidp, &result, 0, req));
}
static int
cpsw_intr_coalesce(SYSCTL_HANDLER_ARGS)
{
int error;
struct cpsw_softc *sc;
uint32_t ctrl, intr_per_ms;
sc = (struct cpsw_softc *)arg1;
error = sysctl_handle_int(oidp, &sc->coal_us, 0, req);
if (error != 0 || req->newptr == NULL)
return (error);
ctrl = cpsw_read_4(sc, CPSW_WR_INT_CONTROL);
ctrl &= ~(CPSW_WR_INT_PACE_EN | CPSW_WR_INT_PRESCALE_MASK);
if (sc->coal_us == 0) {
/* Disable the interrupt pace hardware. */
cpsw_write_4(sc, CPSW_WR_INT_CONTROL, ctrl);
cpsw_write_4(sc, CPSW_WR_C_RX_IMAX(0), 0);
cpsw_write_4(sc, CPSW_WR_C_TX_IMAX(0), 0);
return (0);
}
if (sc->coal_us > CPSW_WR_C_IMAX_US_MAX)
sc->coal_us = CPSW_WR_C_IMAX_US_MAX;
if (sc->coal_us < CPSW_WR_C_IMAX_US_MIN)
sc->coal_us = CPSW_WR_C_IMAX_US_MIN;
intr_per_ms = 1000 / sc->coal_us;
/* Just to make sure... */
if (intr_per_ms > CPSW_WR_C_IMAX_MAX)
intr_per_ms = CPSW_WR_C_IMAX_MAX;
if (intr_per_ms < CPSW_WR_C_IMAX_MIN)
intr_per_ms = CPSW_WR_C_IMAX_MIN;
/* Set the prescale to produce 4us pulses from the 125 Mhz clock. */
ctrl |= (125 * 4) & CPSW_WR_INT_PRESCALE_MASK;
/* Enable the interrupt pace hardware. */
cpsw_write_4(sc, CPSW_WR_C_RX_IMAX(0), intr_per_ms);
cpsw_write_4(sc, CPSW_WR_C_TX_IMAX(0), intr_per_ms);
ctrl |= CPSW_WR_INT_C0_RX_PULSE | CPSW_WR_INT_C0_TX_PULSE;
cpsw_write_4(sc, CPSW_WR_INT_CONTROL, ctrl);
return (0);
}
static int
cpsw_stat_uptime(SYSCTL_HANDLER_ARGS)
{
@ -2576,6 +2626,10 @@ cpsw_add_sysctls(struct cpsw_softc *sc)
CTLTYPE_UINT | CTLFLAG_RD, sc, 0, cpsw_stat_attached, "IU",
"Time since driver attach");
SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "intr_coalesce_us",
CTLTYPE_UINT | CTLFLAG_RW, sc, 0, cpsw_intr_coalesce, "IU",
"minimum time between interrupts");
node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "ports",
CTLFLAG_RD, NULL, "CPSW Ports Statistics");
ports_parent = SYSCTL_CHILDREN(node);

View File

@ -138,6 +138,17 @@
#define CPSW_WR_SOFT_RESET (CPSW_WR_OFFSET + 0x04)
#define CPSW_WR_CONTROL (CPSW_WR_OFFSET + 0x08)
#define CPSW_WR_INT_CONTROL (CPSW_WR_OFFSET + 0x0c)
#define CPSW_WR_INT_C0_RX_PULSE (1 << 16)
#define CPSW_WR_INT_C0_TX_PULSE (1 << 17)
#define CPSW_WR_INT_C1_RX_PULSE (1 << 18)
#define CPSW_WR_INT_C1_TX_PULSE (1 << 19)
#define CPSW_WR_INT_C2_RX_PULSE (1 << 20)
#define CPSW_WR_INT_C2_TX_PULSE (1 << 21)
#define CPSW_WR_INT_PACE_EN \
(CPSW_WR_INT_C0_RX_PULSE | CPSW_WR_INT_C0_TX_PULSE | \
CPSW_WR_INT_C1_RX_PULSE | CPSW_WR_INT_C1_TX_PULSE | \
CPSW_WR_INT_C2_RX_PULSE | CPSW_WR_INT_C2_TX_PULSE)
#define CPSW_WR_INT_PRESCALE_MASK 0xfff
#define CPSW_WR_C_RX_THRESH_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x10)
#define CPSW_WR_C_RX_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x14)
#define CPSW_WR_C_TX_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x18)
@ -151,6 +162,13 @@
#define CPSW_WR_C_MISC_HOST_PEND (1 << 2)
#define CPSW_WR_C_MISC_MDIOLINK (1 << 1)
#define CPSW_WR_C_MISC_MDIOUSER (1 << 0)
#define CPSW_WR_C_RX_IMAX(p) (CPSW_WR_OFFSET + (0x08 * (p)) + 0x70)
#define CPSW_WR_C_TX_IMAX(p) (CPSW_WR_OFFSET + (0x08 * (p)) + 0x74)
#define CPSW_WR_C_IMAX_MASK 0x3f
#define CPSW_WR_C_IMAX_MAX 63
#define CPSW_WR_C_IMAX_MIN 2
#define CPSW_WR_C_IMAX_US_MAX 500
#define CPSW_WR_C_IMAX_US_MIN 16
#define CPSW_CPPI_RAM_OFFSET 0x2000
#define CPSW_CPPI_RAM_SIZE 0x2000

View File

@ -80,6 +80,7 @@ struct cpsw_softc {
phandle_t node;
struct bintime attach_uptime; /* system uptime when attach happened. */
struct cpsw_port port[2];
unsigned coal_us;
/* RX and TX buffer tracking */
struct cpsw_queue rx, tx;