Commit 43aad810 authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'linux-can-fixes-for-5.5-20191208' of...

Merge tag 'linux-can-fixes-for-5.5-20191208' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can



Marc Kleine-Budde says:

====================
pull-request: can 2019-12-08

this is a pull request of 13 patches for net/master.

The first two patches are by Dan Murphy. He adds himself as a maintainer to the
m-can MMIO and tcan SPI driver.

The next two patches the j1939 stack. The first one is by Oleksij Rempel and
fixes a locking problem found by the syzbot, the second one is by me an fixes a
mistake in the documentation.

Srinivas Neeli fixes missing RX CAN packets on CANFD2.0 in the xilinx driver.

Sean Nyekjaer fixes a possible deadlock in the the flexcan driver after
suspend/resume. Joakim Zhang contributes two patches for the flexcan driver
that fix problems with the low power enter/exit.

The next 4 patches all target the tcan part of the m_can driver. Sean Nyekjaer
adds the required delay after reset and fixes the device tree binding example.
Dan Murphy's patches make the wake-gpio optional.

In the last patch Xiaolong Huang fixes several kernel memory info leaks to the
USB device in the kvaser_usb_leaf driver.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e42617b8 da2311a6
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -10,7 +10,6 @@ Required properties:
	- #size-cells: 0
	- spi-max-frequency: Maximum frequency of the SPI bus the chip can
			     operate at should be less than or equal to 18 MHz.
	- device-wake-gpios: Wake up GPIO to wake up the TCAN device.
	- interrupt-parent: the phandle to the interrupt controller which provides
                    the interrupt.
	- interrupts: interrupt specification for data-ready.
@@ -23,6 +22,7 @@ Optional properties:
		       reset.
	- device-state-gpios: Input GPIO that indicates if the device is in
			      a sleep state or if the device is active.
	- device-wake-gpios: Wake up GPIO to wake up the TCAN device.

