1222509Snp/*-
2222509Snp * Copyright (c) 2011 Chelsio Communications, Inc.
3222509Snp * All rights reserved.
4222509Snp *
5222509Snp * Redistribution and use in source and binary forms, with or without
6222509Snp * modification, are permitted provided that the following conditions
7222509Snp * are met:
8222509Snp * 1. Redistributions of source code must retain the above copyright
9222509Snp *    notice, this list of conditions and the following disclaimer.
10222509Snp * 2. Redistributions in binary form must reproduce the above copyright
11222509Snp *    notice, this list of conditions and the following disclaimer in the
12222509Snp *    documentation and/or other materials provided with the distribution.
13222509Snp *
14222509Snp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15222509Snp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16222509Snp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17222509Snp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18222509Snp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19222509Snp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20222509Snp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21222509Snp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22222509Snp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23222509Snp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24222509Snp * SUCH DAMAGE.
25222509Snp *
26222509Snp * $FreeBSD: stable/10/sys/dev/cxgbe/t4_l2t.h 309442 2016-12-02 21:29:52Z jhb $
27222509Snp *
28222509Snp */
29222509Snp
30222509Snp#ifndef __T4_L2T_H
31222509Snp#define __T4_L2T_H
32222509Snp
33237263Snp/* identifies sync vs async L2T_WRITE_REQs */
34237263Snp#define S_SYNC_WR    12
35237263Snp#define V_SYNC_WR(x) ((x) << S_SYNC_WR)
36237263Snp#define F_SYNC_WR    V_SYNC_WR(1)
37237263Snp
38222509Snpenum { L2T_SIZE = 4096 };     /* # of L2T entries */
39222509Snp
40237263Snpenum {
41237263Snp	L2T_STATE_VALID,	/* entry is up to date */
42237263Snp	L2T_STATE_STALE,	/* entry may be used but needs revalidation */
43237263Snp	L2T_STATE_RESOLVING,	/* entry needs address resolution */
44237263Snp	L2T_STATE_FAILED,	/* failed to resolve */
45237263Snp	L2T_STATE_SYNC_WRITE,	/* synchronous write of entry underway */
46237263Snp
47237263Snp	/* when state is one of the below the entry is not hashed */
48237263Snp	L2T_STATE_SWITCHING,	/* entry is being used by a switching filter */
49237263Snp	L2T_STATE_UNUSED	/* entry not in use */
50237263Snp};
51237263Snp
52222509Snp/*
53222509Snp * Each L2T entry plays multiple roles.  First of all, it keeps state for the
54222509Snp * corresponding entry of the HW L2 table and maintains a queue of offload
55222509Snp * packets awaiting address resolution.  Second, it is a node of a hash table
56222509Snp * chain, where the nodes of the chain are linked together through their next
57222509Snp * pointer.  Finally, each node is a bucket of a hash table, pointing to the
58222509Snp * first element in its chain through its first pointer.
59222509Snp */
60222509Snpstruct l2t_entry {
61222509Snp	uint16_t state;			/* entry state */
62222509Snp	uint16_t idx;			/* entry index */
63245434Snp	uint32_t addr[4];		/* next hop IP or IPv6 address */
64309442Sjhb	uint32_t iqid;			/* iqid for reply to write_l2e */
65309442Sjhb	struct sge_wrq *wrq;		/* queue to use for write_l2e */
66222509Snp	struct ifnet *ifp;		/* outgoing interface */
67222509Snp	uint16_t smt_idx;		/* SMT index */
68222509Snp	uint16_t vlan;			/* VLAN TCI (id: 0-11, prio: 13-15) */
69222509Snp	struct l2t_entry *first;	/* start of hash chain */
70222509Snp	struct l2t_entry *next;		/* next l2t_entry on chain */
71237263Snp	STAILQ_HEAD(, wrqe) wr_list;	/* list of WRs awaiting resolution */
72222509Snp	struct mtx lock;
73228561Snp	volatile int refcnt;		/* entry reference count */
74222509Snp	uint16_t hash;			/* hash bucket the entry is on */
75245434Snp	uint8_t ipv6;			/* entry is for an IPv6 address */
76222509Snp	uint8_t lport;			/* associated offload logical port */
77222509Snp	uint8_t dmac[ETHER_ADDR_LEN];	/* next hop's MAC address */
78222509Snp};
79222509Snp
80237263Snpstruct l2t_data {
81237263Snp	struct rwlock lock;
82245434Snp	u_int l2t_size;
83237263Snp	volatile int nfree;	/* number of free entries */
84237263Snp	struct l2t_entry *rover;/* starting point for next allocation */
85245434Snp	struct l2t_entry l2tab[];
86237263Snp};
87237263Snp
88237263Snp
89228561Snpint t4_init_l2t(struct adapter *, int);
90222509Snpint t4_free_l2t(struct l2t_data *);
91237263Snpstruct l2t_entry *t4_alloc_l2e(struct l2t_data *);
92222509Snpstruct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *);
93222509Snpint t4_l2t_set_switching(struct adapter *, struct l2t_entry *, uint16_t,
94222509Snp    uint8_t, uint8_t *);
95309442Sjhbint t4_write_l2e(struct l2t_entry *, int);
96237263Snpint do_l2t_write_rpl(struct sge_iq *, const struct rss_header *, struct mbuf *);
97237263Snp
98237263Snpstatic inline void
99237263Snpt4_l2t_release(struct l2t_entry *e)
100237263Snp{
101241733Sed	struct l2t_data *d = __containerof(e, struct l2t_data, l2tab[e->idx]);
102237263Snp
103237263Snp	if (atomic_fetchadd_int(&e->refcnt, -1) == 1)
104237263Snp		atomic_add_int(&d->nfree, 1);
105237263Snp}
106237263Snp
107237263Snp
108231115Snp#ifdef SBUF_DRAIN
109228561Snpint sysctl_l2t(SYSCTL_HANDLER_ARGS);
110231115Snp#endif
111222509Snp
112222509Snp#endif  /* __T4_L2T_H */
113