linux-can.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Marc Kleine-Budde <mkl@pengutronix.de>
To: Matt Kline <matt@bitbashing.io>
Cc: Wolfgang Grandegger <wg@grandegger.com>, linux-can@vger.kernel.org
Subject: Re: [PATCH v3 1/3] can: m_can: Disable IRQs on FIFO bus errors
Date: Thu, 19 Aug 2021 13:30:51 +0200	[thread overview]
Message-ID: <20210819113051.zrgwqjtrf6rajhtx@pengutronix.de> (raw)
In-Reply-To: <20210817050853.14875-2-matt@bitbashing.io>

[-- Attachment #1: Type: text/plain, Size: 20936 bytes --]

On 16.08.2021 22:08:51, Matt Kline wrote:
> If FIFO reads or writes fail due to the underlying regmap (e.g., SPI)
> I/O, propagate that up to the m_can driver, log an error, and disable
> interrupts, similar to the mcp251xfd driver.
> 
> While reworking the FIFO functions to add this error handling,
> add support for bulk reads and writes of multiple registers.
> 
> Signed-off-by: Matt Kline <matt@bitbashing.io>

Applied with some minor changes, see inline.

regards,
Marc

> ---
>  drivers/net/can/m_can/m_can.c          | 177 +++++++++++++++++--------
>  drivers/net/can/m_can/m_can.h          |   6 +-
>  drivers/net/can/m_can/m_can_pci.c      |  11 +-
>  drivers/net/can/m_can/m_can_platform.c |  15 ++-
>  drivers/net/can/m_can/tcan4x5x-core.c  |  16 +--
>  5 files changed, 152 insertions(+), 73 deletions(-)
> 
> diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
> index 43bca315a66c..83eb5cd51de5 100644
> --- a/drivers/net/can/m_can/m_can.c
> +++ b/drivers/net/can/m_can/m_can.c
> @@ -319,36 +319,36 @@ static inline void m_can_write(struct m_can_classdev *cdev, enum m_can_reg reg,
>  	cdev->ops->write_reg(cdev, reg, val);
>  }
>  
> -static u32 m_can_fifo_read(struct m_can_classdev *cdev,
> -			   u32 fgi, unsigned int offset)
> +static int m_can_fifo_read(struct m_can_classdev *cdev,
> +			   u32 fgi, unsigned int offset, void *val, size_t val_count)

I've reformated some long lines like these to stay below 80 chars.

>  {
>  	u32 addr_offset = cdev->mcfg[MRAM_RXF0].off + fgi * RXF0_ELEMENT_SIZE +
>  		offset;
>  
> -	return cdev->ops->read_fifo(cdev, addr_offset);
> +	return cdev->ops->read_fifo(cdev, addr_offset, val, val_count);
>  }
>  
> -static void m_can_fifo_write(struct m_can_classdev *cdev,
> -			     u32 fpi, unsigned int offset, u32 val)
> +static int m_can_fifo_write(struct m_can_classdev *cdev,
> +			    u32 fpi, unsigned int offset, const void *val, size_t val_count)
>  {
>  	u32 addr_offset = cdev->mcfg[MRAM_TXB].off + fpi * TXB_ELEMENT_SIZE +
>  		offset;
>  
> -	cdev->ops->write_fifo(cdev, addr_offset, val);
> +	return cdev->ops->write_fifo(cdev, addr_offset, val, val_count);
>  }
>  
> -static inline void m_can_fifo_write_no_off(struct m_can_classdev *cdev,
> -					   u32 fpi, u32 val)
> +static inline int m_can_fifo_write_no_off(struct m_can_classdev *cdev,
> +					  u32 fpi, u32 val)
>  {
> -	cdev->ops->write_fifo(cdev, fpi, val);
> +	return cdev->ops->write_fifo(cdev, fpi, &val, 1);
>  }
>  
> -static u32 m_can_txe_fifo_read(struct m_can_classdev *cdev, u32 fgi, u32 offset)
> +static int m_can_txe_fifo_read(struct m_can_classdev *cdev, u32 fgi, u32 offset, u32 *val)
>  {
>  	u32 addr_offset = cdev->mcfg[MRAM_TXE].off + fgi * TXE_ELEMENT_SIZE +
>  		offset;
>  
> -	return cdev->ops->read_fifo(cdev, addr_offset);
> +	return cdev->ops->read_fifo(cdev, addr_offset, val, 1);
>  }
>  
>  static inline bool m_can_tx_fifo_full(struct m_can_classdev *cdev)
> @@ -454,7 +454,7 @@ static void m_can_receive_skb(struct m_can_classdev *cdev,
>  	}
>  }
>  
> -static void m_can_read_fifo(struct net_device *dev, u32 rxfs)
> +static int m_can_read_fifo(struct net_device *dev, u32 rxfs)
>  {
>  	struct net_device_stats *stats = &dev->stats;
>  	struct m_can_classdev *cdev = netdev_priv(dev);
> @@ -462,18 +462,21 @@ static void m_can_read_fifo(struct net_device *dev, u32 rxfs)
>  	struct sk_buff *skb;
>  	u32 id, fgi, dlc;
>  	u32 timestamp = 0;
> -	int i;
> +	int i, err;
>  
>  	/* calculate the fifo get index for where to read data */
>  	fgi = FIELD_GET(RXFS_FGI_MASK, rxfs);
> -	dlc = m_can_fifo_read(cdev, fgi, M_CAN_FIFO_DLC);
> +	err = m_can_fifo_read(cdev, fgi, M_CAN_FIFO_DLC, &dlc, 1);
> +	if (err)
> +		goto out_fail;
> +
>  	if (dlc & RX_BUF_FDF)
>  		skb = alloc_canfd_skb(dev, &cf);
>  	else
>  		skb = alloc_can_skb(dev, (struct can_frame **)&cf);
>  	if (!skb) {
>  		stats->rx_dropped++;
> -		return;
> +		return 0;
>  	}
>  
>  	if (dlc & RX_BUF_FDF)
> @@ -481,7 +484,10 @@ static void m_can_read_fifo(struct net_device *dev, u32 rxfs)
>  	else
>  		cf->len = can_cc_dlc2len((dlc >> 16) & 0x0F);
>  
> -	id = m_can_fifo_read(cdev, fgi, M_CAN_FIFO_ID);
> +	err = m_can_fifo_read(cdev, fgi, M_CAN_FIFO_ID, &id, 1);
> +	if (err)
> +		goto out_fail;
> +
>  	if (id & RX_BUF_XTD)
>  		cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG;
>  	else
> @@ -498,10 +504,11 @@ static void m_can_read_fifo(struct net_device *dev, u32 rxfs)
>  		if (dlc & RX_BUF_BRS)
>  			cf->flags |= CANFD_BRS;
>  
> -		for (i = 0; i < cf->len; i += 4)
> -			*(u32 *)(cf->data + i) =
> -				m_can_fifo_read(cdev, fgi,
> -						M_CAN_FIFO_DATA(i / 4));
> +		for (i = 0; i < cf->len; i += 4) {
> +			err = m_can_fifo_read(cdev, fgi, M_CAN_FIFO_DATA(i / 4), cf->data + i, 1);
> +			if (err)
> +				goto out_fail;
> +		}
>  	}
>  
>  	/* acknowledge rx fifo 0 */
> @@ -513,6 +520,12 @@ static void m_can_read_fifo(struct net_device *dev, u32 rxfs)
>  	timestamp = FIELD_GET(RX_BUF_RXTS_MASK, dlc);
>  
>  	m_can_receive_skb(cdev, skb, timestamp);
> +
> +	return 0;
> +
> +out_fail:
> +	netdev_err(dev, "FIFO read returned %d\n", err);
> +	return err;
>  }
>  
>  static int m_can_do_rx_poll(struct net_device *dev, int quota)
> @@ -520,6 +533,7 @@ static int m_can_do_rx_poll(struct net_device *dev, int quota)
>  	struct m_can_classdev *cdev = netdev_priv(dev);
>  	u32 pkts = 0;
>  	u32 rxfs;
> +	int err;
>  
>  	rxfs = m_can_read(cdev, M_CAN_RXF0S);
>  	if (!(rxfs & RXFS_FFL_MASK)) {
> @@ -528,7 +542,14 @@ static int m_can_do_rx_poll(struct net_device *dev, int quota)
>  	}
>  
>  	while ((rxfs & RXFS_FFL_MASK) && (quota > 0)) {
> -		m_can_read_fifo(dev, rxfs);
> +		err = m_can_read_fifo(dev, rxfs);
> +		if (err) {
> +			/* Trust that an error back from a FIFO read is negative
> +			 * so that we can differentiate it from work done (pkts).
> +			 */
> +			WARN_ON(err >= 0);

m_can_read_fifo() already throws an error message, so I've removed the
WARN_ON here.

> +			return err;
> +		}
>  
>  		quota--;
>  		pkts++;
> @@ -874,6 +895,7 @@ static int m_can_handle_bus_errors(struct net_device *dev, u32 irqstatus,
>  static int m_can_rx_handler(struct net_device *dev, int quota)
>  {
>  	struct m_can_classdev *cdev = netdev_priv(dev);
> +	int rx_work_or_err;
>  	int work_done = 0;
>  	u32 irqstatus, psr;
>  
> @@ -910,8 +932,13 @@ static int m_can_rx_handler(struct net_device *dev, int quota)
>  	if (irqstatus & IR_ERR_BUS_30X)
>  		work_done += m_can_handle_bus_errors(dev, irqstatus, psr);
>  
> -	if (irqstatus & IR_RF0N)
> -		work_done += m_can_do_rx_poll(dev, (quota - work_done));
> +	if (irqstatus & IR_RF0N) {
> +		rx_work_or_err = m_can_do_rx_poll(dev, (quota - work_done));
> +		if (rx_work_or_err < 0)
> +			return rx_work_or_err;
> +
> +		work_done += rx_work_or_err;
> +	}
>  end:
>  	return work_done;
>  }
> @@ -919,12 +946,16 @@ static int m_can_rx_handler(struct net_device *dev, int quota)
>  static int m_can_rx_peripheral(struct net_device *dev)
>  {
>  	struct m_can_classdev *cdev = netdev_priv(dev);
> +	int work_done;
>  
> -	m_can_rx_handler(dev, M_CAN_NAPI_WEIGHT);
> +	work_done = m_can_rx_handler(dev, M_CAN_NAPI_WEIGHT);
>  
> -	m_can_enable_all_interrupts(cdev);
> +	// Don't re-enable interrupts if the driver had a fatal error
> +	// (e.g., FIFO read failure).

No C++ comments please, I've converted to proper netdev block style
comments.

> +	if (work_done >= 0)
> +		m_can_enable_all_interrupts(cdev);
>  
> -	return 0;
> +	return work_done;
>  }
>  
>  static int m_can_poll(struct napi_struct *napi, int quota)
> @@ -934,7 +965,10 @@ static int m_can_poll(struct napi_struct *napi, int quota)
>  	int work_done;
>  
>  	work_done = m_can_rx_handler(dev, quota);
> -	if (work_done < quota) {
> +
> +	// Don't re-enable interrupts if the driver had a fatal error
> +	// (e.g., FIFO read failure).

Same here

> +	if (work_done >= 0 && work_done < quota) {
>  		napi_complete_done(napi, work_done);
>  		m_can_enable_all_interrupts(cdev);
>  	}
> @@ -965,7 +999,7 @@ static void m_can_tx_update_stats(struct m_can_classdev *cdev,
>  	stats->tx_packets++;
>  }
>  
> -static void m_can_echo_tx_event(struct net_device *dev)
> +static int m_can_echo_tx_event(struct net_device *dev)
>  {
>  	u32 txe_count = 0;
>  	u32 m_can_txefs;
> @@ -984,12 +1018,18 @@ 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;
> +		int err;
>  
>  		/* retrieve get index */
>  		fgi = FIELD_GET(TXEFS_EFGI_MASK, m_can_read(cdev, M_CAN_TXEFS));
>  
>  		/* get message marker, timestamp */
> -		txe = m_can_txe_fifo_read(cdev, fgi, 4);
> +		err = m_can_txe_fifo_read(cdev, fgi, 4, &txe);
> +		if (err) {
> +			netdev_err(dev, "TXE FIFO read returned %d\n", err);
> +			return err;
> +		}
> +
>  		msg_mark = FIELD_GET(TX_EVENT_MM_MASK, txe);
>  		timestamp = FIELD_GET(TX_EVENT_TXTS_MASK, txe);
>  
> @@ -1000,6 +1040,8 @@ static void m_can_echo_tx_event(struct net_device *dev)
>  		/* update stats */
>  		m_can_tx_update_stats(cdev, msg_mark, timestamp);
>  	}
> +
> +	return 0;
>  }
>  
>  static irqreturn_t m_can_isr(int irq, void *dev_id)
> @@ -1031,8 +1073,8 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
>  		m_can_disable_all_interrupts(cdev);
>  		if (!cdev->is_peripheral)
>  			napi_schedule(&cdev->napi);
> -		else
> -			m_can_rx_peripheral(dev);
> +		else if (m_can_rx_peripheral(dev) < 0)
> +			goto out_fail;
>  	}
>  
>  	if (cdev->version == 30) {
> @@ -1050,7 +1092,9 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
>  	} else  {
>  		if (ir & IR_TEFN) {
>  			/* New TX FIFO Element arrived */
> -			m_can_echo_tx_event(dev);
> +			if (m_can_echo_tx_event(dev) != 0)
> +				goto out_fail;
> +
>  			can_led_event(dev, CAN_LED_EVENT_TX);
>  			if (netif_queue_stopped(dev) &&
>  			    !m_can_tx_fifo_full(cdev))
> @@ -1059,6 +1103,10 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
>  	}
>  
>  	return IRQ_HANDLED;
> +
> +out_fail:
> +	m_can_disable_all_interrupts(cdev);
> +	return IRQ_HANDLED;
>  }
>  
>  static const struct can_bittiming_const m_can_bittiming_const_30X = {
> @@ -1540,8 +1588,8 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
>  	struct canfd_frame *cf = (struct canfd_frame *)cdev->tx_skb->data;
>  	struct net_device *dev = cdev->net;
>  	struct sk_buff *skb = cdev->tx_skb;
> -	u32 id, cccr, fdflags;
> -	int i;
> +	u32 id, dlc, cccr, fdflags;
> +	int i, err;
>  	int putidx;
>  
>  	cdev->tx_skb = NULL;
> @@ -1562,14 +1610,20 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
>  		netif_stop_queue(dev);
>  
>  		/* message ram configuration */
> -		m_can_fifo_write(cdev, 0, M_CAN_FIFO_ID, id);
> -		m_can_fifo_write(cdev, 0, M_CAN_FIFO_DLC,
> -				 can_fd_len2dlc(cf->len) << 16);
> +		err = m_can_fifo_write(cdev, 0, M_CAN_FIFO_ID, &id, 1);
> +		if (err)
> +			goto out_fail;
>  
> -		for (i = 0; i < cf->len; i += 4)
> -			m_can_fifo_write(cdev, 0,
> -					 M_CAN_FIFO_DATA(i / 4),
> -					 *(u32 *)(cf->data + i));
> +		dlc = can_fd_len2dlc(cf->len) << 16;
> +		err = m_can_fifo_write(cdev, 0, M_CAN_FIFO_DLC, &dlc, 1);
> +		if (err)
> +			goto out_fail;
> +
> +		for (i = 0; i < cf->len; i += 4) {
> +			err = m_can_fifo_write(cdev, 0, M_CAN_FIFO_DATA(i / 4), cf->data + i, 1);
> +			if (err)
> +				goto out_fail;
> +		}
>  
>  		can_put_echo_skb(skb, dev, 0, 0);
>  
> @@ -1614,7 +1668,9 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
>  		putidx = FIELD_GET(TXFQS_TFQPI_MASK,
>  				   m_can_read(cdev, M_CAN_TXFQS));
>  		/* Write ID Field to FIFO Element */
> -		m_can_fifo_write(cdev, putidx, M_CAN_FIFO_ID, id);
> +		err = m_can_fifo_write(cdev, putidx, M_CAN_FIFO_ID, &id, 1);
> +		if (err)
> +			goto out_fail;
>  
>  		/* get CAN FD configuration of frame */
>  		fdflags = 0;
> @@ -1629,15 +1685,19 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
>  		 * it is used in TX interrupt for
>  		 * sending the correct echo frame
>  		 */
> -		m_can_fifo_write(cdev, putidx, M_CAN_FIFO_DLC,
> -				 FIELD_PREP(TX_BUF_MM_MASK, putidx) |
> -				 FIELD_PREP(TX_BUF_DLC_MASK,
> -					    can_fd_len2dlc(cf->len)) |
> -				 fdflags | TX_BUF_EFC);
> +		dlc = FIELD_PREP(TX_BUF_MM_MASK, putidx) |
> +			FIELD_PREP(TX_BUF_DLC_MASK, can_fd_len2dlc(cf->len)) |
> +			fdflags | TX_BUF_EFC;
> +		err = m_can_fifo_write(cdev, putidx, M_CAN_FIFO_DLC, &dlc, 1);
> +		if (err)
> +			goto out_fail;
>  
> -		for (i = 0; i < cf->len; i += 4)
> -			m_can_fifo_write(cdev, putidx, M_CAN_FIFO_DATA(i / 4),
> -					 *(u32 *)(cf->data + i));
> +		for (i = 0; i < cf->len; i += 4) {
> +			err = m_can_fifo_write(cdev, putidx, M_CAN_FIFO_DATA(i / 4),
> +					       cf->data + i, 1);
> +			if (err)
> +				goto out_fail;
> +		}
>  
>  		/* Push loopback echo.
>  		 * Will be looped back on TX interrupt based on message marker
> @@ -1654,6 +1714,11 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
>  	}
>  
>  	return NETDEV_TX_OK;
> +
> +out_fail:
> +	netdev_err(dev, "FIFO write returned %d\n", err);
> +	m_can_disable_all_interrupts(cdev);
> +	return NETDEV_TX_BUSY;
>  }
>  
>  static void m_can_tx_work_queue(struct work_struct *ws)
> @@ -1819,9 +1884,10 @@ static void m_can_of_parse_mram(struct m_can_classdev *cdev,
>  		cdev->mcfg[MRAM_TXB].off, cdev->mcfg[MRAM_TXB].num);
>  }
>  
> -void m_can_init_ram(struct m_can_classdev *cdev)
> +int m_can_init_ram(struct m_can_classdev *cdev)
>  {
>  	int end, i, start;
> +	int err = 0;
>  
>  	/* initialize the entire Message RAM in use to avoid possible
>  	 * ECC/parity checksum errors when reading an uninitialized buffer
> @@ -1830,8 +1896,13 @@ void m_can_init_ram(struct m_can_classdev *cdev)
>  	end = cdev->mcfg[MRAM_TXB].off +
>  		cdev->mcfg[MRAM_TXB].num * TXB_ELEMENT_SIZE;
>  
> -	for (i = start; i < end; i += 4)
> -		m_can_fifo_write_no_off(cdev, i, 0x0);
> +	for (i = start; i < end; i += 4) {
> +		err = m_can_fifo_write_no_off(cdev, i, 0x0);
> +		if (err)
> +			break;
> +	}
> +
> +	return err;
>  }
>  EXPORT_SYMBOL_GPL(m_can_init_ram);
>  
> diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h
> index ace071c3e58c..7a3bc878535c 100644
> --- a/drivers/net/can/m_can/m_can.h
> +++ b/drivers/net/can/m_can/m_can.h
> @@ -64,9 +64,9 @@ struct m_can_ops {
>  	int (*clear_interrupts)(struct m_can_classdev *cdev);
>  	u32 (*read_reg)(struct m_can_classdev *cdev, int reg);
>  	int (*write_reg)(struct m_can_classdev *cdev, int reg, int val);
> -	u32 (*read_fifo)(struct m_can_classdev *cdev, int addr_offset);
> +	int (*read_fifo)(struct m_can_classdev *cdev, int addr_offset, void *val, size_t val_count);
>  	int (*write_fifo)(struct m_can_classdev *cdev, int addr_offset,
> -			  int val);
> +			  const void *val, size_t val_count);
>  	int (*init)(struct m_can_classdev *cdev);
>  };
>  
> @@ -102,7 +102,7 @@ void m_can_class_free_dev(struct net_device *net);
>  int m_can_class_register(struct m_can_classdev *cdev);
>  void m_can_class_unregister(struct m_can_classdev *cdev);
>  int m_can_class_get_clocks(struct m_can_classdev *cdev);
> -void m_can_init_ram(struct m_can_classdev *priv);
> +int m_can_init_ram(struct m_can_classdev *priv);
>  
>  int m_can_class_suspend(struct device *dev);
>  int m_can_class_resume(struct device *dev);
> diff --git a/drivers/net/can/m_can/m_can_pci.c b/drivers/net/can/m_can/m_can_pci.c
> index 128808605c3f..89cc3d41e952 100644
> --- a/drivers/net/can/m_can/m_can_pci.c
> +++ b/drivers/net/can/m_can/m_can_pci.c
> @@ -39,11 +39,13 @@ static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg)
>  	return readl(priv->base + reg);
>  }
>  
> -static u32 iomap_read_fifo(struct m_can_classdev *cdev, int offset)
> +static int iomap_read_fifo(struct m_can_classdev *cdev, int offset, void *val, size_t val_count)
>  {
>  	struct m_can_pci_priv *priv = cdev_to_priv(cdev);
>  
> -	return readl(priv->base + offset);
> +	ioread32_rep(priv->base + offset, val, val_count);
> +
> +	return 0;
>  }
>  
>  static int iomap_write_reg(struct m_can_classdev *cdev, int reg, int val)
> @@ -55,11 +57,12 @@ static int iomap_write_reg(struct m_can_classdev *cdev, int reg, int val)
>  	return 0;
>  }
>  
> -static int iomap_write_fifo(struct m_can_classdev *cdev, int offset, int val)
> +static int iomap_write_fifo(struct m_can_classdev *cdev, int offset,
> +			    const void *val, size_t val_count)
>  {
>  	struct m_can_pci_priv *priv = cdev_to_priv(cdev);
>  
> -	writel(val, priv->base + offset);
> +	iowrite32_rep(priv->base + offset, val, val_count);
>  
>  	return 0;
>  }
> diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c
> index 599de0e08cd7..12dec09cbd9f 100644
> --- a/drivers/net/can/m_can/m_can_platform.c
> +++ b/drivers/net/can/m_can/m_can_platform.c
> @@ -28,11 +28,13 @@ static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg)
>  	return readl(priv->base + reg);
>  }
>  
> -static u32 iomap_read_fifo(struct m_can_classdev *cdev, int offset)
> +static int iomap_read_fifo(struct m_can_classdev *cdev, int offset, void *val, size_t val_count)
>  {
>  	struct m_can_plat_priv *priv = cdev_to_priv(cdev);
>  
> -	return readl(priv->mram_base + offset);
> +	ioread32_rep(priv->mram_base + offset, val, val_count);
> +
> +	return 0;
>  }
>  
>  static int iomap_write_reg(struct m_can_classdev *cdev, int reg, int val)
> @@ -44,11 +46,12 @@ static int iomap_write_reg(struct m_can_classdev *cdev, int reg, int val)
>  	return 0;
>  }
>  
> -static int iomap_write_fifo(struct m_can_classdev *cdev, int offset, int val)
> +static int iomap_write_fifo(struct m_can_classdev *cdev, int offset,
> +			    const void *val, size_t val_count)
>  {
>  	struct m_can_plat_priv *priv = cdev_to_priv(cdev);
>  
> -	writel(val, priv->mram_base + offset);
> +	iowrite32_rep(priv->base + offset, val, val_count);
>  
>  	return 0;
>  }
> @@ -115,7 +118,9 @@ static int m_can_plat_probe(struct platform_device *pdev)
>  
>  	platform_set_drvdata(pdev, mcan_class);
>  
> -	m_can_init_ram(mcan_class);
> +	ret = m_can_init_ram(mcan_class);
> +	if (ret)
> +		goto probe_fail;
>  
>  	pm_runtime_enable(mcan_class->dev);
>  	ret = m_can_class_register(mcan_class);
> diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c
> index 4147cecfbbd6..11c096fe94a2 100644
> --- a/drivers/net/can/m_can/tcan4x5x-core.c
> +++ b/drivers/net/can/m_can/tcan4x5x-core.c
> @@ -154,14 +154,12 @@ static u32 tcan4x5x_read_reg(struct m_can_classdev *cdev, int reg)
>  	return val;
>  }
>  
> -static u32 tcan4x5x_read_fifo(struct m_can_classdev *cdev, int addr_offset)
> +static int tcan4x5x_read_fifo(struct m_can_classdev *cdev, int addr_offset,
> +			      void *val, size_t val_count)
>  {
>  	struct tcan4x5x_priv *priv = cdev_to_priv(cdev);
> -	u32 val;
>  
> -	regmap_read(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, &val);
> -
> -	return val;
> +	return regmap_bulk_read(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, val, val_count);
>  }
>  
>  static int tcan4x5x_write_reg(struct m_can_classdev *cdev, int reg, int val)
> @@ -172,11 +170,11 @@ static int tcan4x5x_write_reg(struct m_can_classdev *cdev, int reg, int val)
>  }
>  
>  static int tcan4x5x_write_fifo(struct m_can_classdev *cdev,
> -			       int addr_offset, int val)
> +			       int addr_offset, const void *val, size_t val_count)
>  {
>  	struct tcan4x5x_priv *priv = cdev_to_priv(cdev);
>  
> -	return regmap_write(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, val);
> +	return regmap_bulk_write(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, val, val_count);
>  }
>  
>  static int tcan4x5x_power_enable(struct regulator *reg, int enable)
> @@ -238,7 +236,9 @@ static int tcan4x5x_init(struct m_can_classdev *cdev)
>  		return ret;
>  
>  	/* Zero out the MCAN buffers */
> -	m_can_init_ram(cdev);
> +	ret = m_can_init_ram(cdev);
> +	if (ret)
> +		return ret;
>  
>  	ret = regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
>  				 TCAN4X5X_MODE_SEL_MASK, TCAN4X5X_MODE_NORMAL);
> -- 
> 2.32.0
> 
> 

-- 
Pengutronix e.K.                 | Marc Kleine-Budde           |
Embedded Linux                   | https://www.pengutronix.de  |
Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

  reply	other threads:[~2021-08-19 11:30 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-17  5:08 [PATCH v3 0/3] can: m_can: Merge FIFO ops to increase throughput Matt Kline
2021-08-17  5:08 ` [PATCH v3 1/3] can: m_can: Disable IRQs on FIFO bus errors Matt Kline
2021-08-19 11:30   ` Marc Kleine-Budde [this message]
2021-08-17  5:08 ` [PATCH v3 2/3] can: m_can: Batch FIFO reads during CAN receive Matt Kline
2021-08-19 11:45   ` Marc Kleine-Budde
2021-09-16 12:04   ` Aswath Govindraju
2021-09-27  8:25     ` Matt Kline
2021-08-17  5:08 ` [PATCH v3 3/3] can: m_can: Batch FIFO writes during CAN transmit Matt Kline

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210819113051.zrgwqjtrf6rajhtx@pengutronix.de \
    --to=mkl@pengutronix.de \
    --cc=linux-can@vger.kernel.org \
    --cc=matt@bitbashing.io \
    --cc=wg@grandegger.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).