@@ -360,24 +360,7 @@ struct receive_queue {
360360 struct xdp_buff * * xsk_buffs ;
361361};
362362
363- /* This structure can contain rss message with maximum settings for indirection table and keysize
364- * Note, that default structure that describes RSS configuration virtio_net_rss_config
365- * contains same info but can't handle table values.
366- * In any case, structure would be passed to virtio hw through sg_buf split by parts
367- * because table sizes may be differ according to the device configuration.
368- */
369363#define VIRTIO_NET_RSS_MAX_KEY_SIZE 40
370- struct virtio_net_ctrl_rss {
371- u32 hash_types ;
372- u16 indirection_table_mask ;
373- u16 unclassified_queue ;
374- u16 hash_cfg_reserved ; /* for HASH_CONFIG (see virtio_net_hash_config for details) */
375- u16 max_tx_vq ;
376- u8 hash_key_length ;
377- u8 key [VIRTIO_NET_RSS_MAX_KEY_SIZE ];
378-
379- u16 * indirection_table ;
380- };
381364
382365/* Control VQ buffers: protected by the rtnl lock */
383366struct control_buf {
@@ -421,7 +404,9 @@ struct virtnet_info {
421404 u16 rss_indir_table_size ;
422405 u32 rss_hash_types_supported ;
423406 u32 rss_hash_types_saved ;
424- struct virtio_net_ctrl_rss rss ;
407+ struct virtio_net_rss_config_hdr * rss_hdr ;
408+ struct virtio_net_rss_config_trailer rss_trailer ;
409+ u8 rss_hash_key_data [VIRTIO_NET_RSS_MAX_KEY_SIZE ];
425410
426411 /* Has control virtqueue */
427412 bool has_cvq ;
@@ -523,23 +508,16 @@ enum virtnet_xmit_type {
523508 VIRTNET_XMIT_TYPE_XSK ,
524509};
525510
526- static int rss_indirection_table_alloc ( struct virtio_net_ctrl_rss * rss , u16 indir_table_size )
511+ static size_t virtnet_rss_hdr_size ( const struct virtnet_info * vi )
527512{
528- if (!indir_table_size ) {
529- rss -> indirection_table = NULL ;
530- return 0 ;
531- }
513+ u16 indir_table_size = vi -> has_rss ? vi -> rss_indir_table_size : 1 ;
532514
533- rss -> indirection_table = kmalloc_array (indir_table_size , sizeof (u16 ), GFP_KERNEL );
534- if (!rss -> indirection_table )
535- return - ENOMEM ;
536-
537- return 0 ;
515+ return struct_size (vi -> rss_hdr , indirection_table , indir_table_size );
538516}
539517
540- static void rss_indirection_table_free ( struct virtio_net_ctrl_rss * rss )
518+ static size_t virtnet_rss_trailer_size ( const struct virtnet_info * vi )
541519{
542- kfree ( rss -> indirection_table );
520+ return struct_size ( & vi -> rss_trailer , hash_key_data , vi -> rss_key_size );
543521}
544522
545523/* We use the last two bits of the pointer to distinguish the xmit type. */
@@ -3638,15 +3616,16 @@ static void virtnet_rss_update_by_qpairs(struct virtnet_info *vi, u16 queue_pair
36383616
36393617 for (; i < vi -> rss_indir_table_size ; ++ i ) {
36403618 indir_val = ethtool_rxfh_indir_default (i , queue_pairs );
3641- vi -> rss . indirection_table [i ] = indir_val ;
3619+ vi -> rss_hdr -> indirection_table [i ] = cpu_to_le16 ( indir_val ) ;
36423620 }
3643- vi -> rss .max_tx_vq = queue_pairs ;
3621+ vi -> rss_trailer .max_tx_vq = cpu_to_le16 ( queue_pairs ) ;
36443622}
36453623
36463624static int virtnet_set_queues (struct virtnet_info * vi , u16 queue_pairs )
36473625{
36483626 struct virtio_net_ctrl_mq * mq __free (kfree ) = NULL ;
3649- struct virtio_net_ctrl_rss old_rss ;
3627+ struct virtio_net_rss_config_hdr * old_rss_hdr ;
3628+ struct virtio_net_rss_config_trailer old_rss_trailer ;
36503629 struct net_device * dev = vi -> dev ;
36513630 struct scatterlist sg ;
36523631
@@ -3661,24 +3640,28 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
36613640 * update (VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET below) and return directly.
36623641 */
36633642 if (vi -> has_rss && !netif_is_rxfh_configured (dev )) {
3664- memcpy (& old_rss , & vi -> rss , sizeof (old_rss ));
3665- if (rss_indirection_table_alloc (& vi -> rss , vi -> rss_indir_table_size )) {
3666- vi -> rss .indirection_table = old_rss .indirection_table ;
3643+ old_rss_hdr = vi -> rss_hdr ;
3644+ old_rss_trailer = vi -> rss_trailer ;
3645+ vi -> rss_hdr = devm_kzalloc (& dev -> dev , virtnet_rss_hdr_size (vi ), GFP_KERNEL );
3646+ if (!vi -> rss_hdr ) {
3647+ vi -> rss_hdr = old_rss_hdr ;
36673648 return - ENOMEM ;
36683649 }
36693650
3651+ * vi -> rss_hdr = * old_rss_hdr ;
36703652 virtnet_rss_update_by_qpairs (vi , queue_pairs );
36713653
36723654 if (!virtnet_commit_rss_command (vi )) {
36733655 /* restore ctrl_rss if commit_rss_command failed */
3674- rss_indirection_table_free (& vi -> rss );
3675- memcpy (& vi -> rss , & old_rss , sizeof (old_rss ));
3656+ devm_kfree (& dev -> dev , vi -> rss_hdr );
3657+ vi -> rss_hdr = old_rss_hdr ;
3658+ vi -> rss_trailer = old_rss_trailer ;
36763659
36773660 dev_warn (& dev -> dev , "Fail to set num of queue pairs to %d, because committing RSS failed\n" ,
36783661 queue_pairs );
36793662 return - EINVAL ;
36803663 }
3681- rss_indirection_table_free ( & old_rss );
3664+ devm_kfree ( & dev -> dev , old_rss_hdr );
36823665 goto succ ;
36833666 }
36843667
@@ -4121,28 +4104,12 @@ static int virtnet_set_ringparam(struct net_device *dev,
41214104static bool virtnet_commit_rss_command (struct virtnet_info * vi )
41224105{
41234106 struct net_device * dev = vi -> dev ;
4124- struct scatterlist sgs [4 ];
4125- unsigned int sg_buf_size ;
4107+ struct scatterlist sgs [2 ];
41264108
41274109 /* prepare sgs */
4128- sg_init_table (sgs , 4 );
4129-
4130- sg_buf_size = offsetof(struct virtio_net_ctrl_rss , hash_cfg_reserved );
4131- sg_set_buf (& sgs [0 ], & vi -> rss , sg_buf_size );
4132-
4133- if (vi -> has_rss ) {
4134- sg_buf_size = sizeof (uint16_t ) * vi -> rss_indir_table_size ;
4135- sg_set_buf (& sgs [1 ], vi -> rss .indirection_table , sg_buf_size );
4136- } else {
4137- sg_set_buf (& sgs [1 ], & vi -> rss .hash_cfg_reserved , sizeof (uint16_t ));
4138- }
4139-
4140- sg_buf_size = offsetof(struct virtio_net_ctrl_rss , key )
4141- - offsetof(struct virtio_net_ctrl_rss , max_tx_vq );
4142- sg_set_buf (& sgs [2 ], & vi -> rss .max_tx_vq , sg_buf_size );
4143-
4144- sg_buf_size = vi -> rss_key_size ;
4145- sg_set_buf (& sgs [3 ], vi -> rss .key , sg_buf_size );
4110+ sg_init_table (sgs , 2 );
4111+ sg_set_buf (& sgs [0 ], vi -> rss_hdr , virtnet_rss_hdr_size (vi ));
4112+ sg_set_buf (& sgs [1 ], & vi -> rss_trailer , virtnet_rss_trailer_size (vi ));
41464113
41474114 if (!virtnet_send_command (vi , VIRTIO_NET_CTRL_MQ ,
41484115 vi -> has_rss ? VIRTIO_NET_CTRL_MQ_RSS_CONFIG
@@ -4159,17 +4126,17 @@ static bool virtnet_commit_rss_command(struct virtnet_info *vi)
41594126
41604127static void virtnet_init_default_rss (struct virtnet_info * vi )
41614128{
4162- vi -> rss . hash_types = vi -> rss_hash_types_supported ;
4129+ vi -> rss_hdr -> hash_types = cpu_to_le32 ( vi -> rss_hash_types_supported ) ;
41634130 vi -> rss_hash_types_saved = vi -> rss_hash_types_supported ;
4164- vi -> rss . indirection_table_mask = vi -> rss_indir_table_size
4165- ? vi -> rss_indir_table_size - 1 : 0 ;
4166- vi -> rss . unclassified_queue = 0 ;
4131+ vi -> rss_hdr -> indirection_table_mask = vi -> rss_indir_table_size
4132+ ? cpu_to_le16 ( vi -> rss_indir_table_size - 1 ) : 0 ;
4133+ vi -> rss_hdr -> unclassified_queue = 0 ;
41674134
41684135 virtnet_rss_update_by_qpairs (vi , vi -> curr_queue_pairs );
41694136
4170- vi -> rss .hash_key_length = vi -> rss_key_size ;
4137+ vi -> rss_trailer .hash_key_length = vi -> rss_key_size ;
41714138
4172- netdev_rss_key_fill (vi -> rss . key , vi -> rss_key_size );
4139+ netdev_rss_key_fill (vi -> rss_hash_key_data , vi -> rss_key_size );
41734140}
41744141
41754142static void virtnet_get_hashflow (const struct virtnet_info * vi , struct ethtool_rxnfc * info )
@@ -4280,7 +4247,7 @@ static bool virtnet_set_hashflow(struct virtnet_info *vi, struct ethtool_rxnfc *
42804247
42814248 if (new_hashtypes != vi -> rss_hash_types_saved ) {
42824249 vi -> rss_hash_types_saved = new_hashtypes ;
4283- vi -> rss . hash_types = vi -> rss_hash_types_saved ;
4250+ vi -> rss_hdr -> hash_types = cpu_to_le32 ( vi -> rss_hash_types_saved ) ;
42844251 if (vi -> dev -> features & NETIF_F_RXHASH )
42854252 return virtnet_commit_rss_command (vi );
42864253 }
@@ -5460,11 +5427,11 @@ static int virtnet_get_rxfh(struct net_device *dev,
54605427
54615428 if (rxfh -> indir ) {
54625429 for (i = 0 ; i < vi -> rss_indir_table_size ; ++ i )
5463- rxfh -> indir [i ] = vi -> rss . indirection_table [i ];
5430+ rxfh -> indir [i ] = le16_to_cpu ( vi -> rss_hdr -> indirection_table [i ]) ;
54645431 }
54655432
54665433 if (rxfh -> key )
5467- memcpy (rxfh -> key , vi -> rss . key , vi -> rss_key_size );
5434+ memcpy (rxfh -> key , vi -> rss_hash_key_data , vi -> rss_key_size );
54685435
54695436 rxfh -> hfunc = ETH_RSS_HASH_TOP ;
54705437
@@ -5488,7 +5455,7 @@ static int virtnet_set_rxfh(struct net_device *dev,
54885455 return - EOPNOTSUPP ;
54895456
54905457 for (i = 0 ; i < vi -> rss_indir_table_size ; ++ i )
5491- vi -> rss . indirection_table [i ] = rxfh -> indir [i ];
5458+ vi -> rss_hdr -> indirection_table [i ] = cpu_to_le16 ( rxfh -> indir [i ]) ;
54925459 update = true;
54935460 }
54945461
@@ -5500,7 +5467,7 @@ static int virtnet_set_rxfh(struct net_device *dev,
55005467 if (!vi -> has_rss && !vi -> has_rss_hash_report )
55015468 return - EOPNOTSUPP ;
55025469
5503- memcpy (vi -> rss . key , rxfh -> key , vi -> rss_key_size );
5470+ memcpy (vi -> rss_hash_key_data , rxfh -> key , vi -> rss_key_size );
55045471 update = true;
55055472 }
55065473
@@ -6109,9 +6076,9 @@ static int virtnet_set_features(struct net_device *dev,
61096076
61106077 if ((dev -> features ^ features ) & NETIF_F_RXHASH ) {
61116078 if (features & NETIF_F_RXHASH )
6112- vi -> rss . hash_types = vi -> rss_hash_types_saved ;
6079+ vi -> rss_hdr -> hash_types = cpu_to_le32 ( vi -> rss_hash_types_saved ) ;
61136080 else
6114- vi -> rss . hash_types = VIRTIO_NET_HASH_REPORT_NONE ;
6081+ vi -> rss_hdr -> hash_types = cpu_to_le32 ( VIRTIO_NET_HASH_REPORT_NONE ) ;
61156082
61166083 if (!virtnet_commit_rss_command (vi ))
61176084 return - EINVAL ;
@@ -6801,9 +6768,11 @@ static int virtnet_probe(struct virtio_device *vdev)
68016768 virtio_cread16 (vdev , offsetof(struct virtio_net_config ,
68026769 rss_max_indirection_table_length ));
68036770 }
6804- err = rss_indirection_table_alloc (& vi -> rss , vi -> rss_indir_table_size );
6805- if (err )
6771+ vi -> rss_hdr = devm_kzalloc (& vdev -> dev , virtnet_rss_hdr_size (vi ), GFP_KERNEL );
6772+ if (!vi -> rss_hdr ) {
6773+ err = - ENOMEM ;
68066774 goto free ;
6775+ }
68076776
68086777 if (vi -> has_rss || vi -> has_rss_hash_report ) {
68096778 vi -> rss_key_size =
@@ -7082,8 +7051,6 @@ static void virtnet_remove(struct virtio_device *vdev)
70827051
70837052 remove_vq_common (vi );
70847053
7085- rss_indirection_table_free (& vi -> rss );
7086-
70877054 free_netdev (vi -> dev );
70887055}
70897056
0 commit comments