Import updated support code for the TOM (tcp offload module).

This commit is contained in:
Kip Macy 2007-12-15 21:54:59 +00:00
parent a0d231fbb8
commit 3e96c7e790
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=174626
13 changed files with 892 additions and 847 deletions

View file

@ -55,12 +55,14 @@ POSSIBILITY OF SUCH DAMAGE.
#ifdef CONFIG_DEFINED
#include <cxgb_osdep.h>
#include <ulp/toecore/toedev.h>
#include <t3cdev.h>
#include <sys/mbufq.h>
#include <ulp/toecore/cxgb_toedev.h>
#else
#include <dev/cxgb/cxgb_osdep.h>
#include <dev/cxgb/t3cdev.h>
#include <dev/cxgb/sys/mbufq.h>
#include <dev/cxgb/ulp/toecore/toedev.h>
#include <dev/cxgb/ulp/toecore/cxgb_toedev.h>
#endif
#define USE_SX
@ -371,7 +373,7 @@ struct adapter {
struct port_info port[MAX_NPORTS];
device_t portdev[MAX_NPORTS];
struct toedev tdev;
struct t3cdev tdev;
char fw_version[64];
uint32_t open_device_map;
uint32_t registered_device_map;
@ -497,7 +499,7 @@ int t3_os_pci_restore_state(struct adapter *adapter);
void t3_os_link_changed(adapter_t *adapter, int port_id, int link_status,
int speed, int duplex, int fc);
void t3_sge_err_intr_handler(adapter_t *adapter);
int t3_offload_tx(struct toedev *, struct mbuf *);
int t3_offload_tx(struct t3cdev *, struct mbuf *);
void t3_os_ext_intr_handler(adapter_t *adapter);
void t3_os_set_hw_addr(adapter_t *adapter, int port_idx, u8 hw_addr[]);
int t3_mgmt_tx(adapter_t *adap, struct mbuf *m);
@ -554,7 +556,7 @@ txq_to_qset(struct sge_txq *q, int qidx)
}
static __inline struct adapter *
tdev2adap(struct toedev *d)
tdev2adap(struct t3cdev *d)
{
return container_of(d, struct adapter, tdev);
}

View file

@ -3,6 +3,7 @@
*/
#ifdef CONFIG_DEFINED
#include <cxgb_osdep.h>
#include <common/cxgb_common.h>
@ -14,11 +15,9 @@
#include <common/cxgb_sge_defs.h>
#include <common/cxgb_firmware_exports.h>
#include <sys/mvec.h>
#include <ulp/toecore/toedev.h>
#include <sys/mbufq.h>
#include <common/jhash.h>
#include <ulp/toecore/cxgb_toedev.h>
#else
#include <dev/cxgb/cxgb_osdep.h>
#include <dev/cxgb/common/cxgb_common.h>
@ -31,7 +30,9 @@
#include <dev/cxgb/common/cxgb_firmware_exports.h>
#include <dev/cxgb/sys/mvec.h>
#include <dev/cxgb/ulp/toecore/toedev.h>
#include <dev/cxgb/sys/mbufq.h>
#include <dev/cxgb/common/jhash.h>
#include <dev/cxgb/ulp/toecore/cxgb_toedev.h>
#endif

View file

