diff options
author | Hadar Hen Zion <hadarh@mellanox.co.il> | 2012-07-05 00:03:49 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-07 19:23:06 -0400 |
commit | 820672812f8284143f933da8ccc60e296230d25d (patch) | |
tree | ad14607c7c82cee5478398c7c5498df1018d1a90 /drivers/net | |
parent | 592e49dda8122ab621cdc59cc429bdb968ee6364 (diff) |
net/mlx4_en: Manage flow steering rules with ethtool
Implement the ethtool APIs for attaching L2/L3/L4 based flow steering
rules to the netdevice RX rings. Added set_rxnfc callback and enhanced
the existing get_rxnfc callback.
Signed-off-by: Hadar Hen Zion <hadarh@mellanox.co.il>
Signed-off-by: Amir Vadai <amirv@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 382 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 7 |
2 files changed, 389 insertions, 0 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index 72901ce2b088..3e72a2076fb5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | |||
@@ -38,6 +38,10 @@ | |||
38 | #include "mlx4_en.h" | 38 | #include "mlx4_en.h" |
39 | #include "en_port.h" | 39 | #include "en_port.h" |
40 | 40 | ||
41 | #define EN_ETHTOOL_QP_ATTACH (1ull << 63) | ||
42 | #define EN_ETHTOOL_MAC_MASK 0xffffffffffffULL | ||
43 | #define EN_ETHTOOL_SHORT_MASK cpu_to_be16(0xffff) | ||
44 | #define EN_ETHTOOL_WORD_MASK cpu_to_be32(0xffffffff) | ||
41 | 45 | ||
42 | static void | 46 | static void |
43 | mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) | 47 | mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) |
@@ -599,16 +603,369 @@ static int mlx4_en_set_rxfh_indir(struct net_device *dev, | |||
599 | return err; | 603 | return err; |
600 | } | 604 | } |
601 | 605 | ||
606 | #define all_zeros_or_all_ones(field) \ | ||
607 | ((field) == 0 || (field) == (__force typeof(field))-1) | ||
608 | |||
609 | static int mlx4_en_validate_flow(struct net_device *dev, | ||
610 | struct ethtool_rxnfc *cmd) | ||
611 | { | ||
612 | struct ethtool_usrip4_spec *l3_mask; | ||
613 | struct ethtool_tcpip4_spec *l4_mask; | ||
614 | struct ethhdr *eth_mask; | ||
615 | u64 full_mac = ~0ull; | ||
616 | u64 zero_mac = 0; | ||
617 | |||
618 | if (cmd->fs.location >= MAX_NUM_OF_FS_RULES) | ||
619 | return -EINVAL; | ||
620 | |||
621 | switch (cmd->fs.flow_type & ~FLOW_EXT) { | ||
622 | case TCP_V4_FLOW: | ||
623 | case UDP_V4_FLOW: | ||
624 | if (cmd->fs.m_u.tcp_ip4_spec.tos) | ||
625 | return -EINVAL; | ||
626 | l4_mask = &cmd->fs.m_u.tcp_ip4_spec; | ||
627 | /* don't allow mask which isn't all 0 or 1 */ | ||
628 | if (!all_zeros_or_all_ones(l4_mask->ip4src) || | ||
629 | !all_zeros_or_all_ones(l4_mask->ip4dst) || | ||
630 | !all_zeros_or_all_ones(l4_mask->psrc) || | ||
631 | !all_zeros_or_all_ones(l4_mask->pdst)) | ||
632 | return -EINVAL; | ||
633 | break; | ||
634 | case IP_USER_FLOW: | ||
635 | l3_mask = &cmd->fs.m_u.usr_ip4_spec; | ||
636 | if (l3_mask->l4_4_bytes || l3_mask->tos || l3_mask->proto || | ||
637 | cmd->fs.h_u.usr_ip4_spec.ip_ver != ETH_RX_NFC_IP4 || | ||
638 | (!l3_mask->ip4src && !l3_mask->ip4dst) || | ||
639 | !all_zeros_or_all_ones(l3_mask->ip4src) || | ||
640 | !all_zeros_or_all_ones(l3_mask->ip4dst)) | ||
641 | return -EINVAL; | ||
642 | break; | ||
643 | case ETHER_FLOW: | ||
644 | eth_mask = &cmd->fs.m_u.ether_spec; | ||
645 | /* source mac mask must not be set */ | ||
646 | if (memcmp(eth_mask->h_source, &zero_mac, ETH_ALEN)) | ||
647 | return -EINVAL; | ||
648 | |||
649 | /* dest mac mask must be ff:ff:ff:ff:ff:ff */ | ||
650 | if (memcmp(eth_mask->h_dest, &full_mac, ETH_ALEN)) | ||
651 | return -EINVAL; | ||
652 | |||
653 | if (!all_zeros_or_all_ones(eth_mask->h_proto)) | ||
654 | return -EINVAL; | ||
655 | break; | ||
656 | default: | ||
657 | return -EINVAL; | ||
658 | } | ||
659 | |||
660 | if ((cmd->fs.flow_type & FLOW_EXT)) { | ||
661 | if (cmd->fs.m_ext.vlan_etype || | ||
662 | !(cmd->fs.m_ext.vlan_tci == 0 || | ||
663 | cmd->fs.m_ext.vlan_tci == cpu_to_be16(0xfff))) | ||
664 | return -EINVAL; | ||
665 | } | ||
666 | |||
667 | return 0; | ||
668 | } | ||
669 | |||
670 | static int add_ip_rule(struct mlx4_en_priv *priv, | ||
671 | struct ethtool_rxnfc *cmd, | ||
672 | struct list_head *list_h) | ||
673 | { | ||
674 | struct mlx4_spec_list *spec_l3; | ||
675 | struct ethtool_usrip4_spec *l3_mask = &cmd->fs.m_u.usr_ip4_spec; | ||
676 | |||
677 | spec_l3 = kzalloc(sizeof *spec_l3, GFP_KERNEL); | ||
678 | if (!spec_l3) { | ||
679 | en_err(priv, "Fail to alloc ethtool rule.\n"); | ||
680 | return -ENOMEM; | ||
681 | } | ||
682 | |||
683 | spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4; | ||
684 | spec_l3->ipv4.src_ip = cmd->fs.h_u.usr_ip4_spec.ip4src; | ||
685 | if (l3_mask->ip4src) | ||
686 | spec_l3->ipv4.src_ip_msk = EN_ETHTOOL_WORD_MASK; | ||
687 | spec_l3->ipv4.dst_ip = cmd->fs.h_u.usr_ip4_spec.ip4dst; | ||
688 | if (l3_mask->ip4dst) | ||
689 | spec_l3->ipv4.dst_ip_msk = EN_ETHTOOL_WORD_MASK; | ||
690 | list_add_tail(&spec_l3->list, list_h); | ||
691 | |||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | static int add_tcp_udp_rule(struct mlx4_en_priv *priv, | ||
696 | struct ethtool_rxnfc *cmd, | ||
697 | struct list_head *list_h, int proto) | ||
698 | { | ||
699 | struct mlx4_spec_list *spec_l3; | ||
700 | struct mlx4_spec_list *spec_l4; | ||
701 | struct ethtool_tcpip4_spec *l4_mask = &cmd->fs.m_u.tcp_ip4_spec; | ||
702 | |||
703 | spec_l3 = kzalloc(sizeof *spec_l3, GFP_KERNEL); | ||
704 | spec_l4 = kzalloc(sizeof *spec_l4, GFP_KERNEL); | ||
705 | if (!spec_l4 || !spec_l3) { | ||
706 | en_err(priv, "Fail to alloc ethtool rule.\n"); | ||
707 | kfree(spec_l3); | ||
708 | kfree(spec_l4); | ||
709 | return -ENOMEM; | ||
710 | } | ||
711 | |||
712 | spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4; | ||
713 | |||
714 | if (proto == TCP_V4_FLOW) { | ||
715 | spec_l4->id = MLX4_NET_TRANS_RULE_ID_TCP; | ||
716 | spec_l3->ipv4.src_ip = cmd->fs.h_u.tcp_ip4_spec.ip4src; | ||
717 | spec_l3->ipv4.dst_ip = cmd->fs.h_u.tcp_ip4_spec.ip4dst; | ||
718 | spec_l4->tcp_udp.src_port = cmd->fs.h_u.tcp_ip4_spec.psrc; | ||
719 | spec_l4->tcp_udp.dst_port = cmd->fs.h_u.tcp_ip4_spec.pdst; | ||
720 | } else { | ||
721 | spec_l4->id = MLX4_NET_TRANS_RULE_ID_UDP; | ||
722 | spec_l3->ipv4.src_ip = cmd->fs.h_u.udp_ip4_spec.ip4src; | ||
723 | spec_l3->ipv4.dst_ip = cmd->fs.h_u.udp_ip4_spec.ip4dst; | ||
724 | spec_l4->tcp_udp.src_port = cmd->fs.h_u.udp_ip4_spec.psrc; | ||
725 | spec_l4->tcp_udp.dst_port = cmd->fs.h_u.udp_ip4_spec.pdst; | ||
726 | } | ||
727 | |||
728 | if (l4_mask->ip4src) | ||
729 | spec_l3->ipv4.src_ip_msk = EN_ETHTOOL_WORD_MASK; | ||
730 | if (l4_mask->ip4dst) | ||
731 | spec_l3->ipv4.dst_ip_msk = EN_ETHTOOL_WORD_MASK; | ||
732 | |||
733 | if (l4_mask->psrc) | ||
734 | spec_l4->tcp_udp.src_port_msk = EN_ETHTOOL_SHORT_MASK; | ||
735 | if (l4_mask->pdst) | ||
736 | spec_l4->tcp_udp.dst_port_msk = EN_ETHTOOL_SHORT_MASK; | ||
737 | |||
738 | list_add_tail(&spec_l3->list, list_h); | ||
739 | list_add_tail(&spec_l4->list, list_h); | ||
740 | |||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | static int mlx4_en_ethtool_to_net_trans_rule(struct net_device *dev, | ||
745 | struct ethtool_rxnfc *cmd, | ||
746 | struct list_head *rule_list_h) | ||
747 | { | ||
748 | int err; | ||
749 | u64 mac; | ||
750 | __be64 be_mac; | ||
751 | struct ethhdr *eth_spec; | ||
752 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
753 | struct mlx4_spec_list *spec_l2; | ||
754 | __be64 mac_msk = cpu_to_be64(EN_ETHTOOL_MAC_MASK << 16); | ||
755 | |||
756 | err = mlx4_en_validate_flow(dev, cmd); | ||
757 | if (err) | ||
758 | return err; | ||
759 | |||
760 | spec_l2 = kzalloc(sizeof *spec_l2, GFP_KERNEL); | ||
761 | if (!spec_l2) | ||
762 | return -ENOMEM; | ||
763 | |||
764 | mac = priv->mac & EN_ETHTOOL_MAC_MASK; | ||
765 | be_mac = cpu_to_be64(mac << 16); | ||
766 | |||
767 | spec_l2->id = MLX4_NET_TRANS_RULE_ID_ETH; | ||
768 | memcpy(spec_l2->eth.dst_mac_msk, &mac_msk, ETH_ALEN); | ||
769 | if ((cmd->fs.flow_type & ~FLOW_EXT) != ETHER_FLOW) | ||
770 | memcpy(spec_l2->eth.dst_mac, &be_mac, ETH_ALEN); | ||
771 | |||
772 | if ((cmd->fs.flow_type & FLOW_EXT) && cmd->fs.m_ext.vlan_tci) { | ||
773 | spec_l2->eth.vlan_id = cmd->fs.h_ext.vlan_tci; | ||
774 | spec_l2->eth.vlan_id_msk = cpu_to_be16(0xfff); | ||
775 | } | ||
776 | |||
777 | list_add_tail(&spec_l2->list, rule_list_h); | ||
778 | |||
779 | switch (cmd->fs.flow_type & ~FLOW_EXT) { | ||
780 | case ETHER_FLOW: | ||
781 | eth_spec = &cmd->fs.h_u.ether_spec; | ||
782 | memcpy(&spec_l2->eth.dst_mac, eth_spec->h_dest, ETH_ALEN); | ||
783 | spec_l2->eth.ether_type = eth_spec->h_proto; | ||
784 | if (eth_spec->h_proto) | ||
785 | spec_l2->eth.ether_type_enable = 1; | ||
786 | break; | ||
787 | case IP_USER_FLOW: | ||
788 | err = add_ip_rule(priv, cmd, rule_list_h); | ||
789 | break; | ||
790 | case TCP_V4_FLOW: | ||
791 | err = add_tcp_udp_rule(priv, cmd, rule_list_h, TCP_V4_FLOW); | ||
792 | break; | ||
793 | case UDP_V4_FLOW: | ||
794 | err = add_tcp_udp_rule(priv, cmd, rule_list_h, UDP_V4_FLOW); | ||
795 | break; | ||
796 | } | ||
797 | |||
798 | return err; | ||
799 | } | ||
800 | |||
801 | static int mlx4_en_flow_replace(struct net_device *dev, | ||
802 | struct ethtool_rxnfc *cmd) | ||
803 | { | ||
804 | int err; | ||
805 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
806 | struct ethtool_flow_id *loc_rule; | ||
807 | struct mlx4_spec_list *spec, *tmp_spec; | ||
808 | u32 qpn; | ||
809 | u64 reg_id; | ||
810 | |||
811 | struct mlx4_net_trans_rule rule = { | ||
812 | .queue_mode = MLX4_NET_TRANS_Q_FIFO, | ||
813 | .exclusive = 0, | ||
814 | .allow_loopback = 1, | ||
815 | .promisc_mode = MLX4_FS_PROMISC_NONE, | ||
816 | }; | ||
817 | |||
818 | rule.port = priv->port; | ||
819 | rule.priority = MLX4_DOMAIN_ETHTOOL | cmd->fs.location; | ||
820 | INIT_LIST_HEAD(&rule.list); | ||
821 | |||
822 | /* Allow direct QP attaches if the EN_ETHTOOL_QP_ATTACH flag is set */ | ||
823 | if (cmd->fs.ring_cookie == RX_CLS_FLOW_DISC) | ||
824 | return -EINVAL; | ||
825 | else if (cmd->fs.ring_cookie & EN_ETHTOOL_QP_ATTACH) { | ||
826 | qpn = cmd->fs.ring_cookie & (EN_ETHTOOL_QP_ATTACH - 1); | ||
827 | } else { | ||
828 | if (cmd->fs.ring_cookie >= priv->rx_ring_num) { | ||
829 | en_warn(priv, "rxnfc: RX ring (%llu) doesn't exist.\n", | ||
830 | cmd->fs.ring_cookie); | ||
831 | return -EINVAL; | ||
832 | } | ||
833 | qpn = priv->rss_map.qps[cmd->fs.ring_cookie].qpn; | ||
834 | if (!qpn) { | ||
835 | en_warn(priv, "rxnfc: RX ring (%llu) is inactive.\n", | ||
836 | cmd->fs.ring_cookie); | ||
837 | return -EINVAL; | ||
838 | } | ||
839 | } | ||
840 | rule.qpn = qpn; | ||
841 | err = mlx4_en_ethtool_to_net_trans_rule(dev, cmd, &rule.list); | ||
842 | if (err) | ||
843 | goto out_free_list; | ||
844 | |||
845 | loc_rule = &priv->ethtool_rules[cmd->fs.location]; | ||
846 | if (loc_rule->id) { | ||
847 | err = mlx4_flow_detach(priv->mdev->dev, loc_rule->id); | ||
848 | if (err) { | ||
849 | en_err(priv, "Fail to detach network rule at location %d. registration id = %llx\n", | ||
850 | cmd->fs.location, loc_rule->id); | ||
851 | goto out_free_list; | ||
852 | } | ||
853 | loc_rule->id = 0; | ||
854 | memset(&loc_rule->flow_spec, 0, | ||
855 | sizeof(struct ethtool_rx_flow_spec)); | ||
856 | } | ||
857 | err = mlx4_flow_attach(priv->mdev->dev, &rule, ®_id); | ||
858 | if (err) { | ||
859 | en_err(priv, "Fail to attach network rule at location %d.\n", | ||
860 | cmd->fs.location); | ||
861 | goto out_free_list; | ||
862 | } | ||
863 | loc_rule->id = reg_id; | ||
864 | memcpy(&loc_rule->flow_spec, &cmd->fs, | ||
865 | sizeof(struct ethtool_rx_flow_spec)); | ||
866 | |||
867 | out_free_list: | ||
868 | list_for_each_entry_safe(spec, tmp_spec, &rule.list, list) { | ||
869 | list_del(&spec->list); | ||
870 | kfree(spec); | ||
871 | } | ||
872 | return err; | ||
873 | } | ||
874 | |||
875 | static int mlx4_en_flow_detach(struct net_device *dev, | ||
876 | struct ethtool_rxnfc *cmd) | ||
877 | { | ||
878 | int err = 0; | ||
879 | struct ethtool_flow_id *rule; | ||
880 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
881 | |||
882 | if (cmd->fs.location >= MAX_NUM_OF_FS_RULES) | ||
883 | return -EINVAL; | ||
884 | |||
885 | rule = &priv->ethtool_rules[cmd->fs.location]; | ||
886 | if (!rule->id) { | ||
887 | err = -ENOENT; | ||
888 | goto out; | ||
889 | } | ||
890 | |||
891 | err = mlx4_flow_detach(priv->mdev->dev, rule->id); | ||
892 | if (err) { | ||
893 | en_err(priv, "Fail to detach network rule at location %d. registration id = 0x%llx\n", | ||
894 | cmd->fs.location, rule->id); | ||
895 | goto out; | ||
896 | } | ||
897 | rule->id = 0; | ||
898 | memset(&rule->flow_spec, 0, sizeof(struct ethtool_rx_flow_spec)); | ||
899 | out: | ||
900 | return err; | ||
901 | |||
902 | } | ||
903 | |||
904 | static int mlx4_en_get_flow(struct net_device *dev, struct ethtool_rxnfc *cmd, | ||
905 | int loc) | ||
906 | { | ||
907 | int err = 0; | ||
908 | struct ethtool_flow_id *rule; | ||
909 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
910 | |||
911 | if (loc < 0 || loc >= MAX_NUM_OF_FS_RULES) | ||
912 | return -EINVAL; | ||
913 | |||
914 | rule = &priv->ethtool_rules[loc]; | ||
915 | if (rule->id) | ||
916 | memcpy(&cmd->fs, &rule->flow_spec, | ||
917 | sizeof(struct ethtool_rx_flow_spec)); | ||
918 | else | ||
919 | err = -ENOENT; | ||
920 | |||
921 | return err; | ||
922 | } | ||
923 | |||
924 | static int mlx4_en_get_num_flows(struct mlx4_en_priv *priv) | ||
925 | { | ||
926 | |||
927 | int i, res = 0; | ||
928 | for (i = 0; i < MAX_NUM_OF_FS_RULES; i++) { | ||
929 | if (priv->ethtool_rules[i].id) | ||
930 | res++; | ||
931 | } | ||
932 | return res; | ||
933 | |||
934 | } | ||
935 | |||
602 | static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, | 936 | static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, |
603 | u32 *rule_locs) | 937 | u32 *rule_locs) |
604 | { | 938 | { |
605 | struct mlx4_en_priv *priv = netdev_priv(dev); | 939 | struct mlx4_en_priv *priv = netdev_priv(dev); |
940 | struct mlx4_en_dev *mdev = priv->mdev; | ||
606 | int err = 0; | 941 | int err = 0; |
942 | int i = 0, priority = 0; | ||
943 | |||
944 | if ((cmd->cmd == ETHTOOL_GRXCLSRLCNT || | ||
945 | cmd->cmd == ETHTOOL_GRXCLSRULE || | ||
946 | cmd->cmd == ETHTOOL_GRXCLSRLALL) && | ||
947 | mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) | ||
948 | return -EINVAL; | ||
607 | 949 | ||
608 | switch (cmd->cmd) { | 950 | switch (cmd->cmd) { |
609 | case ETHTOOL_GRXRINGS: | 951 | case ETHTOOL_GRXRINGS: |
610 | cmd->data = priv->rx_ring_num; | 952 | cmd->data = priv->rx_ring_num; |
611 | break; | 953 | break; |
954 | case ETHTOOL_GRXCLSRLCNT: | ||
955 | cmd->rule_cnt = mlx4_en_get_num_flows(priv); | ||
956 | break; | ||
957 | case ETHTOOL_GRXCLSRULE: | ||
958 | err = mlx4_en_get_flow(dev, cmd, cmd->fs.location); | ||
959 | break; | ||
960 | case ETHTOOL_GRXCLSRLALL: | ||
961 | while ((!err || err == -ENOENT) && priority < cmd->rule_cnt) { | ||
962 | err = mlx4_en_get_flow(dev, cmd, i); | ||
963 | if (!err) | ||
964 | rule_locs[priority++] = i; | ||
965 | i++; | ||
966 | } | ||
967 | err = 0; | ||
968 | break; | ||
612 | default: | 969 | default: |
613 | err = -EOPNOTSUPP; | 970 | err = -EOPNOTSUPP; |
614 | break; | 971 | break; |
@@ -617,6 +974,30 @@ static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, | |||
617 | return err; | 974 | return err; |
618 | } | 975 | } |
619 | 976 | ||
977 | static int mlx4_en_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) | ||
978 | { | ||
979 | int err = 0; | ||
980 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
981 | struct mlx4_en_dev *mdev = priv->mdev; | ||
982 | |||
983 | if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) | ||
984 | return -EINVAL; | ||
985 | |||
986 | switch (cmd->cmd) { | ||
987 | case ETHTOOL_SRXCLSRLINS: | ||
988 | err = mlx4_en_flow_replace(dev, cmd); | ||
989 | break; | ||
990 | case ETHTOOL_SRXCLSRLDEL: | ||
991 | err = mlx4_en_flow_detach(dev, cmd); | ||
992 | break; | ||
993 | default: | ||
994 | en_warn(priv, "Unsupported ethtool command. (%d)\n", cmd->cmd); | ||
995 | return -EINVAL; | ||
996 | } | ||
997 | |||
998 | return err; | ||
999 | } | ||
1000 | |||
620 | const struct ethtool_ops mlx4_en_ethtool_ops = { | 1001 | const struct ethtool_ops mlx4_en_ethtool_ops = { |
621 | .get_drvinfo = mlx4_en_get_drvinfo, | 1002 | .get_drvinfo = mlx4_en_get_drvinfo, |
622 | .get_settings = mlx4_en_get_settings, | 1003 | .get_settings = mlx4_en_get_settings, |
@@ -637,6 +1018,7 @@ const struct ethtool_ops mlx4_en_ethtool_ops = { | |||
637 | .get_ringparam = mlx4_en_get_ringparam, | 1018 | .get_ringparam = mlx4_en_get_ringparam, |
638 | .set_ringparam = mlx4_en_set_ringparam, | 1019 | .set_ringparam = mlx4_en_set_ringparam, |
639 | .get_rxnfc = mlx4_en_get_rxnfc, | 1020 | .get_rxnfc = mlx4_en_get_rxnfc, |
1021 | .set_rxnfc = mlx4_en_set_rxnfc, | ||
640 | .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size, | 1022 | .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size, |
641 | .get_rxfh_indir = mlx4_en_get_rxfh_indir, | 1023 | .get_rxfh_indir = mlx4_en_get_rxfh_indir, |
642 | .set_rxfh_indir = mlx4_en_set_rxfh_indir, | 1024 | .set_rxfh_indir = mlx4_en_set_rxfh_indir, |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 2d6dabe7f55d..8882e70493fe 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | |||
@@ -75,6 +75,7 @@ | |||
75 | #define STAMP_SHIFT 31 | 75 | #define STAMP_SHIFT 31 |
76 | #define STAMP_VAL 0x7fffffff | 76 | #define STAMP_VAL 0x7fffffff |
77 | #define STATS_DELAY (HZ / 4) | 77 | #define STATS_DELAY (HZ / 4) |
78 | #define MAX_NUM_OF_FS_RULES 256 | ||
78 | 79 | ||
79 | /* Typical TSO descriptor with 16 gather entries is 352 bytes... */ | 80 | /* Typical TSO descriptor with 16 gather entries is 352 bytes... */ |
80 | #define MAX_DESC_SIZE 512 | 81 | #define MAX_DESC_SIZE 512 |
@@ -435,6 +436,11 @@ struct mlx4_en_frag_info { | |||
435 | 436 | ||
436 | #endif | 437 | #endif |
437 | 438 | ||
439 | struct ethtool_flow_id { | ||
440 | struct ethtool_rx_flow_spec flow_spec; | ||
441 | u64 id; | ||
442 | }; | ||
443 | |||
438 | struct mlx4_en_priv { | 444 | struct mlx4_en_priv { |
439 | struct mlx4_en_dev *mdev; | 445 | struct mlx4_en_dev *mdev; |
440 | struct mlx4_en_port_profile *prof; | 446 | struct mlx4_en_port_profile *prof; |
@@ -444,6 +450,7 @@ struct mlx4_en_priv { | |||
444 | struct net_device_stats ret_stats; | 450 | struct net_device_stats ret_stats; |
445 | struct mlx4_en_port_state port_state; | 451 | struct mlx4_en_port_state port_state; |
446 | spinlock_t stats_lock; | 452 | spinlock_t stats_lock; |
453 | struct ethtool_flow_id ethtool_rules[MAX_NUM_OF_FS_RULES]; | ||
447 | 454 | ||
448 | unsigned long last_moder_packets[MAX_RX_RINGS]; | 455 | unsigned long last_moder_packets[MAX_RX_RINGS]; |
449 | unsigned long last_moder_tx_packets; | 456 | unsigned long last_moder_tx_packets; |