All of lore.kernel.org
 help / color / mirror / Atom feed
* pull-request: can 2014-04-24
@ 2014-04-24 22:00 Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 01/26] can: c_can_pci: Set the type of the IP core Marc Kleine-Budde
                   ` (27 more replies)
  0 siblings, 28 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel

Hello David,

this is a pull request for net/master, for the v3.15 release cycle, consisting
of 26 patches.

Thomas Gleixner contributes 21 patches for the c_can driver, which address
several shortcomings in the driver like hardware initialisation, concurrency,
message ordering and poor performance. Two patches Oliver Hartkopp, one adds a
missing lock to the sja1000_isa driver, the other one fixes the return value in
the generic bit time configuration function. And finally a patch by Alexander
Stein, that fixes the slcan driver to use the correct spinlock variant.

regards,
Marc

---

The following changes since commit a64d90fd962c2956da7505f98a302408450365e2:

  netfilter: Fix warning in nfnetlink_receive(). (2014-04-24 13:51:29 -0400)

are available in the git repository at:

  git://gitorious.org/linux-can/linux-can.git tags/linux-can-fixes-for-3.15-20140424

for you to fetch changes up to 367525c8c20a34560afe1d0c7cca52a44ccd62e9:

  can: slcan: Fix spinlock variant (2014-04-24 22:32:41 +0200)

----------------------------------------------------------------
linux-can-fixes-for-3.15-20140424

----------------------------------------------------------------
Alexander Stein (1):
      can: slcan: Fix spinlock variant

Oliver Hartkopp (2):
      can: sja1000_isa: add locking for indirect register access mode
      can: fix return value from can_get_bittiming()

Thomas Gleixner (21):
      can: c_can_pci: Set the type of the IP core
      can: c_can: Fix startup logic
      can: c_can: Make bus off interrupt disable logic work
      can: c_can: Do not access skb after net_receive_skb()
      can: c_can: Handle state change correctly
      can: c_can: Fix berr reporting
      can: c_can: Always update error stats
      can: c_can: Simplify buffer reenabling
      can: c_can: Avoid status register update for D_CAN
      can: c_can: Get rid of pointless interrupts
      can: c_can: Disable rx split as workaround
      can: c_can: Work around C_CAN RX wreckage
      can: c_can: Cleanup irq enable/disable
      can: c_can: Cleanup c_can_read_msg_object()
      can: c_can: Cleanup setup of receive buffers
      can: c_can: Cleanup c_can_inval_msg_object()
      can: c_can: Cleanup c_can_msg_obj_put/get()
      can: c_can: Cleanup c_can_write_msg_object()
      can: c_can: Use proper u32 variables in c_can_write_msg_object()
      can: c_can: Remove tx locking
      can: c_can: Speed up tx buffer invalidation

Wolfgang Grandegger (1):
      can: c_can_pci: enable PCI bus master only for MSI

Wolfram Sang (1):
      can: c_can: use proper type for 'instance'

 drivers/net/can/c_can/Kconfig          |   7 +
 drivers/net/can/c_can/c_can.c          | 660 +++++++++++++++------------------
 drivers/net/can/c_can/c_can.h          |  23 +-
 drivers/net/can/c_can/c_can_pci.c      |   9 +-
 drivers/net/can/c_can/c_can_platform.c |   2 +-
 drivers/net/can/dev.c                  |   2 +-
 drivers/net/can/sja1000/sja1000_isa.c  |  16 +-
 drivers/net/can/slcan.c                |   6 +-
 8 files changed, 343 insertions(+), 382 deletions(-)


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 01/26] can: c_can_pci: Set the type of the IP core
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 02/26] can: c_can: Fix startup logic Marc Kleine-Budde
                   ` (26 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

All type checks in c_can.c are != BOSCH_D_CAN so nobody noticed so far
that the pci code does not update the type information.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can_pci.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c
index bce0be5..1b7ff40 100644
--- a/drivers/net/can/c_can/c_can_pci.c
+++ b/drivers/net/can/c_can/c_can_pci.c
@@ -132,6 +132,8 @@ static int c_can_pci_probe(struct pci_dev *pdev,
 		goto out_free_c_can;
 	}
 
+	priv->type = c_can_pci_data->type;
+
 	/* Configure access to registers */
 	switch (c_can_pci_data->reg_align) {
 	case C_CAN_REG_ALIGN_32:
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 02/26] can: c_can: Fix startup logic
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 01/26] can: c_can_pci: Set the type of the IP core Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-29  7:29   ` Yegor Yefremov
  2014-04-24 22:00 ` [PATCH 03/26] can: c_can: Make bus off interrupt disable logic work Marc Kleine-Budde
                   ` (25 subsequent siblings)
  27 siblings, 1 reply; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

c_can_start() enables interrupts way too early. The first enabling
happens when setting the control mode in c_can_chip_config() and then
again at the end of the function.

But that happens before napi_enable() and that means that an interrupt
which comes in will disable interrupts again and call napi_schedule,
which ignores the request and the later napi_enable() is not making
thinks work either. So the interface is up with all device interrupts
disabled.

Move the device interrupt after napi_enable() and add it to the other
callsites of c_can_start() in c_can_set_mode() and c_can_power_up()

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 35 +++++++++++++++++------------------
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index a5c8dcf..b1629a4 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -612,30 +612,22 @@ static int c_can_chip_config(struct net_device *dev)
 	struct c_can_priv *priv = netdev_priv(dev);
 
 	/* enable automatic retransmission */
-	priv->write_reg(priv, C_CAN_CTRL_REG,
-			CONTROL_ENABLE_AR);
+	priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR);
 
 	if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) &&
 	    (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) {
 		/* loopback + silent mode : useful for hot self-test */
-		priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE |
-				CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
-		priv->write_reg(priv, C_CAN_TEST_REG,
-				TEST_LBACK | TEST_SILENT);
+		priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
+		priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK | TEST_SILENT);
 	} else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
 		/* loopback mode : useful for self-test function */
-		priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE |
-				CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
+		priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
 		priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK);
 	} else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
 		/* silent mode : bus-monitoring mode */
-		priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE |
-				CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
+		priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
 		priv->write_reg(priv, C_CAN_TEST_REG, TEST_SILENT);
-	} else
-		/* normal mode*/
-		priv->write_reg(priv, C_CAN_CTRL_REG,
-				CONTROL_EIE | CONTROL_SIE | CONTROL_IE);
+	}
 
 	/* configure message objects */
 	c_can_configure_msg_objects(dev);
@@ -662,9 +654,6 @@ static int c_can_start(struct net_device *dev)
 	/* reset tx helper pointers */
 	priv->tx_next = priv->tx_echo = 0;
 
-	/* enable status change, error and module interrupts */
-	c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
-
 	return 0;
 }
 
@@ -681,6 +670,7 @@ static void c_can_stop(struct net_device *dev)
 
 static int c_can_set_mode(struct net_device *dev, enum can_mode mode)
 {
+	struct c_can_priv *priv = netdev_priv(dev);
 	int err;
 
 	switch (mode) {
@@ -689,6 +679,8 @@ static int c_can_set_mode(struct net_device *dev, enum can_mode mode)
 		if (err)
 			return err;
 		netif_wake_queue(dev);
+		/* enable status change, error and module interrupts */
+		c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
 		break;
 	default:
 		return -EOPNOTSUPP;
@@ -1184,6 +1176,8 @@ static int c_can_open(struct net_device *dev)
 	can_led_event(dev, CAN_LED_EVENT_OPEN);
 
 	napi_enable(&priv->napi);
+	/* enable status change, error and module interrupts */
+	c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
 	netif_start_queue(dev);
 
 	return 0;
@@ -1281,6 +1275,7 @@ int c_can_power_up(struct net_device *dev)
 	u32 val;
 	unsigned long time_out;
 	struct c_can_priv *priv = netdev_priv(dev);
+	int ret;
 
 	if (!(dev->flags & IFF_UP))
 		return 0;
@@ -1307,7 +1302,11 @@ int c_can_power_up(struct net_device *dev)
 	if (time_after(jiffies, time_out))
 		return -ETIMEDOUT;
 
-	return c_can_start(dev);
+	ret = c_can_start(dev);
+	if (!ret)
+		c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(c_can_power_up);
 #endif
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 03/26] can: c_can: Make bus off interrupt disable logic work
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 01/26] can: c_can_pci: Set the type of the IP core Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 02/26] can: c_can: Fix startup logic Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 04/26] can: c_can: Do not access skb after net_receive_skb() Marc Kleine-Budde
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

The state change handler is called with device interrupts disabled
already. So no point in disabling them again when we enter bus off
state.

But what's worse is that we reenable the interrupts at the end of NAPI
poll unconditionally. So c_can_start() which is called from the
restart timer can trigger interrupts which confuse the hell out of the
half reinitialized driver/hw.

Remove the pointless device interrupt disable in the BUS_OFF handler
and prevent reenabling the device interrupts at the end of the poll
routine when the current state is BUS_OFF.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index b1629a4..8c725f4 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -954,11 +954,6 @@ static int c_can_handle_state_change(struct net_device *dev,
 		/* bus-off state */
 		priv->can.state = CAN_STATE_BUS_OFF;
 		cf->can_id |= CAN_ERR_BUSOFF;
-		/*
-		 * disable all interrupts in bus-off mode to ensure that
-		 * the CPU is not hogged down
-		 */
-		c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
 		can_bus_off(dev);
 		break;
 	default:
@@ -1089,6 +1084,7 @@ static int c_can_poll(struct napi_struct *napi, int quota)
 			netdev_dbg(dev, "entered bus off state\n");
 			work_done += c_can_handle_state_change(dev,
 						C_CAN_BUS_OFF);
+			goto end;
 		}
 
 		/* handle bus recovery events */
@@ -1122,8 +1118,9 @@ static int c_can_poll(struct napi_struct *napi, int quota)
 end:
 	if (work_done < quota) {
 		napi_complete(napi);
-		/* enable all IRQs */
-		c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
+		/* enable all IRQs if we are not in bus off state */
+		if (priv->can.state != CAN_STATE_BUS_OFF)
+			c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
 	}
 
 	return work_done;
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 04/26] can: c_can: Do not access skb after net_receive_skb()
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (2 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 03/26] can: c_can: Make bus off interrupt disable logic work Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 05/26] can: c_can: Handle state change correctly Marc Kleine-Budde
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

There is no guarantee that the skb is in the same state after calling
net_receive_skb(). It might be freed or reused. Not really harmful as
its a read access, except you turn on the proper debugging options
which catch a use after free.

The whole can subsystem is full of this. Copy and paste ....

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 8c725f4..6038761 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -429,10 +429,10 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl)
 		}
 	}
 
-	netif_receive_skb(skb);
-
 	stats->rx_packets++;
 	stats->rx_bytes += frame->can_dlc;
+
+	netif_receive_skb(skb);
 	return 0;
 }
 
@@ -960,9 +960,9 @@ static int c_can_handle_state_change(struct net_device *dev,
 		break;
 	}
 
-	netif_receive_skb(skb);
 	stats->rx_packets++;
 	stats->rx_bytes += cf->can_dlc;
+	netif_receive_skb(skb);
 
 	return 1;
 }
@@ -1033,10 +1033,9 @@ static int c_can_handle_bus_err(struct net_device *dev,
 	/* set a `lec` value so that we can check for updates later */
 	priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
 
-	netif_receive_skb(skb);
 	stats->rx_packets++;
 	stats->rx_bytes += cf->can_dlc;
-
+	netif_receive_skb(skb);
 	return 1;
 }
 
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 05/26] can: c_can: Handle state change correctly
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (3 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 04/26] can: c_can: Do not access skb after net_receive_skb() Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 06/26] can: c_can: Fix berr reporting Marc Kleine-Budde
                   ` (22 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

If the allocation of an error skb fails, the state change handling
returns w/o doing any work. That leaves the interface in a wreckaged
state as the internal status is wrong.

Split the interface handling and the skb handling.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 25 ++++++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 6038761..246bcf9 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -914,6 +914,26 @@ static int c_can_handle_state_change(struct net_device *dev,
 	struct sk_buff *skb;
 	struct can_berr_counter bec;
 
+	switch (error_type) {
+	case C_CAN_ERROR_WARNING:
+		/* error warning state */
+		priv->can.can_stats.error_warning++;
+		priv->can.state = CAN_STATE_ERROR_WARNING;
+		break;
+	case C_CAN_ERROR_PASSIVE:
+		/* error passive state */
+		priv->can.can_stats.error_passive++;
+		priv->can.state = CAN_STATE_ERROR_PASSIVE;
+		break;
+	case C_CAN_BUS_OFF:
+		/* bus-off state */
+		priv->can.state = CAN_STATE_BUS_OFF;
+		can_bus_off(dev);
+		break;
+	default:
+		break;
+	}
+
 	/* propagate the error condition to the CAN stack */
 	skb = alloc_can_err_skb(dev, &cf);
 	if (unlikely(!skb))
@@ -927,8 +947,6 @@ static int c_can_handle_state_change(struct net_device *dev,
 	switch (error_type) {
 	case C_CAN_ERROR_WARNING:
 		/* error warning state */
-		priv->can.can_stats.error_warning++;
-		priv->can.state = CAN_STATE_ERROR_WARNING;
 		cf->can_id |= CAN_ERR_CRTL;
 		cf->data[1] = (bec.txerr > bec.rxerr) ?
 			CAN_ERR_CRTL_TX_WARNING :
@@ -939,8 +957,6 @@ static int c_can_handle_state_change(struct net_device *dev,
 		break;
 	case C_CAN_ERROR_PASSIVE:
 		/* error passive state */
-		priv->can.can_stats.error_passive++;
-		priv->can.state = CAN_STATE_ERROR_PASSIVE;
 		cf->can_id |= CAN_ERR_CRTL;
 		if (rx_err_passive)
 			cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
@@ -952,7 +968,6 @@ static int c_can_handle_state_change(struct net_device *dev,
 		break;
 	case C_CAN_BUS_OFF:
 		/* bus-off state */
-		priv->can.state = CAN_STATE_BUS_OFF;
 		cf->can_id |= CAN_ERR_BUSOFF;
 		can_bus_off(dev);
 		break;
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 06/26] can: c_can: Fix berr reporting
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (4 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 05/26] can: c_can: Handle state change correctly Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 07/26] can: c_can: Always update error stats Marc Kleine-Budde
                   ` (21 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

Reading the LEC type with

  return (mode & ENABLED) && (status & LEC_MASK);

is not guaranteed to return (status & LEC_MASK) if the enabled bit in
mode is set. It's guaranteed to return 0 or !=0.

Remove the inline function and call unconditionally into the
berr_handling code and return early when the reporting is disabled.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 246bcf9..9ef45b0 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -171,6 +171,7 @@ enum c_can_lec_type {
 	LEC_BIT0_ERROR,
 	LEC_CRC_ERROR,
 	LEC_UNUSED,
+	LEC_MASK = LEC_UNUSED,
 };
 
 /*
@@ -897,12 +898,6 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota)
 	return pkts;
 }
 
-static inline int c_can_has_and_handle_berr(struct c_can_priv *priv)
-{
-	return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) &&
-		(priv->current_status & LEC_UNUSED);
-}
-
 static int c_can_handle_state_change(struct net_device *dev,
 				enum c_can_bus_error_types error_type)
 {
@@ -998,6 +993,9 @@ static int c_can_handle_bus_err(struct net_device *dev,
 	if (lec_type == LEC_UNUSED || lec_type == LEC_NO_ERROR)
 		return 0;
 
+	if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING))
+		return 0;
+
 	/* propagate the error condition to the CAN stack */
 	skb = alloc_can_err_skb(dev, &cf);
 	if (unlikely(!skb))
@@ -1057,7 +1055,6 @@ static int c_can_handle_bus_err(struct net_device *dev,
 static int c_can_poll(struct napi_struct *napi, int quota)
 {
 	u16 irqstatus;
-	int lec_type = 0;
 	int work_done = 0;
 	struct net_device *dev = napi->dev;
 	struct c_can_priv *priv = netdev_priv(dev);
@@ -1116,9 +1113,8 @@ static int c_can_poll(struct napi_struct *napi, int quota)
 		priv->last_status = priv->current_status;
 
 		/* handle lec errors on the bus */
-		lec_type = c_can_has_and_handle_berr(priv);
-		if (lec_type)
-			work_done += c_can_handle_bus_err(dev, lec_type);
+		work_done += c_can_handle_bus_err(dev,
+					priv->current_status & LEC_MASK);
 	} else if ((irqstatus >= C_CAN_MSG_OBJ_RX_FIRST) &&
 			(irqstatus <= C_CAN_MSG_OBJ_RX_LAST)) {
 		/* handle events corresponding to receive message objects */
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 07/26] can: c_can: Always update error stats
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (5 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 06/26] can: c_can: Fix berr reporting Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 08/26] can: c_can: Simplify buffer reenabling Marc Kleine-Budde
                   ` (20 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

If the allocation of the error skb fails, we still want to see the
error statistics.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 9ef45b0..6170e64 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -378,6 +378,9 @@ static int c_can_handle_lost_msg_obj(struct net_device *dev,
 	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl);
 	c_can_object_put(dev, iface, objno, IF_COMM_CONTROL);
 
+	stats->rx_errors++;
+	stats->rx_over_errors++;
+
 	/* create an error msg */
 	skb = alloc_can_err_skb(dev, &frame);
 	if (unlikely(!skb))
@@ -385,8 +388,6 @@ static int c_can_handle_lost_msg_obj(struct net_device *dev,
 
 	frame->can_id |= CAN_ERR_CRTL;
 	frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
-	stats->rx_errors++;
-	stats->rx_over_errors++;
 
 	netif_receive_skb(skb);
 	return 1;
@@ -996,6 +997,10 @@ static int c_can_handle_bus_err(struct net_device *dev,
 	if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING))
 		return 0;
 
+	/* common for all type of bus errors */
+	priv->can.can_stats.bus_error++;
+	stats->rx_errors++;
+
 	/* propagate the error condition to the CAN stack */
 	skb = alloc_can_err_skb(dev, &cf);
 	if (unlikely(!skb))
@@ -1005,10 +1010,6 @@ static int c_can_handle_bus_err(struct net_device *dev,
 	 * check for 'last error code' which tells us the
 	 * type of the last error to occur on the CAN bus
 	 */
-
-	/* common for all type of bus errors */
-	priv->can.can_stats.bus_error++;
-	stats->rx_errors++;
 	cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
 	cf->data[2] |= CAN_ERR_PROT_UNSPEC;
 
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 08/26] can: c_can: Simplify buffer reenabling
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (6 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 07/26] can: c_can: Always update error stats Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 09/26] can: c_can: Avoid status register update for D_CAN Marc Kleine-Budde
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

Instead of writing to the message object we can simply clear the
NewDat bit with the get method.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 6170e64..2aae073 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -108,6 +108,7 @@
 #define IF_COMM_CONTROL		BIT(4)
 #define IF_COMM_CLR_INT_PND	BIT(3)
 #define IF_COMM_TXRQST		BIT(2)
+#define IF_COMM_CLR_NEWDAT	IF_COMM_TXRQST
 #define IF_COMM_DATAA		BIT(1)
 #define IF_COMM_DATAB		BIT(0)
 #define IF_COMM_ALL		(IF_COMM_MASK | IF_COMM_ARB | \
@@ -120,7 +121,7 @@
 				 IF_COMM_DATAA | IF_COMM_DATAB)
 
 /* For the high buffers we clear the interrupt bit and newdat */
-#define IF_COMM_RCV_HIGH	(IF_COMM_RCV_LOW | IF_COMM_TXRQST)
+#define IF_COMM_RCV_HIGH	(IF_COMM_RCV_LOW | IF_COMM_CLR_NEWDAT)
 
 /* IFx arbitration */
 #define IF_ARB_MSGVAL		BIT(15)
@@ -353,17 +354,12 @@ static void c_can_write_msg_object(struct net_device *dev,
 }
 
 static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev,
-						int iface,
-						int ctrl_mask)
+						       int iface)
 {
 	int i;
-	struct c_can_priv *priv = netdev_priv(dev);
 
-	for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++) {
-		priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface),
-				ctrl_mask & ~IF_MCONT_NEWDAT);
-		c_can_object_put(dev, iface, i, IF_COMM_CONTROL);
-	}
+	for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++)
+		c_can_object_get(dev, iface, i, IF_COMM_CLR_NEWDAT);
 }
 
 static int c_can_handle_lost_msg_obj(struct net_device *dev,
@@ -829,7 +825,7 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
 
 		if (obj == C_CAN_MSG_RX_LOW_LAST)
 			/* activate all lower message objects */
-			c_can_activate_all_lower_rx_msg_obj(dev, IF_RX, ctrl);
+			c_can_activate_all_lower_rx_msg_obj(dev, IF_RX);
 
 		pkts++;
 		quota--;
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 09/26] can: c_can: Avoid status register update for D_CAN
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (7 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 08/26] can: c_can: Simplify buffer reenabling Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 10/26] can: c_can: Get rid of pointless interrupts Marc Kleine-Budde
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

