netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* pull-request: can 2014-03-03
@ 2014-03-03 13:54 Marc Kleine-Budde
  2014-03-03 13:54 ` [PATCH 1/8] can: flexcan: fix shutdown: first disable chip, then all interrupts Marc Kleine-Budde
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Marc Kleine-Budde @ 2014-03-03 13:54 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel

Hello David,

this is a pull request of 8 patches. Oliver Hartkopp contributes a patch which
removes the CAN FD compatibility for CAN 2.0 sockets, as it turns out that this
compatibility has some conceptual cornercases. The remaining 7 patches are by
me, they address a problem in the flexcan driver. When shutting down the
interface ("ifconfig can0 down") under heavy network load the whole system will
hang. This series reworks the actual sequence in close() and the transition
from and to the low power modes of the CAN controller.

regards,
Marc
---

The following changes since commit 635d61a3735e05c8da72740006670f819e5b6a5f:

  USB AX88179/178A: Support D-Link DUB-1312 (2014-03-02 20:29:30 -0500)

are available in the git repository at:

  git://gitorious.org/linux-can/linux-can.git tags/linux-can-fixes-for-3.14-20140303

for you to fetch changes up to 821047c4055cca833c4674f172a9d73003563eb6:

  can: remove CAN FD compatibility for CAN 2.0 sockets (2014-03-03 14:29:52 +0100)

----------------------------------------------------------------
linux-can-fixes-for-3.14-20140303

----------------------------------------------------------------
Marc Kleine-Budde (7):
      can: flexcan: fix shutdown: first disable chip, then all interrupts
      can: flexcan: flexcan_open(): fix error path if flexcan_chip_start() fails
      can: flexcan: fix transition from and to low power mode in chip_{en,dis}able
      can: flexcan: factor out transceiver {en,dis}able into seperate functions
      can: flexcan: fix transition from and to freeze mode in chip_{,un}freeze
      can: flexcan: flexcan_remove(): add missing netif_napi_del()
      can: flexcan: factor out soft reset into seperate funtion

Oliver Hartkopp (1):
      can: remove CAN FD compatibility for CAN 2.0 sockets

 Documentation/networking/can.txt |   6 --
 drivers/net/can/flexcan.c        | 172 +++++++++++++++++++++++++++++----------
 net/can/raw.c                    |  26 ++----
 3 files changed, 136 insertions(+), 68 deletions(-)

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

* [PATCH 1/8] can: flexcan: fix shutdown: first disable chip, then all interrupts
  2014-03-03 13:54 pull-request: can 2014-03-03 Marc Kleine-Budde
@ 2014-03-03 13:54 ` Marc Kleine-Budde
  2014-03-03 13:54 ` [PATCH 2/8] can: flexcan: flexcan_open(): fix error path if flexcan_chip_start() fails Marc Kleine-Budde
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Marc Kleine-Budde @ 2014-03-03 13:54 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Marc Kleine-Budde, linux-stable

When shutting down the CAN interface (ifconfig canX down) during high CAN bus
loads, the CAN core might hang and freeze the whole CPU.

This patch fixes the shutdown sequence by first disabling the CAN core then
disabling all interrupts.

Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 320bef2..dcd69c9 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -827,14 +827,16 @@ static void flexcan_chip_stop(struct net_device *dev)
 	struct flexcan_regs __iomem *regs = priv->base;
 	u32 reg;
 
-	/* Disable all interrupts */
-	flexcan_write(0, &regs->imask1);
-
 	/* Disable + halt module */
 	reg = flexcan_read(&regs->mcr);
 	reg |= FLEXCAN_MCR_MDIS | FLEXCAN_MCR_HALT;
 	flexcan_write(reg, &regs->mcr);
 
+	/* Disable all interrupts */
+	flexcan_write(0, &regs->imask1);
+	flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
+		      &regs->ctrl);
+
 	if (priv->reg_xceiver)
 		regulator_disable(priv->reg_xceiver);
 	priv->can.state = CAN_STATE_STOPPED;
-- 
1.9.0

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

* [PATCH 2/8] can: flexcan: flexcan_open(): fix error path if flexcan_chip_start() fails
  2014-03-03 13:54 pull-request: can 2014-03-03 Marc Kleine-Budde
  2014-03-03 13:54 ` [PATCH 1/8] can: flexcan: fix shutdown: first disable chip, then all interrupts Marc Kleine-Budde
