Skip to content

Commit

Permalink
Merge tag 'linux-can-next-for-4.16-20180116' of ssh://gitolite.kernel…
Browse files Browse the repository at this point in the history
….org/pub/scm/linux/kernel/git/mkl/linux-can-next

Marc Kleine-Budde says:

====================
pull-request: can-next 2018-01-16

this is a pull request for net-next/master consisting of 9 patches.

This is a series of patches, some of them initially by Franklin S Cooper
Jr, which was picked up by Faiz Abbas. Faiz Abbas added some patches
while working on this series, I contributed one as well.

The first two patches add support to CAN device infrastructure to limit
the bitrate of a CAN adapter if the used CAN-transceiver has a certain
maximum bitrate.

The remaining patches improve the m_can driver. They add support for
bitrate limiting to the driver, clean up the driver and add support for
runtime PM.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jan 17, 2018
2 parents 5ef7e0b + 31643dc commit 4f7d585
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 67 deletions.
24 changes: 24 additions & 0 deletions Documentation/devicetree/bindings/net/can/can-transceiver.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Generic CAN transceiver Device Tree binding
------------------------------

CAN transceiver typically limits the max speed in standard CAN and CAN FD
modes. Typically these limitations are static and the transceivers themselves
provide no way to detect this limitation at runtime. For this situation,
the "can-transceiver" node can be used.

Required Properties:
max-bitrate: a positive non 0 value that determines the max
speed that CAN/CAN-FD can run. Any other value
will be ignored.

Examples:

Based on Texas Instrument's TCAN1042HGV CAN Transceiver

m_can0 {
....
can-transceiver {
max-bitrate = <5000000>;
};
...
};
9 changes: 9 additions & 0 deletions Documentation/devicetree/bindings/net/can/m_can.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ Required properties:
Please refer to 2.4.1 Message RAM Configuration in
Bosch M_CAN user manual for details.

Optional Subnode:
- can-transceiver : Can-transceiver subnode describing maximum speed
that can be used for CAN/CAN-FD modes. See
Documentation/devicetree/bindings/net/can/can-transceiver.txt
for details.
Example:
SoC dtsi:
m_can1: can@20e8000 {
Expand All @@ -63,4 +68,8 @@ Board dts:
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_m_can1>;
status = "enabled";

can-transceiver {
max-bitrate = <5000000>;
};
};
45 changes: 44 additions & 1 deletion drivers/net/can/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/can/skb.h>
#include <linux/can/netlink.h>
#include <linux/can/led.h>
#include <linux/of.h>
#include <net/rtnetlink.h>

#define MOD_DESC "CAN device driver interface"
Expand Down Expand Up @@ -814,6 +815,29 @@ int open_candev(struct net_device *dev)
}
EXPORT_SYMBOL_GPL(open_candev);

#ifdef CONFIG_OF
/* Common function that can be used to understand the limitation of
* a transceiver when it provides no means to determine these limitations
* at runtime.
*/
void of_can_transceiver(struct net_device *dev)
{
struct device_node *dn;
struct can_priv *priv = netdev_priv(dev);
struct device_node *np = dev->dev.parent->of_node;
int ret;

dn = of_get_child_by_name(np, "can-transceiver");
if (!dn)
return;

ret = of_property_read_u32(dn, "max-bitrate", &priv->bitrate_max);
if ((ret && ret != -EINVAL) || (!ret && !priv->bitrate_max))
netdev_warn(dev, "Invalid value for transceiver max bitrate. Ignoring bitrate limit.\n");
}
EXPORT_SYMBOL_GPL(of_can_transceiver);
#endif

/*
* Common close function for cleanup before the device gets closed.
*
Expand Down Expand Up @@ -913,6 +937,13 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
priv->bitrate_const_cnt);
if (err)
return err;

if (priv->bitrate_max && bt.bitrate > priv->bitrate_max) {
netdev_err(dev, "arbitration bitrate surpasses transceiver capabilities of %d bps\n",
priv->bitrate_max);
return -EINVAL;
}

memcpy(&priv->bittiming, &bt, sizeof(bt));

if (priv->do_set_bittiming) {
Expand Down Expand Up @@ -997,6 +1028,13 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
priv->data_bitrate_const_cnt);
if (err)
return err;

if (priv->bitrate_max && dbt.bitrate > priv->bitrate_max) {
netdev_err(dev, "canfd data bitrate surpasses transceiver capabilities of %d bps\n",
priv->bitrate_max);
return -EINVAL;
}

memcpy(&priv->data_bittiming, &dbt, sizeof(dbt));

if (priv->do_set_data_bittiming) {
Expand Down Expand Up @@ -1064,6 +1102,7 @@ static size_t can_get_size(const struct net_device *dev)
if (priv->data_bitrate_const) /* IFLA_CAN_DATA_BITRATE_CONST */
size += nla_total_size(sizeof(*priv->data_bitrate_const) *
priv->data_bitrate_const_cnt);
size += sizeof(priv->bitrate_max); /* IFLA_CAN_BITRATE_MAX */

return size;
}
Expand Down Expand Up @@ -1121,7 +1160,11 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
nla_put(skb, IFLA_CAN_DATA_BITRATE_CONST,
sizeof(*priv->data_bitrate_const) *
priv->data_bitrate_const_cnt,
priv->data_bitrate_const))
priv->data_bitrate_const)) ||

(nla_put(skb, IFLA_CAN_BITRATE_MAX,
sizeof(priv->bitrate_max),
&priv->bitrate_max))
)

return -EMSGSIZE;
Expand Down
Loading

0 comments on commit 4f7d585

Please sign in to comment.