Skip to content

Commit a8545b6

Browse files
committed
Merge branch 'hv_netvsc-VF-removal-fixes'
Vitaly Kuznetsov says: ==================== hv_netvsc: fixes for VF removal path Kernel crash is reported after VF is removed and detached from netvsc device. Turns out we have multiple different (but related) issues on the VF removal path which I'm trying to address with PATCHes 2-5 of this series. PATCH1 is required to support the change. Changes since v1: - Re-arrange patches in the series to not introduce new issues [David Miller] - Add PATCH5 which fixes a new issue I discovered while testing. - Add Haiyang' A-b tags to PATCH1-4 With regards to Stephen's suggestion: I believe that switching to using RCU and eliminating vf_use_cnt/vf_inject is the right thing to do long-term, we can either put this on top of this series or do it later in net-next. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 3d7b332 + 0dbff14 commit a8545b6

File tree

3 files changed

+66
-82
lines changed

3 files changed

+66
-82
lines changed

drivers/net/hyperv/hyperv_net.h

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -644,12 +644,6 @@ struct netvsc_reconfig {
644644
u32 event;
645645
};
646646

647-
struct garp_wrk {
648-
struct work_struct dwrk;
649-
struct net_device *netdev;
650-
struct netvsc_device *netvsc_dev;
651-
};
652-
653647
/* The context of the netvsc device */
654648
struct net_device_context {
655649
/* point back to our device context */
@@ -667,7 +661,6 @@ struct net_device_context {
667661

668662
struct work_struct work;
669663
u32 msg_enable; /* debug level */
670-
struct garp_wrk gwrk;
671664

672665
struct netvsc_stats __percpu *tx_stats;
673666
struct netvsc_stats __percpu *rx_stats;
@@ -678,6 +671,15 @@ struct net_device_context {
678671

679672
/* the device is going away */
680673
bool start_remove;
674+
675+
/* State to manage the associated VF interface. */
676+
struct net_device *vf_netdev;
677+
bool vf_inject;
678+
atomic_t vf_use_cnt;
679+
/* 1: allocated, serial number is valid. 0: not allocated */
680+
u32 vf_alloc;
681+
/* Serial number of the VF to team with */
682+
u32 vf_serial;
681683
};
682684

683685
/* Per netvsc device */
@@ -733,15 +735,7 @@ struct netvsc_device {
733735
u32 max_pkt; /* max number of pkt in one send, e.g. 8 */
734736
u32 pkt_align; /* alignment bytes, e.g. 8 */
735737

736-
/* 1: allocated, serial number is valid. 0: not allocated */
737-
u32 vf_alloc;
738-
/* Serial number of the VF to team with */
739-
u32 vf_serial;
740738
atomic_t open_cnt;
741-
/* State to manage the associated VF interface. */
742-
bool vf_inject;
743-
struct net_device *vf_netdev;
744-
atomic_t vf_use_cnt;
745739
};
746740

747741
static inline struct netvsc_device *

drivers/net/hyperv/netvsc.c

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,9 @@ static struct netvsc_device *alloc_net_device(void)
7777
init_waitqueue_head(&net_device->wait_drain);
7878
net_device->destroy = false;
7979
atomic_set(&net_device->open_cnt, 0);
80-
atomic_set(&net_device->vf_use_cnt, 0);
8180
net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT;
8281
net_device->pkt_align = RNDIS_PKT_ALIGN_DEFAULT;
8382

84-
net_device->vf_netdev = NULL;
85-
net_device->vf_inject = false;
86-
8783
return net_device;
8884
}
8985

@@ -1106,24 +1102,24 @@ static void netvsc_send_table(struct hv_device *hdev,
11061102
nvscdev->send_table[i] = tab[i];
11071103
}
11081104

1109-
static void netvsc_send_vf(struct netvsc_device *nvdev,
1105+
static void netvsc_send_vf(struct net_device_context *net_device_ctx,
11101106
struct nvsp_message *nvmsg)
11111107
{
1112-
nvdev->vf_alloc = nvmsg->msg.v4_msg.vf_assoc.allocated;
1113-
nvdev->vf_serial = nvmsg->msg.v4_msg.vf_assoc.serial;
1108+
net_device_ctx->vf_alloc = nvmsg->msg.v4_msg.vf_assoc.allocated;
1109+
net_device_ctx->vf_serial = nvmsg->msg.v4_msg.vf_assoc.serial;
11141110
}
11151111

11161112
static inline void netvsc_receive_inband(struct hv_device *hdev,
1117-
struct netvsc_device *nvdev,
1118-
struct nvsp_message *nvmsg)
1113+
struct net_device_context *net_device_ctx,
1114+
struct nvsp_message *nvmsg)
11191115
{
11201116
switch (nvmsg->hdr.msg_type) {
11211117
case NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE:
11221118
netvsc_send_table(hdev, nvmsg);
11231119
break;
11241120

11251121
case NVSP_MSG4_TYPE_SEND_VF_ASSOCIATION:
1126-
netvsc_send_vf(nvdev, nvmsg);
1122+
netvsc_send_vf(net_device_ctx, nvmsg);
11271123
break;
11281124
}
11291125
}
@@ -1136,6 +1132,7 @@ static void netvsc_process_raw_pkt(struct hv_device *device,
11361132
struct vmpacket_descriptor *desc)
11371133
{
11381134
struct nvsp_message *nvmsg;
1135+
struct net_device_context *net_device_ctx = netdev_priv(ndev);
11391136

11401137
nvmsg = (struct nvsp_message *)((unsigned long)
11411138
desc + (desc->offset8 << 3));
@@ -1150,7 +1147,7 @@ static void netvsc_process_raw_pkt(struct hv_device *device,
11501147
break;
11511148

11521149
case VM_PKT_DATA_INBAND:
1153-
netvsc_receive_inband(device, net_device, nvmsg);
1150+
netvsc_receive_inband(device, net_device_ctx, nvmsg);
11541151
break;
11551152

11561153
default:

drivers/net/hyperv/netvsc_drv.c

Lines changed: 49 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -658,20 +658,19 @@ int netvsc_recv_callback(struct hv_device *device_obj,
658658
struct sk_buff *skb;
659659
struct sk_buff *vf_skb;
660660
struct netvsc_stats *rx_stats;
661-
struct netvsc_device *netvsc_dev = net_device_ctx->nvdev;
662661
u32 bytes_recvd = packet->total_data_buflen;
663662
int ret = 0;
664663

665664
if (!net || net->reg_state != NETREG_REGISTERED)
666665
return NVSP_STAT_FAIL;
667666

668-
if (READ_ONCE(netvsc_dev->vf_inject)) {
669-
atomic_inc(&netvsc_dev->vf_use_cnt);
670-
if (!READ_ONCE(netvsc_dev->vf_inject)) {
667+
if (READ_ONCE(net_device_ctx->vf_inject)) {
668+
atomic_inc(&net_device_ctx->vf_use_cnt);
669+
if (!READ_ONCE(net_device_ctx->vf_inject)) {
671670
/*
672671
* We raced; just move on.
673672
*/
674-
atomic_dec(&netvsc_dev->vf_use_cnt);
673+
atomic_dec(&net_device_ctx->vf_use_cnt);
675674
goto vf_injection_done;
676675
}
677676

@@ -683,17 +682,19 @@ int netvsc_recv_callback(struct hv_device *device_obj,
683682
* the host). Deliver these via the VF interface
684683
* in the guest.
685684
*/
686-
vf_skb = netvsc_alloc_recv_skb(netvsc_dev->vf_netdev, packet,
687-
csum_info, *data, vlan_tci);
685+
vf_skb = netvsc_alloc_recv_skb(net_device_ctx->vf_netdev,
686+
packet, csum_info, *data,
687+
vlan_tci);
688688
if (vf_skb != NULL) {
689-
++netvsc_dev->vf_netdev->stats.rx_packets;
690-
netvsc_dev->vf_netdev->stats.rx_bytes += bytes_recvd;
689+
++net_device_ctx->vf_netdev->stats.rx_packets;
690+
net_device_ctx->vf_netdev->stats.rx_bytes +=
691+
bytes_recvd;
691692
netif_receive_skb(vf_skb);
692693
} else {
693694
++net->stats.rx_dropped;
694695
ret = NVSP_STAT_FAIL;
695696
}
696-
atomic_dec(&netvsc_dev->vf_use_cnt);
697+
atomic_dec(&net_device_ctx->vf_use_cnt);
697698
return ret;
698699
}
699700

@@ -1150,17 +1151,6 @@ static void netvsc_free_netdev(struct net_device *netdev)
11501151
free_netdev(netdev);
11511152
}
11521153

1153-
static void netvsc_notify_peers(struct work_struct *wrk)
1154-
{
1155-
struct garp_wrk *gwrk;
1156-
1157-
gwrk = container_of(wrk, struct garp_wrk, dwrk);
1158-
1159-
netdev_notify_peers(gwrk->netdev);
1160-
1161-
atomic_dec(&gwrk->netvsc_dev->vf_use_cnt);
1162-
}
1163-
11641154
static struct net_device *get_netvsc_net_device(char *mac)
11651155
{
11661156
struct net_device *dev, *found = NULL;
@@ -1203,18 +1193,31 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
12031193

12041194
net_device_ctx = netdev_priv(ndev);
12051195
netvsc_dev = net_device_ctx->nvdev;
1206-
if (netvsc_dev == NULL)
1196+
if (!netvsc_dev || net_device_ctx->vf_netdev)
12071197
return NOTIFY_DONE;
12081198

12091199
netdev_info(ndev, "VF registering: %s\n", vf_netdev->name);
12101200
/*
12111201
* Take a reference on the module.
12121202
*/
12131203
try_module_get(THIS_MODULE);
1214-
netvsc_dev->vf_netdev = vf_netdev;
1204+
net_device_ctx->vf_netdev = vf_netdev;
12151205
return NOTIFY_OK;
12161206
}
12171207

1208+
static void netvsc_inject_enable(struct net_device_context *net_device_ctx)
1209+
{
1210+
net_device_ctx->vf_inject = true;
1211+
}
1212+
1213+
static void netvsc_inject_disable(struct net_device_context *net_device_ctx)
1214+
{
1215+
net_device_ctx->vf_inject = false;
1216+
1217+
/* Wait for currently active users to drain out. */
1218+
while (atomic_read(&net_device_ctx->vf_use_cnt) != 0)
1219+
udelay(50);
1220+
}
12181221

12191222
static int netvsc_vf_up(struct net_device *vf_netdev)
12201223
{
@@ -1233,11 +1236,11 @@ static int netvsc_vf_up(struct net_device *vf_netdev)
12331236
net_device_ctx = netdev_priv(ndev);
12341237
netvsc_dev = net_device_ctx->nvdev;
12351238

1236-
if ((netvsc_dev == NULL) || (netvsc_dev->vf_netdev == NULL))
1239+
if (!netvsc_dev || !net_device_ctx->vf_netdev)
12371240
return NOTIFY_DONE;
12381241

12391242
netdev_info(ndev, "VF up: %s\n", vf_netdev->name);
1240-
netvsc_dev->vf_inject = true;
1243+
netvsc_inject_enable(net_device_ctx);
12411244

12421245
/*
12431246
* Open the device before switching data path.
@@ -1252,15 +1255,8 @@ static int netvsc_vf_up(struct net_device *vf_netdev)
12521255

12531256
netif_carrier_off(ndev);
12541257

1255-
/*
1256-
* Now notify peers. We are scheduling work to
1257-
* notify peers; take a reference to prevent
1258-
* the VF interface from vanishing.
1259-
*/
1260-
atomic_inc(&netvsc_dev->vf_use_cnt);
1261-
net_device_ctx->gwrk.netdev = vf_netdev;
1262-
net_device_ctx->gwrk.netvsc_dev = netvsc_dev;
1263-
schedule_work(&net_device_ctx->gwrk.dwrk);
1258+
/* Now notify peers through VF device. */
1259+
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, vf_netdev);
12641260

12651261
return NOTIFY_OK;
12661262
}
@@ -1283,29 +1279,18 @@ static int netvsc_vf_down(struct net_device *vf_netdev)
12831279
net_device_ctx = netdev_priv(ndev);
12841280
netvsc_dev = net_device_ctx->nvdev;
12851281

1286-
if ((netvsc_dev == NULL) || (netvsc_dev->vf_netdev == NULL))
1282+
if (!netvsc_dev || !net_device_ctx->vf_netdev)
12871283
return NOTIFY_DONE;
12881284

12891285
netdev_info(ndev, "VF down: %s\n", vf_netdev->name);
1290-
netvsc_dev->vf_inject = false;
1291-
/*
1292-
* Wait for currently active users to
1293-
* drain out.
1294-
*/
1295-
1296-
while (atomic_read(&netvsc_dev->vf_use_cnt) != 0)
1297-
udelay(50);
1286+
netvsc_inject_disable(net_device_ctx);
12981287
netvsc_switch_datapath(ndev, false);
12991288
netdev_info(ndev, "Data path switched from VF: %s\n", vf_netdev->name);
13001289
rndis_filter_close(netvsc_dev);
13011290
netif_carrier_on(ndev);
1302-
/*
1303-
* Notify peers.
1304-
*/
1305-
atomic_inc(&netvsc_dev->vf_use_cnt);
1306-
net_device_ctx->gwrk.netdev = ndev;
1307-
net_device_ctx->gwrk.netvsc_dev = netvsc_dev;
1308-
schedule_work(&net_device_ctx->gwrk.dwrk);
1291+
1292+
/* Now notify peers through netvsc device. */
1293+
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, ndev);
13091294

13101295
return NOTIFY_OK;
13111296
}
@@ -1327,11 +1312,11 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev)
13271312

13281313
net_device_ctx = netdev_priv(ndev);
13291314
netvsc_dev = net_device_ctx->nvdev;
1330-
if (netvsc_dev == NULL)
1315+
if (!netvsc_dev || !net_device_ctx->vf_netdev)
13311316
return NOTIFY_DONE;
13321317
netdev_info(ndev, "VF unregistering: %s\n", vf_netdev->name);
1333-
1334-
netvsc_dev->vf_netdev = NULL;
1318+
netvsc_inject_disable(net_device_ctx);
1319+
net_device_ctx->vf_netdev = NULL;
13351320
module_put(THIS_MODULE);
13361321
return NOTIFY_OK;
13371322
}
@@ -1377,11 +1362,14 @@ static int netvsc_probe(struct hv_device *dev,
13771362

13781363
INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change);
13791364
INIT_WORK(&net_device_ctx->work, do_set_multicast);
1380-
INIT_WORK(&net_device_ctx->gwrk.dwrk, netvsc_notify_peers);
13811365

