diff mbox series

[v4,05/12] can: slcan: use CAN network device driver API

Message ID 20220614122821.3646071-6-dario.binacchi@amarulasolutions.com (mailing list archive)
State Awaiting Upstream
Delegated to: Netdev Maintainers
Headers show
Series can: slcan: extend supported features | expand

Checks

Context Check Description
netdev/tree_selection success Series ignored based on subject, async

Commit Message

Dario Binacchi June 14, 2022, 12:28 p.m. UTC
As suggested by commit [1], now the driver uses the functions and the
data structures provided by the CAN network device driver interface.

Currently the driver doesn't implement a way to set bitrate for SLCAN
based devices via ip tool, so you'll have to do this by slcand or
slcan_attach invocation through the -sX parameter:

- slcan_attach -f -s6 -o /dev/ttyACM0
- slcand -f -s8 -o /dev/ttyUSB0

where -s6 in will set adapter's bitrate to 500 Kbit/s and -s8 to
1Mbit/s.
See the table below for further CAN bitrates:
- s0 ->   10 Kbit/s
- s1 ->   20 Kbit/s
- s2 ->   50 Kbit/s
- s3 ->  100 Kbit/s
- s4 ->  125 Kbit/s
- s5 ->  250 Kbit/s
- s6 ->  500 Kbit/s
- s7 ->  800 Kbit/s
- s8 -> 1000 Kbit/s

In doing so, the struct can_priv::bittiming.bitrate of the driver is not
set and since the open_candev() checks that the bitrate has been set, it
must be a non-zero value, the bitrate is set to a fake value (-1U)
before it is called.

The patch also changes the slcan_devs locking from rtnl to spin_lock. The
change was tested with a kernel with the CONFIG_PROVE_LOCKING option
enabled that did not show any errors.

[1] commit 39549eef3587f ("can: CAN Network device driver and Netlink interface")
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>

---

