Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3879d4e3 authored by David S. Miller's avatar David S. Miller
Browse files


Marc Kleine-Budde says:

====================
here is our second pull request for net-next. In this series Federico
Vaga adds a pci driver for c_can/d_can hardware using the existing
generic c_can driver. The remaining 6 patches are by Oliver Hartkopp.
He adds CANFD support to the CAN stack while keeping binary
compatibility for existing applications. CANFD is an extension to the
existing CAN standard, it allows longer CAN frames and/or higher data
rates. There's no real hardware available yet, but this series adds
CANFD support to the vcan driver.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a77f4b4a ea53fe0c
Loading
Loading
Loading
Loading
+146 −8
Original line number Diff line number Diff line
@@ -22,7 +22,8 @@ This file contains
      4.1.2 RAW socket option CAN_RAW_ERR_FILTER
      4.1.3 RAW socket option CAN_RAW_LOOPBACK
      4.1.4 RAW socket option CAN_RAW_RECV_OWN_MSGS
      4.1.5 RAW socket returned message flags
      4.1.5 RAW socket option CAN_RAW_FD_FRAMES
      4.1.6 RAW socket returned message flags
    4.2 Broadcast Manager protocol sockets (SOCK_DGRAM)
    4.3 connected transport protocols (SOCK_SEQPACKET)
    4.4 unconnected transport protocols (SOCK_DGRAM)
@@ -41,7 +42,8 @@ This file contains
      6.5.1 Netlink interface to set/get devices properties
      6.5.2 Setting the CAN bit-timing
      6.5.3 Starting and stopping the CAN network device
    6.6 supported CAN hardware
    6.6 CAN FD (flexible data rate) driver support
    6.7 supported CAN hardware

  7 Socket CAN resources

@@ -273,7 +275,7 @@ solution for a couple of reasons:

    struct can_frame {
            canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
            __u8    can_dlc; /* data length code: 0 .. 8 */
            __u8    can_dlc; /* frame payload length in byte (0 .. 8) */
            __u8    data[8] __attribute__((aligned(8)));
    };

@@ -375,6 +377,51 @@ solution for a couple of reasons:
    nbytes = sendto(s, &frame, sizeof(struct can_frame),
                    0, (struct sockaddr*)&addr, sizeof(addr));

  Remark about CAN FD (flexible data rate) support:

  Generally the handling of CAN FD is very similar to the formerly described
  examples. The new CAN FD capable CAN controllers support two different
  bitrates for the arbitration phase and the payload phase of the CAN FD frame
  and up to 64 bytes of payload. This extended payload length breaks all the
  kernel interfaces (ABI) which heavily rely on the CAN frame with fixed eight
  bytes of payload (struct can_frame) like the CAN_RAW socket. Therefore e.g.
  the CAN_RAW socket supports a new socket option CAN_RAW_FD_FRAMES that
  switches the socket into a mode that allows the handling of CAN FD frames
  and (legacy) CAN frames simultaneously (see section 4.1.5).

  The struct canfd_frame is defined in include/linux/can.h:

    struct canfd_frame {
            canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
            __u8    len;     /* frame payload length in byte (0 .. 64) */
            __u8    flags;   /* additional flags for CAN FD */
            __u8    __res0;  /* reserved / padding */
            __u8    __res1;  /* reserved / padding */
            __u8    data[64] __attribute__((aligned(8)));
    };

  The struct canfd_frame and the existing struct can_frame have the can_id,
  the payload length and the payload data at the same offset inside their
  structures. This allows to handle the different structures very similar.
  When the content of a struct can_frame is copied into a struct canfd_frame
  all structure elements can be used as-is - only the data[] becomes extended.

  When introducing the struct canfd_frame it turned out that the data length
  code (DLC) of the struct can_frame was used as a length information as the
  length and the DLC has a 1:1 mapping in the range of 0 .. 8. To preserve
  the easy handling of the length information the canfd_frame.len element
  contains a plain length value from 0 .. 64. So both canfd_frame.len and
  can_frame.can_dlc are equal and contain a length information and no DLC.
  For details about the distinction of CAN and CAN FD capable devices and
  the mapping to the bus-relevant data length code (DLC), see chapter 6.6.

  The length of the two CAN(FD) frame structures define the maximum transfer
  unit (MTU) of the CAN(FD) network interface and skbuff data length. Two
  definitions are specified for CAN specific MTUs in include/linux/can.h :

  #define CAN_MTU   (sizeof(struct can_frame))   == 16  => 'legacy' CAN frame
  #define CANFD_MTU (sizeof(struct canfd_frame)) == 72  => CAN FD frame

  4.1 RAW protocol sockets with can_filters (SOCK_RAW)

  Using CAN_RAW sockets is extensively comparable to the commonly
@@ -472,7 +519,69 @@ solution for a couple of reasons:
    setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
               &recv_own_msgs, sizeof(recv_own_msgs));

  4.1.5 RAW socket returned message flags
  4.1.5 RAW socket option CAN_RAW_FD_FRAMES

  CAN FD support in CAN_RAW sockets can be enabled with a new socket option
  CAN_RAW_FD_FRAMES which is off by default. When the new socket option is
  not supported by the CAN_RAW socket (e.g. on older kernels), switching the
  CAN_RAW_FD_FRAMES option returns the error -ENOPROTOOPT.

  Once CAN_RAW_FD_FRAMES is enabled the application can send both CAN frames
  and CAN FD frames. OTOH the application has to handle CAN and CAN FD frames
  when reading from the socket.

    CAN_RAW_FD_FRAMES enabled:  CAN_MTU and CANFD_MTU are allowed
    CAN_RAW_FD_FRAMES disabled: only CAN_MTU is allowed (default)

  Example:
    [ remember: CANFD_MTU == sizeof(struct canfd_frame) ]

    struct canfd_frame cfd;

    nbytes = read(s, &cfd, CANFD_MTU);

    if (nbytes == CANFD_MTU) {
            printf("got CAN FD frame with length %d\n", cfd.len);
	    /* cfd.flags contains valid data */
    } else if (nbytes == CAN_MTU) {
            printf("got legacy CAN frame with length %d\n", cfd.len);
	    /* cfd.flags is undefined */
    } else {
            fprintf(stderr, "read: invalid CAN(FD) frame\n");
            return 1;
    }

    /* the content can be handled independently from the received MTU size */

    printf("can_id: %X data length: %d data: ", cfd.can_id, cfd.len);
    for (i = 0; i < cfd.len; i++)
            printf("%02X ", cfd.data[i]);

  When reading with size CANFD_MTU only returns CAN_MTU bytes that have
  been received from the socket a legacy CAN frame has been read into the
  provided CAN FD structure. Note that the canfd_frame.flags data field is
  not specified in the struct can_frame and therefore it is only valid in
  CANFD_MTU sized CAN FD frames.

  As long as the payload length is <=8 the received CAN frames from CAN FD
  capable CAN devices can be received and read by legacy sockets too. When
  user-generated CAN FD frames have a payload length <=8 these can be send
  by legacy CAN network interfaces too. Sending CAN FD frames with payload
  length > 8 to a legacy CAN network interface returns an -EMSGSIZE error.

  Implementation hint for new CAN applications:

  To build a CAN FD aware application use struct canfd_frame as basic CAN
  data structure for CAN_RAW based applications. When the application is
  executed on an older Linux kernel and switching the CAN_RAW_FD_FRAMES
  socket option returns an error: No problem. You'll get legacy CAN frames
  or CAN FD frames and can process them the same way.

  When sending to CAN devices make sure that the device is capable to handle
  CAN FD frames by checking if the device maximum transfer unit is CANFD_MTU.
  The CAN device MTU can be retrieved e.g. with a SIOCGIFMTU ioctl() syscall.

  4.1.6 RAW socket returned message flags

  When using recvmsg() call, the msg->msg_flags may contain following flags:

@@ -573,10 +682,13 @@ solution for a couple of reasons:
    dev->type  = ARPHRD_CAN; /* the netdevice hardware type */
    dev->flags = IFF_NOARP;  /* CAN has no arp */

    dev->mtu   = sizeof(struct can_frame);
    dev->mtu = CAN_MTU; /* sizeof(struct can_frame) -> legacy CAN interface */

  The struct can_frame is the payload of each socket buffer in the
  protocol family PF_CAN.
    or alternative, when the controller supports CAN with flexible data rate:
    dev->mtu = CANFD_MTU; /* sizeof(struct canfd_frame) -> CAN FD interface */

  The struct can_frame or struct canfd_frame is the payload of each socket
  buffer (skbuff) in the protocol family PF_CAN.

  6.2 local loopback of sent frames

@@ -792,7 +904,33 @@ solution for a couple of reasons:
  Note that a restart will also create a CAN error message frame (see
  also chapter 3.4).

  6.6 Supported CAN hardware
  6.6 CAN FD (flexible data rate) driver support

  CAN FD capable CAN controllers support two different bitrates for the
  arbitration phase and the payload phase of the CAN FD frame. Therefore a
  second bittiming has to be specified in order to enable the CAN FD bitrate.

  Additionally CAN FD capable CAN controllers support up to 64 bytes of
  payload. The representation of this length in can_frame.can_dlc and
  canfd_frame.len for userspace applications and inside the Linux network
  layer is a plain value from 0 .. 64 instead of the CAN 'data length code'.
  The data length code was a 1:1 mapping to the payload length in the legacy
  CAN frames anyway. The payload length to the bus-relevant DLC mapping is
  only performed inside the CAN drivers, preferably with the helper
  functions can_dlc2len() and can_len2dlc().

  The CAN netdevice driver capabilities can be distinguished by the network
  devices maximum transfer unit (MTU):

  MTU = 16 (CAN_MTU)   => sizeof(struct can_frame)   => 'legacy' CAN device
  MTU = 72 (CANFD_MTU) => sizeof(struct canfd_frame) => CAN FD capable device

  The CAN device MTU can be retrieved e.g. with a SIOCGIFMTU ioctl() syscall.
  N.B. CAN FD capable devices can also handle and send legacy CAN frames.

  FIXME: Add details about the CAN FD controller configuration when available.

  6.7 Supported CAN hardware

  Please check the "Kconfig" file in "drivers/net/can" to get an actual
  list of the support CAN hardware. On the Socket CAN project website
+7 −0
Original line number Diff line number Diff line
@@ -13,4 +13,11 @@ config CAN_C_CAN_PLATFORM
	  boards from ST Microelectronics (http://www.st.com) like the
	  SPEAr1310 and SPEAr320 evaluation boards & TI (www.ti.com)
	  boards like am335x, dm814x, dm813x and dm811x.

config CAN_C_CAN_PCI
	tristate "Generic PCI Bus based C_CAN/D_CAN driver"
	depends on PCI
	---help---
	  This driver adds support for the C_CAN/D_CAN chips connected
	  to the PCI bus.
endif
+1 −0
Original line number Diff line number Diff line
@@ -4,5 +4,6 @@

obj-$(CONFIG_CAN_C_CAN) += c_can.o
obj-$(CONFIG_CAN_C_CAN_PLATFORM) += c_can_platform.o
obj-$(CONFIG_CAN_C_CAN_PCI) += c_can_pci.o

ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
+236 −0
Original line number Diff line number Diff line
/*
 * PCI bus driver for Bosch C_CAN/D_CAN controller
 *
 * Copyright (C) 2012 Federico Vaga <federico.vaga@gmail.com>
 *
 * Borrowed from c_can_platform.c
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2. This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/clk.h>
#include <linux/pci.h>

#include <linux/can/dev.h>

#include "c_can.h"

enum c_can_pci_reg_align {
	C_CAN_REG_ALIGN_16,
	C_CAN_REG_ALIGN_32,
};

struct c_can_pci_data {
	/* Specify if is C_CAN or D_CAN */
	enum c_can_dev_id type;
	/* Set the register alignment in the memory */
	enum c_can_pci_reg_align reg_align;
	/* Set the frequency if clk is not usable */
	unsigned int freq;
};

/*
 * 16-bit c_can registers can be arranged differently in the memory
 * architecture of different implementations. For example: 16-bit
 * registers can be aligned to a 16-bit boundary or 32-bit boundary etc.
 * Handle the same by providing a common read/write interface.
 */
