@@ -665,18 +665,232 @@ vmxnet3_set_ringparam(struct net_device *netdev,
665
665
return err ;
666
666
}
667
667
668
+ static int
669
+ vmxnet3_get_rss_hash_opts (struct vmxnet3_adapter * adapter ,
670
+ struct ethtool_rxnfc * info )
671
+ {
672
+ enum Vmxnet3_RSSField rss_fields ;
673
+
674
+ if (netif_running (adapter -> netdev )) {
675
+ unsigned long flags ;
676
+
677
+ spin_lock_irqsave (& adapter -> cmd_lock , flags );
678
+
679
+ VMXNET3_WRITE_BAR1_REG (adapter , VMXNET3_REG_CMD ,
680
+ VMXNET3_CMD_GET_RSS_FIELDS );
681
+ rss_fields = VMXNET3_READ_BAR1_REG (adapter , VMXNET3_REG_CMD );
682
+ spin_unlock_irqrestore (& adapter -> cmd_lock , flags );
683
+ } else {
684
+ rss_fields = adapter -> rss_fields ;
685
+ }
686
+
687
+ info -> data = 0 ;
688
+
689
+ /* Report default options for RSS on vmxnet3 */
690
+ switch (info -> flow_type ) {
691
+ case TCP_V4_FLOW :
692
+ case TCP_V6_FLOW :
693
+ info -> data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 |
694
+ RXH_IP_SRC | RXH_IP_DST ;
695
+ break ;
696
+ case UDP_V4_FLOW :
697
+ if (rss_fields & VMXNET3_RSS_FIELDS_UDPIP4 )
698
+ info -> data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 ;
699
+ info -> data |= RXH_IP_SRC | RXH_IP_DST ;
700
+ break ;
701
+ case AH_ESP_V4_FLOW :
702
+ case AH_V4_FLOW :
703
+ case ESP_V4_FLOW :
704
+ if (rss_fields & VMXNET3_RSS_FIELDS_ESPIP4 )
705
+ info -> data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 ;
706
+ /* fallthrough */
707
+ case SCTP_V4_FLOW :
708
+ case IPV4_FLOW :
709
+ info -> data |= RXH_IP_SRC | RXH_IP_DST ;
710
+ break ;
711
+ case UDP_V6_FLOW :
712
+ if (rss_fields & VMXNET3_RSS_FIELDS_UDPIP6 )
713
+ info -> data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 ;
714
+ info -> data |= RXH_IP_SRC | RXH_IP_DST ;
715
+ break ;
716
+ case AH_ESP_V6_FLOW :
717
+ case AH_V6_FLOW :
718
+ case ESP_V6_FLOW :
719
+ case SCTP_V6_FLOW :
720
+ case IPV6_FLOW :
721
+ info -> data |= RXH_IP_SRC | RXH_IP_DST ;
722
+ break ;
723
+ default :
724
+ return - EINVAL ;
725
+ }
726
+
727
+ return 0 ;
728
+ }
729
+
730
+ static int
731
+ vmxnet3_set_rss_hash_opt (struct net_device * netdev ,
732
+ struct vmxnet3_adapter * adapter ,
733
+ struct ethtool_rxnfc * nfc )
734
+ {
735
+ enum Vmxnet3_RSSField rss_fields = adapter -> rss_fields ;
736
+
737
+ /* RSS does not support anything other than hashing
738
+ * to queues on src and dst IPs and ports
739
+ */
740
+ if (nfc -> data & ~(RXH_IP_SRC | RXH_IP_DST |
741
+ RXH_L4_B_0_1 | RXH_L4_B_2_3 ))
742
+ return - EINVAL ;
743
+
744
+ switch (nfc -> flow_type ) {
745
+ case TCP_V4_FLOW :
746
+ case TCP_V6_FLOW :
747
+ if (!(nfc -> data & RXH_IP_SRC ) ||
748
+ !(nfc -> data & RXH_IP_DST ) ||
749
+ !(nfc -> data & RXH_L4_B_0_1 ) ||
750
+ !(nfc -> data & RXH_L4_B_2_3 ))
751
+ return - EINVAL ;
752
+ break ;
753
+ case UDP_V4_FLOW :
754
+ if (!(nfc -> data & RXH_IP_SRC ) ||
755
+ !(nfc -> data & RXH_IP_DST ))
756
+ return - EINVAL ;
757
+ switch (nfc -> data & (RXH_L4_B_0_1 | RXH_L4_B_2_3 )) {
758
+ case 0 :
759
+ rss_fields &= ~VMXNET3_RSS_FIELDS_UDPIP4 ;
760
+ break ;
761
+ case (RXH_L4_B_0_1 | RXH_L4_B_2_3 ):
762
+ rss_fields |= VMXNET3_RSS_FIELDS_UDPIP4 ;
763
+ break ;
764
+ default :
765
+ return - EINVAL ;
766
+ }
767
+ break ;
768
+ case UDP_V6_FLOW :
769
+ if (!(nfc -> data & RXH_IP_SRC ) ||
770
+ !(nfc -> data & RXH_IP_DST ))
771
+ return - EINVAL ;
772
+ switch (nfc -> data & (RXH_L4_B_0_1 | RXH_L4_B_2_3 )) {
773
+ case 0 :
774
+ rss_fields &= ~VMXNET3_RSS_FIELDS_UDPIP6 ;
775
+ break ;
776
+ case (RXH_L4_B_0_1 | RXH_L4_B_2_3 ):
777
+ rss_fields |= VMXNET3_RSS_FIELDS_UDPIP6 ;
778
+ break ;
779
+ default :
780
+ return - EINVAL ;
781
+ }
782
+ break ;
783
+ case ESP_V4_FLOW :
784
+ case AH_V4_FLOW :
785
+ case AH_ESP_V4_FLOW :
786
+ if (!(nfc -> data & RXH_IP_SRC ) ||
787
+ !(nfc -> data & RXH_IP_DST ))
788
+ return - EINVAL ;
789
+ switch (nfc -> data & (RXH_L4_B_0_1 | RXH_L4_B_2_3 )) {
790
+ case 0 :
791
+ rss_fields &= ~VMXNET3_RSS_FIELDS_ESPIP4 ;
792
+ break ;
793
+ case (RXH_L4_B_0_1 | RXH_L4_B_2_3 ):
794
+ rss_fields |= VMXNET3_RSS_FIELDS_ESPIP4 ;
795
+ break ;
796
+ default :
797
+ return - EINVAL ;
798
+ }
799
+ break ;
800
+ case ESP_V6_FLOW :
801
+ case AH_V6_FLOW :
802
+ case AH_ESP_V6_FLOW :
803
+ case SCTP_V4_FLOW :
804
+ case SCTP_V6_FLOW :
805
+ if (!(nfc -> data & RXH_IP_SRC ) ||
806
+ !(nfc -> data & RXH_IP_DST ) ||
807
+ (nfc -> data & RXH_L4_B_0_1 ) ||
808
+ (nfc -> data & RXH_L4_B_2_3 ))
809
+ return - EINVAL ;
810
+ break ;
811
+ default :
812
+ return - EINVAL ;
813
+ }
814
+
815
+ /* if we changed something we need to update flags */
816
+ if (rss_fields != adapter -> rss_fields ) {
817
+ adapter -> default_rss_fields = false;
818
+ if (netif_running (netdev )) {
819
+ struct Vmxnet3_DriverShared * shared = adapter -> shared ;
820
+ union Vmxnet3_CmdInfo * cmdInfo = & shared -> cu .cmdInfo ;
821
+ unsigned long flags ;
822
+
823
+ spin_lock_irqsave (& adapter -> cmd_lock , flags );
824
+ cmdInfo -> setRssFields = rss_fields ;
825
+ VMXNET3_WRITE_BAR1_REG (adapter , VMXNET3_REG_CMD ,
826
+ VMXNET3_CMD_SET_RSS_FIELDS );
827
+
828
+ /* Not all requested RSS may get applied, so get and
829
+ * cache what was actually applied.
830
+ */
831
+ VMXNET3_WRITE_BAR1_REG (adapter , VMXNET3_REG_CMD ,
832
+ VMXNET3_CMD_GET_RSS_FIELDS );
833
+ adapter -> rss_fields =
834
+ VMXNET3_READ_BAR1_REG (adapter , VMXNET3_REG_CMD );
835
+ spin_unlock_irqrestore (& adapter -> cmd_lock , flags );
836
+ } else {
837
+ /* When the device is activated, we will try to apply
838
+ * these rules and cache the applied value later.
839
+ */
840
+ adapter -> rss_fields = rss_fields ;
841
+ }
842
+ }
843
+ return 0 ;
844
+ }
668
845
669
846
static int
670
847
vmxnet3_get_rxnfc (struct net_device * netdev , struct ethtool_rxnfc * info ,
671
848
u32 * rules )
672
849
{
673
850
struct vmxnet3_adapter * adapter = netdev_priv (netdev );
851
+ int err = 0 ;
852
+
674
853
switch (info -> cmd ) {
675
854
case ETHTOOL_GRXRINGS :
676
855
info -> data = adapter -> num_rx_queues ;
677
- return 0 ;
856
+ break ;
857
+ case ETHTOOL_GRXFH :
858
+ if (!VMXNET3_VERSION_GE_4 (adapter )) {
859
+ err = - EOPNOTSUPP ;
860
+ break ;
861
+ }
862
+ err = vmxnet3_get_rss_hash_opts (adapter , info );
863
+ break ;
864
+ default :
865
+ err = - EOPNOTSUPP ;
866
+ break ;
678
867
}
679
- return - EOPNOTSUPP ;
868
+
869
+ return err ;
870
+ }
871
+
872
+ static int
873
+ vmxnet3_set_rxnfc (struct net_device * netdev , struct ethtool_rxnfc * info )
874
+ {
875
+ struct vmxnet3_adapter * adapter = netdev_priv (netdev );
876
+ int err = 0 ;
877
+
878
+ if (!VMXNET3_VERSION_GE_4 (adapter )) {
879
+ err = - EOPNOTSUPP ;
880
+ goto done ;
881
+ }
882
+
883
+ switch (info -> cmd ) {
884
+ case ETHTOOL_SRXFH :
885
+ err = vmxnet3_set_rss_hash_opt (netdev , adapter , info );
886
+ break ;
887
+ default :
888
+ err = - EOPNOTSUPP ;
889
+ break ;
890
+ }
891
+
892
+ done :
893
+ return err ;
680
894
}
681
895
682
896
#ifdef VMXNET3_RSS
@@ -887,6 +1101,7 @@ static const struct ethtool_ops vmxnet3_ethtool_ops = {
887
1101
.get_ringparam = vmxnet3_get_ringparam ,
888
1102
.set_ringparam = vmxnet3_set_ringparam ,
889
1103
.get_rxnfc = vmxnet3_get_rxnfc ,
1104
+ .set_rxnfc = vmxnet3_set_rxnfc ,
890
1105
#ifdef VMXNET3_RSS
891
1106
.get_rxfh_indir_size = vmxnet3_get_rss_indir_size ,
892
1107
.get_rxfh = vmxnet3_get_rss ,
0 commit comments