Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'bnxt_en-ntuple-and-rss-updates'

Michael Chan says:

====================
bnxt_en: Ntuple and RSS updates

This patch series adds more ntuple and RSS features following recent
patches to add support for user configured ntuple filters. Additional
features include L2 ether filters, partial tuple masks, IP filters
besides TCP/UDP, drop action, saving and re-applying user filters
after driver reset, user configured RSS key, and RSS for IPSEC.
====================

Link: https://lore.kernel.org/r/20240205223202.25341-1-michael.chan@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+580 -211
+261 -85
drivers/net/ethernet/broadcom/bnxt/bnxt.c
··· 246 246 247 247 static struct workqueue_struct *bnxt_pf_wq; 248 248 249 + #define BNXT_IPV6_MASK_ALL {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 250 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}} 251 + #define BNXT_IPV6_MASK_NONE {{{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}} 252 + 253 + const struct bnxt_flow_masks BNXT_FLOW_MASK_NONE = { 254 + .ports = { 255 + .src = 0, 256 + .dst = 0, 257 + }, 258 + .addrs = { 259 + .v6addrs = { 260 + .src = BNXT_IPV6_MASK_NONE, 261 + .dst = BNXT_IPV6_MASK_NONE, 262 + }, 263 + }, 264 + }; 265 + 266 + const struct bnxt_flow_masks BNXT_FLOW_IPV6_MASK_ALL = { 267 + .ports = { 268 + .src = cpu_to_be16(0xffff), 269 + .dst = cpu_to_be16(0xffff), 270 + }, 271 + .addrs = { 272 + .v6addrs = { 273 + .src = BNXT_IPV6_MASK_ALL, 274 + .dst = BNXT_IPV6_MASK_ALL, 275 + }, 276 + }, 277 + }; 278 + 279 + const struct bnxt_flow_masks BNXT_FLOW_IPV4_MASK_ALL = { 280 + .ports = { 281 + .src = cpu_to_be16(0xffff), 282 + .dst = cpu_to_be16(0xffff), 283 + }, 284 + .addrs = { 285 + .v4addrs = { 286 + .src = cpu_to_be32(0xffffffff), 287 + .dst = cpu_to_be32(0xffffffff), 288 + }, 289 + }, 290 + }; 291 + 249 292 static bool bnxt_vf_pciid(enum board_idx idx) 250 293 { 251 294 return (idx == NETXTREME_C_VF || idx == NETXTREME_E_VF || ··· 4246 4203 u8 *key = (void *)vnic->rss_hash_key; 4247 4204 int k; 4248 4205 4206 + if (!bp->rss_hash_key_valid && 4207 + !bp->rss_hash_key_updated) { 4208 + get_random_bytes(bp->rss_hash_key, 4209 + HW_HASH_KEY_SIZE); 4210 + bp->rss_hash_key_updated = true; 4211 + } 4212 + 4213 + memcpy(vnic->rss_hash_key, bp->rss_hash_key, 4214 + HW_HASH_KEY_SIZE); 4215 + 4216 + if (!bp->rss_hash_key_updated) 4217 + continue; 4218 + 4219 + bp->rss_hash_key_updated = false; 4220 + bp->rss_hash_key_valid = true; 4221 + 4249 4222 bp->toeplitz_prefix = 0; 4250 - get_random_bytes(vnic->rss_hash_key, 4251 - HW_HASH_KEY_SIZE); 4252 4223 for (k = 0; k < 8; k++) { 4253 4224 bp->toeplitz_prefix <<= 8; 4254 4225 bp->toeplitz_prefix |= key[k]; ··· 4855 4798 } 4856 4799 } 4857 4800 4801 + void bnxt_insert_usr_fltr(struct bnxt *bp, struct bnxt_filter_base *fltr) 4802 + { 4803 + u8 type = fltr->type, flags = fltr->flags; 4804 + 4805 + INIT_LIST_HEAD(&fltr->list); 4806 + if ((type == BNXT_FLTR_TYPE_L2 && flags & BNXT_ACT_RING_DST) || 4807 + (type == BNXT_FLTR_TYPE_NTUPLE && flags & BNXT_ACT_NO_AGING)) 4808 + list_add_tail(&fltr->list, &bp->usr_fltr_list); 4809 + } 4810 + 4811 + void bnxt_del_one_usr_fltr(struct bnxt *bp, struct bnxt_filter_base *fltr) 4812 + { 4813 + if (!list_empty(&fltr->list)) 4814 + list_del_init(&fltr->list); 4815 + } 4816 + 4817 + void bnxt_clear_usr_fltrs(struct bnxt *bp, bool all) 4818 + { 4819 + struct bnxt_filter_base *usr_fltr, *tmp; 4820 + 4821 + list_for_each_entry_safe(usr_fltr, tmp, &bp->usr_fltr_list, list) { 4822 + if (!all && usr_fltr->type == BNXT_FLTR_TYPE_L2) 4823 + continue; 4824 + bnxt_del_one_usr_fltr(bp, usr_fltr); 4825 + } 4826 + } 4827 + 4828 + static void bnxt_del_fltr(struct bnxt *bp, struct bnxt_filter_base *fltr) 4829 + { 4830 + hlist_del(&fltr->hash); 4831 + bnxt_del_one_usr_fltr(bp, fltr); 4832 + if (fltr->flags) { 4833 + clear_bit(fltr->sw_id, bp->ntp_fltr_bmap); 4834 + bp->ntp_fltr_count--; 4835 + } 4836 + kfree(fltr); 4837 + } 4838 + 4858 4839 static void bnxt_free_ntp_fltrs(struct bnxt *bp, bool all) 4859 4840 { 4860 4841 int i; ··· 4908 4813 head = &bp->ntp_fltr_hash_tbl[i]; 4909 4814 hlist_for_each_entry_safe(fltr, tmp, head, base.hash) { 4910 4815 bnxt_del_l2_filter(bp, fltr->l2_fltr); 4911 - if (!all && (fltr->base.flags & BNXT_ACT_FUNC_DST)) 4816 + if (!all && ((fltr->base.flags & BNXT_ACT_FUNC_DST) || 4817 + !list_empty(&fltr->base.list))) 4912 4818 continue; 4913 - hlist_del(&fltr->base.hash); 4914 - clear_bit(fltr->base.sw_id, bp->ntp_fltr_bmap); 4915 - bp->ntp_fltr_count--; 4916 - kfree(fltr); 4819 + bnxt_del_fltr(bp, &fltr->base); 4917 4820 } 4918 4821 } 4919 4822 if (!all) ··· 4933 4840 INIT_HLIST_HEAD(&bp->ntp_fltr_hash_tbl[i]); 4934 4841 4935 4842 bp->ntp_fltr_count = 0; 4936 - bp->ntp_fltr_bmap = bitmap_zalloc(BNXT_MAX_FLTR, GFP_KERNEL); 4843 + bp->ntp_fltr_bmap = bitmap_zalloc(bp->max_fltr, GFP_KERNEL); 4937 4844 4938 4845 if (!bp->ntp_fltr_bmap) 4939 4846 rc = -ENOMEM; ··· 4952 4859 4953 4860 head = &bp->l2_fltr_hash_tbl[i]; 4954 4861 hlist_for_each_entry_safe(fltr, tmp, head, base.hash) { 4955 - if (!all && (fltr->base.flags & BNXT_ACT_FUNC_DST)) 4862 + if (!all && ((fltr->base.flags & BNXT_ACT_FUNC_DST) || 4863 + !list_empty(&fltr->base.list))) 4956 4864 continue; 4957 - hlist_del(&fltr->base.hash); 4958 - if (fltr->base.flags) { 4959 - clear_bit(fltr->base.sw_id, bp->ntp_fltr_bmap); 4960 - bp->ntp_fltr_count--; 4961 - } 4962 - kfree(fltr); 4865 + bnxt_del_fltr(bp, &fltr->base); 4963 4866 } 4964 4867 } 4965 4868 } ··· 5431 5342 return; 5432 5343 } 5433 5344 hlist_del_rcu(&fltr->base.hash); 5345 + bnxt_del_one_usr_fltr(bp, &fltr->base); 5434 5346 if (fltr->base.flags) { 5435 5347 clear_bit(fltr->base.sw_id, bp->ntp_fltr_bmap); 5436 5348 bp->ntp_fltr_count--; ··· 5570 5480 int bit_id; 5571 5481 5572 5482 bit_id = bitmap_find_free_region(bp->ntp_fltr_bmap, 5573 - BNXT_MAX_FLTR, 0); 5483 + bp->max_fltr, 0); 5574 5484 if (bit_id < 0) 5575 5485 return -ENOMEM; 5576 5486 fltr->base.sw_id = (u16)bit_id; 5487 + bp->ntp_fltr_count++; 5577 5488 } 5578 5489 head = &bp->l2_fltr_hash_tbl[idx]; 5579 5490 hlist_add_head_rcu(&fltr->base.hash, head); 5491 + bnxt_insert_usr_fltr(bp, &fltr->base); 5580 5492 set_bit(BNXT_FLTR_INSERTED, &fltr->base.state); 5581 5493 atomic_set(&fltr->refcnt, 1); 5582 5494 return 0; ··· 5608 5516 bnxt_del_l2_filter(bp, fltr); 5609 5517 fltr = ERR_PTR(rc); 5610 5518 } 5519 + return fltr; 5520 + } 5521 + 5522 + struct bnxt_l2_filter *bnxt_alloc_new_l2_filter(struct bnxt *bp, 5523 + struct bnxt_l2_key *key, 5524 + u16 flags) 5525 + { 5526 + struct bnxt_l2_filter *fltr; 5527 + u32 idx; 5528 + int rc; 5529 + 5530 + idx = jhash2(&key->filter_key, BNXT_L2_KEY_SIZE, bp->hash_seed) & 5531 + BNXT_L2_FLTR_HASH_MASK; 5532 + spin_lock_bh(&bp->ntp_fltr_lock); 5533 + fltr = __bnxt_lookup_l2_filter(bp, key, idx); 5534 + if (fltr) { 5535 + fltr = ERR_PTR(-EEXIST); 5536 + goto l2_filter_exit; 5537 + } 5538 + fltr = kzalloc(sizeof(*fltr), GFP_ATOMIC); 5539 + if (!fltr) { 5540 + fltr = ERR_PTR(-ENOMEM); 5541 + goto l2_filter_exit; 5542 + } 5543 + fltr->base.flags = flags; 5544 + rc = bnxt_init_l2_filter(bp, fltr, key, idx); 5545 + if (rc) { 5546 + spin_unlock_bh(&bp->ntp_fltr_lock); 5547 + bnxt_del_l2_filter(bp, fltr); 5548 + return ERR_PTR(rc); 5549 + } 5550 + 5551 + l2_filter_exit: 5552 + spin_unlock_bh(&bp->ntp_fltr_lock); 5611 5553 return fltr; 5612 5554 } 5613 5555 ··· 5781 5655 { 5782 5656 struct hwrm_cfa_ntuple_filter_alloc_output *resp; 5783 5657 struct hwrm_cfa_ntuple_filter_alloc_input *req; 5658 + struct bnxt_flow_masks *masks = &fltr->fmasks; 5784 5659 struct flow_keys *keys = &fltr->fkeys; 5785 5660 struct bnxt_l2_filter *l2_fltr; 5786 5661 struct bnxt_vnic_info *vnic; ··· 5795 5668 l2_fltr = fltr->l2_fltr; 5796 5669 req->l2_filter_id = l2_fltr->base.filter_id; 5797 5670 5798 - 5799 - if (bp->fw_cap & BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX_V2) { 5671 + if (fltr->base.flags & BNXT_ACT_DROP) { 5672 + flags = CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_DROP; 5673 + } else if (bp->fw_cap & BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX_V2) { 5800 5674 flags = CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_DEST_RFS_RING_IDX; 5801 5675 req->dst_id = cpu_to_le16(fltr->base.rxq); 5802 5676 } else { ··· 5815 5687 req->ethertype = htons(ETH_P_IPV6); 5816 5688 req->ip_addr_type = 5817 5689 CFA_NTUPLE_FILTER_ALLOC_REQ_IP_ADDR_TYPE_IPV6; 5818 - if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_SRC_IP) { 5819 - *(struct in6_addr *)&req->src_ipaddr[0] = 5820 - keys->addrs.v6addrs.src; 5821 - bnxt_fill_ipv6_mask(req->src_ipaddr_mask); 5822 - } 5823 - if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_DST_IP) { 5824 - *(struct in6_addr *)&req->dst_ipaddr[0] = 5825 - keys->addrs.v6addrs.dst; 5826 - bnxt_fill_ipv6_mask(req->dst_ipaddr_mask); 5827 - } 5690 + *(struct in6_addr *)&req->src_ipaddr[0] = keys->addrs.v6addrs.src; 5691 + *(struct in6_addr *)&req->src_ipaddr_mask[0] = masks->addrs.v6addrs.src; 5692 + *(struct in6_addr *)&req->dst_ipaddr[0] = keys->addrs.v6addrs.dst; 5693 + *(struct in6_addr *)&req->dst_ipaddr_mask[0] = masks->addrs.v6addrs.dst; 5828 5694 } else { 5829 - if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_SRC_IP) { 5830 - req->src_ipaddr[0] = keys->addrs.v4addrs.src; 5831 - req->src_ipaddr_mask[0] = cpu_to_be32(0xffffffff); 5832 - } 5833 - if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_DST_IP) { 5834 - req->dst_ipaddr[0] = keys->addrs.v4addrs.dst; 5835 - req->dst_ipaddr_mask[0] = cpu_to_be32(0xffffffff); 5836 - } 5695 + req->src_ipaddr[0] = keys->addrs.v4addrs.src; 5696 + req->src_ipaddr_mask[0] = masks->addrs.v4addrs.src; 5697 + req->dst_ipaddr[0] = keys->addrs.v4addrs.dst; 5698 + req->dst_ipaddr_mask[0] = masks->addrs.v4addrs.dst; 5837 5699 } 5838 5700 if (keys->control.flags & FLOW_DIS_ENCAPSULATION) { 5839 5701 req->enables |= cpu_to_le32(BNXT_NTP_TUNNEL_FLTR_FLAG); ··· 5831 5713 CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_ANYTUNNEL; 5832 5714 } 5833 5715 5834 - if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_SRC_PORT) { 5835 - req->src_port = keys->ports.src; 5836 - req->src_port_mask = cpu_to_be16(0xffff); 5837 - } 5838 - if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_DST_PORT) { 5839 - req->dst_port = keys->ports.dst; 5840 - req->dst_port_mask = cpu_to_be16(0xffff); 5841 - } 5716 + req->src_port = keys->ports.src; 5717 + req->src_port_mask = masks->ports.src; 5718 + req->dst_port = keys->ports.dst; 5719 + req->dst_port_mask = masks->ports.dst; 5842 5720 5843 5721 resp = hwrm_req_hold(bp, req); 5844 5722 rc = hwrm_req_send(bp, req); ··· 6099 5985 __bnxt_hwrm_vnic_set_rss(struct bnxt *bp, struct hwrm_vnic_rss_cfg_input *req, 6100 5986 struct bnxt_vnic_info *vnic) 6101 5987 { 6102 - if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) 5988 + if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) { 6103 5989 bnxt_fill_hw_rss_tbl_p5(bp, vnic); 6104 - else 5990 + if (bp->flags & BNXT_FLAG_CHIP_P7) 5991 + req->flags |= VNIC_RSS_CFG_REQ_FLAGS_IPSEC_HASH_TYPE_CFG_SUPPORT; 5992 + } else { 6105 5993 bnxt_fill_hw_rss_tbl(bp, vnic); 5994 + } 6106 5995 6107 5996 if (bp->rss_hash_delta) { 6108 5997 req->hash_type = cpu_to_le32(bp->rss_hash_delta); ··· 6468 6351 } 6469 6352 if (flags & VNIC_QCAPS_RESP_FLAGS_HW_TUNNEL_TPA_CAP) 6470 6353 bp->fw_cap |= BNXT_FW_CAP_VNIC_TUNNEL_TPA; 6354 + if (flags & VNIC_QCAPS_RESP_FLAGS_RSS_IPSEC_AH_SPI_IPV4_CAP) 6355 + bp->rss_cap |= BNXT_RSS_CAP_AH_V4_RSS_CAP; 6356 + if (flags & VNIC_QCAPS_RESP_FLAGS_RSS_IPSEC_AH_SPI_IPV6_CAP) 6357 + bp->rss_cap |= BNXT_RSS_CAP_AH_V6_RSS_CAP; 6358 + if (flags & VNIC_QCAPS_RESP_FLAGS_RSS_IPSEC_ESP_SPI_IPV4_CAP) 6359 + bp->rss_cap |= BNXT_RSS_CAP_ESP_V4_RSS_CAP; 6360 + if (flags & VNIC_QCAPS_RESP_FLAGS_RSS_IPSEC_ESP_SPI_IPV6_CAP) 6361 + bp->rss_cap |= BNXT_RSS_CAP_ESP_V6_RSS_CAP; 6471 6362 } 6472 6363 hwrm_req_drop(bp, req); 6473 6364 return rc; ··· 8834 8709 hw_resc->max_vnics = le16_to_cpu(resp->max_vnics); 8835 8710 hw_resc->max_stat_ctxs = le16_to_cpu(resp->max_stat_ctx); 8836 8711 8712 + hw_resc->max_encap_records = le32_to_cpu(resp->max_encap_records); 8713 + hw_resc->max_decap_records = le32_to_cpu(resp->max_decap_records); 8714 + hw_resc->max_tx_em_flows = le32_to_cpu(resp->max_tx_em_flows); 8715 + hw_resc->max_tx_wm_flows = le32_to_cpu(resp->max_tx_wm_flows); 8716 + hw_resc->max_rx_em_flows = le32_to_cpu(resp->max_rx_em_flows); 8717 + hw_resc->max_rx_wm_flows = le32_to_cpu(resp->max_rx_wm_flows); 8718 + 8837 8719 if (BNXT_PF(bp)) { 8838 8720 struct bnxt_pf_info *pf = &bp->pf; 8839 8721 ··· 8849 8717 memcpy(pf->mac_addr, resp->mac_address, ETH_ALEN); 8850 8718 pf->first_vf_id = le16_to_cpu(resp->first_vf_id); 8851 8719 pf->max_vfs = le16_to_cpu(resp->max_vfs); 8852 - pf->max_encap_records = le32_to_cpu(resp->max_encap_records); 8853 - pf->max_decap_records = le32_to_cpu(resp->max_decap_records); 8854 - pf->max_tx_em_flows = le32_to_cpu(resp->max_tx_em_flows); 8855 - pf->max_tx_wm_flows = le32_to_cpu(resp->max_tx_wm_flows); 8856 - pf->max_rx_em_flows = le32_to_cpu(resp->max_rx_em_flows); 8857 - pf->max_rx_wm_flows = le32_to_cpu(resp->max_rx_wm_flows); 8858 8720 bp->flags &= ~BNXT_FLAG_WOL_CAP; 8859 8721 if (flags & FUNC_QCAPS_RESP_FLAGS_WOL_MAGICPKT_SUPPORTED) 8860 8722 bp->flags |= BNXT_FLAG_WOL_CAP; ··· 8950 8824 if (flags & 8951 8825 CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_RFS_RING_TBL_IDX_V2_SUPPORTED) 8952 8826 bp->fw_cap |= BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX_V2; 8827 + 8828 + if (flags & 8829 + CFA_ADV_FLOW_MGNT_QCAPS_RESP_FLAGS_NTUPLE_FLOW_RX_EXT_IP_PROTO_SUPPORTED) 8830 + bp->fw_cap |= BNXT_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO; 8953 8831 8954 8832 hwrm_cfa_adv_qcaps_exit: 8955 8833 hwrm_req_drop(bp, req); ··· 11573 11443 return rc; 11574 11444 } 11575 11445 11446 + static void bnxt_cfg_one_usr_fltr(struct bnxt *bp, struct bnxt_filter_base *fltr) 11447 + { 11448 + struct bnxt_ntuple_filter *ntp_fltr; 11449 + struct bnxt_l2_filter *l2_fltr; 11450 + 11451 + if (list_empty(&fltr->list)) 11452 + return; 11453 + 11454 + if (fltr->type == BNXT_FLTR_TYPE_NTUPLE) { 11455 + ntp_fltr = container_of(fltr, struct bnxt_ntuple_filter, base); 11456 + l2_fltr = bp->vnic_info[0].l2_filters[0]; 11457 + atomic_inc(&l2_fltr->refcnt); 11458 + ntp_fltr->l2_fltr = l2_fltr; 11459 + if (bnxt_hwrm_cfa_ntuple_filter_alloc(bp, ntp_fltr)) { 11460 + bnxt_del_ntp_filter(bp, ntp_fltr); 11461 + netdev_err(bp->dev, "restoring previously configured ntuple filter id %d failed\n", 11462 + fltr->sw_id); 11463 + } 11464 + } else if (fltr->type == BNXT_FLTR_TYPE_L2) { 11465 + l2_fltr = container_of(fltr, struct bnxt_l2_filter, base); 11466 + if (bnxt_hwrm_l2_filter_alloc(bp, l2_fltr)) { 11467 + bnxt_del_l2_filter(bp, l2_fltr); 11468 + netdev_err(bp->dev, "restoring previously configured l2 filter id %d failed\n", 11469 + fltr->sw_id); 11470 + } 11471 + } 11472 + } 11473 + 11474 + static void bnxt_cfg_usr_fltrs(struct bnxt *bp) 11475 + { 11476 + struct bnxt_filter_base *usr_fltr, *tmp; 11477 + 11478 + list_for_each_entry_safe(usr_fltr, tmp, &bp->usr_fltr_list, list) 11479 + bnxt_cfg_one_usr_fltr(bp, usr_fltr); 11480 + } 11481 + 11576 11482 static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) 11577 11483 { 11578 11484 int rc = 0; ··· 11695 11529 bnxt_vf_reps_open(bp); 11696 11530 bnxt_ptp_init_rtc(bp, true); 11697 11531 bnxt_ptp_cfg_tstamp_filters(bp); 11532 + bnxt_cfg_usr_fltrs(bp); 11698 11533 return 0; 11699 11534 11700 11535 open_err_irq: ··· 12437 12270 12438 12271 if (features & NETIF_F_NTUPLE) 12439 12272 flags |= BNXT_FLAG_RFS; 12273 + else 12274 + bnxt_clear_usr_fltrs(bp, true); 12440 12275 12441 12276 changes = flags ^ bp->flags; 12442 12277 if (changes & BNXT_FLAG_TPA) { ··· 13936 13767 return rc; 13937 13768 13938 13769 eth_hw_addr_set(dev, addr->sa_data); 13770 + bnxt_clear_usr_fltrs(bp, true); 13939 13771 if (netif_running(dev)) { 13940 13772 bnxt_close_nic(bp, false, false); 13941 13773 rc = bnxt_open_nic(bp, false, false); ··· 14070 13900 int bit_id; 14071 13901 14072 13902 spin_lock_bh(&bp->ntp_fltr_lock); 14073 - bit_id = bitmap_find_free_region(bp->ntp_fltr_bmap, BNXT_MAX_FLTR, 0); 13903 + bit_id = bitmap_find_free_region(bp->ntp_fltr_bmap, bp->max_fltr, 0); 14074 13904 if (bit_id < 0) { 14075 13905 spin_unlock_bh(&bp->ntp_fltr_lock); 14076 13906 return -ENOMEM; ··· 14082 13912 head = &bp->ntp_fltr_hash_tbl[idx]; 14083 13913 hlist_add_head_rcu(&fltr->base.hash, head); 14084 13914 set_bit(BNXT_FLTR_INSERTED, &fltr->base.state); 13915 + bnxt_insert_usr_fltr(bp, &fltr->base); 14085 13916 bp->ntp_fltr_count++; 14086 13917 spin_unlock_bh(&bp->ntp_fltr_lock); 14087 13918 return 0; ··· 14091 13920 static bool bnxt_fltr_match(struct bnxt_ntuple_filter *f1, 14092 13921 struct bnxt_ntuple_filter *f2) 14093 13922 { 13923 + struct bnxt_flow_masks *masks1 = &f1->fmasks; 13924 + struct bnxt_flow_masks *masks2 = &f2->fmasks; 14094 13925 struct flow_keys *keys1 = &f1->fkeys; 14095 13926 struct flow_keys *keys2 = &f2->fkeys; 14096 - 14097 - if (f1->ntuple_flags != f2->ntuple_flags) 14098 - return false; 14099 13927 14100 13928 if (keys1->basic.n_proto != keys2->basic.n_proto || 14101 13929 keys1->basic.ip_proto != keys2->basic.ip_proto) 14102 13930 return false; 14103 13931 14104 13932 if (keys1->basic.n_proto == htons(ETH_P_IP)) { 14105 - if (((f1->ntuple_flags & BNXT_NTUPLE_MATCH_SRC_IP) && 14106 - keys1->addrs.v4addrs.src != keys2->addrs.v4addrs.src) || 14107 - ((f1->ntuple_flags & BNXT_NTUPLE_MATCH_DST_IP) && 14108 - keys1->addrs.v4addrs.dst != keys2->addrs.v4addrs.dst)) 13933 + if (keys1->addrs.v4addrs.src != keys2->addrs.v4addrs.src || 13934 + masks1->addrs.v4addrs.src != masks2->addrs.v4addrs.src || 13935 + keys1->addrs.v4addrs.dst != keys2->addrs.v4addrs.dst || 13936 + masks1->addrs.v4addrs.dst != masks2->addrs.v4addrs.dst) 14109 13937 return false; 14110 13938 } else { 14111 - if (((f1->ntuple_flags & BNXT_NTUPLE_MATCH_SRC_IP) && 14112 - memcmp(&keys1->addrs.v6addrs.src, 14113 - &keys2->addrs.v6addrs.src, 14114 - sizeof(keys1->addrs.v6addrs.src))) || 14115 - ((f1->ntuple_flags & BNXT_NTUPLE_MATCH_DST_IP) && 14116 - memcmp(&keys1->addrs.v6addrs.dst, 14117 - &keys2->addrs.v6addrs.dst, 14118 - sizeof(keys1->addrs.v6addrs.dst)))) 13939 + if (!ipv6_addr_equal(&keys1->addrs.v6addrs.src, 13940 + &keys2->addrs.v6addrs.src) || 13941 + !ipv6_addr_equal(&masks1->addrs.v6addrs.src, 13942 + &masks2->addrs.v6addrs.src) || 13943 + !ipv6_addr_equal(&keys1->addrs.v6addrs.dst, 13944 + &keys2->addrs.v6addrs.dst) || 13945 + !ipv6_addr_equal(&masks1->addrs.v6addrs.dst, 13946 + &masks2->addrs.v6addrs.dst)) 14119 13947 return false; 14120 13948 } 14121 13949 14122 - if (((f1->ntuple_flags & BNXT_NTUPLE_MATCH_SRC_PORT) && 14123 - keys1->ports.src != keys2->ports.src) || 14124 - ((f1->ntuple_flags & BNXT_NTUPLE_MATCH_DST_PORT) && 14125 - keys1->ports.dst != keys2->ports.dst)) 14126 - return false; 14127 - 14128 - if (keys1->control.flags == keys2->control.flags && 14129 - f1->l2_fltr == f2->l2_fltr) 14130 - return true; 14131 - 14132 - return false; 13950 + return keys1->ports.src == keys2->ports.src && 13951 + masks1->ports.src == masks2->ports.src && 13952 + keys1->ports.dst == keys2->ports.dst && 13953 + masks1->ports.dst == masks2->ports.dst && 13954 + keys1->control.flags == keys2->control.flags && 13955 + f1->l2_fltr == f2->l2_fltr; 14133 13956 } 14134 13957 14135 13958 struct bnxt_ntuple_filter * ··· 14188 14023 rc = -EPROTONOSUPPORT; 14189 14024 goto err_free; 14190 14025 } 14191 - if (fkeys->basic.n_proto == htons(ETH_P_IPV6) && 14192 - bp->hwrm_spec_code < 0x10601) { 14193 - rc = -EPROTONOSUPPORT; 14194 - goto err_free; 14026 + new_fltr->fmasks = BNXT_FLOW_IPV4_MASK_ALL; 14027 + if (fkeys->basic.n_proto == htons(ETH_P_IPV6)) { 14028 + if (bp->hwrm_spec_code < 0x10601) { 14029 + rc = -EPROTONOSUPPORT; 14030 + goto err_free; 14031 + } 14032 + new_fltr->fmasks = BNXT_FLOW_IPV6_MASK_ALL; 14195 14033 } 14196 14034 flags = fkeys->control.flags; 14197 14035 if (((flags & FLOW_DIS_ENCAPSULATION) && ··· 14202 14034 rc = -EPROTONOSUPPORT; 14203 14035 goto err_free; 14204 14036 } 14205 - 14206 14037 new_fltr->l2_fltr = l2_fltr; 14207 - new_fltr->ntuple_flags = BNXT_NTUPLE_MATCH_ALL; 14208 14038 14209 14039 idx = bnxt_get_ntp_filter_idx(bp, fkeys, skb); 14210 14040 rcu_read_lock(); ··· 14237 14071 return; 14238 14072 } 14239 14073 hlist_del_rcu(&fltr->base.hash); 14074 + bnxt_del_one_usr_fltr(bp, &fltr->base); 14240 14075 bp->ntp_fltr_count--; 14241 14076 spin_unlock_bh(&bp->ntp_fltr_lock); 14242 14077 bnxt_del_l2_filter(bp, fltr->l2_fltr); ··· 14837 14670 14838 14671 static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 14839 14672 { 14673 + struct bnxt_hw_resc *hw_resc; 14840 14674 struct net_device *dev; 14841 14675 struct bnxt *bp; 14842 14676 int rc, max_irqs; ··· 14996 14828 if (rc) 14997 14829 goto init_err_pci_clean; 14998 14830 14831 + hw_resc = &bp->hw_resc; 14832 + bp->max_fltr = hw_resc->max_rx_em_flows + hw_resc->max_rx_wm_flows + 14833 + BNXT_L2_FLTR_MAX_FLTR; 14834 + /* Older firmware may not report these filters properly */ 14835 + if (bp->max_fltr < BNXT_MAX_FLTR) 14836 + bp->max_fltr = BNXT_MAX_FLTR; 14999 14837 bnxt_init_l2_fltr_tbl(bp); 15000 14838 bnxt_set_rx_skb_mode(bp, false); 15001 14839 bnxt_set_tpa_flags(bp); ··· 15053 14879 rc = bnxt_dl_register(bp); 15054 14880 if (rc) 15055 14881 goto init_err_dl; 14882 + 14883 + INIT_LIST_HEAD(&bp->usr_fltr_list); 15056 14884 15057 14885 rc = register_netdev(dev); 15058 14886 if (rc)
+37 -15
drivers/net/ethernet/broadcom/bnxt/bnxt.h
··· 1281 1281 u16 max_nqs; 1282 1282 u16 max_irqs; 1283 1283 u16 resv_irqs; 1284 + u32 max_encap_records; 1285 + u32 max_decap_records; 1286 + u32 max_tx_em_flows; 1287 + u32 max_tx_wm_flows; 1288 + u32 max_rx_em_flows; 1289 + u32 max_rx_wm_flows; 1284 1290 }; 1285 1291 1286 1292 #if defined(CONFIG_BNXT_SRIOV) ··· 1321 1315 u16 active_vfs; 1322 1316 u16 registered_vfs; 1323 1317 u16 max_vfs; 1324 - u32 max_encap_records; 1325 - u32 max_decap_records; 1326 - u32 max_tx_em_flows; 1327 - u32 max_tx_wm_flows; 1328 - u32 max_rx_em_flows; 1329 - u32 max_rx_wm_flows; 1330 1318 unsigned long *vf_event_bmap; 1331 1319 u16 hwrm_cmd_req_pages; 1332 1320 u8 vf_resv_strategy; ··· 1334 1334 1335 1335 struct bnxt_filter_base { 1336 1336 struct hlist_node hash; 1337 + struct list_head list; 1337 1338 __le64 filter_id; 1338 1339 u8 type; 1339 1340 #define BNXT_FLTR_TYPE_NTUPLE 1 ··· 1356 1355 struct rcu_head rcu; 1357 1356 }; 1358 1357 1358 + struct bnxt_flow_masks { 1359 + struct flow_dissector_key_ports ports; 1360 + struct flow_dissector_key_addrs addrs; 1361 + }; 1362 + 1363 + extern const struct bnxt_flow_masks BNXT_FLOW_MASK_NONE; 1364 + extern const struct bnxt_flow_masks BNXT_FLOW_IPV6_MASK_ALL; 1365 + extern const struct bnxt_flow_masks BNXT_FLOW_IPV4_MASK_ALL; 1366 + 1359 1367 struct bnxt_ntuple_filter { 1368 + /* base filter must be the first member */ 1360 1369 struct bnxt_filter_base base; 1361 1370 struct flow_keys fkeys; 1371 + struct bnxt_flow_masks fmasks; 1362 1372 struct bnxt_l2_filter *l2_fltr; 1363 - u32 ntuple_flags; 1364 - #define BNXT_NTUPLE_MATCH_SRC_IP 1 1365 - #define BNXT_NTUPLE_MATCH_DST_IP 2 1366 - #define BNXT_NTUPLE_MATCH_SRC_PORT 4 1367 - #define BNXT_NTUPLE_MATCH_DST_PORT 8 1368 - #define BNXT_NTUPLE_MATCH_ALL (BNXT_NTUPLE_MATCH_SRC_IP | \ 1369 - BNXT_NTUPLE_MATCH_DST_IP | \ 1370 - BNXT_NTUPLE_MATCH_SRC_PORT | \ 1371 - BNXT_NTUPLE_MATCH_DST_PORT) 1372 1373 u32 flow_id; 1373 1374 }; 1374 1375 ··· 1397 1394 #define BNXT_L2_KEY_SIZE (sizeof(struct bnxt_l2_key) / 4) 1398 1395 1399 1396 struct bnxt_l2_filter { 1397 + /* base filter must be the first member */ 1400 1398 struct bnxt_filter_base base; 1401 1399 struct bnxt_l2_key l2_key; 1402 1400 atomic_t refcnt; ··· 2221 2217 #define BNXT_RSS_CAP_UDP_RSS_CAP BIT(1) 2222 2218 #define BNXT_RSS_CAP_NEW_RSS_CAP BIT(2) 2223 2219 #define BNXT_RSS_CAP_RSS_TCAM BIT(3) 2220 + #define BNXT_RSS_CAP_AH_V4_RSS_CAP BIT(4) 2221 + #define BNXT_RSS_CAP_AH_V6_RSS_CAP BIT(5) 2222 + #define BNXT_RSS_CAP_ESP_V4_RSS_CAP BIT(6) 2223 + #define BNXT_RSS_CAP_ESP_V6_RSS_CAP BIT(7) 2224 + 2225 + u8 rss_hash_key[HW_HASH_KEY_SIZE]; 2226 + u8 rss_hash_key_valid:1; 2227 + u8 rss_hash_key_updated:1; 2224 2228 2225 2229 u16 max_mtu; 2226 2230 u8 max_tc; ··· 2313 2301 #define BNXT_FW_CAP_PRE_RESV_VNICS BIT_ULL(35) 2314 2302 #define BNXT_FW_CAP_BACKING_STORE_V2 BIT_ULL(36) 2315 2303 #define BNXT_FW_CAP_VNIC_TUNNEL_TPA BIT_ULL(37) 2304 + #define BNXT_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO BIT_ULL(38) 2316 2305 2317 2306 u32 fw_dbg_cap; 2318 2307 ··· 2441 2428 2442 2429 unsigned long *ntp_fltr_bmap; 2443 2430 int ntp_fltr_count; 2431 + int max_fltr; 2444 2432 2445 2433 #define BNXT_L2_FLTR_MAX_FLTR 1024 2446 2434 #define BNXT_L2_FLTR_HASH_SIZE 32 ··· 2450 2436 2451 2437 u32 hash_seed; 2452 2438 u64 toeplitz_prefix; 2439 + 2440 + struct list_head usr_fltr_list; 2453 2441 2454 2442 /* To protect link related settings during link changes and 2455 2443 * ethtool settings changes. ··· 2657 2641 void bnxt_set_tpa_flags(struct bnxt *bp); 2658 2642 void bnxt_set_ring_params(struct bnxt *); 2659 2643 int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode); 2644 + void bnxt_insert_usr_fltr(struct bnxt *bp, struct bnxt_filter_base *fltr); 2645 + void bnxt_del_one_usr_fltr(struct bnxt *bp, struct bnxt_filter_base *fltr); 2646 + void bnxt_clear_usr_fltrs(struct bnxt *bp, bool all); 2660 2647 int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp, unsigned long *bmap, 2661 2648 int bmap_size, bool async_only); 2662 2649 int bnxt_hwrm_func_drv_unrgtr(struct bnxt *bp); 2663 2650 void bnxt_del_l2_filter(struct bnxt *bp, struct bnxt_l2_filter *fltr); 2651 + struct bnxt_l2_filter *bnxt_alloc_new_l2_filter(struct bnxt *bp, 2652 + struct bnxt_l2_key *key, 2653 + u16 flags); 2664 2654 int bnxt_hwrm_l2_filter_free(struct bnxt *bp, struct bnxt_l2_filter *fltr); 2665 2655 int bnxt_hwrm_l2_filter_alloc(struct bnxt *bp, struct bnxt_l2_filter *fltr); 2666 2656 int bnxt_hwrm_cfa_ntuple_filter_free(struct bnxt *bp,
+280 -111
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
··· 968 968 return -EINVAL; 969 969 } 970 970 971 + bnxt_clear_usr_fltrs(bp, true); 971 972 if (netif_running(dev)) { 972 973 if (BNXT_PF(bp)) { 973 974 /* TODO CHIMP_FW: Send message to all VF's ··· 1059 1058 static int bnxt_grxclsrlall(struct bnxt *bp, struct ethtool_rxnfc *cmd, 1060 1059 u32 *rule_locs) 1061 1060 { 1061 + u32 count; 1062 + 1062 1063 cmd->data = bp->ntp_fltr_count; 1063 1064 rcu_read_lock(); 1065 + count = bnxt_get_all_fltr_ids_rcu(bp, bp->l2_fltr_hash_tbl, 1066 + BNXT_L2_FLTR_HASH_SIZE, rule_locs, 0, 1067 + cmd->rule_cnt); 1064 1068 cmd->rule_cnt = bnxt_get_all_fltr_ids_rcu(bp, bp->ntp_fltr_hash_tbl, 1065 1069 BNXT_NTP_FLTR_HASH_SIZE, 1066 - rule_locs, 0, cmd->rule_cnt); 1070 + rule_locs, count, 1071 + cmd->rule_cnt); 1067 1072 rcu_read_unlock(); 1068 1073 1069 1074 return 0; ··· 1081 1074 (struct ethtool_rx_flow_spec *)&cmd->fs; 1082 1075 struct bnxt_filter_base *fltr_base; 1083 1076 struct bnxt_ntuple_filter *fltr; 1077 + struct bnxt_flow_masks *fmasks; 1084 1078 struct flow_keys *fkeys; 1085 1079 int rc = -EINVAL; 1086 1080 1087 - if (fs->location >= BNXT_NTP_FLTR_MAX_FLTR) 1081 + if (fs->location >= bp->max_fltr) 1088 1082 return rc; 1089 1083 1090 1084 rcu_read_lock(); 1085 + fltr_base = bnxt_get_one_fltr_rcu(bp, bp->l2_fltr_hash_tbl, 1086 + BNXT_L2_FLTR_HASH_SIZE, 1087 + fs->location); 1088 + if (fltr_base) { 1089 + struct ethhdr *h_ether = &fs->h_u.ether_spec; 1090 + struct ethhdr *m_ether = &fs->m_u.ether_spec; 1091 + struct bnxt_l2_filter *l2_fltr; 1092 + struct bnxt_l2_key *l2_key; 1093 + 1094 + l2_fltr = container_of(fltr_base, struct bnxt_l2_filter, base); 1095 + l2_key = &l2_fltr->l2_key; 1096 + fs->flow_type = ETHER_FLOW; 1097 + ether_addr_copy(h_ether->h_dest, l2_key->dst_mac_addr); 1098 + eth_broadcast_addr(m_ether->h_dest); 1099 + if (l2_key->vlan) { 1100 + struct ethtool_flow_ext *m_ext = &fs->m_ext; 1101 + struct ethtool_flow_ext *h_ext = &fs->h_ext; 1102 + 1103 + fs->flow_type |= FLOW_EXT; 1104 + m_ext->vlan_tci = htons(0xfff); 1105 + h_ext->vlan_tci = htons(l2_key->vlan); 1106 + } 1107 + if (fltr_base->flags & BNXT_ACT_RING_DST) 1108 + fs->ring_cookie = fltr_base->rxq; 1109 + if (fltr_base->flags & BNXT_ACT_FUNC_DST) 1110 + fs->ring_cookie = (u64)(fltr_base->vf_idx + 1) << 1111 + ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF; 1112 + rcu_read_unlock(); 1113 + return 0; 1114 + } 1091 1115 fltr_base = bnxt_get_one_fltr_rcu(bp, bp->ntp_fltr_hash_tbl, 1092 1116 BNXT_NTP_FLTR_HASH_SIZE, 1093 1117 fs->location); ··· 1129 1091 fltr = container_of(fltr_base, struct bnxt_ntuple_filter, base); 1130 1092 1131 1093 fkeys = &fltr->fkeys; 1094 + fmasks = &fltr->fmasks; 1132 1095 if (fkeys->basic.n_proto == htons(ETH_P_IP)) { 1133 - if (fkeys->basic.ip_proto == IPPROTO_TCP) 1096 + if (fkeys->basic.ip_proto == IPPROTO_ICMP || 1097 + fkeys->basic.ip_proto == IPPROTO_RAW) { 1098 + fs->flow_type = IP_USER_FLOW; 1099 + fs->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4; 1100 + if (fkeys->basic.ip_proto == IPPROTO_ICMP) 1101 + fs->h_u.usr_ip4_spec.proto = IPPROTO_ICMP; 1102 + else 1103 + fs->h_u.usr_ip4_spec.proto = IPPROTO_RAW; 1104 + fs->m_u.usr_ip4_spec.proto = BNXT_IP_PROTO_FULL_MASK; 1105 + } else if (fkeys->basic.ip_proto == IPPROTO_TCP) { 1134 1106 fs->flow_type = TCP_V4_FLOW; 1135 - else if (fkeys->basic.ip_proto == IPPROTO_UDP) 1107 + } else if (fkeys->basic.ip_proto == IPPROTO_UDP) { 1136 1108 fs->flow_type = UDP_V4_FLOW; 1137 - else 1109 + } else { 1138 1110 goto fltr_err; 1111 + } 1139 1112 1140 - if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_SRC_IP) { 1141 - fs->h_u.tcp_ip4_spec.ip4src = fkeys->addrs.v4addrs.src; 1142 - fs->m_u.tcp_ip4_spec.ip4src = cpu_to_be32(~0); 1143 - } 1144 - if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_DST_IP) { 1145 - fs->h_u.tcp_ip4_spec.ip4dst = fkeys->addrs.v4addrs.dst; 1146 - fs->m_u.tcp_ip4_spec.ip4dst = cpu_to_be32(~0); 1147 - } 1148 - if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_SRC_PORT) { 1113 + fs->h_u.tcp_ip4_spec.ip4src = fkeys->addrs.v4addrs.src; 1114 + fs->m_u.tcp_ip4_spec.ip4src = fmasks->addrs.v4addrs.src; 1115 + fs->h_u.tcp_ip4_spec.ip4dst = fkeys->addrs.v4addrs.dst; 1116 + fs->m_u.tcp_ip4_spec.ip4dst = fmasks->addrs.v4addrs.dst; 1117 + if (fs->flow_type == TCP_V4_FLOW || 1118 + fs->flow_type == UDP_V4_FLOW) { 1149 1119 fs->h_u.tcp_ip4_spec.psrc = fkeys->ports.src; 1150 - fs->m_u.tcp_ip4_spec.psrc = cpu_to_be16(~0); 1151 - } 1152 - if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_DST_PORT) { 1120 + fs->m_u.tcp_ip4_spec.psrc = fmasks->ports.src; 1153 1121 fs->h_u.tcp_ip4_spec.pdst = fkeys->ports.dst; 1154 - fs->m_u.tcp_ip4_spec.pdst = cpu_to_be16(~0); 1122 + fs->m_u.tcp_ip4_spec.pdst = fmasks->ports.dst; 1155 1123 } 1156 1124 } else { 1157 - if (fkeys->basic.ip_proto == IPPROTO_TCP) 1125 + if (fkeys->basic.ip_proto == IPPROTO_ICMPV6 || 1126 + fkeys->basic.ip_proto == IPPROTO_RAW) { 1127 + fs->flow_type = IPV6_USER_FLOW; 1128 + if (fkeys->basic.ip_proto == IPPROTO_ICMPV6) 1129 + fs->h_u.usr_ip6_spec.l4_proto = IPPROTO_ICMPV6; 1130 + else 1131 + fs->h_u.usr_ip6_spec.l4_proto = IPPROTO_RAW; 1132 + fs->m_u.usr_ip6_spec.l4_proto = BNXT_IP_PROTO_FULL_MASK; 1133 + } else if (fkeys->basic.ip_proto == IPPROTO_TCP) { 1158 1134 fs->flow_type = TCP_V6_FLOW; 1159 - else if (fkeys->basic.ip_proto == IPPROTO_UDP) 1135 + } else if (fkeys->basic.ip_proto == IPPROTO_UDP) { 1160 1136 fs->flow_type = UDP_V6_FLOW; 1161 - else 1137 + } else { 1162 1138 goto fltr_err; 1139 + } 1163 1140 1164 - if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_SRC_IP) { 1165 - *(struct in6_addr *)&fs->h_u.tcp_ip6_spec.ip6src[0] = 1166 - fkeys->addrs.v6addrs.src; 1167 - bnxt_fill_ipv6_mask(fs->m_u.tcp_ip6_spec.ip6src); 1168 - } 1169 - if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_DST_IP) { 1170 - *(struct in6_addr *)&fs->h_u.tcp_ip6_spec.ip6dst[0] = 1171 - fkeys->addrs.v6addrs.dst; 1172 - bnxt_fill_ipv6_mask(fs->m_u.tcp_ip6_spec.ip6dst); 1173 - } 1174 - if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_SRC_PORT) { 1141 + *(struct in6_addr *)&fs->h_u.tcp_ip6_spec.ip6src[0] = 1142 + fkeys->addrs.v6addrs.src; 1143 + *(struct in6_addr *)&fs->m_u.tcp_ip6_spec.ip6src[0] = 1144 + fmasks->addrs.v6addrs.src; 1145 + *(struct in6_addr *)&fs->h_u.tcp_ip6_spec.ip6dst[0] = 1146 + fkeys->addrs.v6addrs.dst; 1147 + *(struct in6_addr *)&fs->m_u.tcp_ip6_spec.ip6dst[0] = 1148 + fmasks->addrs.v6addrs.dst; 1149 + if (fs->flow_type == TCP_V6_FLOW || 1150 + fs->flow_type == UDP_V6_FLOW) { 1175 1151 fs->h_u.tcp_ip6_spec.psrc = fkeys->ports.src; 1176 - fs->m_u.tcp_ip6_spec.psrc = cpu_to_be16(~0); 1177 - } 1178 - if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_DST_PORT) { 1152 + fs->m_u.tcp_ip6_spec.psrc = fmasks->ports.src; 1179 1153 fs->h_u.tcp_ip6_spec.pdst = fkeys->ports.dst; 1180 - fs->m_u.tcp_ip6_spec.pdst = cpu_to_be16(~0); 1154 + fs->m_u.tcp_ip6_spec.pdst = fmasks->ports.dst; 1181 1155 } 1182 1156 } 1183 1157 1184 - fs->ring_cookie = fltr->base.rxq; 1158 + if (fltr->base.flags & BNXT_ACT_DROP) 1159 + fs->ring_cookie = RX_CLS_FLOW_DISC; 1160 + else 1161 + fs->ring_cookie = fltr->base.rxq; 1185 1162 rc = 0; 1186 1163 1187 1164 fltr_err: ··· 1205 1152 return rc; 1206 1153 } 1207 1154 1208 - #define IPV4_ALL_MASK ((__force __be32)~0) 1209 - #define L4_PORT_ALL_MASK ((__force __be16)~0) 1210 - 1211 - static bool ipv6_mask_is_full(__be32 mask[4]) 1155 + static int bnxt_add_l2_cls_rule(struct bnxt *bp, 1156 + struct ethtool_rx_flow_spec *fs) 1212 1157 { 1213 - return (mask[0] & mask[1] & mask[2] & mask[3]) == IPV4_ALL_MASK; 1158 + u32 ring = ethtool_get_flow_spec_ring(fs->ring_cookie); 1159 + u8 vf = ethtool_get_flow_spec_ring_vf(fs->ring_cookie); 1160 + struct ethhdr *h_ether = &fs->h_u.ether_spec; 1161 + struct ethhdr *m_ether = &fs->m_u.ether_spec; 1162 + struct bnxt_l2_filter *fltr; 1163 + struct bnxt_l2_key key; 1164 + u16 vnic_id; 1165 + u8 flags; 1166 + int rc; 1167 + 1168 + if (BNXT_CHIP_P5_PLUS(bp)) 1169 + return -EOPNOTSUPP; 1170 + 1171 + if (!is_broadcast_ether_addr(m_ether->h_dest)) 1172 + return -EINVAL; 1173 + ether_addr_copy(key.dst_mac_addr, h_ether->h_dest); 1174 + key.vlan = 0; 1175 + if (fs->flow_type & FLOW_EXT) { 1176 + struct ethtool_flow_ext *m_ext = &fs->m_ext; 1177 + struct ethtool_flow_ext *h_ext = &fs->h_ext; 1178 + 1179 + if (m_ext->vlan_tci != htons(0xfff) || !h_ext->vlan_tci) 1180 + return -EINVAL; 1181 + key.vlan = ntohs(h_ext->vlan_tci); 1182 + } 1183 + 1184 + if (vf) { 1185 + flags = BNXT_ACT_FUNC_DST; 1186 + vnic_id = 0xffff; 1187 + vf--; 1188 + } else { 1189 + flags = BNXT_ACT_RING_DST; 1190 + vnic_id = bp->vnic_info[ring + 1].fw_vnic_id; 1191 + } 1192 + fltr = bnxt_alloc_new_l2_filter(bp, &key, flags); 1193 + if (IS_ERR(fltr)) 1194 + return PTR_ERR(fltr); 1195 + 1196 + fltr->base.fw_vnic_id = vnic_id; 1197 + fltr->base.rxq = ring; 1198 + fltr->base.vf_idx = vf; 1199 + rc = bnxt_hwrm_l2_filter_alloc(bp, fltr); 1200 + if (rc) 1201 + bnxt_del_l2_filter(bp, fltr); 1202 + else 1203 + fs->location = fltr->base.sw_id; 1204 + return rc; 1214 1205 } 1215 1206 1216 - static bool ipv6_mask_is_zero(__be32 mask[4]) 1207 + static bool bnxt_verify_ntuple_ip4_flow(struct ethtool_usrip4_spec *ip_spec, 1208 + struct ethtool_usrip4_spec *ip_mask) 1217 1209 { 1218 - return !(mask[0] | mask[1] | mask[2] | mask[3]); 1210 + if (ip_mask->l4_4_bytes || ip_mask->tos || 1211 + ip_spec->ip_ver != ETH_RX_NFC_IP4 || 1212 + ip_mask->proto != BNXT_IP_PROTO_FULL_MASK || 1213 + (ip_spec->proto != IPPROTO_RAW && ip_spec->proto != IPPROTO_ICMP)) 1214 + return false; 1215 + return true; 1216 + } 1217 + 1218 + static bool bnxt_verify_ntuple_ip6_flow(struct ethtool_usrip6_spec *ip_spec, 1219 + struct ethtool_usrip6_spec *ip_mask) 1220 + { 1221 + if (ip_mask->l4_4_bytes || ip_mask->tclass || 1222 + ip_mask->l4_proto != BNXT_IP_PROTO_FULL_MASK || 1223 + (ip_spec->l4_proto != IPPROTO_RAW && 1224 + ip_spec->l4_proto != IPPROTO_ICMPV6)) 1225 + return false; 1226 + return true; 1219 1227 } 1220 1228 1221 1229 static int bnxt_add_ntuple_cls_rule(struct bnxt *bp, ··· 1286 1172 u32 ring = ethtool_get_flow_spec_ring(fs->ring_cookie); 1287 1173 struct bnxt_ntuple_filter *new_fltr, *fltr; 1288 1174 struct bnxt_l2_filter *l2_fltr; 1175 + struct bnxt_flow_masks *fmasks; 1289 1176 u32 flow_type = fs->flow_type; 1290 1177 struct flow_keys *fkeys; 1291 1178 u32 idx; ··· 1298 1183 if ((flow_type & (FLOW_MAC_EXT | FLOW_EXT)) || vf) 1299 1184 return -EOPNOTSUPP; 1300 1185 1186 + if (flow_type == IP_USER_FLOW) { 1187 + if (!bnxt_verify_ntuple_ip4_flow(&fs->h_u.usr_ip4_spec, 1188 + &fs->m_u.usr_ip4_spec)) 1189 + return -EOPNOTSUPP; 1190 + } 1191 + 1192 + if (flow_type == IPV6_USER_FLOW) { 1193 + if (!bnxt_verify_ntuple_ip6_flow(&fs->h_u.usr_ip6_spec, 1194 + &fs->m_u.usr_ip6_spec)) 1195 + return -EOPNOTSUPP; 1196 + } 1197 + 1301 1198 new_fltr = kzalloc(sizeof(*new_fltr), GFP_KERNEL); 1302 1199 if (!new_fltr) 1303 1200 return -ENOMEM; ··· 1317 1190 l2_fltr = bp->vnic_info[0].l2_filters[0]; 1318 1191 atomic_inc(&l2_fltr->refcnt); 1319 1192 new_fltr->l2_fltr = l2_fltr; 1193 + fmasks = &new_fltr->fmasks; 1320 1194 fkeys = &new_fltr->fkeys; 1321 1195 1322 1196 rc = -EOPNOTSUPP; 1323 1197 switch (flow_type) { 1198 + case IP_USER_FLOW: { 1199 + struct ethtool_usrip4_spec *ip_spec = &fs->h_u.usr_ip4_spec; 1200 + struct ethtool_usrip4_spec *ip_mask = &fs->m_u.usr_ip4_spec; 1201 + 1202 + fkeys->basic.ip_proto = ip_spec->proto; 1203 + fkeys->basic.n_proto = htons(ETH_P_IP); 1204 + fkeys->addrs.v4addrs.src = ip_spec->ip4src; 1205 + fmasks->addrs.v4addrs.src = ip_mask->ip4src; 1206 + fkeys->addrs.v4addrs.dst = ip_spec->ip4dst; 1207 + fmasks->addrs.v4addrs.dst = ip_mask->ip4dst; 1208 + break; 1209 + } 1324 1210 case TCP_V4_FLOW: 1325 1211 case UDP_V4_FLOW: { 1326 1212 struct ethtool_tcpip4_spec *ip_spec = &fs->h_u.tcp_ip4_spec; ··· 1343 1203 if (flow_type == UDP_V4_FLOW) 1344 1204 fkeys->basic.ip_proto = IPPROTO_UDP; 1345 1205 fkeys->basic.n_proto = htons(ETH_P_IP); 1206 + fkeys->addrs.v4addrs.src = ip_spec->ip4src; 1207 + fmasks->addrs.v4addrs.src = ip_mask->ip4src; 1208 + fkeys->addrs.v4addrs.dst = ip_spec->ip4dst; 1209 + fmasks->addrs.v4addrs.dst = ip_mask->ip4dst; 1210 + fkeys->ports.src = ip_spec->psrc; 1211 + fmasks->ports.src = ip_mask->psrc; 1212 + fkeys->ports.dst = ip_spec->pdst; 1213 + fmasks->ports.dst = ip_mask->pdst; 1214 + break; 1215 + } 1216 + case IPV6_USER_FLOW: { 1217 + struct ethtool_usrip6_spec *ip_spec = &fs->h_u.usr_ip6_spec; 1218 + struct ethtool_usrip6_spec *ip_mask = &fs->m_u.usr_ip6_spec; 1346 1219 1347 - if (ip_mask->ip4src == IPV4_ALL_MASK) { 1348 - fkeys->addrs.v4addrs.src = ip_spec->ip4src; 1349 - new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_SRC_IP; 1350 - } else if (ip_mask->ip4src) { 1351 - goto ntuple_err; 1352 - } 1353 - if (ip_mask->ip4dst == IPV4_ALL_MASK) { 1354 - fkeys->addrs.v4addrs.dst = ip_spec->ip4dst; 1355 - new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_DST_IP; 1356 - } else if (ip_mask->ip4dst) { 1357 - goto ntuple_err; 1358 - } 1359 - 1360 - if (ip_mask->psrc == L4_PORT_ALL_MASK) { 1361 - fkeys->ports.src = ip_spec->psrc; 1362 - new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_SRC_PORT; 1363 - } else if (ip_mask->psrc) { 1364 - goto ntuple_err; 1365 - } 1366 - if (ip_mask->pdst == L4_PORT_ALL_MASK) { 1367 - fkeys->ports.dst = ip_spec->pdst; 1368 - new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_DST_PORT; 1369 - } else if (ip_mask->pdst) { 1370 - goto ntuple_err; 1371 - } 1220 + fkeys->basic.ip_proto = ip_spec->l4_proto; 1221 + fkeys->basic.n_proto = htons(ETH_P_IPV6); 1222 + fkeys->addrs.v6addrs.src = *(struct in6_addr *)&ip_spec->ip6src; 1223 + fmasks->addrs.v6addrs.src = *(struct in6_addr *)&ip_mask->ip6src; 1224 + fkeys->addrs.v6addrs.dst = *(struct in6_addr *)&ip_spec->ip6dst; 1225 + fmasks->addrs.v6addrs.dst = *(struct in6_addr *)&ip_mask->ip6dst; 1372 1226 break; 1373 1227 } 1374 1228 case TCP_V6_FLOW: ··· 1375 1241 fkeys->basic.ip_proto = IPPROTO_UDP; 1376 1242 fkeys->basic.n_proto = htons(ETH_P_IPV6); 1377 1243 1378 - if (ipv6_mask_is_full(ip_mask->ip6src)) { 1379 - fkeys->addrs.v6addrs.src = 1380 - *(struct in6_addr *)&ip_spec->ip6src; 1381 - new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_SRC_IP; 1382 - } else if (!ipv6_mask_is_zero(ip_mask->ip6src)) { 1383 - goto ntuple_err; 1384 - } 1385 - if (ipv6_mask_is_full(ip_mask->ip6dst)) { 1386 - fkeys->addrs.v6addrs.dst = 1387 - *(struct in6_addr *)&ip_spec->ip6dst; 1388 - new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_DST_IP; 1389 - } else if (!ipv6_mask_is_zero(ip_mask->ip6dst)) { 1390 - goto ntuple_err; 1391 - } 1392 - 1393 - if (ip_mask->psrc == L4_PORT_ALL_MASK) { 1394 - fkeys->ports.src = ip_spec->psrc; 1395 - new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_SRC_PORT; 1396 - } else if (ip_mask->psrc) { 1397 - goto ntuple_err; 1398 - } 1399 - if (ip_mask->pdst == L4_PORT_ALL_MASK) { 1400 - fkeys->ports.dst = ip_spec->pdst; 1401 - new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_DST_PORT; 1402 - } else if (ip_mask->pdst) { 1403 - goto ntuple_err; 1404 - } 1244 + fkeys->addrs.v6addrs.src = *(struct in6_addr *)&ip_spec->ip6src; 1245 + fmasks->addrs.v6addrs.src = *(struct in6_addr *)&ip_mask->ip6src; 1246 + fkeys->addrs.v6addrs.dst = *(struct in6_addr *)&ip_spec->ip6dst; 1247 + fmasks->addrs.v6addrs.dst = *(struct in6_addr *)&ip_mask->ip6dst; 1248 + fkeys->ports.src = ip_spec->psrc; 1249 + fmasks->ports.src = ip_mask->psrc; 1250 + fkeys->ports.dst = ip_spec->pdst; 1251 + fmasks->ports.dst = ip_mask->pdst; 1405 1252 break; 1406 1253 } 1407 1254 default: 1408 1255 rc = -EOPNOTSUPP; 1409 1256 goto ntuple_err; 1410 1257 } 1411 - if (!new_fltr->ntuple_flags) 1258 + if (!memcmp(&BNXT_FLOW_MASK_NONE, fmasks, sizeof(*fmasks))) 1412 1259 goto ntuple_err; 1413 1260 1414 1261 idx = bnxt_get_ntp_filter_idx(bp, fkeys, NULL); ··· 1402 1287 } 1403 1288 rcu_read_unlock(); 1404 1289 1405 - new_fltr->base.rxq = ring; 1406 1290 new_fltr->base.flags = BNXT_ACT_NO_AGING; 1291 + if (fs->ring_cookie == RX_CLS_FLOW_DISC) 1292 + new_fltr->base.flags |= BNXT_ACT_DROP; 1293 + else 1294 + new_fltr->base.rxq = ring; 1407 1295 __set_bit(BNXT_FLTR_VALID, &new_fltr->base.state); 1408 1296 rc = bnxt_insert_ntp_filter(bp, new_fltr, idx); 1409 1297 if (!rc) { ··· 1439 1321 if (fs->location != RX_CLS_LOC_ANY) 1440 1322 return -EINVAL; 1441 1323 1324 + flow_type = fs->flow_type; 1325 + if ((flow_type == IP_USER_FLOW || 1326 + flow_type == IPV6_USER_FLOW) && 1327 + !(bp->fw_cap & BNXT_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO)) 1328 + return -EOPNOTSUPP; 1329 + if (flow_type & (FLOW_MAC_EXT | FLOW_RSS)) 1330 + return -EINVAL; 1331 + flow_type &= ~FLOW_EXT; 1332 + 1333 + if (fs->ring_cookie == RX_CLS_FLOW_DISC && flow_type != ETHER_FLOW) 1334 + return bnxt_add_ntuple_cls_rule(bp, fs); 1335 + 1442 1336 ring = ethtool_get_flow_spec_ring(fs->ring_cookie); 1443 1337 vf = ethtool_get_flow_spec_ring_vf(fs->ring_cookie); 1444 1338 if (BNXT_VF(bp) && vf) ··· 1460 1330 if (!vf && ring >= bp->rx_nr_rings) 1461 1331 return -EINVAL; 1462 1332 1463 - flow_type = fs->flow_type; 1464 - if (flow_type & (FLOW_MAC_EXT | FLOW_RSS)) 1465 - return -EINVAL; 1466 - flow_type &= ~FLOW_EXT; 1467 1333 if (flow_type == ETHER_FLOW) 1468 - rc = -EOPNOTSUPP; 1334 + rc = bnxt_add_l2_cls_rule(bp, fs); 1469 1335 else 1470 1336 rc = bnxt_add_ntuple_cls_rule(bp, fs); 1471 1337 return rc; ··· 1472 1346 struct ethtool_rx_flow_spec *fs = &cmd->fs; 1473 1347 struct bnxt_filter_base *fltr_base; 1474 1348 struct bnxt_ntuple_filter *fltr; 1349 + u32 id = fs->location; 1475 1350 1476 1351 rcu_read_lock(); 1352 + fltr_base = bnxt_get_one_fltr_rcu(bp, bp->l2_fltr_hash_tbl, 1353 + BNXT_L2_FLTR_HASH_SIZE, id); 1354 + if (fltr_base) { 1355 + struct bnxt_l2_filter *l2_fltr; 1356 + 1357 + l2_fltr = container_of(fltr_base, struct bnxt_l2_filter, base); 1358 + rcu_read_unlock(); 1359 + bnxt_hwrm_l2_filter_free(bp, l2_fltr); 1360 + bnxt_del_l2_filter(bp, l2_fltr); 1361 + return 0; 1362 + } 1477 1363 fltr_base = bnxt_get_one_fltr_rcu(bp, bp->ntp_fltr_hash_tbl, 1478 - BNXT_NTP_FLTR_HASH_SIZE, 1479 - fs->location); 1364 + BNXT_NTP_FLTR_HASH_SIZE, id); 1480 1365 if (!fltr_base) { 1481 1366 rcu_read_unlock(); 1482 1367 return -ENOENT; ··· 1533 1396 cmd->data |= RXH_IP_SRC | RXH_IP_DST | 1534 1397 RXH_L4_B_0_1 | RXH_L4_B_2_3; 1535 1398 fallthrough; 1536 - case SCTP_V4_FLOW: 1537 1399 case AH_ESP_V4_FLOW: 1400 + if (bp->rss_hash_cfg & 1401 + (VNIC_RSS_CFG_REQ_HASH_TYPE_AH_SPI_IPV4 | 1402 + VNIC_RSS_CFG_REQ_HASH_TYPE_ESP_SPI_IPV4)) 1403 + cmd->data |= RXH_IP_SRC | RXH_IP_DST | 1404 + RXH_L4_B_0_1 | RXH_L4_B_2_3; 1405 + fallthrough; 1406 + case SCTP_V4_FLOW: 1538 1407 case AH_V4_FLOW: 1539 1408 case ESP_V4_FLOW: 1540 1409 case IPV4_FLOW: ··· 1558 1415 cmd->data |= RXH_IP_SRC | RXH_IP_DST | 1559 1416 RXH_L4_B_0_1 | RXH_L4_B_2_3; 1560 1417 fallthrough; 1561 - case SCTP_V6_FLOW: 1562 1418 case AH_ESP_V6_FLOW: 1419 + if (bp->rss_hash_cfg & 1420 + (VNIC_RSS_CFG_REQ_HASH_TYPE_AH_SPI_IPV6 | 1421 + VNIC_RSS_CFG_REQ_HASH_TYPE_ESP_SPI_IPV6)) 1422 + cmd->data |= RXH_IP_SRC | RXH_IP_DST | 1423 + RXH_L4_B_0_1 | RXH_L4_B_2_3; 1424 + fallthrough; 1425 + case SCTP_V6_FLOW: 1563 1426 case AH_V6_FLOW: 1564 1427 case ESP_V6_FLOW: 1565 1428 case IPV6_FLOW: ··· 1612 1463 rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6; 1613 1464 if (tuple == 4) 1614 1465 rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6; 1466 + } else if (cmd->flow_type == AH_ESP_V4_FLOW) { 1467 + if (tuple == 4 && (!(bp->rss_cap & BNXT_RSS_CAP_AH_V4_RSS_CAP) || 1468 + !(bp->rss_cap & BNXT_RSS_CAP_ESP_V4_RSS_CAP))) 1469 + return -EINVAL; 1470 + rss_hash_cfg &= ~(VNIC_RSS_CFG_REQ_HASH_TYPE_AH_SPI_IPV4 | 1471 + VNIC_RSS_CFG_REQ_HASH_TYPE_ESP_SPI_IPV4); 1472 + if (tuple == 4) 1473 + rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_AH_SPI_IPV4 | 1474 + VNIC_RSS_CFG_REQ_HASH_TYPE_ESP_SPI_IPV4; 1475 + } else if (cmd->flow_type == AH_ESP_V6_FLOW) { 1476 + if (tuple == 4 && (!(bp->rss_cap & BNXT_RSS_CAP_AH_V6_RSS_CAP) || 1477 + !(bp->rss_cap & BNXT_RSS_CAP_ESP_V6_RSS_CAP))) 1478 + return -EINVAL; 1479 + rss_hash_cfg &= ~(VNIC_RSS_CFG_REQ_HASH_TYPE_AH_SPI_IPV6 | 1480 + VNIC_RSS_CFG_REQ_HASH_TYPE_ESP_SPI_IPV6); 1481 + if (tuple == 4) 1482 + rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_AH_SPI_IPV6 | 1483 + VNIC_RSS_CFG_REQ_HASH_TYPE_ESP_SPI_IPV6; 1615 1484 } else if (tuple == 4) { 1616 1485 return -EINVAL; 1617 1486 } ··· 1688 1521 1689 1522 case ETHTOOL_GRXCLSRLCNT: 1690 1523 cmd->rule_cnt = bp->ntp_fltr_count; 1691 - cmd->data = BNXT_NTP_FLTR_MAX_FLTR | RX_CLS_LOC_SPECIAL; 1524 + cmd->data = bp->max_fltr | RX_CLS_LOC_SPECIAL; 1692 1525 break; 1693 1526 1694 1527 case ETHTOOL_GRXCLSRLALL: ··· 1786 1619 if (rxfh->hfunc && rxfh->hfunc != ETH_RSS_HASH_TOP) 1787 1620 return -EOPNOTSUPP; 1788 1621 1789 - if (rxfh->key) 1790 - return -EOPNOTSUPP; 1622 + if (rxfh->key) { 1623 + memcpy(bp->rss_hash_key, rxfh->key, HW_HASH_KEY_SIZE); 1624 + bp->rss_hash_key_updated = true; 1625 + } 1791 1626 1792 1627 if (rxfh->indir) { 1793 1628 u32 i, pad, tbl_size = bnxt_get_rxfh_indir_size(dev); ··· 1800 1631 if (pad) 1801 1632 memset(&bp->rss_indir_tbl[i], 0, pad * sizeof(u16)); 1802 1633 } 1803 - 1634 + bnxt_clear_usr_fltrs(bp, false); 1804 1635 if (netif_running(bp->dev)) { 1805 1636 bnxt_close_nic(bp, false, false); 1806 1637 rc = bnxt_open_nic(bp, false, false);
+2
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h
··· 43 43 44 44 #define BNXT_PXP_REG_LEN 0x3110 45 45 46 + #define BNXT_IP_PROTO_FULL_MASK 0xFF 47 + 46 48 extern const struct ethtool_ops bnxt_ethtool_ops; 47 49 48 50 u32 bnxt_get_rxfh_indir_size(struct net_device *dev);