Commit 9c0ee085 authored by David S. Miller's avatar David S. Miller

Merge tag 'linux-can-next-for-5.13-20210330' of...

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

Marc Kleine-Budde says:

====================
pull-request: can-next 2021-03-30

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

The first two patches update the MAINTAINERS file. One is by me and
removes Dan Murphy from the from m_can and tcan4x5x. The other one is
by Pankaj Sharma and updates the maintainership of the m-can mmio
driver.

The next three patches are by me and update the CAN echo skb handling.

Vincent Mailhol provides 5 patches where Transmitter Delay
Compensation is added CAN bittiming calculation is cleaned up.

The next patch is by me and adds a missing HAS_IOMEM to the grcan
driver.

Michal Simek's patch for the xilinx driver add dev_err_probe()
support.

Arnd Bergmann's patch for the ucan driver fixes a compiler warning.

Stephane Grosjean provides 3 patches for the peak USB drivers, which
add ethtool set_phys_id and CAN one-shot mode.

Xulin Sun's patch removes a not needed return check in the m-can
driver. Torin Cooper-Bennun provides 3 patches for the m-can driver
that add rx-offload support to ensure that skbs are sent from softirq
context. Wan Jiabing's patch for the tcan4x5x driver removes a
duplicate include.

The next 6 patches are by me and target the mcp251xfd driver. They add
devcoredump support, simplify the UINC handling, and add HW timestamp
support.