On D_CAN the RXOK, TXOK and LEC bits are cleared/set on read of the
status register. No need to update them.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 2aae073..b381f7b 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -1041,7 +1041,8 @@ static int c_can_handle_bus_err(struct net_device *dev,
 	}
 
 	/* set a `lec` value so that we can check for updates later */
-	priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
+	if (priv->type != BOSCH_D_CAN)
+		priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
 
 	stats->rx_packets++;
 	stats->rx_bytes += cf->can_dlc;
@@ -1066,11 +1067,13 @@ static int c_can_poll(struct napi_struct *napi, int quota)
 					C_CAN_STS_REG);
 
 		/* handle Tx/Rx events */
-		if (priv->current_status & STATUS_TXOK)
+		if (priv->current_status & STATUS_TXOK &&
+		    priv->type != BOSCH_D_CAN)
 			priv->write_reg(priv, C_CAN_STS_REG,
 					priv->current_status & ~STATUS_TXOK);
 
-		if (priv->current_status & STATUS_RXOK)
+		if (priv->current_status & STATUS_RXOK &&
+		    priv->type != BOSCH_D_CAN)
 			priv->write_reg(priv, C_CAN_STS_REG,
 					priv->current_status & ~STATUS_RXOK);
 
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 10/26] can: c_can: Get rid of pointless interrupts
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (8 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 09/26] can: c_can: Avoid status register update for D_CAN Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 11/26] can: c_can: Disable rx split as workaround Marc Kleine-Budde
                   ` (17 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

The driver handles pointlessly TWO interrupts per packet. The reason
is that it enables the status interrupt which fires for each rx and tx
packet and it enables the per message object interrupts as well.

The status interrupt merily acks or in case of D_CAN ignores the TX/RX
state and then the message object interrupt fires.

The message objects interrupts are only useful if all message objects
have hardware filters activated.

But we don't have that and its not simple to implement in that driver
without rewriting it completely.

So we can ditch the message object interrupts and handle the RX/TX
right away from the status interrupt. Instead of TWO we handle ONE.

Note: We must keep the TXIE/RXIE bits in the message buffers because
the status interrupt alone is not reliable enough in corner cases.

If we ever have the need for HW filtering, then this code needs a
complete overhaul and we can think about it then. For now we prefer a
lower interrupt load.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 122 ++++++++++++++++--------------------------
 drivers/net/can/c_can/c_can.h |   3 +-
 2 files changed, 48 insertions(+), 77 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index b381f7b..09cb687 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -593,7 +593,7 @@ static void c_can_configure_msg_objects(struct net_device *dev)
 	/* setup receive message objects */
 	for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++)
 		c_can_setup_receive_object(dev, IF_RX, i, 0, 0,
-			(IF_MCONT_RXIE | IF_MCONT_UMASK) & ~IF_MCONT_EOB);
+					   IF_MCONT_RXIE | IF_MCONT_UMASK);
 
 	c_can_setup_receive_object(dev, IF_RX, C_CAN_MSG_OBJ_RX_LAST, 0, 0,
 			IF_MCONT_EOB | IF_MCONT_RXIE | IF_MCONT_UMASK);
@@ -649,8 +649,9 @@ static int c_can_start(struct net_device *dev)
 
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
-	/* reset tx helper pointers */
+	/* reset tx helper pointers and the rx mask */
 	priv->tx_next = priv->tx_echo = 0;
+	priv->rxmasked = 0;
 
 	return 0;
 }
@@ -823,9 +824,13 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
 		/* read the data from the message object */
 		c_can_read_msg_object(dev, IF_RX, ctrl);
 
-		if (obj == C_CAN_MSG_RX_LOW_LAST)
+		if (obj < C_CAN_MSG_RX_LOW_LAST)
+			priv->rxmasked |= BIT(obj - 1);
+		else if (obj == C_CAN_MSG_RX_LOW_LAST) {
+			priv->rxmasked = 0;
 			/* activate all lower message objects */
 			c_can_activate_all_lower_rx_msg_obj(dev, IF_RX);
+		}
 
 		pkts++;
 		quota--;
@@ -870,7 +875,8 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota)
 
 	while (quota > 0) {
 		if (!pend) {
-			pend = priv->read_reg(priv, C_CAN_INTPND1_REG);
+			pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG);
+			pend &= ~priv->rxmasked;
 			if (!pend)
 				break;
 			/*
@@ -1040,10 +1046,6 @@ static int c_can_handle_bus_err(struct net_device *dev,
 		break;
 	}
 
-	/* set a `lec` value so that we can check for updates later */
-	if (priv->type != BOSCH_D_CAN)
-		priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
-
 	stats->rx_packets++;
 	stats->rx_bytes += cf->can_dlc;
 	netif_receive_skb(skb);
@@ -1052,79 +1054,50 @@ static int c_can_handle_bus_err(struct net_device *dev,
 
 static int c_can_poll(struct napi_struct *napi, int quota)
 {
-	u16 irqstatus;
-	int work_done = 0;
 	struct net_device *dev = napi->dev;
 	struct c_can_priv *priv = netdev_priv(dev);
+	u16 curr, last = priv->last_status;
+	int work_done = 0;
 
-	irqstatus = priv->irqstatus;
-	if (!irqstatus)
-		goto end;
+	priv->last_status = curr = priv->read_reg(priv, C_CAN_STS_REG);
+	/* Ack status on C_CAN. D_CAN is self clearing */
+	if (priv->type != BOSCH_D_CAN)
+		priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
 
-	/* status events have the highest priority */
-	if (irqstatus == STATUS_INTERRUPT) {
-		priv->current_status = priv->read_reg(priv,
-					C_CAN_STS_REG);
-
-		/* handle Tx/Rx events */
-		if (priv->current_status & STATUS_TXOK &&
-		    priv->type != BOSCH_D_CAN)
-			priv->write_reg(priv, C_CAN_STS_REG,
-					priv->current_status & ~STATUS_TXOK);
-
-		if (priv->current_status & STATUS_RXOK &&
-		    priv->type != BOSCH_D_CAN)
-			priv->write_reg(priv, C_CAN_STS_REG,
-					priv->current_status & ~STATUS_RXOK);
-
-		/* handle state changes */
-		if ((priv->current_status & STATUS_EWARN) &&
-				(!(priv->last_status & STATUS_EWARN))) {
-			netdev_dbg(dev, "entered error warning state\n");
-			work_done += c_can_handle_state_change(dev,
-						C_CAN_ERROR_WARNING);
-		}
-		if ((priv->current_status & STATUS_EPASS) &&
-				(!(priv->last_status & STATUS_EPASS))) {
-			netdev_dbg(dev, "entered error passive state\n");
-			work_done += c_can_handle_state_change(dev,
-						C_CAN_ERROR_PASSIVE);
-		}
-		if ((priv->current_status & STATUS_BOFF) &&
-				(!(priv->last_status & STATUS_BOFF))) {
-			netdev_dbg(dev, "entered bus off state\n");
-			work_done += c_can_handle_state_change(dev,
-						C_CAN_BUS_OFF);
-			goto end;
-		}
+	/* handle state changes */
+	if ((curr & STATUS_EWARN) && (!(last & STATUS_EWARN))) {
+		netdev_dbg(dev, "entered error warning state\n");
+		work_done += c_can_handle_state_change(dev, C_CAN_ERROR_WARNING);
+	}
 
-		/* handle bus recovery events */
-		if ((!(priv->current_status & STATUS_BOFF)) &&
-				(priv->last_status & STATUS_BOFF)) {
-			netdev_dbg(dev, "left bus off state\n");
-			priv->can.state = CAN_STATE_ERROR_ACTIVE;
-		}
-		if ((!(priv->current_status & STATUS_EPASS)) &&
-				(priv->last_status & STATUS_EPASS)) {
-			netdev_dbg(dev, "left error passive state\n");
-			priv->can.state = CAN_STATE_ERROR_ACTIVE;
-		}
+	if ((curr & STATUS_EPASS) && (!(last & STATUS_EPASS))) {
+		netdev_dbg(dev, "entered error passive state\n");
+		work_done += c_can_handle_state_change(dev, C_CAN_ERROR_PASSIVE);
+	}
 
-		priv->last_status = priv->current_status;
-
-		/* handle lec errors on the bus */
-		work_done += c_can_handle_bus_err(dev,
-					priv->current_status & LEC_MASK);
-	} else if ((irqstatus >= C_CAN_MSG_OBJ_RX_FIRST) &&
-			(irqstatus <= C_CAN_MSG_OBJ_RX_LAST)) {
-		/* handle events corresponding to receive message objects */
-		work_done += c_can_do_rx_poll(dev, (quota - work_done));
-	} else if ((irqstatus >= C_CAN_MSG_OBJ_TX_FIRST) &&
-			(irqstatus <= C_CAN_MSG_OBJ_TX_LAST)) {
-		/* handle events corresponding to transmit message objects */
-		c_can_do_tx(dev);
+	if ((curr & STATUS_BOFF) && (!(last & STATUS_BOFF))) {
+		netdev_dbg(dev, "entered bus off state\n");
+		work_done += c_can_handle_state_change(dev, C_CAN_BUS_OFF);
+		goto end;
 	}
 
+	/* handle bus recovery events */
+	if ((!(curr & STATUS_BOFF)) && (last & STATUS_BOFF)) {
+		netdev_dbg(dev, "left bus off state\n");
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
+	}
+	if ((!(curr & STATUS_EPASS)) && (last & STATUS_EPASS)) {
+		netdev_dbg(dev, "left error passive state\n");
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
+	}
+
+	/* handle lec errors on the bus */
+	work_done += c_can_handle_bus_err(dev, curr & LEC_MASK);
+
+	/* Handle Tx/Rx events. We do this unconditionally */
+	work_done += c_can_do_rx_poll(dev, (quota - work_done));
+	c_can_do_tx(dev);
+
 end:
 	if (work_done < quota) {
 		napi_complete(napi);
@@ -1141,8 +1114,7 @@ static irqreturn_t c_can_isr(int irq, void *dev_id)
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct c_can_priv *priv = netdev_priv(dev);
 
-	priv->irqstatus = priv->read_reg(priv, C_CAN_INT_REG);
-	if (!priv->irqstatus)
+	if (!priv->read_reg(priv, C_CAN_INT_REG))
 		return IRQ_NONE;
 
 	/* disable all interrupts and schedule the NAPI */
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index faa8404..cd91960 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -185,7 +185,6 @@ struct c_can_priv {
 	struct device *device;
 	spinlock_t xmit_lock;
 	int tx_object;
-	int current_status;
 	int last_status;
 	u16 (*read_reg) (struct c_can_priv *priv, enum reg index);
 	void (*write_reg) (struct c_can_priv *priv, enum reg index, u16 val);
@@ -195,11 +194,11 @@ struct c_can_priv {
 	unsigned int tx_next;
 	unsigned int tx_echo;
 	void *priv;		/* for board-specific data */
-	u16 irqstatus;
 	enum c_can_dev_id type;
 	u32 __iomem *raminit_ctrlreg;
 	unsigned int instance;
 	void (*raminit) (const struct c_can_priv *priv, bool enable);
+	u32 rxmasked;
 	u32 dlc[C_CAN_MSG_OBJ_TX_NUM];
 };
 
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 11/26] can: c_can: Disable rx split as workaround
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (9 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 10/26] can: c_can: Get rid of pointless interrupts Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 12/26] can: c_can: Work around C_CAN RX wreckage Marc Kleine-Budde
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

The RX buffer split causes packet loss in the hardware:

What happens is:

RX Packet 1 --> message buffer 1 (newdat bit is not cleared)
RX Packet 2 --> message buffer 2 (newdat bit is not cleared)
RX Packet 3 --> message buffer 3 (newdat bit is not cleared)
RX Packet 4 --> message buffer 4 (newdat bit is not cleared)
RX Packet 5 --> message buffer 5 (newdat bit is not cleared)
RX Packet 6 --> message buffer 6 (newdat bit is not cleared)
RX Packet 7 --> message buffer 7 (newdat bit is not cleared)
RX Packet 8 --> message buffer 8 (newdat bit is not cleared)

Clear newdat bit in message buffer 1
Clear newdat bit in message buffer 2
Clear newdat bit in message buffer 3
Clear newdat bit in message buffer 4
Clear newdat bit in message buffer 5
Clear newdat bit in message buffer 6
Clear newdat bit in message buffer 7
Clear newdat bit in message buffer 8

Now if during that clearing of newdat bits, a new message comes in,
the HW gets confused and drops it.

It does not matter how many of them you clear. I put a delay between
clear of buffer 1 and buffer 2 which was long enough that the message
should have been queued either in buffer 1 or buffer 9. But it did not
show up anywhere. The next message ended up in buffer 1. So the
hardware lost a packet of course without telling it via one of the
error handlers.

That does not happen on all clear newdat bit events. I see one of 10k
packets dropped in the scenario which allows us to reproduce. But the
trace looks always the same.

Not splitting the RX Buffer avoids the packet loss but can cause
reordering. It's hard to trigger, but it CAN happen.

With that mode we use the HW as it was probably designed for. We read
from the buffer 1 upwards and clear the buffer as we get the
message. That's how all microcontrollers use it. So I assume that the
way we handle the buffers was never really tested. According to the
public documentation it should just work :)

Let the user decide which evil is the lesser one.

[ Oliver Hartkopp: Provided a sane config option and help text and
  made me switch to favour potential and unlikely reordering over
  packet loss ]

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/Kconfig |  7 +++++
 drivers/net/can/c_can/c_can.c | 62 +++++++++++++++++++++++++++++++++----------
 2 files changed, 55 insertions(+), 14 deletions(-)

diff --git a/drivers/net/can/c_can/Kconfig b/drivers/net/can/c_can/Kconfig
index 61ffc12..8ab7103 100644
--- a/drivers/net/can/c_can/Kconfig
+++ b/drivers/net/can/c_can/Kconfig
@@ -14,6 +14,13 @@ config CAN_C_CAN_PLATFORM
 	  SPEAr1310 and SPEAr320 evaluation boards & TI (www.ti.com)
 	  boards like am335x, dm814x, dm813x and dm811x.
 
+config CAN_C_CAN_STRICT_FRAME_ORDERING
+	bool "Force a strict RX CAN frame order (may cause frame loss)"
+	---help---
+	  The RX split buffer prevents packet reordering but can cause packet
+	  loss. Only enable this option when you accept to lose CAN frames
+	  in favour of getting the received CAN frames in the correct order.
+
 config CAN_C_CAN_PCI
 	tristate "Generic PCI Bus based C_CAN/D_CAN driver"
 	depends on PCI
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 09cb687..c1a8684 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -791,18 +791,39 @@ static u32 c_can_adjust_pending(u32 pend)
 	return pend & ~((1 << lasts) - 1);
 }
 
+static inline void c_can_rx_object_get(struct net_device *dev, u32 obj)
+{
+#ifdef CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING
+	if (obj < C_CAN_MSG_RX_LOW_LAST)
+		c_can_object_get(dev, IF_RX, obj, IF_COMM_RCV_LOW);
+	else
+#endif
+		c_can_object_get(dev, IF_RX, obj, IF_COMM_RCV_HIGH);
+}
+
+static inline void c_can_rx_finalize(struct net_device *dev,
+				     struct c_can_priv *priv, u32 obj)
+{
+#ifdef CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING
+	if (obj < C_CAN_MSG_RX_LOW_LAST)
+		priv->rxmasked |= BIT(obj - 1);
+	else if (obj == C_CAN_MSG_RX_LOW_LAST) {
+		priv->rxmasked = 0;
+		/* activate all lower message objects */
+		c_can_activate_all_lower_rx_msg_obj(dev, IF_RX);
+	}
+#endif
+}
+
 static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
 			      u32 pend, int quota)
 {
-	u32 pkts = 0, ctrl, obj, mcmd;
+	u32 pkts = 0, ctrl, obj;
 
 	while ((obj = ffs(pend)) && quota > 0) {
 		pend &= ~BIT(obj - 1);
 
-		mcmd = obj < C_CAN_MSG_RX_LOW_LAST ?
-			IF_COMM_RCV_LOW : IF_COMM_RCV_HIGH;
-
-		c_can_object_get(dev, IF_RX, obj, mcmd);
+		c_can_rx_object_get(dev, obj);
 		ctrl = priv->read_reg(priv, C_CAN_IFACE(MSGCTRL_REG, IF_RX));
 
 		if (ctrl & IF_MCONT_MSGLST) {
@@ -824,13 +845,7 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
 		/* read the data from the message object */
 		c_can_read_msg_object(dev, IF_RX, ctrl);
 
-		if (obj < C_CAN_MSG_RX_LOW_LAST)
-			priv->rxmasked |= BIT(obj - 1);
-		else if (obj == C_CAN_MSG_RX_LOW_LAST) {
-			priv->rxmasked = 0;
-			/* activate all lower message objects */
-			c_can_activate_all_lower_rx_msg_obj(dev, IF_RX);
-		}
+		c_can_rx_finalize(dev, priv, obj);
 
 		pkts++;
 		quota--;
@@ -839,6 +854,16 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
 	return pkts;
 }
 
+static inline u32 c_can_get_pending(struct c_can_priv *priv)
+{
+	u32 pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG);
+
+#ifdef CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING
+	pend &= ~priv->rxmasked;
+#endif
+	return pend;
+}
+
 /*
  * theory of operation:
  *
@@ -848,6 +873,8 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
  * has arrived. To work-around this issue, we keep two groups of message
  * objects whose partitioning is defined by C_CAN_MSG_OBJ_RX_SPLIT.
  *
+ * If CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING = y
+ *
  * To ensure in-order frame reception we use the following
  * approach while re-activating a message object to receive further
  * frames:
@@ -860,6 +887,14 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
  * - if the current message object number is greater than
  *   C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of
  *   only this message object.
+ *
+ * This can cause packet loss!
+ *
+ * If CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING = n
+ *
+ * We clear the newdat bit right away.
+ *
+ * This can result in packet reordering when the readout is slow.
  */
 static int c_can_do_rx_poll(struct net_device *dev, int quota)
 {
@@ -875,8 +910,7 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota)
 
 	while (quota > 0) {
 		if (!pend) {
-			pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG);
-			pend &= ~priv->rxmasked;
+			pend = c_can_get_pending(priv);
 			if (!pend)
 				break;
 			/*
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 12/26] can: c_can: Work around C_CAN RX wreckage
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (10 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 11/26] can: c_can: Disable rx split as workaround Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 13/26] can: c_can: Cleanup irq enable/disable Marc Kleine-Budde
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

Alexander reported that the new optimized handling of the RX fifo
causes random packet loss on Intel PCH C_CAN hardware.

After a few fruitless debugging sessions I got hold of a PCH (eg20t)
afflicted system. That machine does not have the CAN interface wired
up, but it was possible to reproduce the issue with the HW loopback
mode.

As Alexander observed correctly, clearing the NewDat flag along with
reading out the message buffer causes that issue on C_CAN, while D_CAN
handles that correctly.

Instead of restoring the original message buffer handling horror the
following workaround solves the issue:

    transfer buffer to IF without clearing the NewDat
    handle the message
    clear NewDat bit

That's similar to the original code but conditional for C_CAN.

I really wonder why all user manuals (C_CAN, Intel PCH and some more)
recommend to clear the NewDat bit right away. The knows it all Oracle
operated by Gurgle does not unearth any useful information either. I
simply cannot believe that we are the first to uncover that HW issue.

Reported-and-tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 13 ++++++++++---
 drivers/net/can/c_can/c_can.h |  1 +
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index c1a8684..5d43c5a 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -647,6 +647,10 @@ static int c_can_start(struct net_device *dev)
 	if (err)
 		return err;
 
+	/* Setup the command for new messages */
+	priv->comm_rcv_high = priv->type != BOSCH_D_CAN ?
+		IF_COMM_RCV_LOW : IF_COMM_RCV_HIGH;
+
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
 	/* reset tx helper pointers and the rx mask */
@@ -791,14 +795,15 @@ static u32 c_can_adjust_pending(u32 pend)
 	return pend & ~((1 << lasts) - 1);
 }
 
-static inline void c_can_rx_object_get(struct net_device *dev, u32 obj)
+static inline void c_can_rx_object_get(struct net_device *dev,
+				       struct c_can_priv *priv, u32 obj)
 {
 #ifdef CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING
 	if (obj < C_CAN_MSG_RX_LOW_LAST)
 		c_can_object_get(dev, IF_RX, obj, IF_COMM_RCV_LOW);
 	else
 #endif
-		c_can_object_get(dev, IF_RX, obj, IF_COMM_RCV_HIGH);
+		c_can_object_get(dev, IF_RX, obj, priv->comm_rcv_high);
 }
 
 static inline void c_can_rx_finalize(struct net_device *dev,
@@ -813,6 +818,8 @@ static inline void c_can_rx_finalize(struct net_device *dev,
 		c_can_activate_all_lower_rx_msg_obj(dev, IF_RX);
 	}
 #endif
+	if (priv->type != BOSCH_D_CAN)
+		c_can_object_get(dev, IF_RX, obj, IF_COMM_CLR_NEWDAT);
 }
 
 static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
@@ -823,7 +830,7 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
 	while ((obj = ffs(pend)) && quota > 0) {
 		pend &= ~BIT(obj - 1);
 
-		c_can_rx_object_get(dev, obj);
+		c_can_rx_object_get(dev, priv, obj);
 		ctrl = priv->read_reg(priv, C_CAN_IFACE(MSGCTRL_REG, IF_RX));
 
 		if (ctrl & IF_MCONT_MSGLST) {
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index cd91960..792944c 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -198,6 +198,7 @@ struct c_can_priv {
 	u32 __iomem *raminit_ctrlreg;
 	unsigned int instance;
 	void (*raminit) (const struct c_can_priv *priv, bool enable);
+	u32 comm_rcv_high;
 	u32 rxmasked;
 	u32 dlc[C_CAN_MSG_OBJ_TX_NUM];
 };
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 13/26] can: c_can: Cleanup irq enable/disable
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (11 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 12/26] can: c_can: Work around C_CAN RX wreckage Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 14/26] can: c_can: Cleanup c_can_read_msg_object() Marc Kleine-Budde
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 37 ++++++++++++-------------------------
 1 file changed, 12 insertions(+), 25 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 5d43c5a..562faef 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -60,6 +60,8 @@
 #define CONTROL_IE		BIT(1)
 #define CONTROL_INIT		BIT(0)
 
+#define CONTROL_IRQMSK		(CONTROL_EIE | CONTROL_IE | CONTROL_SIE)
+
 /* test register */
 #define TEST_RX			BIT(7)
 #define TEST_TX1		BIT(6)
@@ -146,13 +148,6 @@
 #define IF_RX			0
 #define IF_TX			1
 
-/* status interrupt */
-#define STATUS_INTERRUPT	0x8000
-
-/* global interrupt masks */
-#define ENABLE_ALL_INTERRUPTS	1
-#define DISABLE_ALL_INTERRUPTS	0
-
 /* minimum timeout for checking BUSY status */
 #define MIN_TIMEOUT_VALUE	6
 
@@ -246,18 +241,14 @@ static u32 c_can_read_reg32(struct c_can_priv *priv, enum reg index)
 	return val;
 }
 
-static void c_can_enable_all_interrupts(struct c_can_priv *priv,
-						int enable)
+static void c_can_irq_control(struct c_can_priv *priv, bool enable)
 {
-	unsigned int cntrl_save = priv->read_reg(priv,
-						C_CAN_CTRL_REG);
+	u32 ctrl = priv->read_reg(priv,	C_CAN_CTRL_REG) & ~CONTROL_IRQMSK;
 
 	if (enable)
-		cntrl_save |= (CONTROL_SIE | CONTROL_EIE | CONTROL_IE);
-	else
-		cntrl_save &= ~(CONTROL_EIE | CONTROL_IE | CONTROL_SIE);
+		ctrl |= CONTROL_IRQMSK;
 
-	priv->write_reg(priv, C_CAN_CTRL_REG, cntrl_save);
+	priv->write_reg(priv, C_CAN_CTRL_REG, ctrl);
 }
 
 static inline int c_can_msg_obj_is_busy(struct c_can_priv *priv, int iface)
@@ -664,10 +655,7 @@ static void c_can_stop(struct net_device *dev)
 {
 	struct c_can_priv *priv = netdev_priv(dev);
 
-	/* disable all interrupts */
-	c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
-
-	/* set the state as STOPPED */
+	c_can_irq_control(priv, false);
 	priv->can.state = CAN_STATE_STOPPED;
 }
 
@@ -682,8 +670,7 @@ static int c_can_set_mode(struct net_device *dev, enum can_mode mode)
 		if (err)
 			return err;
 		netif_wake_queue(dev);
-		/* enable status change, error and module interrupts */
-		c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
+		c_can_irq_control(priv, true);
 		break;
 	default:
 		return -EOPNOTSUPP;
@@ -1144,7 +1131,7 @@ end:
 		napi_complete(napi);
 		/* enable all IRQs if we are not in bus off state */
 		if (priv->can.state != CAN_STATE_BUS_OFF)
-			c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
+			c_can_irq_control(priv, true);
 	}
 
 	return work_done;
@@ -1159,7 +1146,7 @@ static irqreturn_t c_can_isr(int irq, void *dev_id)
 		return IRQ_NONE;
 
 	/* disable all interrupts and schedule the NAPI */
-	c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
+	c_can_irq_control(priv, false);
 	napi_schedule(&priv->napi);
 
 	return IRQ_HANDLED;
@@ -1197,7 +1184,7 @@ static int c_can_open(struct net_device *dev)
 
 	napi_enable(&priv->napi);
 	/* enable status change, error and module interrupts */
-	c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
+	c_can_irq_control(priv, true);
 	netif_start_queue(dev);
 
 	return 0;
@@ -1324,7 +1311,7 @@ int c_can_power_up(struct net_device *dev)
 
 	ret = c_can_start(dev);
 	if (!ret)
-		c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
+		c_can_irq_control(priv, true);
 
 	return ret;
 }
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 14/26] can: c_can: Cleanup c_can_read_msg_object()
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (12 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 13/26] can: c_can: Cleanup irq enable/disable Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 15/26] can: c_can: Cleanup setup of receive buffers Marc Kleine-Budde
                   ` (13 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 32 +++++++++++++++-----------------
 1 file changed, 15 insertions(+), 17 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 562faef..d0daef8 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -380,15 +380,13 @@ static int c_can_handle_lost_msg_obj(struct net_device *dev,
 	return 1;
 }
 
-static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl)
+static int c_can_read_msg_object(struct net_device *dev, int iface, u32 ctrl)
 {
-	u16 flags, data;
-	int i;
-	unsigned int val;
-	struct c_can_priv *priv = netdev_priv(dev);
 	struct net_device_stats *stats = &dev->stats;
-	struct sk_buff *skb;
+	struct c_can_priv *priv = netdev_priv(dev);
 	struct can_frame *frame;
+	struct sk_buff *skb;
+	u32 arb, data;
 
 	skb = alloc_can_skb(dev, &frame);
 	if (!skb) {
@@ -398,21 +396,21 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl)
 
 	frame->can_dlc = get_can_dlc(ctrl & 0x0F);
 
-	flags =	priv->read_reg(priv, C_CAN_IFACE(ARB2_REG, iface));
-	val = priv->read_reg(priv, C_CAN_IFACE(ARB1_REG, iface)) |
-		(flags << 16);
+	arb = priv->read_reg(priv, C_CAN_IFACE(ARB1_REG, iface));
+	arb |= priv->read_reg(priv, C_CAN_IFACE(ARB2_REG, iface)) << 16;
 
-	if (flags & IF_ARB_MSGXTD)
-		frame->can_id = (val & CAN_EFF_MASK) | CAN_EFF_FLAG;
+	if (arb & (IF_ARB_MSGXTD << 16))
+		frame->can_id = (arb & CAN_EFF_MASK) | CAN_EFF_FLAG;
 	else
-		frame->can_id = (val >> 18) & CAN_SFF_MASK;
+		frame->can_id = (arb >> 18) & CAN_SFF_MASK;
 
-	if (flags & IF_ARB_TRANSMIT)
+	if (arb & (IF_ARB_TRANSMIT << 16)) {
 		frame->can_id |= CAN_RTR_FLAG;
-	else {
-		for (i = 0; i < frame->can_dlc; i += 2) {
-			data = priv->read_reg(priv,
-				C_CAN_IFACE(DATA1_REG, iface) + i / 2);
+	} else {
+		int i, dreg = C_CAN_IFACE(DATA1_REG, iface);
+
+		for (i = 0; i < frame->can_dlc; i += 2, dreg ++) {
+			data = priv->read_reg(priv, dreg);
 			frame->data[i] = data;
 			frame->data[i + 1] = data >> 8;
 		}
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 15/26] can: c_can: Cleanup setup of receive buffers
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (13 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 14/26] can: c_can: Cleanup c_can_read_msg_object() Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 16/26] can: c_can: Cleanup c_can_inval_msg_object() Marc Kleine-Budde
                   ` (12 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 38 +++++++++++++++++---------------------
 1 file changed, 17 insertions(+), 21 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index d0daef8..e4eaa84 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -125,6 +125,10 @@
 /* For the high buffers we clear the interrupt bit and newdat */
 #define IF_COMM_RCV_HIGH	(IF_COMM_RCV_LOW | IF_COMM_CLR_NEWDAT)
 
+
+/* Receive setup of message objects */
+#define IF_COMM_RCV_SETUP	(IF_COMM_MASK | IF_COMM_ARB | IF_COMM_CONTROL)
+
 /* IFx arbitration */
 #define IF_ARB_MSGVAL		BIT(15)
 #define IF_ARB_MSGXTD		BIT(14)
@@ -142,6 +146,9 @@
 #define IF_MCONT_EOB		BIT(7)
 #define IF_MCONT_DLC_MASK	0xf
 
+#define IF_MCONT_RCV		(IF_MCONT_RXIE | IF_MCONT_UMASK)
+#define IF_MCONT_RCV_EOB	(IF_MCONT_RCV | IF_MCONT_EOB)
+
 /*
  * Use IF1 for RX and IF2 for TX
  */
@@ -424,30 +431,20 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, u32 ctrl)
 }
 
 static void c_can_setup_receive_object(struct net_device *dev, int iface,
-					int objno, unsigned int mask,
-					unsigned int id, unsigned int mcont)
+				       u32 obj, u32 mask, u32 id, u32 mcont)
 {
 	struct c_can_priv *priv = netdev_priv(dev);
 
-	priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface),
-			IFX_WRITE_LOW_16BIT(mask));
-
-	/* According to C_CAN documentation, the reserved bit
-	 * in IFx_MASK2 register is fixed 1
-	 */
-	priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface),
-			IFX_WRITE_HIGH_16BIT(mask) | BIT(13));
+	mask |= BIT(29);
+	priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface), mask);
+	priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface), mask >> 16);
 
-	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface),
-			IFX_WRITE_LOW_16BIT(id));
-	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface),
-			(IF_ARB_MSGVAL | IFX_WRITE_HIGH_16BIT(id)));
+	id |= IF_ARB_MSGVAL << 16;
+	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), id);
+	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), id >> 16);
 
 	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), mcont);
-	c_can_object_put(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST);
-
-	netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno,
-			c_can_read_reg32(priv, C_CAN_MSGVAL1_REG));
+	c_can_object_put(dev, iface, obj, IF_COMM_RCV_SETUP);
 }
 
 static void c_can_inval_msg_object(struct net_device *dev, int iface, int objno)
@@ -581,11 +578,10 @@ static void c_can_configure_msg_objects(struct net_device *dev)
 
 	/* setup receive message objects */
 	for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++)
-		c_can_setup_receive_object(dev, IF_RX, i, 0, 0,
-					   IF_MCONT_RXIE | IF_MCONT_UMASK);
+		c_can_setup_receive_object(dev, IF_RX, i, 0, 0, IF_MCONT_RCV);
 
 	c_can_setup_receive_object(dev, IF_RX, C_CAN_MSG_OBJ_RX_LAST, 0, 0,
-			IF_MCONT_EOB | IF_MCONT_RXIE | IF_MCONT_UMASK);
+				   IF_MCONT_RCV_EOB);
 }
 
 /*
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 16/26] can: c_can: Cleanup c_can_inval_msg_object()
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (14 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 15/26] can: c_can: Cleanup setup of receive buffers Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 17/26] can: c_can: Cleanup c_can_msg_obj_put/get() Marc Kleine-Budde
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index e4eaa84..bf3aed4 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -129,6 +129,9 @@
 /* Receive setup of message objects */
 #define IF_COMM_RCV_SETUP	(IF_COMM_MASK | IF_COMM_ARB | IF_COMM_CONTROL)
 
+/* Invalidation of message objects */
+#define IF_COMM_INVAL		(IF_COMM_ARB | IF_COMM_CONTROL)
+
 /* IFx arbitration */
 #define IF_ARB_MSGVAL		BIT(15)
 #define IF_ARB_MSGXTD		BIT(14)
@@ -447,7 +450,7 @@ static void c_can_setup_receive_object(struct net_device *dev, int iface,
 	c_can_object_put(dev, iface, obj, IF_COMM_RCV_SETUP);
 }
 
-static void c_can_inval_msg_object(struct net_device *dev, int iface, int objno)
+static void c_can_inval_msg_object(struct net_device *dev, int iface, int obj)
 {
 	struct c_can_priv *priv = netdev_priv(dev);
 
@@ -455,10 +458,7 @@ static void c_can_inval_msg_object(struct net_device *dev, int iface, int objno)
 	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), 0);
 	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0);
 
-	c_can_object_put(dev, iface, objno, IF_COMM_ARB | IF_COMM_CONTROL);
-
-	netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno,
-			c_can_read_reg32(priv, C_CAN_MSGVAL1_REG));
+	c_can_object_put(dev, iface, obj, IF_COMM_INVAL);
 }
 
 static inline int c_can_is_next_tx_obj_busy(struct c_can_priv *priv, int objno)
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 17/26] can: c_can: Cleanup c_can_msg_obj_put/get()
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (15 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 16/26] can: c_can: Cleanup c_can_inval_msg_object() Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 18/26] can: c_can: Cleanup c_can_write_msg_object() Marc Kleine-Budde
                   ` (10 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

Sigh!

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 60 ++++++++++++-------------------------------
 1 file changed, 16 insertions(+), 44 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index bf3aed4..c654efb 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -261,61 +261,33 @@ static void c_can_irq_control(struct c_can_priv *priv, bool enable)
 	priv->write_reg(priv, C_CAN_CTRL_REG, ctrl);
 }
 
-static inline int c_can_msg_obj_is_busy(struct c_can_priv *priv, int iface)
+static void c_can_obj_update(struct net_device *dev, int iface, u32 cmd, u32 obj)
 {
-	int count = MIN_TIMEOUT_VALUE;
+	struct c_can_priv *priv = netdev_priv(dev);
+	int cnt, reg = C_CAN_IFACE(COMREQ_REG, iface);
+
+	priv->write_reg(priv, reg + 1, cmd);
+	priv->write_reg(priv, reg, obj);
 
-	while (count && priv->read_reg(priv,
-				C_CAN_IFACE(COMREQ_REG, iface)) &
-				IF_COMR_BUSY) {
-		count--;
+	for (cnt = MIN_TIMEOUT_VALUE; cnt; cnt--) {
+		if (!(priv->read_reg(priv, reg) & IF_COMR_BUSY))
+			return;
 		udelay(1);
 	}
+	netdev_err(dev, "Updating object timed out\n");
 
-	if (!count)
-		return 1;
-
-	return 0;
 }
 
-static inline void c_can_object_get(struct net_device *dev,
-					int iface, int objno, int mask)
+static inline void c_can_object_get(struct net_device *dev, int iface,
+				    u32 obj, u32 cmd)
 {
-	struct c_can_priv *priv = netdev_priv(dev);
-
-	/*
-	 * As per specs, after writting the message object number in the
-	 * IF command request register the transfer b/w interface
-	 * register and message RAM must be complete in 6 CAN-CLK
-	 * period.
-	 */
-	priv->write_reg(priv, C_CAN_IFACE(COMMSK_REG, iface),
-			IFX_WRITE_LOW_16BIT(mask));
-	priv->write_reg(priv, C_CAN_IFACE(COMREQ_REG, iface),
-			IFX_WRITE_LOW_16BIT(objno));
-
-	if (c_can_msg_obj_is_busy(priv, iface))
-		netdev_err(dev, "timed out in object get\n");
+	c_can_obj_update(dev, iface, cmd, obj);
 }
 
-static inline void c_can_object_put(struct net_device *dev,
-					int iface, int objno, int mask)
+static inline void c_can_object_put(struct net_device *dev, int iface,
+				    u32 obj, u32 cmd)
 {
-	struct c_can_priv *priv = netdev_priv(dev);
-
-	/*
-	 * As per specs, after writting the message object number in the
-	 * IF command request register the transfer b/w interface
-	 * register and message RAM must be complete in 6 CAN-CLK
-	 * period.
-	 */
-	priv->write_reg(priv, C_CAN_IFACE(COMMSK_REG, iface),
-			(IF_COMM_WR | IFX_WRITE_LOW_16BIT(mask)));
-	priv->write_reg(priv, C_CAN_IFACE(COMREQ_REG, iface),
-			IFX_WRITE_LOW_16BIT(objno));
-
-	if (c_can_msg_obj_is_busy(priv, iface))
-		netdev_err(dev, "timed out in object put\n");
+	c_can_obj_update(dev, iface, cmd | IF_COMM_WR, obj);
 }
 
 static void c_can_write_msg_object(struct net_device *dev,
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 18/26] can: c_can: Cleanup c_can_write_msg_object()
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (16 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 17/26] can: c_can: Cleanup c_can_msg_obj_put/get() Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 19/26] can: c_can: Use proper u32 variables in c_can_write_msg_object() Marc Kleine-Budde
                   ` (9 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

Remove the MASK from the TX transfer side.

Make the code readable and get rid of the annoying IFX_WRITE_XXX_16BIT
macros which are just obfuscating the code.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 49 +++++++++++++++++++++----------------------
 drivers/net/can/c_can/c_can.h |  8 -------
 2 files changed, 24 insertions(+), 33 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index c654efb..7c60e6a 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -113,9 +113,11 @@
 #define IF_COMM_CLR_NEWDAT	IF_COMM_TXRQST
 #define IF_COMM_DATAA		BIT(1)
 #define IF_COMM_DATAB		BIT(0)
-#define IF_COMM_ALL		(IF_COMM_MASK | IF_COMM_ARB | \
-				IF_COMM_CONTROL | IF_COMM_TXRQST | \
-				IF_COMM_DATAA | IF_COMM_DATAB)
+
+/* TX buffer setup */
+#define IF_COMM_TX		(IF_COMM_ARB | IF_COMM_CONTROL | \
+				 IF_COMM_TXRQST |		 \
+				 IF_COMM_DATAA | IF_COMM_DATAB)
 
 /* For the low buffers we clear the interrupt bit, but keep newdat */
 #define IF_COMM_RCV_LOW		(IF_COMM_MASK | IF_COMM_ARB | \
@@ -152,6 +154,8 @@
 #define IF_MCONT_RCV		(IF_MCONT_RXIE | IF_MCONT_UMASK)
 #define IF_MCONT_RCV_EOB	(IF_MCONT_RCV | IF_MCONT_EOB)
 
+#define IF_MCONT_TX		(IF_MCONT_TXIE | IF_MCONT_EOB)
+
 /*
  * Use IF1 for RX and IF2 for TX
  */
@@ -290,40 +294,35 @@ static inline void c_can_object_put(struct net_device *dev, int iface,
 	c_can_obj_update(dev, iface, cmd | IF_COMM_WR, obj);
 }
 
-static void c_can_write_msg_object(struct net_device *dev,
-			int iface, struct can_frame *frame, int objno)
+static void c_can_write_msg_object(struct net_device *dev, int iface,
+				   struct can_frame *frame, int obj)
 {
-	int i;
-	u16 flags = 0;
-	unsigned int id;
 	struct c_can_priv *priv = netdev_priv(dev);
-
-	if (!(frame->can_id & CAN_RTR_FLAG))
-		flags |= IF_ARB_TRANSMIT;
+	u16 ctrl = IF_MCONT_TX | frame->can_dlc;
+	u32 arb = IF_ARB_MSGVAL << 16;
+	int i;
 
 	if (frame->can_id & CAN_EFF_FLAG) {
-		id = frame->can_id & CAN_EFF_MASK;
-		flags |= IF_ARB_MSGXTD;
-	} else
-		id = ((frame->can_id & CAN_SFF_MASK) << 18);
+		arb |= frame->can_id & CAN_EFF_MASK;
+		arb |= IF_ARB_MSGXTD << 16;
+	} else {
+		arb |= (frame->can_id & CAN_SFF_MASK) << 18;
+	}
 
-	flags |= IF_ARB_MSGVAL;
+	if (!(frame->can_id & CAN_RTR_FLAG))
+		arb |= IF_ARB_TRANSMIT << 16;
+
+	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), arb);
+	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), arb >> 16);
 
-	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface),
-				IFX_WRITE_LOW_16BIT(id));
-	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), flags |
-				IFX_WRITE_HIGH_16BIT(id));
+	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl);
 
 	for (i = 0; i < frame->can_dlc; i += 2) {
 		priv->write_reg(priv, C_CAN_IFACE(DATA1_REG, iface) + i / 2,
 				frame->data[i] | (frame->data[i + 1] << 8));
 	}
 
-	/* enable interrupt for this message object */
-	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface),
-			IF_MCONT_TXIE | IF_MCONT_TXRQST | IF_MCONT_EOB |
-			frame->can_dlc);
-	c_can_object_put(dev, iface, objno, IF_COMM_ALL);
+	c_can_object_put(dev, iface, obj, IF_COMM_TX);
 }
 
 static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev,
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index 792944c..d9f59cc4 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -22,14 +22,6 @@
 #ifndef C_CAN_H
 #define C_CAN_H
 
-/*
- * IFx register masks:
- * allow easy operation on 16-bit registers when the
- * argument is 32-bit instead
- */
-#define IFX_WRITE_LOW_16BIT(x)	((x) & 0xFFFF)
-#define IFX_WRITE_HIGH_16BIT(x)	(((x) & 0xFFFF0000) >> 16)
-
 /* message object split */
 #define C_CAN_NO_OF_OBJECTS	32
 #define C_CAN_MSG_OBJ_RX_NUM	16
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 19/26] can: c_can: Use proper u32 variables in c_can_write_msg_object()
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (17 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 18/26] can: c_can: Cleanup c_can_write_msg_object() Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 20/26] can: c_can: Remove tx locking Marc Kleine-Budde
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

Instead of obfuscating the code by artificial 16 bit splits use the
proper 32 bit assignments and split the result when writing to the
interface.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 7c60e6a..61fde41 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -135,9 +135,9 @@
 #define IF_COMM_INVAL		(IF_COMM_ARB | IF_COMM_CONTROL)
 
 /* IFx arbitration */
-#define IF_ARB_MSGVAL		BIT(15)
-#define IF_ARB_MSGXTD		BIT(14)
-#define IF_ARB_TRANSMIT		BIT(13)
+#define IF_ARB_MSGVAL		BIT(31)
+#define IF_ARB_MSGXTD		BIT(30)
+#define IF_ARB_TRANSMIT		BIT(29)
 
 /* IFx message control */
 #define IF_MCONT_NEWDAT		BIT(15)
@@ -299,18 +299,18 @@ static void c_can_write_msg_object(struct net_device *dev, int iface,
 {
 	struct c_can_priv *priv = netdev_priv(dev);
 	u16 ctrl = IF_MCONT_TX | frame->can_dlc;
-	u32 arb = IF_ARB_MSGVAL << 16;
+	u32 arb = IF_ARB_MSGVAL;
 	int i;
 
 	if (frame->can_id & CAN_EFF_FLAG) {
 		arb |= frame->can_id & CAN_EFF_MASK;
-		arb |= IF_ARB_MSGXTD << 16;
+		arb |= IF_ARB_MSGXTD;
 	} else {
 		arb |= (frame->can_id & CAN_SFF_MASK) << 18;
 	}
 
 	if (!(frame->can_id & CAN_RTR_FLAG))
-		arb |= IF_ARB_TRANSMIT << 16;
+		arb |= IF_ARB_TRANSMIT;
 
 	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), arb);
 	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), arb >> 16);
@@ -380,12 +380,12 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, u32 ctrl)
 	arb = priv->read_reg(priv, C_CAN_IFACE(ARB1_REG, iface));
 	arb |= priv->read_reg(priv, C_CAN_IFACE(ARB2_REG, iface)) << 16;
 
-	if (arb & (IF_ARB_MSGXTD << 16))
+	if (arb & IF_ARB_MSGXTD)
 		frame->can_id = (arb & CAN_EFF_MASK) | CAN_EFF_FLAG;
 	else
 		frame->can_id = (arb >> 18) & CAN_SFF_MASK;
 
-	if (arb & (IF_ARB_TRANSMIT << 16)) {
+	if (arb & IF_ARB_TRANSMIT) {
 		frame->can_id |= CAN_RTR_FLAG;
 	} else {
 		int i, dreg = C_CAN_IFACE(DATA1_REG, iface);
@@ -413,7 +413,7 @@ static void c_can_setup_receive_object(struct net_device *dev, int iface,
 	priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface), mask);
 	priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface), mask >> 16);
 
-	id |= IF_ARB_MSGVAL << 16;
+	id |= IF_ARB_MSGVAL;
 	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), id);
 	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), id >> 16);
 
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 20/26] can: c_can: Remove tx locking
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (18 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 19/26] can: c_can: Use proper u32 variables in c_can_write_msg_object() Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 21/26] can: c_can: Speed up tx buffer invalidation Marc Kleine-Budde
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

Mark suggested to use one IF for the softirq and the other for the
xmit function to avoid the xmit lock.

That requires to write the frame into the interface first, then handle
the echo skb and store the dlc before committing the TX request to the
message ram.

We use an atomic to handle the active buffers instead of reading the
MSGVAL register as thats way faster especially on PCH/x86.

Suggested-by: Mark <mark5@del-llc.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 127 ++++++++++++++----------------------------
 drivers/net/can/c_can/c_can.h |   8 +--
 2 files changed, 43 insertions(+), 92 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 61fde41..99d36bf 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -237,24 +237,6 @@ static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable)
 		priv->raminit(priv, enable);
 }
 
-static inline int get_tx_next_msg_obj(const struct c_can_priv *priv)
-{
-	return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) +
-			C_CAN_MSG_OBJ_TX_FIRST;
-}
-
-static inline int get_tx_echo_msg_obj(int txecho)
-{
-	return (txecho & C_CAN_NEXT_MSG_OBJ_MASK) + C_CAN_MSG_OBJ_TX_FIRST;
-}
-
-static u32 c_can_read_reg32(struct c_can_priv *priv, enum reg index)
-{
-	u32 val = priv->read_reg(priv, index);
-	val |= ((u32) priv->read_reg(priv, index + 1)) << 16;
-	return val;
-}
-
 static void c_can_irq_control(struct c_can_priv *priv, bool enable)
 {
 	u32 ctrl = priv->read_reg(priv,	C_CAN_CTRL_REG) & ~CONTROL_IRQMSK;
@@ -294,8 +276,8 @@ static inline void c_can_object_put(struct net_device *dev, int iface,
 	c_can_obj_update(dev, iface, cmd | IF_COMM_WR, obj);
 }
 
-static void c_can_write_msg_object(struct net_device *dev, int iface,
-				   struct can_frame *frame, int obj)
+static void c_can_setup_tx_object(struct net_device *dev, int iface,
+				  struct can_frame *frame, int obj)
 {
 	struct c_can_priv *priv = netdev_priv(dev);
 	u16 ctrl = IF_MCONT_TX | frame->can_dlc;
@@ -321,8 +303,6 @@ static void c_can_write_msg_object(struct net_device *dev, int iface,
 		priv->write_reg(priv, C_CAN_IFACE(DATA1_REG, iface) + i / 2,
 				frame->data[i] | (frame->data[i + 1] << 8));
 	}
-
-	c_can_object_put(dev, iface, obj, IF_COMM_TX);
 }
 
 static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev,
@@ -432,47 +412,38 @@ static void c_can_inval_msg_object(struct net_device *dev, int iface, int obj)
 	c_can_object_put(dev, iface, obj, IF_COMM_INVAL);
 }
 
-static inline int c_can_is_next_tx_obj_busy(struct c_can_priv *priv, int objno)
-{
-	int val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG);
-
-	/*
-	 * as transmission request register's bit n-1 corresponds to
-	 * message object n, we need to handle the same properly.
-	 */
-	if (val & (1 << (objno - 1)))
-		return 1;
-
-	return 0;
-}
-
 static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
-					struct net_device *dev)
+				    struct net_device *dev)
 {
-	u32 msg_obj_no;
-	struct c_can_priv *priv = netdev_priv(dev);
 	struct can_frame *frame = (struct can_frame *)skb->data;
+	struct c_can_priv *priv = netdev_priv(dev);
+	u32 idx, obj;
 
 	if (can_dropped_invalid_skb(dev, skb))
 		return NETDEV_TX_OK;
-
-	spin_lock_bh(&priv->xmit_lock);
-	msg_obj_no = get_tx_next_msg_obj(priv);
-
-	/* prepare message object for transmission */
-	c_can_write_msg_object(dev, IF_TX, frame, msg_obj_no);
-	priv->dlc[msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST] = frame->can_dlc;
-	can_put_echo_skb(skb, dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
-
 	/*
-	 * we have to stop the queue in case of a wrap around or
-	 * if the next TX message object is still in use
+	 * This is not a FIFO. C/D_CAN sends out the buffers
+	 * prioritized. The lowest buffer number wins.
 	 */
-	priv->tx_next++;
-	if (c_can_is_next_tx_obj_busy(priv, get_tx_next_msg_obj(priv)) ||
-			(priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) == 0)
+	idx = fls(atomic_read(&priv->tx_active));
+	obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
+
+	/* If this is the last buffer, stop the xmit queue */
+	if (idx == C_CAN_MSG_OBJ_TX_NUM - 1)
 		netif_stop_queue(dev);
-	spin_unlock_bh(&priv->xmit_lock);
+	/*
+	 * Store the message in the interface so we can call
+	 * can_put_echo_skb(). We must do this before we enable
+	 * transmit as we might race against do_tx().
+	 */
+	c_can_setup_tx_object(dev, IF_TX, frame, obj);
+	priv->dlc[idx] = frame->can_dlc;
+	can_put_echo_skb(skb, dev, idx);
+
+	/* Update the active bits */
+	atomic_add((1 << idx), &priv->tx_active);
+	/* Start transmission */
+	c_can_object_put(dev, IF_TX, obj, IF_COMM_TX);
 
 	return NETDEV_TX_OK;
 }
@@ -589,6 +560,10 @@ static int c_can_chip_config(struct net_device *dev)
 	/* set a `lec` value so that we can check for updates later */
 	priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
 
+	/* Clear all internal status */
+	atomic_set(&priv->tx_active, 0);
+	priv->rxmasked = 0;
+
 	/* set bittiming params */
 	return c_can_set_bittiming(dev);
 }
@@ -609,10 +584,6 @@ static int c_can_start(struct net_device *dev)
 
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
-	/* reset tx helper pointers and the rx mask */
-	priv->tx_next = priv->tx_echo = 0;
-	priv->rxmasked = 0;
-
 	return 0;
 }
 
@@ -671,42 +642,29 @@ static int c_can_get_berr_counter(const struct net_device *dev,
 	return err;
 }
 
-/*
- * priv->tx_echo holds the number of the oldest can_frame put for
- * transmission into the hardware, but not yet ACKed by the CAN tx
- * complete IRQ.
- *
- * We iterate from priv->tx_echo to priv->tx_next and check if the
- * packet has been transmitted, echo it back to the CAN framework.
- * If we discover a not yet transmitted packet, stop looking for more.
- */
 static void c_can_do_tx(struct net_device *dev)
 {
 	struct c_can_priv *priv = netdev_priv(dev);
 	struct net_device_stats *stats = &dev->stats;
-	u32 val, obj, pkts = 0, bytes = 0;
+	u32 idx, obj, pkts = 0, bytes = 0, pend, clr;
 
-	spin_lock_bh(&priv->xmit_lock);
+	clr = pend = priv->read_reg(priv, C_CAN_INTPND2_REG);
 
-	for (; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
-		obj = get_tx_echo_msg_obj(priv->tx_echo);
-		val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG);
-
-		if (val & (1 << (obj - 1)))
-			break;
-
-		can_get_echo_skb(dev, obj - C_CAN_MSG_OBJ_TX_FIRST);
-		bytes += priv->dlc[obj - C_CAN_MSG_OBJ_TX_FIRST];
+	while ((idx = ffs(pend))) {
+		idx--;
+		pend &= ~(1 << idx);
+		obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
+		c_can_inval_msg_object(dev, IF_RX, obj);
+		can_get_echo_skb(dev, idx);
+		bytes += priv->dlc[idx];
 		pkts++;
-		c_can_inval_msg_object(dev, IF_TX, obj);
 	}
 
-	/* restart queue if wrap-up or if queue stalled on last pkt */
-	if (((priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) != 0) ||
-			((priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) == 0))
-		netif_wake_queue(dev);
+	/* Clear the bits in the tx_active mask */
+	atomic_sub(clr, &priv->tx_active);
 
-	spin_unlock_bh(&priv->xmit_lock);
+	if (clr & (1 << (C_CAN_MSG_OBJ_TX_NUM - 1)))
+		netif_wake_queue(dev);
 
 	if (pkts) {
 		stats->tx_bytes += bytes;
@@ -1192,7 +1150,6 @@ struct net_device *alloc_c_can_dev(void)
 		return NULL;
 
 	priv = netdev_priv(dev);
-	spin_lock_init(&priv->xmit_lock);
 	netif_napi_add(dev, &priv->napi, c_can_poll, C_CAN_NAPI_WEIGHT);
 
 	priv->dev = dev;
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index d9f59cc4..a5f10a0 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -37,8 +37,6 @@
 
 #define C_CAN_MSG_OBJ_RX_SPLIT	9
 #define C_CAN_MSG_RX_LOW_LAST	(C_CAN_MSG_OBJ_RX_SPLIT - 1)
-
-#define C_CAN_NEXT_MSG_OBJ_MASK	(C_CAN_MSG_OBJ_TX_NUM - 1)
 #define RECEIVE_OBJECT_BITS	0x0000ffff
 
 enum reg {
@@ -175,16 +173,12 @@ struct c_can_priv {
 	struct napi_struct napi;
 	struct net_device *dev;
 	struct device *device;
-	spinlock_t xmit_lock;
-	int tx_object;
+	atomic_t tx_active;
 	int last_status;
 	u16 (*read_reg) (struct c_can_priv *priv, enum reg index);
 	void (*write_reg) (struct c_can_priv *priv, enum reg index, u16 val);
 	void __iomem *base;
 	const u16 *regs;
-	unsigned long irq_flags; /* for request_irq() */
-	unsigned int tx_next;
-	unsigned int tx_echo;
 	void *priv;		/* for board-specific data */
 	enum c_can_dev_id type;
 	u32 __iomem *raminit_ctrlreg;
-- 
1.9.0.279.gdc9e3eb

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 21/26] can: c_can: Speed up tx buffer invalidation
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (19 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 20/26] can: c_can: Remove tx locking Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 22/26] can: c_can: use proper type for 'instance' Marc Kleine-Budde
                   ` (6 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Thomas Gleixner, Marc Kleine-Budde

From: Thomas Gleixner <tglx@linutronix.de>

It's suffcient to kill the TXIE bit in the message control register
even if the documentation of C and D CAN says that it's not allowed to
do that while MSGVAL is set. Reality tells a different story and this
change gives us another 2% of CPU back for not waiting on I/O.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.c | 54 +++++++++++++++++++++++++++++++------------
 drivers/net/can/c_can/c_can.h |  1 +
 2 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 99d36bf..a2ca820 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -276,11 +276,34 @@ static inline void c_can_object_put(struct net_device *dev, int iface,
 	c_can_obj_update(dev, iface, cmd | IF_COMM_WR, obj);
 }
 
+/*
+ * Note: According to documentation clearing TXIE while MSGVAL is set
+ * is not allowed, but works nicely on C/DCAN. And that lowers the I/O
+ * load significantly.
+ */
+static void c_can_inval_tx_object(struct net_device *dev, int iface, int obj)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0);
+	c_can_object_put(dev, iface, obj, IF_COMM_INVAL);
+}
+
+static void c_can_inval_msg_object(struct net_device *dev, int iface, int obj)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), 0);
+	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), 0);
+	c_can_inval_tx_object(dev, iface, obj);
+}
+
 static void c_can_setup_tx_object(struct net_device *dev, int iface,
-				  struct can_frame *frame, int obj)
+				  struct can_frame *frame, int idx)
 {
 	struct c_can_priv *priv = netdev_priv(dev);
 	u16 ctrl = IF_MCONT_TX | frame->can_dlc;
+	bool rtr = frame->can_id & CAN_RTR_FLAG;
 	u32 arb = IF_ARB_MSGVAL;
 	int i;
 
@@ -291,9 +314,20 @@ static void c_can_setup_tx_object(struct net_device *dev, int iface,
 		arb |= (frame->can_id & CAN_SFF_MASK) << 18;
 	}
 
-	if (!(frame->can_id & CAN_RTR_FLAG))
+	if (!rtr)
 		arb |= IF_ARB_TRANSMIT;
 
+	/*
+	 * If we change the DIR bit, we need to invalidate the buffer
+	 * first, i.e. clear the MSGVAL flag in the arbiter.
+	 */
+	if (rtr != (bool)test_bit(idx, &priv->tx_dir)) {
+		u32 obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
+
+		c_can_inval_msg_object(dev, iface, obj);
+		change_bit(idx, &priv->tx_dir);
+	}
+
 	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), arb);
 	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), arb >> 16);
 
@@ -401,17 +435,6 @@ static void c_can_setup_receive_object(struct net_device *dev, int iface,
 	c_can_object_put(dev, iface, obj, IF_COMM_RCV_SETUP);
 }
 
-static void c_can_inval_msg_object(struct net_device *dev, int iface, int obj)
-{
-	struct c_can_priv *priv = netdev_priv(dev);
-
-	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), 0);
-	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), 0);
-	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0);
-
-	c_can_object_put(dev, iface, obj, IF_COMM_INVAL);
-}
-
 static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
 				    struct net_device *dev)
 {
@@ -436,7 +459,7 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
 	 * can_put_echo_skb(). We must do this before we enable
 	 * transmit as we might race against do_tx().
 	 */
-	c_can_setup_tx_object(dev, IF_TX, frame, obj);
+	c_can_setup_tx_object(dev, IF_TX, frame, idx);
 	priv->dlc[idx] = frame->can_dlc;
 	can_put_echo_skb(skb, dev, idx);
 
@@ -563,6 +586,7 @@ static int c_can_chip_config(struct net_device *dev)
 	/* Clear all internal status */
 	atomic_set(&priv->tx_active, 0);
 	priv->rxmasked = 0;
+	priv->tx_dir = 0;
 
 	/* set bittiming params */
 	return c_can_set_bittiming(dev);
@@ -654,7 +678,7 @@ static void c_can_do_tx(struct net_device *dev)
 		idx--;
 		pend &= ~(1 << idx);
 		obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
-		c_can_inval_msg_object(dev, IF_RX, obj);
+		c_can_inval_tx_object(dev, IF_RX, obj);
 		can_get_echo_skb(dev, idx);
 		bytes += priv->dlc[idx];
 		pkts++;
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index a5f10a0..e7de2b9 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -174,6 +174,7 @@ struct c_can_priv {
 	struct net_device *dev;
 	struct device *device;
 	atomic_t tx_active;
+	unsigned long tx_dir;
 	int last_status;
 	u16 (*read_reg) (struct c_can_priv *priv, enum reg index);
 	void (*write_reg) (struct c_can_priv *priv, enum reg index, u16 val);
-- 
1.9.0.279.gdc9e3eb

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 22/26] can: c_can: use proper type for 'instance'
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (20 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 21/26] can: c_can: Speed up tx buffer invalidation Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 23/26] can: c_can_pci: enable PCI bus master only for MSI Marc Kleine-Budde
                   ` (5 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Wolfram Sang, Marc Kleine-Budde

From: Wolfram Sang <wsa@sang-engineering.com>

Commit 6439fbce1075 (can: c_can: fix error checking of priv->instance in
probe()) found the warning but applied a suboptimal solution. Since, both
pdev->id and of_alias_get_id() return integers, it makes sense to convert the
variable to an integer and avoid the cast.

Signed-off-by: Wolfram Sang <wsa@sang-engineering.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can.h          | 2 +-
 drivers/net/can/c_can/c_can_platform.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index e7de2b9..c56f1b1 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -183,7 +183,7 @@ struct c_can_priv {
 	void *priv;		/* for board-specific data */
 	enum c_can_dev_id type;
 	u32 __iomem *raminit_ctrlreg;
-	unsigned int instance;
+	int instance;
 	void (*raminit) (const struct c_can_priv *priv, bool enable);
 	u32 comm_rcv_high;
 	u32 rxmasked;
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index 806d927..1df0b32 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -222,7 +222,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
 
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 		priv->raminit_ctrlreg = devm_ioremap_resource(&pdev->dev, res);
-		if (IS_ERR(priv->raminit_ctrlreg) || (int)priv->instance < 0)
+		if (IS_ERR(priv->raminit_ctrlreg) || priv->instance < 0)
 			dev_info(&pdev->dev, "control memory is not used for raminit\n");
 		else
 			priv->raminit = c_can_hw_raminit;
-- 
1.9.0.279.gdc9e3eb

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 23/26] can: c_can_pci: enable PCI bus master only for MSI
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (21 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 22/26] can: c_can: use proper type for 'instance' Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 24/26] can: sja1000_isa: add locking for indirect register access mode Marc Kleine-Budde
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Wolfgang Grandegger, Marc Kleine-Budde

From: Wolfgang Grandegger <wg@grandegger.com>

Coverity complains that c_can_pci_probe() calls pci_enable_msi() without
checking the result:

CID 712278 (#1 of 1): Unchecked return value (CHECKED_RETURN) 3. check_return:
Calling pci_enable_msi_block without checking return value (as is done
elsewhere 88 out of 105 times).
 88        pci_enable_msi(pdev);

This is CID 712278.

Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
Reported-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/c_can/c_can_pci.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c
index 1b7ff40..fe5f630 100644
--- a/drivers/net/can/c_can/c_can_pci.c
+++ b/drivers/net/can/c_can/c_can_pci.c
@@ -84,8 +84,11 @@ static int c_can_pci_probe(struct pci_dev *pdev,
 		goto out_disable_device;
 	}
 
-	pci_set_master(pdev);
-	pci_enable_msi(pdev);
+	ret = pci_enable_msi(pdev);
+	if (!ret) {
+		dev_info(&pdev->dev, "MSI enabled\n");
+		pci_set_master(pdev);
+	}
 
 	addr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
 	if (!addr) {
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 24/26] can: sja1000_isa: add locking for indirect register access mode
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (22 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 23/26] can: c_can_pci: enable PCI bus master only for MSI Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 25/26] can: fix return value from can_get_bittiming() Marc Kleine-Budde
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Oliver Hartkopp, Marc Kleine-Budde

From: Oliver Hartkopp <socketcan@hartkopp.net>

When accessing the SJA1000 controller registers in the indirect access mode,
writing the register number and reading/writing the data has to be an atomic
attempt.

As the sja1000_isa driver is an old style driver with a fixed number of
instances the locking variable depends on the same index like all the other
configuration elements given on the module command line.

As a positive side effect dev->dev_id is populated by the instance index,
which was missing in 3e66d0138c05d9 ("can: populate netdev::dev_id for udev
discrimination").

Reported-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/sja1000/sja1000_isa.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c
index df136a2..014695d 100644
--- a/drivers/net/can/sja1000/sja1000_isa.c
+++ b/drivers/net/can/sja1000/sja1000_isa.c
@@ -46,6 +46,7 @@ static int clk[MAXDEV];
 static unsigned char cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
 static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
 static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
+static spinlock_t indirect_lock[MAXDEV];  /* lock for indirect access mode */
 
 module_param_array(port, ulong, NULL, S_IRUGO);
 MODULE_PARM_DESC(port, "I/O port number");
@@ -101,19 +102,26 @@ static void sja1000_isa_port_write_reg(const struct sja1000_priv *priv,
 static u8 sja1000_isa_port_read_reg_indirect(const struct sja1000_priv *priv,
 					     int reg)
 {
-	unsigned long base = (unsigned long)priv->reg_base;
+	unsigned long flags, base = (unsigned long)priv->reg_base;
+	u8 readval;
 
+	spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags);
 	outb(reg, base);
-	return inb(base + 1);
+	readval = inb(base + 1);
+	spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags);
+
+	return readval;
 }
 
 static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv,
 						int reg, u8 val)
 {
-	unsigned long base = (unsigned long)priv->reg_base;
+	unsigned long flags, base = (unsigned long)priv->reg_base;
 
+	spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags);
 	outb(reg, base);
 	outb(val, base + 1);
+	spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags);
 }
 
 static int sja1000_isa_probe(struct platform_device *pdev)
@@ -169,6 +177,7 @@ static int sja1000_isa_probe(struct platform_device *pdev)
 		if (iosize == SJA1000_IOSIZE_INDIRECT) {
 			priv->read_reg = sja1000_isa_port_read_reg_indirect;
 			priv->write_reg = sja1000_isa_port_write_reg_indirect;
+			spin_lock_init(&indirect_lock[idx]);
 		} else {
 			priv->read_reg = sja1000_isa_port_read_reg;
 			priv->write_reg = sja1000_isa_port_write_reg;
@@ -198,6 +207,7 @@ static int sja1000_isa_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
+	dev->dev_id = idx;
 
 	err = register_sja1000dev(dev);
 	if (err) {
-- 
1.9.0.279.gdc9e3eb

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 25/26] can: fix return value from can_get_bittiming()
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (23 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 24/26] can: sja1000_isa: add locking for indirect register access mode Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:00 ` [PATCH 26/26] can: slcan: Fix spinlock variant Marc Kleine-Budde
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Oliver Hartkopp, Marc Kleine-Budde

From: Oliver Hartkopp <socketcan@hartkopp.net>

When trying to set a data bitrate on non CAN FD devices the 'ip' tool
answers with:

	RTNETLINK answers: Unknown error 524

Rename '-ENOTSUPP' to '-EOPNOTSUPP' so that 'ip' answers correctly:

       RTNETLINK answers: Operation not supported

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/dev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index c7a2604..e318e87 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -256,7 +256,7 @@ static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt,
 
 	/* Check if the CAN device has bit-timing parameters */
 	if (!btc)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	/*
 	 * Depending on the given can_bittiming parameter structure the CAN
-- 
1.9.0.279.gdc9e3eb

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 26/26] can: slcan: Fix spinlock variant
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (24 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 25/26] can: fix return value from can_get_bittiming() Marc Kleine-Budde
@ 2014-04-24 22:00 ` Marc Kleine-Budde
  2014-04-24 22:04 ` pull-request: can 2014-04-24 Marc Kleine-Budde
  2014-04-26 16:31 ` David Miller
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Alexander Stein, Marc Kleine-Budde

From: Alexander Stein <alexander.stein@systec-electronic.com>

slc_xmit is called within softirq context and locks sl->lock, but
slcan_write_wakeup is not softirq context, so we need to use
spin_[un]lock_bh!
Detected using kernel lock debugging mechanism.

Signed-off-by: Alexander Stein <alexander.stein@systec-electronic.com>
Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/slcan.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index f5b16e0..dcf9196 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -322,13 +322,13 @@ static void slcan_write_wakeup(struct tty_struct *tty)
 	if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev))
 		return;
 
-	spin_lock(&sl->lock);
+	spin_lock_bh(&sl->lock);
 	if (sl->xleft <= 0)  {
 		/* Now serial buffer is almost free & we can start
 		 * transmission of another packet */
 		sl->dev->stats.tx_packets++;
 		clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-		spin_unlock(&sl->lock);
