<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.&nbsp;<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>&nbsp;</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-&gt;cmdpendingq, not submitted yet.</P>
<P>&nbsp;</P>
<P>int __lbs_cmd(struct lbs_private *priv, uint16_t command,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct cmd_header *in_cmd, int in_cmd_size,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long callback_arg)<BR>{<BR>&nbsp;struct cmd_ctrl_node *cmdnode;<BR>&nbsp;unsigned long flags;<BR>&nbsp;int ret = 0;<BR>&nbsp;<BR>&nbsp;lbs_deb_enter(LBS_DEB_HOST);<BR>&nbsp;<BR>&nbsp;cmdnode = __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,<BR>&nbsp;&nbsp;callback, callback_arg);<BR>&nbsp;if (IS_ERR(cmdnode)) {<BR>&nbsp;&nbsp;ret = PTR_ERR(cmdnode);<BR>&nbsp;&nbsp;goto done;<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;might_sleep();<BR>&nbsp;ret = wait_event_interruptible(cmdnode-&gt;cmdwait_q, cmdnode-&gt;cmdwaitqwoken);<BR>&nbsp;<BR>&nbsp;spin_lock_irqsave(&amp;priv-&gt;driver_lock, flags);<BR>&nbsp;ret = cmdnode-&gt;result;<BR>&nbsp;if (ret)<BR>&nbsp;&nbsp;lbs_pr_info("PREP_CMD: command 0x%04x failed: %d\n",<BR>&nbsp;&nbsp;command, ret);<BR>&nbsp;<BR>&nbsp;__lbs_cleanup_and_insert_cmd(priv, cmdnode);<BR>&nbsp;spin_unlock_irqrestore(&amp;priv-&gt;driver_lock, flags);<BR>&nbsp;<BR>done:<BR>&nbsp;lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);<BR>&nbsp;return ret;<BR>}</P>
<P>&nbsp;</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>&nbsp;&nbsp;/* Flush pending command nodes */<BR>&nbsp;spin_lock_irqsave(&amp;priv-&gt;driver_lock, flags);<BR>&nbsp;lbs_deb_main("clearing pending commands\n");<BR>&nbsp;list_for_each_entry(cmdnode, &amp;priv-&gt;cmdpendingq, list) {<BR>&nbsp;&nbsp;cmdnode-&gt;result = -ENOENT;<BR>&nbsp;&nbsp;cmdnode-&gt;cmdwaitqwoken = 1;<BR>&nbsp;&nbsp;wake_up_interruptible(&amp;cmdnode-&gt;cmdwait_q);<BR>&nbsp;}</P>
<P>&nbsp;</P>
<P>This is because the command node still linked in the priv-&gt;cmdpendingq,and it self link to the <BR>priv-&gt;cmdfreeq.The list_for_each_entry will step to the list head of priv-&gt;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-&gt;prev =c7f38d98,list-&gt;next=c7f38d90,<BR>&nbsp;result = 0, address of callback=0, callback_arg = 0,address of cmdbuf = c1d8d000,<BR>&nbsp;cmdwaitqwoken = 1, address of cmdwait_q = c7ef00f4.<BR>task state= 0, PID= 0.<BR>Dump command node:address of command node =c7f38d90,list-&gt;prev =c7ef00d8,list-&gt;next=c7ef0000,<BR>&nbsp;result = -940637992, address of callback=c7ef0120, callback_arg = c7f38da0,address of cmdbuf = c7f38da0,<BR>&nbsp;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&nbsp;&nbsp;&nbsp; Tainted: G&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; W&nbsp;&nbsp; (2.6.32-00003-g930aecc-dirty #46)<BR>PC is at 0x0<BR>LR is at __wake_up_common+0x34/0x78<BR>pc : [&lt;00000000&gt;]&nbsp;&nbsp;&nbsp; lr : [&lt;c0043d28&gt;]&nbsp;&nbsp;&nbsp; psr: a00000b3<BR>sp : c7fbbdc8&nbsp; ip : 00015000&nbsp; fp : c7fbbdf4<BR>r10: 00000000&nbsp; r9 : 00000001&nbsp; r8 : c7f38dac<BR>r7 : 00000001&nbsp; r6 : 00000001&nbsp; r5 : 001027fc&nbsp; r4 : 00014ff4<BR>r3 : 00000000&nbsp; r2 : 00000000&nbsp; r1 : 00000001&nbsp; r0 : 00014ff4<BR>Flags: NzCv&nbsp; IRQs off&nbsp; FIQs on&nbsp; Mode SVC_32&nbsp; ISA Thumb&nbsp; Segment user<BR>Control: 00c5387d&nbsp; Table: 57eb4008&nbsp; DAC: 00000015<BR>Process WifiService (pid: 1731, stack limit = 0xc7fba268)<BR>Stack: (0xc7fbbdc8 to 0xc7fbc000)<BR>bdc0:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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>[&lt;c0043cf4&gt;] (__wake_up_common+0x0/0x78) from [&lt;c0043d94&gt;] (__wake_up+0x28/0x34)</P>
<P>&nbsp;The command node at the address 0xc7f38d90 is the node we discussed,it link <BR>to the head of free list.</P>
<P>&nbsp;To fix that, i do some change in __lbs_cmd, and the problem seems go <BR>away.<BR>&nbsp;ret = wait_event_interruptible(cmdnode-&gt;cmdwait_q, cmdnode-&gt;cmdwaitqwoken);<BR>&nbsp;if (ret == -ERESTARTSYS || cmdnode-&gt;result == -ENOENT) {<BR>&nbsp;&nbsp;lbs_pr_info("Remove command node from pending list,have pending signal,<BR>&nbsp;&nbsp;cmdnode address %lx.\n", cmdnode);<BR>&nbsp;&nbsp;&nbsp;if (cmdnode != priv-&gt;cur_cmd)<BR>&nbsp;&nbsp;&nbsp;&nbsp;list_del(&amp;cmdnode-&gt;list);<BR>&nbsp;&nbsp;}</P>
<P><BR>&nbsp;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>