|
@@ -265,6 +265,8 @@ static int validate_filter(struct net_device *dev,
|
|
|
fs->mask.pfvf_vld) ||
|
|
|
unsupported(fconf, VNIC_ID_F, fs->val.ovlan_vld,
|
|
|
fs->mask.ovlan_vld) ||
|
|
|
+ unsupported(fconf, VNIC_ID_F, fs->val.encap_vld,
|
|
|
+ fs->mask.encap_vld) ||
|
|
|
unsupported(fconf, VLAN_F, fs->val.ivlan_vld, fs->mask.ivlan_vld))
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
@@ -275,8 +277,12 @@ static int validate_filter(struct net_device *dev,
|
|
|
* carries that overlap, we need to translate any PF/VF
|
|
|
* specification into that internal format below.
|
|
|
*/
|
|
|
- if (is_field_set(fs->val.pfvf_vld, fs->mask.pfvf_vld) &&
|
|
|
- is_field_set(fs->val.ovlan_vld, fs->mask.ovlan_vld))
|
|
|
+ if ((is_field_set(fs->val.pfvf_vld, fs->mask.pfvf_vld) &&
|
|
|
+ is_field_set(fs->val.ovlan_vld, fs->mask.ovlan_vld)) ||
|
|
|
+ (is_field_set(fs->val.pfvf_vld, fs->mask.pfvf_vld) &&
|
|
|
+ is_field_set(fs->val.encap_vld, fs->mask.encap_vld)) ||
|
|
|
+ (is_field_set(fs->val.ovlan_vld, fs->mask.ovlan_vld) &&
|
|
|
+ is_field_set(fs->val.encap_vld, fs->mask.encap_vld)))
|
|
|
return -EOPNOTSUPP;
|
|
|
if (unsupported(iconf, VNIC_F, fs->val.pfvf_vld, fs->mask.pfvf_vld) ||
|
|
|
(is_field_set(fs->val.ovlan_vld, fs->mask.ovlan_vld) &&
|
|
@@ -306,6 +312,9 @@ static int validate_filter(struct net_device *dev,
|
|
|
fs->newvlan == VLAN_REWRITE))
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
+ if (fs->val.encap_vld &&
|
|
|
+ CHELSIO_CHIP_VERSION(adapter->params.chip) < CHELSIO_T6)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -705,6 +714,8 @@ int delete_filter(struct adapter *adapter, unsigned int fidx)
|
|
|
*/
|
|
|
void clear_filter(struct adapter *adap, struct filter_entry *f)
|
|
|
{
|
|
|
+ struct port_info *pi = netdev_priv(f->dev);
|
|
|
+
|
|
|
/* If the new or old filter have loopback rewriteing rules then we'll
|
|
|
* need to free any existing L2T, SMT, CLIP entries of filter
|
|
|
* rule.
|
|
@@ -715,6 +726,12 @@ void clear_filter(struct adapter *adap, struct filter_entry *f)
|
|
|
if (f->smt)
|
|
|
cxgb4_smt_release(f->smt);
|
|
|
|
|
|
+ if (f->fs.val.encap_vld && f->fs.val.ovlan_vld)
|
|
|
+ if (atomic_dec_and_test(&adap->mps_encap[f->fs.val.ovlan &
|
|
|
+ 0x1ff].refcnt))
|
|
|
+ t4_free_encap_mac_filt(adap, pi->viid,
|
|
|
+ f->fs.val.ovlan & 0x1ff, 0);
|
|
|
+
|
|
|
if ((f->fs.hash || is_t6(adap->params.chip)) && f->fs.type)
|
|
|
cxgb4_clip_release(f->dev, (const u32 *)&f->fs.val.lip, 1);
|
|
|
|
|
@@ -840,6 +857,10 @@ bool is_filter_exact_match(struct adapter *adap,
|
|
|
if (!is_hashfilter(adap))
|
|
|
return false;
|
|
|
|
|
|
+ /* Keep tunnel VNI match disabled for hash-filters for now */
|
|
|
+ if (fs->mask.encap_vld)
|
|
|
+ return false;
|
|
|
+
|
|
|
if (fs->type) {
|
|
|
if (is_inaddr_any(fs->val.fip, AF_INET6) ||
|
|
|
!is_addr_all_mask(fs->mask.fip, AF_INET6))
|
|
@@ -961,8 +982,12 @@ static u64 hash_filter_ntuple(struct ch_filter_specification *fs,
|
|
|
ntuple |= (u64)(fs->val.tos) << tp->tos_shift;
|
|
|
|
|
|
if (tp->vnic_shift >= 0) {
|
|
|
- if ((adap->params.tp.ingress_config & VNIC_F) &&
|
|
|
- fs->mask.pfvf_vld)
|
|
|
+ if ((adap->params.tp.ingress_config & USE_ENC_IDX_F) &&
|
|
|
+ fs->mask.encap_vld)
|
|
|
+ ntuple |= (u64)((fs->val.encap_vld << 16) |
|
|
|
+ (fs->val.ovlan)) << tp->vnic_shift;
|
|
|
+ else if ((adap->params.tp.ingress_config & VNIC_F) &&
|
|
|
+ fs->mask.pfvf_vld)
|
|
|
ntuple |= (u64)((fs->val.pfvf_vld << 16) |
|
|
|
(fs->val.pf << 13) |
|
|
|
(fs->val.vf)) << tp->vnic_shift;
|
|
@@ -1076,6 +1101,7 @@ static int cxgb4_set_hash_filter(struct net_device *dev,
|
|
|
struct filter_ctx *ctx)
|
|
|
{
|
|
|
struct adapter *adapter = netdev2adap(dev);
|
|
|
+ struct port_info *pi = netdev_priv(dev);
|
|
|
struct tid_info *t = &adapter->tids;
|
|
|
struct filter_entry *f;
|
|
|
struct sk_buff *skb;
|
|
@@ -1142,13 +1168,34 @@ static int cxgb4_set_hash_filter(struct net_device *dev,
|
|
|
f->fs.mask.ovlan = (fs->mask.pf << 13) | fs->mask.vf;
|
|
|
f->fs.val.ovlan_vld = fs->val.pfvf_vld;
|
|
|
f->fs.mask.ovlan_vld = fs->mask.pfvf_vld;
|
|
|
+ } else if (iconf & USE_ENC_IDX_F) {
|
|
|
+ if (f->fs.val.encap_vld) {
|
|
|
+ struct port_info *pi = netdev_priv(f->dev);
|
|
|
+ u8 match_all_mac[] = { 0, 0, 0, 0, 0, 0 };
|
|
|
+
|
|
|
+ /* allocate MPS TCAM entry */
|
|
|
+ ret = t4_alloc_encap_mac_filt(adapter, pi->viid,
|
|
|
+ match_all_mac,
|
|
|
+ match_all_mac,
|
|
|
+ f->fs.val.vni,
|
|
|
+ f->fs.mask.vni,
|
|
|
+ 0, 1, 1);
|
|
|
+ if (ret < 0)
|
|
|
+ goto free_atid;
|
|
|
+
|
|
|
+ atomic_inc(&adapter->mps_encap[ret].refcnt);
|
|
|
+ f->fs.val.ovlan = ret;
|
|
|
+ f->fs.mask.ovlan = 0xffff;
|
|
|
+ f->fs.val.ovlan_vld = 1;
|
|
|
+ f->fs.mask.ovlan_vld = 1;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
size = sizeof(struct cpl_t6_act_open_req);
|
|
|
if (f->fs.type) {
|
|
|
ret = cxgb4_clip_get(f->dev, (const u32 *)&f->fs.val.lip, 1);
|
|
|
if (ret)
|
|
|
- goto free_atid;
|
|
|
+ goto free_mps;
|
|
|
|
|
|
skb = alloc_skb(size, GFP_KERNEL);
|
|
|
if (!skb) {
|
|
@@ -1163,7 +1210,7 @@ static int cxgb4_set_hash_filter(struct net_device *dev,
|
|
|
skb = alloc_skb(size, GFP_KERNEL);
|
|
|
if (!skb) {
|
|
|
ret = -ENOMEM;
|
|
|
- goto free_atid;
|
|
|
+ goto free_mps;
|
|
|
}
|
|
|
|
|
|
mk_act_open_req(f, skb,
|
|
@@ -1179,6 +1226,10 @@ static int cxgb4_set_hash_filter(struct net_device *dev,
|
|
|
free_clip:
|
|
|
cxgb4_clip_release(f->dev, (const u32 *)&f->fs.val.lip, 1);
|
|
|
|
|
|
+free_mps:
|
|
|
+ if (f->fs.val.encap_vld && f->fs.val.ovlan_vld)
|
|
|
+ t4_free_encap_mac_filt(adapter, pi->viid, f->fs.val.ovlan, 1);
|
|
|
+
|
|
|
free_atid:
|
|
|
cxgb4_free_atid(t, atid);
|
|
|
|
|
@@ -1360,6 +1411,27 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id,
|
|
|
f->fs.mask.ovlan = (fs->mask.pf << 13) | fs->mask.vf;
|
|
|
f->fs.val.ovlan_vld = fs->val.pfvf_vld;
|
|
|
f->fs.mask.ovlan_vld = fs->mask.pfvf_vld;
|
|
|
+ } else if (iconf & USE_ENC_IDX_F) {
|
|
|
+ if (f->fs.val.encap_vld) {
|
|
|
+ struct port_info *pi = netdev_priv(f->dev);
|
|
|
+ u8 match_all_mac[] = { 0, 0, 0, 0, 0, 0 };
|
|
|
+
|
|
|
+ /* allocate MPS TCAM entry */
|
|
|
+ ret = t4_alloc_encap_mac_filt(adapter, pi->viid,
|
|
|
+ match_all_mac,
|
|
|
+ match_all_mac,
|
|
|
+ f->fs.val.vni,
|
|
|
+ f->fs.mask.vni,
|
|
|
+ 0, 1, 1);
|
|
|
+ if (ret < 0)
|
|
|
+ goto free_clip;
|
|
|
+
|
|
|
+ atomic_inc(&adapter->mps_encap[ret].refcnt);
|
|
|
+ f->fs.val.ovlan = ret;
|
|
|
+ f->fs.mask.ovlan = 0x1ff;
|
|
|
+ f->fs.val.ovlan_vld = 1;
|
|
|
+ f->fs.mask.ovlan_vld = 1;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* Attempt to set the filter. If we don't succeed, we clear
|
|
@@ -1376,6 +1448,13 @@ int __cxgb4_set_filter(struct net_device *dev, int filter_id,
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
|
+
|
|
|
+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;
|
|
|
}
|
|
|
|
|
|
static int cxgb4_del_hash_filter(struct net_device *dev, int filter_id,
|