+		spin_unlock_bh(&sl->lock);
 		netif_wake_queue(sl->dev);
 		return;
 	}
@@ -336,7 +336,7 @@ static void slcan_write_wakeup(struct tty_struct *tty)
 	actual = tty->ops->write(tty, sl->xhead, sl->xleft);
 	sl->xleft -= actual;
 	sl->xhead += actual;
-	spin_unlock(&sl->lock);
+	spin_unlock_bh(&sl->lock);
 }
 
 /* Send a can_frame to a TTY queue. */
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: pull-request: can 2014-04-24
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (25 preceding siblings ...)
  2014-04-24 22:00 ` [PATCH 26/26] can: slcan: Fix spinlock variant Marc Kleine-Budde
@ 2014-04-24 22:04 ` Marc Kleine-Budde
  2014-04-26 16:31 ` David Miller
  27 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-04-24 22:04 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel

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

On 04/25/2014 12:00 AM, Marc Kleine-Budde wrote:
> Hello David,
> 
> this is a pull request for net/master, for the v3.15 release cycle, consisting
> of 26 patches.
> 
> Thomas Gleixner contributes 21 patches for the c_can driver, which address
> several shortcomings in the driver like hardware initialisation, concurrency,
> message ordering and poor performance. Two patches Oliver Hartkopp, one adds a
> missing lock to the sja1000_isa driver, the other one fixes the return value in
> the generic bit time configuration function. And finally a patch by Alexander
> Stein, that fixes the slcan driver to use the correct spinlock variant.

To make it 26 patches, I forgot to mention, Wolfgang Grandegger patch
for the c_can_pci driver, which enables the bus master only for MSI and
a patch by Wolfram Sang, which converts the 'instance' in the c_can
driver to the proper type.

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: 242 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: pull-request: can 2014-04-24
  2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
                   ` (26 preceding siblings ...)
  2014-04-24 22:04 ` pull-request: can 2014-04-24 Marc Kleine-Budde
@ 2014-04-26 16:31 ` David Miller
  27 siblings, 0 replies; 31+ messages in thread
