@@ -481,6 +481,142 @@ int wx_set_channels(struct net_device *dev,
481481}
482482EXPORT_SYMBOL (wx_set_channels );
483483
484+ u32 wx_rss_indir_size (struct net_device * netdev )
485+ {
486+ struct wx * wx = netdev_priv (netdev );
487+
488+ return wx_rss_indir_tbl_entries (wx );
489+ }
490+ EXPORT_SYMBOL (wx_rss_indir_size );
491+
492+ u32 wx_get_rxfh_key_size (struct net_device * netdev )
493+ {
494+ return WX_RSS_KEY_SIZE ;
495+ }
496+ EXPORT_SYMBOL (wx_get_rxfh_key_size );
497+
498+ static void wx_get_reta (struct wx * wx , u32 * indir )
499+ {
500+ u32 reta_size = wx_rss_indir_tbl_entries (wx );
501+ u16 rss_m = wx -> ring_feature [RING_F_RSS ].mask ;
502+
503+ if (test_bit (WX_FLAG_SRIOV_ENABLED , wx -> flags ))
504+ rss_m = wx -> ring_feature [RING_F_RSS ].indices - 1 ;
505+
506+ for (u32 i = 0 ; i < reta_size ; i ++ )
507+ indir [i ] = wx -> rss_indir_tbl [i ] & rss_m ;
508+ }
509+
510+ int wx_get_rxfh (struct net_device * netdev ,
511+ struct ethtool_rxfh_param * rxfh )
512+ {
513+ struct wx * wx = netdev_priv (netdev );
514+
515+ rxfh -> hfunc = ETH_RSS_HASH_TOP ;
516+
517+ if (rxfh -> indir )
518+ wx_get_reta (wx , rxfh -> indir );
519+
520+ if (rxfh -> key )
521+ memcpy (rxfh -> key , wx -> rss_key , WX_RSS_KEY_SIZE );
522+
523+ return 0 ;
524+ }
525+ EXPORT_SYMBOL (wx_get_rxfh );
526+
527+ int wx_set_rxfh (struct net_device * netdev ,
528+ struct ethtool_rxfh_param * rxfh ,
529+ struct netlink_ext_ack * extack )
530+ {
531+ struct wx * wx = netdev_priv (netdev );
532+ u32 reta_entries , i ;
533+
534+ if (rxfh -> hfunc != ETH_RSS_HASH_NO_CHANGE &&
535+ rxfh -> hfunc != ETH_RSS_HASH_TOP )
536+ return - EOPNOTSUPP ;
537+
538+ reta_entries = wx_rss_indir_tbl_entries (wx );
539+ /* Fill out the redirection table */
540+ if (rxfh -> indir ) {
541+ for (i = 0 ; i < reta_entries ; i ++ )
542+ wx -> rss_indir_tbl [i ] = rxfh -> indir [i ];
543+
544+ wx_store_reta (wx );
545+ }
546+
547+ /* Fill out the rss hash key */
548+ if (rxfh -> key ) {
549+ memcpy (wx -> rss_key , rxfh -> key , WX_RSS_KEY_SIZE );
550+ wx_store_rsskey (wx );
551+ }
552+
553+ return 0 ;
554+ }
555+ EXPORT_SYMBOL (wx_set_rxfh );
556+
557+ static const struct wx_rss_flow_map rss_flow_table [] = {
558+ { TCP_V4_FLOW , RXH_L4_B_0_1 | RXH_L4_B_2_3 , WX_RSS_FIELD_IPV4_TCP },
559+ { TCP_V6_FLOW , RXH_L4_B_0_1 | RXH_L4_B_2_3 , WX_RSS_FIELD_IPV6_TCP },
560+ { UDP_V4_FLOW , RXH_L4_B_0_1 | RXH_L4_B_2_3 , WX_RSS_FIELD_IPV4_UDP },
561+ { UDP_V6_FLOW , RXH_L4_B_0_1 | RXH_L4_B_2_3 , WX_RSS_FIELD_IPV6_UDP },
562+ { SCTP_V4_FLOW , RXH_L4_B_0_1 | RXH_L4_B_2_3 , WX_RSS_FIELD_IPV4_SCTP },
563+ { SCTP_V6_FLOW , RXH_L4_B_0_1 | RXH_L4_B_2_3 , WX_RSS_FIELD_IPV6_SCTP },
564+ };
565+
566+ int wx_get_rxfh_fields (struct net_device * dev ,
567+ struct ethtool_rxfh_fields * nfc )
568+ {
569+ struct wx * wx = netdev_priv (dev );
570+
571+ nfc -> data = RXH_IP_SRC | RXH_IP_DST ;
572+
573+ for (u32 i = 0 ; i < ARRAY_SIZE (rss_flow_table ); i ++ ) {
574+ const struct wx_rss_flow_map * entry = & rss_flow_table [i ];
575+
576+ if (entry -> flow_type == nfc -> flow_type ) {
577+ if (wx -> rss_flags & entry -> flag )
578+ nfc -> data |= entry -> data ;
579+ break ;
580+ }
581+ }
582+
583+ return 0 ;
584+ }
585+ EXPORT_SYMBOL (wx_get_rxfh_fields );
586+
587+ int wx_set_rxfh_fields (struct net_device * dev ,
588+ const struct ethtool_rxfh_fields * nfc ,
589+ struct netlink_ext_ack * extack )
590+ {
591+ struct wx * wx = netdev_priv (dev );
592+ u8 flags = wx -> rss_flags ;
593+
594+ if (!(nfc -> data & RXH_IP_SRC ) ||
595+ !(nfc -> data & RXH_IP_DST ))
596+ return - EINVAL ;
597+
598+ for (u32 i = 0 ; i < ARRAY_SIZE (rss_flow_table ); i ++ ) {
599+ const struct wx_rss_flow_map * entry = & rss_flow_table [i ];
600+
601+ if (entry -> flow_type == nfc -> flow_type ) {
602+ if (nfc -> data & entry -> data )
603+ flags |= entry -> flag ;
604+ else
605+ flags &= ~entry -> flag ;
606+
607+ if (flags != wx -> rss_flags ) {
608+ wx -> rss_flags = flags ;
609+ wx_config_rss_field (wx );
610+ }
611+
612+ return 0 ;
613+ }
614+ }
615+
616+ return - EINVAL ;
617+ }
618+ EXPORT_SYMBOL (wx_set_rxfh_fields );
619+
484620u32 wx_get_msglevel (struct net_device * netdev )
485621{
486622 struct wx * wx = netdev_priv (netdev );
0 commit comments