Commit cb7fb043 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'linux-can-next-for-5.11-20201130' of...

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.deSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 76810ed8 6d9986b4
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
config CAN_M_CAN menuconfig CAN_M_CAN
tristate "Bosch M_CAN support" tristate "Bosch M_CAN support"
help help
Say Y here if you want support for Bosch M_CAN controller framework. 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. This is common support for devices that embed the Bosch M_CAN IP.
if CAN_M_CAN
config CAN_M_CAN_PLATFORM config CAN_M_CAN_PLATFORM
tristate "Bosch M_CAN support for io-mapped devices" tristate "Bosch M_CAN support for io-mapped devices"
depends on HAS_IOMEM depends on HAS_IOMEM
depends on CAN_M_CAN
help help
Say Y here if you want support for IO Mapped Bosch M_CAN controller. 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 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. IP embedded into the device and the IP is IO Mapped to the processor.
config CAN_M_CAN_TCAN4X5X config CAN_M_CAN_TCAN4X5X
depends on CAN_M_CAN
depends on SPI depends on SPI
select REGMAP_SPI select REGMAP_SPI
tristate "TCAN4X5X M_CAN device" tristate "TCAN4X5X M_CAN device"
...@@ -23,3 +23,5 @@ config CAN_M_CAN_TCAN4X5X ...@@ -23,3 +23,5 @@ config CAN_M_CAN_TCAN4X5X
Say Y here if you want support for Texas Instruments TCAN4x5x Say Y here if you want support for Texas Instruments TCAN4x5x
M_CAN controller. This device is a peripheral device that uses the M_CAN controller. This device is a peripheral device that uses the
SPI bus for communication. SPI bus for communication.
endif
...@@ -1869,6 +1869,14 @@ int m_can_class_register(struct m_can_classdev *m_can_dev) ...@@ -1869,6 +1869,14 @@ int m_can_class_register(struct m_can_classdev *m_can_dev)
} }
EXPORT_SYMBOL_GPL(m_can_class_register); 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) int m_can_class_suspend(struct device *dev)
{ {
struct net_device *ndev = dev_get_drvdata(dev); struct net_device *ndev = dev_get_drvdata(dev);
...@@ -1915,14 +1923,6 @@ int m_can_class_resume(struct device *dev) ...@@ -1915,14 +1923,6 @@ int m_can_class_resume(struct device *dev)
} }
EXPORT_SYMBOL_GPL(m_can_class_resume); 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("Dong Aisheng <b29396@freescale.com>");
MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>"); MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
......
...@@ -89,7 +89,6 @@ struct m_can_classdev { ...@@ -89,7 +89,6 @@ struct m_can_classdev {
void *device_data; void *device_data;
int version; int version;
int freq;
u32 irqstatus; u32 irqstatus;
int pm_clock_support; int pm_clock_support;
......
...@@ -141,8 +141,6 @@ static int m_can_plat_remove(struct platform_device *pdev) ...@@ -141,8 +141,6 @@ static int m_can_plat_remove(struct platform_device *pdev)
m_can_class_free_dev(mcan_class->net); m_can_class_free_dev(mcan_class->net);
platform_set_drvdata(pdev, NULL);
return 0; return 0;
} }
......
...@@ -123,10 +123,6 @@ struct tcan4x5x_priv { ...@@ -123,10 +123,6 @@ struct tcan4x5x_priv {
struct gpio_desc *device_wake_gpio; struct gpio_desc *device_wake_gpio;
struct gpio_desc *device_state_gpio; struct gpio_desc *device_state_gpio;
struct regulator *power; struct regulator *power;
/* Register based ip */
int mram_start;
int reg_offset;
}; };
static struct can_bittiming_const tcan4x5x_bittiming_const = { static struct can_bittiming_const tcan4x5x_bittiming_const = {
...@@ -260,7 +256,7 @@ static u32 tcan4x5x_read_reg(struct m_can_classdev *cdev, int reg) ...@@ -260,7 +256,7 @@ static u32 tcan4x5x_read_reg(struct m_can_classdev *cdev, int reg)
struct tcan4x5x_priv *priv = cdev->device_data; struct tcan4x5x_priv *priv = cdev->device_data;
u32 val; u32 val;
regmap_read(priv->regmap, priv->reg_offset + reg, &val); regmap_read(priv->regmap, TCAN4X5X_MCAN_OFFSET + reg, &val);
return val; return val;
} }
...@@ -270,7 +266,7 @@ static u32 tcan4x5x_read_fifo(struct m_can_classdev *cdev, int addr_offset) ...@@ -270,7 +266,7 @@ static u32 tcan4x5x_read_fifo(struct m_can_classdev *cdev, int addr_offset)
struct tcan4x5x_priv *priv = cdev->device_data; struct tcan4x5x_priv *priv = cdev->device_data;
u32 val; u32 val;
regmap_read(priv->regmap, priv->mram_start + addr_offset, &val); regmap_read(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, &val);
return val; return val;
} }
...@@ -279,7 +275,7 @@ static int tcan4x5x_write_reg(struct m_can_classdev *cdev, int reg, int 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; 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, static int tcan4x5x_write_fifo(struct m_can_classdev *cdev,
...@@ -287,7 +283,7 @@ 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; 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) static int tcan4x5x_power_enable(struct regulator *reg, int enable)
...@@ -328,12 +324,8 @@ static int tcan4x5x_clear_interrupts(struct m_can_classdev *cdev) ...@@ -328,12 +324,8 @@ static int tcan4x5x_clear_interrupts(struct m_can_classdev *cdev)
if (ret) if (ret)
return ret; return ret;
ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_ERROR_STATUS, return tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_ERROR_STATUS,
TCAN4X5X_CLEAR_ALL_INT); TCAN4X5X_CLEAR_ALL_INT);
if (ret)
return ret;
return ret;
} }
static int tcan4x5x_init(struct m_can_classdev *cdev) static int tcan4x5x_init(struct m_can_classdev *cdev)
...@@ -379,7 +371,7 @@ static int tcan4x5x_disable_state(struct m_can_classdev *cdev) ...@@ -379,7 +371,7 @@ static int tcan4x5x_disable_state(struct m_can_classdev *cdev)
TCAN4X5X_DISABLE_INH_MSK, 0x01); 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; struct tcan4x5x_priv *tcan4x5x = cdev->device_data;
int ret; int ret;
...@@ -469,8 +461,6 @@ static int tcan4x5x_can_probe(struct spi_device *spi) ...@@ -469,8 +461,6 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
goto out_m_can_class_free_dev; goto out_m_can_class_free_dev;
} }
priv->reg_offset = TCAN4X5X_MCAN_OFFSET;
priv->mram_start = TCAN4X5X_MRAM_START;
priv->spi = spi; priv->spi = spi;
priv->mcan_dev = mcan_class; priv->mcan_dev = mcan_class;
...@@ -502,7 +492,7 @@ static int tcan4x5x_can_probe(struct spi_device *spi) ...@@ -502,7 +492,7 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
if (ret) if (ret)
goto out_clk; goto out_clk;
ret = tcan4x5x_parse_config(mcan_class); ret = tcan4x5x_get_gpios(mcan_class);
if (ret) if (ret)
goto out_power; goto out_power;
...@@ -526,8 +516,6 @@ static int tcan4x5x_can_probe(struct spi_device *spi) ...@@ -526,8 +516,6 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
} }
out_m_can_class_free_dev: out_m_can_class_free_dev:
m_can_class_free_dev(mcan_class->net); m_can_class_free_dev(mcan_class->net);
dev_err(&spi->dev, "Probe failed, err=%d\n", ret);
return ret; return ret;
} }
......
...@@ -326,17 +326,36 @@ mcp251xfd_tx_ring_init_tx_obj(const struct mcp251xfd_priv *priv, ...@@ -326,17 +326,36 @@ mcp251xfd_tx_ring_init_tx_obj(const struct mcp251xfd_priv *priv,
static void mcp251xfd_ring_init(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_tx_ring *tx_ring;
struct mcp251xfd_rx_ring *rx_ring, *prev_rx_ring = NULL; struct mcp251xfd_rx_ring *rx_ring, *prev_rx_ring = NULL;
struct mcp251xfd_tx_obj *tx_obj; struct mcp251xfd_tx_obj *tx_obj;
u32 val; u32 val;
u16 addr; u16 addr;
u8 len; u8 len;
int i; int i, j;
/* TEF */ /* TEF */
priv->tef.head = 0; tef_ring = priv->tef;
priv->tef.tail = 0; 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 */
tx_ring = priv->tx; tx_ring = priv->tx;
...@@ -370,6 +389,23 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv) ...@@ -370,6 +389,23 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
prev_rx_ring->obj_num; prev_rx_ring->obj_num;
prev_rx_ring = rx_ring; 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) ...@@ -416,7 +452,8 @@ static int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
int rx_obj_num; int rx_obj_num;
rx_obj_num = ram_free / rx_obj_size; 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, rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num,
GFP_KERNEL); GFP_KERNEL);
...@@ -1201,7 +1238,7 @@ mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq) ...@@ -1201,7 +1238,7 @@ mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq)
tef_sta & MCP251XFD_REG_TEFSTA_TEFFIF ? tef_sta & MCP251XFD_REG_TEFSTA_TEFFIF ?
"full" : tef_sta & MCP251XFD_REG_TEFSTA_TEFNEIF ? "full" : tef_sta & MCP251XFD_REG_TEFSTA_TEFNEIF ?
"not empty" : "empty", "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. */ /* The Sequence Number in the TEF doesn't match our tef_tail. */
return -EAGAIN; return -EAGAIN;
...@@ -1211,10 +1248,8 @@ static int ...@@ -1211,10 +1248,8 @@ static int
mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv, mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
const struct mcp251xfd_hw_tef_obj *hw_tef_obj) 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; struct net_device_stats *stats = &priv->ndev->stats;
u32 seq, seq_masked, tef_tail_masked; u32 seq, seq_masked, tef_tail_masked;
int err;
seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK,
hw_tef_obj->flags); hw_tef_obj->flags);
...@@ -1225,7 +1260,7 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv, ...@@ -1225,7 +1260,7 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
*/ */
seq_masked = seq & seq_masked = seq &
field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK); 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); field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK);
if (seq_masked != tef_tail_masked) if (seq_masked != tef_tail_masked)
return mcp251xfd_handle_tefif_recover(priv, seq); return mcp251xfd_handle_tefif_recover(priv, seq);
...@@ -1235,18 +1270,9 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv, ...@@ -1235,18 +1270,9 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
mcp251xfd_get_tef_tail(priv), mcp251xfd_get_tef_tail(priv),
hw_tef_obj->ts); hw_tef_obj->ts);
stats->tx_packets++; stats->tx_packets++;
priv->tef->tail++;
/* finally increment the TEF pointer */ return 0;
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);
} }
static int mcp251xfd_tef_ring_update(struct mcp251xfd_priv *priv) static int mcp251xfd_tef_ring_update(struct mcp251xfd_priv *priv)
...@@ -1263,12 +1289,12 @@ 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. /* chip_tx_tail, is the next TX-Object send by the HW.
* The new TEF head must be >= the old head, ... * The new TEF head must be >= the old head, ...
*/ */
new_head = round_down(priv->tef.head, tx_ring->obj_num) + chip_tx_tail; new_head = round_down(priv->tef->head, tx_ring->obj_num) + chip_tx_tail;
if (new_head <= priv->tef.head) if (new_head <= priv->tef->head)
new_head += tx_ring->obj_num; new_head += tx_ring->obj_num;
/* ... but it cannot exceed the TX head. */ /* ... 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); return mcp251xfd_check_tef_tail(priv);
} }
...@@ -1333,6 +1359,40 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv) ...@@ -1333,6 +1359,40 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
} }
out_netif_wake_queue: 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); mcp251xfd_ecc_tefif_successful(priv);
if (mcp251xfd_get_tx_free(priv->tx)) { if (mcp251xfd_get_tx_free(priv->tx)) {
...@@ -1439,13 +1499,7 @@ mcp251xfd_handle_rxif_one(struct mcp251xfd_priv *priv, ...@@ -1439,13 +1499,7 @@ mcp251xfd_handle_rxif_one(struct mcp251xfd_priv *priv,
if (err) if (err)
stats->rx_fifo_errors++; stats->rx_fifo_errors++;
ring->tail++; return 0;
/* 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);
} }
static inline int static inline int
...@@ -1477,6 +1531,8 @@ mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv, ...@@ -1477,6 +1531,8 @@ mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv,
return err; return err;
while ((len = mcp251xfd_get_rx_linear_len(ring))) { while ((len = mcp251xfd_get_rx_linear_len(ring))) {
struct spi_transfer *last_xfer;
rx_tail = mcp251xfd_get_rx_tail(ring); rx_tail = mcp251xfd_get_rx_tail(ring);
err = mcp251xfd_rx_obj_read(priv, ring, hw_rx_obj, err = mcp251xfd_rx_obj_read(priv, ring, hw_rx_obj,
...@@ -1491,6 +1547,28 @@ mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv, ...@@ -1491,6 +1547,28 @@ mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv,
if (err) if (err)
return 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; return 0;
......
...@@ -368,6 +368,7 @@ ...@@ -368,6 +368,7 @@
* FIFO setup: tef: 8*12 bytes = 96 bytes, tx: 8*16 bytes = 128 bytes * 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 * 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_CAN 8
#define MCP251XFD_TX_OBJ_NUM_CANFD 4 #define MCP251XFD_TX_OBJ_NUM_CANFD 4
...@@ -458,14 +459,6 @@ struct mcp251xfd_hw_rx_obj_canfd { ...@@ -458,14 +459,6 @@ struct mcp251xfd_hw_rx_obj_canfd {
u8 data[sizeof_field(struct canfd_frame, data)]; 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 { struct __packed mcp251xfd_buf_cmd {
__be16 cmd; __be16 cmd;
}; };
...@@ -505,6 +498,17 @@ struct mcp251xfd_tx_obj { ...@@ -505,6 +498,17 @@ struct mcp251xfd_tx_obj {
union mcp251xfd_tx_obj_load_buf buf; 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 { struct mcp251xfd_tx_ring {
unsigned int head; unsigned int head;
unsigned int tail; unsigned int tail;
...@@ -527,6 +531,8 @@ struct mcp251xfd_rx_ring { ...@@ -527,6 +531,8 @@ struct mcp251xfd_rx_ring {
u8 obj_num; u8 obj_num;
u8 obj_size; 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[]; struct mcp251xfd_hw_rx_obj_canfd obj[];
}; };
...@@ -580,7 +586,7 @@ struct mcp251xfd_priv { ...@@ -580,7 +586,7 @@ struct mcp251xfd_priv {
struct spi_device *spi; struct spi_device *spi;
u32 spi_max_speed_hz_orig; 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_tx_ring tx[1];
struct mcp251xfd_rx_ring *rx[1]; struct mcp251xfd_rx_ring *rx[1];
...@@ -741,17 +747,17 @@ mcp251xfd_get_rx_obj_addr(const struct mcp251xfd_rx_ring *ring, u8 n) ...@@ -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) 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) 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) 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) static inline u8 mcp251xfd_get_tef_linear_len(const struct mcp251xfd_priv *priv)
......
...@@ -295,15 +295,16 @@ static void peak_usb_write_bulk_callback(struct urb *urb) ...@@ -295,15 +295,16 @@ static void peak_usb_write_bulk_callback(struct urb *urb)
netif_trans_update(netdev); netif_trans_update(netdev);
break; break;
default:
if (net_ratelimit())
netdev_err(netdev, "Tx urb aborted (%d)\n",
urb->status);
case -EPROTO: case -EPROTO:
case -ENOENT: case -ENOENT:
case -ECONNRESET: case -ECONNRESET:
case -ESHUTDOWN: case -ESHUTDOWN:
break;
default:
if (net_ratelimit())
netdev_err(netdev, "Tx urb aborted (%d)\n",
urb->status);
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