diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -330,6 +330,7 @@ static void em_print_debug_info(struct e1000_softc *); static int em_is_valid_ether_addr(u8 *); static bool em_automask_tso(if_ctx_t); +static int em_sysctl_tso_tcp_flags_mask(SYSCTL_HANDLER_ARGS); static int em_sysctl_int_delay(SYSCTL_HANDLER_ARGS); static void em_add_int_delay_sysctl(struct e1000_softc *, const char *, const char *, struct em_int_delay_info *, int, int); @@ -855,6 +856,24 @@ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0, em_get_rs, "I", "Dump RS indexes"); + SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, + "tso_tcp_flags_mask_first_segment", + CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, + sc, 0, em_sysctl_tso_tcp_flags_mask, "IU", + "TSO TCP flags mask for first segment"); + + SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, + "tso_tcp_flags_mask_middle_segment", + CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, + sc, 1, em_sysctl_tso_tcp_flags_mask, "IU", + "TSO TCP flags mask for middle segment"); + + SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, + "tso_tcp_flags_mask_last_segment", + CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, + sc, 2, em_sysctl_tso_tcp_flags_mask, "IU", + "TSO TCP flags mask for last segment"); + scctx->isc_tx_nsegments = EM_MAX_SCATTER; scctx->isc_nrxqsets_max = scctx->isc_ntxqsets_max = em_set_num_queues(ctx); if (bootverbose) @@ -4896,6 +4915,43 @@ return (0); } +static int +em_sysctl_tso_tcp_flags_mask(SYSCTL_HANDLER_ARGS) +{ + struct e1000_softc *sc; + u32 reg, val, shift; + int error, mask; + + sc = oidp->oid_arg1; + switch (oidp->oid_arg2) { + case 0: + reg = E1000_DTXTCPFLGL; + shift = 0; + break; + case 1: + reg = E1000_DTXTCPFLGL; + shift = 16; + break; + case 2: + reg = E1000_DTXTCPFLGH; + shift = 0; + break; + default: + return (EINVAL); + break; + } + val = E1000_READ_REG(&sc->hw, reg); + mask = (val >> shift) & 0xfff; + error = sysctl_handle_int(oidp, &mask, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + if (mask < 0 || mask > 0xfff) + return (EINVAL); + val = (val & ~(0xfff << shift)) | (mask << shift); + E1000_WRITE_REG(&sc->hw, reg, val); + return (0); +} + static void em_add_int_delay_sysctl(struct e1000_softc *sc, const char *name, const char *description, struct em_int_delay_info *info,