Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1654339 > unrolled thread
| Started by | Liu Xiang <liu.xiang6@zte.com.cn> |
|---|---|
| First post | 2017-05-31 17:20 +0200 |
| Last post | 2017-06-02 20:20 +0200 |
| Articles | 2 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH] net: davicom: dm9000: Avoid spinlock recursion during dm9000_timeout routine Liu Xiang <liu.xiang6@zte.com.cn> - 2017-05-31 17:20 +0200
Re: [PATCH] net: davicom: dm9000: Avoid spinlock recursion during dm9000_timeout routine David Miller <davem@davemloft.net> - 2017-06-02 20:20 +0200
| From | Liu Xiang <liu.xiang6@zte.com.cn> |
|---|---|
| Date | 2017-05-31 17:20 +0200 |
| Subject | [PATCH] net: davicom: dm9000: Avoid spinlock recursion during dm9000_timeout routine |
| Message-ID | <tNdzH-6yx-1@gated-at.bofh.it> |
On the DM9000B, dm9000_phy_write() is called after the main spinlock
is held, during the dm9000_timeout() routine. Spinlock recursion
occurs because the main spinlock is requested again in
dm9000_phy_write(). So spinlock should be avoided in dm9000_phy_write()
during the dm9000_timeout() routine.
Signed-off-by: Liu Xiang <liu.xiang6@zte.com.cn>
---
drivers/net/ethernet/davicom/dm9000.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 008dc81..afe33de 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -337,11 +337,11 @@ static void dm9000_msleep(struct board_info *db, unsigned int ms)
unsigned long reg_save;
dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
- if (!db->in_timeout)
+ if (!db->in_timeout) {
mutex_lock(&db->addr_lock);
- spin_lock_irqsave(&db->lock, flags);
-
+ spin_lock_irqsave(&db->lock, flags);
+ }
/* Save previous register address */
reg_save = readb(db->io_addr);
@@ -356,11 +356,13 @@ static void dm9000_msleep(struct board_info *db, unsigned int ms)
iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);
writeb(reg_save, db->io_addr);
- spin_unlock_irqrestore(&db->lock, flags);
+ if (!db->in_timeout)
+ spin_unlock_irqrestore(&db->lock, flags);
dm9000_msleep(db, 1); /* Wait write complete */
- spin_lock_irqsave(&db->lock, flags);
+ if (!db->in_timeout)
+ spin_lock_irqsave(&db->lock, flags);
reg_save = readb(db->io_addr);
iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */
@@ -368,9 +370,11 @@ static void dm9000_msleep(struct board_info *db, unsigned int ms)
/* restore the previous address */
writeb(reg_save, db->io_addr);
- spin_unlock_irqrestore(&db->lock, flags);
- if (!db->in_timeout)
+ if (!db->in_timeout) {
+ spin_unlock_irqrestore(&db->lock, flags);
+
mutex_unlock(&db->addr_lock);
+ }
}
/* dm9000_set_io
--
1.9.1
[toc] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2017-06-02 20:20 +0200 |
| Subject | Re: [PATCH] net: davicom: dm9000: Avoid spinlock recursion during dm9000_timeout routine |
| Message-ID | <tNZkZ-4FP-1@gated-at.bofh.it> |
| In reply to | #1654339 |
From: Liu Xiang <liu.xiang6@zte.com.cn> Date: Wed, 31 May 2017 23:06:42 +0800 > On the DM9000B, dm9000_phy_write() is called after the main spinlock > is held, during the dm9000_timeout() routine. Spinlock recursion > occurs because the main spinlock is requested again in > dm9000_phy_write(). So spinlock should be avoided in dm9000_phy_write() > during the dm9000_timeout() routine. > > Signed-off-by: Liu Xiang <liu.xiang6@zte.com.cn> It think this is racy. Now, during a timeout device reset, another thread of control can come in and access phy registers without any synchronization whatsoever.
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web