Ticket #2240 (closed defect: fixed)
removing/reloading g_ether not working
| Reported by: | frankmpunkt | Owned by: | openmoko-devel |
|---|---|---|---|
| Priority: | high | Milestone: | |
| Component: | unknown | Version: | unspecified |
| Severity: | normal | Keywords: | |
| Cc: | Blocked By: | ||
| Blocking: | Estimated Completion (week): | ||
| HasPatchForReview: | yes | PatchReviewResult: | positive |
| Reproducible: | always |
Description
The problem has already been recognized long ago:
https://docs.openmoko.org/trac/ticket/15 . This defect has been marked to be fixed later. Now, two years later the same problem still occurs when doing
ifconfig usb0 down rmmod g_ether modprobe g_ether
I'd like to switch between different USB Gadgets easily. But with this bug it's even impossible to reboot properly.
Attachments
Change History
comment:2 Changed 4 years ago by lindi
When ifconfig usb0 up is called. dev->netdev_ops contains a bogus ndo_get_stats pointer:
Breakpoint 5, dev_get_stats (dev=0xc6e48000) at /local/lindi/neolinux/net/core/dev.c:4649
(gdb) p *dev->netdev_ops
$9 = {
ndo_init = 0xe1a0c00d,
ndo_uninit = 0xe92dd800,
ndo_open = 0xe24cb004,
ndo_stop = 0xe5d03030,
ndo_start_xmit = 0xe35300fd,
ndo_select_queue = 0x92833001,
ndo_change_rx_flags = 0x920330ff,
ndo_set_rx_mode = 0x95c03030,
ndo_set_multicast_list = 0x83e00012,
ndo_set_mac_address = 0x91a00003,
ndo_validate_addr = 0xe89da800,
ndo_do_ioctl = 0xe1a0c00d,
ndo_set_config = 0xe92dd810,
ndo_change_mtu = 0xe24cb004,
ndo_neigh_setup = 0xe3a03000,
ndo_tx_timeout = 0xe1a04000,
ndo_get_stats = 0xea000003,
ndo_vlan_rx_register = 0xe1500002,
ndo_vlan_rx_add_vid = 0x1a000001,
ndo_vlan_rx_kill_vid = 0xe59c0000
}
The backtrace to this call is
#0 dev_get_stats (dev=0xc6e48000) at /local/lindi/neolinux/net/core/dev.c:4649 #1 0xc023acc8 in rtnl_fill_ifinfo (skb=0xc7a6bd60, dev=0xc6e48000, type=<value optimized out>, pid=<value optimized out>, seq=1240760974, change=0, flags=<value optimi\ zed out>) at /local/lindi/neolinux/net/core/rtnetlink.c:669 #2 0xc023ae3c in rtnl_dump_ifinfo (skb=0xc7a6bd60, cb=0xc7a976e0) at /local/lindi/neolinux/net/core/rtnetlink.c:695 #3 0xc0246428 in netlink_dump (sk=0xc6f05000) at /local/lindi/neolinux/net/netlink/af_netlink.c:1550 #4 0xc0247044 in netlink_dump_start (ssk=0xc7840c00, skb=<value optimized out>, nlh=0xc6c13e00, dump=<value optimized out>, done=0) at /local/lindi/neolinux/net/netlin\ k/af_netlink.c:1629 #5 0xc023b798 in rtnetlink_rcv_msg (skb=0xc7a6be20, nlh=0xc6c13e00) at /local/lindi/neolinux/net/core/rtnetlink.c:1301 #6 0xc0248880 in netlink_rcv_skb (skb=0xc7a6be20, cb=0xc023b6b8 <rtnetlink_rcv_msg>) at /local/lindi/neolinux/net/netlink/af_netlink.c:1697 #7 0xc023b6a8 in rtnetlink_rcv (skb=0xc7a6be20) at /local/lindi/neolinux/net/core/rtnetlink.c:1337 #8 0xc024829c in netlink_unicast (ssk=0xc6f05000, skb=0xc7a6be20, pid=0, nonblock=<value optimized out>) at /local/lindi/neolinux/net/netlink/af_netlink.c:870 #9 0xc02485ec in netlink_sendmsg (kiocb=<value optimized out>, sock=0xc3413480, msg=0xc6edff54, len=20) at /local/lindi/neolinux/net/netlink/af_netlink.c:1285 #10 0xc02217c0 in sock_sendmsg (sock=<value optimized out>, msg=0xc6edff54, size=96) at /local/lindi/neolinux/net/socket.c:563 #11 0xc0221a90 in sys_sendto (fd=<value optimized out>, buff=0xc6edfed4, len=20, flags=0, addr=0xbe8fd548, addr_len=12) at /local/lindi/neolinux/net/socket.c:1651 #12 0xc002eea0 in kuser_cmpxchg_fixup ()
comment:3 Changed 4 years ago by lindi
A reliable way to crash the kernel is
insmod g_ether.ko.2 sleep 1 ifconfig usb0 up sleep 1 ifconfig usb0 down sleep 1 rmmod g_ether # ip link still shows usb0 sleep 2 insmod g_ether.ko.2 # now uses usb1 instead of usb0 sleep 2 ifconfig usb0 up # crash when dev_open tries to use usb0 sleep 2
I can even do "ifconfig usb0 up" after I have removed the g_ether module completely.
comment:4 Changed 4 years ago by lindi
It seems that "insmod g_ether.ko" calls register_netdev() but "rmmod g_ether" does not call unregister_netdev(). I think the calls _should_ go like
insmod g_ether.ko
init()
usb_composite_register()
usb_gadget_register_driver()
driver->bind() = eth_bind()
gether_setup()
register_netdev()
rmmod g_ether
cleanup()
usb_composite_unregister()
usb_gadget_unregister_driver()
driver->unbind() = eth_unbind()
gether_cleanup()
unregister_netdev()
but the problem is that in s3c2410_udc.c
- usb_gadget_register_driver calls bind() but
- usb_gadget_unregister_driver() does not call unbind().
I checked that _every other_ usb_gadget_unregister_driver in the kernel does call unbind(), for example
- atmel_usba_udc.c
- pxa25x_udc.c
- omap_udc.c
- fsl_usb2_udc.c
so why does s3c2410_udc.c not call unbind()?
Changed 4 years ago by lindi
- Attachment s3c2410_udc-do-unbind.patch added
call unbind() from usb_gadget_unregister_driver of s3c2410_udc.c

I can reproduce this with andy-tracking b4136a36f31a65d0 (Apr 25).