Commit 5947b7f7 authored by David S. Miller's avatar David S. Miller

Merge tag 'linux-can-next-for-6.1-20220915' of...

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

Marc Kleine-Budde says:

====================
Sept. 15, 2022, 8:19 a.m. UTC
Hello Jakub, hello David,

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

the first 2 patches are by me and fix a typo in the rx-offload helper
and the flexcan driver.

Christophe JAILLET's patch cleans up the error handling in
rcar_canfd driver's probe function.

Kenneth Lee's patch converts the kvaser_usb driver from kcalloc() to
kzalloc().

Biju Das contributes 2 patches to the sja1000 driver which update the
DT bindings and support for the RZ/N1 SJA1000 CAN controller.

Jinpeng Cui provides 2 patches that remove redundant variables from
the sja1000 and kvaser_pciefd driver.

2 patches by John Whittington and me add hardware timestamp support to
the gs_usb driver.

Gustavo A. R. Silva's patch converts the etas_es58x driver to make use
of DECLARE_FLEX_ARRAY().

Krzysztof Kozlowski's patch cleans up the sja1000 DT bindings.

Dario Binacchi fixes his invalid email in the flexcan driver
documentation.

Ziyang Xuan contributes 2 patches that clean up the CAN RAW protocol.

Yang Yingliang's patch switches the flexcan driver to dev_err_probe().

