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:
parent
f987297fc9
commit
feeb22f34a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=306376
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user