@ -59,7 +59,7 @@ __FBSDID("$FreeBSD$");
#define VLAN_NONE 0xfff
#define SDL(s) ((struct sockaddr_dl *)s)
#define RT_ENADDR(rt) ((u_char *)LLADDR(SDL((rt))))
#define RT_ENADDR(sa) ((u_char *)LLADDR(SDL((sa))))
#define rt_expire rt_rmx.rmx_expire
struct llinfo_arp {
@ -103,11 +103,8 @@ neigh_replace(struct l2t_entry *e, struct rtentry *rt)
RT_ADDREF(rt);
RT_UNLOCK(rt);
if (e->neigh) {
RT_LOCK(e->neigh);
RT_REMREF(e->neigh);
RT_UNLOCK(e->neigh);
}
if (e->neigh)
RTFREE(e->neigh);
e->neigh = rt;
}
@ -117,7 +114,7 @@ neigh_replace(struct l2t_entry *e, struct rtentry *rt)
* entry locked.
*/
static int
setup_l2e_send_pending(struct toedev *dev, struct mbuf *m,
setup_l2e_send_pending(struct t3cdev *dev, struct mbuf *m,
struct l2t_entry *e)
{
struct cpl_l2t_write_req *req;
@ -130,13 +127,14 @@ setup_l2e_send_pending(struct toedev *dev, struct mbuf *m,
* XXX MH_ALIGN
*/
req = mtod(m, struct cpl_l2t_write_req *);
m->m_pkthdr.len = m->m_len = sizeof(*req);
req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, e->idx));
req->params = htonl(V_L2T_W_IDX(e->idx) | V_L2T_W_IFF(e->smt_idx) |
V_L2T_W_VLAN(e->vlan & EVL_VLID_MASK) |
V_L2T_W_PRIO(vlan_prio(e)));
memcpy(e->dmac, RT_ENADDR(e->neigh), sizeof(e->dmac));
memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac));
m_set_priority(m, CPL_PRIORITY_CONTROL);
cxgb_ofld_send(dev, m);
@ -168,21 +166,24 @@ arpq_enqueue(struct l2t_entry *e, struct mbuf *m)
}
int
t3_l2t_send_slow(struct toedev *dev, struct mbuf *m,
struct l2t_entry *e)
t3_l2t_send_slow(struct t3cdev *dev, struct mbuf *m, struct l2t_entry *e)
{
struct rtentry *rt;
struct mbuf *m0;
if ((m0 = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
return (ENOMEM);
struct rtentry *rt = e->neigh;
struct sockaddr_in sin;
rt = e->neigh;
bzero(&sin, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_addr.s_addr = e->addr;
printf("send slow on rt=%p eaddr=0x%08x\n", rt, e->addr);
again:
switch (e->state) {
case L2T_STATE_STALE: /* entry is stale, kick off revalidation */
arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt));
arpresolve(rt->rt_ifp, rt, NULL, (struct sockaddr *)&sin, e->dmac);
mtx_lock(&e->lock);
if (e->state == L2T_STATE_STALE)
e->state = L2T_STATE_VALID;
@ -197,9 +198,8 @@ t3_l2t_send_slow(struct toedev *dev, struct mbuf *m,
}
arpq_enqueue(e, m);
mtx_unlock(&e->lock);
if ((m0 = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
return (ENOMEM);
printf("enqueueing arp request\n");
/*
* Only the first packet added to the arpq should kick off
* resolution. However, because the m_gethdr below can fail,
@ -208,7 +208,13 @@ t3_l2t_send_slow(struct toedev *dev, struct mbuf *m,
* A better way would be to use a work request to retry L2T
* entries when there's no memory.
*/
if (arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt)) == 0) {
printf("doing arpresolve on 0x%x \n", e->addr);
if (arpresolve(rt->rt_ifp, rt, NULL, (struct sockaddr *)&sin, e->dmac) == 0) {
printf("mac=%x:%x:%x:%x:%x:%x\n",
e->dmac[0], e->dmac[1], e->dmac[2], e->dmac[3], e->dmac[4], e->dmac[5]);
if ((m = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
return (ENOMEM);
mtx_lock(&e->lock);
if (e->arpq_head)
@ -216,16 +222,21 @@ t3_l2t_send_slow(struct toedev *dev, struct mbuf *m,
else
m_freem(m);
mtx_unlock(&e->lock);
}
} else
printf("arpresolve returned non-zero\n");
}
return 0;
}
void
t3_l2t_send_event(struct toedev *dev, struct l2t_entry *e)
t3_l2t_send_event(struct t3cdev *dev, struct l2t_entry *e)
{
struct rtentry *rt;
struct mbuf *m0;
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_addr.s_addr = e->addr;
if ((m0 = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
return;
@ -234,7 +245,7 @@ t3_l2t_send_event(struct toedev *dev, struct l2t_entry *e)
again:
switch (e->state) {
case L2T_STATE_STALE: /* entry is stale, kick off revalidation */
arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt));
arpresolve(rt->rt_ifp, rt, m0, (struct sockaddr *)&sin, e->dmac);
mtx_lock(&e->lock);
if (e->state == L2T_STATE_STALE) {
e->state = L2T_STATE_VALID;
@ -261,7 +272,7 @@ t3_l2t_send_event(struct toedev *dev, struct l2t_entry *e)
* A better way would be to use a work request to retry L2T
* entries when there's no memory.
*/
arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt));
arpresolve(rt->rt_ifp, rt, m0, (struct sockaddr *)&sin, e->dmac);
}
return;
@ -301,6 +312,7 @@ alloc_l2e(struct l2t_data *d)
}
e->state = L2T_STATE_UNUSED;
}
return e;
}
@ -318,19 +330,21 @@ alloc_l2e(struct l2t_data *d)
void
t3_l2e_free(struct l2t_data *d, struct l2t_entry *e)
{
struct rtentry *rt = NULL;
mtx_lock(&e->lock);
if (atomic_load_acq_int(&e->refcnt) == 0) { /* hasn't been recycled */
if (e->neigh) {
RT_LOCK(e->neigh);
RT_REMREF(e->neigh);
RT_UNLOCK(e->neigh);
e->neigh = NULL;
}
rt = e->neigh;
e->neigh = NULL;
}
mtx_unlock(&e->lock);
atomic_add_int(&d->nfree, 1);
if (rt)
RTFREE(rt);
}
/*
* Update an L2T entry that was previously used for the same next hop as neigh.
* Must be called with softirqs disabled.
@ -346,7 +360,7 @@ reuse_entry(struct l2t_entry *e, struct rtentry *neigh)
if (neigh != e->neigh)
neigh_replace(e, neigh);
if (memcmp(e->dmac, RT_ENADDR(neigh), sizeof(e->dmac)) ||
if (memcmp(e->dmac, RT_ENADDR(neigh->rt_gateway), sizeof(e->dmac)) ||
(neigh->rt_expire > time_uptime))
e->state = L2T_STATE_RESOLVING;
else if (la->la_hold == NULL)
@ -357,14 +371,15 @@ reuse_entry(struct l2t_entry *e, struct rtentry *neigh)
}
struct l2t_entry *
t3_l2t_get(struct toedev *dev, struct rtentry *neigh,
unsigned int smt_idx)
t3_l2t_get(struct t3cdev *dev, struct rtentry *neigh, struct ifnet *ifp,
struct sockaddr *sa)
{
struct l2t_entry *e;
struct l2t_data *d = L2DATA(dev);
u32 addr = *(u32 *) rt_key(neigh);
u32 addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
int ifidx = neigh->rt_ifp->if_index;
int hash = arp_hash(addr, ifidx, d);
unsigned int smt_idx = ((struct port_info *)ifp->if_softc)->port_id;
rw_wlock(&d->lock);
for (e = d->l2tab[hash].first; e; e = e->next)
@ -379,14 +394,21 @@ t3_l2t_get(struct toedev *dev, struct rtentry *neigh,
/* Need to allocate a new entry */
e = alloc_l2e(d);
if (e) {
printf("initializing new entry\n");
mtx_lock(&e->lock); /* avoid race with t3_l2t_free */
e->next = d->l2tab[hash].first;
d->l2tab[hash].first = e;
rw_wunlock(&d->lock);
e->state = L2T_STATE_RESOLVING;
e->addr = addr;
e->ifindex = ifidx;
e->smt_idx = smt_idx;
atomic_store_rel_int(&e->refcnt, 1);
e->neigh = NULL;
neigh_replace(e, neigh);
#ifdef notyet
/*
@ -398,7 +420,10 @@ t3_l2t_get(struct toedev *dev, struct rtentry *neigh,
#endif
e->vlan = VLAN_NONE;
mtx_unlock(&e->lock);
return (e);
}
done:
rw_wunlock(&d->lock);
return e;
@ -413,7 +438,7 @@ t3_l2t_get(struct toedev *dev, struct rtentry *neigh,
* handler.
*/
static void
handle_failed_resolution(struct toedev *dev, struct mbuf *arpq)
handle_failed_resolution(struct t3cdev *dev, struct mbuf *arpq)
{
while (arpq) {
@ -433,21 +458,20 @@ handle_failed_resolution(struct toedev *dev, struct mbuf *arpq)
}
#if defined(NETEVENT) || !defined(CONFIG_CHELSIO_T3_MODULE)
/*
* Called when the host's ARP layer makes a change to some entry that is
* loaded into the HW L2 table.
*/
void
t3_l2t_update(struct toedev *dev, struct rtentry *neigh)
t3_l2t_update(struct t3cdev *dev, struct rtentry *neigh, struct sockaddr *sa)
{
struct l2t_entry *e;
struct mbuf *arpq = NULL;
struct l2t_data *d = L2DATA(dev);
u32 addr = *(u32 *) rt_key(neigh);
u32 addr = *(u32 *) &((struct sockaddr_in *)sa)->sin_addr;
int ifidx = neigh->rt_ifp->if_index;
int hash = arp_hash(addr, ifidx, d);
struct llinfo_arp *la;
u_char edst[ETHER_ADDR_LEN];
printf("t3_l2t_update called with arp info\n");
rw_rlock(&d->lock);
for (e = d->l2tab[hash].first; e; e = e->next)
@ -456,10 +480,16 @@ t3_l2t_update(struct toedev *dev, struct rtentry *neigh)
goto found;
}
rw_runlock(&d->lock);
printf("addr=0x%08x not found\n", addr);
return;
found:
printf("found 0x%08x\n", addr);
arpresolve(neigh->rt_ifp, neigh, NULL, sa, edst);
rw_runlock(&d->lock);
memcpy(e->dmac, edst, ETHER_ADDR_LEN);
if (atomic_load_acq_int(&e->refcnt)) {
if (neigh != e->neigh)
neigh_replace(e, neigh);
@ -470,12 +500,11 @@ t3_l2t_update(struct toedev *dev, struct rtentry *neigh)
if (la->la_asked >= 5 /* arp_maxtries */) {
arpq = e->arpq_head;
e->arpq_head = e->arpq_tail = NULL;
} else if (la->la_hold == NULL)
} else
setup_l2e_send_pending(dev, NULL, e);
} else {
e->state = (la->la_hold == NULL) ?
L2T_STATE_VALID : L2T_STATE_STALE;
if (memcmp(e->dmac, RT_ENADDR(neigh), 6))
e->state = L2T_STATE_VALID;
if (memcmp(e->dmac, RT_ENADDR(neigh->rt_gateway), 6))
setup_l2e_send_pending(dev, NULL, e);
}
}
@ -484,71 +513,6 @@ t3_l2t_update(struct toedev *dev, struct rtentry *neigh)
if (arpq)
handle_failed_resolution(dev, arpq);
}
#else
/*
* Called from a kprobe, interrupts are off.
*/
void
t3_l2t_update(struct toedev *dev, struct rtentry *neigh)
{
struct l2t_entry *e;
struct l2t_data *d = L2DATA(dev);
u32 addr = *(u32 *) rt_key(neigh);
int ifidx = neigh->dev->ifindex;
int hash = arp_hash(addr, ifidx, d);
rw_rlock(&d->lock);
for (e = d->l2tab[hash].first; e; e = e->next)
if (e->addr == addr && e->ifindex == ifidx) {
mtx_lock(&e->lock);
if (atomic_load_acq_int(&e->refcnt)) {
if (neigh != e->neigh)
neigh_replace(e, neigh);
e->tdev = dev;
mod_timer(&e->update_timer, jiffies + 1);
}
mtx_unlock(&e->lock);
break;
}
rw_runlock(&d->lock);
}
static void
update_timer_cb(unsigned long data)
{
struct mbuf *arpq = NULL;
struct l2t_entry *e = (struct l2t_entry *)data;
struct rtentry *neigh = e->neigh;
struct toedev *dev = e->tdev;
barrier();
if (!atomic_load_acq_int(&e->refcnt))
return;
rw_rlock(&neigh->lock);
mtx_lock(&e->lock);
if (atomic_load_acq_int(&e->refcnt)) {
if (e->state == L2T_STATE_RESOLVING) {
if (neigh->nud_state & NUD_FAILED) {
arpq = e->arpq_head;
e->arpq_head = e->arpq_tail = NULL;
} else if (neigh_is_connected(neigh) && e->arpq_head)
setup_l2e_send_pending(dev, NULL, e);
} else {
e->state = neigh_is_connected(neigh) ?
L2T_STATE_VALID : L2T_STATE_STALE;
if (memcmp(e->dmac, RT_ENADDR(neigh), sizeof(e->dmac)))
setup_l2e_send_pending(dev, NULL, e);
}
}
mtx_unlock(&e->lock);
rw_runlock(&neigh->lock);
if (arpq)
handle_failed_resolution(dev, arpq);
}
#endif
struct l2t_data *
t3_init_l2t(unsigned int l2t_capacity)
@ -570,12 +534,6 @@ t3_init_l2t(unsigned int l2t_capacity)
d->l2tab[i].state = L2T_STATE_UNUSED;
mtx_init(&d->l2tab[i].lock, "L2TAB", NULL, MTX_DEF);
atomic_store_rel_int(&d->l2tab[i].refcnt, 0);
#ifndef NETEVENT
#ifdef CONFIG_CHELSIO_T3_MODULE
setup_timer(&d->l2tab[i].update_timer, update_timer_cb,
(unsigned long)&d->l2tab[i]);
#endif
#endif
}
return d;
}
@ -583,86 +541,6 @@ t3_init_l2t(unsigned int l2t_capacity)
void
t3_free_l2t(struct l2t_data *d)
{
#ifndef NETEVENT
#ifdef CONFIG_CHELSIO_T3_MODULE
int i;
/* Stop all L2T timers */
for (i = 0; i < d->nentries; ++i)
del_timer_sync(&d->l2tab[i].update_timer);
#endif
#endif
cxgb_free_mem(d);
}
#ifdef CONFIG_PROC_FS
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
static inline void *
l2t_get_idx(struct seq_file *seq, loff_t pos)
{
struct l2t_data *d = seq->private;
return pos >= d->nentries ? NULL : &d->l2tab[pos];
}
static void *
l2t_seq_start(struct seq_file *seq, loff_t *pos)
{
return *pos ? l2t_get_idx(seq, *pos) : SEQ_START_TOKEN;
}
static void *
l2t_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
v = l2t_get_idx(seq, *pos + 1);
if (v)
++*pos;
return v;
}
static void
l2t_seq_stop(struct seq_file *seq, void *v)
{
}
static char
l2e_state(const struct l2t_entry *e)
{
switch (e->state) {
case L2T_STATE_VALID: return 'V'; /* valid, fast-path entry */
case L2T_STATE_STALE: return 'S'; /* needs revalidation, but usable */
case L2T_STATE_RESOLVING:
return e->arpq_head ? 'A' : 'R';
default:
return 'U';
}
}
static int
l2t_seq_show(struct seq_file *seq, void *v)
{
if (v == SEQ_START_TOKEN)
seq_puts(seq, "Index IP address Ethernet address VLAN "
"Prio State Users SMTIDX Port\n");
else {
char ip[20];
struct l2t_entry *e = v;
mtx_lock(&e->lock);
sprintf(ip, "%u.%u.%u.%u", NIPQUAD(e->addr));
seq_printf(seq, "%-5u %-15s %02x:%02x:%02x:%02x:%02x:%02x %4d"
" %3u %c %7u %4u %s\n",
e->idx, ip, e->dmac[0], e->dmac[1], e->dmac[2],
e->dmac[3], e->dmac[4], e->dmac[5],
e->vlan & EVL_VLID_MASK, vlan_prio(e),
l2e_state(e), atomic_load_acq_int(&e->refcnt), e->smt_idx,
e->neigh ? e->neigh->dev->name : "");
mtx_unlock(&e->lock);
}
return 0;
}
#endif

