linux-can-fixes-for-5.5-20191208

-----BEGIN PGP SIGNATURE-----
 
 iQFHBAABCgAxFiEEmvEkXzgOfc881GuFWsYho5HknSAFAl3s3dwTHG1rbEBwZW5n
 dXRyb25peC5kZQAKCRBaxiGjkeSdIKhhB/sE+kGrGECa6DSehxKsSTCvh/5AGw2U
 AGh+AHgpfCRKOPNBeN0yKCdBVSE40fURsIjNvn5SDZ1cY8tUOVCJAyUU31MfgzkW
 b+Xiro5iOu6G/UpfZgMCeGV617FZg/65rz7ylwNzzA7zuUcoml6o4A55/QUFNIXx
 juDzhdKmpmLRQusekzbP9qyCgDGXv8/cPBloI+frzqaDU5bgS6Q3ldHe26lkQzNH
 bwF6bCGpJYykuNFIrLoFpSuJ+7ttZhLexXCwsl90UfpwmHVvUgQKJuF8JVR1AF3x
 5mjHWi3GFyi4aUL4yY4kU3cWWPse3MQLPt5QqMu56dW4UADp1k3FHByo
 =YMzV
 -----END PGP SIGNATURE-----

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: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2019-12-09 09:27:47 -08:00
Родитель e42617b825 da2311a638
Коммит 43aad8104b
8 изменённых файлов: 84 добавлений и 52 удалений

Просмотреть файл

@ -10,7 +10,6 @@ Required properties:
- #size-cells: 0 - #size-cells: 0
- spi-max-frequency: Maximum frequency of the SPI bus the chip can - spi-max-frequency: Maximum frequency of the SPI bus the chip can
operate at should be less than or equal to 18 MHz. 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 - interrupt-parent: the phandle to the interrupt controller which provides
the interrupt. the interrupt.
- interrupts: interrupt specification for data-ready. - interrupts: interrupt specification for data-ready.
@ -23,6 +22,7 @@ Optional properties:
reset. reset.
- device-state-gpios: Input GPIO that indicates if the device is in - device-state-gpios: Input GPIO that indicates if the device is in
a sleep state or if the device is active. a sleep state or if the device is active.
- device-wake-gpios: Wake up GPIO to wake up the TCAN device.
Example: Example:
tcan4x5x: tcan4x5x@0 { tcan4x5x: tcan4x5x@0 {
@ -36,5 +36,5 @@ tcan4x5x: tcan4x5x@0 {
interrupts = <14 GPIO_ACTIVE_LOW>; interrupts = <14 GPIO_ACTIVE_LOW>;
device-state-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; device-state-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
device-wake-gpios = <&gpio1 15 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>;
}; };

Просмотреть файл

@ -339,7 +339,7 @@ To claim an address following code example can be used:
.pgn = J1939_PGN_ADDRESS_CLAIMED, .pgn = J1939_PGN_ADDRESS_CLAIMED,
.pgn_mask = J1939_PGN_PDU1_MAX, .pgn_mask = J1939_PGN_PDU1_MAX,
}, { }, {
.pgn = J1939_PGN_ADDRESS_REQUEST, .pgn = J1939_PGN_REQUEST,
.pgn_mask = J1939_PGN_PDU1_MAX, .pgn_mask = J1939_PGN_PDU1_MAX,
}, { }, {
.pgn = J1939_PGN_ADDRESS_COMMANDED, .pgn = J1939_PGN_ADDRESS_COMMANDED,

Просмотреть файл

@ -10108,6 +10108,7 @@ S: Maintained
F: drivers/media/radio/radio-maxiradio* F: drivers/media/radio/radio-maxiradio*
MCAN MMIO DEVICE DRIVER MCAN MMIO DEVICE DRIVER
M: Dan Murphy <dmurphy@ti.com>
M: Sriram Dash <sriram.dash@samsung.com> M: Sriram Dash <sriram.dash@samsung.com>
L: linux-can@vger.kernel.org L: linux-can@vger.kernel.org
S: Maintained S: Maintained
@ -16533,6 +16534,13 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Odd Fixes S: Odd Fixes
F: sound/soc/codecs/tas571x* 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 TI TRF7970A NFC DRIVER
M: Mark Greer <mgreer@animalcreek.com> M: Mark Greer <mgreer@animalcreek.com>
L: linux-wireless@vger.kernel.org L: linux-wireless@vger.kernel.org

Просмотреть файл

@ -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]); (&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) static void flexcan_enable_wakeup_irq(struct flexcan_priv *priv, bool enable)
{ {
struct flexcan_regs __iomem *regs = priv->regs; 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) static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv)
{ {
struct flexcan_regs __iomem *regs = priv->regs; struct flexcan_regs __iomem *regs = priv->regs;
unsigned int ackval;
u32 reg_mcr; u32 reg_mcr;
reg_mcr = priv->read(&regs->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, regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
1 << priv->stm.req_bit, 1 << priv->stm.req_bit); 1 << priv->stm.req_bit, 1 << priv->stm.req_bit);
/* get stop acknowledgment */ return flexcan_low_power_enter_ack(priv);
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;
} }
static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv) static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
{ {
struct flexcan_regs __iomem *regs = priv->regs; struct flexcan_regs __iomem *regs = priv->regs;
unsigned int ackval;
u32 reg_mcr; u32 reg_mcr;
/* remove stop request */ /* remove stop request */
regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr, regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
1 << priv->stm.req_bit, 0); 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 = priv->read(&regs->mcr);
reg_mcr &= ~FLEXCAN_MCR_SLF_WAK; reg_mcr &= ~FLEXCAN_MCR_SLF_WAK;
priv->write(reg_mcr, &regs->mcr); 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) 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) static int flexcan_chip_enable(struct flexcan_priv *priv)
{ {
struct flexcan_regs __iomem *regs = priv->regs; struct flexcan_regs __iomem *regs = priv->regs;
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
u32 reg; u32 reg;
reg = priv->read(&regs->mcr); reg = priv->read(&regs->mcr);
reg &= ~FLEXCAN_MCR_MDIS; reg &= ~FLEXCAN_MCR_MDIS;
priv->write(reg, &regs->mcr); priv->write(reg, &regs->mcr);
while (timeout-- && (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)) return flexcan_low_power_exit_ack(priv);
udelay(10);
if (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
return -ETIMEDOUT;
return 0;
} }
static int flexcan_chip_disable(struct flexcan_priv *priv) static int flexcan_chip_disable(struct flexcan_priv *priv)
{ {
struct flexcan_regs __iomem *regs = priv->regs; struct flexcan_regs __iomem *regs = priv->regs;
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
u32 reg; u32 reg;
reg = priv->read(&regs->mcr); reg = priv->read(&regs->mcr);
reg |= FLEXCAN_MCR_MDIS; reg |= FLEXCAN_MCR_MDIS;
priv->write(reg, &regs->mcr); priv->write(reg, &regs->mcr);
while (timeout-- && !(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)) return flexcan_low_power_enter_ack(priv);
udelay(10);
if (!(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
return -ETIMEDOUT;
return 0;
} }
static int flexcan_chip_freeze(struct flexcan_priv *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); netif_start_queue(dev);
if (device_may_wakeup(device)) { if (device_may_wakeup(device)) {
disable_irq_wake(dev->irq); disable_irq_wake(dev->irq);
err = flexcan_exit_stop_mode(priv);
if (err)
return err;
} else { } else {
err = pm_runtime_force_resume(device); err = pm_runtime_force_resume(device);
if (err) 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 net_device *dev = dev_get_drvdata(device);
struct flexcan_priv *priv = netdev_priv(dev); 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); flexcan_enable_wakeup_irq(priv, false);
err = flexcan_exit_stop_mode(priv);
if (err)
return err;
}
return 0; return 0;
} }

Просмотреть файл

@ -101,6 +101,8 @@
#define TCAN4X5X_MODE_STANDBY BIT(6) #define TCAN4X5X_MODE_STANDBY BIT(6)
#define TCAN4X5X_MODE_NORMAL BIT(7) #define TCAN4X5X_MODE_NORMAL BIT(7)
#define TCAN4X5X_DISABLE_WAKE_MSK (BIT(31) | BIT(30))
#define TCAN4X5X_SW_RESET BIT(2) #define TCAN4X5X_SW_RESET BIT(2)
#define TCAN4X5X_MCAN_CONFIGURED BIT(5) #define TCAN4X5X_MCAN_CONFIGURED BIT(5)
@ -338,6 +340,14 @@ static int tcan4x5x_init(struct m_can_classdev *cdev)
return ret; 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) static int tcan4x5x_parse_config(struct m_can_classdev *cdev)
{ {
struct tcan4x5x_priv *tcan4x5x = cdev->device_data; 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", tcan4x5x->device_wake_gpio = devm_gpiod_get(cdev->dev, "device-wake",
GPIOD_OUT_HIGH); GPIOD_OUT_HIGH);
if (IS_ERR(tcan4x5x->device_wake_gpio)) { if (IS_ERR(tcan4x5x->device_wake_gpio)) {
dev_err(cdev->dev, "device-wake gpio not defined\n"); if (PTR_ERR(tcan4x5x->power) == -EPROBE_DEFER)
return -EINVAL; return -EPROBE_DEFER;
tcan4x5x_disable_wake(cdev);
} }
tcan4x5x->reset_gpio = devm_gpiod_get_optional(cdev->dev, "reset", 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)) if (IS_ERR(tcan4x5x->reset_gpio))
tcan4x5x->reset_gpio = NULL; tcan4x5x->reset_gpio = NULL;
usleep_range(700, 1000);
tcan4x5x->device_state_gpio = devm_gpiod_get_optional(cdev->dev, tcan4x5x->device_state_gpio = devm_gpiod_get_optional(cdev->dev,
"device-state", "device-state",
GPIOD_IN); GPIOD_IN);
@ -428,10 +442,6 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
spi_set_drvdata(spi, priv); spi_set_drvdata(spi, priv);
ret = tcan4x5x_parse_config(mcan_class);
if (ret)
goto out_clk;
/* Configure the SPI bus */ /* Configure the SPI bus */
spi->bits_per_word = 32; spi->bits_per_word = 32;
ret = spi_setup(spi); 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, priv->regmap = devm_regmap_init(&spi->dev, &tcan4x5x_bus,
&spi->dev, &tcan4x5x_regmap); &spi->dev, &tcan4x5x_regmap);
ret = tcan4x5x_parse_config(mcan_class);
if (ret)
goto out_clk;
tcan4x5x_power_enable(priv->power, 1); tcan4x5x_power_enable(priv->power, 1);
ret = m_can_class_register(mcan_class); ret = m_can_class_register(mcan_class);

