aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorAnish Bhatt <anish@chelsio.com>2014-11-14 19:38:31 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-16 14:50:52 -0500
commit52cff74eef5dd7bdab759300e7d1ca36eba18254 (patch)
treeeaf4980da5e83b19429e9f04589865eea0276394 /net
parent8c2dd54485ccee7fc4086611e188478584758c8d (diff)
dcbnl : Disable software interrupts before taking dcb_lock
Solves possible lockup issues that can be seen from firmware DCB agents calling into the DCB app api. DCB firmware event queues can be tied in with NAPI so that dcb events are generated in softIRQ context. This can results in calls to dcb_*app() functions which try to take the dcb_lock. If the the event triggers while we also have the dcb_lock because lldpad or some other agent happened to be issuing a get/set command we could see a cpu lockup. This code was not originally written with firmware agents in mind, hence grabbing dcb_lock from softIRQ context was not considered. Signed-off-by: Anish Bhatt <anish@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/dcb/dcbnl.c36
1 files changed, 18 insertions, 18 deletions
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index ca11d283bbeb..93ea80196f0e 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -1080,13 +1080,13 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
1080 if (!app) 1080 if (!app)
1081 return -EMSGSIZE; 1081 return -EMSGSIZE;
1082 1082
1083 spin_lock(&dcb_lock); 1083 spin_lock_bh(&dcb_lock);
1084 list_for_each_entry(itr, &dcb_app_list, list) { 1084 list_for_each_entry(itr, &dcb_app_list, list) {
1085 if (itr->ifindex == netdev->ifindex) { 1085 if (itr->ifindex == netdev->ifindex) {
1086 err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app), 1086 err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app),
1087 &itr->app); 1087 &itr->app);
1088 if (err) { 1088 if (err) {
1089 spin_unlock(&dcb_lock); 1089 spin_unlock_bh(&dcb_lock);
1090 return -EMSGSIZE; 1090 return -EMSGSIZE;
1091 } 1091 }
1092 } 1092 }
@@ -1097,7 +1097,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
1097 else 1097 else
1098 dcbx = -EOPNOTSUPP; 1098 dcbx = -EOPNOTSUPP;
1099 1099
1100 spin_unlock(&dcb_lock); 1100 spin_unlock_bh(&dcb_lock);
1101 nla_nest_end(skb, app); 1101 nla_nest_end(skb, app);
1102 1102
1103 /* get peer info if available */ 1103 /* get peer info if available */
@@ -1234,7 +1234,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
1234 } 1234 }
1235 1235
1236 /* local app */ 1236 /* local app */
1237 spin_lock(&dcb_lock); 1237 spin_lock_bh(&dcb_lock);
1238 app = nla_nest_start(skb, DCB_ATTR_CEE_APP_TABLE); 1238 app = nla_nest_start(skb, DCB_ATTR_CEE_APP_TABLE);
1239 if (!app) 1239 if (!app)
1240 goto dcb_unlock; 1240 goto dcb_unlock;
@@ -1271,7 +1271,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
1271 else 1271 else
1272 dcbx = -EOPNOTSUPP; 1272 dcbx = -EOPNOTSUPP;
1273 1273
1274 spin_unlock(&dcb_lock); 1274 spin_unlock_bh(&dcb_lock);
1275 1275
1276 /* features flags */ 1276 /* features flags */
1277 if (ops->getfeatcfg) { 1277 if (ops->getfeatcfg) {
@@ -1326,7 +1326,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
1326 return 0; 1326 return 0;
1327 1327
1328dcb_unlock: 1328dcb_unlock:
1329 spin_unlock(&dcb_lock); 1329 spin_unlock_bh(&dcb_lock);
1330nla_put_failure: 1330nla_put_failure:
1331 return err; 1331 return err;
1332} 1332}
@@ -1762,10 +1762,10 @@ u8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
1762 struct dcb_app_type *itr; 1762 struct dcb_app_type *itr;
1763 u8 prio = 0; 1763 u8 prio = 0;
1764 1764
1765 spin_lock(&dcb_lock); 1765 spin_lock_bh(&dcb_lock);
1766 if ((itr = dcb_app_lookup(app, dev->ifindex, 0))) 1766 if ((itr = dcb_app_lookup(app, dev->ifindex, 0)))
1767 prio = itr->app.priority; 1767 prio = itr->app.priority;
1768 spin_unlock(&dcb_lock); 1768 spin_unlock_bh(&dcb_lock);
1769 1769
1770 return prio; 1770 return prio;
1771} 1771}
@@ -1789,7 +1789,7 @@ int dcb_setapp(struct net_device *dev, struct dcb_app *new)
1789 if (dev->dcbnl_ops->getdcbx) 1789 if (dev->dcbnl_ops->getdcbx)
1790 event.dcbx = dev->dcbnl_ops->getdcbx(dev); 1790 event.dcbx = dev->dcbnl_ops->getdcbx(dev);
1791 1791
1792 spin_lock(&dcb_lock); 1792 spin_lock_bh(&dcb_lock);
1793 /* Search for existing match and replace */ 1793 /* Search for existing match and replace */
1794 if ((itr = dcb_app_lookup(new, dev->ifindex, 0))) { 1794 if ((itr = dcb_app_lookup(new, dev->ifindex, 0))) {
1795 if (new->priority) 1795 if (new->priority)
@@ -1804,7 +1804,7 @@ int dcb_setapp(struct net_device *dev, struct dcb_app *new)
1804 if (new->priority) 1804 if (new->priority)
1805 err = dcb_app_add(new, dev->ifindex); 1805 err = dcb_app_add(new, dev->ifindex);
1806out: 1806out:
1807 spin_unlock(&dcb_lock); 1807 spin_unlock_bh(&dcb_lock);
1808 if (!err) 1808 if (!err)
1809 call_dcbevent_notifiers(DCB_APP_EVENT, &event); 1809 call_dcbevent_notifiers(DCB_APP_EVENT, &event);
1810 return err; 1810 return err;
@@ -1823,10 +1823,10 @@ u8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app)
1823 struct dcb_app_type *itr; 1823 struct dcb_app_type *itr;
1824 u8 prio = 0; 1824 u8 prio = 0;
1825 1825
1826 spin_lock(&dcb_lock); 1826 spin_lock_bh(&dcb_lock);
1827 if ((itr = dcb_app_lookup(app, dev->ifindex, 0))) 1827 if ((itr = dcb_app_lookup(app, dev->ifindex, 0)))
1828 prio |= 1 << itr->app.priority; 1828 prio |= 1 << itr->app.priority;
1829 spin_unlock(&dcb_lock); 1829 spin_unlock_bh(&dcb_lock);
1830 1830
1831 return prio; 1831 return prio;
1832} 1832}
@@ -1850,7 +1850,7 @@ int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
1850 if (dev->dcbnl_ops->getdcbx) 1850 if (dev->dcbnl_ops->getdcbx)
1851 event.dcbx = dev->dcbnl_ops->getdcbx(dev); 1851 event.dcbx = dev->dcbnl_ops->getdcbx(dev);
1852 1852
1853 spin_lock(&dcb_lock); 1853 spin_lock_bh(&dcb_lock);
1854 /* Search for existing match and abort if found */ 1854 /* Search for existing match and abort if found */
1855 if (dcb_app_lookup(new, dev->ifindex, new->priority)) { 1855 if (dcb_app_lookup(new, dev->ifindex, new->priority)) {
1856 err = -EEXIST; 1856 err = -EEXIST;
@@ -1859,7 +1859,7 @@ int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
1859 1859
1860 err = dcb_app_add(new, dev->ifindex); 1860 err = dcb_app_add(new, dev->ifindex);
1861out: 1861out:
1862 spin_unlock(&dcb_lock); 1862 spin_unlock_bh(&dcb_lock);
1863 if (!err) 1863 if (!err)
1864 call_dcbevent_notifiers(DCB_APP_EVENT, &event); 1864 call_dcbevent_notifiers(DCB_APP_EVENT, &event);
1865 return err; 1865 return err;
@@ -1882,7 +1882,7 @@ int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
1882 if (dev->dcbnl_ops->getdcbx) 1882 if (dev->dcbnl_ops->getdcbx)
1883 event.dcbx = dev->dcbnl_ops->getdcbx(dev); 1883 event.dcbx = dev->dcbnl_ops->getdcbx(dev);
1884 1884
1885 spin_lock(&dcb_lock); 1885 spin_lock_bh(&dcb_lock);
1886 /* Search for existing match and remove it. */ 1886 /* Search for existing match and remove it. */
1887 if ((itr = dcb_app_lookup(del, dev->ifindex, del->priority))) { 1887 if ((itr = dcb_app_lookup(del, dev->ifindex, del->priority))) {
1888 list_del(&itr->list); 1888 list_del(&itr->list);
@@ -1890,7 +1890,7 @@ int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
1890 err = 0; 1890 err = 0;
1891 } 1891 }
1892 1892
1893 spin_unlock(&dcb_lock); 1893 spin_unlock_bh(&dcb_lock);
1894 if (!err) 1894 if (!err)
1895 call_dcbevent_notifiers(DCB_APP_EVENT, &event); 1895 call_dcbevent_notifiers(DCB_APP_EVENT, &event);
1896 return err; 1896 return err;
@@ -1902,12 +1902,12 @@ static void dcb_flushapp(void)
1902 struct dcb_app_type *app; 1902 struct dcb_app_type *app;
1903 struct dcb_app_type *tmp; 1903 struct dcb_app_type *tmp;
1904 1904
1905 spin_lock(&dcb_lock); 1905 spin_lock_bh(&dcb_lock);
1906 list_for_each_entry_safe(app, tmp, &dcb_app_list, list) { 1906 list_for_each_entry_safe(app, tmp, &dcb_app_list, list) {
1907 list_del(&app->list); 1907 list_del(&app->list);
1908 kfree(app); 1908 kfree(app);
1909 } 1909 }
1910 spin_unlock(&dcb_lock); 1910 spin_unlock_bh(&dcb_lock);
1911} 1911}
1912 1912
1913static int __init dcbnl_init(void) 1913static int __init dcbnl_init(void)