From: David Miller @ 2014-04-26 16:31 UTC (permalink / raw)
  To: mkl; +Cc: netdev, linux-can, kernel

From: Marc Kleine-Budde <mkl@pengutronix.de>
Date: Fri, 25 Apr 2014 00:00:03 +0200

> this is a pull request for net/master, for the v3.15 release cycle, consisting
> of 26 patches.
> 
> Thomas Gleixner contributes 21 patches for the c_can driver, which address
> several shortcomings in the driver like hardware initialisation, concurrency,
> message ordering and poor performance. Two patches Oliver Hartkopp, one adds a
> missing lock to the sja1000_isa driver, the other one fixes the return value in
> the generic bit time configuration function. And finally a patch by Alexander
> Stein, that fixes the slcan driver to use the correct spinlock variant.

Pulled, thanks.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 02/26] can: c_can: Fix startup logic
  2014-04-24 22:00 ` [PATCH 02/26] can: c_can: Fix startup logic Marc Kleine-Budde
@ 2014-04-29  7:29   ` Yegor Yefremov
  2014-05-02 12:37     ` Marc Kleine-Budde
  0 siblings, 1 reply; 31+ messages in thread
From: Yegor Yefremov @ 2014-04-29  7:29 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: netdev, David Miller, linux-can, kernel, Thomas Gleixner

On Fri, Apr 25, 2014 at 12:00 AM, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
> From: Thomas Gleixner <tglx@linutronix.de>
>
> c_can_start() enables interrupts way too early. The first enabling
> happens when setting the control mode in c_can_chip_config() and then
> again at the end of the function.
>
> But that happens before napi_enable() and that means that an interrupt
> which comes in will disable interrupts again and call napi_schedule,
> which ignores the request and the later napi_enable() is not making
> thinks work either. So the interface is up with all device interrupts
> disabled.
>
> Move the device interrupt after napi_enable() and add it to the other
> callsites of c_can_start() in c_can_set_mode() and c_can_power_up()
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

Tested-by: Yegor Yefremov <yegorslists@googlemail.com>

> ---
>  drivers/net/can/c_can/c_can.c | 35 +++++++++++++++++------------------
>  1 file changed, 17 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
> index a5c8dcf..b1629a4 100644
> --- a/drivers/net/can/c_can/c_can.c
> +++ b/drivers/net/can/c_can/c_can.c
> @@ -612,30 +612,22 @@ static int c_can_chip_config(struct net_device *dev)
>         struct c_can_priv *priv = netdev_priv(dev);
>
>         /* enable automatic retransmission */
> -       priv->write_reg(priv, C_CAN_CTRL_REG,
> -                       CONTROL_ENABLE_AR);
> +       priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR);
>
>         if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) &&
>             (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) {
>                 /* loopback + silent mode : useful for hot self-test */
> -               priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE |
> -                               CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
> -               priv->write_reg(priv, C_CAN_TEST_REG,
> -                               TEST_LBACK | TEST_SILENT);
> +               priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
> +               priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK | TEST_SILENT);
>         } else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
>                 /* loopback mode : useful for self-test function */
> -               priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE |
> -                               CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
> +               priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
>                 priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK);
>         } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
>                 /* silent mode : bus-monitoring mode */
> -               priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE |
> -                               CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
> +               priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
>                 priv->write_reg(priv, C_CAN_TEST_REG, TEST_SILENT);
> -       } else
> -               /* normal mode*/
> -               priv->write_reg(priv, C_CAN_CTRL_REG,
> -                               CONTROL_EIE | CONTROL_SIE | CONTROL_IE);
> +       }
>
>         /* configure message objects */
>         c_can_configure_msg_objects(dev);
> @@ -662,9 +654,6 @@ static int c_can_start(struct net_device *dev)
>         /* reset tx helper pointers */
>         priv->tx_next = priv->tx_echo = 0;
>
> -       /* enable status change, error and module interrupts */
> -       c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
> -
>         return 0;
>  }
>
> @@ -681,6 +670,7 @@ static void c_can_stop(struct net_device *dev)
>
>  static int c_can_set_mode(struct net_device *dev, enum can_mode mode)
>  {
> +       struct c_can_priv *priv = netdev_priv(dev);
>         int err;
>
>         switch (mode) {
> @@ -689,6 +679,8 @@ static int c_can_set_mode(struct net_device *dev, enum can_mode mode)
>                 if (err)
>                         return err;
>                 netif_wake_queue(dev);
> +               /* enable status change, error and module interrupts */
> +               c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
>                 break;
>         default:
>                 return -EOPNOTSUPP;
> @@ -1184,6 +1176,8 @@ static int c_can_open(struct net_device *dev)
>         can_led_event(dev, CAN_LED_EVENT_OPEN);
>
>         napi_enable(&priv->napi);
> +       /* enable status change, error and module interrupts */
> +       c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
>         netif_start_queue(dev);
>
>         return 0;
> @@ -1281,6 +1275,7 @@ int c_can_power_up(struct net_device *dev)
>         u32 val;
>         unsigned long time_out;
>         struct c_can_priv *priv = netdev_priv(dev);
> +       int ret;
>
>         if (!(dev->flags & IFF_UP))
>                 return 0;
> @@ -1307,7 +1302,11 @@ int c_can_power_up(struct net_device *dev)
>         if (time_after(jiffies, time_out))
>                 return -ETIMEDOUT;
>
> -       return c_can_start(dev);
> +       ret = c_can_start(dev);
> +       if (!ret)
> +               c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
> +
> +       return ret;
>  }
>  EXPORT_SYMBOL_GPL(c_can_power_up);
>  #endif
> --
> 1.9.0.279.gdc9e3eb
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-can" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 02/26] can: c_can: Fix startup logic
  2014-04-29  7:29   ` Yegor Yefremov
