diff options
author | David S. Miller <davem@davemloft.net> | 2015-04-01 13:58:06 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-04-01 13:58:06 -0400 |
commit | b9600d2d0901cd0f91cb372e72bd53d22f49638d (patch) | |
tree | 6684a4fd1345c65a5a91aff272785cd0943d347d | |
parent | 8d88c6ebb34c3e54debe81e9b0d81b60411f8179 (diff) | |
parent | 79d5eeddd7d23bd4588e370072977928b7075911 (diff) |
Merge tag 'linux-can-next-for-4.1-20150401' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next
Marc Kleine-Budde says:
====================
pull-request: can-next 2015-04-01
this is a pull request of 5 patches for net-next/master.
There are two patches for the ems_usb driver by Gerhard Uttenthaler and
me, which fix sparse endianess warnings. Oliver Hartkopp adds two
patches to improve and extend the CAN-ID filter handling on RAW CAN
sockets. The last patch is by me, it silences an uninitialized variable
warning in the peak_usb driver.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | Documentation/networking/can.txt | 20 | ||||
-rw-r--r-- | drivers/net/can/usb/ems_usb.c | 11 | ||||
-rw-r--r-- | drivers/net/can/usb/peak_usb/pcan_usb_fd.c | 2 | ||||
-rw-r--r-- | include/uapi/linux/can/raw.h | 1 | ||||
-rw-r--r-- | net/can/raw.c | 50 |
5 files changed, 74 insertions, 10 deletions
diff --git a/Documentation/networking/can.txt b/Documentation/networking/can.txt index 0a2859a8ee7e..5abad1e921ca 100644 --- a/Documentation/networking/can.txt +++ b/Documentation/networking/can.txt | |||
@@ -22,7 +22,8 @@ This file contains | |||
22 | 4.1.3 RAW socket option CAN_RAW_LOOPBACK | 22 | 4.1.3 RAW socket option CAN_RAW_LOOPBACK |
23 | 4.1.4 RAW socket option CAN_RAW_RECV_OWN_MSGS | 23 | 4.1.4 RAW socket option CAN_RAW_RECV_OWN_MSGS |
24 | 4.1.5 RAW socket option CAN_RAW_FD_FRAMES | 24 | 4.1.5 RAW socket option CAN_RAW_FD_FRAMES |
25 | 4.1.6 RAW socket returned message flags | 25 | 4.1.6 RAW socket option CAN_RAW_JOIN_FILTERS |
26 | 4.1.7 RAW socket returned message flags | ||
26 | 4.2 Broadcast Manager protocol sockets (SOCK_DGRAM) | 27 | 4.2 Broadcast Manager protocol sockets (SOCK_DGRAM) |
27 | 4.2.1 Broadcast Manager operations | 28 | 4.2.1 Broadcast Manager operations |
28 | 4.2.2 Broadcast Manager message flags | 29 | 4.2.2 Broadcast Manager message flags |
@@ -601,7 +602,22 @@ solution for a couple of reasons: | |||
601 | CAN FD frames by checking if the device maximum transfer unit is CANFD_MTU. | 602 | CAN FD frames by checking if the device maximum transfer unit is CANFD_MTU. |
602 | The CAN device MTU can be retrieved e.g. with a SIOCGIFMTU ioctl() syscall. | 603 | The CAN device MTU can be retrieved e.g. with a SIOCGIFMTU ioctl() syscall. |
603 | 604 | ||
604 | 4.1.6 RAW socket returned message flags | 605 | 4.1.6 RAW socket option CAN_RAW_JOIN_FILTERS |
606 | |||
607 | The CAN_RAW socket can set multiple CAN identifier specific filters that | ||
608 | lead to multiple filters in the af_can.c filter processing. These filters | ||
609 | are indenpendent from each other which leads to logical OR'ed filters when | ||
610 | applied (see 4.1.1). | ||
611 | |||
612 | This socket option joines the given CAN filters in the way that only CAN | ||
613 | frames are passed to user space that matched *all* given CAN filters. The | ||
614 | semantic for the applied filters is therefore changed to a logical AND. | ||
615 | |||
616 | This is useful especially when the filterset is a combination of filters | ||
617 | where the CAN_INV_FILTER flag is set in order to notch single CAN IDs or | ||
618 | CAN ID ranges from the incoming traffic. | ||
619 | |||
620 | 4.1.7 RAW socket returned message flags | ||
605 | 621 | ||
606 | When using recvmsg() call, the msg->msg_flags may contain following flags: | 622 | When using recvmsg() call, the msg->msg_flags may contain following flags: |
607 | 623 | ||
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index 9376f5e5b94e..866bac0ae7e9 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c | |||
@@ -123,7 +123,7 @@ MODULE_LICENSE("GPL v2"); | |||
123 | * CPC_MSG_TYPE_EXT_CAN_FRAME or CPC_MSG_TYPE_EXT_RTR_FRAME. | 123 | * CPC_MSG_TYPE_EXT_CAN_FRAME or CPC_MSG_TYPE_EXT_RTR_FRAME. |
124 | */ | 124 | */ |
125 | struct cpc_can_msg { | 125 | struct cpc_can_msg { |
126 | u32 id; | 126 | __le32 id; |
127 | u8 length; | 127 | u8 length; |
128 | u8 msg[8]; | 128 | u8 msg[8]; |
129 | }; | 129 | }; |
@@ -200,8 +200,8 @@ struct __packed ems_cpc_msg { | |||
200 | u8 type; /* type of message */ | 200 | u8 type; /* type of message */ |
201 | u8 length; /* length of data within union 'msg' */ | 201 | u8 length; /* length of data within union 'msg' */ |
202 | u8 msgid; /* confirmation handle */ | 202 | u8 msgid; /* confirmation handle */ |
203 | u32 ts_sec; /* timestamp in seconds */ | 203 | __le32 ts_sec; /* timestamp in seconds */ |
204 | u32 ts_nsec; /* timestamp in nano seconds */ | 204 | __le32 ts_nsec; /* timestamp in nano seconds */ |
205 | 205 | ||
206 | union { | 206 | union { |
207 | u8 generic[64]; | 207 | u8 generic[64]; |
@@ -765,7 +765,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne | |||
765 | 765 | ||
766 | msg = (struct ems_cpc_msg *)&buf[CPC_HEADER_SIZE]; | 766 | msg = (struct ems_cpc_msg *)&buf[CPC_HEADER_SIZE]; |
767 | 767 | ||
768 | msg->msg.can_msg.id = cf->can_id & CAN_ERR_MASK; | 768 | msg->msg.can_msg.id = cpu_to_le32(cf->can_id & CAN_ERR_MASK); |
769 | msg->msg.can_msg.length = cf->can_dlc; | 769 | msg->msg.can_msg.length = cf->can_dlc; |
770 | 770 | ||
771 | if (cf->can_id & CAN_RTR_FLAG) { | 771 | if (cf->can_id & CAN_RTR_FLAG) { |
@@ -783,9 +783,6 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne | |||
783 | msg->length = CPC_CAN_MSG_MIN_SIZE + cf->can_dlc; | 783 | msg->length = CPC_CAN_MSG_MIN_SIZE + cf->can_dlc; |
784 | } | 784 | } |
785 | 785 | ||
786 | /* Respect byte order */ | ||
787 | msg->msg.can_msg.id = cpu_to_le32(msg->msg.can_msg.id); | ||
788 | |||
789 | for (i = 0; i < MAX_TX_URBS; i++) { | 786 | for (i = 0; i < MAX_TX_URBS; i++) { |
790 | if (dev->tx_contexts[i].echo_index == MAX_TX_URBS) { | 787 | if (dev->tx_contexts[i].echo_index == MAX_TX_URBS) { |
791 | context = &dev->tx_contexts[i]; | 788 | context = &dev->tx_contexts[i]; |
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c index 0bac0f14edc3..00481eeb9924 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c | |||
@@ -182,7 +182,7 @@ static inline void *pcan_usb_fd_cmd_buffer(struct peak_usb_device *dev) | |||
182 | static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) | 182 | static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) |
183 | { | 183 | { |
184 | void *cmd_head = pcan_usb_fd_cmd_buffer(dev); | 184 | void *cmd_head = pcan_usb_fd_cmd_buffer(dev); |
185 | int err; | 185 | int err = 0; |
186 | u8 *packet_ptr; | 186 | u8 *packet_ptr; |
187 | int i, n = 1, packet_len; | 187 | int i, n = 1, packet_len; |
188 | ptrdiff_t cmd_len; | 188 | ptrdiff_t cmd_len; |
diff --git a/include/uapi/linux/can/raw.h b/include/uapi/linux/can/raw.h index 78ec76fd89a6..8735f1080385 100644 --- a/include/uapi/linux/can/raw.h +++ b/include/uapi/linux/can/raw.h | |||
@@ -57,6 +57,7 @@ enum { | |||
57 | CAN_RAW_LOOPBACK, /* local loopback (default:on) */ | 57 | CAN_RAW_LOOPBACK, /* local loopback (default:on) */ |
58 | CAN_RAW_RECV_OWN_MSGS, /* receive my own msgs (default:off) */ | 58 | CAN_RAW_RECV_OWN_MSGS, /* receive my own msgs (default:off) */ |
59 | CAN_RAW_FD_FRAMES, /* allow CAN FD frames (default:off) */ | 59 | CAN_RAW_FD_FRAMES, /* allow CAN FD frames (default:off) */ |
60 | CAN_RAW_JOIN_FILTERS, /* all filters must match to trigger */ | ||
60 | }; | 61 | }; |
61 | 62 | ||
62 | #endif /* !_UAPI_CAN_RAW_H */ | 63 | #endif /* !_UAPI_CAN_RAW_H */ |
diff --git a/net/can/raw.c b/net/can/raw.c index 63ffdb0f3a23..31b9748cbb4e 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
@@ -74,6 +74,12 @@ MODULE_ALIAS("can-proto-1"); | |||
74 | * storing the single filter in dfilter, to avoid using dynamic memory. | 74 | * storing the single filter in dfilter, to avoid using dynamic memory. |
75 | */ | 75 | */ |
76 | 76 | ||
77 | struct uniqframe { | ||
78 | ktime_t tstamp; | ||
79 | const struct sk_buff *skb; | ||
80 | unsigned int join_rx_count; | ||
81 | }; | ||
82 | |||
77 | struct raw_sock { | 83 | struct raw_sock { |
78 | struct sock sk; | 84 | struct sock sk; |
79 | int bound; | 85 | int bound; |
@@ -82,10 +88,12 @@ struct raw_sock { | |||
82 | int loopback; | 88 | int loopback; |
83 | int recv_own_msgs; | 89 | int recv_own_msgs; |
84 | int fd_frames; | 90 | int fd_frames; |
91 | int join_filters; | ||
85 | int count; /* number of active filters */ | 92 | int count; /* number of active filters */ |
86 | struct can_filter dfilter; /* default/single filter */ | 93 | struct can_filter dfilter; /* default/single filter */ |
87 | struct can_filter *filter; /* pointer to filter(s) */ | 94 | struct can_filter *filter; /* pointer to filter(s) */ |
88 | can_err_mask_t err_mask; | 95 | can_err_mask_t err_mask; |
96 | struct uniqframe __percpu *uniq; | ||
89 | }; | 97 | }; |
90 | 98 | ||
91 | /* | 99 | /* |
@@ -123,6 +131,26 @@ static void raw_rcv(struct sk_buff *oskb, void *data) | |||
123 | if (!ro->fd_frames && oskb->len != CAN_MTU) | 131 | if (!ro->fd_frames && oskb->len != CAN_MTU) |
124 | return; | 132 | return; |
125 | 133 | ||
134 | /* eliminate multiple filter matches for the same skb */ | ||
135 | if (this_cpu_ptr(ro->uniq)->skb == oskb && | ||
136 | ktime_equal(this_cpu_ptr(ro->uniq)->tstamp, oskb->tstamp)) { | ||
137 | if (ro->join_filters) { | ||
138 | this_cpu_inc(ro->uniq->join_rx_count); | ||
139 | /* drop frame until all enabled filters matched */ | ||
140 | if (this_cpu_ptr(ro->uniq)->join_rx_count < ro->count) | ||
141 | return; | ||
142 | } else { | ||
143 | return; | ||
144 | } | ||
145 | } else { | ||
146 | this_cpu_ptr(ro->uniq)->skb = oskb; | ||
147 | this_cpu_ptr(ro->uniq)->tstamp = oskb->tstamp; | ||
148 | this_cpu_ptr(ro->uniq)->join_rx_count = 1; | ||
149 | /* drop first frame to check all enabled filters? */ | ||
150 | if (ro->join_filters && ro->count > 1) | ||
151 | return; | ||
152 | } | ||
153 | |||
126 | /* clone the given skb to be able to enqueue it into the rcv queue */ | 154 | /* clone the given skb to be able to enqueue it into the rcv queue */ |
127 | skb = skb_clone(oskb, GFP_ATOMIC); | 155 | skb = skb_clone(oskb, GFP_ATOMIC); |
128 | if (!skb) | 156 | if (!skb) |
@@ -296,6 +324,12 @@ static int raw_init(struct sock *sk) | |||
296 | ro->loopback = 1; | 324 | ro->loopback = 1; |
297 | ro->recv_own_msgs = 0; | 325 | ro->recv_own_msgs = 0; |
298 | ro->fd_frames = 0; | 326 | ro->fd_frames = 0; |
327 | ro->join_filters = 0; | ||
328 | |||
329 | /* alloc_percpu provides zero'ed memory */ | ||
330 | ro->uniq = alloc_percpu(struct uniqframe); | ||
331 | if (unlikely(!ro->uniq)) | ||
332 | return -ENOMEM; | ||
299 | 333 | ||
300 | /* set notifier */ | 334 | /* set notifier */ |
301 | ro->notifier.notifier_call = raw_notifier; | 335 | ro->notifier.notifier_call = raw_notifier; |
@@ -339,6 +373,7 @@ static int raw_release(struct socket *sock) | |||
339 | ro->ifindex = 0; | 373 | ro->ifindex = 0; |
340 | ro->bound = 0; | 374 | ro->bound = 0; |
341 | ro->count = 0; | 375 | ro->count = 0; |
376 | free_percpu(ro->uniq); | ||
342 | 377 | ||
343 | sock_orphan(sk); | 378 | sock_orphan(sk); |
344 | sock->sk = NULL; | 379 | sock->sk = NULL; |
@@ -583,6 +618,15 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, | |||
583 | 618 | ||
584 | break; | 619 | break; |
585 | 620 | ||
621 | case CAN_RAW_JOIN_FILTERS: | ||
622 | if (optlen != sizeof(ro->join_filters)) | ||
623 | return -EINVAL; | ||
624 | |||
625 | if (copy_from_user(&ro->join_filters, optval, optlen)) | ||
626 | return -EFAULT; | ||
627 | |||
628 | break; | ||
629 | |||
586 | default: | 630 | default: |
587 | return -ENOPROTOOPT; | 631 | return -ENOPROTOOPT; |
588 | } | 632 | } |
@@ -647,6 +691,12 @@ static int raw_getsockopt(struct socket *sock, int level, int optname, | |||
647 | val = &ro->fd_frames; | 691 | val = &ro->fd_frames; |
648 | break; | 692 | break; |
649 | 693 | ||
694 | case CAN_RAW_JOIN_FILTERS: | ||
695 | if (len > sizeof(int)) | ||
696 | len = sizeof(int); | ||
697 | val = &ro->join_filters; | ||
698 | break; | ||
699 | |||
650 | default: | 700 | default: |
651 | return -ENOPROTOOPT; | 701 | return -ENOPROTOOPT; |
652 | } | 702 | } |