@ 2014-03-03 13:54 ` Marc Kleine-Budde
  2014-03-03 13:54 ` [PATCH 3/8] can: flexcan: fix transition from and to low power mode in chip_{en,dis}able Marc Kleine-Budde
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Marc Kleine-Budde @ 2014-03-03 13:54 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Marc Kleine-Budde, linux-stable

If flexcan_chip_start() in flexcan_open() fails, the interrupt is not freed,
this patch adds the missing cleanup.

Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index dcd69c9..30af702 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -868,7 +868,7 @@ static int flexcan_open(struct net_device *dev)
 	/* start chip and queuing */
 	err = flexcan_chip_start(dev);
 	if (err)
-		goto out_close;
+		goto out_free_irq;
 
 	can_led_event(dev, CAN_LED_EVENT_OPEN);
 
@@ -877,6 +877,8 @@ static int flexcan_open(struct net_device *dev)
 
 	return 0;
 
+ out_free_irq:
+	free_irq(dev->irq, dev);
  out_close:
 	close_candev(dev);
  out_disable_per:
-- 
1.9.0

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

* [PATCH 3/8] can: flexcan: fix transition from and to low power mode in chip_{en,dis}able
  2014-03-03 13:54 pull-request: can 2014-03-03 Marc Kleine-Budde
  2014-03-03 13:54 ` [PATCH 1/8] can: flexcan: fix shutdown: first disable chip, then all interrupts Marc Kleine-Budde
  2014-03-03 13:54 ` [PATCH 2/8] can: flexcan: flexcan_open(): fix error path if flexcan_chip_start() fails Marc Kleine-Budde
@ 2014-03-03 13:54 ` Marc Kleine-Budde
  2014-03-03 13:54 ` [PATCH 4/8] can: flexcan: factor out transceiver {en,dis}able into seperate functions Marc Kleine-Budde
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Marc Kleine-Budde @ 2014-03-03 13:54 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Marc Kleine-Budde, linux-stable

In flexcan_chip_enable() and flexcan_chip_disable() fixed delays are used.
Experiments have shown that the transition from and to low power mode may take
several microseconds.

This patch adds a while loop which polls the Low Power Mode ACK bit (LPM_ACK)
that indicates a successfull mode change. If the function runs into a timeout a
error value is returned.

Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 50 +++++++++++++++++++++++++++++++++++------------
 1 file changed, 38 insertions(+), 12 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 30af702..5af60ab 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -144,6 +144,8 @@
 
 #define FLEXCAN_MB_CODE_MASK		(0xf0ffffff)
 
+#define FLEXCAN_TIMEOUT_US             (50)
+
 /*
  * FLEXCAN hardware feature flags
  *
@@ -269,26 +271,42 @@ static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv,
 		(reg_esr & FLEXCAN_ESR_ERR_BUS);
 }
 
-static inline void flexcan_chip_enable(struct flexcan_priv *priv)
+static int flexcan_chip_enable(struct flexcan_priv *priv)
 {
 	struct flexcan_regs __iomem *regs = priv->base;
+	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
 	u32 reg;
 
 	reg = flexcan_read(&regs->mcr);
 	reg &= ~FLEXCAN_MCR_MDIS;
 	flexcan_write(reg, &regs->mcr);
 
-	udelay(10);
+	while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+		usleep_range(10, 20);
+
+	if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
+		return -ETIMEDOUT;
+
+	return 0;
 }
 
-static inline void flexcan_chip_disable(struct flexcan_priv *priv)
+static int flexcan_chip_disable(struct flexcan_priv *priv)
 {
 	struct flexcan_regs __iomem *regs = priv->base;
+	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
 	u32 reg;
 
 	reg = flexcan_read(&regs->mcr);
 	reg |= FLEXCAN_MCR_MDIS;
 	flexcan_write(reg, &regs->mcr);
+
+	while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+		usleep_range(10, 20);
+
+	if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+		return -ETIMEDOUT;
+
+	return 0;
 }
 
 static int flexcan_get_berr_counter(const struct net_device *dev,
@@ -709,7 +727,9 @@ static int flexcan_chip_start(struct net_device *dev)
 	u32 reg_mcr, reg_ctrl;
 
 	/* enable module */