13821366
spin_lock_init(&net_device_ctx->lock);
13831367
INIT_LIST_HEAD(&net_device_ctx->reconfig_events);
13841368

1369+
atomic_set(&net_device_ctx->vf_use_cnt, 0);
1370+
net_device_ctx->vf_netdev = NULL;
1371+
net_device_ctx->vf_inject = false;
1372+
13851373
net->netdev_ops = &device_ops;
13861374

13871375
net->hw_features = NETVSC_HW_FEATURES;
@@ -1494,8 +1482,13 @@ static int netvsc_netdev_event(struct notifier_block *this,
14941482
{
14951483
struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
14961484

1497-
/* Avoid Vlan, Bonding dev with same MAC registering as VF */
1498-
if (event_dev->priv_flags & (IFF_802_1Q_VLAN | IFF_BONDING))
1485+
/* Avoid Vlan dev with same MAC registering as VF */
1486+
if (event_dev->priv_flags & IFF_802_1Q_VLAN)
1487+
return NOTIFY_DONE;
1488+
1489+
/* Avoid Bonding master dev with same MAC registering as VF */
1490+
if (event_dev->priv_flags & IFF_BONDING &&
1491+
event_dev->flags & IFF_MASTER)
14991492
return NOTIFY_DONE;
15001493

15011494
switch (event) {

0 commit comments

Comments
 (0)