@@ -360,24 +360,7 @@ struct receive_queue {
360
360
struct xdp_buff * * xsk_buffs ;
361
361
};
362
362
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
- */
369
363
#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
- };
381
364
382
365
/* Control VQ buffers: protected by the rtnl lock */
383
366
struct control_buf {
@@ -421,7 +404,9 @@ struct virtnet_info {
421
404
u16 rss_indir_table_size ;
422
405
u32 rss_hash_types_supported ;
423
406
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 ];
425
410
426
411
/* Has control virtqueue */
427
412
bool has_cvq ;
@@ -523,23 +508,16 @@ enum virtnet_xmit_type {
523
508
VIRTNET_XMIT_TYPE_XSK ,
524
509
};
525
510
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 )
527
512
{
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 ;
532
514
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 );
538
516
}
539
517
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 )
541
519
{
542
- kfree ( rss -> indirection_table );
520
+ return struct_size ( & vi -> rss_trailer , hash_key_data , vi -> rss_key_size );
543
521
}
544
522
545
523
/* 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
3638
3616
3639
3617
for (; i < vi -> rss_indir_table_size ; ++ i ) {
3640
3618
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 ) ;
3642
3620
}
3643
- vi -> rss .max_tx_vq = queue_pairs ;
3621
+ vi -> rss_trailer .max_tx_vq = cpu_to_le16 ( queue_pairs ) ;
3644
3622
}
3645
3623
3646
3624
static int virtnet_set_queues (struct virtnet_info * vi , u16 queue_pairs )
3647
3625
{
3648
3626
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 ;
3650
3629
struct net_device * dev = vi -> dev ;
3651
3630
struct scatterlist sg ;
3652
3631
@@ -3661,24 +3640,28 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
3661
3640
* update (VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET below) and return directly.
3662
3641
*/
3663
3642
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 ;
3667
3648
return - ENOMEM ;
3668
3649
}
3669
3650
3651
+ * vi -> rss_hdr = * old_rss_hdr ;
3670
3652
virtnet_rss_update_by_qpairs (vi , queue_pairs );
3671
3653
3672
3654
if (!virtnet_commit_rss_command (vi )) {
3673
3655
/* 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 ;
3676
3659
3677
3660
dev_warn (& dev -> dev , "Fail to set num of queue pairs to %d, because committing RSS failed\n" ,
3678
3661
queue_pairs );
3679
3662
return - EINVAL ;
3680
3663
}
3681
- rss_indirection_table_free ( & old_rss );
3664
+ devm_kfree ( & dev -> dev , old_rss_hdr );
3682
3665
goto succ ;
3683
3666
}
3684
3667
@@ -4121,28 +4104,12 @@ static int virtnet_set_ringparam(struct net_device *dev,
4121
4104
static bool virtnet_commit_rss_command (struct virtnet_info * vi )
4122
4105
{
4123
4106
struct net_device * dev = vi -> dev ;
4124
- struct scatterlist sgs [4 ];
4125
- unsigned int sg_buf_size ;
4107
+ struct scatterlist sgs [2 ];
4126
4108
4127
4109
/* 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 ));
4146
4113
4147
4114
if (!virtnet_send_command (vi , VIRTIO_NET_CTRL_MQ ,
4148
4115
vi -> has_rss ? VIRTIO_NET_CTRL_MQ_RSS_CONFIG
@@ -4159,17 +4126,17 @@ static bool virtnet_commit_rss_command(struct virtnet_info *vi)
4159
4126
4160
4127
static void virtnet_init_default_rss (struct virtnet_info * vi )
4161
4128
{
4162
- vi -> rss . hash_types = vi -> rss_hash_types_supported ;
4129
+ vi -> rss_hdr -> hash_types = cpu_to_le32 ( vi -> rss_hash_types_supported ) ;
4163
4130
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 ;
4167
4134
4168
4135
virtnet_rss_update_by_qpairs (vi , vi -> curr_queue_pairs );
4169
4136
4170
- vi -> rss .hash_key_length = vi -> rss_key_size ;
4137
+ vi -> rss_trailer .hash_key_length = vi -> rss_key_size ;
4171
4138
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 );
4173
4140
}
4174
4141
4175
4142
static 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 *
4280
4247
4281
4248
if (new_hashtypes != vi -> rss_hash_types_saved ) {
4282
4249
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 ) ;
4284
4251
if (vi -> dev -> features & NETIF_F_RXHASH )
4285
4252
return virtnet_commit_rss_command (vi );
4286
4253
}
@@ -5460,11 +5427,11 @@ static int virtnet_get_rxfh(struct net_device *dev,
5460
5427
5461
5428
if (rxfh -> indir ) {
5462
5429
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 ]) ;
5464
5431
}
5465
5432
5466
5433
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 );
5468
5435
5469
5436
rxfh -> hfunc = ETH_RSS_HASH_TOP ;
5470
5437
@@ -5488,7 +5455,7 @@ static int virtnet_set_rxfh(struct net_device *dev,
5488
5455
return - EOPNOTSUPP ;
5489
5456
5490
5457
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 ]) ;
5492
5459
update = true;
5493
5460
}
5494
5461
@@ -5500,7 +5467,7 @@ static int virtnet_set_rxfh(struct net_device *dev,
5500
5467
if (!vi -> has_rss && !vi -> has_rss_hash_report )
5501
5468
return - EOPNOTSUPP ;
5502
5469
5503
- memcpy (vi -> rss . key , rxfh -> key , vi -> rss_key_size );
5470
+ memcpy (vi -> rss_hash_key_data , rxfh -> key , vi -> rss_key_size );
5504
5471
update = true;
5505
5472
}
5506
5473
@@ -6109,9 +6076,9 @@ static int virtnet_set_features(struct net_device *dev,
6109
6076
6110
6077
if ((dev -> features ^ features ) & NETIF_F_RXHASH ) {
6111
6078
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 ) ;
6113
6080
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 ) ;
6115
6082
6116
6083
if (!virtnet_commit_rss_command (vi ))
6117
6084
return - EINVAL ;
@@ -6801,9 +6768,11 @@ static int virtnet_probe(struct virtio_device *vdev)
6801
6768
virtio_cread16 (vdev , offsetof(struct virtio_net_config ,
6802
6769
rss_max_indirection_table_length ));
6803
6770
}
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 ;
6806
6774
goto free ;
6775
+ }
6807
6776
6808
6777
if (vi -> has_rss || vi -> has_rss_hash_report ) {
6809
6778
vi -> rss_key_size =
@@ -7082,8 +7051,6 @@ static void virtnet_remove(struct virtio_device *vdev)
7082
7051
7083
7052
remove_vq_common (vi );
7084
7053
7085
- rss_indirection_table_free (& vi -> rss );
7086
-
7087
7054
free_netdev (vi -> dev );
7088
7055
}
7089
7056
0 commit comments