-	flexcan_chip_enable(priv);
+	err = flexcan_chip_enable(priv);
+	if (err)
+		return err;
 
 	/* soft reset */
 	flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
@@ -949,12 +969,16 @@ static int register_flexcandev(struct net_device *dev)
 		goto out_disable_ipg;
 
 	/* select "bus clock", chip must be disabled */
-	flexcan_chip_disable(priv);
+	err = flexcan_chip_disable(priv);
+	if (err)
+		goto out_disable_per;
 	reg = flexcan_read(&regs->ctrl);
 	reg |= FLEXCAN_CTRL_CLK_SRC;
 	flexcan_write(reg, &regs->ctrl);
 
-	flexcan_chip_enable(priv);
+	err = flexcan_chip_enable(priv);
+	if (err)
+		goto out_chip_disable;
 
 	/* set freeze, halt and activate FIFO, restrict register access */
 	reg = flexcan_read(&regs->mcr);
@@ -971,14 +995,15 @@ static int register_flexcandev(struct net_device *dev)
 	if (!(reg & FLEXCAN_MCR_FEN)) {
 		netdev_err(dev, "Could not enable RX FIFO, unsupported core\n");
 		err = -ENODEV;
-		goto out_disable_per;
+		goto out_chip_disable;
 	}
 
 	err = register_candev(dev);
 
- out_disable_per:
 	/* disable core and turn off clocks */
+ out_chip_disable:
 	flexcan_chip_disable(priv);
+ out_disable_per:
 	clk_disable_unprepare(priv->clk_per);
  out_disable_ipg:
 	clk_disable_unprepare(priv->clk_ipg);
@@ -1121,8 +1146,11 @@ static int flexcan_suspend(struct device *device)
 {
 	struct net_device *dev = dev_get_drvdata(device);
 	struct flexcan_priv *priv = netdev_priv(dev);
+	int err;
 
-	flexcan_chip_disable(priv);
+	err = flexcan_chip_disable(priv);
+	if (err)
+		return err;
 
 	if (netif_running(dev)) {
 		netif_stop_queue(dev);
@@ -1143,9 +1171,7 @@ static int flexcan_resume(struct device *device)
 		netif_device_attach(dev);
 		netif_start_queue(dev);
 	}
-	flexcan_chip_enable(priv);
-
-	return 0;
+	return flexcan_chip_enable(priv);
 }
 #endif /* CONFIG_PM_SLEEP */
 
-- 
1.9.0


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

* [PATCH 4/8] can: flexcan: factor out transceiver {en,dis}able into seperate functions
  2014-03-03 13:54 pull-request: can 2014-03-03 Marc Kleine-Budde
                   ` (2 preceding siblings ...)
  2014-03-03 13:54 ` [PATCH 3/8] can: flexcan: fix transition from and to low power mode in chip_{en,dis}able Marc Kleine-Budde
@ 2014-03-03 13:54 ` Marc Kleine-Budde
  2014-03-03 13:54 ` [PATCH 5/8] can: flexcan: fix transition from and to freeze mode in chip_{,un}freeze Marc Kleine-Budde
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Marc Kleine-Budde @ 2014-03-03 13:54 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Marc Kleine-Budde, linux-stable

This patch moves the transceiver enable and disable into seperate functions,
where the NULL pointer check is hidden.

Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 5af60ab..6b0fecd 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -264,6 +264,22 @@ static inline void flexcan_write(u32 val, void __iomem *addr)
 }
 #endif
 
