Commit 8e091340 authored by Tony Camuso's avatar Tony Camuso Committed by David S. Miller

enic: fix lockdep around devcmd_lock

We were experiencing occasional "BUG: scheduling while atomic" splats
in our testing. Enabling DEBUG_SPINLOCK and DEBUG_LOCKDEP in the kernel
exposed a lockdep in the enic driver.

enic 0000:0b:00.0 eth2: Link UP

======================================================
[ INFO: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected ]
3.12.0-rc1.x86_64-dbg+ #2 Tainted: GF       W
------------------------------------------------------
NetworkManager/4209 [HC0[0]:SC0[2]:HE1:SE0] is trying to acquire:
(&(&enic->devcmd_lock)->rlock){+.+...}, at: [<ffffffffa026b7e4>] enic_dev_packet_filter+0x44/0x90 [enic]

The fix was to replace spin_lock with spin_lock_bh for the enic
devcmd_lock, so that soft irqs would be disabled while the lock
is held.
Signed-off-by: default avatarSujith Sankar <ssujith@cisco.com>
Signed-off-by: default avatarTony Camuso <tcamuso@redhat.com>
Signed-off-by: default avatarGovindarajulu Varadarajan <_govind@gmx.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a145df23
...@@ -34,13 +34,13 @@ int enic_api_devcmd_proxy_by_index(struct net_device *netdev, int vf, ...@@ -34,13 +34,13 @@ int enic_api_devcmd_proxy_by_index(struct net_device *netdev, int vf,
struct vnic_dev *vdev = enic->vdev; struct vnic_dev *vdev = enic->vdev;
spin_lock(&enic->enic_api_lock); spin_lock(&enic->enic_api_lock);
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
vnic_dev_cmd_proxy_by_index_start(vdev, vf); vnic_dev_cmd_proxy_by_index_start(vdev, vf);
err = vnic_dev_cmd(vdev, cmd, a0, a1, wait); err = vnic_dev_cmd(vdev, cmd, a0, a1, wait);
vnic_dev_cmd_proxy_end(vdev); vnic_dev_cmd_proxy_end(vdev);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
spin_unlock(&enic->enic_api_lock); spin_unlock(&enic->enic_api_lock);
return err; return err;
......
...@@ -29,9 +29,9 @@ int enic_dev_fw_info(struct enic *enic, struct vnic_devcmd_fw_info **fw_info) ...@@ -29,9 +29,9 @@ int enic_dev_fw_info(struct enic *enic, struct vnic_devcmd_fw_info **fw_info)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_fw_info(enic->vdev, fw_info); err = vnic_dev_fw_info(enic->vdev, fw_info);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -40,9 +40,9 @@ int enic_dev_stats_dump(struct enic *enic, struct vnic_stats **vstats) ...@@ -40,9 +40,9 @@ int enic_dev_stats_dump(struct enic *enic, struct vnic_stats **vstats)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_stats_dump(enic->vdev, vstats); err = vnic_dev_stats_dump(enic->vdev, vstats);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -54,9 +54,9 @@ int enic_dev_add_station_addr(struct enic *enic) ...@@ -54,9 +54,9 @@ int enic_dev_add_station_addr(struct enic *enic)
if (!is_valid_ether_addr(enic->netdev->dev_addr)) if (!is_valid_ether_addr(enic->netdev->dev_addr))
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_add_addr(enic->vdev, enic->netdev->dev_addr); err = vnic_dev_add_addr(enic->vdev, enic->netdev->dev_addr);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -68,9 +68,9 @@ int enic_dev_del_station_addr(struct enic *enic) ...@@ -68,9 +68,9 @@ int enic_dev_del_station_addr(struct enic *enic)
if (!is_valid_ether_addr(enic->netdev->dev_addr)) if (!is_valid_ether_addr(enic->netdev->dev_addr))
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_del_addr(enic->vdev, enic->netdev->dev_addr); err = vnic_dev_del_addr(enic->vdev, enic->netdev->dev_addr);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -80,10 +80,10 @@ int enic_dev_packet_filter(struct enic *enic, int directed, int multicast, ...@@ -80,10 +80,10 @@ int enic_dev_packet_filter(struct enic *enic, int directed, int multicast,
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_packet_filter(enic->vdev, directed, err = vnic_dev_packet_filter(enic->vdev, directed,
multicast, broadcast, promisc, allmulti); multicast, broadcast, promisc, allmulti);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -92,9 +92,9 @@ int enic_dev_add_addr(struct enic *enic, const u8 *addr) ...@@ -92,9 +92,9 @@ int enic_dev_add_addr(struct enic *enic, const u8 *addr)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_add_addr(enic->vdev, addr); err = vnic_dev_add_addr(enic->vdev, addr);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -103,9 +103,9 @@ int enic_dev_del_addr(struct enic *enic, const u8 *addr) ...@@ -103,9 +103,9 @@ int enic_dev_del_addr(struct enic *enic, const u8 *addr)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_del_addr(enic->vdev, addr); err = vnic_dev_del_addr(enic->vdev, addr);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -114,9 +114,9 @@ int enic_dev_notify_unset(struct enic *enic) ...@@ -114,9 +114,9 @@ int enic_dev_notify_unset(struct enic *enic)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_notify_unset(enic->vdev); err = vnic_dev_notify_unset(enic->vdev);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -125,9 +125,9 @@ int enic_dev_hang_notify(struct enic *enic) ...@@ -125,9 +125,9 @@ int enic_dev_hang_notify(struct enic *enic)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_hang_notify(enic->vdev); err = vnic_dev_hang_notify(enic->vdev);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -136,10 +136,10 @@ int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic) ...@@ -136,10 +136,10 @@ int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_set_ig_vlan_rewrite_mode(enic->vdev, err = vnic_dev_set_ig_vlan_rewrite_mode(enic->vdev,
IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN); IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -148,9 +148,9 @@ int enic_dev_enable(struct enic *enic) ...@@ -148,9 +148,9 @@ int enic_dev_enable(struct enic *enic)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_enable_wait(enic->vdev); err = vnic_dev_enable_wait(enic->vdev);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -159,9 +159,9 @@ int enic_dev_disable(struct enic *enic) ...@@ -159,9 +159,9 @@ int enic_dev_disable(struct enic *enic)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_disable(enic->vdev); err = vnic_dev_disable(enic->vdev);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -170,9 +170,9 @@ int enic_dev_intr_coal_timer_info(struct enic *enic) ...@@ -170,9 +170,9 @@ int enic_dev_intr_coal_timer_info(struct enic *enic)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_intr_coal_timer_info(enic->vdev); err = vnic_dev_intr_coal_timer_info(enic->vdev);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -181,9 +181,9 @@ int enic_vnic_dev_deinit(struct enic *enic) ...@@ -181,9 +181,9 @@ int enic_vnic_dev_deinit(struct enic *enic)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_deinit(enic->vdev); err = vnic_dev_deinit(enic->vdev);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -192,10 +192,10 @@ int enic_dev_init_prov2(struct enic *enic, struct vic_provinfo *vp) ...@@ -192,10 +192,10 @@ int enic_dev_init_prov2(struct enic *enic, struct vic_provinfo *vp)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_init_prov2(enic->vdev, err = vnic_dev_init_prov2(enic->vdev,
(u8 *)vp, vic_provinfo_size(vp)); (u8 *)vp, vic_provinfo_size(vp));
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -204,9 +204,9 @@ int enic_dev_deinit_done(struct enic *enic, int *status) ...@@ -204,9 +204,9 @@ int enic_dev_deinit_done(struct enic *enic, int *status)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_deinit_done(enic->vdev, status); err = vnic_dev_deinit_done(enic->vdev, status);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -217,9 +217,9 @@ int enic_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid) ...@@ -217,9 +217,9 @@ int enic_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
struct enic *enic = netdev_priv(netdev); struct enic *enic = netdev_priv(netdev);
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = enic_add_vlan(enic, vid); err = enic_add_vlan(enic, vid);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -230,9 +230,9 @@ int enic_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid) ...@@ -230,9 +230,9 @@ int enic_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
struct enic *enic = netdev_priv(netdev); struct enic *enic = netdev_priv(netdev);
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = enic_del_vlan(enic, vid); err = enic_del_vlan(enic, vid);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -241,9 +241,9 @@ int enic_dev_enable2(struct enic *enic, int active) ...@@ -241,9 +241,9 @@ int enic_dev_enable2(struct enic *enic, int active)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_enable2(enic->vdev, active); err = vnic_dev_enable2(enic->vdev, active);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -252,9 +252,9 @@ int enic_dev_enable2_done(struct enic *enic, int *status) ...@@ -252,9 +252,9 @@ int enic_dev_enable2_done(struct enic *enic, int *status)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_enable2_done(enic->vdev, status); err = vnic_dev_enable2_done(enic->vdev, status);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
*/ */
#define ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnicdevcmdfn, ...) \ #define ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnicdevcmdfn, ...) \
do { \ do { \
spin_lock(&enic->devcmd_lock); \ spin_lock_bh(&enic->devcmd_lock); \
if (enic_is_valid_vf(enic, vf)) { \ if (enic_is_valid_vf(enic, vf)) { \
vnic_dev_cmd_proxy_by_index_start(enic->vdev, vf); \ vnic_dev_cmd_proxy_by_index_start(enic->vdev, vf); \
err = vnicdevcmdfn(enic->vdev, ##__VA_ARGS__); \ err = vnicdevcmdfn(enic->vdev, ##__VA_ARGS__); \
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
} else { \ } else { \
err = vnicdevcmdfn(enic->vdev, ##__VA_ARGS__); \ err = vnicdevcmdfn(enic->vdev, ##__VA_ARGS__); \
} \ } \
spin_unlock(&enic->devcmd_lock); \ spin_unlock_bh(&enic->devcmd_lock); \
} while (0) } while (0)
int enic_dev_fw_info(struct enic *enic, struct vnic_devcmd_fw_info **fw_info); int enic_dev_fw_info(struct enic *enic, struct vnic_devcmd_fw_info **fw_info);
......
...@@ -1465,7 +1465,7 @@ static int enic_dev_notify_set(struct enic *enic) ...@@ -1465,7 +1465,7 @@ static int enic_dev_notify_set(struct enic *enic)
{ {
int err; int err;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
switch (vnic_dev_get_intr_mode(enic->vdev)) { switch (vnic_dev_get_intr_mode(enic->vdev)) {
case VNIC_DEV_INTR_MODE_INTX: case VNIC_DEV_INTR_MODE_INTX:
err = vnic_dev_notify_set(enic->vdev, err = vnic_dev_notify_set(enic->vdev,
...@@ -1479,7 +1479,7 @@ static int enic_dev_notify_set(struct enic *enic) ...@@ -1479,7 +1479,7 @@ static int enic_dev_notify_set(struct enic *enic)
err = vnic_dev_notify_set(enic->vdev, -1 /* no intr */); err = vnic_dev_notify_set(enic->vdev, -1 /* no intr */);
break; break;
} }
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
...@@ -1804,11 +1804,11 @@ static int enic_set_rsskey(struct enic *enic) ...@@ -1804,11 +1804,11 @@ static int enic_set_rsskey(struct enic *enic)
memcpy(rss_key_buf_va, &rss_key, sizeof(union vnic_rss_key)); memcpy(rss_key_buf_va, &rss_key, sizeof(union vnic_rss_key));
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = enic_set_rss_key(enic, err = enic_set_rss_key(enic,
rss_key_buf_pa, rss_key_buf_pa,
sizeof(union vnic_rss_key)); sizeof(union vnic_rss_key));
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
pci_free_consistent(enic->pdev, sizeof(union vnic_rss_key), pci_free_consistent(enic->pdev, sizeof(union vnic_rss_key),
rss_key_buf_va, rss_key_buf_pa); rss_key_buf_va, rss_key_buf_pa);
...@@ -1831,11 +1831,11 @@ static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits) ...@@ -1831,11 +1831,11 @@ static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits)
for (i = 0; i < (1 << rss_hash_bits); i++) for (i = 0; i < (1 << rss_hash_bits); i++)
(*rss_cpu_buf_va).cpu[i/4].b[i%4] = i % enic->rq_count; (*rss_cpu_buf_va).cpu[i/4].b[i%4] = i % enic->rq_count;
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = enic_set_rss_cpu(enic, err = enic_set_rss_cpu(enic,
rss_cpu_buf_pa, rss_cpu_buf_pa,
sizeof(union vnic_rss_cpu)); sizeof(union vnic_rss_cpu));
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
pci_free_consistent(enic->pdev, sizeof(union vnic_rss_cpu), pci_free_consistent(enic->pdev, sizeof(union vnic_rss_cpu),
rss_cpu_buf_va, rss_cpu_buf_pa); rss_cpu_buf_va, rss_cpu_buf_pa);
...@@ -1853,13 +1853,13 @@ static int enic_set_niccfg(struct enic *enic, u8 rss_default_cpu, ...@@ -1853,13 +1853,13 @@ static int enic_set_niccfg(struct enic *enic, u8 rss_default_cpu,
/* Enable VLAN tag stripping. /* Enable VLAN tag stripping.
*/ */
spin_lock(&enic->devcmd_lock); spin_lock_bh(&enic->devcmd_lock);
err = enic_set_nic_cfg(enic, err = enic_set_nic_cfg(enic,
rss_default_cpu, rss_hash_type, rss_default_cpu, rss_hash_type,
rss_hash_bits, rss_base_cpu, rss_hash_bits, rss_base_cpu,
rss_enable, tso_ipid_split_en, rss_enable, tso_ipid_split_en,
ig_vlan_strip_en); ig_vlan_strip_en);
spin_unlock(&enic->devcmd_lock); spin_unlock_bh(&enic->devcmd_lock);
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment