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