Changes in v4:
- Update the commit description.
- Use the CAN_BITRATE_UNKNOWN macro.
- Use kfree_skb() instead of can_put_echo_skb() in the slc_xmit().
- Remove the `if (slcan_devs)' check in the slc_dealloc().

Changes in v3:
- Replace (-1) with (-1U) in the commit description.

Changes in v2:
- Move CAN_SLCAN Kconfig option inside CAN_DEV scope.
- Improve the commit message.

 drivers/net/can/Kconfig |  40 +++++++--------
 drivers/net/can/slcan.c | 107 ++++++++++++++++++++--------------------
 2 files changed, 74 insertions(+), 73 deletions(-)

Comments

Oliver Sang June 28, 2022, 2:40 a.m. UTC | #1
Greeting,

FYI, we noticed the following commit (built with gcc-11):

commit: 39bbbe2356a2a13ec26a8765d8a4e6dfe7ce33e9 ("[PATCH v4 05/12] can: slcan: use CAN network device driver API")
url: https://github.com/intel-lab-lkp/linux/commits/Dario-Binacchi/can-slcan-extend-supported-features/20220614-203636
patch link: https://lore.kernel.org/lkml/20220614122821.3646071-6-dario.binacchi@amarulasolutions.com

in testcase: ltp
version: ltp-x86_64-14c1f76-1_20220625
with following parameters:

	test: pty
	ucode: 0x21

test-description: The LTP testsuite contains a collection of tools for testing the Linux kernel and related features.
test-url: http://linux-test-project.github.io/


on test machine: 4 threads 1 sockets Intel(R) Core(TM) i3-3220 CPU @ 3.30GHz with 8G memory

caused below changes (please refer to attached dmesg/kmsg for entire log/backtrace):



If you fix the issue, kindly add following tag
Reported-by: kernel test robot <oliver.sang@intel.com>


[  164.290583][ T3878] BUG: sleeping function called from invalid context at mm/page_alloc.c:5203
[  164.290589][ T3878] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 3878, name: pty03
[  164.290592][ T3878] preempt_count: 1, expected: 0
[  164.290595][ T3878] CPU: 1 PID: 3878 Comm: pty03 Tainted: G S                5.19.0-rc2-00005-g39bbbe2356a2 #1
[  164.290600][ T3878] Hardware name: Hewlett-Packard p6-1451cx/2ADA, BIOS 8.15 02/05/2013
[  164.290602][ T3878] Call Trace:
[  164.290604][ T3878]  <TASK>
[ 164.290606][ T3878] dump_stack_lvl (lib/dump_stack.c:107 (discriminator 1)) 
[ 164.290615][ T3878] __might_resched.cold (kernel/sched/core.c:9792) 
[ 164.290621][ T3878] prepare_alloc_pages+0x330/0x500 
[ 164.290628][ T3878] ? tty_set_ldisc (drivers/tty/tty_ldisc.c:555) 
[ 164.290634][ T3878] __alloc_pages (mm/page_alloc.c:5415) 
[ 164.290637][ T3878] ? __alloc_pages_slowpath+0x15c0/0x15c0 
[ 164.290641][ T3878] ? tty_set_ldisc (drivers/tty/tty_ldisc.c:555) 
[ 164.290645][ T3878] ? kasan_save_stack (mm/kasan/common.c:40) 
[ 164.290650][ T3878] ? kasan_set_track (mm/kasan/common.c:45) 
[ 164.290654][ T3878] ? __kasan_slab_free (mm/kasan/common.c:368 mm/kasan/common.c:328 mm/kasan/common.c:374) 
[ 164.290658][ T3878] ? entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:115) 
[ 164.290663][ T3878] ? do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) 
[ 164.290668][ T3878] ? entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:115) 
[ 164.290672][ T3878] kmalloc_large_node (mm/slub.c:4432) 
[ 164.290677][ T3878] __kmalloc_node (include/asm-generic/getorder.h:41 mm/slub.c:4450) 
[ 164.290681][ T3878] kvmalloc_node (mm/util.c:619) 
[ 164.290687][ T3878] alloc_netdev_mqs (net/core/dev.c:10577) 
[ 164.290694][ T3878] ? can_get_state_str (drivers/net/can/dev/dev.c:222) can_dev
[ 164.290704][ T3878] ? _raw_spin_lock (arch/x86/include/asm/atomic.h:202 include/linux/atomic/atomic-instrumented.h:543 include/asm-generic/qspinlock.h:111 include/linux/spinlock.h:185 include/linux/spinlock_api_smp.h:134 kernel/locking/spinlock.c:154) 
[ 164.290708][ T3878] alloc_candev_mqs (drivers/net/can/dev/dev.c:262) can_dev
[ 164.290717][ T3878] slcan_open (drivers/net/can/slcan.c:531 drivers/net/can/slcan.c:584) slcan
[ 164.290723][ T3878] tty_ldisc_open (drivers/tty/tty_ldisc.c:433) 
[ 164.290728][ T3878] tty_set_ldisc (drivers/tty/tty_ldisc.c:558) 
[ 164.290733][ T3878] tty_ioctl (drivers/tty/tty_io.c:2714) 
[ 164.290736][ T3878] ? do_sys_openat2 (fs/open.c:1288) 
[ 164.290740][ T3878] ? tty_release (drivers/tty/tty_io.c:2655) 
[ 164.290744][ T3878] ? do_sys_openat2 (fs/open.c:1288) 
[ 164.290747][ T3878] ? build_open_flags (fs/open.c:1264) 
[ 164.290751][ T3878] ? __ia32_sys_stat (fs/stat.c:396) 
[ 164.290755][ T3878] ? userns_owner (kernel/user_namespace.c:371) 
[ 164.290760][ T3878] ? __fget_files (arch/x86/include/asm/atomic64_64.h:22 include/linux/atomic/atomic-arch-fallback.h:2363 include/linux/atomic/atomic-arch-fallback.h:2388 include/linux/atomic/atomic-arch-fallback.h:2404 include/linux/atomic/atomic-long.h:497 include/linux/atomic/atomic-instrumented.h:1854 fs/file.c:882 fs/file.c:913) 
[ 164.290764][ T3878] __x64_sys_ioctl (fs/ioctl.c:52 fs/ioctl.c:870 fs/ioctl.c:856 fs/ioctl.c:856) 
[ 164.290768][ T3878] do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) 
[ 164.290773][ T3878] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:115) 
[  164.290777][ T3878] RIP: 0033:0x7f86f3323cc7
[ 164.290781][ T3878] Code: 00 00 00 48 8b 05 c9 91 0c 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 99 91 0c 00 f7 d8 64 89 01 48
All code
========
   0:	00 00                	add    %al,(%rax)
   2:	00 48 8b             	add    %cl,-0x75(%rax)
   5:	05 c9 91 0c 00       	add    $0xc91c9,%eax
   a:	64 c7 00 26 00 00 00 	movl   $0x26,%fs:(%rax)
  11:	48 c7 c0 ff ff ff ff 	mov    $0xffffffffffffffff,%rax
  18:	c3                   	retq   
  19:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
  20:	00 00 00 
  23:	b8 10 00 00 00       	mov    $0x10,%eax
  28:	0f 05                	syscall 
  2a:*	48 3d 01 f0 ff ff    	cmp    $0xfffffffffffff001,%rax		<-- trapping instruction
  30:	73 01                	jae    0x33
  32:	c3                   	retq   
  33:	48 8b 0d 99 91 0c 00 	mov    0xc9199(%rip),%rcx        # 0xc91d3
  3a:	f7 d8                	neg    %eax
  3c:	64 89 01             	mov    %eax,%fs:(%rcx)
  3f:	48                   	rex.W

Code starting with the faulting instruction
===========================================
   0:	48 3d 01 f0 ff ff    	cmp    $0xfffffffffffff001,%rax
   6:	73 01                	jae    0x9
   8:	c3                   	retq   
   9:	48 8b 0d 99 91 0c 00 	mov    0xc9199(%rip),%rcx        # 0xc91a9
  10:	f7 d8                	neg    %eax
  12:	64 89 01             	mov    %eax,%fs:(%rcx)
  15:	48                   	rex.W
[  164.290784][ T3878] RSP: 002b:00007fff6a8fb8b8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
[  164.290789][ T3878] RAX: ffffffffffffffda RBX: 00007f86f322c6c0 RCX: 00007f86f3323cc7
[  164.290792][ T3878] RDX: 000055911985c700 RSI: 0000000000005423 RDI: 000000000000000d
[  164.290795][ T3878] RBP: 000055911985c700 R08: 0000000000000000 R09: cccccccccccccccd
[  164.290797][ T3878] R10: 0000000000000000 R11: 0000000000000246 R12: 000000000000000d
[  164.290799][ T3878] R13: 0000000000000006 R14: 000055911985c6a0 R15: 0000000000000004
[  164.290803][ T3878]  </TASK>
[  164.738226][ T3878] BUG: scheduling while atomic: pty03/3878/0x00000002
[  164.738233][ T3878] Modules linked in: slcan can_dev n_hdlc netconsole btrfs blake2b_generic xor raid6_pq zstd_compress libcrc32c sd_mod t10_pi crc64_rocksoft_generic crc64_rocksoft crc64 sg i915 intel_rapl_msr intel_gtt intel_rapl_common drm_buddy x86_pkg_temp_thermal drm_display_helper intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul crc32c_intel ahci ttm ghash_clmulni_intel rapl libahci intel_cstate ipmi_devintf drm_kms_helper intel_uncore ipmi_msghandler usb_storage mei_me syscopyarea sysfillrect libata sysimgblt mei fb_sys_fops video drm fuse ip_tables
[  164.738298][ T3878] CPU: 3 PID: 3878 Comm: pty03 Tainted: G S      W         5.19.0-rc2-00005-g39bbbe2356a2 #1
[  164.738302][ T3878] Hardware name: Hewlett-Packard p6-1451cx/2ADA, BIOS 8.15 02/05/2013
[  164.738305][ T3878] Call Trace:
[  164.738307][ T3878]  <TASK>
[ 164.738309][ T3878] dump_stack_lvl (lib/dump_stack.c:107 (discriminator 1)) 
[ 164.738318][ T3878] __schedule_bug.cold (kernel/sched/core.c:5661) 
[ 164.738323][ T3878] schedule_debug (arch/x86/include/asm/preempt.h:35 kernel/sched/core.c:5688) 
[ 164.738329][ T3878] __schedule (arch/x86/include/asm/jump_label.h:27 include/linux/jump_label.h:207 kernel/sched/features.h:40 kernel/sched/core.c:6324) 
[ 164.738335][ T3878] ? node_tag_clear (arch/x86/include/asm/bitops.h:94 include/asm-generic/bitops/instrumented-non-atomic.h:43 lib/radix-tree.c:107 lib/radix-tree.c:1000) 
[ 164.738340][ T3878] ? io_schedule_timeout (kernel/sched/core.c:6310) 
[ 164.738344][ T3878] ? idr_alloc_u32 (lib/idr.c:55) 
[ 164.738349][ T3878] ? _raw_spin_lock_irq (arch/x86/include/asm/atomic.h:202 include/linux/atomic/atomic-instrumented.h:543 include/asm-generic/qspinlock.h:111 include/linux/spinlock.h:185 include/linux/spinlock_api_smp.h:120 kernel/locking/spinlock.c:170) 
[ 164.738353][ T3878] schedule (include/linux/instrumented.h:71 (discriminator 1) include/asm-generic/bitops/instrumented-non-atomic.h:134 (discriminator 1) include/linux/thread_info.h:118 (discriminator 1) include/linux/sched.h:2196 (discriminator 1) kernel/sched/core.c:6502 (discriminator 1)) 
[ 164.738358][ T3878] rwsem_down_write_slowpath (arch/x86/include/asm/current.h:15 kernel/locking/rwsem.c:1174) 
[ 164.738362][ T3878] ? __down_timeout (kernel/locking/rwsem.c:1099) 
[ 164.738365][ T3878] ? _raw_write_lock_irq (kernel/locking/spinlock.c:153) 
[ 164.738370][ T3878] ? idr_get_free (lib/radix-tree.c:1533) 
[ 164.738373][ T3878] ? kernfs_dir_fop_release (fs/kernfs/dir.c:584) 
[ 164.738379][ T3878] down_write (kernel/locking/rwsem.c:1544) 
[ 164.738383][ T3878] ? down_write_killable (kernel/locking/rwsem.c:1540) 
[ 164.738386][ T3878] ? idr_alloc (lib/idr.c:118) 
[ 164.738389][ T3878] ? _raw_spin_lock (arch/x86/include/asm/atomic.h:202 include/linux/atomic/atomic-instrumented.h:543 include/asm-generic/qspinlock.h:111 include/linux/spinlock.h:185 include/linux/spinlock_api_smp.h:134 kernel/locking/spinlock.c:154) 
[ 164.738393][ T3878] ? __fprop_add_percpu_max (lib/idr.c:35) 
[ 164.738397][ T3878] kernfs_add_one (include/linux/kernfs.h:332 fs/kernfs/dir.c:737) 
[ 164.738402][ T3878] ? kernfs_new_node (fs/kernfs/dir.c:659) 
[ 164.738406][ T3878] ? device_remove_bin_file (drivers/base/core.c:2089) 
[ 164.738411][ T3878] __kernfs_create_file (fs/kernfs/file.c:1016) 
[ 164.738415][ T3878] sysfs_add_file_mode_ns (fs/sysfs/file.c:301) 
[ 164.738419][ T3878] ? projid_m_show (kernel/user_namespace.c:308) 
[ 164.738423][ T3878] ? _raw_write_lock_irq (kernel/locking/spinlock.c:153) 
[ 164.738427][ T3878] create_files (fs/sysfs/group.c:66 (discriminator 3)) 
[ 164.738431][ T3878] ? make_kgid (kernel/user_namespace.c:475) 
[ 164.738434][ T3878] internal_create_group (fs/sysfs/group.c:148) 
[ 164.738438][ T3878] ? down_write (arch/x86/include/asm/atomic64_64.h:34 include/linux/atomic/atomic-long.h:41 include/linux/atomic/atomic-instrumented.h:1280 kernel/locking/rwsem.c:139 kernel/locking/rwsem.c:256 kernel/locking/rwsem.c:1286 kernel/locking/rwsem.c:1296 kernel/locking/rwsem.c:1543) 
[ 164.738441][ T3878] ? create_files (fs/sysfs/group.c:109) 
[ 164.738444][ T3878] ? __cond_resched (kernel/sched/core.c:8217) 
[ 164.738448][ T3878] ? down_write (arch/x86/include/asm/atomic64_64.h:34 include/linux/atomic/atomic-long.h:41 include/linux/atomic/atomic-instrumented.h:1280 kernel/locking/rwsem.c:139 kernel/locking/rwsem.c:256 kernel/locking/rwsem.c:1286 kernel/locking/rwsem.c:1296 kernel/locking/rwsem.c:1543) 
[ 164.738452][ T3878] internal_create_groups+0x7c/0x140 
[ 164.738456][ T3878] device_add_attrs (drivers/base/core.c:2621) 
[ 164.738460][ T3878] ? klist_children_put (drivers/base/core.c:2614) 
[ 164.738464][ T3878] ? kernfs_create_link (fs/kernfs/symlink.c:48) 
[ 164.738467][ T3878] ? kernfs_put (arch/x86/include/asm/atomic.h:123 (discriminator 1) include/linux/atomic/atomic-instrumented.h:576 (discriminator 1) fs/kernfs/dir.c:521 (discriminator 1)) 
[ 164.738471][ T3878] device_add (drivers/base/core.c:3368) 
[ 164.738476][ T3878] ? device_initialize (drivers/base/core.c:3200) 
[ 164.738479][ T3878] ? __fw_devlink_link_to_suppliers (drivers/base/core.c:3299) 
[ 164.738484][ T3878] ? __hrtimer_init (kernel/time/hrtimer.c:1559) 
[ 164.738488][ T3878] netdev_register_kobject (net/core/net-sysfs.c:2014) 
[ 164.738493][ T3878] register_netdevice (net/core/dev.c:10047) 
[ 164.738498][ T3878] ? __cond_resched (kernel/sched/core.c:8217) 
[ 164.738502][ T3878] ? netdev_change_features (net/core/dev.c:9942) 
[ 164.738507][ T3878] register_netdev (net/core/dev.c:10171) 
[ 164.738511][ T3878] register_candev (drivers/net/can/dev/dev.c:460) can_dev
[ 164.738522][ T3878] ? can_set_termination (drivers/net/can/dev/dev.c:460) can_dev
[ 164.738529][ T3878] ? _raw_spin_lock (arch/x86/include/asm/atomic.h:202 include/linux/atomic/atomic-instrumented.h:543 include/asm-generic/qspinlock.h:111 include/linux/spinlock.h:185 include/linux/spinlock_api_smp.h:134 kernel/locking/spinlock.c:154) 
[ 164.738533][ T3878] ? alloc_candev_mqs (drivers/net/can/dev/dev.c:284) can_dev
[ 164.738541][ T3878] slcan_open (drivers/net/can/slcan.c:598) slcan
[ 164.738547][ T3878] tty_ldisc_open (drivers/tty/tty_ldisc.c:433) 
[ 164.738552][ T3878] tty_set_ldisc (drivers/tty/tty_ldisc.c:558) 
[ 164.738557][ T3878] tty_ioctl (drivers/tty/tty_io.c:2714) 
[ 164.738561][ T3878] ? tty_release (drivers/tty/tty_io.c:2655) 
[ 164.738565][ T3878] ? __switch_to (arch/x86/kernel/process.h:38 arch/x86/kernel/process_64.c:627) 
[ 164.738569][ T3878] ? __schedule (kernel/sched/core.c:6310) 
[ 164.738574][ T3878] ? io_schedule_timeout (kernel/sched/core.c:6310) 
[ 164.738578][ T3878] ? __fget_files (arch/x86/include/asm/atomic64_64.h:22 include/linux/atomic/atomic-arch-fallback.h:2363 include/linux/atomic/atomic-arch-fallback.h:2388 include/linux/atomic/atomic-arch-fallback.h:2404 include/linux/atomic/atomic-long.h:497 include/linux/atomic/atomic-instrumented.h:1854 fs/file.c:882 fs/file.c:913) 
[ 164.738583][ T3878] __x64_sys_ioctl (fs/ioctl.c:52 fs/ioctl.c:870 fs/ioctl.c:856 fs/ioctl.c:856) 
[ 164.738587][ T3878] do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) 
[ 164.738591][ T3878] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:115) 
[  164.738596][ T3878] RIP: 0033:0x7f86f3323cc7
[ 164.738599][ T3878] Code: 00 00 00 48 8b 05 c9 91 0c 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 99 91 0c 00 f7 d8 64 89 01 48
All code
========
   0:	00 00                	add    %al,(%rax)
   2:	00 48 8b             	add    %cl,-0x75(%rax)
   5:	05 c9 91 0c 00       	add    $0xc91c9,%eax
   a:	64 c7 00 26 00 00 00 	movl   $0x26,%fs:(%rax)
  11:	48 c7 c0 ff ff ff ff 	mov    $0xffffffffffffffff,%rax
  18:	c3                   	retq   
  19:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
  20:	00 00 00 
  23:	b8 10 00 00 00       	mov    $0x10,%eax
  28:	0f 05                	syscall 
  2a:*	48 3d 01 f0 ff ff    	cmp    $0xfffffffffffff001,%rax		<-- trapping instruction
  30:	73 01                	jae    0x33
  32:	c3                   	retq   
  33:	48 8b 0d 99 91 0c 00 	mov    0xc9199(%rip),%rcx        # 0xc91d3
  3a:	f7 d8                	neg    %eax
  3c:	64 89 01             	mov    %eax,%fs:(%rcx)
  3f:	48                   	rex.W

Code starting with the faulting instruction
===========================================
   0:	48 3d 01 f0 ff ff    	cmp    $0xfffffffffffff001,%rax
   6:	73 01                	jae    0x9
   8:	c3                   	retq   
   9:	48 8b 0d 99 91 0c 00 	mov    0xc9199(%rip),%rcx        # 0xc91a9
  10:	f7 d8                	neg    %eax
  12:	64 89 01             	mov    %eax,%fs:(%rcx)
  15:	48                   	rex.W
[  164.738603][ T3878] RSP: 002b:00007fff6a8fb8b8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
[  164.738608][ T3878] RAX: ffffffffffffffda RBX: 00007f86f322c6c0 RCX: 00007f86f3323cc7
[  164.738611][ T3878] RDX: 000055911985c700 RSI: 0000000000005423 RDI: 000000000000000d
[  164.738613][ T3878] RBP: 000055911985c700 R08: 0000000000000000 R09: cccccccccccccccd
[  164.738616][ T3878] R10: 0000000000000000 R11: 0000000000000246 R12: 000000000000000d
[  164.738618][ T3878] R13: 0000000000000006 R14: 000055911985c6a0 R15: 0000000000000004
[  164.738621][ T3878]  </TASK>


To reproduce:

        git clone https://github.com/intel/lkp-tests.git
        cd lkp-tests
        sudo bin/lkp install job.yaml           # job file is attached in this email
        bin/lkp split-job --compatible job.yaml # generate the yaml file for lkp run
        sudo bin/lkp run generated-yaml-file

        # if come across any failure that blocks the test,
        # please remove ~/.lkp and /lkp dir to run from a clean state.
Marc Kleine-Budde June 28, 2022, 9:28 a.m. UTC | #2
On 14.06.2022 14:28:14, Dario Binacchi wrote:
> As suggested by commit [1], now the driver uses the functions and the
> data structures provided by the CAN network device driver interface.
> 
> Currently the driver doesn't implement a way to set bitrate for SLCAN
> based devices via ip tool, so you'll have to do this by slcand or
> slcan_attach invocation through the -sX parameter:
> 
> - slcan_attach -f -s6 -o /dev/ttyACM0
> - slcand -f -s8 -o /dev/ttyUSB0
> 
> where -s6 in will set adapter's bitrate to 500 Kbit/s and -s8 to
> 1Mbit/s.
> See the table below for further CAN bitrates:
> - s0 ->   10 Kbit/s
> - s1 ->   20 Kbit/s
> - s2 ->   50 Kbit/s
> - s3 ->  100 Kbit/s
> - s4 ->  125 Kbit/s
> - s5 ->  250 Kbit/s
> - s6 ->  500 Kbit/s
> - s7 ->  800 Kbit/s
> - s8 -> 1000 Kbit/s
> 
> In doing so, the struct can_priv::bittiming.bitrate of the driver is not
> set and since the open_candev() checks that the bitrate has been set, it
> must be a non-zero value, the bitrate is set to a fake value (-1U)
> before it is called.
> 
> The patch also changes the slcan_devs locking from rtnl to spin_lock. The
> change was tested with a kernel with the CONFIG_PROVE_LOCKING option
> enabled that did not show any errors.

You're not allowed to call alloc_candev() with a spin_lock held. See
today's kernel test robot mail:

| https://lore.kernel.org/all/YrpqO5jepAvv4zkf@xsang-OptiPlex-9020

I think it's best to keep the rtnl for now.

regards,
Marc
Dario Binacchi June 28, 2022, 9:48 a.m. UTC | #3
Hi Marc,

On Tue, Jun 28, 2022 at 11:28 AM Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>
> On 14.06.2022 14:28:14, Dario Binacchi wrote:
> > As suggested by commit [1], now the driver uses the functions and the
> > data structures provided by the CAN network device driver interface.
> >
> > Currently the driver doesn't implement a way to set bitrate for SLCAN
> > based devices via ip tool, so you'll have to do this by slcand or
> > slcan_attach invocation through the -sX parameter:
> >
> > - slcan_attach -f -s6 -o /dev/ttyACM0
> > - slcand -f -s8 -o /dev/ttyUSB0
> >
> > where -s6 in will set adapter's bitrate to 500 Kbit/s and -s8 to
> > 1Mbit/s.
> > See the table below for further CAN bitrates:
> > - s0 ->   10 Kbit/s
> > - s1 ->   20 Kbit/s
> > - s2 ->   50 Kbit/s
> > - s3 ->  100 Kbit/s
> > - s4 ->  125 Kbit/s
> > - s5 ->  250 Kbit/s
> > - s6 ->  500 Kbit/s
> > - s7 ->  800 Kbit/s
> > - s8 -> 1000 Kbit/s
> >
> > In doing so, the struct can_priv::bittiming.bitrate of the driver is not
> > set and since the open_candev() checks that the bitrate has been set, it
> > must be a non-zero value, the bitrate is set to a fake value (-1U)
> > before it is called.
> >
> > The patch also changes the slcan_devs locking from rtnl to spin_lock. The
> > change was tested with a kernel with the CONFIG_PROVE_LOCKING option
> > enabled that did not show any errors.
>
> You're not allowed to call alloc_candev() with a spin_lock held. See
> today's kernel test robot mail:
>
> | https://lore.kernel.org/all/YrpqO5jepAvv4zkf@xsang-OptiPlex-9020
>
> I think it's best to keep the rtnl for now.

The rtnl_lock() uses a mutex while I used a spin_lock.

static DEFINE_MUTEX(rtnl_mutex);

void rtnl_lock(void)
{
mutex_lock(&rtnl_mutex);
}
EXPORT_SYMBOL(rtnl_lock);

So might it be worth trying with a mutex instead of rtnl_lock(), or do
you think it is
safer to return to rtn_lock () anyway?

Thanks and regards,
Dario

>
> regards,
> Marc
>
> --
> Pengutronix e.K.                 | Marc Kleine-Budde           |
> Embedded Linux                   | https://www.pengutronix.de  |
> Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
> Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |
Marc Kleine-Budde June 28, 2022, 10:38 a.m. UTC | #4
On 28.06.2022 11:48:48, Dario Binacchi wrote:
> Hi Marc,
> 
> On Tue, Jun 28, 2022 at 11:28 AM Marc Kleine-Budde <mkl@pengutronix.de> wrote:
> >
> > On 14.06.2022 14:28:14, Dario Binacchi wrote:
> > > As suggested by commit [1], now the driver uses the functions and the
> > > data structures provided by the CAN network device driver interface.
> > >
> > > Currently the driver doesn't implement a way to set bitrate for SLCAN
> > > based devices via ip tool, so you'll have to do this by slcand or
> > > slcan_attach invocation through the -sX parameter:
> > >
> > > - slcan_attach -f -s6 -o /dev/ttyACM0
> > > - slcand -f -s8 -o /dev/ttyUSB0
> > >
> > > where -s6 in will set adapter's bitrate to 500 Kbit/s and -s8 to
> > > 1Mbit/s.
> > > See the table below for further CAN bitrates:
> > > - s0 ->   10 Kbit/s
> > > - s1 ->   20 Kbit/s
> > > - s2 ->   50 Kbit/s
> > > - s3 ->  100 Kbit/s
> > > - s4 ->  125 Kbit/s
> > > - s5 ->  250 Kbit/s
> > > - s6 ->  500 Kbit/s
> > > - s7 ->  800 Kbit/s
> > > - s8 -> 1000 Kbit/s
> > >
> > > In doing so, the struct can_priv::bittiming.bitrate of the driver is not
> > > set and since the open_candev() checks that the bitrate has been set, it
> > > must be a non-zero value, the bitrate is set to a fake value (-1U)
> > > before it is called.
> > >
> > > The patch also changes the slcan_devs locking from rtnl to spin_lock. The
> > > change was tested with a kernel with the CONFIG_PROVE_LOCKING option
> > > enabled that did not show any errors.
> >
> > You're not allowed to call alloc_candev() with a spin_lock held. See
> > today's kernel test robot mail:
> >
> > | https://lore.kernel.org/all/YrpqO5jepAvv4zkf@xsang-OptiPlex-9020
> >
> > I think it's best to keep the rtnl for now.
> 
> The rtnl_lock() uses a mutex while I used a spin_lock.
> 
> static DEFINE_MUTEX(rtnl_mutex);
> 
> void rtnl_lock(void)
> {
> mutex_lock(&rtnl_mutex);
> }
> EXPORT_SYMBOL(rtnl_lock);
> 
> So might it be worth trying with a mutex instead of rtnl_lock(), or do
> you think it is
> safer to return to rtn_lock () anyway?

As Max pointed out the whole static dev array is not needed at all. Just
keep the rtnl, until removing the array altogether.

regards,
Marc
diff mbox series

Patch

diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index b2dcc1e5a388..45997d39621c 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -28,26 +28,6 @@  config CAN_VXCAN
 	  This driver can also be built as a module.  If so, the module
 	  will be called vxcan.
 
-config CAN_SLCAN
-	tristate "Serial / USB serial CAN Adaptors (slcan)"
-	depends on TTY
-	help
-	  CAN driver for several 'low cost' CAN interfaces that are attached
-	  via serial lines or via USB-to-serial adapters using the LAWICEL
-	  ASCII protocol. The driver implements the tty linediscipline N_SLCAN.
-
-	  As only the sending and receiving of CAN frames is implemented, this
-	  driver should work with the (serial/USB) CAN hardware from:
-	  www.canusb.com / www.can232.com / www.mictronics.de / www.canhack.de
-
-	  Userspace tools to attach the SLCAN line discipline (slcan_attach,
-	  slcand) can be found in the can-utils at the linux-can project, see
-	  https://github.com/linux-can/can-utils for details.
-
-	  The slcan driver supports up to 10 CAN netdevices by default which
-	  can be changed by the 'maxdev=xx' module option. This driver can
-	  also be built as a module. If so, the module will be called slcan.
-
 config CAN_DEV
 	tristate "Platform CAN drivers with Netlink support"
 	default y
@@ -118,6 +98,26 @@  config CAN_KVASER_PCIEFD
 	    Kvaser Mini PCI Express HS v2
 	    Kvaser Mini PCI Express 2xHS v2
 
+config CAN_SLCAN
+	tristate "Serial / USB serial CAN Adaptors (slcan)"
+	depends on TTY
+	help
+	  CAN driver for several 'low cost' CAN interfaces that are attached
+	  via serial lines or via USB-to-serial adapters using the LAWICEL
+	  ASCII protocol. The driver implements the tty linediscipline N_SLCAN.
+
+	  As only the sending and receiving of CAN frames is implemented, this
+	  driver should work with the (serial/USB) CAN hardware from:
+	  www.canusb.com / www.can232.com / www.mictronics.de / www.canhack.de
+
+	  Userspace tools to attach the SLCAN line discipline (slcan_attach,
+	  slcand) can be found in the can-utils at the linux-can project, see
+	  https://github.com/linux-can/can-utils for details.
+
+	  The slcan driver supports up to 10 CAN netdevices by default which
+	  can be changed by the 'maxdev=xx' module option. This driver can
+	  also be built as a module. If so, the module will be called slcan.
+
 config CAN_SUN4I
 	tristate "Allwinner A10 CAN controller"
 	depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index c39580b142e0..c7ff11dd2278 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -56,7 +56,6 @@ 
 #include <linux/can.h>
 #include <linux/can/dev.h>
 #include <linux/can/skb.h>
-#include <linux/can/can-ml.h>
 
 MODULE_ALIAS_LDISC(N_SLCAN);
 MODULE_DESCRIPTION("serial line CAN interface");
@@ -79,6 +78,7 @@  MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces");
 #define SLC_EFF_ID_LEN 8
 
 struct slcan {
+	struct can_priv         can;
 	int			magic;
 
 	/* Various fields. */
@@ -100,6 +100,7 @@  struct slcan {
 };
 
 static struct net_device **slcan_devs;
+static DEFINE_SPINLOCK(slcan_lock);
 
  /************************************************************************
   *			SLCAN ENCAPSULATION FORMAT			 *
@@ -394,6 +395,8 @@  static int slc_close(struct net_device *dev)
 		clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
 	}
 	netif_stop_queue(dev);
+	close_candev(dev);
+	sl->can.state = CAN_STATE_STOPPED;
 	sl->rcount   = 0;
 	sl->xleft    = 0;
 	spin_unlock_bh(&sl->lock);
@@ -405,20 +408,34 @@  static int slc_close(struct net_device *dev)
 static int slc_open(struct net_device *dev)
 {
 	struct slcan *sl = netdev_priv(dev);
+	int err;
 
 	if (sl->tty == NULL)
 		return -ENODEV;
 
+	/* The baud rate is not set with the command
+	 * `ip link set <iface> type can bitrate <baud>' and therefore
+	 * can.bittiming.bitrate is CAN_BITRATE_UNSET (0), causing
+	 * open_candev() to fail. So let's set to a fake value.
+	 */
+	sl->can.bittiming.bitrate = CAN_BITRATE_UNKNOWN;
+	err = open_candev(dev);
+	if (err) {
+		netdev_err(dev, "failed to open can device\n");
+		return err;
+	}
+
+	sl->can.state = CAN_STATE_ERROR_ACTIVE;
 	sl->flags &= BIT(SLF_INUSE);
 	netif_start_queue(dev);
 	return 0;
 }
 
