Commit 0d66548a authored by Oliver Hartkopp's avatar Oliver Hartkopp Committed by David S. Miller
Browse files

[CAN]: Add PF_CAN core module



This patch adds the CAN core functionality but no protocols or drivers.
No protocol implementations are included here.  They come as separate
patches.  Protocol numbers are already in include/linux/can.h.
Signed-off-by: default avatarOliver Hartkopp <oliver.hartkopp@volkswagen.de>
Signed-off-by: default avatarUrs Thuermann <urs.thuermann@volkswagen.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cd05acfe
/*
* linux/can.h
*
* Definitions for CAN network layer (socket addr / CAN frame / CAN filter)
*
* Authors: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
* Urs Thuermann <urs.thuermann@volkswagen.de>
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
* All rights reserved.
*
* Send feedback to <socketcan-users@lists.berlios.de>
*
*/
#ifndef CAN_H
#define CAN_H
#include <linux/types.h>
#include <linux/socket.h>
/* controller area network (CAN) kernel definitions */
/* special address description flags for the CAN_ID */
#define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
#define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
#define CAN_ERR_FLAG 0x20000000U /* error frame */
/* valid bits in CAN ID for frame formats */
#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
/*
* Controller Area Network Identifier structure
*
* bit 0-28 : CAN identifier (11/29 bit)
* bit 29 : error frame flag (0 = data frame, 1 = error frame)
* bit 30 : remote transmission request flag (1 = rtr frame)
* bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
*/
typedef __u32 canid_t;
/*
* Controller Area Network Error Frame Mask structure
*
* bit 0-28 : error class mask (see include/linux/can/error.h)
* bit 29-31 : set to zero
*/
typedef __u32 can_err_mask_t;
/**
* struct can_frame - basic CAN frame structure
* @can_id: the CAN ID of the frame and CAN_*_FLAG flags, see above.
* @can_dlc: the data length field of the CAN frame
* @data: the CAN frame payload.
*/
struct can_frame {
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
__u8 can_dlc; /* data length code: 0 .. 8 */
__u8 data[8] __attribute__((aligned(8)));
};
/* particular protocols of the protocol family PF_CAN */
#define CAN_RAW 1 /* RAW sockets */
#define CAN_BCM 2 /* Broadcast Manager */
#define CAN_TP16 3 /* VAG Transport Protocol v1.6 */
#define CAN_TP20 4 /* VAG Transport Protocol v2.0 */
#define CAN_MCNET 5 /* Bosch MCNet */
#define CAN_ISOTP 6 /* ISO 15765-2 Transport Protocol */
#define CAN_NPROTO 7
#define SOL_CAN_BASE 100
/**
* struct sockaddr_can - the sockaddr structure for CAN sockets
* @can_family: address family number AF_CAN.
* @can_ifindex: CAN network interface index.
* @can_addr: protocol specific address information
*/
struct sockaddr_can {
sa_family_t can_family;
int can_ifindex;
union {
/* transport protocol class address information (e.g. ISOTP) */
struct { canid_t rx_id, tx_id; } tp;
/* reserved for future CAN protocols address information */
} can_addr;
};
/**
* struct can_filter - CAN ID based filter in can_register().
* @can_id: relevant bits of CAN ID which are not masked out.
* @can_mask: CAN mask (see description)
*
* Description:
* A filter matches, when
*
* <received_can_id> & mask == can_id & mask
*
* The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
* filter for error frames (CAN_ERR_FLAG bit set in mask).
*/
struct can_filter {
canid_t can_id;
canid_t can_mask;
};
#define CAN_INV_FILTER 0x20000000U /* to be set in can_filter.can_id */
#endif /* CAN_H */
/*
* linux/can/core.h
*
* Protoypes and definitions for CAN protocol modules using the PF_CAN core
*
* Authors: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
* Urs Thuermann <urs.thuermann@volkswagen.de>
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
* All rights reserved.
*
* Send feedback to <socketcan-users@lists.berlios.de>
*
*/
#ifndef CAN_CORE_H
#define CAN_CORE_H
#include <linux/can.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#define CAN_VERSION "20071116"
/* increment this number each time you change some user-space interface */
#define CAN_ABI_VERSION "8"
#define CAN_VERSION_STRING "rev " CAN_VERSION " abi " CAN_ABI_VERSION
#define DNAME(dev) ((dev) ? (dev)->name : "any")
/**
* struct can_proto - CAN protocol structure
* @type: type argument in socket() syscall, e.g. SOCK_DGRAM.
* @protocol: protocol number in socket() syscall.
* @capability: capability needed to open the socket, or -1 for no restriction.
* @ops: pointer to struct proto_ops for sock->ops.
* @prot: pointer to struct proto structure.
*/
struct can_proto {
int type;
int protocol;
int capability;
struct proto_ops *ops;
struct proto *prot;
};
/* function prototypes for the CAN networklayer core (af_can.c) */
extern int can_proto_register(struct can_proto *cp);
extern void can_proto_unregister(struct can_proto *cp);
extern int can_rx_register(struct net_device *dev, canid_t can_id,
canid_t mask,
void (*func)(struct sk_buff *, void *),
void *data, char *ident);
extern void can_rx_unregister(struct net_device *dev, canid_t can_id,
canid_t mask,
void (*func)(struct sk_buff *, void *),
void *data);
extern int can_send(struct sk_buff *skb, int loop);
#endif /* CAN_CORE_H */
/*
* linux/can/error.h
*
* Definitions of the CAN error frame to be filtered and passed to the user.
*
* Author: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
* All rights reserved.
*
* Send feedback to <socketcan-users@lists.berlios.de>
*
*/
#ifndef CAN_ERROR_H
#define CAN_ERROR_H
#define CAN_ERR_DLC 8 /* dlc for error frames */
/* error class (mask) in can_id */
#define CAN_ERR_TX_TIMEOUT 0x00000001U /* TX timeout (by netdevice driver) */
#define CAN_ERR_LOSTARB 0x00000002U /* lost arbitration / data[0] */
#define CAN_ERR_CRTL 0x00000004U /* controller problems / data[1] */
#define CAN_ERR_PROT 0x00000008U /* protocol violations / data[2..3] */
#define CAN_ERR_TRX 0x00000010U /* transceiver status / data[4] */
#define CAN_ERR_ACK 0x00000020U /* received no ACK on transmission */
#define CAN_ERR_BUSOFF 0x00000040U /* bus off */
#define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */
#define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */
/* arbitration lost in bit ... / data[0] */
#define CAN_ERR_LOSTARB_UNSPEC 0x00 /* unspecified */
/* else bit number in bitstream */
/* error status of CAN-controller / data[1] */
#define CAN_ERR_CRTL_UNSPEC 0x00 /* unspecified */
#define CAN_ERR_CRTL_RX_OVERFLOW 0x01 /* RX buffer overflow */
#define CAN_ERR_CRTL_TX_OVERFLOW 0x02 /* TX buffer overflow */
#define CAN_ERR_CRTL_RX_WARNING 0x04 /* reached warning level for RX errors */
#define CAN_ERR_CRTL_TX_WARNING 0x08 /* reached warning level for TX errors */
#define CAN_ERR_CRTL_RX_PASSIVE 0x10 /* reached error passive status RX */
#define CAN_ERR_CRTL_TX_PASSIVE 0x20 /* reached error passive status TX */
/* (at least one error counter exceeds */
/* the protocol-defined level of 127) */
/* error in CAN protocol (type) / data[2] */
#define CAN_ERR_PROT_UNSPEC 0x00 /* unspecified */
#define CAN_ERR_PROT_BIT 0x01 /* single bit error */
#define CAN_ERR_PROT_FORM 0x02 /* frame format error */
#define CAN_ERR_PROT_STUFF 0x04 /* bit stuffing error */
#define CAN_ERR_PROT_BIT0 0x08 /* unable to send dominant bit */
#define CAN_ERR_PROT_BIT1 0x10 /* unable to send recessive bit */
#define CAN_ERR_PROT_OVERLOAD 0x20 /* bus overload */
#define CAN_ERR_PROT_ACTIVE 0x40 /* active error announcement */
#define CAN_ERR_PROT_TX 0x80 /* error occured on transmission */
/* error in CAN protocol (location) / data[3] */
#define CAN_ERR_PROT_LOC_UNSPEC 0x00 /* unspecified */
#define CAN_ERR_PROT_LOC_SOF 0x03 /* start of frame */
#define CAN_ERR_PROT_LOC_ID28_21 0x02 /* ID bits 28 - 21 (SFF: 10 - 3) */
#define CAN_ERR_PROT_LOC_ID20_18 0x06 /* ID bits 20 - 18 (SFF: 2 - 0 )*/
#define CAN_ERR_PROT_LOC_SRTR 0x04 /* substitute RTR (SFF: RTR) */
#define CAN_ERR_PROT_LOC_IDE 0x05 /* identifier extension */
#define CAN_ERR_PROT_LOC_ID17_13 0x07 /* ID bits 17-13 */
#define CAN_ERR_PROT_LOC_ID12_05 0x0F /* ID bits 12-5 */
#define CAN_ERR_PROT_LOC_ID04_00 0x0E /* ID bits 4-0 */
#define CAN_ERR_PROT_LOC_RTR 0x0C /* RTR */
#define CAN_ERR_PROT_LOC_RES1 0x0D /* reserved bit 1 */
#define CAN_ERR_PROT_LOC_RES0 0x09 /* reserved bit 0 */
#define CAN_ERR_PROT_LOC_DLC 0x0B /* data length code */
#define CAN_ERR_PROT_LOC_DATA 0x0A /* data section */
#define CAN_ERR_PROT_LOC_CRC_SEQ 0x08 /* CRC sequence */
#define CAN_ERR_PROT_LOC_CRC_DEL 0x18 /* CRC delimiter */
#define CAN_ERR_PROT_LOC_ACK 0x19 /* ACK slot */
#define CAN_ERR_PROT_LOC_ACK_DEL 0x1B /* ACK delimiter */
#define CAN_ERR_PROT_LOC_EOF 0x1A /* end of frame */
#define CAN_ERR_PROT_LOC_INTERM 0x12 /* intermission */
/* error status of CAN-transceiver / data[4] */
/* CANH CANL */
#define CAN_ERR_TRX_UNSPEC 0x00 /* 0000 0000 */
#define CAN_ERR_TRX_CANH_NO_WIRE 0x04 /* 0000 0100 */
#define CAN_ERR_TRX_CANH_SHORT_TO_BAT 0x05 /* 0000 0101 */
#define CAN_ERR_TRX_CANH_SHORT_TO_VCC 0x06 /* 0000 0110 */
#define CAN_ERR_TRX_CANH_SHORT_TO_GND 0x07 /* 0000 0111 */
#define CAN_ERR_TRX_CANL_NO_WIRE 0x40 /* 0100 0000 */
#define CAN_ERR_TRX_CANL_SHORT_TO_BAT 0x50 /* 0101 0000 */
#define CAN_ERR_TRX_CANL_SHORT_TO_VCC 0x60 /* 0110 0000 */
#define CAN_ERR_TRX_CANL_SHORT_TO_GND 0x70 /* 0111 0000 */
#define CAN_ERR_TRX_CANL_SHORT_TO_CANH 0x80 /* 1000 0000 */
/* controller specific additional information / data[5..7] */
#endif /* CAN_ERROR_H */
......@@ -218,6 +218,7 @@ endmenu
endmenu
source "net/ax25/Kconfig"
source "net/can/Kconfig"
source "net/irda/Kconfig"
source "net/bluetooth/Kconfig"
source "net/rxrpc/Kconfig"
......
......@@ -34,6 +34,7 @@ obj-$(CONFIG_LAPB) += lapb/
obj-$(CONFIG_NETROM) += netrom/
obj-$(CONFIG_ROSE) += rose/
obj-$(CONFIG_AX25) += ax25/
obj-$(CONFIG_CAN) += can/
obj-$(CONFIG_IRDA) += irda/
obj-$(CONFIG_BT) += bluetooth/
obj-$(CONFIG_SUNRPC) += sunrpc/
......
#
# Controller Area Network (CAN) network layer core configuration
#
menuconfig CAN
depends on NET
tristate "CAN bus subsystem support"
---help---
Controller Area Network (CAN) is a slow (up to 1Mbit/s) serial
communications protocol which was developed by Bosch in
1991, mainly for automotive, but now widely used in marine
(NMEA2000), industrial, and medical applications.
More information on the CAN network protocol family PF_CAN
is contained in <Documentation/networking/can.txt>.
If you want CAN support you should say Y here and also to the
specific driver for your controller(s) below.
#
# Makefile for the Linux Controller Area Network core.
#
obj-$(CONFIG_CAN) += can.o
can-objs := af_can.o proc.o
This diff is collapsed.
/*
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Volkswagen nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* Alternatively, provided that this notice is retained in full, this
* software may be distributed under the terms of the GNU General
* Public License ("GPL") version 2, in which case the provisions of the
* GPL apply INSTEAD OF those given above.
*
* The provided data structures and external interfaces from this code
* are not restricted to be used by modules with a GPL compatible license.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* Send feedback to <socketcan-users@lists.berlios.de>
*
*/
#ifndef AF_CAN_H
#define AF_CAN_H
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/list.h>
#include <linux/rcupdate.h>
#include <linux/can.h>
/* af_can rx dispatcher structures */
struct receiver {
struct hlist_node list;
struct rcu_head rcu;
canid_t can_id;
canid_t mask;
unsigned long matches;
void (*func)(struct sk_buff *, void *);
void *data;
char *ident;
};
enum { RX_ERR, RX_ALL, RX_FIL, RX_INV, RX_EFF, RX_MAX };
struct dev_rcv_lists {
struct hlist_node list;
struct rcu_head rcu;
struct net_device *dev;
struct hlist_head rx[RX_MAX];
struct hlist_head rx_sff[0x800];
int remove_on_zero_entries;
int entries;
};
/* statistic structures */
/* can be reset e.g. by can_init_stats() */
struct s_stats {
unsigned long jiffies_init;
unsigned long rx_frames;
unsigned long tx_frames;
unsigned long matches;
unsigned long total_rx_rate;
unsigned long total_tx_rate;
unsigned long total_rx_match_ratio;
unsigned long current_rx_rate;
unsigned long current_tx_rate;
unsigned long current_rx_match_ratio;
unsigned long max_rx_rate;
unsigned long max_tx_rate;
unsigned long max_rx_match_ratio;
unsigned long rx_frames_delta;
unsigned long tx_frames_delta;
unsigned long matches_delta;
};
/* persistent statistics */
struct s_pstats {
unsigned long stats_reset;
unsigned long user_reset;
unsigned long rcv_entries;
unsigned long rcv_entries_max;
};
/* function prototypes for the CAN networklayer procfs (proc.c) */
extern void can_init_proc(void);
extern void can_remove_proc(void);
extern void can_stat_update(unsigned long data);
/* structures and variables from af_can.c needed in proc.c for reading */
extern struct timer_list can_stattimer; /* timer for statistics update */
extern struct s_stats can_stats; /* packet statistics */
extern struct s_pstats can_pstats; /* receive list statistics */
extern struct hlist_head can_rx_dev_list; /* rx dispatcher structures */
#endif /* AF_CAN_H */
/*
* proc.c - procfs support for Protocol family CAN core module
*
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Volkswagen nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* Alternatively, provided that this notice is retained in full, this
* software may be distributed under the terms of the GNU General
* Public License ("GPL") version 2, in which case the provisions of the
* GPL apply INSTEAD OF those given above.
*
* The provided data structures and external interfaces from this code
* are not restricted to be used by modules with a GPL compatible license.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* Send feedback to <socketcan-users@lists.berlios.de>
*
*/
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/list.h>
#include <linux/rcupdate.h>
#include <linux/can/core.h>
#include "af_can.h"
/*
* proc filenames for the PF_CAN core
*/
#define CAN_PROC_VERSION "version"
#define CAN_PROC_STATS "stats"
#define CAN_PROC_RESET_STATS "reset_stats"
#define CAN_PROC_RCVLIST_ALL "rcvlist_all"
#define CAN_PROC_RCVLIST_FIL "rcvlist_fil"
#define CAN_PROC_RCVLIST_INV "rcvlist_inv"
#define CAN_PROC_RCVLIST_SFF "rcvlist_sff"
#define CAN_PROC_RCVLIST_EFF "rcvlist_eff"
#define CAN_PROC_RCVLIST_ERR "rcvlist_err"
static struct proc_dir_entry *can_dir;
static struct proc_dir_entry *pde_version;
static struct proc_dir_entry *pde_stats;
static struct proc_dir_entry *pde_reset_stats;
static struct proc_dir_entry *pde_rcvlist_all;
static struct proc_dir_entry *pde_rcvlist_fil;
static struct proc_dir_entry *pde_rcvlist_inv;
static struct proc_dir_entry *pde_rcvlist_sff;
static struct proc_dir_entry *pde_rcvlist_eff;
static struct proc_dir_entry *pde_rcvlist_err;
static int user_reset;
static const char rx_list_name[][8] = {
[RX_ERR] = "rx_err",
[RX_ALL] = "rx_all",
[RX_FIL] = "rx_fil",
[RX_INV] = "rx_inv",
[RX_EFF] = "rx_eff",
};
/*
* af_can statistics stuff
*/
static void can_init_stats(void)
{
/*
* This memset function is called from a timer context (when
* can_stattimer is active which is the default) OR in a process
* context (reading the proc_fs when can_stattimer is disabled).
*/
memset(&can_stats, 0, sizeof(can_stats));
can_stats.jiffies_init = jiffies;
can_pstats.stats_reset++;
if (user_reset) {
user_reset = 0;
can_pstats.user_reset++;
}
}
static unsigned long calc_rate(unsigned long oldjif, unsigned long newjif,
unsigned long count)
{
unsigned long rate;
if (oldjif == newjif)
return 0;
/* see can_stat_update() - this should NEVER happen! */
if (count > (ULONG_MAX / HZ)) {
printk(KERN_ERR "can: calc_rate: count exceeded! %ld\n",
count);
return 99999999;
}
rate = (count * HZ) / (newjif - oldjif);
return rate;
}
void can_stat_update(unsigned long data)
{
unsigned long j = jiffies; /* snapshot */
/* restart counting in timer context on user request */
if (user_reset)
can_init_stats();
/* restart counting on jiffies overflow */
if (j < can_stats.jiffies_init)
can_init_stats();
/* prevent overflow in calc_rate() */
if (can_stats.rx_frames > (ULONG_MAX / HZ))
can_init_stats();
/* prevent overflow in calc_rate() */
if (can_stats.tx_frames > (ULONG_MAX / HZ))
can_init_stats();
/* matches overflow - very improbable */
if (can_stats.matches > (ULONG_MAX / 100))
can_init_stats();
/* calc total values */
if (can_stats.rx_frames)
can_stats.total_rx_match_ratio = (can_stats.matches * 100) /
can_stats.rx_frames;
can_stats.total_tx_rate = calc_rate(can_stats.jiffies_init, j,
can_stats.tx_frames);
can_stats.total_rx_rate = calc_rate(can_stats.jiffies_init, j,
can_stats.rx_frames);
/* calc current values */
if (can_stats.rx_frames_delta)
can_stats.current_rx_match_ratio =
(can_stats.matches_delta * 100) /
can_stats.rx_frames_delta;
can_stats.current_tx_rate = calc_rate(0, HZ, can_stats.tx_frames_delta);
can_stats.current_rx_rate = calc_rate(0, HZ, can_stats.rx_frames_delta);
/* check / update maximum values */
if (can_stats.max_tx_rate < can_stats.current_tx_rate)
can_stats.max_tx_rate = can_stats.current_tx_rate;
if (can_stats.max_rx_rate < can_stats.current_rx_rate)
can_stats.max_rx_rate = can_stats.current_rx_rate;
if (can_stats.max_rx_match_ratio < can_stats.current_rx_match_ratio)
can_stats.max_rx_match_ratio = can_stats.current_rx_match_ratio;
/* clear values for 'current rate' calculation */
can_stats.tx_frames_delta = 0;
can_stats.rx_frames_delta = 0;
can_stats.matches_delta = 0;
/* restart timer (one second) */
mod_timer(&can_stattimer, round_jiffies(jiffies + HZ));
}
/*
* proc read functions
*
* From known use-cases we expect about 10 entries in a receive list to be
* printed in the proc_fs. So PAGE_SIZE is definitely enough space here.
*
*/
static int can_print_rcvlist(char *page, int len, struct hlist_head *rx_list,
</