The last 7 patches are by Oliver Hartkopp and add support for the next
generation of the CAN protocol: CAN with eXtended data Length (CAN XL).
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2c119d99 c337f103
......@@ -30,8 +30,10 @@ properties:
clocks:
maxItems: 1
power-domains:
maxItems: 1
reg-io-width:
$ref: /schemas/types.yaml#/definitions/uint32
description: I/O register width (in bytes) implemented by this device
default: 1
enum: [ 1, 2, 4 ]
......@@ -105,6 +107,7 @@ allOf:
then:
required:
- clocks
- power-domains
unevaluatedProperties: false
......@@ -129,4 +132,5 @@ examples:
reg-io-width = <4>;
interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysctrl R9A06G032_HCLK_CAN0>;
power-domains = <&sysctrl>;
};
......@@ -5,7 +5,7 @@ Flexcan CAN Controller driver
=============================
Authors: Marc Kleine-Budde <mkl@pengutronix.de>,
Dario Binacchi <dario.binacchi@amarula.solutions.com>
Dario Binacchi <dario.binacchi@amarulasolutions.com>
On/off RTR frames reception
===========================
......
......@@ -657,7 +657,6 @@ static void ctucan_read_rx_frame(struct ctucan_priv *priv, struct canfd_frame *c
cf->can_id = (idw >> 18) & CAN_SFF_MASK;
/* BRS, ESI, RTR Flags */
cf->flags = 0;
if (FIELD_GET(REG_FRAME_FORMAT_W_FDF, ffw)) {
if (FIELD_GET(REG_FRAME_FORMAT_W_BRS, ffw))
cf->flags |= CANFD_BRS;
......
......@@ -247,7 +247,7 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
struct net_device *dev = offload->dev;
struct net_device_stats *stats = &dev->stats;
struct sk_buff *skb;
u8 len;
unsigned int len;
int err;
skb = __can_get_echo_skb(dev, idx, &len, frame_len_ptr);
......@@ -329,7 +329,7 @@ static int can_rx_offload_init_queue(struct net_device *dev,
{
offload->dev = dev;
/* Limit queue len to 4x the weight (rounted to next power of two) */
/* Limit queue len to 4x the weight (rounded to next power of two) */
offload->skb_queue_len_max = 2 << fls(weight);
offload->skb_queue_len_max *= 4;
skb_queue_head_init(&offload->skb_queue);
......
......@@ -91,8 +91,8 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
EXPORT_SYMBOL_GPL(can_put_echo_skb);
struct sk_buff *
__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr,
unsigned int *frame_len_ptr)
__can_get_echo_skb(struct net_device *dev, unsigned int idx,
unsigned int *len_ptr, unsigned int *frame_len_ptr)
{
struct can_priv *priv = netdev_priv(dev);
......@@ -108,16 +108,12 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr,
*/
struct sk_buff *skb = priv->echo_skb[idx];
struct can_skb_priv *can_skb_priv = can_skb_prv(skb);
struct canfd_frame *cf = (struct canfd_frame *)skb->data;
if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)
skb_tstamp_tx(skb, skb_hwtstamps(skb));
/* get the real payload length for netdev statistics */
if (cf->can_id & CAN_RTR_FLAG)
*len_ptr = 0;
else
*len_ptr = cf->len;
*len_ptr = can_skb_get_data_len(skb);
if (frame_len_ptr)
*frame_len_ptr = can_skb_priv->frame_len;
......@@ -147,7 +143,7 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx,
unsigned int *frame_len_ptr)
{
struct sk_buff *skb;
u8 len;
unsigned int len;
skb = __can_get_echo_skb(dev, idx, &len, frame_len_ptr);
if (!skb)
......@@ -191,6 +187,20 @@ void can_free_echo_skb(struct net_device *dev, unsigned int idx,
}
EXPORT_SYMBOL_GPL(can_free_echo_skb);
/* fill common values for CAN sk_buffs */
static void init_can_skb_reserve(struct sk_buff *skb)
{
skb->pkt_type = PACKET_BROADCAST;
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
skb_reset_transport_header(skb);
can_skb_reserve(skb);
can_skb_prv(skb)->skbcnt = 0;
}
struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
{
struct sk_buff *skb;
......@@ -204,16 +214,8 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
}
skb->protocol = htons(ETH_P_CAN);
skb->pkt_type = PACKET_BROADCAST;
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
skb_reset_transport_header(skb);
can_skb_reserve(skb);
init_can_skb_reserve(skb);
can_skb_prv(skb)->ifindex = dev->ifindex;
can_skb_prv(skb)->skbcnt = 0;
*cf = skb_put_zero(skb, sizeof(struct can_frame));
......@@ -235,23 +237,51 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,
}
skb->protocol = htons(ETH_P_CANFD);
skb->pkt_type = PACKET_BROADCAST;
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
skb_reset_transport_header(skb);
can_skb_reserve(skb);
init_can_skb_reserve(skb);
can_skb_prv(skb)->ifindex = dev->ifindex;
can_skb_prv(skb)->skbcnt = 0;
*cfd = skb_put_zero(skb, sizeof(struct canfd_frame));
/* set CAN FD flag by default */
(*cfd)->flags = CANFD_FDF;
return skb;
}
EXPORT_SYMBOL_GPL(alloc_canfd_skb);
struct sk_buff *alloc_canxl_skb(struct net_device *dev,
struct canxl_frame **cxl,
unsigned int data_len)
{
struct sk_buff *skb;
if (data_len < CANXL_MIN_DLEN || data_len > CANXL_MAX_DLEN)
goto out_error;
skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
CANXL_HDR_SIZE + data_len);
if (unlikely(!skb))
goto out_error;
skb->protocol = htons(ETH_P_CANXL);
init_can_skb_reserve(skb);
can_skb_prv(skb)->ifindex = dev->ifindex;
*cxl = skb_put_zero(skb, CANXL_HDR_SIZE + data_len);
/* set CAN XL flag and length information by default */
(*cxl)->flags = CANXL_XLF;
(*cxl)->len = data_len;
return skb;
out_error:
*cxl = NULL;
return NULL;
}
EXPORT_SYMBOL_GPL(alloc_canxl_skb);
struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf)
{
struct sk_buff *skb;
......@@ -291,6 +321,14 @@ static bool can_skb_headroom_valid(struct net_device *dev, struct sk_buff *skb)
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
skb_reset_transport_header(skb);
/* set CANFD_FDF flag for CAN FD frames */
if (can_is_canfd_skb(skb)) {
struct canfd_frame *cfd;
cfd = (struct canfd_frame *)skb->data;
cfd->flags |= CANFD_FDF;
}
}
return true;
......@@ -299,18 +337,25 @@ static bool can_skb_headroom_valid(struct net_device *dev, struct sk_buff *skb)
/* Drop a given socketbuffer if it does not contain a valid CAN frame. */
bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
{
const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
struct can_priv *priv = netdev_priv(dev);
if (skb->protocol == htons(ETH_P_CAN)) {
if (unlikely(skb->len != CAN_MTU ||
cfd->len > CAN_MAX_DLEN))
switch (ntohs(skb->protocol)) {
case ETH_P_CAN:
if (!can_is_can_skb(skb))
goto inval_skb;
} else if (skb->protocol == htons(ETH_P_CANFD)) {
if (unlikely(skb->len != CANFD_MTU ||
cfd->len > CANFD_MAX_DLEN))
break;
case ETH_P_CANFD:
if (!can_is_canfd_skb(skb))
goto inval_skb;
} else {
break;
case ETH_P_CANXL:
if (!can_is_canxl_skb(skb))
goto inval_skb;
break;
default:
goto inval_skb;
}
......
......@@ -295,45 +295,45 @@ static_assert(sizeof(struct flexcan_regs) == 0x4 * 18 + 0xfb8);
static const struct flexcan_devtype_data fsl_mcf5441x_devtype_data = {
.quirks = FLEXCAN_QUIRK_BROKEN_PERR_STATE |
FLEXCAN_QUIRK_NR_IRQ_3 | FLEXCAN_QUIRK_NR_MB_16 |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_FIFO,
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_FIFO,
};
static const struct flexcan_devtype_data fsl_p1010_devtype_data = {
.quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE |
FLEXCAN_QUIRK_BROKEN_PERR_STATE |
FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_FIFO,
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_FIFO,
};
static const struct flexcan_devtype_data fsl_imx25_devtype_data = {
.quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE |
FLEXCAN_QUIRK_BROKEN_PERR_STATE |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_FIFO,
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_FIFO,
};
static const struct flexcan_devtype_data fsl_imx28_devtype_data = {
.quirks = FLEXCAN_QUIRK_BROKEN_PERR_STATE |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_FIFO,
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_FIFO,
};
static const struct flexcan_devtype_data fsl_imx6q_devtype_data = {
.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
FLEXCAN_QUIRK_USE_RX_MAILBOX | FLEXCAN_QUIRK_BROKEN_PERR_STATE |
FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR,
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR,
};
static const struct flexcan_devtype_data fsl_imx8qm_devtype_data = {
.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
FLEXCAN_QUIRK_USE_RX_MAILBOX | FLEXCAN_QUIRK_BROKEN_PERR_STATE |
FLEXCAN_QUIRK_SUPPORT_FD | FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR,
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR,
};
static struct flexcan_devtype_data fsl_imx8mp_devtype_data = {
......@@ -341,23 +341,23 @@ static struct flexcan_devtype_data fsl_imx8mp_devtype_data = {
FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX |
FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR |
FLEXCAN_QUIRK_SUPPORT_FD | FLEXCAN_QUIRK_SUPPORT_ECC |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR,
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR,
};
static const struct flexcan_devtype_data fsl_vf610_devtype_data = {
.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX |
FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_SUPPORT_ECC |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR,
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR,
};
static const struct flexcan_devtype_data fsl_ls1021a_r2_devtype_data = {
.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_USE_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR,
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR,
};
static const struct flexcan_devtype_data fsl_lx2160a_r1_devtype_data = {
......@@ -365,8 +365,8 @@ static const struct flexcan_devtype_data fsl_lx2160a_r1_devtype_data = {
FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_BROKEN_PERR_STATE |
FLEXCAN_QUIRK_USE_RX_MAILBOX | FLEXCAN_QUIRK_SUPPORT_FD |
FLEXCAN_QUIRK_SUPPORT_ECC |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR,
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR,
};
static const struct can_bittiming_const flexcan_bittiming_const = {
......@@ -2085,20 +2085,20 @@ static int flexcan_probe(struct platform_device *pdev)
if ((devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) &&
!((devtype_data->quirks &
(FLEXCAN_QUIRK_USE_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR |
FLEXCAN_QUIRK_SUPPPORT_RX_FIFO)) ==
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR |
FLEXCAN_QUIRK_SUPPORT_RX_FIFO)) ==
(FLEXCAN_QUIRK_USE_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR))) {
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR))) {
dev_err(&pdev->dev, "CAN-FD mode doesn't work in RX-FIFO mode!\n");
return -EINVAL;
}
if ((devtype_data->quirks &
(FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR)) ==
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR) {
(FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR)) ==
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR) {
dev_err(&pdev->dev,
"Quirks (0x%08x) inconsistent: RX_MAILBOX_RX supported but not RX_MAILBOX\n",
devtype_data->quirks);
......@@ -2177,8 +2177,7 @@ static int flexcan_probe(struct platform_device *pdev)
err = flexcan_setup_stop_mode(pdev);
if (err < 0) {
if (err != -EPROBE_DEFER)
dev_err(&pdev->dev, "setup stop mode failed\n");
dev_err_probe(&pdev->dev, err, "setup stop mode failed\n");
goto failed_setup_stop_mode;
}
......
......@@ -63,11 +63,11 @@
/* Setup 16 mailboxes */
#define FLEXCAN_QUIRK_NR_MB_16 BIT(13)
/* Device supports RX via mailboxes */
#define FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX BIT(14)
#define FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX BIT(14)
/* Device supports RTR reception via mailboxes */
#define FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR BIT(15)
#define FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR BIT(15)
/* Device supports RX via FIFO */
#define FLEXCAN_QUIRK_SUPPPORT_RX_FIFO BIT(16)
#define FLEXCAN_QUIRK_SUPPORT_RX_FIFO BIT(16)
struct flexcan_devtype_data {
u32 quirks; /* quirks needed for different IP cores */
......@@ -121,7 +121,7 @@ flexcan_supports_rx_mailbox(const struct flexcan_priv *priv)
{
const u32 quirks = priv->devtype_data.quirks;
return quirks & FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX;
return quirks & FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX;
}
static inline bool
......@@ -129,10 +129,10 @@ flexcan_supports_rx_mailbox_rtr(const struct flexcan_priv *priv)
{
const u32 quirks = priv->devtype_data.quirks;
return (quirks & (FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR)) ==
(FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR);
return (quirks & (FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR)) ==
(FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR);
}
static inline bool
......@@ -140,7 +140,7 @@ flexcan_supports_rx_fifo(const struct flexcan_priv *priv)
{
const u32 quirks = priv->devtype_data.quirks;
return quirks & FLEXCAN_QUIRK_SUPPPORT_RX_FIFO;
return quirks & FLEXCAN_QUIRK_SUPPORT_RX_FIFO;
}
static inline bool
......@@ -149,7 +149,7 @@ flexcan_active_rx_rtr(const struct flexcan_priv *priv)
const u32 quirks = priv->devtype_data.quirks;
if (quirks & FLEXCAN_QUIRK_USE_RX_MAILBOX) {
if (quirks & FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR)
if (quirks & FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR)
return true;
} else {
/* RX-FIFO is always RTR capable */
......
......@@ -329,12 +329,9 @@ MODULE_DEVICE_TABLE(pci, kvaser_pciefd_id_table);
static int kvaser_pciefd_spi_wait_loop(struct kvaser_pciefd *pcie, int msk)
{
u32 res;
int ret;
ret = readl_poll_timeout(pcie->reg_base + KVASER_PCIEFD_SPI_STATUS_REG,
res, res & msk, 0, 10);
return ret;
return readl_poll_timeout(pcie->reg_base + KVASER_PCIEFD_SPI_STATUS_REG,
res, res & msk, 0, 10);
}
static int kvaser_pciefd_spi_cmd(struct kvaser_pciefd *pcie, const u8 *tx,
......
......@@ -1880,10 +1880,9 @@ static int rcar_canfd_probe(struct platform_device *pdev)
/* Global controller context */
gpriv = devm_kzalloc(&pdev->dev, sizeof(*gpriv), GFP_KERNEL);
if (!gpriv) {
err = -ENOMEM;
goto fail_dev;
}
if (!gpriv)
return -ENOMEM;
gpriv->pdev = pdev;
gpriv->channels_mask = channels_mask;
gpriv->fdmode = fdmode;
......@@ -1904,12 +1903,9 @@ static int rcar_canfd_probe(struct platform_device *pdev)
/* Peripheral clock */
gpriv->clkp = devm_clk_get(&pdev->dev, "fck");
if (IS_ERR(gpriv->clkp)) {
err = PTR_ERR(gpriv->clkp);
dev_err(&pdev->dev, "cannot get peripheral clock, error %d\n",
err);
goto fail_dev;
}
if (IS_ERR(gpriv->clkp))
return dev_err_probe(&pdev->dev, PTR_ERR(gpriv->clkp),
"cannot get peripheral clock\n");
/* fCAN clock: Pick External clock. If not available fallback to
* CANFD clock
......@@ -1917,12 +1913,10 @@ static int rcar_canfd_probe(struct platform_device *pdev)
gpriv->can_clk = devm_clk_get(&pdev->dev, "can_clk");
if (IS_ERR(gpriv->can_clk) || (clk_get_rate(gpriv->can_clk) == 0)) {
gpriv->can_clk = devm_clk_get(&pdev->dev, "canfd");
if (IS_ERR(gpriv->can_clk)) {
err = PTR_ERR(gpriv->can_clk);
dev_err(&pdev->dev,
"cannot get canfd clock, error %d\n", err);
goto fail_dev;
}
if (IS_ERR(gpriv->can_clk))
return dev_err_probe(&pdev->dev, PTR_ERR(gpriv->can_clk),
"cannot get canfd clock\n");
gpriv->fcan = RCANFD_CANFDCLK;
} else {
......
......@@ -661,8 +661,6 @@ static const struct ethtool_ops sja1000_ethtool_ops = {
int register_sja1000dev(struct net_device *dev)
{
int ret;
if (!sja1000_probe_chip(dev))
return -ENODEV;
......@@ -673,9 +671,7 @@ int register_sja1000dev(struct net_device *dev)
set_reset_mode(dev);
chipset_init(dev);
ret = register_candev(dev);
return ret;
return register_candev(dev);
}
EXPORT_SYMBOL_GPL(register_sja1000dev);
......
......@@ -14,6 +14,7 @@
#include <linux/irq.h>
#include <linux/can/dev.h>
#include <linux/can/platform/sja1000.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
......@@ -103,6 +104,11 @@ static void sp_technologic_init(struct sja1000_priv *priv, struct device_node *o
spin_lock_init(&tp->io_lock);
}
static void sp_rzn1_init(struct sja1000_priv *priv, struct device_node *of)
{
priv->flags = SJA1000_QUIRK_NO_CDR_REG;
}
static void sp_populate(struct sja1000_priv *priv,
struct sja1000_platform_data *pdata,
unsigned long resource_mem_flags)
......@@ -153,11 +159,13 @@ static void sp_populate_of(struct sja1000_priv *priv, struct device_node *of)
priv->write_reg = sp_write_reg8;
}
err = of_property_read_u32(of, "nxp,external-clock-frequency", &prop);
if (!err)
priv->can.clock.freq = prop / 2;
else
priv->can.clock.freq = SP_CAN_CLOCK; /* default */
if (!priv->can.clock.freq) {
err = of_property_read_u32(of, "nxp,external-clock-frequency", &prop);
if (!err)
priv->can.clock.freq = prop / 2;
else
priv->can.clock.freq = SP_CAN_CLOCK; /* default */
}
err = of_property_read_u32(of, "nxp,tx-output-mode", &prop);
if (!err)
......@@ -192,8 +200,13 @@ static struct sja1000_of_data technologic_data = {
.init = sp_technologic_init,
};
static struct sja1000_of_data renesas_data = {
.init = sp_rzn1_init,
};
static const struct of_device_id sp_of_table[] = {
{ .compatible = "nxp,sja1000", .data = NULL, },
{ .compatible = "renesas,rzn1-sja1000", .data = &renesas_data, },
{ .compatible = "technologic,sja1000", .data = &technologic_data, },
{ /* sentinel */ },
};
......@@ -210,6 +223,7 @@ static int sp_probe(struct platform_device *pdev)
struct device_node *of = pdev->dev.of_node;
const struct sja1000_of_data *of_data = NULL;
size_t priv_sz = 0;
struct clk *clk;
pdata = dev_get_platdata(&pdev->dev);
if (!pdata && !of) {
......@@ -234,6 +248,11 @@ static int sp_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
if (IS_ERR(clk))
return dev_err_probe(&pdev->dev, PTR_ERR(clk),
"CAN clk operation failed");
} else {
res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res_irq)
......@@ -262,6 +281,15 @@ static int sp_probe(struct platform_device *pdev)
priv->reg_base = addr;
if (of) {
if (clk) {
priv->can.clock.freq = clk_get_rate(clk) / 2;
if (!priv->can.clock.freq) {
err = -EINVAL;
dev_err(&pdev->dev, "Zero CAN clk rate");
goto exit_free;
}
}
sp_populate_of(priv, of);
if (of_data && of_data->init)
......
......@@ -222,7 +222,7 @@ union es58x_urb_cmd {
u8 cmd_type;
u8 cmd_id;
} __packed;
u8 raw_cmd[0];
DECLARE_FLEX_ARRAY(u8, raw_cmd);
};
/**
......
This diff is collapsed.
......@@ -534,7 +534,7 @@ static int kvaser_usb_hydra_send_simple_cmd(struct kvaser_usb *dev,
struct kvaser_cmd *cmd;
int err;
cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
......@@ -573,7 +573,7 @@ kvaser_usb_hydra_send_simple_cmd_async(struct kvaser_usb_net_priv *priv,
struct kvaser_usb *dev = priv->dev;
int err;
cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_ATOMIC);
cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
if (!cmd)
return -ENOMEM;
......@@ -694,7 +694,7 @@ static int kvaser_usb_hydra_map_channel(struct kvaser_usb *dev, u16 transid,
struct kvaser_cmd *cmd;
int err;
cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
......@@ -735,7 +735,7 @@ static int kvaser_usb_hydra_get_single_capability(struct kvaser_usb *dev,
int err;
int i;
cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
......@@ -1394,7 +1394,7 @@ kvaser_usb_hydra_frame_to_cmd_ext(const struct kvaser_usb_net_priv *priv,
u32 kcan_id;
u32 kcan_header;
cmd = kcalloc(1, sizeof(struct kvaser_cmd_ext), GFP_ATOMIC);
cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
if (!cmd)
return NULL;
......@@ -1468,7 +1468,7 @@ kvaser_usb_hydra_frame_to_cmd_std(const struct kvaser_usb_net_priv *priv,
u32 flags;
u32 id;
cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_ATOMIC);
cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
if (!cmd)
return NULL;
......@@ -1533,7 +1533,7 @@ static int kvaser_usb_hydra_set_bittiming(struct net_device *netdev)
int sjw = bt->sjw;
int err;
cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
......@@ -1567,7 +1567,7 @@ static int kvaser_usb_hydra_set_data_bittiming(struct net_device *netdev)
int sjw = dbt->sjw;
int err;
cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
......@@ -1711,7 +1711,7 @@ static int kvaser_usb_hydra_get_software_details(struct kvaser_usb *dev)
u32 flags;
struct kvaser_usb_dev_card_data *card_data = &dev->card_data;
cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
......@@ -1851,7 +1851,7 @@ static int kvaser_usb_hydra_set_opt_mode(const struct kvaser_usb_net_priv *priv)
return -EINVAL;
}
cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
......
......@@ -71,11 +71,10 @@ MODULE_PARM_DESC(echo, "Echo sent frames (for testing). Default: 0 (Off)");
static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
{
struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
struct net_device_stats *stats = &dev->stats;
stats->rx_packets++;
stats->rx_bytes += cfd->len;
stats->rx_bytes += can_skb_get_data_len(skb);
skb->pkt_type = PACKET_BROADCAST;
skb->dev = dev;
......@@ -86,14 +85,14 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)
{
struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
struct net_device_stats *stats = &dev->stats;
int loop, len;
unsigned int len;
int loop;
if (can_dropped_invalid_skb(dev, skb))
return NETDEV_TX_OK;
len = cfd->can_id & CAN_RTR_FLAG ? 0 : cfd->len;
len = can_skb_get_data_len(skb);
stats->tx_packets++;
stats->tx_bytes += len;
......@@ -137,7 +136,8 @@ static int vcan_change_mtu(struct net_device *dev, int new_mtu)
if (dev->flags & IFF_UP)
return -EBUSY;
if (new_mtu != CAN_MTU && new_mtu != CANFD_MTU)
if (new_mtu != CAN_MTU && new_mtu != CANFD_MTU &&
!can_is_canxl_dev_mtu(new_mtu))
return -EINVAL;
dev->mtu = new_mtu;
......
......@@ -38,10 +38,9 @@ static netdev_tx_t vxcan_xmit(struct sk_buff *oskb, struct net_device *dev)
{
struct vxcan_priv *priv = netdev_priv(dev);
struct net_device *peer;
struct canfd_frame *cfd = (struct canfd_frame *)oskb->data;
struct net_device_stats *peerstats, *srcstats = &dev->stats;
struct sk_buff *skb;
u8 len;
unsigned int len;
if (can_dropped_invalid_skb(dev, oskb))
return NETDEV_TX_OK;
......@@ -70,7 +69,7 @@ static netdev_tx_t vxcan_xmit(struct sk_buff *oskb, struct net_device *dev)
skb->dev = peer;
skb->ip_summed = CHECKSUM_UNNECESSARY;
len = cfd->can_id & CAN_RTR_FLAG ? 0 : cfd->len;
len = can_skb_get_data_len(skb);
if (netif_rx(skb) == NET_RX_SUCCESS) {
srcstats->tx_packets++;
srcstats->tx_bytes += len;
......@@ -132,7 +131,8 @@ static int vxcan_change_mtu(struct net_device *dev, int new_mtu)
if (dev->flags & IFF_UP)
return -EBUSY;
if (new_mtu != CAN_MTU && new_mtu != CANFD_MTU)
if (new_mtu != CAN_MTU && new_mtu != CANFD_MTU &&
!can_is_canxl_dev_mtu(new_mtu))
return -EINVAL;
dev->mtu = new_mtu;
......
......@@ -147,6 +147,11 @@ static inline u32 can_get_static_ctrlmode(struct can_priv *priv)
return priv->ctrlmode & ~priv->ctrlmode_supported;
}
static inline bool can_is_canxl_dev_mtu(unsigned int mtu)
{
return (mtu >= CANXL_MIN_MTU && mtu <= CANXL_MAX_MTU);
}
void can_setup(struct net_device *dev);
struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
......
......@@ -20,7 +20,8 @@ void can_flush_echo_skb(struct net_device *dev);
int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
unsigned int idx, unsigned int frame_len);
struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
u8 *len_ptr, unsigned int *frame_len_ptr);
unsigned int *len_ptr,
unsigned int *frame_len_ptr);
unsigned int __must_check can_get_echo_skb(struct net_device *dev,
unsigned int idx,
unsigned int *frame_len_ptr);
......@@ -29,6 +30,9 @@ void can_free_echo_skb(struct net_device *dev, unsigned int idx,
struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf);
struct sk_buff *alloc_canfd_skb(struct net_device *dev,
struct canfd_frame **cfd);
struct sk_buff *alloc_canxl_skb(struct net_device *dev,
struct canxl_frame **cxl,
unsigned int data_len);
struct sk_buff *alloc_can_err_skb(struct net_device *dev,
struct can_frame **cf);
bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb);
......@@ -97,10 +101,59 @@ static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)
return nskb;
}
static inline bool can_is_can_skb(const struct sk_buff *skb)
{
struct can_frame *cf = (struct can_frame *)skb->data;
/* the CAN specific type of skb is identified by its data length */
return (skb->len == CAN_MTU && cf->len <= CAN_MAX_DLEN);
}
static inline bool can_is_canfd_skb(const struct sk_buff *skb)
{
struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
/* the CAN specific type of skb is identified by its data length */
return skb->len == CANFD_MTU;
return (skb->len == CANFD_MTU && cfd->len <= CANFD_MAX_DLEN);
}
static inline bool can_is_canxl_skb(const struct sk_buff *skb)
{
const struct canxl_frame *cxl = (struct canxl_frame *)skb->data;
if (skb->len < CANXL_HDR_SIZE + CANXL_MIN_DLEN || skb->len > CANXL_MTU)
return false;
/* this also checks valid CAN XL data length boundaries */
if (skb->len != CANXL_HDR_SIZE + cxl->len)
return false;
return cxl->flags & CANXL_XLF;
}
/* get length element value from can[|fd|xl]_frame structure */
static inline unsigned int can_skb_get_len_val(struct sk_buff *skb)
{
const struct canxl_frame *cxl = (struct canxl_frame *)skb->data;
const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
if (can_is_canxl_skb(skb))
return cxl->len;
return cfd->len;
}
/* get needed data length inside CAN frame for all frame types (RTR aware) */
static inline unsigned int can_skb_get_data_len(struct sk_buff *skb)
{
unsigned int len = can_skb_get_len_val(skb);
const struct can_frame *cf = (struct can_frame *)skb->data;
/* RTR frames have an actual length of zero */
if (can_is_can_skb(skb) && cf->can_id & CAN_RTR_FLAG)
return 0;
return len;
}
#endif /* !_CAN_SKB_H */
......@@ -48,6 +48,7 @@
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/stddef.h> /* for offsetof */
/* controller area network (CAN) kernel definitions */
......@@ -60,6 +61,7 @@
#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
#define CANXL_PRIO_MASK CAN_SFF_MASK /* 11 bit priority mask */
/*
* Controller Area Network Identifier structure
......@@ -73,6 +75,7 @@ typedef __u32 canid_t;
#define CAN_SFF_ID_BITS 11
#define CAN_EFF_ID_BITS 29
#define CANXL_PRIO_BITS CAN_SFF_ID_BITS
/*
* Controller Area Network Error Message Frame Mask structure
......@@ -91,6 +94,16 @@ typedef __u32 can_err_mask_t;
#define CANFD_MAX_DLC 15
#define CANFD_MAX_DLEN 64
/*
* CAN XL payload length and DLC definitions according to ISO 11898-1
* CAN XL DLC ranges from 0 .. 2047 => data length from 1 .. 2048 byte
*/
#define CANXL_MIN_DLC 0
#define CANXL_MAX_DLC 2047
#define CANXL_MAX_DLC_MASK 0x07FF
#define CANXL_MIN_DLEN 1
#define CANXL_MAX_DLEN 2048
/**
* struct can_frame - Classical CAN frame structure (aka CAN 2.0B)
* @can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition
......@@ -141,8 +154,8 @@ struct can_frame {
* When this is done the former differentiation via CAN_MTU / CANFD_MTU gets
* lost. CANFD_FDF allows programmers to mark CAN FD frames in the case of
* using struct canfd_frame for mixed CAN / CAN FD content (dual use).
* N.B. the Kernel APIs do NOT provide mixed CAN / CAN FD content inside of
* struct canfd_frame therefore the CANFD_FDF flag is disregarded by Linux.
* Since the introduction of CAN XL the CANFD_FDF flag is set in all CAN FD
* frame structures provided by the CAN subsystem of the Linux kernel.
*/
#define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */
#define CANFD_ESI 0x02 /* error state indicator of the transmitting node */
......@@ -166,8 +179,46 @@ struct canfd_frame {
__u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
};
/*
* defined bits for canxl_frame.flags
*
* The canxl_frame.flags element contains two bits CANXL_XLF and CANXL_SEC
* and shares the relative position of the struct can[fd]_frame.len element.
* The CANXL_XLF bit ALWAYS needs to be set to indicate a valid CAN XL frame.
* As a side effect setting this bit intentionally breaks the length checks
* for Classical CAN and CAN FD frames.
*
* Undefined bits in canxl_frame.flags are reserved and shall be set to zero.
*/
#define CANXL_XLF 0x80 /* mandatory CAN XL frame flag (must always be set!) */
#define CANXL_SEC 0x01 /* Simple Extended Content (security/segmentation) */
/**
* struct canxl_frame - CAN with e'X'tended frame 'L'ength frame structure
* @prio: 11 bit arbitration priority with zero'ed CAN_*_FLAG flags
* @flags: additional flags for CAN XL
* @sdt: SDU (service data unit) type
* @len: frame payload length in byte (CANXL_MIN_DLEN .. CANXL_MAX_DLEN)
* @af: acceptance field
* @data: CAN XL frame payload (CANXL_MIN_DLEN .. CANXL_MAX_DLEN byte)
*
* @prio shares the same position as @can_id from struct can[fd]_frame.
*/
struct canxl_frame {
canid_t prio; /* 11 bit priority for arbitration (canid_t) */
__u8 flags; /* additional flags for CAN XL */
__u8 sdt; /* SDU (service data unit) type */
__u16 len; /* frame payload length in byte */
__u32 af; /* acceptance field */
__u8 data[CANXL_MAX_DLEN];
};
#define CAN_MTU (sizeof(struct can_frame))
#define CANFD_MTU (sizeof(struct canfd_frame))
#define CANXL_MTU (sizeof(struct canxl_frame))
#define CANXL_HDR_SIZE (offsetof(struct canxl_frame, data))
#define CANXL_MIN_MTU (CANXL_HDR_SIZE + 64)
#define CANXL_MAX_MTU CANXL_MTU
/* particular protocols of the protocol family PF_CAN */
#define CAN_RAW 1 /* RAW sockets */
......
......@@ -62,6 +62,7 @@ enum {
CAN_RAW_RECV_OWN_MSGS, /* receive my own msgs (default:off) */
CAN_RAW_FD_FRAMES, /* allow CAN FD frames (default:off) */
CAN_RAW_JOIN_FILTERS, /* all filters must match to trigger */
CAN_RAW_XL_FRAMES, /* allow CAN XL frames (default:off) */
};
#endif /* !_UAPI_CAN_RAW_H */
......@@ -138,6 +138,7 @@
#define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudo type */
#define ETH_P_CAN 0x000C /* CAN: Controller Area Network */
#define ETH_P_CANFD 0x000D /* CANFD: CAN flexible data rate*/
#define ETH_P_CANXL 0x000E /* CANXL: eXtended frame Length */
#define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/
#define ETH_P_TR_802_2 0x0011 /* 802.2 frames */
#define ETH_P_MOBITEX 0x0015 /* Mobitex (kaz@cafe.net) */
......
......@@ -199,27 +199,26 @@ static int can_create(struct net *net, struct socket *sock, int protocol,
int can_send(struct sk_buff *skb, int loop)
{
struct sk_buff *newskb = NULL;
struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
struct can_pkg_stats *pkg_stats = dev_net(skb->dev)->can.pkg_stats;
int err = -EINVAL;
if (skb->len == CAN_MTU) {
if (can_is_canxl_skb(skb)) {
skb->protocol = htons(ETH_P_CANXL);
} else if (can_is_can_skb(skb)) {
skb->protocol = htons(ETH_P_CAN);
if (unlikely(cfd->len > CAN_MAX_DLEN))
goto inval_skb;
} else if (skb->len == CANFD_MTU) {
} else if (can_is_canfd_skb(skb)) {
struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
skb->protocol = htons(ETH_P_CANFD);
if (unlikely(cfd->len > CANFD_MAX_DLEN))
goto inval_skb;
/* set CAN FD flag for CAN FD frames by default */
cfd->flags |= CANFD_FDF;
} else {
goto inval_skb;
}
/* Make sure the CAN frame can pass the selected CAN netdevice.
* As structs can_frame and canfd_frame are similar, we can provide
* CAN FD frames to legacy CAN drivers as long as the length is <= 8
*/
if (unlikely(skb->len > skb->dev->mtu && cfd->len > CAN_MAX_DLEN)) {
/* Make sure the CAN frame can pass the selected CAN netdevice. */
if (unlikely(skb->len > skb->dev->mtu)) {
err = -EMSGSIZE;
goto inval_skb;
}
......@@ -678,53 +677,46 @@ static void can_receive(struct sk_buff *skb, struct net_device *dev)
static int can_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
{
struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
if (unlikely(dev->type != ARPHRD_CAN || skb->len != CAN_MTU)) {
if (unlikely(dev->type != ARPHRD_CAN || (!can_is_can_skb(skb)))) {
pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d\n",
dev->type, skb->len);
goto free_skb;
}
/* This check is made separately since cfd->len would be uninitialized if skb->len = 0. */
if (unlikely(cfd->len > CAN_MAX_DLEN)) {
pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d, datalen %d\n",
dev->type, skb->len, cfd->len);
goto free_skb;
kfree_skb(skb);
return NET_RX_DROP;
}
can_receive(skb, dev);
return NET_RX_SUCCESS;
free_skb:
kfree_skb(skb);
return NET_RX_DROP;
}
static int canfd_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
{
struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
if (unlikely(dev->type != ARPHRD_CAN || skb->len != CANFD_MTU)) {
if (unlikely(dev->type != ARPHRD_CAN || (!can_is_canfd_skb(skb)))) {
pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d\n",
dev->type, skb->len);
goto free_skb;
}
/* This check is made separately since cfd->len would be uninitialized if skb->len = 0. */
if (unlikely(cfd->len > CANFD_MAX_DLEN)) {
pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d, datalen %d\n",
dev->type, skb->len, cfd->len);
goto free_skb;
kfree_skb(skb);
return NET_RX_DROP;
}
can_receive(skb, dev);
return NET_RX_SUCCESS;
}
free_skb:
kfree_skb(skb);
return NET_RX_DROP;
static int canxl_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
{
if (unlikely(dev->type != ARPHRD_CAN || (!can_is_canxl_skb(skb)))) {
pr_warn_once("PF_CAN: dropped non conform CAN XL skbuff: dev type %d, len %d\n",
dev->type, skb->len);
kfree_skb(skb);
return NET_RX_DROP;
}
can_receive(skb, dev);
return NET_RX_SUCCESS;
}
/* af_can protocol functions */
......@@ -851,6 +843,11 @@ static struct packet_type canfd_packet __read_mostly = {
.func = canfd_rcv,
};
static struct packet_type canxl_packet __read_mostly = {
.type = cpu_to_be16(ETH_P_CANXL),
.func = canxl_rcv,
};
static const struct net_proto_family can_family_ops = {
.family = PF_CAN,
.create = can_create,
......@@ -890,6 +887,7 @@ static __init int can_init(void)
dev_add_pack(&can_packet);
dev_add_pack(&canfd_packet);
dev_add_pack(&canxl_packet);
return 0;
......
......@@ -648,8 +648,13 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
return;
/* make sure to handle the correct frame type (CAN / CAN FD) */
if (skb->len != op->cfsiz)
return;
if (op->flags & CAN_FD_FRAME) {
if (!can_is_canfd_skb(skb))
return;
} else {
if (!can_is_can_skb(skb))
return;
}
/* disable timeout */
hrtimer_cancel(&op->timer);
......
......@@ -463,10 +463,10 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
/* process strictly Classic CAN or CAN FD frames */
if (gwj->flags & CGW_FLAGS_CAN_FD) {
if (skb->len != CANFD_MTU)
if (!can_is_canfd_skb(skb))
return;
} else {
if (skb->len != CAN_MTU)
if (!can_is_can_skb(skb))
return;
}
......
......@@ -669,7 +669,7 @@ static void isotp_rcv(struct sk_buff *skb, void *data)
if (cf->len <= CAN_MAX_DLEN) {
isotp_rcv_sf(sk, cf, SF_PCI_SZ4 + ae, skb, sf_dl);
} else {
if (skb->len == CANFD_MTU) {
if (can_is_canfd_skb(skb)) {
/* We have a CAN FD frame and CAN_DL is greater than 8:
* Only frames with the SF_DL == 0 ESC value are valid.
*
......
......@@ -42,6 +42,10 @@ static void j1939_can_recv(struct sk_buff *iskb, void *data)
struct j1939_sk_buff_cb *skcb, *iskcb;
struct can_frame *cf;
/* make sure we only get Classical CAN frames */
if (!can_is_can_skb(iskb))
return;
/* create a copy of the skb
* j1939 only delivers the real data bytes,
* the header goes into sockaddr.
......
......@@ -50,6 +50,7 @@
#include <linux/skbuff.h>
#include <linux/can.h>
#include <linux/can/core.h>
#include <linux/can/dev.h> /* for can_is_canxl_dev_mtu() */
#include <linux/can/skb.h>
#include <linux/can/raw.h>
#include <net/sock.h>
......@@ -87,6 +88,7 @@ struct raw_sock {
int loopback;
int recv_own_msgs;
int fd_frames;
int xl_frames;
int join_filters;
int count; /* number of active filters */
struct can_filter dfilter; /* default/single filter */
......@@ -129,21 +131,21 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
if (!ro->recv_own_msgs && oskb->sk == sk)
return;
/* do not pass non-CAN2.0 frames to a legacy socket */
if (!ro->fd_frames && oskb->len != CAN_MTU)
/* make sure to not pass oversized frames to the socket */
if ((can_is_canfd_skb(oskb) && !ro->fd_frames && !ro->xl_frames) ||
(can_is_canxl_skb(oskb) && !ro->xl_frames))
return;
/* eliminate multiple filter matches for the same skb */
if (this_cpu_ptr(ro->uniq)->skb == oskb &&
this_cpu_ptr(ro->uniq)->skbcnt == can_skb_prv(oskb)->skbcnt) {
if (ro->join_filters) {
this_cpu_inc(ro->uniq->join_rx_count);
/* drop frame until all enabled filters matched */
if (this_cpu_ptr(ro->uniq)->join_rx_count < ro->count)
return;
} else {
if (!ro->join_filters)
return;
this_cpu_inc(ro->uniq->join_rx_count);
/* drop frame until all enabled filters matched */
if (this_cpu_ptr(ro->uniq)->join_rx_count < ro->count)
return;
}
} else {
this_cpu_ptr(ro->uniq)->skb = oskb;
this_cpu_ptr(ro->uniq)->skbcnt = can_skb_prv(oskb)->skbcnt;
......@@ -346,6 +348,7 @@ static int raw_init(struct sock *sk)
ro->loopback = 1;
ro->recv_own_msgs = 0;
ro->fd_frames = 0;
ro->xl_frames = 0;
ro->join_filters = 0;
/* alloc_percpu provides zero'ed memory */
......@@ -669,6 +672,15 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
break;
case CAN_RAW_XL_FRAMES:
if (optlen != sizeof(ro->xl_frames))
return -EINVAL;
if (copy_from_sockptr(&ro->xl_frames, optval, optlen))
return -EFAULT;
break;
case CAN_RAW_JOIN_FILTERS:
if (optlen != sizeof(ro->join_filters))
return -EINVAL;
......@@ -751,6 +763,12 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
val = &ro->fd_frames;
break;
case CAN_RAW_XL_FRAMES:
if (len > sizeof(int))
len = sizeof(int);
val = &ro->xl_frames;
break;
case CAN_RAW_JOIN_FILTERS:
if (len > sizeof(int))
len = sizeof(int);
......@@ -776,7 +794,11 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
struct sk_buff *skb;
struct net_device *dev;
int ifindex;
int err;
int err = -EINVAL;
/* check for valid CAN frame sizes */
if (size < CANXL_HDR_SIZE + CANXL_MIN_DLEN || size > CANXL_MTU)
return -EINVAL;
if (msg->msg_name) {
DECLARE_SOCKADDR(struct sockaddr_can *, addr, msg->msg_name);
......@@ -796,15 +818,6 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
if (!dev)
return -ENXIO;
err = -EINVAL;
if (ro->fd_frames && dev->mtu == CANFD_MTU) {
if (unlikely(size != CANFD_MTU && size != CAN_MTU))
goto put_dev;
} else {
if (unlikely(size != CAN_MTU))
goto put_dev;
}
skb = sock_alloc_send_skb(sk, size + sizeof(struct can_skb_priv),
msg->msg_flags & MSG_DONTWAIT, &err);
if (!skb)
......@@ -814,10 +827,27 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
can_skb_prv(skb)->ifindex = dev->ifindex;
can_skb_prv(skb)->skbcnt = 0;
/* fill the skb before testing for valid CAN frames */
err = memcpy_from_msg(skb_put(skb, size), msg, size);
if (err < 0)
goto free_skb;
err = -EINVAL;
if (ro->xl_frames && can_is_canxl_dev_mtu(dev->mtu)) {
/* CAN XL, CAN FD and Classical CAN */
if (!can_is_canxl_skb(skb) && !can_is_canfd_skb(skb) &&
!can_is_can_skb(skb))
goto free_skb;
} else if (ro->fd_frames && dev->mtu == CANFD_MTU) {
/* CAN FD and Classical CAN */
if (!can_is_canfd_skb(skb) && !can_is_can_skb(skb))
goto free_skb;
} else {
/* Classical CAN */
if (!can_is_can_skb(skb))
goto free_skb;
}
sockcm_init(&sockc, sk);
if (msg->msg_controllen) {
err = sock_cmsg_send(sk, msg, &sockc);
......@@ -942,12 +972,20 @@ static __init int raw_module_init(void)
pr_info("can: raw protocol\n");
err = register_netdevice_notifier(&canraw_notifier);
if (err)
return err;
err = can_proto_register(&raw_can_proto);
if (err < 0)
if (err < 0) {
pr_err("can: registration of raw protocol failed\n");
else
register_netdevice_notifier(&canraw_notifier);
goto register_proto_failed;
}
return 0;
register_proto_failed:
unregister_netdevice_notifier(&canraw_notifier);
return err;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment