Skip to content

Commit

Permalink
net: core: add generic lockdep keys
Browse files Browse the repository at this point in the history
Some interface types could be nested.
(VLAN, BONDING, TEAM, MACSEC, MACVLAN, IPVLAN, VIRT_WIFI, VXLAN, etc..)
These interface types should set lockdep class because, without lockdep
class key, lockdep always warn about unexisting circular locking.

In the current code, these interfaces have their own lockdep class keys and
these manage itself. So that there are so many duplicate code around the
/driver/net and /net/.
This patch adds new generic lockdep keys and some helper functions for it.

This patch does below changes.
a) Add lockdep class keys in struct net_device
   - qdisc_running, xmit, addr_list, qdisc_busylock
   - these keys are used as dynamic lockdep key.
b) When net_device is being allocated, lockdep keys are registered.
   - alloc_netdev_mqs()
c) When net_device is being free'd llockdep keys are unregistered.
   - free_netdev()
d) Add generic lockdep key helper function
   - netdev_register_lockdep_key()
   - netdev_unregister_lockdep_key()
   - netdev_update_lockdep_key()
e) Remove unnecessary generic lockdep macro and functions
f) Remove unnecessary lockdep code of each interfaces.

After this patch, each interface modules don't need to maintain
their lockdep keys.

Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
TaeheeYoo authored and davem330 committed Oct 24, 2019
1 parent 5343da4 commit ab92d68
Show file tree
Hide file tree
Showing 25 changed files with 63 additions and 356 deletions.
1 change: 0 additions & 1 deletion drivers/net/bonding/bond_main.c
Expand Up @@ -4769,7 +4769,6 @@ static int bond_init(struct net_device *bond_dev)
return -ENOMEM;

bond->nest_level = SINGLE_DEPTH_NESTING;
netdev_lockdep_set_classes(bond_dev);

list_add_tail(&bond->bond_list, &bn->dev_list);

Expand Down
18 changes: 0 additions & 18 deletions drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
Expand Up @@ -299,22 +299,6 @@ static void nfp_repr_clean(struct nfp_repr *repr)
nfp_port_free(repr->port);
}

static struct lock_class_key nfp_repr_netdev_xmit_lock_key;
static struct lock_class_key nfp_repr_netdev_addr_lock_key;

static void nfp_repr_set_lockdep_class_one(struct net_device *dev,
struct netdev_queue *txq,
void *_unused)
{
lockdep_set_class(&txq->_xmit_lock, &nfp_repr_netdev_xmit_lock_key);
}

static void nfp_repr_set_lockdep_class(struct net_device *dev)
{
lockdep_set_class(&dev->addr_list_lock, &nfp_repr_netdev_addr_lock_key);
netdev_for_each_tx_queue(dev, nfp_repr_set_lockdep_class_one, NULL);
}

int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
u32 cmsg_port_id, struct nfp_port *port,
struct net_device *pf_netdev)
Expand All @@ -324,8 +308,6 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
u32 repr_cap = nn->tlv_caps.repr_cap;
int err;

nfp_repr_set_lockdep_class(netdev);

