mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-11 16:24:26 +08:00
cxgb4: add support for offloading u32 filters
Add support for offloading u32 filter onto hardware. Links are stored in a jump table to perform necessary jumps to match TCP/UDP header. When inserting rules in the linked bucket, the TCP/UDP match fields in the corresponding entry of the jump table are appended to the filter rule before insertion. If a link is deleted, then all corresponding filters associated with the link are also deleted. Also enable hardware tc offload as a supported feature. Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com> Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2e8aad7bf2
commit
d893184748
@ -4,7 +4,7 @@
|
||||
|
||||
obj-$(CONFIG_CHELSIO_T4) += cxgb4.o
|
||||
|
||||
cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o clip_tbl.o cxgb4_ethtool.o cxgb4_uld.o sched.o cxgb4_filter.o
|
||||
cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o clip_tbl.o cxgb4_ethtool.o cxgb4_uld.o sched.o cxgb4_filter.o cxgb4_tc_u32.o
|
||||
cxgb4-$(CONFIG_CHELSIO_T4_DCB) += cxgb4_dcb.o
|
||||
cxgb4-$(CONFIG_CHELSIO_T4_FCOE) += cxgb4_fcoe.o
|
||||
cxgb4-$(CONFIG_DEBUG_FS) += cxgb4_debugfs.o
|
||||
|
@ -851,6 +851,9 @@ struct adapter {
|
||||
|
||||
spinlock_t stats_lock;
|
||||
spinlock_t win0_lock ____cacheline_aligned_in_smp;
|
||||
|
||||
/* TC u32 offload */
|
||||
struct cxgb4_tc_u32_table *tc_u32;
|
||||
};
|
||||
|
||||
/* Support for "sched-class" command to allow a TX Scheduling Class to be
|
||||
|
@ -78,6 +78,7 @@
|
||||
#include "clip_tbl.h"
|
||||
#include "l2t.h"
|
||||
#include "sched.h"
|
||||
#include "cxgb4_tc_u32.h"
|
||||
|
||||
char cxgb4_driver_name[] = KBUILD_MODNAME;
|
||||
|
||||
@ -2711,6 +2712,35 @@ static int cxgb_set_tx_maxrate(struct net_device *dev, int index, u32 rate)
|
||||
return err;
|
||||
}
|
||||
|
||||
int cxgb_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
|
||||
struct tc_to_netdev *tc)
|
||||
{
|
||||
struct port_info *pi = netdev2pinfo(dev);
|
||||
struct adapter *adap = netdev2adap(dev);
|
||||
|
||||
if (!(adap->flags & FULL_INIT_DONE)) {
|
||||
dev_err(adap->pdev_dev,
|
||||
"Failed to setup tc on port %d. Link Down?\n",
|
||||
pi->port_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (TC_H_MAJ(handle) == TC_H_MAJ(TC_H_INGRESS) &&
|
||||
tc->type == TC_SETUP_CLSU32) {
|
||||
switch (tc->cls_u32->command) {
|
||||
case TC_CLSU32_NEW_KNODE:
|
||||
case TC_CLSU32_REPLACE_KNODE:
|
||||
return cxgb4_config_knode(dev, proto, tc->cls_u32);
|
||||
case TC_CLSU32_DELETE_KNODE:
|
||||
return cxgb4_delete_knode(dev, proto, tc->cls_u32);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static const struct net_device_ops cxgb4_netdev_ops = {
|
||||
.ndo_open = cxgb_open,
|
||||
.ndo_stop = cxgb_close,
|
||||
@ -2734,6 +2764,7 @@ static const struct net_device_ops cxgb4_netdev_ops = {
|
||||
.ndo_busy_poll = cxgb_busy_poll,
|
||||
#endif
|
||||
.ndo_set_tx_maxrate = cxgb_set_tx_maxrate,
|
||||
.ndo_setup_tc = cxgb_setup_tc,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
@ -4406,6 +4437,7 @@ static void free_some_resources(struct adapter *adapter)
|
||||
t4_free_mem(adapter->l2t);
|
||||
t4_cleanup_sched(adapter);
|
||||
t4_free_mem(adapter->tids.tid_tab);
|
||||
cxgb4_cleanup_tc_u32(adapter);
|
||||
kfree(adapter->sge.egr_map);
|
||||
kfree(adapter->sge.ingr_map);
|
||||
kfree(adapter->sge.starving_fl);
|
||||
@ -4750,7 +4782,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
netdev->hw_features = NETIF_F_SG | TSO_FLAGS |
|
||||
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
|
||||
NETIF_F_RXCSUM | NETIF_F_RXHASH |
|
||||
NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
|
||||
NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
|
||||
NETIF_F_HW_TC;
|
||||
if (highdma)
|
||||
netdev->hw_features |= NETIF_F_HIGHDMA;
|
||||
netdev->features |= netdev->hw_features;
|
||||
@ -4838,6 +4871,12 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
dev_warn(&pdev->dev, "could not allocate TID table, "
|
||||
"continuing\n");
|
||||
adapter->params.offload = 0;
|
||||
} else {
|
||||
adapter->tc_u32 = cxgb4_init_tc_u32(adapter,
|
||||
CXGB4_MAX_LINK_HANDLE);
|
||||
if (!adapter->tc_u32)
|
||||
dev_warn(&pdev->dev,
|
||||
"could not offload tc u32, continuing\n");
|
||||
}
|
||||
|
||||
if (is_offload(adapter)) {
|
||||
|
412
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
Normal file
412
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
Normal file
@ -0,0 +1,412 @@
|
||||
/*
|
||||
* This file is part of the Chelsio T4 Ethernet driver for Linux.
|
||||
*
|
||||
* Copyright (c) 2016 Chelsio Communications, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "cxgb4.h"
|
||||
#include "cxgb4_tc_u32_parse.h"
|
||||
#include "cxgb4_tc_u32.h"
|
||||
|
||||
/* Fill ch_filter_specification with parsed match value/mask pair. */
|
||||
static int fill_match_fields(struct adapter *adap,
|
||||
struct ch_filter_specification *fs,
|
||||
struct tc_cls_u32_offload *cls,
|
||||
const struct cxgb4_match_field *entry,
|
||||
bool next_header)
|
||||
{
|
||||
unsigned int i, j;
|
||||
u32 val, mask;
|
||||
int off, err;
|
||||
bool found;
|
||||
|
||||
for (i = 0; i < cls->knode.sel->nkeys; i++) {
|
||||
off = cls->knode.sel->keys[i].off;
|
||||
val = cls->knode.sel->keys[i].val;
|
||||
mask = cls->knode.sel->keys[i].mask;
|
||||
|
||||
if (next_header) {
|
||||
/* For next headers, parse only keys with offmask */
|
||||
if (!cls->knode.sel->keys[i].offmask)
|
||||
continue;
|
||||
} else {
|
||||
/* For the remaining, parse only keys without offmask */
|
||||
if (cls->knode.sel->keys[i].offmask)
|
||||
continue;
|
||||
}
|
||||
|
||||
found = false;
|
||||
|
||||
for (j = 0; entry[j].val; j++) {
|
||||
if (off == entry[j].off) {
|
||||
found = true;
|
||||
err = entry[j].val(fs, val, mask);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cxgb4_config_knode(struct net_device *dev, __be16 protocol,
|
||||
struct tc_cls_u32_offload *cls)
|
||||
{
|
||||
const struct cxgb4_match_field *start, *link_start = NULL;
|
||||
struct adapter *adapter = netdev2adap(dev);
|
||||
struct ch_filter_specification fs;
|
||||
struct cxgb4_tc_u32_table *t;
|
||||
struct cxgb4_link *link;
|
||||
unsigned int filter_id;
|
||||
u32 uhtid, link_uhtid;
|
||||
bool is_ipv6 = false;
|
||||
int ret;
|
||||
|
||||
if (!can_tc_u32_offload(dev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (protocol != htons(ETH_P_IP) && protocol != htons(ETH_P_IPV6))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Fetch the location to insert the filter. */
|
||||
filter_id = cls->knode.handle & 0xFFFFF;
|
||||
|
||||
if (filter_id > adapter->tids.nftids) {
|
||||
dev_err(adapter->pdev_dev,
|
||||
"Location %d out of range for insertion. Max: %d\n",
|
||||
filter_id, adapter->tids.nftids);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
t = adapter->tc_u32;
|
||||
uhtid = TC_U32_USERHTID(cls->knode.handle);
|
||||
link_uhtid = TC_U32_USERHTID(cls->knode.link_handle);
|
||||
|
||||
/* Ensure that uhtid is either root u32 (i.e. 0x800)
|
||||
* or a a valid linked bucket.
|
||||
*/
|
||||
if (uhtid != 0x800 && uhtid >= t->size)
|
||||
return -EINVAL;
|
||||
|
||||
/* Ensure link handle uhtid is sane, if specified. */
|
||||
if (link_uhtid >= t->size)
|
||||
return -EINVAL;
|
||||
|
||||
memset(&fs, 0, sizeof(fs));
|
||||
|
||||
if (protocol == htons(ETH_P_IPV6)) {
|
||||
start = cxgb4_ipv6_fields;
|
||||
is_ipv6 = true;
|
||||
} else {
|
||||
start = cxgb4_ipv4_fields;
|
||||
is_ipv6 = false;
|
||||
}
|
||||
|
||||
if (uhtid != 0x800) {
|
||||
/* Link must exist from root node before insertion. */
|
||||
if (!t->table[uhtid - 1].link_handle)
|
||||
return -EINVAL;
|
||||
|
||||
/* Link must have a valid supported next header. */
|
||||
link_start = t->table[uhtid - 1].match_field;
|
||||
if (!link_start)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Parse links and record them for subsequent jumps to valid
|
||||
* next headers.
|
||||
*/
|
||||
if (link_uhtid) {
|
||||
const struct cxgb4_next_header *next;
|
||||
bool found = false;
|
||||
unsigned int i, j;
|
||||
u32 val, mask;
|
||||
int off;
|
||||
|
||||
if (t->table[link_uhtid - 1].link_handle) {
|
||||
dev_err(adapter->pdev_dev,
|
||||
"Link handle exists for: 0x%x\n",
|
||||
link_uhtid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
next = is_ipv6 ? cxgb4_ipv6_jumps : cxgb4_ipv4_jumps;
|
||||
|
||||
/* Try to find matches that allow jumps to next header. */
|
||||
for (i = 0; next[i].jump; i++) {
|
||||
if (next[i].offoff != cls->knode.sel->offoff ||
|
||||
next[i].shift != cls->knode.sel->offshift ||
|
||||
next[i].mask != cls->knode.sel->offmask ||
|
||||
next[i].offset != cls->knode.sel->off)
|
||||
continue;
|
||||
|
||||
/* Found a possible candidate. Find a key that
|
||||
* matches the corresponding offset, value, and
|
||||
* mask to jump to next header.
|
||||
*/
|
||||
for (j = 0; j < cls->knode.sel->nkeys; j++) {
|
||||
off = cls->knode.sel->keys[j].off;
|
||||
val = cls->knode.sel->keys[j].val;
|
||||
mask = cls->knode.sel->keys[j].mask;
|
||||
|
||||
if (next[i].match_off == off &&
|
||||
next[i].match_val == val &&
|
||||
next[i].match_mask == mask) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
continue; /* Try next candidate. */
|
||||
|
||||
/* Candidate to jump to next header found.
|
||||
* Translate all keys to internal specification
|
||||
* and store them in jump table. This spec is copied
|
||||
* later to set the actual filters.
|
||||
*/
|
||||
ret = fill_match_fields(adapter, &fs, cls,
|
||||
start, false);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
link = &t->table[link_uhtid - 1];
|
||||
link->match_field = next[i].jump;
|
||||
link->link_handle = cls->knode.handle;
|
||||
memcpy(&link->fs, &fs, sizeof(fs));
|
||||
break;
|
||||
}
|
||||
|
||||
/* No candidate found to jump to next header. */
|
||||
if (!found)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fill ch_filter_specification match fields to be shipped to hardware.
|
||||
* Copy the linked spec (if any) first. And then update the spec as
|
||||
* needed.
|
||||
*/
|
||||
if (uhtid != 0x800 && t->table[uhtid - 1].link_handle) {
|
||||
/* Copy linked ch_filter_specification */
|
||||
memcpy(&fs, &t->table[uhtid - 1].fs, sizeof(fs));
|
||||
ret = fill_match_fields(adapter, &fs, cls,
|
||||
link_start, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fill_match_fields(adapter, &fs, cls, start, false);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* The filter spec has been completely built from the info
|
||||
* provided from u32. We now set some default fields in the
|
||||
* spec for sanity.
|
||||
*/
|
||||
|
||||
/* Match only packets coming from the ingress port where this
|
||||
* filter will be created.
|
||||
*/
|
||||
fs.val.iport = netdev2pinfo(dev)->port_id;
|
||||
fs.mask.iport = ~0;
|
||||
|
||||
/* Enable filter hit counts. */
|
||||
fs.hitcnts = 1;
|
||||
|
||||
/* Set type of filter - IPv6 or IPv4 */
|
||||
fs.type = is_ipv6 ? 1 : 0;
|
||||
|
||||
/* Set the filter */
|
||||
ret = cxgb4_set_filter(dev, filter_id, &fs);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* If this is a linked bucket, then set the corresponding
|
||||
* entry in the bitmap to mark it as belonging to this linked
|
||||
* bucket.
|
||||
*/
|
||||
if (uhtid != 0x800 && t->table[uhtid - 1].link_handle)
|
||||
set_bit(filter_id, t->table[uhtid - 1].tid_map);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxgb4_delete_knode(struct net_device *dev, __be16 protocol,
|
||||
struct tc_cls_u32_offload *cls)
|
||||
{
|
||||
struct adapter *adapter = netdev2adap(dev);
|
||||
unsigned int filter_id, max_tids, i, j;
|
||||
struct cxgb4_link *link = NULL;
|
||||
struct cxgb4_tc_u32_table *t;
|
||||
u32 handle, uhtid;
|
||||
int ret;
|
||||
|
||||
if (!can_tc_u32_offload(dev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Fetch the location to delete the filter. */
|
||||
filter_id = cls->knode.handle & 0xFFFFF;
|
||||
|
||||
if (filter_id > adapter->tids.nftids) {
|
||||
dev_err(adapter->pdev_dev,
|
||||
"Location %d out of range for deletion. Max: %d\n",
|
||||
filter_id, adapter->tids.nftids);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
t = adapter->tc_u32;
|
||||
handle = cls->knode.handle;
|
||||
uhtid = TC_U32_USERHTID(cls->knode.handle);
|
||||
|
||||
/* Ensure that uhtid is either root u32 (i.e. 0x800)
|
||||
* or a a valid linked bucket.
|
||||
*/
|
||||
if (uhtid != 0x800 && uhtid >= t->size)
|
||||
return -EINVAL;
|
||||
|
||||
/* Delete the specified filter */
|
||||
if (uhtid != 0x800) {
|
||||
link = &t->table[uhtid - 1];
|
||||
if (!link->link_handle)
|
||||
return -EINVAL;
|
||||
|
||||
if (!test_bit(filter_id, link->tid_map))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = cxgb4_del_filter(dev, filter_id);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (link)
|
||||
clear_bit(filter_id, link->tid_map);
|
||||
|
||||
/* If a link is being deleted, then delete all filters
|
||||
* associated with the link.
|
||||
*/
|
||||
max_tids = adapter->tids.nftids;
|
||||
for (i = 0; i < t->size; i++) {
|
||||
link = &t->table[i];
|
||||
|
||||
if (link->link_handle == handle) {
|
||||
for (j = 0; j < max_tids; j++) {
|
||||
if (!test_bit(j, link->tid_map))
|
||||
continue;
|
||||
|
||||
ret = __cxgb4_del_filter(dev, j, NULL);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
clear_bit(j, link->tid_map);
|
||||
}
|
||||
|
||||
/* Clear the link state */
|
||||
link->match_field = NULL;
|
||||
link->link_handle = 0;
|
||||
memset(&link->fs, 0, sizeof(link->fs));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cxgb4_cleanup_tc_u32(struct adapter *adap)
|
||||
{
|
||||
struct cxgb4_tc_u32_table *t;
|
||||
unsigned int i;
|
||||
|
||||
if (!adap->tc_u32)
|
||||
return;
|
||||
|
||||
/* Free up all allocated memory. */
|
||||
t = adap->tc_u32;
|
||||
for (i = 0; i < t->size; i++) {
|
||||
struct cxgb4_link *link = &t->table[i];
|
||||
|
||||
t4_free_mem(link->tid_map);
|
||||
}
|
||||
t4_free_mem(adap->tc_u32);
|
||||
}
|
||||
|
||||
struct cxgb4_tc_u32_table *cxgb4_init_tc_u32(struct adapter *adap,
|
||||
unsigned int size)
|
||||
{
|
||||
struct cxgb4_tc_u32_table *t;
|
||||
unsigned int i;
|
||||
|
||||
if (!size)
|
||||
return NULL;
|
||||
|
||||
t = t4_alloc_mem(sizeof(*t) +
|
||||
(size * sizeof(struct cxgb4_link)));
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
t->size = size;
|
||||
|
||||
for (i = 0; i < t->size; i++) {
|
||||
struct cxgb4_link *link = &t->table[i];
|
||||
unsigned int bmap_size;
|
||||
unsigned int max_tids;
|
||||
|
||||
max_tids = adap->tids.nftids;
|
||||
bmap_size = BITS_TO_LONGS(max_tids);
|
||||
link->tid_map = t4_alloc_mem(sizeof(unsigned long) * bmap_size);
|
||||
if (!link->tid_map)
|
||||
goto out_no_mem;
|
||||
bitmap_zero(link->tid_map, max_tids);
|
||||
}
|
||||
|
||||
return t;
|
||||
|
||||
out_no_mem:
|
||||
for (i = 0; i < t->size; i++) {
|
||||
struct cxgb4_link *link = &t->table[i];
|
||||
|
||||
if (link->tid_map)
|
||||
t4_free_mem(link->tid_map);
|
||||
}
|
||||
|
||||
if (t)
|
||||
t4_free_mem(t);
|
||||
|
||||
return NULL;
|
||||
}
|
57
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.h
Normal file
57
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of the Chelsio T4 Ethernet driver for Linux.
|
||||
*
|
||||
* Copyright (c) 2016 Chelsio Communications, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __CXGB4_TC_U32_H
|
||||
#define __CXGB4_TC_U32_H
|
||||
|
||||
#include <net/pkt_cls.h>
|
||||
|
||||
#define CXGB4_MAX_LINK_HANDLE 32
|
||||
|
||||
static inline bool can_tc_u32_offload(struct net_device *dev)
|
||||
{
|
||||
struct adapter *adap = netdev2adap(dev);
|
||||
|
||||
return (dev->features & NETIF_F_HW_TC) && adap->tc_u32 ? true : false;
|
||||
}
|
||||
|
||||
int cxgb4_config_knode(struct net_device *dev, __be16 protocol,
|
||||
struct tc_cls_u32_offload *cls);
|
||||
int cxgb4_delete_knode(struct net_device *dev, __be16 protocol,
|
||||
struct tc_cls_u32_offload *cls);
|
||||
|
||||
void cxgb4_cleanup_tc_u32(struct adapter *adapter);
|
||||
struct cxgb4_tc_u32_table *cxgb4_init_tc_u32(struct adapter *adap,
|
||||
unsigned int size);
|
||||
#endif /* __CXGB4_TC_U32_H */
|
@ -279,4 +279,16 @@ static const struct cxgb4_next_header cxgb4_ipv6_jumps[] = {
|
||||
.jump = cxgb4_udp_fields },
|
||||
{ .jump = NULL }
|
||||
};
|
||||
|
||||
struct cxgb4_link {
|
||||
const struct cxgb4_match_field *match_field; /* Next header */
|
||||
struct ch_filter_specification fs; /* Match spec associated with link */
|
||||
u32 link_handle; /* Knode handle associated with the link */
|
||||
unsigned long *tid_map; /* Bitmap for filter tids */
|
||||
};
|
||||
|
||||
struct cxgb4_tc_u32_table {
|
||||
unsigned int size; /* number of entries in table */
|
||||
struct cxgb4_link table[0]; /* Jump table */
|
||||
};
|
||||
#endif /* __CXGB4_TC_U32_PARSE_H */
|
||||
|
Loading…
Reference in New Issue
Block a user