developer | 7e32f7e | 2022-05-18 21:10:08 +0800 | [diff] [blame] | 1 | From 1a33e10e4a95cb109ff1145098175df3113313ef Mon Sep 17 00:00:00 2001 |
| 2 | From: Cong Wang <xiyou.wangcong@gmail.com> |
| 3 | Date: Sat, 2 May 2020 22:22:19 -0700 |
| 4 | Subject: net: partially revert dynamic lockdep key changes |
| 5 | |
| 6 | This patch reverts the folowing commits: |
| 7 | |
| 8 | commit 064ff66e2bef84f1153087612032b5b9eab005bd |
| 9 | "bonding: add missing netdev_update_lockdep_key()" |
| 10 | |
| 11 | commit 53d374979ef147ab51f5d632dfe20b14aebeccd0 |
| 12 | "net: avoid updating qdisc_xmit_lock_key in netdev_update_lockdep_key()" |
| 13 | |
| 14 | commit 1f26c0d3d24125992ab0026b0dab16c08df947c7 |
| 15 | "net: fix kernel-doc warning in <linux/netdevice.h>" |
| 16 | |
| 17 | commit ab92d68fc22f9afab480153bd82a20f6e2533769 |
| 18 | "net: core: add generic lockdep keys" |
| 19 | |
| 20 | but keeps the addr_list_lock_key because we still lock |
| 21 | addr_list_lock nestedly on stack devices, unlikely xmit_lock |
| 22 | this is safe because we don't take addr_list_lock on any fast |
| 23 | path. |
| 24 | |
| 25 | Reported-and-tested-by: syzbot+aaa6fa4949cc5d9b7b25@syzkaller.appspotmail.com |
| 26 | Cc: Dmitry Vyukov <dvyukov@google.com> |
| 27 | Cc: Taehee Yoo <ap420073@gmail.com> |
| 28 | Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> |
| 29 | Acked-by: Taehee Yoo <ap420073@gmail.com> |
| 30 | Signed-off-by: David S. Miller <davem@davemloft.net> |
| 31 | --- |
| 32 | drivers/net/bonding/bond_main.c | 1 + |
| 33 | drivers/net/ethernet/netronome/nfp/nfp_net_repr.c | 16 ++++ |
| 34 | drivers/net/hamradio/bpqether.c | 20 +++++ |
| 35 | drivers/net/hyperv/netvsc_drv.c | 2 + |
| 36 | drivers/net/ipvlan/ipvlan_main.c | 2 + |
| 37 | drivers/net/macsec.c | 2 + |
| 38 | drivers/net/macvlan.c | 2 + |
| 39 | drivers/net/ppp/ppp_generic.c | 2 + |
| 40 | drivers/net/team/team.c | 1 + |
| 41 | drivers/net/vrf.c | 1 + |
| 42 | drivers/net/wireless/intersil/hostap/hostap_hw.c | 22 ++++++ |
| 43 | include/linux/netdevice.h | 27 +++++-- |
| 44 | net/8021q/vlan_dev.c | 21 ++++++ |
| 45 | net/batman-adv/soft-interface.c | 30 ++++++++ |
| 46 | net/bluetooth/6lowpan.c | 8 ++ |
| 47 | net/core/dev.c | 90 ++++++++++++++++++----- |
| 48 | net/dsa/slave.c | 12 +++ |
| 49 | net/ieee802154/6lowpan/core.c | 8 ++ |
| 50 | net/l2tp/l2tp_eth.c | 1 + |
| 51 | net/netrom/af_netrom.c | 21 ++++++ |
| 52 | net/rose/af_rose.c | 21 ++++++ |
| 53 | net/sched/sch_generic.c | 17 +++-- |
| 54 | 22 files changed, 294 insertions(+), 33 deletions(-) |
| 55 | |
| 56 | diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c |
| 57 | index 2e70e43c5df5c..d01871321d220 100644 |
| 58 | --- a/drivers/net/bonding/bond_main.c |
| 59 | +++ b/drivers/net/bonding/bond_main.c |
| 60 | @@ -4898,6 +4898,7 @@ static int bond_init(struct net_device *bond_dev) |
| 61 | spin_lock_init(&bond->stats_lock); |
| 62 | lockdep_register_key(&bond->stats_lock_key); |
| 63 | lockdep_set_class(&bond->stats_lock, &bond->stats_lock_key); |
| 64 | + netdev_lockdep_set_classes(bond_dev); |
| 65 | |
| 66 | list_add_tail(&bond->bond_list, &bn->dev_list); |
| 67 | |
| 68 | diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c |
| 69 | index 79d72c88bbef2..b3cabc274121b 100644 |
| 70 | --- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c |
| 71 | +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c |
| 72 | @@ -299,6 +299,20 @@ static void nfp_repr_clean(struct nfp_repr *repr) |
| 73 | nfp_port_free(repr->port); |
| 74 | } |
| 75 | |
| 76 | +static struct lock_class_key nfp_repr_netdev_xmit_lock_key; |
| 77 | + |
| 78 | +static void nfp_repr_set_lockdep_class_one(struct net_device *dev, |
| 79 | + struct netdev_queue *txq, |
| 80 | + void *_unused) |
| 81 | +{ |
| 82 | + lockdep_set_class(&txq->_xmit_lock, &nfp_repr_netdev_xmit_lock_key); |
| 83 | +} |
| 84 | + |
| 85 | +static void nfp_repr_set_lockdep_class(struct net_device *dev) |
| 86 | +{ |
| 87 | + netdev_for_each_tx_queue(dev, nfp_repr_set_lockdep_class_one, NULL); |
| 88 | +} |
| 89 | + |
| 90 | int nfp_repr_init(struct nfp_app *app, struct net_device *netdev, |
| 91 | u32 cmsg_port_id, struct nfp_port *port, |
| 92 | struct net_device *pf_netdev) |
| 93 | @@ -308,6 +322,8 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev, |
| 94 | u32 repr_cap = nn->tlv_caps.repr_cap; |
| 95 | int err; |
| 96 | |
| 97 | + nfp_repr_set_lockdep_class(netdev); |
| 98 | + |
| 99 | repr->port = port; |
| 100 | repr->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL); |
| 101 | if (!repr->dst) |
| 102 | diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c |
| 103 | index fbea6f232819e..206688154fdfa 100644 |
| 104 | --- a/drivers/net/hamradio/bpqether.c |
| 105 | +++ b/drivers/net/hamradio/bpqether.c |
| 106 | @@ -107,6 +107,25 @@ struct bpqdev { |
| 107 | |
| 108 | static LIST_HEAD(bpq_devices); |
| 109 | |
| 110 | +/* |
| 111 | + * bpqether network devices are paired with ethernet devices below them, so |
| 112 | + * form a special "super class" of normal ethernet devices; split their locks |
| 113 | + * off into a separate class since they always nest. |
| 114 | + */ |
| 115 | +static struct lock_class_key bpq_netdev_xmit_lock_key; |
| 116 | + |
| 117 | +static void bpq_set_lockdep_class_one(struct net_device *dev, |
| 118 | + struct netdev_queue *txq, |
| 119 | + void *_unused) |
| 120 | +{ |
| 121 | + lockdep_set_class(&txq->_xmit_lock, &bpq_netdev_xmit_lock_key); |
| 122 | +} |
| 123 | + |
| 124 | +static void bpq_set_lockdep_class(struct net_device *dev) |
| 125 | +{ |
| 126 | + netdev_for_each_tx_queue(dev, bpq_set_lockdep_class_one, NULL); |
| 127 | +} |
| 128 | + |
| 129 | /* ------------------------------------------------------------------------ */ |
| 130 | |
| 131 | |
| 132 | @@ -477,6 +496,7 @@ static int bpq_new_device(struct net_device *edev) |
| 133 | err = register_netdevice(ndev); |
| 134 | if (err) |
| 135 | goto error; |
| 136 | + bpq_set_lockdep_class(ndev); |
| 137 | |
| 138 | /* List protected by RTNL */ |
| 139 | list_add_rcu(&bpq->bpq_list, &bpq_devices); |
| 140 | diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c |
| 141 | index d8e86bdbfba1e..c0b647a4c8934 100644 |
| 142 | --- a/drivers/net/hyperv/netvsc_drv.c |
| 143 | +++ b/drivers/net/hyperv/netvsc_drv.c |
| 144 | @@ -2456,6 +2456,8 @@ static int netvsc_probe(struct hv_device *dev, |
| 145 | NETIF_F_HW_VLAN_CTAG_RX; |
| 146 | net->vlan_features = net->features; |
| 147 | |
| 148 | + netdev_lockdep_set_classes(net); |
| 149 | + |
| 150 | /* MTU range: 68 - 1500 or 65521 */ |
| 151 | net->min_mtu = NETVSC_MTU_MIN; |
| 152 | if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2) |
| 153 | diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c |
| 154 | index f195f278a83aa..15e87c097b0b3 100644 |
| 155 | --- a/drivers/net/ipvlan/ipvlan_main.c |
| 156 | +++ b/drivers/net/ipvlan/ipvlan_main.c |
| 157 | @@ -131,6 +131,8 @@ static int ipvlan_init(struct net_device *dev) |
| 158 | dev->gso_max_segs = phy_dev->gso_max_segs; |
| 159 | dev->hard_header_len = phy_dev->hard_header_len; |
| 160 | |
| 161 | + netdev_lockdep_set_classes(dev); |
| 162 | + |
| 163 | ipvlan->pcpu_stats = netdev_alloc_pcpu_stats(struct ipvl_pcpu_stats); |
| 164 | if (!ipvlan->pcpu_stats) |
| 165 | return -ENOMEM; |
| 166 | diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c |
| 167 | index 758baf7cb8a16..ea3f25cc79efa 100644 |
| 168 | --- a/drivers/net/macsec.c |
| 169 | +++ b/drivers/net/macsec.c |
| 170 | @@ -4047,6 +4047,8 @@ static int macsec_newlink(struct net *net, struct net_device *dev, |
| 171 | if (err < 0) |
| 172 | return err; |
| 173 | |
| 174 | + netdev_lockdep_set_classes(dev); |
| 175 | + |
| 176 | err = netdev_upper_dev_link(real_dev, dev, extack); |
| 177 | if (err < 0) |
| 178 | goto unregister; |
| 179 | diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c |
| 180 | index d45600e0a38cd..34eb073cdd744 100644 |
| 181 | --- a/drivers/net/macvlan.c |
| 182 | +++ b/drivers/net/macvlan.c |
| 183 | @@ -890,6 +890,8 @@ static int macvlan_init(struct net_device *dev) |
| 184 | dev->gso_max_segs = lowerdev->gso_max_segs; |
| 185 | dev->hard_header_len = lowerdev->hard_header_len; |
| 186 | |
| 187 | + netdev_lockdep_set_classes(dev); |
| 188 | + |
| 189 | vlan->pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); |
| 190 | if (!vlan->pcpu_stats) |
| 191 | return -ENOMEM; |
| 192 | diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c |
| 193 | index 22cc2cb9d878f..7d005896a0f93 100644 |
| 194 | --- a/drivers/net/ppp/ppp_generic.c |
| 195 | +++ b/drivers/net/ppp/ppp_generic.c |
| 196 | @@ -1410,6 +1410,8 @@ static int ppp_dev_init(struct net_device *dev) |
| 197 | { |
| 198 | struct ppp *ppp; |
| 199 | |
| 200 | + netdev_lockdep_set_classes(dev); |
| 201 | + |
| 202 | ppp = netdev_priv(dev); |
| 203 | /* Let the netdevice take a reference on the ppp file. This ensures |
| 204 | * that ppp_destroy_interface() won't run before the device gets |
| 205 | diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c |
| 206 | index 04845a4017f93..8c1e02752ff61 100644 |
| 207 | --- a/drivers/net/team/team.c |
| 208 | +++ b/drivers/net/team/team.c |
| 209 | @@ -1647,6 +1647,7 @@ static int team_init(struct net_device *dev) |
| 210 | |
| 211 | lockdep_register_key(&team->team_lock_key); |
| 212 | __mutex_init(&team->lock, "team->team_lock_key", &team->team_lock_key); |
| 213 | + netdev_lockdep_set_classes(dev); |
| 214 | |
| 215 | return 0; |
| 216 | |
| 217 | diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c |
| 218 | index 56f8aab46f89b..43928a1c2f2a4 100644 |
| 219 | --- a/drivers/net/vrf.c |
| 220 | +++ b/drivers/net/vrf.c |
| 221 | @@ -867,6 +867,7 @@ static int vrf_dev_init(struct net_device *dev) |
| 222 | |
| 223 | /* similarly, oper state is irrelevant; set to up to avoid confusion */ |
| 224 | dev->operstate = IF_OPER_UP; |
| 225 | + netdev_lockdep_set_classes(dev); |
| 226 | return 0; |
| 227 | |
| 228 | out_rth: |
| 229 | diff --git a/drivers/net/wireless/intersil/hostap/hostap_hw.c b/drivers/net/wireless/intersil/hostap/hostap_hw.c |
| 230 | index 58212c532c900..aadf3dec5bf32 100644 |
| 231 | --- a/drivers/net/wireless/intersil/hostap/hostap_hw.c |
| 232 | +++ b/drivers/net/wireless/intersil/hostap/hostap_hw.c |
| 233 | @@ -3041,6 +3041,27 @@ static void prism2_clear_set_tim_queue(local_info_t *local) |
| 234 | } |
| 235 | } |
| 236 | |
| 237 | + |
| 238 | +/* |
| 239 | + * HostAP uses two layers of net devices, where the inner |
| 240 | + * layer gets called all the time from the outer layer. |
| 241 | + * This is a natural nesting, which needs a split lock type. |
| 242 | + */ |
| 243 | +static struct lock_class_key hostap_netdev_xmit_lock_key; |
| 244 | + |
| 245 | +static void prism2_set_lockdep_class_one(struct net_device *dev, |
| 246 | + struct netdev_queue *txq, |
| 247 | + void *_unused) |
| 248 | +{ |
| 249 | + lockdep_set_class(&txq->_xmit_lock, |
| 250 | + &hostap_netdev_xmit_lock_key); |
| 251 | +} |
| 252 | + |
| 253 | +static void prism2_set_lockdep_class(struct net_device *dev) |
| 254 | +{ |
| 255 | + netdev_for_each_tx_queue(dev, prism2_set_lockdep_class_one, NULL); |
| 256 | +} |
| 257 | + |
| 258 | static struct net_device * |
| 259 | prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx, |
| 260 | struct device *sdev) |
| 261 | @@ -3199,6 +3220,7 @@ while (0) |
| 262 | if (ret >= 0) |
| 263 | ret = register_netdevice(dev); |
| 264 | |
| 265 | + prism2_set_lockdep_class(dev); |
| 266 | rtnl_unlock(); |
| 267 | if (ret < 0) { |
| 268 | printk(KERN_WARNING "%s: register netdevice failed!\n", |
| 269 | diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h |
| 270 | index 5a8d40f1ffe2a..7725efd6e48a1 100644 |
| 271 | --- a/include/linux/netdevice.h |
| 272 | +++ b/include/linux/netdevice.h |
| 273 | @@ -1805,13 +1805,11 @@ enum netdev_priv_flags { |
| 274 | * @phydev: Physical device may attach itself |
| 275 | * for hardware timestamping |
| 276 | * @sfp_bus: attached &struct sfp_bus structure. |
| 277 | - * @qdisc_tx_busylock_key: lockdep class annotating Qdisc->busylock |
| 278 | - * spinlock |
| 279 | - * @qdisc_running_key: lockdep class annotating Qdisc->running seqcount |
| 280 | - * @qdisc_xmit_lock_key: lockdep class annotating |
| 281 | - * netdev_queue->_xmit_lock spinlock |
| 282 | + * |
| 283 | * @addr_list_lock_key: lockdep class annotating |
| 284 | * net_device->addr_list_lock spinlock |
| 285 | + * @qdisc_tx_busylock: lockdep class annotating Qdisc->busylock spinlock |
| 286 | + * @qdisc_running_key: lockdep class annotating Qdisc->running seqcount |
| 287 | * |
| 288 | * @proto_down: protocol port state information can be sent to the |
| 289 | * switch driver and used to set the phys state of the |
| 290 | @@ -2112,10 +2110,9 @@ struct net_device { |
| 291 | #endif |
| 292 | struct phy_device *phydev; |
| 293 | struct sfp_bus *sfp_bus; |
| 294 | - struct lock_class_key qdisc_tx_busylock_key; |
| 295 | - struct lock_class_key qdisc_running_key; |
| 296 | - struct lock_class_key qdisc_xmit_lock_key; |
| 297 | struct lock_class_key addr_list_lock_key; |
| 298 | + struct lock_class_key *qdisc_tx_busylock; |
| 299 | + struct lock_class_key *qdisc_running_key; |
| 300 | bool proto_down; |
| 301 | unsigned wol_enabled:1; |
| 302 | |
| 303 | @@ -2200,6 +2197,20 @@ static inline void netdev_for_each_tx_queue(struct net_device *dev, |
| 304 | f(dev, &dev->_tx[i], arg); |
| 305 | } |
| 306 | |
| 307 | +#define netdev_lockdep_set_classes(dev) \ |
| 308 | +{ \ |
| 309 | + static struct lock_class_key qdisc_tx_busylock_key; \ |
| 310 | + static struct lock_class_key qdisc_running_key; \ |
| 311 | + static struct lock_class_key qdisc_xmit_lock_key; \ |
| 312 | + unsigned int i; \ |
| 313 | + \ |
| 314 | + (dev)->qdisc_tx_busylock = &qdisc_tx_busylock_key; \ |
| 315 | + (dev)->qdisc_running_key = &qdisc_running_key; \ |
| 316 | + for (i = 0; i < (dev)->num_tx_queues; i++) \ |
| 317 | + lockdep_set_class(&(dev)->_tx[i]._xmit_lock, \ |
| 318 | + &qdisc_xmit_lock_key); \ |
| 319 | +} |
| 320 | + |
| 321 | u16 netdev_pick_tx(struct net_device *dev, struct sk_buff *skb, |
| 322 | struct net_device *sb_dev); |
| 323 | struct netdev_queue *netdev_core_pick_tx(struct net_device *dev, |
| 324 | diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c |
| 325 | index 990b9fde28c65..319220b2341dd 100644 |
| 326 | --- a/net/8021q/vlan_dev.c |
| 327 | +++ b/net/8021q/vlan_dev.c |
| 328 | @@ -489,6 +489,25 @@ static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) |
| 329 | dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); |
| 330 | } |
| 331 | |
| 332 | +/* |
| 333 | + * vlan network devices have devices nesting below it, and are a special |
| 334 | + * "super class" of normal network devices; split their locks off into a |
| 335 | + * separate class since they always nest. |
| 336 | + */ |
| 337 | +static struct lock_class_key vlan_netdev_xmit_lock_key; |
| 338 | + |
| 339 | +static void vlan_dev_set_lockdep_one(struct net_device *dev, |
| 340 | + struct netdev_queue *txq, |
| 341 | + void *unused) |
| 342 | +{ |
| 343 | + lockdep_set_class(&txq->_xmit_lock, &vlan_netdev_xmit_lock_key); |
| 344 | +} |
| 345 | + |
| 346 | +static void vlan_dev_set_lockdep_class(struct net_device *dev) |
| 347 | +{ |
| 348 | + netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, NULL); |
| 349 | +} |
| 350 | + |
| 351 | static const struct header_ops vlan_header_ops = { |
| 352 | .create = vlan_dev_hard_header, |
| 353 | .parse = eth_header_parse, |
| 354 | @@ -579,6 +598,8 @@ static int vlan_dev_init(struct net_device *dev) |
| 355 | |
| 356 | SET_NETDEV_DEVTYPE(dev, &vlan_type); |
| 357 | |
| 358 | + vlan_dev_set_lockdep_class(dev); |
| 359 | + |
| 360 | vlan->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); |
| 361 | if (!vlan->vlan_pcpu_stats) |
| 362 | return -ENOMEM; |
| 363 | diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c |
| 364 | index 5f05a728f347a..822af540b8540 100644 |
| 365 | --- a/net/batman-adv/soft-interface.c |
| 366 | +++ b/net/batman-adv/soft-interface.c |
| 367 | @@ -739,6 +739,34 @@ static int batadv_interface_kill_vid(struct net_device *dev, __be16 proto, |
| 368 | return 0; |
| 369 | } |
| 370 | |
| 371 | +/* batman-adv network devices have devices nesting below it and are a special |
| 372 | + * "super class" of normal network devices; split their locks off into a |
| 373 | + * separate class since they always nest. |
| 374 | + */ |
| 375 | +static struct lock_class_key batadv_netdev_xmit_lock_key; |
| 376 | + |
| 377 | +/** |
| 378 | + * batadv_set_lockdep_class_one() - Set lockdep class for a single tx queue |
| 379 | + * @dev: device which owns the tx queue |
| 380 | + * @txq: tx queue to modify |
| 381 | + * @_unused: always NULL |
| 382 | + */ |
| 383 | +static void batadv_set_lockdep_class_one(struct net_device *dev, |
| 384 | + struct netdev_queue *txq, |
| 385 | + void *_unused) |
| 386 | +{ |
| 387 | + lockdep_set_class(&txq->_xmit_lock, &batadv_netdev_xmit_lock_key); |
| 388 | +} |
| 389 | + |
| 390 | +/** |
| 391 | + * batadv_set_lockdep_class() - Set txq and addr_list lockdep class |
| 392 | + * @dev: network device to modify |
| 393 | + */ |
| 394 | +static void batadv_set_lockdep_class(struct net_device *dev) |
| 395 | +{ |
| 396 | + netdev_for_each_tx_queue(dev, batadv_set_lockdep_class_one, NULL); |
| 397 | +} |
| 398 | + |
| 399 | /** |
| 400 | * batadv_softif_init_late() - late stage initialization of soft interface |
| 401 | * @dev: registered network device to modify |
| 402 | @@ -752,6 +780,8 @@ static int batadv_softif_init_late(struct net_device *dev) |
| 403 | int ret; |
| 404 | size_t cnt_len = sizeof(u64) * BATADV_CNT_NUM; |
| 405 | |
| 406 | + batadv_set_lockdep_class(dev); |
| 407 | + |
| 408 | bat_priv = netdev_priv(dev); |
| 409 | bat_priv->soft_iface = dev; |
| 410 | |
| 411 | diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c |
| 412 | index 4febc82a7c761..bb55d92691b06 100644 |
| 413 | --- a/net/bluetooth/6lowpan.c |
| 414 | +++ b/net/bluetooth/6lowpan.c |
| 415 | @@ -571,7 +571,15 @@ static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev) |
| 416 | return err < 0 ? NET_XMIT_DROP : err; |
| 417 | } |
| 418 | |
| 419 | +static int bt_dev_init(struct net_device *dev) |
| 420 | +{ |
| 421 | + netdev_lockdep_set_classes(dev); |
| 422 | + |
| 423 | + return 0; |
| 424 | +} |
| 425 | + |
| 426 | static const struct net_device_ops netdev_ops = { |
| 427 | + .ndo_init = bt_dev_init, |
| 428 | .ndo_start_xmit = bt_xmit, |
| 429 | }; |
| 430 | |
| 431 | diff --git a/net/core/dev.c b/net/core/dev.c |
| 432 | index afff16849c261..f8d83922a6afb 100644 |
| 433 | --- a/net/core/dev.c |
| 434 | +++ b/net/core/dev.c |
| 435 | @@ -398,6 +398,74 @@ static RAW_NOTIFIER_HEAD(netdev_chain); |
| 436 | DEFINE_PER_CPU_ALIGNED(struct softnet_data, softnet_data); |
| 437 | EXPORT_PER_CPU_SYMBOL(softnet_data); |
| 438 | |
| 439 | +#ifdef CONFIG_LOCKDEP |
| 440 | +/* |
| 441 | + * register_netdevice() inits txq->_xmit_lock and sets lockdep class |
| 442 | + * according to dev->type |
| 443 | + */ |
| 444 | +static const unsigned short netdev_lock_type[] = { |
| 445 | + ARPHRD_NETROM, ARPHRD_ETHER, ARPHRD_EETHER, ARPHRD_AX25, |
| 446 | + ARPHRD_PRONET, ARPHRD_CHAOS, ARPHRD_IEEE802, ARPHRD_ARCNET, |
| 447 | + ARPHRD_APPLETLK, ARPHRD_DLCI, ARPHRD_ATM, ARPHRD_METRICOM, |
| 448 | + ARPHRD_IEEE1394, ARPHRD_EUI64, ARPHRD_INFINIBAND, ARPHRD_SLIP, |
| 449 | + ARPHRD_CSLIP, ARPHRD_SLIP6, ARPHRD_CSLIP6, ARPHRD_RSRVD, |
| 450 | + ARPHRD_ADAPT, ARPHRD_ROSE, ARPHRD_X25, ARPHRD_HWX25, |
| 451 | + ARPHRD_PPP, ARPHRD_CISCO, ARPHRD_LAPB, ARPHRD_DDCMP, |
| 452 | + ARPHRD_RAWHDLC, ARPHRD_TUNNEL, ARPHRD_TUNNEL6, ARPHRD_FRAD, |
| 453 | + ARPHRD_SKIP, ARPHRD_LOOPBACK, ARPHRD_LOCALTLK, ARPHRD_FDDI, |
| 454 | + ARPHRD_BIF, ARPHRD_SIT, ARPHRD_IPDDP, ARPHRD_IPGRE, |
| 455 | + ARPHRD_PIMREG, ARPHRD_HIPPI, ARPHRD_ASH, ARPHRD_ECONET, |
| 456 | + ARPHRD_IRDA, ARPHRD_FCPP, ARPHRD_FCAL, ARPHRD_FCPL, |
| 457 | + ARPHRD_FCFABRIC, ARPHRD_IEEE80211, ARPHRD_IEEE80211_PRISM, |
| 458 | + ARPHRD_IEEE80211_RADIOTAP, ARPHRD_PHONET, ARPHRD_PHONET_PIPE, |
| 459 | + ARPHRD_IEEE802154, ARPHRD_VOID, ARPHRD_NONE}; |
| 460 | + |
| 461 | +static const char *const netdev_lock_name[] = { |
| 462 | + "_xmit_NETROM", "_xmit_ETHER", "_xmit_EETHER", "_xmit_AX25", |
| 463 | + "_xmit_PRONET", "_xmit_CHAOS", "_xmit_IEEE802", "_xmit_ARCNET", |
| 464 | + "_xmit_APPLETLK", "_xmit_DLCI", "_xmit_ATM", "_xmit_METRICOM", |
| 465 | + "_xmit_IEEE1394", "_xmit_EUI64", "_xmit_INFINIBAND", "_xmit_SLIP", |
| 466 | + "_xmit_CSLIP", "_xmit_SLIP6", "_xmit_CSLIP6", "_xmit_RSRVD", |
| 467 | + "_xmit_ADAPT", "_xmit_ROSE", "_xmit_X25", "_xmit_HWX25", |
| 468 | + "_xmit_PPP", "_xmit_CISCO", "_xmit_LAPB", "_xmit_DDCMP", |
| 469 | + "_xmit_RAWHDLC", "_xmit_TUNNEL", "_xmit_TUNNEL6", "_xmit_FRAD", |
| 470 | + "_xmit_SKIP", "_xmit_LOOPBACK", "_xmit_LOCALTLK", "_xmit_FDDI", |
| 471 | + "_xmit_BIF", "_xmit_SIT", "_xmit_IPDDP", "_xmit_IPGRE", |
| 472 | + "_xmit_PIMREG", "_xmit_HIPPI", "_xmit_ASH", "_xmit_ECONET", |
| 473 | + "_xmit_IRDA", "_xmit_FCPP", "_xmit_FCAL", "_xmit_FCPL", |
| 474 | + "_xmit_FCFABRIC", "_xmit_IEEE80211", "_xmit_IEEE80211_PRISM", |
| 475 | + "_xmit_IEEE80211_RADIOTAP", "_xmit_PHONET", "_xmit_PHONET_PIPE", |
| 476 | + "_xmit_IEEE802154", "_xmit_VOID", "_xmit_NONE"}; |
| 477 | + |
| 478 | +static struct lock_class_key netdev_xmit_lock_key[ARRAY_SIZE(netdev_lock_type)]; |
| 479 | + |
| 480 | +static inline unsigned short netdev_lock_pos(unsigned short dev_type) |
| 481 | +{ |
| 482 | + int i; |
| 483 | + |
| 484 | + for (i = 0; i < ARRAY_SIZE(netdev_lock_type); i++) |
| 485 | + if (netdev_lock_type[i] == dev_type) |
| 486 | + return i; |
| 487 | + /* the last key is used by default */ |
| 488 | + return ARRAY_SIZE(netdev_lock_type) - 1; |
| 489 | +} |
| 490 | + |
| 491 | +static inline void netdev_set_xmit_lockdep_class(spinlock_t *lock, |
| 492 | + unsigned short dev_type) |
| 493 | +{ |
| 494 | + int i; |
| 495 | + |
| 496 | + i = netdev_lock_pos(dev_type); |
| 497 | + lockdep_set_class_and_name(lock, &netdev_xmit_lock_key[i], |
| 498 | + netdev_lock_name[i]); |
| 499 | +} |
| 500 | +#else |
| 501 | +static inline void netdev_set_xmit_lockdep_class(spinlock_t *lock, |
| 502 | + unsigned short dev_type) |
| 503 | +{ |
| 504 | +} |
| 505 | +#endif |
| 506 | + |
| 507 | /******************************************************************************* |
| 508 | * |
| 509 | * Protocol management and registration routines |
| 510 | @@ -9208,7 +9276,7 @@ static void netdev_init_one_queue(struct net_device *dev, |
| 511 | { |
| 512 | /* Initialize queue lock */ |
| 513 | spin_lock_init(&queue->_xmit_lock); |
| 514 | - lockdep_set_class(&queue->_xmit_lock, &dev->qdisc_xmit_lock_key); |
| 515 | + netdev_set_xmit_lockdep_class(&queue->_xmit_lock, dev->type); |
| 516 | queue->xmit_lock_owner = -1; |
| 517 | netdev_queue_numa_node_write(queue, NUMA_NO_NODE); |
| 518 | queue->dev = dev; |
| 519 | @@ -9255,22 +9323,6 @@ void netif_tx_stop_all_queues(struct net_device *dev) |
| 520 | } |
| 521 | EXPORT_SYMBOL(netif_tx_stop_all_queues); |
| 522 | |
| 523 | -static void netdev_register_lockdep_key(struct net_device *dev) |
| 524 | -{ |
| 525 | - lockdep_register_key(&dev->qdisc_tx_busylock_key); |
| 526 | - lockdep_register_key(&dev->qdisc_running_key); |
| 527 | - lockdep_register_key(&dev->qdisc_xmit_lock_key); |
| 528 | - lockdep_register_key(&dev->addr_list_lock_key); |
| 529 | -} |
| 530 | - |
| 531 | -static void netdev_unregister_lockdep_key(struct net_device *dev) |
| 532 | -{ |
| 533 | - lockdep_unregister_key(&dev->qdisc_tx_busylock_key); |
| 534 | - lockdep_unregister_key(&dev->qdisc_running_key); |
| 535 | - lockdep_unregister_key(&dev->qdisc_xmit_lock_key); |
| 536 | - lockdep_unregister_key(&dev->addr_list_lock_key); |
| 537 | -} |
| 538 | - |
| 539 | void netdev_update_lockdep_key(struct net_device *dev) |
| 540 | { |
| 541 | lockdep_unregister_key(&dev->addr_list_lock_key); |
| 542 | @@ -9837,7 +9889,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, |
| 543 | |
| 544 | dev_net_set(dev, &init_net); |
| 545 | |
| 546 | - netdev_register_lockdep_key(dev); |
| 547 | + lockdep_register_key(&dev->addr_list_lock_key); |
| 548 | |
| 549 | dev->gso_max_size = GSO_MAX_SIZE; |
| 550 | dev->gso_max_segs = GSO_MAX_SEGS; |
| 551 | @@ -9926,7 +9978,7 @@ void free_netdev(struct net_device *dev) |
| 552 | free_percpu(dev->xdp_bulkq); |
| 553 | dev->xdp_bulkq = NULL; |
| 554 | |
| 555 | - netdev_unregister_lockdep_key(dev); |
| 556 | + lockdep_unregister_key(&dev->addr_list_lock_key); |
| 557 | |
| 558 | /* Compatibility with error handling in drivers */ |
| 559 | if (dev->reg_state == NETREG_UNINITIALIZED) { |
| 560 | diff --git a/net/dsa/slave.c b/net/dsa/slave.c |
| 561 | index ba8bf90dc0cc1..fa26340437519 100644 |
| 562 | --- a/net/dsa/slave.c |
| 563 | +++ b/net/dsa/slave.c |
| 564 | @@ -1671,6 +1671,15 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev) |
| 565 | return ret; |
| 566 | } |
| 567 | |
| 568 | +static struct lock_class_key dsa_slave_netdev_xmit_lock_key; |
| 569 | +static void dsa_slave_set_lockdep_class_one(struct net_device *dev, |
| 570 | + struct netdev_queue *txq, |
| 571 | + void *_unused) |
| 572 | +{ |
| 573 | + lockdep_set_class(&txq->_xmit_lock, |
| 574 | + &dsa_slave_netdev_xmit_lock_key); |
| 575 | +} |
| 576 | + |
| 577 | int dsa_slave_suspend(struct net_device *slave_dev) |
| 578 | { |
| 579 | struct dsa_port *dp = dsa_slave_to_port(slave_dev); |
| 580 | @@ -1754,6 +1763,9 @@ int dsa_slave_create(struct dsa_port *port) |
| 581 | slave_dev->max_mtu = ETH_MAX_MTU; |
| 582 | SET_NETDEV_DEVTYPE(slave_dev, &dsa_type); |
| 583 | |
| 584 | + netdev_for_each_tx_queue(slave_dev, dsa_slave_set_lockdep_class_one, |
| 585 | + NULL); |
| 586 | + |
| 587 | SET_NETDEV_DEV(slave_dev, port->ds->dev); |
| 588 | slave_dev->dev.of_node = port->dn; |
| 589 | slave_dev->vlan_features = master->vlan_features; |
| 590 | diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c |
| 591 | index c0b107cdd7153..3297e7fa99458 100644 |
| 592 | --- a/net/ieee802154/6lowpan/core.c |
| 593 | +++ b/net/ieee802154/6lowpan/core.c |
| 594 | @@ -58,6 +58,13 @@ static const struct header_ops lowpan_header_ops = { |
| 595 | .create = lowpan_header_create, |
| 596 | }; |
| 597 | |
| 598 | +static int lowpan_dev_init(struct net_device *ldev) |
| 599 | +{ |
| 600 | + netdev_lockdep_set_classes(ldev); |
| 601 | + |
| 602 | + return 0; |
| 603 | +} |
| 604 | + |
| 605 | static int lowpan_open(struct net_device *dev) |
| 606 | { |
| 607 | if (!open_count) |
| 608 | @@ -89,6 +96,7 @@ static int lowpan_get_iflink(const struct net_device *dev) |
| 609 | } |
| 610 | |
| 611 | static const struct net_device_ops lowpan_netdev_ops = { |
| 612 | + .ndo_init = lowpan_dev_init, |
| 613 | .ndo_start_xmit = lowpan_xmit, |
| 614 | .ndo_open = lowpan_open, |
| 615 | .ndo_stop = lowpan_stop, |
| 616 | diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c |
| 617 | index d3b520b9b2c9d..fd5ac2788e45c 100644 |
| 618 | --- a/net/l2tp/l2tp_eth.c |
| 619 | +++ b/net/l2tp/l2tp_eth.c |
| 620 | @@ -56,6 +56,7 @@ static int l2tp_eth_dev_init(struct net_device *dev) |
| 621 | { |
| 622 | eth_hw_addr_random(dev); |
| 623 | eth_broadcast_addr(dev->broadcast); |
| 624 | + netdev_lockdep_set_classes(dev); |
| 625 | |
| 626 | return 0; |
| 627 | } |
| 628 | diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c |
| 629 | index 7b1a74f74aad5..eccc7d366e17f 100644 |
| 630 | --- a/net/netrom/af_netrom.c |
| 631 | +++ b/net/netrom/af_netrom.c |
| 632 | @@ -63,6 +63,26 @@ static DEFINE_SPINLOCK(nr_list_lock); |
| 633 | |
| 634 | static const struct proto_ops nr_proto_ops; |
| 635 | |
| 636 | +/* |
| 637 | + * NETROM network devices are virtual network devices encapsulating NETROM |
| 638 | + * frames into AX.25 which will be sent through an AX.25 device, so form a |
| 639 | + * special "super class" of normal net devices; split their locks off into a |
| 640 | + * separate class since they always nest. |
| 641 | + */ |
| 642 | +static struct lock_class_key nr_netdev_xmit_lock_key; |
| 643 | + |
| 644 | +static void nr_set_lockdep_one(struct net_device *dev, |
| 645 | + struct netdev_queue *txq, |
| 646 | + void *_unused) |
| 647 | +{ |
| 648 | + lockdep_set_class(&txq->_xmit_lock, &nr_netdev_xmit_lock_key); |
| 649 | +} |
| 650 | + |
| 651 | +static void nr_set_lockdep_key(struct net_device *dev) |
| 652 | +{ |
| 653 | + netdev_for_each_tx_queue(dev, nr_set_lockdep_one, NULL); |
| 654 | +} |
| 655 | + |
| 656 | /* |
| 657 | * Socket removal during an interrupt is now safe. |
| 658 | */ |
| 659 | @@ -1394,6 +1414,7 @@ static int __init nr_proto_init(void) |
| 660 | free_netdev(dev); |
| 661 | goto fail; |
| 662 | } |
| 663 | + nr_set_lockdep_key(dev); |
| 664 | dev_nr[i] = dev; |
| 665 | } |
| 666 | |
| 667 | diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c |
| 668 | index 1e8eeb044b07d..e7a872207b464 100644 |
| 669 | --- a/net/rose/af_rose.c |
| 670 | +++ b/net/rose/af_rose.c |
| 671 | @@ -64,6 +64,26 @@ static const struct proto_ops rose_proto_ops; |
| 672 | |
| 673 | ax25_address rose_callsign; |
| 674 | |
| 675 | +/* |
| 676 | + * ROSE network devices are virtual network devices encapsulating ROSE |
| 677 | + * frames into AX.25 which will be sent through an AX.25 device, so form a |
| 678 | + * special "super class" of normal net devices; split their locks off into a |
| 679 | + * separate class since they always nest. |
| 680 | + */ |
| 681 | +static struct lock_class_key rose_netdev_xmit_lock_key; |
| 682 | + |
| 683 | +static void rose_set_lockdep_one(struct net_device *dev, |
| 684 | + struct netdev_queue *txq, |
| 685 | + void *_unused) |
| 686 | +{ |
| 687 | + lockdep_set_class(&txq->_xmit_lock, &rose_netdev_xmit_lock_key); |
| 688 | +} |
| 689 | + |
| 690 | +static void rose_set_lockdep_key(struct net_device *dev) |
| 691 | +{ |
| 692 | + netdev_for_each_tx_queue(dev, rose_set_lockdep_one, NULL); |
| 693 | +} |
| 694 | + |
| 695 | /* |
| 696 | * Convert a ROSE address into text. |
| 697 | */ |
| 698 | @@ -1511,6 +1531,7 @@ static int __init rose_proto_init(void) |
| 699 | free_netdev(dev); |
| 700 | goto fail; |
| 701 | } |
| 702 | + rose_set_lockdep_key(dev); |
| 703 | dev_rose[i] = dev; |
| 704 | } |
| 705 | |
| 706 | diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c |
| 707 | index ad24fa1a51e63..ebc55d8842473 100644 |
| 708 | --- a/net/sched/sch_generic.c |
| 709 | +++ b/net/sched/sch_generic.c |
| 710 | @@ -794,6 +794,9 @@ struct Qdisc_ops pfifo_fast_ops __read_mostly = { |
| 711 | }; |
| 712 | EXPORT_SYMBOL(pfifo_fast_ops); |
| 713 | |
| 714 | +static struct lock_class_key qdisc_tx_busylock; |
| 715 | +static struct lock_class_key qdisc_running_key; |
| 716 | + |
| 717 | struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, |
| 718 | const struct Qdisc_ops *ops, |
| 719 | struct netlink_ext_ack *extack) |
| 720 | @@ -846,9 +849,17 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, |
| 721 | } |
| 722 | |
| 723 | spin_lock_init(&sch->busylock); |
| 724 | + lockdep_set_class(&sch->busylock, |
| 725 | + dev->qdisc_tx_busylock ?: &qdisc_tx_busylock); |
| 726 | + |
| 727 | /* seqlock has the same scope of busylock, for NOLOCK qdisc */ |
| 728 | spin_lock_init(&sch->seqlock); |
| 729 | + lockdep_set_class(&sch->busylock, |
| 730 | + dev->qdisc_tx_busylock ?: &qdisc_tx_busylock); |
| 731 | + |
| 732 | seqcount_init(&sch->running); |
| 733 | + lockdep_set_class(&sch->running, |
| 734 | + dev->qdisc_running_key ?: &qdisc_running_key); |
| 735 | |
| 736 | sch->ops = ops; |
| 737 | sch->flags = ops->static_flags; |
| 738 | @@ -859,12 +870,6 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, |
| 739 | dev_hold(dev); |
| 740 | refcount_set(&sch->refcnt, 1); |
| 741 | |
| 742 | - if (sch != &noop_qdisc) { |
| 743 | - lockdep_set_class(&sch->busylock, &dev->qdisc_tx_busylock_key); |
| 744 | - lockdep_set_class(&sch->seqlock, &dev->qdisc_tx_busylock_key); |
| 745 | - lockdep_set_class(&sch->running, &dev->qdisc_running_key); |
| 746 | - } |
| 747 | - |
| 748 | return sch; |
| 749 | errout1: |
| 750 | kfree(p); |
| 751 | -- |
| 752 | cgit 1.2.3-1.el7 |
| 753 | |