Commit ce225298 authored by David S. Miller's avatar David S. Miller

Merge tag 'linux-can-fixes-for-5.12-20210316' of...

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

Marc Kleine-Budde says:

====================
pull-request: can 2021-03-16

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

The first patch is by Martin Willi and fixes the deletion of network
name spaces with physical CAN interfaces in them.

The next two patches are by me an fix the ISOTP protocol, to ensure
that unused flags in classical CAN frames are properly initialized to
zero.

Stephane Grosjean contributes a patch for the pcan_usb_fd driver,
which add MODULE_SUPPORTED_DEVICE lines for two supported devices.

Angelo Dureghello's patch for the flexcan driver fixes a potential div
by zero, if the bitrate is not set during driver probe.

Jimmy Assarsson's patch for the kvaser_pciefd disables bus load
reporting in the device, if it was previously enabled by the vendor's
out of tree drier. A patch for the kvaser_usb adds support for a new
device, by adding the appropriate USB product ID.

Tong Zhang contributes two patches for the c_can driver. First a
use-after-free in the c_can_pci driver is fixed, in the second patch
the runtime PM for the c_can_pci is fixed by moving the runtime PM
enable/disable from the core driver to the platform driver.

The last two patches are by Torin Cooper-Bennun for the m_can driver.
First a extraneous msg loss warning is removed then he fixes the
RX-path, which might be blocked by errors.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8a4452ca e98d9ee6
...@@ -212,18 +212,6 @@ static const struct can_bittiming_const c_can_bittiming_const = { ...@@ -212,18 +212,6 @@ static const struct can_bittiming_const c_can_bittiming_const = {
.brp_inc = 1, .brp_inc = 1,
}; };
static inline void c_can_pm_runtime_enable(const struct c_can_priv *priv)
{
if (priv->device)
pm_runtime_enable(priv->device);
}
static inline void c_can_pm_runtime_disable(const struct c_can_priv *priv)
{
if (priv->device)
pm_runtime_disable(priv->device);
}
static inline void c_can_pm_runtime_get_sync(const struct c_can_priv *priv) static inline void c_can_pm_runtime_get_sync(const struct c_can_priv *priv)
{ {
if (priv->device) if (priv->device)
...@@ -1335,7 +1323,6 @@ static const struct net_device_ops c_can_netdev_ops = { ...@@ -1335,7 +1323,6 @@ static const struct net_device_ops c_can_netdev_ops = {
int register_c_can_dev(struct net_device *dev) int register_c_can_dev(struct net_device *dev)
{ {
struct c_can_priv *priv = netdev_priv(dev);
int err; int err;
/* Deactivate pins to prevent DRA7 DCAN IP from being /* Deactivate pins to prevent DRA7 DCAN IP from being
...@@ -1345,28 +1332,19 @@ int register_c_can_dev(struct net_device *dev) ...@@ -1345,28 +1332,19 @@ int register_c_can_dev(struct net_device *dev)
*/ */
pinctrl_pm_select_sleep_state(dev->dev.parent); pinctrl_pm_select_sleep_state(dev->dev.parent);
c_can_pm_runtime_enable(priv);
dev->flags |= IFF_ECHO; /* we support local echo */ dev->flags |= IFF_ECHO; /* we support local echo */
dev->netdev_ops = &c_can_netdev_ops; dev->netdev_ops = &c_can_netdev_ops;
err = register_candev(dev); err = register_candev(dev);
if (err) if (!err)
c_can_pm_runtime_disable(priv);
else
devm_can_led_init(dev); devm_can_led_init(dev);
return err; return err;
} }
EXPORT_SYMBOL_GPL(register_c_can_dev); EXPORT_SYMBOL_GPL(register_c_can_dev);
void unregister_c_can_dev(struct net_device *dev) void unregister_c_can_dev(struct net_device *dev)
{ {
struct c_can_priv *priv = netdev_priv(dev);
unregister_candev(dev); unregister_candev(dev);
c_can_pm_runtime_disable(priv);
} }
EXPORT_SYMBOL_GPL(unregister_c_can_dev); EXPORT_SYMBOL_GPL(unregister_c_can_dev);
......
...@@ -239,12 +239,13 @@ static void c_can_pci_remove(struct pci_dev *pdev) ...@@ -239,12 +239,13 @@ static void c_can_pci_remove(struct pci_dev *pdev)
{ {
struct net_device *dev = pci_get_drvdata(pdev); struct net_device *dev = pci_get_drvdata(pdev);
struct c_can_priv *priv = netdev_priv(dev); struct c_can_priv *priv = netdev_priv(dev);
void __iomem *addr = priv->base;
unregister_c_can_dev(dev); unregister_c_can_dev(dev);
free_c_can_dev(dev); free_c_can_dev(dev);
pci_iounmap(pdev, priv->base); pci_iounmap(pdev, addr);
pci_disable_msi(pdev); pci_disable_msi(pdev);
pci_clear_master(pdev); pci_clear_master(pdev);
pci_release_regions(pdev); pci_release_regions(pdev);
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
...@@ -386,6 +387,7 @@ static int c_can_plat_probe(struct platform_device *pdev) ...@@ -386,6 +387,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev); SET_NETDEV_DEV(dev, &pdev->dev);
pm_runtime_enable(priv->device);
ret = register_c_can_dev(dev); ret = register_c_can_dev(dev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "registering %s failed (err=%d)\n", dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
...@@ -398,6 +400,7 @@ static int c_can_plat_probe(struct platform_device *pdev) ...@@ -398,6 +400,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
return 0; return 0;
exit_free_device: exit_free_device:
pm_runtime_disable(priv->device);
free_c_can_dev(dev); free_c_can_dev(dev);
exit: exit:
dev_err(&pdev->dev, "probe failed\n"); dev_err(&pdev->dev, "probe failed\n");
...@@ -408,9 +411,10 @@ static int c_can_plat_probe(struct platform_device *pdev) ...@@ -408,9 +411,10 @@ static int c_can_plat_probe(struct platform_device *pdev)
static int c_can_plat_remove(struct platform_device *pdev) static int c_can_plat_remove(struct platform_device *pdev)
{ {
struct net_device *dev = platform_get_drvdata(pdev); struct net_device *dev = platform_get_drvdata(pdev);
struct c_can_priv *priv = netdev_priv(dev);
unregister_c_can_dev(dev); unregister_c_can_dev(dev);
pm_runtime_disable(priv->device);
free_c_can_dev(dev); free_c_can_dev(dev);
return 0; return 0;
......
...@@ -355,6 +355,7 @@ static void can_dellink(struct net_device *dev, struct list_head *head) ...@@ -355,6 +355,7 @@ static void can_dellink(struct net_device *dev, struct list_head *head)
struct rtnl_link_ops can_link_ops __read_mostly = { struct rtnl_link_ops can_link_ops __read_mostly = {
.kind = "can", .kind = "can",
.netns_refund = true,
.maxtype = IFLA_CAN_MAX, .maxtype = IFLA_CAN_MAX,
.policy = can_policy, .policy = can_policy,
.setup = can_setup, .setup = can_setup,
......
...@@ -697,9 +697,15 @@ static int flexcan_chip_disable(struct flexcan_priv *priv) ...@@ -697,9 +697,15 @@ static int flexcan_chip_disable(struct flexcan_priv *priv)
static int flexcan_chip_freeze(struct flexcan_priv *priv) static int flexcan_chip_freeze(struct flexcan_priv *priv)
{ {
struct flexcan_regs __iomem *regs = priv->regs; struct flexcan_regs __iomem *regs = priv->regs;
unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate; unsigned int timeout;
u32 bitrate = priv->can.bittiming.bitrate;
u32 reg; u32 reg;
if (bitrate)
timeout = 1000 * 1000 * 10 / bitrate;
else
timeout = FLEXCAN_TIMEOUT_US / 10;
reg = priv->read(&regs->mcr); reg = priv->read(&regs->mcr);
reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT; reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT;
priv->write(reg, &regs->mcr); priv->write(reg, &regs->mcr);
......
...@@ -57,6 +57,7 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); ...@@ -57,6 +57,7 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
#define KVASER_PCIEFD_KCAN_STAT_REG 0x418 #define KVASER_PCIEFD_KCAN_STAT_REG 0x418
#define KVASER_PCIEFD_KCAN_MODE_REG 0x41c #define KVASER_PCIEFD_KCAN_MODE_REG 0x41c
#define KVASER_PCIEFD_KCAN_BTRN_REG 0x420 #define KVASER_PCIEFD_KCAN_BTRN_REG 0x420
#define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424
#define KVASER_PCIEFD_KCAN_BTRD_REG 0x428 #define KVASER_PCIEFD_KCAN_BTRD_REG 0x428
#define KVASER_PCIEFD_KCAN_PWM_REG 0x430 #define KVASER_PCIEFD_KCAN_PWM_REG 0x430
/* Loopback control register */ /* Loopback control register */
...@@ -949,6 +950,9 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie) ...@@ -949,6 +950,9 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer, timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer,
0); 0);
/* Disable Bus load reporting */
iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_BUS_LOAD_REG);
tx_npackets = ioread32(can->reg_base + tx_npackets = ioread32(can->reg_base +
KVASER_PCIEFD_KCAN_TX_NPACKETS_REG); KVASER_PCIEFD_KCAN_TX_NPACKETS_REG);
if (((tx_npackets >> KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT) & if (((tx_npackets >> KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT) &
......
...@@ -501,9 +501,6 @@ static int m_can_do_rx_poll(struct net_device *dev, int quota) ...@@ -501,9 +501,6 @@ static int m_can_do_rx_poll(struct net_device *dev, int quota)
} }
while ((rxfs & RXFS_FFL_MASK) && (quota > 0)) { while ((rxfs & RXFS_FFL_MASK) && (quota > 0)) {
if (rxfs & RXFS_RFL)
netdev_warn(dev, "Rx FIFO 0 Message Lost\n");
m_can_read_fifo(dev, rxfs); m_can_read_fifo(dev, rxfs);
quota--; quota--;
...@@ -876,7 +873,7 @@ static int m_can_rx_peripheral(struct net_device *dev) ...@@ -876,7 +873,7 @@ static int m_can_rx_peripheral(struct net_device *dev)
{ {
struct m_can_classdev *cdev = netdev_priv(dev); struct m_can_classdev *cdev = netdev_priv(dev);
m_can_rx_handler(dev, 1); m_can_rx_handler(dev, M_CAN_NAPI_WEIGHT);
m_can_enable_all_interrupts(cdev); m_can_enable_all_interrupts(cdev);
......
...@@ -73,6 +73,7 @@ config CAN_KVASER_USB ...@@ -73,6 +73,7 @@ config CAN_KVASER_USB
- Kvaser Memorator Pro 5xHS - Kvaser Memorator Pro 5xHS
- Kvaser USBcan Light 4xHS - Kvaser USBcan Light 4xHS
- Kvaser USBcan Pro 2xHS v2 - Kvaser USBcan Pro 2xHS v2
- Kvaser USBcan Pro 4xHS
- Kvaser USBcan Pro 5xHS - Kvaser USBcan Pro 5xHS
- Kvaser U100 - Kvaser U100
- Kvaser U100P - Kvaser U100P
......
...@@ -86,8 +86,9 @@ ...@@ -86,8 +86,9 @@
#define USB_U100_PRODUCT_ID 273 #define USB_U100_PRODUCT_ID 273
#define USB_U100P_PRODUCT_ID 274 #define USB_U100P_PRODUCT_ID 274
#define USB_U100S_PRODUCT_ID 275 #define USB_U100S_PRODUCT_ID 275
#define USB_USBCAN_PRO_4HS_PRODUCT_ID 276
#define USB_HYDRA_PRODUCT_ID_END \ #define USB_HYDRA_PRODUCT_ID_END \
USB_U100S_PRODUCT_ID USB_USBCAN_PRO_4HS_PRODUCT_ID
static inline bool kvaser_is_leaf(const struct usb_device_id *id) static inline bool kvaser_is_leaf(const struct usb_device_id *id)
{ {
...@@ -193,6 +194,7 @@ static const struct usb_device_id kvaser_usb_table[] = { ...@@ -193,6 +194,7 @@ static const struct usb_device_id kvaser_usb_table[] = {
{ USB_DEVICE(KVASER_VENDOR_ID, USB_U100_PRODUCT_ID) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_U100_PRODUCT_ID) },
{ USB_DEVICE(KVASER_VENDOR_ID, USB_U100P_PRODUCT_ID) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_U100P_PRODUCT_ID) },
{ USB_DEVICE(KVASER_VENDOR_ID, USB_U100S_PRODUCT_ID) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_U100S_PRODUCT_ID) },
{ USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_4HS_PRODUCT_ID) },
{ } { }
}; };
MODULE_DEVICE_TABLE(usb, kvaser_usb_table); MODULE_DEVICE_TABLE(usb, kvaser_usb_table);
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
MODULE_SUPPORTED_DEVICE("PEAK-System PCAN-USB FD adapter"); MODULE_SUPPORTED_DEVICE("PEAK-System PCAN-USB FD adapter");
MODULE_SUPPORTED_DEVICE("PEAK-System PCAN-USB Pro FD adapter"); MODULE_SUPPORTED_DEVICE("PEAK-System PCAN-USB Pro FD adapter");
MODULE_SUPPORTED_DEVICE("PEAK-System PCAN-Chip USB");
MODULE_SUPPORTED_DEVICE("PEAK-System PCAN-USB X6 adapter");
#define PCAN_USBPROFD_CHANNEL_COUNT 2 #define PCAN_USBPROFD_CHANNEL_COUNT 2
#define PCAN_USBFD_CHANNEL_COUNT 1 #define PCAN_USBFD_CHANNEL_COUNT 1
......
...@@ -33,6 +33,7 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) ...@@ -33,6 +33,7 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh)
* *
* @list: Used internally * @list: Used internally
* @kind: Identifier * @kind: Identifier
* @netns_refund: Physical device, move to init_net on netns exit
* @maxtype: Highest device specific netlink attribute number * @maxtype: Highest device specific netlink attribute number
* @policy: Netlink policy for device specific attribute validation * @policy: Netlink policy for device specific attribute validation
* @validate: Optional validation function for netlink/changelink parameters * @validate: Optional validation function for netlink/changelink parameters
...@@ -64,6 +65,7 @@ struct rtnl_link_ops { ...@@ -64,6 +65,7 @@ struct rtnl_link_ops {
size_t priv_size; size_t priv_size;
void (*setup)(struct net_device *dev); void (*setup)(struct net_device *dev);
bool netns_refund;
unsigned int maxtype; unsigned int maxtype;
const struct nla_policy *policy; const struct nla_policy *policy;
int (*validate)(struct nlattr *tb[], int (*validate)(struct nlattr *tb[],
......
...@@ -215,7 +215,6 @@ static int isotp_send_fc(struct sock *sk, int ae, u8 flowstatus) ...@@ -215,7 +215,6 @@ static int isotp_send_fc(struct sock *sk, int ae, u8 flowstatus)
if (ae) if (ae)
ncf->data[0] = so->opt.ext_address; ncf->data[0] = so->opt.ext_address;
if (so->ll.mtu == CANFD_MTU)
ncf->flags = so->ll.tx_flags; ncf->flags = so->ll.tx_flags;
can_send_ret = can_send(nskb, 1); can_send_ret = can_send(nskb, 1);
...@@ -790,7 +789,6 @@ static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer) ...@@ -790,7 +789,6 @@ static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
so->tx.sn %= 16; so->tx.sn %= 16;
so->tx.bs++; so->tx.bs++;
if (so->ll.mtu == CANFD_MTU)
cf->flags = so->ll.tx_flags; cf->flags = so->ll.tx_flags;
skb->dev = dev; skb->dev = dev;
...@@ -939,7 +937,6 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) ...@@ -939,7 +937,6 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
} }
/* send the first or only CAN frame */ /* send the first or only CAN frame */
if (so->ll.mtu == CANFD_MTU)
cf->flags = so->ll.tx_flags; cf->flags = so->ll.tx_flags;
skb->dev = dev; skb->dev = dev;
...@@ -1228,7 +1225,8 @@ static int isotp_setsockopt(struct socket *sock, int level, int optname, ...@@ -1228,7 +1225,8 @@ static int isotp_setsockopt(struct socket *sock, int level, int optname,
if (ll.mtu != CAN_MTU && ll.mtu != CANFD_MTU) if (ll.mtu != CAN_MTU && ll.mtu != CANFD_MTU)
return -EINVAL; return -EINVAL;
if (ll.mtu == CAN_MTU && ll.tx_dl > CAN_MAX_DLEN) if (ll.mtu == CAN_MTU &&
(ll.tx_dl > CAN_MAX_DLEN || ll.tx_flags != 0))
return -EINVAL; return -EINVAL;
memcpy(&so->ll, &ll, sizeof(ll)); memcpy(&so->ll, &ll, sizeof(ll));
......
...@@ -11346,7 +11346,7 @@ static void __net_exit default_device_exit(struct net *net) ...@@ -11346,7 +11346,7 @@ static void __net_exit default_device_exit(struct net *net)
continue; continue;
/* Leave virtual devices for the generic cleanup */ /* Leave virtual devices for the generic cleanup */
if (dev->rtnl_link_ops) if (dev->rtnl_link_ops && !dev->rtnl_link_ops->netns_refund)
continue; continue;
/* Push remaining network devices to init_net */ /* Push remaining network devices to init_net */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment