@@ -6505,6 +6505,23 @@ EXPORT_SYMBOL(napi_busy_loop);
6505
6505
6506
6506
#endif /* CONFIG_NET_RX_BUSY_POLL */
6507
6507
6508
+ static void __napi_hash_add_with_id (struct napi_struct * napi ,
6509
+ unsigned int napi_id )
6510
+ {
6511
+ napi -> napi_id = napi_id ;
6512
+ hlist_add_head_rcu (& napi -> napi_hash_node ,
6513
+ & napi_hash [napi -> napi_id % HASH_SIZE (napi_hash )]);
6514
+ }
6515
+
6516
+ static void napi_hash_add_with_id (struct napi_struct * napi ,
6517
+ unsigned int napi_id )
6518
+ {
6519
+ spin_lock (& napi_hash_lock );
6520
+ WARN_ON_ONCE (napi_by_id (napi_id ));
6521
+ __napi_hash_add_with_id (napi , napi_id );
6522
+ spin_unlock (& napi_hash_lock );
6523
+ }
6524
+
6508
6525
static void napi_hash_add (struct napi_struct * napi )
6509
6526
{
6510
6527
if (test_bit (NAPI_STATE_NO_BUSY_POLL , & napi -> state ))
@@ -6517,10 +6534,8 @@ static void napi_hash_add(struct napi_struct *napi)
6517
6534
if (unlikely (++ napi_gen_id < MIN_NAPI_ID ))
6518
6535
napi_gen_id = MIN_NAPI_ID ;
6519
6536
} while (napi_by_id (napi_gen_id ));
6520
- napi -> napi_id = napi_gen_id ;
6521
6537
6522
- hlist_add_head_rcu (& napi -> napi_hash_node ,
6523
- & napi_hash [napi -> napi_id % HASH_SIZE (napi_hash )]);
6538
+ __napi_hash_add_with_id (napi , napi_gen_id );
6524
6539
6525
6540
spin_unlock (& napi_hash_lock );
6526
6541
}
@@ -6643,6 +6658,28 @@ void netif_queue_set_napi(struct net_device *dev, unsigned int queue_index,
6643
6658
}
6644
6659
EXPORT_SYMBOL (netif_queue_set_napi );
6645
6660
6661
+ static void napi_restore_config (struct napi_struct * n )
6662
+ {
6663
+ n -> defer_hard_irqs = n -> config -> defer_hard_irqs ;
6664
+ n -> gro_flush_timeout = n -> config -> gro_flush_timeout ;
6665
+ /* a NAPI ID might be stored in the config, if so use it. if not, use
6666
+ * napi_hash_add to generate one for us. It will be saved to the config
6667
+ * in napi_disable.
6668
+ */
6669
+ if (n -> config -> napi_id )
6670
+ napi_hash_add_with_id (n , n -> config -> napi_id );
6671
+ else
6672
+ napi_hash_add (n );
6673
+ }
6674
+
6675
+ static void napi_save_config (struct napi_struct * n )
6676
+ {
6677
+ n -> config -> defer_hard_irqs = n -> defer_hard_irqs ;
6678
+ n -> config -> gro_flush_timeout = n -> gro_flush_timeout ;
6679
+ n -> config -> napi_id = n -> napi_id ;
6680
+ napi_hash_del (n );
6681
+ }
6682
+
6646
6683
void netif_napi_add_weight (struct net_device * dev , struct napi_struct * napi ,
6647
6684
int (* poll )(struct napi_struct * , int ), int weight )
6648
6685
{
@@ -6653,8 +6690,6 @@ void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi,
6653
6690
INIT_HLIST_NODE (& napi -> napi_hash_node );
6654
6691
hrtimer_init (& napi -> timer , CLOCK_MONOTONIC , HRTIMER_MODE_REL_PINNED );
6655
6692
napi -> timer .function = napi_watchdog ;
6656
- napi_set_defer_hard_irqs (napi , READ_ONCE (dev -> napi_defer_hard_irqs ));
6657
- napi_set_gro_flush_timeout (napi , READ_ONCE (dev -> gro_flush_timeout ));
6658
6693
init_gro_hash (napi );
6659
6694
napi -> skb = NULL ;
6660
6695
INIT_LIST_HEAD (& napi -> rx_list );
@@ -6672,7 +6707,13 @@ void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi,
6672
6707
set_bit (NAPI_STATE_SCHED , & napi -> state );
6673
6708
set_bit (NAPI_STATE_NPSVC , & napi -> state );
6674
6709
list_add_rcu (& napi -> dev_list , & dev -> napi_list );
6675
- napi_hash_add (napi );
6710
+
6711
+ /* default settings from sysfs are applied to all NAPIs. any per-NAPI
6712
+ * configuration will be loaded in napi_enable
6713
+ */
6714
+ napi_set_defer_hard_irqs (napi , READ_ONCE (dev -> napi_defer_hard_irqs ));
6715
+ napi_set_gro_flush_timeout (napi , READ_ONCE (dev -> gro_flush_timeout ));
6716
+
6676
6717
napi_get_frags_check (napi );
6677
6718
/* Create kthread for this napi if dev->threaded is set.
6678
6719
* Clear dev->threaded if kthread creation failed so that
@@ -6704,6 +6745,11 @@ void napi_disable(struct napi_struct *n)
6704
6745
6705
6746
hrtimer_cancel (& n -> timer );
6706
6747
6748
+ if (n -> config )
6749
+ napi_save_config (n );
6750
+ else
6751
+ napi_hash_del (n );
6752
+
6707
6753
clear_bit (NAPI_STATE_DISABLE , & n -> state );
6708
6754
}
6709
6755
EXPORT_SYMBOL (napi_disable );
@@ -6719,6 +6765,11 @@ void napi_enable(struct napi_struct *n)
6719
6765
{
6720
6766
unsigned long new , val = READ_ONCE (n -> state );
6721
6767
6768
+ if (n -> config )
6769
+ napi_restore_config (n );
6770
+ else
6771
+ napi_hash_add (n );
6772
+
6722
6773
do {
6723
6774
BUG_ON (!test_bit (NAPI_STATE_SCHED , & val ));
6724
6775
@@ -6748,7 +6799,11 @@ void __netif_napi_del(struct napi_struct *napi)
6748
6799
if (!test_and_clear_bit (NAPI_STATE_LISTED , & napi -> state ))
6749
6800
return ;
6750
6801
6751
- napi_hash_del (napi );
6802
+ if (napi -> config ) {
6803
+ napi -> index = -1 ;
6804
+ napi -> config = NULL ;
6805
+ }
6806
+
6752
6807
list_del_rcu (& napi -> dev_list );
6753
6808
napi_free_frags (napi );
6754
6809
@@ -11085,6 +11140,8 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
11085
11140
unsigned int txqs , unsigned int rxqs )
11086
11141
{
11087
11142
struct net_device * dev ;
11143
+ size_t napi_config_sz ;
11144
+ unsigned int maxqs ;
11088
11145
11089
11146
BUG_ON (strlen (name ) >= sizeof (dev -> name ));
11090
11147
@@ -11098,6 +11155,8 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
11098
11155
return NULL ;
11099
11156
}
11100
11157
11158
+ maxqs = max (txqs , rxqs );
11159
+
11101
11160
dev = kvzalloc (struct_size (dev , priv , sizeof_priv ),
11102
11161
GFP_KERNEL_ACCOUNT | __GFP_RETRY_MAYFAIL );
11103
11162
if (!dev )
@@ -11174,6 +11233,11 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
11174
11233
if (!dev -> ethtool )
11175
11234
goto free_all ;
11176
11235
11236
+ napi_config_sz = array_size (maxqs , sizeof (* dev -> napi_config ));
11237
+ dev -> napi_config = kvzalloc (napi_config_sz , GFP_KERNEL_ACCOUNT );
11238
+ if (!dev -> napi_config )
11239
+ goto free_all ;
11240
+
11177
11241
strscpy (dev -> name , name );
11178
11242
dev -> name_assign_type = name_assign_type ;
11179
11243
dev -> group = INIT_NETDEV_GROUP ;
@@ -11237,6 +11301,8 @@ void free_netdev(struct net_device *dev)
11237
11301
list_for_each_entry_safe (p , n , & dev -> napi_list , dev_list )
11238
11302
netif_napi_del (p );
11239
11303
11304
+ kvfree (dev -> napi_config );
11305
+
11240
11306
ref_tracker_dir_exit (& dev -> refcnt_tracker );
11241
11307
#ifdef CONFIG_PCPU_DEV_REFCNT
11242
11308
free_percpu (dev -> pcpu_refcnt );
0 commit comments