]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 10 Jul 2022 14:22:24 +0000 (16:22 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 10 Jul 2022 14:22:24 +0000 (16:22 +0200)
added patches:
can-kvaser_usb-kvaser_usb_leaf-fix-bittiming-limits.patch
can-kvaser_usb-kvaser_usb_leaf-fix-can-clock-frequency-regression.patch
can-kvaser_usb-replace-run-time-checks-with-struct-kvaser_usb_driver_info.patch
powerpc-powernv-delay-rng-platform-device-creation-until-later-in-boot.patch

queue-4.19/can-kvaser_usb-kvaser_usb_leaf-fix-bittiming-limits.patch [new file with mode: 0644]
queue-4.19/can-kvaser_usb-kvaser_usb_leaf-fix-can-clock-frequency-regression.patch [new file with mode: 0644]
queue-4.19/can-kvaser_usb-replace-run-time-checks-with-struct-kvaser_usb_driver_info.patch [new file with mode: 0644]
queue-4.19/powerpc-powernv-delay-rng-platform-device-creation-until-later-in-boot.patch [new file with mode: 0644]
queue-4.19/series

diff --git a/queue-4.19/can-kvaser_usb-kvaser_usb_leaf-fix-bittiming-limits.patch b/queue-4.19/can-kvaser_usb-kvaser_usb_leaf-fix-bittiming-limits.patch
new file mode 100644 (file)
index 0000000..74136e6
--- /dev/null
@@ -0,0 +1,195 @@
+From foo@baz Sun Jul 10 04:20:24 PM CEST 2022
+From: Jimmy Assarsson <extja@kvaser.com>
+Date: Fri,  8 Jul 2022 20:47:26 +0200
+Subject: can: kvaser_usb: kvaser_usb_leaf: fix bittiming limits
+To: stable@vger.kernel.org, linux-can@vger.kernel.org, Marc Kleine-Budde <mkl@pengutronix.de>
+Cc: Jimmy Assarsson <jimmyassarsson@gmail.com>, Jimmy Assarsson <extja@kvaser.com>
+Message-ID: <20220708184726.280961-4-extja@kvaser.com>
+
+From: Jimmy Assarsson <extja@kvaser.com>
+
+commit b3b6df2c56d80b8c6740433cff5f016668b8de70 upstream.
+
+Use correct bittiming limits depending on device. For devices based on
+USBcanII, Leaf M32C or Leaf i.MX28.
+
+Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices")
+Fixes: b4f20130af23 ("can: kvaser_usb: add support for Kvaser Leaf v2 and usb mini PCIe")
+Fixes: f5d4abea3ce0 ("can: kvaser_usb: Add support for the USBcan-II family")
+Link: https://lore.kernel.org/all/20220603083820.800246-4-extja@kvaser.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Jimmy Assarsson <extja@kvaser.com>
+[mkl: remove stray netlink.h include]
+[mkl: keep struct can_bittiming_const kvaser_usb_flexc_bittiming_const in kvaser_usb_hydra.c]
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/can/usb/kvaser_usb/kvaser_usb.h       |    2 
+ drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c |    4 -
+ drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c  |   76 ++++++++++++----------
+ 3 files changed, 47 insertions(+), 35 deletions(-)
+
+--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
+@@ -188,4 +188,6 @@ int kvaser_usb_send_cmd_async(struct kva
+ int kvaser_usb_can_rx_over_error(struct net_device *netdev);
++extern const struct can_bittiming_const kvaser_usb_flexc_bittiming_const;
++
+ #endif /* KVASER_USB_H */
+--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
+@@ -371,7 +371,7 @@ static const struct can_bittiming_const
+       .brp_inc = 1,
+ };
+-static const struct can_bittiming_const kvaser_usb_hydra_flexc_bittiming_c = {
++const struct can_bittiming_const kvaser_usb_flexc_bittiming_const = {
+       .name = "kvaser_usb_flex",
+       .tseg1_min = 4,
+       .tseg1_max = 16,
+@@ -2024,5 +2024,5 @@ static const struct kvaser_usb_dev_cfg k
+               .freq = 24000000,
+       },
+       .timestamp_freq = 1,
+-      .bittiming_const = &kvaser_usb_hydra_flexc_bittiming_c,
++      .bittiming_const = &kvaser_usb_flexc_bittiming_const,
+ };
+--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
+@@ -100,16 +100,6 @@
+ #define USBCAN_ERROR_STATE_RX_ERROR   BIT(1)
+ #define USBCAN_ERROR_STATE_BUSERROR   BIT(2)
+-/* bittiming parameters */
+-#define KVASER_USB_TSEG1_MIN          1
+-#define KVASER_USB_TSEG1_MAX          16
+-#define KVASER_USB_TSEG2_MIN          1
+-#define KVASER_USB_TSEG2_MAX          8
+-#define KVASER_USB_SJW_MAX            4
+-#define KVASER_USB_BRP_MIN            1
+-#define KVASER_USB_BRP_MAX            64
+-#define KVASER_USB_BRP_INC            1
+-
+ /* ctrl modes */
+ #define KVASER_CTRL_MODE_NORMAL               1
+ #define KVASER_CTRL_MODE_SILENT               2
+@@ -342,48 +332,68 @@ struct kvaser_usb_err_summary {
+       };
+ };
+-static const struct can_bittiming_const kvaser_usb_leaf_bittiming_const = {
+-      .name = "kvaser_usb",
+-      .tseg1_min = KVASER_USB_TSEG1_MIN,
+-      .tseg1_max = KVASER_USB_TSEG1_MAX,
+-      .tseg2_min = KVASER_USB_TSEG2_MIN,
+-      .tseg2_max = KVASER_USB_TSEG2_MAX,
+-      .sjw_max = KVASER_USB_SJW_MAX,
+-      .brp_min = KVASER_USB_BRP_MIN,
+-      .brp_max = KVASER_USB_BRP_MAX,
+-      .brp_inc = KVASER_USB_BRP_INC,
++static const struct can_bittiming_const kvaser_usb_leaf_m16c_bittiming_const = {
++      .name = "kvaser_usb_ucii",
++      .tseg1_min = 4,
++      .tseg1_max = 16,
++      .tseg2_min = 2,
++      .tseg2_max = 8,
++      .sjw_max = 4,
++      .brp_min = 1,
++      .brp_max = 16,
++      .brp_inc = 1,
++};
++
++static const struct can_bittiming_const kvaser_usb_leaf_m32c_bittiming_const = {
++      .name = "kvaser_usb_leaf",
++      .tseg1_min = 3,
++      .tseg1_max = 16,
++      .tseg2_min = 2,
++      .tseg2_max = 8,
++      .sjw_max = 4,
++      .brp_min = 2,
++      .brp_max = 128,
++      .brp_inc = 2,
+ };
+-static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_8mhz = {
++static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_usbcan_dev_cfg = {
+       .clock = {
+               .freq = 8000000,
+       },
+       .timestamp_freq = 1,
+-      .bittiming_const = &kvaser_usb_leaf_bittiming_const,
++      .bittiming_const = &kvaser_usb_leaf_m16c_bittiming_const,
++};
++
++static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_m32c_dev_cfg = {
++      .clock = {
++              .freq = 16000000,
++      },
++      .timestamp_freq = 1,
++      .bittiming_const = &kvaser_usb_leaf_m32c_bittiming_const,
+ };
+-static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_16mhz = {
++static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_16mhz = {
+       .clock = {
+               .freq = 16000000,
+       },
+       .timestamp_freq = 1,
+-      .bittiming_const = &kvaser_usb_leaf_bittiming_const,
++      .bittiming_const = &kvaser_usb_flexc_bittiming_const,
+ };
+-static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_24mhz = {
++static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_24mhz = {
+       .clock = {
+               .freq = 24000000,
+       },
+       .timestamp_freq = 1,
+-      .bittiming_const = &kvaser_usb_leaf_bittiming_const,
++      .bittiming_const = &kvaser_usb_flexc_bittiming_const,
+ };
+-static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_32mhz = {
++static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_32mhz = {
+       .clock = {
+               .freq = 32000000,
+       },
+       .timestamp_freq = 1,
+-      .bittiming_const = &kvaser_usb_leaf_bittiming_const,
++      .bittiming_const = &kvaser_usb_flexc_bittiming_const,
+ };
+ static void *
+@@ -529,17 +539,17 @@ static void kvaser_usb_leaf_get_software
+               /* Firmware expects bittiming parameters calculated for 16MHz
+                * clock, regardless of the actual clock
+                */
+-              dev->cfg = &kvaser_usb_leaf_dev_cfg_16mhz;
++              dev->cfg = &kvaser_usb_leaf_m32c_dev_cfg;
+       } else {
+               switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) {
+               case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK:
+-                      dev->cfg = &kvaser_usb_leaf_dev_cfg_16mhz;
++                      dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_16mhz;
+                       break;
+               case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK:
+-                      dev->cfg = &kvaser_usb_leaf_dev_cfg_24mhz;
++                      dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_24mhz;
+                       break;
+               case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK:
+-                      dev->cfg = &kvaser_usb_leaf_dev_cfg_32mhz;
++                      dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_32mhz;
+                       break;
+               }
+       }
+@@ -566,7 +576,7 @@ static int kvaser_usb_leaf_get_software_
+               dev->fw_version = le32_to_cpu(cmd.u.usbcan.softinfo.fw_version);
+               dev->max_tx_urbs =
+                       le16_to_cpu(cmd.u.usbcan.softinfo.max_outstanding_tx);
+-              dev->cfg = &kvaser_usb_leaf_dev_cfg_8mhz;
++              dev->cfg = &kvaser_usb_leaf_usbcan_dev_cfg;
+               break;
+       }
diff --git a/queue-4.19/can-kvaser_usb-kvaser_usb_leaf-fix-can-clock-frequency-regression.patch b/queue-4.19/can-kvaser_usb-kvaser_usb_leaf-fix-can-clock-frequency-regression.patch
new file mode 100644 (file)
index 0000000..9e6e0a0
--- /dev/null
@@ -0,0 +1,149 @@
+From foo@baz Sun Jul 10 04:20:24 PM CEST 2022
+From: Jimmy Assarsson <extja@kvaser.com>
+Date: Fri,  8 Jul 2022 20:47:25 +0200
+Subject: can: kvaser_usb: kvaser_usb_leaf: fix CAN clock frequency regression
+To: stable@vger.kernel.org, linux-can@vger.kernel.org, Marc Kleine-Budde <mkl@pengutronix.de>
+Cc: Jimmy Assarsson <jimmyassarsson@gmail.com>, Jimmy Assarsson <extja@kvaser.com>
+Message-ID: <20220708184726.280961-3-extja@kvaser.com>
+
+From: Jimmy Assarsson <extja@kvaser.com>
+
+commit e6c80e601053ffdac5709f11ff3ec1e19ed05f7b upstream.
+
+The firmware of M32C based Leaf devices expects bittiming parameters
+calculated for 16MHz clock. Since we use the actual clock frequency of
+the device, the device may end up with wrong bittiming parameters,
+depending on user requested parameters.
+
+This regression affects M32C based Leaf devices with non-16MHz clock.
+
+Fixes: 7a09ebf00238 ("can: kvaser_usb: get CAN clock frequency from device")
+Link: https://lore.kernel.org/all/20220603083820.800246-3-extja@kvaser.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Jimmy Assarsson <extja@kvaser.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/can/usb/kvaser_usb/kvaser_usb.h      |    1 
+ drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c |   29 +++++++++++++++--------
+ drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c |   25 ++++++++++++-------
+ 3 files changed, 36 insertions(+), 19 deletions(-)
+
+--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
+@@ -38,6 +38,7 @@
+ /* Kvaser USB device quirks */
+ #define KVASER_USB_QUIRK_HAS_SILENT_MODE      BIT(0)
+ #define KVASER_USB_QUIRK_HAS_TXRX_ERRORS      BIT(1)
++#define KVASER_USB_QUIRK_IGNORE_CLK_FREQ      BIT(2)
+ /* Device capabilities */
+ #define KVASER_USB_CAP_BERR_CAP                       0x01
+--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
+@@ -92,26 +92,33 @@ static const struct kvaser_usb_driver_in
+ };
+ static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf = {
+-      .quirks = 0,
++      .quirks = KVASER_USB_QUIRK_IGNORE_CLK_FREQ,
+       .family = KVASER_LEAF,
+       .ops = &kvaser_usb_leaf_dev_ops,
+ };
+ static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf_err = {
+-      .quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS,
++      .quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS |
++                KVASER_USB_QUIRK_IGNORE_CLK_FREQ,
+       .family = KVASER_LEAF,
+       .ops = &kvaser_usb_leaf_dev_ops,
+ };
+ static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf_err_listen = {
+       .quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS |
+-                KVASER_USB_QUIRK_HAS_SILENT_MODE,
++                KVASER_USB_QUIRK_HAS_SILENT_MODE |
++                KVASER_USB_QUIRK_IGNORE_CLK_FREQ,
+       .family = KVASER_LEAF,
+       .ops = &kvaser_usb_leaf_dev_ops,
+ };
++static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leafimx = {
++      .quirks = 0,
++      .ops = &kvaser_usb_leaf_dev_ops,
++};
++
+ static const struct usb_device_id kvaser_usb_table[] = {
+-      /* Leaf USB product IDs */
++      /* Leaf M32C USB product IDs */
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_PRODUCT_ID),
+@@ -152,16 +159,18 @@ static const struct usb_device_id kvaser
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_CAN_R_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
++
++      /* Leaf i.MX28 USB product IDs */
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_V2_PRODUCT_ID),
+-              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_HS_PRODUCT_ID),
+-              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM_PRODUCT_ID),
+-              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_2HS_PRODUCT_ID),
+-              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_2HS_PRODUCT_ID),
+-              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+       /* USBCANII USB product IDs */
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN2_PRODUCT_ID),
+@@ -190,7 +199,7 @@ static const struct usb_device_id kvaser
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_2HS_V2_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_2CANLIN_PRODUCT_ID),
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_CANLIN_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_USBCAN_PRO_2HS_V2_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
+@@ -525,16 +525,23 @@ static void kvaser_usb_leaf_get_software
+       dev->fw_version = le32_to_cpu(softinfo->fw_version);
+       dev->max_tx_urbs = le16_to_cpu(softinfo->max_outstanding_tx);
+-      switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) {
+-      case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK:
++      if (dev->driver_info->quirks & KVASER_USB_QUIRK_IGNORE_CLK_FREQ) {
++              /* Firmware expects bittiming parameters calculated for 16MHz
++               * clock, regardless of the actual clock
++               */
+               dev->cfg = &kvaser_usb_leaf_dev_cfg_16mhz;
+-              break;
+-      case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK:
+-              dev->cfg = &kvaser_usb_leaf_dev_cfg_24mhz;
+-              break;
+-      case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK:
+-              dev->cfg = &kvaser_usb_leaf_dev_cfg_32mhz;
+-              break;
++      } else {
++              switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) {
++              case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK:
++                      dev->cfg = &kvaser_usb_leaf_dev_cfg_16mhz;
++                      break;
++              case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK:
++                      dev->cfg = &kvaser_usb_leaf_dev_cfg_24mhz;
++                      break;
++              case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK:
++                      dev->cfg = &kvaser_usb_leaf_dev_cfg_32mhz;
++                      break;
++              }
+       }
+ }
diff --git a/queue-4.19/can-kvaser_usb-replace-run-time-checks-with-struct-kvaser_usb_driver_info.patch b/queue-4.19/can-kvaser_usb-replace-run-time-checks-with-struct-kvaser_usb_driver_info.patch
new file mode 100644 (file)
index 0000000..08f2ce1
--- /dev/null
@@ -0,0 +1,619 @@
+From foo@baz Sun Jul 10 04:20:24 PM CEST 2022
+From: Jimmy Assarsson <extja@kvaser.com>
+Date: Fri,  8 Jul 2022 20:47:24 +0200
+Subject: can: kvaser_usb: replace run-time checks with struct kvaser_usb_driver_info
+To: stable@vger.kernel.org, linux-can@vger.kernel.org, Marc Kleine-Budde <mkl@pengutronix.de>
+Cc: Jimmy Assarsson <jimmyassarsson@gmail.com>, Jimmy Assarsson <extja@kvaser.com>
+Message-ID: <20220708184726.280961-2-extja@kvaser.com>
+
+From: Jimmy Assarsson <extja@kvaser.com>
+
+commit 49f274c72357d2d74cba70b172cf369768909707 upstream.
+
+Unify and move compile-time known information into new struct
+kvaser_usb_driver_info, in favor of run-time checks.
+
+All Kvaser USBcanII supports listen-only mode and error counter
+reporting.
+
+Link: https://lore.kernel.org/all/20220603083820.800246-2-extja@kvaser.com
+Suggested-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Cc: stable@vger.kernel.org
+Signed-off-by: Jimmy Assarsson <extja@kvaser.com>
+[mkl: move struct kvaser_usb_driver_info into kvaser_usb_core.c]
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/can/usb/kvaser_usb/kvaser_usb.h      |   22 +-
+ drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c |  244 ++++++++++++-----------
+ drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c |   24 +-
+ 3 files changed, 155 insertions(+), 135 deletions(-)
+
+--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
+@@ -35,9 +35,9 @@
+ #define KVASER_USB_RX_BUFFER_SIZE             3072
+ #define KVASER_USB_MAX_NET_DEVICES            5
+-/* USB devices features */
+-#define KVASER_USB_HAS_SILENT_MODE            BIT(0)
+-#define KVASER_USB_HAS_TXRX_ERRORS            BIT(1)
++/* Kvaser USB device quirks */
++#define KVASER_USB_QUIRK_HAS_SILENT_MODE      BIT(0)
++#define KVASER_USB_QUIRK_HAS_TXRX_ERRORS      BIT(1)
+ /* Device capabilities */
+ #define KVASER_USB_CAP_BERR_CAP                       0x01
+@@ -65,12 +65,7 @@ struct kvaser_usb_dev_card_data_hydra {
+ struct kvaser_usb_dev_card_data {
+       u32 ctrlmode_supported;
+       u32 capabilities;
+-      union {
+-              struct {
+-                      enum kvaser_usb_leaf_family family;
+-              } leaf;
+-              struct kvaser_usb_dev_card_data_hydra hydra;
+-      };
++      struct kvaser_usb_dev_card_data_hydra hydra;
+ };
+ /* Context for an outstanding, not yet ACKed, transmission */
+@@ -84,7 +79,7 @@ struct kvaser_usb {
+       struct usb_device *udev;
+       struct usb_interface *intf;
+       struct kvaser_usb_net_priv *nets[KVASER_USB_MAX_NET_DEVICES];
+-      const struct kvaser_usb_dev_ops *ops;
++      const struct kvaser_usb_driver_info *driver_info;
+       const struct kvaser_usb_dev_cfg *cfg;
+       struct usb_endpoint_descriptor *bulk_in, *bulk_out;
+@@ -166,6 +161,12 @@ struct kvaser_usb_dev_ops {
+                                 int *cmd_len, u16 transid);
+ };
++struct kvaser_usb_driver_info {
++      u32 quirks;
++      enum kvaser_usb_leaf_family family;
++      const struct kvaser_usb_dev_ops *ops;
++};
++
+ struct kvaser_usb_dev_cfg {
+       const struct can_clock clock;
+       const unsigned int timestamp_freq;
+@@ -185,4 +186,5 @@ int kvaser_usb_send_cmd_async(struct kva
+                             int len);
+ int kvaser_usb_can_rx_over_error(struct net_device *netdev);
++
+ #endif /* KVASER_USB_H */
+--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
+@@ -79,104 +79,125 @@
+ #define USB_ATI_MEMO_PRO_2HS_V2_PRODUCT_ID    269
+ #define USB_HYBRID_PRO_CANLIN_PRODUCT_ID      270
+-static inline bool kvaser_is_leaf(const struct usb_device_id *id)
+-{
+-      return (id->idProduct >= USB_LEAF_DEVEL_PRODUCT_ID &&
+-              id->idProduct <= USB_CAN_R_PRODUCT_ID) ||
+-              (id->idProduct >= USB_LEAF_LITE_V2_PRODUCT_ID &&
+-               id->idProduct <= USB_MINI_PCIE_2HS_PRODUCT_ID);
+-}
++static const struct kvaser_usb_driver_info kvaser_usb_driver_info_hydra = {
++      .quirks = 0,
++      .ops = &kvaser_usb_hydra_dev_ops,
++};
+-static inline bool kvaser_is_usbcan(const struct usb_device_id *id)
+-{
+-      return id->idProduct >= USB_USBCAN_REVB_PRODUCT_ID &&
+-             id->idProduct <= USB_MEMORATOR_PRODUCT_ID;
+-}
++static const struct kvaser_usb_driver_info kvaser_usb_driver_info_usbcan = {
++      .quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS |
++                KVASER_USB_QUIRK_HAS_SILENT_MODE,
++      .family = KVASER_USBCAN,
++      .ops = &kvaser_usb_leaf_dev_ops,
++};
+-static inline bool kvaser_is_hydra(const struct usb_device_id *id)
+-{
+-      return id->idProduct >= USB_BLACKBIRD_V2_PRODUCT_ID &&
+-             id->idProduct <= USB_HYBRID_PRO_CANLIN_PRODUCT_ID;
+-}
++static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf = {
++      .quirks = 0,
++      .family = KVASER_LEAF,
++      .ops = &kvaser_usb_leaf_dev_ops,
++};
++
++static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf_err = {
++      .quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS,
++      .family = KVASER_LEAF,
++      .ops = &kvaser_usb_leaf_dev_ops,
++};
++
++static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf_err_listen = {
++      .quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS |
++                KVASER_USB_QUIRK_HAS_SILENT_MODE,
++      .family = KVASER_LEAF,
++      .ops = &kvaser_usb_leaf_dev_ops,
++};
+ static const struct usb_device_id kvaser_usb_table[] = {
+       /* Leaf USB product IDs */
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_PRODUCT_ID) },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
+-                             KVASER_USB_HAS_SILENT_MODE },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
+-                             KVASER_USB_HAS_SILENT_MODE },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LS_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
+-                             KVASER_USB_HAS_SILENT_MODE },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_SWC_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
+-                             KVASER_USB_HAS_SILENT_MODE },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LIN_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
+-                             KVASER_USB_HAS_SILENT_MODE },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_LS_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
+-                             KVASER_USB_HAS_SILENT_MODE },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_SWC_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
+-                             KVASER_USB_HAS_SILENT_MODE },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_DEVEL_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
+-                             KVASER_USB_HAS_SILENT_MODE },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSHS_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
+-                             KVASER_USB_HAS_SILENT_MODE },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_UPRO_HSHS_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_GI_PRODUCT_ID) },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_GI_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_OBDII_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
+-                             KVASER_USB_HAS_SILENT_MODE },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSLS_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_CH_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_SPRO_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_MERCURY_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_LEAF_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_CAN_R_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_V2_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_HS_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_2HS_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_2HS_PRODUCT_ID) },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_V2_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_HS_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_2HS_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_2HS_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
+       /* USBCANII USB product IDs */
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN2_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_REVB_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMORATOR_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_VCI2_PRODUCT_ID),
+-              .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan },
+       /* Minihydra USB product IDs */
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_V2_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_5HS_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_5HS_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_4HS_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_HS_V2_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_2HS_V2_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_2HS_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_2HS_V2_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_CANLIN_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_USBCAN_PRO_2HS_V2_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_MEMO_PRO_2HS_V2_PRODUCT_ID) },
+-      { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_PRO_CANLIN_PRODUCT_ID) },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_V2_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_5HS_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_5HS_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_4HS_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_HS_V2_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_2HS_V2_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_2HS_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_2HS_V2_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_2CANLIN_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_USBCAN_PRO_2HS_V2_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_MEMO_PRO_2HS_V2_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
++      { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_PRO_CANLIN_PRODUCT_ID),
++              .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { }
+ };
+ MODULE_DEVICE_TABLE(usb, kvaser_usb_table);
+@@ -267,6 +288,7 @@ int kvaser_usb_can_rx_over_error(struct
+ static void kvaser_usb_read_bulk_callback(struct urb *urb)
+ {
+       struct kvaser_usb *dev = urb->context;
++      const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
+       int err;
+       unsigned int i;
+@@ -283,8 +305,8 @@ static void kvaser_usb_read_bulk_callbac
+               goto resubmit_urb;
+       }
+-      dev->ops->dev_read_bulk_callback(dev, urb->transfer_buffer,
+-                                       urb->actual_length);
++      ops->dev_read_bulk_callback(dev, urb->transfer_buffer,
++                                  urb->actual_length);
+ resubmit_urb:
+       usb_fill_bulk_urb(urb, dev->udev,
+@@ -378,6 +400,7 @@ static int kvaser_usb_open(struct net_de
+ {
+       struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+       struct kvaser_usb *dev = priv->dev;
++      const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
+       int err;
+       err = open_candev(netdev);
+@@ -388,11 +411,11 @@ static int kvaser_usb_open(struct net_de
+       if (err)
+               goto error;
+-      err = dev->ops->dev_set_opt_mode(priv);
++      err = ops->dev_set_opt_mode(priv);
+       if (err)
+               goto error;
+-      err = dev->ops->dev_start_chip(priv);
++      err = ops->dev_start_chip(priv);
+       if (err) {
+               netdev_warn(netdev, "Cannot start device, error %d\n", err);
+               goto error;
+@@ -449,22 +472,23 @@ static int kvaser_usb_close(struct net_d
+ {
+       struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+       struct kvaser_usb *dev = priv->dev;
++      const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
+       int err;
+       netif_stop_queue(netdev);
+-      err = dev->ops->dev_flush_queue(priv);
++      err = ops->dev_flush_queue(priv);
+       if (err)
+               netdev_warn(netdev, "Cannot flush queue, error %d\n", err);
+-      if (dev->ops->dev_reset_chip) {
+-              err = dev->ops->dev_reset_chip(dev, priv->channel);
++      if (ops->dev_reset_chip) {
++              err = ops->dev_reset_chip(dev, priv->channel);
+               if (err)
+                       netdev_warn(netdev, "Cannot reset card, error %d\n",
+                                   err);
+       }
+-      err = dev->ops->dev_stop_chip(priv);
++      err = ops->dev_stop_chip(priv);
+       if (err)
+               netdev_warn(netdev, "Cannot stop device, error %d\n", err);
+@@ -503,6 +527,7 @@ static netdev_tx_t kvaser_usb_start_xmit
+ {
+       struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+       struct kvaser_usb *dev = priv->dev;
++      const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
+       struct net_device_stats *stats = &netdev->stats;
+       struct kvaser_usb_tx_urb_context *context = NULL;
+       struct urb *urb;
+@@ -545,8 +570,8 @@ static netdev_tx_t kvaser_usb_start_xmit
+               goto freeurb;
+       }
+-      buf = dev->ops->dev_frame_to_cmd(priv, skb, &context->dlc, &cmd_len,
+-                                       context->echo_index);
++      buf = ops->dev_frame_to_cmd(priv, skb, &context->dlc, &cmd_len,
++                                  context->echo_index);
+       if (!buf) {
+               stats->tx_dropped++;
+               dev_kfree_skb(skb);
+@@ -630,15 +655,16 @@ static void kvaser_usb_remove_interfaces
+       }
+ }
+-static int kvaser_usb_init_one(struct kvaser_usb *dev,
+-                             const struct usb_device_id *id, int channel)
++static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
+ {
+       struct net_device *netdev;
+       struct kvaser_usb_net_priv *priv;
++      const struct kvaser_usb_driver_info *driver_info = dev->driver_info;
++      const struct kvaser_usb_dev_ops *ops = driver_info->ops;
+       int err;
+-      if (dev->ops->dev_reset_chip) {
+-              err = dev->ops->dev_reset_chip(dev, channel);
++      if (ops->dev_reset_chip) {
++              err = ops->dev_reset_chip(dev, channel);
+               if (err)
+                       return err;
+       }
+@@ -668,20 +694,19 @@ static int kvaser_usb_init_one(struct kv
+       priv->can.state = CAN_STATE_STOPPED;
+       priv->can.clock.freq = dev->cfg->clock.freq;
+       priv->can.bittiming_const = dev->cfg->bittiming_const;
+-      priv->can.do_set_bittiming = dev->ops->dev_set_bittiming;
+-      priv->can.do_set_mode = dev->ops->dev_set_mode;
+-      if ((id->driver_info & KVASER_USB_HAS_TXRX_ERRORS) ||
++      priv->can.do_set_bittiming = ops->dev_set_bittiming;
++      priv->can.do_set_mode = ops->dev_set_mode;
++      if ((driver_info->quirks & KVASER_USB_QUIRK_HAS_TXRX_ERRORS) ||
+           (priv->dev->card_data.capabilities & KVASER_USB_CAP_BERR_CAP))
+-              priv->can.do_get_berr_counter = dev->ops->dev_get_berr_counter;
+-      if (id->driver_info & KVASER_USB_HAS_SILENT_MODE)
++              priv->can.do_get_berr_counter = ops->dev_get_berr_counter;
++      if (driver_info->quirks & KVASER_USB_QUIRK_HAS_SILENT_MODE)
+               priv->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
+       priv->can.ctrlmode_supported |= dev->card_data.ctrlmode_supported;
+       if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) {
+               priv->can.data_bittiming_const = dev->cfg->data_bittiming_const;
+-              priv->can.do_set_data_bittiming =
+-                                      dev->ops->dev_set_data_bittiming;
++              priv->can.do_set_data_bittiming = ops->dev_set_data_bittiming;
+       }
+       netdev->flags |= IFF_ECHO;
+@@ -712,29 +737,22 @@ static int kvaser_usb_probe(struct usb_i
+       struct kvaser_usb *dev;
+       int err;
+       int i;
++      const struct kvaser_usb_driver_info *driver_info;
++      const struct kvaser_usb_dev_ops *ops;
++
++      driver_info = (const struct kvaser_usb_driver_info *)id->driver_info;
++      if (!driver_info)
++              return -ENODEV;
+       dev = devm_kzalloc(&intf->dev, sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+-      if (kvaser_is_leaf(id)) {
+-              dev->card_data.leaf.family = KVASER_LEAF;
+-              dev->ops = &kvaser_usb_leaf_dev_ops;
+-      } else if (kvaser_is_usbcan(id)) {
+-              dev->card_data.leaf.family = KVASER_USBCAN;
+-              dev->ops = &kvaser_usb_leaf_dev_ops;
+-      } else if (kvaser_is_hydra(id)) {
+-              dev->ops = &kvaser_usb_hydra_dev_ops;
+-      } else {
+-              dev_err(&intf->dev,
+-                      "Product ID (%d) is not a supported Kvaser USB device\n",
+-                      id->idProduct);
+-              return -ENODEV;
+-      }
+-
+       dev->intf = intf;
++      dev->driver_info = driver_info;
++      ops = driver_info->ops;
+-      err = dev->ops->dev_setup_endpoints(dev);
++      err = ops->dev_setup_endpoints(dev);
+       if (err) {
+               dev_err(&intf->dev, "Cannot get usb endpoint(s)");
+               return err;
+@@ -748,22 +766,22 @@ static int kvaser_usb_probe(struct usb_i
+       dev->card_data.ctrlmode_supported = 0;
+       dev->card_data.capabilities = 0;
+-      err = dev->ops->dev_init_card(dev);
++      err = ops->dev_init_card(dev);
+       if (err) {
+               dev_err(&intf->dev,
+                       "Failed to initialize card, error %d\n", err);
+               return err;
+       }
+-      err = dev->ops->dev_get_software_info(dev);
++      err = ops->dev_get_software_info(dev);
+       if (err) {
+               dev_err(&intf->dev,
+                       "Cannot get software info, error %d\n", err);
+               return err;
+       }
+-      if (dev->ops->dev_get_software_details) {
+-              err = dev->ops->dev_get_software_details(dev);
++      if (ops->dev_get_software_details) {
++              err = ops->dev_get_software_details(dev);
+               if (err) {
+                       dev_err(&intf->dev,
+                               "Cannot get software details, error %d\n", err);
+@@ -781,14 +799,14 @@ static int kvaser_usb_probe(struct usb_i
+       dev_dbg(&intf->dev, "Max outstanding tx = %d URBs\n", dev->max_tx_urbs);
+-      err = dev->ops->dev_get_card_info(dev);
++      err = ops->dev_get_card_info(dev);
+       if (err) {
+               dev_err(&intf->dev, "Cannot get card info, error %d\n", err);
+               return err;
+       }
+-      if (dev->ops->dev_get_capabilities) {
+-              err = dev->ops->dev_get_capabilities(dev);
++      if (ops->dev_get_capabilities) {
++              err = ops->dev_get_capabilities(dev);
+               if (err) {
+                       dev_err(&intf->dev,
+                               "Cannot get capabilities, error %d\n", err);
+@@ -798,7 +816,7 @@ static int kvaser_usb_probe(struct usb_i
+       }
+       for (i = 0; i < dev->nchannels; i++) {
+-              err = kvaser_usb_init_one(dev, id, i);
++              err = kvaser_usb_init_one(dev, i);
+               if (err) {
+                       kvaser_usb_remove_interfaces(dev);
+                       return err;
+--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
+@@ -405,7 +405,7 @@ kvaser_usb_leaf_frame_to_cmd(const struc
+                                     sizeof(struct kvaser_cmd_tx_can);
+               cmd->u.tx_can.channel = priv->channel;
+-              switch (dev->card_data.leaf.family) {
++              switch (dev->driver_info->family) {
+               case KVASER_LEAF:
+                       cmd_tx_can_flags = &cmd->u.tx_can.leaf.flags;
+                       break;
+@@ -551,7 +551,7 @@ static int kvaser_usb_leaf_get_software_
+       if (err)
+               return err;
+-      switch (dev->card_data.leaf.family) {
++      switch (dev->driver_info->family) {
+       case KVASER_LEAF:
+               kvaser_usb_leaf_get_software_info_leaf(dev, &cmd.u.leaf.softinfo);
+               break;
+@@ -598,7 +598,7 @@ static int kvaser_usb_leaf_get_card_info
+       dev->nchannels = cmd.u.cardinfo.nchannels;
+       if (dev->nchannels > KVASER_USB_MAX_NET_DEVICES ||
+-          (dev->card_data.leaf.family == KVASER_USBCAN &&
++          (dev->driver_info->family == KVASER_USBCAN &&
+            dev->nchannels > MAX_USBCAN_NET_DEVICES))
+               return -EINVAL;
+@@ -734,7 +734,7 @@ kvaser_usb_leaf_rx_error_update_can_stat
+           new_state < CAN_STATE_BUS_OFF)
+               priv->can.can_stats.restarts++;
+-      switch (dev->card_data.leaf.family) {
++      switch (dev->driver_info->family) {
+       case KVASER_LEAF:
+               if (es->leaf.error_factor) {
+                       priv->can.can_stats.bus_error++;
+@@ -813,7 +813,7 @@ static void kvaser_usb_leaf_rx_error(con
+               }
+       }
+-      switch (dev->card_data.leaf.family) {
++      switch (dev->driver_info->family) {
+       case KVASER_LEAF:
+               if (es->leaf.error_factor) {
+                       cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
+@@ -1005,7 +1005,7 @@ static void kvaser_usb_leaf_rx_can_msg(c
+       stats = &priv->netdev->stats;
+       if ((cmd->u.rx_can_header.flag & MSG_FLAG_ERROR_FRAME) &&
+-          (dev->card_data.leaf.family == KVASER_LEAF &&
++          (dev->driver_info->family == KVASER_LEAF &&
+            cmd->id == CMD_LEAF_LOG_MESSAGE)) {
+               kvaser_usb_leaf_leaf_rx_error(dev, cmd);
+               return;
+@@ -1021,7 +1021,7 @@ static void kvaser_usb_leaf_rx_can_msg(c
+               return;
+       }
+-      switch (dev->card_data.leaf.family) {
++      switch (dev->driver_info->family) {
+       case KVASER_LEAF:
+               rx_data = cmd->u.leaf.rx_can.data;
+               break;
+@@ -1036,7 +1036,7 @@ static void kvaser_usb_leaf_rx_can_msg(c
+               return;
+       }
+-      if (dev->card_data.leaf.family == KVASER_LEAF && cmd->id ==
++      if (dev->driver_info->family == KVASER_LEAF && cmd->id ==
+           CMD_LEAF_LOG_MESSAGE) {
+               cf->can_id = le32_to_cpu(cmd->u.leaf.log_message.id);
+               if (cf->can_id & KVASER_EXTENDED_FRAME)
+@@ -1133,14 +1133,14 @@ static void kvaser_usb_leaf_handle_comma
+               break;
+       case CMD_LEAF_LOG_MESSAGE:
+-              if (dev->card_data.leaf.family != KVASER_LEAF)
++              if (dev->driver_info->family != KVASER_LEAF)
+                       goto warn;
+               kvaser_usb_leaf_rx_can_msg(dev, cmd);
+               break;
+       case CMD_CHIP_STATE_EVENT:
+       case CMD_CAN_ERROR_EVENT:
+-              if (dev->card_data.leaf.family == KVASER_LEAF)
++              if (dev->driver_info->family == KVASER_LEAF)
+                       kvaser_usb_leaf_leaf_rx_error(dev, cmd);
+               else
+                       kvaser_usb_leaf_usbcan_rx_error(dev, cmd);
+@@ -1152,12 +1152,12 @@ static void kvaser_usb_leaf_handle_comma
+       /* Ignored commands */
+       case CMD_USBCAN_CLOCK_OVERFLOW_EVENT:
+-              if (dev->card_data.leaf.family != KVASER_USBCAN)
++              if (dev->driver_info->family != KVASER_USBCAN)
+                       goto warn;
+               break;
+       case CMD_FLUSH_QUEUE_REPLY:
+-              if (dev->card_data.leaf.family != KVASER_LEAF)
++              if (dev->driver_info->family != KVASER_LEAF)
+                       goto warn;
+               break;
diff --git a/queue-4.19/powerpc-powernv-delay-rng-platform-device-creation-until-later-in-boot.patch b/queue-4.19/powerpc-powernv-delay-rng-platform-device-creation-until-later-in-boot.patch
new file mode 100644 (file)
index 0000000..6b77703
--- /dev/null
@@ -0,0 +1,73 @@
+From 887502826549caa7e4215fd9e628f48f14c0825a Mon Sep 17 00:00:00 2001
+From: "Jason A. Donenfeld" <Jason@zx2c4.com>
+Date: Thu, 30 Jun 2022 14:16:54 +0200
+Subject: powerpc/powernv: delay rng platform device creation until later in boot
+
+From: Jason A. Donenfeld <Jason@zx2c4.com>
+
+commit 887502826549caa7e4215fd9e628f48f14c0825a upstream.
+
+The platform device for the rng must be created much later in boot.
+Otherwise it tries to connect to a parent that doesn't yet exist,
+resulting in this splat:
+
+  [    0.000478] kobject: '(null)' ((____ptrval____)): is not initialized, yet kobject_get() is being called.
+  [    0.002925] [c000000002a0fb30] [c00000000073b0bc] kobject_get+0x8c/0x100 (unreliable)
+  [    0.003071] [c000000002a0fba0] [c00000000087e464] device_add+0xf4/0xb00
+  [    0.003194] [c000000002a0fc80] [c000000000a7f6e4] of_device_add+0x64/0x80
+  [    0.003321] [c000000002a0fcb0] [c000000000a800d0] of_platform_device_create_pdata+0xd0/0x1b0
+  [    0.003476] [c000000002a0fd00] [c00000000201fa44] pnv_get_random_long_early+0x240/0x2e4
+  [    0.003623] [c000000002a0fe20] [c000000002060c38] random_init+0xc0/0x214
+
+This patch fixes the issue by doing the platform device creation inside
+of machine_subsys_initcall.
+
+Fixes: f3eac426657d ("powerpc/powernv: wire up rng during setup_arch")
+Cc: stable@vger.kernel.org
+Reported-by: Sachin Sant <sachinp@linux.ibm.com>
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Tested-by: Sachin Sant <sachinp@linux.ibm.com>
+[mpe: Change "of node" to "platform device" in change log]
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20220630121654.1939181-1-Jason@zx2c4.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/powerpc/platforms/powernv/rng.c |   16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+--- a/arch/powerpc/platforms/powernv/rng.c
++++ b/arch/powerpc/platforms/powernv/rng.c
+@@ -180,12 +180,8 @@ static int __init pnv_get_random_long_ea
+                   NULL) != pnv_get_random_long_early)
+               return 0;
+-      for_each_compatible_node(dn, NULL, "ibm,power-rng") {
+-              if (rng_create(dn))
+-                      continue;
+-              /* Create devices for hwrng driver */
+-              of_platform_device_create(dn, NULL, NULL);
+-      }
++      for_each_compatible_node(dn, NULL, "ibm,power-rng")
++              rng_create(dn);
+       if (!ppc_md.get_random_seed)
+               return 0;
+@@ -209,10 +205,18 @@ void __init pnv_rng_init(void)
+ static int __init pnv_rng_late_init(void)
+ {
++      struct device_node *dn;
+       unsigned long v;
++
+       /* In case it wasn't called during init for some other reason. */
+       if (ppc_md.get_random_seed == pnv_get_random_long_early)
+               pnv_get_random_long_early(&v);
++
++      if (ppc_md.get_random_seed == powernv_get_random_long) {
++              for_each_compatible_node(dn, NULL, "ibm,power-rng")
++                      of_platform_device_create(dn, NULL, NULL);
++      }
++
+       return 0;
+ }
+ machine_subsys_initcall(powernv, pnv_rng_late_init);
index 589234c64069f0bb4a9d56ad985ed87c22d9f230..0a77dd642a81288faf8c1cd319f5ae7de0085486 100644 (file)
@@ -8,3 +8,7 @@ net-rose-fix-uaf-bug-caused-by-rose_t0timer_expiry.patch
 iommu-vt-d-fix-pci-bus-rescan-device-hot-add.patch
 fbcon-disallow-setting-font-bigger-than-screen-size.patch
 video-of_display_timing.h-include-errno.h.patch
+powerpc-powernv-delay-rng-platform-device-creation-until-later-in-boot.patch
+can-kvaser_usb-replace-run-time-checks-with-struct-kvaser_usb_driver_info.patch
+can-kvaser_usb-kvaser_usb_leaf-fix-can-clock-frequency-regression.patch
+can-kvaser_usb-kvaser_usb_leaf-fix-bittiming-limits.patch