diff options
author | Takashi Iwai <tiwai@suse.de> | 2021-01-26 07:51:48 +0100 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2021-01-26 07:51:48 +0100 |
commit | 4f2da3324eaff382ab1c6aaef8c10180b2f4d08c (patch) | |
tree | 38dab378ba4ad014d83151f020cc1e5979be0d6d /net/core/dev.c | |
parent | 6755568ad111394da224c823e8baf31a05a1469c (diff) | |
parent | 30e88d017fcbeb50c4b07577fe059558361067e7 (diff) | |
download | lwn-4f2da3324eaff382ab1c6aaef8c10180b2f4d08c.tar.gz lwn-4f2da3324eaff382ab1c6aaef8c10180b2f4d08c.zip |
Merge tag 'tags/isa-void-remove-callback' into for-next
isa: Make the remove callback for isa drivers return void
Link: https://lore.kernel.org/r/20210122092449.426097-1-uwe@kleine-koenig.org
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 8fa739259041..c360bb5367e2 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -9661,9 +9661,15 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, } } - if ((features & NETIF_F_HW_TLS_TX) && !(features & NETIF_F_HW_CSUM)) { - netdev_dbg(dev, "Dropping TLS TX HW offload feature since no CSUM feature.\n"); - features &= ~NETIF_F_HW_TLS_TX; + if (features & NETIF_F_HW_TLS_TX) { + bool ip_csum = (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) == + (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + bool hw_csum = features & NETIF_F_HW_CSUM; + + if (!ip_csum && !hw_csum) { + netdev_dbg(dev, "Dropping TLS TX HW offload feature since no CSUM feature.\n"); + features &= ~NETIF_F_HW_TLS_TX; + } } return features; @@ -10077,17 +10083,11 @@ int register_netdevice(struct net_device *dev) ret = call_netdevice_notifiers(NETDEV_REGISTER, dev); ret = notifier_to_errno(ret); if (ret) { + /* Expect explicit free_netdev() on failure */ + dev->needs_free_netdev = false; rollback_registered(dev); - rcu_barrier(); - - dev->reg_state = NETREG_UNREGISTERED; - /* We should put the kobject that hold in - * netdev_unregister_kobject(), otherwise - * the net device cannot be freed when - * driver calls free_netdev(), because the - * kobject is being hold. - */ - kobject_put(&dev->dev.kobj); + net_set_todo(dev); + goto out; } /* * Prevent userspace races by waiting until the network @@ -10631,6 +10631,17 @@ void free_netdev(struct net_device *dev) struct napi_struct *p, *n; might_sleep(); + + /* When called immediately after register_netdevice() failed the unwind + * handling may still be dismantling the device. Handle that case by + * deferring the free. + */ + if (dev->reg_state == NETREG_UNREGISTERING) { + ASSERT_RTNL(); + dev->needs_free_netdev = true; + return; + } + netif_free_tx_queues(dev); netif_free_rx_queues(dev); |