From owner-svn-src-all@FreeBSD.ORG Tue Jan 15 07:07:30 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id DA464D17; Tue, 15 Jan 2013 07:07:30 +0000 (UTC) (envelope-from np@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id B352D81; Tue, 15 Jan 2013 07:07:30 +0000 (UTC) Received: from svn.freebsd.org (svn.FreeBSD.org [8.8.178.70]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id r0F77UUK020589; Tue, 15 Jan 2013 07:07:30 GMT (envelope-from np@svn.freebsd.org) Received: (from np@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id r0F77UxB020587; Tue, 15 Jan 2013 07:07:30 GMT (envelope-from np@svn.freebsd.org) Message-Id: <201301150707.r0F77UxB020587@svn.freebsd.org> From: Navdeep Parhar Date: Tue, 15 Jan 2013 07:07:30 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r245448 - head/sys/dev/cxgbe/tom X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 15 Jan 2013 07:07:30 -0000 Author: np Date: Tue Jan 15 07:07:29 2013 New Revision: 245448 URL: http://svnweb.freebsd.org/changeset/base/245448 Log: cxgbe/tom: Basic CLIP table management. This is the Compressed Local IPv6 table on the chip. To save space, the chip uses an index into this table instead of a full IPv6 address in some of its hardware data structures. For now the driver fills this table with all the local IPv6 addresses that it sees at the time the table is initialized. I'll improve this later so that the table is updated whenever new IPv6 addresses are configured or existing ones deleted. MFC after: 1 week Modified: head/sys/dev/cxgbe/tom/t4_tom.c head/sys/dev/cxgbe/tom/t4_tom.h Modified: head/sys/dev/cxgbe/tom/t4_tom.c ============================================================================== --- head/sys/dev/cxgbe/tom/t4_tom.c Tue Jan 15 05:33:40 2013 (r245447) +++ head/sys/dev/cxgbe/tom/t4_tom.c Tue Jan 15 07:07:29 2013 (r245448) @@ -41,11 +41,14 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include +#include #include #include #include +#include #define TCPSTATES #include #include @@ -82,6 +85,11 @@ static void queue_tid_release(struct ada static void release_offload_resources(struct toepcb *); static int alloc_tid_tabs(struct tid_info *); static void free_tid_tabs(struct tid_info *); +static int add_lip(struct adapter *, struct in6_addr *); +static int delete_lip(struct adapter *, struct in6_addr *); +static struct clip_entry *search_lip(struct tom_data *, struct in6_addr *); +static void init_clip_table(struct adapter *, struct tom_data *); +static void destroy_clip_table(struct adapter *, struct tom_data *); static void free_tom_data(struct adapter *, struct tom_data *); struct toepcb * @@ -246,8 +254,8 @@ release_offload_resources(struct toepcb KASSERT(!(toep->flags & TPF_ATTACHED), ("%s: %p is still attached.", __func__, toep)); - CTR4(KTR_CXGBE, "%s: toep %p (tid %d, l2te %p)", - __func__, toep, tid, toep->l2te); + CTR5(KTR_CXGBE, "%s: toep %p (tid %d, l2te %p, ce %p)", + __func__, toep, tid, toep->l2te, toep->ce); if (toep->ulp_mode == ULP_MODE_TCPDDP) release_ddp_resources(toep); @@ -260,6 +268,9 @@ release_offload_resources(struct toepcb release_tid(sc, tid, toep->ctrlq); } + if (toep->ce) + release_lip(td, toep->ce); + mtx_lock(&td->toep_list_lock); TAILQ_REMOVE(&td->toep_list, toep, link); mtx_unlock(&td->toep_list_lock); @@ -588,9 +599,157 @@ free_tid_tabs(struct tid_info *t) mtx_destroy(&t->stid_lock); } +static int +add_lip(struct adapter *sc, struct in6_addr *lip) +{ + struct fw_clip_cmd c; + + ASSERT_SYNCHRONIZED_OP(sc); + /* mtx_assert(&td->clip_table_lock, MA_OWNED); */ + + memset(&c, 0, sizeof(c)); + c.op_to_write = htonl(V_FW_CMD_OP(FW_CLIP_CMD) | F_FW_CMD_REQUEST | + F_FW_CMD_WRITE); + c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_ALLOC | FW_LEN16(c)); + c.ip_hi = *(uint64_t *)&lip->s6_addr[0]; + c.ip_lo = *(uint64_t *)&lip->s6_addr[8]; + + return (t4_wr_mbox_ns(sc, sc->mbox, &c, sizeof(c), &c)); +} + +static int +delete_lip(struct adapter *sc, struct in6_addr *lip) +{ + struct fw_clip_cmd c; + + ASSERT_SYNCHRONIZED_OP(sc); + /* mtx_assert(&td->clip_table_lock, MA_OWNED); */ + + memset(&c, 0, sizeof(c)); + c.op_to_write = htonl(V_FW_CMD_OP(FW_CLIP_CMD) | F_FW_CMD_REQUEST | + F_FW_CMD_READ); + c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_FREE | FW_LEN16(c)); + c.ip_hi = *(uint64_t *)&lip->s6_addr[0]; + c.ip_lo = *(uint64_t *)&lip->s6_addr[8]; + + return (t4_wr_mbox_ns(sc, sc->mbox, &c, sizeof(c), &c)); +} + +static struct clip_entry * +search_lip(struct tom_data *td, struct in6_addr *lip) +{ + struct clip_entry *ce; + + mtx_assert(&td->clip_table_lock, MA_OWNED); + + TAILQ_FOREACH(ce, &td->clip_table, link) { + if (IN6_ARE_ADDR_EQUAL(&ce->lip, lip)) + return (ce); + } + + return (NULL); +} + +struct clip_entry * +hold_lip(struct tom_data *td, struct in6_addr *lip) +{ + struct clip_entry *ce; + + mtx_lock(&td->clip_table_lock); + ce = search_lip(td, lip); + if (ce != NULL) + ce->refcount++; + mtx_unlock(&td->clip_table_lock); + + return (ce); +} + +void +release_lip(struct tom_data *td, struct clip_entry *ce) +{ + + mtx_lock(&td->clip_table_lock); + KASSERT(search_lip(td, &ce->lip) == ce, + ("%s: CLIP entry %p p not in CLIP table.", __func__, ce)); + KASSERT(ce->refcount > 0, + ("%s: CLIP entry %p has refcount 0", __func__, ce)); + --ce->refcount; + mtx_unlock(&td->clip_table_lock); +} + +static void +init_clip_table(struct adapter *sc, struct tom_data *td) +{ + struct in6_ifaddr *ia; + struct in6_addr *lip, tlip; + struct clip_entry *ce; + + ASSERT_SYNCHRONIZED_OP(sc); + + mtx_init(&td->clip_table_lock, "CLIP table lock", NULL, MTX_DEF); + TAILQ_INIT(&td->clip_table); + + IN6_IFADDR_RLOCK(); + TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) { + lip = &ia->ia_addr.sin6_addr; + + KASSERT(!IN6_IS_ADDR_MULTICAST(lip), + ("%s: mcast address in in6_ifaddr list", __func__)); + + if (IN6_IS_ADDR_LOOPBACK(lip)) + continue; + if (IN6_IS_SCOPE_EMBED(lip)) { + /* Remove the embedded scope */ + tlip = *lip; + lip = &tlip; + in6_clearscope(lip); + } + /* + * XXX: how to weed out the link local address for the loopback + * interface? It's fe80::1 usually (always?). + */ + + mtx_lock(&td->clip_table_lock); + if (search_lip(td, lip) == NULL) { + ce = malloc(sizeof(*ce), M_CXGBE, M_NOWAIT); + memcpy(&ce->lip, lip, sizeof(ce->lip)); + ce->refcount = 0; + if (add_lip(sc, lip) == 0) + TAILQ_INSERT_TAIL(&td->clip_table, ce, link); + else + free(ce, M_CXGBE); + } + mtx_unlock(&td->clip_table_lock); + } + IN6_IFADDR_RUNLOCK(); +} + +static void +destroy_clip_table(struct adapter *sc, struct tom_data *td) +{ + struct clip_entry *ce, *ce_temp; + + if (mtx_initialized(&td->clip_table_lock)) { + mtx_lock(&td->clip_table_lock); + TAILQ_FOREACH_SAFE(ce, &td->clip_table, link, ce_temp) { + KASSERT(ce->refcount == 0, + ("%s: CLIP entry %p still in use (%d)", __func__, + ce, ce->refcount)); + TAILQ_REMOVE(&td->clip_table, ce, link); + delete_lip(sc, &ce->lip); + free(ce, M_CXGBE); + } + mtx_unlock(&td->clip_table_lock); + mtx_destroy(&td->clip_table_lock); + } +} + static void free_tom_data(struct adapter *sc, struct tom_data *td) { + + ASSERT_SYNCHRONIZED_OP(sc); + KASSERT(TAILQ_EMPTY(&td->toep_list), ("%s: TOE PCB list is not empty.", __func__)); KASSERT(td->lctx_count == 0, @@ -599,6 +758,7 @@ free_tom_data(struct adapter *sc, struct t4_uninit_l2t_cpl_handlers(sc); t4_uninit_cpl_io_handlers(sc); t4_uninit_ddp(sc, td); + destroy_clip_table(sc, td); if (td->listen_mask != 0) hashdestroy(td->listen_hash, M_CXGBE, td->listen_mask); @@ -644,8 +804,12 @@ t4_tom_activate(struct adapter *sc) if (rc != 0) goto done; + /* DDP page pods and CPL handlers */ t4_init_ddp(sc, td); + /* CLIP table for IPv6 offload */ + init_clip_table(sc, td); + /* CPL handlers */ t4_init_connect_cpl_handlers(sc); t4_init_l2t_cpl_handlers(sc); Modified: head/sys/dev/cxgbe/tom/t4_tom.h ============================================================================== --- head/sys/dev/cxgbe/tom/t4_tom.h Tue Jan 15 05:33:40 2013 (r245447) +++ head/sys/dev/cxgbe/tom/t4_tom.h Tue Jan 15 07:07:29 2013 (r245448) @@ -109,6 +109,7 @@ struct toepcb { struct sge_ofld_rxq *ofld_rxq; struct sge_wrq *ctrlq; struct l2t_entry *l2te; /* L2 table entry used by this connection */ + struct clip_entry *ce; /* CLIP table entry used by this tid */ int tid; /* Connection identifier */ unsigned int tx_credits;/* tx WR credits (in 16 byte units) remaining */ unsigned int sb_cc; /* last noted value of so_rcv->sb_cc */ @@ -175,6 +176,12 @@ struct listen_ctx { TAILQ_HEAD(ppod_head, ppod_region); +struct clip_entry { + TAILQ_ENTRY(clip_entry) link; + struct in6_addr lip; /* local IPv6 address */ + u_int refcount; +}; + struct tom_data { struct toedev tod; @@ -192,6 +199,9 @@ struct tom_data { int nppods_free; /* # of available ppods */ int nppods_free_head; /* # of available ppods at the begining */ struct ppod_head ppods; + + struct mtx clip_table_lock; + TAILQ_HEAD(, clip_entry) clip_table; }; static inline struct tom_data * @@ -226,6 +236,8 @@ uint64_t calc_opt0(struct socket *, stru int, int, int, int); uint32_t select_ntuple(struct port_info *, struct l2t_entry *, uint32_t); void set_tcpddp_ulp_mode(struct toepcb *); +struct clip_entry *hold_lip(struct tom_data *, struct in6_addr *); +void release_lip(struct tom_data *, struct clip_entry *); /* t4_connect.c */ void t4_init_connect_cpl_handlers(struct adapter *);