forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge tag 'linux-can-next-for-5.16-20211024' of git://git.kernel.org/…
…pub/scm/linux/kernel/git/mkl/linux-can-next Marc Kleine-Budde says: ==================== pull-request: can-next 2021-10-24 this is a pull request of 15 patches for net-next/master. The first patch is by Thomas Gleixner and makes use of hrtimer_forward_now() in the CAN broad cast manager (bcm). The next patch is by me and changes the type of the variables used in the CAN bit timing calculation can_fixup_bittiming() to unsigned int. Vincent Mailhol provides 6 patches targeting the CAN device infrastructure. The CAN-FD specific Transmitter Delay Compensation (TDC) is updated and configuration via the CAN netlink interface is added. Qing Wang's patch updates the at91 and janz-ican3 drivers to use sysfs_emit() instead of snprintf() in the sysfs show functions. Geert Uytterhoeven's patch drops the unneeded ARM dependency from the rar Kconfig. Cai Huoqing's patch converts the mscan driver to make use of the dev_err_probe() helper function. A patch by me against the gsusb driver changes the printf format strings to use %u to print unsigned values. Stephane Grosjean's patch updates the peak_usb CAN-FD driver to use the 64 bit timestamps provided by the hardware. The last 2 patches target the xilinx_can driver. Michal Simek provides a patch that removes repeated word from the kernel-doc and Dongliang Mu's patch removes a redundant netif_napi_del() from the xcan_remove() function. ==================== Signed-off-by: David S. Miller <[email protected]>
- Loading branch information
Showing
16 changed files
with
402 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix | ||
* Copyright (C) 2006 Andrey Volkov, Varma Electronics | ||
* Copyright (C) 2008-2009 Wolfgang Grandegger <[email protected]> | ||
* Copyright (C) 2021 Vincent Mailhol <[email protected]> | ||
*/ | ||
|
||
#include <linux/can/dev.h> | ||
|
@@ -19,6 +20,19 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = { | |
[IFLA_CAN_DATA_BITTIMING] = { .len = sizeof(struct can_bittiming) }, | ||
[IFLA_CAN_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) }, | ||
[IFLA_CAN_TERMINATION] = { .type = NLA_U16 }, | ||
[IFLA_CAN_TDC] = { .type = NLA_NESTED }, | ||
}; | ||
|
||
static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = { | ||
[IFLA_CAN_TDC_TDCV_MIN] = { .type = NLA_U32 }, | ||
[IFLA_CAN_TDC_TDCV_MAX] = { .type = NLA_U32 }, | ||
[IFLA_CAN_TDC_TDCO_MIN] = { .type = NLA_U32 }, | ||
[IFLA_CAN_TDC_TDCO_MAX] = { .type = NLA_U32 }, | ||
[IFLA_CAN_TDC_TDCF_MIN] = { .type = NLA_U32 }, | ||
[IFLA_CAN_TDC_TDCF_MAX] = { .type = NLA_U32 }, | ||
[IFLA_CAN_TDC_TDCV] = { .type = NLA_U32 }, | ||
[IFLA_CAN_TDC_TDCO] = { .type = NLA_U32 }, | ||
[IFLA_CAN_TDC_TDCF] = { .type = NLA_U32 }, | ||
}; | ||
|
||
static int can_validate(struct nlattr *tb[], struct nlattr *data[], | ||
|
@@ -30,35 +44,120 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[], | |
* - nominal/arbitration bittiming | ||
* - data bittiming | ||
* - control mode with CAN_CTRLMODE_FD set | ||
* - TDC parameters are coherent (details below) | ||
*/ | ||
|
||
if (!data) | ||
return 0; | ||
|
||
if (data[IFLA_CAN_CTRLMODE]) { | ||
struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]); | ||
u32 tdc_flags = cm->flags & CAN_CTRLMODE_TDC_MASK; | ||
|
||
is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD; | ||
|
||
/* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually exclusive */ | ||
if (tdc_flags == CAN_CTRLMODE_TDC_MASK) | ||
return -EOPNOTSUPP; | ||
/* If one of the CAN_CTRLMODE_TDC_* flag is set then | ||
* TDC must be set and vice-versa | ||
*/ | ||
if (!!tdc_flags != !!data[IFLA_CAN_TDC]) | ||
return -EOPNOTSUPP; | ||
/* If providing TDC parameters, at least TDCO is | ||
* needed. TDCV is needed if and only if | ||
* CAN_CTRLMODE_TDC_MANUAL is set | ||
*/ | ||
if (data[IFLA_CAN_TDC]) { | ||
struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1]; | ||
int err; | ||
|
||
err = nla_parse_nested(tb_tdc, IFLA_CAN_TDC_MAX, | ||
data[IFLA_CAN_TDC], | ||
can_tdc_policy, extack); | ||
if (err) | ||
return err; | ||
|
||
if (tb_tdc[IFLA_CAN_TDC_TDCV]) { | ||
if (tdc_flags & CAN_CTRLMODE_TDC_AUTO) | ||
return -EOPNOTSUPP; | ||
} else { | ||
if (tdc_flags & CAN_CTRLMODE_TDC_MANUAL) | ||
return -EOPNOTSUPP; | ||
} | ||
|
||
if (!tb_tdc[IFLA_CAN_TDC_TDCO]) | ||
return -EOPNOTSUPP; | ||
} | ||
} | ||
|
||
if (is_can_fd) { | ||
if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING]) | ||
return -EOPNOTSUPP; | ||
} | ||
|
||
if (data[IFLA_CAN_DATA_BITTIMING]) { | ||
if (data[IFLA_CAN_DATA_BITTIMING] || data[IFLA_CAN_TDC]) { | ||
if (!is_can_fd) | ||
return -EOPNOTSUPP; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int can_tdc_changelink(struct can_priv *priv, const struct nlattr *nla, | ||
struct netlink_ext_ack *extack) | ||
{ | ||
struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1]; | ||
struct can_tdc tdc = { 0 }; | ||
const struct can_tdc_const *tdc_const = priv->tdc_const; | ||
int err; | ||
|
||
if (!tdc_const || !can_tdc_is_enabled(priv)) | ||
return -EOPNOTSUPP; | ||
|
||
err = nla_parse_nested(tb_tdc, IFLA_CAN_TDC_MAX, nla, | ||
can_tdc_policy, extack); | ||
if (err) | ||
return err; | ||
|
||
if (tb_tdc[IFLA_CAN_TDC_TDCV]) { | ||
u32 tdcv = nla_get_u32(tb_tdc[IFLA_CAN_TDC_TDCV]); | ||
|
||
if (tdcv < tdc_const->tdcv_min || tdcv > tdc_const->tdcv_max) | ||
return -EINVAL; | ||
|
||
tdc.tdcv = tdcv; | ||
} | ||
|
||
if (tb_tdc[IFLA_CAN_TDC_TDCO]) { | ||
u32 tdco = nla_get_u32(tb_tdc[IFLA_CAN_TDC_TDCO]); | ||
|
||
if (tdco < tdc_const->tdco_min || tdco > tdc_const->tdco_max) | ||
return -EINVAL; | ||
|
||
tdc.tdco = tdco; | ||
} | ||
|
||
if (tb_tdc[IFLA_CAN_TDC_TDCF]) { | ||
u32 tdcf = nla_get_u32(tb_tdc[IFLA_CAN_TDC_TDCF]); | ||
|
||
if (tdcf < tdc_const->tdcf_min || tdcf > tdc_const->tdcf_max) | ||
return -EINVAL; | ||
|
||
tdc.tdcf = tdcf; | ||
} | ||
|
||
priv->tdc = tdc; | ||
|
||
return 0; | ||
} | ||
|
||
static int can_changelink(struct net_device *dev, struct nlattr *tb[], | ||
struct nlattr *data[], | ||
struct netlink_ext_ack *extack) | ||
{ | ||
struct can_priv *priv = netdev_priv(dev); | ||
u32 tdc_mask = 0; | ||
int err; | ||
|
||
/* We need synchronization with dev->stop() */ | ||
|
@@ -138,7 +237,16 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[], | |
dev->mtu = CAN_MTU; | ||
memset(&priv->data_bittiming, 0, | ||
sizeof(priv->data_bittiming)); | ||
priv->ctrlmode &= ~CAN_CTRLMODE_TDC_MASK; | ||
memset(&priv->tdc, 0, sizeof(priv->tdc)); | ||
} | ||
|
||
tdc_mask = cm->mask & CAN_CTRLMODE_TDC_MASK; | ||
/* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually | ||
* exclusive: make sure to turn the other one off | ||
*/ | ||
if (tdc_mask) | ||
priv->ctrlmode &= cm->flags | ~CAN_CTRLMODE_TDC_MASK; | ||
} | ||
|
||
if (data[IFLA_CAN_RESTART_MS]) { | ||
|
@@ -187,9 +295,26 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[], | |
return -EINVAL; | ||
} | ||
|
||
memcpy(&priv->data_bittiming, &dbt, sizeof(dbt)); | ||
memset(&priv->tdc, 0, sizeof(priv->tdc)); | ||
if (data[IFLA_CAN_TDC]) { | ||
/* TDC parameters are provided: use them */ | ||
err = can_tdc_changelink(priv, data[IFLA_CAN_TDC], | ||
extack); | ||
if (err) { | ||
priv->ctrlmode &= ~CAN_CTRLMODE_TDC_MASK; | ||
return err; | ||
} | ||
} else if (!tdc_mask) { | ||
/* Neither of TDC parameters nor TDC flags are | ||
* provided: do calculation | ||
*/ | ||
can_calc_tdco(&priv->tdc, priv->tdc_const, &priv->data_bittiming, | ||
&priv->ctrlmode, priv->ctrlmode_supported); | ||
} /* else: both CAN_CTRLMODE_TDC_{AUTO,MANUAL} are explicitly | ||
* turned off. TDC is disabled: do nothing | ||
*/ | ||
|
||
can_calc_tdco(dev); | ||
memcpy(&priv->data_bittiming, &dbt, sizeof(dbt)); | ||
|
||
if (priv->do_set_data_bittiming) { | ||
/* Finally, set the bit-timing registers */ | ||
|
@@ -226,6 +351,38 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[], | |
return 0; | ||
} | ||
|
||
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) | ||
return 0; | ||
|
||
size = nla_total_size(0); /* nest IFLA_CAN_TDC */ | ||
if (priv->ctrlmode_supported & CAN_CTRLMODE_TDC_MANUAL) { | ||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCV_MIN */ | ||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCV_MAX */ | ||
} | ||
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) { | ||
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) | ||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCV */ | ||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO */ | ||
if (priv->tdc_const->tdcf_max) | ||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCF */ | ||
} | ||
|
||
return size; | ||
} | ||
|
||
static size_t can_get_size(const struct net_device *dev) | ||
{ | ||
struct can_priv *priv = netdev_priv(dev); | ||
|
@@ -257,10 +414,64 @@ static size_t can_get_size(const struct net_device *dev) | |
size += nla_total_size(sizeof(*priv->data_bitrate_const) * | ||
priv->data_bitrate_const_cnt); | ||
size += sizeof(priv->bitrate_max); /* IFLA_CAN_BITRATE_MAX */ | ||
size += can_tdc_get_size(dev); /* IFLA_CAN_TDC */ | ||
|
||
return size; | ||
} | ||
|
||
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; | ||
|
||
if (!tdc_const) | ||
return 0; | ||
|
||
nest = nla_nest_start(skb, IFLA_CAN_TDC); | ||
if (!nest) | ||
return -EMSGSIZE; | ||
|
||
if (priv->ctrlmode_supported & CAN_CTRLMODE_TDC_MANUAL && | ||
(nla_put_u32(skb, IFLA_CAN_TDC_TDCV_MIN, tdc_const->tdcv_min) || | ||
nla_put_u32(skb, IFLA_CAN_TDC_TDCV_MAX, tdc_const->tdcv_max))) | ||
goto err_cancel; | ||
if (nla_put_u32(skb, IFLA_CAN_TDC_TDCO_MIN, tdc_const->tdco_min) || | ||
nla_put_u32(skb, IFLA_CAN_TDC_TDCO_MAX, tdc_const->tdco_max)) | ||
goto err_cancel; | ||
if (tdc_const->tdcf_max && | ||
(nla_put_u32(skb, IFLA_CAN_TDC_TDCF_MIN, tdc_const->tdcf_min) || | ||
nla_put_u32(skb, IFLA_CAN_TDC_TDCF_MAX, tdc_const->tdcf_max))) | ||
goto err_cancel; | ||
|
||
if (can_tdc_is_enabled(priv)) { | ||
u32 tdcv; | ||
int err = -EINVAL; | ||
|
||
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); | ||
} | ||
if (!err && nla_put_u32(skb, IFLA_CAN_TDC_TDCV, tdcv)) | ||
goto err_cancel; | ||
if (nla_put_u32(skb, IFLA_CAN_TDC_TDCO, tdc->tdco)) | ||
goto err_cancel; | ||
if (tdc_const->tdcf_max && | ||
nla_put_u32(skb, IFLA_CAN_TDC_TDCF, tdc->tdcf)) | ||
goto err_cancel; | ||
} | ||
|
||
nla_nest_end(skb, nest); | ||
return 0; | ||
|
||
err_cancel: | ||
nla_nest_cancel(skb, nest); | ||
return -EMSGSIZE; | ||
} | ||
|
||
static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) | ||
{ | ||
struct can_priv *priv = netdev_priv(dev); | ||
|
@@ -318,7 +529,9 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) | |
|
||
(nla_put(skb, IFLA_CAN_BITRATE_MAX, | ||
sizeof(priv->bitrate_max), | ||
&priv->bitrate_max)) | ||
&priv->bitrate_max)) || | ||
|
||
(can_tdc_fill_info(skb, dev)) | ||
) | ||
|
||
return -EMSGSIZE; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.