static int can_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt);
static int can_rcv_filter(struct rcv_dev_list *q, struct sk_buff *skb);
-static struct rcv_list **find_rcv_list(canid_t *can_id, canid_t *mask, struct net_device *dev);
+static struct rcv_list **find_rcv_list(canid_t *can_id, canid_t *mask,
+ struct net_device *dev);
struct notifier_list {
- struct notifier_list *next;
- struct net_device *dev;
- void (*func)(unsigned long msg, void *data);
- void *data;
+ struct notifier_list *next;
+ struct net_device *dev;
+ void (*func)(unsigned long msg, void *data);
+ void *data;
};
static struct notifier_list *nlist;
rwlock_t rcv_lists_lock = RW_LOCK_UNLOCKED;
static struct packet_type can_packet = {
- .type = __constant_htons(ETH_P_CAN),
- .dev = NULL,
- .func = can_rcv,
+ .type = __constant_htons(ETH_P_CAN),
+ .dev = NULL,
+ .func = can_rcv,
};
static struct net_proto_family can_family_ops = {
- .family = PF_CAN,
- .create = can_create,
+ .family = PF_CAN,
+ .create = can_create,
};
static struct notifier_block can_netdev_notifier = {
- .notifier_call = can_notifier,
+ .notifier_call = can_notifier,
};
static struct proto_ops *proto_tab[CAN_MAX];
static __init int can_init(void)
{
- printk(banner);
+ printk(banner);
- if (stats_timer) {
- /* statistics init */
- init_timer(&stattimer);
- }
+ if (stats_timer) {
+ /* statistics init */
+ init_timer(&stattimer);
+ }
- /* procfs init */
- can_init_proc();
+ /* procfs init */
+ can_init_proc();
- /* protocol register */
- sock_register(&can_family_ops);
- register_netdevice_notifier(&can_netdev_notifier);
- dev_add_pack(&can_packet);
+ /* protocol register */
+ sock_register(&can_family_ops);
+ register_netdevice_notifier(&can_netdev_notifier);
+ dev_add_pack(&can_packet);
- return 0;
+ return 0;
}
static __exit void can_exit(void)
{
- if (stats_timer) {
- /* stop statistics timer */
- del_timer(&stattimer);
- }
-
- /* procfs remove */
- can_remove_proc();
-
- /* protocol unregister */
- dev_remove_pack(&can_packet);
- unregister_netdevice_notifier(&can_netdev_notifier);
- sock_unregister(PF_CAN);
+ if (stats_timer) {
+ /* stop statistics timer */
+ del_timer(&stattimer);
+ }
+
+ /* procfs remove */
+ can_remove_proc();
+
+ /* protocol unregister */
+ dev_remove_pack(&can_packet);
+ unregister_netdevice_notifier(&can_netdev_notifier);
+ sock_unregister(PF_CAN);
}
/**************************************************/
void can_proto_register(int proto, struct proto_ops *ops)
{
- if (proto < 0 || proto >= CAN_MAX) {
- printk(KERN_ERR "CAN: protocol number %d out of range\n", proto);
- return;
- }
- if (proto_tab[proto]) {
- printk(KERN_ERR "CAN: protocol %d already registered\n", proto);
- return;
- }
- proto_tab[proto] = ops;
-
- /* use our generic ioctl function if the module doesn't bring its own */
- if (!ops->ioctl)
- ops->ioctl = can_ioctl;
+ if (proto < 0 || proto >= CAN_MAX) {
+ printk(KERN_ERR "CAN: protocol number %d out of range\n", proto);
+ return;
+ }
+ if (proto_tab[proto]) {
+ printk(KERN_ERR "CAN: protocol %d already registered\n", proto);
+ return;
+ }
+ proto_tab[proto] = ops;
+
+ /* use our generic ioctl function if the module doesn't bring its own */
+ if (!ops->ioctl)
+ ops->ioctl = can_ioctl;
}
void can_proto_unregister(int proto)
{
- if (!proto_tab[proto]) {
- printk(KERN_ERR "CAN: protocol %d is not registered\n", proto);
- return;
- }
- proto_tab[proto] = NULL;
+ if (!proto_tab[proto]) {
+ printk(KERN_ERR "CAN: protocol %d is not registered\n", proto);
+ return;
+ }
+ proto_tab[proto] = NULL;
}
void can_dev_register(struct net_device *dev,
void (*func)(unsigned long msg, void *), void *data)
{
- struct notifier_list *p = kmalloc(sizeof(*p), GFP_KERNEL);
+ struct notifier_list *p = kmalloc(sizeof(*p), GFP_KERNEL);
- DBG("called for %s\n", dev->name);
+ DBG("called for %s\n", dev->name);
- if (!p)
- return;
- p->next = nlist;
- p->dev = dev;
- p->func = func;
- p->data = data;
- nlist = p;
+ if (!p)
+ return;
+ p->next = nlist;
+ p->dev = dev;
+ p->func = func;
+ p->data = data;
+ nlist = p;
}
void can_dev_unregister(struct net_device *dev,
void (*func)(unsigned long msg, void *), void *data)
{
- struct notifier_list *p, **q;
+ struct notifier_list *p, **q;
- DBG("called for %s\n", dev->name);
+ DBG("called for %s\n", dev->name);
- for (q = &nlist; p = *q; q = &p->next) {
- if (p->dev == dev && p->func == func && p->data == data) {
- *q = p->next;
- kfree(p);
- return;
+ for (q = &nlist; p = *q; q = &p->next) {
+ if (p->dev == dev && p->func == func && p->data == data) {
+ *q = p->next;
+ kfree(p);
+ return;
+ }
}
- }
}
/**************************************************/
static void can_sock_destruct(struct sock *sk)
{
- skb_queue_purge(&sk->receive_queue);
+ skb_queue_purge(&sk->receive_queue);
}
static int can_create(struct socket *sock, int protocol)
{
- struct sock *sk;
-
- DBG("socket %p, type %d, proto %d\n", sock, sock->type, protocol);
-
- sock->state = SS_UNCONNECTED;
-
- switch (sock->type) {
- case SOCK_SEQPACKET:
- switch (protocol) {
- case CAN_TP16:
- break;
- case CAN_TP20:
- break;
- case CAN_MCNET:
- break;
- case CAN_ISOTP:
- break;
- default:
- return -EPROTONOSUPPORT;
- }
- break;
- case SOCK_DGRAM:
- switch (protocol) {
- case CAN_BCM:
- break;
- case CAN_BAP:
- break;
- default:
- return -EPROTONOSUPPORT;
- }
- break;
- case SOCK_RAW:
- switch (protocol) {
- case CAN_RAW:
- if (!capable(CAP_NET_RAW))
- return -EPERM;
- break;
+ struct sock *sk;
+
+ DBG("socket %p, type %d, proto %d\n", sock, sock->type, protocol);
+
+ sock->state = SS_UNCONNECTED;
+
+ switch (sock->type) {
+ case SOCK_SEQPACKET:
+ switch (protocol) {
+ case CAN_TP16:
+ break;
+ case CAN_TP20:
+ break;
+ case CAN_MCNET:
+ break;
+ case CAN_ISOTP:
+ break;
+ default:
+ return -EPROTONOSUPPORT;
+ }
+ break;
+ case SOCK_DGRAM:
+ switch (protocol) {
+ case CAN_BCM:
+ break;
+ case CAN_BAP:
+ break;
+ default:
+ return -EPROTONOSUPPORT;
+ }
+ break;
+ case SOCK_RAW:
+ switch (protocol) {
+ case CAN_RAW:
+ if (!capable(CAP_NET_RAW))
+ return -EPERM;
+ break;
+ default:
+ return -EPROTONOSUPPORT;
+ }
+ break;
default:
- return -EPROTONOSUPPORT;
+ return -ESOCKTNOSUPPORT;
+ break;
}
- break;
- default:
- return -ESOCKTNOSUPPORT;
- break;
- }
- DBG("looking up proto %d in proto_tab[]\n", protocol);
+ DBG("looking up proto %d in proto_tab[]\n", protocol);
- /* try to load protocol module, when CONFIG_KMOD is defined */
- if (!proto_tab[protocol]) {
- char module_name[30];
- sprintf(module_name, "can-proto-%d", protocol);
- if (request_module(module_name) == -ENOSYS)
- printk(KERN_INFO "af_can: request_module(%s) not implemented.\n",
- module_name);
- }
+ /* try to load protocol module, when CONFIG_KMOD is defined */
+ if (!proto_tab[protocol]) {
+ char module_name[30];
+ sprintf(module_name, "can-proto-%d", protocol);
+ if (request_module(module_name) == -ENOSYS)
+ printk(KERN_INFO "af_can: request_module(%s) not implemented.\n",
+ module_name);
+ }
- /* check for success */
- if (!proto_tab[protocol])
- return -EPROTONOSUPPORT;
+ /* check for success */
+ if (!proto_tab[protocol])
+ return -EPROTONOSUPPORT;
- sock->ops = proto_tab[protocol];
+ sock->ops = proto_tab[protocol];
- if (!(sk = sk_alloc(PF_CAN, GFP_KERNEL, 1)))
- goto oom;
+ if (!(sk = sk_alloc(PF_CAN, GFP_KERNEL, 1)))
+ goto oom;
- sock_init_data(sock, sk);
- sk->destruct = can_sock_destruct;
+ sock_init_data(sock, sk);
+ sk->destruct = can_sock_destruct;
- DBG("created sock: %p\n", sk);
+ DBG("created sock: %p\n", sk);
- return 0;
+ return 0;
oom:
- return -ENOMEM;
+ return -ENOMEM;
}
static int can_notifier(struct notifier_block *nb,
unsigned long msg, void *data)
{
- struct net_device *dev = (struct net_device *)data;
- struct notifier_list *p;
+ struct net_device *dev = (struct net_device *)data;
+ struct notifier_list *p;
- DBG("called for %s, msg = %lu\n", dev->name, msg);
+ DBG("called for %s, msg = %lu\n", dev->name, msg);
- for (p = nlist; p; p = p->next) {
- if (p->dev == dev)
- p->func(msg, p->data);
- }
- return 0;
+ for (p = nlist; p; p = p->next) {
+ if (p->dev == dev)
+ p->func(msg, p->data);
+ }
+ return 0;
}
static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
- int err;
- struct sock *sk = sock->sk;
-
- switch (cmd) {
- case SIOCGSTAMP:
- if (sk->stamp.tv_sec == 0)
- return -ENOENT;
- if (err = copy_to_user((void *)arg, &sk->stamp, sizeof(sk->stamp)))
- return err;
- break;
- default:
- return dev_ioctl(cmd, (void *)arg);
- }
- return 0;
+ int err;
+ struct sock *sk = sock->sk;
+
+ switch (cmd) {
+ case SIOCGSTAMP:
+ if (sk->stamp.tv_sec == 0)
+ return -ENOENT;
+ if (err = copy_to_user((void *)arg, &sk->stamp, sizeof(sk->stamp)))
+ return err;
+ break;
+ default:
+ return dev_ioctl(cmd, (void *)arg);
+ }
+ return 0;
}
/**************************************************/
int can_send(struct sk_buff *skb)
{
- struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
- int err;
+ struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
+ int err;
- if (!(skb->dev->flags & IFF_UP))
- err = -ENETDOWN;
- else if ((err = dev_queue_xmit(skb)) > 0) /* send to netdevice */
- err = net_xmit_errno(err);
+ if (!(skb->dev->flags & IFF_UP))
+ err = -ENETDOWN;
+ else if ((err = dev_queue_xmit(skb)) > 0) /* send to netdevice */
+ err = net_xmit_errno(err);
- /* update statistics */
- stats.tx_frames++;
- stats.tx_frames_delta++;
+ /* update statistics */
+ stats.tx_frames++;
+ stats.tx_frames_delta++;
- newskb->protocol = htons(ETH_P_CAN);
- newskb->ip_summed = CHECKSUM_UNNECESSARY;
- netif_rx(newskb); /* local loopback */
+ newskb->protocol = htons(ETH_P_CAN);
+ newskb->ip_summed = CHECKSUM_UNNECESSARY;
+ netif_rx(newskb); /* local loopback */
- return err;
+ return err;
}
/**************************************************/
/**************************************************/
void can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
- void (*func)(struct sk_buff *, void *), void *data, char *ident)
+ void (*func)(struct sk_buff *, void *), void *data,
+ char *ident)
{
- struct rcv_list *p, **q;
- struct rcv_dev_list *d;
-
- DBG("dev %p, id %03X, mask %03X, callback %p, data %p, ident %s\n",
- dev, can_id, mask, func, data, ident);
-
- write_lock_bh(&rcv_lists_lock);
-
- q = find_rcv_list(&can_id, &mask, dev);
-
- if (!q) {
- printk(KERN_ERR "CAN: receive list not found for "
- "dev %s, id %03X, mask %03X, ident %s\n",
- dev->name, can_id, mask, ident);
- goto out;
- }
-
- /* insert (dev,canid,mask) -> (func,data) */
- if (!(p = kmalloc(sizeof(struct rcv_list), GFP_KERNEL)))
- goto out;
-
- p->can_id = can_id;
- p->mask = mask;
- p->matches = 0;
- p->func = func;
- p->data = data;
- p->ident = ident;
- p->next = *q;
- *q = p;
-
- if (!dev)
- d = &rx_alldev_list;
- else
- for (d = rx_dev_list; d; d = d->next)
- if (d->dev == dev)
- break;
- d->entries++;
+ struct rcv_list *p, **q;
+ struct rcv_dev_list *d;
+
+ DBG("dev %p, id %03X, mask %03X, callback %p, data %p, ident %s\n",
+ dev, can_id, mask, func, data, ident);
+
+ write_lock_bh(&rcv_lists_lock);
- pstats.rcv_entries++;
- if (pstats.rcv_entries_max < pstats.rcv_entries)
- pstats.rcv_entries_max = pstats.rcv_entries;
+ q = find_rcv_list(&can_id, &mask, dev);
-out:
- write_unlock_bh(&rcv_lists_lock);
+ if (!q) {
+ printk(KERN_ERR "CAN: receive list not found for "
+ "dev %s, id %03X, mask %03X, ident %s\n",
+ dev->name, can_id, mask, ident);
+ goto out;
+ }
+
+ /* insert (dev,canid,mask) -> (func,data) */
+ if (!(p = kmalloc(sizeof(struct rcv_list), GFP_KERNEL)))
+ goto out;
+
+ p->can_id = can_id;
+ p->mask = mask;
+ p->matches = 0;
+ p->func = func;
+ p->data = data;
+ p->ident = ident;
+ p->next = *q;
+ *q = p;
+
+ if (!dev)
+ d = &rx_alldev_list;
+ else
+ for (d = rx_dev_list; d; d = d->next)
+ if (d->dev == dev)
+ break;
+ d->entries++;
+
+ pstats.rcv_entries++;
+ if (pstats.rcv_entries_max < pstats.rcv_entries)
+ pstats.rcv_entries_max = pstats.rcv_entries;
+
+ out:
+ write_unlock_bh(&rcv_lists_lock);
}
void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask,
- void (*func)(struct sk_buff *, void *), void *data)
+ void (*func)(struct sk_buff *, void *), void *data)
{
- struct rcv_list *p, **q;
- struct rcv_dev_list *d;
+ struct rcv_list *p, **q;
+ struct rcv_dev_list *d;
- DBG("dev %p, id %03X, mask %03X, callback %p, data %p\n",
- dev, can_id, mask, func, data);
+ DBG("dev %p, id %03X, mask %03X, callback %p, data %p\n",
+ dev, can_id, mask, func, data);
- write_lock_bh(&rcv_lists_lock);
+ write_lock_bh(&rcv_lists_lock);
- q = find_rcv_list(&can_id, &mask, dev);
+ q = find_rcv_list(&can_id, &mask, dev);
- if (!q) {
- printk(KERN_ERR "CAN: receive list not found for "
- "dev %s, id %03X, mask %03X\n", dev->name, can_id, mask);
- goto out;
- }
+ if (!q) {
+ printk(KERN_ERR "CAN: receive list not found for "
+ "dev %s, id %03X, mask %03X\n", dev->name, can_id, mask);
+ goto out;
+ }
- for (; p = *q; q = &p->next) {
- if (p->can_id == can_id && p->mask == mask
- && p->func == func && p->data == data)
- break;
- }
+ for (; p = *q; q = &p->next) {
+ if (p->can_id == can_id && p->mask == mask
+ && p->func == func && p->data == data)
+ break;
+ }
- if (!p) {
- printk(KERN_ERR "CAN: receive list entry not found for "
- "dev %s, id %03X, mask %03X\n", dev->name, can_id, mask);
- goto out;
- }
+ if (!p) {
+ printk(KERN_ERR "CAN: receive list entry not found for "
+ "dev %s, id %03X, mask %03X\n", dev->name, can_id, mask);
+ goto out;
+ }
- *q = p->next;
- kfree(p);
+ *q = p->next;
+ kfree(p);
- if (pstats.rcv_entries > 0)
- pstats.rcv_entries--;
+ if (pstats.rcv_entries > 0)
+ pstats.rcv_entries--;
- if (!dev)
- d = &rx_alldev_list;
- else
- for (d = rx_dev_list; d; d = d->next)
- if (d->dev == dev)
- break;
- d->entries--;
+ if (!dev)
+ d = &rx_alldev_list;
+ else
+ for (d = rx_dev_list; d; d = d->next)
+ if (d->dev == dev)
+ break;
+ d->entries--;
- if (!d->entries)
- d->dev = NULL; /* mark unused */
+ if (!d->entries)
+ d->dev = NULL; /* mark unused */
-out:
- write_unlock_bh(&rcv_lists_lock);
+ out:
+ write_unlock_bh(&rcv_lists_lock);
}
static int can_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
{
- struct rcv_dev_list *q;
- int matches;
+ struct rcv_dev_list *q;
+ int matches;
- DBG("received skbuff on device %s, ptype %04x\n",
- dev->name, ntohs(pt->type));
- DBG_SKB(skb);
- DBG_FRAME("af_can: can_rcv: received CAN frame",
- (struct can_frame *)skb->data);
+ DBG("received skbuff on device %s, ptype %04x\n",
+ dev->name, ntohs(pt->type));
+ DBG_SKB(skb);
+ DBG_FRAME("af_can: can_rcv: received CAN frame",
+ (struct can_frame *)skb->data);
- /* update statistics */
- stats.rx_frames++;
- stats.rx_frames_delta++;
+ /* update statistics */
+ stats.rx_frames++;
+ stats.rx_frames_delta++;
- read_lock(&rcv_lists_lock);
+ read_lock(&rcv_lists_lock);
- matches = can_rcv_filter(&rx_alldev_list, skb);
+ matches = can_rcv_filter(&rx_alldev_list, skb);
- /* find receive list for this device */
- for (q = rx_dev_list; q; q = q->next)
- if (q->dev == dev)
- break;
+ /* find receive list for this device */
+ for (q = rx_dev_list; q; q = q->next)
+ if (q->dev == dev)
+ break;
- if (q)
- matches += can_rcv_filter(q, skb);
+ if (q)
+ matches += can_rcv_filter(q, skb);
- read_unlock(&rcv_lists_lock);
+ read_unlock(&rcv_lists_lock);
- DBG("freeing skbuff %p\n", skb);
- kfree_skb(skb);
+ DBG("freeing skbuff %p\n", skb);
+ kfree_skb(skb);
- if (matches > 0) {
- stats.matches++;
- stats.matches_delta++;
- }
+ if (matches > 0) {
+ stats.matches++;
+ stats.matches_delta++;
+ }
- return 0;
+ return 0;
}
static inline void deliver(struct sk_buff *skb, struct rcv_list *p)
{
- struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
- DBG("skbuff %p cloned to %p\n", skb, clone);
- if (clone) {
- p->func(clone, p->data);
- p->matches++; /* update specific statistics */
- }
+ struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
+ DBG("skbuff %p cloned to %p\n", skb, clone);
+ if (clone) {
+ p->func(clone, p->data);
+ p->matches++; /* update specific statistics */
+ }
}
static int can_rcv_filter(struct rcv_dev_list *q, struct sk_buff *skb)
{
- struct rcv_list *p;
- int matches = 0;
- struct can_frame *cf = (struct can_frame*)skb->data;
- canid_t can_id = cf->can_id;
-
- if (q->entries == 0)
- return 0;
+ struct rcv_list *p;
+ int matches = 0;
+ struct can_frame *cf = (struct can_frame*)skb->data;
+ canid_t can_id = cf->can_id;
+
+ if (q->entries == 0)
+ return 0;
+
+ if (can_id & CAN_ERR_FLAG) {
+ /* check for error frame entries only */
+ for (p = q->rx_err; p; p = p->next) {
+ if (can_id & p->mask) {
+ DBG("match on rx_err skbuff %p\n", skb);
+ deliver(skb, p);
+ matches++;
+ }
+ }
+ goto out;
+ }
- if (can_id & CAN_ERR_FLAG) {
- /* check for error frame entries only */
- for (p = q->rx_err; p; p = p->next) {
- if (can_id & p->mask) {
- DBG("match on rx_err skbuff %p\n", skb);
+ /* check for unfiltered entries */
+ for (p = q->rx_all; p; p = p->next) {
+ DBG("match on rx_all skbuff %p\n", skb);
deliver(skb, p);
matches++;
- }
}
- goto out;
- }
-
- /* check for unfiltered entries */
- for (p = q->rx_all; p; p = p->next) {
- DBG("match on rx_all skbuff %p\n", skb);
- deliver(skb, p);
- matches++;
- }
-
- /* check for can_id/mask entries */
- for (p = q->rx_fil; p; p = p->next) {
- if ((can_id & p->mask) == p->can_id) {
- DBG("match on rx_fil skbuff %p\n", skb);
- deliver(skb, p);
- matches++;
- }
- }
-
- /* check for inverted can_id/mask entries */
- for (p = q->rx_inv; p; p = p->next) {
- if ((can_id & p->mask) != p->can_id) {
- DBG("match on rx_inv skbuff %p\n", skb);
- deliver(skb, p);
- matches++;
+
+ /* check for can_id/mask entries */
+ for (p = q->rx_fil; p; p = p->next) {
+ if ((can_id & p->mask) == p->can_id) {
+ DBG("match on rx_fil skbuff %p\n", skb);
+ deliver(skb, p);
+ matches++;
+ }
}
- }
- /* check CAN_ID specific entries */
- if (can_id & CAN_EFF_FLAG) {
- for (p = q->rx_eff; p; p = p->next) {
- if (p->can_id == can_id) {
- DBG("match on rx_eff skbuff %p\n", skb);
- deliver(skb, p);
- matches++;
- }
+ /* check for inverted can_id/mask entries */
+ for (p = q->rx_inv; p; p = p->next) {
+ if ((can_id & p->mask) != p->can_id) {
+ DBG("match on rx_inv skbuff %p\n", skb);
+ deliver(skb, p);
+ matches++;
+ }
}
- } else {
- for (p = q->rx_sff[can_id & CAN_SFF_MASK]; p; p = p->next) {
- DBG("match on rx_sff skbuff %p\n", skb);
- deliver(skb, p);
- matches++;
+
+ /* check CAN_ID specific entries */
+ if (can_id & CAN_EFF_FLAG) {
+ for (p = q->rx_eff; p; p = p->next) {
+ if (p->can_id == can_id) {
+ DBG("match on rx_eff skbuff %p\n", skb);
+ deliver(skb, p);
+ matches++;
+ }
+ }
+ } else {
+ for (p = q->rx_sff[can_id & CAN_SFF_MASK]; p; p = p->next) {
+ DBG("match on rx_sff skbuff %p\n", skb);
+ deliver(skb, p);
+ matches++;
+ }
}
- }
-out:
- return matches;
+ out:
+ return matches;
}
-static struct rcv_list **find_rcv_list(canid_t *can_id, canid_t *mask, struct net_device *dev)
+static struct rcv_list **find_rcv_list(canid_t *can_id, canid_t *mask,
+ struct net_device *dev)
{
- canid_t inv = *can_id & CAN_INV_FILTER; /* save flag before masking values */
- canid_t eff = *can_id & *mask & CAN_EFF_FLAG; /* correct EFF check? */
- canid_t rtr = *can_id & *mask & CAN_RTR_FLAG; /* correct RTR check? */
- canid_t err = *mask & CAN_ERR_FLAG; /* mask for error frames only */
-
- struct rcv_dev_list *p;
-
- /* make some paranoic operations */
- if (*can_id & CAN_EFF_FLAG)
- *mask &= (CAN_EFF_MASK | eff | rtr);
- else
- *mask &= (CAN_SFF_MASK | rtr);
-
- *can_id &= *mask;
-
- /* find receive list for this device */
- if (!dev)
- p = &rx_alldev_list;
- else {
- /* find the list for dev or an unused list entry, otherwise */
- struct rcv_dev_list *q;
- p = NULL;
- for (q = rx_dev_list; q; q = q->next)
- if (!q->dev)
- p = q;
- else if (q->dev == dev) {
- p = q;
- break;
- }
-
- if (p && !p->dev) {
- DBG("reactivating rcv_dev_list for %s\n", dev->name);
- p->dev = dev;
+ canid_t inv = *can_id & CAN_INV_FILTER; /* save flag before masking values */
+ canid_t eff = *can_id & *mask & CAN_EFF_FLAG; /* correct EFF check? */
+ canid_t rtr = *can_id & *mask & CAN_RTR_FLAG; /* correct RTR check? */
+ canid_t err = *mask & CAN_ERR_FLAG; /* mask for error frames only */
+
+ struct rcv_dev_list *p;
+
+ /* make some paranoic operations */
+ if (*can_id & CAN_EFF_FLAG)
+ *mask &= (CAN_EFF_MASK | eff | rtr);
+ else
+ *mask &= (CAN_SFF_MASK | rtr);
+
+ *can_id &= *mask;
+
+ /* find receive list for this device */
+ if (!dev)
+ p = &rx_alldev_list;
+ else {
+ /* find the list for dev or an unused list entry, otherwise */
+ struct rcv_dev_list *q;
+ p = NULL;
+ for (q = rx_dev_list; q; q = q->next)
+ if (!q->dev)
+ p = q;
+ else if (q->dev == dev) {
+ p = q;
+ break;
+ }
+
+ if (p && !p->dev) {
+ DBG("reactivating rcv_dev_list for %s\n", dev->name);
+ p->dev = dev;
+ }
}
- }
-
- if (!p) {
- /* create new rcv_dev_list for this device */
- DBG("creating new rcv_dev_list for %s\n", dev->name);
- if (!(p = kmalloc(sizeof(struct rcv_dev_list), GFP_KERNEL))) {
- printk(KERN_ERR "CAN: allocation of receive list failed\n");
- return NULL;
+
+ if (!p) {
+ /* create new rcv_dev_list for this device */
+ DBG("creating new rcv_dev_list for %s\n", dev->name);
+ if (!(p = kmalloc(sizeof(struct rcv_dev_list), GFP_KERNEL))) {
+ printk(KERN_ERR "CAN: allocation of receive list failed\n");
+ return NULL;
+ }
+ memset (p, 0, sizeof(struct rcv_dev_list));
+ p->dev = dev;
+ p->next = rx_dev_list;
+ rx_dev_list = p;
}
- memset (p, 0, sizeof(struct rcv_dev_list));
- p->dev = dev;
- p->next = rx_dev_list;
- rx_dev_list = p;
- }
- if (err) /* error frames */
- return &p->rx_err;
+ if (err) /* error frames */
+ return &p->rx_err;
- if (inv) /* inverse can_id/can_mask filter and RTR */
- return &p->rx_inv;
+ if (inv) /* inverse can_id/can_mask filter and RTR */
+ return &p->rx_inv;
- if (*can_id & CAN_RTR_FLAG) /* positive filter RTR */
- return &p->rx_fil;
+ if (*can_id & CAN_RTR_FLAG) /* positive filter RTR */
+ return &p->rx_fil;
- if (!(*mask)) /* mask == 0 => no filter */
- return &p->rx_all;
+ if (!(*mask)) /* mask == 0 => no filter */
+ return &p->rx_all;
- if (*can_id & CAN_EFF_FLAG) {
- if (*mask == CAN_EFF_MASK) /* filter exact EFF can_id */
- return &p->rx_eff;
- } else {
- if (*mask == CAN_SFF_MASK) /* filter exact SFF can_id */
- return &p->rx_sff[*can_id];
- }
+ if (*can_id & CAN_EFF_FLAG) {
+ if (*mask == CAN_EFF_MASK) /* filter exact EFF can_id */
+ return &p->rx_eff;
+ } else {
+ if (*mask == CAN_SFF_MASK) /* filter exact SFF can_id */
+ return &p->rx_sff[*can_id];
+ }
- return &p->rx_fil; /* filter via can_id/can_mask */
+ return &p->rx_fil; /* filter via can_id/can_mask */
}
/**************************************************/
unsigned long timeval2jiffies(struct timeval *tv, int round_up)
{
- unsigned long jif;
- unsigned long sec = tv->tv_sec;
- unsigned long usec = tv->tv_usec;
+ unsigned long jif;
+ unsigned long sec = tv->tv_sec;
+ unsigned long usec = tv->tv_usec;
- if (sec > ULONG_MAX / HZ) /* check for overflow */
- return ULONG_MAX;
+ if (sec > ULONG_MAX / HZ) /* check for overflow */
+ return ULONG_MAX;
- if (round_up) /* any usec below one HZ? */
- usec += 1000000 / HZ - 1; /* pump it up */
+ if (round_up) /* any usec below one HZ? */
+ usec += 1000000 / HZ - 1; /* pump it up */
- jif = usec / (1000000 / HZ);
+ jif = usec / (1000000 / HZ);
- if (sec * HZ > ULONG_MAX - jif) /* check for overflow */
- return ULONG_MAX;
- else
- return jif + sec * HZ;
+ if (sec * HZ > ULONG_MAX - jif) /* check for overflow */
+ return ULONG_MAX;
+ else
+ return jif + sec * HZ;
}
void can_debug_cframe(const char *msg, struct can_frame *cf, ...)
{
- va_list ap;
- int len;
- int dlc, i;
- char buf[1024];
-
- len = sprintf(buf, KERN_DEBUG);
- va_start(ap, cf);
- len += snprintf(buf + len, sizeof(buf) - 64, msg, ap);
- buf[len++] = ':';
- buf[len++] = ' ';
- va_end(ap);
-
- if ((dlc = cf->can_dlc) > 8)
- dlc = 8;
-
- if (cf->can_id & CAN_EFF_FLAG)
- len += sprintf(buf + len, "<%08X> [%X] ",
- cf->can_id & CAN_EFF_MASK, dlc);
- else
- len += sprintf(buf + len, "<%03X> [%X] ",
- cf->can_id & CAN_SFF_MASK, dlc);
-
- for (i = 0; i < dlc; i++)
- len += sprintf(buf + len, "%02X ", cf->data[i]);
-
- if (cf->can_id & CAN_RTR_FLAG)
- len += sprintf(buf + len, "(RTR)");
-
- buf[len++] = '\n';
- buf[len] = '\0';
- printk(buf);
+ va_list ap;
+ int len;
+ int dlc, i;
+ char buf[1024];
+
+ len = sprintf(buf, KERN_DEBUG);
+ va_start(ap, cf);
+ len += snprintf(buf + len, sizeof(buf) - 64, msg, ap);
+ buf[len++] = ':';
+ buf[len++] = ' ';
+ va_end(ap);
+
+ if ((dlc = cf->can_dlc) > 8)
+ dlc = 8;
+
+ if (cf->can_id & CAN_EFF_FLAG)
+ len += sprintf(buf + len, "<%08X> [%X] ",
+ cf->can_id & CAN_EFF_MASK, dlc);
+ else
+ len += sprintf(buf + len, "<%03X> [%X] ",
+ cf->can_id & CAN_SFF_MASK, dlc);
+
+ for (i = 0; i < dlc; i++)
+ len += sprintf(buf + len, "%02X ", cf->data[i]);
+
+ if (cf->can_id & CAN_RTR_FLAG)
+ len += sprintf(buf + len, "(RTR)");
+
+ buf[len++] = '\n';
+ buf[len] = '\0';
+ printk(buf);
}
void can_debug_skb(struct sk_buff *skb)
{
- int len, nbytes, i;
- char buf[1024];
-
- len = sprintf(buf,
- KERN_DEBUG " skbuff at %p, dev: %d, proto: %04x\n"
- KERN_DEBUG " users: %d, dataref: %d, nr_frags: %d, "
- "h,d,t,e,l: %p %+d %+d %+d, %d",
- skb, skb->dev ? skb->dev->ifindex : -1, ntohs(skb->protocol),
- atomic_read(&skb->users),
- atomic_read(&(skb_shinfo(skb)->dataref)),
- skb_shinfo(skb)->nr_frags,
- skb->head, skb->data - skb->head,
- skb->tail - skb->head, skb->end - skb->head, skb->len);
- nbytes = skb->end - skb->head;
- for (i = 0; i < nbytes; i++) {
- if (i % 16 == 0)
- len += sprintf(buf + len, "\n" KERN_DEBUG " ");
- if (len < sizeof(buf) - 16) {
- len += sprintf(buf + len, " %02x", skb->head[i]);
- } else {
- len += sprintf(buf + len, "...");
- break;
+ int len, nbytes, i;
+ char buf[1024];
+
+ len = sprintf(buf,
+ KERN_DEBUG " skbuff at %p, dev: %d, proto: %04x\n"
+ KERN_DEBUG " users: %d, dataref: %d, nr_frags: %d, "
+ "h,d,t,e,l: %p %+d %+d %+d, %d",
+ skb, skb->dev ? skb->dev->ifindex : -1,
+ ntohs(skb->protocol),
+ atomic_read(&skb->users),
+ atomic_read(&(skb_shinfo(skb)->dataref)),
+ skb_shinfo(skb)->nr_frags,
+ skb->head, skb->data - skb->head,
+ skb->tail - skb->head, skb->end - skb->head, skb->len);
+ nbytes = skb->end - skb->head;
+ for (i = 0; i < nbytes; i++) {
+ if (i % 16 == 0)
+ len += sprintf(buf + len, "\n" KERN_DEBUG " ");
+ if (len < sizeof(buf) - 16) {
+ len += sprintf(buf + len, " %02x", skb->head[i]);
+ } else {
+ len += sprintf(buf + len, "...");
+ break;
+ }
}
- }
- buf[len++] = '\n';
- buf[len] = '\0';
- printk(buf);
+ buf[len++] = '\n';
+ buf[len] = '\0';
+ printk(buf);
}
#ifdef EXPORT_SYMTAB
#define SOL_CAN_BASE 100
struct sockaddr_can {
- sa_family_t can_family;
- int can_ifindex;
- union {
- struct { canid_t rx_id, tx_id; } tp16;
- struct { canid_t rx_id, tx_id; } tp20;
- struct { canid_t rx_id, tx_id; } mcnet;
- } can_addr;
+ sa_family_t can_family;
+ int can_ifindex;
+ union {
+ struct { canid_t rx_id, tx_id; } tp16;
+ struct { canid_t rx_id, tx_id; } tp20;
+ struct { canid_t rx_id, tx_id; } mcnet;
+ } can_addr;
};
typedef canid_t can_err_mask_t;
struct can_filter {
- canid_t can_id;
- canid_t can_mask;
+ canid_t can_id;
+ canid_t can_mask;
};
#define CAN_INV_FILTER 0x20000000U /* to be set in can_filter.can_id */
void can_proto_register(int proto, struct proto_ops *ops);
void can_proto_unregister(int proto);
void can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
- void (*func)(struct sk_buff *, void *), void *data, char *ident);
+ void (*func)(struct sk_buff *, void *), void *data,
+ char *ident);
void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask,
- void (*func)(struct sk_buff *, void *), void *data);
+ void (*func)(struct sk_buff *, void *), void *data);
void can_dev_register(struct net_device *dev,
- void (*func)(unsigned long msg, void *), void *data);
+ void (*func)(unsigned long msg, void *), void *data);
void can_dev_unregister(struct net_device *dev,
- void (*func)(unsigned long msg, void *), void *data);
+ void (*func)(unsigned long msg, void *), void *data);
int can_send(struct sk_buff *skb);
unsigned long timeval2jiffies(struct timeval *tv, int round_up);
/* af_can rx dispatcher structures */
struct rcv_list {
- struct rcv_list *next;
- canid_t can_id;
- canid_t mask;
- unsigned long matches;
- void (*func)(struct sk_buff *, void *);
- void *data;
- char *ident;
+ struct rcv_list *next;
+ canid_t can_id;
+ canid_t mask;
+ unsigned long matches;
+ void (*func)(struct sk_buff *, void *);
+ void *data;
+ char *ident;
};
struct rcv_dev_list {
- struct rcv_dev_list *next;
- struct net_device *dev;
- struct rcv_list *rx_err;
- struct rcv_list *rx_all;
- struct rcv_list *rx_fil;
- struct rcv_list *rx_inv;
- struct rcv_list *rx_sff[0x800];
- struct rcv_list *rx_eff;
- int entries;
+ struct rcv_dev_list *next;
+ struct net_device *dev;
+ struct rcv_list *rx_err;
+ struct rcv_list *rx_all;
+ struct rcv_list *rx_fil;
+ struct rcv_list *rx_inv;
+ struct rcv_list *rx_sff[0x800];
+ struct rcv_list *rx_eff;
+ int entries;
};
/* statistic structures */
struct s_stats {
- unsigned long jiffies_init;
+ unsigned long jiffies_init;
- unsigned long rx_frames;
- unsigned long tx_frames;
- unsigned long matches;
+ 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 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 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 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;
+ unsigned long rx_frames_delta;
+ unsigned long tx_frames_delta;
+ unsigned long matches_delta;
}; /* can be reset e.g. by can_init_stats() */
struct s_pstats {
- unsigned long stats_reset;
- unsigned long rcv_entries;
- unsigned long rcv_entries_max;
+ unsigned long stats_reset;
+ unsigned long rcv_entries;
+ unsigned long rcv_entries_max;
}; /* persistent statistics */
void can_init_proc(void);
#define GET_U64(p) (*(unsigned long long*)(p)->data)
struct bcm_op {
- struct bcm_op *next;
- canid_t can_id;
- int flags;
- unsigned long j_ival1, j_ival2, j_lastmsg;
- unsigned long frames_abs, frames_filtered;
- struct timeval ival1, ival2, stamp;
- struct timer_list timer, thrtimer;
- int count;
- int nframes;
- int currframe;
- struct can_frame *frames;
- struct can_frame *last_frames;
- struct sock *sk;
+ struct bcm_op *next;
+ canid_t can_id;
+ int flags;
+ unsigned long j_ival1, j_ival2, j_lastmsg;
+ unsigned long frames_abs, frames_filtered;
+ struct timeval ival1, ival2, stamp;
+ struct timer_list timer, thrtimer;
+ int count;
+ int nframes;
+ int currframe;
+ struct can_frame *frames;
+ struct can_frame *last_frames;
+ struct sock *sk;
};
struct bcm_user_data {
- struct bcm_op *rx_ops;
- struct bcm_op *tx_ops;
- struct proc_dir_entry *bcm_proc_read;
- char procname [9];
+ struct bcm_op *rx_ops;
+ struct bcm_op *tx_ops;
+ struct proc_dir_entry *bcm_proc_read;
+ char procname [9];
};
#define bcm_sk(sk) ((struct bcm_user_data *)(sk)->user_data)
static struct proc_dir_entry *proc_dir = NULL;
-int bcm_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data);
+int bcm_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
static void bcm_notifier(unsigned long msg, void *data);
static int bcm_release(struct socket *sock);
struct can_frame *rxdata);
static struct proto_ops bcm_ops = {
- .family = PF_CAN,
- .release = bcm_release,
- .bind = sock_no_bind,
- .connect = bcm_connect,
- .socketpair = sock_no_socketpair,
- .accept = sock_no_accept,
- .getname = sock_no_getname,
- .poll = bcm_poll,
- .ioctl = NULL, /* use can_ioctl() from af_can.c */
- .listen = sock_no_listen,
- .shutdown = sock_no_shutdown,
- .setsockopt = sock_no_setsockopt,
- .getsockopt = sock_no_getsockopt,
- .sendmsg = bcm_sendmsg,
- .recvmsg = bcm_recvmsg,
- .mmap = sock_no_mmap,
- .sendpage = sock_no_sendpage,
+ .family = PF_CAN,
+ .release = bcm_release,
+ .bind = sock_no_bind,
+ .connect = bcm_connect,
+ .socketpair = sock_no_socketpair,
+ .accept = sock_no_accept,
+ .getname = sock_no_getname,
+ .poll = bcm_poll,
+ .ioctl = NULL, /* use can_ioctl() from af_can.c */
+ .listen = sock_no_listen,
+ .shutdown = sock_no_shutdown,
+ .setsockopt = sock_no_setsockopt,
+ .getsockopt = sock_no_getsockopt,
+ .sendmsg = bcm_sendmsg,
+ .recvmsg = bcm_recvmsg,
+ .mmap = sock_no_mmap,
+ .sendpage = sock_no_sendpage,
};
static int __init bcm_init(void)
{
- printk(banner);
+ printk(banner);
- can_proto_register(CAN_BCM, &bcm_ops);
+ can_proto_register(CAN_BCM, &bcm_ops);
- /* create /proc/can/bcm directory */
- proc_dir = proc_mkdir(CAN_PROC_DIR"/"IDENT, NULL);
+ /* create /proc/can/bcm directory */
+ proc_dir = proc_mkdir(CAN_PROC_DIR"/"IDENT, NULL);
- if (proc_dir)
- proc_dir->owner = THIS_MODULE;
+ if (proc_dir)
+ proc_dir->owner = THIS_MODULE;
- return 0;
+ return 0;
}
static void __exit bcm_exit(void)
{
- can_proto_unregister(CAN_BCM);
+ can_proto_unregister(CAN_BCM);
- if (proc_dir)
- remove_proc_entry(CAN_PROC_DIR"/"IDENT, NULL);
+ if (proc_dir)
+ remove_proc_entry(CAN_PROC_DIR"/"IDENT, NULL);
}
static void bcm_notifier(unsigned long msg, void *data)
{
- struct sock *sk = (struct sock *)data;
-
- DBG("called for sock %p\n", sk);
-
- switch (msg)
- {
- case NETDEV_UNREGISTER:
- sk->bound_dev_if = 0;
- case NETDEV_DOWN:
- sk->err = ENETDOWN;
- sk->error_report(sk);
- }
+ struct sock *sk = (struct sock *)data;
+
+ DBG("called for sock %p\n", sk);
+
+ switch (msg) {
+ case NETDEV_UNREGISTER:
+ sk->bound_dev_if = 0;
+ case NETDEV_DOWN:
+ sk->err = ENETDOWN;
+ sk->error_report(sk);
+ }
}
static int bcm_release(struct socket *sock)
{
- struct sock *sk = sock->sk;
- struct bcm_user_data *ud = bcm_sk(sk);
- struct bcm_op *op,*next;
+ struct sock *sk = sock->sk;
+ struct bcm_user_data *ud = bcm_sk(sk);
+ struct bcm_op *op,*next;
- /* many things to do here:
- free all rx_ops and tx_ops, bcm_user_data structure,
- can_rx_unregister(dev, canid, raw_rcv) and can-data in ?x_ops */
+ /* many things to do here:
+ free all rx_ops and tx_ops, bcm_user_data structure,
+ can_rx_unregister(dev, canid, raw_rcv) and can-data in ?x_ops */
- DBG("socket %p, sk %p\n", sock, sk);
+ DBG("socket %p, sk %p\n", sock, sk);
- /* remove userdata, bcm_ops, timer, etc. */
+ /* remove userdata, bcm_ops, timer, etc. */
- if (ud) {
- for (op = ud->tx_ops; op ; op = next) {
- DBG("removing tx_op (%p) for can_id <%03X>\n", op, op->can_id);
- next = op->next;
- bcm_remove_op(op);
- }
+ if (ud) {
+ for (op = ud->tx_ops; op ; op = next) {
+ DBG("removing tx_op (%p) for can_id <%03X>\n", op, op->can_id);
+ next = op->next;
+ bcm_remove_op(op);
+ }
- for (op = ud->rx_ops; op ; op = next) {
- DBG("removing rx_op (%p) for can_id <%03X>\n", op, op->can_id);
- next = op->next;
+ for (op = ud->rx_ops; op ; op = next) {
+ DBG("removing rx_op (%p) for can_id <%03X>\n", op, op->can_id);
+ next = op->next;
- if (sk->bound_dev_if) {
- struct net_device *dev = dev_get_by_index(sk->bound_dev_if);
- if (dev) {
- can_rx_unregister(dev, op->can_id, 0xFFFFFFFFU, bcm_rx_handler, op);
- dev_put(dev);
+ if (sk->bound_dev_if) {
+ struct net_device *dev = dev_get_by_index(sk->bound_dev_if);
+ if (dev) {
+ can_rx_unregister(dev, op->can_id, 0xFFFFFFFFU, bcm_rx_handler, op);
+ dev_put(dev);
+ }
+ } else
+ DBG("sock %p not bound for can_rx_unregister()\n", sk);
+
+ bcm_remove_op(op);
}
- } else
- DBG("sock %p not bound for can_rx_unregister()\n", sk);
- bcm_remove_op(op);
- }
+ if ((proc_dir) && (ud->bcm_proc_read)) {
+ remove_proc_entry(ud->procname, proc_dir);
+ }
- if ((proc_dir) && (ud->bcm_proc_read)) {
- remove_proc_entry(ud->procname, proc_dir);
+ kfree (ud);
}
- kfree (ud);
- }
-
- if (sk->bound_dev_if) {
- struct net_device *dev = dev_get_by_index(sk->bound_dev_if);
- if (dev) {
- can_dev_unregister(dev, bcm_notifier, sk);
- dev_put(dev);
- }
- } else
- DBG("sock %p not bound for can_dev_unregister()\n", sk);
+ if (sk->bound_dev_if) {
+ struct net_device *dev = dev_get_by_index(sk->bound_dev_if);
+ if (dev) {
+ can_dev_unregister(dev, bcm_notifier, sk);
+ dev_put(dev);
+ }
+ } else
+ DBG("sock %p not bound for can_dev_unregister()\n", sk);
- sock_put(sk);
+ sock_put(sk);
- return 0;
+ return 0;
}
static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,
int flags)
{
- struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
- struct sock *sk = sock->sk;
- struct net_device *dev;
- struct bcm_user_data *ud;
+ struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
+ struct sock *sk = sock->sk;
+ struct net_device *dev;
+ struct bcm_user_data *ud;
- /* bind a device to this socket */
+ /* bind a device to this socket */
- dev = dev_get_by_index(addr->can_ifindex);
- if (!dev) {
- DBG("could not find device %d\n", addr->can_ifindex);
- return -ENODEV;
- }
- sk->bound_dev_if = dev->ifindex;
- can_dev_register(dev, bcm_notifier, sk);
- dev_put(dev);
+ dev = dev_get_by_index(addr->can_ifindex);
+ if (!dev) {
+ DBG("could not find device %d\n", addr->can_ifindex);
+ return -ENODEV;
+ }
+ sk->bound_dev_if = dev->ifindex;
+ can_dev_register(dev, bcm_notifier, sk);
+ dev_put(dev);
- DBG("socket %p to device %s (idx %d)\n", sock, dev->name, dev->ifindex);
+ DBG("socket %p to device %s (idx %d)\n", sock, dev->name, dev->ifindex);
- /* create struct for BCM-specific data for this socket */
+ /* create struct for BCM-specific data for this socket */
- if (!(ud = kmalloc(sizeof(struct bcm_user_data), GFP_KERNEL)))
- return -ENOMEM;
+ if (!(ud = kmalloc(sizeof(struct bcm_user_data), GFP_KERNEL)))
+ return -ENOMEM;
- /* intitial BCM operations */
- ud->tx_ops = NULL;
- ud->rx_ops = NULL;
- ud->bcm_proc_read = NULL;
+ /* intitial BCM operations */
+ ud->tx_ops = NULL;
+ ud->rx_ops = NULL;
+ ud->bcm_proc_read = NULL;
- sk->user_data = ud;
+ sk->user_data = ud;
- if (proc_dir) {
- sprintf(ud->procname, "%p", ud);
- ud->bcm_proc_read = create_proc_read_entry(ud->procname, 0644,
- proc_dir, bcm_read_proc, ud);
- }
+ if (proc_dir) {
+ sprintf(ud->procname, "%p", ud);
+ ud->bcm_proc_read = create_proc_read_entry(ud->procname, 0644,
+ proc_dir, bcm_read_proc, ud);
+ }
- return 0;
+ return 0;
}
int bcm_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
{
- int len = 0;
- struct bcm_user_data *ud = (struct bcm_user_data *) data;
- struct bcm_op *op;
- struct net_device *dev = NULL;
-
- MOD_INC_USE_COUNT;
-
- len += snprintf(page + len, PAGE_SIZE - len,">>> ud %p", ud);
-
- if (ud->rx_ops) {
- if (ud->rx_ops->sk->bound_dev_if)
- dev = dev_get_by_index(ud->rx_ops->sk->bound_dev_if);
- len += snprintf(page + len, PAGE_SIZE - len,
- " / sk %p / socket %p", ud->rx_ops->sk, ud->rx_ops->sk->socket);
- }
- else
- if (ud->tx_ops) {
- if (ud->tx_ops->sk->bound_dev_if)
- dev = dev_get_by_index(ud->tx_ops->sk->bound_dev_if);
- len += snprintf(page + len, PAGE_SIZE - len,
- " / sk %p / socket %p", ud->tx_ops->sk, ud->tx_ops->sk->socket);
- }
-
- if (dev) {
- len += snprintf(page + len, PAGE_SIZE - len, " / %s", dev->name);
- dev_put(dev);
- }
+ int len = 0;
+ struct bcm_user_data *ud = (struct bcm_user_data *) data;
+ struct bcm_op *op;
+ struct net_device *dev = NULL;
- len += snprintf(page + len, PAGE_SIZE - len, " <<<\n");
+ MOD_INC_USE_COUNT;
- for (op = ud->rx_ops; op && (len < PAGE_SIZE - 100); op = op->next) {
+ len += snprintf(page + len, PAGE_SIZE - len,">>> ud %p", ud);
- unsigned long reduction;
+ if (ud->rx_ops) {
+ if (ud->rx_ops->sk->bound_dev_if)
+ dev = dev_get_by_index(ud->rx_ops->sk->bound_dev_if);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " / sk %p / socket %p", ud->rx_ops->sk, ud->rx_ops->sk->socket);
+ }
+ else
+ if (ud->tx_ops) {
+ if (ud->tx_ops->sk->bound_dev_if)
+ dev = dev_get_by_index(ud->tx_ops->sk->bound_dev_if);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " / sk %p / socket %p", ud->tx_ops->sk, ud->tx_ops->sk->socket);
+ }
- /* print only active entries & prevent division by zero */
- if (!op->frames_abs)
- continue;
+ if (dev) {
+ len += snprintf(page + len, PAGE_SIZE - len, " / %s", dev->name);
+ dev_put(dev);
+ }
- len += snprintf(page + len, PAGE_SIZE - len, "rx_op: %03X [%d]%c ",
- op->can_id, op->nframes,(op->flags & RX_CHECK_DLC)?'d':' ');
- if (op->j_ival1)
- len += snprintf(page + len, PAGE_SIZE - len, "timeo=%ld ", op->j_ival1);
+ len += snprintf(page + len, PAGE_SIZE - len, " <<<\n");
- if (op->j_ival2)
- len += snprintf(page + len, PAGE_SIZE - len, "thr=%ld ", op->j_ival2);
+ for (op = ud->rx_ops; op && (len < PAGE_SIZE - 100); op = op->next) {
- len += snprintf(page + len, PAGE_SIZE - len, "# recv %ld (%ld) => reduction: ",
- op->frames_filtered, op->frames_abs);
+ unsigned long reduction;
- reduction = 100 - (op->frames_filtered * 100) / op->frames_abs;
+ /* print only active entries & prevent division by zero */
+ if (!op->frames_abs)
+ continue;
- len += snprintf(page + len, PAGE_SIZE - len, "%s%ld%%\n",
- (reduction == 100)?"near ":"", reduction);
+ len += snprintf(page + len, PAGE_SIZE - len, "rx_op: %03X [%d]%c ",
+ op->can_id, op->nframes,(op->flags & RX_CHECK_DLC)?'d':' ');
+ if (op->j_ival1)
+ len += snprintf(page + len, PAGE_SIZE - len, "timeo=%ld ", op->j_ival1);
- if (len > PAGE_SIZE - 100) /* 100 Bytes before end of buffer */
- len += snprintf(page + len, PAGE_SIZE - len, "(..)\n"); /* mark output cutted off */
- }
+ if (op->j_ival2)
+ len += snprintf(page + len, PAGE_SIZE - len, "thr=%ld ", op->j_ival2);
- for (op = ud->tx_ops; op && (len < PAGE_SIZE - 100); op = op->next) {
+ len += snprintf(page + len, PAGE_SIZE - len, "# recv %ld (%ld) => reduction: ",
+ op->frames_filtered, op->frames_abs);
- len += snprintf(page + len, PAGE_SIZE - len, "tx_op: %03X [%d] ",
- op->can_id, op->nframes);
- if (op->j_ival1)
- len += snprintf(page + len, PAGE_SIZE - len, "t1=%ld ", op->j_ival1);
+ reduction = 100 - (op->frames_filtered * 100) / op->frames_abs;
- if (op->j_ival2)
- len += snprintf(page + len, PAGE_SIZE - len, "t2=%ld ", op->j_ival2);
+ len += snprintf(page + len, PAGE_SIZE - len, "%s%ld%%\n",
+ (reduction == 100)?"near ":"", reduction);
- len += snprintf(page + len, PAGE_SIZE - len, "# sent %ld\n", op->frames_abs);
+ if (len > PAGE_SIZE - 100) /* 100 Bytes before end of buffer */
+ len += snprintf(page + len, PAGE_SIZE - len, "(..)\n"); /* mark output cutted off */
+ }
+
+ for (op = ud->tx_ops; op && (len < PAGE_SIZE - 100); op = op->next) {
+
+ len += snprintf(page + len, PAGE_SIZE - len, "tx_op: %03X [%d] ",
+ op->can_id, op->nframes);
+ if (op->j_ival1)
+ len += snprintf(page + len, PAGE_SIZE - len, "t1=%ld ", op->j_ival1);
- if (len > PAGE_SIZE - 100) /* 100 Bytes before end of buffer */
- len += snprintf(page + len, PAGE_SIZE - len, "(..)\n"); /* mark output cutted off */
- }
+ if (op->j_ival2)
+ len += snprintf(page + len, PAGE_SIZE - len, "t2=%ld ", op->j_ival2);
- len += snprintf(page + len, PAGE_SIZE - len, "\n");
+ len += snprintf(page + len, PAGE_SIZE - len, "# sent %ld\n", op->frames_abs);
+
+ if (len > PAGE_SIZE - 100) /* 100 Bytes before end of buffer */
+ len += snprintf(page + len, PAGE_SIZE - len, "(..)\n"); /* mark output cutted off */
+ }
- MOD_DEC_USE_COUNT;
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
- *eof = 1;
- return len;
+ MOD_DEC_USE_COUNT;
+
+ *eof = 1;
+ return len;
}
static unsigned int bcm_poll(struct file *file, struct socket *sock,
poll_table *wait)
{
- unsigned int mask = 0;
+ unsigned int mask = 0;
- DBG("socket %p\n", sock);
+ DBG("socket %p\n", sock);
- mask = datagram_poll(file, sock, wait);
- return mask;
+ mask = datagram_poll(file, sock, wait);
+ return mask;
}
static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, int size,
struct scm_cookie *scm)
{
- struct bcm_msg_head msg_head;
- int i;
- struct bcm_op *op;
- int err;
- struct sock *sk = sock->sk;
- struct bcm_user_data *ud = bcm_sk(sk);
- char c;
- int rbytes = 0; /* read bytes as return value */
-
- /* read message head information */
-
- if ((err = memcpy_fromiovec((unsigned char*)&msg_head, msg->msg_iov,
- sizeof(msg_head))) < 0)
- return err;
-
- DBG("opcode %d for can_id <%03X>\n", msg_head.opcode, msg_head.can_id);
-
- if (!sk->bound_dev_if) {
- DBG("sock %p not bound\n", sk); /* and therefore ud not initialized */
- return -ENOTCONN;
- }
+ struct bcm_msg_head msg_head;
+ int i;
+ struct bcm_op *op;
+ int err;
+ struct sock *sk = sock->sk;
+ struct bcm_user_data *ud = bcm_sk(sk);
+ char c;
+ int rbytes = 0; /* read bytes as return value */
+
+ /* read message head information */
+
+ if ((err = memcpy_fromiovec((unsigned char*)&msg_head, msg->msg_iov,
+ sizeof(msg_head))) < 0)
+ return err;
+
+ DBG("opcode %d for can_id <%03X>\n", msg_head.opcode, msg_head.can_id);
+
+ if (!sk->bound_dev_if) {
+ DBG("sock %p not bound\n", sk); /* and therefore ud not initialized */
+ return -ENOTCONN;
+ }
- switch (msg_head.opcode) {
+ switch (msg_head.opcode) {
- case TX_SETUP:
+ case TX_SETUP:
- if (msg_head.nframes < 1) /* we need at least one can_frame */
- return -EINVAL;
+ if (msg_head.nframes < 1) /* we need at least one can_frame */
+ return -EINVAL;
- /* check the given can_id */
+ /* check the given can_id */
- if (!(op = bcm_find_op(ud->tx_ops, msg_head.can_id))) {
+ if (!(op = bcm_find_op(ud->tx_ops, msg_head.can_id))) {
- /* insert new BCM operation for the given can_id */
+ /* insert new BCM operation for the given can_id */
- if (!(op = kmalloc(sizeof(struct bcm_op), GFP_KERNEL)))
- return -ENOMEM;
+ if (!(op = kmalloc(sizeof(struct bcm_op), GFP_KERNEL)))
+ return -ENOMEM;
- memset(op, 0, sizeof(struct bcm_op)); /* init to zero, e.g. for timers */
+ memset(op, 0, sizeof(struct bcm_op)); /* init to zero, e.g. for timers */
- DBG("TX_SETUP: creating new tx_op (%p) for can_id <%03X>\n",
- op, msg_head.can_id);
+ DBG("TX_SETUP: creating new tx_op (%p) for can_id <%03X>\n",
+ op, msg_head.can_id);
- op->can_id = msg_head.can_id;
+ op->can_id = msg_head.can_id;
- /* create array for can_frames and copy the data */
- if (!(op->frames = kmalloc(msg_head.nframes * sizeof(struct can_frame), GFP_KERNEL))) {
- kfree(op);
- return -ENOMEM;
- }
+ /* create array for can_frames and copy the data */
+ if (!(op->frames = kmalloc(msg_head.nframes * sizeof(struct can_frame), GFP_KERNEL))) {
+ kfree(op);
+ return -ENOMEM;
+ }
- for (i = 0; i < msg_head.nframes; i++) {
- memcpy_fromiovec((unsigned char*)&op->frames[i], msg->msg_iov, sizeof(struct can_frame));
- if (msg_head.flags & TX_CP_CAN_ID)
- op->frames[i].can_id = msg_head.can_id; /* copy can_id into frame */
- }
+ for (i = 0; i < msg_head.nframes; i++) {
+ memcpy_fromiovec((unsigned char*)&op->frames[i], msg->msg_iov, sizeof(struct can_frame));
+ if (msg_head.flags & TX_CP_CAN_ID)
+ op->frames[i].can_id = msg_head.can_id; /* copy can_id into frame */
+ }
- op->last_frames = NULL; /* tx_ops never compare with previous received messages */
+ op->last_frames = NULL; /* tx_ops never compare with previous received messages */
- op->sk = sk; /* bcm_can_tx / bcm_tx_timeout_handler needs this */
+ op->sk = sk; /* bcm_can_tx / bcm_tx_timeout_handler needs this */
- init_timer(&op->timer); /* initialize uninitialized (kmalloc) structure */
- init_timer(&op->thrtimer); /* currently unused in tx_ops */
+ init_timer(&op->timer); /* initialize uninitialized (kmalloc) structure */
+ init_timer(&op->thrtimer); /* currently unused in tx_ops */
- op->timer.function = bcm_tx_timeout_handler; /* handler for tx_ops */
- op->timer.data = (unsigned long)op; /* timer.data points to this op-structure */
+ op->timer.function = bcm_tx_timeout_handler; /* handler for tx_ops */
+ op->timer.data = (unsigned long)op; /* timer.data points to this op-structure */
- /* add this bcm_op to the list of the tx_ops */
- bcm_insert_op(&ud->tx_ops, op);
+ /* add this bcm_op to the list of the tx_ops */
+ bcm_insert_op(&ud->tx_ops, op);
- }
- else {
- /* update existing BCM operation */
+ } else {
+ /* update existing BCM operation */
- DBG("TX_SETUP: modifying existing tx_op (%p) for can_id <%03X>\n",
- op, msg_head.can_id);
+ DBG("TX_SETUP: modifying existing tx_op (%p) for can_id <%03X>\n",
+ op, msg_head.can_id);
- /* do we need more space for the can_frames? */
- if (msg_head.nframes > op->nframes) {
+ /* do we need more space for the can_frames? */
+ if (msg_head.nframes > op->nframes) {
- /* yes => create new array */
+ /* yes => create new array */
- struct can_frame *p;
- if (!(p = kmalloc(msg_head.nframes * sizeof(struct can_frame), GFP_KERNEL)))
- return -ENOMEM;
+ struct can_frame *p;
+ if (!(p = kmalloc(msg_head.nframes * sizeof(struct can_frame), GFP_KERNEL)))
+ return -ENOMEM;
- kfree (op->frames);
- op->frames = p;
- }
+ kfree (op->frames);
+ op->frames = p;
+ }
- /* update can_frames content */
- for (i = 0; i < msg_head.nframes; i++) {
- memcpy_fromiovec((unsigned char*)&op->frames[i], msg->msg_iov, sizeof(struct can_frame));
- if (msg_head.flags & TX_CP_CAN_ID)
- op->frames[i].can_id = msg_head.can_id; /* copy can_id into frame */
- }
+ /* update can_frames content */
+ for (i = 0; i < msg_head.nframes; i++) {
+ memcpy_fromiovec((unsigned char*)&op->frames[i], msg->msg_iov, sizeof(struct can_frame));
+ if (msg_head.flags & TX_CP_CAN_ID)
+ op->frames[i].can_id = msg_head.can_id; /* copy can_id into frame */
+ }
- }
-
- if (op->nframes != msg_head.nframes) {
- op->nframes = msg_head.nframes;
- op->currframe = 0; /* start multiple frame transmission with index 0 */
- }
-
- /* check flags */
+ }
- op->flags = msg_head.flags;
+ if (op->nframes != msg_head.nframes) {
+ op->nframes = msg_head.nframes;
+ op->currframe = 0; /* start multiple frame transmission with index 0 */
+ }
- if (op->flags & TX_RESET_MULTI_IDX)
- op->currframe = 0; /* start multiple frame transmission with index 0 */
+ /* check flags */
- if (op->flags & SETTIMER) {
+ op->flags = msg_head.flags;
- /* set timer values */
+ if (op->flags & TX_RESET_MULTI_IDX)
+ op->currframe = 0; /* start multiple frame transmission with index 0 */
- op->count = msg_head.count;
- op->ival1 = msg_head.ival1;
- op->ival2 = msg_head.ival2;
- op->j_ival1 = timeval2jiffies(&msg_head.ival1, 1);
- op->j_ival2 = timeval2jiffies(&msg_head.ival2, 1);
+ if (op->flags & SETTIMER) {
- DBG("TX_SETUP: SETTIMER count=%d j_ival1=%ld j_ival2=%ld\n",
- op->count, op->j_ival1, op->j_ival2);
+ /* set timer values */
- /* disable an active timer due to zero values? */
- if (!op->j_ival1 && !op->j_ival2) {
- del_timer(&op->timer);
- DBG("TX_SETUP: SETTIMER disabled timer.\n");
- }
+ op->count = msg_head.count;
+ op->ival1 = msg_head.ival1;
+ op->ival2 = msg_head.ival2;
+ op->j_ival1 = timeval2jiffies(&msg_head.ival1, 1);
+ op->j_ival2 = timeval2jiffies(&msg_head.ival2, 1);
- }
+ DBG("TX_SETUP: SETTIMER count=%d j_ival1=%ld j_ival2=%ld\n",
+ op->count, op->j_ival1, op->j_ival2);
- if ((op->flags & STARTTIMER) && ((op->j_ival1 && op->count) || op->j_ival2)) {
+ /* disable an active timer due to zero values? */
+ if (!op->j_ival1 && !op->j_ival2) {
+ del_timer(&op->timer);
+ DBG("TX_SETUP: SETTIMER disabled timer.\n");
+ }
- del_timer(&op->timer);
-
- op->flags |= TX_ANNOUNCE; /* spec: send can_frame when starting timer */
- if (op->j_ival1 && (op->count > 0)){
- op->timer.expires = jiffies + op->j_ival1;
- /* op->count-- is done in bcm_tx_timeout_handler */
- DBG("TX_SETUP: adding timer ival1. func=%p data=(%p) exp=0x%08X\n",
- op->timer.function,
- (char*) op->timer.data,
- (unsigned int) op->timer.expires);
- }
- else{
- op->timer.expires = jiffies + op->j_ival2;
- DBG("TX_SETUP: adding timer ival2. func=%p data=(%p) exp=0x%08X\n",
- op->timer.function,
- (char*) op->timer.data,
- (unsigned int) op->timer.expires);
- }
+ }
- add_timer(&op->timer);
- }
+ if ((op->flags & STARTTIMER) && ((op->j_ival1 && op->count) || op->j_ival2)) {
+
+ del_timer(&op->timer);
+
+ op->flags |= TX_ANNOUNCE; /* spec: send can_frame when starting timer */
+ if (op->j_ival1 && (op->count > 0)){
+ op->timer.expires = jiffies + op->j_ival1;
+ /* op->count-- is done in bcm_tx_timeout_handler */
+ DBG("TX_SETUP: adding timer ival1. func=%p data=(%p) exp=0x%08X\n",
+ op->timer.function,
+ (char*) op->timer.data,
+ (unsigned int) op->timer.expires);
+ } else{
+ op->timer.expires = jiffies + op->j_ival2;
+ DBG("TX_SETUP: adding timer ival2. func=%p data=(%p) exp=0x%08X\n",
+ op->timer.function,
+ (char*) op->timer.data,
+ (unsigned int) op->timer.expires);
+ }
+
+ add_timer(&op->timer);
+ }
- if (op->flags & TX_ANNOUNCE)
- bcm_can_tx(op);
+ if (op->flags & TX_ANNOUNCE)
+ bcm_can_tx(op);
- rbytes = msg_head.nframes * sizeof(struct can_frame) + sizeof(struct bcm_msg_head);
+ rbytes = msg_head.nframes * sizeof(struct can_frame) + sizeof(struct bcm_msg_head);
- break; /* TX_SETUP */
+ break; /* TX_SETUP */
- case TX_DELETE:
+ case TX_DELETE:
- bcm_delete_tx_op(&ud->tx_ops, msg_head.can_id);
+ bcm_delete_tx_op(&ud->tx_ops, msg_head.can_id);
- rbytes = sizeof(struct bcm_msg_head);
+ rbytes = sizeof(struct bcm_msg_head);
- break; /* TX_DELETE */
+ break; /* TX_DELETE */
- case TX_READ:
+ case TX_READ:
- /* reuse msg_head for the reply */
- msg_head.opcode = TX_STATUS; /* reply to TX_READ */
- op = bcm_find_op(ud->tx_ops, msg_head.can_id);
- c = 'T'; /* for nice debug output ... */
+ /* reuse msg_head for the reply */
+ msg_head.opcode = TX_STATUS; /* reply to TX_READ */
+ op = bcm_find_op(ud->tx_ops, msg_head.can_id);
+ c = 'T'; /* for nice debug output ... */
- goto TRX_READ;
+ goto TRX_READ;
- case RX_READ:
+ case RX_READ:
- /* reuse msg_head for the reply */
- msg_head.opcode = RX_STATUS; /* reply to RX_READ */
- op = bcm_find_op(ud->rx_ops, msg_head.can_id);
- c = 'R'; /* for nice debug output ... */
+ /* reuse msg_head for the reply */
+ msg_head.opcode = RX_STATUS; /* reply to RX_READ */
+ op = bcm_find_op(ud->rx_ops, msg_head.can_id);
+ c = 'R'; /* for nice debug output ... */
- TRX_READ:
+ TRX_READ:
- /* check the given can_id */
+ /* check the given can_id */
- if (!op) {
- DBG("%cX_READ: did not find op for can_id <%03X>\n",
- c, msg_head.can_id);
+ if (!op) {
+ DBG("%cX_READ: did not find op for can_id <%03X>\n",
+ c, msg_head.can_id);
- msg_head.flags |= CMD_ERROR;
- msg_head.nframes = 0;
- bcm_send_to_user(sk, &msg_head, NULL, NULL);
- }
- else {
- DBG("%cX_READ: sending status for can_id <%03X>\n",
- c, msg_head.can_id);
-
- /* put current values into msg_head */
- msg_head.flags = op->flags;
- msg_head.count = op->count;
- msg_head.ival1 = op->ival1;
- msg_head.ival2 = op->ival2;
- msg_head.nframes = op->nframes;
-
- bcm_send_to_user(sk, &msg_head, op->frames, NULL);
- }
+ msg_head.flags |= CMD_ERROR;
+ msg_head.nframes = 0;
+ bcm_send_to_user(sk, &msg_head, NULL, NULL);
+ }
+ else {
+ DBG("%cX_READ: sending status for can_id <%03X>\n",
+ c, msg_head.can_id);
+
+ /* put current values into msg_head */
+ msg_head.flags = op->flags;
+ msg_head.count = op->count;
+ msg_head.ival1 = op->ival1;
+ msg_head.ival2 = op->ival2;
+ msg_head.nframes = op->nframes;
+
+ bcm_send_to_user(sk, &msg_head, op->frames, NULL);
+ }
- rbytes = sizeof(struct bcm_msg_head);
+ rbytes = sizeof(struct bcm_msg_head);
- break; /* [T|R]X_READ */
+ break; /* [T|R]X_READ */
- case TX_SEND:
+ case TX_SEND:
{
- struct sk_buff *skb;
- struct net_device *dev;
+ struct sk_buff *skb;
+ struct net_device *dev;
- /* just copy and send one can_frame */
+ /* just copy and send one can_frame */
- if (msg_head.nframes < 1) /* we need at least one can_frame */
- return -EINVAL;
+ if (msg_head.nframes < 1) /* we need at least one can_frame */
+ return -EINVAL;
- skb = alloc_skb(sizeof(struct can_frame), GFP_KERNEL);
+ skb = alloc_skb(sizeof(struct can_frame), GFP_KERNEL);
- if (!skb)
- break;
+ if (!skb)
+ break;
- memcpy_fromiovec(skb_put(skb, sizeof(struct can_frame)), msg->msg_iov, sizeof(struct can_frame));
+ memcpy_fromiovec(skb_put(skb, sizeof(struct can_frame)), msg->msg_iov, sizeof(struct can_frame));
- DBG_FRAME("BCM: TX_SEND: sending frame",
- (struct can_frame *)skb->data);
- dev = dev_get_by_index(sk->bound_dev_if);
+ DBG_FRAME("BCM: TX_SEND: sending frame",
+ (struct can_frame *)skb->data);
+ dev = dev_get_by_index(sk->bound_dev_if);
- if (dev) {
- skb->dev = dev;
- can_send(skb);
- dev_put(dev);
- }
+ if (dev) {
+ skb->dev = dev;
+ can_send(skb);
+ dev_put(dev);
+ }
- rbytes = sizeof(struct can_frame) + sizeof(struct bcm_msg_head);
+ rbytes = sizeof(struct can_frame) + sizeof(struct bcm_msg_head);
}
break;
- case RX_SETUP:
+ case RX_SETUP:
- if ((msg_head.flags & RX_FILTER_ID) || (!(msg_head.nframes))) {
- /* be robust against wrong usage ... */
- msg_head.flags |= RX_FILTER_ID;
- msg_head.nframes = 0; /* ignore trailing garbage */
- }
+ if ((msg_head.flags & RX_FILTER_ID) || (!(msg_head.nframes))) {
+ /* be robust against wrong usage ... */
+ msg_head.flags |= RX_FILTER_ID;
+ msg_head.nframes = 0; /* ignore trailing garbage */
+ }
- if ((msg_head.flags & RX_RTR_FRAME) &&
- ((msg_head.nframes != 1) || (!(msg_head.can_id & CAN_RTR_FLAG)))) {
+ if ((msg_head.flags & RX_RTR_FRAME) &&
+ ((msg_head.nframes != 1) || (!(msg_head.can_id & CAN_RTR_FLAG)))) {
- DBG("RX_SETUP: bad RX_RTR_FRAME setup!\n");
+ DBG("RX_SETUP: bad RX_RTR_FRAME setup!\n");
- msg_head.flags |= CMD_ERROR; /* return msg_head back to sender */
- msg_head.nframes = 0;
- bcm_send_to_user(sk, &msg_head, NULL, NULL);
+ msg_head.flags |= CMD_ERROR; /* return msg_head back to sender */
+ msg_head.nframes = 0;
+ bcm_send_to_user(sk, &msg_head, NULL, NULL);
- rbytes = sizeof(struct bcm_msg_head);
+ rbytes = sizeof(struct bcm_msg_head);
- break;
- }
+ break;
+ }
- /* check the given can_id */
+ /* check the given can_id */
- if (!(op = bcm_find_op(ud->rx_ops, msg_head.can_id))) {
+ if (!(op = bcm_find_op(ud->rx_ops, msg_head.can_id))) {
- /* insert new BCM operation for the given can_id */
+ /* insert new BCM operation for the given can_id */
- if (!(op = kmalloc(sizeof(struct bcm_op), GFP_KERNEL)))
- return -ENOMEM;
+ if (!(op = kmalloc(sizeof(struct bcm_op), GFP_KERNEL)))
+ return -ENOMEM;
- memset(op, 0, sizeof(struct bcm_op)); /* init to zero, e.g. for timers */
+ memset(op, 0, sizeof(struct bcm_op)); /* init to zero, e.g. for timers */
- DBG("RX_SETUP: creating new rx_op (%p) for can_id <%03X>\n",
- op, msg_head.can_id);
+ DBG("RX_SETUP: creating new rx_op (%p) for can_id <%03X>\n",
+ op, msg_head.can_id);
- op->can_id = msg_head.can_id;
- op->nframes = msg_head.nframes;
+ op->can_id = msg_head.can_id;
+ op->nframes = msg_head.nframes;
- if (op->nframes) {
+ if (op->nframes) {
- /* create array for can_frames and copy the data */
- if (!(op->frames = kmalloc(msg_head.nframes * sizeof(struct can_frame), GFP_KERNEL))) {
- kfree(op);
- return -ENOMEM;
- }
+ /* create array for can_frames and copy the data */
+ if (!(op->frames = kmalloc(msg_head.nframes * sizeof(struct can_frame), GFP_KERNEL))) {
+ kfree(op);
+ return -ENOMEM;
+ }
- for (i = 0; i < msg_head.nframes; i++)
- memcpy_fromiovec((unsigned char*)&op->frames[i], msg->msg_iov, sizeof(struct can_frame));
+ for (i = 0; i < msg_head.nframes; i++)
+ memcpy_fromiovec((unsigned char*)&op->frames[i], msg->msg_iov, sizeof(struct can_frame));
- /* create array for received can_frames */
- if (!(op->last_frames = kmalloc(msg_head.nframes * sizeof(struct can_frame), GFP_KERNEL))) {
- kfree(op->frames);
- kfree(op);
- return -ENOMEM;
- }
+ /* create array for received can_frames */
+ if (!(op->last_frames = kmalloc(msg_head.nframes * sizeof(struct can_frame), GFP_KERNEL))) {
+ kfree(op->frames);
+ kfree(op);
+ return -ENOMEM;
+ }
- /* clear received can_frames to indicate 'nothing received' */
- memset(op->last_frames, 0, msg_head.nframes * sizeof(struct can_frame));
- }
- else {
- op->frames = NULL;
-
- /* even when we have the RX_FILTER_ID case, we need to store the last frame */
- /* for the throttle functionality */
-
- /* create array for received can_frames */
- if (!(op->last_frames = kmalloc(sizeof(struct can_frame), GFP_KERNEL))) {
- kfree(op);
- return -ENOMEM;
- }
+ /* clear received can_frames to indicate 'nothing received' */
+ memset(op->last_frames, 0, msg_head.nframes * sizeof(struct can_frame));
+ } else {
+ op->frames = NULL;
- /* clear received can_frames to indicate 'nothing received' */
- memset(op->last_frames, 0, sizeof(struct can_frame));
- }
+ /* even when we have the RX_FILTER_ID case, we need to store the last frame */
+ /* for the throttle functionality */
- op->sk = sk; /* bcm_delete_rx_op() needs this */
+ /* create array for received can_frames */
+ if (!(op->last_frames = kmalloc(sizeof(struct can_frame), GFP_KERNEL))) {
+ kfree(op);
+ return -ENOMEM;
+ }
- init_timer(&op->timer); /* initialize uninitialized (kmalloc) structure */
- init_timer(&op->thrtimer); /* init throttle timer for RX_CHANGED */
+ /* clear received can_frames to indicate 'nothing received' */
+ memset(op->last_frames, 0, sizeof(struct can_frame));
+ }
- op->timer.function = bcm_rx_timeout_handler; /* handler for rx timeouts */
- op->timer.data = (unsigned long)op; /* timer.data points to this op-structure */
+ op->sk = sk; /* bcm_delete_rx_op() needs this */
- op->thrtimer.function = bcm_rx_thr_handler; /* handler for RX_CHANGED throttle timeouts */
- op->thrtimer.data = (unsigned long)op; /* timer.data points to this op-structure */
- op->thrtimer.expires = 0; /* mark disabled timer */
+ init_timer(&op->timer); /* initialize uninitialized (kmalloc) structure */
+ init_timer(&op->thrtimer); /* init throttle timer for RX_CHANGED */
- /* add this bcm_op to the list of the tx_ops */
- bcm_insert_op(&ud->rx_ops, op);
+ op->timer.function = bcm_rx_timeout_handler; /* handler for rx timeouts */
+ op->timer.data = (unsigned long)op; /* timer.data points to this op-structure */
- c=1; /* call can_rx_register() at end of RX_SETUP */
+ op->thrtimer.function = bcm_rx_thr_handler; /* handler for RX_CHANGED throttle timeouts */
+ op->thrtimer.data = (unsigned long)op; /* timer.data points to this op-structure */
+ op->thrtimer.expires = 0; /* mark disabled timer */
- }
- else {
- /* update existing BCM operation */
+ /* add this bcm_op to the list of the tx_ops */
+ bcm_insert_op(&ud->rx_ops, op);
- DBG("RX_SETUP: modifying existing rx_op (%p) for can_id <%03X>\n",
- op, msg_head.can_id);
+ c=1; /* call can_rx_register() at end of RX_SETUP */
- /* do we need more space for the can_frames? */
- if (msg_head.nframes > op->nframes) {
+ } else {
+ /* update existing BCM operation */
- /* yes => create new arrays */
+ DBG("RX_SETUP: modifying existing rx_op (%p) for can_id <%03X>\n",
+ op, msg_head.can_id);
- struct can_frame *p;
+ /* do we need more space for the can_frames? */
+ if (msg_head.nframes > op->nframes) {
- if (!(p = kmalloc(msg_head.nframes * sizeof(struct can_frame), GFP_KERNEL)))
- return -ENOMEM;
+ /* yes => create new arrays */
- if (op->frames)
- kfree (op->frames);
- op->frames = p;
+ struct can_frame *p;
- if (!(p = kmalloc(msg_head.nframes * sizeof(struct can_frame), GFP_KERNEL)))
- return -ENOMEM;
- if (op->last_frames)
- kfree (op->last_frames);
- op->last_frames = p;
- }
+ if (!(p = kmalloc(msg_head.nframes * sizeof(struct can_frame), GFP_KERNEL)))
+ return -ENOMEM;
- if (msg_head.nframes) {
- /* update can_frames content */
- for (i = 0; i < msg_head.nframes; i++)
- memcpy_fromiovec((unsigned char*)&op->frames[i], msg->msg_iov, sizeof(struct can_frame));
+ if (op->frames)
+ kfree (op->frames);
+ op->frames = p;
- /* clear received can_frames to indicate 'nothing received' */
- memset(op->last_frames, 0, msg_head.nframes * sizeof(struct can_frame));
- }
+ if (!(p = kmalloc(msg_head.nframes * sizeof(struct can_frame), GFP_KERNEL)))
+ return -ENOMEM;
+ if (op->last_frames)
+ kfree (op->last_frames);
+ op->last_frames = p;
+ }
- op->nframes = msg_head.nframes;
- c=0; /* do not call can_rx_register() at end of RX_SETUP */
+ if (msg_head.nframes) {
+ /* update can_frames content */
+ for (i = 0; i < msg_head.nframes; i++)
+ memcpy_fromiovec((unsigned char*)&op->frames[i], msg->msg_iov, sizeof(struct can_frame));
- } /* if (!bcm_find_op(ud->tx_ops, msg_head.can_id)) */
+ /* clear received can_frames to indicate 'nothing received' */
+ memset(op->last_frames, 0, msg_head.nframes * sizeof(struct can_frame));
+ }
+ op->nframes = msg_head.nframes;
+ c=0; /* do not call can_rx_register() at end of RX_SETUP */
- /* check flags */
+ } /* if (!bcm_find_op(ud->tx_ops, msg_head.can_id)) */
- op->flags = msg_head.flags;
- if (op->flags & RX_RTR_FRAME) {
+ /* check flags */
- /* no timers in RTR-mode */
- del_timer(&op->thrtimer);
- del_timer(&op->timer);
+ op->flags = msg_head.flags;
- /* funny feature in RX(!)_SETUP only for RTR-mode: */
- /* copy can_id into frame BUT without RTR-flag to */
- /* prevent a full-load-loopback-test ... ;-] */
- if ((op->flags & TX_CP_CAN_ID) ||
- (op->frames[0].can_id == op->can_id))
- op->frames[0].can_id = op->can_id & ~CAN_RTR_FLAG;
+ if (op->flags & RX_RTR_FRAME) {
- }
- else {
- if (op->flags & SETTIMER) {
+ /* no timers in RTR-mode */
+ del_timer(&op->thrtimer);
+ del_timer(&op->timer);
- /* set timer value */
+ /* funny feature in RX(!)_SETUP only for RTR-mode: */
+ /* copy can_id into frame BUT without RTR-flag to */
+ /* prevent a full-load-loopback-test ... ;-] */
+ if ((op->flags & TX_CP_CAN_ID) ||
+ (op->frames[0].can_id == op->can_id))
+ op->frames[0].can_id = op->can_id & ~CAN_RTR_FLAG;
- op->ival1 = msg_head.ival1;
- op->j_ival1 = timeval2jiffies(&msg_head.ival1, 1);
- op->ival2 = msg_head.ival2;
- op->j_ival2 = timeval2jiffies(&msg_head.ival2, 1);
+ } else {
+ if (op->flags & SETTIMER) {
- DBG("RX_SETUP: SETTIMER j_ival1=%ld j_ival2=%ld\n",
- op->j_ival1, op->j_ival2);
+ /* set timer value */
- /* disable an active timer due to zero value? */
- if (!op->j_ival1) {
- del_timer(&op->timer);
- DBG("RX_SETUP: disabled timer for rx timeouts.\n");
- }
+ op->ival1 = msg_head.ival1;
+ op->j_ival1 = timeval2jiffies(&msg_head.ival1, 1);
+ op->ival2 = msg_head.ival2;
+ op->j_ival2 = timeval2jiffies(&msg_head.ival2, 1);
- /* free currently blocked msgs ? */
- if (op->thrtimer.expires) { /* running throttle timer? */
- DBG("RX_SETUP: unblocking throttled msgs.\n");
- del_timer(&op->thrtimer);
- op->thrtimer.expires = jiffies + 2; /* send blocked msgs hereafter */
- add_timer(&op->thrtimer);
- }
- /* if (op->j_ival2) is zero, no (new) throttling will happen */
- /* see bcm_rx_update_and_send() and bcm_rx_thr_handler() */
- }
+ DBG("RX_SETUP: SETTIMER j_ival1=%ld j_ival2=%ld\n",
+ op->j_ival1, op->j_ival2);
- if ((op->flags & STARTTIMER) && op->j_ival1) {
+ /* disable an active timer due to zero value? */
+ if (!op->j_ival1) {
+ del_timer(&op->timer);
+ DBG("RX_SETUP: disabled timer for rx timeouts.\n");
+ }
- del_timer(&op->timer);
+ /* free currently blocked msgs ? */
+ if (op->thrtimer.expires) { /* running throttle timer? */
+ DBG("RX_SETUP: unblocking throttled msgs.\n");
+ del_timer(&op->thrtimer);
+ op->thrtimer.expires = jiffies + 2; /* send blocked msgs hereafter */
+ add_timer(&op->thrtimer);
+ }
+ /* if (op->j_ival2) is zero, no (new) throttling will happen */
+ /* see bcm_rx_update_and_send() and bcm_rx_thr_handler() */
+ }
- op->timer.expires = jiffies + op->j_ival1;
+ if ((op->flags & STARTTIMER) && op->j_ival1) {
- DBG("RX_SETUP: adding timer ival1. func=%p data=(%p) exp=0x%08X\n",
- (char *) op->timer.function,
- (char *) op->timer.data,
- (unsigned int) op->timer.expires);
+ del_timer(&op->timer);
- add_timer(&op->timer);
- }
- }
+ op->timer.expires = jiffies + op->j_ival1;
- /* now we can register for can_ids, if we added a new bcm_op */
- if (c) {
- struct net_device *dev = dev_get_by_index(sk->bound_dev_if);
+ DBG("RX_SETUP: adding timer ival1. func=%p data=(%p) exp=0x%08X\n",
+ (char *) op->timer.function,
+ (char *) op->timer.data,
+ (unsigned int) op->timer.expires);
- DBG("RX_SETUP: can_rx_register() for can_id <%03X>. rx_op is (%p)\n", op->can_id, op);
+ add_timer(&op->timer);
+ }
+ }
- if (dev) {
- can_rx_register(dev, op->can_id, 0xFFFFFFFFU, bcm_rx_handler, op, IDENT);
- dev_put(dev);
- }
- }
+ /* now we can register for can_ids, if we added a new bcm_op */
+ if (c) {
+ struct net_device *dev = dev_get_by_index(sk->bound_dev_if);
- rbytes = msg_head.nframes * sizeof(struct can_frame) + sizeof(struct bcm_msg_head);
+ DBG("RX_SETUP: can_rx_register() for can_id <%03X>. rx_op is (%p)\n", op->can_id, op);
- break; /* RX_SETUP */
+ if (dev) {
+ can_rx_register(dev, op->can_id, 0xFFFFFFFFU, bcm_rx_handler, op, IDENT);
+ dev_put(dev);
+ }
+ }
- case RX_DELETE:
+ rbytes = msg_head.nframes * sizeof(struct can_frame) + sizeof(struct bcm_msg_head);
- bcm_delete_rx_op(&ud->rx_ops, msg_head.can_id);
+ break; /* RX_SETUP */
- rbytes = sizeof(struct bcm_msg_head);
+ case RX_DELETE:
- break; /* RX_DELETE */
+ bcm_delete_rx_op(&ud->rx_ops, msg_head.can_id);
- default:
+ rbytes = sizeof(struct bcm_msg_head);
- DBG("Unknown opcode %d\n", msg_head.opcode);
+ break; /* RX_DELETE */
- msg_head.flags |= CMD_ERROR; /* return msg_head back to sender */
- msg_head.nframes = 0;
- bcm_send_to_user(sk, &msg_head, NULL, NULL);
+ default:
- rbytes = sizeof(struct bcm_msg_head);
+ DBG("Unknown opcode %d\n", msg_head.opcode);
- break;
- }
+ msg_head.flags |= CMD_ERROR; /* return msg_head back to sender */
+ msg_head.nframes = 0;
+ bcm_send_to_user(sk, &msg_head, NULL, NULL);
+
+ rbytes = sizeof(struct bcm_msg_head);
- return rbytes;
+ break;
+ }
+
+ return rbytes;
}
static int bcm_recvmsg(struct socket *sock, struct msghdr *msg, int size,
int flags, struct scm_cookie *scm)
{
- struct sock *sk = sock->sk;
- struct sk_buff *skb;
- int error = 0;
- int noblock;
- int err;
-
- DBG("socket %p, sk %p\n", sock, sk);
-
- noblock = flags & MSG_DONTWAIT;
- flags &= ~MSG_DONTWAIT;
- if (!(skb = skb_recv_datagram(sk, flags, noblock, &error))) {
- return error;
- }
-
- DBG("delivering skbuff %p\n", skb);
- DBG_SKB(skb);
-
- if (skb->len < size)
- size = skb->len;
- if ((err = memcpy_toiovec(msg->msg_iov, skb->data, size)) < 0) {
- skb_free_datagram(sk, skb);
- return err;
- }
+ struct sock *sk = sock->sk;
+ struct sk_buff *skb;
+ int error = 0;
+ int noblock;
+ int err;
+
+ DBG("socket %p, sk %p\n", sock, sk);
+
+ noblock = flags & MSG_DONTWAIT;
+ flags &= ~MSG_DONTWAIT;
+ if (!(skb = skb_recv_datagram(sk, flags, noblock, &error))) {
+ return error;
+ }
+
+ DBG("delivering skbuff %p\n", skb);
+ DBG_SKB(skb);
+
+ if (skb->len < size)
+ size = skb->len;
+ if ((err = memcpy_toiovec(msg->msg_iov, skb->data, size)) < 0) {
+ skb_free_datagram(sk, skb);
+ return err;
+ }
- sock_recv_timestamp(msg, sk, skb);
+ sock_recv_timestamp(msg, sk, skb);
- DBG("freeing sock %p, skbuff %p\n", sk, skb);
- skb_free_datagram(sk, skb);
+ DBG("freeing sock %p, skbuff %p\n", sk, skb);
+ skb_free_datagram(sk, skb);
- return size;
+ return size;
}
static void bcm_tx_timeout_handler(unsigned long data)
{
- struct bcm_op *op = (struct bcm_op*)data;
+ struct bcm_op *op = (struct bcm_op*)data;
- DBG("Called with bcm_op (%p)\n", op);
+ DBG("Called with bcm_op (%p)\n", op);
- if (op->j_ival1 && (op->count > 0)) {
+ if (op->j_ival1 && (op->count > 0)) {
- op->count--;
+ op->count--;
- if (!op->count && (op->flags & TX_COUNTEVT)) { /* create notification to user? */
+ if (!op->count && (op->flags & TX_COUNTEVT)) { /* create notification to user? */
- struct bcm_msg_head msg_head;
+ struct bcm_msg_head msg_head;
- DBG("sending TX_EXPIRED for can_id <%03X>\n", op->can_id);
+ DBG("sending TX_EXPIRED for can_id <%03X>\n", op->can_id);
- msg_head.opcode = TX_EXPIRED;
- msg_head.flags = op->flags;
- msg_head.count = op->count;
- msg_head.ival1 = op->ival1;
- msg_head.ival2 = op->ival2;
- msg_head.can_id = op->can_id;
- msg_head.nframes = 0;
+ msg_head.opcode = TX_EXPIRED;
+ msg_head.flags = op->flags;
+ msg_head.count = op->count;
+ msg_head.ival1 = op->ival1;
+ msg_head.ival2 = op->ival2;
+ msg_head.can_id = op->can_id;
+ msg_head.nframes = 0;
- bcm_send_to_user(op->sk, &msg_head, NULL, NULL);
+ bcm_send_to_user(op->sk, &msg_head, NULL, NULL);
+ }
}
- }
- DBG("count=%d j_ival1=%ld j_ival2=%ld\n",
- op->count, op->j_ival1, op->j_ival2);
+ DBG("count=%d j_ival1=%ld j_ival2=%ld\n",
+ op->count, op->j_ival1, op->j_ival2);
- if (op->j_ival1 && (op->count > 0)) {
+ if (op->j_ival1 && (op->count > 0)) {
- op->timer.expires = jiffies + op->j_ival1;
- add_timer(&op->timer);
+ op->timer.expires = jiffies + op->j_ival1;
+ add_timer(&op->timer);
- DBG("adding timer ival1. func=%p data=(%p) exp=0x%08X\n",
- op->timer.function,
- (char*) op->timer.data,
- (unsigned int) op->timer.expires);
+ DBG("adding timer ival1. func=%p data=(%p) exp=0x%08X\n",
+ op->timer.function,
+ (char*) op->timer.data,
+ (unsigned int) op->timer.expires);
- bcm_can_tx(op); /* send (next) frame */
- }
- else {
- if (op->j_ival2) {
- op->timer.expires = jiffies + op->j_ival2;
- add_timer(&op->timer);
+ bcm_can_tx(op); /* send (next) frame */
+ } else {
+ if (op->j_ival2) {
+ op->timer.expires = jiffies + op->j_ival2;
+ add_timer(&op->timer);
- DBG("adding timer ival2. func=%p data=(%p) exp=0x%08X\n",
- op->timer.function,
- (char*) op->timer.data,
- (unsigned int) op->timer.expires);
+ DBG("adding timer ival2. func=%p data=(%p) exp=0x%08X\n",
+ op->timer.function,
+ (char*) op->timer.data,
+ (unsigned int) op->timer.expires);
- bcm_can_tx(op); /* send (next) frame */
+ bcm_can_tx(op); /* send (next) frame */
+ } else
+ DBG("no timer restart\n");
}
- else
- DBG("no timer restart\n");
- }
- return;
+ return;
}
static void bcm_rx_handler(struct sk_buff *skb, void *data)
{
- struct bcm_op *op = (struct bcm_op*)data;
- struct can_frame rxframe;
- int i;
-
- del_timer(&op->timer); /* disable timeout */
-
- DBG("Called with bcm_op (%p)\n", op);
-
- if (skb->len == sizeof(rxframe)) {
- memcpy(&rxframe, skb->data, sizeof(rxframe));
- op->stamp = skb->stamp; /* save rx timestamp */
- op->frames_abs++; /* statistics */
- kfree_skb(skb);
- DBG("got can_frame with can_id <%03X>\n", rxframe.can_id);
- }
- else {
- DBG("Wrong skb->len = %d\n", skb->len);
- kfree_skb(skb);
- return;
- }
+ struct bcm_op *op = (struct bcm_op*)data;
+ struct can_frame rxframe;
+ int i;
+
+ del_timer(&op->timer); /* disable timeout */
+
+ DBG("Called with bcm_op (%p)\n", op);
+
+ if (skb->len == sizeof(rxframe)) {
+ memcpy(&rxframe, skb->data, sizeof(rxframe));
+ op->stamp = skb->stamp; /* save rx timestamp */
+ op->frames_abs++; /* statistics */
+ kfree_skb(skb);
+ DBG("got can_frame with can_id <%03X>\n", rxframe.can_id);
+ } else {
+ DBG("Wrong skb->len = %d\n", skb->len);
+ kfree_skb(skb);
+ return;
+ }
- DBG_FRAME("BCM: bcm_rx_handler: CAN frame", &rxframe);
+ DBG_FRAME("BCM: bcm_rx_handler: CAN frame", &rxframe);
- if (op->can_id != rxframe.can_id) {
- DBG("ERROR! Got wrong can_id <%03X>! Expected <%03X>.\n",
- rxframe.can_id, op->can_id);
- return;
- }
+ if (op->can_id != rxframe.can_id) {
+ DBG("ERROR! Got wrong can_id <%03X>! Expected <%03X>.\n",
+ rxframe.can_id, op->can_id);
+ return;
+ }
- if (op->flags & RX_RTR_FRAME) { /* send reply for RTR-request */
- DBG("RTR-request\n");
- bcm_can_tx(op); /* send op->frames[0] to CAN device */
- return;
- }
+ if (op->flags & RX_RTR_FRAME) { /* send reply for RTR-request */
+ DBG("RTR-request\n");
+ bcm_can_tx(op); /* send op->frames[0] to CAN device */
+ return;
+ }
- if (op->flags & RX_FILTER_ID) { /* the easiest case */
- DBG("Easy does it with RX_FILTER_ID\n");
- bcm_rx_update_and_send(op, &op->last_frames[0], &rxframe);
- bcm_rx_starttimer(op);
- return;
- }
+ if (op->flags & RX_FILTER_ID) { /* the easiest case */
+ DBG("Easy does it with RX_FILTER_ID\n");
+ bcm_rx_update_and_send(op, &op->last_frames[0], &rxframe);
+ bcm_rx_starttimer(op);
+ return;
+ }
- if (op->nframes == 1) { /* simple compare with index 0 */
- DBG("Simple compare\n");
- bcm_rx_cmp_to_index(op, 0, &rxframe);
- bcm_rx_starttimer(op);
- return;
- }
+ if (op->nframes == 1) { /* simple compare with index 0 */
+ DBG("Simple compare\n");
+ bcm_rx_cmp_to_index(op, 0, &rxframe);
+ bcm_rx_starttimer(op);
+ return;
+ }
- if (op->nframes > 1) { /* multiplex compare */
+ if (op->nframes > 1) { /* multiplex compare */
- DBG("Multiplex compare\n");
- /* find the first multiplex mask that fits */
- /* MUX-mask is in index 0 */
+ DBG("Multiplex compare\n");
+ /* find the first multiplex mask that fits */
+ /* MUX-mask is in index 0 */
- for (i=1; i < op->nframes; i++) {
+ for (i=1; i < op->nframes; i++) {
- if ((GET_U64(&op->frames[0]) & GET_U64(&rxframe)) ==
- (GET_U64(&op->frames[0]) & GET_U64(&op->frames[i]))) {
- DBG("found MUX index %d\n", i);
- bcm_rx_cmp_to_index(op, i, &rxframe);
- break;
- }
+ if ((GET_U64(&op->frames[0]) & GET_U64(&rxframe)) ==
+ (GET_U64(&op->frames[0]) & GET_U64(&op->frames[i]))) {
+ DBG("found MUX index %d\n", i);
+ bcm_rx_cmp_to_index(op, i, &rxframe);
+ break;
+ }
+ }
+ bcm_rx_starttimer(op);
}
- bcm_rx_starttimer(op);
- }
}
static void bcm_rx_cmp_to_index(struct bcm_op *op, int index,
struct can_frame *rxdata)
{
- /* no one uses the MSBs of can_dlc for comparation, */
- /* so we use it here to detect the first time of reception */
+ /* no one uses the MSBs of can_dlc for comparation, */
+ /* so we use it here to detect the first time of reception */
- if (!(op->last_frames[index].can_dlc & RX_RECV)) { /* first time? */
- DBG("first time :)\n");
- bcm_rx_update_and_send(op, &op->last_frames[index], rxdata);
- return;
- }
+ if (!(op->last_frames[index].can_dlc & RX_RECV)) { /* first time? */
+ DBG("first time :)\n");
+ bcm_rx_update_and_send(op, &op->last_frames[index], rxdata);
+ return;
+ }
- /* do a real check in can_data */
+ /* do a real check in can_data */
- DBG("op->frames[index].data = 0x%016llx\n", GET_U64(&op->frames[index]));
- DBG("op->last_frames[index].data = 0x%016llx\n",
- GET_U64(&op->last_frames[index]));
- DBG("rxdata->data = 0x%016llx\n", GET_U64(rxdata));
+ DBG("op->frames[index].data = 0x%016llx\n", GET_U64(&op->frames[index]));
+ DBG("op->last_frames[index].data = 0x%016llx\n",
+ GET_U64(&op->last_frames[index]));
+ DBG("rxdata->data = 0x%016llx\n", GET_U64(rxdata));
- if ((GET_U64(&op->frames[index]) & GET_U64(rxdata)) !=
- (GET_U64(&op->frames[index]) & GET_U64(&op->last_frames[index]))) {
- DBG("relevant data change :)\n");
- bcm_rx_update_and_send(op, &op->last_frames[index], rxdata);
- return;
- }
+ if ((GET_U64(&op->frames[index]) & GET_U64(rxdata)) !=
+ (GET_U64(&op->frames[index]) & GET_U64(&op->last_frames[index]))) {
+ DBG("relevant data change :)\n");
+ bcm_rx_update_and_send(op, &op->last_frames[index], rxdata);
+ return;
+ }
- if (op->flags & RX_CHECK_DLC) {
+ if (op->flags & RX_CHECK_DLC) {
- /* do a real check in dlc */
+ /* do a real check in dlc */
- if (rxdata->can_dlc != (op->last_frames[index].can_dlc & BCM_CAN_DLC_MASK)) {
- DBG("dlc change :)\n");
- bcm_rx_update_and_send(op, &op->last_frames[index], rxdata);
- return;
+ if (rxdata->can_dlc != (op->last_frames[index].can_dlc & BCM_CAN_DLC_MASK)) {
+ DBG("dlc change :)\n");
+ bcm_rx_update_and_send(op, &op->last_frames[index], rxdata);
+ return;
+ }
}
- }
- DBG("no relevant change :(\n");
+ DBG("no relevant change :(\n");
}
static void bcm_rx_update_and_send(struct bcm_op *op,
struct can_frame *lastdata,
struct can_frame *rxdata)
{
- unsigned long nexttx = op->j_lastmsg + op->j_ival2;
+ unsigned long nexttx = op->j_lastmsg + op->j_ival2;
- memcpy(lastdata, rxdata, sizeof(struct can_frame));
- lastdata->can_dlc |= RX_RECV; /* mark as used */
+ memcpy(lastdata, rxdata, sizeof(struct can_frame));
+ lastdata->can_dlc |= RX_RECV; /* mark as used */
- /* throttle bcm_rx_changed ? */
- if ((op->thrtimer.expires) || /* somebody else is already waiting OR */
- ((op->j_ival2) && (nexttx > jiffies))) { /* we have to wait */
+ /* throttle bcm_rx_changed ? */
+ if ((op->thrtimer.expires) || /* somebody else is already waiting OR */
+ ((op->j_ival2) && (nexttx > jiffies))) { /* we have to wait */
- lastdata->can_dlc |= RX_THR; /* mark as 'throttled' */
+ lastdata->can_dlc |= RX_THR; /* mark as 'throttled' */
- if (!(op->thrtimer.expires)) { /* start only the first time */
- op->thrtimer.expires = nexttx;
- add_timer(&op->thrtimer);
+ if (!(op->thrtimer.expires)) { /* start only the first time */
+ op->thrtimer.expires = nexttx;
+ add_timer(&op->thrtimer);
- DBG("adding thrtimer. func=%p data=(%p) exp=0x%08X\n",
- op->thrtimer.function,
- (char*) op->thrtimer.data,
- (unsigned int) op->thrtimer.expires);
- }
- }
- else
- bcm_rx_changed(op, rxdata); /* send RX_CHANGED to the user */
+ DBG("adding thrtimer. func=%p data=(%p) exp=0x%08X\n",
+ op->thrtimer.function,
+ (char*) op->thrtimer.data,
+ (unsigned int) op->thrtimer.expires);
+ }
+ } else
+ bcm_rx_changed(op, rxdata); /* send RX_CHANGED to the user */
}
static void bcm_rx_starttimer(struct bcm_op *op)
{
- if (op->flags & RX_NO_AUTOTIMER)
- return;
+ if (op->flags & RX_NO_AUTOTIMER)
+ return;
- if (op->j_ival1) {
+ if (op->j_ival1) {
- op->timer.expires = jiffies + op->j_ival1;
+ op->timer.expires = jiffies + op->j_ival1;
- DBG("adding rx timeout timer ival1. func=%p data=(%p) exp=0x%08X\n",
- op->timer.function,
- (char*) op->timer.data,
- (unsigned int) op->timer.expires);
+ DBG("adding rx timeout timer ival1. func=%p data=(%p) exp=0x%08X\n",
+ op->timer.function,
+ (char*) op->timer.data,
+ (unsigned int) op->timer.expires);
- add_timer(&op->timer);
- }
+ add_timer(&op->timer);
+ }
}
static void bcm_rx_changed(struct bcm_op *op, struct can_frame *data)
{
- struct bcm_msg_head head;
+ struct bcm_msg_head head;
- op->j_lastmsg = jiffies;
- op->frames_filtered++; /* statistics */
+ op->j_lastmsg = jiffies;
+ op->frames_filtered++; /* statistics */
- if (op->frames_filtered > ULONG_MAX/100)
- op->frames_filtered = op->frames_abs = 0; /* restart - spinlock ? */
+ if (op->frames_filtered > ULONG_MAX/100)
+ op->frames_filtered = op->frames_abs = 0; /* restart - spinlock ? */
- DBG("setting j_lastmsg to 0x%08X for rx_op(%p)\n",
- (unsigned int) op->j_lastmsg, op);
- DBG("sending notification\n");
+ DBG("setting j_lastmsg to 0x%08X for rx_op(%p)\n",
+ (unsigned int) op->j_lastmsg, op);
+ DBG("sending notification\n");
- head.opcode = RX_CHANGED;
- head.flags = op->flags;
- head.count = op->count;
- head.ival1 = op->ival1;
- head.ival2 = op->ival2;
- head.can_id = op->can_id;
- head.nframes = 1;
+ head.opcode = RX_CHANGED;
+ head.flags = op->flags;
+ head.count = op->count;
+ head.ival1 = op->ival1;
+ head.ival2 = op->ival2;
+ head.can_id = op->can_id;
+ head.nframes = 1;
- bcm_send_to_user(op->sk, &head, data, &op->stamp);
+ bcm_send_to_user(op->sk, &head, data, &op->stamp);
}
static void bcm_rx_timeout_handler(unsigned long data)
{
- struct bcm_op *op = (struct bcm_op*)data;
- struct bcm_msg_head msg_head;
+ struct bcm_op *op = (struct bcm_op*)data;
+ struct bcm_msg_head msg_head;
- DBG("sending RX_TIMEOUT for can_id <%03X>. op is (%p)\n", op->can_id, op);
+ DBG("sending RX_TIMEOUT for can_id <%03X>. op is (%p)\n", op->can_id, op);
- msg_head.opcode = RX_TIMEOUT;
- msg_head.flags = op->flags;
- msg_head.count = op->count;
- msg_head.ival1 = op->ival1;
- msg_head.ival2 = op->ival2;
- msg_head.can_id = op->can_id;
- msg_head.nframes = 0;
+ msg_head.opcode = RX_TIMEOUT;
+ msg_head.flags = op->flags;
+ msg_head.count = op->count;
+ msg_head.ival1 = op->ival1;
+ msg_head.ival2 = op->ival2;
+ msg_head.can_id = op->can_id;
+ msg_head.nframes = 0;
- bcm_send_to_user(op->sk, &msg_head, NULL, NULL);
+ bcm_send_to_user(op->sk, &msg_head, NULL, NULL);
- /* no restart of the timer is done here! */
+ /* no restart of the timer is done here! */
- /* if the user wants to be informed, when cyclic CAN-Messages come back ... */
- if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) {
- /* clear received can_frames to indicate 'nothing received' */
- memset(op->last_frames, 0, op->nframes * sizeof(struct can_frame));
- DBG("RX_ANNOUNCE_RESTART\n");
- }
+ /* if the user wants to be informed, when cyclic CAN-Messages come back ... */
+ if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) {
+ /* clear received can_frames to indicate 'nothing received' */
+ memset(op->last_frames, 0, op->nframes * sizeof(struct can_frame));
+ DBG("RX_ANNOUNCE_RESTART\n");
+ }
}
static void bcm_rx_thr_handler(unsigned long data)
{
- struct bcm_op *op = (struct bcm_op*)data;
- int i = 0;
+ struct bcm_op *op = (struct bcm_op*)data;
+ int i = 0;
- op->thrtimer.expires = 0; /* mark disabled / consumed timer */
+ op->thrtimer.expires = 0; /* mark disabled / consumed timer */
- if (op->nframes > 1){
+ if (op->nframes > 1){
- DBG("sending MUX RX_CHANGED for can_id <%03X>. op is (%p)\n",
- op->can_id, op);
- /* for MUX filter we start at index 1 */
- for (i=1; i<op->nframes; i++){
- if ((op->last_frames) && (op->last_frames[i].can_dlc & RX_THR)){
- op->last_frames[i].can_dlc &= ~RX_THR;
- bcm_rx_changed(op, &op->last_frames[i]);
- }
- }
- }
- else{
-
- DBG("sending simple RX_CHANGED for can_id <%03X>. op is (%p)\n",
- op->can_id, op);
- /* for RX_FILTER_ID and simple filter */
- if (op->last_frames && (op->last_frames[0].can_dlc & RX_THR)){
- op->last_frames[0].can_dlc &= ~RX_THR;
- bcm_rx_changed(op, &op->last_frames[0]);
+ DBG("sending MUX RX_CHANGED for can_id <%03X>. op is (%p)\n",
+ op->can_id, op);
+ /* for MUX filter we start at index 1 */
+ for (i=1; i<op->nframes; i++){
+ if ((op->last_frames) && (op->last_frames[i].can_dlc & RX_THR)){
+ op->last_frames[i].can_dlc &= ~RX_THR;
+ bcm_rx_changed(op, &op->last_frames[i]);
+ }
+ }
+ } else {
+
+ DBG("sending simple RX_CHANGED for can_id <%03X>. op is (%p)\n",
+ op->can_id, op);
+ /* for RX_FILTER_ID and simple filter */
+ if (op->last_frames && (op->last_frames[0].can_dlc & RX_THR)){
+ op->last_frames[0].can_dlc &= ~RX_THR;
+ bcm_rx_changed(op, &op->last_frames[0]);
+ }
}
- }
}
static void bcm_can_tx(struct bcm_op *op)
{
- struct sk_buff *skb;
- struct net_device *dev;
- struct can_frame *cf = &op->frames[op->currframe];
+ struct sk_buff *skb;
+ struct net_device *dev;
+ struct can_frame *cf = &op->frames[op->currframe];
- DBG_FRAME("BCM: bcm_can_tx: sending frame", cf);
+ DBG_FRAME("BCM: bcm_can_tx: sending frame", cf);
- skb = alloc_skb(sizeof(struct can_frame), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+ skb = alloc_skb(sizeof(struct can_frame),
+ in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
- if (!skb)
- return;
+ if (!skb)
+ return;
- memcpy(skb_put(skb, sizeof(struct can_frame)), cf, sizeof(struct can_frame));
+ memcpy(skb_put(skb, sizeof(struct can_frame)), cf, sizeof(struct can_frame));
- if (op->sk->bound_dev_if) {
- dev = dev_get_by_index(op->sk->bound_dev_if);
+ if (op->sk->bound_dev_if) {
+ dev = dev_get_by_index(op->sk->bound_dev_if);
- if (dev) {
- skb->dev = dev;
- can_send(skb);
- dev_put(dev);
+ if (dev) {
+ skb->dev = dev;
+ can_send(skb);
+ dev_put(dev);
+ }
}
- }
- op->currframe++;
- op->frames_abs++; /* statistics */
+ op->currframe++;
+ op->frames_abs++; /* statistics */
- /* reached last frame? */
- if (op->currframe >= op->nframes)
- op->currframe = 0;
+ /* reached last frame? */
+ if (op->currframe >= op->nframes)
+ op->currframe = 0;
}
static void bcm_send_to_user(struct sock *sk, struct bcm_msg_head *head,
struct can_frame *frames, struct timeval *tv)
{
- struct sk_buff *skb;
- struct can_frame *firstframe;
- int datalen = head->nframes * sizeof(struct can_frame);
- int err;
+ struct sk_buff *skb;
+ struct can_frame *firstframe;
+ int datalen = head->nframes * sizeof(struct can_frame);
+ int err;
+
+ if (!sk) {
+ DBG("no sk available\n");
+ return;
+ }
- if (!sk) {
- DBG("no sk available\n");
- return;
- }
-
- skb = alloc_skb(sizeof(*head) + datalen, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
- memcpy(skb_put(skb, sizeof(*head)), head, sizeof(*head));
- firstframe = (struct can_frame *) skb->tail; /* can_frames starting here */
-
- if (tv)
- skb->stamp = *tv;
-
- if (head->nframes){
- memcpy(skb_put(skb, datalen), frames, datalen);
-
- /* the BCM uses the can_dlc-element of the can_frame structure */
- /* for internal purposes. This is only relevant for updates that */
- /* are generated by the BCM, where nframes is 1 */
- if (head->nframes == 1)
- firstframe->can_dlc &= BCM_CAN_DLC_MASK;
- }
- if ((err = sock_queue_rcv_skb(sk, skb)) < 0) {
- DBG("sock_queue_rcv_skb failed: %d\n", err);
- kfree_skb(skb);
- }
+ skb = alloc_skb(sizeof(*head) + datalen,
+ in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+ memcpy(skb_put(skb, sizeof(*head)), head, sizeof(*head));
+ firstframe = (struct can_frame *) skb->tail; /* can_frames starting here */
+
+ if (tv)
+ skb->stamp = *tv;
+
+ if (head->nframes){
+ memcpy(skb_put(skb, datalen), frames, datalen);
+
+ /* the BCM uses the can_dlc-element of the can_frame structure
+ for internal purposes. This is only relevant for updates
+ that are generated by the BCM, where nframes is 1
+ */
+ if (head->nframes == 1)
+ firstframe->can_dlc &= BCM_CAN_DLC_MASK;
+ }
+ if ((err = sock_queue_rcv_skb(sk, skb)) < 0) {
+ DBG("sock_queue_rcv_skb failed: %d\n", err);
+ kfree_skb(skb);
+ }
}
static struct bcm_op *bcm_find_op(struct bcm_op *ops, canid_t can_id)
{
- struct bcm_op *p;
+ struct bcm_op *p;
- for (p = ops; p; p = p->next)
- if (p->can_id == can_id)
- return p;
+ for (p = ops; p; p = p->next)
+ if (p->can_id == can_id)
+ return p;
- return NULL;
+ return NULL;
}
static void bcm_delete_rx_op(struct bcm_op **ops, canid_t can_id)
{
- struct bcm_op *p, **q;
-
- for (q = ops; p = *q; q = &p->next)
- if (p->can_id == can_id) {
- *q = p->next;
- DBG("removing rx_op (%p) for can_id <%03X>\n", p, p->can_id);
-
- if (p->sk->bound_dev_if) {
- struct net_device *dev = dev_get_by_index(p->sk->bound_dev_if);
- if (dev) {
- can_rx_unregister(dev, p->can_id, 0xFFFFFFFFU, bcm_rx_handler, p);
- dev_put(dev);
+ struct bcm_op *p, **q;
+
+ for (q = ops; p = *q; q = &p->next)
+ if (p->can_id == can_id) {
+ *q = p->next;
+ DBG("removing rx_op (%p) for can_id <%03X>\n", p, p->can_id);
+
+ if (p->sk->bound_dev_if) {
+ struct net_device *dev = dev_get_by_index(p->sk->bound_dev_if);
+ if (dev) {
+ can_rx_unregister(dev, p->can_id, 0xFFFFFFFFU, bcm_rx_handler, p);
+ dev_put(dev);
+ }
+ } else
+ DBG("sock %p not bound for can_rx_unregister()\n", p->sk);
+
+ bcm_remove_op(p);
+ return;
}
- } else
- DBG("sock %p not bound for can_rx_unregister()\n", p->sk);
-
- bcm_remove_op(p);
- return;
- }
}
static void bcm_delete_tx_op(struct bcm_op **ops, canid_t can_id)
{
- struct bcm_op *p, **q;
-
- for (q = ops; p = *q; q = &p->next)
- if (p->can_id == can_id) {
- *q = p->next;
- DBG("removing rx_op (%p) for can_id <%03X>\n", p, p->can_id);
- bcm_remove_op(p);
- return;
- }
+ struct bcm_op *p, **q;
+
+ for (q = ops; p = *q; q = &p->next)
+ if (p->can_id == can_id) {
+ *q = p->next;
+ DBG("removing rx_op (%p) for can_id <%03X>\n",
+ p, p->can_id);
+ bcm_remove_op(p);
+ return;
+ }
}
static void bcm_remove_op(struct bcm_op *op)
{
- del_timer(&op->timer);
- del_timer(&op->thrtimer);
- if (op->frames)
- kfree(op->frames);
- if (op->last_frames)
- kfree(op->last_frames);
- kfree(op);
-
- return;
+ del_timer(&op->timer);
+ del_timer(&op->thrtimer);
+ if (op->frames)
+ kfree(op->frames);
+ if (op->last_frames)
+ kfree(op->last_frames);
+ kfree(op);
+
+ return;
}
static void bcm_insert_op(struct bcm_op **ops, struct bcm_op *op)
{
- op->next = *ops;
- *ops = op;
+ op->next = *ops;
+ *ops = op;
}
module_init(bcm_init);
#endif
struct bcm_msg_head {
- int opcode; /* command */
- int flags; /* special flags */
- int count; /* run 'count' times ival1 then ival2 */
- struct timeval ival1, ival2; /* intervals */
- canid_t can_id; /* 32 Bit SFF/EFF. MSB set at EFF */
- int nframes; /* number of following can_frame's */
- struct can_frame frames[0];
+ int opcode; /* command */
+ int flags; /* special flags */
+ int count; /* run 'count' times ival1 then ival2 */
+ struct timeval ival1, ival2; /* intervals */
+ canid_t can_id; /* 32 Bit SFF/EFF. MSB set at EFF */
+ int nframes; /* number of following can_frame's */
+ struct can_frame frames[0];
};
-enum {NO_OP,
- TX_SETUP, TX_DELETE, TX_READ, TX_SEND, RX_SETUP, RX_DELETE, RX_READ,
- TX_STATUS, TX_EXPIRED, RX_STATUS, RX_TIMEOUT, RX_CHANGED};
+enum {
+ NO_OP,
+ TX_SETUP, TX_DELETE, TX_READ, TX_SEND, RX_SETUP, RX_DELETE, RX_READ,
+ TX_STATUS, TX_EXPIRED, RX_STATUS, RX_TIMEOUT, RX_CHANGED
+};
#define SETTIMER 0x0001
#define STARTTIMER 0x0002
struct can_device_stats {
- int error_warning;
- int data_overrun;
- int wakeup;
- int bus_error;
- int error_passive;
- int arbitration_lost;
- int restarts;
- int bus_error_at_init;
-
+ int error_warning;
+ int data_overrun;
+ int wakeup;
+ int bus_error;
+ int error_passive;
+ int arbitration_lost;
+ int restarts;
+ int bus_error_at_init;
};
#endif /* CAN_IOCTL_H */
static void can_init_stats(int caller);
static void can_stat_update(unsigned long data);
-static struct proc_dir_entry *can_create_proc_read_entry(const char *name, mode_t mode, read_proc_t* read_proc, void *data);
+static struct proc_dir_entry *can_create_proc_read_entry(const char *name,
+ mode_t mode, read_proc_t* read_proc, void *data);
static void can_remove_proc_entry(const char *name);
-static unsigned long calc_rate(unsigned long oldjif, unsigned long newjif, unsigned long count);
-
-static int can_proc_read_version(char *page, char **start, off_t off, int count, int *eof, void *data);
-static int can_proc_read_stats(char *page, char **start, off_t off, int count, int *eof, void *data);
-static int can_proc_read_reset_stats(char *page, char **start, off_t off, int count, int *eof, void *data);
-static int can_proc_read_rcvlist_all(char *page, char **start, off_t off, int count, int *eof, void *data);
-static int can_proc_read_rcvlist_fil(char *page, char **start, off_t off, int count, int *eof, void *data);
-static int can_proc_read_rcvlist_inv(char *page, char **start, off_t off, int count, int *eof, void *data);
-static int can_proc_read_rcvlist_sff(char *page, char **start, off_t off, int count, int *eof, void *data);
-static int can_proc_read_rcvlist_eff(char *page, char **start, off_t off, int count, int *eof, void *data);
-static int can_proc_read_rcvlist_err(char *page, char **start, off_t off, int count, int *eof, void *data);
+static unsigned long calc_rate(unsigned long oldjif, unsigned long newjif,
+ unsigned long count);
+
+static int can_proc_read_version(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+static int can_proc_read_stats(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+static int can_proc_read_reset_stats(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+static int can_proc_read_rcvlist_all(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+static int can_proc_read_rcvlist_fil(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+static int can_proc_read_rcvlist_inv(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+static int can_proc_read_rcvlist_sff(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+static int can_proc_read_rcvlist_eff(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+static int can_proc_read_rcvlist_err(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
static struct proc_dir_entry *can_dir = NULL;
static struct proc_dir_entry *pde_version = NULL;
void can_init_proc(void)
{
- /* procfs init */
-
- /* create /proc/can directory */
- can_dir = proc_mkdir(CAN_PROC_DIR, NULL);
-
- if (!can_dir) {
- printk(KERN_INFO "af_can: failed to create CAN_PROC_DIR. "
- "CONFIG_PROC_FS missing?\n");
- return;
- }
-
- can_dir->owner = THIS_MODULE;
-
- /* own procfs entries from the AF_CAN core */
- pde_version = can_create_proc_read_entry(
- CAN_PROC_VERSION, 0644, can_proc_read_version, NULL);
- pde_stats = can_create_proc_read_entry(
- CAN_PROC_STATS, 0644, can_proc_read_stats, NULL);
- pde_reset_stats = can_create_proc_read_entry(
- CAN_PROC_RESET_STATS, 0644, can_proc_read_reset_stats, NULL);
- pde_rcvlist_all = can_create_proc_read_entry(
- CAN_PROC_RCVLIST_ALL, 0644, can_proc_read_rcvlist_all, NULL);
- pde_rcvlist_fil = can_create_proc_read_entry(
- CAN_PROC_RCVLIST_FIL, 0644, can_proc_read_rcvlist_fil, NULL);
- pde_rcvlist_inv = can_create_proc_read_entry(
- CAN_PROC_RCVLIST_INV, 0644, can_proc_read_rcvlist_inv, NULL);
- pde_rcvlist_sff = can_create_proc_read_entry(
- CAN_PROC_RCVLIST_SFF, 0644, can_proc_read_rcvlist_sff, NULL);
- pde_rcvlist_eff = can_create_proc_read_entry(
- CAN_PROC_RCVLIST_EFF, 0644, can_proc_read_rcvlist_eff, NULL);
- pde_rcvlist_err = can_create_proc_read_entry(
- CAN_PROC_RCVLIST_ERR, 0644, can_proc_read_rcvlist_err, NULL);
-
- if (stats_timer) {
- /* the statistics are updated every second (timer triggered) */
- stattimer.function = can_stat_update;
- stattimer.data = 0;
- stattimer.expires = jiffies + HZ; /* every second */
- add_timer(&stattimer); /* start statistics timer */
- }
+ /* procfs init */
+
+ /* create /proc/can directory */
+ can_dir = proc_mkdir(CAN_PROC_DIR, NULL);
+
+ if (!can_dir) {
+ printk(KERN_INFO "af_can: failed to create CAN_PROC_DIR. "
+ "CONFIG_PROC_FS missing?\n");
+ return;
+ }
+
+ can_dir->owner = THIS_MODULE;
+
+ /* own procfs entries from the AF_CAN core */
+ pde_version = can_create_proc_read_entry(
+ CAN_PROC_VERSION, 0644, can_proc_read_version, NULL);
+ pde_stats = can_create_proc_read_entry(
+ CAN_PROC_STATS, 0644, can_proc_read_stats, NULL);
+ pde_reset_stats = can_create_proc_read_entry(
+ CAN_PROC_RESET_STATS, 0644, can_proc_read_reset_stats, NULL);
+ pde_rcvlist_all = can_create_proc_read_entry(
+ CAN_PROC_RCVLIST_ALL, 0644, can_proc_read_rcvlist_all, NULL);
+ pde_rcvlist_fil = can_create_proc_read_entry(
+ CAN_PROC_RCVLIST_FIL, 0644, can_proc_read_rcvlist_fil, NULL);
+ pde_rcvlist_inv = can_create_proc_read_entry(
+ CAN_PROC_RCVLIST_INV, 0644, can_proc_read_rcvlist_inv, NULL);
+ pde_rcvlist_sff = can_create_proc_read_entry(
+ CAN_PROC_RCVLIST_SFF, 0644, can_proc_read_rcvlist_sff, NULL);
+ pde_rcvlist_eff = can_create_proc_read_entry(
+ CAN_PROC_RCVLIST_EFF, 0644, can_proc_read_rcvlist_eff, NULL);
+ pde_rcvlist_err = can_create_proc_read_entry(
+ CAN_PROC_RCVLIST_ERR, 0644, can_proc_read_rcvlist_err, NULL);
+
+ if (stats_timer) {
+ /* the statistics are updated every second (timer triggered) */
+ stattimer.function = can_stat_update;
+ stattimer.data = 0;
+ stattimer.expires = jiffies + HZ; /* every second */
+ add_timer(&stattimer); /* start statistics timer */
+ }
}
void can_remove_proc(void)
{
- /* procfs remove */
- if (pde_version)
- can_remove_proc_entry(CAN_PROC_VERSION);
+ /* procfs remove */
+ if (pde_version)
+ can_remove_proc_entry(CAN_PROC_VERSION);
- if (pde_stats)
- can_remove_proc_entry(CAN_PROC_STATS);
+ if (pde_stats)
+ can_remove_proc_entry(CAN_PROC_STATS);
- if (pde_reset_stats)
- can_remove_proc_entry(CAN_PROC_RESET_STATS);
+ if (pde_reset_stats)
+ can_remove_proc_entry(CAN_PROC_RESET_STATS);
- if (pde_rcvlist_all)
- can_remove_proc_entry(CAN_PROC_RCVLIST_ALL);
+ if (pde_rcvlist_all)
+ can_remove_proc_entry(CAN_PROC_RCVLIST_ALL);
- if (pde_rcvlist_fil)
- can_remove_proc_entry(CAN_PROC_RCVLIST_FIL);
+ if (pde_rcvlist_fil)
+ can_remove_proc_entry(CAN_PROC_RCVLIST_FIL);
- if (pde_rcvlist_inv)
- can_remove_proc_entry(CAN_PROC_RCVLIST_INV);
+ if (pde_rcvlist_inv)
+ can_remove_proc_entry(CAN_PROC_RCVLIST_INV);
- if (pde_rcvlist_sff)
- can_remove_proc_entry(CAN_PROC_RCVLIST_SFF);
+ if (pde_rcvlist_sff)
+ can_remove_proc_entry(CAN_PROC_RCVLIST_SFF);
- if (pde_rcvlist_eff)
- can_remove_proc_entry(CAN_PROC_RCVLIST_EFF);
+ if (pde_rcvlist_eff)
+ can_remove_proc_entry(CAN_PROC_RCVLIST_EFF);
- if (pde_rcvlist_err)
- can_remove_proc_entry(CAN_PROC_RCVLIST_ERR);
+ if (pde_rcvlist_err)
+ can_remove_proc_entry(CAN_PROC_RCVLIST_ERR);
- if (can_dir)
- remove_proc_entry(CAN_PROC_DIR, NULL);
+ if (can_dir)
+ remove_proc_entry(CAN_PROC_DIR, NULL);
}
/**************************************************/
/* proc read functions */
/**************************************************/
-static int can_print_recv_list(char *page, int len, struct rcv_list *rx_list, struct net_device *dev)
+static int can_print_recv_list(char *page, int len, struct rcv_list *rx_list,
+ struct net_device *dev)
{
- struct rcv_list *p;
-
- for (p = rx_list; p; p = p->next) {
- char *fmt = p->can_id & CAN_EFF_FLAG ? /* EFF & CAN_ID_ALL */
- " %-5s %08X %08x %08x %08x %8ld %s\n" :
- " %-5s %03X %08x %08x %08x %8ld %s\n";
-
- len += snprintf(page + len, PAGE_SIZE - len, fmt,
- dev->name, p->can_id, p->mask, (unsigned int)p->func,
- (unsigned int)p->data, p->matches, p->ident);
-
- /* does a typical line fit into the current buffer? */
- /* 100 Bytes before end of buffer */
- if (len > PAGE_SIZE - 100) {
- /* mark output cut off */
- len += snprintf(page + len, PAGE_SIZE - len, " (..)\n");
- return len;
+ struct rcv_list *p;
+
+ for (p = rx_list; p; p = p->next) {
+ char *fmt = p->can_id & CAN_EFF_FLAG ? /* EFF & CAN_ID_ALL */
+ " %-5s %08X %08x %08x %08x %8ld %s\n" :
+ " %-5s %03X %08x %08x %08x %8ld %s\n";
+
+ len += snprintf(page + len, PAGE_SIZE - len, fmt,
+ dev->name, p->can_id, p->mask,
+ (unsigned int)p->func, (unsigned int)p->data,
+ p->matches, p->ident);
+
+ /* does a typical line fit into the current buffer? */
+ /* 100 Bytes before end of buffer */
+ if (len > PAGE_SIZE - 100) {
+ /* mark output cut off */
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " (..)\n");
+ return len;
+ }
}
- }
- return len;
+ return len;
}
static int can_print_recv_banner(char *page, int len)
{
- /* can1. 00000000 00000000 00000000 .......0 tp20 */
- len += snprintf(page + len, PAGE_SIZE - len,
- " device can_id can_mask function userdata matches ident\n");
+ /* can1. 00000000 00000000 00000000
+ ....... 0 tp20 */
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " device can_id can_mask function"
+ " userdata matches ident\n");
- return len;
+ return len;
}
-static int can_proc_read_stats(char *page, char **start, off_t off, int count, int *eof, void *data)
+static int can_proc_read_stats(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
{
- int len = 0;
+ int len = 0;
- MOD_INC_USE_COUNT;
+ MOD_INC_USE_COUNT;
- len += snprintf(page + len, PAGE_SIZE - len, "\n");
- len += snprintf(page + len, PAGE_SIZE - len, " %8ld transmitted frames (TXF)\n",
- stats.tx_frames);
- len += snprintf(page + len, PAGE_SIZE - len, " %8ld received frames (RXF)\n",
- stats.rx_frames);
- len += snprintf(page + len, PAGE_SIZE - len, " %8ld matched frames (RXMF)\n",
- stats.matches);
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld transmitted frames (TXF)\n", stats.tx_frames);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld received frames (RXF)\n", stats.rx_frames);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld matched frames (RXMF)\n", stats.matches);
- len += snprintf(page + len, PAGE_SIZE - len, "\n");
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
- len += snprintf(page + len, PAGE_SIZE - len, " %8ld %% total match ratio (RXMR)\n",
- stats.total_rx_match_ratio);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld %% total match ratio (RXMR)\n",
+ stats.total_rx_match_ratio);
- len += snprintf(page + len, PAGE_SIZE - len, " %8ld frames/s total tx rate (TXR)\n",
- stats.total_tx_rate);
- len += snprintf(page + len, PAGE_SIZE - len, " %8ld frames/s total rx rate (RXR)\n",
- stats.total_rx_rate);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld frames/s total tx rate (TXR)\n",
+ stats.total_tx_rate);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld frames/s total rx rate (RXR)\n",
+ stats.total_rx_rate);
- len += snprintf(page + len, PAGE_SIZE - len, "\n");
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
- len += snprintf(page + len, PAGE_SIZE - len, " %8ld %% current match ratio (CRXMR)\n",
- stats.current_rx_match_ratio);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld %% current match ratio (CRXMR)\n",
+ stats.current_rx_match_ratio);
- len += snprintf(page + len, PAGE_SIZE - len, " %8ld frames/s current tx rate (CTXR)\n",
- stats.current_tx_rate);
- len += snprintf(page + len, PAGE_SIZE - len, " %8ld frames/s current rx rate (CRXR)\n",
- stats.current_rx_rate);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld frames/s current tx rate (CTXR)\n",
+ stats.current_tx_rate);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld frames/s current rx rate (CRXR)\n",
+ stats.current_rx_rate);
- len += snprintf(page + len, PAGE_SIZE - len, "\n");
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
- len += snprintf(page + len, PAGE_SIZE - len, " %8ld %% max match ratio (MRXMR)\n",
- stats.max_rx_match_ratio);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld %% max match ratio (MRXMR)\n",
+ stats.max_rx_match_ratio);
- len += snprintf(page + len, PAGE_SIZE - len, " %8ld frames/s max tx rate (MTXR)\n",
- stats.max_tx_rate);
- len += snprintf(page + len, PAGE_SIZE - len, " %8ld frames/s max rx rate (MRXR)\n",
- stats.max_rx_rate);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld frames/s max tx rate (MTXR)\n",
+ stats.max_tx_rate);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld frames/s max rx rate (MRXR)\n",
+ stats.max_rx_rate);
- len += snprintf(page + len, PAGE_SIZE - len, "\n");
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
- len += snprintf(page + len, PAGE_SIZE - len, " %8ld current receive list entries (CRCV)\n", pstats.rcv_entries);
- len += snprintf(page + len, PAGE_SIZE - len, " %8ld maximum receive list entries (MRCV)\n", pstats.rcv_entries_max);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld current receive list entries (CRCV)\n",
+ pstats.rcv_entries);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " %8ld maximum receive list entries (MRCV)\n",
+ pstats.rcv_entries_max);
- if (pstats.stats_reset)
- len += snprintf(page + len, PAGE_SIZE - len, "\n %8ld statistic resets (STR)\n", pstats.stats_reset);
+ if (pstats.stats_reset)
+ len += snprintf(page + len, PAGE_SIZE - len,
+ "\n %8ld statistic resets (STR)\n",
+ pstats.stats_reset);
- len += snprintf(page + len, PAGE_SIZE - len, "\n");
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
- MOD_DEC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
- *eof = 1;
- return len;
+ *eof = 1;
+ return len;
}
-static int can_proc_read_reset_stats(char *page, char **start, off_t off, int count, int *eof, void *data)
+static int can_proc_read_reset_stats(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
{
- int len = 0;
+ int len = 0;
- MOD_INC_USE_COUNT;
+ MOD_INC_USE_COUNT;
- can_init_stats(1);
+ can_init_stats(1);
- len += snprintf(page + len, PAGE_SIZE - len, "CAN statistic reset #%ld done.\n", pstats.stats_reset);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ "CAN statistic reset #%ld done.\n", pstats.stats_reset);
- MOD_DEC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
- *eof = 1;
- return len;
+ *eof = 1;
+ return len;
}
-static int can_proc_read_version(char *page, char **start, off_t off, int count, int *eof, void *data)
+static int can_proc_read_version(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
{
- int len = 0;
+ int len = 0;
- MOD_INC_USE_COUNT;
+ MOD_INC_USE_COUNT;
- len += snprintf(page + len, PAGE_SIZE - len,
- "%06X [ Volkswagen AG - Low Level CAN Framework (LLCF) v%s ]\n",
- LLCF_VERSION_CODE, VERSION);
+ len += snprintf(page + len, PAGE_SIZE - len,
+ "%06X [ Volkswagen AG - Low Level CAN Framework (LLCF) v%s ]\n",
+ LLCF_VERSION_CODE, VERSION);
- MOD_DEC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
- *eof = 1;
- return len;
+ *eof = 1;
+ return len;
}
-static int can_proc_read_rcvlist_all(char *page, char **start, off_t off, int count, int *eof, void *data)
+static int can_proc_read_rcvlist_all(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
{
- int len = 0;
- struct rcv_dev_list *p;
+ int len = 0;
+ struct rcv_dev_list *p;
- MOD_INC_USE_COUNT;
+ MOD_INC_USE_COUNT;
- /* RX_ALL */
- len += snprintf(page + len, PAGE_SIZE - len, "\nreceive list 'rx_all':\n");
+ /* RX_ALL */
+ len += snprintf(page + len, PAGE_SIZE - len,
+ "\nreceive list 'rx_all':\n");
- /* find receive list for this device */
- for (p = rx_dev_list; p; p = p->next) {
+ /* find receive list for this device */
+ for (p = rx_dev_list; p; p = p->next) {
- if (p->rx_all) {
- len = can_print_recv_banner(page, len);
- len = can_print_recv_list(page, len, p->rx_all, p->dev);
- } else if (p->dev)
- len += snprintf(page + len, PAGE_SIZE - len, " (%s: no entry)\n", p->dev->name);
- }
+ if (p->rx_all) {
+ len = can_print_recv_banner(page, len);
+ len = can_print_recv_list(page, len, p->rx_all, p->dev);
+ } else if (p->dev)
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " (%s: no entry)\n", p->dev->name);
+ }
- len += snprintf(page + len, PAGE_SIZE - len, "\n");
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
- MOD_DEC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
- *eof = 1;
- return len;
+ *eof = 1;
+ return len;
}
-static int can_proc_read_rcvlist_fil(char *page, char **start, off_t off, int count, int *eof, void *data)
+static int can_proc_read_rcvlist_fil(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
{
- int len = 0;
- struct rcv_dev_list *p;
+ int len = 0;
+ struct rcv_dev_list *p;
- MOD_INC_USE_COUNT;
+ MOD_INC_USE_COUNT;
- /* RX_FIL */
- len += snprintf(page + len, PAGE_SIZE - len, "\nreceive list 'rx_fil':\n");
+ /* RX_FIL */
+ len += snprintf(page + len, PAGE_SIZE - len,
+ "\nreceive list 'rx_fil':\n");
- /* find receive list for this device */
- for (p = rx_dev_list; p; p = p->next) {
+ /* find receive list for this device */
+ for (p = rx_dev_list; p; p = p->next) {
- if (p->rx_fil) {
- len = can_print_recv_banner(page, len);
- len = can_print_recv_list(page, len, p->rx_fil, p->dev);
- } else if (p->dev)
- len += snprintf(page + len, PAGE_SIZE - len, " (%s: no entry)\n", p->dev->name);
- }
+ if (p->rx_fil) {
+ len = can_print_recv_banner(page, len);
+ len = can_print_recv_list(page, len, p->rx_fil, p->dev);
+ } else if (p->dev)
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " (%s: no entry)\n", p->dev->name);
+ }
- len += snprintf(page + len, PAGE_SIZE - len, "\n");
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
- MOD_DEC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
- *eof = 1;
- return len;
+ *eof = 1;
+ return len;
}
-static int can_proc_read_rcvlist_inv(char *page, char **start, off_t off, int count, int *eof, void *data)
+static int can_proc_read_rcvlist_inv(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
{
- int len = 0;
- struct rcv_dev_list *p;
+ int len = 0;
+ struct rcv_dev_list *p;
- MOD_INC_USE_COUNT;
+ MOD_INC_USE_COUNT;
- /* RX_INV */
- len += snprintf(page + len, PAGE_SIZE - len, "\nreceive list 'rx_inv':\n");
+ /* RX_INV */
+ len += snprintf(page + len, PAGE_SIZE - len,
+ "\nreceive list 'rx_inv':\n");
- /* find receive list for this device */
- for (p = rx_dev_list; p; p = p->next) {
+ /* find receive list for this device */
+ for (p = rx_dev_list; p; p = p->next) {
- if (p->rx_inv) {
- len = can_print_recv_banner(page, len);
- len = can_print_recv_list(page, len, p->rx_inv, p->dev);
- } else if (p->dev)
- len += snprintf(page + len, PAGE_SIZE - len, " (%s: no entry)\n", p->dev->name);
- }
+ if (p->rx_inv) {
+ len = can_print_recv_banner(page, len);
+ len = can_print_recv_list(page, len, p->rx_inv, p->dev);
+ } else if (p->dev)
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " (%s: no entry)\n", p->dev->name);
+ }
- len += snprintf(page + len, PAGE_SIZE - len, "\n");
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
- MOD_DEC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
- *eof = 1;
- return len;
+ *eof = 1;
+ return len;
}
-static int can_proc_read_rcvlist_sff(char *page, char **start, off_t off, int count, int *eof, void *data)
+static int can_proc_read_rcvlist_sff(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
{
- int len = 0;
- struct rcv_dev_list *p;
-
- MOD_INC_USE_COUNT;
-
- /* RX_SFF */
- len += snprintf(page + len, PAGE_SIZE - len, "\nreceive list 'rx_sff':\n");
-
- /* find receive list for this device */
- for (p = rx_dev_list; p; p = p->next) {
- int i, all_empty = 1;
- /* check wether at least one list is non-empty */
- for(i = 0; i < 0x800; i++)
- if (p->rx_sff[i]) {
- all_empty = 0;
- break;
- }
-
- if (!all_empty) {
- len = can_print_recv_banner(page, len);
- for(i = 0; i < 0x800; i++) {
- if (p->rx_sff[i] && len < PAGE_SIZE - 100)
- len = can_print_recv_list(page, len, p->rx_sff[i], p->dev);
- }
- } else if (p->dev)
- len += snprintf(page + len, PAGE_SIZE - len, " (%s: no entry)\n", p->dev->name);
- }
-
- len += snprintf(page + len, PAGE_SIZE - len, "\n");
-
- MOD_DEC_USE_COUNT;
-
- *eof = 1;
- return len;
+ int len = 0;
+ struct rcv_dev_list *p;
+
+ MOD_INC_USE_COUNT;
+
+ /* RX_SFF */
+ len += snprintf(page + len, PAGE_SIZE - len,
+ "\nreceive list 'rx_sff':\n");
+
+ /* find receive list for this device */
+ for (p = rx_dev_list; p; p = p->next) {
+ int i, all_empty = 1;
+ /* check wether at least one list is non-empty */
+ for (i = 0; i < 0x800; i++)
+ if (p->rx_sff[i]) {
+ all_empty = 0;
+ break;
+ }
+
+ if (!all_empty) {
+ len = can_print_recv_banner(page, len);
+ for (i = 0; i < 0x800; i++) {
+ if (p->rx_sff[i] && len < PAGE_SIZE - 100)
+ len = can_print_recv_list(page, len, p->rx_sff[i], p->dev);
+ }
+ } else if (p->dev)
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " (%s: no entry)\n", p->dev->name);
+ }
+
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
+
+ MOD_DEC_USE_COUNT;
+
+ *eof = 1;
+ return len;
}
-static int can_proc_read_rcvlist_eff(char *page, char **start, off_t off, int count, int *eof, void *data)
+static int can_proc_read_rcvlist_eff(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
{
- int len = 0;
- struct rcv_dev_list *p;
+ int len = 0;
+ struct rcv_dev_list *p;
- MOD_INC_USE_COUNT;
+ MOD_INC_USE_COUNT;
- /* RX_EFF */
- len += snprintf(page + len, PAGE_SIZE - len, "\nreceive list 'rx_eff':\n");
+ /* RX_EFF */
+ len += snprintf(page + len, PAGE_SIZE - len,
+ "\nreceive list 'rx_eff':\n");
- /* find receive list for this device */
- for (p = rx_dev_list; p; p = p->next) {
+ /* find receive list for this device */
+ for (p = rx_dev_list; p; p = p->next) {
- if (p->rx_eff) {
- len = can_print_recv_banner(page, len);
- len = can_print_recv_list(page, len, p->rx_eff, p->dev);
- } else if (p->dev)
- len += snprintf(page + len, PAGE_SIZE - len, " (%s: no entry)\n", p->dev->name);
- }
+ if (p->rx_eff) {
+ len = can_print_recv_banner(page, len);
+ len = can_print_recv_list(page, len, p->rx_eff, p->dev);
+ } else if (p->dev)
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " (%s: no entry)\n", p->dev->name);
+ }
- len += snprintf(page + len, PAGE_SIZE - len, "\n");
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
- MOD_DEC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
- *eof = 1;
- return len;
+ *eof = 1;
+ return len;
}
-static int can_proc_read_rcvlist_err(char *page, char **start, off_t off, int count, int *eof, void *data)
+static int can_proc_read_rcvlist_err(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
{
- int len = 0;
- struct rcv_dev_list *p;
+ int len = 0;
+ struct rcv_dev_list *p;
- MOD_INC_USE_COUNT;
+ MOD_INC_USE_COUNT;
- /* RX_ERR */
- len += snprintf(page + len, PAGE_SIZE - len, "\nreceive list 'rx_err':\n");
+ /* RX_ERR */
+ len += snprintf(page + len, PAGE_SIZE - len,
+ "\nreceive list 'rx_err':\n");
- /* find receive list for this device */
- for (p = rx_dev_list; p; p = p->next) {
+ /* find receive list for this device */
+ for (p = rx_dev_list; p; p = p->next) {
- if (p->rx_err) {
- len = can_print_recv_banner(page, len);
- len = can_print_recv_list(page, len, p->rx_err, p->dev);
- } else if (p->dev)
- len += snprintf(page + len, PAGE_SIZE - len, " (%s: no entry)\n", p->dev->name);
- }
+ if (p->rx_err) {
+ len = can_print_recv_banner(page, len);
+ len = can_print_recv_list(page, len, p->rx_err, p->dev);
+ } else if (p->dev)
+ len += snprintf(page + len, PAGE_SIZE - len,
+ " (%s: no entry)\n", p->dev->name);
+ }
- len += snprintf(page + len, PAGE_SIZE - len, "\n");
+ len += snprintf(page + len, PAGE_SIZE - len, "\n");
- MOD_DEC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
- *eof = 1;
- return len;
+ *eof = 1;
+ return len;
}
/**************************************************/
static struct proc_dir_entry *can_create_proc_read_entry(const char *name, mode_t mode, read_proc_t* read_proc, void *data)
{
- if (can_dir)
- return create_proc_read_entry(name, mode, can_dir, read_proc, data);
- else
- return NULL;
+ if (can_dir)
+ return create_proc_read_entry(name, mode, can_dir, read_proc, data);
+ else
+ return NULL;
}
static void can_remove_proc_entry(const char *name)
{
- if (can_dir)
- remove_proc_entry(name, can_dir);
+ if (can_dir)
+ remove_proc_entry(name, can_dir);
}
-static unsigned long calc_rate(unsigned long oldjif, unsigned long newjif, unsigned long count){
-
- unsigned long ret = 0;
+static unsigned long calc_rate(unsigned long oldjif, unsigned long newjif,
+ unsigned long count)
+{
+ unsigned long ret = 0;
- if (oldjif == newjif)
- return 0;
+ if (oldjif == newjif)
+ return 0;
- if (count > (ULONG_MAX / HZ)) { /* see can_rcv() - this should NEVER happen! */
- printk(KERN_ERR "af_can: calc_rate: count exceeded! %ld\n", count);
- return 99999999;
- }
+ /* see can_rcv() - this should NEVER happen! */
+ if (count > (ULONG_MAX / HZ)) {
+ printk(KERN_ERR "af_can: calc_rate: count exceeded! %ld\n", count);
+ return 99999999;
+ }
- ret = (count * HZ) / (newjif - oldjif);
+ ret = (count * HZ) / (newjif - oldjif);
- return ret;
-};
+ return ret;
+}
/**************************************************/
/* af_can statistics stuff */
/**************************************************/
-static void can_init_stats(int caller){
-
- memset(&stats, 0, sizeof(stats));
- stats.jiffies_init = jiffies;
- pstats.stats_reset++;
-};
-
-static void can_stat_update(unsigned long data){
+static void can_init_stats(int caller)
+{
+ memset(&stats, 0, sizeof(stats));
+ stats.jiffies_init = jiffies;
+ pstats.stats_reset++;
+}
- unsigned long j = jiffies; /* snapshot */
+static void can_stat_update(unsigned long data)
+{
+ unsigned long j = jiffies; /* snapshot */
- //DBG("af_can: can_stat_update() jiffies = %ld\n", j);
+ //DBG("af_can: can_stat_update() jiffies = %ld\n", j);
- if (j < stats.jiffies_init) /* jiffies overflow */
- can_init_stats(2);
+ if (j < stats.jiffies_init) /* jiffies overflow */
+ can_init_stats(2);
- /* stats.rx_frames is the definitively max. statistic value */
- if (stats.rx_frames > (ULONG_MAX / HZ)) /* prevent overflow in calc_rate() */
- can_init_stats(3); /* restart */
+ /* stats.rx_frames is the definitively max. statistic value */
- if (stats.matches > (ULONG_MAX / 100)) /* matches overflow - very improbable */
- can_init_stats(4);
+ /* prevent overflow in calc_rate() */
+ if (stats.rx_frames > (ULONG_MAX / HZ))
+ can_init_stats(3); /* restart */
- /* calc total values */
- if (stats.rx_frames)
- stats.total_rx_match_ratio = (stats.matches * 100) / stats.rx_frames;
+ /* matches overflow - very improbable */
+ if (stats.matches > (ULONG_MAX / 100))
+ can_init_stats(4);
- stats.total_tx_rate = calc_rate(stats.jiffies_init, j, stats.tx_frames);
- stats.total_rx_rate = calc_rate(stats.jiffies_init, j, stats.rx_frames);
+ /* calc total values */
+ if (stats.rx_frames)
+ stats.total_rx_match_ratio = (stats.matches * 100) / stats.rx_frames;
- /* calc current values */
- if (stats.rx_frames_delta)
- stats.current_rx_match_ratio = (stats.matches_delta * 100) / stats.rx_frames_delta;
+ stats.total_tx_rate = calc_rate(stats.jiffies_init, j, stats.tx_frames);
+ stats.total_rx_rate = calc_rate(stats.jiffies_init, j, stats.rx_frames);
- stats.current_tx_rate = calc_rate(0, HZ, stats.tx_frames_delta);
- stats.current_rx_rate = calc_rate(0, HZ, stats.rx_frames_delta);
+ /* calc current values */
+ if (stats.rx_frames_delta)
+ stats.current_rx_match_ratio =
+ (stats.matches_delta * 100) / stats.rx_frames_delta;
- /* check / update maximum values */
- if (stats.max_tx_rate < stats.current_tx_rate)
- stats.max_tx_rate = stats.current_tx_rate;
+ stats.current_tx_rate = calc_rate(0, HZ, stats.tx_frames_delta);
+ stats.current_rx_rate = calc_rate(0, HZ, stats.rx_frames_delta);
- if (stats.max_rx_rate < stats.current_rx_rate)
- stats.max_rx_rate = stats.current_rx_rate;
+ /* check / update maximum values */
+ if (stats.max_tx_rate < stats.current_tx_rate)
+ stats.max_tx_rate = stats.current_tx_rate;
- if (stats.max_rx_match_ratio < stats.current_rx_match_ratio)
- stats.max_rx_match_ratio = stats.current_rx_match_ratio;
+ if (stats.max_rx_rate < stats.current_rx_rate)
+ stats.max_rx_rate = stats.current_rx_rate;
- /* clear values for 'current rate' calculation */
- stats.tx_frames_delta = 0;
- stats.rx_frames_delta = 0;
- stats.matches_delta = 0;
+ if (stats.max_rx_match_ratio < stats.current_rx_match_ratio)
+ stats.max_rx_match_ratio = stats.current_rx_match_ratio;
- /* restart timer */
- stattimer.expires = jiffies + HZ; /* every second */
- add_timer(&stattimer);
-};
+ /* clear values for 'current rate' calculation */
+ stats.tx_frames_delta = 0;
+ stats.rx_frames_delta = 0;
+ stats.matches_delta = 0;
-/**************************************************/
-/* EOF */
-/**************************************************/
+ /* restart timer */
+ stattimer.expires = jiffies + HZ; /* every second */
+ add_timer(&stattimer);
+}
*/
struct canraw_opt {
- int bound;
- int ifindex;
- int count;
- struct can_filter *filter;
- can_err_mask_t err_mask;
+ int bound;
+ int ifindex;
+ int count;
+ struct can_filter *filter;
+ can_err_mask_t err_mask;
};
#define canraw_sk(sk) ((struct canraw_opt *)&(sk)->tp_pinfo)
#define MASK_ALL 0
static struct proto_ops raw_ops = {
- .family = PF_CAN,
- .release = raw_release,
- .bind = raw_bind,
- .connect = sock_no_connect,
- .socketpair = sock_no_socketpair,
- .accept = sock_no_accept,
- .getname = raw_getname,
- .poll = raw_poll,
- .ioctl = NULL, /* use can_ioctl() from af_can.c */
- .listen = sock_no_listen,
- .shutdown = sock_no_shutdown,
- .setsockopt = raw_setsockopt,
- .getsockopt = raw_getsockopt,
- .sendmsg = raw_sendmsg,
- .recvmsg = raw_recvmsg,
- .mmap = sock_no_mmap,
- .sendpage = sock_no_sendpage,
+ .family = PF_CAN,
+ .release = raw_release,
+ .bind = raw_bind,
+ .connect = sock_no_connect,
+ .socketpair = sock_no_socketpair,
+ .accept = sock_no_accept,
+ .getname = raw_getname,
+ .poll = raw_poll,
+ .ioctl = NULL, /* use can_ioctl() from af_can.c */
+ .listen = sock_no_listen,
+ .shutdown = sock_no_shutdown,
+ .setsockopt = raw_setsockopt,
+ .getsockopt = raw_getsockopt,
+ .sendmsg = raw_sendmsg,
+ .recvmsg = raw_recvmsg,
+ .mmap = sock_no_mmap,
+ .sendpage = sock_no_sendpage,
};
static __init int raw_init(void)
{
- printk(banner);
+ printk(banner);
- can_proto_register(CAN_RAW, &raw_ops);
- return 0;
+ can_proto_register(CAN_RAW, &raw_ops);
+ return 0;
}
static __exit void raw_exit(void)
{
- can_proto_unregister(CAN_RAW);
+ can_proto_unregister(CAN_RAW);
}
static int raw_release(struct socket *sock)
{
- struct sock *sk = sock->sk;
- struct net_device *dev = NULL;
+ struct sock *sk = sock->sk;
+ struct net_device *dev = NULL;
- DBG("socket %p, sk %p\n", sock, sk);
+ DBG("socket %p, sk %p\n", sock, sk);
- if (canraw_sk(sk)->bound && canraw_sk(sk)->ifindex)
- dev = dev_get_by_index(canraw_sk(sk)->ifindex);
+ if (canraw_sk(sk)->bound && canraw_sk(sk)->ifindex)
+ dev = dev_get_by_index(canraw_sk(sk)->ifindex);
- /* remove current filters & unregister */
- if (canraw_sk(sk)->count > 0) {
- if (canraw_sk(sk)->bound)
- raw_remove_filters(dev, sk);
- kfree(canraw_sk(sk)->filter);
- } else if (canraw_sk(sk)->bound)
- can_rx_unregister(dev, 0, MASK_ALL, raw_rcv, sk);
+ /* remove current filters & unregister */
+ if (canraw_sk(sk)->count > 0) {
+ if (canraw_sk(sk)->bound)
+ raw_remove_filters(dev, sk);
+ kfree(canraw_sk(sk)->filter);
+ } else if (canraw_sk(sk)->bound)
+ can_rx_unregister(dev, 0, MASK_ALL, raw_rcv, sk);
- /* remove current error mask */
- if (canraw_sk(sk)->err_mask && canraw_sk(sk)->bound)
- can_rx_unregister(dev, 0, (canid_t)(canraw_sk(sk)->err_mask | CAN_ERR_FLAG), raw_rcv, sk);
+ /* remove current error mask */
+ if (canraw_sk(sk)->err_mask && canraw_sk(sk)->bound)
+ can_rx_unregister(dev, 0, (canid_t)(canraw_sk(sk)->err_mask | CAN_ERR_FLAG), raw_rcv, sk);
- if (dev) {
- can_dev_unregister(dev, raw_notifier, sk);
- dev_put(dev);
- }
+ if (dev) {
+ can_dev_unregister(dev, raw_notifier, sk);
+ dev_put(dev);
+ }
- sock_put(sk);
+ sock_put(sk);
- return 0;
+ return 0;
}
static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len)
{
- struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
- struct sock *sk = sock->sk;
- struct net_device *dev;
+ struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
+ struct sock *sk = sock->sk;
+ struct net_device *dev;
- DBG("socket %p to device %d\n", sock, addr->can_ifindex);
+ DBG("socket %p to device %d\n", sock, addr->can_ifindex);
- if (len < sizeof(*addr))
- return -EINVAL;
+ if (len < sizeof(*addr))
+ return -EINVAL;
- if (canraw_sk(sk)->bound) {
+ if (canraw_sk(sk)->bound) {
#if 1
- return -EOPNOTSUPP;
+ return -EOPNOTSUPP;
#else
- /* remove current bindings */
- if (canraw_sk(sk)->ifindex) {
- dev = dev_get_by_index(canraw_sk(sk)->ifindex);
- ; /* remove notifier */
- } else
- dev = NULL;
- if (canraw_sk(sk)->count > 0) {
- raw_remove_filters(sk);
- } else {
- can_rx_unregister(dev, 0, MASK_ALL, raw_rcv, sk);
- }
- if (dev)
- dev_put(dev);
- canraw_sk(sk)->bound = 0;
+ /* remove current bindings */
+ if (canraw_sk(sk)->ifindex) {
+ dev = dev_get_by_index(canraw_sk(sk)->ifindex);
+ ; /* remove notifier */
+ } else
+ dev = NULL;
+ if (canraw_sk(sk)->count > 0) {
+ raw_remove_filters(sk);
+ } else {
+ can_rx_unregister(dev, 0, MASK_ALL, raw_rcv, sk);
+ }
+ if (dev)
+ dev_put(dev);
+ canraw_sk(sk)->bound = 0;
#endif
- }
-
- if (addr->can_ifindex) {
- dev = dev_get_by_index(addr->can_ifindex);
- if (!dev) {
- DBG("could not find device %d\n", addr->can_ifindex);
- return -ENODEV;
}
- if (!(dev->flags & IFF_UP)) {
- sk->err = ENETDOWN;
- sk->error_report(sk);
- goto out;
- }
- can_dev_register(dev, raw_notifier, sk);
- } else
- dev = NULL;
- canraw_sk(sk)->ifindex = addr->can_ifindex;
+ if (addr->can_ifindex) {
+ dev = dev_get_by_index(addr->can_ifindex);
+ if (!dev) {
+ DBG("could not find device %d\n", addr->can_ifindex);
+ return -ENODEV;
+ }
+ if (!(dev->flags & IFF_UP)) {
+ sk->err = ENETDOWN;
+ sk->error_report(sk);
+ goto out;
+ }
+ can_dev_register(dev, raw_notifier, sk);
+ } else
+ dev = NULL;
+
+ canraw_sk(sk)->ifindex = addr->can_ifindex;
- if (canraw_sk(sk)->count > 0) /* filters set by setsockopt */
- raw_add_filters(dev, sk);
- else
- can_rx_register(dev, 0, MASK_ALL, raw_rcv, sk, IDENT);
+ if (canraw_sk(sk)->count > 0) /* filters set by setsockopt */
+ raw_add_filters(dev, sk);
+ else
+ can_rx_register(dev, 0, MASK_ALL, raw_rcv, sk, IDENT);
- if (canraw_sk(sk)->err_mask) /* error frame filter set by setsockopt */
- can_rx_register(dev, 0, (canid_t)(canraw_sk(sk)->err_mask | CAN_ERR_FLAG), raw_rcv, sk, IDENT);
+ if (canraw_sk(sk)->err_mask) /* error frame filter set by setsockopt */
+ can_rx_register(dev, 0, (canid_t)(canraw_sk(sk)->err_mask | CAN_ERR_FLAG), raw_rcv, sk, IDENT);
- canraw_sk(sk)->bound = 1;
+ canraw_sk(sk)->bound = 1;
out:
- if (dev)
- dev_put(dev);
+ if (dev)
+ dev_put(dev);
- return 0;
+ return 0;
}
static int raw_getname(struct socket *sock, struct sockaddr *uaddr,
int *len, int peer)
{
- struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
- struct sock *sk = sock->sk;
+ struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
+ struct sock *sk = sock->sk;
- if (peer)
- return -EOPNOTSUPP;
+ if (peer)
+ return -EOPNOTSUPP;
- addr->can_family = AF_CAN;
- addr->can_ifindex = canraw_sk(sk)->ifindex;
- *len = sizeof(*addr);
+ addr->can_family = AF_CAN;
+ addr->can_ifindex = canraw_sk(sk)->ifindex;
+ *len = sizeof(*addr);
- return 0;
+ return 0;
}
static unsigned int raw_poll(struct file *file, struct socket *sock,
poll_table *wait)
{
- unsigned int mask = 0;
+ unsigned int mask = 0;
- DBG("socket %p\n", sock);
+ DBG("socket %p\n", sock);
- mask = datagram_poll(file, sock, wait);
- return mask;
+ mask = datagram_poll(file, sock, wait);
+ return mask;
}
static int raw_setsockopt(struct socket *sock, int level, int optname,
char *optval, int optlen)
{
- struct sock *sk = sock->sk;
- struct can_filter *filter = NULL;
- struct net_device *dev = NULL;
- can_err_mask_t err_mask = 0;
- int count = 0;
- int err;
-
- if (level != SOL_CAN_RAW)
- return -EINVAL;
-
- switch (optname) {
- case CAN_RAW_FILTER:
- if (optlen) {
- if (optlen % sizeof(struct can_filter) != 0)
+ struct sock *sk = sock->sk;
+ struct can_filter *filter = NULL;
+ struct net_device *dev = NULL;
+ can_err_mask_t err_mask = 0;
+ int count = 0;
+ int err;
+
+ if (level != SOL_CAN_RAW)
return -EINVAL;
- if (!(filter = kmalloc(optlen, GFP_KERNEL)))
- return -ENOMEM;
- if (err = copy_from_user(filter, optval, optlen)) {
- kfree(filter);
- return err;
- }
- count = optlen / sizeof(struct can_filter);
- }
-
- if (canraw_sk(sk)->bound && canraw_sk(sk)->ifindex)
- dev = dev_get_by_index(canraw_sk(sk)->ifindex);
- /* remove current filters & unregister */
- if (canraw_sk(sk)->count > 0) {
-
- if (canraw_sk(sk)->bound)
- raw_remove_filters(dev, sk);
-
- kfree(canraw_sk(sk)->filter);
- canraw_sk(sk)->count = 0;
- canraw_sk(sk)->filter = NULL;
- } else if (canraw_sk(sk)->bound)
- can_rx_unregister(dev, 0, MASK_ALL, raw_rcv, sk);
-
- /* add new filters & register */
- if (optlen) {
- canraw_sk(sk)->filter = filter;
- canraw_sk(sk)->count = count;
- if (canraw_sk(sk)->bound)
- raw_add_filters(dev, sk);
- } else if (canraw_sk(sk)->bound)
- can_rx_register(dev, 0, MASK_ALL, raw_rcv, sk, IDENT);
-
- if (dev)
- dev_put(dev);
-
- break;
-
- case CAN_RAW_ERR_FILTER:
- if (optlen) {
- if (optlen != sizeof(err_mask))
- return -EINVAL;
- if (err = copy_from_user(&err_mask, optval, optlen)) {
- return err;
- }
+ switch (optname) {
+ case CAN_RAW_FILTER:
+ if (optlen) {
+ if (optlen % sizeof(struct can_filter) != 0)
+ return -EINVAL;
+ if (!(filter = kmalloc(optlen, GFP_KERNEL)))
+ return -ENOMEM;
+ if (err = copy_from_user(filter, optval, optlen)) {
+ kfree(filter);
+ return err;
+ }
+ count = optlen / sizeof(struct can_filter);
+ }
+
+ if (canraw_sk(sk)->bound && canraw_sk(sk)->ifindex)
+ dev = dev_get_by_index(canraw_sk(sk)->ifindex);
+
+ /* remove current filters & unregister */
+ if (canraw_sk(sk)->count > 0) {
+
+ if (canraw_sk(sk)->bound)
+ raw_remove_filters(dev, sk);
+
+ kfree(canraw_sk(sk)->filter);
+ canraw_sk(sk)->count = 0;
+ canraw_sk(sk)->filter = NULL;
+ } else if (canraw_sk(sk)->bound)
+ can_rx_unregister(dev, 0, MASK_ALL, raw_rcv, sk);
+
+ /* add new filters & register */
+ if (optlen) {
+ canraw_sk(sk)->filter = filter;
+ canraw_sk(sk)->count = count;
+ if (canraw_sk(sk)->bound)
+ raw_add_filters(dev, sk);
+ } else if (canraw_sk(sk)->bound)
+ can_rx_register(dev, 0, MASK_ALL, raw_rcv, sk, IDENT);
+
+ if (dev)
+ dev_put(dev);
+
+ break;
+
+ case CAN_RAW_ERR_FILTER:
+ if (optlen) {
+ if (optlen != sizeof(err_mask))
+ return -EINVAL;
+ if (err = copy_from_user(&err_mask, optval, optlen)) {
+ return err;
+ }
+ }
+
+ err_mask &= CAN_ERR_MASK;
+
+ if (canraw_sk(sk)->bound && canraw_sk(sk)->ifindex)
+ dev = dev_get_by_index(canraw_sk(sk)->ifindex);
+
+ /* remove current error mask */
+ if (canraw_sk(sk)->err_mask && canraw_sk(sk)->bound)
+ can_rx_unregister(dev, 0, (canid_t)(canraw_sk(sk)->err_mask | CAN_ERR_FLAG), raw_rcv, sk);
+
+ /* add new error mask */
+ if (optlen) {
+ canraw_sk(sk)->err_mask = err_mask;
+ if (canraw_sk(sk)->err_mask & canraw_sk(sk)->bound)
+ can_rx_register(dev, 0, (canid_t)(canraw_sk(sk)->err_mask | CAN_ERR_FLAG), raw_rcv, sk, IDENT);
+ }
+
+ if (dev)
+ dev_put(dev);
+
+ break;
+
+ default:
+ return -ENOPROTOOPT;
}
-
- err_mask &= CAN_ERR_MASK;
-
- if (canraw_sk(sk)->bound && canraw_sk(sk)->ifindex)
- dev = dev_get_by_index(canraw_sk(sk)->ifindex);
-
- /* remove current error mask */
- if (canraw_sk(sk)->err_mask && canraw_sk(sk)->bound)
- can_rx_unregister(dev, 0, (canid_t)(canraw_sk(sk)->err_mask | CAN_ERR_FLAG), raw_rcv, sk);
-
- /* add new error mask */
- if (optlen) {
- canraw_sk(sk)->err_mask = err_mask;
- if (canraw_sk(sk)->err_mask & canraw_sk(sk)->bound)
- can_rx_register(dev, 0, (canid_t)(canraw_sk(sk)->err_mask | CAN_ERR_FLAG), raw_rcv, sk, IDENT);
- }
-
- if (dev)
- dev_put(dev);
-
- break;
-
- default:
- return -ENOPROTOOPT;
- }
- return 0;
+ return 0;
}
static int raw_getsockopt(struct socket *sock, int level, int optname,
char *optval, int *optlen)
{
- struct sock *sk = sock->sk;
- struct can_filter *filter = canraw_sk(sk)->filter;
- int len;
-
- if (level != SOL_CAN_RAW)
- return -EINVAL;
+ struct sock *sk = sock->sk;
+ struct can_filter *filter = canraw_sk(sk)->filter;
+ int len;
- switch (optname) {
- case CAN_RAW_FILTER:
- if (get_user(len, optlen))
- return -EFAULT;
-
- if (filter) {
- int filter_size = canraw_sk(sk)->count * sizeof(struct can_filter);
- if (len < filter_size)
+ if (level != SOL_CAN_RAW)
return -EINVAL;
- if (len > filter_size)
- len = filter_size;
- if (copy_to_user(optval, filter, len))
- return -EFAULT;
- } else
- len = 0;
- if (put_user(len, optlen))
- return -EFAULT;
- break;
-
- case CAN_RAW_ERR_FILTER:
- if (get_user(len, optlen))
- return -EFAULT;
-
- if (len < sizeof(can_err_mask_t))
- return -EINVAL;
-
- if (len > sizeof(can_err_mask_t))
- len = sizeof(can_err_mask_t);
- if (copy_to_user(optval, &canraw_sk(sk)->err_mask, len))
- return -EFAULT;
-
- if (put_user(len, optlen))
- return -EFAULT;
- break;
-
- default:
- return -ENOPROTOOPT;
- }
- return 0;
+ switch (optname) {
+ case CAN_RAW_FILTER:
+ if (get_user(len, optlen))
+ return -EFAULT;
+
+ if (filter) {
+ int filter_size = canraw_sk(sk)->count * sizeof(struct can_filter);
+ if (len < filter_size)
+ return -EINVAL;
+ if (len > filter_size)
+ len = filter_size;
+ if (copy_to_user(optval, filter, len))
+ return -EFAULT;
+ } else
+ len = 0;
+ if (put_user(len, optlen))
+ return -EFAULT;
+ break;
+
+ case CAN_RAW_ERR_FILTER:
+ if (get_user(len, optlen))
+ return -EFAULT;
+
+ if (len < sizeof(can_err_mask_t))
+ return -EINVAL;
+
+ if (len > sizeof(can_err_mask_t))
+ len = sizeof(can_err_mask_t);
+
+ if (copy_to_user(optval, &canraw_sk(sk)->err_mask, len))
+ return -EFAULT;
+
+ if (put_user(len, optlen))
+ return -EFAULT;
+ break;
+
+ default:
+ return -ENOPROTOOPT;
+ }
+ return 0;
}
static void raw_add_filters(struct net_device *dev, struct sock *sk)
{
- struct can_filter *filter = canraw_sk(sk)->filter;
- int i;
-
- for (i = 0; i < canraw_sk(sk)->count; i++) {
- can_rx_register(dev, filter[i].can_id, filter[i].can_mask,
- raw_rcv, sk, IDENT);
- DBG("filter can_id %08X, can_mask %08X%s, sk %p\n",
- filter[i].can_id, filter[i].can_mask,
- filter[i].can_id & CAN_INV_FILTER ? " (inv)" : "", sk);
- }
+ struct can_filter *filter = canraw_sk(sk)->filter;
+ int i;
+
+ for (i = 0; i < canraw_sk(sk)->count; i++) {
+ can_rx_register(dev, filter[i].can_id, filter[i].can_mask,
+ raw_rcv, sk, IDENT);
+ DBG("filter can_id %08X, can_mask %08X%s, sk %p\n",
+ filter[i].can_id, filter[i].can_mask,
+ filter[i].can_id & CAN_INV_FILTER ? " (inv)" : "", sk);
+ }
}
static void raw_remove_filters(struct net_device *dev, struct sock *sk)
{
- struct can_filter *filter = canraw_sk(sk)->filter;
- int i;
-
- for (i = 0; i < canraw_sk(sk)->count; i++) {
- can_rx_unregister(dev, filter[i].can_id, filter[i].can_mask,
- raw_rcv, sk);
- DBG("filter can_id %08X, can_mask %08X%s, sk %p\n",
- filter[i].can_id, filter[i].can_mask,
- filter[i].can_id & CAN_INV_FILTER ? " (inv)" : "", sk);
- }
+ struct can_filter *filter = canraw_sk(sk)->filter;
+ int i;
+
+ for (i = 0; i < canraw_sk(sk)->count; i++) {
+ can_rx_unregister(dev, filter[i].can_id, filter[i].can_mask,
+ raw_rcv, sk);
+ DBG("filter can_id %08X, can_mask %08X%s, sk %p\n",
+ filter[i].can_id, filter[i].can_mask,
+ filter[i].can_id & CAN_INV_FILTER ? " (inv)" : "", sk);
+ }
}
static int raw_sendmsg(struct socket *sock, struct msghdr *msg, int size,
struct scm_cookie *scm)
{
- struct sock *sk = sock->sk;
- struct sk_buff *skb;
- struct net_device *dev;
- int ifindex;
- int err;
-
- DBG("socket %p, sk %p\n", sock, sk);
-
- if (msg->msg_name) {
- struct sockaddr_can *addr = (struct sockaddr_can *)msg->msg_name;
- if (addr->can_family != AF_CAN)
- return -EINVAL;
- ifindex = addr->can_ifindex;
- } else
- ifindex = canraw_sk(sk)->ifindex;
-
- if (!(dev = dev_get_by_index(ifindex))) {
- DBG("device %d not found\n", ifindex);
- return -ENXIO;
- }
-
- skb = alloc_skb(size, GFP_KERNEL);
- if ((err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size)) < 0) {
- kfree_skb(skb);
- dev_put(dev);
- return err;
- }
- skb->dev = dev;
+ struct sock *sk = sock->sk;
+ struct sk_buff *skb;
+ struct net_device *dev;
+ int ifindex;
+ int err;
+
+ DBG("socket %p, sk %p\n", sock, sk);
+
+ if (msg->msg_name) {
+ struct sockaddr_can *addr = (struct sockaddr_can *)msg->msg_name;
+ if (addr->can_family != AF_CAN)
+ return -EINVAL;
+ ifindex = addr->can_ifindex;
+ } else
+ ifindex = canraw_sk(sk)->ifindex;
+
+ if (!(dev = dev_get_by_index(ifindex))) {
+ DBG("device %d not found\n", ifindex);
+ return -ENXIO;
+ }
+
+ skb = alloc_skb(size, GFP_KERNEL);
+ if ((err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size)) < 0) {
+ kfree_skb(skb);
+ dev_put(dev);
+ return err;
+ }
+ skb->dev = dev;
- DBG("sending skbuff to interface %d\n", ifindex);
- DBG_SKB(skb);
+ DBG("sending skbuff to interface %d\n", ifindex);
+ DBG_SKB(skb);
- err = can_send(skb);
+ err = can_send(skb);
- dev_put(dev);
+ dev_put(dev);
- if (err)
- return err;
+ if (err)
+ return err;
- return size;
+ return size;
}
static int raw_recvmsg(struct socket *sock, struct msghdr *msg, int size,
int flags, struct scm_cookie *scm)
{
- struct sock *sk = sock->sk;
- struct sk_buff *skb;
- int error = 0;
- int noblock;
-
- DBG("socket %p, sk %p\n", sock, sk);
-
- noblock = flags & MSG_DONTWAIT;
- flags &= ~MSG_DONTWAIT;
- if (!(skb = skb_recv_datagram(sk, flags, noblock, &error))) {
- return error;
- }
-
- DBG("delivering skbuff %p\n", skb);
- DBG_SKB(skb);
-
- if (size < skb->len)
- msg->msg_flags |= MSG_TRUNC;
- else
- size = skb->len;
- if ((error = memcpy_toiovec(msg->msg_iov, skb->data, size)) < 0) {
- skb_free_datagram(sk, skb);
- return error;
- }
+ struct sock *sk = sock->sk;
+ struct sk_buff *skb;
+ int error = 0;
+ int noblock;
- sock_recv_timestamp(msg, sk, skb);
+ DBG("socket %p, sk %p\n", sock, sk);
- if (msg->msg_name) {
- msg->msg_namelen = sizeof(struct sockaddr_can);
- memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
- }
+ noblock = flags & MSG_DONTWAIT;
+ flags &= ~MSG_DONTWAIT;
+ if (!(skb = skb_recv_datagram(sk, flags, noblock, &error))) {
+ return error;
+ }
+
+ DBG("delivering skbuff %p\n", skb);
+ DBG_SKB(skb);
+
+ if (size < skb->len)
+ msg->msg_flags |= MSG_TRUNC;
+ else
+ size = skb->len;
+ if ((error = memcpy_toiovec(msg->msg_iov, skb->data, size)) < 0) {
+ skb_free_datagram(sk, skb);
+ return error;
+ }
+
+ sock_recv_timestamp(msg, sk, skb);
- DBG("freeing sock %p, skbuff %p\n", sk, skb);
- skb_free_datagram(sk, skb);
+ if (msg->msg_name) {
+ msg->msg_namelen = sizeof(struct sockaddr_can);
+ memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
+ }
+
+ DBG("freeing sock %p, skbuff %p\n", sk, skb);
+ skb_free_datagram(sk, skb);
- return size;
+ return size;
}
static void raw_rcv(struct sk_buff *skb, void *data)
{
- struct sock *sk = (struct sock*)data;
- struct sockaddr_can *addr;
- int error;
-
- DBG("received skbuff %p, sk %p\n", skb, sk);
- DBG_SKB(skb);
-
- addr = (struct sockaddr_can *)skb->cb;
- memset(addr, 0, sizeof(*addr));
- addr->can_family = AF_CAN;
- addr->can_ifindex = skb->dev->ifindex;
-
- if ((error = sock_queue_rcv_skb(sk, skb)) < 0) {
- DBG("sock_queue_rcv_skb failed: %d\n", error);
- DBG("freeing skbuff %p\n", skb);
- kfree_skb(skb);
- }
+ struct sock *sk = (struct sock*)data;
+ struct sockaddr_can *addr;
+ int error;
+
+ DBG("received skbuff %p, sk %p\n", skb, sk);
+ DBG_SKB(skb);
+
+ addr = (struct sockaddr_can *)skb->cb;
+ memset(addr, 0, sizeof(*addr));
+ addr->can_family = AF_CAN;
+ addr->can_ifindex = skb->dev->ifindex;
+
+ if ((error = sock_queue_rcv_skb(sk, skb)) < 0) {
+ DBG("sock_queue_rcv_skb failed: %d\n", error);
+ DBG("freeing skbuff %p\n", skb);
+ kfree_skb(skb);
+ }
}
static void raw_notifier(unsigned long msg, void *data)
{
- struct sock *sk = (struct sock *)data;
-
- DBG("called for sock %p\n", sk);
-
- switch (msg) {
- case NETDEV_UNREGISTER:
- canraw_sk(sk)->ifindex = 0;
- /* fallthrough */
- case NETDEV_DOWN:
- sk->err = ENETDOWN;
- sk->error_report(sk);
- break;
- }
+ struct sock *sk = (struct sock *)data;
+
+ DBG("called for sock %p\n", sk);
+
+ switch (msg) {
+ case NETDEV_UNREGISTER:
+ canraw_sk(sk)->ifindex = 0;
+ /* fallthrough */
+ case NETDEV_DOWN:
+ sk->err = ENETDOWN;
+ sk->error_report(sk);
+ break;
+ }
}
static int vcan_init(struct net_device *dev);
static struct net_device vcan_devs[NDEVICES] = {
- { .init = vcan_init, .name = "vcan%d" },
- { .init = vcan_init, .name = "vcan%d" },
- { .init = vcan_init, .name = "vcan%d" },
- { .init = vcan_init, .name = "vcan%d" },
+ { .init = vcan_init, .name = "vcan%d" },
+ { .init = vcan_init, .name = "vcan%d" },
+ { .init = vcan_init, .name = "vcan%d" },
+ { .init = vcan_init, .name = "vcan%d" },
};
static int vcan_open(struct net_device *dev)
{
- DBG("%s: interface up\n", dev->name);
+ DBG("%s: interface up\n", dev->name);
- netif_start_queue(dev);
- return 0;
+ netif_start_queue(dev);
+ return 0;
}
static int vcan_stop(struct net_device *dev)
{
- DBG("%s: interface down\n", dev->name);
+ DBG("%s: interface down\n", dev->name);
- netif_stop_queue(dev);
- return 0;
+ netif_stop_queue(dev);
+ return 0;
}
#ifdef DO_LOOPBACK
static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
{
- struct net_device_stats *stats = netdev_priv(dev);
- stats->rx_packets++;
- stats->rx_bytes += skb->len;
+ struct net_device_stats *stats = netdev_priv(dev);
+ stats->rx_packets++;
+ stats->rx_bytes += skb->len;
- skb->protocol = htons(ETH_P_CAN);
- skb->dev = dev;
- skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->protocol = htons(ETH_P_CAN);
+ skb->dev = dev;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
- DBG("received skbuff on interface %d\n", dev->ifindex);
- DBG_SKB(skb);
+ DBG("received skbuff on interface %d\n", dev->ifindex);
+ DBG_SKB(skb);
- netif_rx(skb);
+ netif_rx(skb);
}
#endif
static int vcan_tx(struct sk_buff *skb, struct net_device *dev)
{
- struct net_device_stats *stats = netdev_priv(dev);
+ struct net_device_stats *stats = netdev_priv(dev);
- DBG("sending skbuff on interface %s\n", dev->name);
- DBG_SKB(skb);
- DBG_FRAME("VCAN: transmit CAN frame", (struct can_frame *)skb->data);
+ DBG("sending skbuff on interface %s\n", dev->name);
+ DBG_SKB(skb);
+ DBG_FRAME("VCAN: transmit CAN frame", (struct can_frame *)skb->data);
#ifdef DO_LOOPBACK
- if (atomic_read(&skb->users) != 1) {
- struct sk_buff *old_skb = skb;
- skb = skb_clone(old_skb, GFP_ATOMIC);
- DBG(" freeing old skbuff %p, using new skbuff %p\n", old_skb, skb);
- kfree_skb(old_skb);
- if (!skb) {
- return 0;
- }
- } else
- skb_orphan(skb);
+ if (atomic_read(&skb->users) != 1) {
+ struct sk_buff *old_skb = skb;
+ skb = skb_clone(old_skb, GFP_ATOMIC);
+ DBG(" freeing old skbuff %p, using new skbuff %p\n",
+ old_skb, skb);
+ kfree_skb(old_skb);
+ if (!skb) {
+ return 0;
+ }
+ } else
+ skb_orphan(skb);
#endif
- stats->tx_packets++;
- stats->tx_bytes += skb->len;
+ stats->tx_packets++;
+ stats->tx_bytes += skb->len;
#ifdef DO_LOOPBACK
- vcan_rx(skb, dev);
+ vcan_rx(skb, dev);
#else
- stats->rx_packets++;
- stats->rx_bytes += skb->len;
- kfree_skb(skb);
+ stats->rx_packets++;
+ stats->rx_bytes += skb->len;
+ kfree_skb(skb);
#endif
- return 0;
+ return 0;
}
static int vcan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- return -EOPNOTSUPP;
+ return -EOPNOTSUPP;
}
static int vcan_rebuild_header(struct sk_buff *skb)
{
- DBG("called on skbuff %p\n", skb);
- DBG_SKB(skb);
- return 0;
+ DBG("called on skbuff %p\n", skb);
+ DBG_SKB(skb);
+ return 0;
}
static int vcan_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, void *daddr, void *saddr,
unsigned int len)
{
- DBG("called skbuff %p device %p\n", skb, dev);
- DBG_SKB(skb);
- return 0;
+ DBG("called skbuff %p device %p\n", skb, dev);
+ DBG_SKB(skb);
+ return 0;
}
static struct net_device_stats *vcan_get_stats(struct net_device *dev)
{
- struct net_device_stats *stats = netdev_priv(dev);
- return stats;
+ struct net_device_stats *stats = netdev_priv(dev);
+ return stats;
}
static int vcan_init(struct net_device *dev)
{
- DBG("dev %s\n", dev->name);
+ DBG("dev %s\n", dev->name);
- ether_setup(dev);
+ ether_setup(dev);
- dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
- if (!dev->priv)
- return -ENOMEM;
- memset(dev->priv, 0, sizeof(struct net_device_stats));
+ dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
+ if (!dev->priv)
+ return -ENOMEM;
+ memset(dev->priv, 0, sizeof(struct net_device_stats));
- dev->open = vcan_open;
- dev->stop = vcan_stop;
- dev->set_config = NULL;
- dev->hard_start_xmit = vcan_tx;
- dev->do_ioctl = vcan_ioctl;
- dev->get_stats = vcan_get_stats;
+ dev->open = vcan_open;
+ dev->stop = vcan_stop;
+ dev->set_config = NULL;
+ dev->hard_start_xmit = vcan_tx;
+ dev->do_ioctl = vcan_ioctl;
+ dev->get_stats = vcan_get_stats;
- dev->mtu = sizeof(struct can_frame);
- dev->flags = IFF_LOOPBACK;
- dev->hard_header = vcan_header;
- dev->rebuild_header = vcan_rebuild_header;
- dev->hard_header_cache = NULL;
- dev->type = ARPHRD_LOOPBACK;
+ dev->mtu = sizeof(struct can_frame);
+ dev->flags = IFF_LOOPBACK;
+ dev->hard_header = vcan_header;
+ dev->rebuild_header = vcan_rebuild_header;
+ dev->hard_header_cache = NULL;
+ dev->type = ARPHRD_LOOPBACK;
- SET_MODULE_OWNER(dev);
+ SET_MODULE_OWNER(dev);
- return 0;
+ return 0;
}
static __init int vcan_init_module(void)
{
- int i, ndev = 0, result;
-
- printk(banner);
-
- for (i = 0; i < NDEVICES; i++) {
- if (result = register_netdev(vcan_devs + i))
- printk(KERN_ERR "vcan: error %d registering interface %s\n",
- result, vcan_devs[i].name);
- else {
- DBG("successfully registered interface %s\n", vcan_devs[i].name);
- ndev++;
+ int i, ndev = 0, result;
+
+ printk(banner);
+
+ for (i = 0; i < NDEVICES; i++) {
+ if (result = register_netdev(vcan_devs + i))
+ printk(KERN_ERR "vcan: error %d registering interface %s\n",
+ result, vcan_devs[i].name);
+ else {
+ DBG("successfully registered interface %s\n",
+ vcan_devs[i].name);
+ ndev++;
+ }
}
- }
- return ndev ? 0 : -ENODEV;
+ return ndev ? 0 : -ENODEV;
}
static __exit void vcan_cleanup_module(void)
{
- int i;
- for (i = 0; i < NDEVICES; i++)
- unregister_netdev(vcan_devs + i);
+ int i;
+ for (i = 0; i < NDEVICES; i++)
+ unregister_netdev(vcan_devs + i);
}
module_init(vcan_init_module);