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

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

Merge tag 'linux-can-next-for-4.2-20150609' of...

Merge tag 'linux-can-next-for-4.2-20150609' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next



Marc Kleine-Budde says:

====================
pull-request: can-next 2015-05-06

this is a pull request of a two patches for net-next.

The first patch is by Tomas Krcka, he fixes the (currently unused)
register address for acceptance filters. Oliver Hartkopp contributes a
patch for the cangw, where an optional UID is added to reference
routing jobs.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c3eee1fb dd895d7f
Loading
Loading
Loading
Loading
+5 −4
Original line number Original line Diff line number Diff line
@@ -190,10 +190,11 @@
#define RXBEID0_OFF 4
#define RXBEID0_OFF 4
#define RXBDLC_OFF  5
#define RXBDLC_OFF  5
#define RXBDAT_OFF  6
#define RXBDAT_OFF  6
#define RXFSIDH(n) ((n) * 4)
#define RXFSID(n) ((n < 3) ? 0 : 4)
#define RXFSIDL(n) ((n) * 4 + 1)
#define RXFSIDH(n) ((n) * 4 + RXFSID(n))
#define RXFEID8(n) ((n) * 4 + 2)
#define RXFSIDL(n) ((n) * 4 + 1 + RXFSID(n))
#define RXFEID0(n) ((n) * 4 + 3)
#define RXFEID8(n) ((n) * 4 + 2 + RXFSID(n))
#define RXFEID0(n) ((n) * 4 + 3 + RXFSID(n))
#define RXMSIDH(n) ((n) * 4 + 0x20)
#define RXMSIDH(n) ((n) * 4 + 0x20)
#define RXMSIDL(n) ((n) * 4 + 0x21)
#define RXMSIDL(n) ((n) * 4 + 0x21)
#define RXMEID8(n) ((n) * 4 + 0x22)
#define RXMEID8(n) ((n) * 4 + 0x22)
+5 −0
Original line number Original line Diff line number Diff line
@@ -78,6 +78,7 @@ enum {
	CGW_FILTER,	/* specify struct can_filter on source CAN device */
	CGW_FILTER,	/* specify struct can_filter on source CAN device */
	CGW_DELETED,	/* number of deleted CAN frames (see max_hops param) */
	CGW_DELETED,	/* number of deleted CAN frames (see max_hops param) */
	CGW_LIM_HOPS,	/* limit the number of hops of this specific rule */
	CGW_LIM_HOPS,	/* limit the number of hops of this specific rule */
	CGW_MOD_UID,	/* user defined identifier for modification updates */
	__CGW_MAX
	__CGW_MAX
};
};


@@ -162,6 +163,10 @@ enum {
 * load time of the can-gw module). This value is used to reduce the number of
 * load time of the can-gw module). This value is used to reduce the number of
 * possible hops for this gateway rule to a value smaller then max_hops.
 * possible hops for this gateway rule to a value smaller then max_hops.
 *
 *
 * CGW_MOD_UID (length 4 bytes):
 * Optional non-zero user defined routing job identifier to alter existing
 * modification settings at runtime.
 *
 * CGW_CS_XOR (length 4 bytes):
 * CGW_CS_XOR (length 4 bytes):
 * Set a simple XOR checksum starting with an initial value into
 * Set a simple XOR checksum starting with an initial value into
 * data[result-idx] using data[start-idx] .. data[end-idx]
 * data[result-idx] using data[start-idx] .. data[end-idx]
+56 −12
Original line number Original line Diff line number Diff line
@@ -110,6 +110,7 @@ struct cf_mod {
		void (*xor)(struct can_frame *cf, struct cgw_csum_xor *xor);
		void (*xor)(struct can_frame *cf, struct cgw_csum_xor *xor);
		void (*crc8)(struct can_frame *cf, struct cgw_csum_crc8 *crc8);
		void (*crc8)(struct can_frame *cf, struct cgw_csum_crc8 *crc8);
	} csumfunc;
	} csumfunc;
	u32 uid;
};
};




