Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
8f961fae
Commit
8f961fae
authored
Jul 07, 2012
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-davem' of
git://gitorious.org/linux-can/linux-can-next
parents
95162d65
f057bbb6
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
320 additions
and
23 deletions
+320
-23
Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
+3
-0
drivers/net/can/cc770/cc770.c
drivers/net/can/cc770/cc770.c
+1
-1
drivers/net/can/dev.c
drivers/net/can/dev.c
+1
-1
drivers/net/can/flexcan.c
drivers/net/can/flexcan.c
+55
-16
include/linux/can.h
include/linux/can.h
+3
-0
include/linux/pkt_cls.h
include/linux/pkt_cls.h
+3
-2
net/can/af_can.h
net/can/af_can.h
+3
-0
net/can/proc.c
net/can/proc.c
+0
-3
net/sched/Kconfig
net/sched/Kconfig
+10
-0
net/sched/Makefile
net/sched/Makefile
+1
-0
net/sched/em_canid.c
net/sched/em_canid.c
+240
-0
No files found.
Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
View file @
8f961fae
...
...
@@ -11,6 +11,9 @@ Required properties:
- reg : Offset and length of the register set for this device
- interrupts : Interrupt tuple for this device
Optional properties:
- clock-frequency : The oscillator frequency driving the flexcan device
Example:
...
...
drivers/net/can/cc770/cc770.c
View file @
8f961fae
...
...
@@ -695,7 +695,7 @@ static void cc770_tx_interrupt(struct net_device *dev, unsigned int o)
netif_wake_queue
(
dev
);
}
irqreturn_t
cc770_interrupt
(
int
irq
,
void
*
dev_id
)
static
irqreturn_t
cc770_interrupt
(
int
irq
,
void
*
dev_id
)
{
struct
net_device
*
dev
=
(
struct
net_device
*
)
dev_id
;
struct
cc770_priv
*
priv
=
netdev_priv
(
dev
);
...
...
drivers/net/can/dev.c
View file @
8f961fae
...
...
@@ -401,7 +401,7 @@ EXPORT_SYMBOL_GPL(can_free_echo_skb);
/*
* CAN device restart for bus-off recovery
*/
void
can_restart
(
unsigned
long
data
)
static
void
can_restart
(
unsigned
long
data
)
{
struct
net_device
*
dev
=
(
struct
net_device
*
)
data
;
struct
can_priv
*
priv
=
netdev_priv
(
dev
);
...
...
drivers/net/can/flexcan.c
View file @
8f961fae
...
...
@@ -34,6 +34,7 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/consumer.h>
...
...
@@ -165,10 +166,21 @@ struct flexcan_regs {
u32
imask1
;
/* 0x28 */
u32
iflag2
;
/* 0x2c */
u32
iflag1
;
/* 0x30 */
u32
_reserved2
[
19
];
u32
crl2
;
/* 0x34 */
u32
esr2
;
/* 0x38 */
u32
imeur
;
/* 0x3c */
u32
lrfr
;
/* 0x40 */
u32
crcr
;
/* 0x44 */
u32
rxfgmask
;
/* 0x48 */
u32
rxfir
;
/* 0x4c */
u32
_reserved3
[
12
];
struct
flexcan_mb
cantxfg
[
64
];
};
struct
flexcan_devtype_data
{
u32
hw_ver
;
/* hardware controller version */
};
struct
flexcan_priv
{
struct
can_priv
can
;
struct
net_device
*
dev
;
...
...
@@ -180,6 +192,15 @@ struct flexcan_priv {
struct
clk
*
clk
;
struct
flexcan_platform_data
*
pdata
;
struct
flexcan_devtype_data
*
devtype_data
;
};
static
struct
flexcan_devtype_data
fsl_p1010_devtype_data
=
{
.
hw_ver
=
3
,
};
static
struct
flexcan_devtype_data
fsl_imx6q_devtype_data
=
{
.
hw_ver
=
10
,
};
static
struct
can_bittiming_const
flexcan_bittiming_const
=
{
...
...
@@ -750,6 +771,9 @@ static int flexcan_chip_start(struct net_device *dev)
flexcan_write
(
0x0
,
&
regs
->
rx14mask
);
flexcan_write
(
0x0
,
&
regs
->
rx15mask
);
if
(
priv
->
devtype_data
->
hw_ver
>=
10
)
flexcan_write
(
0x0
,
&
regs
->
rxfgmask
);
flexcan_transceiver_switch
(
priv
,
1
);
/* synchronize with the can bus */
...
...
@@ -922,8 +946,21 @@ static void __devexit unregister_flexcandev(struct net_device *dev)
unregister_candev
(
dev
);
}
static
const
struct
of_device_id
flexcan_of_match
[]
=
{
{
.
compatible
=
"fsl,p1010-flexcan"
,
.
data
=
&
fsl_p1010_devtype_data
,
},
{
.
compatible
=
"fsl,imx6q-flexcan"
,
.
data
=
&
fsl_imx6q_devtype_data
,
},
{
/* sentinel */
},
};
static
const
struct
platform_device_id
flexcan_id_table
[]
=
{
{
.
name
=
"flexcan"
,
.
driver_data
=
(
kernel_ulong_t
)
&
fsl_p1010_devtype_data
,
},
{
/* sentinel */
},
};
static
int
__devinit
flexcan_probe
(
struct
platform_device
*
pdev
)
{
const
struct
of_device_id
*
of_id
;
struct
flexcan_devtype_data
*
devtype_data
;
struct
net_device
*
dev
;
struct
flexcan_priv
*
priv
;
struct
resource
*
mem
;
...
...
@@ -938,14 +975,9 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
if
(
IS_ERR
(
pinctrl
))
return
PTR_ERR
(
pinctrl
);
if
(
pdev
->
dev
.
of_node
)
{
const
__be32
*
clock_freq_p
;
clock_freq_p
=
of_get_property
(
pdev
->
dev
.
of_node
,
"clock-frequency"
,
NULL
);
if
(
clock_freq_p
)
clock_freq
=
be32_to_cpup
(
clock_freq_p
);
}
if
(
pdev
->
dev
.
of_node
)
of_property_read_u32
(
pdev
->
dev
.
of_node
,
"clock-frequency"
,
&
clock_freq
);
if
(
!
clock_freq
)
{
clk
=
clk_get
(
&
pdev
->
dev
,
NULL
);
...
...
@@ -982,6 +1014,17 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
goto
failed_alloc
;
}
of_id
=
of_match_device
(
flexcan_of_match
,
&
pdev
->
dev
);
if
(
of_id
)
{
devtype_data
=
of_id
->
data
;
}
else
if
(
pdev
->
id_entry
->
driver_data
)
{
devtype_data
=
(
struct
flexcan_devtype_data
*
)
pdev
->
id_entry
->
driver_data
;
}
else
{
err
=
-
ENODEV
;
goto
failed_devtype
;
}
dev
->
netdev_ops
=
&
flexcan_netdev_ops
;
dev
->
irq
=
irq
;
dev
->
flags
|=
IFF_ECHO
;
...
...
@@ -998,6 +1041,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
priv
->
dev
=
dev
;
priv
->
clk
=
clk
;
priv
->
pdata
=
pdev
->
dev
.
platform_data
;
priv
->
devtype_data
=
devtype_data
;
netif_napi_add
(
dev
,
&
priv
->
napi
,
flexcan_poll
,
FLEXCAN_NAPI_WEIGHT
);
...
...
@@ -1016,6 +1060,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
return
0
;
failed_register:
failed_devtype:
free_candev
(
dev
);
failed_alloc:
iounmap
(
base
);
...
...
@@ -1049,13 +1094,6 @@ static int __devexit flexcan_remove(struct platform_device *pdev)
return
0
;
}
static
struct
of_device_id
flexcan_of_match
[]
=
{
{
.
compatible
=
"fsl,p1010-flexcan"
,
},
{},
};
#ifdef CONFIG_PM
static
int
flexcan_suspend
(
struct
platform_device
*
pdev
,
pm_message_t
state
)
{
...
...
@@ -1102,6 +1140,7 @@ static struct platform_driver flexcan_driver = {
.
remove
=
__devexit_p
(
flexcan_remove
),
.
suspend
=
flexcan_suspend
,
.
resume
=
flexcan_resume
,
.
id_table
=
flexcan_id_table
,
};
module_platform_driver
(
flexcan_driver
);
...
...
include/linux/can.h
View file @
8f961fae
...
...
@@ -38,6 +38,9 @@
*/
typedef
__u32
canid_t
;
#define CAN_SFF_ID_BITS 11
#define CAN_EFF_ID_BITS 29
/*
* Controller Area Network Error Message Frame Mask structure
*
...
...
include/linux/pkt_cls.h
View file @
8f961fae
...
...
@@ -452,7 +452,8 @@ enum {
#define TCF_EM_META 4
#define TCF_EM_TEXT 5
#define TCF_EM_VLAN 6
#define TCF_EM_MAX 6
#define TCF_EM_CANID 7
#define TCF_EM_MAX 7
enum
{
TCF_EM_PROG_TC
...
...
net/can/af_can.h
View file @
8f961fae
...
...
@@ -104,6 +104,9 @@ struct s_pstats {
unsigned
long
rcv_entries_max
;
};
/* receive filters subscribed for 'all' CAN devices */
extern
struct
dev_rcv_lists
can_rx_alldev_list
;
/* function prototypes for the CAN networklayer procfs (proc.c) */
extern
void
can_init_proc
(
void
);
extern
void
can_remove_proc
(
void
);
...
...
net/can/proc.c
View file @
8f961fae
...
...
@@ -83,9 +83,6 @@ static const char rx_list_name[][8] = {
[
RX_EFF
]
=
"rx_eff"
,
};
/* receive filters subscribed for 'all' CAN devices */
extern
struct
dev_rcv_lists
can_rx_alldev_list
;
/*
* af_can statistics stuff
*/
...
...
net/sched/Kconfig
View file @
8f961fae
...
...
@@ -507,6 +507,16 @@ config NET_EMATCH_TEXT
To compile this code as a module, choose M here: the
module will be called em_text.
config NET_EMATCH_CANID
tristate "CAN Identifier"
depends on NET_EMATCH && CAN
---help---
Say Y here if you want to be able to classify CAN frames based
on CAN Identifier.
To compile this code as a module, choose M here: the
module will be called em_canid.
config NET_CLS_ACT
bool "Actions"
---help---
...
...
net/sched/Makefile
View file @
8f961fae
...
...
@@ -55,3 +55,4 @@ obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o
obj-$(CONFIG_NET_EMATCH_U32)
+=
em_u32.o
obj-$(CONFIG_NET_EMATCH_META)
+=
em_meta.o
obj-$(CONFIG_NET_EMATCH_TEXT)
+=
em_text.o
obj-$(CONFIG_NET_EMATCH_CANID)
+=
em_canid.o
net/sched/em_canid.c
0 → 100644
View file @
8f961fae
/*
* em_canid.c Ematch rule to match CAN frames according to their CAN IDs
*
* This program is free software; you can distribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Idea: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
* Copyright: (c) 2011 Czech Technical University in Prague
* (c) 2011 Volkswagen Group Research
* Authors: Michal Sojka <sojkam1@fel.cvut.cz>
* Pavel Pisa <pisa@cmp.felk.cvut.cz>
* Rostislav Lisovy <lisovy@gmail.cz>
* Funded by: Volkswagen Group Research
*/
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/skbuff.h>
#include <net/pkt_cls.h>
#include <linux/can.h>
#define EM_CAN_RULES_MAX 500
struct
canid_match
{
/* For each SFF CAN ID (11 bit) there is one record in this bitfield */
DECLARE_BITMAP
(
match_sff
,
(
1
<<
CAN_SFF_ID_BITS
));
int
rules_count
;
int
sff_rules_count
;
int
eff_rules_count
;
/*
* Raw rules copied from netlink message; Used for sending
* information to userspace (when 'tc filter show' is invoked)
* AND when matching EFF frames
*/
struct
can_filter
rules_raw
[];
};
/**
* em_canid_get_id() - Extracts Can ID out of the sk_buff structure.
*/
static
canid_t
em_canid_get_id
(
struct
sk_buff
*
skb
)
{
/* CAN ID is stored within the data field */
struct
can_frame
*
cf
=
(
struct
can_frame
*
)
skb
->
data
;
return
cf
->
can_id
;
}
static
void
em_canid_sff_match_add
(
struct
canid_match
*
cm
,
u32
can_id
,
u32
can_mask
)
{
int
i
;
/*
* Limit can_mask and can_id to SFF range to
* protect against write after end of array
*/
can_mask
&=
CAN_SFF_MASK
;
can_id
&=
can_mask
;
/* Single frame */
if
(
can_mask
==
CAN_SFF_MASK
)
{
set_bit
(
can_id
,
cm
->
match_sff
);
return
;
}
/* All frames */
if
(
can_mask
==
0
)
{
bitmap_fill
(
cm
->
match_sff
,
(
1
<<
CAN_SFF_ID_BITS
));
return
;
}
/*
* Individual frame filter.
* Add record (set bit to 1) for each ID that
* conforms particular rule
*/
for
(
i
=
0
;
i
<
(
1
<<
CAN_SFF_ID_BITS
);
i
++
)
{
if
((
i
&
can_mask
)
==
can_id
)
set_bit
(
i
,
cm
->
match_sff
);
}
}
static
inline
struct
canid_match
*
em_canid_priv
(
struct
tcf_ematch
*
m
)
{
return
(
struct
canid_match
*
)
m
->
data
;
}
static
int
em_canid_match
(
struct
sk_buff
*
skb
,
struct
tcf_ematch
*
m
,
struct
tcf_pkt_info
*
info
)
{
struct
canid_match
*
cm
=
em_canid_priv
(
m
);
canid_t
can_id
;
int
match
=
0
;
int
i
;
const
struct
can_filter
*
lp
;
can_id
=
em_canid_get_id
(
skb
);
if
(
can_id
&
CAN_EFF_FLAG
)
{
for
(
i
=
0
,
lp
=
cm
->
rules_raw
;
i
<
cm
->
eff_rules_count
;
i
++
,
lp
++
)
{
if
(
!
(((
lp
->
can_id
^
can_id
)
&
lp
->
can_mask
)))
{
match
=
1
;
break
;
}
}
}
else
{
/* SFF */
can_id
&=
CAN_SFF_MASK
;
match
=
(
test_bit
(
can_id
,
cm
->
match_sff
)
?
1
:
0
);
}
return
match
;
}
static
int
em_canid_change
(
struct
tcf_proto
*
tp
,
void
*
data
,
int
len
,
struct
tcf_ematch
*
m
)
{
struct
can_filter
*
conf
=
data
;
/* Array with rules */
struct
canid_match
*
cm
;
struct
canid_match
*
cm_old
=
(
struct
canid_match
*
)
m
->
data
;
int
i
;
if
(
!
len
)
return
-
EINVAL
;
if
(
len
%
sizeof
(
struct
can_filter
))
return
-
EINVAL
;
if
(
len
>
sizeof
(
struct
can_filter
)
*
EM_CAN_RULES_MAX
)
return
-
EINVAL
;
cm
=
kzalloc
(
sizeof
(
struct
canid_match
)
+
len
,
GFP_KERNEL
);
if
(
!
cm
)
return
-
ENOMEM
;
cm
->
rules_count
=
len
/
sizeof
(
struct
can_filter
);
/*
* We need two for() loops for copying rules into two contiguous
* areas in rules_raw to process all eff rules with a simple loop.
* NB: The configuration interface supports sff and eff rules.
* We do not support filters here that match for the same can_id
* provided in a SFF and EFF frame (e.g. 0x123 / 0x80000123).
* For this (unusual case) two filters have to be specified. The
* SFF/EFF separation is done with the CAN_EFF_FLAG in the can_id.
*/
/* Fill rules_raw with EFF rules first */
for
(
i
=
0
;
i
<
cm
->
rules_count
;
i
++
)
{
if
(
conf
[
i
].
can_id
&
CAN_EFF_FLAG
)
{
memcpy
(
cm
->
rules_raw
+
cm
->
eff_rules_count
,
&
conf
[
i
],
sizeof
(
struct
can_filter
));
cm
->
eff_rules_count
++
;
}
}
/* append SFF frame rules */
for
(
i
=
0
;
i
<
cm
->
rules_count
;
i
++
)
{
if
(
!
(
conf
[
i
].
can_id
&
CAN_EFF_FLAG
))
{
memcpy
(
cm
->
rules_raw
+
cm
->
eff_rules_count
+
cm
->
sff_rules_count
,
&
conf
[
i
],
sizeof
(
struct
can_filter
));
cm
->
sff_rules_count
++
;
em_canid_sff_match_add
(
cm
,
conf
[
i
].
can_id
,
conf
[
i
].
can_mask
);
}
}
m
->
datalen
=
sizeof
(
struct
canid_match
)
+
len
;
m
->
data
=
(
unsigned
long
)
cm
;
if
(
cm_old
!=
NULL
)
{
pr_err
(
"canid: Configuring an existing ematch!
\n
"
);
kfree
(
cm_old
);
}
return
0
;
}
static
void
em_canid_destroy
(
struct
tcf_proto
*
tp
,
struct
tcf_ematch
*
m
)
{
struct
canid_match
*
cm
=
em_canid_priv
(
m
);
kfree
(
cm
);
}
static
int
em_canid_dump
(
struct
sk_buff
*
skb
,
struct
tcf_ematch
*
m
)
{
struct
canid_match
*
cm
=
em_canid_priv
(
m
);
/*
* When configuring this ematch 'rules_count' is set not to exceed
* 'rules_raw' array size
*/
if
(
nla_put_nohdr
(
skb
,
sizeof
(
struct
can_filter
)
*
cm
->
rules_count
,
&
cm
->
rules_raw
)
<
0
)
return
-
EMSGSIZE
;
return
0
;
}
static
struct
tcf_ematch_ops
em_canid_ops
=
{
.
kind
=
TCF_EM_CANID
,
.
change
=
em_canid_change
,
.
match
=
em_canid_match
,
.
destroy
=
em_canid_destroy
,
.
dump
=
em_canid_dump
,
.
owner
=
THIS_MODULE
,
.
link
=
LIST_HEAD_INIT
(
em_canid_ops
.
link
)
};
static
int
__init
init_em_canid
(
void
)
{
return
tcf_em_register
(
&
em_canid_ops
);
}
static
void
__exit
exit_em_canid
(
void
)
{
tcf_em_unregister
(
&
em_canid_ops
);
}
MODULE_LICENSE
(
"GPL"
);
module_init
(
init_em_canid
);
module_exit
(
exit_em_canid
);
MODULE_ALIAS_TCF_EMATCH
(
TCF_EM_CANID
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment