linux-can-next-for-5.11-20201130

-----BEGIN PGP SIGNATURE-----
 
 iQFHBAABCgAxFiEEK3kIWJt9yTYMP3ehqclaivrt76kFAl/E/NkTHG1rbEBwZW5n
 dXRyb25peC5kZQAKCRCpyVqK+u3vqREXB/93EL5RGMeI48Yni3WEk0HZadw8oelq
 LWooZQjkNbpzboxwy9w7PspiMfrswkADH3bpPnGnWk9StUeHKgk7T+HxhWsQn/C+
 6xkeOjTr4/qxrKMC+xmgLpML+29gOXdyXFw2FOsHYi6F+bHZWWx483JiLUBc/+SP
 78TiyGSC8Y6cKkU113iPTEg/8FRqmajj/W0hbGgYdksXUPkCxQ3LK0jjt8jybCj0
 ojn7wsqiB0l7nZrgL09L1v9+jgsWwbC1I1kJSOxFVXK3gEcAbV08dbIufpWd649G
 sx8BOa+mkLHiOLdf9KZoLbvHXa/uVS1rZcmTBThdAkUw1cTwq2GmO/zI
 =3YGc
 -----END PGP SIGNATURE-----

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

Marc Kleine-Budde says:

====================
pull-request: can-next 2020-11-30

Gustavo A. R. Silva's patch for the pcan_usb driver fixes fall-through warnings
for Clang.

The next 5 patches target the mcp251xfd driver and are by Ursula Maplehurst and
me. They optimizie the TEF and RX path by reducing number of SPI core requests
to set the UINC bit.

The remaining 8 patches target the m_can driver. The first 4 are various
cleanups for the SPI binding driver (tcan4x5x) by Sean Nyekjaer, Dan Murphy and
me. Followed by 4 cleanup patches by me for the m_can and m_can_platform
driver.

* tag 'linux-can-next-for-5.11-20201130' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next:
  can: m_can: m_can_class_unregister(): move right after m_can_class_register()
  can: m_can: m_can_plat_remove(): remove unneeded platform_set_drvdata()
  can: m_can: remove not used variable struct m_can_classdev::freq
  can: m_can: Kconfig: convert the into menu
  can: tcan4x5x: tcan4x5x_can_probe(): remove probe failed error message
  can: tcan4x5x: remove mram_start and reg_offset from struct tcan4x5x_priv
  can: tcan4x5x: rename parse_config() function
  can: tcan4x5x: tcan4x5x_clear_interrupts(): remove redundant return statement
  can: mcp251xfd: tef-path: reduce number of SPI core requests to set UINC bit
  can: mcp251xfd: move struct mcp251xfd_tef_ring definition
  can: mcp251xfd: struct mcp251xfd_priv::tef to array of length 1
  can: mcp25xxfd: rx-path: reduce number of SPI core requests to set UINC bit
  can: mcp251xfd: mcp25xxfd_ring_alloc(): add define instead open coding the maximum number of RX objects
  can: pcan_usb_core: fix fall-through warnings for Clang
====================

Link: https://lore.kernel.org/r/20201130141432.278219-1-mkl@pengutronix.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2020-11-30 19:03:31 -08:00
commit cb7fb043e6
8 changed files with 151 additions and 79 deletions

View File

@ -1,21 +1,21 @@
# SPDX-License-Identifier: GPL-2.0-only
config CAN_M_CAN
menuconfig CAN_M_CAN
tristate "Bosch M_CAN support"
help
Say Y here if you want support for Bosch M_CAN controller framework.
This is common support for devices that embed the Bosch M_CAN IP.
if CAN_M_CAN
config CAN_M_CAN_PLATFORM
tristate "Bosch M_CAN support for io-mapped devices"
depends on HAS_IOMEM
depends on CAN_M_CAN
help
Say Y here if you want support for IO Mapped Bosch M_CAN controller.
This support is for devices that have the Bosch M_CAN controller
IP embedded into the device and the IP is IO Mapped to the processor.
config CAN_M_CAN_TCAN4X5X
depends on CAN_M_CAN
depends on SPI
select REGMAP_SPI
tristate "TCAN4X5X M_CAN device"
@ -23,3 +23,5 @@ config CAN_M_CAN_TCAN4X5X
Say Y here if you want support for Texas Instruments TCAN4x5x
M_CAN controller. This device is a peripheral device that uses the
SPI bus for communication.
endif

View File

@ -1869,6 +1869,14 @@ int m_can_class_register(struct m_can_classdev *m_can_dev)
}
EXPORT_SYMBOL_GPL(m_can_class_register);
void m_can_class_unregister(struct m_can_classdev *m_can_dev)
{
unregister_candev(m_can_dev->net);
m_can_clk_stop(m_can_dev);
}
EXPORT_SYMBOL_GPL(m_can_class_unregister);
int m_can_class_suspend(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
@ -1915,14 +1923,6 @@ int m_can_class_resume(struct device *dev)
}
EXPORT_SYMBOL_GPL(m_can_class_resume);
void m_can_class_unregister(struct m_can_classdev *m_can_dev)
{
unregister_candev(m_can_dev->net);
m_can_clk_stop(m_can_dev);
}
EXPORT_SYMBOL_GPL(m_can_class_unregister);
MODULE_AUTHOR("Dong Aisheng <b29396@freescale.com>");
MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
MODULE_LICENSE("GPL v2");

View File

@ -89,7 +89,6 @@ struct m_can_classdev {
void *device_data;
int version;
int freq;
u32 irqstatus;
int pm_clock_support;

View File

@ -141,8 +141,6 @@ static int m_can_plat_remove(struct platform_device *pdev)
m_can_class_free_dev(mcan_class->net);
platform_set_drvdata(pdev, NULL);
return 0;
}

View File

@ -123,10 +123,6 @@ struct tcan4x5x_priv {
struct gpio_desc *device_wake_gpio;
struct gpio_desc *device_state_gpio;
struct regulator *power;
/* Register based ip */
int mram_start;
int reg_offset;
};
static struct can_bittiming_const tcan4x5x_bittiming_const = {
@ -260,7 +256,7 @@ static u32 tcan4x5x_read_reg(struct m_can_classdev *cdev, int reg)
struct tcan4x5x_priv *priv = cdev->device_data;
u32 val;
regmap_read(priv->regmap, priv->reg_offset + reg, &val);
regmap_read(priv->regmap, TCAN4X5X_MCAN_OFFSET + reg, &val);
return val;
}
@ -270,7 +266,7 @@ static u32 tcan4x5x_read_fifo(struct m_can_classdev *cdev, int addr_offset)
struct tcan4x5x_priv *priv = cdev->device_data;
u32 val;
regmap_read(priv->regmap, priv->mram_start + addr_offset, &val);
regmap_read(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, &val);
return val;
}
@ -279,7 +275,7 @@ static int tcan4x5x_write_reg(struct m_can_classdev *cdev, int reg, int val)
{
struct tcan4x5x_priv *priv = cdev->device_data;
return regmap_write(priv->regmap, priv->reg_offset + reg, val);
return regmap_write(priv->regmap, TCAN4X5X_MCAN_OFFSET + reg, val);
}
static int tcan4x5x_write_fifo(struct m_can_classdev *cdev,
@ -287,7 +283,7 @@ static int tcan4x5x_write_fifo(struct m_can_classdev *cdev,
{
struct tcan4x5x_priv *priv = cdev->device_data;
return regmap_write(priv->regmap, priv->mram_start + addr_offset, val);
return regmap_write(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, val);
}
static int tcan4x5x_power_enable(struct regulator *reg, int enable)
@ -328,12 +324,8 @@ static int tcan4x5x_clear_interrupts(struct m_can_classdev *cdev)
if (ret)
return ret;
ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_ERROR_STATUS,
TCAN4X5X_CLEAR_ALL_INT);
if (ret)
return ret;
return ret;
return tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_ERROR_STATUS,
TCAN4X5X_CLEAR_ALL_INT);
}
static int tcan4x5x_init(struct m_can_classdev *cdev)
@ -379,7 +371,7 @@ static int tcan4x5x_disable_state(struct m_can_classdev *cdev)
TCAN4X5X_DISABLE_INH_MSK, 0x01);
}
static int tcan4x5x_parse_config(struct m_can_classdev *cdev)
static int tcan4x5x_get_gpios(struct m_can_classdev *cdev)
{
struct tcan4x5x_priv *tcan4x5x = cdev->device_data;
int ret;
@ -469,8 +461,6 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
goto out_m_can_class_free_dev;
}
priv->reg_offset = TCAN4X5X_MCAN_OFFSET;
priv->mram_start = TCAN4X5X_MRAM_START;
priv->spi = spi;
priv->mcan_dev = mcan_class;
@ -502,7 +492,7 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
if (ret)
goto out_clk;
ret = tcan4x5x_parse_config(mcan_class);
ret = tcan4x5x_get_gpios(mcan_class);
if (ret)
goto out_power;
@ -526,8 +516,6 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
}
out_m_can_class_free_dev:
m_can_class_free_dev(mcan_class->net);
dev_err(&spi->dev, "Probe failed, err=%d\n", ret);
return ret;
}

View File

@ -326,17 +326,36 @@ mcp251xfd_tx_ring_init_tx_obj(const struct mcp251xfd_priv *priv,
static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
{
struct mcp251xfd_tef_ring *tef_ring;
struct mcp251xfd_tx_ring *tx_ring;
struct mcp251xfd_rx_ring *rx_ring, *prev_rx_ring = NULL;
struct mcp251xfd_tx_obj *tx_obj;
u32 val;
u16 addr;
u8 len;
int i;
int i, j;
/* TEF */
priv->tef.head = 0;
priv->tef.tail = 0;
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++) {
struct spi_transfer *xfer;
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;
}
/* TX */
tx_ring = priv->tx;
@ -370,6 +389,23 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
prev_rx_ring->obj_num;
prev_rx_ring = rx_ring;
/* FIFO increment RX tail pointer */
addr = MCP251XFD_REG_FIFOCON(rx_ring->fifo_nr);
val = MCP251XFD_REG_FIFOCON_UINC;
len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->uinc_buf,
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;
xfer->cs_change = 1;
xfer->cs_change_delay.value = 0;
xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
}
}
}
@ -416,7 +452,8 @@ static int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
int rx_obj_num;
rx_obj_num = ram_free / rx_obj_size;
rx_obj_num = min(1 << (fls(rx_obj_num) - 1), 32);
rx_obj_num = min(1 << (fls(rx_obj_num) - 1),
MCP251XFD_RX_OBJ_NUM_MAX);
rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num,
GFP_KERNEL);
@ -1201,7 +1238,7 @@ mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq)
tef_sta & MCP251XFD_REG_TEFSTA_TEFFIF ?
"full" : tef_sta & MCP251XFD_REG_TEFSTA_TEFNEIF ?
"not empty" : "empty",
seq, priv->tef.tail, priv->tef.head, tx_ring->head);
seq, priv->tef->tail, priv->tef->head, tx_ring->head);
/* The Sequence Number in the TEF doesn't match our tef_tail. */
return -EAGAIN;
@ -1211,10 +1248,8 @@ static int
mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
const struct mcp251xfd_hw_tef_obj *hw_tef_obj)
{
struct mcp251xfd_tx_ring *tx_ring = priv->tx;
struct net_device_stats *stats = &priv->ndev->stats;
u32 seq, seq_masked, tef_tail_masked;
int err;
seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK,
hw_tef_obj->flags);
@ -1225,7 +1260,7 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
*/
seq_masked = seq &
field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK);
tef_tail_masked = priv->tef.tail &
tef_tail_masked = priv->tef->tail &
field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK);
if (seq_masked != tef_tail_masked)
return mcp251xfd_handle_tefif_recover(priv, seq);
@ -1235,18 +1270,9 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
mcp251xfd_get_tef_tail(priv),
hw_tef_obj->ts);
stats->tx_packets++;
priv->tef->tail++;
/* finally increment the TEF pointer */
err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_TEFCON,
GENMASK(15, 8),
MCP251XFD_REG_TEFCON_UINC);
if (err)
return err;
priv->tef.tail++;
tx_ring->tail++;
return mcp251xfd_check_tef_tail(priv);
return 0;
}
static int mcp251xfd_tef_ring_update(struct mcp251xfd_priv *priv)
@ -1263,12 +1289,12 @@ static int mcp251xfd_tef_ring_update(struct mcp251xfd_priv *priv)
/* chip_tx_tail, is the next TX-Object send by the HW.
* The new TEF head must be >= the old head, ...
*/
new_head = round_down(priv->tef.head, tx_ring->obj_num) + chip_tx_tail;
if (new_head <= priv->tef.head)
new_head = round_down(priv->tef->head, tx_ring->obj_num) + chip_tx_tail;
if (new_head <= priv->tef->head)
new_head += tx_ring->obj_num;
/* ... but it cannot exceed the TX head. */
priv->tef.head = min(new_head, tx_ring->head);
priv->tef->head = min(new_head, tx_ring->head);
return mcp251xfd_check_tef_tail(priv);
}
@ -1333,6 +1359,40 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
}
out_netif_wake_queue:
len = i; /* number of handled goods TEFs */
if (len) {
struct mcp251xfd_tef_ring *ring = priv->tef;
struct mcp251xfd_tx_ring *tx_ring = priv->tx;
struct spi_transfer *last_xfer;
tx_ring->tail += len;
/* 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.
*/
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;
if (err)
return err;
err = mcp251xfd_check_tef_tail(priv);
if (err)
return err;
}
mcp251xfd_ecc_tefif_successful(priv);
if (mcp251xfd_get_tx_free(priv->tx)) {
@ -1439,13 +1499,7 @@ mcp251xfd_handle_rxif_one(struct mcp251xfd_priv *priv,
if (err)
stats->rx_fifo_errors++;
ring->tail++;
/* finally increment the RX pointer */
return regmap_update_bits(priv->map_reg,
MCP251XFD_REG_FIFOCON(ring->fifo_nr),
GENMASK(15, 8),
MCP251XFD_REG_FIFOCON_UINC);
return 0;
}
static inline int
@ -1477,6 +1531,8 @@ mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv,
return err;
while ((len = mcp251xfd_get_rx_linear_len(ring))) {
struct spi_transfer *last_xfer;
rx_tail = mcp251xfd_get_rx_tail(ring);
err = mcp251xfd_rx_obj_read(priv, ring, hw_rx_obj,
@ -1491,6 +1547,28 @@ mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv,
if (err)
return err;
}
/* Increment the RX FIFO tail pointer 'len' times in a
* single SPI message.
*/
ring->tail += len;
/* 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.
*/
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;
if (err)
return err;
}
return 0;

View File

@ -368,6 +368,7 @@
* FIFO setup: tef: 8*12 bytes = 96 bytes, tx: 8*16 bytes = 128 bytes
* FIFO setup: tef: 4*12 bytes = 48 bytes, tx: 4*72 bytes = 288 bytes
*/
#define MCP251XFD_RX_OBJ_NUM_MAX 32
#define MCP251XFD_TX_OBJ_NUM_CAN 8
#define MCP251XFD_TX_OBJ_NUM_CANFD 4
@ -458,14 +459,6 @@ struct mcp251xfd_hw_rx_obj_canfd {
u8 data[sizeof_field(struct canfd_frame, data)];
};
struct mcp251xfd_tef_ring {
unsigned int head;
unsigned int tail;
/* u8 obj_num equals tx_ring->obj_num */
/* u8 obj_size equals sizeof(struct mcp251xfd_hw_tef_obj) */
};
struct __packed mcp251xfd_buf_cmd {
__be16 cmd;
};
@ -505,6 +498,17 @@ struct mcp251xfd_tx_obj {
union mcp251xfd_tx_obj_load_buf buf;
};
struct mcp251xfd_tef_ring {
unsigned int head;
unsigned int tail;
/* u8 obj_num equals tx_ring->obj_num */
/* u8 obj_size equals sizeof(struct mcp251xfd_hw_tef_obj) */
union mcp251xfd_write_reg_buf uinc_buf;
struct spi_transfer uinc_xfer[MCP251XFD_TX_OBJ_NUM_MAX];
};
struct mcp251xfd_tx_ring {
unsigned int head;
unsigned int tail;
@ -527,6 +531,8 @@ struct mcp251xfd_rx_ring {
u8 obj_num;
u8 obj_size;
union mcp251xfd_write_reg_buf uinc_buf;
struct spi_transfer uinc_xfer[MCP251XFD_RX_OBJ_NUM_MAX];
struct mcp251xfd_hw_rx_obj_canfd obj[];
};
@ -580,7 +586,7 @@ struct mcp251xfd_priv {
struct spi_device *spi;
u32 spi_max_speed_hz_orig;
struct mcp251xfd_tef_ring tef;
struct mcp251xfd_tef_ring tef[1];
struct mcp251xfd_tx_ring tx[1];
struct mcp251xfd_rx_ring *rx[1];
@ -741,17 +747,17 @@ mcp251xfd_get_rx_obj_addr(const struct mcp251xfd_rx_ring *ring, u8 n)
static inline u8 mcp251xfd_get_tef_head(const struct mcp251xfd_priv *priv)
{
return priv->tef.head & (priv->tx->obj_num - 1);
return priv->tef->head & (priv->tx->obj_num - 1);
}
static inline u8 mcp251xfd_get_tef_tail(const struct mcp251xfd_priv *priv)
{
return priv->tef.tail & (priv->tx->obj_num - 1);
return priv->tef->tail & (priv->tx->obj_num - 1);
}
static inline u8 mcp251xfd_get_tef_len(const struct mcp251xfd_priv *priv)
{
return priv->tef.head - priv->tef.tail;
return priv->tef->head - priv->tef->tail;
}
static inline u8 mcp251xfd_get_tef_linear_len(const struct mcp251xfd_priv *priv)

View File

@ -295,15 +295,16 @@ static void peak_usb_write_bulk_callback(struct urb *urb)
netif_trans_update(netdev);
break;
default:
if (net_ratelimit())
netdev_err(netdev, "Tx urb aborted (%d)\n",
urb->status);
case -EPROTO:
case -ENOENT:
case -ECONNRESET:
case -ESHUTDOWN:
break;
default:
if (net_ratelimit())
netdev_err(netdev, "Tx urb aborted (%d)\n",
urb->status);
break;
}