Merge branch 'for-davem' of git://gitorious.org/linux-can/linux-can-next
Marc Kleine-Budde says: ==================== here's a pull request for net-next. It includes a patch by Oliver Hartkopp et al. that adds documentation for the broadcast manager to Documentation/networking/can.txt. Three patches by me that clean up the netlink handling code in the CAN core. And another patch that removes a not needed function from the ti_hecc driver. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
13521a5797
|
@ -25,6 +25,12 @@ This file contains
|
||||||
4.1.5 RAW socket option CAN_RAW_FD_FRAMES
|
4.1.5 RAW socket option CAN_RAW_FD_FRAMES
|
||||||
4.1.6 RAW socket returned message flags
|
4.1.6 RAW socket returned message flags
|
||||||
4.2 Broadcast Manager protocol sockets (SOCK_DGRAM)
|
4.2 Broadcast Manager protocol sockets (SOCK_DGRAM)
|
||||||
|
4.2.1 Broadcast Manager operations
|
||||||
|
4.2.2 Broadcast Manager message flags
|
||||||
|
4.2.3 Broadcast Manager transmission timers
|
||||||
|
4.2.4 Broadcast Manager message sequence transmission
|
||||||
|
4.2.5 Broadcast Manager receive filter timers
|
||||||
|
4.2.6 Broadcast Manager multiplex message receive filter
|
||||||
4.3 connected transport protocols (SOCK_SEQPACKET)
|
4.3 connected transport protocols (SOCK_SEQPACKET)
|
||||||
4.4 unconnected transport protocols (SOCK_DGRAM)
|
4.4 unconnected transport protocols (SOCK_DGRAM)
|
||||||
|
|
||||||
|
@ -593,6 +599,217 @@ solution for a couple of reasons:
|
||||||
In order to receive such messages, CAN_RAW_RECV_OWN_MSGS must be set.
|
In order to receive such messages, CAN_RAW_RECV_OWN_MSGS must be set.
|
||||||
|
|
||||||
4.2 Broadcast Manager protocol sockets (SOCK_DGRAM)
|
4.2 Broadcast Manager protocol sockets (SOCK_DGRAM)
|
||||||
|
|
||||||
|
The Broadcast Manager protocol provides a command based configuration
|
||||||
|
interface to filter and send (e.g. cyclic) CAN messages in kernel space.
|
||||||
|
|
||||||
|
Receive filters can be used to down sample frequent messages; detect events
|
||||||
|
such as message contents changes, packet length changes, and do time-out
|
||||||
|
monitoring of received messages.
|
||||||
|
|
||||||
|
Periodic transmission tasks of CAN frames or a sequence of CAN frames can be
|
||||||
|
created and modified at runtime; both the message content and the two
|
||||||
|
possible transmit intervals can be altered.
|
||||||
|
|
||||||
|
A BCM socket is not intended for sending individual CAN frames using the
|
||||||
|
struct can_frame as known from the CAN_RAW socket. Instead a special BCM
|
||||||
|
configuration message is defined. The basic BCM configuration message used
|
||||||
|
to communicate with the broadcast manager and the available operations are
|
||||||
|
defined in the linux/can/bcm.h include. The BCM message consists of a
|
||||||
|
message header with a command ('opcode') followed by zero or more CAN frames.
|
||||||
|
The broadcast manager sends responses to user space in the same form:
|
||||||
|
|
||||||
|
struct bcm_msg_head {
|
||||||
|
__u32 opcode; /* command */
|
||||||
|
__u32 flags; /* special flags */
|
||||||
|
__u32 count; /* run 'count' times with ival1 */
|
||||||
|
struct timeval ival1, ival2; /* count and subsequent interval */
|
||||||
|
canid_t can_id; /* unique can_id for task */
|
||||||
|
__u32 nframes; /* number of can_frames following */
|
||||||
|
struct can_frame frames[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
The aligned payload 'frames' uses the same basic CAN frame structure defined
|
||||||
|
at the beginning of section 4 and in the include/linux/can.h include. All
|
||||||
|
messages to the broadcast manager from user space have this structure.
|
||||||
|
|
||||||
|
Note a CAN_BCM socket must be connected instead of bound after socket
|
||||||
|
creation (example without error checking):
|
||||||
|
|
||||||
|
int s;
|
||||||
|
struct sockaddr_can addr;
|
||||||
|
struct ifreq ifr;
|
||||||
|
|
||||||
|
s = socket(PF_CAN, SOCK_DGRAM, CAN_BCM);
|
||||||
|
|
||||||
|
strcpy(ifr.ifr_name, "can0");
|
||||||
|
ioctl(s, SIOCGIFINDEX, &ifr);
|
||||||
|
|
||||||
|
addr.can_family = AF_CAN;
|
||||||
|
addr.can_ifindex = ifr.ifr_ifindex;
|
||||||
|
|
||||||
|
connect(s, (struct sockaddr *)&addr, sizeof(addr))
|
||||||
|
|
||||||
|
(..)
|
||||||
|
|
||||||
|
The broadcast manager socket is able to handle any number of in flight
|
||||||
|
transmissions or receive filters concurrently. The different RX/TX jobs are
|
||||||
|
distinguished by the unique can_id in each BCM message. However additional
|
||||||
|
CAN_BCM sockets are recommended to communicate on multiple CAN interfaces.
|
||||||
|
When the broadcast manager socket is bound to 'any' CAN interface (=> the
|
||||||
|
interface index is set to zero) the configured receive filters apply to any
|
||||||
|
CAN interface unless the sendto() syscall is used to overrule the 'any' CAN
|
||||||
|
interface index. When using recvfrom() instead of read() to retrieve BCM
|
||||||
|
socket messages the originating CAN interface is provided in can_ifindex.
|
||||||
|
|
||||||
|
4.2.1 Broadcast Manager operations
|
||||||
|
|
||||||
|
The opcode defines the operation for the broadcast manager to carry out,
|
||||||
|
or details the broadcast managers response to several events, including
|
||||||
|
user requests.
|
||||||
|
|
||||||
|
Transmit Operations (user space to broadcast manager):
|
||||||
|
|
||||||
|
TX_SETUP: Create (cyclic) transmission task.
|
||||||
|
|
||||||
|
TX_DELETE: Remove (cyclic) transmission task, requires only can_id.
|
||||||
|
|
||||||
|
TX_READ: Read properties of (cyclic) transmission task for can_id.
|
||||||
|
|
||||||
|
TX_SEND: Send one CAN frame.
|
||||||
|
|
||||||
|
Transmit Responses (broadcast manager to user space):
|
||||||
|
|
||||||
|
TX_STATUS: Reply to TX_READ request (transmission task configuration).
|
||||||
|
|
||||||
|
TX_EXPIRED: Notification when counter finishes sending at initial interval
|
||||||
|
'ival1'. Requires the TX_COUNTEVT flag to be set at TX_SETUP.
|
||||||
|
|
||||||
|
Receive Operations (user space to broadcast manager):
|
||||||
|
|
||||||
|
RX_SETUP: Create RX content filter subscription.
|
||||||
|
|
||||||
|
RX_DELETE: Remove RX content filter subscription, requires only can_id.
|
||||||
|
|
||||||
|
RX_READ: Read properties of RX content filter subscription for can_id.
|
||||||
|
|
||||||
|
Receive Responses (broadcast manager to user space):
|
||||||
|
|
||||||
|
RX_STATUS: Reply to RX_READ request (filter task configuration).
|
||||||
|
|
||||||
|
RX_TIMEOUT: Cyclic message is detected to be absent (timer ival1 expired).
|
||||||
|
|
||||||
|
RX_CHANGED: BCM message with updated CAN frame (detected content change).
|
||||||
|
Sent on first message received or on receipt of revised CAN messages.
|
||||||
|
|
||||||
|
4.2.2 Broadcast Manager message flags
|
||||||
|
|
||||||
|
When sending a message to the broadcast manager the 'flags' element may
|
||||||
|
contain the following flag definitions which influence the behaviour:
|
||||||
|
|
||||||
|
SETTIMER: Set the values of ival1, ival2 and count
|
||||||
|
|
||||||
|
STARTTIMER: Start the timer with the actual values of ival1, ival2
|
||||||
|
and count. Starting the timer leads simultaneously to emit a CAN frame.
|
||||||
|
|
||||||
|
TX_COUNTEVT: Create the message TX_EXPIRED when count expires
|
||||||
|
|
||||||
|
TX_ANNOUNCE: A change of data by the process is emitted immediately.
|
||||||
|
|
||||||
|
TX_CP_CAN_ID: Copies the can_id from the message header to each
|
||||||
|
subsequent frame in frames. This is intended as usage simplification. For
|
||||||
|
TX tasks the unique can_id from the message header may differ from the
|
||||||
|
can_id(s) stored for transmission in the subsequent struct can_frame(s).
|
||||||
|
|
||||||
|
RX_FILTER_ID: Filter by can_id alone, no frames required (nframes=0).
|
||||||
|
|
||||||
|
RX_CHECK_DLC: A change of the DLC leads to an RX_CHANGED.
|
||||||
|
|
||||||
|
RX_NO_AUTOTIMER: Prevent automatically starting the timeout monitor.
|
||||||
|
|
||||||
|
RX_ANNOUNCE_RESUME: If passed at RX_SETUP and a receive timeout occured, a
|
||||||
|
RX_CHANGED message will be generated when the (cyclic) receive restarts.
|
||||||
|
|
||||||
|
TX_RESET_MULTI_IDX: Reset the index for the multiple frame transmission.
|
||||||
|
|
||||||
|
RX_RTR_FRAME: Send reply for RTR-request (placed in op->frames[0]).
|
||||||
|
|
||||||
|
4.2.3 Broadcast Manager transmission timers
|
||||||
|
|
||||||
|
Periodic transmission configurations may use up to two interval timers.
|
||||||
|
In this case the BCM sends a number of messages ('count') at an interval
|
||||||
|
'ival1', then continuing to send at another given interval 'ival2'. When
|
||||||
|
only one timer is needed 'count' is set to zero and only 'ival2' is used.
|
||||||
|
When SET_TIMER and START_TIMER flag were set the timers are activated.
|
||||||
|
The timer values can be altered at runtime when only SET_TIMER is set.
|
||||||
|
|
||||||
|
4.2.4 Broadcast Manager message sequence transmission
|
||||||
|
|
||||||
|
Up to 256 CAN frames can be transmitted in a sequence in the case of a cyclic
|
||||||
|
TX task configuration. The number of CAN frames is provided in the 'nframes'
|
||||||
|
element of the BCM message head. The defined number of CAN frames are added
|
||||||
|
as array to the TX_SETUP BCM configuration message.
|
||||||
|
|
||||||
|
/* create a struct to set up a sequence of four CAN frames */
|
||||||
|
struct {
|
||||||
|
struct bcm_msg_head msg_head;
|
||||||
|
struct can_frame frame[4];
|
||||||
|
} mytxmsg;
|
||||||
|
|
||||||
|
(..)
|
||||||
|
mytxmsg.nframes = 4;
|
||||||
|
(..)
|
||||||
|
|
||||||
|
write(s, &mytxmsg, sizeof(mytxmsg));
|
||||||
|
|
||||||
|
With every transmission the index in the array of CAN frames is increased
|
||||||
|
and set to zero at index overflow.
|
||||||
|
|
||||||
|
4.2.5 Broadcast Manager receive filter timers
|
||||||
|
|
||||||
|
The timer values ival1 or ival2 may be set to non-zero values at RX_SETUP.
|
||||||
|
When the SET_TIMER flag is set the timers are enabled:
|
||||||
|
|
||||||
|
ival1: Send RX_TIMEOUT when a received message is not received again within
|
||||||
|
the given time. When START_TIMER is set at RX_SETUP the timeout detection
|
||||||
|
is activated directly - even without a former CAN frame reception.
|
||||||
|
|
||||||
|
ival2: Throttle the received message rate down to the value of ival2. This
|
||||||
|
is useful to reduce messages for the application when the signal inside the
|
||||||
|
CAN frame is stateless as state changes within the ival2 periode may get
|
||||||
|
lost.
|
||||||
|
|
||||||
|
4.2.6 Broadcast Manager multiplex message receive filter
|
||||||
|
|
||||||
|
To filter for content changes in multiplex message sequences an array of more
|
||||||
|
than one CAN frames can be passed in a RX_SETUP configuration message. The
|
||||||
|
data bytes of the first CAN frame contain the mask of relevant bits that
|
||||||
|
have to match in the subsequent CAN frames with the received CAN frame.
|
||||||
|
If one of the subsequent CAN frames is matching the bits in that frame data
|
||||||
|
mark the relevant content to be compared with the previous received content.
|
||||||
|
Up to 257 CAN frames (multiplex filter bit mask CAN frame plus 256 CAN
|
||||||
|
filters) can be added as array to the TX_SETUP BCM configuration message.
|
||||||
|
|
||||||
|
/* usually used to clear CAN frame data[] - beware of endian problems! */
|
||||||
|
#define U64_DATA(p) (*(unsigned long long*)(p)->data)
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct bcm_msg_head msg_head;
|
||||||
|
struct can_frame frame[5];
|
||||||
|
} msg;
|
||||||
|
|
||||||
|
msg.msg_head.opcode = RX_SETUP;
|
||||||
|
msg.msg_head.can_id = 0x42;
|
||||||
|
msg.msg_head.flags = 0;
|
||||||
|
msg.msg_head.nframes = 5;
|
||||||
|
U64_DATA(&msg.frame[0]) = 0xFF00000000000000ULL; /* MUX mask */
|
||||||
|
U64_DATA(&msg.frame[1]) = 0x01000000000000FFULL; /* data mask (MUX 0x01) */
|
||||||
|
U64_DATA(&msg.frame[2]) = 0x0200FFFF000000FFULL; /* data mask (MUX 0x02) */
|
||||||
|
U64_DATA(&msg.frame[3]) = 0x330000FFFFFF0003ULL; /* data mask (MUX 0x33) */
|
||||||
|
U64_DATA(&msg.frame[4]) = 0x4F07FC0FF0000000ULL; /* data mask (MUX 0x4F) */
|
||||||
|
|
||||||
|
write(s, &msg, sizeof(msg));
|
||||||
|
|
||||||
4.3 connected transport protocols (SOCK_SEQPACKET)
|
4.3 connected transport protocols (SOCK_SEQPACKET)
|
||||||
4.4 unconnected transport protocols (SOCK_DGRAM)
|
4.4 unconnected transport protocols (SOCK_DGRAM)
|
||||||
|
|
||||||
|
|
|
@ -645,19 +645,6 @@ static int can_changelink(struct net_device *dev,
|
||||||
/* We need synchronization with dev->stop() */
|
/* We need synchronization with dev->stop() */
|
||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
|
|
||||||
if (data[IFLA_CAN_CTRLMODE]) {
|
|
||||||
struct can_ctrlmode *cm;
|
|
||||||
|
|
||||||
/* Do not allow changing controller mode while running */
|
|
||||||
if (dev->flags & IFF_UP)
|
|
||||||
return -EBUSY;
|
|
||||||
cm = nla_data(data[IFLA_CAN_CTRLMODE]);
|
|
||||||
if (cm->flags & ~priv->ctrlmode_supported)
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
priv->ctrlmode &= ~cm->mask;
|
|
||||||
priv->ctrlmode |= cm->flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data[IFLA_CAN_BITTIMING]) {
|
if (data[IFLA_CAN_BITTIMING]) {
|
||||||
struct can_bittiming bt;
|
struct can_bittiming bt;
|
||||||
|
|
||||||
|
@ -680,6 +667,19 @@ static int can_changelink(struct net_device *dev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data[IFLA_CAN_CTRLMODE]) {
|
||||||
|
struct can_ctrlmode *cm;
|
||||||
|
|
||||||
|
/* Do not allow changing controller mode while running */
|
||||||
|
if (dev->flags & IFF_UP)
|
||||||
|
return -EBUSY;
|
||||||
|
cm = nla_data(data[IFLA_CAN_CTRLMODE]);
|
||||||
|
if (cm->flags & ~priv->ctrlmode_supported)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
priv->ctrlmode &= ~cm->mask;
|
||||||
|
priv->ctrlmode |= cm->flags;
|
||||||
|
}
|
||||||
|
|
||||||
if (data[IFLA_CAN_RESTART_MS]) {
|
if (data[IFLA_CAN_RESTART_MS]) {
|
||||||
/* Do not allow changing restart delay while running */
|
/* Do not allow changing restart delay while running */
|
||||||
if (dev->flags & IFF_UP)
|
if (dev->flags & IFF_UP)
|
||||||
|
@ -702,17 +702,17 @@ static int can_changelink(struct net_device *dev,
|
||||||
static size_t can_get_size(const struct net_device *dev)
|
static size_t can_get_size(const struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct can_priv *priv = netdev_priv(dev);
|
struct can_priv *priv = netdev_priv(dev);
|
||||||
size_t size;
|
size_t size = 0;
|
||||||
|
|
||||||
size = nla_total_size(sizeof(u32)); /* IFLA_CAN_STATE */
|
size += nla_total_size(sizeof(struct can_bittiming)); /* IFLA_CAN_BITTIMING */
|
||||||
size += nla_total_size(sizeof(struct can_ctrlmode)); /* IFLA_CAN_CTRLMODE */
|
if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */
|
||||||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */
|
|
||||||
size += nla_total_size(sizeof(struct can_bittiming)); /* IFLA_CAN_BITTIMING */
|
|
||||||
size += nla_total_size(sizeof(struct can_clock)); /* IFLA_CAN_CLOCK */
|
|
||||||
if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */
|
|
||||||
size += nla_total_size(sizeof(struct can_berr_counter));
|
|
||||||
if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */
|
|
||||||
size += nla_total_size(sizeof(struct can_bittiming_const));
|
size += nla_total_size(sizeof(struct can_bittiming_const));
|
||||||
|
size += nla_total_size(sizeof(struct can_clock)); /* IFLA_CAN_CLOCK */
|
||||||
|
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_STATE */
|
||||||
|
size += nla_total_size(sizeof(struct can_ctrlmode)); /* IFLA_CAN_CTRLMODE */
|
||||||
|
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */
|
||||||
|
if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */
|
||||||
|
size += nla_total_size(sizeof(struct can_berr_counter));
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
@ -726,23 +726,20 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
|
||||||
|
|
||||||
if (priv->do_get_state)
|
if (priv->do_get_state)
|
||||||
priv->do_get_state(dev, &state);
|
priv->do_get_state(dev, &state);
|
||||||
if (nla_put_u32(skb, IFLA_CAN_STATE, state) ||
|
if (nla_put(skb, IFLA_CAN_BITTIMING,
|
||||||
nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) ||
|
|
||||||
nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) ||
|
|
||||||
nla_put(skb, IFLA_CAN_BITTIMING,
|
|
||||||
sizeof(priv->bittiming), &priv->bittiming) ||
|
sizeof(priv->bittiming), &priv->bittiming) ||
|
||||||
nla_put(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock) ||
|
|
||||||
(priv->do_get_berr_counter &&
|
|
||||||
!priv->do_get_berr_counter(dev, &bec) &&
|
|
||||||
nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)) ||
|
|
||||||
(priv->bittiming_const &&
|
(priv->bittiming_const &&
|
||||||
nla_put(skb, IFLA_CAN_BITTIMING_CONST,
|
nla_put(skb, IFLA_CAN_BITTIMING_CONST,
|
||||||
sizeof(*priv->bittiming_const), priv->bittiming_const)))
|
sizeof(*priv->bittiming_const), priv->bittiming_const)) ||
|
||||||
goto nla_put_failure;
|
nla_put(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock) ||
|
||||||
|
nla_put_u32(skb, IFLA_CAN_STATE, state) ||
|
||||||
|
nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) ||
|
||||||
|
nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) ||
|
||||||
|
(priv->do_get_berr_counter &&
|
||||||
|
!priv->do_get_berr_counter(dev, &bec) &&
|
||||||
|
nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)))
|
||||||
|
return -EMSGSIZE;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
nla_put_failure:
|
|
||||||
return -EMSGSIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t can_get_xstats_size(const struct net_device *dev)
|
static size_t can_get_xstats_size(const struct net_device *dev)
|
||||||
|
|
|
@ -286,15 +286,6 @@ static inline u32 hecc_get_bit(struct ti_hecc_priv *priv, int reg, u32 bit_mask)
|
||||||
return (hecc_read(priv, reg) & bit_mask) ? 1 : 0;
|
return (hecc_read(priv, reg) & bit_mask) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ti_hecc_get_state(const struct net_device *ndev,
|
|
||||||
enum can_state *state)
|
|
||||||
{
|
|
||||||
struct ti_hecc_priv *priv = netdev_priv(ndev);
|
|
||||||
|
|
||||||
*state = priv->can.state;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ti_hecc_set_btc(struct ti_hecc_priv *priv)
|
static int ti_hecc_set_btc(struct ti_hecc_priv *priv)
|
||||||
{
|
{
|
||||||
struct can_bittiming *bit_timing = &priv->can.bittiming;
|
struct can_bittiming *bit_timing = &priv->can.bittiming;
|
||||||
|
@ -940,7 +931,6 @@ static int ti_hecc_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
priv->can.bittiming_const = &ti_hecc_bittiming_const;
|
priv->can.bittiming_const = &ti_hecc_bittiming_const;
|
||||||
priv->can.do_set_mode = ti_hecc_do_set_mode;
|
priv->can.do_set_mode = ti_hecc_do_set_mode;
|
||||||
priv->can.do_get_state = ti_hecc_get_state;
|
|
||||||
priv->can.do_get_berr_counter = ti_hecc_get_berr_counter;
|
priv->can.do_get_berr_counter = ti_hecc_get_berr_counter;
|
||||||
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
|
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче