All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marc Kleine-Budde <mkl@pengutronix.de>
To: Marek Vasut <marex@denx.de>, netdev@vger.kernel.org
Cc: Oliver Hartkopp <socketcan@hartkopp.net>,
	Mark Rutland <mark.rutland@arm.com>,
	Wolfgang Grandegger <wg@grandegger.com>
Subject: Re: [PATCH V3 5/5] net: can: ifi: Add IFI CANFD IP support
Date: Wed, 20 Jan 2016 15:39:51 +0100	[thread overview]
Message-ID: <569F9C37.60007@pengutronix.de> (raw)
In-Reply-To: <1453300419-5716-1-git-send-email-marex@denx.de>

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

On 01/20/2016 03:33 PM, Marek Vasut wrote:
> The patch adds support for IFI CAN/FD controller [1]. This driver
> currently supports sending and receiving both standard CAN and new
> CAN/FD frames. Both ISO and BOSCH variant of CAN/FD is supported.
> 
> [1] http://www.ifi-pld.de/IP/CANFD/canfd.html
> 
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Marc Kleine-Budde <mkl@pengutronix.de>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Oliver Hartkopp <socketcan@hartkopp.net>
> Cc: Wolfgang Grandegger <wg@grandegger.com>
> ---
> V2: - Move request_irq()/free_irq() into ifi_canfd_open()/ifi_canfd_close()
>       just like other drivers do it to prevent crash when reloading module.
>     - Fix Woverflow complains on x86_64 and itanium, exactly the same way
>       as in commit dec23dca5a9ca4b9eb2fb66926f567889028b904 .
> 
> V3: - Hopefully fix all problems with BIT(31) by adding more u32 casts.
>     - Drop struct device from struct ifi_canfd_priv .
> 
> NOTE: The driver is surprisingly similar to m_can, but the register
>       layout of the IFI core is completely different, so it's clear
>       that those are two different IP cores.
> ---
>  drivers/net/can/Kconfig               |   2 +
>  drivers/net/can/Makefile              |   1 +
>  drivers/net/can/ifi_canfd/Kconfig     |   8 +
>  drivers/net/can/ifi_canfd/Makefile    |   5 +
>  drivers/net/can/ifi_canfd/ifi_canfd.c | 917 ++++++++++++++++++++++++++++++++++
>  5 files changed, 933 insertions(+)
>  create mode 100644 drivers/net/can/ifi_canfd/Kconfig
>  create mode 100644 drivers/net/can/ifi_canfd/Makefile
>  create mode 100644 drivers/net/can/ifi_canfd/ifi_canfd.c
> 
> diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
> index ca49d15..20be638 100644
> --- a/drivers/net/can/Kconfig
> +++ b/drivers/net/can/Kconfig
> @@ -151,6 +151,8 @@ source "drivers/net/can/c_can/Kconfig"
>  
>  source "drivers/net/can/cc770/Kconfig"
>  
> +source "drivers/net/can/ifi_canfd/Kconfig"
> +
>  source "drivers/net/can/m_can/Kconfig"
>  
>  source "drivers/net/can/mscan/Kconfig"
> diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
> index 4f85c2b..e3db0c8 100644
> --- a/drivers/net/can/Makefile
> +++ b/drivers/net/can/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_CAN_CC770)		+= cc770/
>  obj-$(CONFIG_CAN_C_CAN)		+= c_can/
>  obj-$(CONFIG_CAN_FLEXCAN)	+= flexcan.o
>  obj-$(CONFIG_CAN_GRCAN)		+= grcan.o
> +obj-$(CONFIG_CAN_IFI_CANFD)	+= ifi_canfd/
>  obj-$(CONFIG_CAN_JANZ_ICAN3)	+= janz-ican3.o
>  obj-$(CONFIG_CAN_MSCAN)		+= mscan/
>  obj-$(CONFIG_CAN_M_CAN)		+= m_can/
> diff --git a/drivers/net/can/ifi_canfd/Kconfig b/drivers/net/can/ifi_canfd/Kconfig
> new file mode 100644
> index 0000000..9e8934f
> --- /dev/null
> +++ b/drivers/net/can/ifi_canfd/Kconfig
> @@ -0,0 +1,8 @@
> +config CAN_IFI_CANFD
> +	depends on HAS_IOMEM
> +	tristate "IFI CAN_FD IP"
> +	---help---
> +	  This driver adds support for the I/F/I CAN_FD soft IP block
> +	  connected to the "platform bus" (Linux abstraction for directly
> +	  to the processor attached devices). The CAN_FD is most often
> +	  synthesised into an FPGA or CPLD.
> diff --git a/drivers/net/can/ifi_canfd/Makefile b/drivers/net/can/ifi_canfd/Makefile
> new file mode 100644
> index 0000000..b229960
> --- /dev/null
> +++ b/drivers/net/can/ifi_canfd/Makefile
> @@ -0,0 +1,5 @@
> +#
> +#  Makefile for the IFI CANFD controller driver.
> +#
> +
> +obj-$(CONFIG_CAN_IFI_CANFD) += ifi_canfd.o
> diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c
> new file mode 100644
> index 0000000..639868b
> --- /dev/null
> +++ b/drivers/net/can/ifi_canfd/ifi_canfd.c
> @@ -0,0 +1,917 @@
> +/*
> + * CAN bus driver for IFI CANFD controller
> + *
> + * Copyright (C) 2016 Marek Vasut <marex@denx.de>
> + *
> + * Details about this controller can be found at
> + * http://www.ifi-pld.de/IP/CANFD/canfd.html
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/netdevice.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +
> +#include <linux/can/dev.h>
> +
> +#define IFI_CANFD_STCMD				0x0
> +#define IFI_CANFD_STCMD_HARDRESET		0xDEADCAFD
> +#define IFI_CANFD_STCMD_ENABLE			BIT(0)
> +#define IFI_CANFD_STCMD_ERROR_ACTIVE		BIT(2)
> +#define IFI_CANFD_STCMD_ERROR_PASSIVE		BIT(3)
> +#define IFI_CANFD_STCMD_BUSOFF			BIT(4)
> +#define IFI_CANFD_STCMD_BUSMONITOR		BIT(16)
> +#define IFI_CANFD_STCMD_LOOPBACK		BIT(18)
> +#define IFI_CANFD_STCMD_DISABLE_CANFD		BIT(24)
> +#define IFI_CANFD_STCMD_ENABLE_ISO		BIT(25)
> +#define IFI_CANFD_STCMD_NORMAL_MODE		((u32)BIT(31))
> +
> +#define IFI_CANFD_RXSTCMD			0x4
> +#define IFI_CANFD_RXSTCMD_REMOVE_MSG		BIT(0)
> +#define IFI_CANFD_RXSTCMD_RESET			BIT(7)
> +#define IFI_CANFD_RXSTCMD_EMPTY			BIT(8)
> +#define IFI_CANFD_RXSTCMD_OVERFLOW		BIT(13)
> +
> +#define IFI_CANFD_TXSTCMD			0x8
> +#define IFI_CANFD_TXSTCMD_ADD_MSG		BIT(0)
> +#define IFI_CANFD_TXSTCMD_HIGH_PRIO		BIT(1)
> +#define IFI_CANFD_TXSTCMD_RESET			BIT(7)
> +#define IFI_CANFD_TXSTCMD_EMPTY			BIT(8)
> +#define IFI_CANFD_TXSTCMD_FULL			BIT(12)
> +#define IFI_CANFD_TXSTCMD_OVERFLOW		BIT(13)
> +
> +#define IFI_CANFD_INTERRUPT			0xc
> +#define IFI_CANFD_INTERRUPT_ERROR_WARNING	BIT(1)
> +#define IFI_CANFD_INTERRUPT_TXFIFO_EMPTY	BIT(16)
> +#define IFI_CANFD_INTERRUPT_TXFIFO_REMOVE	BIT(22)
> +#define IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY	BIT(24)
> +#define IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER	BIT(25)
> +#define IFI_CANFD_INTERRUPT_SET_IRQ		((u32)BIT(31))
> +
> +#define IFI_CANFD_IRQMASK			0x10
> +#define IFI_CANFD_IRQMASK_SET_ERR		BIT(7)
> +#define IFI_CANFD_IRQMASK_SET_TS		BIT(15)
> +#define IFI_CANFD_IRQMASK_TXFIFO_EMPTY		BIT(16)
> +#define IFI_CANFD_IRQMASK_SET_TX		BIT(23)
> +#define IFI_CANFD_IRQMASK_RXFIFO_NEMPTY		BIT(24)
> +#define IFI_CANFD_IRQMASK_SET_RX		((u32)BIT(31))
> +
> +#define IFI_CANFD_TIME				0x14
> +#define IFI_CANFD_FTIME				0x18
> +#define IFI_CANFD_TIME_TIMEB_OFF		0
> +#define IFI_CANFD_TIME_TIMEA_OFF		8
> +#define IFI_CANFD_TIME_PRESCALE_OFF		16
> +#define IFI_CANFD_TIME_SJW_OFF_ISO		25
> +#define IFI_CANFD_TIME_SJW_OFF_BOSCH		28
> +#define IFI_CANFD_TIME_SET_SJW_BOSCH		BIT(6)
> +#define IFI_CANFD_TIME_SET_TIMEB_BOSCH		BIT(7)
> +#define IFI_CANFD_TIME_SET_PRESC_BOSCH		BIT(14)
> +#define IFI_CANFD_TIME_SET_TIMEA_BOSCH		BIT(15)
> +
> +#define IFI_CANFD_TDELAY			0x1c
> +
> +#define IFI_CANFD_ERROR				0x20
> +#define IFI_CANFD_ERROR_TX_OFFSET		0
> +#define IFI_CANFD_ERROR_TX_MASK			0xff
> +#define IFI_CANFD_ERROR_RX_OFFSET		16
> +#define IFI_CANFD_ERROR_RX_MASK			0xff
> +
> +#define IFI_CANFD_ERRCNT			0x24
> +
> +#define IFI_CANFD_SUSPEND			0x28
> +
> +#define IFI_CANFD_REPEAT			0x2c
> +
> +#define IFI_CANFD_TRAFFIC			0x30
> +
> +#define IFI_CANFD_TSCONTROL			0x34
> +
> +#define IFI_CANFD_TSC				0x38
> +
> +#define IFI_CANFD_TST				0x3c
> +
> +#define IFI_CANFD_RES1				0x40
> +
> +#define IFI_CANFD_RES2				0x44
> +
> +#define IFI_CANFD_PAR				0x48
> +
> +#define IFI_CANFD_CANCLOCK			0x4c
> +
> +#define IFI_CANFD_SYSCLOCK			0x50
> +
> +#define IFI_CANFD_VER				0x54
> +
> +#define IFI_CANFD_IP_ID				0x58
> +#define IFI_CANFD_IP_ID_VALUE			0xD073CAFD
> +
> +#define IFI_CANFD_TEST				0x5c
> +
> +#define IFI_CANFD_RXFIFO_TS_63_32		0x60
> +
> +#define IFI_CANFD_RXFIFO_TS_31_0		0x64
> +
> +#define IFI_CANFD_RXFIFO_DLC			0x68
> +#define IFI_CANFD_RXFIFO_DLC_DLC_OFFSET		0
> +#define IFI_CANFD_RXFIFO_DLC_DLC_MASK		0xf
> +#define IFI_CANFD_RXFIFO_DLC_RTR		BIT(4)
> +#define IFI_CANFD_RXFIFO_DLC_EDL		BIT(5)
> +#define IFI_CANFD_RXFIFO_DLC_BRS		BIT(6)
> +#define IFI_CANFD_RXFIFO_DLC_ESI		BIT(7)
> +#define IFI_CANFD_RXFIFO_DLC_OBJ_OFFSET		8
> +#define IFI_CANFD_RXFIFO_DLC_OBJ_MASK		0x1ff
> +#define IFI_CANFD_RXFIFO_DLC_FNR_OFFSET		24
> +#define IFI_CANFD_RXFIFO_DLC_FNR_MASK		0xff
> +
> +#define IFI_CANFD_RXFIFO_ID			0x6c
> +#define IFI_CANFD_RXFIFO_ID_ID_OFFSET		0
> +#define IFI_CANFD_RXFIFO_ID_ID_STD_MASK		0x3ff
> +#define IFI_CANFD_RXFIFO_ID_ID_XTD_MASK		0x1fffffff
> +#define IFI_CANFD_RXFIFO_ID_IDE			BIT(29)
> +
> +#define IFI_CANFD_RXFIFO_DATA			0x70	/* 0x70..0xac */
> +
> +#define IFI_CANFD_TXFIFO_SUSPEND_US		0xb0
> +
> +#define IFI_CANFD_TXFIFO_REPEATCOUNT		0xb4
> +
> +#define IFI_CANFD_TXFIFO_DLC			0xb8
> +#define IFI_CANFD_TXFIFO_DLC_DLC_OFFSET		0
> +#define IFI_CANFD_TXFIFO_DLC_DLC_MASK		0xf
> +#define IFI_CANFD_TXFIFO_DLC_RTR		BIT(4)
> +#define IFI_CANFD_TXFIFO_DLC_EDL		BIT(5)
> +#define IFI_CANFD_TXFIFO_DLC_BRS		BIT(6)
> +#define IFI_CANFD_TXFIFO_DLC_FNR_OFFSET		24
> +#define IFI_CANFD_TXFIFO_DLC_FNR_MASK		0xff
> +
> +#define IFI_CANFD_TXFIFO_ID			0xbc
> +#define IFI_CANFD_TXFIFO_ID_ID_OFFSET		0
> +#define IFI_CANFD_TXFIFO_ID_ID_STD_MASK		0x3ff
> +#define IFI_CANFD_TXFIFO_ID_ID_XTD_MASK		0x1fffffff
> +#define IFI_CANFD_TXFIFO_ID_IDE			BIT(29)
> +
> +#define IFI_CANFD_TXFIFO_DATA			0xc0	/* 0xb0..0xfc */
> +
> +#define IFI_CANFD_FILTER_MASK(n)		(0x800 + ((n) * 8) + 0)
> +#define IFI_CANFD_FILTER_MASK_EXT		BIT(29)
> +#define IFI_CANFD_FILTER_MASK_EDL		BIT(30)
> +#define IFI_CANFD_FILTER_MASK_VALID		((u32)BIT(31))
> +
> +#define IFI_CANFD_FILTER_IDENT(n)		(0x800 + ((n) * 8) + 4)
> +#define IFI_CANFD_FILTER_IDENT_IDE		BIT(29)
> +#define IFI_CANFD_FILTER_IDENT_CANFD		BIT(30)
> +#define IFI_CANFD_FILTER_IDENT_VALID		((u32)BIT(31))
> +
> +/* IFI CANFD private data structure */
> +struct ifi_canfd_priv {
> +	struct can_priv		can;	/* must be the first member */
> +	struct napi_struct	napi;
> +	struct net_device	*ndev;
> +	void __iomem		*base;
> +};
> +
> +static void ifi_canfd_irq_enable(struct net_device *ndev, bool enable)
> +{
> +	struct ifi_canfd_priv *priv = netdev_priv(ndev);
> +	u32 enirq = 0;
> +
> +	if (enable) {
> +		enirq = IFI_CANFD_IRQMASK_TXFIFO_EMPTY |
> +			IFI_CANFD_IRQMASK_RXFIFO_NEMPTY;
> +	}
> +
> +	writel(IFI_CANFD_IRQMASK_SET_ERR |
> +	       IFI_CANFD_IRQMASK_SET_TS |
> +	       IFI_CANFD_IRQMASK_SET_TX |
> +	       IFI_CANFD_IRQMASK_SET_RX | enirq,
> +	       priv->base + IFI_CANFD_IRQMASK);
> +}
> +
> +static void ifi_canfd_read_fifo(struct net_device *ndev)
> +{
> +	struct net_device_stats *stats = &ndev->stats;
> +	struct ifi_canfd_priv *priv = netdev_priv(ndev);
> +	struct canfd_frame *cf;
> +	struct sk_buff *skb;
> +	const u32 rx_irq_mask = IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY |
> +				IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER;
> +	u32 rxdlc, rxid;
> +	u32 dlc, id;
> +	int i;
> +
> +	rxdlc = readl(priv->base + IFI_CANFD_RXFIFO_DLC);
> +	if (rxdlc & IFI_CANFD_RXFIFO_DLC_EDL)
> +		skb = alloc_canfd_skb(ndev, &cf);
> +	else
> +		skb = alloc_can_skb(ndev, (struct can_frame **)&cf);
> +
> +	if (!skb) {
> +		stats->rx_dropped++;
> +		return;
> +	}
> +
> +	dlc = (rxdlc >> IFI_CANFD_RXFIFO_DLC_DLC_OFFSET) &
> +	      IFI_CANFD_RXFIFO_DLC_DLC_MASK;
> +	if (rxdlc & IFI_CANFD_RXFIFO_DLC_EDL)
> +		cf->len = can_dlc2len(dlc);
> +	else
> +		cf->len = get_can_dlc(dlc);
> +
> +	rxid = readl(priv->base + IFI_CANFD_RXFIFO_ID);
> +	id = (rxid >> IFI_CANFD_RXFIFO_ID_ID_OFFSET);
> +	if (id & IFI_CANFD_RXFIFO_ID_IDE)
> +		id &= IFI_CANFD_RXFIFO_ID_ID_XTD_MASK;
> +	else
> +		id &= IFI_CANFD_RXFIFO_ID_ID_STD_MASK;
> +	cf->can_id = id;
> +
> +	if (rxdlc & IFI_CANFD_RXFIFO_DLC_ESI) {
> +		cf->flags |= CANFD_ESI;
> +		netdev_dbg(ndev, "ESI Error\n");
> +	}
> +
> +	if (!(rxdlc & IFI_CANFD_RXFIFO_DLC_EDL) &&
> +	    (rxdlc & IFI_CANFD_RXFIFO_DLC_RTR)) {
> +		cf->can_id |= CAN_RTR_FLAG;
> +	} else {
> +		if (rxdlc & IFI_CANFD_RXFIFO_DLC_BRS)
> +			cf->flags |= CANFD_BRS;
> +
> +		for (i = 0; i < cf->len; i += 4) {
> +			*(u32 *)(cf->data + i) =
> +				readl(priv->base + IFI_CANFD_RXFIFO_DATA + i);
> +		}
> +	}
> +
> +	/* Remove the packet from FIFO */
> +	writel(IFI_CANFD_RXSTCMD_REMOVE_MSG, priv->base + IFI_CANFD_RXSTCMD);
> +	writel(rx_irq_mask, priv->base + IFI_CANFD_INTERRUPT);
> +
> +	stats->rx_packets++;
> +	stats->rx_bytes += cf->len;
> +
> +	netif_receive_skb(skb);
> +}
> +
> +static int ifi_canfd_do_rx_poll(struct net_device *ndev, int quota)
> +{
> +	struct ifi_canfd_priv *priv = netdev_priv(ndev);
> +	u32 pkts = 0;
> +	u32 rxst;
> +
> +	rxst = readl(priv->base + IFI_CANFD_RXSTCMD);
> +	if (rxst & IFI_CANFD_RXSTCMD_EMPTY) {
> +		netdev_dbg(ndev, "No messages in RX FIFO\n");
> +		return 0;
> +	}
> +
> +	for (;;) {
> +		if (rxst & IFI_CANFD_RXSTCMD_EMPTY)
> +			break;
> +		if (quota <= 0)
> +			break;
> +
> +		ifi_canfd_read_fifo(ndev);
> +		quota--;
> +		pkts++;
> +		rxst = readl(priv->base + IFI_CANFD_RXSTCMD);
> +	}
> +
> +	if (pkts)
> +		can_led_event(ndev, CAN_LED_EVENT_RX);
> +
> +	return pkts;
> +}
> +
> +static int ifi_canfd_handle_lost_msg(struct net_device *ndev)
> +{
> +	struct net_device_stats *stats = &ndev->stats;
> +	struct sk_buff *skb;
> +	struct can_frame *frame;
> +
> +	netdev_err(ndev, "RX FIFO overflow, message(s) lost.\n");
> +
> +	stats->rx_errors++;
> +	stats->rx_over_errors++;
> +
> +	skb = alloc_can_err_skb(ndev, &frame);
> +	if (unlikely(!skb))
> +		return 0;
> +
> +	frame->can_id |= CAN_ERR_CRTL;
> +	frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
> +
> +	netif_receive_skb(skb);
> +
> +	return 1;
> +}
> +
> +static int ifi_canfd_get_berr_counter(const struct net_device *ndev,
> +				      struct can_berr_counter *bec)
> +{
> +	struct ifi_canfd_priv *priv = netdev_priv(ndev);
> +	u32 err;
> +
> +	err = readl(priv->base + IFI_CANFD_ERROR);
> +	bec->rxerr = (err >> IFI_CANFD_ERROR_RX_OFFSET) &
> +		     IFI_CANFD_ERROR_RX_MASK;
> +	bec->txerr = (err >> IFI_CANFD_ERROR_TX_OFFSET) &
> +		     IFI_CANFD_ERROR_TX_MASK;
> +
> +	return 0;
> +}
> +
> +static int ifi_canfd_handle_state_change(struct net_device *ndev,
> +					 enum can_state new_state)
> +{
> +	struct ifi_canfd_priv *priv = netdev_priv(ndev);
> +	struct net_device_stats *stats = &ndev->stats;
> +	struct can_frame *cf;
> +	struct sk_buff *skb;
> +	struct can_berr_counter bec;
> +
> +	switch (new_state) {
> +	case CAN_STATE_ERROR_ACTIVE:
> +		/* error warning state */
> +		priv->can.can_stats.error_warning++;
> +		priv->can.state = CAN_STATE_ERROR_WARNING;
> +		break;
> +	case CAN_STATE_ERROR_PASSIVE:
> +		/* error passive state */
> +		priv->can.can_stats.error_passive++;
> +		priv->can.state = CAN_STATE_ERROR_PASSIVE;
> +		break;
> +	case CAN_STATE_BUS_OFF:
> +		/* bus-off state */
> +		priv->can.state = CAN_STATE_BUS_OFF;
> +		ifi_canfd_irq_enable(ndev, 0);
> +		priv->can.can_stats.bus_off++;
> +		can_bus_off(ndev);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	/* propagate the error condition to the CAN stack */
> +	skb = alloc_can_err_skb(ndev, &cf);
> +	if (unlikely(!skb))
> +		return 0;
> +
> +	ifi_canfd_get_berr_counter(ndev, &bec);
> +
> +	switch (new_state) {
> +	case CAN_STATE_ERROR_ACTIVE:
> +		/* error warning state */
> +		cf->can_id |= CAN_ERR_CRTL;
> +		cf->data[1] = (bec.txerr > bec.rxerr) ?
> +			CAN_ERR_CRTL_TX_WARNING :
> +			CAN_ERR_CRTL_RX_WARNING;
> +		cf->data[6] = bec.txerr;
> +		cf->data[7] = bec.rxerr;
> +		break;
> +	case CAN_STATE_ERROR_PASSIVE:
> +		/* error passive state */
> +		cf->can_id |= CAN_ERR_CRTL;
> +		cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
> +		if (bec.txerr > 127)
> +			cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
> +		cf->data[6] = bec.txerr;
> +		cf->data[7] = bec.rxerr;
> +		break;
> +	case CAN_STATE_BUS_OFF:
> +		/* bus-off state */
> +		cf->can_id |= CAN_ERR_BUSOFF;
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	stats->rx_packets++;
> +	stats->rx_bytes += cf->can_dlc;
> +	netif_receive_skb(skb);
> +
> +	return 1;
> +}
> +
> +static int ifi_canfd_handle_state_errors(struct net_device *ndev, u32 stcmd)
> +{
> +	struct ifi_canfd_priv *priv = netdev_priv(ndev);
> +	int work_done = 0;
> +	u32 isr;
> +
> +	/*
> +	 * The ErrWarn condition is a little special, since the bit is
> +	 * located in the INTERRUPT register instead of STCMD register.
> +	 */
> +	isr = readl(priv->base + IFI_CANFD_INTERRUPT);
> +	if ((isr & IFI_CANFD_INTERRUPT_ERROR_WARNING) &&
> +	    (priv->can.state != CAN_STATE_ERROR_WARNING)) {
> +		/* Clear the interrupt */
> +		writel(IFI_CANFD_INTERRUPT_ERROR_WARNING,
> +		       priv->base + IFI_CANFD_INTERRUPT);
> +		netdev_dbg(ndev, "Error, entered warning state\n");
> +		work_done += ifi_canfd_handle_state_change(ndev,
> +						CAN_STATE_ERROR_WARNING);
> +	}
> +
> +	if ((stcmd & IFI_CANFD_STCMD_ERROR_PASSIVE) &&
> +	    (priv->can.state != CAN_STATE_ERROR_PASSIVE)) {
> +		netdev_dbg(ndev, "Error, entered passive state\n");
> +		work_done += ifi_canfd_handle_state_change(ndev,
> +						CAN_STATE_ERROR_PASSIVE);
> +	}
> +
> +	if ((stcmd & IFI_CANFD_STCMD_BUSOFF) &&
> +	    (priv->can.state != CAN_STATE_BUS_OFF)) {
> +		netdev_dbg(ndev, "Error, entered bus-off state\n");
> +		work_done += ifi_canfd_handle_state_change(ndev,
> +						CAN_STATE_BUS_OFF);
> +	}
> +
> +	return work_done;
> +}
> +
> +static int ifi_canfd_poll(struct napi_struct *napi, int quota)
> +{
> +	struct net_device *ndev = napi->dev;
> +	struct ifi_canfd_priv *priv = netdev_priv(ndev);
> +	const u32 stcmd_state_mask = IFI_CANFD_STCMD_ERROR_PASSIVE |
> +				     IFI_CANFD_STCMD_BUSOFF;
> +	int work_done = 0;
> +
> +	u32 stcmd = readl(priv->base + IFI_CANFD_STCMD);
> +	u32 rxstcmd = readl(priv->base + IFI_CANFD_STCMD);
> +
> +	/* Handle bus state changes */
> +	if ((stcmd & stcmd_state_mask) ||
> +	    ((stcmd & IFI_CANFD_STCMD_ERROR_ACTIVE) == 0))
> +		work_done += ifi_canfd_handle_state_errors(ndev, stcmd);
> +
> +	/* Handle lost messages on RX */
> +	if (rxstcmd & IFI_CANFD_RXSTCMD_OVERFLOW)
> +		work_done += ifi_canfd_handle_lost_msg(ndev);
> +
> +	/* Handle normal messages on RX */
> +	if (!(rxstcmd & IFI_CANFD_RXSTCMD_EMPTY))
> +		work_done += ifi_canfd_do_rx_poll(ndev, quota - work_done);
> +
> +	if (work_done < quota) {
> +		napi_complete(napi);
> +		ifi_canfd_irq_enable(ndev, 1);
> +	}
> +
> +	return work_done;
> +}
> +
> +static irqreturn_t ifi_canfd_isr(int irq, void *dev_id)
> +{
> +	struct net_device *ndev = (struct net_device *)dev_id;
> +	struct ifi_canfd_priv *priv = netdev_priv(ndev);
> +	struct net_device_stats *stats = &ndev->stats;
> +	const u32 rx_irq_mask = IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY |
> +				IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER;
> +	const u32 tx_irq_mask = IFI_CANFD_INTERRUPT_TXFIFO_EMPTY |
> +				IFI_CANFD_INTERRUPT_TXFIFO_REMOVE;
> +	const u32 clr_irq_mask = (u32)(~(IFI_CANFD_INTERRUPT_SET_IRQ |
> +					 IFI_CANFD_INTERRUPT_ERROR_WARNING));

I've squashed:

>> -       const u32 clr_irq_mask = (u32)(~(IFI_CANFD_INTERRUPT_SET_IRQ |
>> -                                        IFI_CANFD_INTERRUPT_ERROR_WARNING));
>> +       const u32 clr_irq_mask = ~(IFI_CANFD_INTERRUPT_SET_IRQ |
>> +                                  IFI_CANFD_INTERRUPT_ERROR_WARNING);

and the driver compiles without warnings.

Applied to can-next.

thanks,
Marc

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


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

  reply	other threads:[~2016-01-20 14:40 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-11 18:47 [PATCH 1/5] net: can: Sort the Kconfig includes Marek Vasut
2016-01-11 18:48 ` [PATCH 2/5] net: can: Sort the Makefile Marek Vasut
2016-01-11 18:48 ` [PATCH 3/5] of: Add vendor prefix for I/F/I Marek Vasut
2016-01-11 18:48 ` [PATCH 4/5] net: can: ifi: Add DT bindings for ifi,canfd Marek Vasut
2016-01-11 18:48 ` [PATCH 5/5] net: can: ifi: Add IFI CANFD IP support Marek Vasut
2016-01-11 19:29   ` kbuild test robot
2016-01-11 19:33     ` Marek Vasut
2016-01-12 11:06   ` kbuild test robot
2016-01-12 23:59   ` [PATCH V2 " Marek Vasut
2016-01-20 10:39     ` Marc Kleine-Budde
2016-01-20 10:54       ` Marc Kleine-Budde
2016-01-20 12:58         ` Marek Vasut
2016-01-20 14:06           ` Marc Kleine-Budde
2016-01-20 14:25             ` Marek Vasut
2016-01-23  0:11               ` Rustad, Mark D
2016-01-20 14:33             ` [PATCH V3 " Marek Vasut
2016-01-20 14:39               ` Marc Kleine-Budde [this message]
2016-01-20 14:41                 ` Marek Vasut
2016-01-20 14:46                   ` Marc Kleine-Budde
2016-01-20 15:03                     ` Marek Vasut
2016-01-20 15:09                       ` Marc Kleine-Budde
2016-01-20 15:40                         ` Marek Vasut

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=569F9C37.60007@pengutronix.de \
    --to=mkl@pengutronix.de \
    --cc=marex@denx.de \
    --cc=mark.rutland@arm.com \
    --cc=netdev@vger.kernel.org \
    --cc=socketcan@hartkopp.net \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.