mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-23 07:23:12 +02:00
linux-can-next-for-6.16-20250522
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEn/sM2K9nqF/8FWzzDHRl3/mQkZwFAmgu4Z8THG1rbEBwZW5n dXRyb25peC5kZQAKCRAMdGXf+ZCRnBV7B/9i36vJXJuRMvLhP6vQNeEtixa5YkWe AZ/ALtAlYVzQXIKYJs7st+bxzQLmN7BfvcGdtXmtgIsNttNL1Kl1asvKFuRN3hqp CNjH83vqmoJMbKjcnPmxi/t3IfprfTU99g34gz5ayJN15rYptQAZRIFoX63Di6jC XvJbhM2ztJqHA5o5kMseCJ8kRq+RCAunI5Z1hltaAUWmypdc1RPWAJQed4x1ssSM 8ctyWGy32ctyIoZ+B8tXzE3FoTay5UditN0lfdOe9pE+j6ZeYZRKdquKh4gLvK9c mFjxQm/TqbWWIWuts30iy2dp2PgNEyFrcJUZWu8/y5rhZSQQeqzQww8v =ILU2 -----END PGP SIGNATURE----- Merge tag 'linux-can-next-for-6.16-20250522' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next Marc Kleine-Budde says: ==================== pull-request: can-next 2025-05-22 this is a pull request of 22 patches for net-next/main. The series by Biju Das contains 19 patches and adds RZ/G3E CANFD support to the rcar_canfd driver. The patch by Vincent Mailhol adds a struct data_bittiming_params to group FD parameters as a preparation patch for CAN-XL support. Felix Maurer's patch imports tst-filter from can-tests into the kernel self tests and Vincent Mailhol adds support for physical CAN interfaces. linux-can-next-for-6.16-20250522 * tag 'linux-can-next-for-6.16-20250522' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next: (22 commits) selftests: can: test_raw_filter.sh: add support of physical interfaces selftests: can: Import tst-filter from can-tests can: dev: add struct data_bittiming_params to group FD parameters can: rcar_canfd: Add RZ/G3E support can: rcar_canfd: Enhance multi_channel_irqs handling can: rcar_canfd: Add external_clk variable to struct rcar_canfd_hw_info can: rcar_canfd: Add sh variable to struct rcar_canfd_hw_info can: rcar_canfd: Add struct rcanfd_regs variable to struct rcar_canfd_hw_info can: rcar_canfd: Add shared_can_regs variable to struct rcar_canfd_hw_info can: rcar_canfd: Add ch_interface_mode variable to struct rcar_canfd_hw_info can: rcar_canfd: Add {nom,data}_bittiming variables to struct rcar_canfd_hw_info can: rcar_canfd: Add max_cftml variable to struct rcar_canfd_hw_info can: rcar_canfd: Add max_aflpn variable to struct rcar_canfd_hw_info can: rcar_canfd: Add rnc_field_width variable to struct rcar_canfd_hw_info can: rcar_canfd: Update RCANFD_GAFLCFG macro can: rcar_canfd: Add rcar_canfd_setrnc() can: rcar_canfd: Drop the mask operation in RCANFD_GAFLCFG_SETRNC macro can: rcar_canfd: Update RCANFD_GERFL_ERR macro can: rcar_canfd: Drop RCANFD_GAFLCFG_GETRNC macro can: rcar_canfd: Use of_get_available_child_by_name() ... ==================== Link: https://patch.msgid.link/20250522084128.501049-1-mkl@pengutronix.de Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
34d26315db
|
@ -42,19 +42,80 @@ properties:
|
|||
- renesas,r9a07g054-canfd # RZ/V2L
|
||||
- const: renesas,rzg2l-canfd # RZ/G2L family
|
||||
|
||||
- const: renesas,r9a09g047-canfd # RZ/G3E
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts: true
|
||||
interrupts:
|
||||
oneOf:
|
||||
- items:
|
||||
- description: Channel interrupt
|
||||
- description: Global interrupt
|
||||
- items:
|
||||
- description: CAN global error interrupt
|
||||
- description: CAN receive FIFO interrupt
|
||||
- description: CAN0 error interrupt
|
||||
- description: CAN0 transmit interrupt
|
||||
- description: CAN0 transmit/receive FIFO receive completion interrupt
|
||||
- description: CAN1 error interrupt
|
||||
- description: CAN1 transmit interrupt
|
||||
- description: CAN1 transmit/receive FIFO receive completion interrupt
|
||||
- description: CAN2 error interrupt
|
||||
- description: CAN2 transmit interrupt
|
||||
- description: CAN2 transmit/receive FIFO receive completion interrupt
|
||||
- description: CAN3 error interrupt
|
||||
- description: CAN3 transmit interrupt
|
||||
- description: CAN3 transmit/receive FIFO receive completion interrupt
|
||||
- description: CAN4 error interrupt
|
||||
- description: CAN4 transmit interrupt
|
||||
- description: CAN4 transmit/receive FIFO receive completion interrupt
|
||||
- description: CAN5 error interrupt
|
||||
- description: CAN5 transmit interrupt
|
||||
- description: CAN5 transmit/receive FIFO receive completion interrupt
|
||||
minItems: 8
|
||||
|
||||
interrupt-names:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: ch_int
|
||||
- const: g_int
|
||||
- items:
|
||||
- const: g_err
|
||||
- const: g_recc
|
||||
- const: ch0_err
|
||||
- const: ch0_rec
|
||||
- const: ch0_trx
|
||||
- const: ch1_err
|
||||
- const: ch1_rec
|
||||
- const: ch1_trx
|
||||
- const: ch2_err
|
||||
- const: ch2_rec
|
||||
- const: ch2_trx
|
||||
- const: ch3_err
|
||||
- const: ch3_rec
|
||||
- const: ch3_trx
|
||||
- const: ch4_err
|
||||
- const: ch4_rec
|
||||
- const: ch4_trx
|
||||
- const: ch5_err
|
||||
- const: ch5_rec
|
||||
- const: ch5_trx
|
||||
minItems: 8
|
||||
|
||||
clocks:
|
||||
maxItems: 3
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: fck
|
||||
- const: canfd
|
||||
- const: can_clk
|
||||
oneOf:
|
||||
- items:
|
||||
- const: fck
|
||||
- const: canfd
|
||||
- const: can_clk
|
||||
- items:
|
||||
- const: fck
|
||||
- const: ram_clk
|
||||
- const: can_clk
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
@ -117,52 +178,77 @@ allOf:
|
|||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
items:
|
||||
- description: CAN global error interrupt
|
||||
- description: CAN receive FIFO interrupt
|
||||
- description: CAN0 error interrupt
|
||||
- description: CAN0 transmit interrupt
|
||||
- description: CAN0 transmit/receive FIFO receive completion interrupt
|
||||
- description: CAN1 error interrupt
|
||||
- description: CAN1 transmit interrupt
|
||||
- description: CAN1 transmit/receive FIFO receive completion interrupt
|
||||
maxItems: 8
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: g_err
|
||||
- const: g_recc
|
||||
- const: ch0_err
|
||||
- const: ch0_rec
|
||||
- const: ch0_trx
|
||||
- const: ch1_err
|
||||
- const: ch1_rec
|
||||
- const: ch1_trx
|
||||
maxItems: 8
|
||||
|
||||
resets:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: rstp_n
|
||||
- const: rstc_n
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
|
||||
required:
|
||||
- reset-names
|
||||
else:
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,rcar-gen3-canfd
|
||||
- renesas,rcar-gen4-canfd
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
items:
|
||||
- description: Channel interrupt
|
||||
- description: Global interrupt
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: ch_int
|
||||
- const: g_int
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,r9a09g047-canfd
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 20
|
||||
|
||||
interrupt-names:
|
||||
minItems: 20
|
||||
|
||||
resets:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
|
||||
reset-names:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
|
||||
required:
|
||||
- reset-names
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,rcar-gen3-canfd
|
||||
- renesas,rzg2l-canfd
|
||||
then:
|
||||
patternProperties:
|
||||
"^channel[2-7]$": false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
@ -171,16 +257,15 @@ allOf:
|
|||
then:
|
||||
patternProperties:
|
||||
"^channel[4-7]$": false
|
||||
else:
|
||||
if:
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,rcar-gen4-canfd
|
||||
then:
|
||||
patternProperties:
|
||||
"^channel[2-7]$": false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,r9a09g047-canfd
|
||||
then:
|
||||
patternProperties:
|
||||
"^channel[6-7]$": false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
|
|
@ -5274,6 +5274,7 @@ F: include/uapi/linux/can/isotp.h
|
|||
F: include/uapi/linux/can/raw.h
|
||||
F: net/can/
|
||||
F: net/sched/em_canid.c
|
||||
F: tools/testing/selftests/net/can/
|
||||
|
||||
CAN-J1939 NETWORK LAYER
|
||||
M: Robin van der Gracht <robin@protonic.nl>
|
||||
|
@ -17076,6 +17077,7 @@ X: net/ceph/
|
|||
X: net/mac80211/
|
||||
X: net/rfkill/
|
||||
X: net/wireless/
|
||||
X: tools/testing/selftests/net/can/
|
||||
|
||||
NETWORKING [IPSEC]
|
||||
M: Steffen Klassert <steffen.klassert@secunet.com>
|
||||
|
|
|
@ -275,7 +275,7 @@ static int ctucan_set_bittiming(struct net_device *ndev)
|
|||
static int ctucan_set_data_bittiming(struct net_device *ndev)
|
||||
{
|
||||
struct ctucan_priv *priv = netdev_priv(ndev);
|
||||
struct can_bittiming *dbt = &priv->can.data_bittiming;
|
||||
struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
|
||||
|
||||
/* Note that dbt may be modified here */
|
||||
return ctucan_set_btr(ndev, dbt, false);
|
||||
|
@ -290,7 +290,7 @@ static int ctucan_set_data_bittiming(struct net_device *ndev)
|
|||
static int ctucan_set_secondary_sample_point(struct net_device *ndev)
|
||||
{
|
||||
struct ctucan_priv *priv = netdev_priv(ndev);
|
||||
struct can_bittiming *dbt = &priv->can.data_bittiming;
|
||||
struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
|
||||
int ssp_offset = 0;
|
||||
u32 ssp_cfg = 0; /* No SSP by default */
|
||||
|
||||
|
@ -1358,12 +1358,12 @@ int ctucan_probe_common(struct device *dev, void __iomem *addr, int irq, unsigne
|
|||
priv->ntxbufs = ntxbufs;
|
||||
priv->dev = dev;
|
||||
priv->can.bittiming_const = &ctu_can_fd_bit_timing_max;
|
||||
priv->can.data_bittiming_const = &ctu_can_fd_bit_timing_data_max;
|
||||
priv->can.fd.data_bittiming_const = &ctu_can_fd_bit_timing_data_max;
|
||||
priv->can.do_set_mode = ctucan_do_set_mode;
|
||||
|
||||
/* Needed for timing adjustment to be performed as soon as possible */
|
||||
priv->can.do_set_bittiming = ctucan_set_bittiming;
|
||||
priv->can.do_set_data_bittiming = ctucan_set_data_bittiming;
|
||||
priv->can.fd.do_set_data_bittiming = ctucan_set_data_bittiming;
|
||||
|
||||
priv->can.do_get_berr_counter = ctucan_get_berr_counter;
|
||||
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK
|
||||
|
|
|
@ -404,8 +404,8 @@ int open_candev(struct net_device *dev)
|
|||
|
||||
/* For CAN FD the data bitrate has to be >= the arbitration bitrate */
|
||||
if ((priv->ctrlmode & CAN_CTRLMODE_FD) &&
|
||||
(!priv->data_bittiming.bitrate ||
|
||||
priv->data_bittiming.bitrate < priv->bittiming.bitrate)) {
|
||||
(!priv->fd.data_bittiming.bitrate ||
|
||||
priv->fd.data_bittiming.bitrate < priv->bittiming.bitrate)) {
|
||||
netdev_err(dev, "incorrect/missing data bit-timing\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -543,16 +543,16 @@ int register_candev(struct net_device *dev)
|
|||
if (!priv->bitrate_const != !priv->bitrate_const_cnt)
|
||||
return -EINVAL;
|
||||
|
||||
if (!priv->data_bitrate_const != !priv->data_bitrate_const_cnt)
|
||||
if (!priv->fd.data_bitrate_const != !priv->fd.data_bitrate_const_cnt)
|
||||
return -EINVAL;
|
||||
|
||||
/* We only support either fixed bit rates or bit timing const. */
|
||||
if ((priv->bitrate_const || priv->data_bitrate_const) &&
|
||||
(priv->bittiming_const || priv->data_bittiming_const))
|
||||
if ((priv->bitrate_const || priv->fd.data_bitrate_const) &&
|
||||
(priv->bittiming_const || priv->fd.data_bittiming_const))
|
||||
return -EINVAL;
|
||||
|
||||
if (!can_bittiming_const_valid(priv->bittiming_const) ||
|
||||
!can_bittiming_const_valid(priv->data_bittiming_const))
|
||||
!can_bittiming_const_valid(priv->fd.data_bittiming_const))
|
||||
return -EINVAL;
|
||||
|
||||
if (!priv->termination_const) {
|
||||
|
|
|
@ -141,7 +141,7 @@ static int can_tdc_changelink(struct can_priv *priv, const struct nlattr *nla,
|
|||
{
|
||||
struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1];
|
||||
struct can_tdc tdc = { 0 };
|
||||
const struct can_tdc_const *tdc_const = priv->tdc_const;
|
||||
const struct can_tdc_const *tdc_const = priv->fd.tdc_const;
|
||||
int err;
|
||||
|
||||
if (!tdc_const || !can_tdc_is_enabled(priv))
|
||||
|
@ -179,7 +179,7 @@ static int can_tdc_changelink(struct can_priv *priv, const struct nlattr *nla,
|
|||
tdc.tdcf = tdcf;
|
||||
}
|
||||
|
||||
priv->tdc = tdc;
|
||||
priv->fd.tdc = tdc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -228,10 +228,10 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
|
|||
dev->mtu = CANFD_MTU;
|
||||
} else {
|
||||
dev->mtu = CAN_MTU;
|
||||
memset(&priv->data_bittiming, 0,
|
||||
sizeof(priv->data_bittiming));
|
||||
memset(&priv->fd.data_bittiming, 0,
|
||||
sizeof(priv->fd.data_bittiming));
|
||||
priv->ctrlmode &= ~CAN_CTRLMODE_TDC_MASK;
|
||||
memset(&priv->tdc, 0, sizeof(priv->tdc));
|
||||
memset(&priv->fd.tdc, 0, sizeof(priv->fd.tdc));
|
||||
}
|
||||
|
||||
tdc_mask = cm->mask & CAN_CTRLMODE_TDC_MASK;
|
||||
|
@ -312,16 +312,16 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
|
|||
* directly via do_set_bitrate(). Bail out if neither
|
||||
* is given.
|
||||
*/
|
||||
if (!priv->data_bittiming_const && !priv->do_set_data_bittiming &&
|
||||
!priv->data_bitrate_const)
|
||||
if (!priv->fd.data_bittiming_const && !priv->fd.do_set_data_bittiming &&
|
||||
!priv->fd.data_bitrate_const)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]),
|
||||
sizeof(dbt));
|
||||
err = can_get_bittiming(dev, &dbt,
|
||||
priv->data_bittiming_const,
|
||||
priv->data_bitrate_const,
|
||||
priv->data_bitrate_const_cnt,
|
||||
priv->fd.data_bittiming_const,
|
||||
priv->fd.data_bitrate_const,
|
||||
priv->fd.data_bitrate_const_cnt,
|
||||
extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -333,7 +333,7 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(&priv->tdc, 0, sizeof(priv->tdc));
|
||||
memset(&priv->fd.tdc, 0, sizeof(priv->fd.tdc));
|
||||
if (data[IFLA_CAN_TDC]) {
|
||||
/* TDC parameters are provided: use them */
|
||||
err = can_tdc_changelink(priv, data[IFLA_CAN_TDC],
|
||||
|
@ -346,17 +346,17 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
|
|||
/* Neither of TDC parameters nor TDC flags are
|
||||
* provided: do calculation
|
||||
*/
|
||||
can_calc_tdco(&priv->tdc, priv->tdc_const, &dbt,
|
||||
can_calc_tdco(&priv->fd.tdc, priv->fd.tdc_const, &dbt,
|
||||
&priv->ctrlmode, priv->ctrlmode_supported);
|
||||
} /* else: both CAN_CTRLMODE_TDC_{AUTO,MANUAL} are explicitly
|
||||
* turned off. TDC is disabled: do nothing
|
||||
*/
|
||||
|
||||
memcpy(&priv->data_bittiming, &dbt, sizeof(dbt));
|
||||
memcpy(&priv->fd.data_bittiming, &dbt, sizeof(dbt));
|
||||
|
||||
if (priv->do_set_data_bittiming) {
|
||||
if (priv->fd.do_set_data_bittiming) {
|
||||
/* Finally, set the bit-timing registers */
|
||||
err = priv->do_set_data_bittiming(dev);
|
||||
err = priv->fd.do_set_data_bittiming(dev);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
@ -394,7 +394,7 @@ static size_t can_tdc_get_size(const struct net_device *dev)
|
|||
struct can_priv *priv = netdev_priv(dev);
|
||||
size_t size;
|
||||
|
||||
if (!priv->tdc_const)
|
||||
if (!priv->fd.tdc_const)
|
||||
return 0;
|
||||
|
||||
size = nla_total_size(0); /* nest IFLA_CAN_TDC */
|
||||
|
@ -404,17 +404,17 @@ static size_t can_tdc_get_size(const struct net_device *dev)
|
|||
}
|
||||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO_MIN */
|
||||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO_MAX */
|
||||
if (priv->tdc_const->tdcf_max) {
|
||||
if (priv->fd.tdc_const->tdcf_max) {
|
||||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCF_MIN */
|
||||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCF_MAX */
|
||||
}
|
||||
|
||||
if (can_tdc_is_enabled(priv)) {
|
||||
if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL ||
|
||||
priv->do_get_auto_tdcv)
|
||||
priv->fd.do_get_auto_tdcv)
|
||||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCV */
|
||||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO */
|
||||
if (priv->tdc_const->tdcf_max)
|
||||
if (priv->fd.tdc_const->tdcf_max)
|
||||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCF */
|
||||
}
|
||||
|
||||
|
@ -442,9 +442,9 @@ static size_t can_get_size(const struct net_device *dev)
|
|||
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->data_bittiming.bitrate) /* IFLA_CAN_DATA_BITTIMING */
|
||||
if (priv->fd.data_bittiming.bitrate) /* IFLA_CAN_DATA_BITTIMING */
|
||||
size += nla_total_size(sizeof(struct can_bittiming));
|
||||
if (priv->data_bittiming_const) /* IFLA_CAN_DATA_BITTIMING_CONST */
|
||||
if (priv->fd.data_bittiming_const) /* IFLA_CAN_DATA_BITTIMING_CONST */
|
||||
size += nla_total_size(sizeof(struct can_bittiming_const));
|
||||
if (priv->termination_const) {
|
||||
size += nla_total_size(sizeof(priv->termination)); /* IFLA_CAN_TERMINATION */
|
||||
|
@ -454,9 +454,9 @@ static size_t can_get_size(const struct net_device *dev)
|
|||
if (priv->bitrate_const) /* IFLA_CAN_BITRATE_CONST */
|
||||
size += nla_total_size(sizeof(*priv->bitrate_const) *
|
||||
priv->bitrate_const_cnt);
|
||||
if (priv->data_bitrate_const) /* IFLA_CAN_DATA_BITRATE_CONST */
|
||||
size += nla_total_size(sizeof(*priv->data_bitrate_const) *
|
||||
priv->data_bitrate_const_cnt);
|
||||
if (priv->fd.data_bitrate_const) /* IFLA_CAN_DATA_BITRATE_CONST */
|
||||
size += nla_total_size(sizeof(*priv->fd.data_bitrate_const) *
|
||||
priv->fd.data_bitrate_const_cnt);
|
||||
size += sizeof(priv->bitrate_max); /* IFLA_CAN_BITRATE_MAX */
|
||||
size += can_tdc_get_size(dev); /* IFLA_CAN_TDC */
|
||||
size += can_ctrlmode_ext_get_size(); /* IFLA_CAN_CTRLMODE_EXT */
|
||||
|
@ -468,8 +468,8 @@ static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev)
|
|||
{
|
||||
struct nlattr *nest;
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
struct can_tdc *tdc = &priv->tdc;
|
||||
const struct can_tdc_const *tdc_const = priv->tdc_const;
|
||||
struct can_tdc *tdc = &priv->fd.tdc;
|
||||
const struct can_tdc_const *tdc_const = priv->fd.tdc_const;
|
||||
|
||||
if (!tdc_const)
|
||||
return 0;
|
||||
|
@ -497,8 +497,8 @@ static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev)
|
|||
if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL) {
|
||||
tdcv = tdc->tdcv;
|
||||
err = 0;
|
||||
} else if (priv->do_get_auto_tdcv) {
|
||||
err = priv->do_get_auto_tdcv(dev, &tdcv);
|
||||
} else if (priv->fd.do_get_auto_tdcv) {
|
||||
err = priv->fd.do_get_auto_tdcv(dev, &tdcv);
|
||||
}
|
||||
if (!err && nla_put_u32(skb, IFLA_CAN_TDC_TDCV, tdcv))
|
||||
goto err_cancel;
|
||||
|
@ -564,14 +564,14 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
|
|||
!priv->do_get_berr_counter(dev, &bec) &&
|
||||
nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)) ||
|
||||
|
||||
(priv->data_bittiming.bitrate &&
|
||||
(priv->fd.data_bittiming.bitrate &&
|
||||
nla_put(skb, IFLA_CAN_DATA_BITTIMING,
|
||||
sizeof(priv->data_bittiming), &priv->data_bittiming)) ||
|
||||
sizeof(priv->fd.data_bittiming), &priv->fd.data_bittiming)) ||
|
||||
|
||||
(priv->data_bittiming_const &&
|
||||
(priv->fd.data_bittiming_const &&
|
||||
nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST,
|
||||
sizeof(*priv->data_bittiming_const),
|
||||
priv->data_bittiming_const)) ||
|
||||
sizeof(*priv->fd.data_bittiming_const),
|
||||
priv->fd.data_bittiming_const)) ||
|
||||
|
||||
(priv->termination_const &&
|
||||
(nla_put_u16(skb, IFLA_CAN_TERMINATION, priv->termination) ||
|
||||
|
@ -586,11 +586,11 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
|
|||
priv->bitrate_const_cnt,
|
||||
priv->bitrate_const)) ||
|
||||
|
||||
(priv->data_bitrate_const &&
|
||||
(priv->fd.data_bitrate_const &&
|
||||
nla_put(skb, IFLA_CAN_DATA_BITRATE_CONST,
|
||||
sizeof(*priv->data_bitrate_const) *
|
||||
priv->data_bitrate_const_cnt,
|
||||
priv->data_bitrate_const)) ||
|
||||
sizeof(*priv->fd.data_bitrate_const) *
|
||||
priv->fd.data_bitrate_const_cnt,
|
||||
priv->fd.data_bitrate_const)) ||
|
||||
|
||||
(nla_put(skb, IFLA_CAN_BITRATE_MAX,
|
||||
sizeof(priv->bitrate_max),
|
||||
|
|
|
@ -1226,7 +1226,7 @@ static void flexcan_set_bittiming_cbt(const struct net_device *dev)
|
|||
{
|
||||
struct flexcan_priv *priv = netdev_priv(dev);
|
||||
struct can_bittiming *bt = &priv->can.bittiming;
|
||||
struct can_bittiming *dbt = &priv->can.data_bittiming;
|
||||
struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
|
||||
struct flexcan_regs __iomem *regs = priv->regs;
|
||||
u32 reg_cbt, reg_fdctrl;
|
||||
|
||||
|
@ -2239,7 +2239,7 @@ static int flexcan_probe(struct platform_device *pdev)
|
|||
priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD |
|
||||
CAN_CTRLMODE_FD_NON_ISO;
|
||||
priv->can.bittiming_const = &flexcan_fd_bittiming_const;
|
||||
priv->can.data_bittiming_const =
|
||||
priv->can.fd.data_bittiming_const =
|
||||
&flexcan_fd_data_bittiming_const;
|
||||
} else {
|
||||
priv->can.bittiming_const = &flexcan_bittiming_const;
|
||||
|
|
|
@ -669,7 +669,7 @@ static void ifi_canfd_set_bittiming(struct net_device *ndev)
|
|||
{
|
||||
struct ifi_canfd_priv *priv = netdev_priv(ndev);
|
||||
const struct can_bittiming *bt = &priv->can.bittiming;
|
||||
const struct can_bittiming *dbt = &priv->can.data_bittiming;
|
||||
const struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
|
||||
u16 brp, sjw, tseg1, tseg2, tdc;
|
||||
|
||||
/* Configure bit timing */
|
||||
|
@ -1000,10 +1000,10 @@ static int ifi_canfd_plat_probe(struct platform_device *pdev)
|
|||
|
||||
priv->can.clock.freq = readl(addr + IFI_CANFD_CANCLOCK);
|
||||
|
||||
priv->can.bittiming_const = &ifi_canfd_bittiming_const;
|
||||
priv->can.data_bittiming_const = &ifi_canfd_bittiming_const;
|
||||
priv->can.do_set_mode = ifi_canfd_set_mode;
|
||||
priv->can.do_get_berr_counter = ifi_canfd_get_berr_counter;
|
||||
priv->can.bittiming_const = &ifi_canfd_bittiming_const;
|
||||
priv->can.fd.data_bittiming_const = &ifi_canfd_bittiming_const;
|
||||
priv->can.do_set_mode = ifi_canfd_set_mode;
|
||||
priv->can.do_get_berr_counter = ifi_canfd_get_berr_counter;
|
||||
|
||||
/* IFI CANFD can do both Bosch FD and ISO FD */
|
||||
priv->can.ctrlmode = CAN_CTRLMODE_FD;
|
||||
|
|
|
@ -863,7 +863,7 @@ static int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data)
|
|||
struct can_bittiming *bt;
|
||||
|
||||
if (data)
|
||||
bt = &can->can.data_bittiming;
|
||||
bt = &can->can.fd.data_bittiming;
|
||||
else
|
||||
bt = &can->can.bittiming;
|
||||
|
||||
|
@ -999,9 +999,9 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
|
|||
spin_lock_init(&can->lock);
|
||||
|
||||
can->can.bittiming_const = &kvaser_pciefd_bittiming_const;
|
||||
can->can.data_bittiming_const = &kvaser_pciefd_bittiming_const;
|
||||
can->can.fd.data_bittiming_const = &kvaser_pciefd_bittiming_const;
|
||||
can->can.do_set_bittiming = kvaser_pciefd_set_nominal_bittiming;
|
||||
can->can.do_set_data_bittiming = kvaser_pciefd_set_data_bittiming;
|
||||
can->can.fd.do_set_data_bittiming = kvaser_pciefd_set_data_bittiming;
|
||||
can->can.do_set_mode = kvaser_pciefd_set_mode;
|
||||
can->can.do_get_berr_counter = kvaser_pciefd_get_berr_counter;
|
||||
can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY |
|
||||
|
|
|
@ -1372,7 +1372,7 @@ static int m_can_set_bittiming(struct net_device *dev)
|
|||
{
|
||||
struct m_can_classdev *cdev = netdev_priv(dev);
|
||||
const struct can_bittiming *bt = &cdev->can.bittiming;
|
||||
const struct can_bittiming *dbt = &cdev->can.data_bittiming;
|
||||
const struct can_bittiming *dbt = &cdev->can.fd.data_bittiming;
|
||||
u16 brp, sjw, tseg1, tseg2;
|
||||
u32 reg_btp;
|
||||
|
||||
|
@ -1738,7 +1738,7 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
|
|||
if (err)
|
||||
return err;
|
||||
cdev->can.bittiming_const = &m_can_bittiming_const_30X;
|
||||
cdev->can.data_bittiming_const = &m_can_data_bittiming_const_30X;
|
||||
cdev->can.fd.data_bittiming_const = &m_can_data_bittiming_const_30X;
|
||||
break;
|
||||
case 31:
|
||||
/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */
|
||||
|
@ -1746,13 +1746,13 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
|
|||
if (err)
|
||||
return err;
|
||||
cdev->can.bittiming_const = &m_can_bittiming_const_31X;
|
||||
cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
|
||||
cdev->can.fd.data_bittiming_const = &m_can_data_bittiming_const_31X;
|
||||
break;
|
||||
case 32:
|
||||
case 33:
|
||||
/* Support both MCAN version v3.2.x and v3.3.0 */
|
||||
cdev->can.bittiming_const = &m_can_bittiming_const_31X;
|
||||
cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
|
||||
cdev->can.fd.data_bittiming_const = &m_can_data_bittiming_const_31X;
|
||||
|
||||
niso = m_can_niso_supported(cdev);
|
||||
if (niso < 0)
|
||||
|
|
|
@ -624,7 +624,7 @@ static int peak_canfd_set_data_bittiming(struct net_device *ndev)
|
|||
{
|
||||
struct peak_canfd_priv *priv = netdev_priv(ndev);
|
||||
|
||||
return pucan_set_timing_fast(priv, &priv->can.data_bittiming);
|
||||
return pucan_set_timing_fast(priv, &priv->can.fd.data_bittiming);
|
||||
}
|
||||
|
||||
static int peak_canfd_close(struct net_device *ndev)
|
||||
|
@ -813,12 +813,12 @@ struct net_device *alloc_peak_canfd_dev(int sizeof_priv, int index,
|
|||
/* complete now socket-can initialization side */
|
||||
priv->can.state = CAN_STATE_STOPPED;
|
||||
priv->can.bittiming_const = &peak_canfd_nominal_const;
|
||||
priv->can.data_bittiming_const = &peak_canfd_data_const;
|
||||
priv->can.fd.data_bittiming_const = &peak_canfd_data_const;
|
||||
|
||||
priv->can.do_set_mode = peak_canfd_set_mode;
|
||||
priv->can.do_get_berr_counter = peak_canfd_get_berr_counter;
|
||||
priv->can.do_set_bittiming = peak_canfd_set_bittiming;
|
||||
priv->can.do_set_data_bittiming = peak_canfd_set_data_bittiming;
|
||||
priv->can.fd.do_set_data_bittiming = peak_canfd_set_data_bittiming;
|
||||
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
|
||||
CAN_CTRLMODE_LISTENONLY |
|
||||
CAN_CTRLMODE_3_SAMPLES |
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
* wherever it is modified to a readable name.
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/can/dev.h>
|
||||
|
@ -74,33 +75,24 @@
|
|||
#define RCANFD_GSTS_GNOPM (BIT(0) | BIT(1) | BIT(2) | BIT(3))
|
||||
|
||||
/* RSCFDnCFDGERFL / RSCFDnGERFL */
|
||||
#define RCANFD_GERFL_EEF0_7 GENMASK(23, 16)
|
||||
#define RCANFD_GERFL_EEF(ch) BIT(16 + (ch))
|
||||
#define RCANFD_GERFL_EEF GENMASK(23, 16)
|
||||
#define RCANFD_GERFL_CMPOF BIT(3) /* CAN FD only */
|
||||
#define RCANFD_GERFL_THLES BIT(2)
|
||||
#define RCANFD_GERFL_MES BIT(1)
|
||||
#define RCANFD_GERFL_DEF BIT(0)
|
||||
|
||||
#define RCANFD_GERFL_ERR(gpriv, x) \
|
||||
((x) & (reg_gen4(gpriv, RCANFD_GERFL_EEF0_7, \
|
||||
RCANFD_GERFL_EEF(0) | RCANFD_GERFL_EEF(1)) | \
|
||||
RCANFD_GERFL_MES | \
|
||||
((gpriv)->fdmode ? RCANFD_GERFL_CMPOF : 0)))
|
||||
({\
|
||||
typeof(gpriv) (_gpriv) = (gpriv); \
|
||||
((x) & ((FIELD_PREP(RCANFD_GERFL_EEF, (_gpriv)->channels_mask)) | \
|
||||
RCANFD_GERFL_MES | ((_gpriv)->fdmode ? RCANFD_GERFL_CMPOF : 0))); \
|
||||
})
|
||||
|
||||
/* AFL Rx rules registers */
|
||||
|
||||
/* RSCFDnCFDGAFLCFG0 / RSCFDnGAFLCFG0 */
|
||||
#define RCANFD_GAFLCFG_SETRNC(gpriv, n, x) \
|
||||
(((x) & reg_gen4(gpriv, 0x1ff, 0xff)) << \
|
||||
(reg_gen4(gpriv, 16, 24) - ((n) & 1) * reg_gen4(gpriv, 16, 8)))
|
||||
|
||||
#define RCANFD_GAFLCFG_GETRNC(gpriv, n, x) \
|
||||
(((x) >> (reg_gen4(gpriv, 16, 24) - ((n) & 1) * reg_gen4(gpriv, 16, 8))) & \
|
||||
reg_gen4(gpriv, 0x1ff, 0xff))
|
||||
|
||||
/* RSCFDnCFDGAFLECTR / RSCFDnGAFLECTR */
|
||||
#define RCANFD_GAFLECTR_AFLDAE BIT(8)
|
||||
#define RCANFD_GAFLECTR_AFLPN(gpriv, x) ((x) & reg_gen4(gpriv, 0x7f, 0x1f))
|
||||
#define RCANFD_GAFLECTR_AFLPN(gpriv, page_num) ((page_num) & (gpriv)->info->max_aflpn)
|
||||
|
||||
/* RSCFDnCFDGAFLIDj / RSCFDnGAFLIDj */
|
||||
#define RCANFD_GAFLID_GAFLLB BIT(29)
|
||||
|
@ -118,13 +110,13 @@
|
|||
|
||||
/* RSCFDnCFDCmNCFG - CAN FD only */
|
||||
#define RCANFD_NCFG_NTSEG2(gpriv, x) \
|
||||
(((x) & reg_gen4(gpriv, 0x7f, 0x1f)) << reg_gen4(gpriv, 25, 24))
|
||||
(((x) & ((gpriv)->info->nom_bittiming->tseg2_max - 1)) << (gpriv)->info->sh->ntseg2)
|
||||
|
||||
#define RCANFD_NCFG_NTSEG1(gpriv, x) \
|
||||
(((x) & reg_gen4(gpriv, 0xff, 0x7f)) << reg_gen4(gpriv, 17, 16))
|
||||
(((x) & ((gpriv)->info->nom_bittiming->tseg1_max - 1)) << (gpriv)->info->sh->ntseg1)
|
||||
|
||||
#define RCANFD_NCFG_NSJW(gpriv, x) \
|
||||
(((x) & reg_gen4(gpriv, 0x7f, 0x1f)) << reg_gen4(gpriv, 10, 11))
|
||||
(((x) & ((gpriv)->info->nom_bittiming->sjw_max - 1)) << (gpriv)->info->sh->nsjw)
|
||||
|
||||
#define RCANFD_NCFG_NBRP(x) (((x) & 0x3ff) << 0)
|
||||
|
||||
|
@ -186,13 +178,13 @@
|
|||
#define RCANFD_CERFL_ERR(x) ((x) & (0x7fff)) /* above bits 14:0 */
|
||||
|
||||
/* RSCFDnCFDCmDCFG */
|
||||
#define RCANFD_DCFG_DSJW(gpriv, x) (((x) & reg_gen4(gpriv, 0xf, 0x7)) << 24)
|
||||
#define RCANFD_DCFG_DSJW(gpriv, x) (((x) & ((gpriv)->info->data_bittiming->sjw_max - 1)) << 24)
|
||||
|
||||
#define RCANFD_DCFG_DTSEG2(gpriv, x) \
|
||||
(((x) & reg_gen4(gpriv, 0x0f, 0x7)) << reg_gen4(gpriv, 16, 20))
|
||||
(((x) & ((gpriv)->info->data_bittiming->tseg2_max - 1)) << (gpriv)->info->sh->dtseg2)
|
||||
|
||||
#define RCANFD_DCFG_DTSEG1(gpriv, x) \
|
||||
(((x) & reg_gen4(gpriv, 0x1f, 0xf)) << reg_gen4(gpriv, 8, 16))
|
||||
(((x) & ((gpriv)->info->data_bittiming->tseg1_max - 1)) << (gpriv)->info->sh->dtseg1)
|
||||
|
||||
#define RCANFD_DCFG_DBRP(x) (((x) & 0xff) << 0)
|
||||
|
||||
|
@ -233,11 +225,14 @@
|
|||
/* Common FIFO bits */
|
||||
|
||||
/* RSCFDnCFDCFCCk */
|
||||
#define RCANFD_CFCC_CFTML(gpriv, x) \
|
||||
(((x) & reg_gen4(gpriv, 0x1f, 0xf)) << reg_gen4(gpriv, 16, 20))
|
||||
#define RCANFD_CFCC_CFM(gpriv, x) (((x) & 0x3) << reg_gen4(gpriv, 8, 16))
|
||||
#define RCANFD_CFCC_CFTML(gpriv, cftml) \
|
||||
({\
|
||||
typeof(gpriv) (_gpriv) = (gpriv); \
|
||||
(((cftml) & (_gpriv)->info->max_cftml) << (_gpriv)->info->sh->cftml); \
|
||||
})
|
||||
#define RCANFD_CFCC_CFM(gpriv, x) (((x) & 0x3) << (gpriv)->info->sh->cfm)
|
||||
#define RCANFD_CFCC_CFIM BIT(12)
|
||||
#define RCANFD_CFCC_CFDC(gpriv, x) (((x) & 0x7) << reg_gen4(gpriv, 21, 8))
|
||||
#define RCANFD_CFCC_CFDC(gpriv, x) (((x) & 0x7) << (gpriv)->info->sh->cfdc)
|
||||
#define RCANFD_CFCC_CFPLS(x) (((x) & 0x7) << 4)
|
||||
#define RCANFD_CFCC_CFTXIE BIT(2)
|
||||
#define RCANFD_CFCC_CFE BIT(0)
|
||||
|
@ -298,14 +293,14 @@
|
|||
/* RSCFDnCFDGAFLECTR / RSCFDnGAFLECTR */
|
||||
#define RCANFD_GAFLECTR (0x0098)
|
||||
/* RSCFDnCFDGAFLCFG / RSCFDnGAFLCFG */
|
||||
#define RCANFD_GAFLCFG(ch) (0x009c + (0x04 * ((ch) / 2)))
|
||||
#define RCANFD_GAFLCFG(w) (0x009c + (0x04 * (w)))
|
||||
/* RSCFDnCFDRMNB / RSCFDnRMNB */
|
||||
#define RCANFD_RMNB (0x00a4)
|
||||
/* RSCFDnCFDRMND / RSCFDnRMND */
|
||||
#define RCANFD_RMND(y) (0x00a8 + (0x04 * (y)))
|
||||
|
||||
/* RSCFDnCFDRFCCx / RSCFDnRFCCx */
|
||||
#define RCANFD_RFCC(gpriv, x) (reg_gen4(gpriv, 0x00c0, 0x00b8) + (0x04 * (x)))
|
||||
#define RCANFD_RFCC(gpriv, x) ((gpriv)->info->regs->rfcc + (0x04 * (x)))
|
||||
/* RSCFDnCFDRFSTSx / RSCFDnRFSTSx */
|
||||
#define RCANFD_RFSTS(gpriv, x) (RCANFD_RFCC(gpriv, x) + 0x20)
|
||||
/* RSCFDnCFDRFPCTRx / RSCFDnRFPCTRx */
|
||||
|
@ -315,13 +310,13 @@
|
|||
|
||||
/* RSCFDnCFDCFCCx / RSCFDnCFCCx */
|
||||
#define RCANFD_CFCC(gpriv, ch, idx) \
|
||||
(reg_gen4(gpriv, 0x0120, 0x0118) + (0x0c * (ch)) + (0x04 * (idx)))
|
||||
((gpriv)->info->regs->cfcc + (0x0c * (ch)) + (0x04 * (idx)))
|
||||
/* RSCFDnCFDCFSTSx / RSCFDnCFSTSx */
|
||||
#define RCANFD_CFSTS(gpriv, ch, idx) \
|
||||
(reg_gen4(gpriv, 0x01e0, 0x0178) + (0x0c * (ch)) + (0x04 * (idx)))
|
||||
((gpriv)->info->regs->cfsts + (0x0c * (ch)) + (0x04 * (idx)))
|
||||
/* RSCFDnCFDCFPCTRx / RSCFDnCFPCTRx */
|
||||
#define RCANFD_CFPCTR(gpriv, ch, idx) \
|
||||
(reg_gen4(gpriv, 0x0240, 0x01d8) + (0x0c * (ch)) + (0x04 * (idx)))
|
||||
((gpriv)->info->regs->cfpctr + (0x0c * (ch)) + (0x04 * (idx)))
|
||||
|
||||
/* RSCFDnCFDFESTS / RSCFDnFESTS */
|
||||
#define RCANFD_FESTS (0x0238)
|
||||
|
@ -437,7 +432,7 @@
|
|||
/* CAN FD mode specific register map */
|
||||
|
||||
/* RSCFDnCFDCmXXX -> RCANFD_F_XXX(m) */
|
||||
#define RCANFD_F_DCFG(gpriv, m) (reg_gen4(gpriv, 0x1400, 0x0500) + (0x20 * (m)))
|
||||
#define RCANFD_F_DCFG(gpriv, m) ((gpriv)->info->regs->f_dcfg + (0x20 * (m)))
|
||||
#define RCANFD_F_CFDCFG(m) (0x0504 + (0x20 * (m)))
|
||||
#define RCANFD_F_CFDCTR(m) (0x0508 + (0x20 * (m)))
|
||||
#define RCANFD_F_CFDSTS(m) (0x050c + (0x20 * (m)))
|
||||
|
@ -453,7 +448,7 @@
|
|||
#define RCANFD_F_RMDF(q, b) (0x200c + (0x04 * (b)) + (0x20 * (q)))
|
||||
|
||||
/* RSCFDnCFDRFXXx -> RCANFD_F_RFXX(x) */
|
||||
#define RCANFD_F_RFOFFSET(gpriv) reg_gen4(gpriv, 0x6000, 0x3000)
|
||||
#define RCANFD_F_RFOFFSET(gpriv) ((gpriv)->info->regs->rfoffset)
|
||||
#define RCANFD_F_RFID(gpriv, x) (RCANFD_F_RFOFFSET(gpriv) + (0x80 * (x)))
|
||||
#define RCANFD_F_RFPTR(gpriv, x) (RCANFD_F_RFOFFSET(gpriv) + 0x04 + (0x80 * (x)))
|
||||
#define RCANFD_F_RFFDSTS(gpriv, x) (RCANFD_F_RFOFFSET(gpriv) + 0x08 + (0x80 * (x)))
|
||||
|
@ -461,7 +456,7 @@
|
|||
(RCANFD_F_RFOFFSET(gpriv) + 0x0c + (0x80 * (x)) + (0x04 * (df)))
|
||||
|
||||
/* RSCFDnCFDCFXXk -> RCANFD_F_CFXX(ch, k) */
|
||||
#define RCANFD_F_CFOFFSET(gpriv) reg_gen4(gpriv, 0x6400, 0x3400)
|
||||
#define RCANFD_F_CFOFFSET(gpriv) ((gpriv)->info->regs->cfoffset)
|
||||
|
||||
#define RCANFD_F_CFID(gpriv, ch, idx) \
|
||||
(RCANFD_F_CFOFFSET(gpriv) + (0x180 * (ch)) + (0x80 * (idx)))
|
||||
|
@ -510,12 +505,43 @@
|
|||
|
||||
struct rcar_canfd_global;
|
||||
|
||||
struct rcar_canfd_regs {
|
||||
u16 rfcc; /* RX FIFO Configuration/Control Register */
|
||||
u16 cfcc; /* Common FIFO Configuration/Control Register */
|
||||
u16 cfsts; /* Common FIFO Status Register */
|
||||
u16 cfpctr; /* Common FIFO Pointer Control Register */
|
||||
u16 f_dcfg; /* Global FD Configuration Register */
|
||||
u16 rfoffset; /* Receive FIFO buffer access ID register */
|
||||
u16 cfoffset; /* Transmit/receive FIFO buffer access ID register */
|
||||
};
|
||||
|
||||
struct rcar_canfd_shift_data {
|
||||
u8 ntseg2; /* Nominal Bit Rate Time Segment 2 Control */
|
||||
u8 ntseg1; /* Nominal Bit Rate Time Segment 1 Control */
|
||||
u8 nsjw; /* Nominal Bit Rate Resynchronization Jump Width Control */
|
||||
u8 dtseg2; /* Data Bit Rate Time Segment 2 Control */
|
||||
u8 dtseg1; /* Data Bit Rate Time Segment 1 Control */
|
||||
u8 cftml; /* Common FIFO TX Message Buffer Link */
|
||||
u8 cfm; /* Common FIFO Mode */
|
||||
u8 cfdc; /* Common FIFO Depth Configuration */
|
||||
};
|
||||
|
||||
struct rcar_canfd_hw_info {
|
||||
const struct can_bittiming_const *nom_bittiming;
|
||||
const struct can_bittiming_const *data_bittiming;
|
||||
const struct rcar_canfd_regs *regs;
|
||||
const struct rcar_canfd_shift_data *sh;
|
||||
u8 rnc_field_width;
|
||||
u8 max_aflpn;
|
||||
u8 max_cftml;
|
||||
u8 max_channels;
|
||||
u8 postdiv;
|
||||
/* hardware features */
|
||||
unsigned shared_global_irqs:1; /* Has shared global irqs */
|
||||
unsigned multi_channel_irqs:1; /* Has multiple channel irqs */
|
||||
unsigned ch_interface_mode:1; /* Has channel interface mode */
|
||||
unsigned shared_can_regs:1; /* Has shared classical can registers */
|
||||
unsigned external_clk:1; /* Has external clock */
|
||||
};
|
||||
|
||||
/* Channel priv data */
|
||||
|
@ -548,7 +574,7 @@ struct rcar_canfd_global {
|
|||
};
|
||||
|
||||
/* CAN FD mode nominal rate constants */
|
||||
static const struct can_bittiming_const rcar_canfd_nom_bittiming_const = {
|
||||
static const struct can_bittiming_const rcar_canfd_gen3_nom_bittiming_const = {
|
||||
.name = RCANFD_DRV_NAME,
|
||||
.tseg1_min = 2,
|
||||
.tseg1_max = 128,
|
||||
|
@ -560,8 +586,20 @@ static const struct can_bittiming_const rcar_canfd_nom_bittiming_const = {
|
|||
.brp_inc = 1,
|
||||
};
|
||||
|
||||
static const struct can_bittiming_const rcar_canfd_gen4_nom_bittiming_const = {
|
||||
.name = RCANFD_DRV_NAME,
|
||||
.tseg1_min = 2,
|
||||
.tseg1_max = 256,
|
||||
.tseg2_min = 2,
|
||||
.tseg2_max = 128,
|
||||
.sjw_max = 128,
|
||||
.brp_min = 1,
|
||||
.brp_max = 1024,
|
||||
.brp_inc = 1,
|
||||
};
|
||||
|
||||
/* CAN FD mode data rate constants */
|
||||
static const struct can_bittiming_const rcar_canfd_data_bittiming_const = {
|
||||
static const struct can_bittiming_const rcar_canfd_gen3_data_bittiming_const = {
|
||||
.name = RCANFD_DRV_NAME,
|
||||
.tseg1_min = 2,
|
||||
.tseg1_max = 16,
|
||||
|
@ -573,6 +611,18 @@ static const struct can_bittiming_const rcar_canfd_data_bittiming_const = {
|
|||
.brp_inc = 1,
|
||||
};
|
||||
|
||||
static const struct can_bittiming_const rcar_canfd_gen4_data_bittiming_const = {
|
||||
.name = RCANFD_DRV_NAME,
|
||||
.tseg1_min = 2,
|
||||
.tseg1_max = 32,
|
||||
.tseg2_min = 2,
|
||||
.tseg2_max = 16,
|
||||
.sjw_max = 16,
|
||||
.brp_min = 1,
|
||||
.brp_max = 256,
|
||||
.brp_inc = 1,
|
||||
};
|
||||
|
||||
/* Classical CAN mode bitrate constants */
|
||||
static const struct can_bittiming_const rcar_canfd_bittiming_const = {
|
||||
.name = RCANFD_DRV_NAME,
|
||||
|
@ -586,36 +636,113 @@ static const struct can_bittiming_const rcar_canfd_bittiming_const = {
|
|||
.brp_inc = 1,
|
||||
};
|
||||
|
||||
static const struct rcar_canfd_regs rcar_gen3_regs = {
|
||||
.rfcc = 0x00b8,
|
||||
.cfcc = 0x0118,
|
||||
.cfsts = 0x0178,
|
||||
.cfpctr = 0x01d8,
|
||||
.f_dcfg = 0x0500,
|
||||
.rfoffset = 0x3000,
|
||||
.cfoffset = 0x3400,
|
||||
};
|
||||
|
||||
static const struct rcar_canfd_regs rcar_gen4_regs = {
|
||||
.rfcc = 0x00c0,
|
||||
.cfcc = 0x0120,
|
||||
.cfsts = 0x01e0,
|
||||
.cfpctr = 0x0240,
|
||||
.f_dcfg = 0x1400,
|
||||
.rfoffset = 0x6000,
|
||||
.cfoffset = 0x6400,
|
||||
};
|
||||
|
||||
static const struct rcar_canfd_shift_data rcar_gen3_shift_data = {
|
||||
.ntseg2 = 24,
|
||||
.ntseg1 = 16,
|
||||
.nsjw = 11,
|
||||
.dtseg2 = 20,
|
||||
.dtseg1 = 16,
|
||||
.cftml = 20,
|
||||
.cfm = 16,
|
||||
.cfdc = 8,
|
||||
};
|
||||
|
||||
static const struct rcar_canfd_shift_data rcar_gen4_shift_data = {
|
||||
.ntseg2 = 25,
|
||||
.ntseg1 = 17,
|
||||
.nsjw = 10,
|
||||
.dtseg2 = 16,
|
||||
.dtseg1 = 8,
|
||||
.cftml = 16,
|
||||
.cfm = 8,
|
||||
.cfdc = 21,
|
||||
};
|
||||
|
||||
static const struct rcar_canfd_hw_info rcar_gen3_hw_info = {
|
||||
.nom_bittiming = &rcar_canfd_gen3_nom_bittiming_const,
|
||||
.data_bittiming = &rcar_canfd_gen3_data_bittiming_const,
|
||||
.regs = &rcar_gen3_regs,
|
||||
.sh = &rcar_gen3_shift_data,
|
||||
.rnc_field_width = 8,
|
||||
.max_aflpn = 31,
|
||||
.max_cftml = 15,
|
||||
.max_channels = 2,
|
||||
.postdiv = 2,
|
||||
.shared_global_irqs = 1,
|
||||
.ch_interface_mode = 0,
|
||||
.shared_can_regs = 0,
|
||||
.external_clk = 1,
|
||||
};
|
||||
|
||||
static const struct rcar_canfd_hw_info rcar_gen4_hw_info = {
|
||||
.nom_bittiming = &rcar_canfd_gen4_nom_bittiming_const,
|
||||
.data_bittiming = &rcar_canfd_gen4_data_bittiming_const,
|
||||
.regs = &rcar_gen4_regs,
|
||||
.sh = &rcar_gen4_shift_data,
|
||||
.rnc_field_width = 16,
|
||||
.max_aflpn = 127,
|
||||
.max_cftml = 31,
|
||||
.max_channels = 8,
|
||||
.postdiv = 2,
|
||||
.shared_global_irqs = 1,
|
||||
.ch_interface_mode = 1,
|
||||
.shared_can_regs = 1,
|
||||
.external_clk = 1,
|
||||
};
|
||||
|
||||
static const struct rcar_canfd_hw_info rzg2l_hw_info = {
|
||||
.nom_bittiming = &rcar_canfd_gen3_nom_bittiming_const,
|
||||
.data_bittiming = &rcar_canfd_gen3_data_bittiming_const,
|
||||
.regs = &rcar_gen3_regs,
|
||||
.sh = &rcar_gen3_shift_data,
|
||||
.rnc_field_width = 8,
|
||||
.max_aflpn = 31,
|
||||
.max_cftml = 15,
|
||||
.max_channels = 2,
|
||||
.postdiv = 1,
|
||||
.multi_channel_irqs = 1,
|
||||
.ch_interface_mode = 0,
|
||||
.shared_can_regs = 0,
|
||||
.external_clk = 1,
|
||||
};
|
||||
|
||||
static const struct rcar_canfd_hw_info r9a09g047_hw_info = {
|
||||
.nom_bittiming = &rcar_canfd_gen4_nom_bittiming_const,
|
||||
.data_bittiming = &rcar_canfd_gen4_data_bittiming_const,
|
||||
.regs = &rcar_gen4_regs,
|
||||
.sh = &rcar_gen4_shift_data,
|
||||
.rnc_field_width = 16,
|
||||
.max_aflpn = 63,
|
||||
.max_cftml = 31,
|
||||
.max_channels = 6,
|
||||
.postdiv = 1,
|
||||
.multi_channel_irqs = 1,
|
||||
.ch_interface_mode = 1,
|
||||
.shared_can_regs = 1,
|
||||
.external_clk = 0,
|
||||
};
|
||||
|
||||
/* Helper functions */
|
||||
static inline bool is_gen4(struct rcar_canfd_global *gpriv)
|
||||
{
|
||||
return gpriv->info == &rcar_gen4_hw_info;
|
||||
}
|
||||
|
||||
static inline u32 reg_gen4(struct rcar_canfd_global *gpriv,
|
||||
u32 gen4, u32 not_gen4)
|
||||
{
|
||||
return is_gen4(gpriv) ? gen4 : not_gen4;
|
||||
}
|
||||
|
||||
static inline void rcar_canfd_update(u32 mask, u32 val, u32 __iomem *reg)
|
||||
{
|
||||
u32 data = readl(reg);
|
||||
|
@ -681,9 +808,20 @@ static void rcar_canfd_tx_failure_cleanup(struct net_device *ndev)
|
|||
can_free_echo_skb(ndev, i, NULL);
|
||||
}
|
||||
|
||||
static void rcar_canfd_setrnc(struct rcar_canfd_global *gpriv, unsigned int ch,
|
||||
unsigned int num_rules)
|
||||
{
|
||||
unsigned int rnc_stride = 32 / gpriv->info->rnc_field_width;
|
||||
unsigned int shift = 32 - (ch % rnc_stride + 1) * gpriv->info->rnc_field_width;
|
||||
unsigned int w = ch / rnc_stride;
|
||||
u32 rnc = num_rules << shift;
|
||||
|
||||
rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLCFG(w), rnc);
|
||||
}
|
||||
|
||||
static void rcar_canfd_set_mode(struct rcar_canfd_global *gpriv)
|
||||
{
|
||||
if (is_gen4(gpriv)) {
|
||||
if (gpriv->info->ch_interface_mode) {
|
||||
u32 ch, val = gpriv->fdmode ? RCANFD_GEN4_FDCFG_FDOE
|
||||
: RCANFD_GEN4_FDCFG_CLOE;
|
||||
|
||||
|
@ -789,7 +927,7 @@ static void rcar_canfd_configure_controller(struct rcar_canfd_global *gpriv)
|
|||
static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv,
|
||||
u32 ch, u32 rule_entry)
|
||||
{
|
||||
int offset, page, num_rules = RCANFD_CHANNEL_NUMRULES;
|
||||
unsigned int offset, page, num_rules = RCANFD_CHANNEL_NUMRULES;
|
||||
u32 rule_entry_index = rule_entry % 16;
|
||||
u32 ridx = ch + RCANFD_RFFIFO_IDX;
|
||||
|
||||
|
@ -800,9 +938,8 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv,
|
|||
RCANFD_GAFLECTR_AFLDAE));
|
||||
|
||||
/* Write number of rules for channel */
|
||||
rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLCFG(ch),
|
||||
RCANFD_GAFLCFG_SETRNC(gpriv, ch, num_rules));
|
||||
if (is_gen4(gpriv))
|
||||
rcar_canfd_setrnc(gpriv, ch, num_rules);
|
||||
if (gpriv->info->shared_can_regs)
|
||||
offset = RCANFD_GEN4_GAFL_OFFSET;
|
||||
else if (gpriv->fdmode)
|
||||
offset = RCANFD_F_GAFL_OFFSET;
|
||||
|
@ -942,7 +1079,7 @@ static void rcar_canfd_global_error(struct net_device *ndev)
|
|||
u32 ridx = ch + RCANFD_RFFIFO_IDX;
|
||||
|
||||
gerfl = rcar_canfd_read(priv->base, RCANFD_GERFL);
|
||||
if (gerfl & RCANFD_GERFL_EEF(ch)) {
|
||||
if (gerfl & FIELD_PREP(RCANFD_GERFL_EEF, BIT(ch))) {
|
||||
netdev_dbg(ndev, "Ch%u: ECC Error flag\n", ch);
|
||||
stats->tx_dropped++;
|
||||
}
|
||||
|
@ -1304,7 +1441,7 @@ static void rcar_canfd_set_bittiming(struct net_device *dev)
|
|||
struct rcar_canfd_channel *priv = netdev_priv(dev);
|
||||
struct rcar_canfd_global *gpriv = priv->gpriv;
|
||||
const struct can_bittiming *bt = &priv->can.bittiming;
|
||||
const struct can_bittiming *dbt = &priv->can.data_bittiming;
|
||||
const struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
|
||||
u16 brp, sjw, tseg1, tseg2;
|
||||
u32 cfg;
|
||||
u32 ch = priv->channel;
|
||||
|
@ -1338,7 +1475,7 @@ static void rcar_canfd_set_bittiming(struct net_device *dev)
|
|||
brp, sjw, tseg1, tseg2);
|
||||
} else {
|
||||
/* Classical CAN only mode */
|
||||
if (is_gen4(gpriv)) {
|
||||
if (gpriv->info->shared_can_regs) {
|
||||
cfg = (RCANFD_NCFG_NTSEG1(gpriv, tseg1) |
|
||||
RCANFD_NCFG_NBRP(brp) |
|
||||
RCANFD_NCFG_NSJW(gpriv, sjw) |
|
||||
|
@ -1503,7 +1640,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb,
|
|||
|
||||
dlc = RCANFD_CFPTR_CFDLC(can_fd_len2dlc(cf->len));
|
||||
|
||||
if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) || is_gen4(gpriv)) {
|
||||
if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) || gpriv->info->shared_can_regs) {
|
||||
rcar_canfd_write(priv->base,
|
||||
RCANFD_F_CFID(gpriv, ch, RCANFD_CFFIFO_IDX), id);
|
||||
rcar_canfd_write(priv->base,
|
||||
|
@ -1562,7 +1699,7 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv)
|
|||
u32 ch = priv->channel;
|
||||
u32 ridx = ch + RCANFD_RFFIFO_IDX;
|
||||
|
||||
if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) || is_gen4(gpriv)) {
|
||||
if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) || gpriv->info->shared_can_regs) {
|
||||
id = rcar_canfd_read(priv->base, RCANFD_F_RFID(gpriv, ridx));
|
||||
dlc = rcar_canfd_read(priv->base, RCANFD_F_RFPTR(gpriv, ridx));
|
||||
|
||||
|
@ -1613,7 +1750,7 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv)
|
|||
cf->len = can_cc_dlc2len(RCANFD_RFPTR_RFDLC(dlc));
|
||||
if (id & RCANFD_RFID_RFRTR)
|
||||
cf->can_id |= CAN_RTR_FLAG;
|
||||
else if (is_gen4(gpriv))
|
||||
else if (gpriv->info->shared_can_regs)
|
||||
rcar_canfd_get_data(priv, cf, RCANFD_F_RFDF(gpriv, ridx, 0));
|
||||
else
|
||||
rcar_canfd_get_data(priv, cf, RCANFD_C_RFDF(ridx, 0));
|
||||
|
@ -1736,16 +1873,19 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
|
|||
|
||||
if (info->multi_channel_irqs) {
|
||||
char *irq_name;
|
||||
char name[10];
|
||||
int err_irq;
|
||||
int tx_irq;
|
||||
|
||||
err_irq = platform_get_irq_byname(pdev, ch == 0 ? "ch0_err" : "ch1_err");
|
||||
scnprintf(name, sizeof(name), "ch%u_err", ch);
|
||||
err_irq = platform_get_irq_byname(pdev, name);
|
||||
if (err_irq < 0) {
|
||||
err = err_irq;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
tx_irq = platform_get_irq_byname(pdev, ch == 0 ? "ch0_trx" : "ch1_trx");
|
||||
scnprintf(name, sizeof(name), "ch%u_trx", ch);
|
||||
tx_irq = platform_get_irq_byname(pdev, name);
|
||||
if (tx_irq < 0) {
|
||||
err = tx_irq;
|
||||
goto fail;
|
||||
|
@ -1782,9 +1922,8 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
|
|||
}
|
||||
|
||||
if (gpriv->fdmode) {
|
||||
priv->can.bittiming_const = &rcar_canfd_nom_bittiming_const;
|
||||
priv->can.data_bittiming_const =
|
||||
&rcar_canfd_data_bittiming_const;
|
||||
priv->can.bittiming_const = gpriv->info->nom_bittiming;
|
||||
priv->can.fd.data_bittiming_const = gpriv->info->data_bittiming;
|
||||
|
||||
/* Controller starts in CAN FD only mode */
|
||||
err = can_set_static_ctrlmode(ndev, CAN_CTRLMODE_FD);
|
||||
|
@ -1846,6 +1985,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)
|
|||
u32 rule_entry = 0;
|
||||
bool fdmode = true; /* CAN FD only mode - default */
|
||||
char name[9] = "channelX";
|
||||
struct clk *clk_ram;
|
||||
int i;
|
||||
|
||||
info = of_device_get_match_data(dev);
|
||||
|
@ -1855,13 +1995,13 @@ static int rcar_canfd_probe(struct platform_device *pdev)
|
|||
|
||||
for (i = 0; i < info->max_channels; ++i) {
|
||||
name[7] = '0' + i;
|
||||
of_child = of_get_child_by_name(dev->of_node, name);
|
||||
if (of_child && of_device_is_available(of_child)) {
|
||||
of_child = of_get_available_child_by_name(dev->of_node, name);
|
||||
if (of_child) {
|
||||
channels_mask |= BIT(i);
|
||||
transceivers[i] = devm_of_phy_optional_get(dev,
|
||||
of_child, NULL);
|
||||
of_node_put(of_child);
|
||||
}
|
||||
of_node_put(of_child);
|
||||
if (IS_ERR(transceivers[i]))
|
||||
return PTR_ERR(transceivers[i]);
|
||||
}
|
||||
|
@ -1932,9 +2072,14 @@ static int rcar_canfd_probe(struct platform_device *pdev)
|
|||
fcan_freq = clk_get_rate(gpriv->can_clk) / info->postdiv;
|
||||
} else {
|
||||
fcan_freq = clk_get_rate(gpriv->can_clk);
|
||||
gpriv->extclk = true;
|
||||
gpriv->extclk = gpriv->info->external_clk;
|
||||
}
|
||||
|
||||
clk_ram = devm_clk_get_optional_enabled(dev, "ram_clk");
|
||||
if (IS_ERR(clk_ram))
|
||||
return dev_err_probe(dev, PTR_ERR(clk_ram),
|
||||
"cannot get enabled ram clock\n");
|
||||
|
||||
addr = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(addr)) {
|
||||
err = PTR_ERR(addr);
|
||||
|
@ -2097,6 +2242,7 @@ static SIMPLE_DEV_PM_OPS(rcar_canfd_pm_ops, rcar_canfd_suspend,
|
|||
|
||||
static const __maybe_unused struct of_device_id rcar_canfd_of_table[] = {
|
||||
{ .compatible = "renesas,r8a779a0-canfd", .data = &rcar_gen4_hw_info },
|
||||
{ .compatible = "renesas,r9a09g047-canfd", .data = &r9a09g047_hw_info },
|
||||
{ .compatible = "renesas,rcar-gen3-canfd", .data = &rcar_gen3_hw_info },
|
||||
{ .compatible = "renesas,rcar-gen4-canfd", .data = &rcar_gen4_hw_info },
|
||||
{ .compatible = "renesas,rzg2l-canfd", .data = &rzg2l_hw_info },
|
||||
|
|
|
@ -118,7 +118,7 @@ static void rkcanfd_chip_set_work_mode(const struct rkcanfd_priv *priv)
|
|||
|
||||
static int rkcanfd_set_bittiming(struct rkcanfd_priv *priv)
|
||||
{
|
||||
const struct can_bittiming *dbt = &priv->can.data_bittiming;
|
||||
const struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
|
||||
const struct can_bittiming *bt = &priv->can.bittiming;
|
||||
u32 reg_nbt, reg_dbt, reg_tdc;
|
||||
u32 tdco;
|
||||
|
@ -899,7 +899,7 @@ static int rkcanfd_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, priv);
|
||||
priv->can.clock.freq = clk_get_rate(priv->clks[0].clk);
|
||||
priv->can.bittiming_const = &rkcanfd_bittiming_const;
|
||||
priv->can.data_bittiming_const = &rkcanfd_data_bittiming_const;
|
||||
priv->can.fd.data_bittiming_const = &rkcanfd_data_bittiming_const;
|
||||
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
|
||||
CAN_CTRLMODE_BERR_REPORTING;
|
||||
priv->can.do_set_mode = rkcanfd_set_mode;
|
||||
|
|
|
@ -39,7 +39,7 @@ static void rkcanfd_timestamp_work(struct work_struct *work)
|
|||
|
||||
void rkcanfd_timestamp_init(struct rkcanfd_priv *priv)
|
||||
{
|
||||
const struct can_bittiming *dbt = &priv->can.data_bittiming;
|
||||
const struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
|
||||
const struct can_bittiming *bt = &priv->can.bittiming;
|
||||
struct cyclecounter *cc = &priv->cc;
|
||||
u32 bitrate, div, reg, rate;
|
||||
|
|
|
@ -527,7 +527,7 @@ static int mcp251xfd_chip_timestamp_init(const struct mcp251xfd_priv *priv)
|
|||
static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv)
|
||||
{
|
||||
const struct can_bittiming *bt = &priv->can.bittiming;
|
||||
const struct can_bittiming *dbt = &priv->can.data_bittiming;
|
||||
const struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
|
||||
u32 tdcmod, val = 0;
|
||||
int err;
|
||||
|
||||
|
@ -600,8 +600,8 @@ static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv)
|
|||
tdcmod = MCP251XFD_REG_TDC_TDCMOD_DISABLED;
|
||||
|
||||
val = FIELD_PREP(MCP251XFD_REG_TDC_TDCMOD_MASK, tdcmod) |
|
||||
FIELD_PREP(MCP251XFD_REG_TDC_TDCV_MASK, priv->can.tdc.tdcv) |
|
||||
FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, priv->can.tdc.tdco);
|
||||
FIELD_PREP(MCP251XFD_REG_TDC_TDCV_MASK, priv->can.fd.tdc.tdcv) |
|
||||
FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, priv->can.fd.tdc.tdco);
|
||||
|
||||
return regmap_write(priv->map_reg, MCP251XFD_REG_TDC, val);
|
||||
}
|
||||
|
@ -2104,8 +2104,8 @@ static int mcp251xfd_probe(struct spi_device *spi)
|
|||
priv->can.do_set_mode = mcp251xfd_set_mode;
|
||||
priv->can.do_get_berr_counter = mcp251xfd_get_berr_counter;
|
||||
priv->can.bittiming_const = &mcp251xfd_bittiming_const;
|
||||
priv->can.data_bittiming_const = &mcp251xfd_data_bittiming_const;
|
||||
priv->can.tdc_const = &mcp251xfd_tdc_const;
|
||||
priv->can.fd.data_bittiming_const = &mcp251xfd_data_bittiming_const;
|
||||
priv->can.fd.tdc_const = &mcp251xfd_tdc_const;
|
||||
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
|
||||
CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING |
|
||||
CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO |
|
||||
|
|
|
@ -1098,7 +1098,7 @@ static int esd_usb_3_set_bittiming(struct net_device *netdev)
|
|||
const struct can_bittiming_const *data_btc = &esd_usb_3_data_bittiming_const;
|
||||
struct esd_usb_net_priv *priv = netdev_priv(netdev);
|
||||
struct can_bittiming *nom_bt = &priv->can.bittiming;
|
||||
struct can_bittiming *data_bt = &priv->can.data_bittiming;
|
||||
struct can_bittiming *data_bt = &priv->can.fd.data_bittiming;
|
||||
struct esd_usb_3_set_baudrate_msg_x *baud_x;
|
||||
union esd_usb_msg *msg;
|
||||
u16 flags = 0;
|
||||
|
@ -1218,9 +1218,9 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index)
|
|||
priv->can.clock.freq = ESD_USB_3_CAN_CLOCK;
|
||||
priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
|
||||
priv->can.bittiming_const = &esd_usb_3_nom_bittiming_const;
|
||||
priv->can.data_bittiming_const = &esd_usb_3_data_bittiming_const;
|
||||
priv->can.fd.data_bittiming_const = &esd_usb_3_data_bittiming_const;
|
||||
priv->can.do_set_bittiming = esd_usb_3_set_bittiming;
|
||||
priv->can.do_set_data_bittiming = esd_usb_3_set_bittiming;
|
||||
priv->can.fd.do_set_data_bittiming = esd_usb_3_set_bittiming;
|
||||
break;
|
||||
|
||||
case ESD_USB_CANUSBM_PRODUCT_ID:
|
||||
|
|
|
@ -2059,8 +2059,8 @@ static int es58x_init_priv(struct es58x_device *es58x_dev,
|
|||
|
||||
can->bittiming_const = param->bittiming_const;
|
||||
if (param->ctrlmode_supported & CAN_CTRLMODE_FD) {
|
||||
can->data_bittiming_const = param->data_bittiming_const;
|
||||
can->tdc_const = param->tdc_const;
|
||||
can->fd.data_bittiming_const = param->data_bittiming_const;
|
||||
can->fd.tdc_const = param->tdc_const;
|
||||
}
|
||||
can->bitrate_max = param->bitrate_max;
|
||||
can->clock = param->clock;
|
||||
|
|
|
@ -427,12 +427,12 @@ static int es58x_fd_enable_channel(struct es58x_priv *priv)
|
|||
|
||||
if (tx_conf_msg.canfd_enabled) {
|
||||
es58x_fd_convert_bittiming(&tx_conf_msg.data_bittiming,
|
||||
&priv->can.data_bittiming);
|
||||
&priv->can.fd.data_bittiming);
|
||||
|
||||
if (can_tdc_is_enabled(&priv->can)) {
|
||||
tx_conf_msg.tdc_enabled = 1;
|
||||
tx_conf_msg.tdco = cpu_to_le16(priv->can.tdc.tdco);
|
||||
tx_conf_msg.tdcf = cpu_to_le16(priv->can.tdc.tdcf);
|
||||
tx_conf_msg.tdco = cpu_to_le16(priv->can.fd.tdc.tdco);
|
||||
tx_conf_msg.tdcf = cpu_to_le16(priv->can.fd.tdc.tdcf);
|
||||
}
|
||||
|
||||
conf_len = ES58X_FD_CANFD_CONF_LEN;
|
||||
|
|
|
@ -728,7 +728,7 @@ static int gs_usb_set_bittiming(struct net_device *netdev)
|
|||
static int gs_usb_set_data_bittiming(struct net_device *netdev)
|
||||
{
|
||||
struct gs_can *dev = netdev_priv(netdev);
|
||||
struct can_bittiming *bt = &dev->can.data_bittiming;
|
||||
struct can_bittiming *bt = &dev->can.fd.data_bittiming;
|
||||
struct gs_device_bittiming dbt = {
|
||||
.prop_seg = cpu_to_le32(bt->prop_seg),
|
||||
.phase_seg1 = cpu_to_le32(bt->phase_seg1),
|
||||
|
@ -1300,8 +1300,8 @@ static struct gs_can *gs_make_candev(unsigned int channel,
|
|||
/* The data bit timing will be overwritten, if
|
||||
* GS_CAN_FEATURE_BT_CONST_EXT is set.
|
||||
*/
|
||||
dev->can.data_bittiming_const = &dev->bt_const;
|
||||
dev->can.do_set_data_bittiming = gs_usb_set_data_bittiming;
|
||||
dev->can.fd.data_bittiming_const = &dev->bt_const;
|
||||
dev->can.fd.do_set_data_bittiming = gs_usb_set_data_bittiming;
|
||||
}
|
||||
|
||||
if (feature & GS_CAN_FEATURE_TERMINATION) {
|
||||
|
@ -1381,7 +1381,7 @@ static struct gs_can *gs_make_candev(unsigned int channel,
|
|||
dev->data_bt_const.brp_max = le32_to_cpu(bt_const_extended.dbrp_max);
|
||||
dev->data_bt_const.brp_inc = le32_to_cpu(bt_const_extended.dbrp_inc);
|
||||
|
||||
dev->can.data_bittiming_const = &dev->data_bt_const;
|
||||
dev->can.fd.data_bittiming_const = &dev->data_bt_const;
|
||||
}
|
||||
|
||||
can_rx_offload_add_manual(netdev, &dev->offload, GS_NAPI_WEIGHT);
|
||||
|
|
|
@ -137,7 +137,7 @@ struct kvaser_usb_net_priv {
|
|||
* @dev_set_mode: used for can.do_set_mode
|
||||
* @dev_set_bittiming: used for can.do_set_bittiming
|
||||
* @dev_get_busparams: readback arbitration busparams
|
||||
* @dev_set_data_bittiming: used for can.do_set_data_bittiming
|
||||
* @dev_set_data_bittiming: used for can.fd.do_set_data_bittiming
|
||||
* @dev_get_data_busparams: readback data busparams
|
||||
* @dev_get_berr_counter: used for can.do_get_berr_counter
|
||||
*
|
||||
|
|
|
@ -592,7 +592,7 @@ static int kvaser_usb_set_data_bittiming(struct net_device *netdev)
|
|||
struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
|
||||
struct kvaser_usb *dev = priv->dev;
|
||||
const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
|
||||
struct can_bittiming *dbt = &priv->can.data_bittiming;
|
||||
struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
|
||||
struct kvaser_usb_busparams busparams;
|
||||
int tseg1 = dbt->prop_seg + dbt->phase_seg1;
|
||||
int tseg2 = dbt->phase_seg2;
|
||||
|
@ -842,8 +842,8 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
|
|||
priv->can.ctrlmode_supported |= dev->card_data.ctrlmode_supported;
|
||||
|
||||
if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) {
|
||||
priv->can.data_bittiming_const = dev->cfg->data_bittiming_const;
|
||||
priv->can.do_set_data_bittiming = kvaser_usb_set_data_bittiming;
|
||||
priv->can.fd.data_bittiming_const = dev->cfg->data_bittiming_const;
|
||||
priv->can.fd.do_set_data_bittiming = kvaser_usb_set_data_bittiming;
|
||||
}
|
||||
|
||||
netdev->flags |= IFF_ECHO;
|
||||
|
|
|
@ -770,7 +770,7 @@ static int peak_usb_set_data_bittiming(struct net_device *netdev)
|
|||
const struct peak_usb_adapter *pa = dev->adapter;
|
||||
|
||||
if (pa->dev_set_data_bittiming) {
|
||||
struct can_bittiming *bt = &dev->can.data_bittiming;
|
||||
struct can_bittiming *bt = &dev->can.fd.data_bittiming;
|
||||
int err = pa->dev_set_data_bittiming(dev, bt);
|
||||
|
||||
if (err)
|
||||
|
@ -954,8 +954,8 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter,
|
|||
dev->can.clock = peak_usb_adapter->clock;
|
||||
dev->can.bittiming_const = peak_usb_adapter->bittiming_const;
|
||||
dev->can.do_set_bittiming = peak_usb_set_bittiming;
|
||||
dev->can.data_bittiming_const = peak_usb_adapter->data_bittiming_const;
|
||||
dev->can.do_set_data_bittiming = peak_usb_set_data_bittiming;
|
||||
dev->can.fd.data_bittiming_const = peak_usb_adapter->data_bittiming_const;
|
||||
dev->can.fd.do_set_data_bittiming = peak_usb_set_data_bittiming;
|
||||
dev->can.do_set_mode = peak_usb_set_mode;
|
||||
dev->can.do_get_berr_counter = peak_usb_adapter->do_get_berr_counter;
|
||||
dev->can.ctrlmode_supported = peak_usb_adapter->ctrlmode_supported;
|
||||
|
|
|
@ -481,7 +481,7 @@ static int xcan_set_bittiming(struct net_device *ndev)
|
|||
{
|
||||
struct xcan_priv *priv = netdev_priv(ndev);
|
||||
struct can_bittiming *bt = &priv->can.bittiming;
|
||||
struct can_bittiming *dbt = &priv->can.data_bittiming;
|
||||
struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
|
||||
u32 btr0, btr1;
|
||||
u32 is_config_mode;
|
||||
|
||||
|
@ -517,10 +517,10 @@ static int xcan_set_bittiming(struct net_device *ndev)
|
|||
btr0 = dbt->brp - 1;
|
||||
if (can_tdc_is_enabled(&priv->can)) {
|
||||
if (priv->devtype.cantype == XAXI_CANFD)
|
||||
btr0 |= FIELD_PREP(XCAN_BRPR_TDCO_MASK, priv->can.tdc.tdco) |
|
||||
btr0 |= FIELD_PREP(XCAN_BRPR_TDCO_MASK, priv->can.fd.tdc.tdco) |
|
||||
XCAN_BRPR_TDC_ENABLE;
|
||||
else
|
||||
btr0 |= FIELD_PREP(XCAN_2_BRPR_TDCO_MASK, priv->can.tdc.tdco) |
|
||||
btr0 |= FIELD_PREP(XCAN_2_BRPR_TDCO_MASK, priv->can.fd.tdc.tdco) |
|
||||
XCAN_BRPR_TDC_ENABLE;
|
||||
}
|
||||
|
||||
|
@ -1967,22 +1967,22 @@ static int xcan_probe(struct platform_device *pdev)
|
|||
goto err_free;
|
||||
|
||||
if (devtype->cantype == XAXI_CANFD) {
|
||||
priv->can.data_bittiming_const =
|
||||
priv->can.fd.data_bittiming_const =
|
||||
&xcan_data_bittiming_const_canfd;
|
||||
priv->can.tdc_const = &xcan_tdc_const_canfd;
|
||||
priv->can.fd.tdc_const = &xcan_tdc_const_canfd;
|
||||
}
|
||||
|
||||
if (devtype->cantype == XAXI_CANFD_2_0) {
|
||||
priv->can.data_bittiming_const =
|
||||
priv->can.fd.data_bittiming_const =
|
||||
&xcan_data_bittiming_const_canfd2;
|
||||
priv->can.tdc_const = &xcan_tdc_const_canfd2;
|
||||
priv->can.fd.tdc_const = &xcan_tdc_const_canfd2;
|
||||
}
|
||||
|
||||
if (devtype->cantype == XAXI_CANFD ||
|
||||
devtype->cantype == XAXI_CANFD_2_0) {
|
||||
priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD |
|
||||
CAN_CTRLMODE_TDC_AUTO;
|
||||
priv->can.do_get_auto_tdcv = xcan_get_auto_tdcv;
|
||||
priv->can.fd.do_get_auto_tdcv = xcan_get_auto_tdcv;
|
||||
}
|
||||
|
||||
priv->reg_base = addr;
|
||||
|
|
|
@ -38,6 +38,17 @@ enum can_termination_gpio {
|
|||
CAN_TERMINATION_GPIO_MAX,
|
||||
};
|
||||
|
||||
struct data_bittiming_params {
|
||||
const struct can_bittiming_const *data_bittiming_const;
|
||||
struct can_bittiming data_bittiming;
|
||||
const struct can_tdc_const *tdc_const;
|
||||
struct can_tdc tdc;
|
||||
const u32 *data_bitrate_const;
|
||||
unsigned int data_bitrate_const_cnt;
|
||||
int (*do_set_data_bittiming)(struct net_device *dev);
|
||||
int (*do_get_auto_tdcv)(const struct net_device *dev, u32 *tdcv);
|
||||
};
|
||||
|
||||
/*
|
||||
* CAN common private data
|
||||
*/
|
||||
|
@ -45,16 +56,11 @@ struct can_priv {
|
|||
struct net_device *dev;
|
||||
struct can_device_stats can_stats;
|
||||
|
||||
const struct can_bittiming_const *bittiming_const,
|
||||
*data_bittiming_const;
|
||||
struct can_bittiming bittiming, data_bittiming;
|
||||
const struct can_tdc_const *tdc_const;
|
||||
struct can_tdc tdc;
|
||||
|
||||
const struct can_bittiming_const *bittiming_const;
|
||||
struct can_bittiming bittiming;
|
||||
struct data_bittiming_params fd;
|
||||
unsigned int bitrate_const_cnt;
|
||||
const u32 *bitrate_const;
|
||||
const u32 *data_bitrate_const;
|
||||
unsigned int data_bitrate_const_cnt;
|
||||
u32 bitrate_max;
|
||||
struct can_clock clock;
|
||||
|
||||
|
@ -77,14 +83,12 @@ struct can_priv {
|
|||
struct delayed_work restart_work;
|
||||
|
||||
int (*do_set_bittiming)(struct net_device *dev);
|
||||
int (*do_set_data_bittiming)(struct net_device *dev);
|
||||
int (*do_set_mode)(struct net_device *dev, enum can_mode mode);
|
||||
int (*do_set_termination)(struct net_device *dev, u16 term);
|
||||
int (*do_get_state)(const struct net_device *dev,
|
||||
enum can_state *state);
|
||||
int (*do_get_berr_counter)(const struct net_device *dev,
|
||||
struct can_berr_counter *bec);
|
||||
int (*do_get_auto_tdcv)(const struct net_device *dev, u32 *tdcv);
|
||||
};
|
||||
|
||||
static inline bool can_tdc_is_enabled(const struct can_priv *priv)
|
||||
|
@ -114,11 +118,11 @@ static inline bool can_tdc_is_enabled(const struct can_priv *priv)
|
|||
*/
|
||||
static inline s32 can_get_relative_tdco(const struct can_priv *priv)
|
||||
{
|
||||
const struct can_bittiming *dbt = &priv->data_bittiming;
|
||||
const struct can_bittiming *dbt = &priv->fd.data_bittiming;
|
||||
s32 sample_point_in_tc = (CAN_SYNC_SEG + dbt->prop_seg +
|
||||
dbt->phase_seg1) * dbt->brp;
|
||||
|
||||
return (s32)priv->tdc.tdco - sample_point_in_tc;
|
||||
return (s32)priv->fd.tdc.tdco - sample_point_in_tc;
|
||||
}
|
||||
|
||||
/* helper to define static CAN controller features at device creation time */
|
||||
|
|
|
@ -66,6 +66,7 @@ TARGETS += mseal_system_mappings
|
|||
TARGETS += nci
|
||||
TARGETS += net
|
||||
TARGETS += net/af_unix
|
||||
TARGETS += net/can
|
||||
TARGETS += net/forwarding
|
||||
TARGETS += net/hsr
|
||||
TARGETS += net/mptcp
|
||||
|
|
2
tools/testing/selftests/net/can/.gitignore
vendored
Normal file
2
tools/testing/selftests/net/can/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
test_raw_filter
|
11
tools/testing/selftests/net/can/Makefile
Normal file
11
tools/testing/selftests/net/can/Makefile
Normal file
|
@ -0,0 +1,11 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
top_srcdir = ../../../../..
|
||||
|
||||
CFLAGS += -Wall -Wl,--no-as-needed -O2 -g -I$(top_srcdir)/usr/include $(KHDR_INCLUDES)
|
||||
|
||||
TEST_PROGS := test_raw_filter.sh
|
||||
|
||||
TEST_GEN_FILES := test_raw_filter
|
||||
|
||||
include ../../lib.mk
|
405
tools/testing/selftests/net/can/test_raw_filter.c
Normal file
405
tools/testing/selftests/net/can/test_raw_filter.c
Normal file
|
@ -0,0 +1,405 @@
|
|||
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
|
||||
/*
|
||||
* Copyright (c) 2011 Volkswagen Group Electronic Research
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <net/if.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
#include <linux/can.h>
|
||||
#include <linux/can/raw.h>
|
||||
|
||||
#include "../../kselftest_harness.h"
|
||||
|
||||
#define ID 0x123
|
||||
|
||||
char CANIF[IFNAMSIZ];
|
||||
|
||||
static int send_can_frames(int sock, int testcase)
|
||||
{
|
||||
struct can_frame frame;
|
||||
|
||||
frame.can_dlc = 1;
|
||||
frame.data[0] = testcase;
|
||||
|
||||
frame.can_id = ID;
|
||||
if (write(sock, &frame, sizeof(frame)) < 0)
|
||||
goto write_err;
|
||||
|
||||
frame.can_id = (ID | CAN_RTR_FLAG);
|
||||
if (write(sock, &frame, sizeof(frame)) < 0)
|
||||
goto write_err;
|
||||
|
||||
frame.can_id = (ID | CAN_EFF_FLAG);
|
||||
if (write(sock, &frame, sizeof(frame)) < 0)
|
||||
goto write_err;
|
||||
|
||||
frame.can_id = (ID | CAN_EFF_FLAG | CAN_RTR_FLAG);
|
||||
if (write(sock, &frame, sizeof(frame)) < 0)
|
||||
goto write_err;
|
||||
|
||||
return 0;
|
||||
|
||||
write_err:
|
||||
perror("write");
|
||||
return 1;
|
||||
}
|
||||
|
||||
FIXTURE(can_filters) {
|
||||
int sock;
|
||||
};
|
||||
|
||||
FIXTURE_SETUP(can_filters)
|
||||
{
|
||||
struct sockaddr_can addr;
|
||||
struct ifreq ifr;
|
||||
int recv_own_msgs = 1;
|
||||
int s, ret;
|
||||
|
||||
s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||
ASSERT_GE(s, 0)
|
||||
TH_LOG("failed to create CAN_RAW socket: %d", errno);
|
||||
|
||||
strncpy(ifr.ifr_name, CANIF, sizeof(ifr.ifr_name));
|
||||
ret = ioctl(s, SIOCGIFINDEX, &ifr);
|
||||
ASSERT_GE(ret, 0)
|
||||
TH_LOG("failed SIOCGIFINDEX: %d", errno);
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
|
||||
&recv_own_msgs, sizeof(recv_own_msgs));
|
||||
|
||||
ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
|
||||
ASSERT_EQ(ret, 0)
|
||||
TH_LOG("failed bind socket: %d", errno);
|
||||
|
||||
self->sock = s;
|
||||
}
|
||||
|
||||
FIXTURE_TEARDOWN(can_filters)
|
||||
{
|
||||
close(self->sock);
|
||||
}
|
||||
|
||||
FIXTURE_VARIANT(can_filters) {
|
||||
int testcase;
|
||||
canid_t id;
|
||||
canid_t mask;
|
||||
int exp_num_rx;
|
||||
canid_t exp_flags[];
|
||||
};
|
||||
|
||||
/* Receive all frames when filtering for the ID in standard frame format */
|
||||
FIXTURE_VARIANT_ADD(can_filters, base) {
|
||||
.testcase = 1,
|
||||
.id = ID,
|
||||
.mask = CAN_SFF_MASK,
|
||||
.exp_num_rx = 4,
|
||||
.exp_flags = {
|
||||
0,
|
||||
CAN_RTR_FLAG,
|
||||
CAN_EFF_FLAG,
|
||||
CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* Ignore EFF flag in filter ID if not covered by filter mask */
|
||||
FIXTURE_VARIANT_ADD(can_filters, base_eff) {
|
||||
.testcase = 2,
|
||||
.id = ID | CAN_EFF_FLAG,
|
||||
.mask = CAN_SFF_MASK,
|
||||
.exp_num_rx = 4,
|
||||
.exp_flags = {
|
||||
0,
|
||||
CAN_RTR_FLAG,
|
||||
CAN_EFF_FLAG,
|
||||
CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* Ignore RTR flag in filter ID if not covered by filter mask */
|
||||
FIXTURE_VARIANT_ADD(can_filters, base_rtr) {
|
||||
.testcase = 3,
|
||||
.id = ID | CAN_RTR_FLAG,
|
||||
.mask = CAN_SFF_MASK,
|
||||
.exp_num_rx = 4,
|
||||
.exp_flags = {
|
||||
0,
|
||||
CAN_RTR_FLAG,
|
||||
CAN_EFF_FLAG,
|
||||
CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* Ignore EFF and RTR flags in filter ID if not covered by filter mask */
|
||||
FIXTURE_VARIANT_ADD(can_filters, base_effrtr) {
|
||||
.testcase = 4,
|
||||
.id = ID | CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
.mask = CAN_SFF_MASK,
|
||||
.exp_num_rx = 4,
|
||||
.exp_flags = {
|
||||
0,
|
||||
CAN_RTR_FLAG,
|
||||
CAN_EFF_FLAG,
|
||||
CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* Receive only SFF frames when expecting no EFF flag */
|
||||
FIXTURE_VARIANT_ADD(can_filters, filter_eff) {
|
||||
.testcase = 5,
|
||||
.id = ID,
|
||||
.mask = CAN_SFF_MASK | CAN_EFF_FLAG,
|
||||
.exp_num_rx = 2,
|
||||
.exp_flags = {
|
||||
0,
|
||||
CAN_RTR_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* Receive only EFF frames when filter id and filter mask include EFF flag */
|
||||
FIXTURE_VARIANT_ADD(can_filters, filter_eff_eff) {
|
||||
.testcase = 6,
|
||||
.id = ID | CAN_EFF_FLAG,
|
||||
.mask = CAN_SFF_MASK | CAN_EFF_FLAG,
|
||||
.exp_num_rx = 2,
|
||||
.exp_flags = {
|
||||
CAN_EFF_FLAG,
|
||||
CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* Receive only SFF frames when expecting no EFF flag, ignoring RTR flag */
|
||||
FIXTURE_VARIANT_ADD(can_filters, filter_eff_rtr) {
|
||||
.testcase = 7,
|
||||
.id = ID | CAN_RTR_FLAG,
|
||||
.mask = CAN_SFF_MASK | CAN_EFF_FLAG,
|
||||
.exp_num_rx = 2,
|
||||
.exp_flags = {
|
||||
0,
|
||||
CAN_RTR_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* Receive only EFF frames when filter id and filter mask include EFF flag,
|
||||
* ignoring RTR flag
|
||||
*/
|
||||
FIXTURE_VARIANT_ADD(can_filters, filter_eff_effrtr) {
|
||||
.testcase = 8,
|
||||
.id = ID | CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
.mask = CAN_SFF_MASK | CAN_EFF_FLAG,
|
||||
.exp_num_rx = 2,
|
||||
.exp_flags = {
|
||||
CAN_EFF_FLAG,
|
||||
CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* Receive no remote frames when filtering for no RTR flag */
|
||||
FIXTURE_VARIANT_ADD(can_filters, filter_rtr) {
|
||||
.testcase = 9,
|
||||
.id = ID,
|
||||
.mask = CAN_SFF_MASK | CAN_RTR_FLAG,
|
||||
.exp_num_rx = 2,
|
||||
.exp_flags = {
|
||||
0,
|
||||
CAN_EFF_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* Receive no remote frames when filtering for no RTR flag, ignoring EFF flag */
|
||||
FIXTURE_VARIANT_ADD(can_filters, filter_rtr_eff) {
|
||||
.testcase = 10,
|
||||
.id = ID | CAN_EFF_FLAG,
|
||||
.mask = CAN_SFF_MASK | CAN_RTR_FLAG,
|
||||
.exp_num_rx = 2,
|
||||
.exp_flags = {
|
||||
0,
|
||||
CAN_EFF_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* Receive only remote frames when filter includes RTR flag */
|
||||
FIXTURE_VARIANT_ADD(can_filters, filter_rtr_rtr) {
|
||||
.testcase = 11,
|
||||
.id = ID | CAN_RTR_FLAG,
|
||||
.mask = CAN_SFF_MASK | CAN_RTR_FLAG,
|
||||
.exp_num_rx = 2,
|
||||
.exp_flags = {
|
||||
CAN_RTR_FLAG,
|
||||
CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* Receive only remote frames when filter includes RTR flag, ignoring EFF
|
||||
* flag
|
||||
*/
|
||||
FIXTURE_VARIANT_ADD(can_filters, filter_rtr_effrtr) {
|
||||
.testcase = 12,
|
||||
.id = ID | CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
.mask = CAN_SFF_MASK | CAN_RTR_FLAG,
|
||||
.exp_num_rx = 2,
|
||||
.exp_flags = {
|
||||
CAN_RTR_FLAG,
|
||||
CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* Receive only SFF data frame when filtering for no flags */
|
||||
FIXTURE_VARIANT_ADD(can_filters, filter_effrtr) {
|
||||
.testcase = 13,
|
||||
.id = ID,
|
||||
.mask = CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
.exp_num_rx = 1,
|
||||
.exp_flags = {
|
||||
0,
|
||||
},
|
||||
};
|
||||
|
||||
/* Receive only EFF data frame when filtering for EFF but no RTR flag */
|
||||
FIXTURE_VARIANT_ADD(can_filters, filter_effrtr_eff) {
|
||||
.testcase = 14,
|
||||
.id = ID | CAN_EFF_FLAG,
|
||||
.mask = CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
.exp_num_rx = 1,
|
||||
.exp_flags = {
|
||||
CAN_EFF_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* Receive only SFF remote frame when filtering for RTR but no EFF flag */
|
||||
FIXTURE_VARIANT_ADD(can_filters, filter_effrtr_rtr) {
|
||||
.testcase = 15,
|
||||
.id = ID | CAN_RTR_FLAG,
|
||||
.mask = CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
.exp_num_rx = 1,
|
||||
.exp_flags = {
|
||||
CAN_RTR_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* Receive only EFF remote frame when filtering for EFF and RTR flag */
|
||||
FIXTURE_VARIANT_ADD(can_filters, filter_effrtr_effrtr) {
|
||||
.testcase = 16,
|
||||
.id = ID | CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
.mask = CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
.exp_num_rx = 1,
|
||||
.exp_flags = {
|
||||
CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* Receive only SFF data frame when filtering for no EFF flag and no RTR flag
|
||||
* but based on EFF mask
|
||||
*/
|
||||
FIXTURE_VARIANT_ADD(can_filters, eff) {
|
||||
.testcase = 17,
|
||||
.id = ID,
|
||||
.mask = CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
.exp_num_rx = 1,
|
||||
.exp_flags = {
|
||||
0,
|
||||
},
|
||||
};
|
||||
|
||||
/* Receive only EFF data frame when filtering for EFF flag and no RTR flag but
|
||||
* based on EFF mask
|
||||
*/
|
||||
FIXTURE_VARIANT_ADD(can_filters, eff_eff) {
|
||||
.testcase = 18,
|
||||
.id = ID | CAN_EFF_FLAG,
|
||||
.mask = CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
|
||||
.exp_num_rx = 1,
|
||||
.exp_flags = {
|
||||
CAN_EFF_FLAG,
|
||||
},
|
||||
};
|
||||
|
||||
/* This test verifies that the raw CAN filters work, by checking if only frames
|
||||
* with the expected set of flags are received. For each test case, the given
|
||||
* filter (id and mask) is added and four CAN frames are sent with every
|
||||
* combination of set/unset EFF/RTR flags.
|
||||
*/
|
||||
TEST_F(can_filters, test_filter)
|
||||
{
|
||||
struct can_filter rfilter;
|
||||
int ret;
|
||||
|
||||
rfilter.can_id = variant->id;
|
||||
rfilter.can_mask = variant->mask;
|
||||
setsockopt(self->sock, SOL_CAN_RAW, CAN_RAW_FILTER,
|
||||
&rfilter, sizeof(rfilter));
|
||||
|
||||
TH_LOG("filters: can_id = 0x%08X can_mask = 0x%08X",
|
||||
rfilter.can_id, rfilter.can_mask);
|
||||
|
||||
ret = send_can_frames(self->sock, variant->testcase);
|
||||
ASSERT_EQ(ret, 0)
|
||||
TH_LOG("failed to send CAN frames");
|
||||
|
||||
for (int i = 0; i <= variant->exp_num_rx; i++) {
|
||||
struct can_frame frame;
|
||||
struct timeval tv = {
|
||||
.tv_sec = 0,
|
||||
.tv_usec = 50000, /* 50ms timeout */
|
||||
};
|
||||
fd_set rdfs;
|
||||
|
||||
FD_ZERO(&rdfs);
|
||||
FD_SET(self->sock, &rdfs);
|
||||
|
||||
ret = select(self->sock + 1, &rdfs, NULL, NULL, &tv);
|
||||
ASSERT_GE(ret, 0)
|
||||
TH_LOG("failed select for frame %d, err: %d)", i, errno);
|
||||
|
||||
ret = FD_ISSET(self->sock, &rdfs);
|
||||
if (i == variant->exp_num_rx) {
|
||||
ASSERT_EQ(ret, 0)
|
||||
TH_LOG("too many frames received");
|
||||
} else {
|
||||
ASSERT_NE(ret, 0)
|
||||
TH_LOG("too few frames received");
|
||||
|
||||
ret = read(self->sock, &frame, sizeof(frame));
|
||||
ASSERT_GE(ret, 0)
|
||||
TH_LOG("failed to read frame %d, err: %d", i, errno);
|
||||
|
||||
TH_LOG("rx: can_id = 0x%08X rx = %d", frame.can_id, i);
|
||||
|
||||
ASSERT_EQ(ID, frame.can_id & CAN_SFF_MASK)
|
||||
TH_LOG("received wrong can_id");
|
||||
ASSERT_EQ(variant->testcase, frame.data[0])
|
||||
TH_LOG("received wrong test case");
|
||||
|
||||
ASSERT_EQ(frame.can_id & ~CAN_ERR_MASK,
|
||||
variant->exp_flags[i])
|
||||
TH_LOG("received unexpected flags");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *ifname = getenv("CANIF");
|
||||
|
||||
if (!ifname) {
|
||||
printf("CANIF environment variable must contain the test interface\n");
|
||||
return KSFT_FAIL;
|
||||
}
|
||||
|
||||
strncpy(CANIF, ifname, sizeof(CANIF) - 1);
|
||||
|
||||
return test_harness_run(argc, argv);
|
||||
}
|
45
tools/testing/selftests/net/can/test_raw_filter.sh
Executable file
45
tools/testing/selftests/net/can/test_raw_filter.sh
Executable file
|
@ -0,0 +1,45 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
ALL_TESTS="
|
||||
test_raw_filter
|
||||
"
|
||||
|
||||
net_dir=$(dirname $0)/..
|
||||
source $net_dir/lib.sh
|
||||
|
||||
export CANIF=${CANIF:-"vcan0"}
|
||||
BITRATE=${BITRATE:-500000}
|
||||
|
||||
setup()
|
||||
{
|
||||
if [[ $CANIF == vcan* ]]; then
|
||||
ip link add name $CANIF type vcan || exit $ksft_skip
|
||||
else
|
||||
ip link set dev $CANIF type can bitrate $BITRATE || exit $ksft_skip
|
||||
fi
|
||||
ip link set dev $CANIF up
|
||||
pwd
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
ip link set dev $CANIF down
|
||||
if [[ $CANIF == vcan* ]]; then
|
||||
ip link delete $CANIF
|
||||
fi
|
||||
}
|
||||
|
||||
test_raw_filter()
|
||||
{
|
||||
./test_raw_filter
|
||||
check_err $?
|
||||
log_test "test_raw_filter"
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
setup
|
||||
|
||||
tests_run
|
||||
|
||||
exit $EXIT_STATUS
|
Loading…
Reference in New Issue
Block a user