cxgbe(4): knobs to enable/disable PAUSE frame based flow control.
MFC after: 1 week
This commit is contained in:
parent
60c8581b5e
commit
cc95d45388
@ -240,8 +240,19 @@ The default is -1 which lets the driver pick a pad boundary.
|
|||||||
Controls the hardware response to congestion.
|
Controls the hardware response to congestion.
|
||||||
-1 disables congestion feedback and is not recommended.
|
-1 disables congestion feedback and is not recommended.
|
||||||
0 instructs the hardware to backpressure its pipeline on congestion.
|
0 instructs the hardware to backpressure its pipeline on congestion.
|
||||||
This usually results in the port emitting pause frames.
|
This usually results in the port emitting PAUSE frames.
|
||||||
1 instructs the hardware to drop frames destined for congested queues.
|
1 instructs the hardware to drop frames destined for congested queues.
|
||||||
|
.It Va hw.cxgbe.pause_settings
|
||||||
|
PAUSE frame settings.
|
||||||
|
Bit 0 is rx_pause, bit 1 is tx_pause.
|
||||||
|
rx_pause = 1 instructs the hardware to heed incoming PAUSE frames, 0 instructs
|
||||||
|
it to ignore them.
|
||||||
|
tx_pause = 1 allows the hardware to emit PAUSE frames when its receive FIFO
|
||||||
|
reaches a high threshold, 0 prohibits the hardware from emitting PAUSE frames.
|
||||||
|
The default is 3 (both rx_pause and tx_pause = 1).
|
||||||
|
This tunable establishes the default PAUSE settings for all ports.
|
||||||
|
Settings can be displayed and controlled on a per-port basis via the
|
||||||
|
dev.cxgbe.X.pause_settings (dev.cxl.X.pause_settings for T5 cards) sysctl.
|
||||||
.It Va hw.cxgbe.buffer_packing
|
.It Va hw.cxgbe.buffer_packing
|
||||||
Allow the hardware to deliver multiple frames in the same receive buffer
|
Allow the hardware to deliver multiple frames in the same receive buffer
|
||||||
opportunistically.
|
opportunistically.
|
||||||
|
@ -280,6 +280,15 @@ TUNABLE_INT("hw.cxgbe.interrupt_types", &t4_intr_types);
|
|||||||
static char t4_cfg_file[32] = DEFAULT_CF;
|
static char t4_cfg_file[32] = DEFAULT_CF;
|
||||||
TUNABLE_STR("hw.cxgbe.config_file", t4_cfg_file, sizeof(t4_cfg_file));
|
TUNABLE_STR("hw.cxgbe.config_file", t4_cfg_file, sizeof(t4_cfg_file));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PAUSE settings (bit 0, 1 = rx_pause, tx_pause respectively).
|
||||||
|
* rx_pause = 1 to heed incoming PAUSE frames, 0 to ignore them.
|
||||||
|
* tx_pause = 1 to emit PAUSE frames when the rx FIFO reaches its high water
|
||||||
|
* mark or when signalled to do so, 0 to never emit PAUSE.
|
||||||
|
*/
|
||||||
|
static int t4_pause_settings = PAUSE_TX | PAUSE_RX;
|
||||||
|
TUNABLE_INT("hw.cxgbe.pause_settings", &t4_pause_settings);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Firmware auto-install by driver during attach (0, 1, 2 = prohibited, allowed,
|
* Firmware auto-install by driver during attach (0, 1, 2 = prohibited, allowed,
|
||||||
* encouraged respectively).
|
* encouraged respectively).
|
||||||
@ -393,6 +402,7 @@ static int sysctl_holdoff_tmr_idx(SYSCTL_HANDLER_ARGS);
|
|||||||
static int sysctl_holdoff_pktc_idx(SYSCTL_HANDLER_ARGS);
|
static int sysctl_holdoff_pktc_idx(SYSCTL_HANDLER_ARGS);
|
||||||
static int sysctl_qsize_rxq(SYSCTL_HANDLER_ARGS);
|
static int sysctl_qsize_rxq(SYSCTL_HANDLER_ARGS);
|
||||||
static int sysctl_qsize_txq(SYSCTL_HANDLER_ARGS);
|
static int sysctl_qsize_txq(SYSCTL_HANDLER_ARGS);
|
||||||
|
static int sysctl_pause_settings(SYSCTL_HANDLER_ARGS);
|
||||||
static int sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS);
|
static int sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS);
|
||||||
static int sysctl_temperature(SYSCTL_HANDLER_ARGS);
|
static int sysctl_temperature(SYSCTL_HANDLER_ARGS);
|
||||||
#ifdef SBUF_DRAIN
|
#ifdef SBUF_DRAIN
|
||||||
@ -697,6 +707,12 @@ t4_attach(device_t dev)
|
|||||||
sc->port[i] = NULL;
|
sc->port[i] = NULL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pi->link_cfg.requested_fc &= ~(PAUSE_TX | PAUSE_RX);
|
||||||
|
pi->link_cfg.requested_fc |= t4_pause_settings;
|
||||||
|
pi->link_cfg.fc &= ~(PAUSE_TX | PAUSE_RX);
|
||||||
|
pi->link_cfg.fc |= t4_pause_settings;
|
||||||
|
|
||||||
rc = -t4_link_start(sc, sc->mbox, pi->tx_chan, &pi->link_cfg);
|
rc = -t4_link_start(sc, sc->mbox, pi->tx_chan, &pi->link_cfg);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
device_printf(dev, "port %d l1cfg failed: %d\n", i, rc);
|
device_printf(dev, "port %d l1cfg failed: %d\n", i, rc);
|
||||||
@ -4771,6 +4787,10 @@ cxgbe_sysctls(struct port_info *pi)
|
|||||||
CTLTYPE_INT | CTLFLAG_RW, pi, 0, sysctl_qsize_txq, "I",
|
CTLTYPE_INT | CTLFLAG_RW, pi, 0, sysctl_qsize_txq, "I",
|
||||||
"tx queue size");
|
"tx queue size");
|
||||||
|
|
||||||
|
SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "pause_settings",
|
||||||
|
CTLTYPE_STRING | CTLFLAG_RW, pi, PAUSE_TX, sysctl_pause_settings,
|
||||||
|
"A", "PAUSE settings (bit 0 = rx_pause, bit 1 = tx_pause)");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dev.cxgbe.X.stats.
|
* dev.cxgbe.X.stats.
|
||||||
*/
|
*/
|
||||||
@ -5151,6 +5171,65 @@ sysctl_qsize_txq(SYSCTL_HANDLER_ARGS)
|
|||||||
return (rc);
|
return (rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sysctl_pause_settings(SYSCTL_HANDLER_ARGS)
|
||||||
|
{
|
||||||
|
struct port_info *pi = arg1;
|
||||||
|
struct adapter *sc = pi->adapter;
|
||||||
|
struct link_config *lc = &pi->link_cfg;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (req->newptr == NULL) {
|
||||||
|
struct sbuf *sb;
|
||||||
|
static char *bits = "\20\1PAUSE_RX\2PAUSE_TX";
|
||||||
|
|
||||||
|
rc = sysctl_wire_old_buffer(req, 0);
|
||||||
|
if (rc != 0)
|
||||||
|
return(rc);
|
||||||
|
|
||||||
|
sb = sbuf_new_for_sysctl(NULL, NULL, 128, req);
|
||||||
|
if (sb == NULL)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
sbuf_printf(sb, "%b", lc->fc & (PAUSE_TX | PAUSE_RX), bits);
|
||||||
|
rc = sbuf_finish(sb);
|
||||||
|
sbuf_delete(sb);
|
||||||
|
} else {
|
||||||
|
char s[2];
|
||||||
|
int n;
|
||||||
|
|
||||||
|
s[0] = '0' + (lc->requested_fc & (PAUSE_TX | PAUSE_RX));
|
||||||
|
s[1] = 0;
|
||||||
|
|
||||||
|
rc = sysctl_handle_string(oidp, s, sizeof(s), req);
|
||||||
|
if (rc != 0)
|
||||||
|
return(rc);
|
||||||
|
|
||||||
|
if (s[1] != 0)
|
||||||
|
return (EINVAL);
|
||||||
|
if (s[0] < '0' || s[0] > '9')
|
||||||
|
return (EINVAL); /* not a number */
|
||||||
|
n = s[0] - '0';
|
||||||
|
if (n & ~(PAUSE_TX | PAUSE_RX))
|
||||||
|
return (EINVAL); /* some other bit is set too */
|
||||||
|
|
||||||
|
rc = begin_synchronized_op(sc, pi, SLEEP_OK | INTR_OK, "t4PAUSE");
|
||||||
|
if (rc)
|
||||||
|
return (rc);
|
||||||
|
if ((lc->requested_fc & (PAUSE_TX | PAUSE_RX)) != n) {
|
||||||
|
int link_ok = lc->link_ok;
|
||||||
|
|
||||||
|
lc->requested_fc &= ~(PAUSE_TX | PAUSE_RX);
|
||||||
|
lc->requested_fc |= n;
|
||||||
|
rc = -t4_link_start(sc, sc->mbox, pi->tx_chan, lc);
|
||||||
|
lc->link_ok = link_ok; /* restore */
|
||||||
|
}
|
||||||
|
end_synchronized_op(sc, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (rc);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS)
|
sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user