+static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv)
+{
+	if (!priv->reg_xceiver)
+		return 0;
+
+	return regulator_enable(priv->reg_xceiver);
+}
+
+static inline int flexcan_transceiver_disable(const struct flexcan_priv *priv)
+{
+	if (!priv->reg_xceiver)
+		return 0;
+
+	return regulator_disable(priv->reg_xceiver);
+}
+
 static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv,
 					      u32 reg_esr)
 {
@@ -808,11 +824,9 @@ static int flexcan_chip_start(struct net_device *dev)
 	if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES)
 		flexcan_write(0x0, &regs->rxfgmask);
 
-	if (priv->reg_xceiver)	{
-		err = regulator_enable(priv->reg_xceiver);
-		if (err)
-			goto out;
-	}
+	err = flexcan_transceiver_enable(priv);
+	if (err)
+		goto out;
 
 	/* synchronize with the can bus */
 	reg_mcr = flexcan_read(&regs->mcr);
@@ -857,8 +871,7 @@ static void flexcan_chip_stop(struct net_device *dev)
 	flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
 		      &regs->ctrl);
 
-	if (priv->reg_xceiver)
-		regulator_disable(priv->reg_xceiver);
+	flexcan_transceiver_disable(priv);
 	priv->can.state = CAN_STATE_STOPPED;
 
 	return;
-- 
1.9.0

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

* [PATCH 5/8] can: flexcan: fix transition from and to freeze mode in chip_{,un}freeze
  2014-03-03 13:54 pull-request: can 2014-03-03 Marc Kleine-Budde
                   ` (3 preceding siblings ...)
  2014-03-03 13:54 ` [PATCH 4/8] can: flexcan: factor out transceiver {en,dis}able into seperate functions Marc Kleine-Budde
@ 2014-03-03 13:54 ` Marc Kleine-Budde
  2014-03-03 13:54 ` [PATCH 6/8] can: flexcan: flexcan_remove(): add missing netif_napi_del() Marc Kleine-Budde
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Marc Kleine-Budde @ 2014-03-03 13:54 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Marc Kleine-Budde, linux-stable

This patch factors out freeze and unfreeze of the CAN core into seperate
functions. Experiments have shown that the transition from and to freeze mode
may take several microseconds, especially the time entering the freeze mode
depends on the current bitrate.

This patch adds a while loop which polls the Freeze Mode ACK bit (FRZ_ACK) that
indicates a successfull mode change. If the function runs into a timeout a
error value is returned.

Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 60 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 49 insertions(+), 11 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 6b0fecd..330b5b9 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -325,6 +325,44 @@ static int flexcan_chip_disable(struct flexcan_priv *priv)
 	return 0;
 }
 