-/* Hook the destructor so we can free slcan devs at the right point in time */
-static void slc_free_netdev(struct net_device *dev)
+static void slc_dealloc(struct slcan *sl)
 {
-	int i = dev->base_addr;
+	int i = sl->dev->base_addr;
 
+	free_candev(sl->dev);
 	slcan_devs[i] = NULL;
 }
 
@@ -434,24 +451,6 @@  static const struct net_device_ops slc_netdev_ops = {
 	.ndo_change_mtu         = slcan_change_mtu,
 };
 
-static void slc_setup(struct net_device *dev)
-{
-	dev->netdev_ops		= &slc_netdev_ops;
-	dev->needs_free_netdev	= true;
-	dev->priv_destructor	= slc_free_netdev;
-
-	dev->hard_header_len	= 0;
-	dev->addr_len		= 0;
-	dev->tx_queue_len	= 10;
-
-	dev->mtu		= CAN_MTU;
-	dev->type		= ARPHRD_CAN;
-
-	/* New-style flags. */
-	dev->flags		= IFF_NOARP;
-	dev->features           = NETIF_F_HW_CSUM;
-}
-
 /******************************************
   Routines looking at TTY side.
  ******************************************/
@@ -514,11 +513,8 @@  static void slc_sync(void)
 static struct slcan *slc_alloc(void)
 {
 	int i;
-	char name[IFNAMSIZ];
 	struct net_device *dev = NULL;
-	struct can_ml_priv *can_ml;
 	struct slcan       *sl;
-	int size;
 
 	for (i = 0; i < maxdev; i++) {
 		dev = slcan_devs[i];
@@ -531,16 +527,14 @@  static struct slcan *slc_alloc(void)
 	if (i >= maxdev)
 		return NULL;
 
-	sprintf(name, "slcan%d", i);
-	size = ALIGN(sizeof(*sl), NETDEV_ALIGN) + sizeof(struct can_ml_priv);
-	dev = alloc_netdev(size, name, NET_NAME_UNKNOWN, slc_setup);
+	dev = alloc_candev(sizeof(*sl), 1);
 	if (!dev)
 		return NULL;
 
+	snprintf(dev->name, sizeof(dev->name), "slcan%d", i);
+	dev->netdev_ops = &slc_netdev_ops;
 	dev->base_addr  = i;
 	sl = netdev_priv(dev);
-	can_ml = (void *)sl + ALIGN(sizeof(*sl), NETDEV_ALIGN);
-	can_set_ml_priv(dev, can_ml);
 
 	/* Initialize channel control data */
 	sl->magic = SLCAN_MAGIC;
@@ -573,11 +567,7 @@  static int slcan_open(struct tty_struct *tty)
 	if (tty->ops->write == NULL)
 		return -EOPNOTSUPP;
 
-	/* RTnetlink lock is misused here to serialize concurrent
-	   opens of slcan channels. There are better ways, but it is
-	   the simplest one.
-	 */
-	rtnl_lock();
+	spin_lock(&slcan_lock);
 
 	/* Collect hanged up channels. */
 	slc_sync();
@@ -605,13 +595,15 @@  static int slcan_open(struct tty_struct *tty)
 
 		set_bit(SLF_INUSE, &sl->flags);
 
-		err = register_netdevice(sl->dev);
-		if (err)
+		err = register_candev(sl->dev);
+		if (err) {
+			pr_err("slcan: can't register candev\n");
 			goto err_free_chan;
+		}
 	}
 
 	/* Done.  We have linked the TTY line to a channel. */
-	rtnl_unlock();
+	spin_unlock(&slcan_lock);
 	tty->receive_room = 65536;	/* We don't flow control */
 
 	/* TTY layer expects 0 on success */
@@ -621,14 +613,10 @@  static int slcan_open(struct tty_struct *tty)
 	sl->tty = NULL;
 	tty->disc_data = NULL;
 	clear_bit(SLF_INUSE, &sl->flags);
-	slc_free_netdev(sl->dev);
-	/* do not call free_netdev before rtnl_unlock */
-	rtnl_unlock();
-	free_netdev(sl->dev);
-	return err;
+	slc_dealloc(sl);
 
 err_exit:
-	rtnl_unlock();
+	spin_unlock(&slcan_lock);
 
 	/* Count references from TTY module */
 	return err;
@@ -658,9 +646,11 @@  static void slcan_close(struct tty_struct *tty)
 	synchronize_rcu();
 	flush_work(&sl->tx_work);
 
-	/* Flush network side */
-	unregister_netdev(sl->dev);
-	/* This will complete via sl_free_netdev */
+	slc_close(sl->dev);
+	unregister_candev(sl->dev);
+	spin_lock(&slcan_lock);
+	slc_dealloc(sl);
+	spin_unlock(&slcan_lock);
 }
 
 static void slcan_hangup(struct tty_struct *tty)
@@ -768,18 +758,29 @@  static void __exit slcan_exit(void)
 		dev = slcan_devs[i];
 		if (!dev)
 			continue;
-		slcan_devs[i] = NULL;
 
-		sl = netdev_priv(dev);
-		if (sl->tty) {
-			netdev_err(dev, "tty discipline still running\n");
-		}
+		spin_lock(&slcan_lock);
+		dev = slcan_devs[i];
+		if (dev) {
+			slcan_devs[i] = NULL;
+			spin_unlock(&slcan_lock);
+			sl = netdev_priv(dev);
+			if (sl->tty) {
+				netdev_err(dev,
+					   "tty discipline still running\n");
+			}
 
-		unregister_netdev(dev);
+			slc_close(dev);
+			unregister_candev(dev);
+		} else {
+			spin_unlock(&slcan_lock);
+		}
 	}
 
+	spin_lock(&slcan_lock);
 	kfree(slcan_devs);
 	slcan_devs = NULL;
+	spin_unlock(&slcan_lock);
 
 	tty_unregister_ldisc(&slc_ldisc);
 }