提交 c2193999 编写于 作者: S Shahjada Abul Husain 提交者: David S. Miller

cxgb4: add support for high priority filters

T6 has a separate region known as high priority filter region
that allows classifying packets going through ULD path. So,
query firmware for HPFILTER resources and enable the high
priority offload filter support when it is available.
Signed-off-by: NShahjada Abul Husain <shahjada@chelsio.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 6525b5ef
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include <asm/io.h> #include <asm/io.h>
#include "t4_chip_type.h" #include "t4_chip_type.h"
#include "cxgb4_uld.h" #include "cxgb4_uld.h"
#include "t4fw_api.h"
#define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__) #define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
extern struct list_head adapter_list; extern struct list_head adapter_list;
...@@ -68,6 +69,16 @@ extern struct mutex uld_mutex; ...@@ -68,6 +69,16 @@ extern struct mutex uld_mutex;
#define ETHTXQ_STOP_THRES \ #define ETHTXQ_STOP_THRES \
(1 + DIV_ROUND_UP((3 * MAX_SKB_FRAGS) / 2 + (MAX_SKB_FRAGS & 1), 8)) (1 + DIV_ROUND_UP((3 * MAX_SKB_FRAGS) / 2 + (MAX_SKB_FRAGS & 1), 8))
#define FW_PARAM_DEV(param) \
(FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | \
FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_##param))
#define FW_PARAM_PFVF(param) \
(FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_PFVF) | \
FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_PFVF_##param) | \
FW_PARAMS_PARAM_Y_V(0) | \
FW_PARAMS_PARAM_Z_V(0))
enum { enum {
MAX_NPORTS = 4, /* max # of ports */ MAX_NPORTS = 4, /* max # of ports */
SERNUM_LEN = 24, /* Serial # length */ SERNUM_LEN = 24, /* Serial # length */
......
...@@ -3240,6 +3240,9 @@ static int tid_info_show(struct seq_file *seq, void *v) ...@@ -3240,6 +3240,9 @@ static int tid_info_show(struct seq_file *seq, void *v)
seq_printf(seq, "SFTID range: %u..%u in use: %u\n", seq_printf(seq, "SFTID range: %u..%u in use: %u\n",
t->sftid_base, t->sftid_base + t->nsftids - 2, t->sftid_base, t->sftid_base + t->nsftids - 2,
t->sftids_in_use); t->sftids_in_use);
if (t->nhpftids)
seq_printf(seq, "HPFTID range: %u..%u\n", t->hpftid_base,
t->hpftid_base + t->nhpftids - 1);
if (t->ntids) if (t->ntids)
seq_printf(seq, "HW TID usage: %u IP users, %u IPv6 users\n", seq_printf(seq, "HW TID usage: %u IP users, %u IPv6 users\n",
t4_read_reg(adap, LE_DB_ACT_CNT_IPV4_A), t4_read_reg(adap, LE_DB_ACT_CNT_IPV4_A),
......
...@@ -507,6 +507,24 @@ static int cxgb4_set_ftid(struct tid_info *t, int fidx, int family, ...@@ -507,6 +507,24 @@ static int cxgb4_set_ftid(struct tid_info *t, int fidx, int family,
return 0; return 0;
} }
static int cxgb4_set_hpftid(struct tid_info *t, int fidx, int family)
{
spin_lock_bh(&t->ftid_lock);
if (test_bit(fidx, t->hpftid_bmap)) {
spin_unlock_bh(&t->ftid_lock);
return -EBUSY;
}
if (family == PF_INET)
__set_bit(fidx, t->hpftid_bmap);
else
bitmap_allocate_region(t->hpftid_bmap, fidx, 1);
spin_unlock_bh(&t->ftid_lock);
return 0;
}
static void cxgb4_clear_ftid(struct tid_info *t, int fidx, int family, static void cxgb4_clear_ftid(struct tid_info *t, int fidx, int family,
unsigned int chip_ver) unsigned int chip_ver)
{ {
...@@ -522,33 +540,58 @@ static void cxgb4_clear_ftid(struct tid_info *t, int fidx, int family, ...@@ -522,33 +540,58 @@ static void cxgb4_clear_ftid(struct tid_info *t, int fidx, int family,
spin_unlock_bh(&t->ftid_lock); spin_unlock_bh(&t->ftid_lock);
} }
static void cxgb4_clear_hpftid(struct tid_info *t, int fidx, int family)
{
spin_lock_bh(&t->ftid_lock);
if (family == PF_INET)
__clear_bit(fidx, t->hpftid_bmap);
else
bitmap_release_region(t->hpftid_bmap, fidx, 1);
spin_unlock_bh(&t->ftid_lock);
}
bool cxgb4_filter_prio_in_range(struct net_device *dev, u32 idx, u32 prio) bool cxgb4_filter_prio_in_range(struct net_device *dev, u32 idx, u32 prio)
{ {
struct filter_entry *prev_fe, *next_fe, *tab;
struct adapter *adap = netdev2adap(dev); struct adapter *adap = netdev2adap(dev);
struct filter_entry *prev_fe, *next_fe; u32 prev_ftid, next_ftid, max_tid;
struct tid_info *t = &adap->tids; struct tid_info *t = &adap->tids;
u32 prev_ftid, next_ftid; unsigned long *bmap;
bool valid = true; bool valid = true;
if (idx < t->nhpftids) {
bmap = t->hpftid_bmap;
tab = t->hpftid_tab;
max_tid = t->nhpftids;
} else {
idx -= t->nhpftids;
bmap = t->ftid_bmap;
tab = t->ftid_tab;
max_tid = t->nftids;
}
/* Only insert the rule if both of the following conditions /* Only insert the rule if both of the following conditions
* are met: * are met:
* 1. The immediate previous rule has priority <= @prio. * 1. The immediate previous rule has priority <= @prio.
* 2. The immediate next rule has priority >= @prio. * 2. The immediate next rule has priority >= @prio.
*/ */
spin_lock_bh(&t->ftid_lock); spin_lock_bh(&t->ftid_lock);
/* Don't insert if there's a rule already present at @idx. */ /* Don't insert if there's a rule already present at @idx. */
if (test_bit(idx, t->ftid_bmap)) { if (test_bit(idx, bmap)) {
valid = false; valid = false;
goto out_unlock; goto out_unlock;
} }
next_ftid = find_next_bit(t->ftid_bmap, t->nftids, idx); next_ftid = find_next_bit(bmap, max_tid, idx);
if (next_ftid >= t->nftids) if (next_ftid >= max_tid)
next_ftid = idx; next_ftid = idx;
next_fe = &adap->tids.ftid_tab[next_ftid]; next_fe = &tab[next_ftid];
prev_ftid = find_last_bit(t->ftid_bmap, idx); prev_ftid = find_last_bit(bmap, idx);
if (prev_ftid >= idx) if (prev_ftid >= idx)
prev_ftid = idx; prev_ftid = idx;
...@@ -558,13 +601,13 @@ bool cxgb4_filter_prio_in_range(struct net_device *dev, u32 idx, u32 prio) ...@@ -558,13 +601,13 @@ bool cxgb4_filter_prio_in_range(struct net_device *dev, u32 idx, u32 prio)
* accordingly. * accordingly.
*/ */
if (CHELSIO_CHIP_VERSION(adap->params.chip) < CHELSIO_T6) { if (CHELSIO_CHIP_VERSION(adap->params.chip) < CHELSIO_T6) {
prev_fe = &adap->tids.ftid_tab[prev_ftid & ~0x3]; prev_fe = &tab[prev_ftid & ~0x3];
if (!prev_fe->fs.type) if (!prev_fe->fs.type)
prev_fe = &adap->tids.ftid_tab[prev_ftid]; prev_fe = &tab[prev_ftid];
} else { } else {
prev_fe = &adap->tids.ftid_tab[prev_ftid & ~0x1]; prev_fe = &tab[prev_ftid & ~0x1];
if (!prev_fe->fs.type) if (!prev_fe->fs.type)
prev_fe = &adap->tids.ftid_tab[prev_ftid]; prev_fe = &tab[prev_ftid];
} }
if ((prev_fe->valid && prio < prev_fe->fs.tc_prio) || if ((prev_fe->valid && prio < prev_fe->fs.tc_prio) ||
...@@ -579,11 +622,16 @@ bool cxgb4_filter_prio_in_range(struct net_device *dev, u32 idx, u32 prio) ...@@ -579,11 +622,16 @@ bool cxgb4_filter_prio_in_range(struct net_device *dev, u32 idx, u32 prio)
/* Delete the filter at a specified index. */ /* Delete the filter at a specified index. */
static int del_filter_wr(struct adapter *adapter, int fidx) static int del_filter_wr(struct adapter *adapter, int fidx)
{ {
struct filter_entry *f = &adapter->tids.ftid_tab[fidx];
struct fw_filter_wr *fwr; struct fw_filter_wr *fwr;
struct filter_entry *f;
struct sk_buff *skb; struct sk_buff *skb;
unsigned int len; unsigned int len;
if (fidx < adapter->tids.nhpftids)
f = &adapter->tids.hpftid_tab[fidx];
else
f = &adapter->tids.ftid_tab[fidx - adapter->tids.nhpftids];
len = sizeof(*fwr); len = sizeof(*fwr);
skb = alloc_skb(len, GFP_KERNEL); skb = alloc_skb(len, GFP_KERNEL);
...@@ -609,10 +657,15 @@ static int del_filter_wr(struct adapter *adapter, int fidx) ...@@ -609,10 +657,15 @@ static int del_filter_wr(struct adapter *adapter, int fidx)
*/ */
int set_filter_wr(struct adapter *adapter, int fidx) int set_filter_wr(struct adapter *adapter, int fidx)
{ {
struct filter_entry *f = &adapter->tids.ftid_tab[fidx];
struct fw_filter2_wr *fwr; struct fw_filter2_wr *fwr;
struct filter_entry *f;
struct sk_buff *skb; struct sk_buff *skb;
if (fidx < adapter->tids.nhpftids)
f = &adapter->tids.hpftid_tab[fidx];
else
f = &adapter->tids.ftid_tab[fidx - adapter->tids.nhpftids];
skb = alloc_skb(sizeof(*fwr), GFP_KERNEL); skb = alloc_skb(sizeof(*fwr), GFP_KERNEL);
if (!skb) if (!skb)
return -ENOMEM; return -ENOMEM;
...@@ -811,12 +864,22 @@ void clear_all_filters(struct adapter *adapter) ...@@ -811,12 +864,22 @@ void clear_all_filters(struct adapter *adapter)
struct net_device *dev = adapter->port[0]; struct net_device *dev = adapter->port[0];
unsigned int i; unsigned int i;
if (adapter->tids.hpftid_tab) {
struct filter_entry *f = &adapter->tids.hpftid_tab[0];
for (i = 0; i < adapter->tids.nhpftids; i++, f++)
if (f->valid || f->pending)
cxgb4_del_filter(dev, i, &f->fs);
}
if (adapter->tids.ftid_tab) { if (adapter->tids.ftid_tab) {
struct filter_entry *f = &adapter->tids.ftid_tab[0]; struct filter_entry *f = &adapter->tids.ftid_tab[0];
unsigned int max_ftid = adapter->tids.nftids + unsigned int max_ftid = adapter->tids.nftids +
adapter->tids.nsftids; adapter->tids.nsftids +
adapter->tids.nhpftids;
/* Clear all TCAM filters */ /* Clear all TCAM filters */
for (i = 0; i < max_ftid; i++, f++) for (i = adapter->tids.nhpftids; i < max_ftid; i++, f++)
if (f->valid || f->pending) if (f->valid || f->pending)
cxgb4_del_filter(dev, i, &f->fs); cxgb4_del_filter(dev, i, &f->fs);
} }
...@@ -1319,17 +1382,17 @@ static int cxgb4_set_hash_filter(struct net_device *dev, ...@@ -1319,17 +1382,17 @@ static int cxgb4_set_hash_filter(struct net_device *dev,
* filter specification in order to facilitate signaling completion of the * filter specification in order to facilitate signaling completion of the
* operation. * operation.
*/ */
int __cxgb4_set_filter(struct net_device *dev, int filter_id, int __cxgb4_set_filter(struct net_device *dev, int ftid,
struct ch_filter_specification *fs, struct ch_filter_specification *fs,
struct filter_ctx *ctx) struct filter_ctx *ctx)
{ {
struct adapter *adapter = netdev2adap(dev); struct adapter *adapter = netdev2adap(dev);
unsigned int chip_ver = CHELSIO_CHIP_VERSION(adapter->params.chip); unsigned int max_fidx, fidx, chip_ver;
unsigned int max_fidx, fidx; int iq, ret, filter_id = ftid;
struct filter_entry *f; struct filter_entry *f, *tab;
u32 iconf; u32 iconf;
int iq, ret;
chip_ver = CHELSIO_CHIP_VERSION(adapter->params.chip);
if (fs->hash) { if (fs->hash) {
if (is_hashfilter(adapter)) if (is_hashfilter(adapter))
return cxgb4_set_hash_filter(dev, fs, ctx); return cxgb4_set_hash_filter(dev, fs, ctx);
...@@ -1338,7 +1401,7 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id, ...@@ -1338,7 +1401,7 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id,
return -EINVAL; return -EINVAL;
} }
max_fidx = adapter->tids.nftids; max_fidx = adapter->tids.nftids + adapter->tids.nhpftids;
if (filter_id != (max_fidx + adapter->tids.nsftids - 1) && if (filter_id != (max_fidx + adapter->tids.nsftids - 1) &&
filter_id >= max_fidx) filter_id >= max_fidx)
return -E2BIG; return -E2BIG;
...@@ -1353,6 +1416,13 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id, ...@@ -1353,6 +1416,13 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id,
if (iq < 0) if (iq < 0)
return iq; return iq;
if (fs->prio) {
tab = &adapter->tids.hpftid_tab[0];
} else {
tab = &adapter->tids.ftid_tab[0];
filter_id = ftid - adapter->tids.nhpftids;
}
/* IPv6 filters occupy four slots and must be aligned on /* IPv6 filters occupy four slots and must be aligned on
* four-slot boundaries. IPv4 filters only occupy a single * four-slot boundaries. IPv4 filters only occupy a single
* slot and have no alignment requirements but writing a new * slot and have no alignment requirements but writing a new
...@@ -1373,9 +1443,8 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id, ...@@ -1373,9 +1443,8 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id,
else else
fidx = filter_id & ~0x1; fidx = filter_id & ~0x1;
if (fidx != filter_id && if (fidx != filter_id && tab[fidx].fs.type) {
adapter->tids.ftid_tab[fidx].fs.type) { f = &tab[fidx];
f = &adapter->tids.ftid_tab[fidx];
if (f->valid) { if (f->valid) {
dev_err(adapter->pdev_dev, dev_err(adapter->pdev_dev,
"Invalid location. IPv6 requires 4 slots and is occupying slots %u to %u\n", "Invalid location. IPv6 requires 4 slots and is occupying slots %u to %u\n",
...@@ -1399,7 +1468,7 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id, ...@@ -1399,7 +1468,7 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id,
*/ */
for (fidx = filter_id + 1; fidx < filter_id + 4; for (fidx = filter_id + 1; fidx < filter_id + 4;
fidx++) { fidx++) {
f = &adapter->tids.ftid_tab[fidx]; f = &tab[fidx];
if (f->valid) { if (f->valid) {
dev_err(adapter->pdev_dev, dev_err(adapter->pdev_dev,
"Invalid location. IPv6 requires 4 slots and an IPv4 filter exists at %u\n", "Invalid location. IPv6 requires 4 slots and an IPv4 filter exists at %u\n",
...@@ -1415,7 +1484,7 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id, ...@@ -1415,7 +1484,7 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id,
return -EINVAL; return -EINVAL;
/* Check overlapping IPv4 filter slot */ /* Check overlapping IPv4 filter slot */
fidx = filter_id + 1; fidx = filter_id + 1;
f = &adapter->tids.ftid_tab[fidx]; f = &tab[fidx];
if (f->valid) { if (f->valid) {
pr_err("%s: IPv6 filter requires 2 indices. IPv4 filter already present at %d. Please remove IPv4 filter first.\n", pr_err("%s: IPv6 filter requires 2 indices. IPv4 filter already present at %d. Please remove IPv4 filter first.\n",
__func__, fidx); __func__, fidx);
...@@ -1427,36 +1496,35 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id, ...@@ -1427,36 +1496,35 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id,
/* Check to make sure that provided filter index is not /* Check to make sure that provided filter index is not
* already in use by someone else * already in use by someone else
*/ */
f = &adapter->tids.ftid_tab[filter_id]; f = &tab[filter_id];
if (f->valid) if (f->valid)
return -EBUSY; return -EBUSY;
fidx = filter_id + adapter->tids.ftid_base; if (fs->prio) {
ret = cxgb4_set_ftid(&adapter->tids, filter_id, fidx = filter_id + adapter->tids.hpftid_base;
fs->type ? PF_INET6 : PF_INET, ret = cxgb4_set_hpftid(&adapter->tids, filter_id,
chip_ver); fs->type ? PF_INET6 : PF_INET);
} else {
fidx = filter_id + adapter->tids.ftid_base;
ret = cxgb4_set_ftid(&adapter->tids, filter_id,
fs->type ? PF_INET6 : PF_INET,
chip_ver);
}
if (ret) if (ret)
return ret; return ret;
/* Check t make sure the filter requested is writable ... */ /* Check t make sure the filter requested is writable ... */
ret = writable_filter(f); ret = writable_filter(f);
if (ret) { if (ret)
/* Clear the bits we have set above */ goto free_tid;
cxgb4_clear_ftid(&adapter->tids, filter_id,
fs->type ? PF_INET6 : PF_INET,
chip_ver);
return ret;
}
if (is_t6(adapter->params.chip) && fs->type && if (is_t6(adapter->params.chip) && fs->type &&
ipv6_addr_type((const struct in6_addr *)fs->val.lip) != ipv6_addr_type((const struct in6_addr *)fs->val.lip) !=
IPV6_ADDR_ANY) { IPV6_ADDR_ANY) {
ret = cxgb4_clip_get(dev, (const u32 *)&fs->val.lip, 1); ret = cxgb4_clip_get(dev, (const u32 *)&fs->val.lip, 1);
if (ret) { if (ret)
cxgb4_clear_ftid(&adapter->tids, filter_id, PF_INET6, goto free_tid;
chip_ver);
return ret;
}
} }
/* Convert the filter specification into our internal format. /* Convert the filter specification into our internal format.
...@@ -1487,7 +1555,7 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id, ...@@ -1487,7 +1555,7 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id,
f->fs.mask.vni, f->fs.mask.vni,
0, 1, 1); 0, 1, 1);
if (ret < 0) if (ret < 0)
goto free_clip; goto free_tid;
f->fs.val.ovlan = ret; f->fs.val.ovlan = ret;
f->fs.mask.ovlan = 0x1ff; f->fs.mask.ovlan = 0x1ff;
...@@ -1501,21 +1569,22 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id, ...@@ -1501,21 +1569,22 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id,
*/ */
f->ctx = ctx; f->ctx = ctx;
f->tid = fidx; /* Save the actual tid */ f->tid = fidx; /* Save the actual tid */
ret = set_filter_wr(adapter, filter_id); ret = set_filter_wr(adapter, ftid);
if (ret) { if (ret)
goto free_tid;
return ret;
free_tid:
if (f->fs.prio)
cxgb4_clear_hpftid(&adapter->tids, filter_id,
fs->type ? PF_INET6 : PF_INET);
else
cxgb4_clear_ftid(&adapter->tids, filter_id, cxgb4_clear_ftid(&adapter->tids, filter_id,
fs->type ? PF_INET6 : PF_INET, fs->type ? PF_INET6 : PF_INET,
chip_ver); chip_ver);
clear_filter(adapter, f);
}
return ret; clear_filter(adapter, f);
free_clip:
if (is_t6(adapter->params.chip) && f->fs.type)
cxgb4_clip_release(f->dev, (const u32 *)&f->fs.val.lip, 1);
cxgb4_clear_ftid(&adapter->tids, filter_id,
fs->type ? PF_INET6 : PF_INET, chip_ver);
return ret; return ret;
} }
...@@ -1590,11 +1659,11 @@ int __cxgb4_del_filter(struct net_device *dev, int filter_id, ...@@ -1590,11 +1659,11 @@ int __cxgb4_del_filter(struct net_device *dev, int filter_id,
struct filter_ctx *ctx) struct filter_ctx *ctx)
{ {
struct adapter *adapter = netdev2adap(dev); struct adapter *adapter = netdev2adap(dev);
unsigned int chip_ver = CHELSIO_CHIP_VERSION(adapter->params.chip); unsigned int max_fidx, chip_ver;
struct filter_entry *f; struct filter_entry *f;
unsigned int max_fidx;
int ret; int ret;
chip_ver = CHELSIO_CHIP_VERSION(adapter->params.chip);
if (fs && fs->hash) { if (fs && fs->hash) {
if (is_hashfilter(adapter)) if (is_hashfilter(adapter))
return cxgb4_del_hash_filter(dev, filter_id, ctx); return cxgb4_del_hash_filter(dev, filter_id, ctx);
...@@ -1603,21 +1672,31 @@ int __cxgb4_del_filter(struct net_device *dev, int filter_id, ...@@ -1603,21 +1672,31 @@ int __cxgb4_del_filter(struct net_device *dev, int filter_id,
return -EINVAL; return -EINVAL;
} }
max_fidx = adapter->tids.nftids; max_fidx = adapter->tids.nftids + adapter->tids.nhpftids;
if (filter_id != (max_fidx + adapter->tids.nsftids - 1) && if (filter_id != (max_fidx + adapter->tids.nsftids - 1) &&
filter_id >= max_fidx) filter_id >= max_fidx)
return -E2BIG; return -E2BIG;
f = &adapter->tids.ftid_tab[filter_id]; if (filter_id < adapter->tids.nhpftids)
f = &adapter->tids.hpftid_tab[filter_id];
else
f = &adapter->tids.ftid_tab[filter_id - adapter->tids.nhpftids];
ret = writable_filter(f); ret = writable_filter(f);
if (ret) if (ret)
return ret; return ret;
if (f->valid) { if (f->valid) {
f->ctx = ctx; f->ctx = ctx;
cxgb4_clear_ftid(&adapter->tids, filter_id, if (f->fs.prio)
f->fs.type ? PF_INET6 : PF_INET, cxgb4_clear_hpftid(&adapter->tids,
chip_ver); f->tid - adapter->tids.hpftid_base,
f->fs.type ? PF_INET6 : PF_INET);
else
cxgb4_clear_ftid(&adapter->tids,
f->tid - adapter->tids.ftid_base,
f->fs.type ? PF_INET6 : PF_INET,
chip_ver);
return del_filter_wr(adapter, filter_id); return del_filter_wr(adapter, filter_id);
} }
...@@ -1842,11 +1921,18 @@ void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl) ...@@ -1842,11 +1921,18 @@ void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl)
max_fidx = adap->tids.nftids + adap->tids.nsftids; max_fidx = adap->tids.nftids + adap->tids.nsftids;
/* Get the corresponding filter entry for this tid */ /* Get the corresponding filter entry for this tid */
if (adap->tids.ftid_tab) { if (adap->tids.ftid_tab) {
/* Check this in normal filter region */ idx = tid - adap->tids.hpftid_base;
idx = tid - adap->tids.ftid_base; if (idx < adap->tids.nhpftids) {
if (idx >= max_fidx) f = &adap->tids.hpftid_tab[idx];
return; } else {
f = &adap->tids.ftid_tab[idx]; /* Check this in normal filter region */
idx = tid - adap->tids.ftid_base;
if (idx >= max_fidx)
return;
f = &adap->tids.ftid_tab[idx];
idx += adap->tids.nhpftids;
}
if (f->tid != tid) if (f->tid != tid)
return; return;
} }
......
...@@ -804,6 +804,26 @@ static int setup_ppod_edram(struct adapter *adap) ...@@ -804,6 +804,26 @@ static int setup_ppod_edram(struct adapter *adap)
return 0; return 0;
} }
static void adap_config_hpfilter(struct adapter *adapter)
{
u32 param, val = 0;
int ret;
/* Enable HP filter region. Older fw will fail this request and
* it is fine.
*/
param = FW_PARAM_DEV(HPFILTER_REGION_SUPPORT);
ret = t4_set_params(adapter, adapter->mbox, adapter->pf, 0,
1, &param, &val);
/* An error means FW doesn't know about HP filter support,
* it's not a problem, don't return an error.
*/
if (ret < 0)
dev_err(adapter->pdev_dev,
"HP filter region isn't supported by FW\n");
}
/** /**
* cxgb4_write_rss - write the RSS table for a given port * cxgb4_write_rss - write the RSS table for a given port
* @pi: the port * @pi: the port
...@@ -1518,6 +1538,7 @@ static int tid_init(struct tid_info *t) ...@@ -1518,6 +1538,7 @@ static int tid_init(struct tid_info *t)
struct adapter *adap = container_of(t, struct adapter, tids); struct adapter *adap = container_of(t, struct adapter, tids);
unsigned int max_ftids = t->nftids + t->nsftids; unsigned int max_ftids = t->nftids + t->nsftids;
unsigned int natids = t->natids; unsigned int natids = t->natids;
unsigned int hpftid_bmap_size;
unsigned int eotid_bmap_size; unsigned int eotid_bmap_size;
unsigned int stid_bmap_size; unsigned int stid_bmap_size;
unsigned int ftid_bmap_size; unsigned int ftid_bmap_size;
...@@ -1525,12 +1546,15 @@ static int tid_init(struct tid_info *t) ...@@ -1525,12 +1546,15 @@ static int tid_init(struct tid_info *t)
stid_bmap_size = BITS_TO_LONGS(t->nstids + t->nsftids); stid_bmap_size = BITS_TO_LONGS(t->nstids + t->nsftids);
ftid_bmap_size = BITS_TO_LONGS(t->nftids); ftid_bmap_size = BITS_TO_LONGS(t->nftids);
hpftid_bmap_size = BITS_TO_LONGS(t->nhpftids);
eotid_bmap_size = BITS_TO_LONGS(t->neotids); eotid_bmap_size = BITS_TO_LONGS(t->neotids);
size = t->ntids * sizeof(*t->tid_tab) + size = t->ntids * sizeof(*t->tid_tab) +
natids * sizeof(*t->atid_tab) + natids * sizeof(*t->atid_tab) +
t->nstids * sizeof(*t->stid_tab) + t->nstids * sizeof(*t->stid_tab) +
t->nsftids * sizeof(*t->stid_tab) + t->nsftids * sizeof(*t->stid_tab) +
stid_bmap_size * sizeof(long) + stid_bmap_size * sizeof(long) +
t->nhpftids * sizeof(*t->hpftid_tab) +
hpftid_bmap_size * sizeof(long) +
max_ftids * sizeof(*t->ftid_tab) + max_ftids * sizeof(*t->ftid_tab) +
ftid_bmap_size * sizeof(long) + ftid_bmap_size * sizeof(long) +
t->neotids * sizeof(*t->eotid_tab) + t->neotids * sizeof(*t->eotid_tab) +
...@@ -1543,7 +1567,9 @@ static int tid_init(struct tid_info *t) ...@@ -1543,7 +1567,9 @@ static int tid_init(struct tid_info *t)
t->atid_tab = (union aopen_entry *)&t->tid_tab[t->ntids]; t->atid_tab = (union aopen_entry *)&t->tid_tab[t->ntids];
t->stid_tab = (struct serv_entry *)&t->atid_tab[natids]; t->stid_tab = (struct serv_entry *)&t->atid_tab[natids];
t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids + t->nsftids]; t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids + t->nsftids];
t->ftid_tab = (struct filter_entry *)&t->stid_bmap[stid_bmap_size]; t->hpftid_tab = (struct filter_entry *)&t->stid_bmap[stid_bmap_size];
t->hpftid_bmap = (unsigned long *)&t->hpftid_tab[t->nhpftids];
t->ftid_tab = (struct filter_entry *)&t->hpftid_bmap[hpftid_bmap_size];
t->ftid_bmap = (unsigned long *)&t->ftid_tab[max_ftids]; t->ftid_bmap = (unsigned long *)&t->ftid_tab[max_ftids];
t->eotid_tab = (struct eotid_entry *)&t->ftid_bmap[ftid_bmap_size]; t->eotid_tab = (struct eotid_entry *)&t->ftid_bmap[ftid_bmap_size];
t->eotid_bmap = (unsigned long *)&t->eotid_tab[t->neotids]; t->eotid_bmap = (unsigned long *)&t->eotid_tab[t->neotids];
...@@ -1578,6 +1604,8 @@ static int tid_init(struct tid_info *t) ...@@ -1578,6 +1604,8 @@ static int tid_init(struct tid_info *t)
bitmap_zero(t->eotid_bmap, t->neotids); bitmap_zero(t->eotid_bmap, t->neotids);
} }
if (t->nhpftids)
bitmap_zero(t->hpftid_bmap, t->nhpftids);
bitmap_zero(t->ftid_bmap, t->nftids); bitmap_zero(t->ftid_bmap, t->nftids);
return 0; return 0;
} }
...@@ -4351,6 +4379,7 @@ static int adap_init0_config(struct adapter *adapter, int reset) ...@@ -4351,6 +4379,7 @@ static int adap_init0_config(struct adapter *adapter, int reset)
"HMA configuration failed with error %d\n", ret); "HMA configuration failed with error %d\n", ret);
if (is_t6(adapter->params.chip)) { if (is_t6(adapter->params.chip)) {
adap_config_hpfilter(adapter);
ret = setup_ppod_edram(adapter); ret = setup_ppod_edram(adapter);
if (!ret) if (!ret)
dev_info(adapter->pdev_dev, "Successfully enabled " dev_info(adapter->pdev_dev, "Successfully enabled "
...@@ -4660,16 +4689,6 @@ static int adap_init0(struct adapter *adap, int vpd_skip) ...@@ -4660,16 +4689,6 @@ static int adap_init0(struct adapter *adap, int vpd_skip)
/* /*
* Grab some of our basic fundamental operating parameters. * Grab some of our basic fundamental operating parameters.
*/ */
#define FW_PARAM_DEV(param) \
(FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | \
FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_##param))
#define FW_PARAM_PFVF(param) \
FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_PFVF) | \
FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_PFVF_##param)| \
FW_PARAMS_PARAM_Y_V(0) | \
FW_PARAMS_PARAM_Z_V(0)
params[0] = FW_PARAM_PFVF(EQ_START); params[0] = FW_PARAM_PFVF(EQ_START);
params[1] = FW_PARAM_PFVF(L2T_START); params[1] = FW_PARAM_PFVF(L2T_START);
params[2] = FW_PARAM_PFVF(L2T_END); params[2] = FW_PARAM_PFVF(L2T_END);
...@@ -4687,6 +4706,16 @@ static int adap_init0(struct adapter *adap, int vpd_skip) ...@@ -4687,6 +4706,16 @@ static int adap_init0(struct adapter *adap, int vpd_skip)
adap->sge.ingr_start = val[5]; adap->sge.ingr_start = val[5];
if (CHELSIO_CHIP_VERSION(adap->params.chip) > CHELSIO_T5) { if (CHELSIO_CHIP_VERSION(adap->params.chip) > CHELSIO_T5) {
params[0] = FW_PARAM_PFVF(HPFILTER_START);
params[1] = FW_PARAM_PFVF(HPFILTER_END);
ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 2,
params, val);
if (ret < 0)
goto bye;
adap->tids.hpftid_base = val[0];
adap->tids.nhpftids = val[1] - val[0] + 1;
/* Read the raw mps entries. In T6, the last 2 tcam entries /* Read the raw mps entries. In T6, the last 2 tcam entries
* are reserved for raw mac addresses (rawf = 2, one per port). * are reserved for raw mac addresses (rawf = 2, one per port).
*/ */
...@@ -5050,8 +5079,6 @@ static int adap_init0(struct adapter *adap, int vpd_skip) ...@@ -5050,8 +5079,6 @@ static int adap_init0(struct adapter *adap, int vpd_skip)
} }
adap->params.crypto = ntohs(caps_cmd.cryptocaps); adap->params.crypto = ntohs(caps_cmd.cryptocaps);
} }
#undef FW_PARAM_PFVF
#undef FW_PARAM_DEV
/* The MTU/MSS Table is initialized by now, so load their values. If /* The MTU/MSS Table is initialized by now, so load their values. If
* we're initializing the adapter, then we'll make any modifications * we're initializing the adapter, then we'll make any modifications
......
...@@ -672,10 +672,13 @@ int cxgb4_tc_flower_replace(struct net_device *dev, ...@@ -672,10 +672,13 @@ int cxgb4_tc_flower_replace(struct net_device *dev,
* 0 to driver. However, the hardware TCAM index * 0 to driver. However, the hardware TCAM index
* starts from 0. Hence, the -1 here. * starts from 0. Hence, the -1 here.
*/ */
if (cls->common.prio <= adap->tids.nftids) if (cls->common.prio <= adap->tids.nftids) {
fidx = cls->common.prio - 1; fidx = cls->common.prio - 1;
else if (fidx < adap->tids.nhpftids)
fs->prio = 1;
} else {
fidx = cxgb4_get_free_ftid(dev, inet_family); fidx = cxgb4_get_free_ftid(dev, inet_family);
}
/* Only insert FLOWER rule if its priority doesn't /* Only insert FLOWER rule if its priority doesn't
* conflict with existing rules in the LETCAM. * conflict with existing rules in the LETCAM.
......
...@@ -156,6 +156,8 @@ static int cxgb4_matchall_alloc_filter(struct net_device *dev, ...@@ -156,6 +156,8 @@ static int cxgb4_matchall_alloc_filter(struct net_device *dev,
fs = &tc_port_matchall->ingress.fs; fs = &tc_port_matchall->ingress.fs;
memset(fs, 0, sizeof(*fs)); memset(fs, 0, sizeof(*fs));
if (fidx < adap->tids.nhpftids)
fs->prio = 1;
fs->tc_prio = cls->common.prio; fs->tc_prio = cls->common.prio;
fs->tc_cookie = cls->cookie; fs->tc_cookie = cls->cookie;
fs->hitcnts = 1; fs->hitcnts = 1;
......
...@@ -176,7 +176,7 @@ int cxgb4_config_knode(struct net_device *dev, struct tc_cls_u32_offload *cls) ...@@ -176,7 +176,7 @@ int cxgb4_config_knode(struct net_device *dev, struct tc_cls_u32_offload *cls)
/* Only insert U32 rule if its priority doesn't conflict with /* Only insert U32 rule if its priority doesn't conflict with
* existing rules in the LETCAM. * existing rules in the LETCAM.
*/ */
if (filter_id >= adapter->tids.nftids || if (filter_id >= adapter->tids.nftids + adapter->tids.nhpftids ||
!cxgb4_filter_prio_in_range(dev, filter_id, cls->common.prio)) { !cxgb4_filter_prio_in_range(dev, filter_id, cls->common.prio)) {
NL_SET_ERR_MSG_MOD(extack, NL_SET_ERR_MSG_MOD(extack,
"No free LETCAM index available"); "No free LETCAM index available");
...@@ -199,6 +199,8 @@ int cxgb4_config_knode(struct net_device *dev, struct tc_cls_u32_offload *cls) ...@@ -199,6 +199,8 @@ int cxgb4_config_knode(struct net_device *dev, struct tc_cls_u32_offload *cls)
memset(&fs, 0, sizeof(fs)); memset(&fs, 0, sizeof(fs));
if (filter_id < adapter->tids.nhpftids)
fs.prio = 1;
fs.tc_prio = cls->common.prio; fs.tc_prio = cls->common.prio;
fs.tc_cookie = cls->knode.handle; fs.tc_cookie = cls->knode.handle;
...@@ -355,6 +357,7 @@ int cxgb4_delete_knode(struct net_device *dev, struct tc_cls_u32_offload *cls) ...@@ -355,6 +357,7 @@ int cxgb4_delete_knode(struct net_device *dev, struct tc_cls_u32_offload *cls)
unsigned int filter_id, max_tids, i, j; unsigned int filter_id, max_tids, i, j;
struct cxgb4_link *link = NULL; struct cxgb4_link *link = NULL;
struct cxgb4_tc_u32_table *t; struct cxgb4_tc_u32_table *t;
struct filter_entry *f;
u32 handle, uhtid; u32 handle, uhtid;
int ret; int ret;
...@@ -363,8 +366,15 @@ int cxgb4_delete_knode(struct net_device *dev, struct tc_cls_u32_offload *cls) ...@@ -363,8 +366,15 @@ int cxgb4_delete_knode(struct net_device *dev, struct tc_cls_u32_offload *cls)
/* Fetch the location to delete the filter. */ /* Fetch the location to delete the filter. */
filter_id = TC_U32_NODE(cls->knode.handle) - 1; filter_id = TC_U32_NODE(cls->knode.handle) - 1;
if (filter_id >= adapter->tids.nftids || if (filter_id >= adapter->tids.nftids + adapter->tids.nhpftids)
cls->knode.handle != adapter->tids.ftid_tab[filter_id].fs.tc_cookie) return -ERANGE;
if (filter_id < adapter->tids.nhpftids)
f = &adapter->tids.hpftid_tab[filter_id];
else
f = &adapter->tids.ftid_tab[filter_id - adapter->tids.nhpftids];
if (cls->knode.handle != f->fs.tc_cookie)
return -ERANGE; return -ERANGE;
t = adapter->tc_u32; t = adapter->tc_u32;
...@@ -445,7 +455,7 @@ void cxgb4_cleanup_tc_u32(struct adapter *adap) ...@@ -445,7 +455,7 @@ void cxgb4_cleanup_tc_u32(struct adapter *adap)
struct cxgb4_tc_u32_table *cxgb4_init_tc_u32(struct adapter *adap) struct cxgb4_tc_u32_table *cxgb4_init_tc_u32(struct adapter *adap)
{ {
unsigned int max_tids = adap->tids.nftids; unsigned int max_tids = adap->tids.nftids + adap->tids.nhpftids;
struct cxgb4_tc_u32_table *t; struct cxgb4_tc_u32_table *t;
unsigned int i; unsigned int i;
......
...@@ -111,6 +111,11 @@ struct tid_info { ...@@ -111,6 +111,11 @@ struct tid_info {
unsigned int natids; unsigned int natids;
unsigned int atid_base; unsigned int atid_base;
struct filter_entry *hpftid_tab;
unsigned long *hpftid_bmap;
unsigned int nhpftids;
unsigned int hpftid_base;
struct filter_entry *ftid_tab; struct filter_entry *ftid_tab;
unsigned long *ftid_bmap; unsigned long *ftid_bmap;
unsigned int nftids; unsigned int nftids;
......
...@@ -1321,6 +1321,7 @@ enum fw_params_param_dev { ...@@ -1321,6 +1321,7 @@ enum fw_params_param_dev {
FW_PARAMS_PARAM_DEV_RDMA_WRITE_WITH_IMM = 0x21, FW_PARAMS_PARAM_DEV_RDMA_WRITE_WITH_IMM = 0x21,
FW_PARAMS_PARAM_DEV_PPOD_EDRAM = 0x23, FW_PARAMS_PARAM_DEV_PPOD_EDRAM = 0x23,
FW_PARAMS_PARAM_DEV_RI_WRITE_CMPL_WR = 0x24, FW_PARAMS_PARAM_DEV_RI_WRITE_CMPL_WR = 0x24,
FW_PARAMS_PARAM_DEV_HPFILTER_REGION_SUPPORT = 0x26,
FW_PARAMS_PARAM_DEV_OPAQUE_VIID_SMT_EXTN = 0x27, FW_PARAMS_PARAM_DEV_OPAQUE_VIID_SMT_EXTN = 0x27,
FW_PARAMS_PARAM_DEV_HASHFILTER_WITH_OFLD = 0x28, FW_PARAMS_PARAM_DEV_HASHFILTER_WITH_OFLD = 0x28,
FW_PARAMS_PARAM_DEV_DBQ_TIMER = 0x29, FW_PARAMS_PARAM_DEV_DBQ_TIMER = 0x29,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册