Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 13521a57 authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 9f9843a7 26896fd9
Loading
Loading
Loading
Loading
+217 −0
Original line number Diff line number Diff line
@@ -25,6 +25,12 @@ This file contains
      4.1.5 RAW socket option CAN_RAW_FD_FRAMES
      4.1.6 RAW socket returned message flags
    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.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.

  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.4 unconnected transport protocols (SOCK_DGRAM)

+32 −35
Original line number Diff line number Diff line
@@ -645,19 +645,6 @@ static int can_changelink(struct net_device *dev,
	/* We need synchronization with dev->stop() */
	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]) {
		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]) {
		/* Do not allow changing restart delay while running */
		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)
{
	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_ctrlmode));  /* IFLA_CAN_CTRLMODE */
	size += nla_total_size(sizeof(u32));  /* IFLA_CAN_RESTART_MS */
	size += nla_total_size(sizeof(struct can_bittiming));	/* IFLA_CAN_BITTIMING */
	if (priv->bittiming_const)				/* IFLA_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));
	if (priv->bittiming_const)	      /* IFLA_CAN_BITTIMING_CONST */
		size += nla_total_size(sizeof(struct can_bittiming_const));

	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)
		priv->do_get_state(dev, &state);
	if (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) ||
	    nla_put(skb, IFLA_CAN_BITTIMING,
	if (nla_put(skb, IFLA_CAN_BITTIMING,
		    sizeof(priv->bittiming), &priv->bittiming) ||
	    (priv->bittiming_const &&
	     nla_put(skb, IFLA_CAN_BITTIMING_CONST,
		     sizeof(*priv->bittiming_const), priv->bittiming_const)) ||
	    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)) ||
	    (priv->bittiming_const &&
	     nla_put(skb, IFLA_CAN_BITTIMING_CONST,
		     sizeof(*priv->bittiming_const), priv->bittiming_const)))
		goto nla_put_failure;
	return 0;

nla_put_failure:
	     nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)))
		return -EMSGSIZE;
	return 0;
}

static size_t can_get_xstats_size(const struct net_device *dev)
+0 −10
Original line number Diff line number Diff line
@@ -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;
}

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)
{
	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.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.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;