static u16 c_can_pci_read_reg_aligned_to_16bit(struct c_can_priv *priv,
						enum reg index)
{
	return readw(priv->base + priv->regs[index]);
}

static void c_can_pci_write_reg_aligned_to_16bit(struct c_can_priv *priv,
						enum reg index, u16 val)
{
	writew(val, priv->base + priv->regs[index]);
}

static u16 c_can_pci_read_reg_aligned_to_32bit(struct c_can_priv *priv,
						enum reg index)
{
	return readw(priv->base + 2 * priv->regs[index]);
}

static void c_can_pci_write_reg_aligned_to_32bit(struct c_can_priv *priv,
						enum reg index, u16 val)
{
	writew(val, priv->base + 2 * priv->regs[index]);
}

static int __devinit c_can_pci_probe(struct pci_dev *pdev,
				     const struct pci_device_id *ent)
{
	struct c_can_pci_data *c_can_pci_data = (void *)ent->driver_data;
	struct c_can_priv *priv;
	struct net_device *dev;
	void __iomem *addr;
	struct clk *clk;
	int ret;

	ret = pci_enable_device(pdev);
	if (ret) {
		dev_err(&pdev->dev, "pci_enable_device FAILED\n");
		goto out;
	}

	ret = pci_request_regions(pdev, KBUILD_MODNAME);
	if (ret) {
		dev_err(&pdev->dev, "pci_request_regions FAILED\n");
		goto out_disable_device;
	}

	pci_set_master(pdev);
	pci_enable_msi(pdev);

	addr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
	if (!addr) {
		dev_err(&pdev->dev,
			"device has no PCI memory resources, "
			"failing adapter\n");
		ret = -ENOMEM;
		goto out_release_regions;
	}

	/* allocate the c_can device */
	dev = alloc_c_can_dev();
	if (!dev) {
		ret = -ENOMEM;
		goto out_iounmap;
	}

	priv = netdev_priv(dev);
	pci_set_drvdata(pdev, dev);
	SET_NETDEV_DEV(dev, &pdev->dev);

	dev->irq = pdev->irq;
	priv->base = addr;

	if (!c_can_pci_data->freq) {
		/* get the appropriate clk */
		clk = clk_get(&pdev->dev, NULL);
		if (IS_ERR(clk)) {
			dev_err(&pdev->dev, "no clock defined\n");
			ret = -ENODEV;
			goto out_free_c_can;
		}
		priv->can.clock.freq = clk_get_rate(clk);
		priv->priv = clk;
	} else {
		priv->can.clock.freq = c_can_pci_data->freq;
		priv->priv = NULL;
	}

	/* Configure CAN type */
	switch (c_can_pci_data->type) {
	case C_CAN_DEVTYPE:
		priv->regs = reg_map_c_can;
		break;
	case D_CAN_DEVTYPE:
		priv->regs = reg_map_d_can;
		priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
		break;
	default:
		ret = -EINVAL;
		goto out_free_clock;
	}

	/* Configure access to registers */
	switch (c_can_pci_data->reg_align) {
	case C_CAN_REG_ALIGN_32:
		priv->read_reg = c_can_pci_read_reg_aligned_to_32bit;
		priv->write_reg = c_can_pci_write_reg_aligned_to_32bit;
		break;
	case C_CAN_REG_ALIGN_16:
		priv->read_reg = c_can_pci_read_reg_aligned_to_16bit;
		priv->write_reg = c_can_pci_write_reg_aligned_to_16bit;
		break;
	default:
		ret = -EINVAL;
		goto out_free_clock;
	}

	ret = register_c_can_dev(dev);
	if (ret) {
		dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
			KBUILD_MODNAME, ret);
		goto out_free_clock;
	}

	dev_dbg(&pdev->dev, "%s device registered (regs=%p, irq=%d)\n",
		 KBUILD_MODNAME, priv->regs, dev->irq);

	return 0;

out_free_clock:
	if (priv->priv)
		clk_put(priv->priv);
out_free_c_can:
	pci_set_drvdata(pdev, NULL);
	free_c_can_dev(dev);