+static int flexcan_chip_freeze(struct flexcan_priv *priv)
+{
+	struct flexcan_regs __iomem *regs = priv->base;
+	unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate;
+	u32 reg;
+
+	reg = flexcan_read(&regs->mcr);
+	reg |= FLEXCAN_MCR_HALT;
+	flexcan_write(reg, &regs->mcr);
+
+	while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
+		usleep_range(100, 200);
+
+	if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
+{
+	struct flexcan_regs __iomem *regs = priv->base;
+	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
+	u32 reg;
+
+	reg = flexcan_read(&regs->mcr);
+	reg &= ~FLEXCAN_MCR_HALT;
+	flexcan_write(reg, &regs->mcr);
+
+	while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
+		usleep_range(10, 20);
+
+	if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
 static int flexcan_get_berr_counter(const struct net_device *dev,
 				    struct can_berr_counter *bec)
 {
@@ -756,7 +794,7 @@ static int flexcan_chip_start(struct net_device *dev)
 		netdev_err(dev, "Failed to softreset can module (mcr=0x%08x)\n",
 			   reg_mcr);
 		err = -ENODEV;
-		goto out;
+		goto out_chip_disable;
 	}
 
 	flexcan_set_bittiming(dev);
@@ -826,12 +864,12 @@ static int flexcan_chip_start(struct net_device *dev)
 
 	err = flexcan_transceiver_enable(priv);
 	if (err)
-		goto out;
+		goto out_chip_disable;
 
 	/* synchronize with the can bus */
-	reg_mcr = flexcan_read(&regs->mcr);
-	reg_mcr &= ~FLEXCAN_MCR_HALT;
-	flexcan_write(reg_mcr, &regs->mcr);
+	err = flexcan_chip_unfreeze(priv);
+	if (err)
+		goto out_transceiver_disable;
 
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
@@ -844,7 +882,9 @@ static int flexcan_chip_start(struct net_device *dev)
 
 	return 0;
 
- out:
+ out_transceiver_disable:
+	flexcan_transceiver_disable(priv);
+ out_chip_disable:
 	flexcan_chip_disable(priv);
 	return err;
 }
@@ -859,12 +899,10 @@ static void flexcan_chip_stop(struct net_device *dev)
 {
 	struct flexcan_priv *priv = netdev_priv(dev);
 	struct flexcan_regs __iomem *regs = priv->base;
-	u32 reg;
 
-	/* Disable + halt module */
-	reg = flexcan_read(&regs->mcr);
-	reg |= FLEXCAN_MCR_MDIS | FLEXCAN_MCR_HALT;
-	flexcan_write(reg, &regs->mcr);
+	/* freeze + disable module */
+	flexcan_chip_freeze(priv);
+	flexcan_chip_disable(priv);
 
 	/* Disable all interrupts */
 	flexcan_write(0, &regs->imask1);
-- 
1.9.0

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

* [PATCH 6/8] can: flexcan: flexcan_remove(): add missing netif_napi_del()
  2014-03-03 13:54 pull-request: can 2014-03-03 Marc Kleine-Budde
                   ` (4 preceding siblings ...)
  2014-03-03 13:54 ` [PATCH 5/8] can: flexcan: fix transition from and to freeze mode in chip_{,un}freeze Marc Kleine-Budde
@ 2014-03-03 13:54 ` Marc Kleine-Budde
  2014-03-03 13:54 ` [PATCH 7/8] can: flexcan: factor out soft reset into seperate funtion Marc Kleine-Budde
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Marc Kleine-Budde @ 2014-03-03 13:54 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Marc Kleine-Budde, linux-stable

This patch adds the missing netif_napi_del() to the flexcan_remove() function.

Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 330b5b9..dff4fa4 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -1184,9 +1184,10 @@ static int flexcan_probe(struct platform_device *pdev)
 static int flexcan_remove(struct platform_device *pdev)
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
+	struct flexcan_priv *priv = netdev_priv(dev);
 
 	unregister_flexcandev(dev);
-
+	netif_napi_del(&priv->napi);
 	free_candev(dev);
 
 	return 0;
-- 
1.9.0

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

* [PATCH 7/8] can: flexcan: factor out soft reset into seperate funtion
  2014-03-03 13:54 pull-request: can 2014-03-03 Marc Kleine-Budde
                   ` (5 preceding siblings ...)
  2014-03-03 13:54 ` [PATCH 6/8] can: flexcan: flexcan_remove(): add missing netif_napi_del() Marc Kleine-Budde
@ 2014-03-03 13:54 ` Marc Kleine-Budde
  2014-03-03 13:54 ` [PATCH 8/8] can: remove CAN FD compatibility for CAN 2.0 sockets Marc Kleine-Budde
  2014-03-03 21:05 ` pull-request: can 2014-03-03 David Miller
  8 siblings, 0 replies; 10+ messages in thread
From: Marc Kleine-Budde @ 2014-03-03 13:54 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Marc Kleine-Budde

This patch moves the soft reset into a seperate function.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index dff4fa4..61376ab 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -363,6 +363,21 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
 	return 0;
 }
 
+static int flexcan_chip_softreset(struct flexcan_priv *priv)
+{
+	struct flexcan_regs __iomem *regs = priv->base;
+	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
+
+	flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
+	while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST))
+		usleep_range(10, 20);
+
+	if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
 static int flexcan_get_berr_counter(const struct net_device *dev,
 				    struct can_berr_counter *bec)
 {
@@ -786,16 +801,9 @@ static int flexcan_chip_start(struct net_device *dev)
 		return err;
 
 	/* soft reset */
-	flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
-	udelay(10);
-
-	reg_mcr = flexcan_read(&regs->mcr);
-	if (reg_mcr & FLEXCAN_MCR_SOFTRST) {
-		netdev_err(dev, "Failed to softreset can module (mcr=0x%08x)\n",
-			   reg_mcr);
-		err = -ENODEV;
+	err = flexcan_chip_softreset(priv);
+	if (err)
 		goto out_chip_disable;
-	}
 
 	flexcan_set_bittiming(dev);
 
-- 
1.9.0


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

* [PATCH 8/8] can: remove CAN FD compatibility for CAN 2.0 sockets
  2014-03-03 13:54 pull-request: can 2014-03-03 Marc Kleine-Budde
                   ` (6 preceding siblings ...)
  2014-03-03 13:54 ` [PATCH 7/8] can: flexcan: factor out soft reset into seperate funtion Marc Kleine-Budde
@ 2014-03-03 13:54 ` Marc Kleine-Budde
  2014-03-03 21:05 ` pull-request: can 2014-03-03 David Miller
  8 siblings, 0 replies; 10+ messages in thread
From: Marc Kleine-Budde @ 2014-03-03 13:54 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Oliver Hartkopp, Marc Kleine-Budde

From: Oliver Hartkopp <socketcan@hartkopp.net>

In commit e2d265d3b587 (canfd: add support for CAN FD in CAN_RAW sockets)
CAN FD frames with a payload length up to 8 byte are passed to legacy
sockets where the CAN FD support was not enabled by the application.

After some discussions with developers at a fair this well meant feature
leads to confusion as no clean switch for CAN / CAN FD is provided to the
application programmer. Additionally a compatibility like this for legacy
CAN_RAW sockets requires some compatibility handling for the sending, e.g.
make CAN2.0 frames a CAN FD frame with BRS at transmission time (?!?).

This will become a mess when people start to develop applications with
real CAN FD hardware. This patch reverts the bad compatibility code
together with the documentation describing the removed feature.

Acked-by: Stephane Grosjean <s.grosjean@peak-system.com>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 Documentation/networking/can.txt |  6 ------
 net/can/raw.c                    | 26 +++++---------------------
 2 files changed, 5 insertions(+), 27 deletions(-)

diff --git a/Documentation/networking/can.txt b/Documentation/networking/can.txt
index f3089d4..0cbe6ec 100644
--- a/Documentation/networking/can.txt
+++ b/Documentation/networking/can.txt
@@ -554,12 +554,6 @@ solution for a couple of reasons:
   not specified in the struct can_frame and therefore it is only valid in
   CANFD_MTU sized CAN FD frames.
 
-  As long as the payload length is <=8 the received CAN frames from CAN FD
-  capable CAN devices can be received and read by legacy sockets too. When
-  user-generated CAN FD frames have a payload length <=8 these can be send
-  by legacy CAN network interfaces too. Sending CAN FD frames with payload
-  length > 8 to a legacy CAN network interface returns an -EMSGSIZE error.
-
   Implementation hint for new CAN applications:
 
   To build a CAN FD aware application use struct canfd_frame as basic CAN
diff --git a/net/can/raw.c b/net/can/raw.c
index 8be757c..081e81f 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -121,13 +121,9 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
 	if (!ro->recv_own_msgs && oskb->sk == sk)
 		return;
 
-	/* do not pass frames with DLC > 8 to a legacy socket */
-	if (!ro->fd_frames) {
-		struct canfd_frame *cfd = (struct canfd_frame *)oskb->data;
-
-		if (unlikely(cfd->len > CAN_MAX_DLEN))
-			return;
-	}
+	/* do not pass non-CAN2.0 frames to a legacy socket */
+	if (!ro->fd_frames && oskb->len != CAN_MTU)
+		return;
 
 	/* clone the given skb to be able to enqueue it into the rcv queue */
 	skb = skb_clone(oskb, GFP_ATOMIC);
@@ -738,9 +734,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
 		       struct msghdr *msg, size_t size, int flags)
 {
 	struct sock *sk = sock->sk;
-	struct raw_sock *ro = raw_sk(sk);
 	struct sk_buff *skb;
-	int rxmtu;
 	int err = 0;
 	int noblock;
 
@@ -751,20 +745,10 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
 	if (!skb)
 		return err;
 
-	/*
-	 * when serving a legacy socket the DLC <= 8 is already checked inside
-	 * raw_rcv(). Now check if we need to pass a canfd_frame to a legacy
-	 * socket and cut the possible CANFD_MTU/CAN_MTU length to CAN_MTU
-	 */
-	if (!ro->fd_frames)
-		rxmtu = CAN_MTU;
-	else
-		rxmtu = skb->len;
-
-	if (size < rxmtu)
+	if (size < skb->len)
 		msg->msg_flags |= MSG_TRUNC;
 	else
-		size = rxmtu;
+		size = skb->len;
 
 	err = memcpy_toiovec(msg->msg_iov, skb->data, size);
 	if (err < 0) {
-- 
1.9.0


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

* Re: pull-request: can 2014-03-03
  2014-03-03 13:54 pull-request: can 2014-03-03 Marc Kleine-Budde
                   ` (7 preceding siblings ...)
  2014-03-03 13:54 ` [PATCH 8/8] can: remove CAN FD compatibility for CAN 2.0 sockets Marc Kleine-Budde
@ 2014-03-03 21:05 ` David Miller
  8 siblings, 0 replies; 10+ messages in thread
From: David Miller @ 2014-03-03 21:05 UTC (permalink / raw)
  To: mkl; +Cc: netdev, linux-can, kernel

From: Marc Kleine-Budde <mkl@pengutronix.de>
Date: Mon,  3 Mar 2014 14:54:27 +0100

> this is a pull request of 8 patches. Oliver Hartkopp contributes a patch which
> removes the CAN FD compatibility for CAN 2.0 sockets, as it turns out that this
> compatibility has some conceptual cornercases. The remaining 7 patches are by
> me, they address a problem in the flexcan driver. When shutting down the
> interface ("ifconfig can0 down") under heavy network load the whole system will
> hang. This series reworks the actual sequence in close() and the transition
> from and to the low power modes of the CAN controller.

Pulled, thanks a lot Marc.

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

end of thread, other threads:[~2014-03-03 21:05 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-03 13:54 pull-request: can 2014-03-03 Marc Kleine-Budde
2014-03-03 13:54 ` [PATCH 1/8] can: flexcan: fix shutdown: first disable chip, then all interrupts Marc Kleine-Budde
2014-03-03 13:54 ` [PATCH 2/8] can: flexcan: flexcan_open(): fix error path if flexcan_chip_start() fails Marc Kleine-Budde
2014-03-03 13:54 ` [PATCH 3/8] can: flexcan: fix transition from and to low power mode in chip_{en,dis}able Marc Kleine-Budde
2014-03-03 13:54 ` [PATCH 4/8] can: flexcan: factor out transceiver {en,dis}able into seperate functions Marc Kleine-Budde
2014-03-03 13:54 ` [PATCH 5/8] can: flexcan: fix transition from and to freeze mode in chip_{,un}freeze Marc Kleine-Budde
2014-03-03 13:54 ` [PATCH 6/8] can: flexcan: flexcan_remove(): add missing netif_napi_del() Marc Kleine-Budde
2014-03-03 13:54 ` [PATCH 7/8] can: flexcan: factor out soft reset into seperate funtion Marc Kleine-Budde
2014-03-03 13:54 ` [PATCH 8/8] can: remove CAN FD compatibility for CAN 2.0 sockets Marc Kleine-Budde
2014-03-03 21:05 ` pull-request: can 2014-03-03 David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).