#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
-#include <linux/hrtimer.h>
-#endif
#include <linux/list.h>
#include <linux/proc_fs.h>
#include <linux/uio.h>
#include <linux/can/core.h>
#include <linux/can/bcm.h>
#include <net/sock.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
-#include <net/net_namespace.h>
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
#include "compat.h"
-#endif
#include <linux/can/version.h> /* for RCSID. Removed by mkpatch script */
RCSID("$Id$");
int flags;
unsigned long frames_abs, frames_filtered;
struct timeval ival1, ival2;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- struct hrtimer timer, thrtimer;
- ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
-#else
struct timer_list timer, thrtimer;
struct timeval rx_stamp;
unsigned long j_ival1, j_ival2, j_lastmsg;
-#endif
int rx_ifindex;
int count;
int nframes;
#define OPSIZ sizeof(struct bcm_op)
#define MHSIZ sizeof(struct bcm_msg_head)
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
/*
* rounded_tv2jif - calculate jiffies from timeval including optional up
* @tv: pointer to timeval
return jif + sec * HZ;
}
-#endif
/*
* procfs functions
len += snprintf(page + len, PAGE_SIZE - len, "[%d]%c ",
op->nframes,
(op->flags & RX_CHECK_DLC)?'d':' ');
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- if (op->kt_ival1.tv64)
- len += snprintf(page + len, PAGE_SIZE - len,
- "timeo=%lld ",
- (long long)
- ktime_to_us(op->kt_ival1));
-
- if (op->kt_ival2.tv64)
- len += snprintf(page + len, PAGE_SIZE - len,
- "thr=%lld ",
- (long long)
- ktime_to_us(op->kt_ival2));
-#else
if (op->j_ival1)
len += snprintf(page + len, PAGE_SIZE - len,
"timeo=%ld ", op->j_ival1);
if (op->j_ival2)
len += snprintf(page + len, PAGE_SIZE - len,
"thr=%ld ", op->j_ival2);
-#endif
len += snprintf(page + len, PAGE_SIZE - len,
"# recv %ld (%ld) => reduction: ",
op->can_id, bcm_proc_getifname(op->ifindex),
op->nframes);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- if (op->kt_ival1.tv64)
- len += snprintf(page + len, PAGE_SIZE - len, "t1=%lld ",
- (long long) ktime_to_us(op->kt_ival1));
-
- if (op->kt_ival2.tv64)
- len += snprintf(page + len, PAGE_SIZE - len, "t2=%lld ",
- (long long) ktime_to_us(op->kt_ival2));
-#else
if (op->j_ival1)
len += snprintf(page + len, PAGE_SIZE - len, "t1=%ld ",
op->j_ival1);
if (op->j_ival2)
len += snprintf(page + len, PAGE_SIZE - len, "t2=%ld ",
op->j_ival2);
-#endif
len += snprintf(page + len, PAGE_SIZE - len, "# sent %ld\n",
op->frames_abs);
if (head->nframes) {
/* can_frames starting here */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- firstframe = (struct can_frame *)skb_tail_pointer(skb);
-#else
firstframe = (struct can_frame *)skb->tail;
-#endif
memcpy(skb_put(skb, datalen), frames, datalen);
if (has_timestamp) {
/* restore rx timestamp */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- skb->tstamp = op->rx_stamp;
-#else
skb_set_timestamp(skb, &op->rx_stamp);
-#endif
}
/*
/*
* bcm_tx_timeout_handler - performes cyclic CAN frame transmissions
*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
-static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
-{
- struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
- enum hrtimer_restart ret = HRTIMER_NORESTART;
-
- if (op->kt_ival1.tv64 && (op->count > 0)) {
-#else
static void bcm_tx_timeout_handler(unsigned long data)
{
struct bcm_op *op = (struct bcm_op *)data;
if (op->j_ival1 && (op->count > 0)) {
-#endif
op->count--;
if (!op->count && (op->flags & TX_COUNTEVT)) {
}
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- if (op->kt_ival1.tv64 && (op->count > 0)) {
-
- /* send (next) frame */
- bcm_can_tx(op);
- hrtimer_forward(hrtimer, ktime_get(), op->kt_ival1);
- ret = HRTIMER_RESTART;
-
- } else {
- if (op->kt_ival2.tv64) {
-
- /* send (next) frame */
- bcm_can_tx(op);
- hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
- ret = HRTIMER_RESTART;
- }
- }
-
- return ret;
-#else
if (op->j_ival1 && (op->count > 0)) {
/* send (next) frame */
}
return;
-#endif
}
/*
{
struct bcm_msg_head head;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
op->j_lastmsg = jiffies;
-#endif
/* update statistics */
op->frames_filtered++;
bcm_send_to_user(op, &head, data, 1);
}
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,25)
-/* is part of linux/hrtimer.h since 2.6.26 */
-static inline int hrtimer_callback_running(struct hrtimer *timer)
-{
- return timer->state & HRTIMER_STATE_CALLBACK;
-}
-#endif
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,22)
-static inline s64 ktime_us_delta(const ktime_t later, const ktime_t earlier)
-{
- return ktime_to_us(ktime_sub(later, earlier));
-}
-#endif
/*
* bcm_rx_update_and_send - process a detected relevant receive content change
* 1. update the last received data
struct can_frame *lastdata,
struct can_frame *rxdata)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- memcpy(lastdata, rxdata, CFSIZ);
-
- /* mark as used */
- lastdata->can_dlc |= RX_RECV;
-
- /* throtteling mode inactive OR data update already on the run ? */
- if (!op->kt_ival2.tv64 || hrtimer_callback_running(&op->thrtimer)) {
- /* send RX_CHANGED to the user immediately */
- bcm_rx_changed(op, rxdata);
- return;
- }
-
- if (hrtimer_active(&op->thrtimer)) {
- /* mark as 'throttled' */
- lastdata->can_dlc |= RX_THR;
- return;
- }
-
- if (!op->kt_lastmsg.tv64) {
- /* send first RX_CHANGED to the user immediately */
- bcm_rx_changed(op, rxdata);
- op->kt_lastmsg = ktime_get();
- return;
- }
-
- if (ktime_us_delta(ktime_get(), op->kt_lastmsg) <
- ktime_to_us(op->kt_ival2)) {
- /* mark as 'throttled' and start timer */
- lastdata->can_dlc |= RX_THR;
- hrtimer_start(&op->thrtimer,
- ktime_add(op->kt_lastmsg, op->kt_ival2),
- HRTIMER_MODE_ABS);
- return;
- }
-
- /* the gap was that big, that throttling was not needed here */
- bcm_rx_changed(op, rxdata);
- op->kt_lastmsg = ktime_get();
-#else
unsigned long nexttx = op->j_lastmsg + op->j_ival2;
memcpy(lastdata, rxdata, CFSIZ);
/* send RX_CHANGED to the user immediately */
bcm_rx_changed(op, rxdata);
}
-#endif
}
/*
if (op->flags & RX_NO_AUTOTIMER)
return;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- if (op->kt_ival1.tv64)
- hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL);
-#else
if (op->j_ival1)
mod_timer(&op->timer, jiffies + op->j_ival1);
-#endif
}
/*
* bcm_rx_timeout_handler - when the (cyclic) CAN frame receiption timed out
*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
-static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
-{
- struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
-#else
static void bcm_rx_timeout_handler(unsigned long data)
{
struct bcm_op *op = (struct bcm_op *)data;
-#endif
struct bcm_msg_head msg_head;
msg_head.opcode = RX_TIMEOUT;
/* clear received can_frames to indicate 'nothing received' */
memset(op->last_frames, 0, op->nframes * CFSIZ);
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
-
- return HRTIMER_NORESTART;
-#endif
}
/*
* bcm_rx_thr_handler - the time for blocked content updates is over now:
* Check for throttled data and send it to the userspace
*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
-static enum hrtimer_restart bcm_rx_thr_handler(struct hrtimer *hrtimer)
-{
- struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer);
-
- if (bcm_rx_thr_flush(op)) {
- hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
- return HRTIMER_RESTART;
- } else {
- /* rearm throttle handling */
- op->kt_lastmsg = ktime_set(0, 0);
- return HRTIMER_NORESTART;
- }
-}
-#else
static void bcm_rx_thr_handler(unsigned long data)
{
struct bcm_op *op = (struct bcm_op *)data;
op->thrtimer.expires = 0;
}
}
-#endif
/*
* bcm_rx_handler - handle a CAN frame receiption
int i;
/* disable timeout */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- hrtimer_cancel(&op->timer);
-#else
del_timer(&op->timer);
-#endif
if (skb->len == sizeof(rxframe)) {
memcpy(&rxframe, skb->data, sizeof(rxframe));
/* save rx timestamp */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- op->rx_stamp = skb->tstamp;
-#else
skb_get_timestamp(skb, &op->rx_stamp);
-#endif
/* save originator for recvfrom() */
op->rx_ifindex = skb->dev->ifindex;
/* update statistics */
static void bcm_remove_op(struct bcm_op *op)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- hrtimer_cancel(&op->timer);
- hrtimer_cancel(&op->thrtimer);
-#else
del_timer(&op->timer);
del_timer(&op->thrtimer);
-#endif
if ((op->frames) && (op->frames != &op->sframe))
kfree(op->frames);
op->ifindex = ifindex;
/* initialize uninitialized (kzalloc) structure */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- op->timer.function = bcm_tx_timeout_handler;
-
- /* currently unused in tx_ops */
- hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-#else
setup_timer(&op->timer, bcm_tx_timeout_handler,
(unsigned long)op);
/* currently unused in tx_ops */
init_timer(&op->thrtimer);
-#endif
/* add this bcm_op to the list of the tx_ops */
list_add(&op->list, &bo->tx_ops);
op->currframe = 0;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- if (op->flags & SETTIMER) {
- /* set timer values */
- op->count = msg_head->count;
- op->ival1 = msg_head->ival1;
- op->ival2 = msg_head->ival2;
- op->kt_ival1 = timeval_to_ktime(msg_head->ival1);
- op->kt_ival2 = timeval_to_ktime(msg_head->ival2);
-
- /* disable an active timer due to zero values? */
- if (!op->kt_ival1.tv64 && !op->kt_ival2.tv64)
- hrtimer_cancel(&op->timer);
- }
-
- if ((op->flags & STARTTIMER) &&
- ((op->kt_ival1.tv64 && op->count) || op->kt_ival2.tv64)) {
-
- /* spec: send can_frame when starting timer */
- op->flags |= TX_ANNOUNCE;
-
- if (op->kt_ival1.tv64 && (op->count > 0)) {
- /* op->count-- is done in bcm_tx_timeout_handler */
- hrtimer_start(&op->timer, op->kt_ival1,
- HRTIMER_MODE_REL);
- } else
- hrtimer_start(&op->timer, op->kt_ival2,
- HRTIMER_MODE_REL);
- }
-#else
if (op->flags & SETTIMER) {
/* set timer values */
op->count = msg_head->count;
} else
mod_timer(&op->timer, jiffies + op->j_ival2);
}
-#endif
if (op->flags & TX_ANNOUNCE)
bcm_can_tx(op);
op->ifindex = ifindex;
/* initialize uninitialized (kzalloc) structure */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- op->timer.function = bcm_rx_timeout_handler;
-
- hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- op->thrtimer.function = bcm_rx_thr_handler;
-#else
setup_timer(&op->timer, bcm_rx_timeout_handler,
(unsigned long)op);
/* mark disabled timer */
op->thrtimer.expires = 0;
-#endif
/* add this bcm_op to the list of the rx_ops */
list_add(&op->list, &bo->rx_ops);
if (op->flags & RX_RTR_FRAME) {
/* no timers in RTR-mode */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- hrtimer_cancel(&op->thrtimer);
- hrtimer_cancel(&op->timer);
-#else
del_timer(&op->thrtimer);
del_timer(&op->timer);
-#endif
/*
* funny feature in RX(!)_SETUP only for RTR-mode:
op->frames[0].can_id = op->can_id & ~CAN_RTR_FLAG;
} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- if (op->flags & SETTIMER) {
-
- /* set timer value */
- op->ival1 = msg_head->ival1;
- op->ival2 = msg_head->ival2;
- op->kt_ival1 = timeval_to_ktime(msg_head->ival1);
- op->kt_ival2 = timeval_to_ktime(msg_head->ival2);
-
- /* disable an active timer due to zero value? */
- if (!op->kt_ival1.tv64)
- hrtimer_cancel(&op->timer);
-
- /*
- * In any case cancel the throttle timer, flush
- * potentially blocked msgs and reset throttle handling
- */
- op->kt_lastmsg = ktime_set(0, 0);
- hrtimer_cancel(&op->thrtimer);
- bcm_rx_thr_flush(op);
- }
-
- if ((op->flags & STARTTIMER) && op->kt_ival1.tv64)
- hrtimer_start(&op->timer, op->kt_ival1,
- HRTIMER_MODE_REL);
-#else
if (op->flags & SETTIMER) {
/* set timer value */
if ((op->flags & STARTTIMER) && op->j_ival1)
mod_timer(&op->timer, jiffies + op->j_ival1);
-#endif
}
/* now we can register for can_ids, if we added a new bcm_op */
struct bcm_op *op;
int notify_enodev = 0;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
- if (!net_eq(dev_net(dev), &init_net))
- return NOTIFY_DONE;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
- if (dev->nd_net != &init_net)
- return NOTIFY_DONE;
-#endif
-
if (dev->type != ARPHRD_CAN)
return NOTIFY_DONE;
}
/* create /proc/net/can-bcm directory */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
- proc_dir = proc_mkdir("can-bcm", init_net.proc_net);
-#else
proc_dir = proc_mkdir("can-bcm", proc_net);
-#endif
if (proc_dir)
proc_dir->owner = THIS_MODULE;
can_proto_unregister(&bcm_can_proto);
if (proc_dir)
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
- proc_net_remove(&init_net, "can-bcm");
-#else
proc_net_remove("can-bcm");
-#endif
}
module_init(bcm_module_init);
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
#include <linux/hrtimer.h>
-#endif
#include <linux/list.h>
#include <linux/proc_fs.h>
#include <linux/uio.h>
int flags;
unsigned long frames_abs, frames_filtered;
struct timeval ival1, ival2;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
struct hrtimer timer, thrtimer;
ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
-#else
- struct timer_list timer, thrtimer;
- struct timeval rx_stamp;
- unsigned long j_ival1, j_ival2, j_lastmsg;
-#endif
int rx_ifindex;
int count;
int nframes;
static struct proc_dir_entry *proc_dir;
struct bcm_sock {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
struct sock sk;
-#else
- struct sock *sk;
-#endif
int bound;
int ifindex;
struct notifier_block notifier;
static inline struct bcm_sock *bcm_sk(const struct sock *sk)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
return (struct bcm_sock *)sk;
-#else
- return (struct bcm_sock *)sk->sk_protinfo;
-#endif
}
#define CFSIZ sizeof(struct can_frame)
#define OPSIZ sizeof(struct bcm_op)
#define MHSIZ sizeof(struct bcm_msg_head)
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
-/*
- * rounded_tv2jif - calculate jiffies from timeval including optional up
- * @tv: pointer to timeval
- *
- * Description:
- * Unlike timeval_to_jiffies() provided in include/linux/jiffies.h, this
- * function is intentionally more relaxed on precise timer ticks to get
- * exact one jiffy for requested 1000us on a 1000HZ machine.
- * This code is to be removed when upgrading to kernel hrtimer.
- *
- * Return:
- * calculated jiffies (max: ULONG_MAX)
- */
-static unsigned long rounded_tv2jif(const struct timeval *tv)
-{
- unsigned long sec = tv->tv_sec;
- unsigned long usec = tv->tv_usec;
- unsigned long jif;
-
- if (sec > ULONG_MAX / HZ)
- return ULONG_MAX;
-
- /* round up to get at least the requested time */
- usec += 1000000 / HZ - 1;
-
- jif = usec / (1000000 / HZ);
-
- if (sec * HZ > ULONG_MAX - jif)
- return ULONG_MAX;
-
- return jif + sec * HZ;
-}
-#endif
-
/*
* procfs functions
*/
len += snprintf(page + len, PAGE_SIZE - len, "[%d]%c ",
op->nframes,
(op->flags & RX_CHECK_DLC)?'d':' ');
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
if (op->kt_ival1.tv64)
len += snprintf(page + len, PAGE_SIZE - len,
"timeo=%lld ",
"thr=%lld ",
(long long)
ktime_to_us(op->kt_ival2));
-#else
- if (op->j_ival1)
- len += snprintf(page + len, PAGE_SIZE - len,
- "timeo=%ld ", op->j_ival1);
-
- if (op->j_ival2)
- len += snprintf(page + len, PAGE_SIZE - len,
- "thr=%ld ", op->j_ival2);
-#endif
len += snprintf(page + len, PAGE_SIZE - len,
"# recv %ld (%ld) => reduction: ",
op->can_id, bcm_proc_getifname(op->ifindex),
op->nframes);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
if (op->kt_ival1.tv64)
len += snprintf(page + len, PAGE_SIZE - len, "t1=%lld ",
(long long) ktime_to_us(op->kt_ival1));
if (op->kt_ival2.tv64)
len += snprintf(page + len, PAGE_SIZE - len, "t2=%lld ",
(long long) ktime_to_us(op->kt_ival2));
-#else
- if (op->j_ival1)
- len += snprintf(page + len, PAGE_SIZE - len, "t1=%ld ",
- op->j_ival1);
-
- if (op->j_ival2)
- len += snprintf(page + len, PAGE_SIZE - len, "t2=%ld ",
- op->j_ival2);
-#endif
len += snprintf(page + len, PAGE_SIZE - len, "# sent %ld\n",
op->frames_abs);
if (head->nframes) {
/* can_frames starting here */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
firstframe = (struct can_frame *)skb_tail_pointer(skb);
-#else
- firstframe = (struct can_frame *)skb->tail;
-#endif
memcpy(skb_put(skb, datalen), frames, datalen);
if (has_timestamp) {
/* restore rx timestamp */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
skb->tstamp = op->rx_stamp;
-#else
- skb_set_timestamp(skb, &op->rx_stamp);
-#endif
}
/*
/*
* bcm_tx_timeout_handler - performes cyclic CAN frame transmissions
*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
{
struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
enum hrtimer_restart ret = HRTIMER_NORESTART;
if (op->kt_ival1.tv64 && (op->count > 0)) {
-#else
-static void bcm_tx_timeout_handler(unsigned long data)
-{
- struct bcm_op *op = (struct bcm_op *)data;
-
- if (op->j_ival1 && (op->count > 0)) {
-#endif
op->count--;
if (!op->count && (op->flags & TX_COUNTEVT)) {
}
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
if (op->kt_ival1.tv64 && (op->count > 0)) {
/* send (next) frame */
}
return ret;
-#else
- if (op->j_ival1 && (op->count > 0)) {
-
- /* send (next) frame */
- bcm_can_tx(op);
- mod_timer(&op->timer, jiffies + op->j_ival1);
-
- } else {
- if (op->j_ival2) {
-
- /* send (next) frame */
- bcm_can_tx(op);
- mod_timer(&op->timer, jiffies + op->j_ival2);
- }
- }
-
- return;
-#endif
}
/*
{
struct bcm_msg_head head;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
- op->j_lastmsg = jiffies;
-#endif
-
/* update statistics */
op->frames_filtered++;
struct can_frame *lastdata,
struct can_frame *rxdata)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
memcpy(lastdata, rxdata, CFSIZ);
/* mark as used */
/* the gap was that big, that throttling was not needed here */
bcm_rx_changed(op, rxdata);
op->kt_lastmsg = ktime_get();
-#else
- unsigned long nexttx = op->j_lastmsg + op->j_ival2;
-
- memcpy(lastdata, rxdata, CFSIZ);
-
- /* mark as used */
- lastdata->can_dlc |= RX_RECV;
-
- /* throttle bcm_rx_changed ? */
- if ((op->thrtimer.expires) ||
- ((op->j_ival2) && (nexttx > jiffies))) {
- /* we are already waiting OR we have to start waiting */
-
- /* mark as 'throttled' */
- lastdata->can_dlc |= RX_THR;
-
- if (!(op->thrtimer.expires)) {
- /* start the timer only the first time */
- mod_timer(&op->thrtimer, nexttx);
- }
-
- } else {
- /* send RX_CHANGED to the user immediately */
- bcm_rx_changed(op, rxdata);
- }
-#endif
}
/*
if (op->flags & RX_NO_AUTOTIMER)
return;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
if (op->kt_ival1.tv64)
hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL);
-#else
- if (op->j_ival1)
- mod_timer(&op->timer, jiffies + op->j_ival1);
-#endif
}
/*
* bcm_rx_timeout_handler - when the (cyclic) CAN frame receiption timed out
*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
{
struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
-#else
-static void bcm_rx_timeout_handler(unsigned long data)
-{
- struct bcm_op *op = (struct bcm_op *)data;
-#endif
struct bcm_msg_head msg_head;
msg_head.opcode = RX_TIMEOUT;
/* clear received can_frames to indicate 'nothing received' */
memset(op->last_frames, 0, op->nframes * CFSIZ);
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
return HRTIMER_NORESTART;
-#endif
}
/*
* bcm_rx_thr_handler - the time for blocked content updates is over now:
* Check for throttled data and send it to the userspace
*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
static enum hrtimer_restart bcm_rx_thr_handler(struct hrtimer *hrtimer)
{
struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer);
return HRTIMER_NORESTART;
}
}
-#else
-static void bcm_rx_thr_handler(unsigned long data)
-{
- struct bcm_op *op = (struct bcm_op *)data;
-
- if (bcm_rx_thr_flush(op))
- mod_timer(&op->thrtimer, jiffies + op->j_ival2);
- else {
- /* mark disabled / consumed timer */
- op->thrtimer.expires = 0;
- }
-}
-#endif
/*
* bcm_rx_handler - handle a CAN frame receiption
int i;
/* disable timeout */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
hrtimer_cancel(&op->timer);
-#else
- del_timer(&op->timer);
-#endif
if (skb->len == sizeof(rxframe)) {
memcpy(&rxframe, skb->data, sizeof(rxframe));
/* save rx timestamp */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
op->rx_stamp = skb->tstamp;
-#else
- skb_get_timestamp(skb, &op->rx_stamp);
-#endif
/* save originator for recvfrom() */
op->rx_ifindex = skb->dev->ifindex;
/* update statistics */
static void bcm_remove_op(struct bcm_op *op)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
hrtimer_cancel(&op->timer);
hrtimer_cancel(&op->thrtimer);
-#else
- del_timer(&op->timer);
- del_timer(&op->thrtimer);
-#endif
if ((op->frames) && (op->frames != &op->sframe))
kfree(op->frames);
op->ifindex = ifindex;
/* initialize uninitialized (kzalloc) structure */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
op->timer.function = bcm_tx_timeout_handler;
/* currently unused in tx_ops */
hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-#else
- setup_timer(&op->timer, bcm_tx_timeout_handler,
- (unsigned long)op);
-
- /* currently unused in tx_ops */
- init_timer(&op->thrtimer);
-#endif
/* add this bcm_op to the list of the tx_ops */
list_add(&op->list, &bo->tx_ops);
op->currframe = 0;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
if (op->flags & SETTIMER) {
/* set timer values */
op->count = msg_head->count;
hrtimer_start(&op->timer, op->kt_ival2,
HRTIMER_MODE_REL);
}
-#else
- if (op->flags & SETTIMER) {
- /* set timer values */
- op->count = msg_head->count;
- op->ival1 = msg_head->ival1;
- op->ival2 = msg_head->ival2;
- op->j_ival1 = rounded_tv2jif(&msg_head->ival1);
- op->j_ival2 = rounded_tv2jif(&msg_head->ival2);
-
- /* disable an active timer due to zero values? */
- if (!op->j_ival1 && !op->j_ival2)
- del_timer(&op->timer);
- }
-
- if ((op->flags & STARTTIMER) &&
- ((op->j_ival1 && op->count) || op->j_ival2)) {
-
- /* spec: send can_frame when starting timer */
- op->flags |= TX_ANNOUNCE;
-
- if (op->j_ival1 && (op->count > 0)) {
- /* op->count-- is done in bcm_tx_timeout_handler */
- mod_timer(&op->timer, jiffies + op->j_ival1);
- } else
- mod_timer(&op->timer, jiffies + op->j_ival2);
- }
-#endif
if (op->flags & TX_ANNOUNCE)
bcm_can_tx(op);
op->ifindex = ifindex;
/* initialize uninitialized (kzalloc) structure */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
op->timer.function = bcm_rx_timeout_handler;
hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
op->thrtimer.function = bcm_rx_thr_handler;
-#else
- setup_timer(&op->timer, bcm_rx_timeout_handler,
- (unsigned long)op);
-
- /* init throttle timer for RX_CHANGED */
- setup_timer(&op->thrtimer, bcm_rx_thr_handler,
- (unsigned long)op);
-
- /* mark disabled timer */
- op->thrtimer.expires = 0;
-#endif
/* add this bcm_op to the list of the rx_ops */
list_add(&op->list, &bo->rx_ops);
if (op->flags & RX_RTR_FRAME) {
/* no timers in RTR-mode */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
hrtimer_cancel(&op->thrtimer);
hrtimer_cancel(&op->timer);
-#else
- del_timer(&op->thrtimer);
- del_timer(&op->timer);
-#endif
/*
* funny feature in RX(!)_SETUP only for RTR-mode:
op->frames[0].can_id = op->can_id & ~CAN_RTR_FLAG;
} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
if (op->flags & SETTIMER) {
/* set timer value */
if ((op->flags & STARTTIMER) && op->kt_ival1.tv64)
hrtimer_start(&op->timer, op->kt_ival1,
HRTIMER_MODE_REL);
-#else
- if (op->flags & SETTIMER) {
-
- /* set timer value */
- op->ival1 = msg_head->ival1;
- op->ival2 = msg_head->ival2;
- op->j_ival1 = rounded_tv2jif(&msg_head->ival1);
- op->j_ival2 = rounded_tv2jif(&msg_head->ival2);
-
- /* disable an active timer due to zero value? */
- if (!op->j_ival1)
- del_timer(&op->timer);
-
- /*
- * In any case cancel the throttle timer, flush
- * potentially blocked msgs and reset throttle handling
- */
- del_timer(&op->thrtimer);
- bcm_rx_thr_flush(op);
- op->thrtimer.expires = 0;
- }
-
- if ((op->flags & STARTTIMER) && op->j_ival1)
- mod_timer(&op->timer, jiffies + op->j_ival1);
-#endif
}
/* now we can register for can_ids, if we added a new bcm_op */
{
struct net_device *dev = (struct net_device *)data;
struct bcm_sock *bo = container_of(nb, struct bcm_sock, notifier);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
struct sock *sk = &bo->sk;
-#else
- struct sock *sk = bo->sk;
-#endif
struct bcm_op *op;
int notify_enodev = 0;
{
struct bcm_sock *bo = bcm_sk(sk);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
- bo->sk = sk;
-#endif
bo->bound = 0;
bo->ifindex = 0;
bo->dropped_usr_msgs = 0;
.sendpage = sock_no_sendpage,
};
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
static struct proto bcm_proto __read_mostly = {
.name = "CAN_BCM",
.owner = THIS_MODULE,
.ops = &bcm_ops,
.prot = &bcm_proto,
};
-#else
-static struct can_proto bcm_can_proto __read_mostly = {
- .type = SOCK_DGRAM,
- .protocol = CAN_BCM,
- .capability = -1,
- .ops = &bcm_ops,
- .owner = THIS_MODULE,
- .obj_size = sizeof(struct bcm_sock),
- .init = bcm_init,
-};
-#endif
static int __init bcm_module_init(void)
{