repr->port = port;
repr->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL);
if (!repr->dst)
Expand Down
22 changes: 0 additions & 22 deletions drivers/net/hamradio/bpqether.c
Expand Up @@ -107,27 +107,6 @@ struct bpqdev {

static LIST_HEAD(bpq_devices);

/*
* bpqether network devices are paired with ethernet devices below them, so
* form a special "super class" of normal ethernet devices; split their locks
* off into a separate class since they always nest.
*/
static struct lock_class_key bpq_netdev_xmit_lock_key;
static struct lock_class_key bpq_netdev_addr_lock_key;

static void bpq_set_lockdep_class_one(struct net_device *dev,
struct netdev_queue *txq,
void *_unused)
{
lockdep_set_class(&txq->_xmit_lock, &bpq_netdev_xmit_lock_key);
}

static void bpq_set_lockdep_class(struct net_device *dev)
{
lockdep_set_class(&dev->addr_list_lock, &bpq_netdev_addr_lock_key);
netdev_for_each_tx_queue(dev, bpq_set_lockdep_class_one, NULL);
}

/* ------------------------------------------------------------------------ */


Expand Down Expand Up @@ -498,7 +477,6 @@ static int bpq_new_device(struct net_device *edev)
err = register_netdevice(ndev);
if (err)
goto error;
bpq_set_lockdep_class(ndev);

/* List protected by RTNL */
list_add_rcu(&bpq->bpq_list, &bpq_devices);
Expand Down
2 changes: 0 additions & 2 deletions drivers/net/hyperv/netvsc_drv.c
Expand Up @@ -2335,8 +2335,6 @@ static int netvsc_probe(struct hv_device *dev,
NETIF_F_HW_VLAN_CTAG_RX;
net->vlan_features = net->features;

netdev_lockdep_set_classes(net);

/* MTU range: 68 - 1500 or 65521 */
net->min_mtu = NETVSC_MTU_MIN;
if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
Expand Down
2 changes: 0 additions & 2 deletions drivers/net/ipvlan/ipvlan_main.c
Expand Up @@ -131,8 +131,6 @@ static int ipvlan_init(struct net_device *dev)
dev->gso_max_segs = phy_dev->gso_max_segs;
dev->hard_header_len = phy_dev->hard_header_len;

netdev_lockdep_set_classes(dev);

ipvlan->pcpu_stats = netdev_alloc_pcpu_stats(struct ipvl_pcpu_stats);
if (!ipvlan->pcpu_stats)
return -ENOMEM;
Expand Down
5 changes: 0 additions & 5 deletions drivers/net/macsec.c
Expand Up @@ -2750,7 +2750,6 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,

#define MACSEC_FEATURES \
(NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST)
static struct lock_class_key macsec_netdev_addr_lock_key;

static int macsec_dev_init(struct net_device *dev)
{
Expand Down Expand Up @@ -3264,10 +3263,6 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
dev_hold(real_dev);

macsec->nest_level = dev_get_nest_level(real_dev) + 1;
netdev_lockdep_set_classes(dev);
lockdep_set_class_and_subclass(&dev->addr_list_lock,
&macsec_netdev_addr_lock_key,
macsec_get_nest_level(dev));

err = netdev_upper_dev_link(real_dev, dev, extack);
if (err < 0)
Expand Down
12 changes: 0 additions & 12 deletions drivers/net/macvlan.c
Expand Up @@ -852,8 +852,6 @@ static int macvlan_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
* "super class" of normal network devices; split their locks off into a
* separate class since they always nest.
*/
static struct lock_class_key macvlan_netdev_addr_lock_key;

#define ALWAYS_ON_OFFLOADS \
(NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | \
NETIF_F_GSO_ROBUST | NETIF_F_GSO_ENCAP_ALL)
Expand All @@ -874,14 +872,6 @@ static int macvlan_get_nest_level(struct net_device *dev)
return ((struct macvlan_dev *)netdev_priv(dev))->nest_level;
}

static void macvlan_set_lockdep_class(struct net_device *dev)
{
netdev_lockdep_set_classes(dev);
lockdep_set_class_and_subclass(&dev->addr_list_lock,
&macvlan_netdev_addr_lock_key,
macvlan_get_nest_level(dev));
}

static int macvlan_init(struct net_device *dev)
{
struct macvlan_dev *vlan = netdev_priv(dev);
Expand All @@ -900,8 +890,6 @@ static int macvlan_init(struct net_device *dev)
dev->gso_max_segs = lowerdev->gso_max_segs;
dev->hard_header_len = lowerdev->hard_header_len;

macvlan_set_lockdep_class(dev);

vlan->pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
if (!vlan->pcpu_stats)
return -ENOMEM;
Expand Down
2 changes: 0 additions & 2 deletions drivers/net/ppp/ppp_generic.c
Expand Up @@ -1324,8 +1324,6 @@ static int ppp_dev_init(struct net_device *dev)
{
struct ppp *ppp;

netdev_lockdep_set_classes(dev);

ppp = netdev_priv(dev);
/* Let the netdevice take a reference on the ppp file. This ensures
* that ppp_destroy_interface() won't run before the device gets
Expand Down
2 changes: 0 additions & 2 deletions drivers/net/team/team.c
Expand Up @@ -1642,8 +1642,6 @@ static int team_init(struct net_device *dev)
goto err_options_register;
netif_carrier_off(dev);

netdev_lockdep_set_classes(dev);

return 0;

err_options_register:
Expand Down
1 change: 0 additions & 1 deletion drivers/net/vrf.c
Expand Up @@ -865,7 +865,6 @@ static int vrf_dev_init(struct net_device *dev)

/* similarly, oper state is irrelevant; set to up to avoid confusion */
dev->operstate = IF_OPER_UP;
netdev_lockdep_set_classes(dev);
return 0;

out_rth:
Expand Down
25 changes: 0 additions & 25 deletions drivers/net/wireless/intersil/hostap/hostap_hw.c
Expand Up @@ -3041,30 +3041,6 @@ static void prism2_clear_set_tim_queue(local_info_t *local)
}
}


/*
* HostAP uses two layers of net devices, where the inner
* layer gets called all the time from the outer layer.
* This is a natural nesting, which needs a split lock type.
*/
static struct lock_class_key hostap_netdev_xmit_lock_key;
static struct lock_class_key hostap_netdev_addr_lock_key;

static void prism2_set_lockdep_class_one(struct net_device *dev,
struct netdev_queue *txq,
void *_unused)
{
lockdep_set_class(&txq->_xmit_lock,
&hostap_netdev_xmit_lock_key);
}

static void prism2_set_lockdep_class(struct net_device *dev)
{
lockdep_set_class(&dev->addr_list_lock,
&hostap_netdev_addr_lock_key);
netdev_for_each_tx_queue(dev, prism2_set_lockdep_class_one, NULL);
}

static struct net_device *
prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
struct device *sdev)
Expand Down Expand Up @@ -3223,7 +3199,6 @@ while (0)
if (ret >= 0)
ret = register_netdevice(dev);

prism2_set_lockdep_class(dev);
rtnl_unlock();
if (ret < 0) {
printk(KERN_WARNING "%s: register netdevice failed!\n",
Expand Down
35 changes: 13 additions & 22 deletions include/linux/netdevice.h
Expand Up @@ -925,6 +925,7 @@ struct dev_ifalias {
struct devlink;
struct tlsdev_ops;


/*
* This structure defines the management hooks for network devices.
* The following hooks can be defined; unless noted otherwise, they are
Expand Down Expand Up @@ -1760,9 +1761,13 @@ enum netdev_priv_flags {
* @phydev: Physical device may attach itself
* for hardware timestamping
* @sfp_bus: attached &struct sfp_bus structure.
*
* @qdisc_tx_busylock: lockdep class annotating Qdisc->busylock spinlock
* @qdisc_running_key: lockdep class annotating Qdisc->running seqcount
* @qdisc_tx_busylock_key: lockdep class annotating Qdisc->busylock
spinlock
* @qdisc_running_key: lockdep class annotating Qdisc->running seqcount
* @qdisc_xmit_lock_key: lockdep class annotating
* netdev_queue->_xmit_lock spinlock
* @addr_list_lock_key: lockdep class annotating
* net_device->addr_list_lock spinlock
*
* @proto_down: protocol port state information can be sent to the
* switch driver and used to set the phys state of the
Expand Down Expand Up @@ -2049,8 +2054,10 @@ struct net_device {
#endif
struct phy_device *phydev;
struct sfp_bus *sfp_bus;
struct lock_class_key *qdisc_tx_busylock;
struct lock_class_key *qdisc_running_key;
struct lock_class_key qdisc_tx_busylock_key;
struct lock_class_key qdisc_running_key;
struct lock_class_key qdisc_xmit_lock_key;
struct lock_class_key addr_list_lock_key;
bool proto_down;
unsigned wol_enabled:1;
};
Expand Down Expand Up @@ -2128,23 +2135,6 @@ static inline void netdev_for_each_tx_queue(struct net_device *dev,
f(dev, &dev->_tx[i], arg);
}

#define netdev_lockdep_set_classes(dev) \
{ \
static struct lock_class_key qdisc_tx_busylock_key; \
static struct lock_class_key qdisc_running_key; \
static struct lock_class_key qdisc_xmit_lock_key; \
static struct lock_class_key dev_addr_list_lock_key; \
unsigned int i; \
\
(dev)->qdisc_tx_busylock = &qdisc_tx_busylock_key; \
(dev)->qdisc_running_key = &qdisc_running_key; \
lockdep_set_class(&(dev)->addr_list_lock, \
&dev_addr_list_lock_key); \
for (i = 0; i < (dev)->num_tx_queues; i++) \
lockdep_set_class(&(dev)->_tx[i]._xmit_lock, \
&qdisc_xmit_lock_key); \
}

u16 netdev_pick_tx(struct net_device *dev, struct sk_buff *skb,
struct net_device *sb_dev);
struct netdev_queue *netdev_core_pick_tx(struct net_device *dev,
Expand Down Expand Up @@ -3143,6 +3133,7 @@ static inline void netif_stop_queue(struct net_device *dev)
}

void netif_tx_stop_all_queues(struct net_device *dev);
void netdev_update_lockdep_key(struct net_device *dev);

static inline bool netif_tx_queue_stopped(const struct netdev_queue *dev_queue)
{
Expand Down
27 changes: 0 additions & 27 deletions net/8021q/vlan_dev.c
Expand Up @@ -489,31 +489,6 @@ static void vlan_dev_set_rx_mode(struct net_device *vlan_dev)
dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev);
}

/*
* vlan network devices have devices nesting below it, and are a special
* "super class" of normal network devices; split their locks off into a
* separate class since they always nest.
*/
static struct lock_class_key vlan_netdev_xmit_lock_key;
static struct lock_class_key vlan_netdev_addr_lock_key;

static void vlan_dev_set_lockdep_one(struct net_device *dev,
struct netdev_queue *txq,
void *_subclass)
{
lockdep_set_class_and_subclass(&txq->_xmit_lock,
&vlan_netdev_xmit_lock_key,
*(int *)_subclass);
}

static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass)
{
lockdep_set_class_and_subclass(&dev->addr_list_lock,
&vlan_netdev_addr_lock_key,
subclass);
netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass);
}

static int vlan_dev_get_lock_subclass(struct net_device *dev)
{
return vlan_dev_priv(dev)->nest_level;
Expand Down Expand Up @@ -609,8 +584,6 @@ static int vlan_dev_init(struct net_device *dev)

SET_NETDEV_DEVTYPE(dev, &vlan_type);

vlan_dev_set_lockdep_class(dev, vlan_dev_get_lock_subclass(dev));

vlan->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
if (!vlan->vlan_pcpu_stats)
return -ENOMEM;
Expand Down
32 changes: 0 additions & 32 deletions net/batman-adv/soft-interface.c
Expand Up @@ -740,36 +740,6 @@ static int batadv_interface_kill_vid(struct net_device *dev, __be16 proto,
return 0;
}

/* batman-adv network devices have devices nesting below it and are a special
* "super class" of normal network devices; split their locks off into a
* separate class since they always nest.
*/
static struct lock_class_key batadv_netdev_xmit_lock_key;
static struct lock_class_key batadv_netdev_addr_lock_key;

/**
* batadv_set_lockdep_class_one() - Set lockdep class for a single tx queue
* @dev: device which owns the tx queue
* @txq: tx queue to modify
* @_unused: always NULL
*/
static void batadv_set_lockdep_class_one(struct net_device *dev,
struct netdev_queue *txq,
void *_unused)
{
lockdep_set_class(&txq->_xmit_lock, &batadv_netdev_xmit_lock_key);
}

/**
* batadv_set_lockdep_class() - Set txq and addr_list lockdep class
* @dev: network device to modify
*/
static void batadv_set_lockdep_class(struct net_device *dev)
{
lockdep_set_class(&dev->addr_list_lock, &batadv_netdev_addr_lock_key);
netdev_for_each_tx_queue(dev, batadv_set_lockdep_class_one, NULL);
}

/**
* batadv_softif_init_late() - late stage initialization of soft interface
* @dev: registered network device to modify
Expand All @@ -783,8 +753,6 @@ static int batadv_softif_init_late(struct net_device *dev)
int ret;
size_t cnt_len = sizeof(u64) * BATADV_CNT_NUM;

batadv_set_lockdep_class(dev);

bat_priv = netdev_priv(dev);
bat_priv->soft_iface = dev;

Expand Down
8 changes: 0 additions & 8 deletions net/bluetooth/6lowpan.c
Expand Up @@ -571,15 +571,7 @@ static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
return err < 0 ? NET_XMIT_DROP : err;
}

static int bt_dev_init(struct net_device *dev)
{
netdev_lockdep_set_classes(dev);

return 0;
}

static const struct net_device_ops netdev_ops = {
.ndo_init = bt_dev_init,
.ndo_start_xmit = bt_xmit,
};

Expand Down

0 comments on commit ab92d68

Please sign in to comment.