out_iounmap:
	pci_iounmap(pdev, addr);
out_release_regions:
	pci_disable_msi(pdev);
	pci_clear_master(pdev);
	pci_release_regions(pdev);
out_disable_device:
	pci_disable_device(pdev);
out:
	return ret;
}

static void __devexit c_can_pci_remove(struct pci_dev *pdev)
{
	struct net_device *dev = pci_get_drvdata(pdev);
	struct c_can_priv *priv = netdev_priv(dev);

	unregister_c_can_dev(dev);

	if (priv->priv)
		clk_put(priv->priv);

	pci_set_drvdata(pdev, NULL);
	free_c_can_dev(dev);

	pci_iounmap(pdev, priv->base);
	pci_disable_msi(pdev);
	pci_clear_master(pdev);
	pci_release_regions(pdev);
	pci_disable_device(pdev);
}

static struct c_can_pci_data c_can_sta2x11= {
	.type = C_CAN_DEVTYPE,
	.reg_align = C_CAN_REG_ALIGN_32,
	.freq = 52000000, /* 52 Mhz */
};

#define C_CAN_ID(_vend, _dev, _driverdata) {		\
	PCI_DEVICE(_vend, _dev),			\
	.driver_data = (unsigned long)&_driverdata,	\
}
static DEFINE_PCI_DEVICE_TABLE(c_can_pci_tbl) = {
	C_CAN_ID(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_CAN,
		 c_can_sta2x11),
	{},
};
static struct pci_driver c_can_pci_driver = {
	.name = KBUILD_MODNAME,
	.id_table = c_can_pci_tbl,
	.probe = c_can_pci_probe,
	.remove = __devexit_p(c_can_pci_remove),
};

module_pci_driver(c_can_pci_driver);

MODULE_AUTHOR("Federico Vaga <federico.vaga@gmail.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("PCI CAN bus driver for Bosch C_CAN/D_CAN controller");
MODULE_DEVICE_TABLE(pci, c_can_pci_tbl);
+34 −1
Original line number Diff line number Diff line
@@ -33,6 +33,39 @@ MODULE_DESCRIPTION(MOD_DESC);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");

/* CAN DLC to real data length conversion helpers */

static const u8 dlc2len[] = {0, 1, 2, 3, 4, 5, 6, 7,
			     8, 12, 16, 20, 24, 32, 48, 64};

/* get data length from can_dlc with sanitized can_dlc */
u8 can_dlc2len(u8 can_dlc)
{
	return dlc2len[can_dlc & 0x0F];
}
EXPORT_SYMBOL_GPL(can_dlc2len);

static const u8 len2dlc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8,		/* 0 - 8 */
			     9, 9, 9, 9,			/* 9 - 12 */
			     10, 10, 10, 10,			/* 13 - 16 */
			     11, 11, 11, 11,			/* 17 - 20 */
			     12, 12, 12, 12,			/* 21 - 24 */
			     13, 13, 13, 13, 13, 13, 13, 13,	/* 25 - 32 */
			     14, 14, 14, 14, 14, 14, 14, 14,	/* 33 - 40 */
			     14, 14, 14, 14, 14, 14, 14, 14,	/* 41 - 48 */
			     15, 15, 15, 15, 15, 15, 15, 15,	/* 49 - 56 */
			     15, 15, 15, 15, 15, 15, 15, 15};	/* 57 - 64 */

/* map the sanitized data length to an appropriate data length code */
u8 can_len2dlc(u8 len)
{
	if (unlikely(len > 64))
		return 0xF;

	return len2dlc[len];
}
EXPORT_SYMBOL_GPL(can_len2dlc);

#ifdef CONFIG_CAN_CALC_BITTIMING
#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */

@@ -454,7 +487,7 @@ EXPORT_SYMBOL_GPL(can_bus_off);
static void can_setup(struct net_device *dev)
{
	dev->type = ARPHRD_CAN;
	dev->mtu = sizeof(struct can_frame);
	dev->mtu = CAN_MTU;
	dev->hard_header_len = 0;
	dev->addr_len = 0;
	dev->tx_queue_len = 10;
Loading