summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornp <np@FreeBSD.org>2017-01-04 06:58:35 +0000
committernp <np@FreeBSD.org>2017-01-04 06:58:35 +0000
commitd08c08a0ef7af3fe3dbd293f517b165a4c4740c3 (patch)
tree3f588b80aaf340db18cf4b642363b7dbbc8c77d5
parent941299131dc6acb7dc7bba2dd276298147162c45 (diff)
downloadFreeBSD-src-d08c08a0ef7af3fe3dbd293f517b165a4c4740c3.zip
FreeBSD-src-d08c08a0ef7af3fe3dbd293f517b165a4c4740c3.tar.gz
MFC r309666, r310033, r310049, r310100, r310152, and r310807.
r309666: cxgbe(4): unsigned short isn't large enough to store link speed (which is in Mbps) for 100Gbps links. r310033: cxgbe(4): Retire t4_bus_space_read_8 and t4_bus_space_write_8. r310049: cxgbe(4): Fix the tid range shown for T6 cards in misc.tids. r310100: cxgbe(4): Deal with compressed error vectors. r310152: cxgbe(4): Fix typo in an unused macro. r310807: cxgbe(4): Updates to link configuration. - Update struct link_settings and associated shared code. - Add tunables to control FEC and autonegotiation. All ports inherit these values as their initial settings. hw.cxgbe.fec hw.cxgbe.autoneg - Add per-port sysctls to control FEC and autonegotiation. These can be modified at any time. dev.<port>.<n>.fec dev.<port>.<n>.autoneg
-rw-r--r--share/man/man4/cxgbe.418
-rw-r--r--sys/dev/cxgbe/adapter.h57
-rw-r--r--sys/dev/cxgbe/common/common.h16
-rw-r--r--sys/dev/cxgbe/common/t4_hw.c77
-rw-r--r--sys/dev/cxgbe/common/t4_msg.h4
-rw-r--r--sys/dev/cxgbe/t4_main.c185
-rw-r--r--sys/dev/cxgbe/t4_sge.c2
-rw-r--r--sys/dev/cxgbe/t4_vf.c2
8 files changed, 250 insertions, 111 deletions
diff --git a/share/man/man4/cxgbe.4 b/share/man/man4/cxgbe.4
index fceda86..a4800e1 100644
--- a/share/man/man4/cxgbe.4
+++ b/share/man/man4/cxgbe.4
@@ -290,6 +290,24 @@ 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.<port>.X.pause_settings sysctl.
+.It Va hw.cxgbe.fec
+FEC (Forward Error Correction) settings.
+0 diables FEC.
+Bit 0 enables RS FEC, bit 1 enables BASE-R RS, bit 3 is reserved.
+The default is -1 which lets the driver pick a value.
+This tunable establishes the default FEC settings for all ports.
+Settings can be displayed and controlled on a per-port basis via the
+dev.<port>.X.fec sysctl.
+.It Va hw.cxgbe.autoneg
+Link autonegotiation settings.
+This tunable establishes the default autonegotiation settings for all ports.
+Settings can be displayed and controlled on a per-port basis via the
+dev.<port>.X.autoneg sysctl.
+0 disables autonegotiation.
+1 enables autonegotiation.
+The default is -1 which lets the driver pick a value.
+dev.<port>.X.autoneg is -1 for port and module combinations that do not support
+autonegotiation.
.It Va hw.cxgbe.buffer_packing
Allow the hardware to deliver multiple frames in the same receive buffer
opportunistically.
diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h
index 2e74f8f..5801140 100644
--- a/sys/dev/cxgbe/adapter.h
+++ b/sys/dev/cxgbe/adapter.h
@@ -78,45 +78,6 @@ prefetch(void *x)
#define SBUF_DRAIN 1
#endif
-#ifdef __amd64__
-/* XXX: need systemwide bus_space_read_8/bus_space_write_8 */
-static __inline uint64_t
-t4_bus_space_read_8(bus_space_tag_t tag, bus_space_handle_t handle,
- bus_size_t offset)
-{
- KASSERT(tag == X86_BUS_SPACE_MEM,
- ("%s: can only handle mem space", __func__));
-
- return (*(volatile uint64_t *)(handle + offset));
-}
-
-static __inline void
-t4_bus_space_write_8(bus_space_tag_t tag, bus_space_handle_t bsh,
- bus_size_t offset, uint64_t value)
-{
- KASSERT(tag == X86_BUS_SPACE_MEM,
- ("%s: can only handle mem space", __func__));
-
- *(volatile uint64_t *)(bsh + offset) = value;
-}
-#else
-static __inline uint64_t
-t4_bus_space_read_8(bus_space_tag_t tag, bus_space_handle_t handle,
- bus_size_t offset)
-{
- return (uint64_t)bus_space_read_4(tag, handle, offset) +
- ((uint64_t)bus_space_read_4(tag, handle, offset + 4) << 32);
-}
-
-static __inline void
-t4_bus_space_write_8(bus_space_tag_t tag, bus_space_handle_t bsh,
- bus_size_t offset, uint64_t value)
-{
- bus_space_write_4(tag, bsh, offset, value);
- bus_space_write_4(tag, bsh, offset + 4, value >> 32);
-}
-#endif
-
struct adapter;
typedef struct adapter adapter_t;
@@ -298,7 +259,6 @@ struct port_info {
uint8_t tx_chan;
uint8_t rx_chan_map; /* rx MPS channel bitmap */
- int linkdnrc;
struct link_config link_cfg;
struct timeval last_refreshed;
@@ -970,14 +930,25 @@ static inline uint64_t
t4_read_reg64(struct adapter *sc, uint32_t reg)
{
- return t4_bus_space_read_8(sc->bt, sc->bh, reg);
+#if defined(__LP64__) && !defined(__ia64__)
+ return bus_space_read_8(sc->bt, sc->bh, reg);
+#else
+ return (uint64_t)bus_space_read_4(sc->bt, sc->bh, reg) +
+ ((uint64_t)bus_space_read_4(sc->bt, sc->bh, reg + 4) << 32);
+
+#endif
}
static inline void
t4_write_reg64(struct adapter *sc, uint32_t reg, uint64_t val)
{
- t4_bus_space_write_8(sc->bt, sc->bh, reg, val);
+#if defined(__LP64__) && !defined(__ia64__)
+ bus_space_write_8(sc->bt, sc->bh, reg, val);
+#else
+ bus_space_write_4(sc->bt, sc->bh, reg, val);
+ bus_space_write_4(sc->bt, sc->bh, reg + 4, val>> 32);
+#endif
}
static inline void
@@ -1119,7 +1090,7 @@ int t4_os_find_pci_capability(struct adapter *, int);
int t4_os_pci_save_state(struct adapter *);
int t4_os_pci_restore_state(struct adapter *);
void t4_os_portmod_changed(const struct adapter *, int);
-void t4_os_link_changed(struct adapter *, int, int, int);
+void t4_os_link_changed(struct adapter *, int, int);
void t4_iterate(void (*)(struct adapter *, void *), void *);
void t4_init_devnames(struct adapter *);
void t4_add_adapter(struct adapter *);
diff --git a/sys/dev/cxgbe/common/common.h b/sys/dev/cxgbe/common/common.h
index 790dbe5..04fdeb1 100644
--- a/sys/dev/cxgbe/common/common.h
+++ b/sys/dev/cxgbe/common/common.h
@@ -62,6 +62,12 @@ enum {
PAUSE_AUTONEG = 1 << 2
};
+enum {
+ FEC_RS = 1 << 0,
+ FEC_BASER_RS = 1 << 1,
+ FEC_RESERVED = 1 << 2,
+};
+
struct port_stats {
u64 tx_octets; /* total # of octets in good frames */
u64 tx_frames; /* all good frames */
@@ -227,7 +233,7 @@ struct tp_params {
uint32_t vlan_pri_map;
uint32_t ingress_config;
- uint32_t rx_pkt_encap;
+ __be16 err_vec_mask;
int8_t fcoe_shift;
int8_t port_shift;
@@ -392,12 +398,16 @@ struct trace_params {
struct link_config {
unsigned short supported; /* link capabilities */
unsigned short advertising; /* advertised capabilities */
- unsigned short requested_speed; /* speed user has requested */
- unsigned short speed; /* actual link speed */
+ unsigned short lp_advertising; /* peer advertised capabilities */
+ unsigned int requested_speed; /* speed user has requested */
+ unsigned int speed; /* actual link speed */
unsigned char requested_fc; /* flow control user has requested */
unsigned char fc; /* actual link flow control */
+ unsigned char requested_fec; /* FEC user has requested */
+ unsigned char fec; /* actual FEC */
unsigned char autoneg; /* autonegotiating? */
unsigned char link_ok; /* link up? */
+ unsigned char link_down_rc; /* link down reason */
};
#include "adapter.h"
diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c
index 5f8f3cc..a549d35 100644
--- a/sys/dev/cxgbe/common/t4_hw.c
+++ b/sys/dev/cxgbe/common/t4_hw.c
@@ -3680,9 +3680,7 @@ void t4_ulprx_read_la(struct adapter *adap, u32 *la_buf)
}
}
-#define ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\
- FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_SPEED_25G | \
- FW_PORT_CAP_SPEED_40G | FW_PORT_CAP_SPEED_100G | \
+#define ADVERT_MASK (V_FW_PORT_CAP_SPEED(M_FW_PORT_CAP_SPEED) | \
FW_PORT_CAP_ANEG)
/**
@@ -3702,14 +3700,23 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
struct link_config *lc)
{
struct fw_port_cmd c;
- unsigned int fc = 0, mdi = V_FW_PORT_CAP_MDI(FW_PORT_CAP_MDI_AUTO);
+ unsigned int mdi = V_FW_PORT_CAP_MDI(FW_PORT_CAP_MDI_AUTO);
+ unsigned int fc, fec;
- lc->link_ok = 0;
+ fc = 0;
if (lc->requested_fc & PAUSE_RX)
fc |= FW_PORT_CAP_FC_RX;
if (lc->requested_fc & PAUSE_TX)
fc |= FW_PORT_CAP_FC_TX;
+ fec = 0;
+ if (lc->requested_fec & FEC_RS)
+ fec |= FW_PORT_CAP_FEC_RS;
+ if (lc->requested_fec & FEC_BASER_RS)
+ fec |= FW_PORT_CAP_FEC_BASER_RS;
+ if (lc->requested_fec & FEC_RESERVED)
+ fec |= FW_PORT_CAP_FEC_RESERVED;
+
memset(&c, 0, sizeof(c));
c.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) |
F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
@@ -3720,13 +3727,16 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
if (!(lc->supported & FW_PORT_CAP_ANEG)) {
c.u.l1cfg.rcap = cpu_to_be32((lc->supported & ADVERT_MASK) |
- fc);
- lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
+ fc | fec);
+ lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
+ lc->fec = lc->requested_fec;
} else if (lc->autoneg == AUTONEG_DISABLE) {
- c.u.l1cfg.rcap = cpu_to_be32(lc->requested_speed | fc | mdi);
- lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
+ c.u.l1cfg.rcap = cpu_to_be32(lc->requested_speed |
+ fc | fec | mdi);
+ lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
+ lc->fec = lc->requested_fec;
} else
- c.u.l1cfg.rcap = cpu_to_be32(lc->advertising | fc | mdi);
+ c.u.l1cfg.rcap = cpu_to_be32(lc->advertising | fc | fec | mdi);
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
@@ -7514,18 +7524,14 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
}
if (link_ok != lc->link_ok || speed != lc->speed ||
fc != lc->fc) { /* something changed */
- int reason;
-
if (!link_ok && lc->link_ok)
- reason = G_FW_PORT_CMD_LINKDNRC(stat);
- else
- reason = -1;
-
+ lc->link_down_rc = G_FW_PORT_CMD_LINKDNRC(stat);
lc->link_ok = link_ok;
lc->speed = speed;
lc->fc = fc;
lc->supported = be16_to_cpu(p->u.info.pcap);
- t4_os_link_changed(adap, i, link_ok, reason);
+ lc->lp_advertising = be16_to_cpu(p->u.info.lpacap);
+ t4_os_link_changed(adap, i, link_ok);
}
} else {
CH_WARN_RATELIMIT(adap, "Unknown firmware reply %d\n", opcode);
@@ -7559,17 +7565,34 @@ static void get_pci_mode(struct adapter *adapter,
/**
* init_link_config - initialize a link's SW state
* @lc: structure holding the link state
- * @caps: link capabilities
+ * @pcaps: supported link capabilities
+ * @acaps: advertised link capabilities
*
* Initializes the SW state maintained for each link, including the link's
* capabilities and default speed/flow-control/autonegotiation settings.
*/
-static void init_link_config(struct link_config *lc, unsigned int caps)
+static void init_link_config(struct link_config *lc, unsigned int pcaps,
+ unsigned int acaps)
{
- lc->supported = caps;
+ unsigned int fec;
+
+ lc->supported = pcaps;
+ lc->lp_advertising = 0;
lc->requested_speed = 0;
lc->speed = 0;
lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
+ lc->link_ok = 0;
+ lc->link_down_rc = 255;
+
+ fec = 0;
+ if (acaps & FW_PORT_CAP_FEC_RS)
+ fec |= FEC_RS;
+ if (acaps & FW_PORT_CAP_FEC_BASER_RS)
+ fec |= FEC_BASER_RS;
+ if (acaps & FW_PORT_CAP_FEC_RESERVED)
+ fec |= FEC_RESERVED;
+ lc->requested_fec = lc->fec = fec;
+
if (lc->supported & FW_PORT_CAP_ANEG) {
lc->advertising = lc->supported & ADVERT_MASK;
lc->autoneg = AUTONEG_ENABLE;
@@ -8017,12 +8040,17 @@ int t4_init_tp_params(struct adapter *adap)
read_filter_mode_and_ingress_config(adap);
/*
- * For T6, cache the adapter's compressed error vector
- * and passing outer header info for encapsulated packets.
+ * Cache a mask of the bits that represent the error vector portion of
+ * rx_pkt.err_vec. T6+ can use a compressed error vector to make room
+ * for information about outer encapsulation (GENEVE/VXLAN/NVGRE).
*/
+ tpp->err_vec_mask = htobe16(0xffff);
if (chip_id(adap) > CHELSIO_T5) {
v = t4_read_reg(adap, A_TP_OUT_CONFIG);
- tpp->rx_pkt_encap = (v & F_CRXPKTENC) ? 1 : 0;
+ if (v & F_CRXPKTENC) {
+ tpp->err_vec_mask =
+ htobe16(V_T6_COMPR_RXERR_VEC(M_T6_COMPR_RXERR_VEC));
+ }
}
return 0;
@@ -8118,7 +8146,8 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf, int port_id)
p->port_type = G_FW_PORT_CMD_PTYPE(ret);
p->mod_type = G_FW_PORT_CMD_MODTYPE(ret);
- init_link_config(&p->link_cfg, be16_to_cpu(c.u.info.pcap));
+ init_link_config(&p->link_cfg, be16_to_cpu(c.u.info.pcap),
+ be16_to_cpu(c.u.info.acap));
}
ret = t4_alloc_vi(adap, mbox, j, pf, vf, 1, addr, &rss_size);
diff --git a/sys/dev/cxgbe/common/t4_msg.h b/sys/dev/cxgbe/common/t4_msg.h
index ea48fc6..830743b 100644
--- a/sys/dev/cxgbe/common/t4_msg.h
+++ b/sys/dev/cxgbe/common/t4_msg.h
@@ -2014,7 +2014,7 @@ struct cpl_rx_pkt {
#define S_T6_COMPR_RXERR_VEC 0
#define M_T6_COMPR_RXERR_VEC 0x3F
-#define V_T6_COMPR_RXERR_VEC(x) ((x) << S_T6_COMPR_RXERR_LEN)
+#define V_T6_COMPR_RXERR_VEC(x) ((x) << S_T6_COMPR_RXERR_VEC)
#define G_T6_COMPR_RXERR_VEC(x) \
(((x) >> S_T6_COMPR_RXERR_VEC) & M_T6_COMPR_RXERR_VEC)
@@ -2026,7 +2026,7 @@ struct cpl_rx_pkt {
* RX_ERROR_IP_HDR_LEN, RX_ERROR_ETH_HDR_LEN
*/
#define S_T6_COMPR_RXERR_LEN 1
-#define V_T6_COMPR_RXERR_LEN(x) ((x) << S_COMPR_T6_RXERR_LEN)
+#define V_T6_COMPR_RXERR_LEN(x) ((x) << S_T6_COMPR_RXERR_LEN)
#define F_T6_COMPR_RXERR_LEN V_COMPR_T6_RXERR_LEN(1U)
#define S_T6_COMPR_RXERR_TCP_OPT 2
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index 2a8305d..d976313 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -348,6 +348,24 @@ static int t4_pause_settings = PAUSE_TX | PAUSE_RX;
TUNABLE_INT("hw.cxgbe.pause_settings", &t4_pause_settings);
/*
+ * Forward Error Correction settings (bit 0, 1, 2 = FEC_RS, FEC_BASER_RS,
+ * FEC_RESERVED respectively).
+ * -1 to run with the firmware default.
+ * 0 to disable FEC.
+ */
+static int t4_fec = -1;
+TUNABLE_INT("hw.cxgbe.fec", &t4_fec);
+
+/*
+ * Link autonegotiation.
+ * -1 to run with the firmware default.
+ * 0 to disable.
+ * 1 to enable.
+ */
+static int t4_autoneg = -1;
+TUNABLE_INT("hw.cxgbe.autoneg", &t4_autoneg);
+
+/*
* Firmware auto-install by driver during attach (0, 1, 2 = prohibited, allowed,
* encouraged respectively).
*/
@@ -482,6 +500,8 @@ static int sysctl_holdoff_pktc_idx(SYSCTL_HANDLER_ARGS);
static int sysctl_qsize_rxq(SYSCTL_HANDLER_ARGS);
static int sysctl_qsize_txq(SYSCTL_HANDLER_ARGS);
static int sysctl_pause_settings(SYSCTL_HANDLER_ARGS);
+static int sysctl_fec(SYSCTL_HANDLER_ARGS);
+static int sysctl_autoneg(SYSCTL_HANDLER_ARGS);
static int sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS);
static int sysctl_temperature(SYSCTL_HANDLER_ARGS);
#ifdef SBUF_DRAIN
@@ -910,6 +930,7 @@ t4_attach(device_t dev)
n10g = n1g = 0;
for_each_port(sc, i) {
struct port_info *pi;
+ struct link_config *lc;
pi = malloc(sizeof(*pi), M_CXGBE, M_ZERO | M_WAITOK);
sc->port[i] = pi;
@@ -938,12 +959,19 @@ t4_attach(device_t dev)
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;
+ lc = &pi->link_cfg;
+ lc->requested_fc &= ~(PAUSE_TX | PAUSE_RX);
+ lc->requested_fc |= t4_pause_settings;
+ if (t4_fec != -1) {
+ lc->requested_fec = t4_fec &
+ G_FW_PORT_CAP_FEC(lc->supported);
+ }
+ if (lc->supported & FW_PORT_CAP_ANEG && t4_autoneg != -1) {
+ lc->autoneg = t4_autoneg ? AUTONEG_ENABLE :
+ AUTONEG_DISABLE;
+ }
- rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, &pi->link_cfg);
+ rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc);
if (rc != 0) {
device_printf(dev, "port %d l1cfg failed: %d\n", i, rc);
free(pi->vi, M_CXGBE);
@@ -966,8 +994,6 @@ t4_attach(device_t dev)
n1g++;
}
- pi->linkdnrc = -1;
-
pi->dev = device_add_child(dev, sc->names->ifnet_name, -1);
if (pi->dev == NULL) {
device_printf(dev,
@@ -3867,8 +3893,8 @@ cxgbe_uninit_synchronized(struct vi_info *vi)
pi->link_cfg.link_ok = 0;
pi->link_cfg.speed = 0;
- pi->linkdnrc = -1;
- t4_os_link_changed(sc, pi->port_id, 0, -1);
+ pi->link_cfg.link_down_rc = 255;
+ t4_os_link_changed(sc, pi->port_id, 0);
return (0);
}
@@ -5124,8 +5150,14 @@ cxgbe_sysctls(struct port_info *pi)
}
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)");
+ CTLTYPE_STRING | CTLFLAG_RW, pi, 0, sysctl_pause_settings, "A",
+ "PAUSE settings (bit 0 = rx_pause, bit 1 = tx_pause)");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "fec",
+ CTLTYPE_STRING | CTLFLAG_RW, pi, 0, sysctl_fec, "A",
+ "Forward Error Correction (bit 0 = RS, bit 1 = BASER_RS)");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "autoneg",
+ CTLTYPE_INT | CTLFLAG_RW, pi, 0, sysctl_autoneg, "I",
+ "autonegotiation (-1 = not supported)");
SYSCTL_ADD_INT(ctx, children, OID_AUTO, "max_speed", CTLFLAG_RD, NULL,
port_top_speed(pi), "max speed (in Gbps)");
@@ -5586,12 +5618,9 @@ sysctl_pause_settings(SYSCTL_HANDLER_ARGS)
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_l1cfg(sc, sc->mbox, pi->tx_chan, lc);
- lc->link_ok = link_ok; /* restore */
}
end_synchronized_op(sc, 0);
}
@@ -5600,6 +5629,97 @@ sysctl_pause_settings(SYSCTL_HANDLER_ARGS)
}
static int
+sysctl_fec(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\1RS\2BASER_RS\3RESERVED";
+
+ 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->fec & M_FW_PORT_CAP_FEC, bits);
+ rc = sbuf_finish(sb);
+ sbuf_delete(sb);
+ } else {
+ char s[2];
+ int n;
+
+ s[0] = '0' + (lc->requested_fec & M_FW_PORT_CAP_FEC);
+ 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 & ~M_FW_PORT_CAP_FEC)
+ return (EINVAL); /* some other bit is set too */
+
+ rc = begin_synchronized_op(sc, &pi->vi[0], SLEEP_OK | INTR_OK,
+ "t4fec");
+ if (rc)
+ return (rc);
+ if ((lc->requested_fec & M_FW_PORT_CAP_FEC) != n) {
+ lc->requested_fec = n &
+ G_FW_PORT_CAP_FEC(lc->supported);
+ rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc);
+ }
+ end_synchronized_op(sc, 0);
+ }
+
+ return (rc);
+}
+
+static int
+sysctl_autoneg(SYSCTL_HANDLER_ARGS)
+{
+ struct port_info *pi = arg1;
+ struct adapter *sc = pi->adapter;
+ struct link_config *lc = &pi->link_cfg;
+ int rc, val, old;
+
+ if (lc->supported & FW_PORT_CAP_ANEG)
+ val = lc->autoneg == AUTONEG_ENABLE ? 1 : 0;
+ else
+ val = -1;
+ rc = sysctl_handle_int(oidp, &val, 0, req);
+ if (rc != 0 || req->newptr == NULL)
+ return (rc);
+ if ((lc->supported & FW_PORT_CAP_ANEG) == 0)
+ return (ENOTSUP);
+
+ val = val ? AUTONEG_ENABLE : AUTONEG_DISABLE;
+ if (lc->autoneg == val)
+ return (0); /* no change */
+
+ rc = begin_synchronized_op(sc, &pi->vi[0], SLEEP_OK | INTR_OK,
+ "t4aneg");
+ if (rc)
+ return (rc);
+ old = lc->autoneg;
+ lc->autoneg = val;
+ rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc);
+ if (rc != 0)
+ lc->autoneg = old;
+ return (rc);
+}
+
+static int
sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS)
{
struct adapter *sc = arg1;
@@ -6344,6 +6464,7 @@ sysctl_linkdnrc(SYSCTL_HANDLER_ARGS)
{
int rc = 0;
struct port_info *pi = arg1;
+ struct link_config *lc = &pi->link_cfg;
struct sbuf *sb;
rc = sysctl_wire_old_buffer(req, 0);
@@ -6353,10 +6474,10 @@ sysctl_linkdnrc(SYSCTL_HANDLER_ARGS)
if (sb == NULL)
return (ENOMEM);
- if (pi->linkdnrc < 0)
+ if (lc->link_ok || lc->link_down_rc == 255)
sbuf_printf(sb, "n/a");
else
- sbuf_printf(sb, "%s", t4_link_down_rc_str(pi->linkdnrc));
+ sbuf_printf(sb, "%s", t4_link_down_rc_str(lc->link_down_rc));
rc = sbuf_finish(sb);
sbuf_delete(sb);
@@ -7070,25 +7191,23 @@ sysctl_tids(SYSCTL_HANDLER_ARGS)
}
if (t->ntids) {
+ sbuf_printf(sb, "TID range: ");
if (t4_read_reg(sc, A_LE_DB_CONFIG) & F_HASHEN) {
- uint32_t b;
+ uint32_t b, hb;
- if (chip_id(sc) <= CHELSIO_T5)
+ if (chip_id(sc) <= CHELSIO_T5) {
b = t4_read_reg(sc, A_LE_DB_SERVER_INDEX) / 4;
- else
- b = t4_read_reg(sc, A_LE_DB_SRVR_START_INDEX);
-
- if (b) {
- sbuf_printf(sb, "TID range: 0-%u, %u-%u", b - 1,
- t4_read_reg(sc, A_LE_DB_TID_HASHBASE) / 4,
- t->ntids - 1);
+ hb = t4_read_reg(sc, A_LE_DB_TID_HASHBASE) / 4;
} else {
- sbuf_printf(sb, "TID range: %u-%u",
- t4_read_reg(sc, A_LE_DB_TID_HASHBASE) / 4,
- t->ntids - 1);
+ b = t4_read_reg(sc, A_LE_DB_SRVR_START_INDEX);
+ hb = t4_read_reg(sc, A_T6_LE_DB_HASH_TID_BASE);
}
+
+ if (b)
+ sbuf_printf(sb, "0-%u, ", b - 1);
+ sbuf_printf(sb, "%u-%u", hb, t->ntids - 1);
} else
- sbuf_printf(sb, "TID range: 0-%u", t->ntids - 1);
+ sbuf_printf(sb, "0-%u", t->ntids - 1);
sbuf_printf(sb, ", in use: %u\n",
atomic_load_acq_int(&t->tids_in_use));
}
@@ -8826,19 +8945,13 @@ t4_os_portmod_changed(const struct adapter *sc, int idx)
}
void
-t4_os_link_changed(struct adapter *sc, int idx, int link_stat, int reason)
+t4_os_link_changed(struct adapter *sc, int idx, int link_stat)
{
struct port_info *pi = sc->port[idx];
struct vi_info *vi;
struct ifnet *ifp;
int v;
- if (link_stat)
- pi->linkdnrc = -1;
- else {
- if (reason >= 0)
- pi->linkdnrc = reason;
- }
for_each_vi(pi, v, vi) {
ifp = vi->ifp;
if (ifp == NULL)
diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c
index 9be9acb..9152d9f 100644
--- a/sys/dev/cxgbe/t4_sge.c
+++ b/sys/dev/cxgbe/t4_sge.c
@@ -1799,7 +1799,7 @@ t4_eth_rx(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m0)
M_HASHTYPE_SET(m0, M_HASHTYPE_OPAQUE);
m0->m_pkthdr.flowid = be32toh(rss->hash_val);
- if (cpl->csum_calc && !cpl->err_vec) {
+ if (cpl->csum_calc && !(cpl->err_vec & sc->params.tp.err_vec_mask)) {
if (ifp->if_capenable & IFCAP_RXCSUM &&
cpl->l2info & htobe32(F_RXF_IP)) {
m0->m_pkthdr.csum_flags = (CSUM_IP_CHECKED |
diff --git a/sys/dev/cxgbe/t4_vf.c b/sys/dev/cxgbe/t4_vf.c
index 4492eba..705b206 100644
--- a/sys/dev/cxgbe/t4_vf.c
+++ b/sys/dev/cxgbe/t4_vf.c
@@ -670,8 +670,6 @@ t4vf_attach(device_t dev)
n1g++;
}
- pi->linkdnrc = -1;
-
pi->dev = device_add_child(dev, sc->names->vf_ifnet_name, -1);
if (pi->dev == NULL) {
device_printf(dev,
OpenPOWER on IntegriCloud