svn commit: r333782 - head/sys/dev/cxgbe
Navdeep Parhar
np at FreeBSD.org
Fri May 18 06:09:17 UTC 2018
Author: np
Date: Fri May 18 06:09:15 2018
New Revision: 333782
URL: https://svnweb.freebsd.org/changeset/base/333782
Log:
cxgbe(4): Implement ifnet callbacks that deal with send tags.
An etid (ethoffload tid) is allocated for a send tag and it acquires a
reference on the traffic class that matches the send parameters
associated with the tag.
Sponsored by: Chelsio Communications
Modified:
head/sys/dev/cxgbe/adapter.h
head/sys/dev/cxgbe/offload.h
head/sys/dev/cxgbe/t4_main.c
head/sys/dev/cxgbe/t4_sched.c
Modified: head/sys/dev/cxgbe/adapter.h
==============================================================================
--- head/sys/dev/cxgbe/adapter.h Fri May 18 04:13:58 2018 (r333781)
+++ head/sys/dev/cxgbe/adapter.h Fri May 18 06:09:15 2018 (r333782)
@@ -1236,6 +1236,15 @@ int t4_free_tx_sched(struct adapter *);
void t4_update_tx_sched(struct adapter *);
int t4_reserve_cl_rl_kbps(struct adapter *, int, u_int, int *);
void t4_release_cl_rl_kbps(struct adapter *, int, int);
+#ifdef RATELIMIT
+void t4_init_etid_table(struct adapter *);
+void t4_free_etid_table(struct adapter *);
+int cxgbe_snd_tag_alloc(struct ifnet *, union if_snd_tag_alloc_params *,
+ struct m_snd_tag **);
+int cxgbe_snd_tag_modify(struct m_snd_tag *, union if_snd_tag_modify_params *);
+int cxgbe_snd_tag_query(struct m_snd_tag *, union if_snd_tag_query_params *);
+void cxgbe_snd_tag_free(struct m_snd_tag *);
+#endif
/* t4_filter.c */
int get_filter_mode(struct adapter *, uint32_t *);
Modified: head/sys/dev/cxgbe/offload.h
==============================================================================
--- head/sys/dev/cxgbe/offload.h Fri May 18 04:13:58 2018 (r333781)
+++ head/sys/dev/cxgbe/offload.h Fri May 18 06:09:15 2018 (r333782)
@@ -79,6 +79,38 @@ union aopen_entry {
union aopen_entry *next;
};
+struct cxgbe_snd_tag {
+ struct m_snd_tag com;
+ struct adapter *adapter;
+ u_int flags;
+ struct mtx lock;
+ int port_id;
+ int etid;
+ struct sge_wrq *eo_txq;
+ uint16_t iqid;
+ int8_t schedcl;
+ uint64_t max_rate; /* in bytes/s */
+ int8_t next_credits; /* need these many tx credits next */
+ uint8_t next_nsegs; /* next WR will have these many GL segs total */
+ uint8_t next_msegs; /* max segs for a single mbuf in next chain */
+ uint8_t tx_total; /* total tx WR credits (in 16B units) */
+ uint8_t tx_credits; /* tx WR credits (in 16B units) available */
+ uint8_t tx_nocompl; /* tx WR credits since last compl request */
+ uint8_t ncompl; /* # of completions outstanding. */
+};
+
+static inline struct cxgbe_snd_tag *
+mst_to_cst(struct m_snd_tag *t)
+{
+
+ return (__containerof(t, struct cxgbe_snd_tag, com));
+}
+
+union etid_entry {
+ struct cxgbe_snd_tag *cst;
+ union etid_entry *next;
+};
+
/*
* Holds the size, base address, free list start, etc of the TID, server TID,
* and active-open TID tables. The tables themselves are allocated dynamically.
@@ -98,8 +130,8 @@ struct tid_info {
struct mtx atid_lock __aligned(CACHE_LINE_SIZE);
union aopen_entry *atid_tab;
- u_int natids;
union aopen_entry *afree;
+ u_int natids;
u_int atids_in_use;
struct mtx ftid_lock __aligned(CACHE_LINE_SIZE);
@@ -115,9 +147,11 @@ struct tid_info {
/* ntids, tids_in_use */
struct mtx etid_lock __aligned(CACHE_LINE_SIZE);
- struct etid_entry *etid_tab;
+ union etid_entry *etid_tab;
+ union etid_entry *efree;
u_int netids;
u_int etid_base;
+ u_int etids_in_use;
};
struct t4_range {
Modified: head/sys/dev/cxgbe/t4_main.c
==============================================================================
--- head/sys/dev/cxgbe/t4_main.c Fri May 18 04:13:58 2018 (r333781)
+++ head/sys/dev/cxgbe/t4_main.c Fri May 18 06:09:15 2018 (r333782)
@@ -1105,6 +1105,9 @@ t4_attach(device_t dev)
t4_init_l2t(sc, M_WAITOK);
t4_init_tx_sched(sc);
+#ifdef RATELIMIT
+ t4_init_etid_table(sc);
+#endif
/*
* Second pass over the ports. This time we know the number of rx and
@@ -1375,6 +1378,9 @@ t4_detach_common(device_t dev)
if (sc->l2t)
t4_free_l2t(sc->l2t);
+#ifdef RATELIMIT
+ t4_free_etid_table(sc);
+#endif
#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
free(sc->sge.ofld_txq, M_CXGBE);
@@ -1486,6 +1492,12 @@ cxgbe_vi_attach(device_t dev, struct vi_info *vi)
ifp->if_transmit = cxgbe_transmit;
ifp->if_qflush = cxgbe_qflush;
ifp->if_get_counter = cxgbe_get_counter;
+#ifdef RATELIMIT
+ ifp->if_snd_tag_alloc = cxgbe_snd_tag_alloc;
+ ifp->if_snd_tag_modify = cxgbe_snd_tag_modify;
+ ifp->if_snd_tag_query = cxgbe_snd_tag_query;
+ ifp->if_snd_tag_free = cxgbe_snd_tag_free;
+#endif
ifp->if_capabilities = T4_CAP;
#ifdef TCP_OFFLOAD
@@ -7928,8 +7940,8 @@ sysctl_tids(SYSCTL_HANDLER_ARGS)
}
if (t->netids) {
- sbuf_printf(sb, "ETID range: %u-%u\n", t->etid_base,
- t->etid_base + t->netids - 1);
+ sbuf_printf(sb, "ETID range: %u-%u, in use: %u\n", t->etid_base,
+ t->etid_base + t->netids - 1, t->etids_in_use);
}
sbuf_printf(sb, "HW TID usage: %u IP users, %u IPv6 users",
Modified: head/sys/dev/cxgbe/t4_sched.c
==============================================================================
--- head/sys/dev/cxgbe/t4_sched.c Fri May 18 04:13:58 2018 (r333781)
+++ head/sys/dev/cxgbe/t4_sched.c Fri May 18 06:09:15 2018 (r333782)
@@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_inet6.h"
+#include "opt_ratelimit.h"
#include <sys/types.h>
#include <sys/malloc.h>
@@ -463,3 +464,197 @@ t4_release_cl_rl_kbps(struct adapter *sc, int port_id,
tc->refcount--;
mtx_unlock(&sc->tc_lock);
}
+
+#ifdef RATELIMIT
+void
+t4_init_etid_table(struct adapter *sc)
+{
+ int i;
+ struct tid_info *t;
+
+ if (!is_ethoffload(sc))
+ return;
+
+ t = &sc->tids;
+ MPASS(t->netids > 0);
+
+ mtx_init(&t->etid_lock, "etid lock", NULL, MTX_DEF);
+ t->etid_tab = malloc(sizeof(*t->etid_tab) * t->netids, M_CXGBE,
+ M_ZERO | M_WAITOK);
+ t->efree = t->etid_tab;
+ t->etids_in_use = 0;
+ for (i = 1; i < t->netids; i++)
+ t->etid_tab[i - 1].next = &t->etid_tab[i];
+ t->etid_tab[t->netids - 1].next = NULL;
+}
+
+void
+t4_free_etid_table(struct adapter *sc)
+{
+ struct tid_info *t;
+
+ if (!is_ethoffload(sc))
+ return;
+
+ t = &sc->tids;
+ MPASS(t->netids > 0);
+
+ free(t->etid_tab, M_CXGBE);
+ t->etid_tab = NULL;
+
+ if (mtx_initialized(&t->etid_lock))
+ mtx_destroy(&t->etid_lock);
+}
+
+/* etid services */
+static int alloc_etid(struct adapter *, struct cxgbe_snd_tag *);
+static void free_etid(struct adapter *, int);
+
+static int
+alloc_etid(struct adapter *sc, struct cxgbe_snd_tag *cst)
+{
+ struct tid_info *t = &sc->tids;
+ int etid = -1;
+
+ mtx_lock(&t->etid_lock);
+ if (t->efree) {
+ union etid_entry *p = t->efree;
+
+ etid = p - t->etid_tab + t->etid_base;
+ t->efree = p->next;
+ p->cst = cst;
+ t->etids_in_use++;
+ }
+ mtx_unlock(&t->etid_lock);
+ return (etid);
+}
+
+#ifdef notyet
+struct cxgbe_snd_tag *
+lookup_etid(struct adapter *sc, int etid)
+{
+ struct tid_info *t = &sc->tids;
+
+ return (t->etid_tab[etid - t->etid_base].cst);
+}
+#endif
+
+static void
+free_etid(struct adapter *sc, int etid)
+{
+ struct tid_info *t = &sc->tids;
+ union etid_entry *p = &t->etid_tab[etid - t->etid_base];
+
+ mtx_lock(&t->etid_lock);
+ p->next = t->efree;
+ t->efree = p;
+ t->etids_in_use--;
+ mtx_unlock(&t->etid_lock);
+}
+
+int
+cxgbe_snd_tag_alloc(struct ifnet *ifp, union if_snd_tag_alloc_params *params,
+ struct m_snd_tag **pt)
+{
+ int rc, schedcl;
+ struct vi_info *vi = ifp->if_softc;
+ struct port_info *pi = vi->pi;
+ struct adapter *sc = pi->adapter;
+ struct cxgbe_snd_tag *cst;
+
+ if (params->hdr.type != IF_SND_TAG_TYPE_RATE_LIMIT)
+ return (ENOTSUP);
+
+ rc = t4_reserve_cl_rl_kbps(sc, pi->port_id,
+ (params->rate_limit.max_rate * 8ULL / 1000), &schedcl);
+ if (rc != 0)
+ return (rc);
+ MPASS(schedcl >= 0 && schedcl < sc->chip_params->nsched_cls);
+
+ cst = malloc(sizeof(*cst), M_CXGBE, M_ZERO | M_NOWAIT);
+ if (cst == NULL) {
+failed:
+ t4_release_cl_rl_kbps(sc, pi->port_id, schedcl);
+ return (ENOMEM);
+ }
+
+ cst->etid = alloc_etid(sc, cst);
+ if (cst->etid < 0) {
+ free(cst, M_CXGBE);
+ goto failed;
+ }
+
+ mtx_init(&cst->lock, "cst_lock", NULL, MTX_DEF);
+ cst->com.ifp = ifp;
+ cst->adapter = sc;
+ cst->port_id = pi->port_id;
+ cst->schedcl = schedcl;
+ cst->max_rate = params->rate_limit.max_rate;
+ cst->next_credits = -1;
+ cst->tx_credits = sc->params.ofldq_wr_cred;
+ cst->tx_total = cst->tx_credits;
+
+ /*
+ * Queues will be selected later when the connection flowid is available.
+ */
+
+ *pt = &cst->com;
+ return (0);
+}
+
+/*
+ * Change in parameters, no change in ifp.
+ */
+int
+cxgbe_snd_tag_modify(struct m_snd_tag *mst,
+ union if_snd_tag_modify_params *params)
+{
+ int rc, schedcl;
+ struct cxgbe_snd_tag *cst = mst_to_cst(mst);
+ struct adapter *sc = cst->adapter;
+
+ /* XXX: is schedcl -1 ok here? */
+ MPASS(cst->schedcl >= 0 && cst->schedcl < sc->chip_params->nsched_cls);
+
+ rc = t4_reserve_cl_rl_kbps(sc, cst->port_id,
+ (params->rate_limit.max_rate * 8ULL / 1000), &schedcl);
+ if (rc != 0)
+ return (rc);
+ MPASS(schedcl >= 0 && schedcl < sc->chip_params->nsched_cls);
+ t4_release_cl_rl_kbps(sc, cst->port_id, cst->schedcl);
+ cst->schedcl = schedcl;
+ cst->max_rate = params->rate_limit.max_rate;
+
+ return (0);
+}
+
+int
+cxgbe_snd_tag_query(struct m_snd_tag *mst,
+ union if_snd_tag_query_params *params)
+{
+ struct cxgbe_snd_tag *cst = mst_to_cst(mst);
+
+ params->rate_limit.max_rate = cst->max_rate;
+
+#define CST_TO_MST_QLEVEL_SCALE (IF_SND_QUEUE_LEVEL_MAX / cst->tx_total)
+ params->rate_limit.queue_level =
+ (cst->tx_total - cst->tx_credits) * CST_TO_MST_QLEVEL_SCALE;
+
+ return (0);
+}
+
+void
+cxgbe_snd_tag_free(struct m_snd_tag *mst)
+{
+ struct cxgbe_snd_tag *cst = mst_to_cst(mst);
+ struct adapter *sc = cst->adapter;
+
+ if (cst->etid >= 0)
+ free_etid(sc, cst->etid);
+ if (cst->schedcl != -1)
+ t4_release_cl_rl_kbps(sc, cst->port_id, cst->schedcl);
+ if (mtx_initialized(&cst->lock))
+ mtx_destroy(&cst->lock);
+ free(cst, M_CXGBE);
+}
+#endif
More information about the svn-src-head
mailing list