View file

@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef _CHELSIO_L2T_H
#define _CHELSIO_L2T_H
#include <dev/cxgb/ulp/toecore/toedev.h>
#include <dev/cxgb/ulp/toecore/cxgb_toedev.h>
#include <sys/lock.h>
#if __FreeBSD_version > 700000
@ -76,12 +76,6 @@ struct l2t_entry {
struct mtx lock;
volatile uint32_t refcnt; /* entry reference count */
uint8_t dmac[6]; /* neighbour's MAC address */
#ifndef NETEVENT
#ifdef CONFIG_CHELSIO_T3_MODULE
struct timer_list update_timer;
struct toedev *tdev;
#endif
#endif
};
struct l2t_data {
@ -92,7 +86,10 @@ struct l2t_data {
struct l2t_entry l2tab[0];
};
typedef void (*arp_failure_handler_func)(struct toedev *dev,
typedef void (*arp_failure_handler_func)(struct t3cdev *dev,
struct mbuf *m);
typedef void (*opaque_arp_failure_handler_func)(void *dev,
struct mbuf *m);
/*
@ -111,10 +108,8 @@ struct l2t_mbuf_cb {
static __inline void set_arp_failure_handler(struct mbuf *m,
arp_failure_handler_func hnd)
{
#if 0
L2T_SKB_CB(skb)->arp_failure_handler = hnd;
#endif
panic("implement me");
m->m_pkthdr.header = (opaque_arp_failure_handler_func)hnd;
}
/*
@ -123,12 +118,12 @@ static __inline void set_arp_failure_handler(struct mbuf *m,
#define L2DATA(dev) ((dev)->l2opt)
void t3_l2e_free(struct l2t_data *d, struct l2t_entry *e);
void t3_l2t_update(struct toedev *dev, struct rtentry *ifp);
struct l2t_entry *t3_l2t_get(struct toedev *dev, struct rtentry *neigh,
unsigned int smt_idx);
int t3_l2t_send_slow(struct toedev *dev, struct mbuf *m,
void t3_l2t_update(struct t3cdev *dev, struct rtentry *rt, struct sockaddr *sa);
struct l2t_entry *t3_l2t_get(struct t3cdev *dev, struct rtentry *neigh,
struct ifnet *ifp, struct sockaddr *sa);
int t3_l2t_send_slow(struct t3cdev *dev, struct mbuf *m,
struct l2t_entry *e);
void t3_l2t_send_event(struct toedev *dev, struct l2t_entry *e);
void t3_l2t_send_event(struct t3cdev *dev, struct l2t_entry *e);
struct l2t_data *t3_init_l2t(unsigned int l2t_capacity);
void t3_free_l2t(struct l2t_data *d);
@ -140,14 +135,17 @@ void t3_l2t_proc_free(struct proc_dir_entry *dir);
#define l2t_proc_free(dir)
#endif
int cxgb_ofld_send(struct toedev *dev, struct mbuf *m);
int cxgb_ofld_send(struct t3cdev *dev, struct mbuf *m);
static inline int l2t_send(struct toedev *dev, struct mbuf *m,
static inline int l2t_send(struct t3cdev *dev, struct mbuf *m,
struct l2t_entry *e)
{
if (__predict_true(e->state == L2T_STATE_VALID))
return cxgb_ofld_send(dev, m);
return t3_l2t_send_slow(dev, m, e);
if (__predict_true(e->state == L2T_STATE_VALID)) {
return cxgb_ofld_send(dev, (struct mbuf *)m);
}
printf("send slow\n");
return t3_l2t_send_slow(dev, (struct mbuf *)m, e);
}
static inline void l2t_release(struct l2t_data *d, struct l2t_entry *e)

View file

@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/ioccom.h>
#include <sys/mbuf.h>
#include <sys/linker.h>
#include <sys/syslog.h>
#include <sys/firmware.h>
#include <sys/socket.h>
#include <sys/sockio.h>
@ -116,7 +117,7 @@ static int offload_open(struct port_info *pi);
static void touch_bars(device_t dev);
#ifdef notyet
static int offload_close(struct toedev *tdev);
static int offload_close(struct t3cdev *tdev);
#endif
@ -1235,7 +1236,7 @@ setup_rss(adapter_t *adap)
* after dealing with any active network taps.
*/
static inline int
offload_tx(struct toedev *tdev, struct mbuf *m)
offload_tx(struct t3cdev *tdev, struct mbuf *m)
{
int ret;
@ -1556,7 +1557,7 @@ static int
offload_open(struct port_info *pi)
{
struct adapter *adapter = pi->adapter;
struct toedev *tdev = TOEDEV(pi->ifp);
struct t3cdev *tdev = TOEDEV(pi->ifp);
int adap_up = adapter->open_device_map & PORT_MASK;
int err = 0;
@ -1599,7 +1600,7 @@ offload_open(struct port_info *pi)
}
#ifdef notyet
static int
offload_close(struct toedev *tdev)
offload_close(struct t3cev *tdev)
{
struct adapter *adapter = tdev2adap(tdev);

File diff suppressed because it is too large Load diff

View file

@ -38,13 +38,17 @@ POSSIBILITY OF SUCH DAMAGE.
#include <cxgb_config.h>
#include <cxgb_l2t.h>
#include <common/cxgb_tcb.h>
#include <t3cdev.h>
#else
#include <dev/cxgb/common/cxgb_version.h>
#include <dev/cxgb/cxgb_config.h>
#include <dev/cxgb/cxgb_l2t.h>
#include <dev/cxgb/common/cxgb_tcb.h>
#include <dev/cxgb/t3cdev.h>
#endif
MALLOC_DECLARE(M_CXGB);
struct adapter;
struct cxgb_client;
@ -55,30 +59,30 @@ void cxgb_adapter_ofld(struct adapter *adapter);
void cxgb_adapter_unofld(struct adapter *adapter);
int cxgb_offload_activate(struct adapter *adapter);
void cxgb_offload_deactivate(struct adapter *adapter);
int cxgb_ofld_recv(struct toedev *dev, struct mbuf **m, int n);
int cxgb_ofld_recv(struct t3cdev *dev, struct mbuf **m, int n);
void cxgb_set_dummy_ops(struct toedev *dev);
void cxgb_set_dummy_ops(struct t3cdev *dev);
/*
* Client registration. Users of T3 driver must register themselves.
* The T3 driver will call the add function of every client for each T3
* adapter activated, passing up the toedev ptr. Each client fills out an
* adapter activated, passing up the t3cdev ptr. Each client fills out an
* array of callback functions to process CPL messages.
*/
void cxgb_register_client(struct cxgb_client *client);
void cxgb_unregister_client(struct cxgb_client *client);
void cxgb_add_clients(struct toedev *tdev);
void cxgb_remove_clients(struct toedev *tdev);
void cxgb_add_clients(struct t3cdev *tdev);
void cxgb_remove_clients(struct t3cdev *tdev);
typedef int (*cxgb_cpl_handler_func)(struct toedev *dev,
typedef int (*cxgb_cpl_handler_func)(struct t3cdev *dev,
struct mbuf *m, void *ctx);
struct cxgb_client {
char *name;
void (*add) (struct toedev *);
void (*remove) (struct toedev *);
void (*add) (struct t3cdev *);
void (*remove) (struct t3cdev *);
cxgb_cpl_handler_func *handlers;
int (*redirect)(void *ctx, struct rtentry *old,
struct rtentry *new,
@ -89,17 +93,18 @@ struct cxgb_client {
/*
* TID allocation services.
*/
int cxgb_alloc_atid(struct toedev *dev, struct cxgb_client *client,
int cxgb_alloc_atid(struct t3cdev *dev, struct cxgb_client *client,
void *ctx);
int cxgb_alloc_stid(struct toedev *dev, struct cxgb_client *client,
int cxgb_alloc_stid(struct t3cdev *dev, struct cxgb_client *client,
void *ctx);
void *cxgb_free_atid(struct toedev *dev, int atid);
void cxgb_free_stid(struct toedev *dev, int stid);
void cxgb_insert_tid(struct toedev *dev, struct cxgb_client *client,
void *cxgb_free_atid(struct t3cdev *dev, int atid);
void cxgb_free_stid(struct t3cdev *dev, int stid);
void *cxgb_get_lctx(struct t3cdev *tdev, int stid);
void cxgb_insert_tid(struct t3cdev *dev, struct cxgb_client *client,
void *ctx,
unsigned int tid);
void cxgb_queue_tid_release(struct toedev *dev, unsigned int tid);
void cxgb_remove_tid(struct toedev *dev, void *ctx, unsigned int tid);
void cxgb_queue_tid_release(struct t3cdev *dev, unsigned int tid);
void cxgb_remove_tid(struct t3cdev *dev, void *ctx, unsigned int tid);
struct toe_tid_entry {
struct cxgb_client *client;
@ -123,7 +128,7 @@ enum {
CPL_RET_UNKNOWN_TID = 4 // unexpected unknown TID
};
typedef int (*cpl_handler_func)(struct toedev *dev, struct mbuf *m);
typedef int (*cpl_handler_func)(struct t3cdev *dev, struct mbuf *m);
/*
* Returns a pointer to the first byte of the CPL header in an sk_buff that
@ -181,11 +186,8 @@ struct tid_info {
unsigned int stids_in_use;
};
struct toe_data {
#ifdef notyet
struct list_head list_node;
#endif
struct toedev *dev;
struct t3c_data {
struct t3cdev *dev;
unsigned int tx_max_chunk; /* max payload for TX_DATA */
unsigned int max_wrs; /* max in-flight WRs per connection */
unsigned int nmtus;
@ -198,9 +200,9 @@ struct toe_data {
};
/*
* toedev -> toe_data accessor
* t3cdev -> toe_data accessor
*/
#define TOE_DATA(dev) (*(struct toe_data **)&(dev)->l4opt)
#define T3C_DATA(dev) (*(struct t3c_data **)&(dev)->l4opt)
/*
* Map an ATID or STID to their entries in the corresponding TID tables.
@ -251,11 +253,11 @@ static inline struct toe_tid_entry *lookup_atid(const struct tid_info *t,
void *cxgb_alloc_mem(unsigned long size);
void cxgb_free_mem(void *addr);
void cxgb_neigh_update(struct rtentry *rt);
void cxgb_redirect(struct rtentry *old, struct rtentry *new);
int process_rx(struct toedev *dev, struct mbuf **m, int n);
int attach_toedev(struct toedev *dev);
void detach_toedev(struct toedev *dev);
void cxgb_neigh_update(struct rtentry *rt, struct sockaddr *sa);
void cxgb_redirect(struct rtentry *old, struct rtentry *new, struct sockaddr *sa);
int process_rx(struct t3cdev *dev, struct mbuf **m, int n);
int attach_t3cdev(struct t3cdev *dev);
void detach_t3cdev(struct t3cdev *dev);
#define UNIMPLEMENTED() panic("IMPLEMENT: %s:%s:%d", __FUNCTION__, __FILE__, __LINE__)
#endif

View file

@ -60,7 +60,7 @@ struct t3_mbuf_hdr {
#define PANIC_IF(exp) do { \
if (exp) \
panic("BUG: %s", exp); \
panic("BUG: %s", #exp); \
} while (0)
@ -97,9 +97,6 @@ struct t3_mbuf_hdr {
#define CXGB_TX_CLEANUP_THRESHOLD 32
#define LOG_WARNING 1
#define LOG_ERR 2
#ifdef DEBUG_PRINT
#define DPRINTF printf
#else

View file

@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
#include <sys/taskqueue.h>
#include <sys/proc.h>
@ -1988,7 +1989,7 @@ is_ctrl_pkt(const struct mbuf *m)
* should be sent as regular or control, bits 1-3 select the queue set.
*/
int
t3_offload_tx(struct toedev *tdev, struct mbuf *m)
t3_offload_tx(struct t3cdev *tdev, struct mbuf *m)
{
adapter_t *adap = tdev2adap(tdev);
struct sge_qset *qs = &adap->sge.qs[queue_set(m)];
@ -2009,7 +2010,7 @@ t3_offload_tx(struct toedev *tdev, struct mbuf *m)
* Delivers a (partial) bundle of Rx offload packets to an offload device.
*/
static __inline void
deliver_partial_bundle(struct toedev *tdev,
deliver_partial_bundle(struct t3cdev *tdev,
struct sge_rspq *q,
struct mbuf *mbufs[], int n)
{
@ -2020,7 +2021,7 @@ deliver_partial_bundle(struct toedev *tdev,
}
static __inline int
rx_offload(struct toedev *tdev, struct sge_rspq *rq,
rx_offload(struct t3cdev *tdev, struct sge_rspq *rq,
struct mbuf *m, struct mbuf *rx_gather[],
unsigned int gather_idx)
{

61
sys/dev/cxgb/t3cdev.h Normal file
View file

@ -0,0 +1,61 @@
/*-
* Copyright (c) 2007, Chelsio Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Neither the name of the Chelsio Corporation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _T3CDEV_H_
#define _T3CDEV_H_
#define T3CNAMSIZ 16
/* Get the t3cdev associated with an ifnet */
#define T3CDEV(ifp) (&(((struct port_info *)(ifp)->if_softc))->adapter->tdev)
struct cxgb3_client;
enum t3ctype {
T3A = 0,
T3B
};
struct t3cdev {
char name[T3CNAMSIZ]; /* T3C device name */
enum t3ctype type;
TAILQ_ENTRY(t3cdev) entry; /* for list linking */
struct ifnet *lldev; /* LL dev associated with T3C messages */
struct adapter *adapter;
int (*send)(struct t3cdev *dev, struct mbuf *m);
int (*recv)(struct t3cdev *dev, struct mbuf **m, int n);
int (*ctl)(struct t3cdev *dev, unsigned int req, void *data);
void (*arp_update)(struct t3cdev *dev, struct rtentry *neigh, struct sockaddr *sa);
void *priv; /* driver private data */
void *l2opt; /* optional layer 2 data */
void *l3opt; /* optional layer 3 data */
void *l4opt; /* optional layer 4 data */
void *ulp; /* ulp stuff */
};
#endif /* _T3CDEV_H_ */

View file

@ -0,0 +1,46 @@
/**************************************************************************
Copyright (c) 2007, Chelsio Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Neither the name of the Chelsio Corporation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
$FreeBSD$
***************************************************************************/
#ifndef _CXGB_TOEDEV_H_
#define _CXGB_TOEDEV_H_
#include <netinet/toedev.h>
/* offload type ids */
enum {
TOE_ID_CHELSIO_T1 = 1,
TOE_ID_CHELSIO_T1C,
TOE_ID_CHELSIO_T2,
TOE_ID_CHELSIO_T3,
TOE_ID_CHELSIO_T3B,
};
#endif

View file

@ -0,0 +1,424 @@
/**************************************************************************
Copyright (c) 2007, Chelsio Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Neither the name of the Chelsio Corporation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/module.h>
#include <sys/queue.h>
#include <sys/mbuf.h>
#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <net/bpf.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/route.h>
/*
* XXX
*/
#ifdef CONFIG_DEFINED
#include <cxgb_include.h>
#else
#include <dev/cxgb/cxgb_include.h>
#endif
static struct mtx offload_db_lock;
static TAILQ_HEAD(, toedev) offload_dev_list;
static TAILQ_HEAD(, tom_info) offload_module_list;
/*
* Returns the entry in the given table with the given offload id, or NULL
* if the id is not found.
*/
static const struct offload_id *
id_find(unsigned int id, const struct offload_id *table)
{
for ( ; table->id; ++table)
if (table->id == id)
return table;
return NULL;
}
/*
* Returns true if an offload device is presently attached to an offload module.
*/
static inline int
is_attached(const struct toedev *dev)
{
return dev->tod_offload_mod != NULL;
}
/*
* Try to attach a new offload device to an existing TCP offload module that
* can handle the device's offload id. Returns 0 if it succeeds.
*
* Must be called with the offload_db_lock held.
*/
static int
offload_attach(struct toedev *dev)
{
struct tom_info *t;
TAILQ_FOREACH(t, &offload_module_list, entry) {
const struct offload_id *entry;
entry = id_find(dev->tod_ttid, t->ti_id_table);
if (entry && t->ti_attach(dev, entry) == 0) {
dev->tod_offload_mod = t;
return 0;
}
}
return (ENOPROTOOPT);
}
/**
* register_tom - register a TCP Offload Module (TOM)
* @t: the offload module to register
*
* Register a TCP Offload Module (TOM).
*/
int
register_tom(struct tom_info *t)
{
mtx_lock(&offload_db_lock);
TAILQ_INSERT_HEAD(&offload_module_list, t, entry);
mtx_unlock(&offload_db_lock);
return 0;
}
/**
* unregister_tom - unregister a TCP Offload Module (TOM)
* @t: the offload module to register
*
* Unregister a TCP Offload Module (TOM). Note that this does not affect any
* TOE devices to which the TOM is already attached.
*/
int
unregister_tom(struct tom_info *t)
{
mtx_lock(&offload_db_lock);
TAILQ_REMOVE(&offload_module_list, t, entry);
mtx_unlock(&offload_db_lock);
return 0;
}
/*
* Find an offload device by name. Must be called with offload_db_lock held.
*/
static struct toedev *
__find_offload_dev_by_name(const char *name)
{
struct toedev *dev;
TAILQ_FOREACH(dev, &offload_dev_list, entry) {
if (!strncmp(dev->tod_name, name, TOENAMSIZ))
return dev;
}
return NULL;
}
/*
* Returns true if an offload device is already registered.
* Must be called with the offload_db_lock held.
*/
static int
is_registered(const struct toedev *dev)
{
struct toedev *d;
TAILQ_FOREACH(d, &offload_dev_list, entry) {
if (d == dev)
return 1;
}
return 0;
}
/*
* Finalize the name of an offload device by assigning values to any format
* strings in its name.
*/
static int
assign_name(struct toedev *dev, const char *name, int limit)
{
int i;
for (i = 0; i < limit; ++i) {
char s[TOENAMSIZ];
if (snprintf(s, sizeof(s), name, i) >= sizeof(s))
return -1; /* name too long */
if (!__find_offload_dev_by_name(s)) {
strcpy(dev->tod_name, s);
return 0;
}
}
return -1;
}
/**
* register_toedev - register a TOE device
* @dev: the device
* @name: a name template for the device
*
* Register a TOE device and try to attach an appropriate TCP offload module
* to it. @name is a template that may contain at most one %d format
* specifier.
*/
int
register_toedev(struct toedev *dev, const char *name)
{
int ret;
const char *p;
/*
* Validate the name template. Only one %d allowed and name must be
* a valid filename so it can appear in sysfs.
*/
if (!name || !*name || !strcmp(name, ".") || !strcmp(name, "..") ||
strchr(name, '/'))
return EINVAL;
p = strchr(name, '%');
if (p && (p[1] != 'd' || strchr(p + 2, '%')))
return EINVAL;
mtx_lock(&offload_db_lock);
if (is_registered(dev)) { /* device already registered */
ret = EEXIST;
goto out;
}
if ((ret = assign_name(dev, name, 32)) != 0)
goto out;
dev->tod_offload_mod = NULL;
TAILQ_INSERT_TAIL(&offload_dev_list, dev, entry);
out:
mtx_unlock(&offload_db_lock);
return ret;
}
/**
* unregister_toedev - unregister a TOE device
* @dev: the device
*
* Unregister a TOE device. The device must not be attached to an offload
* module.
*/
int
unregister_toedev(struct toedev *dev)
{
int ret = 0;
mtx_lock(&offload_db_lock);
if (!is_registered(dev)) {
ret = ENODEV;
goto out;
}
if (is_attached(dev)) {
ret = EBUSY;
goto out;
}
TAILQ_REMOVE(&offload_dev_list, dev, entry);
out:
mtx_unlock(&offload_db_lock);
return ret;
}
/**
* activate_offload - activate an offload device
* @dev: the device
*
* Activate an offload device by locating an appropriate registered offload
* module. If no module is found the operation fails and may be retried at
* a later time.
*/
int
activate_offload(struct toedev *dev)
{
int ret = 0;
mtx_lock(&offload_db_lock);
if (!is_registered(dev))
ret = ENODEV;
else if (!is_attached(dev))
ret = offload_attach(dev);
mtx_unlock(&offload_db_lock);
return ret;
}
/**
* toe_send - send a packet to a TOE device
* @dev: the device
* @m: the packet
*
* Sends an mbuf to a TOE driver after dealing with any active network taps.
*/
int
toe_send(struct toedev *dev, struct mbuf *m)
{
int r;
critical_enter(); /* XXX neccessary? */
r = dev->tod_send(dev, m);
critical_exit();
if (r)
BPF_MTAP(dev->tod_lldev, m);
return r;
}
/**
* toe_receive_mbuf - process n received TOE packets
* @dev: the toe device
* @m: an array of offload packets
* @n: the number of offload packets
*
* Process an array of ingress offload packets. Each packet is forwarded
* to any active network taps and then passed to the toe device's receive
* method. We optimize passing packets to the receive method by passing
* it the whole array at once except when there are active taps.
*/
int
toe_receive_mbuf(struct toedev *dev, struct mbuf **m, int n)
{
if (__predict_true(!bpf_peers_present(dev->tod_lldev->if_bpf)))
return dev->tod_recv(dev, m, n);
for ( ; n; n--, m++) {
m[0]->m_pkthdr.rcvif = dev->tod_lldev;
BPF_MTAP(dev->tod_lldev, m[0]);
dev->tod_recv(dev, m, 1);
}
return 0;
}
static inline int
ifnet_is_offload(const struct ifnet *ifp)
{
return (ifp->if_flags & IFCAP_TOE);
}
void
toe_arp_update(struct rtentry *rt)
{
struct ifnet *ifp = rt->rt_ifp;
if (ifp && ifnet_is_offload(ifp)) {
struct toedev *tdev = TOEDEV(ifp);
if (tdev && tdev->tod_arp_update)
tdev->tod_arp_update(tdev, rt);
}
}
/**
* offload_get_phys_egress - find the physical egress device
* @root_dev: the root device anchoring the search
* @so: the socket used to determine egress port in bonding mode
* @context: in bonding mode, indicates a connection set up or failover
*
* Given a root network device it returns the physical egress device that is a
* descendant of the root device. The root device may be either a physical
* device, in which case it is the device returned, or a virtual device, such
* as a VLAN or bonding device. In case of a bonding device the search
* considers the decisions of the bonding device given its mode to locate the
* correct egress device.
*/
struct ifnet *
offload_get_phys_egress(struct ifnet *root_dev, struct socket *so, int context)
{
#if 0
while (root_dev && ifnet_is_offload(root_dev)) {
if (root_dev->tod_priv_flags & IFF_802_1Q_VLAN)
root_dev = VLAN_DEV_INFO(root_dev)->real_dev;
else if (root_dev->tod_flags & IFF_MASTER)
root_dev = toe_bond_get_slave(root_dev, sk, context);
else
break;
}
#endif
return root_dev;
}
static int
toecore_load(module_t mod, int cmd, void *arg)
{
int err = 0;
switch (cmd) {
case MOD_LOAD:
mtx_init(&offload_db_lock, "toedev lock", NULL, MTX_DEF);
TAILQ_INIT(&offload_dev_list);
TAILQ_INIT(&offload_module_list);
break;
case MOD_QUIESCE:
break;
case MOD_UNLOAD:
mtx_lock(&offload_db_lock);
if (!TAILQ_EMPTY(&offload_dev_list) ||
!TAILQ_EMPTY(&offload_module_list)) {
err = EBUSY;
mtx_unlock(&offload_db_lock);
break;
}
mtx_unlock(&offload_db_lock);
mtx_destroy(&offload_db_lock);
break;
case MOD_SHUTDOWN:
break;
default:
err = EOPNOTSUPP;
break;
}
return (err);
}
static moduledata_t mod_data= {
"toecore",
toecore_load,
0
};
MODULE_VERSION(toecore, 1);
DECLARE_MODULE(toecore, mod_data, SI_SUB_EXEC, SI_ORDER_ANY);

View file

@ -1,172 +0,0 @@
/**************************************************************************
Copyright (c) 2007, Chelsio Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Neither the name of the Chelsio Corporation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
$FreeBSD$
***************************************************************************/
#ifndef _OFFLOAD_DEV_H_
#define _OFFLOAD_DEV_H_
/* Parameter values for offload_get_phys_egress() */
enum {
TOE_OPEN,
TOE_FAILOVER,
};
/* Parameter values for toe_failover() */
enum {
TOE_ACTIVE_SLAVE,
TOE_LINK_DOWN,
TOE_LINK_UP,
TOE_RELEASE,
TOE_RELEASE_ALL,
};
#define TOENAMSIZ 16
/* belongs in linux/netdevice.h */
#define NETIF_F_TCPIP_OFFLOAD (1 << 15)
/* Get the toedev associated with a ifnet */
#define TOEDEV(netdev) (*(struct toedev **)&(netdev)->if_softc)
/* offload type ids */
enum {
TOE_ID_CHELSIO_T1 = 1,
TOE_ID_CHELSIO_T1C,
TOE_ID_CHELSIO_T2,
TOE_ID_CHELSIO_T3,
TOE_ID_CHELSIO_T3B,
};
struct offload_id {
unsigned int id;
unsigned long data;
};
struct ifnet;
struct rt_entry;
struct tom_info;
struct sysctl_oid;
struct socket;
struct mbuf;
enum toetype {
T3A = 0,
T3B
};
struct toedev {
char name[TOENAMSIZ]; /* TOE device name */
enum toetype type;
struct adapter *adapter;
unsigned int ttid; /* TOE type id */
unsigned long flags; /* device flags */
unsigned int mtu; /* max size of TX offloaded data */
unsigned int nconn; /* max # of offloaded connections */
struct ifnet *lldev; /* LL device associated with TOE messages */
const struct tom_info *offload_mod; /* attached TCP offload module */
struct sysctl_oid *sysctl_root; /* root of proc dir for this TOE */
TAILQ_ENTRY(toedev) ofld_entry; /* for list linking */
int (*open)(struct toedev *dev);
int (*close)(struct toedev *dev);
int (*can_offload)(struct toedev *dev, struct socket *so);
int (*connect)(struct toedev *dev, struct socket *so,
struct ifnet *egress_ifp);
int (*send)(struct toedev *dev, struct mbuf *m);
int (*recv)(struct toedev *dev, struct mbuf **m, int n);
int (*ctl)(struct toedev *dev, unsigned int req, void *data);
void (*neigh_update)(struct toedev *dev, struct rtentry *neigh);
void (*failover)(struct toedev *dev, struct ifnet *bond_ifp,
struct ifnet *ndev, int event);
void *priv; /* driver private data */
void *l2opt; /* optional layer 2 data */
void *l3opt; /* optional layer 3 data */
void *l4opt; /* optional layer 4 data */
void *ulp; /* ulp stuff */
};
struct tom_info {
int (*attach)(struct toedev *dev, const struct offload_id *entry);
int (*detach)(struct toedev *dev);
const char *name;
const struct offload_id *id_table;
TAILQ_ENTRY(tom_info) entry;
};
static inline void init_offload_dev(struct toedev *dev)
{
}
extern int register_tom(struct tom_info *t);
extern int unregister_tom(struct tom_info *t);
extern int register_toedev(struct toedev *dev, const char *name);
extern int unregister_toedev(struct toedev *dev);
extern int activate_offload(struct toedev *dev);
extern int toe_send(struct toedev *dev, struct mbuf *m);
extern struct ifnet *offload_get_phys_egress(struct ifnet *dev,
struct socket *so,
int context);
#if defined(CONFIG_TCP_OFFLOAD_MODULE)
static inline int toe_receive_mbuf(struct toedev *dev, struct mbuf **m,
int n)
{
return dev->recv(dev, m, n);
}
extern int prepare_tcp_for_offload(void);
extern void restore_tcp_to_nonoffload(void);
#elif defined(CONFIG_TCP_OFFLOAD)
extern int toe_receive_mbuf(struct toedev *dev, struct mbuf **m, int n);
#endif
#if defined(CONFIG_TCP_OFFLOAD) || \
(defined(CONFIG_TCP_OFFLOAD_MODULE) && defined(MODULE))
extern void toe_neigh_update(struct rtentry *neigh);
extern void toe_failover(struct ifnet *bond_ifp,
struct ifnet *fail_ifp, int event);
extern int toe_enslave(struct ifnet *bond_ifp,
struct ifnet *slave_ifp);
#else
static inline void toe_neigh_update(struct ifnet *neigh) {}
static inline void toe_failover(struct ifnet *bond_ifp,
struct ifnet *fail_ifp, int event)
{}
static inline int toe_enslave(struct ifnet *bond_ifp,
struct ifnet *slave_ifp)
{
return 0;
}
#endif /* CONFIG_TCP_OFFLOAD */
#endif /* _OFFLOAD_DEV_H_ */