@ 2014-05-02 12:37     ` Marc Kleine-Budde
  0 siblings, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2014-05-02 12:37 UTC (permalink / raw)
  To: Yegor Yefremov; +Cc: netdev, David Miller, linux-can, kernel, Thomas Gleixner

On 04/29/2014 09:29 AM, Yegor Yefremov wrote:
> On Fri, Apr 25, 2014 at 12:00 AM, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>> From: Thomas Gleixner <tglx@linutronix.de>
>>
>> c_can_start() enables interrupts way too early. The first enabling
>> happens when setting the control mode in c_can_chip_config() and then
>> again at the end of the function.
>>
>> But that happens before napi_enable() and that means that an interrupt
>> which comes in will disable interrupts again and call napi_schedule,
>> which ignores the request and the later napi_enable() is not making
>> thinks work either. So the interface is up with all device interrupts
>> disabled.
>>
>> Move the device interrupt after napi_enable() and add it to the other
>> callsites of c_can_start() in c_can_set_mode() and c_can_power_up()
>>
>> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>> Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
>> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> 
> Tested-by: Yegor Yefremov <yegorslists@googlemail.com>

Thanks, as this branch is already merged by David, it's too late to add
your Tested-by.

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   |

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2014-05-02 12:38 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-24 22:00 pull-request: can 2014-04-24 Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 01/26] can: c_can_pci: Set the type of the IP core Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 02/26] can: c_can: Fix startup logic Marc Kleine-Budde
2014-04-29  7:29   ` Yegor Yefremov
2014-05-02 12:37     ` Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 03/26] can: c_can: Make bus off interrupt disable logic work Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 04/26] can: c_can: Do not access skb after net_receive_skb() Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 05/26] can: c_can: Handle state change correctly Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 06/26] can: c_can: Fix berr reporting Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 07/26] can: c_can: Always update error stats Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 08/26] can: c_can: Simplify buffer reenabling Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 09/26] can: c_can: Avoid status register update for D_CAN Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 10/26] can: c_can: Get rid of pointless interrupts Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 11/26] can: c_can: Disable rx split as workaround Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 12/26] can: c_can: Work around C_CAN RX wreckage Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 13/26] can: c_can: Cleanup irq enable/disable Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 14/26] can: c_can: Cleanup c_can_read_msg_object() Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 15/26] can: c_can: Cleanup setup of receive buffers Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 16/26] can: c_can: Cleanup c_can_inval_msg_object() Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 17/26] can: c_can: Cleanup c_can_msg_obj_put/get() Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 18/26] can: c_can: Cleanup c_can_write_msg_object() Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 19/26] can: c_can: Use proper u32 variables in c_can_write_msg_object() Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 20/26] can: c_can: Remove tx locking Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 21/26] can: c_can: Speed up tx buffer invalidation Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 22/26] can: c_can: use proper type for 'instance' Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 23/26] can: c_can_pci: enable PCI bus master only for MSI Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 24/26] can: sja1000_isa: add locking for indirect register access mode Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 25/26] can: fix return value from can_get_bittiming() Marc Kleine-Budde
2014-04-24 22:00 ` [PATCH 26/26] can: slcan: Fix spinlock variant Marc Kleine-Budde
2014-04-24 22:04 ` pull-request: can 2014-04-24 Marc Kleine-Budde
2014-04-26 16:31 ` David Miller

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.