<P>Dear All<BR>I am porting wifi support on Android to the s3c6410 developement board, and my kernel version is 2.6.32.<BR>The problem i'm dealing with is that sometimes when user unload the libertas_sdio driver,the kernel panic at<BR>lbs_stop_card. <BR></P>
<P>I track the problem, and find out it is cause by the kill system call.I tried to fix this, but i'm not </P>
<P>sure if i did it right.</P>
<P> </P>
<P>My analysis of this problem is as follows:<BR>In Android, when user want to disable the driver,the java service will ask the init process to stop the<BR>wpa_supplicant process,and then unload the wifi driver.The init process will call kill system call to do <BR>stop wpa_supplicant. This may cause a problem:<BR></P>
<P>When kernel send a kill signal,it has to wake up the target process,and wpa_supplicant process is probably <BR>sleeping in __lbs_cmd while waiting for a command to complete,and at the mean time the command may still in the<BR>priv->cmdpendingq, not submitted yet.</P>
<P> </P>
<P>int __lbs_cmd(struct lbs_private *priv, uint16_t command,<BR> struct cmd_header *in_cmd, int in_cmd_size,<BR> int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),<BR> unsigned long callback_arg)<BR>{<BR> struct cmd_ctrl_node *cmdnode;<BR> unsigned long flags;<BR> int ret = 0;<BR> <BR> lbs_deb_enter(LBS_DEB_HOST);<BR> <BR> cmdnode = __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,<BR> callback, callback_arg);<BR> if (IS_ERR(cmdnode)) {<BR> ret = PTR_ERR(cmdnode);<BR> goto done;<BR> }<BR> <BR> might_sleep();<BR> ret = wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);<BR> <BR> spin_lock_irqsave(&priv->driver_lock, flags);<BR> ret = cmdnode->result;<BR> if (ret)<BR> lbs_pr_info("PREP_CMD: command 0x%04x failed: %d\n",<BR> command, ret);<BR> <BR> __lbs_cleanup_and_insert_cmd(priv, cmdnode);<BR> spin_unlock_irqrestore(&priv->driver_lock, flags);<BR> <BR>done:<BR> lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);<BR> return ret;<BR>}</P>
<P> </P>
<P>So after kernel wake up the process from wait_event_interruptible and clean up the node and<BR>add it to the free list, the other pending list node or head is still keep link to it. <BR>When user unload the driver,the kernel will crash at __wake_up_common in lbs_stop_card.*/<BR> /* Flush pending command nodes */<BR> spin_lock_irqsave(&priv->driver_lock, flags);<BR> lbs_deb_main("clearing pending commands\n");<BR> list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {<BR> cmdnode->result = -ENOENT;<BR> cmdnode->cmdwaitqwoken = 1;<BR> wake_up_interruptible(&cmdnode->cmdwait_q);<BR> }</P>
<P> </P>
<P>This is because the command node still linked in the priv->cmdpendingq,and it self link to the <BR>priv->cmdfreeq.The list_for_each_entry will step to the list head of priv->cmdfreeq,which is doesn't<BR>have a command node structure,and this will cause kernel penic when doing wake_up to it. The dump<BR>log is as follows, i dump the command node structure befor the wake up:</P>
<P><BR>libertas enter: lbs_stop_card()<BR>libertas main: clearing pending commands<BR>lbs_stop_card:has pending command node.<BR>Dump command node:address of command node =c7ef00d8,list->prev =c7f38d98,list->next=c7f38d90,<BR> result = 0, address of callback=0, callback_arg = 0,address of cmdbuf = c1d8d000,<BR> cmdwaitqwoken = 1, address of cmdwait_q = c7ef00f4.<BR>task state= 0, PID= 0.<BR>Dump command node:address of command node =c7f38d90,list->prev =c7ef00d8,list->next=c7ef0000,<BR> result = -940637992, address of callback=c7ef0120, callback_arg = c7f38da0,address of cmdbuf = c7f38da0,<BR> cmdwaitqwoken = 8449, address of cmdwait_q = c7f38dac.<BR>task state= 4001b508, PID= 65686361.<BR>Unable to handle kernel NULL pointer dereference at virtual address 00000000<BR>pgd = c7eb4000<BR>[00000000] *pgd=57ead031, *pte=00000000, *ppte=00000000<BR>Internal error: Oops: 80000007 [#1]<BR>last sysfs file: /sys/android_power/request_state<BR>Modules linked in: wlan(-) [last unloaded: wlan]<BR>CPU: 0 Tainted: G W (2.6.32-00003-g930aecc-dirty #46)<BR>PC is at 0x0<BR>LR is at __wake_up_common+0x34/0x78<BR>pc : [<00000000>] lr : [<c0043d28>] psr: a00000b3<BR>sp : c7fbbdc8 ip : 00015000 fp : c7fbbdf4<BR>r10: 00000000 r9 : 00000001 r8 : c7f38dac<BR>r7 : 00000001 r6 : 00000001 r5 : 001027fc r4 : 00014ff4<BR>r3 : 00000000 r2 : 00000000 r1 : 00000001 r0 : 00014ff4<BR>Flags: NzCv IRQs off FIQs on Mode SVC_32 ISA Thumb Segment user<BR>Control: 00c5387d Table: 57eb4008 DAC: 00000015<BR>Process WifiService (pid: 1731, stack limit = 0xc7fba268)<BR>Stack: (0xc7fbbdc8 to 0xc7fbc000)<BR>bdc0: 00000000 60000093 c7f38d90 c7f382c0 c7f38d98 c7f38000<BR>bde0: c7fba000 00000013 c7fbbe14 c7fbbdf8 c0043d94 c0043d00 00000000 c7fbbe18<BR>be00: c020239c c7f38dac c7fbbe54 c7fbbe18 c02023b0 c0043d78 c7ef00d8 c7ef0120<BR>be20: c7f38da0 c7f38da0 00002101 c7f38dac c7cef3e0 c7fe0000 c7cef3e0 00000880<BR>be40: c002c028 00000000 c7fbbe84 c7fbbe58 bf03015c c02021fc 00000000 c7cef3f0<BR>be60: bf032a30 c7cef3e8 bf032a30 c7cef3e0 bf032a30 bf032a30 c7fbbe9c c7fbbe88<BR>be80: c024bbac bf03000c c7cef3e8 bf032a30 c7fbbeb4 c7fbbea0 c01d11f4 c024bb98<BR>bea0: c7cef3e8 c7cef41c c7fbbed4 c7fbbeb8 c01d129c c01d1194 bf032a30 bf032a30<BR>bec0: c041d93c 00000880 c7fbbef4 c7fbbed8 c01d04a4 c01d1240 00000000 bf032a30<BR>bee0: 00000000 00000880 c7fbbf14 c7fbbef8 c01d1800 c01d0418 00000000 bf032a64<BR>bf00: c7fbbf3c 00000880 c7fbbf24 c7fbbf18 c024bd9c c01d17a4 c7fbbf34 c7fbbf28<BR>bf20: bf03208c c024bd88 c7fbbfa4 c7fbbf38 c006ccbc bf032024 c1c4f1e0 6e616c77<BR>bf40: c7892200 00000006 c002c028 00000000 c7fbbf6c c7fbbf60 c009d3c0 c009d1d4<BR>bf60: c7fbbf8c c7fbbf70 c009a00c c009d39c c7892240 00c4f1e0 bf032a64 00000880<BR>bf80: c7fbbf84 00000000 a9c07658 ffffffff 00000009 00000081 00000000 c7fbbfa8<BR>bfa0: c002be80 c006caf4 a9c07658 ffffffff a9c062e4 00000880 42747f3c 425f327c<BR>bfc0: a9c07658 ffffffff 00000009 00000081 46364d88 42747ee4 42747ed0 002d90c8<BR>bfe0: a9c07680 46364d50 a9c05c69 afe0d8ac 00000010 a9c062e4 00000000 00000000<BR>Backtrace: <BR>[<c0043cf4>] (__wake_up_common+0x0/0x78) from [<c0043d94>] (__wake_up+0x28/0x34)</P>
<P> The command node at the address 0xc7f38d90 is the node we discussed,it link <BR>to the head of free list.</P>
<P> To fix that, i do some change in __lbs_cmd, and the problem seems go <BR>away.<BR> ret = wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);<BR> if (ret == -ERESTARTSYS || cmdnode->result == -ENOENT) {<BR> lbs_pr_info("Remove command node from pending list,have pending signal,<BR> cmdnode address %lx.\n", cmdnode);<BR> if (cmdnode != priv->cur_cmd)<BR> list_del(&cmdnode->list);<BR> }</P>
<P><BR> Am i do it right?<SPAN style="WIDOWS: 2; TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: medium Simsun; WHITE-SPACE: normal; ORPHANS: 2; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class=Apple-style-span></P><PRE><I>Thanks very much and Best Regards Liang Yifei</I></PRE></SPAN>