Просмотреть файл

@ -608,7 +608,7 @@ static int kvaser_usb_leaf_simple_cmd_async(struct kvaser_usb_net_priv *priv,
struct kvaser_cmd *cmd; struct kvaser_cmd *cmd;
int err; int err;
cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC); cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
if (!cmd) if (!cmd)
return -ENOMEM; return -ENOMEM;
@ -1140,7 +1140,7 @@ static int kvaser_usb_leaf_set_opt_mode(const struct kvaser_usb_net_priv *priv)
struct kvaser_cmd *cmd; struct kvaser_cmd *cmd;
int rc; int rc;
cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) if (!cmd)
return -ENOMEM; return -ENOMEM;
@ -1206,7 +1206,7 @@ static int kvaser_usb_leaf_flush_queue(struct kvaser_usb_net_priv *priv)
struct kvaser_cmd *cmd; struct kvaser_cmd *cmd;
int rc; int rc;
cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) if (!cmd)
return -ENOMEM; return -ENOMEM;

Просмотреть файл

@ -60,6 +60,8 @@ enum xcan_reg {
XCAN_TXMSG_BASE_OFFSET = 0x0100, /* TX Message Space */ XCAN_TXMSG_BASE_OFFSET = 0x0100, /* TX Message Space */
XCAN_RXMSG_BASE_OFFSET = 0x1100, /* RX Message Space */ XCAN_RXMSG_BASE_OFFSET = 0x1100, /* RX Message Space */
XCAN_RXMSG_2_BASE_OFFSET = 0x2100, /* RX Message Space */ XCAN_RXMSG_2_BASE_OFFSET = 0x2100, /* RX Message Space */
XCAN_AFR_2_MASK_OFFSET = 0x0A00, /* Acceptance Filter MASK */
XCAN_AFR_2_ID_OFFSET = 0x0A04, /* Acceptance Filter ID */
}; };
#define XCAN_FRAME_ID_OFFSET(frame_base) ((frame_base) + 0x00) #define XCAN_FRAME_ID_OFFSET(frame_base) ((frame_base) + 0x00)
@ -1809,6 +1811,11 @@ static int xcan_probe(struct platform_device *pdev)
pm_runtime_put(&pdev->dev); pm_runtime_put(&pdev->dev);
if (priv->devtype.flags & XCAN_FLAG_CANFD_2) {
priv->write_reg(priv, XCAN_AFR_2_ID_OFFSET, 0x00000000);
priv->write_reg(priv, XCAN_AFR_2_MASK_OFFSET, 0x00000000);
}
netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx buffers: actual %d, using %d\n", netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx buffers: actual %d, using %d\n",
priv->reg_base, ndev->irq, priv->can.clock.freq, priv->reg_base, ndev->irq, priv->can.clock.freq,
hw_tx_max, priv->tx_max); hw_tx_max, priv->tx_max);

Просмотреть файл

@ -423,9 +423,9 @@ static int j1939_sk_bind(struct socket *sock, struct sockaddr *uaddr, int len)
{ {
struct sockaddr_can *addr = (struct sockaddr_can *)uaddr; struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
struct j1939_sock *jsk = j1939_sk(sock->sk); struct j1939_sock *jsk = j1939_sk(sock->sk);
struct j1939_priv *priv = jsk->priv; struct j1939_priv *priv;
struct sock *sk = sock->sk; struct sock *sk;
struct net *net = sock_net(sk); struct net *net;
int ret = 0; int ret = 0;
ret = j1939_sk_sanity_check(addr, len); ret = j1939_sk_sanity_check(addr, len);
@ -434,6 +434,10 @@ static int j1939_sk_bind(struct socket *sock, struct sockaddr *uaddr, int len)
lock_sock(sock->sk); lock_sock(sock->sk);
priv = jsk->priv;
sk = sock->sk;
net = sock_net(sk);
/* Already bound to an interface? */ /* Already bound to an interface? */
if (jsk->state & J1939_SOCK_BOUND) { if (jsk->state & J1939_SOCK_BOUND) {
/* A re-bind() to a different interface is not /* A re-bind() to a different interface is not