@@ -548,6 +549,11 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type,
			goto cancel;
			goto cancel;
	}
	}


	if (gwj->mod.uid) {
		if (nla_put_u32(skb, CGW_MOD_UID, gwj->mod.uid) < 0)
			goto cancel;
	}

	if (gwj->mod.csumfunc.crc8) {
	if (gwj->mod.csumfunc.crc8) {
		if (nla_put(skb, CGW_CS_CRC8, CGW_CS_CRC8_LEN,
		if (nla_put(skb, CGW_CS_CRC8, CGW_CS_CRC8_LEN,
			    &gwj->mod.csum.crc8) < 0)
			    &gwj->mod.csum.crc8) < 0)
@@ -619,6 +625,7 @@ static const struct nla_policy cgw_policy[CGW_MAX+1] = {
	[CGW_DST_IF]	= { .type = NLA_U32 },
	[CGW_DST_IF]	= { .type = NLA_U32 },
	[CGW_FILTER]	= { .len = sizeof(struct can_filter) },
	[CGW_FILTER]	= { .len = sizeof(struct can_filter) },
	[CGW_LIM_HOPS]	= { .type = NLA_U8 },
	[CGW_LIM_HOPS]	= { .type = NLA_U8 },
	[CGW_MOD_UID]	= { .type = NLA_U32 },
};
};


/* check for common and gwtype specific attributes */
/* check for common and gwtype specific attributes */
@@ -761,6 +768,10 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod,
			else
			else
				mod->csumfunc.xor = cgw_csum_xor_neg;
				mod->csumfunc.xor = cgw_csum_xor_neg;
		}
		}

		if (tb[CGW_MOD_UID]) {
			nla_memcpy(&mod->uid, tb[CGW_MOD_UID], sizeof(u32));
		}
	}
	}


	if (gwtype == CGW_TYPE_CAN_CAN) {
	if (gwtype == CGW_TYPE_CAN_CAN) {
@@ -802,6 +813,8 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh)
{
{
	struct rtcanmsg *r;
	struct rtcanmsg *r;
	struct cgw_job *gwj;
	struct cgw_job *gwj;
	struct cf_mod mod;
	struct can_can_gw ccgw;
	u8 limhops = 0;
	u8 limhops = 0;
	int err = 0;
	int err = 0;


@@ -819,6 +832,36 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh)
	if (r->gwtype != CGW_TYPE_CAN_CAN)
	if (r->gwtype != CGW_TYPE_CAN_CAN)
		return -EINVAL;
		return -EINVAL;


	err = cgw_parse_attr(nlh, &mod, CGW_TYPE_CAN_CAN, &ccgw, &limhops);
	if (err < 0)
		return err;

	if (mod.uid) {

		ASSERT_RTNL();

		/* check for updating an existing job with identical uid */
		hlist_for_each_entry(gwj, &cgw_list, list) {

			if (gwj->mod.uid != mod.uid)
				continue;

			/* interfaces & filters must be identical */
			if (memcmp(&gwj->ccgw, &ccgw, sizeof(ccgw)))
				return -EINVAL;

			/* update modifications with disabled softirq & quit */
			local_bh_disable();
			memcpy(&gwj->mod, &mod, sizeof(mod));
			local_bh_enable();
			return 0;
		}
	}

	/* ifindex == 0 is not allowed for job creation */
	if (!ccgw.src_idx || !ccgw.dst_idx)
		return -ENODEV;

	gwj = kmem_cache_alloc(cgw_cache, GFP_KERNEL);
	gwj = kmem_cache_alloc(cgw_cache, GFP_KERNEL);
	if (!gwj)
	if (!gwj)
		return -ENOMEM;
		return -ENOMEM;
@@ -828,18 +871,14 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh)
	gwj->deleted_frames = 0;
	gwj->deleted_frames = 0;
	gwj->flags = r->flags;
	gwj->flags = r->flags;
	gwj->gwtype = r->gwtype;
	gwj->gwtype = r->gwtype;
	gwj->limit_hops = limhops;


	err = cgw_parse_attr(nlh, &gwj->mod, CGW_TYPE_CAN_CAN, &gwj->ccgw,
	/* insert already parsed information */
			     &limhops);
	memcpy(&gwj->mod, &mod, sizeof(mod));
	if (err < 0)
	memcpy(&gwj->ccgw, &ccgw, sizeof(ccgw));
		goto out;


	err = -ENODEV;
	err = -ENODEV;


	/* ifindex == 0 is not allowed for job creation */
	if (!gwj->ccgw.src_idx || !gwj->ccgw.dst_idx)
		goto out;

	gwj->src.dev = __dev_get_by_index(&init_net, gwj->ccgw.src_idx);
	gwj->src.dev = __dev_get_by_index(&init_net, gwj->ccgw.src_idx);


	if (!gwj->src.dev)
	if (!gwj->src.dev)
@@ -856,8 +895,6 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh)
	if (gwj->dst.dev->type != ARPHRD_CAN)
	if (gwj->dst.dev->type != ARPHRD_CAN)
		goto out;
		goto out;


	gwj->limit_hops = limhops;

	ASSERT_RTNL();
	ASSERT_RTNL();


	err = cgw_register_filter(gwj);
	err = cgw_register_filter(gwj);
@@ -931,8 +968,15 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh)
		if (gwj->limit_hops != limhops)
		if (gwj->limit_hops != limhops)
			continue;
			continue;


		/* we have a match when uid is enabled and identical */
		if (gwj->mod.uid || mod.uid) {
			if (gwj->mod.uid != mod.uid)
				continue;
		} else {
			/* no uid => check for identical modifications */
			if (memcmp(&gwj->mod, &mod, sizeof(mod)))
			if (memcmp(&gwj->mod, &mod, sizeof(mod)))
				continue;
				continue;
		}


		/* if (r->gwtype == CGW_TYPE_CAN_CAN) - is made sure here */
		/* if (r->gwtype == CGW_TYPE_CAN_CAN) - is made sure here */
		if (memcmp(&gwj->ccgw, &ccgw, sizeof(ccgw)))
		if (memcmp(&gwj->ccgw, &ccgw, sizeof(ccgw)))