aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReece R. Pollack2013-06-11 13:01:39 -0500
committerMurali Karicheri2014-12-03 10:29:50 -0600
commit90df6850f2b660501f4afe1175d08f829de54ccc (patch)
treeff93737404a778a4d50ecb288ba403c8e4e60fdd /drivers/net/ethernet/ti/keystone_ethss.c
parent1a6ae2b73feefc6cdb40b508a51d594f88ccb22b (diff)
downloadlinux-90df6850f2b660501f4afe1175d08f829de54ccc.tar.gz
linux-90df6850f2b660501f4afe1175d08f829de54ccc.tar.xz
linux-90df6850f2b660501f4afe1175d08f829de54ccc.zip
net: keystone: Fix "scheduling while atomic" crash in cpsw_timer
Modification of statistics counters needs to be atomic, but a mutex cannot be acquired from within a timer (softirq context). This patch changes the mutex to a spinlock, and uses spin_lock_bh() to properly synchronize the accesses. Signed-off-by: Reece R. Pollack <x0183204@ti.com>
Diffstat (limited to 'drivers/net/ethernet/ti/keystone_ethss.c')
-rw-r--r--drivers/net/ethernet/ti/keystone_ethss.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/net/ethernet/ti/keystone_ethss.c b/drivers/net/ethernet/ti/keystone_ethss.c
index fb12fd070aa..896e036a6b1 100644
--- a/drivers/net/ethernet/ti/keystone_ethss.c
+++ b/drivers/net/ethernet/ti/keystone_ethss.c
@@ -253,7 +253,7 @@ struct cpsw_priv {
253 struct kobject tx_pri_kobj; 253 struct kobject tx_pri_kobj;
254 struct kobject pvlan_kobj; 254 struct kobject pvlan_kobj;
255 struct kobject stats_kobj; 255 struct kobject stats_kobj;
256 struct mutex hw_stats_lock; 256 spinlock_t hw_stats_lock;
257}; 257};
258 258
259struct cpsw_intf { 259struct cpsw_intf {
@@ -1127,9 +1127,9 @@ static ssize_t cpsw_stats_mod_store(struct cpsw_priv *cpsw_dev,
1127 return -EINVAL; 1127 return -EINVAL;
1128 1128
1129 stat_mod = (int)(attr->context); 1129 stat_mod = (int)(attr->context);
1130 mutex_lock(&cpsw_dev->hw_stats_lock); 1130 spin_lock_bh(&cpsw_dev->hw_stats_lock);
1131 cpsw_reset_mod_stats(cpsw_dev, stat_mod); 1131 cpsw_reset_mod_stats(cpsw_dev, stat_mod);
1132 mutex_unlock(&cpsw_dev->hw_stats_lock); 1132 spin_unlock_bh(&cpsw_dev->hw_stats_lock);
1133 return count; 1133 return count;
1134} 1134}
1135 1135
@@ -1291,9 +1291,9 @@ static void keystone_get_ethtool_stats(struct net_device *ndev,
1291 struct ethtool_stats *stats, 1291 struct ethtool_stats *stats,
1292 uint64_t *data) 1292 uint64_t *data)
1293{ 1293{
1294 mutex_lock(&priv->hw_stats_lock); 1294 spin_lock_bh(&priv->hw_stats_lock);
1295 cpsw_update_stats(priv, data); 1295 cpsw_update_stats(priv, data);
1296 mutex_unlock(&priv->hw_stats_lock); 1296 spin_unlock_bh(&priv->hw_stats_lock);
1297 1297
1298 return; 1298 return;
1299} 1299}
@@ -1785,9 +1785,9 @@ static void cpsw_timer(unsigned long arg)
1785 netif_stop_queue(cpsw_intf->ndev); 1785 netif_stop_queue(cpsw_intf->ndev);
1786 } 1786 }
1787 1787
1788 mutex_lock(&cpsw_dev->hw_stats_lock); 1788 spin_lock_bh(&cpsw_dev->hw_stats_lock);
1789 cpsw_update_stats(cpsw_dev, NULL); 1789 cpsw_update_stats(cpsw_dev, NULL);
1790 mutex_unlock(&cpsw_dev->hw_stats_lock); 1790 spin_unlock_bh(&cpsw_dev->hw_stats_lock);
1791 1791
1792 cpsw_intf->timer.expires = jiffies + (HZ/10); 1792 cpsw_intf->timer.expires = jiffies + (HZ/10);
1793 add_timer(&cpsw_intf->timer); 1793 add_timer(&cpsw_intf->timer);
@@ -2209,7 +2209,7 @@ static int cpsw_probe(struct netcp_device *netcp_device,
2209 NULL, cpsw_dev->intf_tx_queues, 2209 NULL, cpsw_dev->intf_tx_queues,
2210 1, 0); 2210 1, 0);
2211 /* init the hw stats lock */ 2211 /* init the hw stats lock */
2212 mutex_init(&cpsw_dev->hw_stats_lock); 2212 spin_lock_init(&cpsw_dev->hw_stats_lock);
2213 2213
2214 ret = cpsw_create_sysfs_entries(cpsw_dev); 2214 ret = cpsw_create_sysfs_entries(cpsw_dev);
2215 if (ret) 2215 if (ret)