diff options
author | Stephane Grosjean <s.grosjean@peak-system.com> | 2018-06-21 09:23:31 -0400 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2018-07-23 08:34:45 -0400 |
commit | 5d4c94ed9f564224d7b37dbee13f7c5d4a8a01ac (patch) | |
tree | e8a0111772874e1ca329d7f0a17cc389c7e72eaa | |
parent | c9ce1fa1c24b08e13c2a3b5b1f94a19c9eaa982c (diff) |
can: peak_canfd: fix firmware < v3.3.0: limit allocation to 32-bit DMA addr only
The DMA logic in firmwares < v3.3.0 embedded in the PCAN-PCIe FD cards
family is not capable of handling a mix of 32-bit and 64-bit logical
addresses. If the board is equipped with 2 or 4 CAN ports, then such a
situation might lead to a PCIe Bus Error "Malformed TLP" packet
as well as "irq xx: nobody cared" issue.
This patch adds a workaround that requests only 32-bit DMA addresses
when these might be allocated outside of the 4 GB area.
This issue has been fixed in firmware v3.3.0 and next.
Signed-off-by: Stephane Grosjean <s.grosjean@peak-system.com>
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r-- | drivers/net/can/peak_canfd/peak_pciefd_main.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/net/can/peak_canfd/peak_pciefd_main.c b/drivers/net/can/peak_canfd/peak_pciefd_main.c index b9e28578bc7b..455a3797a200 100644 --- a/drivers/net/can/peak_canfd/peak_pciefd_main.c +++ b/drivers/net/can/peak_canfd/peak_pciefd_main.c | |||
@@ -58,6 +58,10 @@ MODULE_LICENSE("GPL v2"); | |||
58 | #define PCIEFD_REG_SYS_VER1 0x0040 /* version reg #1 */ | 58 | #define PCIEFD_REG_SYS_VER1 0x0040 /* version reg #1 */ |
59 | #define PCIEFD_REG_SYS_VER2 0x0044 /* version reg #2 */ | 59 | #define PCIEFD_REG_SYS_VER2 0x0044 /* version reg #2 */ |
60 | 60 | ||
61 | #define PCIEFD_FW_VERSION(x, y, z) (((u32)(x) << 24) | \ | ||
62 | ((u32)(y) << 16) | \ | ||
63 | ((u32)(z) << 8)) | ||
64 | |||
61 | /* System Control Registers Bits */ | 65 | /* System Control Registers Bits */ |
62 | #define PCIEFD_SYS_CTL_TS_RST 0x00000001 /* timestamp clock */ | 66 | #define PCIEFD_SYS_CTL_TS_RST 0x00000001 /* timestamp clock */ |
63 | #define PCIEFD_SYS_CTL_CLK_EN 0x00000002 /* system clock */ | 67 | #define PCIEFD_SYS_CTL_CLK_EN 0x00000002 /* system clock */ |
@@ -782,6 +786,21 @@ static int peak_pciefd_probe(struct pci_dev *pdev, | |||
782 | "%ux CAN-FD PCAN-PCIe FPGA v%u.%u.%u:\n", can_count, | 786 | "%ux CAN-FD PCAN-PCIe FPGA v%u.%u.%u:\n", can_count, |
783 | hw_ver_major, hw_ver_minor, hw_ver_sub); | 787 | hw_ver_major, hw_ver_minor, hw_ver_sub); |
784 | 788 | ||
789 | #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT | ||
790 | /* FW < v3.3.0 DMA logic doesn't handle correctly the mix of 32-bit and | ||
791 | * 64-bit logical addresses: this workaround forces usage of 32-bit | ||
792 | * DMA addresses only when such a fw is detected. | ||
793 | */ | ||
794 | if (PCIEFD_FW_VERSION(hw_ver_major, hw_ver_minor, hw_ver_sub) < | ||
795 | PCIEFD_FW_VERSION(3, 3, 0)) { | ||
796 | err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); | ||
797 | if (err) | ||
798 | dev_warn(&pdev->dev, | ||
799 | "warning: can't set DMA mask %llxh (err %d)\n", | ||
800 | DMA_BIT_MASK(32), err); | ||
801 | } | ||
802 | #endif | ||
803 | |||
785 | /* stop system clock */ | 804 | /* stop system clock */ |
786 | pciefd_sys_writereg(pciefd, PCIEFD_SYS_CTL_CLK_EN, | 805 | pciefd_sys_writereg(pciefd, PCIEFD_SYS_CTL_CLK_EN, |
787 | PCIEFD_REG_SYS_CTL_CLR); | 806 | PCIEFD_REG_SYS_CTL_CLR); |