Commit fee62ea7 authored by David S. Miller's avatar David S. Miller

Merge tag 'linux-can-next-for-5.18-20220224' of...

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

Marc Kleine-Budde says:

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

The first 5 patches are by me and update various CAN DT bindings.

Eric Dumazet's patch for the CAN GW replaces a costly
synchronize_rcu() by a call_rcu().

The next 2 patches by me enhance the CAN bit rate handling, the bit
rate checking is simplified and the arguments and local variables of
functions are marked as const.

A patch by me for the kvaser_usb driver removes a redundant variable.

The next patch by me lets the c_can driver use the default ethtool
drvinfo.

Minghao Chi's patch for the softing driver removes a redundant
variable.

Srinivas Neeli contributes an enhancement for the xilinx_can NAPI poll
function.

Vincent Mailhol's patch for the etas_es58x driver converts to
BITS_PER_TYPE() from of manual calculation.

The next 23 patches target the mcp251xfd driver and are by me. The
first 15 patches, add support for the internal PLL, which includes
simplifying runtime PM handling, better chip detection and error
handling after wakeup, and the PLL handling. The last 8 patches
prepare the driver to support multiple RX-FIFOs and runtime
configurable RX/TX rings. The actual runtime ring configuration via
ethtool will be added in a later patch series.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e422eef2 aada7422
...@@ -10,6 +10,9 @@ maintainers: ...@@ -10,6 +10,9 @@ maintainers:
- Chen-Yu Tsai <wens@csie.org> - Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <mripard@kernel.org> - Maxime Ripard <mripard@kernel.org>
allOf:
- $ref: can-controller.yaml#
properties: properties:
compatible: compatible:
oneOf: oneOf:
......
...@@ -9,7 +9,10 @@ title: Bosch MCAN controller Bindings ...@@ -9,7 +9,10 @@ title: Bosch MCAN controller Bindings
description: Bosch MCAN controller for CAN bus description: Bosch MCAN controller for CAN bus
maintainers: maintainers:
- Sriram Dash <sriram.dash@samsung.com> - Chandrasekar Ramakrishnan <rcsekar@samsung.com>
allOf:
- $ref: can-controller.yaml#
properties: properties:
compatible: compatible:
...@@ -66,8 +69,8 @@ properties: ...@@ -66,8 +69,8 @@ properties:
M_CAN includes the following elements according to user manual: M_CAN includes the following elements according to user manual:
11-bit Filter 0-128 elements / 0-128 words 11-bit Filter 0-128 elements / 0-128 words
29-bit Filter 0-64 elements / 0-128 words 29-bit Filter 0-64 elements / 0-128 words
Rx FIFO 0 0-64 elements / 0-1152 words Rx FIFO 0 0-64 elements / 0-1152 words
Rx FIFO 1 0-64 elements / 0-1152 words Rx FIFO 1 0-64 elements / 0-1152 words
Rx Buffers 0-64 elements / 0-1152 words Rx Buffers 0-64 elements / 0-1152 words
Tx Event FIFO 0-32 elements / 0-64 words Tx Event FIFO 0-32 elements / 0-64 words
Tx Buffers 0-32 elements / 0-576 words Tx Buffers 0-32 elements / 0-576 words
......
...@@ -11,6 +11,9 @@ title: ...@@ -11,6 +11,9 @@ title:
maintainers: maintainers:
- Marc Kleine-Budde <mkl@pengutronix.de> - Marc Kleine-Budde <mkl@pengutronix.de>
allOf:
- $ref: can-controller.yaml#
properties: properties:
compatible: compatible:
oneOf: oneOf:
......
...@@ -11,14 +11,6 @@ ...@@ -11,14 +11,6 @@
#include "c_can.h" #include "c_can.h"
static void c_can_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *info)
{
struct c_can_priv *priv = netdev_priv(netdev);
strscpy(info->driver, "c_can", sizeof(info->driver));
strscpy(info->bus_info, dev_name(priv->device), sizeof(info->bus_info));
}
static void c_can_get_ringparam(struct net_device *netdev, static void c_can_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring, struct ethtool_ringparam *ring,
struct kernel_ethtool_ringparam *kernel_ring, struct kernel_ethtool_ringparam *kernel_ring,
...@@ -33,7 +25,6 @@ static void c_can_get_ringparam(struct net_device *netdev, ...@@ -33,7 +25,6 @@ static void c_can_get_ringparam(struct net_device *netdev,
} }
static const struct ethtool_ops c_can_ethtool_ops = { static const struct ethtool_ops c_can_ethtool_ops = {
.get_drvinfo = c_can_get_drvinfo,
.get_ringparam = c_can_get_ringparam, .get_ringparam = c_can_get_ringparam,
}; };
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
*/ */
static int static int
can_update_sample_point(const struct can_bittiming_const *btc, can_update_sample_point(const struct can_bittiming_const *btc,
unsigned int sample_point_nominal, unsigned int tseg, const unsigned int sample_point_nominal, const unsigned int tseg,
unsigned int *tseg1_ptr, unsigned int *tseg2_ptr, unsigned int *tseg1_ptr, unsigned int *tseg2_ptr,
unsigned int *sample_point_error_ptr) unsigned int *sample_point_error_ptr)
{ {
...@@ -63,7 +63,7 @@ can_update_sample_point(const struct can_bittiming_const *btc, ...@@ -63,7 +63,7 @@ can_update_sample_point(const struct can_bittiming_const *btc,
return best_sample_point; return best_sample_point;
} }
int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc) const struct can_bittiming_const *btc)
{ {
struct can_priv *priv = netdev_priv(dev); struct can_priv *priv = netdev_priv(dev);
...@@ -208,10 +208,10 @@ void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const, ...@@ -208,10 +208,10 @@ void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
* prescaler value brp. You can find more information in the header * prescaler value brp. You can find more information in the header
* file linux/can/netlink.h. * file linux/can/netlink.h.
*/ */
static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt, static int can_fixup_bittiming(const struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc) const struct can_bittiming_const *btc)
{ {
struct can_priv *priv = netdev_priv(dev); const struct can_priv *priv = netdev_priv(dev);
unsigned int tseg1, alltseg; unsigned int tseg1, alltseg;
u64 brp64; u64 brp64;
...@@ -244,25 +244,21 @@ static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt, ...@@ -244,25 +244,21 @@ static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt,
/* Checks the validity of predefined bitrate settings */ /* Checks the validity of predefined bitrate settings */
static int static int
can_validate_bitrate(struct net_device *dev, struct can_bittiming *bt, can_validate_bitrate(const struct net_device *dev, const struct can_bittiming *bt,
const u32 *bitrate_const, const u32 *bitrate_const,
const unsigned int bitrate_const_cnt) const unsigned int bitrate_const_cnt)
{ {
struct can_priv *priv = netdev_priv(dev);
unsigned int i; unsigned int i;
for (i = 0; i < bitrate_const_cnt; i++) { for (i = 0; i < bitrate_const_cnt; i++) {
if (bt->bitrate == bitrate_const[i]) if (bt->bitrate == bitrate_const[i])
break; return 0;
} }
if (i >= priv->bitrate_const_cnt) return -EINVAL;
return -EINVAL;
return 0;
} }
int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt, int can_get_bittiming(const struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc, const struct can_bittiming_const *btc,
const u32 *bitrate_const, const u32 *bitrate_const,
const unsigned int bitrate_const_cnt) const unsigned int bitrate_const_cnt)
......
...@@ -392,13 +392,10 @@ static int softing_netdev_open(struct net_device *ndev) ...@@ -392,13 +392,10 @@ static int softing_netdev_open(struct net_device *ndev)
static int softing_netdev_stop(struct net_device *ndev) static int softing_netdev_stop(struct net_device *ndev)
{ {
int ret;
netif_stop_queue(ndev); netif_stop_queue(ndev);
/* softing cycle does close_candev() */ /* softing cycle does close_candev() */
ret = softing_startstop(ndev, 0); return softing_startstop(ndev, 0);
return ret;
} }
static int softing_candev_set_mode(struct net_device *ndev, enum can_mode mode) static int softing_candev_set_mode(struct net_device *ndev, enum can_mode mode)
......
...@@ -78,7 +78,7 @@ int mcp251xfd_chip_fifo_init(const struct mcp251xfd_priv *priv) ...@@ -78,7 +78,7 @@ int mcp251xfd_chip_fifo_init(const struct mcp251xfd_priv *priv)
if (err) if (err)
return err; return err;
/* FIFO 1 - TX */ /* TX FIFO */
val = FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK, val = FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK,
tx_ring->obj_num - 1) | tx_ring->obj_num - 1) |
MCP251XFD_REG_FIFOCON_TXEN | MCP251XFD_REG_FIFOCON_TXEN |
...@@ -99,7 +99,7 @@ int mcp251xfd_chip_fifo_init(const struct mcp251xfd_priv *priv) ...@@ -99,7 +99,7 @@ int mcp251xfd_chip_fifo_init(const struct mcp251xfd_priv *priv)
MCP251XFD_REG_FIFOCON_TXAT_UNLIMITED); MCP251XFD_REG_FIFOCON_TXAT_UNLIMITED);
err = regmap_write(priv->map_reg, err = regmap_write(priv->map_reg,
MCP251XFD_REG_FIFOCON(MCP251XFD_TX_FIFO), MCP251XFD_REG_FIFOCON(priv->tx->fifo_nr),
val); val);
if (err) if (err)
return err; return err;
......
...@@ -207,10 +207,10 @@ static void mcp251xfd_dump_tx_ring(const struct mcp251xfd_priv *priv, ...@@ -207,10 +207,10 @@ static void mcp251xfd_dump_tx_ring(const struct mcp251xfd_priv *priv,
.val = tx->base, .val = tx->base,
}, { }, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_NR, .key = MCP251XFD_DUMP_OBJECT_RING_KEY_NR,
.val = 0, .val = tx->nr,
}, { }, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_FIFO_NR, .key = MCP251XFD_DUMP_OBJECT_RING_KEY_FIFO_NR,
.val = MCP251XFD_TX_FIFO, .val = tx->fifo_nr,
}, { }, {
.key = MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_NUM, .key = MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_NUM,
.val = tx->obj_num, .val = tx->obj_num,
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// //
// mcp251xfd - Microchip MCP251xFD Family CAN controller driver // mcp251xfd - Microchip MCP251xFD Family CAN controller driver
// //
// Copyright (c) 2019, 2020 Pengutronix, // Copyright (c) 2019, 2020, 2021 Pengutronix,
// Marc Kleine-Budde <kernel@pengutronix.de> // Marc Kleine-Budde <kernel@pengutronix.de>
// //
#include "mcp251xfd.h" #include "mcp251xfd.h"
...@@ -47,22 +47,32 @@ mcp251xfd_regmap_nocrc_gather_write(void *context, ...@@ -47,22 +47,32 @@ mcp251xfd_regmap_nocrc_gather_write(void *context,
return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer)); return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
} }
static inline bool mcp251xfd_update_bits_read_reg(unsigned int reg) static inline bool
mcp251xfd_update_bits_read_reg(const struct mcp251xfd_priv *priv,
unsigned int reg)
{ {
struct mcp251xfd_rx_ring *ring;
int n;
switch (reg) { switch (reg) {
case MCP251XFD_REG_INT: case MCP251XFD_REG_INT:
case MCP251XFD_REG_TEFCON: case MCP251XFD_REG_TEFCON:
case MCP251XFD_REG_FIFOCON(MCP251XFD_RX_FIFO(0)):
case MCP251XFD_REG_FLTCON(0): case MCP251XFD_REG_FLTCON(0):
case MCP251XFD_REG_ECCSTAT: case MCP251XFD_REG_ECCSTAT:
case MCP251XFD_REG_CRC: case MCP251XFD_REG_CRC:
return false; return false;
case MCP251XFD_REG_CON: case MCP251XFD_REG_CON:
case MCP251XFD_REG_FIFOSTA(MCP251XFD_RX_FIFO(0)):
case MCP251XFD_REG_OSC: case MCP251XFD_REG_OSC:
case MCP251XFD_REG_ECCCON: case MCP251XFD_REG_ECCCON:
return true; return true;
default: default:
mcp251xfd_for_each_rx_ring(priv, ring, n) {
if (reg == MCP251XFD_REG_FIFOCON(ring->fifo_nr))
return false;
if (reg == MCP251XFD_REG_FIFOSTA(ring->fifo_nr))
return true;
}
WARN(1, "Status of reg 0x%04x unknown.\n", reg); WARN(1, "Status of reg 0x%04x unknown.\n", reg);
} }
...@@ -92,7 +102,7 @@ mcp251xfd_regmap_nocrc_update_bits(void *context, unsigned int reg, ...@@ -92,7 +102,7 @@ mcp251xfd_regmap_nocrc_update_bits(void *context, unsigned int reg,
last_byte = mcp251xfd_last_byte_set(mask); last_byte = mcp251xfd_last_byte_set(mask);
len = last_byte - first_byte + 1; len = last_byte - first_byte + 1;
if (mcp251xfd_update_bits_read_reg(reg)) { if (mcp251xfd_update_bits_read_reg(priv, reg)) {
struct spi_transfer xfer[2] = { }; struct spi_transfer xfer[2] = { };
struct spi_message msg; struct spi_message msg;
...@@ -368,7 +378,7 @@ mcp251xfd_regmap_crc_read(void *context, ...@@ -368,7 +378,7 @@ mcp251xfd_regmap_crc_read(void *context,
* to the caller. It will take care of both cases. * to the caller. It will take care of both cases.
* *
*/ */
if (reg == MCP251XFD_REG_OSC) { if (reg == MCP251XFD_REG_OSC && val_len == sizeof(__le32)) {
err = 0; err = 0;
goto out; goto out;
} }
......
...@@ -52,6 +52,49 @@ mcp251xfd_cmd_prepare_write_reg(const struct mcp251xfd_priv *priv, ...@@ -52,6 +52,49 @@ mcp251xfd_cmd_prepare_write_reg(const struct mcp251xfd_priv *priv,
return len; return len;
} }
static void
mcp251xfd_ring_init_tef(struct mcp251xfd_priv *priv, u16 *base)
{
struct mcp251xfd_tef_ring *tef_ring;
struct spi_transfer *xfer;
u32 val;
u16 addr;
u8 len;
int i;
/* TEF */
tef_ring = priv->tef;
tef_ring->head = 0;
tef_ring->tail = 0;
/* TEF- and TX-FIFO have same number of objects */
*base = mcp251xfd_get_tef_obj_addr(priv->tx->obj_num);
/* FIFO increment TEF tail pointer */
addr = MCP251XFD_REG_TEFCON;
val = MCP251XFD_REG_TEFCON_UINC;
len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->uinc_buf,
addr, val, val);
for (i = 0; i < ARRAY_SIZE(tef_ring->uinc_xfer); i++) {
xfer = &tef_ring->uinc_xfer[i];
xfer->tx_buf = &tef_ring->uinc_buf;
xfer->len = len;
xfer->cs_change = 1;
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;
}
static void static void
mcp251xfd_tx_ring_init_tx_obj(const struct mcp251xfd_priv *priv, mcp251xfd_tx_ring_init_tx_obj(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_tx_ring *ring, const struct mcp251xfd_tx_ring *ring,
...@@ -88,81 +131,55 @@ mcp251xfd_tx_ring_init_tx_obj(const struct mcp251xfd_priv *priv, ...@@ -88,81 +131,55 @@ mcp251xfd_tx_ring_init_tx_obj(const struct mcp251xfd_priv *priv,
ARRAY_SIZE(tx_obj->xfer)); ARRAY_SIZE(tx_obj->xfer));
} }
void mcp251xfd_ring_init(struct mcp251xfd_priv *priv) static void
mcp251xfd_ring_init_tx(struct mcp251xfd_priv *priv, u16 *base, u8 *fifo_nr)
{ {
struct mcp251xfd_tef_ring *tef_ring;
struct mcp251xfd_tx_ring *tx_ring; struct mcp251xfd_tx_ring *tx_ring;
struct mcp251xfd_rx_ring *rx_ring, *prev_rx_ring = NULL;
struct mcp251xfd_tx_obj *tx_obj; struct mcp251xfd_tx_obj *tx_obj;
struct spi_transfer *xfer;
u32 val; u32 val;
u16 addr; u16 addr;
u8 len; u8 len;
int i, j; int i;
netdev_reset_queue(priv->ndev);
/* TEF */
tef_ring = priv->tef;
tef_ring->head = 0;
tef_ring->tail = 0;
/* FIFO increment TEF tail pointer */
addr = MCP251XFD_REG_TEFCON;
val = MCP251XFD_REG_TEFCON_UINC;
len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->uinc_buf,
addr, val, val);
for (j = 0; j < ARRAY_SIZE(tef_ring->uinc_xfer); j++) {
xfer = &tef_ring->uinc_xfer[j];
xfer->tx_buf = &tef_ring->uinc_buf;
xfer->len = len;
xfer->cs_change = 1;
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;
/* TX */
tx_ring = priv->tx; tx_ring = priv->tx;
tx_ring->head = 0; tx_ring->head = 0;
tx_ring->tail = 0; tx_ring->tail = 0;
tx_ring->base = mcp251xfd_get_tef_obj_addr(tx_ring->obj_num); tx_ring->base = *base;
tx_ring->nr = 0;
tx_ring->fifo_nr = *fifo_nr;
*base = mcp251xfd_get_tx_obj_addr(tx_ring, tx_ring->obj_num);
*fifo_nr += 1;
/* FIFO request to send */ /* FIFO request to send */
addr = MCP251XFD_REG_FIFOCON(MCP251XFD_TX_FIFO); addr = MCP251XFD_REG_FIFOCON(tx_ring->fifo_nr);
val = MCP251XFD_REG_FIFOCON_TXREQ | MCP251XFD_REG_FIFOCON_UINC; val = MCP251XFD_REG_FIFOCON_TXREQ | MCP251XFD_REG_FIFOCON_UINC;
len = mcp251xfd_cmd_prepare_write_reg(priv, &tx_ring->rts_buf, len = mcp251xfd_cmd_prepare_write_reg(priv, &tx_ring->rts_buf,
addr, val, val); addr, val, val);
mcp251xfd_for_each_tx_obj(tx_ring, tx_obj, i) mcp251xfd_for_each_tx_obj(tx_ring, tx_obj, i)
mcp251xfd_tx_ring_init_tx_obj(priv, tx_ring, tx_obj, len, i); mcp251xfd_tx_ring_init_tx_obj(priv, tx_ring, tx_obj, len, i);
}
static void
mcp251xfd_ring_init_rx(struct mcp251xfd_priv *priv, u16 *base, u8 *fifo_nr)
{
struct mcp251xfd_rx_ring *rx_ring;
struct spi_transfer *xfer;
u32 val;
u16 addr;
u8 len;
int i, j;
/* RX */
mcp251xfd_for_each_rx_ring(priv, rx_ring, i) { mcp251xfd_for_each_rx_ring(priv, rx_ring, i) {
rx_ring->head = 0; rx_ring->head = 0;
rx_ring->tail = 0; rx_ring->tail = 0;
rx_ring->base = *base;
rx_ring->nr = i; rx_ring->nr = i;
rx_ring->fifo_nr = MCP251XFD_RX_FIFO(i); rx_ring->fifo_nr = *fifo_nr;
if (!prev_rx_ring)
rx_ring->base =
mcp251xfd_get_tx_obj_addr(tx_ring,
tx_ring->obj_num);
else
rx_ring->base = prev_rx_ring->base +
prev_rx_ring->obj_size *
prev_rx_ring->obj_num;
prev_rx_ring = rx_ring; *base = mcp251xfd_get_rx_obj_addr(rx_ring, rx_ring->obj_num);
*fifo_nr += 1;
/* FIFO increment RX tail pointer */ /* FIFO increment RX tail pointer */
addr = MCP251XFD_REG_FIFOCON(rx_ring->fifo_nr); addr = MCP251XFD_REG_FIFOCON(rx_ring->fifo_nr);
...@@ -190,6 +207,74 @@ void mcp251xfd_ring_init(struct mcp251xfd_priv *priv) ...@@ -190,6 +207,74 @@ void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
} }
} }
int mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
{
const struct mcp251xfd_rx_ring *rx_ring;
u16 base = 0, ram_used;
u8 fifo_nr = 1;
int i;
netdev_reset_queue(priv->ndev);
mcp251xfd_ring_init_tef(priv, &base);
mcp251xfd_ring_init_rx(priv, &base, &fifo_nr);
mcp251xfd_ring_init_tx(priv, &base, &fifo_nr);
/* mcp251xfd_handle_rxif() will iterate over all RX rings.
* Rings with their corresponding bit set in
* priv->regs_status.rxif are read out.
*
* If the chip is configured for only 1 RX-FIFO, and if there
* is an RX interrupt pending (RXIF in INT register is set),
* it must be the 1st RX-FIFO.
*
* We mark the RXIF of the 1st FIFO as pending here, so that
* we can skip the read of the RXIF register in
* mcp251xfd_read_regs_status() for the 1 RX-FIFO only case.
*
* If we use more than 1 RX-FIFO, this value gets overwritten
* in mcp251xfd_read_regs_status(), so set it unconditionally
* here.
*/
priv->regs_status.rxif = BIT(priv->rx[0]->fifo_nr);
netdev_dbg(priv->ndev,
"FIFO setup: TEF: 0x%03x: %2d*%zu bytes = %4zu bytes\n",
mcp251xfd_get_tef_obj_addr(0),
priv->tx->obj_num, sizeof(struct mcp251xfd_hw_tef_obj),
priv->tx->obj_num * sizeof(struct mcp251xfd_hw_tef_obj));
mcp251xfd_for_each_rx_ring(priv, rx_ring, i) {
netdev_dbg(priv->ndev,
"FIFO setup: RX-%u: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes\n",
rx_ring->nr, rx_ring->fifo_nr,
mcp251xfd_get_rx_obj_addr(rx_ring, 0),
rx_ring->obj_num, rx_ring->obj_size,
rx_ring->obj_num * rx_ring->obj_size);
}
netdev_dbg(priv->ndev,
"FIFO setup: TX: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes\n",
priv->tx->fifo_nr,
mcp251xfd_get_tx_obj_addr(priv->tx, 0),
priv->tx->obj_num, priv->tx->obj_size,
priv->tx->obj_num * priv->tx->obj_size);
netdev_dbg(priv->ndev,
"FIFO setup: free: %4u bytes\n",
MCP251XFD_RAM_SIZE - (base - MCP251XFD_RAM_START));
ram_used = base - MCP251XFD_RAM_START;
if (ram_used > MCP251XFD_RAM_SIZE) {
netdev_err(priv->ndev,
"Error during ring configuration, using more RAM (%u bytes) than available (%u bytes).\n",
ram_used, MCP251XFD_RAM_SIZE);
return -ENOMEM;
}
return 0;
}
void mcp251xfd_ring_free(struct mcp251xfd_priv *priv) void mcp251xfd_ring_free(struct mcp251xfd_priv *priv)
{ {
int i; int i;
...@@ -249,21 +334,5 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv) ...@@ -249,21 +334,5 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
} }
priv->rx_ring_num = i; priv->rx_ring_num = i;
netdev_dbg(priv->ndev,
"FIFO setup: TEF: %d*%d bytes = %d bytes, TX: %d*%d bytes = %d bytes\n",
tx_obj_num, tef_obj_size, tef_obj_size * tx_obj_num,
tx_obj_num, tx_obj_size, tx_obj_size * tx_obj_num);
mcp251xfd_for_each_rx_ring(priv, rx_ring, i) {
netdev_dbg(priv->ndev,
"FIFO setup: RX-%d: %d*%d bytes = %d bytes\n",
i, rx_ring->obj_num, rx_ring->obj_size,
rx_ring->obj_size * rx_ring->obj_num);
}
netdev_dbg(priv->ndev,
"FIFO setup: free: %d bytes\n",
ram_free);
return 0; return 0;
} }
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
static inline int static inline int
mcp251xfd_rx_head_get_from_chip(const struct mcp251xfd_priv *priv, mcp251xfd_rx_head_get_from_chip(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_rx_ring *ring, const struct mcp251xfd_rx_ring *ring,
u8 *rx_head) u8 *rx_head, bool *fifo_empty)
{ {
u32 fifo_sta; u32 fifo_sta;
int err; int err;
...@@ -30,6 +30,7 @@ mcp251xfd_rx_head_get_from_chip(const struct mcp251xfd_priv *priv, ...@@ -30,6 +30,7 @@ mcp251xfd_rx_head_get_from_chip(const struct mcp251xfd_priv *priv,
return err; return err;
*rx_head = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta); *rx_head = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta);
*fifo_empty = !(fifo_sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF);
return 0; return 0;
} }
...@@ -84,10 +85,12 @@ mcp251xfd_rx_ring_update(const struct mcp251xfd_priv *priv, ...@@ -84,10 +85,12 @@ mcp251xfd_rx_ring_update(const struct mcp251xfd_priv *priv,
{ {
u32 new_head; u32 new_head;
u8 chip_rx_head; u8 chip_rx_head;
bool fifo_empty;
int err; int err;
err = mcp251xfd_rx_head_get_from_chip(priv, ring, &chip_rx_head); err = mcp251xfd_rx_head_get_from_chip(priv, ring, &chip_rx_head,
if (err) &fifo_empty);
if (err || fifo_empty)
return err; return err;
/* chip_rx_head, is the next RX-Object filled by the HW. /* chip_rx_head, is the next RX-Object filled by the HW.
...@@ -251,6 +254,9 @@ int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv) ...@@ -251,6 +254,9 @@ int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv)
int err, n; int err, n;
mcp251xfd_for_each_rx_ring(priv, ring, n) { mcp251xfd_for_each_rx_ring(priv, ring, n) {
if (!(priv->regs_status.rxif & BIT(ring->fifo_nr)))
continue;
err = mcp251xfd_handle_rxif_ring(priv, ring); err = mcp251xfd_handle_rxif_ring(priv, ring);
if (err) if (err)
return err; return err;
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
* *
* mcp251xfd - Microchip MCP251xFD Family CAN controller driver * mcp251xfd - Microchip MCP251xFD Family CAN controller driver
* *
* Copyright (c) 2019 Pengutronix, * Copyright (c) 2019, 2020, 2021 Pengutronix,
* Marc Kleine-Budde <kernel@pengutronix.de> * Marc Kleine-Budde <kernel@pengutronix.de>
* Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org> * Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org>
*/ */
...@@ -383,8 +383,6 @@ ...@@ -383,8 +383,6 @@
#endif #endif
#define MCP251XFD_NAPI_WEIGHT 32 #define MCP251XFD_NAPI_WEIGHT 32
#define MCP251XFD_TX_FIFO 1
#define MCP251XFD_RX_FIFO(x) (MCP251XFD_TX_FIFO + 1 + (x))
/* SPI commands */ /* SPI commands */
#define MCP251XFD_SPI_INSTRUCTION_RESET 0x0000 #define MCP251XFD_SPI_INSTRUCTION_RESET 0x0000
...@@ -412,6 +410,15 @@ static_assert(MCP251XFD_TIMESTAMP_WORK_DELAY_SEC < ...@@ -412,6 +410,15 @@ static_assert(MCP251XFD_TIMESTAMP_WORK_DELAY_SEC <
#define MCP251XFD_SANITIZE_SPI 1 #define MCP251XFD_SANITIZE_SPI 1
#define MCP251XFD_SANITIZE_CAN 1 #define MCP251XFD_SANITIZE_CAN 1
/* FIFO and Ring */
#define MCP251XFD_FIFO_TEF_NUM 1U
#define MCP251XFD_FIFO_RX_NUM_MAX 1U
#define MCP251XFD_FIFO_TX_NUM 1U
static_assert(MCP251XFD_FIFO_TEF_NUM == 1U);
static_assert(MCP251XFD_FIFO_TEF_NUM == MCP251XFD_FIFO_TX_NUM);
static_assert(MCP251XFD_FIFO_RX_NUM_MAX <= 4U);
/* Silence TX MAB overflow warnings */ /* Silence TX MAB overflow warnings */
#define MCP251XFD_QUIRK_MAB_NO_WARN BIT(0) #define MCP251XFD_QUIRK_MAB_NO_WARN BIT(0)
/* Use CRC to access registers */ /* Use CRC to access registers */
...@@ -521,6 +528,8 @@ struct mcp251xfd_tx_ring { ...@@ -521,6 +528,8 @@ struct mcp251xfd_tx_ring {
unsigned int tail; unsigned int tail;
u16 base; u16 base;
u8 nr;
u8 fifo_nr;
u8 obj_num; u8 obj_num;
u8 obj_size; u8 obj_size;
...@@ -561,6 +570,7 @@ struct mcp251xfd_ecc { ...@@ -561,6 +570,7 @@ struct mcp251xfd_ecc {
struct mcp251xfd_regs_status { struct mcp251xfd_regs_status {
u32 intf; u32 intf;
u32 rxif;
}; };
enum mcp251xfd_model { enum mcp251xfd_model {
...@@ -592,10 +602,12 @@ struct mcp251xfd_priv { ...@@ -592,10 +602,12 @@ struct mcp251xfd_priv {
struct spi_device *spi; struct spi_device *spi;
u32 spi_max_speed_hz_orig; u32 spi_max_speed_hz_orig;
u32 spi_max_speed_hz_fast;
u32 spi_max_speed_hz_slow;
struct mcp251xfd_tef_ring tef[1]; struct mcp251xfd_tef_ring tef[MCP251XFD_FIFO_TEF_NUM];
struct mcp251xfd_tx_ring tx[1]; struct mcp251xfd_rx_ring *rx[MCP251XFD_FIFO_RX_NUM_MAX];
struct mcp251xfd_rx_ring *rx[1]; struct mcp251xfd_tx_ring tx[MCP251XFD_FIFO_TX_NUM];
u8 rx_ring_num; u8 rx_ring_num;
...@@ -608,6 +620,7 @@ struct mcp251xfd_priv { ...@@ -608,6 +620,7 @@ struct mcp251xfd_priv {
struct gpio_desc *rx_int; struct gpio_desc *rx_int;
struct clk *clk; struct clk *clk;
bool pll_enable;
struct regulator *reg_vdd; struct regulator *reg_vdd;
struct regulator *reg_xceiver; struct regulator *reg_xceiver;
...@@ -776,7 +789,7 @@ mcp251xfd_tx_tail_get_from_chip(const struct mcp251xfd_priv *priv, ...@@ -776,7 +789,7 @@ mcp251xfd_tx_tail_get_from_chip(const struct mcp251xfd_priv *priv,
int err; int err;
err = regmap_read(priv->map_reg, err = regmap_read(priv->map_reg,
MCP251XFD_REG_FIFOSTA(MCP251XFD_TX_FIFO), MCP251XFD_REG_FIFOSTA(priv->tx->fifo_nr),
&fifo_sta); &fifo_sta);
if (err) if (err)
return err; return err;
...@@ -879,7 +892,7 @@ u16 mcp251xfd_crc16_compute2(const void *cmd, size_t cmd_size, ...@@ -879,7 +892,7 @@ u16 mcp251xfd_crc16_compute2(const void *cmd, size_t cmd_size,
const void *data, size_t data_size); const void *data, size_t data_size);
u16 mcp251xfd_crc16_compute(const void *data, size_t data_size); u16 mcp251xfd_crc16_compute(const void *data, size_t data_size);
int mcp251xfd_regmap_init(struct mcp251xfd_priv *priv); int mcp251xfd_regmap_init(struct mcp251xfd_priv *priv);
void mcp251xfd_ring_init(struct mcp251xfd_priv *priv); int mcp251xfd_ring_init(struct mcp251xfd_priv *priv);
void mcp251xfd_ring_free(struct mcp251xfd_priv *priv); void mcp251xfd_ring_free(struct mcp251xfd_priv *priv);
int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv); int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv);
int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv); int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv);
......
...@@ -69,7 +69,8 @@ static int es58x_fd_echo_msg(struct net_device *netdev, ...@@ -69,7 +69,8 @@ static int es58x_fd_echo_msg(struct net_device *netdev,
int i, num_element; int i, num_element;
u32 rcv_packet_idx; u32 rcv_packet_idx;
const u32 mask = GENMASK(31, sizeof(echo_msg->packet_idx) * 8); const u32 mask = GENMASK(BITS_PER_TYPE(mask) - 1,
BITS_PER_TYPE(echo_msg->packet_idx));
num_element = es58x_msg_num_element(es58x_dev->dev, num_element = es58x_msg_num_element(es58x_dev->dev,
es58x_fd_urb_cmd->echo_msg, es58x_fd_urb_cmd->echo_msg,
......
...@@ -205,12 +205,10 @@ MODULE_DEVICE_TABLE(usb, kvaser_usb_table); ...@@ -205,12 +205,10 @@ MODULE_DEVICE_TABLE(usb, kvaser_usb_table);
int kvaser_usb_send_cmd(const struct kvaser_usb *dev, void *cmd, int len) int kvaser_usb_send_cmd(const struct kvaser_usb *dev, void *cmd, int len)
{ {
int actual_len; /* Not used */
return usb_bulk_msg(dev->udev, return usb_bulk_msg(dev->udev,
usb_sndbulkpipe(dev->udev, usb_sndbulkpipe(dev->udev,
dev->bulk_out->bEndpointAddress), dev->bulk_out->bEndpointAddress),
cmd, len, &actual_len, KVASER_USB_TIMEOUT); cmd, len, NULL, KVASER_USB_TIMEOUT);
} }
int kvaser_usb_recv_cmd(const struct kvaser_usb *dev, void *cmd, int len, int kvaser_usb_recv_cmd(const struct kvaser_usb *dev, void *cmd, int len,
......
...@@ -1215,10 +1215,11 @@ static int xcan_rx_poll(struct napi_struct *napi, int quota) ...@@ -1215,10 +1215,11 @@ static int xcan_rx_poll(struct napi_struct *napi, int quota)
} }
if (work_done < quota) { if (work_done < quota) {
napi_complete_done(napi, work_done); if (napi_complete_done(napi, work_done)) {
ier = priv->read_reg(priv, XCAN_IER_OFFSET); ier = priv->read_reg(priv, XCAN_IER_OFFSET);
ier |= xcan_rx_int_mask(priv); ier |= xcan_rx_int_mask(priv);
priv->write_reg(priv, XCAN_IER_OFFSET, ier); priv->write_reg(priv, XCAN_IER_OFFSET, ier);
}
} }
return work_done; return work_done;
} }
......
...@@ -113,7 +113,7 @@ struct can_tdc_const { ...@@ -113,7 +113,7 @@ struct can_tdc_const {
}; };
#ifdef CONFIG_CAN_CALC_BITTIMING #ifdef CONFIG_CAN_CALC_BITTIMING
int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc); const struct can_bittiming_const *btc);
void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const, void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
...@@ -121,7 +121,7 @@ void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const, ...@@ -121,7 +121,7 @@ void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
u32 *ctrlmode, u32 ctrlmode_supported); u32 *ctrlmode, u32 ctrlmode_supported);
#else /* !CONFIG_CAN_CALC_BITTIMING */ #else /* !CONFIG_CAN_CALC_BITTIMING */
static inline int static inline int
can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc) const struct can_bittiming_const *btc)
{ {
netdev_err(dev, "bit-timing calculation not available\n"); netdev_err(dev, "bit-timing calculation not available\n");
...@@ -136,7 +136,7 @@ can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const, ...@@ -136,7 +136,7 @@ can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
} }
#endif /* CONFIG_CAN_CALC_BITTIMING */ #endif /* CONFIG_CAN_CALC_BITTIMING */
int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt, int can_get_bittiming(const struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc, const struct can_bittiming_const *btc,
const u32 *bitrate_const, const u32 *bitrate_const,
const unsigned int bitrate_const_cnt); const unsigned int bitrate_const_cnt);
......
...@@ -577,6 +577,13 @@ static inline void cgw_unregister_filter(struct net *net, struct cgw_job *gwj) ...@@ -577,6 +577,13 @@ static inline void cgw_unregister_filter(struct net *net, struct cgw_job *gwj)
gwj->ccgw.filter.can_mask, can_can_gw_rcv, gwj); gwj->ccgw.filter.can_mask, can_can_gw_rcv, gwj);
} }
static void cgw_job_free_rcu(struct rcu_head *rcu_head)
{
struct cgw_job *gwj = container_of(rcu_head, struct cgw_job, rcu);
kmem_cache_free(cgw_cache, gwj);
}
static int cgw_notifier(struct notifier_block *nb, static int cgw_notifier(struct notifier_block *nb,
unsigned long msg, void *ptr) unsigned long msg, void *ptr)
{ {
...@@ -596,8 +603,7 @@ static int cgw_notifier(struct notifier_block *nb, ...@@ -596,8 +603,7 @@ static int cgw_notifier(struct notifier_block *nb,
if (gwj->src.dev == dev || gwj->dst.dev == dev) { if (gwj->src.dev == dev || gwj->dst.dev == dev) {
hlist_del(&gwj->list); hlist_del(&gwj->list);
cgw_unregister_filter(net, gwj); cgw_unregister_filter(net, gwj);
synchronize_rcu(); call_rcu(&gwj->rcu, cgw_job_free_rcu);
kmem_cache_free(cgw_cache, gwj);
} }
} }
} }
...@@ -1155,8 +1161,7 @@ static void cgw_remove_all_jobs(struct net *net) ...@@ -1155,8 +1161,7 @@ static void cgw_remove_all_jobs(struct net *net)
hlist_for_each_entry_safe(gwj, nx, &net->can.cgw_list, list) { hlist_for_each_entry_safe(gwj, nx, &net->can.cgw_list, list) {
hlist_del(&gwj->list); hlist_del(&gwj->list);
cgw_unregister_filter(net, gwj); cgw_unregister_filter(net, gwj);
synchronize_rcu(); call_rcu(&gwj->rcu, cgw_job_free_rcu);
kmem_cache_free(cgw_cache, gwj);
} }
} }
...@@ -1224,8 +1229,7 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1224,8 +1229,7 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh,
hlist_del(&gwj->list); hlist_del(&gwj->list);
cgw_unregister_filter(net, gwj); cgw_unregister_filter(net, gwj);
synchronize_rcu(); call_rcu(&gwj->rcu, cgw_job_free_rcu);
kmem_cache_free(cgw_cache, gwj);
err = 0; err = 0;
break; break;
} }
......
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