@@ -138,8 +138,9 @@ struct virtnet_info {
138
138
/* Does the affinity hint is set for virtqueues? */
139
139
bool affinity_hint_set ;
140
140
141
- /* CPU hot plug notifier */
142
- struct notifier_block nb ;
141
+ /* CPU hotplug instances for online & dead */
142
+ struct hlist_node node ;
143
+ struct hlist_node node_dead ;
143
144
144
145
/* Control VQ buffers: protected by the rtnl lock */
145
146
struct virtio_net_ctrl_hdr ctrl_hdr ;
@@ -1237,25 +1238,53 @@ static void virtnet_set_affinity(struct virtnet_info *vi)
1237
1238
vi -> affinity_hint_set = true;
1238
1239
}
1239
1240
1240
- static int virtnet_cpu_callback (struct notifier_block * nfb ,
1241
- unsigned long action , void * hcpu )
1241
+ static int virtnet_cpu_online (unsigned int cpu , struct hlist_node * node )
1242
1242
{
1243
- struct virtnet_info * vi = container_of (nfb , struct virtnet_info , nb );
1243
+ struct virtnet_info * vi = hlist_entry_safe (node , struct virtnet_info ,
1244
+ node );
1245
+ virtnet_set_affinity (vi );
1246
+ return 0 ;
1247
+ }
1244
1248
1245
- switch (action & ~CPU_TASKS_FROZEN ) {
1246
- case CPU_ONLINE :
1247
- case CPU_DOWN_FAILED :
1248
- case CPU_DEAD :
1249
- virtnet_set_affinity (vi );
1250
- break ;
1251
- case CPU_DOWN_PREPARE :
1252
- virtnet_clean_affinity (vi , (long )hcpu );
1253
- break ;
1254
- default :
1255
- break ;
1256
- }
1249
+ static int virtnet_cpu_dead (unsigned int cpu , struct hlist_node * node )
1250
+ {
1251
+ struct virtnet_info * vi = hlist_entry_safe (node , struct virtnet_info ,
1252
+ node_dead );
1253
+ virtnet_set_affinity (vi );
1254
+ return 0 ;
1255
+ }
1257
1256
1258
- return NOTIFY_OK ;
1257
+ static int virtnet_cpu_down_prep (unsigned int cpu , struct hlist_node * node )
1258
+ {
1259
+ struct virtnet_info * vi = hlist_entry_safe (node , struct virtnet_info ,
1260
+ node );
1261
+
1262
+ virtnet_clean_affinity (vi , cpu );
1263
+ return 0 ;
1264
+ }
1265
+
1266
+ static enum cpuhp_state virtionet_online ;
1267
+
1268
+ static int virtnet_cpu_notif_add (struct virtnet_info * vi )
1269
+ {
1270
+ int ret ;
1271
+
1272
+ ret = cpuhp_state_add_instance_nocalls (virtionet_online , & vi -> node );
1273
+ if (ret )
1274
+ return ret ;
1275
+ ret = cpuhp_state_add_instance_nocalls (CPUHP_VIRT_NET_DEAD ,
1276
+ & vi -> node_dead );
1277
+ if (!ret )
1278
+ return ret ;
1279
+ cpuhp_state_remove_instance_nocalls (virtionet_online , & vi -> node );
1280
+ return ret ;
1281
+ }
1282
+
1283
+ static void virtnet_cpu_notif_remove (struct virtnet_info * vi )
1284
+ {
1285
+ cpuhp_state_remove_instance_nocalls (virtionet_online , & vi -> node );
1286
+ cpuhp_state_remove_instance_nocalls (CPUHP_VIRT_NET_DEAD ,
1287
+ & vi -> node_dead );
1259
1288
}
1260
1289
1261
1290
static void virtnet_get_ringparam (struct net_device * dev ,
@@ -1879,8 +1908,7 @@ static int virtnet_probe(struct virtio_device *vdev)
1879
1908
1880
1909
virtio_device_ready (vdev );
1881
1910
1882
- vi -> nb .notifier_call = & virtnet_cpu_callback ;
1883
- err = register_hotcpu_notifier (& vi -> nb );
1911
+ err = virtnet_cpu_notif_add (vi );
1884
1912
if (err ) {
1885
1913
pr_debug ("virtio_net: registering cpu notifier failed\n" );
1886
1914
goto free_unregister_netdev ;
@@ -1934,7 +1962,7 @@ static void virtnet_remove(struct virtio_device *vdev)
1934
1962
{
1935
1963
struct virtnet_info * vi = vdev -> priv ;
1936
1964
1937
- unregister_hotcpu_notifier ( & vi -> nb );
1965
+ virtnet_cpu_notif_remove ( vi );
1938
1966
1939
1967
/* Make sure no work handler is accessing the device. */
1940
1968
flush_work (& vi -> config_work );
@@ -1953,7 +1981,7 @@ static int virtnet_freeze(struct virtio_device *vdev)
1953
1981
struct virtnet_info * vi = vdev -> priv ;
1954
1982
int i ;
1955
1983
1956
- unregister_hotcpu_notifier ( & vi -> nb );
1984
+ virtnet_cpu_notif_remove ( vi );
1957
1985
1958
1986
/* Make sure no work handler is accessing the device */
1959
1987
flush_work (& vi -> config_work );
@@ -1997,7 +2025,7 @@ static int virtnet_restore(struct virtio_device *vdev)
1997
2025
virtnet_set_queues (vi , vi -> curr_queue_pairs );
1998
2026
rtnl_unlock ();
1999
2027
2000
- err = register_hotcpu_notifier ( & vi -> nb );
2028
+ err = virtnet_cpu_notif_add ( vi );
2001
2029
if (err )
2002
2030
return err ;
2003
2031
@@ -2039,7 +2067,41 @@ static struct virtio_driver virtio_net_driver = {
2039
2067
#endif
2040
2068
};
2041
2069
2042
- module_virtio_driver (virtio_net_driver );
2070
+ static __init int virtio_net_driver_init (void )
2071
+ {
2072
+ int ret ;
2073
+
2074
+ ret = cpuhp_setup_state_multi (CPUHP_AP_ONLINE_DYN , "AP_VIRT_NET_ONLINE" ,
2075
+ virtnet_cpu_online ,
2076
+ virtnet_cpu_down_prep );
2077
+ if (ret < 0 )
2078
+ goto out ;
2079
+ virtionet_online = ret ;
2080
+ ret = cpuhp_setup_state_multi (CPUHP_VIRT_NET_DEAD , "VIRT_NET_DEAD" ,
2081
+ NULL , virtnet_cpu_dead );
2082
+ if (ret )
2083
+ goto err_dead ;
2084
+
2085
+ ret = register_virtio_driver (& virtio_net_driver );
2086
+ if (ret )
2087
+ goto err_virtio ;
2088
+ return 0 ;
2089
+ err_virtio :
2090
+ cpuhp_remove_multi_state (CPUHP_VIRT_NET_DEAD );
2091
+ err_dead :
2092
+ cpuhp_remove_multi_state (virtionet_online );
2093
+ out :
2094
+ return ret ;
2095
+ }
2096
+ module_init (virtio_net_driver_init );
2097
+
2098
+ static __exit void virtio_net_driver_exit (void )
2099
+ {
2100
+ cpuhp_remove_multi_state (CPUHP_VIRT_NET_DEAD );
2101
+ cpuhp_remove_multi_state (virtionet_online );
2102
+ unregister_virtio_driver (& virtio_net_driver );
2103
+ }
2104
+ module_exit (virtio_net_driver_exit );
2043
2105
2044
2106
MODULE_DEVICE_TABLE (virtio , id_table );
2045
2107
MODULE_DESCRIPTION ("Virtio network driver" );
0 commit comments