The remaining 12 patches target the c_can driver. The first 6 are by
me and do generic checkpatch related cleanup work. Dario Binacchi's
patches bring some cleanups and increase the number of usable message
objects from 16 to 64.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 402a66ed 132f2d45
......@@ -10910,8 +10910,7 @@ T: git git://linuxtv.org/media_tree.git
F: drivers/media/radio/radio-maxiradio*
MCAN MMIO DEVICE DRIVER
M: Dan Murphy <dmurphy@ti.com>
M: Pankaj Sharma <pankj.sharma@samsung.com>
M: Chandrasekar Ramakrishnan <rcsekar@samsung.com>
L: linux-can@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/net/can/bosch,m_can.yaml
......@@ -17983,13 +17982,6 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Odd Fixes
F: sound/soc/codecs/tas571x*
TI TCAN4X5X DEVICE DRIVER
M: Dan Murphy <dmurphy@ti.com>
L: linux-can@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/net/can/tcan4x5x.txt
F: drivers/net/can/m_can/tcan4x5x*
TI TRF7970A NFC DRIVER
M: Mark Greer <mgreer@animalcreek.com>
L: linux-wireless@vger.kernel.org
......
......@@ -103,7 +103,7 @@ config CAN_FLEXCAN
config CAN_GRCAN
tristate "Aeroflex Gaisler GRCAN and GRHCAN CAN devices"
depends on OF && HAS_DMA
depends on OF && HAS_DMA && HAS_IOMEM
help
Say Y here if you want to use Aeroflex Gaisler GRCAN or GRHCAN.
Note that the driver supports little endian, even though little
......
......@@ -132,7 +132,6 @@
/* For the high buffers we clear the interrupt bit and newdat */
#define IF_COMM_RCV_HIGH (IF_COMM_RCV_LOW | IF_COMM_CLR_NEWDAT)
/* Receive setup of message objects */
#define IF_COMM_RCV_SETUP (IF_COMM_MASK | IF_COMM_ARB | IF_COMM_CONTROL)
......@@ -161,9 +160,7 @@
#define IF_MCONT_TX (IF_MCONT_TXIE | IF_MCONT_EOB)
/*
* Use IF1 for RX and IF2 for TX
*/
/* Use IF1 for RX and IF2 for TX */
#define IF_RX 0
#define IF_TX 1
......@@ -173,9 +170,6 @@
/* Wait for ~1 sec for INIT bit */
#define INIT_WAIT_MS 1000
/* napi related */
#define C_CAN_NAPI_WEIGHT C_CAN_MSG_OBJ_RX_NUM
/* c_can lec values */
enum c_can_lec_type {
LEC_NO_ERROR = 0,
......@@ -189,8 +183,7 @@ enum c_can_lec_type {
LEC_MASK = LEC_UNUSED,
};
/*
* c_can error types:
/* c_can error types:
* Bus errors (BUS_OFF, ERROR_WARNING, ERROR_PASSIVE) are supported
*/
enum c_can_bus_error_types {
......@@ -253,7 +246,6 @@ static void c_can_obj_update(struct net_device *dev, int iface, u32 cmd, u32 obj
udelay(1);
}
netdev_err(dev, "Updating object timed out\n");
}
static inline void c_can_object_get(struct net_device *dev, int iface,
......@@ -268,8 +260,7 @@ static inline void c_can_object_put(struct net_device *dev, int iface,
c_can_obj_update(dev, iface, cmd | IF_COMM_WR, obj);
}
/*
* Note: According to documentation clearing TXIE while MSGVAL is set
/* Note: According to documentation clearing TXIE while MSGVAL is set
* is not allowed, but works nicely on C/DCAN. And that lowers the I/O
* load significantly.
*/
......@@ -285,8 +276,7 @@ static void c_can_inval_msg_object(struct net_device *dev, int iface, int obj)
{
struct c_can_priv *priv = netdev_priv(dev);
priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), 0);
priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), 0);
priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), 0);
c_can_inval_tx_object(dev, iface, obj);
}
......@@ -309,12 +299,11 @@ static void c_can_setup_tx_object(struct net_device *dev, int iface,
if (!rtr)
arb |= IF_ARB_TRANSMIT;
/*
* If we change the DIR bit, we need to invalidate the buffer
/* If we change the DIR bit, we need to invalidate the buffer
* first, i.e. clear the MSGVAL flag in the arbiter.
*/
if (rtr != (bool)test_bit(idx, &priv->tx_dir)) {
u32 obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
u32 obj = idx + priv->msg_obj_tx_first;
c_can_inval_msg_object(dev, iface, obj);
change_bit(idx, &priv->tx_dir);
......@@ -447,18 +436,16 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
if (can_dropped_invalid_skb(dev, skb))
return NETDEV_TX_OK;
/*
* This is not a FIFO. C/D_CAN sends out the buffers
/* This is not a FIFO. C/D_CAN sends out the buffers
* prioritized. The lowest buffer number wins.
*/
idx = fls(atomic_read(&priv->tx_active));
obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
obj = idx + priv->msg_obj_tx_first;
/* If this is the last buffer, stop the xmit queue */
if (idx == C_CAN_MSG_OBJ_TX_NUM - 1)
if (idx == priv->msg_obj_tx_num - 1)
netif_stop_queue(dev);
/*
* Store the message in the interface so we can call
/* Store the message in the interface so we can call
* can_put_echo_skb(). We must do this before we enable
* transmit as we might race against do_tx().
*/
......@@ -467,7 +454,7 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
can_put_echo_skb(skb, dev, idx, 0);
/* Update the active bits */
atomic_add((1 << idx), &priv->tx_active);
atomic_add(BIT(idx), &priv->tx_active);
/* Start transmission */
c_can_object_put(dev, IF_TX, obj, IF_COMM_TX);
......@@ -527,8 +514,7 @@ static int c_can_set_bittiming(struct net_device *dev)
return c_can_wait_for_ctrl_init(dev, priv, 0);
}
/*
* Configure C_CAN message objects for Tx and Rx purposes:
/* Configure C_CAN message objects for Tx and Rx purposes:
* C_CAN provides a total of 32 message objects that can be configured
* either for Tx or Rx purposes. Here the first 16 message objects are used as
* a reception FIFO. The end of reception FIFO is signified by the EoB bit
......@@ -538,17 +524,18 @@ static int c_can_set_bittiming(struct net_device *dev)
*/
static void c_can_configure_msg_objects(struct net_device *dev)
{
struct c_can_priv *priv = netdev_priv(dev);
int i;
/* first invalidate all message objects */
for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_NO_OF_OBJECTS; i++)
for (i = priv->msg_obj_rx_first; i <= priv->msg_obj_num; i++)
c_can_inval_msg_object(dev, IF_RX, i);
/* setup receive message objects */
for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++)
for (i = priv->msg_obj_rx_first; i < priv->msg_obj_rx_last; i++)
c_can_setup_receive_object(dev, IF_RX, i, 0, 0, IF_MCONT_RCV);
c_can_setup_receive_object(dev, IF_RX, C_CAN_MSG_OBJ_RX_LAST, 0, 0,
c_can_setup_receive_object(dev, IF_RX, priv->msg_obj_rx_last, 0, 0,
IF_MCONT_RCV_EOB);
}
......@@ -572,8 +559,7 @@ static int c_can_software_reset(struct net_device *dev)
return 0;
}
/*
* Configure C_CAN chip:
/* Configure C_CAN chip:
* - enable/disable auto-retransmission
* - set operating mode
* - configure message objects
......@@ -714,12 +700,21 @@ static void c_can_do_tx(struct net_device *dev)
struct net_device_stats *stats = &dev->stats;
u32 idx, obj, pkts = 0, bytes = 0, pend, clr;
clr = pend = priv->read_reg(priv, C_CAN_INTPND2_REG);
if (priv->msg_obj_tx_last > 32)
pend = priv->read_reg32(priv, C_CAN_INTPND3_REG);
else
pend = priv->read_reg(priv, C_CAN_INTPND2_REG);
clr = pend;
while ((idx = ffs(pend))) {
idx--;
pend &= ~(1 << idx);
obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
pend &= ~BIT(idx);
obj = idx + priv->msg_obj_tx_first;
/* We use IF_RX interface instead of IF_TX because we
* are called from c_can_poll(), which runs inside
* NAPI. We are not trasmitting.
*/
c_can_inval_tx_object(dev, IF_RX, obj);
can_get_echo_skb(dev, idx, NULL);
bytes += priv->dlc[idx];
......@@ -729,7 +724,7 @@ static void c_can_do_tx(struct net_device *dev)
/* Clear the bits in the tx_active mask */
atomic_sub(clr, &priv->tx_active);
if (clr & (1 << (C_CAN_MSG_OBJ_TX_NUM - 1)))
if (clr & BIT(priv->msg_obj_tx_num - 1))
netif_wake_queue(dev);
if (pkts) {
......@@ -739,20 +734,18 @@ static void c_can_do_tx(struct net_device *dev)
}
}
/*
* If we have a gap in the pending bits, that means we either
/* If we have a gap in the pending bits, that means we either
* raced with the hardware or failed to readout all upper
* objects in the last run due to quota limit.
*/
static u32 c_can_adjust_pending(u32 pend)
static u32 c_can_adjust_pending(u32 pend, u32 rx_mask)
{
u32 weight, lasts;
if (pend == RECEIVE_OBJECT_BITS)
if (pend == rx_mask)
return pend;
/*
* If the last set bit is larger than the number of pending
/* If the last set bit is larger than the number of pending
* bits we have a gap.
*/
weight = hweight32(pend);
......@@ -762,13 +755,13 @@ static u32 c_can_adjust_pending(u32 pend)
if (lasts == weight)
return pend;
/*
* Find the first set bit after the gap. We walk backwards
/* Find the first set bit after the gap. We walk backwards
* from the last set bit.
*/
for (lasts--; pend & (1 << (lasts - 1)); lasts--);
for (lasts--; pend & BIT(lasts - 1); lasts--)
;
return pend & ~((1 << lasts) - 1);
return pend & ~GENMASK(lasts - 1, 0);
}
static inline void c_can_rx_object_get(struct net_device *dev,
......@@ -803,8 +796,7 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
continue;
}
/*
* This really should not happen, but this covers some
/* This really should not happen, but this covers some
* odd HW behaviour. Do not remove that unless you
* want to brick your machine.
*/
......@@ -825,19 +817,22 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
static inline u32 c_can_get_pending(struct c_can_priv *priv)
{
u32 pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG);
u32 pend;
if (priv->msg_obj_rx_last > 16)
pend = priv->read_reg32(priv, C_CAN_NEWDAT1_REG);
else
pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG);
return pend;
}
/*
* theory of operation:
/* theory of operation:
*
* c_can core saves a received CAN message into the first free message
* object it finds free (starting with the lowest). Bits NEWDAT and
* INTPND are set for this message object indicating that a new message
* has arrived. To work-around this issue, we keep two groups of message
* objects whose partitioning is defined by C_CAN_MSG_OBJ_RX_SPLIT.
* has arrived.
*
* We clear the newdat bit right away.
*
......@@ -848,23 +843,16 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota)
struct c_can_priv *priv = netdev_priv(dev);
u32 pkts = 0, pend = 0, toread, n;
/*
* It is faster to read only one 16bit register. This is only possible
* for a maximum number of 16 objects.
*/
BUILD_BUG_ON_MSG(C_CAN_MSG_OBJ_RX_LAST > 16,
"Implementation does not support more message objects than 16");
while (quota > 0) {
if (!pend) {
pend = c_can_get_pending(priv);
if (!pend)
break;
/*
* If the pending field has a gap, handle the
/* If the pending field has a gap, handle the
* bits above the gap first.
*/
toread = c_can_adjust_pending(pend);
toread = c_can_adjust_pending(pend,
priv->msg_obj_rx_mask);
} else {
toread = pend;
}
......@@ -979,8 +967,7 @@ static int c_can_handle_bus_err(struct net_device *dev,
struct can_frame *cf;
struct sk_buff *skb;
/*
* early exit if no lec update or no error.
/* early exit if no lec update or no error.
* no lec update means that no CAN bus event has been detected
* since CPU wrote 0x7 value to status reg.
*/
......@@ -999,8 +986,7 @@ static int c_can_handle_bus_err(struct net_device *dev,
if (unlikely(!skb))
return 0;
/*
* check for 'last error code' which tells us the
/* check for 'last error code' which tells us the
* type of the last error to occur on the CAN bus
*/
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
......@@ -1049,7 +1035,8 @@ static int c_can_poll(struct napi_struct *napi, int quota)
/* Only read the status register if a status interrupt was pending */
if (atomic_xchg(&priv->sie_pending, 0)) {
priv->last_status = curr = priv->read_reg(priv, C_CAN_STS_REG);
priv->last_status = priv->read_reg(priv, C_CAN_STS_REG);
curr = priv->last_status;
/* Ack status on C_CAN. D_CAN is self clearing */
if (priv->type != BOSCH_D_CAN)
priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
......@@ -1195,17 +1182,31 @@ static int c_can_close(struct net_device *dev)
return 0;
}
struct net_device *alloc_c_can_dev(void)
struct net_device *alloc_c_can_dev(int msg_obj_num)
{
struct net_device *dev;
struct c_can_priv *priv;
int msg_obj_tx_num = msg_obj_num / 2;
dev = alloc_candev(sizeof(struct c_can_priv), C_CAN_MSG_OBJ_TX_NUM);
dev = alloc_candev(struct_size(priv, dlc, msg_obj_tx_num),
msg_obj_tx_num);
if (!dev)
return NULL;
priv = netdev_priv(dev);
netif_napi_add(dev, &priv->napi, c_can_poll, C_CAN_NAPI_WEIGHT);
priv->msg_obj_num = msg_obj_num;
priv->msg_obj_rx_num = msg_obj_num - msg_obj_tx_num;
priv->msg_obj_rx_first = 1;
priv->msg_obj_rx_last =
priv->msg_obj_rx_first + priv->msg_obj_rx_num - 1;
priv->msg_obj_rx_mask = GENMASK(priv->msg_obj_rx_num - 1, 0);
priv->msg_obj_tx_num = msg_obj_tx_num;
priv->msg_obj_tx_first = priv->msg_obj_rx_last + 1;
priv->msg_obj_tx_last =
priv->msg_obj_tx_first + priv->msg_obj_tx_num - 1;
netif_napi_add(dev, &priv->napi, c_can_poll, priv->msg_obj_rx_num);
priv->dev = dev;
priv->can.bittiming_const = &c_can_bittiming_const;
......
......@@ -22,23 +22,6 @@
#ifndef C_CAN_H
#define C_CAN_H
/* message object split */
#define C_CAN_NO_OF_OBJECTS 32
#define C_CAN_MSG_OBJ_RX_NUM 16
#define C_CAN_MSG_OBJ_TX_NUM 16
#define C_CAN_MSG_OBJ_RX_FIRST 1
#define C_CAN_MSG_OBJ_RX_LAST (C_CAN_MSG_OBJ_RX_FIRST + \
C_CAN_MSG_OBJ_RX_NUM - 1)
#define C_CAN_MSG_OBJ_TX_FIRST (C_CAN_MSG_OBJ_RX_LAST + 1)
#define C_CAN_MSG_OBJ_TX_LAST (C_CAN_MSG_OBJ_TX_FIRST + \
C_CAN_MSG_OBJ_TX_NUM - 1)
#define C_CAN_MSG_OBJ_RX_SPLIT 9
#define C_CAN_MSG_RX_LOW_LAST (C_CAN_MSG_OBJ_RX_SPLIT - 1)
#define RECEIVE_OBJECT_BITS 0x0000ffff
enum reg {
C_CAN_CTRL_REG = 0,
C_CAN_CTRL_EX_REG,
......@@ -76,6 +59,7 @@ enum reg {
C_CAN_NEWDAT2_REG,
C_CAN_INTPND1_REG,
C_CAN_INTPND2_REG,
C_CAN_INTPND3_REG,
C_CAN_MSGVAL1_REG,
C_CAN_MSGVAL2_REG,
C_CAN_FUNCTION_REG,
......@@ -137,6 +121,7 @@ static const u16 __maybe_unused reg_map_d_can[] = {
[C_CAN_NEWDAT2_REG] = 0x9E,
[C_CAN_INTPND1_REG] = 0xB0,
[C_CAN_INTPND2_REG] = 0xB2,
[C_CAN_INTPND3_REG] = 0xB4,
[C_CAN_MSGVAL1_REG] = 0xC4,
[C_CAN_MSGVAL2_REG] = 0xC6,
[C_CAN_IF1_COMREQ_REG] = 0x100,
......@@ -176,6 +161,7 @@ struct raminit_bits {
struct c_can_driver_data {
enum c_can_dev_id id;
unsigned int msg_obj_num;
/* RAMINIT register description. Optional. */
const struct raminit_bits *raminit_bits; /* Array of START/DONE bit positions */
......@@ -197,26 +183,34 @@ struct c_can_priv {
struct napi_struct napi;
struct net_device *dev;
struct device *device;
unsigned int msg_obj_num;
unsigned int msg_obj_rx_num;
unsigned int msg_obj_tx_num;
unsigned int msg_obj_rx_first;
unsigned int msg_obj_rx_last;
unsigned int msg_obj_tx_first;
unsigned int msg_obj_tx_last;
u32 msg_obj_rx_mask;
atomic_t tx_active;
atomic_t sie_pending;
unsigned long tx_dir;
int last_status;
u16 (*read_reg) (const struct c_can_priv *priv, enum reg index);
void (*write_reg) (const struct c_can_priv *priv, enum reg index, u16 val);
u32 (*read_reg32) (const struct c_can_priv *priv, enum reg index);
void (*write_reg32) (const struct c_can_priv *priv, enum reg index, u32 val);
u16 (*read_reg)(const struct c_can_priv *priv, enum reg index);
void (*write_reg)(const struct c_can_priv *priv, enum reg index, u16 val);
u32 (*read_reg32)(const struct c_can_priv *priv, enum reg index);
void (*write_reg32)(const struct c_can_priv *priv, enum reg index, u32 val);
void __iomem *base;
const u16 *regs;
void *priv; /* for board-specific data */
enum c_can_dev_id type;
struct c_can_raminit raminit_sys; /* RAMINIT via syscon regmap */
void (*raminit) (const struct c_can_priv *priv, bool enable);
void (*raminit)(const struct c_can_priv *priv, bool enable);
u32 comm_rcv_high;
u32 rxmasked;
u32 dlc[C_CAN_MSG_OBJ_TX_NUM];
u32 dlc[];
};
struct net_device *alloc_c_can_dev(void);
struct net_device *alloc_c_can_dev(int msg_obj_num);
void free_c_can_dev(struct net_device *dev);
int register_c_can_dev(struct net_device *dev);
void unregister_c_can_dev(struct net_device *dev);
......
......@@ -31,6 +31,8 @@ enum c_can_pci_reg_align {
struct c_can_pci_data {
/* Specify if is C_CAN or D_CAN */
enum c_can_dev_id type;
/* Number of message objects */
unsigned int msg_obj_num;
/* Set the register alignment in the memory */
enum c_can_pci_reg_align reg_align;
/* Set the frequency */
......@@ -41,8 +43,7 @@ struct c_can_pci_data {
void (*init)(const struct c_can_priv *priv, bool enable);
};
/*
* 16-bit c_can registers can be arranged differently in the memory
/* 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.
......@@ -88,7 +89,7 @@ static u32 c_can_pci_read_reg32(const struct c_can_priv *priv, enum reg index)
u32 val;
val = priv->read_reg(priv, index);
val |= ((u32) priv->read_reg(priv, index + 1)) << 16;
val |= ((u32)priv->read_reg(priv, index + 1)) << 16;
return val;
}
......@@ -142,14 +143,13 @@ static int c_can_pci_probe(struct pci_dev *pdev,
pci_resource_len(pdev, c_can_pci_data->bar));
if (!addr) {
dev_err(&pdev->dev,
"device has no PCI memory resources, "
"failing adapter\n");
"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();
dev = alloc_c_can_dev(c_can_pci_data->msg_obj_num);
if (!dev) {
ret = -ENOMEM;
goto out_iounmap;
......@@ -252,8 +252,9 @@ static void c_can_pci_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
static const struct c_can_pci_data c_can_sta2x11= {
static const struct c_can_pci_data c_can_sta2x11 = {
.type = BOSCH_C_CAN,
.msg_obj_num = 32,
.reg_align = C_CAN_REG_ALIGN_32,
.freq = 52000000, /* 52 Mhz */
.bar = 0,
......@@ -261,6 +262,7 @@ static const struct c_can_pci_data c_can_sta2x11= {
static const struct c_can_pci_data c_can_pch = {
.type = BOSCH_C_CAN,
.msg_obj_num = 32,
.reg_align = C_CAN_REG_32,
.freq = 50000000, /* 50 MHz */
.init = c_can_pci_reset_pch,
......@@ -269,7 +271,7 @@ static const struct c_can_pci_data c_can_pch = {
#define C_CAN_ID(_vend, _dev, _driverdata) { \
PCI_DEVICE(_vend, _dev), \
.driver_data = (unsigned long)&_driverdata, \
.driver_data = (unsigned long)&(_driverdata), \
}
static const struct pci_device_id c_can_pci_tbl[] = {
......@@ -279,6 +281,7 @@ static const struct pci_device_id c_can_pci_tbl[] = {
c_can_pch),
{},
};
static struct pci_driver c_can_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = c_can_pci_tbl,
......
......@@ -193,10 +193,12 @@ static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable)
static const struct c_can_driver_data c_can_drvdata = {
.id = BOSCH_C_CAN,
.msg_obj_num = 32,
};
static const struct c_can_driver_data d_can_drvdata = {
.id = BOSCH_D_CAN,
.msg_obj_num = 32,
};
static const struct raminit_bits dra7_raminit_bits[] = {
......@@ -206,6 +208,7 @@ static const struct raminit_bits dra7_raminit_bits[] = {
static const struct c_can_driver_data dra7_dcan_drvdata = {
.id = BOSCH_D_CAN,
.msg_obj_num = 64,
.raminit_num = ARRAY_SIZE(dra7_raminit_bits),
.raminit_bits = dra7_raminit_bits,
.raminit_pulse = true,
......@@ -218,6 +221,7 @@ static const struct raminit_bits am3352_raminit_bits[] = {
static const struct c_can_driver_data am3352_dcan_drvdata = {
.id = BOSCH_D_CAN,
.msg_obj_num = 64,
.raminit_num = ARRAY_SIZE(am3352_raminit_bits),
.raminit_bits = am3352_raminit_bits,
};
......@@ -294,7 +298,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
}
/* allocate the c_can device */
dev = alloc_c_can_dev();
dev = alloc_c_can_dev(drvdata->msg_obj_num);
if (!dev) {
ret = -ENOMEM;
goto exit;
......
......@@ -81,9 +81,9 @@ int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
if (bt->sample_point) {
sample_point_nominal = bt->sample_point;
} else {
if (bt->bitrate > 800000)
if (bt->bitrate > 800 * CAN_KBPS)
sample_point_nominal = 750;
else if (bt->bitrate > 500000)
else if (bt->bitrate > 500 * CAN_KBPS)
sample_point_nominal = 800;
else
sample_point_nominal = 875;
......@@ -174,6 +174,30 @@ int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
return 0;
}
void can_calc_tdco(struct net_device *dev)
{
struct can_priv *priv = netdev_priv(dev);
const struct can_bittiming *dbt = &priv->data_bittiming;
struct can_tdc *tdc = &priv->tdc;
const struct can_tdc_const *tdc_const = priv->tdc_const;
if (!tdc_const)
return;
/* As specified in ISO 11898-1 section 11.3.3 "Transmitter
* delay compensation" (TDC) is only applicable if data BRP is
* one or two.
*/
if (dbt->brp == 1 || dbt->brp == 2) {
/* Reuse "normal" sample point and convert it to time quanta */
u32 sample_point_in_tq = can_bit_time(dbt) * dbt->sample_point / 1000;
tdc->tdco = min(sample_point_in_tq, tdc_const->tdco_max);
} else {
tdc->tdco = 0;
}
}
#endif /* CONFIG_CAN_CALC_BITTIMING */
/* Checks the validity of the specified bit-timing parameters prop_seg,
......
......@@ -13,14 +13,11 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
[IFLA_CAN_RESTART_MS] = { .type = NLA_U32 },
[IFLA_CAN_RESTART] = { .type = NLA_U32 },
[IFLA_CAN_BITTIMING] = { .len = sizeof(struct can_bittiming) },
[IFLA_CAN_BITTIMING_CONST]
= { .len = sizeof(struct can_bittiming_const) },
[IFLA_CAN_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) },
[IFLA_CAN_CLOCK] = { .len = sizeof(struct can_clock) },
[IFLA_CAN_BERR_COUNTER] = { .len = sizeof(struct can_berr_counter) },
[IFLA_CAN_DATA_BITTIMING]
= { .len = sizeof(struct can_bittiming) },
[IFLA_CAN_DATA_BITTIMING_CONST]
= { .len = sizeof(struct can_bittiming_const) },
[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 },
};
......@@ -189,6 +186,8 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
memcpy(&priv->data_bittiming, &dbt, sizeof(dbt));
can_calc_tdco(dev);
if (priv->do_set_data_bittiming) {
/* Finally, set the bit-timing registers */
err = priv->do_set_data_bittiming(dev);
......
......@@ -45,7 +45,7 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
BUG_ON(idx >= priv->echo_skb_max);
/* check flag whether this packet has to be looped back */
if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK ||
if (!(dev->flags & IFF_ECHO) ||
(skb->protocol != htons(ETH_P_CAN) &&
skb->protocol != htons(ETH_P_CANFD))) {
kfree_skb(skb);
......@@ -58,7 +58,6 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
return -ENOMEM;
/* make settings for echo to reduce code in irq context */
skb->pkt_type = PACKET_BROADCAST;
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->dev = dev;
......@@ -111,6 +110,13 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr,
priv->echo_skb[idx] = NULL;
if (skb->pkt_type == PACKET_LOOPBACK) {
skb->pkt_type = PACKET_BROADCAST;
} else {
dev_consume_skb_any(skb);
return NULL;
}
return skb;
}
......@@ -147,14 +153,25 @@ EXPORT_SYMBOL_GPL(can_get_echo_skb);
*
* The function is typically called when TX failed.
*/
void can_free_echo_skb(struct net_device *dev, unsigned int idx)
void can_free_echo_skb(struct net_device *dev, unsigned int idx,
unsigned int *frame_len_ptr)
{
struct can_priv *priv = netdev_priv(dev);
BUG_ON(idx >= priv->echo_skb_max);
if (idx >= priv->echo_skb_max) {
netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
__func__, idx, priv->echo_skb_max);
return;
}
if (priv->echo_skb[idx]) {
dev_kfree_skb_any(priv->echo_skb[idx]);
struct sk_buff *skb = priv->echo_skb[idx];
struct can_skb_priv *can_skb_priv = can_skb_prv(skb);
if (frame_len_ptr)
*frame_len_ptr = can_skb_priv->frame_len;
dev_kfree_skb_any(skb);
priv->echo_skb[idx] = NULL;
}
}
......
......@@ -520,7 +520,7 @@ static int catch_up_echo_skb(struct net_device *dev, int budget, bool echo)
can_get_echo_skb(dev, i, NULL);
} else {
/* For cleanup of untransmitted messages */
can_free_echo_skb(dev, i);
can_free_echo_skb(dev, i, NULL);
}
priv->eskbp = grcan_ring_add(priv->eskbp, GRCAN_MSG_SIZE,
......
......@@ -8,6 +8,7 @@
* https://github.com/linux-can/can-doc/tree/master/m_can
*/
#include <linux/bitfield.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
......@@ -148,6 +149,16 @@ enum m_can_reg {
#define NBTP_NTSEG2_SHIFT 0
#define NBTP_NTSEG2_MASK (0x7f << NBTP_NTSEG2_SHIFT)
/* Timestamp Counter Configuration Register (TSCC) */
#define TSCC_TCP_MASK GENMASK(19, 16)
#define TSCC_TSS_MASK GENMASK(1, 0)
#define TSCC_TSS_DISABLE 0x0
#define TSCC_TSS_INTERNAL 0x1
#define TSCC_TSS_EXTERNAL 0x2
/* Timestamp Counter Value Register (TSCV) */
#define TSCV_TSC_MASK GENMASK(15, 0)
/* Error Counter Register(ECR) */
#define ECR_RP BIT(15)
#define ECR_REC_SHIFT 8
......@@ -302,6 +313,7 @@ enum m_can_reg {
#define RX_BUF_ANMF BIT(31)
#define RX_BUF_FDF BIT(21)
#define RX_BUF_BRS BIT(20)
#define RX_BUF_RXTS_MASK GENMASK(15, 0)
/* Tx Buffer Element */
/* T0 */
......@@ -319,6 +331,7 @@ enum m_can_reg {
/* E1 */
#define TX_EVENT_MM_SHIFT TX_BUF_MM_SHIFT
#define TX_EVENT_MM_MASK (0xff << TX_EVENT_MM_SHIFT)
#define TX_EVENT_TXTS_MASK GENMASK(15, 0)
static inline u32 m_can_read(struct m_can_classdev *cdev, enum m_can_reg reg)
{
......@@ -413,6 +426,20 @@ static inline void m_can_disable_all_interrupts(struct m_can_classdev *cdev)
m_can_write(cdev, M_CAN_ILE, 0x0);
}
/* Retrieve internal timestamp counter from TSCV.TSC, and shift it to 32-bit
* width.
*/
static u32 m_can_get_timestamp(struct m_can_classdev *cdev)
{
u32 tscv;
u32 tsc;
tscv = m_can_read(cdev, M_CAN_TSCV);
tsc = FIELD_GET(TSCV_TSC_MASK, tscv);
return (tsc << 16);
}
static void m_can_clean(struct net_device *net)
{
struct m_can_classdev *cdev = netdev_priv(net);
......@@ -425,11 +452,26 @@ static void m_can_clean(struct net_device *net)
putidx = ((m_can_read(cdev, M_CAN_TXFQS) &
TXFQS_TFQPI_MASK) >> TXFQS_TFQPI_SHIFT);
can_free_echo_skb(cdev->net, putidx);
can_free_echo_skb(cdev->net, putidx, NULL);
cdev->tx_skb = NULL;
}
}
/* For peripherals, pass skb to rx-offload, which will push skb from
* napi. For non-peripherals, RX is done in napi already, so push
* directly. timestamp is used to ensure good skb ordering in
* rx-offload and is ignored for non-peripherals.
*/
static void m_can_receive_skb(struct m_can_classdev *cdev,
struct sk_buff *skb,
u32 timestamp)
{
if (cdev->is_peripheral)
can_rx_offload_queue_sorted(&cdev->offload, skb, timestamp);
else
netif_receive_skb(skb);
}
static void m_can_read_fifo(struct net_device *dev, u32 rxfs)
{
struct net_device_stats *stats = &dev->stats;
......@@ -437,6 +479,7 @@ static void m_can_read_fifo(struct net_device *dev, u32 rxfs)
struct canfd_frame *cf;
struct sk_buff *skb;
u32 id, fgi, dlc;
u32 timestamp = 0;
int i;
/* calculate the fifo get index for where to read data */
......@@ -485,7 +528,9 @@ static void m_can_read_fifo(struct net_device *dev, u32 rxfs)
stats->rx_packets++;
stats->rx_bytes += cf->len;
netif_receive_skb(skb);
timestamp = FIELD_GET(RX_BUF_RXTS_MASK, dlc);
m_can_receive_skb(cdev, skb, timestamp);
}
static int m_can_do_rx_poll(struct net_device *dev, int quota)
......@@ -516,9 +561,11 @@ static int m_can_do_rx_poll(struct net_device *dev, int quota)
static int m_can_handle_lost_msg(struct net_device *dev)
{
struct m_can_classdev *cdev = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
struct sk_buff *skb;
struct can_frame *frame;
u32 timestamp = 0;
netdev_err(dev, "msg lost in rxf0\n");
......@@ -532,7 +579,10 @@ static int m_can_handle_lost_msg(struct net_device *dev)
frame->can_id |= CAN_ERR_CRTL;
frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
netif_receive_skb(skb);
if (cdev->is_peripheral)
timestamp = m_can_get_timestamp(cdev);
m_can_receive_skb(cdev, skb, timestamp);
return 1;
}
......@@ -544,6 +594,7 @@ static int m_can_handle_lec_err(struct net_device *dev,
struct net_device_stats *stats = &dev->stats;
struct can_frame *cf;
struct sk_buff *skb;
u32 timestamp = 0;
cdev->can.can_stats.bus_error++;
stats->rx_errors++;
......@@ -589,7 +640,11 @@ static int m_can_handle_lec_err(struct net_device *dev,
stats->rx_packets++;
stats->rx_bytes += cf->len;
netif_receive_skb(skb);
if (cdev->is_peripheral)
timestamp = m_can_get_timestamp(cdev);
m_can_receive_skb(cdev, skb, timestamp);
return 1;
}
......@@ -647,6 +702,7 @@ static int m_can_handle_state_change(struct net_device *dev,
struct sk_buff *skb;
struct can_berr_counter bec;
unsigned int ecr;
u32 timestamp = 0;
switch (new_state) {
case CAN_STATE_ERROR_WARNING:
......@@ -708,7 +764,11 @@ static int m_can_handle_state_change(struct net_device *dev,
stats->rx_packets++;
stats->rx_bytes += cf->len;
netif_receive_skb(skb);
if (cdev->is_peripheral)
timestamp = m_can_get_timestamp(cdev);
m_can_receive_skb(cdev, skb, timestamp);
return 1;
}
......@@ -773,6 +833,7 @@ static int m_can_handle_protocol_error(struct net_device *dev, u32 irqstatus)
struct m_can_classdev *cdev = netdev_priv(dev);
struct can_frame *cf;
struct sk_buff *skb;
u32 timestamp = 0;
/* propagate the error condition to the CAN stack */
skb = alloc_can_err_skb(dev, &cf);
......@@ -794,7 +855,11 @@ static int m_can_handle_protocol_error(struct net_device *dev, u32 irqstatus)
netdev_dbg(dev, "allocation of skb failed\n");
return 0;
}
netif_receive_skb(skb);
if (cdev->is_peripheral)
timestamp = m_can_get_timestamp(cdev);
m_can_receive_skb(cdev, skb, timestamp);
return 1;
}
......@@ -895,6 +960,29 @@ static int m_can_poll(struct napi_struct *napi, int quota)
return work_done;
}
/* Echo tx skb and update net stats. Peripherals use rx-offload for
* echo. timestamp is used for peripherals to ensure correct ordering
* by rx-offload, and is ignored for non-peripherals.
*/
static void m_can_tx_update_stats(struct m_can_classdev *cdev,
unsigned int msg_mark,
u32 timestamp)
{
struct net_device *dev = cdev->net;
struct net_device_stats *stats = &dev->stats;
if (cdev->is_peripheral)
stats->tx_bytes +=
can_rx_offload_get_echo_skb(&cdev->offload,
msg_mark,
timestamp,
NULL);
else
stats->tx_bytes += can_get_echo_skb(dev, msg_mark, NULL);
stats->tx_packets++;
}
static void m_can_echo_tx_event(struct net_device *dev)
{
u32 txe_count = 0;
......@@ -904,7 +992,6 @@ static void m_can_echo_tx_event(struct net_device *dev)
unsigned int msg_mark;
struct m_can_classdev *cdev = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
/* read tx event fifo status */
m_can_txefs = m_can_read(cdev, M_CAN_TXEFS);
......@@ -914,21 +1001,23 @@ static void m_can_echo_tx_event(struct net_device *dev)
/* Get and process all sent elements */
for (i = 0; i < txe_count; i++) {
u32 txe, timestamp = 0;
/* retrieve get index */
fgi = (m_can_read(cdev, M_CAN_TXEFS) & TXEFS_EFGI_MASK) >>
TXEFS_EFGI_SHIFT;
/* get message marker */
msg_mark = (m_can_txe_fifo_read(cdev, fgi, 4) &
TX_EVENT_MM_MASK) >> TX_EVENT_MM_SHIFT;
/* get message marker, timestamp */
txe = m_can_txe_fifo_read(cdev, fgi, 4);
msg_mark = (txe & TX_EVENT_MM_MASK) >> TX_EVENT_MM_SHIFT;
timestamp = FIELD_GET(TX_EVENT_TXTS_MASK, txe);
/* ack txe element */
m_can_write(cdev, M_CAN_TXEFA, (TXEFA_EFAI_MASK &
(fgi << TXEFA_EFAI_SHIFT)));
/* update stats */
stats->tx_bytes += can_get_echo_skb(dev, msg_mark, NULL);
stats->tx_packets++;
m_can_tx_update_stats(cdev, msg_mark, timestamp);
}
}
......@@ -936,7 +1025,6 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
struct m_can_classdev *cdev = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
u32 ir;
if (pm_runtime_suspended(cdev->dev))
......@@ -969,8 +1057,12 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
if (cdev->version == 30) {
if (ir & IR_TC) {
/* Transmission Complete Interrupt*/
stats->tx_bytes += can_get_echo_skb(dev, 0, NULL);
stats->tx_packets++;
u32 timestamp = 0;
if (cdev->is_peripheral)
timestamp = m_can_get_timestamp(cdev);
m_can_tx_update_stats(cdev, 0, timestamp);
can_led_event(dev, CAN_LED_EVENT_TX);
netif_wake_queue(dev);
}
......@@ -1108,6 +1200,7 @@ static int m_can_set_bittiming(struct net_device *dev)
* - >= v3.1.x: TX FIFO is used
* - configure mode
* - setup bittiming
* - configure timestamp generation
*/
static void m_can_chip_config(struct net_device *dev)
{
......@@ -1219,6 +1312,10 @@ static void m_can_chip_config(struct net_device *dev)
/* set bittiming params */
m_can_set_bittiming(dev);
/* enable internal timestamp generation, with a prescalar of 16. The
* prescalar is applied to the nominal bit timing */
m_can_write(cdev, M_CAN_TSCC, FIELD_PREP(TSCC_TCP_MASK, 0xf));
m_can_config_endisable(cdev, false);
if (cdev->ops->init)
......@@ -1426,6 +1523,9 @@ static int m_can_close(struct net_device *dev)
cdev->tx_wq = NULL;
}
if (cdev->is_peripheral)
can_rx_offload_disable(&cdev->offload);
close_candev(dev);
can_led_event(dev, CAN_LED_EVENT_STOP);
......@@ -1624,6 +1724,9 @@ static int m_can_open(struct net_device *dev)
goto exit_disable_clks;
}
if (cdev->is_peripheral)
can_rx_offload_enable(&cdev->offload);
/* register interrupt handler */
if (cdev->is_peripheral) {
cdev->tx_skb = NULL;
......@@ -1665,6 +1768,8 @@ static int m_can_open(struct net_device *dev)
if (cdev->is_peripheral)
destroy_workqueue(cdev->tx_wq);
out_wq_fail:
if (cdev->is_peripheral)
can_rx_offload_disable(&cdev->offload);
close_candev(dev);
exit_disable_clks:
m_can_clk_stop(cdev);
......@@ -1787,11 +1892,6 @@ struct m_can_classdev *m_can_class_allocate_dev(struct device *dev,
}
class_dev = netdev_priv(net_dev);
if (!class_dev) {
dev_err(dev, "Failed to init netdev cdevate");
goto out;
}
class_dev->net = net_dev;
class_dev->dev = dev;
SET_NETDEV_DEV(net_dev, dev);
......@@ -1818,15 +1918,22 @@ int m_can_class_register(struct m_can_classdev *cdev)
return ret;
}
ret = m_can_dev_setup(cdev);
if (cdev->is_peripheral) {
ret = can_rx_offload_add_manual(cdev->net, &cdev->offload,
M_CAN_NAPI_WEIGHT);
if (ret)
goto clk_disable;
}
ret = m_can_dev_setup(cdev);
if (ret)
goto rx_offload_del;
ret = register_m_can_dev(cdev->net);
if (ret) {
dev_err(cdev->dev, "registering %s failed (err=%d)\n",
cdev->net->name, ret);
goto clk_disable;
goto rx_offload_del;
}
devm_can_led_init(cdev->net);
......@@ -1839,6 +1946,13 @@ int m_can_class_register(struct m_can_classdev *cdev)
/* Probe finished
* Stop clocks. They will be reactivated once the M_CAN device is opened
*/
m_can_clk_stop(cdev);
return 0;
rx_offload_del:
if (cdev->is_peripheral)
can_rx_offload_del(&cdev->offload);
clk_disable:
m_can_clk_stop(cdev);
......@@ -1848,6 +1962,8 @@ EXPORT_SYMBOL_GPL(m_can_class_register);
void m_can_class_unregister(struct m_can_classdev *cdev)
{
if (cdev->is_peripheral)
can_rx_offload_del(&cdev->offload);
unregister_candev(cdev->net);
}
EXPORT_SYMBOL_GPL(m_can_class_unregister);
......
......@@ -8,6 +8,7 @@
#include <linux/can/core.h>
#include <linux/can/led.h>
#include <linux/can/rx-offload.h>
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
......@@ -71,6 +72,7 @@ struct m_can_ops {
struct m_can_classdev {
struct can_priv can;
struct can_rx_offload offload;
struct napi_struct napi;
struct net_device *net;
struct device *dev;
......
......@@ -11,7 +11,6 @@
#include <linux/gpio/consumer.h>
#include <linux/regmap.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
......
......@@ -217,7 +217,7 @@ static void tx_failure_cleanup(struct net_device *ndev)
int i;
for (i = 0; i < RCAR_CAN_FIFO_DEPTH; i++)
can_free_echo_skb(ndev, i);
can_free_echo_skb(ndev, i, NULL);
}
static void rcar_can_error(struct net_device *ndev)
......
......@@ -617,7 +617,7 @@ static void rcar_canfd_tx_failure_cleanup(struct net_device *ndev)
u32 i;
for (i = 0; i < RCANFD_FIFO_DEPTH; i++)
can_free_echo_skb(ndev, i);
can_free_echo_skb(ndev, i, NULL);
}
static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv)
......
......@@ -525,7 +525,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT &&
!(status & SR_TCS)) {
stats->tx_errors++;
can_free_echo_skb(dev, 0);
can_free_echo_skb(dev, 0, NULL);
} else {
/* transmission complete */
stats->tx_bytes +=
......
......@@ -179,7 +179,7 @@ static void hi3110_clean(struct net_device *net)
net->stats.tx_errors++;
dev_kfree_skb(priv->tx_skb);
if (priv->tx_len)
can_free_echo_skb(priv->net, 0);
can_free_echo_skb(priv->net, 0, NULL);
priv->tx_skb = NULL;
priv->tx_len = 0;
}
......
......@@ -276,7 +276,7 @@ static void mcp251x_clean(struct net_device *net)
net->stats.tx_errors++;
dev_kfree_skb(priv->tx_skb);
if (priv->tx_len)
can_free_echo_skb(priv->net, 0);
can_free_echo_skb(priv->net, 0, NULL);
priv->tx_skb = NULL;
priv->tx_len = 0;
}
......
......@@ -3,6 +3,7 @@
config CAN_MCP251XFD
tristate "Microchip MCP251xFD SPI CAN controllers"
select REGMAP
select WANT_DEV_COREDUMP
help
Driver for the Microchip MCP251XFD SPI FD-CAN controller
family.
......
......@@ -6,3 +6,6 @@ mcp251xfd-objs :=
mcp251xfd-objs += mcp251xfd-core.o
mcp251xfd-objs += mcp251xfd-crc16.o
mcp251xfd-objs += mcp251xfd-regmap.o
mcp251xfd-objs += mcp251xfd-timestamp.o
mcp251xfd-$(CONFIG_DEV_COREDUMP) += mcp251xfd-dump.o
......@@ -2,7 +2,7 @@
//
// mcp251xfd - Microchip MCP251xFD Family CAN controller driver
//
// Copyright (c) 2019, 2020 Pengutronix,
// Copyright (c) 2019, 2020, 2021 Pengutronix,
// Marc Kleine-Budde <kernel@pengutronix.de>
//
// Based on:
......@@ -16,7 +16,6 @@
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
......@@ -330,6 +329,7 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
struct mcp251xfd_tx_ring *tx_ring;
struct mcp251xfd_rx_ring *rx_ring, *prev_rx_ring = NULL;
struct mcp251xfd_tx_obj *tx_obj;
struct spi_transfer *xfer;
u32 val;
u16 addr;
u8 len;
......@@ -347,8 +347,6 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
addr, val, val);
for (j = 0; j < ARRAY_SIZE(tef_ring->uinc_xfer); j++) {
struct spi_transfer *xfer;
xfer = &tef_ring->uinc_xfer[j];
xfer->tx_buf = &tef_ring->uinc_buf;
xfer->len = len;
......@@ -357,6 +355,15 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
}
/* "cs_change == 1" on the last transfer results in an active
* chip select after the complete SPI message. This causes the
* controller to interpret the next register access as
* data. Set "cs_change" of the last transfer to "0" to
* properly deactivate the chip select at the end of the
* message.
*/
xfer->cs_change = 0;
/* TX */
tx_ring = priv->tx;
tx_ring->head = 0;
......@@ -397,8 +404,6 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
addr, val, val);
for (j = 0; j < ARRAY_SIZE(rx_ring->uinc_xfer); j++) {
struct spi_transfer *xfer;
xfer = &rx_ring->uinc_xfer[j];
xfer->tx_buf = &rx_ring->uinc_buf;
xfer->len = len;
......@@ -406,6 +411,15 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
xfer->cs_change_delay.value = 0;
xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
}
/* "cs_change == 1" on the last transfer results in an
* active chip select after the complete SPI
* message. This causes the controller to interpret
* the next register access as data. Set "cs_change"
* of the last transfer to "0" to properly deactivate
* the chip select at the end of the message.
*/
xfer->cs_change = 0;
}
}
......@@ -1097,6 +1111,7 @@ static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv)
return 0;
out_chip_stop:
mcp251xfd_dump(priv);
mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED);
return err;
......@@ -1250,7 +1265,8 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
const struct mcp251xfd_hw_tef_obj *hw_tef_obj)
{
struct net_device_stats *stats = &priv->ndev->stats;
u32 seq, seq_masked, tef_tail_masked;
struct sk_buff *skb;
u32 seq, seq_masked, tef_tail_masked, tef_tail;
seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK,
hw_tef_obj->flags);
......@@ -1266,9 +1282,13 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
if (seq_masked != tef_tail_masked)
return mcp251xfd_handle_tefif_recover(priv, seq);
tef_tail = mcp251xfd_get_tef_tail(priv);
skb = priv->can.echo_skb[tef_tail];
if (skb)
mcp251xfd_skb_set_timestamp(priv, skb, hw_tef_obj->ts);
stats->tx_bytes +=
can_rx_offload_get_echo_skb(&priv->offload,
mcp251xfd_get_tef_tail(priv),
tef_tail,
hw_tef_obj->ts, NULL);
stats->tx_packets++;
priv->tef->tail++;
......@@ -1365,25 +1385,20 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
if (len) {
struct mcp251xfd_tef_ring *ring = priv->tef;
struct mcp251xfd_tx_ring *tx_ring = priv->tx;
struct spi_transfer *last_xfer;
int offset;
/* Increment the TEF FIFO tail pointer 'len' times in
* a single SPI message.
*
* Note:
*
* "cs_change == 1" on the last transfer results in an
* active chip select after the complete SPI
* message. This causes the controller to interpret
* the next register access as data. Temporary set
* "cs_change" of the last transfer to "0" to properly
* deactivate the chip select at the end of the
* message.
* Calculate offset, so that the SPI transfer ends on
* the last message of the uinc_xfer array, which has
* "cs_change == 0", to properly deactivate the chip
* select.
*/
last_xfer = &ring->uinc_xfer[len - 1];
last_xfer->cs_change = 0;
err = spi_sync_transfer(priv->spi, ring->uinc_xfer, len);
last_xfer->cs_change = 1;
offset = ARRAY_SIZE(ring->uinc_xfer) - len;
err = spi_sync_transfer(priv->spi,
ring->uinc_xfer + offset, len);
if (err)
return err;
......@@ -1432,7 +1447,7 @@ mcp251xfd_rx_ring_update(const struct mcp251xfd_priv *priv,
}
static void
mcp251xfd_hw_rx_obj_to_skb(const struct mcp251xfd_priv *priv,
mcp251xfd_hw_rx_obj_to_skb(struct mcp251xfd_priv *priv,
const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj,
struct sk_buff *skb)
{
......@@ -1475,6 +1490,8 @@ mcp251xfd_hw_rx_obj_to_skb(const struct mcp251xfd_priv *priv,
if (!(hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR))
memcpy(cfd->data, hw_rx_obj->data, cfd->len);
mcp251xfd_skb_set_timestamp(priv, skb, hw_rx_obj->ts);
}
static int
......@@ -1535,7 +1552,7 @@ mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv,
return err;
while ((len = mcp251xfd_get_rx_linear_len(ring))) {
struct spi_transfer *last_xfer;
int offset;
rx_tail = mcp251xfd_get_rx_tail(ring);
......@@ -1556,19 +1573,14 @@ mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv,
* single SPI message.
*
* Note:
*
* "cs_change == 1" on the last transfer results in an
* active chip select after the complete SPI
* message. This causes the controller to interpret
* the next register access as data. Temporary set
* "cs_change" of the last transfer to "0" to properly
* deactivate the chip select at the end of the
* message.
* Calculate offset, so that the SPI transfer ends on
* the last message of the uinc_xfer array, which has
* "cs_change == 0", to properly deactivate the chip
* select.
*/
last_xfer = &ring->uinc_xfer[len - 1];
last_xfer->cs_change = 0;
err = spi_sync_transfer(priv->spi, ring->uinc_xfer, len);
last_xfer->cs_change = 1;
offset = ARRAY_SIZE(ring->uinc_xfer) - len;
err = spi_sync_transfer(priv->spi,
ring->uinc_xfer + offset, len);
if (err)
return err;
......@@ -1592,23 +1604,22 @@ static int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv)
return 0;
}
static inline int mcp251xfd_get_timestamp(const struct mcp251xfd_priv *priv,
u32 *timestamp)
{
return regmap_read(priv->map_reg, MCP251XFD_REG_TBC, timestamp);
}
static struct sk_buff *
mcp251xfd_alloc_can_err_skb(const struct mcp251xfd_priv *priv,
mcp251xfd_alloc_can_err_skb(struct mcp251xfd_priv *priv,
struct can_frame **cf, u32 *timestamp)
{
struct sk_buff *skb;
int err;
err = mcp251xfd_get_timestamp(priv, timestamp);
if (err)
return NULL;
return alloc_can_err_skb(priv->ndev, cf);
skb = alloc_can_err_skb(priv->ndev, cf);
if (skb)
mcp251xfd_skb_set_timestamp(priv, skb, *timestamp);
return skb;
}
static int mcp251xfd_handle_rxovif(struct mcp251xfd_priv *priv)
......@@ -1760,6 +1771,7 @@ static int mcp251xfd_handle_ivmif(struct mcp251xfd_priv *priv)
if (!cf)
return 0;
mcp251xfd_skb_set_timestamp(priv, skb, timestamp);
err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);
if (err)
stats->rx_fifo_errors++;
......@@ -2277,6 +2289,7 @@ static irqreturn_t mcp251xfd_irq(int irq, void *dev_id)
out_fail:
netdev_err(priv->ndev, "IRQ handler returned %d (intf=0x%08x).\n",
err, priv->regs_status.intf);
mcp251xfd_dump(priv);
mcp251xfd_chip_interrupts_disable(priv);
return handled;
......@@ -2493,6 +2506,7 @@ static int mcp251xfd_open(struct net_device *ndev)
if (err)
goto out_transceiver_disable;
mcp251xfd_timestamp_init(priv);
can_rx_offload_enable(&priv->offload);
err = request_threaded_irq(spi->irq, NULL, mcp251xfd_irq,
......@@ -2513,6 +2527,7 @@ static int mcp251xfd_open(struct net_device *ndev)
free_irq(spi->irq, priv);
out_can_rx_offload_disable:
can_rx_offload_disable(&priv->offload);
mcp251xfd_timestamp_stop(priv);
out_transceiver_disable:
mcp251xfd_transceiver_disable(priv);
out_mcp251xfd_ring_free:
......@@ -2534,6 +2549,7 @@ static int mcp251xfd_stop(struct net_device *ndev)
mcp251xfd_chip_interrupts_disable(priv);
free_irq(ndev->irq, priv);
can_rx_offload_disable(&priv->offload);
mcp251xfd_timestamp_stop(priv);
mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED);
mcp251xfd_transceiver_disable(priv);
mcp251xfd_ring_free(priv);
......
// SPDX-License-Identifier: GPL-2.0
//
// mcp251xfd - Microchip MCP251xFD Family CAN controller driver
//
// Copyright (c) 2020, 2021 Pengutronix,
// Marc Kleine-Budde <kernel@pengutronix.de>
// Copyright (C) 2015-2018 Etnaviv Project
//
#include <linux/devcoredump.h>
#include "mcp251xfd.h"
#include "mcp251xfd-dump.h"
struct mcp251xfd_dump_iter {
void *start;
struct mcp251xfd_dump_object_header *hdr;
void *data;
};
struct mcp251xfd_dump_reg_space {
u16 base;
u16 size;
};
struct mcp251xfd_dump_ring {
enum mcp251xfd_dump_object_ring_key key;
u32 val;
};
static const struct mcp251xfd_dump_reg_space mcp251xfd_dump_reg_space[] = {
{
.base = MCP251XFD_REG_CON,
.size = MCP251XFD_REG_FLTOBJ(32) - MCP251XFD_REG_CON,
}, {
.base = MCP251XFD_RAM_START,
.size = MCP251XFD_RAM_SIZE,
}, {
.base = MCP251XFD_REG_OSC,
.size = MCP251XFD_REG_DEVID - MCP251XFD_REG_OSC,
},
};
static void mcp251xfd_dump_header(struct mcp251xfd_dump_iter *iter,
enum mcp251xfd_dump_object_type object_type,
const void *data_end)
{
struct mcp251xfd_dump_object_header *hdr = iter->hdr;
unsigned int len;
len = data_end - iter->data;
if (!len)
return;
hdr->magic = cpu_to_le32(MCP251XFD_DUMP_MAGIC);
hdr->type = cpu_to_le32(object_type);
hdr->offset = cpu_to_le32(iter->data - iter->start);
hdr->len = cpu_to_le32(len);
iter->hdr++;
iter->data += len;
}
static void mcp251xfd_dump_registers(const struct mcp251xfd_priv *priv,
struct mcp251xfd_dump_iter *iter)
{
const int val_bytes = regmap_get_val_bytes(priv->map_rx);
struct mcp251xfd_dump_object_reg *reg = iter->data;
unsigned int i, j;
int err;
for (i = 0; i < ARRAY_SIZE(mcp251xfd_dump_reg_space); i++) {
const struct mcp251xfd_dump_reg_space *reg_space;
void *buf;
reg_space = &mcp251xfd_dump_reg_space[i];
buf = kmalloc(reg_space->size, GFP_KERNEL);
if (!buf)
goto out;
err = regmap_bulk_read(priv->map_reg, reg_space->base,
buf, reg_space->size / val_bytes);
if (err) {
kfree(buf);
continue;
}
for (j = 0; j < reg_space->size; j += sizeof(u32), reg++) {
reg->reg = cpu_to_le32(reg_space->base + j);
reg->val = cpu_to_le32p(buf + j);
}
kfree(buf);
}
out:
mcp251xfd_dump_header(iter, MCP251XFD_DUMP_OBJECT_TYPE_REG, reg);
}
static void mcp251xfd_dump_ring(struct mcp251xfd_dump_iter *iter,
enum mcp251xfd_dump_object_type object_type,
const struct mcp251xfd_dump_ring *dump_ring,
unsigned int len)
{
struct mcp251xfd_dump_object_reg *reg = iter->data;
unsigned int i;
for (i = 0; i < len; i++, reg++) {
reg->reg = cpu_to_le32(dump_ring[i].key);
reg->val = cpu_to_le32(dump_ring[i].val);
}
mcp251xfd_dump_header(iter, object_type, reg);
}
static void mcp251xfd_dump_tef_ring(const struct mcp251xfd_priv *priv,
struct mcp251xfd_dump_iter *iter)
{
const struct mcp251xfd_tef_ring *tef = priv->tef;
const struct mcp251xfd_tx_ring *tx = priv->tx;
const struct mcp251xfd_dump_ring dump_ring[] = {
{
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_HEAD,
.val = tef->head,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_TAIL,
.val = tef->tail,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_BASE,
.val = 0,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_NR,
.val = 0,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_FIFO_NR,
.val = 0,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_NUM,
.val = tx->obj_num,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_SIZE,
.val = sizeof(struct mcp251xfd_hw_tef_obj),
},
};
mcp251xfd_dump_ring(iter, MCP251XFD_DUMP_OBJECT_TYPE_TEF,
dump_ring, ARRAY_SIZE(dump_ring));
}
static void mcp251xfd_dump_rx_ring_one(const struct mcp251xfd_priv *priv,
struct mcp251xfd_dump_iter *iter,
const struct mcp251xfd_rx_ring *rx)
{
const struct mcp251xfd_dump_ring dump_ring[] = {
{
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_HEAD,
.val = rx->head,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_TAIL,
.val = rx->tail,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_BASE,
.val = rx->base,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_NR,
.val = rx->nr,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_FIFO_NR,
.val = rx->fifo_nr,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_NUM,
.val = rx->obj_num,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_SIZE,
.val = rx->obj_size,
},
};
mcp251xfd_dump_ring(iter, MCP251XFD_DUMP_OBJECT_TYPE_RX,
dump_ring, ARRAY_SIZE(dump_ring));
}
static void mcp251xfd_dump_rx_ring(const struct mcp251xfd_priv *priv,
struct mcp251xfd_dump_iter *iter)
{
struct mcp251xfd_rx_ring *rx_ring;
unsigned int i;
mcp251xfd_for_each_rx_ring(priv, rx_ring, i)
mcp251xfd_dump_rx_ring_one(priv, iter, rx_ring);
}
static void mcp251xfd_dump_tx_ring(const struct mcp251xfd_priv *priv,
struct mcp251xfd_dump_iter *iter)
{
const struct mcp251xfd_tx_ring *tx = priv->tx;
const struct mcp251xfd_dump_ring dump_ring[] = {
{
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_HEAD,
.val = tx->head,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_TAIL,
.val = tx->tail,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_BASE,
.val = tx->base,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_NR,
.val = 0,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_FIFO_NR,
.val = MCP251XFD_TX_FIFO,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_NUM,
.val = tx->obj_num,
}, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_SIZE,
.val = tx->obj_size,
},
};
mcp251xfd_dump_ring(iter, MCP251XFD_DUMP_OBJECT_TYPE_TX,
dump_ring, ARRAY_SIZE(dump_ring));
}
static void mcp251xfd_dump_end(const struct mcp251xfd_priv *priv,
struct mcp251xfd_dump_iter *iter)
{
struct mcp251xfd_dump_object_header *hdr = iter->hdr;
hdr->magic = cpu_to_le32(MCP251XFD_DUMP_MAGIC);
hdr->type = cpu_to_le32(MCP251XFD_DUMP_OBJECT_TYPE_END);
hdr->offset = cpu_to_le32(0);
hdr->len = cpu_to_le32(0);
/* provoke NULL pointer access, if used after END object */
iter->hdr = NULL;
}
void mcp251xfd_dump(const struct mcp251xfd_priv *priv)
{
struct mcp251xfd_dump_iter iter;
unsigned int rings_num, obj_num;
unsigned int file_size = 0;
unsigned int i;
/* register space + end marker */
obj_num = 2;
/* register space */
for (i = 0; i < ARRAY_SIZE(mcp251xfd_dump_reg_space); i++)
file_size += mcp251xfd_dump_reg_space[i].size / sizeof(u32) *
sizeof(struct mcp251xfd_dump_object_reg);
/* TEF ring, RX ring, TX rings */
rings_num = 1 + priv->rx_ring_num + 1;
obj_num += rings_num;
file_size += rings_num * __MCP251XFD_DUMP_OBJECT_RING_KEY_MAX *
sizeof(struct mcp251xfd_dump_object_reg);
/* size of the headers */
file_size += sizeof(*iter.hdr) * obj_num;
/* allocate the file in vmalloc memory, it's likely to be big */
iter.start = __vmalloc(file_size, GFP_KERNEL | __GFP_NOWARN |
__GFP_ZERO | __GFP_NORETRY);
if (!iter.start) {
netdev_warn(priv->ndev, "Failed to allocate devcoredump file.\n");
return;
}
/* point the data member after the headers */
iter.hdr = iter.start;
iter.data = &iter.hdr[obj_num];
mcp251xfd_dump_registers(priv, &iter);
mcp251xfd_dump_tef_ring(priv, &iter);
mcp251xfd_dump_rx_ring(priv, &iter);
mcp251xfd_dump_tx_ring(priv, &iter);
mcp251xfd_dump_end(priv, &iter);
dev_coredumpv(&priv->spi->dev, iter.start,
iter.data - iter.start, GFP_KERNEL);
}
/* SPDX-License-Identifier: GPL-2.0
*
* mcp251xfd - Microchip MCP251xFD Family CAN controller driver
*
* Copyright (c) 2019, 2020, 2021 Pengutronix,
* Marc Kleine-Budde <kernel@pengutronix.de>
*/
#ifndef _MCP251XFD_DUMP_H
#define _MCP251XFD_DUMP_H
#define MCP251XFD_DUMP_MAGIC 0x1825434d
enum mcp251xfd_dump_object_type {
MCP251XFD_DUMP_OBJECT_TYPE_REG,
MCP251XFD_DUMP_OBJECT_TYPE_TEF,
MCP251XFD_DUMP_OBJECT_TYPE_RX,
MCP251XFD_DUMP_OBJECT_TYPE_TX,
MCP251XFD_DUMP_OBJECT_TYPE_END = -1,
};
enum mcp251xfd_dump_object_ring_key {
MCP251XFD_DUMP_OBJECT_RING_KEY_HEAD,
MCP251XFD_DUMP_OBJECT_RING_KEY_TAIL,
MCP251XFD_DUMP_OBJECT_RING_KEY_BASE,
MCP251XFD_DUMP_OBJECT_RING_KEY_NR,
MCP251XFD_DUMP_OBJECT_RING_KEY_FIFO_NR,
MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_NUM,
MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_SIZE,
__MCP251XFD_DUMP_OBJECT_RING_KEY_MAX,
};
struct mcp251xfd_dump_object_header {
__le32 magic;
__le32 type;
__le32 offset;
__le32 len;
};
struct mcp251xfd_dump_object_reg {
__le32 reg;
__le32 val;
};
#endif
// SPDX-License-Identifier: GPL-2.0
//
// mcp251xfd - Microchip MCP251xFD Family CAN controller driver
//
// Copyright (c) 2021 Pengutronix,
// Marc Kleine-Budde <kernel@pengutronix.de>
//
#include <linux/clocksource.h>
#include <linux/workqueue.h>
#include "mcp251xfd.h"
static u64 mcp251xfd_timestamp_read(const struct cyclecounter *cc)
{
struct mcp251xfd_priv *priv;
u32 timestamp = 0;
int err;
priv = container_of(cc, struct mcp251xfd_priv, cc);
err = mcp251xfd_get_timestamp(priv, &timestamp);
if (err)
netdev_err(priv->ndev,
"Error %d while reading timestamp. HW timestamps may be inaccurate.",
err);
return timestamp;
}
static void mcp251xfd_timestamp_work(struct work_struct *work)
{
struct delayed_work *delayed_work = to_delayed_work(work);
struct mcp251xfd_priv *priv;
priv = container_of(delayed_work, struct mcp251xfd_priv, timestamp);
timecounter_read(&priv->tc);
schedule_delayed_work(&priv->timestamp,
MCP251XFD_TIMESTAMP_WORK_DELAY_SEC * HZ);
}
void mcp251xfd_skb_set_timestamp(struct mcp251xfd_priv *priv,
struct sk_buff *skb, u32 timestamp)
{
struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb);
u64 ns;
ns = timecounter_cyc2time(&priv->tc, timestamp);
hwtstamps->hwtstamp = ns_to_ktime(ns);
}
void mcp251xfd_timestamp_init(struct mcp251xfd_priv *priv)
{
struct cyclecounter *cc = &priv->cc;
cc->read = mcp251xfd_timestamp_read;
cc->mask = CYCLECOUNTER_MASK(32);
cc->shift = 1;
cc->mult = clocksource_hz2mult(priv->can.clock.freq, cc->shift);
timecounter_init(&priv->tc, &priv->cc, ktime_get_real_ns());
INIT_DELAYED_WORK(&priv->timestamp, mcp251xfd_timestamp_work);
schedule_delayed_work(&priv->timestamp,
MCP251XFD_TIMESTAMP_WORK_DELAY_SEC * HZ);
}
void mcp251xfd_timestamp_stop(struct mcp251xfd_priv *priv)
{
cancel_delayed_work_sync(&priv->timestamp);
}
......@@ -15,9 +15,12 @@
#include <linux/can/rx-offload.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/timecounter.h>
#include <linux/workqueue.h>
/* MPC251x registers */
......@@ -394,6 +397,9 @@
#define MCP251XFD_SYSCLOCK_HZ_MAX 40000000
#define MCP251XFD_SYSCLOCK_HZ_MIN 1000000
#define MCP251XFD_SPICLOCK_HZ_MAX 20000000
#define MCP251XFD_TIMESTAMP_WORK_DELAY_SEC 45
static_assert(MCP251XFD_TIMESTAMP_WORK_DELAY_SEC <
CYCLECOUNTER_MASK(32) / MCP251XFD_SYSCLOCK_HZ_MAX / 2);
#define MCP251XFD_OSC_PLL_MULTIPLIER 10
#define MCP251XFD_OSC_STAB_SLEEP_US (3 * USEC_PER_MSEC)
#define MCP251XFD_OSC_STAB_TIMEOUT_US (10 * MCP251XFD_OSC_STAB_SLEEP_US)
......@@ -595,6 +601,10 @@ struct mcp251xfd_priv {
struct mcp251xfd_ecc ecc;
struct mcp251xfd_regs_status regs_status;
struct cyclecounter cc;
struct timecounter tc;
struct delayed_work timestamp;
struct gpio_desc *rx_int;
struct clk *clk;
struct regulator *reg_vdd;
......@@ -727,6 +737,12 @@ mcp251xfd_spi_cmd_write(const struct mcp251xfd_priv *priv,
return data;
}
static inline int mcp251xfd_get_timestamp(const struct mcp251xfd_priv *priv,
u32 *timestamp)
{
return regmap_read(priv->map_reg, MCP251XFD_REG_TBC, timestamp);
}
static inline u16 mcp251xfd_get_tef_obj_addr(u8 n)
{
return MCP251XFD_RAM_START +
......@@ -837,5 +853,17 @@ int mcp251xfd_regmap_init(struct mcp251xfd_priv *priv);
u16 mcp251xfd_crc16_compute2(const void *cmd, size_t cmd_size,
const void *data, size_t data_size);
u16 mcp251xfd_crc16_compute(const void *data, size_t data_size);
void mcp251xfd_skb_set_timestamp(struct mcp251xfd_priv *priv,
struct sk_buff *skb, u32 timestamp);
void mcp251xfd_timestamp_init(struct mcp251xfd_priv *priv);
void mcp251xfd_timestamp_stop(struct mcp251xfd_priv *priv);
#if IS_ENABLED(CONFIG_DEV_COREDUMP)
void mcp251xfd_dump(const struct mcp251xfd_priv *priv);
#else
static inline void mcp251xfd_dump(const struct mcp251xfd_priv *priv)
{
}
#endif
#endif
......@@ -807,7 +807,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
err = usb_submit_urb(urb, GFP_ATOMIC);
if (unlikely(err)) {
can_free_echo_skb(netdev, context->echo_index);
can_free_echo_skb(netdev, context->echo_index, NULL);
usb_unanchor_urb(urb);
usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
......
......@@ -360,7 +360,7 @@ static void esd_usb2_tx_done_msg(struct esd_usb2_net_priv *priv,
can_get_echo_skb(netdev, context->echo_index, NULL);
} else {
stats->tx_errors++;
can_free_echo_skb(netdev, context->echo_index);
can_free_echo_skb(netdev, context->echo_index, NULL);
}
/* Release context */
......@@ -793,7 +793,7 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb,
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err) {
can_free_echo_skb(netdev, context->echo_index);
can_free_echo_skb(netdev, context->echo_index, NULL);
atomic_dec(&priv->active_tx_jobs);
usb_unanchor_urb(urb);
......
......@@ -533,7 +533,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
if (unlikely(rc)) { /* usb send failed */
atomic_dec(&dev->active_tx_urbs);
can_free_echo_skb(netdev, idx);
can_free_echo_skb(netdev, idx, NULL);
gs_free_tx_context(txc);
usb_unanchor_urb(urb);
......
......@@ -593,7 +593,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
if (unlikely(err)) {
spin_lock_irqsave(&priv->tx_contexts_lock, flags);
can_free_echo_skb(netdev, context->echo_index);
can_free_echo_skb(netdev, context->echo_index, NULL);
context->echo_index = dev->max_tx_urbs;
--priv->active_tx_contexts;
netif_wake_queue(netdev);
......
......@@ -364,7 +364,7 @@ static netdev_tx_t mcba_usb_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
xmit_failed:
can_free_echo_skb(priv->netdev, ctx->ndx);
can_free_echo_skb(priv->netdev, ctx->ndx, NULL);
mcba_usb_free_ctx(ctx);
dev_kfree_skb(skb);
stats->tx_dropped++;
......
......@@ -11,6 +11,7 @@
#include <linux/netdevice.h>
#include <linux/usb.h>
#include <linux/module.h>
#include <linux/ethtool.h>
#include <linux/can.h>
#include <linux/can/dev.h>
......@@ -40,6 +41,7 @@
#define PCAN_USB_CMD_REGISTER 9
#define PCAN_USB_CMD_EXT_VCC 10
#define PCAN_USB_CMD_ERR_FR 11
#define PCAN_USB_CMD_LED 12
/* PCAN_USB_CMD_SET_BUS number arg */
#define PCAN_USB_BUS_XCVER 2
......@@ -248,6 +250,15 @@ static int pcan_usb_set_ext_vcc(struct peak_usb_device *dev, u8 onoff)
return pcan_usb_send_cmd(dev, PCAN_USB_CMD_EXT_VCC, PCAN_USB_SET, args);
}
static int pcan_usb_set_led(struct peak_usb_device *dev, u8 onoff)
{
u8 args[PCAN_USB_CMD_ARGS_LEN] = {
[0] = !!onoff,
};
return pcan_usb_send_cmd(dev, PCAN_USB_CMD_LED, PCAN_USB_SET, args);
}
/*
* set bittiming value to can
*/
......@@ -971,6 +982,40 @@ static int pcan_usb_probe(struct usb_interface *intf)
return 0;
}
static int pcan_usb_set_phys_id(struct net_device *netdev,
enum ethtool_phys_id_state state)
{
struct peak_usb_device *dev = netdev_priv(netdev);
int err = 0;
switch (state) {
case ETHTOOL_ID_ACTIVE:
/* call ON/OFF twice a second */
return 2;
case ETHTOOL_ID_OFF:
err = pcan_usb_set_led(dev, 0);
break;
case ETHTOOL_ID_ON:
fallthrough;
case ETHTOOL_ID_INACTIVE:
/* restore LED default */
err = pcan_usb_set_led(dev, 1);
break;
default:
break;
}
return err;
}
static const struct ethtool_ops pcan_usb_ethtool_ops = {
.set_phys_id = pcan_usb_set_phys_id,
};
/*
* describe the PCAN-USB adapter
*/
......@@ -1001,6 +1046,8 @@ const struct peak_usb_adapter pcan_usb = {
/* size of device private data */
.sizeof_dev_private = sizeof(struct pcan_usb),
.ethtool_ops = &pcan_usb_ethtool_ops,
/* timestamps usage */
.ts_used_bits = 16,
.ts_period = 24575, /* calibration period in ts. */
......
......@@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/usb.h>
#include <linux/ethtool.h>
#include <linux/can.h>
#include <linux/can/dev.h>
......@@ -371,7 +372,7 @@ static netdev_tx_t peak_usb_ndo_start_xmit(struct sk_buff *skb,
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err) {
can_free_echo_skb(netdev, context->echo_index);
can_free_echo_skb(netdev, context->echo_index, NULL);
usb_unanchor_urb(urb);
......@@ -820,6 +821,9 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter,
netdev->flags |= IFF_ECHO; /* we support local echo */
/* add ethtool support */
netdev->ethtool_ops = peak_usb_adapter->ethtool_ops;
init_usb_anchor(&dev->rx_submitted);
init_usb_anchor(&dev->tx_submitted);
......
......@@ -46,6 +46,8 @@ struct peak_usb_adapter {
const struct can_bittiming_const * const data_bittiming_const;
unsigned int ctrl_count;
const struct ethtool_ops *ethtool_ops;
int (*intf_probe)(struct usb_interface *intf);
int (*dev_init)(struct peak_usb_device *dev);
......
......@@ -7,6 +7,7 @@
#include <linux/netdevice.h>
#include <linux/usb.h>
#include <linux/module.h>
#include <linux/ethtool.h>
#include <linux/can.h>
#include <linux/can/dev.h>
......@@ -773,6 +774,10 @@ static int pcan_usb_fd_encode_msg(struct peak_usb_device *dev,
tx_msg_flags |= PUCAN_MSG_RTR;
}
/* Single-Shot frame */
if (dev->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
tx_msg_flags |= PUCAN_MSG_SINGLE_SHOT;
tx_msg->flags = cpu_to_le16(tx_msg_flags);
tx_msg->channel_dlc = PUCAN_MSG_CHANNEL_DLC(dev->ctrl_idx, dlc);
memcpy(tx_msg->d, cfd->data, cfd->len);
......@@ -1006,6 +1011,31 @@ static void pcan_usb_fd_free(struct peak_usb_device *dev)
}
}
/* blink LED's */
static int pcan_usb_fd_set_phys_id(struct net_device *netdev,
enum ethtool_phys_id_state state)
{
struct peak_usb_device *dev = netdev_priv(netdev);
int err = 0;
switch (state) {
case ETHTOOL_ID_ACTIVE:
err = pcan_usb_fd_set_can_led(dev, PCAN_UFD_LED_FAST);
break;
case ETHTOOL_ID_INACTIVE:
err = pcan_usb_fd_set_can_led(dev, PCAN_UFD_LED_DEF);
break;
default:
break;
}
return err;
}
static const struct ethtool_ops pcan_usb_fd_ethtool_ops = {
.set_phys_id = pcan_usb_fd_set_phys_id,
};
/* describes the PCAN-USB FD adapter */
static const struct can_bittiming_const pcan_usb_fd_const = {
.name = "pcan_usb_fd",
......@@ -1037,7 +1067,7 @@ const struct peak_usb_adapter pcan_usb_fd = {
.ctrl_count = PCAN_USBFD_CHANNEL_COUNT,
.ctrlmode_supported = CAN_CTRLMODE_FD |
CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_CC_LEN8_DLC,
CAN_CTRLMODE_ONE_SHOT | CAN_CTRLMODE_CC_LEN8_DLC,
.clock = {
.freq = PCAN_UFD_CRYSTAL_HZ,
},
......@@ -1047,6 +1077,8 @@ const struct peak_usb_adapter pcan_usb_fd = {
/* size of device private data */
.sizeof_dev_private = sizeof(struct pcan_usb_fd_device),
.ethtool_ops = &pcan_usb_fd_ethtool_ops,
/* timestamps usage */
.ts_used_bits = 32,
.ts_period = 1000000, /* calibration period in ts. */
......@@ -1110,7 +1142,7 @@ const struct peak_usb_adapter pcan_usb_chip = {
.ctrl_count = PCAN_USBFD_CHANNEL_COUNT,
.ctrlmode_supported = CAN_CTRLMODE_FD |
CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_CC_LEN8_DLC,
CAN_CTRLMODE_ONE_SHOT | CAN_CTRLMODE_CC_LEN8_DLC,
.clock = {
.freq = PCAN_UFD_CRYSTAL_HZ,
},
......@@ -1120,6 +1152,8 @@ const struct peak_usb_adapter pcan_usb_chip = {
/* size of device private data */
.sizeof_dev_private = sizeof(struct pcan_usb_fd_device),
.ethtool_ops = &pcan_usb_fd_ethtool_ops,
/* timestamps usage */
.ts_used_bits = 32,
.ts_period = 1000000, /* calibration period in ts. */
......@@ -1183,7 +1217,7 @@ const struct peak_usb_adapter pcan_usb_pro_fd = {
.ctrl_count = PCAN_USBPROFD_CHANNEL_COUNT,
.ctrlmode_supported = CAN_CTRLMODE_FD |
CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_CC_LEN8_DLC,
CAN_CTRLMODE_ONE_SHOT | CAN_CTRLMODE_CC_LEN8_DLC,
.clock = {
.freq = PCAN_UFD_CRYSTAL_HZ,
},
......@@ -1193,6 +1227,8 @@ const struct peak_usb_adapter pcan_usb_pro_fd = {
/* size of device private data */
.sizeof_dev_private = sizeof(struct pcan_usb_fd_device),
.ethtool_ops = &pcan_usb_fd_ethtool_ops,
/* timestamps usage */
.ts_used_bits = 32,
.ts_period = 1000000, /* calibration period in ts. */
......@@ -1256,7 +1292,7 @@ const struct peak_usb_adapter pcan_usb_x6 = {
.ctrl_count = PCAN_USBPROFD_CHANNEL_COUNT,
.ctrlmode_supported = CAN_CTRLMODE_FD |
CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_CC_LEN8_DLC,
CAN_CTRLMODE_ONE_SHOT | CAN_CTRLMODE_CC_LEN8_DLC,
.clock = {
.freq = PCAN_UFD_CRYSTAL_HZ,
},
......@@ -1266,6 +1302,8 @@ const struct peak_usb_adapter pcan_usb_x6 = {
/* size of device private data */
.sizeof_dev_private = sizeof(struct pcan_usb_fd_device),
.ethtool_ops = &pcan_usb_fd_ethtool_ops,
/* timestamps usage */
.ts_used_bits = 32,
.ts_period = 1000000, /* calibration period in ts. */
......
......@@ -9,6 +9,7 @@
#include <linux/netdevice.h>
#include <linux/usb.h>
#include <linux/module.h>
#include <linux/ethtool.h>
#include <linux/can.h>
#include <linux/can/dev.h>
......@@ -36,6 +37,7 @@
#define PCAN_USBPRO_RTR 0x01
#define PCAN_USBPRO_EXT 0x02
#define PCAN_USBPRO_SS 0x08
#define PCAN_USBPRO_CMD_BUFFER_SIZE 512
......@@ -776,9 +778,13 @@ static int pcan_usb_pro_encode_msg(struct peak_usb_device *dev,
flags = 0;
if (cf->can_id & CAN_EFF_FLAG)
flags |= 0x02;
flags |= PCAN_USBPRO_EXT;
if (cf->can_id & CAN_RTR_FLAG)
flags |= 0x01;
flags |= PCAN_USBPRO_RTR;
/* Single-Shot frame */
if (dev->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
flags |= PCAN_USBPRO_SS;
pcan_msg_add_rec(&usb_msg, data_type, 0, flags, len, cf->can_id,
cf->data);
......@@ -906,7 +912,7 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev)
usb_if->dev[dev->ctrl_idx] = dev;
/* set LED in default state (end of init phase) */
pcan_usb_pro_set_led(dev, 0, 1);
pcan_usb_pro_set_led(dev, PCAN_USBPRO_LED_DEVICE, 1);
kfree(bi);
kfree(fi);
......@@ -990,6 +996,35 @@ int pcan_usb_pro_probe(struct usb_interface *intf)
return 0;
}
static int pcan_usb_pro_set_phys_id(struct net_device *netdev,
enum ethtool_phys_id_state state)
{
struct peak_usb_device *dev = netdev_priv(netdev);
int err = 0;
switch (state) {
case ETHTOOL_ID_ACTIVE:
/* fast blinking forever */
err = pcan_usb_pro_set_led(dev, PCAN_USBPRO_LED_BLINK_FAST,
0xffffffff);
break;
case ETHTOOL_ID_INACTIVE:
/* restore LED default */
err = pcan_usb_pro_set_led(dev, PCAN_USBPRO_LED_DEVICE, 1);
break;
default:
break;
}
return err;
}
static const struct ethtool_ops pcan_usb_pro_ethtool_ops = {
.set_phys_id = pcan_usb_pro_set_phys_id,
};
/*
* describe the PCAN-USB Pro adapter
*/
......@@ -1009,7 +1044,8 @@ const struct peak_usb_adapter pcan_usb_pro = {
.name = "PCAN-USB Pro",
.device_id = PCAN_USBPRO_PRODUCT_ID,
.ctrl_count = PCAN_USBPRO_CHANNEL_COUNT,
.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LISTENONLY,
.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_ONE_SHOT,
.clock = {
.freq = PCAN_USBPRO_CRYSTAL_HZ,
},
......@@ -1018,6 +1054,8 @@ const struct peak_usb_adapter pcan_usb_pro = {
/* size of device private data */
.sizeof_dev_private = sizeof(struct pcan_usb_pro_device),
.ethtool_ops = &pcan_usb_pro_ethtool_ops,
/* timestamps usage */
.ts_used_bits = 32,
.ts_period = 1000000, /* calibration period in ts. */
......
......@@ -115,6 +115,12 @@ struct __packed pcan_usb_pro_devid {
__le32 serial_num;
};
#define PCAN_USBPRO_LED_DEVICE 0x00
#define PCAN_USBPRO_LED_BLINK_FAST 0x01
#define PCAN_USBPRO_LED_BLINK_SLOW 0x02
#define PCAN_USBPRO_LED_ON 0x03
#define PCAN_USBPRO_LED_OFF 0x04
struct __packed pcan_usb_pro_setled {
u8 data_type;
u8 channel;
......
......@@ -246,7 +246,7 @@ struct ucan_message_in {
*/
struct ucan_tx_complete_entry_t can_tx_complete_msg[0];
} __aligned(0x4) msg;
} __packed;
} __packed __aligned(0x4);
/* Macros to calculate message lengths */
#define UCAN_OUT_HDR_SIZE offsetof(struct ucan_message_out, msg)
......@@ -675,7 +675,7 @@ static void ucan_tx_complete_msg(struct ucan_priv *up,
can_get_echo_skb(up->netdev, echo_index, NULL);
} else {
up->netdev->stats.tx_dropped++;
can_free_echo_skb(up->netdev, echo_index);
can_free_echo_skb(up->netdev, echo_index, NULL);
}
spin_unlock_irqrestore(&up->echo_skb_lock, flags);
}
......@@ -843,7 +843,7 @@ static void ucan_write_bulk_callback(struct urb *urb)
/* update counters an cleanup */
spin_lock_irqsave(&up->echo_skb_lock, flags);
can_free_echo_skb(up->netdev, context - up->context_array);
can_free_echo_skb(up->netdev, context - up->context_array, NULL);
spin_unlock_irqrestore(&up->echo_skb_lock, flags);
up->netdev->stats.tx_dropped++;
......@@ -1157,7 +1157,7 @@ static netdev_tx_t ucan_start_xmit(struct sk_buff *skb,
* frees the skb
*/
spin_lock_irqsave(&up->echo_skb_lock, flags);
can_free_echo_skb(up->netdev, echo_index);
can_free_echo_skb(up->netdev, echo_index, NULL);
spin_unlock_irqrestore(&up->echo_skb_lock, flags);
if (ret == -ENODEV) {
......
......@@ -691,7 +691,7 @@ static netdev_tx_t usb_8dev_start_xmit(struct sk_buff *skb,
return NETDEV_TX_BUSY;
failed:
can_free_echo_skb(netdev, context->echo_index);
can_free_echo_skb(netdev, context->echo_index, NULL);
usb_unanchor_urb(urb);
usb_free_coherent(priv->udev, size, buf, urb->transfer_dma);
......
......@@ -1772,17 +1772,15 @@ static int xcan_probe(struct platform_device *pdev)
/* Getting the CAN can_clk info */
priv->can_clk = devm_clk_get(&pdev->dev, "can_clk");
if (IS_ERR(priv->can_clk)) {
if (PTR_ERR(priv->can_clk) != -EPROBE_DEFER)
dev_err(&pdev->dev, "Device clock not found.\n");
ret = PTR_ERR(priv->can_clk);
ret = dev_err_probe(&pdev->dev, PTR_ERR(priv->can_clk),
"device clock not found\n");
goto err_free;
}
priv->bus_clk = devm_clk_get(&pdev->dev, devtype->bus_clk_name);
if (IS_ERR(priv->bus_clk)) {
if (PTR_ERR(priv->bus_clk) != -EPROBE_DEFER)
dev_err(&pdev->dev, "bus clock not found\n");
ret = PTR_ERR(priv->bus_clk);
ret = dev_err_probe(&pdev->dev, PTR_ERR(priv->bus_clk),
"bus clock not found\n");
goto err_free;
}
......
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2020 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
* Copyright (c) 2021 Vincent Mailhol <mailhol.vincent@wanadoo.fr>
*/
#ifndef _CAN_BITTIMING_H
......@@ -10,9 +11,83 @@
#define CAN_SYNC_SEG 1
/* Kilobits and Megabits per second */
#define CAN_KBPS 1000UL
#define CAN_MBPS 1000000UL
/* Megahertz */
#define CAN_MHZ 1000000UL
/*
* struct can_tdc - CAN FD Transmission Delay Compensation parameters
*
* At high bit rates, the propagation delay from the TX pin to the RX
* pin of the transceiver causes measurement errors: the sample point
* on the RX pin might occur on the previous bit.
*
* To solve this issue, ISO 11898-1 introduces in section 11.3.3
* "Transmitter delay compensation" a SSP (Secondary Sample Point)
* equal to the distance, in time quanta, from the start of the bit
* time on the TX pin to the actual measurement on the RX pin.
*
* This structure contains the parameters to calculate that SSP.
*
* @tdcv: Transmitter Delay Compensation Value. Distance, in time
* quanta, from when the bit is sent on the TX pin to when it is
* received on the RX pin of the transmitter. Possible options:
*
* O: automatic mode. The controller dynamically measure @tdcv
* for each transmitted CAN FD frame.
*
* Other values: manual mode. Use the fixed provided value.
*
* @tdco: Transmitter Delay Compensation Offset. Offset value, in time
* quanta, defining the distance between the start of the bit
* reception on the RX pin of the transceiver and the SSP
* position such as SSP = @tdcv + @tdco.
*
* If @tdco is zero, then TDC is disabled and both @tdcv and
* @tdcf should be ignored.
*
* @tdcf: Transmitter Delay Compensation Filter window. Defines the
* minimum value for the SSP position in time quanta. If SSP is
* less than @tdcf, then no delay compensations occur and the
* normal sampling point is used instead. The feature is enabled
* if and only if @tdcv is set to zero (automatic mode) and @tdcf
* is configured to a value greater than @tdco.
*/
struct can_tdc {
u32 tdcv;
u32 tdco;
u32 tdcf;
};
/*
* struct can_tdc_const - CAN hardware-dependent constant for
* Transmission Delay Compensation
*
* @tdcv_max: Transmitter Delay Compensation Value maximum value.
* Should be set to zero if the controller does not support
* manual mode for tdcv.
* @tdco_max: Transmitter Delay Compensation Offset maximum value.
* Should not be zero. If the controller does not support TDC,
* then the pointer to this structure should be NULL.
* @tdcf_max: Transmitter Delay Compensation Filter window maximum
* value. Should be set to zero if the controller does not
* support this feature.
*/
struct can_tdc_const {
u32 tdcv_max;
u32 tdco_max;
u32 tdcf_max;
};
#ifdef CONFIG_CAN_CALC_BITTIMING
int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc);
void can_calc_tdco(struct net_device *dev);
#else /* !CONFIG_CAN_CALC_BITTIMING */
static inline int
can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
......@@ -21,6 +96,10 @@ can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
netdev_err(dev, "bit-timing calculation not available\n");
return -EINVAL;
}
static inline void can_calc_tdco(struct net_device *dev)
{
}
#endif /* CONFIG_CAN_CALC_BITTIMING */
int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt,
......
......@@ -39,19 +39,23 @@ struct can_priv {
struct net_device *dev;
struct can_device_stats can_stats;
struct can_bittiming bittiming, data_bittiming;
const struct can_bittiming_const *bittiming_const,
*data_bittiming_const;
const u16 *termination_const;
unsigned int termination_const_cnt;
u16 termination;
const u32 *bitrate_const;
struct can_bittiming bittiming, data_bittiming;
const struct can_tdc_const *tdc_const;
struct can_tdc tdc;
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;
unsigned int termination_const_cnt;
const u16 *termination_const;
u16 termination;
enum can_state state;
/* CAN controller features - see include/uapi/linux/can/netlink.h */
......
......@@ -23,7 +23,8 @@ struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
u8 *len_ptr, unsigned int *frame_len_ptr);
unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx,
unsigned int *frame_len_ptr);
void can_free_echo_skb(struct net_device *dev, unsigned int idx);
void can_free_echo_skb(struct net_device *dev, unsigned int idx,
unsigned int *frame_len_ptr);
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);
......
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