]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.32.17/dm9000-fix-bug-spinlock-recursion.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.32.17 / dm9000-fix-bug-spinlock-recursion.patch
CommitLineData
6c840dcf
GKH
1From 380fefb2ddabd4cd5f14dbe090481f0544e65078 Mon Sep 17 00:00:00 2001
2From: Baruch Siach <baruch@tkos.co.il>
3Date: Mon, 17 May 2010 17:45:48 -0700
4Subject: dm9000: fix "BUG: spinlock recursion"
5
6From: Baruch Siach <baruch@tkos.co.il>
7
8commit 380fefb2ddabd4cd5f14dbe090481f0544e65078 upstream.
9
10dm9000_set_rx_csum and dm9000_hash_table are called from atomic context (in
11dm9000_init_dm9000), and from non-atomic context (via ethtool_ops and
12net_device_ops respectively). This causes a spinlock recursion BUG. Fix this by
13renaming these functions to *_unlocked for the atomic context, and make the
14original functions locking wrappers for use in the non-atomic context.
15
16Signed-off-by: Baruch Siach <baruch@tkos.co.il>
17Signed-off-by: David S. Miller <davem@davemloft.net>
18Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
19
20---
21 drivers/net/dm9000.c | 38 +++++++++++++++++++++++++++-----------
22 1 file changed, 27 insertions(+), 11 deletions(-)
23
24--- a/drivers/net/dm9000.c
25+++ b/drivers/net/dm9000.c
26@@ -471,17 +471,13 @@ static uint32_t dm9000_get_rx_csum(struc
27 return dm->rx_csum;
28 }
29
30-static int dm9000_set_rx_csum(struct net_device *dev, uint32_t data)
31+static int dm9000_set_rx_csum_unlocked(struct net_device *dev, uint32_t data)
32 {
33 board_info_t *dm = to_dm9000_board(dev);
34- unsigned long flags;
35
36 if (dm->can_csum) {
37 dm->rx_csum = data;
38-
39- spin_lock_irqsave(&dm->lock, flags);
40 iow(dm, DM9000_RCSR, dm->rx_csum ? RCSR_CSUM : 0);
41- spin_unlock_irqrestore(&dm->lock, flags);
42
43 return 0;
44 }
45@@ -489,6 +485,19 @@ static int dm9000_set_rx_csum(struct net
46 return -EOPNOTSUPP;
47 }
48
49+static int dm9000_set_rx_csum(struct net_device *dev, uint32_t data)
50+{
51+ board_info_t *dm = to_dm9000_board(dev);
52+ unsigned long flags;
53+ int ret;
54+
55+ spin_lock_irqsave(&dm->lock, flags);
56+ ret = dm9000_set_rx_csum_unlocked(dev, data);
57+ spin_unlock_irqrestore(&dm->lock, flags);
58+
59+ return ret;
60+}
61+
62 static int dm9000_set_tx_csum(struct net_device *dev, uint32_t data)
63 {
64 board_info_t *dm = to_dm9000_board(dev);
65@@ -667,7 +676,7 @@ static unsigned char dm9000_type_to_char
66 * Set DM9000 multicast address
67 */
68 static void
69-dm9000_hash_table(struct net_device *dev)
70+dm9000_hash_table_unlocked(struct net_device *dev)
71 {
72 board_info_t *db = netdev_priv(dev);
73 struct dev_mc_list *mcptr = dev->mc_list;
74@@ -676,12 +685,9 @@ dm9000_hash_table(struct net_device *dev
75 u32 hash_val;
76 u16 hash_table[4];
77 u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;
78- unsigned long flags;
79
80 dm9000_dbg(db, 1, "entering %s\n", __func__);
81
82- spin_lock_irqsave(&db->lock, flags);
83-
84 for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
85 iow(db, oft, dev->dev_addr[i]);
86
87@@ -711,6 +717,16 @@ dm9000_hash_table(struct net_device *dev
88 }
89
90 iow(db, DM9000_RCR, rcr);
91+}
92+
93+static void
94+dm9000_hash_table(struct net_device *dev)
95+{
96+ board_info_t *db = netdev_priv(dev);
97+ unsigned long flags;
98+
99+ spin_lock_irqsave(&db->lock, flags);
100+ dm9000_hash_table_unlocked(dev);
101 spin_unlock_irqrestore(&db->lock, flags);
102 }
103
104@@ -729,7 +745,7 @@ dm9000_init_dm9000(struct net_device *de
105 db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */
106
107 /* Checksum mode */
108- dm9000_set_rx_csum(dev, db->rx_csum);
109+ dm9000_set_rx_csum_unlocked(dev, db->rx_csum);
110
111 /* GPIO0 on pre-activate PHY */
112 iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */
113@@ -749,7 +765,7 @@ dm9000_init_dm9000(struct net_device *de
114 iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */
115
116 /* Set address filter table */
117- dm9000_hash_table(dev);
118+ dm9000_hash_table_unlocked(dev);
119
120 imr = IMR_PAR | IMR_PTM | IMR_PRM;
121 if (db->type != TYPE_DM9000E)