Re: help, BUG: spinlock recursion on CPU#0, httpd/29

From: angelo
Date: Sun Oct 31 2010 - 14:05:02 EST


On 31/10/2010 18:29, Greg Oliver wrote:
On Sun, Oct 31, 2010 at 12:27 PM, _angelo<angelo70@xxxxxxxxx> wrote:
hi all,
i don't know if this is the right forum, but i don't see other appropriate
kernel forums actually

starting from a main line kernel 2.6.36-rc3, i am trying to interface a
coldfire mcf5307 to a dm9000 ethernet chip in a little custom board. I did
some small changes to the dm9000.c driver, since it was for little-endian
cpus. Now it is mostly working, icmp ping and telnet are working fine.
The only issue happen when i use http, through a browser i try to read the
board html testpage: first load (GET) works, then refreshing 2 or 3 times,
kernel goes into following error:

# BUG: recent printk recursion!
<7>dm9000 dm9000: entering dm9000_interrupt
BUG: spinlock recursion on CPU#0, httpd/29
lock: 00177648, .magic: dead4ead, .owner: httpd/29, .owner_cpu: 0
Stack from 00e559b4:
0014f790 000a7d6c 00169918 00177648 dead4ead 00e26594 0000001d
00000000
00177648 000288d4 0014f79e 000a7f2e 00177648 0016997e 00177648
00e55acc
0000001f 00000000 0000010a 0017760c 000288d4 0014f79e 00029d90
0014f7a8
00177648 000289ec 00177648 0000001f 00e55acc 0000001f 0017760c
000288d4
0014f79e 00029d90 0014f790 00000b96 0000001f 00177648 00dbe5b0
000032e2
0000001f 00e55a5c 00000001 00177648 00dbe5b0 0000001f 00000000
00e55000
Call Trace with CONFIG_FRAME_POINTER disabled:
[0014f790] [000a7d6c] [00169918] [000288d4] [0014f79e]
[000a7f2e] [0016997e] [000288d4] [0014f79e] [00029d90]
[0014f7a8] [000289ec] [000288d4] [0014f79e] [00029d90]
[0014f790] [00000b96] [000032e2] [00028a6a] [0014f790]
[0014f79e] [00000b96] [000032e2] [0014f790] [000a7fda]
[0014f790] [0014f79e] [0014f7a8] [00109d94] [000fceb0]
[00103a2c] [000a4510] [00117300] [00117a40] [00004000]
[0011757e] [00118538] [000005a8] [00001ad0] [0014ce8e]
[0012ce2a] [00007f67] [00001ad0] [0012dd82] [0012923c]
[000005a8] [000005a8] [00002d80] [00030200] [0012a4b8]
[0014f790] [00008b06] [00004124] [00128a4e] [0012abae]
[000005a8] [00128048] [000005a8] [0014de4a] [00004124]
[0012dca8] [0014de4a] [00004124] [0016fae3] [0014f79e]
[000ee208] [0011f72a] [00002860] [000005a8] [000005a8]
[00002860] [000005a8] [0013aad2] [00002860] [000eb4e4]
[00002860] [0004260a] [00002860] [0004293c] [00042df6]
[0001ffff] [00002860] [00002860] [000125fa] [00002860]
[00042a10] [00002860] [00042e36] [00002860] [0000318c]
[00002860]
BUG: spinlock lockup on CPU#0, httpd/29, 00177648
...

Actually, from some debugging, the issue seems triggered from the
dm9000_interrupt routine:

static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
board_info_t *db = netdev_priv(dev);
int int_status;
unsigned long flags;
u8 reg_save;

/* A real interrupt coming */

/* holders of db->lock must always block IRQs */
spin_lock_irqsave(&db->lock, flags);

dm9000_dbg(db, 3, "entering %s\n", __func__);

/* Save previous register address */
#ifdef BE_STRAIGHT_WIRED
reg_save = (u8)readl(db->io_addr);
#else
reg_save = readb(db->io_addr);
#endif

/* Disable all interrupts */
iow(db, DM9000_IMR, IMR_PAR);

/* Got DM9000 interrupt status */
int_status = ior(db, DM9000_ISR); /* Got ISR */
iow(db, DM9000_ISR, int_status); /* Clear ISR status */

if (netif_msg_intr(db))
dev_dbg(db->dev, "interrupt status %02x\n", int_status);

/* Received the coming packet */
if (int_status& ISR_PRS)
dm9000_rx(dev);

/* Trnasmit Interrupt check */
if (int_status& ISR_PTS)
dm9000_tx_done(dev, db);

if (db->type != TYPE_DM9000E) {
if (int_status& ISR_LNKCHNG) {
/* fire a link-change request */
schedule_delayed_work(&db->phy_poll, 1);
}
}

/* Re-enable interrupt mask */
iow(db, DM9000_IMR, db->imr_all);

/* Restore previous register address */
#ifdef BE_STRAIGHT_WIRED
writel(reg_save, db->io_addr);
#else
writeb(reg_save, db->io_addr);
#endif

spin_unlock_irqrestore(&db->lock, flags);

return IRQ_HANDLED;
}


I really don't have the kernel experience to get out of this issue, so i
hope in some help or suggestion

many thanks
regards,
angelo


--
View this message in context:http://old.nabble.com/help%2C-BUG%3A-spinlock-recursion-on-CPU-0%2C-httpd-29-tp30099327p30099327.html
Sent from the linux-kernel mailing list archive at Nabble.com.
I would assume posting your *modifications* would be the first step....
Hi greg,

thanks for the reply,

i changed/added only some routines, due to the fact that i wired all the 32 bit bus of the ethernet chip straight to the CPU. But since the driver is for little-endian CPUs, all the data transfer was not working, So, just for testing this prototype board (i can wire the HW bus byte-swapped in a future prototype), i reworked some functions as below:

static void
iow(board_info_t * db, int reg, int value)
{
#ifdef BE_STRAIGHT_WIRED
writel(reg, db->io_addr);
writel(value, db->io_data);
#else
writeb(reg, db->io_addr);
writeb(value, db->io_data);
#endif
}

/* routines for sending block to chip */

static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count)
{
#ifdef CONFIG_COLDFIRE
u8 *p=(u8 *)data;

while (count--)
#ifdef BE_STRAIGHT_WIRED
writel((int)(*p++), reg);
#else
writeb(*p++, reg);
#endif
#else
writesb(reg, data, count);
#endif
}

static void dm9000_outblk_16bit(void __iomem *reg, void *data, int count)
{
#ifdef CONFIG_COLDFIRE
// TO DO
#else
writesw(reg, data, (count+1) >> 1);
#endif
}

static void dm9000_outblk_32bit(void __iomem *reg, void *data, int count)
{
#ifdef CONFIG_COLDFIRE
u32 *p = (u32*)data;

count = (count+3)>>2;

while (count--)
#ifdef BE_STRAIGHT_WIRED
writel(le32_to_cpu(*p++), reg);
#else
writel(*p++, reg);
#endif
#else
writesl(reg, data, (count+3) >> 2);
#endif
}


and still, some ioread, as below, here and there were needed.

#ifdef BE_STRAIGHT_WIRED
reg_save = (u8)readl(db->io_addr);
#else
reg_save = readb(db->io_addr);
#endif

#ifdef BE_STRAIGHT_WIRED
writel(reg_save, db->io_addr);
#else
writeb(reg_save, db->io_addr);
#endif

I defined BE_STRAIGHT_WIRED only for testing this prototype, otherwise the driver should work as is.

I didn't change anything else, to avoid damaging the well working dm9000.c driver,

thanks
angelo









--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/