Example:
tcan4x5x: tcan4x5x@0 {
@@ -36,5 +36,5 @@ tcan4x5x: tcan4x5x@0 {
		interrupts = <14 GPIO_ACTIVE_LOW>;
		device-state-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
		device-wake-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
		reset-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>;
		reset-gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
};
+1 −1
Original line number Diff line number Diff line
@@ -339,7 +339,7 @@ To claim an address following code example can be used:
			.pgn = J1939_PGN_ADDRESS_CLAIMED,
			.pgn_mask = J1939_PGN_PDU1_MAX,
		}, {
			.pgn = J1939_PGN_ADDRESS_REQUEST,
			.pgn = J1939_PGN_REQUEST,
			.pgn_mask = J1939_PGN_PDU1_MAX,
		}, {
			.pgn = J1939_PGN_ADDRESS_COMMANDED,
+8 −0
Original line number Diff line number Diff line
@@ -10108,6 +10108,7 @@ S: Maintained
F:	drivers/media/radio/radio-maxiradio*
MCAN MMIO DEVICE DRIVER
M:	Dan Murphy <dmurphy@ti.com>
M:	Sriram Dash <sriram.dash@samsung.com>
L:	linux-can@vger.kernel.org
S:	Maintained
@@ -16533,6 +16534,13 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S:	Odd Fixes
F:	sound/soc/codecs/tas571x*
TI TCAN4X5X DEVICE DRIVER
M:	Dan Murphy <dmurphy@ti.com>
L:	linux-can@vger.kernel.org
S:	Maintained
F:	Documentation/devicetree/bindings/net/can/tcan4x5x.txt
F:	drivers/net/can/m_can/tcan4x5x.c
TI TRF7970A NFC DRIVER
M:	Mark Greer <mgreer@animalcreek.com>
L:	linux-wireless@vger.kernel.org
+36 −37
Original line number Diff line number Diff line
@@ -389,6 +389,34 @@ static struct flexcan_mb __iomem *flexcan_get_mb(const struct flexcan_priv *priv
		(&priv->regs->mb[bank][priv->mb_size * mb_index]);
}

static int flexcan_low_power_enter_ack(struct flexcan_priv *priv)
{
	struct flexcan_regs __iomem *regs = priv->regs;
	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;

	while (timeout-- && !(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
		udelay(10);

	if (!(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
		return -ETIMEDOUT;

	return 0;
}

static int flexcan_low_power_exit_ack(struct flexcan_priv *priv)
{
	struct flexcan_regs __iomem *regs = priv->regs;
	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;

	while (timeout-- && (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
		udelay(10);

	if (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
		return -ETIMEDOUT;

	return 0;
}

static void flexcan_enable_wakeup_irq(struct flexcan_priv *priv, bool enable)
{
	struct flexcan_regs __iomem *regs = priv->regs;
@@ -407,7 +435,6 @@ static void flexcan_enable_wakeup_irq(struct flexcan_priv *priv, bool enable)
static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv)
{
	struct flexcan_regs __iomem *regs = priv->regs;
	unsigned int ackval;
	u32 reg_mcr;

	reg_mcr = priv->read(&regs->mcr);
@@ -418,36 +445,24 @@ static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv)
	regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
			   1 << priv->stm.req_bit, 1 << priv->stm.req_bit);

	/* get stop acknowledgment */
	if (regmap_read_poll_timeout(priv->stm.gpr, priv->stm.ack_gpr,
				     ackval, ackval & (1 << priv->stm.ack_bit),
				     0, FLEXCAN_TIMEOUT_US))
		return -ETIMEDOUT;

	return 0;
	return flexcan_low_power_enter_ack(priv);
}

static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
{
	struct flexcan_regs __iomem *regs = priv->regs;
	unsigned int ackval;
	u32 reg_mcr;

	/* remove stop request */
	regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
			   1 << priv->stm.req_bit, 0);

	/* get stop acknowledgment */
	if (regmap_read_poll_timeout(priv->stm.gpr, priv->stm.ack_gpr,
				     ackval, !(ackval & (1 << priv->stm.ack_bit)),
				     0, FLEXCAN_TIMEOUT_US))
		return -ETIMEDOUT;

	reg_mcr = priv->read(&regs->mcr);
	reg_mcr &= ~FLEXCAN_MCR_SLF_WAK;
	priv->write(reg_mcr, &regs->mcr);

	return 0;
	return flexcan_low_power_exit_ack(priv);
}

static inline void flexcan_error_irq_enable(const struct flexcan_priv *priv)
@@ -506,39 +521,25 @@ static inline int flexcan_transceiver_disable(const struct flexcan_priv *priv)
static int flexcan_chip_enable(struct flexcan_priv *priv)
{
	struct flexcan_regs __iomem *regs = priv->regs;
	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
	u32 reg;

	reg = priv->read(&regs->mcr);
	reg &= ~FLEXCAN_MCR_MDIS;
	priv->write(reg, &regs->mcr);

	while (timeout-- && (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
		udelay(10);

	if (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
		return -ETIMEDOUT;

	return 0;
	return flexcan_low_power_exit_ack(priv);
}

static int flexcan_chip_disable(struct flexcan_priv *priv)
{
	struct flexcan_regs __iomem *regs = priv->regs;
	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
	u32 reg;

	reg = priv->read(&regs->mcr);
	reg |= FLEXCAN_MCR_MDIS;
	priv->write(reg, &regs->mcr);

	while (timeout-- && !(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
		udelay(10);

	if (!(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
		return -ETIMEDOUT;

	return 0;
	return flexcan_low_power_enter_ack(priv);
}

static int flexcan_chip_freeze(struct flexcan_priv *priv)
@@ -1722,6 +1723,9 @@ static int __maybe_unused flexcan_resume(struct device *device)
		netif_start_queue(dev);
		if (device_may_wakeup(device)) {
			disable_irq_wake(dev->irq);
			err = flexcan_exit_stop_mode(priv);
			if (err)
				return err;
		} else {
			err = pm_runtime_force_resume(device);
			if (err)
@@ -1767,14 +1771,9 @@ static int __maybe_unused flexcan_noirq_resume(struct device *device)
{
	struct net_device *dev = dev_get_drvdata(device);
	struct flexcan_priv *priv = netdev_priv(dev);
	int err;

	if (netif_running(dev) && device_may_wakeup(device)) {
	if (netif_running(dev) && device_may_wakeup(device))
		flexcan_enable_wakeup_irq(priv, false);
		err = flexcan_exit_stop_mode(priv);
		if (err)
			return err;
	}

	return 0;
}
+20 −6
Original line number Diff line number Diff line
@@ -101,6 +101,8 @@
#define TCAN4X5X_MODE_STANDBY BIT(6)
#define TCAN4X5X_MODE_NORMAL BIT(7)

#define TCAN4X5X_DISABLE_WAKE_MSK	(BIT(31) | BIT(30))

#define TCAN4X5X_SW_RESET BIT(2)

#define TCAN4X5X_MCAN_CONFIGURED BIT(5)
@@ -338,6 +340,14 @@ static int tcan4x5x_init(struct m_can_classdev *cdev)
	return ret;
}

static int tcan4x5x_disable_wake(struct m_can_classdev *cdev)
{
	struct tcan4x5x_priv *tcan4x5x = cdev->device_data;

	return regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
				  TCAN4X5X_DISABLE_WAKE_MSK, 0x00);
}

static int tcan4x5x_parse_config(struct m_can_classdev *cdev)
{
	struct tcan4x5x_priv *tcan4x5x = cdev->device_data;
@@ -345,8 +355,10 @@ static int tcan4x5x_parse_config(struct m_can_classdev *cdev)
	tcan4x5x->device_wake_gpio = devm_gpiod_get(cdev->dev, "device-wake",
						    GPIOD_OUT_HIGH);
	if (IS_ERR(tcan4x5x->device_wake_gpio)) {
		dev_err(cdev->dev, "device-wake gpio not defined\n");
		return -EINVAL;
		if (PTR_ERR(tcan4x5x->power) == -EPROBE_DEFER)
			return -EPROBE_DEFER;

		tcan4x5x_disable_wake(cdev);
	}

	tcan4x5x->reset_gpio = devm_gpiod_get_optional(cdev->dev, "reset",
@@ -354,6 +366,8 @@ static int tcan4x5x_parse_config(struct m_can_classdev *cdev)
	if (IS_ERR(tcan4x5x->reset_gpio))
		tcan4x5x->reset_gpio = NULL;

	usleep_range(700, 1000);

	tcan4x5x->device_state_gpio = devm_gpiod_get_optional(cdev->dev,
							      "device-state",
							      GPIOD_IN);
@@ -428,10 +442,6 @@ static int tcan4x5x_can_probe(struct spi_device *spi)

	spi_set_drvdata(spi, priv);

	ret = tcan4x5x_parse_config(mcan_class);
	if (ret)
		goto out_clk;

	/* Configure the SPI bus */
	spi->bits_per_word = 32;
	ret = spi_setup(spi);
@@ -441,6 +451,10 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
	priv->regmap = devm_regmap_init(&spi->dev, &tcan4x5x_bus,
					&spi->dev, &tcan4x5x_regmap);

	ret = tcan4x5x_parse_config(mcan_class);
	if (ret)
		goto out_clk;

	tcan4x5x_power_enable(priv->power, 1);

	ret = m_can_class_register(mcan_class);
Loading