can: CAN network device driver interface and drivers
Subsystems (5)
v2 cover can: CAN network device driver interface and drivers
Hello,
here comes v2 of the patch series posted some time ago. See
http://marc.info/?l=linux-netdev&m=123507025810612&w=4.
Changes since v1:
- The SysFS interface has been replaced by the Netlink interface as suggested by Patrick. For further information have a look to chapter 6.5 of "Documentation/networking/can.txt" and the header file "include/linux/can/netdev.h". The patch for the "ip" program of the iproute2 utility suite will be provided separately.
- The restart function is now properly protected by "dev->tx_lock" using the "netif_tx_[lock|unlock]" functions.
- For the restart, the device driver must now handle CAN_MODE_STOP as well, apart from CAN_MODE_START to avoid race conditions.
- The "irq_lock" member of "struct can_priv" has been removed. The CAN controller driver may should provide its own synchronization if necessary.
- The restart function is now protected by "dev->tx_lock" using the "netif_tx_lock/unlock" functions.
- Cleanup timer usage for the restart function.
- The unused do_set/get_ctrlmode member of "struct can_priv" have been removed.
- "const" has been added to "struct net_device" for some functions not allowed to touch that structure.
- The library functions "can_set_bittiming" and "can_close_cleanup" have been renamed to the more general names "open_candev" and "close_candev", respectively.
- Use "del_timer_sync" instead of "del_timer" for the re-start timer.
- The macro "ND2D()" has been replaced by "dev->dev.parent" as it does not make the code more readable.
- Fix improper BTR setting for triple-sampling for the SJA1000 as pointed out by Oliver.
- Dont use __u8 but __u32 as before for some members of "struct can_bittiming[_const]" to avoid alignment trouble.
- Definitions shared with user-space applications have been moved to "include/linux/can/netlink.h".
- Various other minor correction suggested on the netdev ML.
- The MSCAN driver for the MPC5200 has been removed. It needs to be presented on the Linuxppc-dev and Devicetree-discuss ML as well, which will be done by a sub-sequent patch.
- Add more source code documentation, especially for the structures and functions related to bit-timing.
The PF_CAN protocol family for the Controller Area Network is available in the kernel since version 2.6.25 but drivers for real CAN devices are still missing. This patch series adds a generic CAN network device driver interface and, as a start, a few drivers. It is the result of the on-going discussion and development of the Socket-CAN project hosted at the BerliOS web-server (http://developer.berlios.de/projects/socketcan).
The patch series consists of the following patches:
1/8) can: Documentation for the CAN device driver interface 2/8) can: Update MAINTAINERS and CREDITS file 3/8) can: CAN Network device driver and Netlink interface 4/8) can: Driver for the SJA1000 CAN controller 5/8) can: SJA1000 generic platform bus driver 6/8) can: SJA1000 driver for EMS PCI cards
7/8) can: SJA1000 driver for Kvaser PCI cards
Please consider these patches for inclusion.
Thanks,
Wolfgang.
PATCH v2 1/8 can: Documentation for the CAN device driver interface
This patch documents the CAN netowrk device drivers interface, removes obsolete documentation and adds some useful links to CAN resources.
--- Documentation/networking/can.txt | 239 ++++++++++++++++++++++++++++++++------- 1 file changed, 199 insertions(+), 40 deletions(-)
Documentation/networking/can.txt +199 -40
@@ -36,10 +36,15 @@ 6.2 local loopback of sent frames 6.3 CAN controller hardware filters 6.4 The virtual CAN driver (vcan) - 6.5 currently supported CAN hardware - 6.6 todo + 6.5 The CAN network device driver interface + 6.5.1 Netlink interface to set/get devices properties + 6.5.2 Setting the CAN bit-timing + 6.5.3 Starting and stopping the CAN network device + 6.6 supported CAN hardware - 7 Credits + 7 Socket CAN resources + + 8 Credits ============================================================================
@@ -234,6 +239,8 @@ the user application using the common CAN filter mechanisms. Inside this filter definition the (interested) type of errors may be selected. The reception of error frames is disabled by default. + The format of the CAN error frame is briefly decribed in the Linux + header file "include/linux/can/error.h". 4. How to use Socket CAN ------------------------
@@ -605,61 +612,213 @@ removal of vcan network devices can be managed with the ip(8) tool: - Create a virtual CAN network interface: - ip link add type vcan + $ ip link add type vcan - Create a virtual CAN network interface with a specific name 'vcan42': - ip link add dev vcan42 type vcan + $ ip link add dev vcan42 type vcan - Remove a (virtual CAN) network interface 'vcan42': - ip link del vcan42 - - The tool 'vcan' from the SocketCAN SVN repository on BerliOS is obsolete. - - Virtual CAN network device creation in older Kernels: - In Linux Kernel versions < 2.6.24 the vcan driver creates 4 vcan - netdevices at module load time by default. This value can be changed - with the module parameter 'numdev'. E.g. 'modprobe vcan numdev=8' - - 6.5 currently supported CAN hardware - - On the project website http://developer.berlios.de/projects/socketcan - there are different drivers available: - - vcan: Virtual CAN interface driver (if no real hardware is available) - sja1000: Philips SJA1000 CAN controller (recommended) - i82527: Intel i82527 CAN controller - mscan: Motorola/Freescale CAN controller (e.g. inside SOC MPC5200) - ccan: CCAN controller core (e.g. inside SOC h7202) - slcan: For a bunch of CAN adaptors that are attached via a - serial line ASCII protocol (for serial / USB adaptors) + $ ip link del vcan42 - Additionally the different CAN adaptors (ISA/PCI/PCMCIA/USB/Parport) - from PEAK Systemtechnik support the CAN netdevice driver model - since Linux driver v6.0: http://www.peak-system.com/linux/index.htm + 6.5 The CAN network device driver interface - Please check the Mailing Lists on the berlios OSS project website. + The CAN network device driver interface provides a generic interface + to setup, configure and monitor CAN network devices. The user can then + configure the CAN device, like setting the bit-timing parameters, via + the netlink interface using the program "ip" from the "IPROUTE2" + utility suite. The following chapter describes briefly how to use it. + Furthermore, the interface uses a common data structure and exports a + set of common functions, which all real CAN network device drivers + should use. Please have a look to the SJA1000 or MSCAN driver to + understand how to use them. The name of the module is can-dev.ko. + + 6.5.1 Netlink interface to set/get devices properties + + The CAN device must be configured via netlink interface. The supported + netlink message types are defined and briefly described in + "include/linux/can/netlink.h". CAN link support for the program "ip" + of the IPROUTE2 utility suite is avaiable and it can be used as shown + below: + + - Setting CAN device properties: + + $ ip link set can0 type can help + Usage: ip link set DEVICE type can + [ bitrate BITRATE [ sample-point SAMPLE-POINT] ] | + [ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1 + phase-seg2 PHASE-SEG2 [ sjw SJW ] ] + + [ loopback { on | off } ] + [ listen-only { on | off } ] + [ triple-sampling { on | off } ] + + [ restart-ms TIME-MS ] + [ restart ] + + Where: BITRATE := { 1..1000000 } + SAMPLE-POINT := { 0.000..0.999 } + TQ := { NUMBER } + PROP-SEG := { 1..8 } + PHASE-SEG1 := { 1..8 } + PHASE-SEG2 := { 1..8 } + SJW := { 1..4 } + RESTART-MS := { 0 | NUMBER } + + - Display CAN device details and statistics: + + $ ip -details -statistics link show can0 + 2: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP qlen 10 + link/can + can <TRIPLE-SAMPLING> state ERROR-ACTIVE restart-ms 100 + bitrate 125000 sample_point 0.875 + tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1 + sja1000: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1 + clock 8000000 + re-started bus-errors arbit-lost error-warn error-pass bus-off + 41 17457 0 41 42 41 + RX: bytes packets errors dropped overrun mcast + 140859 17608 17457 0 0 0 + TX: bytes packets errors dropped carrier collsns + 861 112 0 41 0 0 + + More info to the above output: + + "<TRIPLE-SAMPLING>" + Shows the list of selected CAN controller modes: LOOPBACK, + LISTEN-ONLY, or TRIPLE-SAMPLING. + + "state ERROR-ACTIVE" + The current state of the CAN controller: "ERROR-ACTIVE", + "ERROR-WARNING", "ERROR-PASSIVE", "BUS-OFF" or "STOPPED" + + "restart-ms 100" + Automatic restart delay time. If set to a non-zero value, a + restart of the CAN controller will be triggered automatically + in case of a bus-off condition after the specified delay time + in milliseconds. By default it's off. + + "bitrate 125000 sample_point 0.875" + Shows the real bit-rate in bits/sec and the sample-point in the + range 0.000..0.999. If the calculation of bit-timing parameters + is enabled in the kernel (CONFIG_CAN_CALC_BITTIMING=y), the + bit-timing can be defined by setting the "bitrate" argument. + Optionally the "sample-point" can be specified. By default it's + 0.000 assuming CIA-recommended sample-points. + + "tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1" + Shows the time quanta in ns, propagation segment, phase buffer + segment 1 and 2 and the synchronisation jump width in units of + tq. They allow to define the CAN bit-timing in a hardware + independent format as proposed by the Bosch CAN 2.0 spec (see + chapter 8 of http://www.semiconductors.bosch.de/pdf/can2spec.pdf). + + "sja1000: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1 + clock 8000000" + Shows the bit-timing constants of the CAN controller, here the + "sja1000". The minimum and maximum values of the time segment 1 + and 2, the synchronisation jump width in units of tq, the + bitrate pre-scaler and the CAN system clock frequency in Hz. + These constants could be used for user-defined (non-standard) + bit-timing calculation algorithms in user-space. + + "re-started bus-errors arbit-lost error-warn error-pass bus-off" + Shows the number of restarts, bus and arbitration lost errors, + and the state changes to the error-warning, error-passive and + bus-off state. RX overrun errors are listed in the "overrun" + field of the standard network statistics. + + 6.5.2 Setting the CAN bit-timing + + The CAN bit-timing parameters can always be defined in a hardware + independent format as proposed in the Bosch CAN 2.0 specification + specifying the arguments "tq", "prop_seg", "phase_seg1", "phase_seg2" + and "sjw": + + $ ip link set canX type can tq 125 prop-seg 6 \ + phase-seg1 7 phase-seg2 2 sjw 1 + + If the kernel option CONFIG_CAN_CALC_BITTIMING is enabled, CIA + recommended CAN bit-timing parameters will be calculated if the bit- + rate is specified with the argument "bitrate": + + $ ip link set canX type can bitrate 125000 + + Note that this works fine for the most common CAN controllers with + standard bit-rates but may *fail* for exotic bit-rates or CAN system + clock frequencies. Disabling CONFIG_CAN_CALC_BITTIMING saves some + space and allows user-space tools to solely determine and set the + bit-timing parameters. The CAN controller specific bit-timing + constants can be used for that purpose. They are listed by the + following command: + + $ ip -details link show can0 + ... + sja1000: clock 8000000 tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1 + + 6.5.3 Starting and stopping the CAN network device + + A CAN network device is started or stopped as usual with the command + "ifconfig canX up/down" or "ip link set canX up/down". Be aware that + you *must* define proper bit-timing parameters for real CAN devices + before you can start it to avoid error-prone default settings: + + $ ip link set canX up type can bitrate 125000 + + A device may enter the "bus-off" state if too much errors occurred on + the CAN bus. Then no more messages are received or sent. An automatic + bus-off recovery can be enabled by setting the "restart-ms" to a + non-zero value, e.g.: + + $ ip link set canX type can restart-ms 100 + + Alternatively, the application may realize the "bus-off" condition + by monitoring CAN error frames and do a restart when appropriate with + the command: + + $ ip link set canX type can restart + + Note that a restart will also create a CAN error frame (see also + chapter 3.4). + + 6.6 Supported CAN hardware + + Please check the "Kconfig" file in "drivers/net/can" to get an actual + list of the support CAN hardware. On the Socket CAN project website + (see chapter 7) there might be further drivers available, also for + older kernel versions. + +7. Socket CAN resources +----------------------- + + You can find further resources for Socket CAN like user space tools, + support for old kernel versions, more drivers, mailing lists, etc. + at the BerliOS OSS project website for Socket CAN: - 6.6 todo + http://developer.berlios.de/projects/socketcan - The configuration interface for CAN network drivers is still an open - issue that has not been finalized in the socketcan project. Also the - idea of having a library module (candev.ko) that holds functions - that are needed by all CAN netdevices is not ready to ship. - Your contribution is welcome. + If you have questions, bug fixes, etc., don't hesitate to post them to + the Socketcan-Users mailing list. But please search the archives first. -7. Credits +8. Credits ---------- - Oliver Hartkopp (PF_CAN core, filters, drivers, bcm) + Oliver Hartkopp (PF_CAN core, filters, drivers, bcm, SJA1000 driver) Urs Thuermann (PF_CAN core, kernel integration, socket interfaces, raw, vcan) Jan Kizka (RT-SocketCAN core, Socket-API reconciliation) - Wolfgang Grandegger (RT-SocketCAN core & drivers, Raw Socket-API reviews) + Wolfgang Grandegger (RT-SocketCAN core & drivers, Raw Socket-API reviews, + CAN device driver interface, MSCAN driver) Robert Schwebel (design reviews, PTXdist integration) Marc Kleine-Budde (design reviews, Kernel 2.6 cleanups, drivers) Benedikt Spranger (reviews) Thomas Gleixner (LKML reviews, coding style, posting hints) - Andrey Volkov (kernel subtree structure, ioctls, mscan driver) + Andrey Volkov (kernel subtree structure, ioctls, MSCAN driver) Matthias Brukner (first SJA1000 CAN netdevice implementation Q2/2003) Klaus Hitschler (PEAK driver integration) Uwe Koppe (CAN netdevices with PF_PACKET approach) Michael Schulze (driver layer loopback requirement, RT CAN drivers review) + Pavel Pisa (Bit-timing calculation) + Sascha Hauer (SJA1000 platform driver) + Sebastian Haas (SJA1000 EMS PCI driver) + Markus Plessing (SJA1000 EMS PCI driver) + Per Dalen (SJA1000 Kvaser PCI driver) + Sam Ravnborg (reviews, coding style, kbuild help)
PATCH v2 2/8 can: Update MAINTAINERS and CREDITS file
In reply to Wolfgang Grandegger--- CREDITS | 4 ++++ MAINTAINERS | 7 +++++++ 2 files changed, 11 insertions(+)
CREDITS +4 -0
@@ -1253,6 +1253,10 @@ S: Sterling Heights, Michigan 48313 S: USA +N: Wolfgang Grandegger +E: [email protected] +D: Controller Area Network (device drivers) + N: William Greathouse E: [email protected] E: [email protected]
MAINTAINERS +7 -0
@@ -1278,6 +1278,13 @@ F: include/linux/can/ F: include/linux/can.h +CAN NETWORK DRIVERS +P: Wolfgang Grandegger +M: [email protected] +L: [email protected] (subscribers-only) +W: http://developer.berlios.de/projects/socketcan/ +S: Maintained + CELL BROADBAND ENGINE ARCHITECTURE P: Arnd Bergmann M: [email protected]
PATCH v2 3/8 can: CAN Network device driver and Netlink interface
In reply to Wolfgang GrandeggerThe CAN network device driver interface provides a generic interface to setup, configure and monitor CAN network devices. It exports a set of common data structures and functions, which all real CAN network device drivers should use. Please have a look to the SJA1000 or MSCAN driver to understand how to use them. The name of the module is can-dev.ko.
Furthermore, it adds a Netlink interface allowing to configure the CAN device using the program "ip" from the iproute2 utility suite.
For further information please check "Documentation/networking/can.txt"
--- drivers/net/can/Kconfig | 23 + drivers/net/can/Makefile | 5 drivers/net/can/dev.c | 659 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/can/Kbuild | 1 include/linux/can/dev.h | 70 ++++ include/linux/can/netlink.h | 113 +++++++ 6 files changed, 871 insertions(+) create mode 100644 drivers/net/can/dev.c create mode 100644 drivers/net/can/sysfs.c create mode 100644 drivers/net/can/sysfs.h create mode 100644 include/linux/can/dev.h
drivers/net/can/Kconfig +23 -0
@@ -12,6 +12,29 @@ This driver can also be built as a module. If so, the module will be called vcan. +config CAN_DEV + tristate "Platform CAN drivers with Netlink support" + depends on CAN + default Y + ---help--- + Enables the common framework for platform CAN drivers with Netlink + support. This is the standard library for CAN drivers. + If unsure, say Y. + +config CAN_CALC_BITTIMING + bool "CAN bit-timing calculation" + depends on CAN_DEV + default Y + ---help--- + If enabled, CAN bit-timing parameters will be calculated for the + bit-rate specified via Netlink argument "bitrate" when the device + get started. This works fine for the most common CAN controllers + with standard bit-rates but may fail for exotic bit-rates or CAN + source clock frequencies. Disabling saves some space, but then the + bit-timing parameters must be specified directly using the Netlink + arguments "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw". + If unsure, say Y. + config CAN_DEBUG_DEVICES bool "CAN devices debugging messages" depends on CAN
drivers/net/can/Makefile +5 -0
@@ -3,3 +3,8 @@ # obj-$(CONFIG_CAN_VCAN) += vcan.o + +obj-$(CONFIG_CAN_DEV) += can-dev.o +can-dev-y := dev.o + +ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
drivers/net/can/dev.c new file +659 -0
659 lines not on this page · raw message
include/linux/can/dev.h new file +70 -0
70 lines not on this page · raw message
include/linux/can/netlink.h new file +113 -0
113 lines not on this page · raw message
include/linux/can/Kbuild +1 -0
@@ -1,3 +1,4 @@ header-y += raw.h header-y += bcm.h header-y += error.h +header-y += netlink.h
Re: [PATCH v2 3/7] [PATCH 3/8] can: CAN Network device driver and Netlink interface
Quoted 12 lines · On Tue, 12 May 2009 11:28:00 +0200 Wolfgang Grandegger <[email protected]>…
drivers/net/can/dev.c new file +12
-0+int can_restart_now (struct net_device *dev) +{ +struct can_priv *priv =netdev_priv (dev); +struct net_device_stats *stats = &dev->stats; +struct sk_buff *skb; +struct can_frame *cf; +int err; + +/* Synchronize with dev->hard_start_xmit() */ +netif_tx_lock (dev); + +/* Ensure that no more messages can go out */
drivers/net/can/dev.c line 349
Quoted 10 lines
drivers/net/can/dev.c new file +10
-0+if (netif_carrier_ok (dev)) +netif_carrier_off (dev); + +/* Ensure that no more messages can come in */ + err = priv->do_set_mode (dev,CAN_MODE_STOP ); +if (err) +return err; + +/* Now it's save to clean up */ +del_timer_sync (&priv->restart_timer);
This is deadlockable.
It calls del_timer_sync() while holding netif_tx_lock(). But the timer handler (can_restart_now()) also takes netif_tx_lock(). So if the timer handler is presently running, it's sitting there spinning in netif_tx_lock(). And del_timer_sync() is sitting there waiting for the timer handler to complete.
Re: [PATCH v2 3/7] [PATCH 3/8] can: CAN Network device driver and Netlink interface
Quoted 27 lines · On Tue, 12 May 2009 23:30:52 -0700 Andrew Morton <[email protected]>…
Quoted 12 lines · On Tue, 12 May 2009 11:28:00 +0200 Wolfgang Grandegger <[email protected]>…
drivers/net/can/dev.c new file +12
-0+int can_restart_now (struct net_device *dev) +{ +struct can_priv *priv =netdev_priv (dev); +struct net_device_stats *stats = &dev->stats; +struct sk_buff *skb; +struct can_frame *cf; +int err; + +/* Synchronize with dev->hard_start_xmit() */ +netif_tx_lock (dev); + +/* Ensure that no more messages can go out */ drivers/net/can/dev.c line 349
Quoted 10 lines
drivers/net/can/dev.c new file +10
-0+if (netif_carrier_ok (dev)) +netif_carrier_off (dev); + +/* Ensure that no more messages can come in */ + err = priv->do_set_mode (dev,CAN_MODE_STOP ); +if (err) +return err; + +/* Now it's save to clean up */ +del_timer_sync (&priv->restart_timer);This is deadlockable.
Quoted 5 lines
It calls
del_timer_sync()while holdingnetif_tx_lock(). But the timer handler (can_restart_now()) also takesnetif_tx_lock(). So if the timer handler is presently running, it's sitting there spinning innetif_tx_lock(). Anddel_timer_sync()is sitting there waiting for the timer handler to complete.
Also, I wonder if it's safe to take netif_tx_lock() from a timer handler when other parts of the code might be taking it from process context (I didn't check).
lockdep should be able to detect this, and I trust this code has been fully runtime tested with lockdep enabled?
<boggles at the size of the inlined netif_tx_lock()>
Re: [PATCH v2 3/7] [PATCH 3/8] can: CAN Network device driver and Netlink interface
Quoted 28 lines · Andrew Morton
Quoted 26 lines · On Tue, 12 May 2009 23:30:52 -0700 Andrew Morton <[email protected]>…
Quoted 12 lines · On Tue, 12 May 2009 11:28:00 +0200 Wolfgang Grandegger <[email protected]>…
drivers/net/can/dev.c new file +12
-0+int can_restart_now (struct net_device *dev) +{ +struct can_priv *priv =netdev_priv (dev); +struct net_device_stats *stats = &dev->stats; +struct sk_buff *skb; +struct can_frame *cf; +int err; + +/* Synchronize with dev->hard_start_xmit() */ +netif_tx_lock (dev); + +/* Ensure that no more messages can go out */ drivers/net/can/dev.c line 349
Quoted 10 lines
drivers/net/can/dev.c new file +10
-0+if (netif_carrier_ok (dev)) +netif_carrier_off (dev); + +/* Ensure that no more messages can come in */ + err = priv->do_set_mode (dev,CAN_MODE_STOP ); +if (err) +return err; + +/* Now it's save to clean up */ +del_timer_sync (&priv->restart_timer);This is deadlockable.
Quoted 5 lines
Quoted 5 lines
It calls
del_timer_sync()while holdingnetif_tx_lock(). But the timer handler (can_restart_now()) also takesnetif_tx_lock(). So if the timer handler is presently running, it's sitting there spinning innetif_tx_lock(). Anddel_timer_sync()is sitting there waiting for the timer handler to complete.
Oops, I have obviously overlook that.
Quoted 6 lines
Also, I wonder if it's safe to take
netif_tx_lock()from a timer handler when other parts of the code might be taking it from process context (I didn't check).lockdep should be able to detect this, and I trust this code has been fully runtime tested with lockdep enabled?
Well, CONFIG_PROVE_LOCKING would be cool, but I'm unable to enabled it for my MPC5200 test system. Only 64bit PowerPC's seem to support TRACE_IRQFLAGS_SUPPORT. I'm going to test the code on a PC as well.
Thanks,
Wolfgang.
Re: [PATCH v2 3/7] [PATCH 3/8] can: CAN Network device driver and Netlink interface
Quoted 10 lines · On Wed, 13 May 2009 13:37:16 +0200 Wolfgang Grandegger <[email protected]>…
Quoted 6 lines
Also, I wonder if it's safe to take
netif_tx_lock()from a timer handler when other parts of the code might be taking it from process context (I didn't check).lockdep should be able to detect this, and I trust this code has been fully runtime tested with lockdep enabled?
Well,
CONFIG_PROVE_LOCKINGwould be cool, but I'm unable to enabled it for my MPC5200 test system. Only 64bit PowerPC's seem to supportTRACE_IRQFLAGS_SUPPORT. I'm going to test the code on a PC as well.
I discussed this off-list with Peter Zijlstra and Johannes Berg. Apparently lockdep _will_ detect this deadlockable situation - Johannes recently added the capability because he had the same situation in wireless code somewhere.
But of course it does require that the timer handler has executed at least once. Many handlers in the kernel never fire in normal operation.
Re: [PATCH v2 3/7] [PATCH 3/8] can: CAN Network device driver and Netlink interface
Quoted 8 lines · Andrew Morton
Quoted 6 lines · On Wed, 13 May 2009 13:37:16 +0200 Wolfgang Grandegger <[email protected]>…
Quoted 6 lines
Also, I wonder if it's safe to take
netif_tx_lock()from a timer handler when other parts of the code might be taking it from process context (I didn't check).lockdep should be able to detect this, and I trust this code has been fully runtime tested with lockdep enabled?
Quoted 8 lines
Quoted 3 lines
Well,
CONFIG_PROVE_LOCKINGwould be cool, but I'm unable to enabled it for my MPC5200 test system. Only 64bit PowerPC's seem to supportTRACE_IRQFLAGS_SUPPORT. I'm going to test the code on a PC as well.I discussed this off-list with Peter Zijlstra and Johannes Berg. Apparently lockdep _will_ detect this deadlockable situation - Johannes recently added the capability because he had the same situation in wireless code somewhere.
Below is the kernel message I get with CONFIG_PROVE_LOCKING enabled when I call can_restart_now() from the user context via netlink interface. I have some difficulties interpreting the message, but it seems to confirm your fears.
Quoted 2 lines
But of course it does require that the timer handler has executed at least once. Many handlers in the kernel never fire in normal operation.
I do not see problems if can_restart_now() is called via timer callback (after replacing del_timer_sync with del_timer).
Wolfgang.
peak_pci 0000:01:08.0: setting BTR0=0x00 BTR1=0x14
can: controller area network core (rev 20090105 abi 8)
NET: Registered protocol family 29
can: request_module (can-proto-1) failed.
can: raw protocol (rev 20090105)peak_pci 0000:01:08.0: error warning interrupt peak_pci 0000:01:08.0: error passive interrupt peak_pci 0000:01:08.0: error warning interrupt peak_pci 0000:01:08.0: bus-off
=================================
[ INFO: inconsistent lock state ]
2.6.29.3 #1
---------------------------------
inconsistent {in-softirq-W} -> {softirq-on-W} usage.
ip/2847 [HC0[0]:SC0[0]:HE1:SE1] takes:
(&dev->tx_global_lock){-+..}, at: [<f7e29806>] can_restart_now+0x26/0x1c1 [can_dev]
{in-softirq-W} state was registered at:
[<c044957d>] __lock_acquire+0x244/0xb01 [<c0449e95>] lock_acquire+0x5b/0x81 [<c067c29b>] _spin_lock+0x1b/0x2a [<c06031fd>] netif_tx_lock+0x18/0x6a [<c06032a2>] dev_watchdog+0xf/0x10d [<c04331bc>] run_timer_softirq+0x13b/0x19b [<c043000e>] __do_softirq+0x98/0x136 [<ffffffff>] 0xffffffff irq event stamp: 1973 hardirqs last enabled at (1973): [<c067b100>] __mutex_lock_common+0x2be/0x313 hardirqs last disabled at (1972): [<c067aeb4>] __mutex_lock_common+0x72/0x313 softirqs last enabled at (1790): [<c05fe73b>] sk_filter+0x9a/0xa7 softirqs last disabled at (1788): [<c05fe6bf>] sk_filter+0x1e/0xa7
other info that might help us debug this:
1 lock held by ip/2847:
#0: (rtnl_mutex){--..}, at: [<c05fcef7>] rtnetlink_rcv+0x12/0x26
stack backtrace: Pid: 2847, comm: ip Not tainted 2.6.29.3 #1 Call Trace: [<c0679d30>] ? printk+0xf/0x17 [<c044860c>] valid_state+0x12a/0x13d [<c04489dc>] mark_lock+0x248/0x349 [<c04495fe>] __lock_acquire+0x2c5/0xb01 [<c04858e4>] ? handle_mm_fault+0x6a4/0x6b7 [<c0449e95>] lock_acquire+0x5b/0x81 [<f7e29806>] ? can_restart_now+0x26/0x1c1 [can_dev] [<c067c29b>] _spin_lock+0x1b/0x2a [<f7e29806>] ? can_restart_now+0x26/0x1c1 [can_dev] [<f7e29806>] can_restart_now+0x26/0x1c1 [can_dev] [<f7e29ab8>] can_changelink+0x117/0x12f [can_dev] [<c060a7aa>] ? nla_parse+0x57/0xb2 [<f7e299a1>] ? can_changelink+0x0/0x12f [can_dev] [<c05fd306>] rtnl_newlink+0x249/0x3df [<c05fd1fe>] ? rtnl_newlink+0x141/0x3df [<c05fd0bd>] ? rtnl_newlink+0x0/0x3df [<c05fd0a3>] rtnetlink_rcv_msg+0x198/0x1b2 [<c05fcf0b>] ? rtnetlink_rcv_msg+0x0/0x1b2 [<c060a2a0>] netlink_rcv_skb+0x30/0x78 [<c05fcf03>] rtnetlink_rcv+0x1e/0x26 [<c0609e8a>] netlink_unicast+0xf6/0x156 [<c060a130>] netlink_sendmsg+0x246/0x253 [<c05e8b28>] __sock_sendmsg+0x45/0x4e [<c05e9303>] sock_sendmsg+0xb8/0xce [<c043c15f>] ? autoremove_wake_function+0x0/0x33 [<c048348d>] ? might_fault+0x43/0x80 [<c048348d>] ? might_fault+0x43/0x80 [<c051aa39>] ? copy_from_user+0x2a/0x111 [<c05eff69>] ? verify_iovec+0x40/0x6f [<c05e9458>] sys_sendmsg+0x13f/0x192 [<c067e281>] ? do_page_fault+0x380/0x690 [<c0447a3f>] ? register_lock_class+0x17/0x290 [<c04487b2>] ? mark_lock+0x1e/0x349 [<c04487b2>] ? mark_lock+0x1e/0x349 [<c048348d>] ? might_fault+0x43/0x80 [<c05ea3f4>] sys_socketcall+0x153/0x183 [<c04038eb>] sysenter_do_call+0x12/0x3f
Re: [PATCH v2 3/7] [PATCH 3/8] can: CAN Network device driver and Netlink interface
In reply to Andrew MortonQuoted 29 lines · Andrew Morton
Quoted 13 lines · On Tue, 12 May 2009 11:28:00 +0200 Wolfgang Grandegger <[email protected]>…
drivers/net/can/dev.c new file +12
-0+int can_restart_now (struct net_device *dev) +{ +struct can_priv *priv =netdev_priv (dev); +struct net_device_stats *stats = &dev->stats; +struct sk_buff *skb; +struct can_frame *cf; +int err; + +/* Synchronize with dev->hard_start_xmit() */ +netif_tx_lock (dev); + +/* Ensure that no more messages can go out */ drivers/net/can/dev.c line 349
Quoted 10 lines
drivers/net/can/dev.c new file +10
-0+if (netif_carrier_ok (dev)) +netif_carrier_off (dev); + +/* Ensure that no more messages can come in */ + err = priv->do_set_mode (dev,CAN_MODE_STOP ); +if (err) +return err; + +/* Now it's save to clean up */ +del_timer_sync (&priv->restart_timer);This is deadlockable.
Quoted 8 lines
It calls
del_timer_sync()while holdingnetif_tx_lock(). But the timer handler (can_restart_now()) also takesnetif_tx_lock(). So if the timer handler is presently running, it's sitting there spinning innetif_tx_lock(). Anddel_timer_sync()is sitting there waiting for the timer handler to complete.
Hi Wolfgang,
would it be an appropriate solution, just to invoke
netif_stop_queue() in can_bus_off()
and invoke
netif_wake_queue() in can_restart_now()
???
In a BUSOFF condition we're not able to send CAN frames anyway, so we can disable the device queue and the we won't need any netif_tx_lock() right?
AFAIK this was the original implementation before some of the latest improvement with the netif_carrier stuff.
What do you think?
Best regards,
Oliver
Re: [PATCH v2 3/7] [PATCH 3/8] can: CAN Network device driver and Netlink interface
Quoted 52 lines · Oliver Hartkopp
Quoted 30 lines · Andrew Morton
Quoted 13 lines · On Tue, 12 May 2009 11:28:00 +0200 Wolfgang Grandegger <[email protected]>…
drivers/net/can/dev.c new file +12
-0+int can_restart_now (struct net_device *dev) +{ +struct can_priv *priv =netdev_priv (dev); +struct net_device_stats *stats = &dev->stats; +struct sk_buff *skb; +struct can_frame *cf; +int err; + +/* Synchronize with dev->hard_start_xmit() */ +netif_tx_lock (dev); + +/* Ensure that no more messages can go out */ drivers/net/can/dev.c line 349
Quoted 10 lines
drivers/net/can/dev.c new file +10
-0+if (netif_carrier_ok (dev)) +netif_carrier_off (dev); + +/* Ensure that no more messages can come in */ + err = priv->do_set_mode (dev,CAN_MODE_STOP ); +if (err) +return err; + +/* Now it's save to clean up */ +del_timer_sync (&priv->restart_timer);This is deadlockable.
Quoted 8 lines
It calls
del_timer_sync()while holdingnetif_tx_lock(). But the timer handler (can_restart_now()) also takesnetif_tx_lock(). So if the timer handler is presently running, it's sitting there spinning innetif_tx_lock(). Anddel_timer_sync()is sitting there waiting for the timer handler to complete.Hi Wolfgang,
would it be an appropriate solution, just to invoke
netif_stop_queue()incan_bus_off()and invoke
netif_wake_queue()incan_restart_now()???
Quoted 8 lines
In a BUSOFF condition we're not able to send CAN frames anyway, so we can disable the device queue and the we won't need any
netif_tx_lock()right?AFAIK this was the original implementation before some of the latest improvement with the
netif_carrierstuff.What do you think?
The problem is the "manual" restart triggered via the netlink interface, which can occur in the middle of ndo_start_xmit().
Wolfgang.
Re: [PATCH v2 3/7] [PATCH 3/8] can: CAN Network device driver and Netlink interface
Quoted 60 lines · Wolfgang Grandegger
Quoted 58 lines · Oliver Hartkopp
Quoted 31 lines · Andrew Morton
Quoted 14 lines · On Tue, 12 May 2009 11:28:00 +0200 Wolfgang Grandegger <[email protected]>…
drivers/net/can/dev.c new file +12
-0+int can_restart_now (struct net_device *dev) +{ +struct can_priv *priv =netdev_priv (dev); +struct net_device_stats *stats = &dev->stats; +struct sk_buff *skb; +struct can_frame *cf; +int err; + +/* Synchronize with dev->hard_start_xmit() */ +netif_tx_lock (dev); + +/* Ensure that no more messages can go out */ drivers/net/can/dev.c line 349
Quoted 10 lines
drivers/net/can/dev.c new file +10
-0+if (netif_carrier_ok (dev)) +netif_carrier_off (dev); + +/* Ensure that no more messages can come in */ + err = priv->do_set_mode (dev,CAN_MODE_STOP ); +if (err) +return err; + +/* Now it's save to clean up */ +del_timer_sync (&priv->restart_timer);This is deadlockable.
Quoted 9 lines
It calls
del_timer_sync()while holdingnetif_tx_lock(). But the timer handler (can_restart_now()) also takesnetif_tx_lock(). So if the timer handler is presently running, it's sitting there spinning innetif_tx_lock(). Anddel_timer_sync()is sitting there waiting for the timer handler to complete.Hi Wolfgang,
would it be an appropriate solution, just to invoke
netif_stop_queue()incan_bus_off()and invoke
netif_wake_queue()incan_restart_now()???
In a BUSOFF condition we're not able to send CAN frames anyway, so we can disable the device queue and the we won't need any
netif_tx_lock()right?
Quoted 10 lines
Quoted 5 lines
AFAIK this was the original implementation before some of the latest improvement with the
netif_carrierstuff.What do you think?
The problem is the "manual" restart triggered via the netlink interface, which can occur in the middle of
ndo_start_xmit().
Ah, i see.
What if the manual restart via netlink would also stop the queue and start the timer?
Regards,
Oliver
Re: [PATCH v2 3/7] [PATCH 3/8] can: CAN Network device driver and Netlink interface
Quoted 70 lines · Oliver Hartkopp
Quoted 58 lines · Wolfgang Grandegger
Quoted 56 lines · Oliver Hartkopp
Quoted 30 lines · Andrew Morton
Quoted 13 lines · On Tue, 12 May 2009 11:28:00 +0200 Wolfgang Grandegger <[email protected]>…
drivers/net/can/dev.c new file +12
-0+int can_restart_now (struct net_device *dev) +{ +struct can_priv *priv =netdev_priv (dev); +struct net_device_stats *stats = &dev->stats; +struct sk_buff *skb; +struct can_frame *cf; +int err; + +/* Synchronize with dev->hard_start_xmit() */ +netif_tx_lock (dev); + +/* Ensure that no more messages can go out */ drivers/net/can/dev.c line 349
Quoted 10 lines
drivers/net/can/dev.c new file +10
-0+if (netif_carrier_ok (dev)) +netif_carrier_off (dev); + +/* Ensure that no more messages can come in */ + err = priv->do_set_mode (dev,CAN_MODE_STOP ); +if (err) +return err; + +/* Now it's save to clean up */ +del_timer_sync (&priv->restart_timer);This is deadlockable.
Quoted 8 lines
It calls
del_timer_sync()while holdingnetif_tx_lock(). But the timer handler (can_restart_now()) also takesnetif_tx_lock(). So if the timer handler is presently running, it's sitting there spinning innetif_tx_lock(). Anddel_timer_sync()is sitting there waiting for the timer handler to complete.Hi Wolfgang,
would it be an appropriate solution, just to invoke
netif_stop_queue()incan_bus_off()and invoke
netif_wake_queue()incan_restart_now()???
In a BUSOFF condition we're not able to send CAN frames anyway, so we can disable the device queue and the we won't need any
netif_tx_lock()right?Quoted 10 lines
Quoted 5 lines
AFAIK this was the original implementation before some of the latest improvement with the
netif_carrierstuff.What do you think?
The problem is the "manual" restart triggered via the netlink interface, which can occur in the middle of
ndo_start_xmit().
Quoted 4 lines
Ah, i see.
What if the manual restart via netlink would also stop the queue and start the timer?
It will not help if the restart is triggered in the middle of ndo_start_xmit().
Wolfgang.
Re: [PATCH v2 3/7] [PATCH 3/8] can: CAN Network device driver and Netlink interface
Quoted 78 lines · Wolfgang Grandegger
Quoted 76 lines · Oliver Hartkopp
Quoted 74 lines · Wolfgang Grandegger
Quoted 56 lines · Oliver Hartkopp
Quoted 32 lines · Andrew Morton
Quoted 14 lines · On Tue, 12 May 2009 11:28:00 +0200 Wolfgang Grandegger <[email protected]>…
drivers/net/can/dev.c new file +12
-0+int can_restart_now (struct net_device *dev) +{ +struct can_priv *priv =netdev_priv (dev); +struct net_device_stats *stats = &dev->stats; +struct sk_buff *skb; +struct can_frame *cf; +int err; + +/* Synchronize with dev->hard_start_xmit() */ +netif_tx_lock (dev); + +/* Ensure that no more messages can go out */ drivers/net/can/dev.c line 349
Quoted 10 lines
drivers/net/can/dev.c new file +10
-0+if (netif_carrier_ok (dev)) +netif_carrier_off (dev); + +/* Ensure that no more messages can come in */ + err = priv->do_set_mode (dev,CAN_MODE_STOP ); +if (err) +return err; + +/* Now it's save to clean up */ +del_timer_sync (&priv->restart_timer);This is deadlockable.
Quoted 9 lines
It calls
del_timer_sync()while holdingnetif_tx_lock(). But the timer handler (can_restart_now()) also takesnetif_tx_lock(). So if the timer handler is presently running, it's sitting there spinning innetif_tx_lock(). Anddel_timer_sync()is sitting there waiting for the timer handler to complete.Hi Wolfgang,
would it be an appropriate solution, just to invoke
netif_stop_queue()incan_bus_off()and invoke
netif_wake_queue()incan_restart_now()???
Quoted 10 lines
In a BUSOFF condition we're not able to send CAN frames anyway, so we can disable the device queue and the we won't need any
netif_tx_lock()right?AFAIK this was the original implementation before some of the latest improvement with the
netif_carrierstuff.What do you think?
The problem is the "manual" restart triggered via the netlink interface, which can occur in the middle of
ndo_start_xmit().
Quoted 10 lines
Quoted 5 lines
Ah, i see.
What if the manual restart via netlink would also stop the queue and start the timer?
It will not help if the restart is triggered in the middle of
ndo_start_xmit().
Hi Wolfgang,
i think, i found a solution that removes the locking problem completely:
When a bus-off occurs in the controller, the communication on the CAN bus can be treated as unusable for this controller (let's say it is dead). E.g. the SJA1000 set's its reset bit for that reason and waits to be initialized by the CPU again.
So IMO restarting the CAN controller while in operational state is not a valid use case.
When a bus-off (interrupt) occurs, we should
- invoke netif_carrier_off(dev)
- invoke netif_stop_queue(dev)
- set the state to CAN_STATE_BUS_OFF
and of course create the error message, clear the interrupts(!) and then leave the irq service function.
That's it.
When the automatic CAN controller restart is enabled: start the timer.
For the manual netlink function: Test for CAN_STATE_BUS_OFF (!) and invoke the current can_restart_now(dev) or start the timer with e.g. 1ms ...
This approach should make it and fulfills the bus-off intention of the CAN controllers ("disabled and wait for re-initialisation").
And there's no locking of the tx_queue needed anymore as the tx_queue is already stopped, when the restart is performed.
What do you think about this approach?
Regards,
Oliver
Re: [PATCH v2 3/7] [PATCH 3/8] can: CAN Network device driver and Netlink interface
Quoted 102 lines · Oliver Hartkopp
Quoted 76 lines · Wolfgang Grandegger
Quoted 74 lines · Oliver Hartkopp
Quoted 72 lines · Wolfgang Grandegger
Quoted 59 lines · Oliver Hartkopp
Quoted 30 lines · Andrew Morton
Quoted 13 lines · On Tue, 12 May 2009 11:28:00 +0200 Wolfgang Grandegger <[email protected]>…
(quoted diff) +12
-0+int can_restart_now(struct net_device *dev) +{ + struct can_priv *priv = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + struct sk_buff *skb; + struct can_frame *cf; + int err; + + /* Synchronize with dev->hard_start_xmit() */ + netif_tx_lock(dev); + + /* Ensure that no more messages can go out */Review
Quoted 10 lines
(quoted diff) +10
-0+ if (netif_carrier_ok(dev)) + netif_carrier_off(dev); + + /* Ensure that no more messages can come in */ + err = priv->do_set_mode(dev, CAN_MODE_STOP); + if (err) + return err; + + /* Now it's save to clean up */ + del_timer_sync(&priv->restart_timer);This is deadlockable.
Quoted 10 lines
It calls
del_timer_sync()while holdingnetif_tx_lock(). But the timer
handler (can_restart_now()) also takesnetif_tx_lock(). So if the timer handler is presently running, it's sitting there spinning innetif_tx_lock(). Anddel_timer_sync()is sitting there waiting for the
timer handler to complete.Hi Wolfgang,
would it be an appropriate solution, just to invoke
netif_stop_queue()incan_bus_off()and invoke
netif_wake_queue()incan_restart_now()???
In a BUSOFF condition we're not able to send CAN frames anyway, so we can disable the device queue and the we won't need any
netif_tx_lock()
right?Quoted 5 lines
AFAIK this was the original implementation before some of the latest improvement with the
netif_carrierstuff.What do you think?
The problem is the "manual" restart triggered via the netlink interface,
which can occur in the middle ofndo_start_xmit().Quoted 10 lines
Quoted 5 lines
Ah, i see.
What if the manual restart via netlink would also stop the queue and start the timer?
It will not help if the restart is triggered in the middle of
ndo_start_xmit().Hi Wolfgang,
i think, i found a solution that removes the locking problem completely:
When a bus-off occurs in the controller, the communication on the CAN bus can be treated as unusable for this controller (let's say it is dead). E.g. the SJA1000 set's its reset bit for that reason and waits to be initialized by the CPU again.
So IMO restarting the CAN controller while in operational state is not a valid use case.
When a bus-off (interrupt) occurs, we should
Quoted 8 lines
- invoke
netif_carrier_off(dev)
- invokenetif_stop_queue(dev)
- set the state toCAN_STATE_BUS_OFFand of course create the error message, clear the interrupts(!) and then leave the irq service function.
That's it.
It's already like that.
Quoted 6 lines
When the automatic CAN controller restart is enabled: start the timer.
For the manual netlink function: Test for
CAN_STATE_BUS_OFF(!) and invoke the currentcan_restart_now(dev)or start the timer with e.g. 1ms
...
Quoted 7 lines
This approach should make it and fulfills the bus-off intention of the CAN controllers ("disabled and wait for re-initialisation").
And there's no locking of the
tx_queueneeded anymore as thetx_queueis already stopped, when the restart is performed.What do you think about this approach?
That's a solution and would comply with the can spec, I believe, but it should be discussed on the Socket-CAN mailing list. We should not change policy just to avoid locking or simplify the code.
Wolfgang.
Jonathan Corbet
maintainerRe: [PATCH v2 3/7] [PATCH 3/8] can: CAN Network device driver and Netlink interface
In reply to Wolfgang Grandegger[Quick review ...]
Quoted 12 lines
drivers/net/can/dev.c new file +12
-0+/* +* CAN device restart for bus-off recovery +*/ +int can_restart_now (struct net_device *dev) +{ +struct can_priv *priv =netdev_priv (dev); +struct net_device_stats *stats = &dev->stats; +struct sk_buff *skb; +struct can_frame *cf; +int err; + +/* Synchronize with dev->hard_start_xmit() */
drivers/net/can/dev.c line 346
Quoted 10 lines
drivers/net/can/dev.c new file +10
-0+netif_tx_lock (dev); + +/* Ensure that no more messages can go out */ +if (netif_carrier_ok (dev)) +netif_carrier_off (dev); + +/* Ensure that no more messages can come in */ + err = priv->do_set_mode (dev,CAN_MODE_STOP ); +if (err) +return err;
This leaves _xmit_lock held and carrier off. Is that really what you want to do?
drivers/net/can/dev.c line 358
Quoted 12 lines
drivers/net/can/dev.c new file +12
-0+ +/* Now it's save to clean up */ +del_timer_sync (&priv->restart_timer); +can_flush_echo_skb (dev); + +dev_dbg (dev->dev.parent,"restarted\n" ); + priv->can_stats.restarts++; + +/* send restart message upstream */ + skb =dev_alloc_skb (sizeof (struct can_frame )); +if (skb ==NULL ) +return -ENOMEM ;
...here too...
Quoted 7 lines
drivers/net/can/dev.c new file +7
-0+ skb->dev = dev; + skb->protocol =htons (ETH_P_CAN ); + cf = (struct can_frame *)skb_put (skb,sizeof (struct can_frame )); +memset (cf,0 ,sizeof (struct can_frame )); + cf->can_id =CAN_ERR_FLAG |CAN_ERR_RESTARTED ; + cf->can_dlc =CAN_ERR_DLC ; +
drivers/net/can/dev.c line 375
Quoted 10 lines
drivers/net/can/dev.c new file +10
-0+netif_rx (skb); + + dev->last_rx = jiffies; + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc; + +/* Now restart the device */ + err = priv->do_set_mode (dev,CAN_MODE_START ); +if (err) +return err;
...and here too. Do you maybe want to get rid of the middle-of-function returns and switch to the "goto out" convention?
drivers/net/can/dev.c line 389
Quoted 13 lines
drivers/net/can/dev.c new file +13
-0+netif_carrier_on (dev); + +netif_tx_unlock (dev); + +return 0 ; +} + +static void can_restart_after (unsigned long data) +{ +struct net_device *dev = (struct net_device *)data; + +can_restart_now (dev); +}
can_restart_after what? I find myself confused by this function and wondering why it exists.
jon
Re: [PATCH v2 3/7] [PATCH 3/8] can: CAN Network device driver and Netlink interface
Quoted 55 lines · Jonathan Corbet
[Quick review ...]
Quoted 12 lines
drivers/net/can/dev.c new file +12
-0+/* +* CAN device restart for bus-off recovery +*/ +int can_restart_now (struct net_device *dev) +{ +struct can_priv *priv =netdev_priv (dev); +struct net_device_stats *stats = &dev->stats; +struct sk_buff *skb; +struct can_frame *cf; +int err; + +/* Synchronize with dev->hard_start_xmit() */ drivers/net/can/dev.c line 346
Quoted 10 lines
drivers/net/can/dev.c new file +10
-0+netif_tx_lock (dev); + +/* Ensure that no more messages can go out */ +if (netif_carrier_ok (dev)) +netif_carrier_off (dev); + +/* Ensure that no more messages can come in */ + err = priv->do_set_mode (dev,CAN_MODE_STOP ); +if (err) +return err;This leaves
_xmit_lockheld and carrier off. Is that really what you want to do?drivers/net/can/dev.c line 358
Quoted 12 lines
drivers/net/can/dev.c new file +12
-0+ +/* Now it's save to clean up */ +del_timer_sync (&priv->restart_timer); +can_flush_echo_skb (dev); + +dev_dbg (dev->dev.parent,"restarted\n" ); + priv->can_stats.restarts++; + +/* send restart message upstream */ + skb =dev_alloc_skb (sizeof (struct can_frame )); +if (skb ==NULL ) +return -ENOMEM ;...here too...
Quoted 12 lines
drivers/net/can/dev.c new file +12
-0+ skb->dev = dev; + skb->protocol =htons (ETH_P_CAN ); + cf = (struct can_frame *)skb_put (skb,sizeof (struct can_frame )); +memset (cf,0 ,sizeof (struct can_frame )); + cf->can_id =CAN_ERR_FLAG |CAN_ERR_RESTARTED ; + cf->can_dlc =CAN_ERR_DLC ; + +netif_rx (skb); + + dev->last_rx = jiffies; + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc;
Quoted 8 lines
drivers/net/can/dev.c line 375
Quoted 5 lines
drivers/net/can/dev.c new file +5
-0+ +/* Now restart the device */ + err = priv->do_set_mode (dev,CAN_MODE_START ); +if (err) +return err;...and here too. Do you maybe want to get rid of the middle-of-function returns and switch to the "goto out" convention?
Right, needs to be fixed.
Quoted 8 lines
Quoted 8 lines
drivers/net/can/dev.c new file +8
-0+netif_carrier_on (dev); + +netif_tx_unlock (dev); + +return 0 ; +} + +static void can_restart_after (unsigned long data)
Quoted 8 lines
drivers/net/can/dev.c line 389
Quoted 5 lines
drivers/net/can/dev.c new file +5
-0+{ +struct net_device *dev = (struct net_device *)data; + +can_restart_now (dev); +}
can_restart_afterwhat? I find myself confused by this function and wondering why it exists.
It's just a wrapper to make the compile happy. It's the timer callback function used here:
priv->restart_timer.function = can_restart_after;
in contrast to can_restart_now(), which can be called via netlink interface as well. Would the name "can_restart_callback" be more appropriate?
Wolfgang.
PATCH v2 4/8 can: Driver for the SJA1000 CAN controller
In reply to Wolfgang GrandeggerThis patch adds the generic Socket-CAN driver for the Philips SJA1000 full CAN controller.
--- drivers/net/can/Kconfig | 6 drivers/net/can/Makefile | 2 drivers/net/can/sja1000/Makefile | 7 drivers/net/can/sja1000/sja1000.c | 645 ++++++++++++++++++++++++++++++++++++++ drivers/net/can/sja1000/sja1000.h | 177 ++++++++++ 5 files changed, 837 insertions(+) create mode 100644 drivers/net/can/sja1000/Makefile create mode 100644 drivers/net/can/sja1000/sja1000.c create mode 100644 drivers/net/can/sja1000/sja1000.h
drivers/net/can/Kconfig +6 -0
@@ -35,6 +35,12 @@ arguments "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw". If unsure, say Y. +config CAN_SJA1000 + depends on CAN_DEV + tristate "Philips SJA1000" + ---help--- + Driver for the SJA1000 CAN controllers from Philips or NXP + config CAN_DEBUG_DEVICES bool "CAN devices debugging messages" depends on CAN
drivers/net/can/Makefile +2 -0
@@ -7,4 +7,6 @@ obj-$(CONFIG_CAN_DEV) += can-dev.o can-dev-y := dev.o +obj-$(CONFIG_CAN_SJA1000) += sja1000/ + ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
drivers/net/can/sja1000/Makefile new file +7 -0
@@ -0,0 +1,7 @@ +# +# Makefile for the SJA1000 CAN controller drivers. +# + +obj-$(CONFIG_CAN_SJA1000) += sja1000.o + +ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
drivers/net/can/sja1000/sja1000.c new file +645 -0
645 lines not on this page · raw message
drivers/net/can/sja1000/sja1000.h new file +177 -0
177 lines not on this page · raw message
Jonathan Corbet
maintainerRe: [PATCH v2 4/7] [PATCH 4/8] can: Driver for the SJA1000 CAN controller
[Quick drive-by review continues...]
drivers/net/can/sja1000/sja1000.c line 90
Quoted 4 lines
drivers/net/can/sja1000/sja1000.c new file +4
-0+ +static int sja1000_probe_chip (struct net_device *dev) +{ +struct sja1000_priv *priv =netdev_priv (dev);
Looking down toward the bottom, I see:
drivers/net/can/sja1000/sja1000.h line 153
Quoted 2 lines
drivers/net/can/sja1000/sja1000.h new file +2
-0+struct sja1000_priv { +struct can_priv can;
So you're still using the "put the higher-level structure at the top so we can treat it like either kind of pointer" trick. I'd still recommend against that. Far better to do something like:
struct can_priv *canpriv = netdev_priv(dev); struct sja_1000_priv *priv = container_of(canpriv, struct sja_1000_priv, can);
Of course, you can put that dance into a helper function.
drivers/net/can/sja1000/sja1000.c line 98
Quoted 7 lines
drivers/net/can/sja1000/sja1000.c new file +7
-0+if (dev->base_addr && (priv->read_reg (dev,0 ) ==0xFF )) { +printk (KERN_INFO "%s: probing @0x%lX failed\n" , +DRV_NAME , dev->base_addr); +return 0 ; + } +return 1 ; +}
So zero is an error return? That's contrary to usual practice.
Quoted 9 lines
drivers/net/can/sja1000/sja1000.c new file +9
-0+static int set_reset_mode (struct net_device *dev) +{ +struct sja1000_priv *priv =netdev_priv (dev); +unsigned char status = priv->read_reg (dev,REG_MOD ); +int i; + +/* disable interrupts */ + priv->write_reg (dev,REG_IER ,IRQ_OFF ); +
drivers/net/can/sja1000/sja1000.c line 118
Quoted 10 lines
drivers/net/can/sja1000/sja1000.c new file +10
-0+for (i =0 ; i <100 ; i++) { +/* check reset bit */ +if (status &MOD_RM ) { + priv->can.state =CAN_STATE_STOPPED ; +return 0 ; + } + + priv->write_reg (dev,REG_MOD ,MOD_RM );/* reset chip */ + status = priv->read_reg (dev,REG_MOD ); +udelay (10 );
Wouldn't you want to read the new state *after* the delay?
Quoted 17 lines
drivers/net/can/sja1000/sja1000.c new file +17
-0+ } + +dev_err (dev->dev.parent,"setting SJA1000 into reset mode failed!\n" ); +return 1 ; + +} + +static int set_normal_mode (struct net_device *dev) +{ +struct sja1000_priv *priv =netdev_priv (dev); +unsigned char status = priv->read_reg (dev,REG_MOD ); +int i; + +for (i =0 ; i <100 ; i++) { +/* check reset bit */ +if ((status &MOD_RM ) ==0 ) { + priv->can.state =CAN_STATE_ERROR_ACTIVE ;
drivers/net/can/sja1000/sja1000.c line 145
Quoted 10 lines
drivers/net/can/sja1000/sja1000.c new file +10
-0+/* enable all interrupts */ + priv->write_reg (dev,REG_IER ,IRQ_ALL ); + +return 0 ; + } + +/* set chip to normal mode */ + priv->write_reg (dev,REG_MOD ,0x00 ); + status = priv->read_reg (dev,REG_MOD ); +udelay (10 );
Here too?
Quoted 7 lines
drivers/net/can/sja1000/sja1000.c new file +7
-0+ } + +dev_err (dev->dev.parent,"setting SJA1000 into normal mode failed!\n" ); +return 1 ; + +} +
[...]
Quoted 11 lines
drivers/net/can/sja1000/sja1000.c new file +11
-0+irqreturn_t sja1000_interrupt (int irq,void *dev_id) +{ +struct net_device *dev = (struct net_device *)dev_id; +struct sja1000_priv *priv =netdev_priv (dev); +struct net_device_stats *stats = &dev->stats; +uint8_t isrc, status; +int n =0 ; + +/* Shared interrupts and IRQ off? */ +if (priv->read_reg (dev,REG_IER ) ==IRQ_OFF ) +return IRQ_NONE ;
drivers/net/can/sja1000/sja1000.c line 495
Quoted 10 lines
drivers/net/can/sja1000/sja1000.c new file +10
-0+ +if (priv->pre_irq) + priv->pre_irq (dev); + +while ((isrc = priv->read_reg (dev,REG_IR )) && (n <SJA1000_MAX_IRQ )) { + n++; + status = priv->read_reg (dev,REG_SR ); + +if (isrc &IRQ_WUI ) +dev_warn (dev->dev.parent,"wakeup interrupt\n" );
How many of these might you get? Should this be rate limited?
Quoted 39 lines
drivers/net/can/sja1000/sja1000.c new file +39
-0+if (isrc &IRQ_TI ) { +/* transmission complete interrupt */ + stats->tx_packets++; +can_get_echo_skb (dev,0 ); +netif_wake_queue (dev); + } +if (isrc &IRQ_RI ) { +/* receive interrupt */ +while (status &SR_RBS ) { +sja1000_rx (dev); + status = priv->read_reg (dev,REG_SR ); + } + } +if (isrc & (IRQ_DOI |IRQ_EI |IRQ_BEI |IRQ_EPI |IRQ_ALI )) { +/* error interrupt */ +if (sja1000_err (dev, isrc, status)) +break ; + } + } + +if (priv->post_irq) + priv->post_irq (dev); + +if (n >=SJA1000_MAX_IRQ ) +dev_dbg (dev->dev.parent,"%d messages handled in ISR" , n); + +return (n) ?IRQ_HANDLED :IRQ_NONE ; +} +EXPORT_SYMBOL_GPL (sja1000_interrupt); + +static int sja1000_open (struct net_device *dev) +{ +struct sja1000_priv *priv =netdev_priv (dev); +int err; + +/* set chip into reset mode */ +set_reset_mode (dev); + +/* common open */
drivers/net/can/sja1000/sja1000.c line 545
Quoted 10 lines
drivers/net/can/sja1000/sja1000.c new file +10
-0+ err =open_candev (dev); +if (err) +return err; + +/* register interrupt handler, if not done by the device driver */ +if (!(priv->flags &SJA1000_CUSTOM_IRQ_HANDLER )) { + err =request_irq (dev->irq, &sja1000_interrupt,IRQF_SHARED , + dev->name, (void *)dev); +if (err) +return -EAGAIN ;
If you return here you fail, but you've not undone open_candev(). Looking there, it seems no harm will be done - until somebody changes open_candev() someday.
Quoted 11 lines
drivers/net/can/sja1000/sja1000.c new file +11
-0+ } + +/* init and start chi */ +sja1000_start (dev); + priv->open_time = jiffies; + +netif_start_queue (dev); + +return 0 ; +} +
[...]
drivers/net/can/sja1000/sja1000.h line 160
Quoted 12 lines
drivers/net/can/sja1000/sja1000.h new file +12
-0+/* +* SJA1000 private data structure +*/ +struct sja1000_priv { +struct can_priv can; +long open_time; +struct sk_buff *echo_skb; + +u8 (*read_reg) (const struct net_device *dev,int reg); +void (*write_reg) (const struct net_device *dev,int reg,u8 val); +void (*pre_irq) (const struct net_device *dev); +void (*post_irq) (const struct net_device *dev);
What are the locking rules for functions like ->read_reg() now? Entirely up to the lower level? Would be good to document that near the structure definition.
drivers/net/can/sja1000/sja1000.h line 167
Quoted 7 lines
drivers/net/can/sja1000/sja1000.h new file +7
-0+ +void *priv;/* for board-specific data */ +struct net_device *dev; + +u8 ocr; +u8 cdr; +u32 flags;
The meaning of these fields is not exactly clear.
Quoted 1 line
+};
jon
Re: [PATCH v2 4/7] [PATCH 4/8] can: Driver for the SJA1000 CAN controller
Quoted 16 lines · Jonathan Corbet
[Quick drive-by review continues...]
drivers/net/can/sja1000/sja1000.c line 90
Quoted 4 lines
drivers/net/can/sja1000/sja1000.c new file +4
-0+ +static int sja1000_probe_chip (struct net_device *dev) +{ +struct sja1000_priv *priv =netdev_priv (dev);Looking down toward the bottom, I see:
drivers/net/can/sja1000/sja1000.h line 153
Quoted 2 lines
drivers/net/can/sja1000/sja1000.h new file +2
-0+struct sja1000_priv { +struct can_priv can;So you're still using the "put the higher-level structure at the top so we can treat it like either kind of pointer" trick. I'd still recommend against that. Far better to do something like:
Quoted 4 lines
struct can_priv *canpriv = netdev_priv(dev); struct sja_1000_priv *priv = container_of(canpriv, struct sja_1000_priv, can);Of course, you can put that dance into a helper function.
There is no way to initialize the value returned by netdev_priv() as it does not point to a member of struct net_device. I already commented here:
http://marc.info/?l=linux-netdev&m=124120212106891&w=2
Have I missed something?
Quoted 9 lines
drivers/net/can/sja1000/sja1000.c line 98
Quoted 7 lines
drivers/net/can/sja1000/sja1000.c new file +7
-0+if (dev->base_addr && (priv->read_reg (dev,0 ) ==0xFF )) { +printk (KERN_INFO "%s: probing @0x%lX failed\n" , +DRV_NAME , dev->base_addr); +return 0 ; + } +return 1 ; +}So zero is an error return? That's contrary to usual practice.
OK, will fix.
Quoted 13 lines
Quoted 13 lines
drivers/net/can/sja1000/sja1000.c new file +13
-0+static int set_reset_mode (struct net_device *dev) +{ +struct sja1000_priv *priv =netdev_priv (dev); +unsigned char status = priv->read_reg (dev,REG_MOD ); +int i; + +/* disable interrupts */ + priv->write_reg (dev,REG_IER ,IRQ_OFF ); + +for (i =0 ; i <100 ; i++) { +/* check reset bit */ +if (status &MOD_RM ) { + priv->can.state =CAN_STATE_STOPPED ;
Quoted 8 lines
drivers/net/can/sja1000/sja1000.c line 118
Quoted 6 lines
drivers/net/can/sja1000/sja1000.c new file +6
-0+return 0 ; + } + + priv->write_reg (dev,REG_MOD ,MOD_RM );/* reset chip */ + status = priv->read_reg (dev,REG_MOD ); +udelay (10 );Wouldn't you want to read the new state *after* the delay?
Yes, that makes more sense.
Quoted 4 lines
drivers/net/can/sja1000/sja1000.c line 122
Quoted 4 lines
drivers/net/can/sja1000/sja1000.c new file +4
-0+ } + +dev_err (dev->dev.parent,"setting SJA1000 into reset mode failed!\n" ); +return 1 ;
Will fix this return value as well.
Quoted 51 lines
Quoted 13 lines
drivers/net/can/sja1000/sja1000.c new file +13
-0+ +} + +static int set_normal_mode (struct net_device *dev) +{ +struct sja1000_priv *priv =netdev_priv (dev); +unsigned char status = priv->read_reg (dev,REG_MOD ); +int i; + +for (i =0 ; i <100 ; i++) { +/* check reset bit */ +if ((status &MOD_RM ) ==0 ) { + priv->can.state =CAN_STATE_ERROR_ACTIVE ;drivers/net/can/sja1000/sja1000.c line 145
Quoted 10 lines
drivers/net/can/sja1000/sja1000.c new file +10
-0+/* enable all interrupts */ + priv->write_reg (dev,REG_IER ,IRQ_ALL ); + +return 0 ; + } + +/* set chip to normal mode */ + priv->write_reg (dev,REG_MOD ,0x00 ); + status = priv->read_reg (dev,REG_MOD ); +udelay (10 );Here too?
Quoted 7 lines
drivers/net/can/sja1000/sja1000.c new file +7
-0+ } + +dev_err (dev->dev.parent,"setting SJA1000 into normal mode failed!\n" ); +return 1 ; + +} +[...]
Quoted 15 lines
drivers/net/can/sja1000/sja1000.c new file +15
-0+irqreturn_t sja1000_interrupt (int irq,void *dev_id) +{ +struct net_device *dev = (struct net_device *)dev_id; +struct sja1000_priv *priv =netdev_priv (dev); +struct net_device_stats *stats = &dev->stats; +uint8_t isrc, status; +int n =0 ; + +/* Shared interrupts and IRQ off? */ +if (priv->read_reg (dev,REG_IER ) ==IRQ_OFF ) +return IRQ_NONE ; + +if (priv->pre_irq) + priv->pre_irq (dev); +
Quoted 8 lines
drivers/net/can/sja1000/sja1000.c line 495
Quoted 6 lines
drivers/net/can/sja1000/sja1000.c new file +6
-0+while ((isrc = priv->read_reg (dev,REG_IR )) && (n <SJA1000_MAX_IRQ )) { + n++; + status = priv->read_reg (dev,REG_SR ); + +if (isrc &IRQ_WUI ) +dev_warn (dev->dev.parent,"wakeup interrupt\n" );How many of these might you get? Should this be rate limited?
None, because the driver does not (yet) support the sleep mode. For that reason it's a warning.
Quoted 45 lines
Quoted 45 lines
drivers/net/can/sja1000/sja1000.c new file +45
-0+if (isrc &IRQ_TI ) { +/* transmission complete interrupt */ + stats->tx_packets++; +can_get_echo_skb (dev,0 ); +netif_wake_queue (dev); + } +if (isrc &IRQ_RI ) { +/* receive interrupt */ +while (status &SR_RBS ) { +sja1000_rx (dev); + status = priv->read_reg (dev,REG_SR ); + } + } +if (isrc & (IRQ_DOI |IRQ_EI |IRQ_BEI |IRQ_EPI |IRQ_ALI )) { +/* error interrupt */ +if (sja1000_err (dev, isrc, status)) +break ; + } + } + +if (priv->post_irq) + priv->post_irq (dev); + +if (n >=SJA1000_MAX_IRQ ) +dev_dbg (dev->dev.parent,"%d messages handled in ISR" , n); + +return (n) ?IRQ_HANDLED :IRQ_NONE ; +} +EXPORT_SYMBOL_GPL (sja1000_interrupt); + +static int sja1000_open (struct net_device *dev) +{ +struct sja1000_priv *priv =netdev_priv (dev); +int err; + +/* set chip into reset mode */ +set_reset_mode (dev); + +/* common open */ + err =open_candev (dev); +if (err) +return err; + +/* register interrupt handler, if not done by the device driver */ +if (!(priv->flags &SJA1000_CUSTOM_IRQ_HANDLER )) {
Quoted 8 lines
drivers/net/can/sja1000/sja1000.c line 545
Quoted 4 lines
drivers/net/can/sja1000/sja1000.c new file +4
-0+ err =request_irq (dev->irq, &sja1000_interrupt,IRQF_SHARED , + dev->name, (void *)dev); +if (err) +return -EAGAIN ;If you return here you fail, but you've not undone
open_candev(). Looking there, it seems no harm will be done - until somebody changesopen_candev()someday.
Right, the missing close_candev() does currently not harm but that might change in the future. Will change.
Quoted 14 lines
Quoted 11 lines
drivers/net/can/sja1000/sja1000.c new file +11
-0+ } + +/* init and start chi */ +sja1000_start (dev); + priv->open_time = jiffies; + +netif_start_queue (dev); + +return 0 ; +} +[...]
Quoted 16 lines
drivers/net/can/sja1000/sja1000.h line 160
Quoted 12 lines
drivers/net/can/sja1000/sja1000.h new file +12
-0+/* +* SJA1000 private data structure +*/ +struct sja1000_priv { +struct can_priv can; +long open_time; +struct sk_buff *echo_skb; + +u8 (*read_reg) (const struct net_device *dev,int reg); +void (*write_reg) (const struct net_device *dev,int reg,u8 val); +void (*pre_irq) (const struct net_device *dev); +void (*post_irq) (const struct net_device *dev);What are the locking rules for functions like ->read_reg() now? Entirely up to the lower level? Would be good to document that near the structure definition.
Yes, it's up to the lower level.
Quoted 9 lines
drivers/net/can/sja1000/sja1000.h line 167
Quoted 7 lines
drivers/net/can/sja1000/sja1000.h new file +7
-0+ +void *priv;/* for board-specific data */ +struct net_device *dev; + +u8 ocr; +u8 cdr; +u32 flags;The meaning of these fields is not exactly clear.
I will add a description.
Wolfgang.
Jonathan Corbet
maintainerRe: [PATCH v2 4/7] [PATCH 4/8] can: Driver for the SJA1000 CAN controller
Quoted 7 lines · On Thu, 14 May 2009 11:03:53 +0200 Wolfgang Grandegger <[email protected]>…
Quoted 7 lines
So you're still using the "put the higher-level structure at the top so we can treat it like either kind of pointer" trick. I'd still recommend against that. Far better to do something like:
struct can_priv *canpriv = netdev_priv(dev); struct sja_1000_priv *priv = container_of(canpriv, struct sja_1000_priv, can);
Quoted 8 lines
Quoted 1 line
Of course, you can put that dance into a helper function.
There is no way to initialize the value returned by
netdev_priv()as it does not point to a member of structnet_device. I already commented here:http://marc.info/?l=linux-netdev&m=124120212106891&w=2
Have I missed something?
I'm confused. It points to the struct can_priv that you registered at the beginning. Since that structure is contained within struct sja1000_priv, you can use container_of(), as described above, to get it.
I would probably just write something like:
static inline struct sja1000_priv *to_sja1000_priv(struct net_device *dev)
{
return container_of(netdev_priv(dev), struct sja1000_priv, can);
}So have *I* missed something?
jon
Re: [PATCH v2 4/7] [PATCH 4/8] can: Driver for the SJA1000 CAN controller
Quoted 23 lines · Jonathan Corbet
Quoted 7 lines · On Thu, 14 May 2009 11:03:53 +0200 Wolfgang Grandegger <[email protected]>…
Quoted 7 lines
So you're still using the "put the higher-level structure at the top so we can treat it like either kind of pointer" trick. I'd still recommend against that. Far better to do something like:
struct can_priv *canpriv = netdev_priv(dev); struct sja_1000_priv *priv = container_of(canpriv, struct sja_1000_priv, can);Quoted 7 lines
Quoted 1 line
Of course, you can put that dance into a helper function.
There is no way to initialize the value returned by
netdev_priv()as it does not point to a member of structnet_device. I already commented here:http://marc.info/?l=linux-netdev&m=124120212106891&w=2
Have I missed something?
I'm confused. It points to the struct
can_privthat you registered at the beginning. Since that structure is contained within structsja1000_priv, you can usecontainer_of(), as described above, to get it.
Quoted 8 lines
I would probably just write something like:
static inline struct
sja1000_priv*to_sja1000_priv(structnet_device*dev){ return container_of(netdev_priv(dev), struct sja1000_priv, can); }So have *I* missed something?
Furthermore, the higher layer needs to known the location of the member "struct sja1000_priv can", e.g. by defining:
dev->priv = &dev_specific_priv->can;
But "struct net_device" does not have a "priv" member. netdev_priv(dev) always points to the beginning of the private data area. See:
http://lxr.linux.no/linux+v2.6.29/include/linux/netdevice.h#L953
Wolfgang.
Re: [PATCH v2 4/7] [PATCH 4/8] can: Driver for the SJA1000 CAN controller
Quoted 35 lines · Wolfgang Grandegger
Quoted 22 lines · Jonathan Corbet
Quoted 7 lines · On Thu, 14 May 2009 11:03:53 +0200 Wolfgang Grandegger <[email protected]>…
Quoted 7 lines
So you're still using the "put the higher-level structure at the top so we can treat it like either kind of pointer" trick. I'd still recommend against that. Far better to do something like:
struct can_priv *canpriv = netdev_priv(dev); struct sja_1000_priv *priv = container_of(canpriv, struct sja_1000_priv, can);Quoted 7 lines
Quoted 1 line
Of course, you can put that dance into a helper function.
There is no way to initialize the value returned by
netdev_priv()as it does not point to a member of structnet_device. I already commented here:http://marc.info/?l=linux-netdev&m=124120212106891&w=2
Have I missed something?
I'm confused. It points to the struct
can_privthat you registered at the beginning. Since that structure is contained within structsja1000_priv, you can usecontainer_of(), as described above, to get it.Quoted 8 lines
I would probably just write something like:
static inline struct
sja1000_priv*to_sja1000_priv(structnet_device*dev){ return container_of(netdev_priv(dev), struct sja1000_priv, can); }So have *I* missed something?
Furthermore, the higher layer needs to known the location of the member "struct
sja1000_privcan", e.g. by defining:
Quoted 6 lines
dev->priv = &dev_specific_priv->can;But "struct
net_device" does not have a "priv" member.netdev_priv(dev)always points to the beginning of the private data area. See:http://lxr.linux.no/linux+v2.6.29/include/linux/netdevice.h#L953
I could use container_of() as you suggested, of course, if the "struct can_priv" remains the first member of "struct sja1000_priv". Would that already be an improvement?
Wolfgang.
Jonathan Corbet
maintainerRe: [PATCH v2 4/7] [PATCH 4/8] can: Driver for the SJA1000 CAN controller
Quoted 8 lines · On Sat, 16 May 2009 08:57:03 +0200 Wolfgang Grandegger <[email protected]>…
Quoted 4 lines
But "struct
net_device" does not have a "priv" member.netdev_priv(dev)always points to the beginning of the private data area. See:http://lxr.linux.no/linux+v2.6.29/include/linux/netdevice.h#L953I could use
container_of()as you suggested, of course, if the "structcan_priv" remains the first member of "structsja1000_priv". Would that already be an improvement?
Ah, OK, I'm a little slow, sorry. I do get what the problem is here.
Using container_of() in that situation doesn't help a whole lot. The point is to get away from this assumption that struct can_priv is the first element of the structure.
Perhaps what you have is as good as it gets for now, but please add a comment to the structure noting that struct can_priv has to come first and why.
Thanks,
jon
PATCH v2 5/8 can: SJA1000 generic platform bus driver
In reply to Wolfgang GrandeggerThis driver adds support for the SJA1000 chips connected to the "platform bus", which can be found on various embedded systems.
--- drivers/net/can/Kconfig | 10 + drivers/net/can/sja1000/Makefile | 1 drivers/net/can/sja1000/sja1000_platform.c | 169 +++++++++++++++++++++++++++++ include/linux/can/platform/sja1000.h | 32 +++++ 4 files changed, 212 insertions(+) create mode 100644 drivers/net/can/sja1000/sja1000_platform.c create mode 100644 include/linux/can/platform/sja1000.h
drivers/net/can/Kconfig +10 -0
@@ -41,6 +41,16 @@ ---help--- Driver for the SJA1000 CAN controllers from Philips or NXP +config CAN_SJA1000_PLATFORM + depends on CAN_SJA1000 + tristate "Generic Platform Bus based SJA1000 driver" + ---help--- + This driver adds support for the SJA1000 chips connected to + the "platform bus" (Linux abstraction for directly to the + processor attached devices). Which can be found on various + boards from Phytec (http://www.phytec.de) like the PCM027, + PCM038. + config CAN_DEBUG_DEVICES bool "CAN devices debugging messages" depends on CAN
drivers/net/can/sja1000/Makefile +1 -0
@@ -3,5 +3,6 @@ # obj-$(CONFIG_CAN_SJA1000) += sja1000.o +obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
drivers/net/can/sja1000/sja1000_platform.c new file +169 -0
169 lines not on this page · raw message
include/linux/can/platform/sja1000.h new file +32 -0
@@ -0,0 +1,32 @@ +#ifndef _CAN_PLATFORM_SJA1000_H_ +#define _CAN_PLATFORM_SJA1000_H_ + +/* clock divider register */ +#define CDR_CLKOUT_MASK 0x07 +#define CDR_CLK_OFF 0x08/* Clock off (CLKOUT pin) */ +#define CDR_RXINPEN 0x20/* TX1 output is RX irq output */ +#define CDR_CBP 0x40/* CAN input comparator bypass */ +#define CDR_PELICAN 0x80/* PeliCAN mode */ + +/* output control register */ +#define OCR_MODE_BIPHASE 0x00 +#define OCR_MODE_TEST 0x01 +#define OCR_MODE_NORMAL 0x02 +#define OCR_MODE_CLOCK 0x03 +#define OCR_TX0_INVERT 0x04 +#define OCR_TX0_PULLDOWN 0x08 +#define OCR_TX0_PULLUP 0x10 +#define OCR_TX0_PUSHPULL 0x18 +#define OCR_TX1_INVERT 0x20 +#define OCR_TX1_PULLDOWN 0x40 +#define OCR_TX1_PULLUP 0x80 +#define OCR_TX1_PUSHPULL 0xc0 + +struct sja1000_platform_data { +u32 clock;/* CAN bus oscillator frequency in Hz */ + +u8 ocr;/* output control register */ +u8 cdr;/* clock divider register */ +}; + +#endif /* !_CAN_PLATFORM_SJA1000_H_ */
Jonathan Corbet
maintainerRe: [PATCH v2 5/7] [PATCH 5/8] can: SJA1000 generic platform bus driver
Quoted 2 lines · On Tue, 12 May 2009 11:28:02 +0200 Wolfgang Grandegger <[email protected]>…
This driver adds support for the SJA1000 chips connected to the "platform bus", which can be found on various embedded systems.
[...]
drivers/net/can/sja1000/sja1000_platform.c line 48
Quoted 10 lines
drivers/net/can/sja1000/sja1000_platform.c new file +10
-0+ +static u8 sp_read_reg (const struct net_device *dev,int reg) +{ +return ioread8 ((void __iomem *)(dev->base_addr + reg)); +} + +static void sp_write_reg (const struct net_device *dev,int reg,u8 val) +{ +iowrite8 (val, (void __iomem *)(dev->base_addr + reg)); +}
So there's no locking around accesses to the hardware at all. How do you protect against concurrent access?
[...]
drivers/net/can/sja1000/sja1000_platform.c line 142
Quoted 12 lines
drivers/net/can/sja1000/sja1000_platform.c new file +12
-0+static int sp_remove (struct platform_device *pdev) +{ +struct net_device *dev =dev_get_drvdata (&pdev->dev); +struct resource *res; + +unregister_sja1000dev (dev); +dev_set_drvdata (&pdev->dev,NULL ); + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +release_mem_region (res->start, res->end - res->start +1 ); + +if (dev->base_addr) +iounmap ((void __iomem *)dev->base_addr);
Seems like you should unmap it before releasing it back to the kernel. Nobody else is ever going to jump in and try to map it, but still...
drivers/net/can/sja1000/sja1000_platform.c line 147
Quoted 4 lines
drivers/net/can/sja1000/sja1000_platform.c new file +4
-0+free_sja1000dev (dev); + +return 0 ; +}
jon
Re: [PATCH v2 5/7] [PATCH 5/8] can: SJA1000 generic platform bus driver
Quoted 8 lines · Jonathan Corbet
Quoted 2 lines · On Tue, 12 May 2009 11:28:02 +0200 Wolfgang Grandegger <[email protected]>…
This driver adds support for the SJA1000 chips connected to the "platform bus", which can be found on various embedded systems.
[...]
Quoted 13 lines
drivers/net/can/sja1000/sja1000_platform.c line 48
Quoted 10 lines
drivers/net/can/sja1000/sja1000_platform.c new file +10
-0+ +static u8 sp_read_reg (const struct net_device *dev,int reg) +{ +return ioread8 ((void __iomem *)(dev->base_addr + reg)); +} + +static void sp_write_reg (const struct net_device *dev,int reg,u8 val) +{ +iowrite8 (val, (void __iomem *)(dev->base_addr + reg)); +}So there's no locking around accesses to the hardware at all. How do you protect against concurrent access?
There is no concurrent access to the same register and PCI register accesses do not need to be serialized.
Quoted 17 lines
[...]
drivers/net/can/sja1000/sja1000_platform.c line 142
Quoted 12 lines
drivers/net/can/sja1000/sja1000_platform.c new file +12
-0+static int sp_remove (struct platform_device *pdev) +{ +struct net_device *dev =dev_get_drvdata (&pdev->dev); +struct resource *res; + +unregister_sja1000dev (dev); +dev_set_drvdata (&pdev->dev,NULL ); + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +release_mem_region (res->start, res->end - res->start +1 ); + +if (dev->base_addr) +iounmap ((void __iomem *)dev->base_addr);Seems like you should unmap it before releasing it back to the kernel. Nobody else is ever going to jump in and try to map it, but still...
Will fix.
Wolfgang.
Re: [PATCH v2 5/7] [PATCH 5/8] can: SJA1000 generic platform bus driver
In reply to Wolfgang GrandeggerHi Wolfgang,
some comments inline.
Sascha
Quoted 118 lines · Wolfgang Grandegger
This driver adds support for the SJA1000 chips connected to the "platform bus", which can be found on various embedded systems.
Signed-off-by Sascha Hauer <[email protected]>Signed-off-by Wolfgang Grandegger <[email protected]>Signed-off-by Marc Kleine-Budde <[email protected]>Signed-off-by Oliver Hartkopp <[email protected]>--- drivers/net/can/Kconfig | 10 + drivers/net/can/sja1000/Makefile | 1 drivers/net/can/sja1000/sja1000_platform.c | 169 +++++++++++++++++++++++++++++ include/linux/can/platform/sja1000.h | 32 +++++ 4 files changed, 212 insertions(+) create mode 100644 drivers/net/can/sja1000/sja1000_platform.c create mode 100644 include/linux/can/platform/sja1000.hIndex: net-next-2.6/drivers/net/can/Kconfig
===================================================================drivers/net/can/Kconfig +10
-0@@ -41,6 +41,16 @@ ---help--- Driver for the SJA1000 CAN controllers from Philips or NXP +config CAN_SJA1000_PLATFORM + depends on CAN_SJA1000 + tristate "Generic Platform Bus based SJA1000 driver" + ---help--- + This driver adds support for the SJA1000 chips connected to + the "platform bus" (Linux abstraction for directly to the + processor attached devices). Which can be found on various + boards from Phytec (http://www.phytec.de) like the PCM027, + PCM038. + config CAN_DEBUG_DEVICES bool "CAN devices debugging messages" depends on CANIndex: net-next-2.6/drivers/net/can/sja1000/Makefile
===================================================================drivers/net/can/sja1000/Makefile +1
-0@@ -3,5 +3,6 @@ # obj-$(CONFIG_CAN_SJA1000) += sja1000.o +obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUGIndex:
net-next-2.6/drivers/net/can/sja1000/sja1000_platform.c
===================================================================drivers/net/can/sja1000/sja1000_platform.c new file +65
-0@@ -0,0 +1,169 @@ +/* +* Copyright (C) 2005 Sascha Hauer, Pengutronix +* Copyright (C) 2007 Wolfgang Grandegger <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the version 2 of the GNU General Public License +* as published by the Free Software Foundation +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/netdevice.h> +#include <linux/delay.h> +#include <linux/pci.h> +#include <linux/platform_device.h> +#include <linux/irq.h> +#include <linux/can.h> +#include <linux/can/dev.h> +#include <linux/can/platform/sja1000.h> +#include <linux/io.h> + +#include "sja1000.h" + +#define DRV_NAME "sja1000_platform" + +MODULE_AUTHOR ("Sascha Hauer <[email protected]>" ); +MODULE_DESCRIPTION ("Socket-CAN driver for SJA1000 on the platform bus" ); +MODULE_LICENSE ("GPL v2" ); + +static u8 sp_read_reg (const struct net_device *dev,int reg) +{ +return ioread8 ((void __iomem *)(dev->base_addr + reg)); +} + +static void sp_write_reg (const struct net_device *dev,int reg,u8 val) +{ +iowrite8 (val, (void __iomem *)(dev->base_addr + reg)); +} + +static int sp_probe (struct platform_device *pdev) +{ +int err, irq; +void __iomem *addr; +struct net_device *dev; +struct sja1000_priv *priv; +struct resource *res_mem, *res_irq; +struct sja1000_platform_data *pdata; + + pdata = pdev->dev.platform_data; +if (!pdata) { +dev_err (&pdev->dev,"No platform data provided!\n" ); + err = -ENODEV ; + goto exit; + } +
drivers/net/can/sja1000/sja1000_platform.c line 75
Quoted 10 lines
drivers/net/can/sja1000/sja1000_platform.c new file +10
-0+ res_mem =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + res_irq =platform_get_resource (pdev,IORESOURCE_IRQ ,0 ); +if (!res_mem || !res_irq) { + err = -ENODEV ; + goto exit; + } + +if (!request_mem_region (res_mem->start, + res_mem->end - res_mem->start +1 , +DRV_NAME )) {
resource_size(res_mem) please, also for the other occurrences in this file
Quoted 4 lines
drivers/net/can/sja1000/sja1000_platform.c new file +4
-0+ err = -EBUSY ; + goto exit; + } +
drivers/net/can/sja1000/sja1000_platform.c line 89
Quoted 10 lines
drivers/net/can/sja1000/sja1000_platform.c new file +10
-0+ addr =ioremap_nocache (res_mem->start, + res_mem->end - res_mem->start +1 ); +if (!addr) { + err = -ENOMEM ; + goto exit_release; + } + + irq = res_irq->start; +if (res_irq->flags &IRQF_TRIGGER_MASK ) +set_irq_type (irq, res_irq->flags &IRQF_TRIGGER_MASK );
You shouldn't use set_irq_type on not yet requested irqs but instead pass the flags to the real driver and pass them in request_irq.
Quoted 19 lines
drivers/net/can/sja1000/sja1000_platform.c new file +19
-0+ + dev =alloc_sja1000dev (0 ); +if (!dev) { + err = -ENOMEM ; + goto exit_iounmap; + } + priv =netdev_priv (dev); + + priv->read_reg = sp_read_reg; + priv->write_reg = sp_write_reg; + priv->can.clock.freq = pdata->clock; + priv->ocr = pdata->ocr; + priv->cdr = pdata->cdr; + + dev->irq = irq; + dev->base_addr = (unsigned long )addr; + +dev_set_drvdata (&pdev->dev, dev); +SET_NETDEV_DEV (dev, &pdev->dev);
drivers/net/can/sja1000/sja1000_platform.c line 118
Quoted 10 lines
drivers/net/can/sja1000/sja1000_platform.c new file +10
-0+ + err =register_sja1000dev (dev); +if (err) { +dev_err (&pdev->dev,"registering %s failed (err=%d)\n" , +DRV_NAME , err); + goto exit_free; + } + +dev_info (&pdev->dev,"%s device registered (base_addr=%#lx, irq=%d)\n" , +DRV_NAME , dev->base_addr, dev->irq);
dev_info will already print the driver name twice, printing DRV_NAME again seems unnecessary.
Quoted 90 lines
drivers/net/can/sja1000/sja1000_platform.c new file +51
-0+return 0 ; + + exit_free: +free_sja1000dev (dev); + exit_iounmap: +iounmap (addr); + exit_release: +release_mem_region (res_mem->start, res_mem->end - res_mem->start +1 ); + exit: +return err; +} + +static int sp_remove (struct platform_device *pdev) +{ +struct net_device *dev =dev_get_drvdata (&pdev->dev); +struct resource *res; + +unregister_sja1000dev (dev); +dev_set_drvdata (&pdev->dev,NULL ); + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +release_mem_region (res->start, res->end - res->start +1 ); + +if (dev->base_addr) +iounmap ((void __iomem *)dev->base_addr); + +free_sja1000dev (dev); + +return 0 ; +} + +static struct platform_driver sp_driver = { + .probe = sp_probe, + .remove = sp_remove, + .driver = { + .name =DRV_NAME , + .owner =THIS_MODULE , + }, +}; + +static int __init sp_init (void ) +{ +return platform_driver_register (&sp_driver); +} + +static void __exit sp_exit(void) +{ +platform_driver_unregister (&sp_driver); +} + +module_init (sp_init); +module_exit (sp_exit);Index:
net-next-2.6/include/linux/can/platform/sja1000.h
===================================================================include/linux/can/platform/sja1000.h new file +32
-0@@ -0,0 +1,32 @@ +#ifndef _CAN_PLATFORM_SJA1000_H_ +#define _CAN_PLATFORM_SJA1000_H_ + +/* clock divider register */ +#define CDR_CLKOUT_MASK 0x07 +#define CDR_CLK_OFF 0x08/* Clock off (CLKOUT pin) */ +#define CDR_RXINPEN 0x20/* TX1 output is RX irq output */ +#define CDR_CBP 0x40/* CAN input comparator bypass */ +#define CDR_PELICAN 0x80/* PeliCAN mode */ + +/* output control register */ +#define OCR_MODE_BIPHASE 0x00 +#define OCR_MODE_TEST 0x01 +#define OCR_MODE_NORMAL 0x02 +#define OCR_MODE_CLOCK 0x03 +#define OCR_TX0_INVERT 0x04 +#define OCR_TX0_PULLDOWN 0x08 +#define OCR_TX0_PULLUP 0x10 +#define OCR_TX0_PUSHPULL 0x18 +#define OCR_TX1_INVERT 0x20 +#define OCR_TX1_PULLDOWN 0x40 +#define OCR_TX1_PULLUP 0x80 +#define OCR_TX1_PUSHPULL 0xc0 + +struct sja1000_platform_data { +u32 clock;/* CAN bus oscillator frequency in Hz */ + +u8 ocr;/* output control register */ +u8 cdr;/* clock divider register */ +}; + +#endif /* !_CAN_PLATFORM_SJA1000_H_ */
Signature · 4 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
Re: [PATCH v2 5/7] [PATCH 5/8] can: SJA1000 generic platform bus driver
Hi Sascha,
Quoted 130 lines · Sascha Hauer
Hi Wolfgang,
some comments inline.
Sascha
Quoted 123 lines · Wolfgang Grandegger
This driver adds support for the SJA1000 chips connected to the "platform bus", which can be found on various embedded systems.
Signed-off-by Sascha Hauer <[email protected]>Signed-off-by Wolfgang Grandegger <[email protected]>Signed-off-by Marc Kleine-Budde <[email protected]>Signed-off-by Oliver Hartkopp <[email protected]>--- drivers/net/can/Kconfig | 10 + drivers/net/can/sja1000/Makefile | 1 drivers/net/can/sja1000/sja1000_platform.c | 169 +++++++++++++++++++++++++++++ include/linux/can/platform/sja1000.h | 32 +++++ 4 files changed, 212 insertions(+) create mode 100644 drivers/net/can/sja1000/sja1000_platform.c create mode 100644 include/linux/can/platform/sja1000.hIndex: net-next-2.6/drivers/net/can/Kconfig
===================================================================drivers/net/can/Kconfig +10
-0@@ -41,6 +41,16 @@ ---help--- Driver for the SJA1000 CAN controllers from Philips or NXP +config CAN_SJA1000_PLATFORM + depends on CAN_SJA1000 + tristate "Generic Platform Bus based SJA1000 driver" + ---help--- + This driver adds support for the SJA1000 chips connected to + the "platform bus" (Linux abstraction for directly to the + processor attached devices). Which can be found on various + boards from Phytec (http://www.phytec.de) like the PCM027, + PCM038. + config CAN_DEBUG_DEVICES bool "CAN devices debugging messages" depends on CANIndex: net-next-2.6/drivers/net/can/sja1000/Makefile
===================================================================drivers/net/can/sja1000/Makefile +1
-0@@ -3,5 +3,6 @@ # obj-$(CONFIG_CAN_SJA1000) += sja1000.o +obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUGIndex:
net-next-2.6/drivers/net/can/sja1000/sja1000_platform.c
===================================================================drivers/net/can/sja1000/sja1000_platform.c new file +70
-0@@ -0,0 +1,169 @@ +/* +* Copyright (C) 2005 Sascha Hauer, Pengutronix +* Copyright (C) 2007 Wolfgang Grandegger <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the version 2 of the GNU General Public License +* as published by the Free Software Foundation +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/netdevice.h> +#include <linux/delay.h> +#include <linux/pci.h> +#include <linux/platform_device.h> +#include <linux/irq.h> +#include <linux/can.h> +#include <linux/can/dev.h> +#include <linux/can/platform/sja1000.h> +#include <linux/io.h> + +#include "sja1000.h" + +#define DRV_NAME "sja1000_platform" + +MODULE_AUTHOR ("Sascha Hauer <[email protected]>" ); +MODULE_DESCRIPTION ("Socket-CAN driver for SJA1000 on the platform bus" ); +MODULE_LICENSE ("GPL v2" ); + +static u8 sp_read_reg (const struct net_device *dev,int reg) +{ +return ioread8 ((void __iomem *)(dev->base_addr + reg)); +} + +static void sp_write_reg (const struct net_device *dev,int reg,u8 val) +{ +iowrite8 (val, (void __iomem *)(dev->base_addr + reg)); +} + +static int sp_probe (struct platform_device *pdev) +{ +int err, irq; +void __iomem *addr; +struct net_device *dev; +struct sja1000_priv *priv; +struct resource *res_mem, *res_irq; +struct sja1000_platform_data *pdata; + + pdata = pdev->dev.platform_data; +if (!pdata) { +dev_err (&pdev->dev,"No platform data provided!\n" ); + err = -ENODEV ; + goto exit; + } + + res_mem =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + res_irq =platform_get_resource (pdev,IORESOURCE_IRQ ,0 ); +if (!res_mem || !res_irq) { + err = -ENODEV ; + goto exit;
Quoted 8 lines
drivers/net/can/sja1000/sja1000_platform.c line 75
Quoted 5 lines
drivers/net/can/sja1000/sja1000_platform.c new file +5
-0+ } + +if (!request_mem_region (res_mem->start, + res_mem->end - res_mem->start +1 , +DRV_NAME )) {
resource_size(res_mem)please, also for the other occurrences in this file
OK.
Quoted 9 lines
Quoted 9 lines
drivers/net/can/sja1000/sja1000_platform.c new file +9
-0+ err = -EBUSY ; + goto exit; + } + + addr =ioremap_nocache (res_mem->start, + res_mem->end - res_mem->start +1 ); +if (!addr) { + err = -ENOMEM ; + goto exit_release;
Quoted 8 lines
drivers/net/can/sja1000/sja1000_platform.c line 89
Quoted 5 lines
drivers/net/can/sja1000/sja1000_platform.c new file +5
-0+ } + + irq = res_irq->start; +if (res_irq->flags &IRQF_TRIGGER_MASK ) +set_irq_type (irq, res_irq->flags &IRQF_TRIGGER_MASK );You shouldn't use
set_irq_typeon not yet requested irqs but instead pass the flags to the real driver and pass them inrequest_irq.
Why? I would require an extra member in the struct sja1000_priv.
Wolfgang.
Re: [PATCH v2 5/7] [PATCH 5/8] can: SJA1000 generic platform bus driver
Quoted 162 lines · Wolfgang Grandegger
Hi Sascha,
Quoted 130 lines · Sascha Hauer
Hi Wolfgang,
some comments inline.
Sascha
Quoted 123 lines · Wolfgang Grandegger
This driver adds support for the SJA1000 chips connected to the "platform bus", which can be found on various embedded systems.
Signed-off-by Sascha Hauer <[email protected]>Signed-off-by Wolfgang Grandegger <[email protected]>Signed-off-by Marc Kleine-Budde <[email protected]>Signed-off-by Oliver Hartkopp <[email protected]>--- drivers/net/can/Kconfig | 10 + drivers/net/can/sja1000/Makefile | 1 drivers/net/can/sja1000/sja1000_platform.c | 169 +++++++++++++++++++++++++++++ include/linux/can/platform/sja1000.h | 32 +++++ 4 files changed, 212 insertions(+) create mode 100644 drivers/net/can/sja1000/sja1000_platform.c create mode 100644 include/linux/can/platform/sja1000.hIndex: net-next-2.6/drivers/net/can/Kconfig
===================================================================drivers/net/can/Kconfig +10
-0@@ -41,6 +41,16 @@ ---help--- Driver for the SJA1000 CAN controllers from Philips or NXP +config CAN_SJA1000_PLATFORM + depends on CAN_SJA1000 + tristate "Generic Platform Bus based SJA1000 driver" + ---help--- + This driver adds support for the SJA1000 chips connected to + the "platform bus" (Linux abstraction for directly to the + processor attached devices). Which can be found on various + boards from Phytec (http://www.phytec.de) like the PCM027, + PCM038. + config CAN_DEBUG_DEVICES bool "CAN devices debugging messages" depends on CANIndex: net-next-2.6/drivers/net/can/sja1000/Makefile
===================================================================drivers/net/can/sja1000/Makefile +1
-0@@ -3,5 +3,6 @@ # obj-$(CONFIG_CAN_SJA1000) += sja1000.o +obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUGIndex:
net-next-2.6/drivers/net/can/sja1000/sja1000_platform.c
===================================================================drivers/net/can/sja1000/sja1000_platform.c new file +70
-0@@ -0,0 +1,169 @@ +/* +* Copyright (C) 2005 Sascha Hauer, Pengutronix +* Copyright (C) 2007 Wolfgang Grandegger <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the version 2 of the GNU General Public License +* as published by the Free Software Foundation +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/netdevice.h> +#include <linux/delay.h> +#include <linux/pci.h> +#include <linux/platform_device.h> +#include <linux/irq.h> +#include <linux/can.h> +#include <linux/can/dev.h> +#include <linux/can/platform/sja1000.h> +#include <linux/io.h> + +#include "sja1000.h" + +#define DRV_NAME "sja1000_platform" + +MODULE_AUTHOR ("Sascha Hauer <[email protected]>" ); +MODULE_DESCRIPTION ("Socket-CAN driver for SJA1000 on the platform bus" ); +MODULE_LICENSE ("GPL v2" ); + +static u8 sp_read_reg (const struct net_device *dev,int reg) +{ +return ioread8 ((void __iomem *)(dev->base_addr + reg)); +} + +static void sp_write_reg (const struct net_device *dev,int reg,u8 val) +{ +iowrite8 (val, (void __iomem *)(dev->base_addr + reg)); +} + +static int sp_probe (struct platform_device *pdev) +{ +int err, irq; +void __iomem *addr; +struct net_device *dev; +struct sja1000_priv *priv; +struct resource *res_mem, *res_irq; +struct sja1000_platform_data *pdata; + + pdata = pdev->dev.platform_data; +if (!pdata) { +dev_err (&pdev->dev,"No platform data provided!\n" ); + err = -ENODEV ; + goto exit; + } + + res_mem =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + res_irq =platform_get_resource (pdev,IORESOURCE_IRQ ,0 ); +if (!res_mem || !res_irq) { + err = -ENODEV ; + goto exit;Quoted 8 lines
drivers/net/can/sja1000/sja1000_platform.c line 75
Quoted 5 lines
drivers/net/can/sja1000/sja1000_platform.c new file +5
-0+ } + +if (!request_mem_region (res_mem->start, + res_mem->end - res_mem->start +1 , +DRV_NAME )) {
resource_size(res_mem)please, also for the other occurrences in this fileOK.
Quoted 9 lines
Quoted 9 lines
drivers/net/can/sja1000/sja1000_platform.c new file +9
-0+ err = -EBUSY ; + goto exit; + } + + addr =ioremap_nocache (res_mem->start, + res_mem->end - res_mem->start +1 ); +if (!addr) { + err = -ENOMEM ; + goto exit_release;Quoted 8 lines
drivers/net/can/sja1000/sja1000_platform.c line 89
Quoted 5 lines
drivers/net/can/sja1000/sja1000_platform.c new file +5
-0+ } + + irq = res_irq->start; +if (res_irq->flags &IRQF_TRIGGER_MASK ) +set_irq_type (irq, res_irq->flags &IRQF_TRIGGER_MASK );You shouldn't use
set_irq_typeon not yet requested irqs but instead pass the flags to the real driver and pass them inrequest_irq.
Quoted 1 line
Why? I would require an extra member in the struct
sja1000_priv.
You change a resource you do not own. What if request_irq returns with -EBUSY? You already screwed up any other potential user.
Sascha
Signature · 4 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
Re: [PATCH v2 5/7] [PATCH 5/8] can: SJA1000 generic platform bus driver
Quoted 5 lines · Sascha Hauer
Quoted 4 lines · Wolfgang Grandegger
Hi Sascha,
Quoted 1 line · Sascha Hauer
Hi Wolfgang,
[...}
Quoted 9 lines
Quoted 6 lines
Quoted 5 lines
drivers/net/can/sja1000/sja1000_platform.c line 89
Quoted 3 lines
drivers/net/can/sja1000/sja1000_platform.c new file +3
-0+ irq = res_irq->start; +if (res_irq->flags &IRQF_TRIGGER_MASK ) +set_irq_type (irq, res_irq->flags &IRQF_TRIGGER_MASK );You shouldn't use
set_irq_typeon not yet requested irqs but instead pass the flags to the real driver and pass them inrequest_irq.Why? I would require an extra member in the struct
sja1000_priv.You change a resource you do not own. What if
request_irqreturns with-EBUSY? You already screwed up any other potential user.
OK, I added irq_flags to struct sja1000_priv, which will then be used by the request_irq(). The driver must to set it appropriately, including IRQF_SHARED. This also fixes the problem, that drivers used IRQF_SHARED without reason.
Thanks,
Wolfgang.
PATCH v2 6/8 can: SJA1000 driver for EMS PCI cards
In reply to Wolfgang GrandeggerThe patch adds support for the one or two channel CPC-PCI and CPC-PCIe cards from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
--- drivers/net/can/Kconfig | 7 drivers/net/can/sja1000/Makefile | 1 drivers/net/can/sja1000/ems_pci.c | 328 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 336 insertions(+) create mode 100644 drivers/net/can/sja1000/ems_pci.c
drivers/net/can/Kconfig +7 -0
@@ -51,6 +51,13 @@ boards from Phytec (http://www.phytec.de) like the PCM027, PCM038. +config CAN_EMS_PCI + tristate "EMS CPC-PCI and CPC-PCIe Card" + depends on PCI && CAN_SJA1000 + ---help--- + This driver is for the one or two channel CPC-PCI and CPC-PCIe + cards from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de). + config CAN_DEBUG_DEVICES bool "CAN devices debugging messages" depends on CAN
drivers/net/can/sja1000/Makefile +1 -0
@@ -4,5 +4,6 @@ obj-$(CONFIG_CAN_SJA1000) += sja1000.o obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o +obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
drivers/net/can/sja1000/ems_pci.c new file +328 -0
328 lines not on this page · raw message
PATCH v2 7/8 can: SJA1000 driver for Kvaser PCI cards
In reply to Wolfgang GrandeggerThe patch adds support for the PCI cards: PCIcan and PCIcanx (1, 2 or 4 channel) from Kvaser (http://www.kvaser.com).
--- drivers/net/can/Kconfig | 7 drivers/net/can/sja1000/Makefile | 1 drivers/net/can/sja1000/kvaser_pci.c | 415 +++++++++++++++++++++++++++++++++++ 3 files changed, 423 insertions(+) create mode 100644 drivers/net/can/sja1000/kvaser_pci.c
drivers/net/can/Kconfig +7 -0
@@ -58,6 +58,13 @@ This driver is for the one or two channel CPC-PCI and CPC-PCIe cards from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de). +config CAN_KVASER_PCI + tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards" + depends on PCI && CAN_SJA1000 + ---help--- + This driver is for the the PCIcanx and PCIcan cards (1, 2 or + 4 channel) from Kvaser (http://www.kvaser.com). + config CAN_DEBUG_DEVICES bool "CAN devices debugging messages" depends on CAN
drivers/net/can/sja1000/Makefile +1 -0
@@ -5,5 +5,6 @@ obj-$(CONFIG_CAN_SJA1000) += sja1000.o obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o +obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
drivers/net/can/sja1000/kvaser_pci.c new file +415 -0
415 lines not on this page · raw message
Jonathan Corbet
maintainerRe: [PATCH v2 7/7] [PATCH 7/8] can: SJA1000 driver for Kvaser PCI cards
drivers/net/can/sja1000/kvaser_pci.c line 135
Quoted 8 lines · On Tue, 12 May 2009 11:28:04 +0200 Wolfgang Grandegger <[email protected]>…
The patch adds support for the PCI cards: PCIcan and PCIcanx (1, 2 or 4 channel) from Kvaser (http://www.kvaser.com).
drivers/net/can/sja1000/kvaser_pci.c new file +5
-0+static void kvaser_pci_disable_irq (struct net_device *dev) +{ +struct sja1000_priv *priv =netdev_priv (dev); +struct kvaser_pci *board = priv->priv; +u32 tmp;
I've seen certain reviewers getting grumpy about variables called "tmp" recently.
Quoted 5 lines
drivers/net/can/sja1000/kvaser_pci.c new file +5
-0+/* Disable interrupts from card */ + tmp =ioread32 (board->conf_addr +S5920_INTCSR ); + tmp &= ~INTCSR_ADDON_INTENABLE_M ; +iowrite32 (tmp, board->conf_addr +S5920_INTCSR ); +}
[...]
Quoted 5 lines
drivers/net/can/sja1000/kvaser_pci.c new file +5
-0+static int number_of_sja1000_chip (void __iomem *base_addr) +{ +u8 status; +int i; +
drivers/net/can/sja1000/kvaser_pci.c line 169
Quoted 10 lines
drivers/net/can/sja1000/kvaser_pci.c new file +10
-0+for (i =0 ; i <MAX_NO_OF_CHANNELS ; i++) { +/* reset chip */ +iowrite8 (MOD_RM , base_addr + + (i *KVASER_PCI_PORT_BYTES ) +REG_MOD ); + status =ioread8 (base_addr + + (i *KVASER_PCI_PORT_BYTES ) +REG_MOD ); +udelay (10 ); +/* check reset bit */ +if (!(status &MOD_RM )) +break ;
Why would you delay before checking status? It ain't gonna change.
Quoted 6 lines
drivers/net/can/sja1000/kvaser_pci.c new file +6
-0+ } + +return i; +} + +static void kvaser_pci_del_chan (struct net_device *dev)
drivers/net/can/sja1000/kvaser_pci.c line 185
Quoted 10 lines
drivers/net/can/sja1000/kvaser_pci.c new file +10
-0+{ +struct sja1000_priv *priv; +struct kvaser_pci *board; +int i; + +if (!dev) +return ; + priv =netdev_priv (dev); +if (!priv) +return ;
Can this happen?
Quoted 9 lines
drivers/net/can/sja1000/kvaser_pci.c new file +9
-0+ board = priv->priv; +if (!board) +return ; + +dev_info (&board->pci_dev->dev,"Removing device %s\n" , + dev->name); + +for (i =0 ; i < board->no_channels -1 ; i++) { +if (board->slave_dev[i]) {
drivers/net/can/sja1000/kvaser_pci.c line 204
Quoted 10 lines
drivers/net/can/sja1000/kvaser_pci.c new file +10
-0+dev_info (&board->pci_dev->dev,"Removing device %s\n" , + board->slave_dev[i]->name); +unregister_sja1000dev (board->slave_dev[i]); +free_sja1000dev (board->slave_dev[i]); + } + } +unregister_sja1000dev (dev); + +/* Disable PCI interrupts */ +kvaser_pci_disable_irq (dev);
It seems to me like you might want to disable interrupts *before* tearing down all that structure? What happens if it interrupts after the sja1000 layer has forgotten about it?
Quoted 13 lines
drivers/net/can/sja1000/kvaser_pci.c new file +13
-0+pci_iounmap (board->pci_dev, (void __iomem *)dev->base_addr); +pci_iounmap (board->pci_dev, board->conf_addr); +pci_iounmap (board->pci_dev, board->res_addr); + +free_sja1000dev (dev); +} + +static int kvaser_pci_add_chan (struct pci_dev *pdev,int channel, +struct net_device **master_dev, +void __iomem *conf_addr, +void __iomem *res_addr, +unsigned long base_addr) +{
drivers/net/can/sja1000/kvaser_pci.c line 228
Quoted 10 lines
drivers/net/can/sja1000/kvaser_pci.c new file +10
-0+struct net_device *dev; +struct sja1000_priv *priv; +struct kvaser_pci *board; +int err, init_step; + + dev =alloc_sja1000dev (sizeof (struct kvaser_pci )); +if (dev ==NULL ) +return -ENOMEM ; + + priv =netdev_priv (dev);
Here you don't have the !priv check.
Quoted 14 lines
drivers/net/can/sja1000/kvaser_pci.c new file +14
-0+ board = priv->priv; + + board->pci_dev = pdev; + board->channel = channel; + +/*S5920*/ + board->conf_addr = conf_addr; + +/*XILINX board wide address*/ + board->res_addr = res_addr; + +if (channel ==0 ) { + board->xilinx_ver = +ioread8 (board->res_addr +XILINX_VERINT ) >>4 ;
drivers/net/can/sja1000/kvaser_pci.c line 252
Quoted 10 lines
drivers/net/can/sja1000/kvaser_pci.c new file +10
-0+ init_step =2 ; + +/* Assert PTADR# - we're in passive mode so the other bits are +not important */ +iowrite32 (0x80808080UL , board->conf_addr +S5920_PTCR ); + +/* Disable interrupts from card */ +kvaser_pci_disable_irq (dev); +/* Enable interrupts from card */ +kvaser_pci_enable_irq (dev);
I'm sure there's a perfectly good reason for the disable/enable dance. Presumably the hardware needs it or it misbehaves? Worth commenting.
Quoted 64 lines
drivers/net/can/sja1000/kvaser_pci.c new file +64
-0+ }else { +struct sja1000_priv *master_priv =netdev_priv (*master_dev); +struct kvaser_pci *master_board = master_priv->priv; + master_board->slave_dev[channel -1 ] = dev; + master_board->no_channels = channel +1 ; + board->xilinx_ver = master_board->xilinx_ver; + } + + dev->base_addr = base_addr + channel *KVASER_PCI_PORT_BYTES ; + + priv->read_reg = kvaser_pci_read_reg; + priv->write_reg = kvaser_pci_write_reg; + + priv->can.clock.freq =KVASER_PCI_CAN_CLOCK ; + + priv->ocr =KVASER_PCI_OCR ; + priv->cdr =KVASER_PCI_CDR ; + +/* Register and setup interrupt handling */ + dev->irq = pdev->irq; + init_step =4 ; + +dev_info (&pdev->dev,"base_addr=%#lx conf_addr=%p irq=%d\n" , + dev->base_addr, board->conf_addr, dev->irq); + +SET_NETDEV_DEV (dev, &pdev->dev); + +/* Register SJA1000 device */ + err =register_sja1000dev (dev); +if (err) { +dev_err (&pdev->dev,"Registering device failed (err=%d)\n" , + err); + goto failure; + } + +if (channel ==0 ) + *master_dev = dev; + +return 0 ; + +failure: +kvaser_pci_del_chan (dev); +return err; +} + +static int __devinit kvaser_pci_init_one (struct pci_dev *pdev, +const struct pci_device_id *ent) +{ +int err; +struct net_device *master_dev =NULL ; +struct sja1000_priv *priv; +struct kvaser_pci *board; +int no_channels; +void __iomem *base_addr =NULL ; +void __iomem *conf_addr =NULL ; +void __iomem *res_addr =NULL ; +int i; + +dev_info (&pdev->dev,"initializing device %04x:%04x\n" , + pdev->vendor, pdev->device); + + err =pci_enable_device (pdev); +if (err) + goto failure;
drivers/net/can/sja1000/kvaser_pci.c line 326
Quoted 10 lines
drivers/net/can/sja1000/kvaser_pci.c new file +10
-0+ + err =pci_request_regions (pdev,DRV_NAME ); +if (err) + goto failure_release_pci; + +/*S5920*/ + conf_addr =pci_iomap (pdev,0 ,PCI_CONFIG_PORT_SIZE ); +if (conf_addr ==NULL ) { + err = -ENODEV ; + goto failure_iounmap;
Why go there? You know there's nothing to unmap.
Quoted 48 lines
drivers/net/can/sja1000/kvaser_pci.c new file +48
-0+ } + +/*XILINX board wide address*/ + res_addr =pci_iomap (pdev,2 ,PCI_PORT_XILINX_SIZE ); +if (res_addr ==NULL ) { + err = -ENOMEM ; + goto failure_iounmap; + } + + base_addr =pci_iomap (pdev,1 ,PCI_PORT_SIZE ); +if (base_addr ==NULL ) { + err = -ENOMEM ; + goto failure_iounmap; + } + + no_channels =number_of_sja1000_chip (base_addr); +if (no_channels ==0 ) { + err = -ENOMEM ; + goto failure_iounmap; + } + +for (i =0 ; i < no_channels; i++) { + err =kvaser_pci_add_chan (pdev, i, &master_dev, + conf_addr, res_addr, + (unsigned long )base_addr); +if (err) + goto failure_cleanup; + } + + priv =netdev_priv (master_dev); + board = priv->priv; + +dev_info (&pdev->dev,"xilinx version=%d number of channels=%d\n" , + board->xilinx_ver, board->no_channels); + +pci_set_drvdata (pdev, master_dev); +return 0 ; + +failure_cleanup: +kvaser_pci_del_chan (master_dev); + +failure_iounmap: +if (conf_addr ==NULL ) +pci_iounmap (pdev, conf_addr); +if (res_addr ==NULL ) +pci_iounmap (pdev, res_addr); +if (base_addr ==NULL ) +pci_iounmap (pdev, base_addr);
drivers/net/can/sja1000/kvaser_pci.c line 384
Quoted 10 lines
drivers/net/can/sja1000/kvaser_pci.c new file +10
-0+ +pci_release_regions (pdev); + +failure_release_pci: +pci_disable_device (pdev); + +failure: +return err; + +}
jon
Re: [PATCH v2 7/7] [PATCH 7/8] can: SJA1000 driver for Kvaser PCI cards
Quoted 6 lines · Jonathan Corbet
Quoted 2 lines · On Tue, 12 May 2009 11:28:04 +0200 Wolfgang Grandegger <[email protected]>…
The patch adds support for the PCI cards: PCIcan and PCIcanx (1, 2 or 4 channel) from Kvaser (http://www.kvaser.com).
Quoted 8 lines
drivers/net/can/sja1000/kvaser_pci.c line 135
Quoted 5 lines
drivers/net/can/sja1000/kvaser_pci.c new file +5
-0+static void kvaser_pci_disable_irq (struct net_device *dev) +{ +struct sja1000_priv *priv =netdev_priv (dev); +struct kvaser_pci *board = priv->priv; +u32 tmp;I've seen certain reviewers getting grumpy about variables called "tmp" recently.
No problem. I'm going to change the name to something more reasonable.
Quoted 17 lines
Quoted 5 lines
drivers/net/can/sja1000/kvaser_pci.c new file +5
-0+/* Disable interrupts from card */ + tmp =ioread32 (board->conf_addr +S5920_INTCSR ); + tmp &= ~INTCSR_ADDON_INTENABLE_M ; +iowrite32 (tmp, board->conf_addr +S5920_INTCSR ); +}[...]
Quoted 9 lines
drivers/net/can/sja1000/kvaser_pci.c new file +9
-0+static int number_of_sja1000_chip (void __iomem *base_addr) +{ +u8 status; +int i; + +for (i =0 ; i <MAX_NO_OF_CHANNELS ; i++) { +/* reset chip */ +iowrite8 (MOD_RM , base_addr + + (i *KVASER_PCI_PORT_BYTES ) +REG_MOD );
Quoted 8 lines
drivers/net/can/sja1000/kvaser_pci.c line 169
Quoted 6 lines
drivers/net/can/sja1000/kvaser_pci.c new file +6
-0+ status =ioread8 (base_addr + + (i *KVASER_PCI_PORT_BYTES ) +REG_MOD ); +udelay (10 ); +/* check reset bit */ +if (!(status &MOD_RM )) +break ;Why would you delay before checking status? It ain't gonna change.
Right.
Quoted 10 lines
Quoted 10 lines
drivers/net/can/sja1000/kvaser_pci.c new file +10
-0+ } + +return i; +} + +static void kvaser_pci_del_chan (struct net_device *dev) +{ +struct sja1000_priv *priv; +struct kvaser_pci *board; +int i;
Quoted 8 lines
drivers/net/can/sja1000/kvaser_pci.c line 185
Quoted 6 lines
drivers/net/can/sja1000/kvaser_pci.c new file +6
-0+ +if (!dev) +return ; + priv =netdev_priv (dev); +if (!priv) +return ;Can this happen?
No, it's a bug if it happens.
Quoted 15 lines
Quoted 15 lines
drivers/net/can/sja1000/kvaser_pci.c new file +15
-0+ board = priv->priv; +if (!board) +return ; + +dev_info (&board->pci_dev->dev,"Removing device %s\n" , + dev->name); + +for (i =0 ; i < board->no_channels -1 ; i++) { +if (board->slave_dev[i]) { +dev_info (&board->pci_dev->dev,"Removing device %s\n" , + board->slave_dev[i]->name); +unregister_sja1000dev (board->slave_dev[i]); +free_sja1000dev (board->slave_dev[i]); + } + }
Quoted 8 lines
drivers/net/can/sja1000/kvaser_pci.c line 204
Quoted 4 lines
drivers/net/can/sja1000/kvaser_pci.c new file +4
-0+unregister_sja1000dev (dev); + +/* Disable PCI interrupts */ +kvaser_pci_disable_irq (dev);It seems to me like you might want to disable interrupts *before* tearing down all that structure? What happens if it interrupts after the sja1000 layer has forgotten about it?
Right.
Quoted 45 lines
Quoted 13 lines
drivers/net/can/sja1000/kvaser_pci.c new file +13
-0+pci_iounmap (board->pci_dev, (void __iomem *)dev->base_addr); +pci_iounmap (board->pci_dev, board->conf_addr); +pci_iounmap (board->pci_dev, board->res_addr); + +free_sja1000dev (dev); +} + +static int kvaser_pci_add_chan (struct pci_dev *pdev,int channel, +struct net_device **master_dev, +void __iomem *conf_addr, +void __iomem *res_addr, +unsigned long base_addr) +{drivers/net/can/sja1000/kvaser_pci.c line 228
Quoted 10 lines
drivers/net/can/sja1000/kvaser_pci.c new file +10
-0+struct net_device *dev; +struct sja1000_priv *priv; +struct kvaser_pci *board; +int err, init_step; + + dev =alloc_sja1000dev (sizeof (struct kvaser_pci )); +if (dev ==NULL ) +return -ENOMEM ; + + priv =netdev_priv (dev);Here you don't have the !priv check.
Quoted 19 lines
drivers/net/can/sja1000/kvaser_pci.c new file +19
-0+ board = priv->priv; + + board->pci_dev = pdev; + board->channel = channel; + +/*S5920*/ + board->conf_addr = conf_addr; + +/*XILINX board wide address*/ + board->res_addr = res_addr; + +if (channel ==0 ) { + board->xilinx_ver = +ioread8 (board->res_addr +XILINX_VERINT ) >>4 ; + init_step =2 ; + +/* Assert PTADR# - we're in passive mode so the other bits are +not important */ +iowrite32 (0x80808080UL , board->conf_addr +S5920_PTCR );
Quoted 8 lines
drivers/net/can/sja1000/kvaser_pci.c line 252
Quoted 5 lines
drivers/net/can/sja1000/kvaser_pci.c new file +5
-0+ +/* Disable interrupts from card */ +kvaser_pci_disable_irq (dev); +/* Enable interrupts from card */ +kvaser_pci_enable_irq (dev);I'm sure there's a perfectly good reason for the disable/enable dance. Presumably the hardware needs it or it misbehaves? Worth commenting.
Hm, I think the hardware does not need it. I will check with original other.
Quoted 68 lines
Quoted 68 lines
drivers/net/can/sja1000/kvaser_pci.c new file +68
-0+ }else { +struct sja1000_priv *master_priv =netdev_priv (*master_dev); +struct kvaser_pci *master_board = master_priv->priv; + master_board->slave_dev[channel -1 ] = dev; + master_board->no_channels = channel +1 ; + board->xilinx_ver = master_board->xilinx_ver; + } + + dev->base_addr = base_addr + channel *KVASER_PCI_PORT_BYTES ; + + priv->read_reg = kvaser_pci_read_reg; + priv->write_reg = kvaser_pci_write_reg; + + priv->can.clock.freq =KVASER_PCI_CAN_CLOCK ; + + priv->ocr =KVASER_PCI_OCR ; + priv->cdr =KVASER_PCI_CDR ; + +/* Register and setup interrupt handling */ + dev->irq = pdev->irq; + init_step =4 ; + +dev_info (&pdev->dev,"base_addr=%#lx conf_addr=%p irq=%d\n" , + dev->base_addr, board->conf_addr, dev->irq); + +SET_NETDEV_DEV (dev, &pdev->dev); + +/* Register SJA1000 device */ + err =register_sja1000dev (dev); +if (err) { +dev_err (&pdev->dev,"Registering device failed (err=%d)\n" , + err); + goto failure; + } + +if (channel ==0 ) + *master_dev = dev; + +return 0 ; + +failure: +kvaser_pci_del_chan (dev); +return err; +} + +static int __devinit kvaser_pci_init_one (struct pci_dev *pdev, +const struct pci_device_id *ent) +{ +int err; +struct net_device *master_dev =NULL ; +struct sja1000_priv *priv; +struct kvaser_pci *board; +int no_channels; +void __iomem *base_addr =NULL ; +void __iomem *conf_addr =NULL ; +void __iomem *res_addr =NULL ; +int i; + +dev_info (&pdev->dev,"initializing device %04x:%04x\n" , + pdev->vendor, pdev->device); + + err =pci_enable_device (pdev); +if (err) + goto failure; + + err =pci_request_regions (pdev,DRV_NAME ); +if (err) + goto failure_release_pci;
Quoted 8 lines
drivers/net/can/sja1000/kvaser_pci.c line 326
Quoted 6 lines
drivers/net/can/sja1000/kvaser_pci.c new file +6
-0+ +/*S5920*/ + conf_addr =pci_iomap (pdev,0 ,PCI_CONFIG_PORT_SIZE ); +if (conf_addr ==NULL ) { + err = -ENODEV ; + goto failure_iounmap;Why go there? You know there's nothing to unmap.
OK.
I will resend a revised patch a.s.a.p.
Thanks,
Wolfgang.