From a6bf3eea97c83deb5e50a9bcc826ae319c4b64f9 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Oct 13 2020 13:49:03 +0000 Subject: Merge branch 'SLE12-SP5' (4962a63a9a8b) into 'SLE12-SP5-RT' - No -rt specific changes this merge. --- diff --git a/patches.suse/0001-net-8390-Fix-manufacturer-name-in-Kconfig-help-text.patch b/patches.suse/0001-net-8390-Fix-manufacturer-name-in-Kconfig-help-text.patch new file mode 100644 index 0000000..0e3f51e --- /dev/null +++ b/patches.suse/0001-net-8390-Fix-manufacturer-name-in-Kconfig-help-text.patch @@ -0,0 +1,37 @@ +From 44b1650d2d69b0c5afc39ae0360f012edf1cdbf7 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Wed, 31 Jul 2019 15:22:09 +0200 +Subject: [PATCH 01/59] net: 8390: Fix manufacturer name in Kconfig help text +References: git-fixes +Patch-mainline: v5.3-rc4 +Git-commit: 14f1c0f2ff156c89b14fa4c52605e7586436ffb8 + +The help text refers to Western Digital instead of National +Semiconductor 8390, presumably because it was copied from the former. + +Fixes: 644570b830266ff3 ("8390: Move the 8390 related drivers") +Signed-off-by: Geert Uytterhoeven +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/8390/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/8390/Kconfig b/drivers/net/ethernet/8390/Kconfig +index 29c3075bfb05..22fe2cf97d8d 100644 +--- a/drivers/net/ethernet/8390/Kconfig ++++ b/drivers/net/ethernet/8390/Kconfig +@@ -11,8 +11,8 @@ config NET_VENDOR_8390 + + Note that the answer to this question doesn't directly affect the + kernel: saying N will just cause the configurator to skip all +- the questions about Western Digital cards. If you say Y, you will be +- asked for your specific card in the following questions. ++ the questions about National Semiconductor 8390 cards. If you say Y, ++ you will be asked for your specific card in the following questions. + + if NET_VENDOR_8390 + +-- +2.16.4 + diff --git a/patches.suse/0002-net-apple-Fix-manufacturer-name-in-Kconfig-help-text.patch b/patches.suse/0002-net-apple-Fix-manufacturer-name-in-Kconfig-help-text.patch new file mode 100644 index 0000000..b5d5c5b --- /dev/null +++ b/patches.suse/0002-net-apple-Fix-manufacturer-name-in-Kconfig-help-text.patch @@ -0,0 +1,37 @@ +From 79025558d4ed7d26470c463c98fd7f4f725e9f90 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Wed, 31 Jul 2019 15:22:11 +0200 +Subject: [PATCH 02/59] net: apple: Fix manufacturer name in Kconfig help text +References: git-fixes +Patch-mainline: v5.3-rc4 +Git-commit: ac0e3f20c7a9fbace30d38e7d306ab15f3e6fd31 + +The help text refers to IBM instead of Apple, presumably because it was +copied from the former. + +Fixes: 8fb6b0908176704a ("bmac/mace/macmace/mac89x0/cs89x0: Move the Macintosh (Apple) drivers") +Signed-off-by: Geert Uytterhoeven +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/apple/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/apple/Kconfig b/drivers/net/ethernet/apple/Kconfig +index 31071297896c..1de1c76a535a 100644 +--- a/drivers/net/ethernet/apple/Kconfig ++++ b/drivers/net/ethernet/apple/Kconfig +@@ -10,8 +10,8 @@ config NET_VENDOR_APPLE + If you have a network (Ethernet) card belonging to this class, say Y. + + Note that the answer to this question doesn't directly affect the +- kernel: saying N will just cause the configurator to skip all +- the questions about IBM devices. If you say Y, you will be asked for ++ kernel: saying N will just cause the configurator to skip all the ++ questions about Apple devices. If you say Y, you will be asked for + your specific card in the following questions. + + if NET_VENDOR_APPLE +-- +2.16.4 + diff --git a/patches.suse/0003-net-broadcom-Fix-manufacturer-name-in-Kconfig-help-t.patch b/patches.suse/0003-net-broadcom-Fix-manufacturer-name-in-Kconfig-help-t.patch new file mode 100644 index 0000000..ff1d06e --- /dev/null +++ b/patches.suse/0003-net-broadcom-Fix-manufacturer-name-in-Kconfig-help-t.patch @@ -0,0 +1,40 @@ +From 2154721c60e9070a1bd530448f7f1306418905af Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Wed, 31 Jul 2019 15:22:12 +0200 +Subject: [PATCH 03/59] net: broadcom: Fix manufacturer name in Kconfig help + text +References: git-fixes +Patch-mainline: v5.3-rc4 +Git-commit: aca3432a607b6f9db2a9fe34f4b87d01cd99a68a + +The help text refers to AMD instead of Broadcom, presumably because it +was copied from the former. + +Fixes: adfc5217e9db68d3 ("broadcom: Move the Broadcom drivers") +Signed-off-by: Geert Uytterhoeven +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/broadcom/Kconfig | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig +index d38f3fdc2417..982fcf18c87c 100644 +--- a/drivers/net/ethernet/broadcom/Kconfig ++++ b/drivers/net/ethernet/broadcom/Kconfig +@@ -12,9 +12,9 @@ config NET_VENDOR_BROADCOM + say Y. + + Note that the answer to this question does not directly affect +- the kernel: saying N will just case the configurator to skip all +- the questions regarding AMD chipsets. If you say Y, you will be asked +- for your specific chipset/driver in the following questions. ++ the kernel: saying N will just cause the configurator to skip all ++ the questions regarding Broadcom chipsets. If you say Y, you will ++ be asked for your specific chipset/driver in the following questions. + + if NET_VENDOR_BROADCOM + +-- +2.16.4 + diff --git a/patches.suse/0004-net-mvmdio-defer-probe-of-orion-mdio-if-a-clock-is-n.patch b/patches.suse/0004-net-mvmdio-defer-probe-of-orion-mdio-if-a-clock-is-n.patch new file mode 100644 index 0000000..a6a942a --- /dev/null +++ b/patches.suse/0004-net-mvmdio-defer-probe-of-orion-mdio-if-a-clock-is-n.patch @@ -0,0 +1,47 @@ +From 877ea6eae8dfbd5dc4cf348597e91c801cb0abe1 Mon Sep 17 00:00:00 2001 +From: Josua Mayer +Date: Tue, 9 Jul 2019 15:01:01 +0200 +Subject: [PATCH 04/59] net: mvmdio: defer probe of orion-mdio if a clock is + not ready +References: git-fixes +Patch-mainline: v5.3-rc1 +Git-commit: 433a06d7d74e677c40b1148c70c48677ff62fb6b + +Defer probing of the orion-mdio interface when getting a clock returns +EPROBE_DEFER. This avoids locking up the Armada 8k SoC when mdio is used +before all clocks have been enabled. + +Signed-off-by: Josua Mayer +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/marvell/mvmdio.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c +index 0a254fede597..b6ff143c9cff 100644 +--- a/drivers/net/ethernet/marvell/mvmdio.c ++++ b/drivers/net/ethernet/marvell/mvmdio.c +@@ -321,6 +321,10 @@ static int orion_mdio_probe(struct platform_device *pdev) + + for (i = 0; i < ARRAY_SIZE(dev->clk); i++) { + dev->clk[i] = of_clk_get(pdev->dev.of_node, i); ++ if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) { ++ ret = -EPROBE_DEFER; ++ goto out_clk; ++ } + if (IS_ERR(dev->clk[i])) + break; + clk_prepare_enable(dev->clk[i]); +@@ -365,6 +369,7 @@ static int orion_mdio_probe(struct platform_device *pdev) + if (dev->err_interrupt > 0) + writel(0, dev->regs + MVMDIO_ERR_INT_MASK); + ++out_clk: + for (i = 0; i < ARRAY_SIZE(dev->clk); i++) { + if (IS_ERR(dev->clk[i])) + break; +-- +2.16.4 + diff --git a/patches.suse/0005-drivers-net-ethernet-marvell-mvmdio.c-Fix-non-OF-cas.patch b/patches.suse/0005-drivers-net-ethernet-marvell-mvmdio.c-Fix-non-OF-cas.patch new file mode 100644 index 0000000..30f99ca --- /dev/null +++ b/patches.suse/0005-drivers-net-ethernet-marvell-mvmdio.c-Fix-non-OF-cas.patch @@ -0,0 +1,70 @@ +From c4cc2f82e6967c327932f79c524250ca163d8684 Mon Sep 17 00:00:00 2001 +From: "Arnaud Patard (Rtp)" +Date: Fri, 2 Aug 2019 10:32:40 +0200 +Subject: [PATCH 05/59] drivers/net/ethernet/marvell/mvmdio.c: Fix non OF case +References: git-fixes +Patch-mainline: v5.3-rc4 +Git-commit: d934423ac26ed373dfe089734d505dca5ff679b6 + +Orion5.x systems are still using machine files and not device-tree. +Commit 96cb4342382290c9 ("net: mvmdio: allow up to three clocks to be +specified for orion-mdio") has replaced devm_clk_get() with of_clk_get(), +leading to a oops at boot and not working network, as reported in +https://lists.debian.org/debian-arm/2019/07/msg00088.html and possibly in +https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=908712. + +Link: https://lists.debian.org/debian-arm/2019/07/msg00088.html +Fixes: 96cb4342382290c9 ("net: mvmdio: allow up to three clocks to be specified for orion-mdio") +Signed-off-by: Arnaud Patard +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/marvell/mvmdio.c | 28 ++++++++++++++++++++++------ + 1 file changed, 22 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c +index b6ff143c9cff..7a03d5fb493c 100644 +--- a/drivers/net/ethernet/marvell/mvmdio.c ++++ b/drivers/net/ethernet/marvell/mvmdio.c +@@ -319,15 +319,31 @@ static int orion_mdio_probe(struct platform_device *pdev) + + init_waitqueue_head(&dev->smi_busy_wait); + +- for (i = 0; i < ARRAY_SIZE(dev->clk); i++) { +- dev->clk[i] = of_clk_get(pdev->dev.of_node, i); +- if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) { ++ if (pdev->dev.of_node) { ++ for (i = 0; i < ARRAY_SIZE(dev->clk); i++) { ++ dev->clk[i] = of_clk_get(pdev->dev.of_node, i); ++ if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) { ++ ret = -EPROBE_DEFER; ++ goto out_clk; ++ } ++ if (IS_ERR(dev->clk[i])) ++ break; ++ clk_prepare_enable(dev->clk[i]); ++ } ++ ++ if (!IS_ERR(of_clk_get(pdev->dev.of_node, ++ ARRAY_SIZE(dev->clk)))) ++ dev_warn(&pdev->dev, ++ "unsupported number of clocks, limiting to the first " ++ __stringify(ARRAY_SIZE(dev->clk)) "\n"); ++ } else { ++ dev->clk[0] = clk_get(&pdev->dev, NULL); ++ if (PTR_ERR(dev->clk[0]) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + goto out_clk; + } +- if (IS_ERR(dev->clk[i])) +- break; +- clk_prepare_enable(dev->clk[i]); ++ if (!IS_ERR(dev->clk[0])) ++ clk_prepare_enable(dev->clk[0]); + } + + dev->err_interrupt = platform_get_irq(pdev, 0); +-- +2.16.4 + diff --git a/patches.suse/0006-net-tc35815-Explicitly-check-NET_IP_ALIGN-is-not-zer.patch b/patches.suse/0006-net-tc35815-Explicitly-check-NET_IP_ALIGN-is-not-zer.patch new file mode 100644 index 0000000..622e9f5 --- /dev/null +++ b/patches.suse/0006-net-tc35815-Explicitly-check-NET_IP_ALIGN-is-not-zer.patch @@ -0,0 +1,56 @@ +From f909de7dead71a47a487c6ad76c7e788b5e1806b Mon Sep 17 00:00:00 2001 +From: Nathan Chancellor +Date: Sun, 11 Aug 2019 20:13:45 -0700 +Subject: [PATCH 06/59] net: tc35815: Explicitly check NET_IP_ALIGN is not zero + in tc35815_rx +References: git-fixes +Patch-mainline: v5.3-rc6 +Git-commit: 125b7e0949d4e72b15c2b1a1590f8cece985a918 + +clang warns: + +drivers/net/ethernet/toshiba/tc35815.c:1507:30: warning: use of logical +'&&' with constant operand [-Wconstant-logical-operand] + if (!HAVE_DMA_RXALIGN(lp) && NET_IP_ALIGN) + ^ ~~~~~~~~~~~~ +drivers/net/ethernet/toshiba/tc35815.c:1507:30: note: use '&' for a +bitwise operation + if (!HAVE_DMA_RXALIGN(lp) && NET_IP_ALIGN) + ^~ + & +drivers/net/ethernet/toshiba/tc35815.c:1507:30: note: remove constant to +silence this warning + if (!HAVE_DMA_RXALIGN(lp) && NET_IP_ALIGN) + ~^~~~~~~~~~~~~~~ +1 warning generated. + +Explicitly check that NET_IP_ALIGN is not zero, which matches how this +is checked in other parts of the tree. Because NET_IP_ALIGN is a build +time constant, this check will be constant folded away during +optimization. + +Fixes: 82a9928db560 ("tc35815: Enable StripCRC feature") +Link: https://github.com/ClangBuiltLinux/linux/issues/608 +Signed-off-by: Nathan Chancellor +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/toshiba/tc35815.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c +index d9db8a06afd2..7d873a1b66f0 100644 +--- a/drivers/net/ethernet/toshiba/tc35815.c ++++ b/drivers/net/ethernet/toshiba/tc35815.c +@@ -1497,7 +1497,7 @@ tc35815_rx(struct net_device *dev, int limit) + pci_unmap_single(lp->pci_dev, + lp->rx_skbs[cur_bd].skb_dma, + RX_BUF_SIZE, PCI_DMA_FROMDEVICE); +- if (!HAVE_DMA_RXALIGN(lp) && NET_IP_ALIGN) ++ if (!HAVE_DMA_RXALIGN(lp) && NET_IP_ALIGN != 0) + memmove(skb->data, skb->data - NET_IP_ALIGN, + pkt_len); + data = skb_put(skb, pkt_len); +-- +2.16.4 + diff --git a/patches.suse/0007-amd-xgbe-Fix-debug-output-of-max-channel-counts.patch b/patches.suse/0007-amd-xgbe-Fix-debug-output-of-max-channel-counts.patch new file mode 100644 index 0000000..1e8091d --- /dev/null +++ b/patches.suse/0007-amd-xgbe-Fix-debug-output-of-max-channel-counts.patch @@ -0,0 +1,35 @@ +From 2bbb944ee721ad7a0c3cf4d4390388294e40005e Mon Sep 17 00:00:00 2001 +From: Tom Lendacky +Date: Wed, 23 May 2018 11:38:11 -0500 +Subject: [PATCH 07/59] amd-xgbe: Fix debug output of max channel counts +References: git-fixes +Patch-mainline: v4.18-rc1 +Git-commit: 6c2799c11e3681729f448706e6484cffad8a5633 + +A debug output print statement uses the wrong variable to output the +maximum Rx channel count (cut and paste error, basically). Fix the +statement to use the proper variable. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-pci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +index b0b0ac74f641..4f1538a84774 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +@@ -338,7 +338,7 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + if (netif_msg_probe(pdata)) { + dev_dbg(dev, "max tx/rx channel count = %u/%u\n", + pdata->tx_max_channel_count, +- pdata->tx_max_channel_count); ++ pdata->rx_max_channel_count); + dev_dbg(dev, "max tx/rx hw queue count = %u/%u\n", + pdata->tx_max_q_count, pdata->rx_max_q_count); + } +-- +2.16.4 + diff --git a/patches.suse/0008-amd-xgbe-Read-and-save-the-port-property-registers-d.patch b/patches.suse/0008-amd-xgbe-Read-and-save-the-port-property-registers-d.patch new file mode 100644 index 0000000..cfb6910 --- /dev/null +++ b/patches.suse/0008-amd-xgbe-Read-and-save-the-port-property-registers-d.patch @@ -0,0 +1,247 @@ +From 4a5412e756b6186402c8edf1818bd36c17543976 Mon Sep 17 00:00:00 2001 +From: Tom Lendacky +Date: Wed, 23 May 2018 11:38:20 -0500 +Subject: [PATCH 08/59] amd-xgbe: Read and save the port property registers + during probe +References: git-fixes +Patch-mainline: v4.18-rc1 +Git-commit: b93c3ab6006b379f2df238693b6e131cba9b37b3 + +Read and save the port property registers once during the device probe +and then use the saved values as they are needed. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-pci.c | 34 +++++++++++---- + drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 68 ++++++++++++----------------- + drivers/net/ethernet/amd/xgbe/xgbe.h | 7 +++ + 3 files changed, 62 insertions(+), 47 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +index 4f1538a84774..bd1eb9de2f34 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +@@ -331,12 +331,29 @@ static int xgbe_pci_probe(struct pci_dev + pdata->awcr = XGBE_DMA_PCI_AWCR; + pdata->awarcr = XGBE_DMA_PCI_AWARCR; + ++ /* Read the port property registers */ ++ pdata->pp0 = XP_IOREAD(pdata, XP_PROP_0); ++ pdata->pp1 = XP_IOREAD(pdata, XP_PROP_1); ++ pdata->pp2 = XP_IOREAD(pdata, XP_PROP_2); ++ pdata->pp3 = XP_IOREAD(pdata, XP_PROP_3); ++ pdata->pp4 = XP_IOREAD(pdata, XP_PROP_4); ++ if (netif_msg_probe(pdata)) { ++ dev_dbg(dev, "port property 0 = %#010x\n", pdata->pp0); ++ dev_dbg(dev, "port property 1 = %#010x\n", pdata->pp1); ++ dev_dbg(dev, "port property 2 = %#010x\n", pdata->pp2); ++ dev_dbg(dev, "port property 3 = %#010x\n", pdata->pp3); ++ dev_dbg(dev, "port property 4 = %#010x\n", pdata->pp4); ++ } ++ + /* Set the maximum channels and queues */ +- reg = XP_IOREAD(pdata, XP_PROP_1); +- pdata->tx_max_channel_count = XP_GET_BITS(reg, XP_PROP_1, MAX_TX_DMA); +- pdata->rx_max_channel_count = XP_GET_BITS(reg, XP_PROP_1, MAX_RX_DMA); +- pdata->tx_max_q_count = XP_GET_BITS(reg, XP_PROP_1, MAX_TX_QUEUES); +- pdata->rx_max_q_count = XP_GET_BITS(reg, XP_PROP_1, MAX_RX_QUEUES); ++ pdata->tx_max_channel_count = XP_GET_BITS(pdata->pp1, XP_PROP_1, ++ MAX_TX_DMA); ++ pdata->rx_max_channel_count = XP_GET_BITS(pdata->pp1, XP_PROP_1, ++ MAX_RX_DMA); ++ pdata->tx_max_q_count = XP_GET_BITS(pdata->pp1, XP_PROP_1, ++ MAX_TX_QUEUES); ++ pdata->rx_max_q_count = XP_GET_BITS(pdata->pp1, XP_PROP_1, ++ MAX_RX_QUEUES); + if (netif_msg_probe(pdata)) { + dev_dbg(dev, "max tx/rx channel count = %u/%u\n", + pdata->tx_max_channel_count, +@@ -347,12 +364,13 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + xgbe_set_counts(pdata); + + /* Set the maximum fifo amounts */ +- reg = XP_IOREAD(pdata, XP_PROP_2); +- pdata->tx_max_fifo_size = XP_GET_BITS(reg, XP_PROP_2, TX_FIFO_SIZE); ++ pdata->tx_max_fifo_size = XP_GET_BITS(pdata->pp2, XP_PROP_2, ++ TX_FIFO_SIZE); + pdata->tx_max_fifo_size *= 16384; + pdata->tx_max_fifo_size = min(pdata->tx_max_fifo_size, + pdata->vdata->tx_max_fifo_size); +- pdata->rx_max_fifo_size = XP_GET_BITS(reg, XP_PROP_2, RX_FIFO_SIZE); ++ pdata->rx_max_fifo_size = XP_GET_BITS(pdata->pp2, XP_PROP_2, ++ RX_FIFO_SIZE); + pdata->rx_max_fifo_size *= 16384; + pdata->rx_max_fifo_size = min(pdata->rx_max_fifo_size, + pdata->vdata->rx_max_fifo_size); +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index aa18ee5e1e5a..a888ba6b9635 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -2458,22 +2458,21 @@ static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart) + static void xgbe_phy_sfp_gpio_setup(struct xgbe_prv_data *pdata) + { + struct xgbe_phy_data *phy_data = pdata->phy_data; +- unsigned int reg; +- +- reg = XP_IOREAD(pdata, XP_PROP_3); + + phy_data->sfp_gpio_address = XGBE_GPIO_ADDRESS_PCA9555 + +- XP_GET_BITS(reg, XP_PROP_3, GPIO_ADDR); ++ XP_GET_BITS(pdata->pp3, XP_PROP_3, ++ GPIO_ADDR); + +- phy_data->sfp_gpio_mask = XP_GET_BITS(reg, XP_PROP_3, GPIO_MASK); ++ phy_data->sfp_gpio_mask = XP_GET_BITS(pdata->pp3, XP_PROP_3, ++ GPIO_MASK); + +- phy_data->sfp_gpio_rx_los = XP_GET_BITS(reg, XP_PROP_3, ++ phy_data->sfp_gpio_rx_los = XP_GET_BITS(pdata->pp3, XP_PROP_3, + GPIO_RX_LOS); +- phy_data->sfp_gpio_tx_fault = XP_GET_BITS(reg, XP_PROP_3, ++ phy_data->sfp_gpio_tx_fault = XP_GET_BITS(pdata->pp3, XP_PROP_3, + GPIO_TX_FAULT); +- phy_data->sfp_gpio_mod_absent = XP_GET_BITS(reg, XP_PROP_3, ++ phy_data->sfp_gpio_mod_absent = XP_GET_BITS(pdata->pp3, XP_PROP_3, + GPIO_MOD_ABS); +- phy_data->sfp_gpio_rate_select = XP_GET_BITS(reg, XP_PROP_3, ++ phy_data->sfp_gpio_rate_select = XP_GET_BITS(pdata->pp3, XP_PROP_3, + GPIO_RATE_SELECT); + + if (netif_msg_probe(pdata)) { +@@ -2495,18 +2494,17 @@ static void xgbe_phy_sfp_gpio_setup(struct xgbe_prv_data *pdata) + static void xgbe_phy_sfp_comm_setup(struct xgbe_prv_data *pdata) + { + struct xgbe_phy_data *phy_data = pdata->phy_data; +- unsigned int reg, mux_addr_hi, mux_addr_lo; ++ unsigned int mux_addr_hi, mux_addr_lo; + +- reg = XP_IOREAD(pdata, XP_PROP_4); +- +- mux_addr_hi = XP_GET_BITS(reg, XP_PROP_4, MUX_ADDR_HI); +- mux_addr_lo = XP_GET_BITS(reg, XP_PROP_4, MUX_ADDR_LO); ++ mux_addr_hi = XP_GET_BITS(pdata->pp4, XP_PROP_4, MUX_ADDR_HI); ++ mux_addr_lo = XP_GET_BITS(pdata->pp4, XP_PROP_4, MUX_ADDR_LO); + if (mux_addr_lo == XGBE_SFP_DIRECT) + return; + + phy_data->sfp_comm = XGBE_SFP_COMM_PCA9545; + phy_data->sfp_mux_address = (mux_addr_hi << 2) + mux_addr_lo; +- phy_data->sfp_mux_channel = XP_GET_BITS(reg, XP_PROP_4, MUX_CHAN); ++ phy_data->sfp_mux_channel = XP_GET_BITS(pdata->pp4, XP_PROP_4, ++ MUX_CHAN); + + if (netif_msg_probe(pdata)) { + dev_dbg(pdata->dev, "SFP: mux_address=%#x\n", +@@ -2629,13 +2627,11 @@ static bool xgbe_phy_redrv_error(struct xgbe_phy_data *phy_data) + static int xgbe_phy_mdio_reset_setup(struct xgbe_prv_data *pdata) + { + struct xgbe_phy_data *phy_data = pdata->phy_data; +- unsigned int reg; + + if (phy_data->conn_type != XGBE_CONN_TYPE_MDIO) + return 0; + +- reg = XP_IOREAD(pdata, XP_PROP_3); +- phy_data->mdio_reset = XP_GET_BITS(reg, XP_PROP_3, MDIO_RESET); ++ phy_data->mdio_reset = XP_GET_BITS(pdata->pp3, XP_PROP_3, MDIO_RESET); + switch (phy_data->mdio_reset) { + case XGBE_MDIO_RESET_NONE: + case XGBE_MDIO_RESET_I2C_GPIO: +@@ -2649,12 +2645,12 @@ static int xgbe_phy_mdio_reset_setup(struct xgbe_prv_data *pdata) + + if (phy_data->mdio_reset == XGBE_MDIO_RESET_I2C_GPIO) { + phy_data->mdio_reset_addr = XGBE_GPIO_ADDRESS_PCA9555 + +- XP_GET_BITS(reg, XP_PROP_3, ++ XP_GET_BITS(pdata->pp3, XP_PROP_3, + MDIO_RESET_I2C_ADDR); +- phy_data->mdio_reset_gpio = XP_GET_BITS(reg, XP_PROP_3, ++ phy_data->mdio_reset_gpio = XP_GET_BITS(pdata->pp3, XP_PROP_3, + MDIO_RESET_I2C_GPIO); + } else if (phy_data->mdio_reset == XGBE_MDIO_RESET_INT_GPIO) { +- phy_data->mdio_reset_gpio = XP_GET_BITS(reg, XP_PROP_3, ++ phy_data->mdio_reset_gpio = XP_GET_BITS(pdata->pp3, XP_PROP_3, + MDIO_RESET_INT_GPIO); + } + +@@ -2744,12 +2740,9 @@ static bool xgbe_phy_conn_type_mismatch(struct xgbe_prv_data *pdata) + + static bool xgbe_phy_port_enabled(struct xgbe_prv_data *pdata) + { +- unsigned int reg; +- +- reg = XP_IOREAD(pdata, XP_PROP_0); +- if (!XP_GET_BITS(reg, XP_PROP_0, PORT_SPEEDS)) ++ if (!XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_SPEEDS)) + return false; +- if (!XP_GET_BITS(reg, XP_PROP_0, CONN_TYPE)) ++ if (!XP_GET_BITS(pdata->pp0, XP_PROP_0, CONN_TYPE)) + return false; + + return true; +@@ -3018,7 +3018,6 @@ static int xgbe_phy_init(struct xgbe_prv + struct ethtool_link_ksettings *lks = &pdata->phy.lks; + struct xgbe_phy_data *phy_data; + struct mii_bus *mii; +- unsigned int reg; + int ret; + + /* Check if enabled */ +@@ -2976,12 +2968,11 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) + return -ENOMEM; + pdata->phy_data = phy_data; + +- reg = XP_IOREAD(pdata, XP_PROP_0); +- phy_data->port_mode = XP_GET_BITS(reg, XP_PROP_0, PORT_MODE); +- phy_data->port_id = XP_GET_BITS(reg, XP_PROP_0, PORT_ID); +- phy_data->port_speeds = XP_GET_BITS(reg, XP_PROP_0, PORT_SPEEDS); +- phy_data->conn_type = XP_GET_BITS(reg, XP_PROP_0, CONN_TYPE); +- phy_data->mdio_addr = XP_GET_BITS(reg, XP_PROP_0, MDIO_ADDR); ++ phy_data->port_mode = XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_MODE); ++ phy_data->port_id = XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_ID); ++ phy_data->port_speeds = XP_GET_BITS(pdata->pp0, XP_PROP_0, PORT_SPEEDS); ++ phy_data->conn_type = XP_GET_BITS(pdata->pp0, XP_PROP_0, CONN_TYPE); ++ phy_data->mdio_addr = XP_GET_BITS(pdata->pp0, XP_PROP_0, MDIO_ADDR); + if (netif_msg_probe(pdata)) { + dev_dbg(pdata->dev, "port mode=%u\n", phy_data->port_mode); + dev_dbg(pdata->dev, "port id=%u\n", phy_data->port_id); +@@ -2990,12 +2981,11 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) + dev_dbg(pdata->dev, "mdio addr=%u\n", phy_data->mdio_addr); + } + +- reg = XP_IOREAD(pdata, XP_PROP_4); +- phy_data->redrv = XP_GET_BITS(reg, XP_PROP_4, REDRV_PRESENT); +- phy_data->redrv_if = XP_GET_BITS(reg, XP_PROP_4, REDRV_IF); +- phy_data->redrv_addr = XP_GET_BITS(reg, XP_PROP_4, REDRV_ADDR); +- phy_data->redrv_lane = XP_GET_BITS(reg, XP_PROP_4, REDRV_LANE); +- phy_data->redrv_model = XP_GET_BITS(reg, XP_PROP_4, REDRV_MODEL); ++ phy_data->redrv = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_PRESENT); ++ phy_data->redrv_if = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_IF); ++ phy_data->redrv_addr = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_ADDR); ++ phy_data->redrv_lane = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_LANE); ++ phy_data->redrv_model = XP_GET_BITS(pdata->pp4, XP_PROP_4, REDRV_MODEL); + if (phy_data->redrv && netif_msg_probe(pdata)) { + dev_dbg(pdata->dev, "redrv present\n"); + dev_dbg(pdata->dev, "redrv i/f=%u\n", phy_data->redrv_if); +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index efc774f207eb..7df3e12aa200 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -956,6 +956,13 @@ struct xgbe_prv_data { + void __iomem *xprop_regs; /* XGBE property registers */ + void __iomem *xi2c_regs; /* XGBE I2C CSRs */ + ++ /* Port property registers */ ++ unsigned int pp0; ++ unsigned int pp1; ++ unsigned int pp2; ++ unsigned int pp3; ++ unsigned int pp4; ++ + /* Overall device lock */ + spinlock_t lock; + +-- +2.16.4 + diff --git a/patches.suse/0009-amd-xgbe-Remove-use-of-comm_owned-field.patch b/patches.suse/0009-amd-xgbe-Remove-use-of-comm_owned-field.patch new file mode 100644 index 0000000..315e817 --- /dev/null +++ b/patches.suse/0009-amd-xgbe-Remove-use-of-comm_owned-field.patch @@ -0,0 +1,79 @@ +From d4fa6bc6cb38d5d379d049c085d5cc1b7e5949f8 Mon Sep 17 00:00:00 2001 +From: Tom Lendacky +Date: Wed, 23 May 2018 11:38:29 -0500 +Subject: [PATCH 09/59] amd-xgbe: Remove use of comm_owned field +References: git-fixes +Patch-mainline: v4.18-rc1 +Git-commit: 0d2b5255ea7b69f2270e41130ee25346b1f68b7b + +The comm_owned field can hide logic where double locking is attempted +and prevent multiple threads for the same device from accessing the +mutex properly. Remove the comm_owned field and use the mutex API +exclusively for gaining ownership. The current driver has been audited +and is obtaining communications ownership properly. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 16 ---------------- + 1 file changed, 16 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index a888ba6b9635..1823c5533e37 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -327,8 +327,6 @@ struct xgbe_phy_data { + + unsigned int mdio_addr; + +- unsigned int comm_owned; +- + /* SFP Support */ + enum xgbe_sfp_comm sfp_comm; + unsigned int sfp_mux_address; +@@ -382,12 +380,6 @@ static enum xgbe_an_mode xgbe_phy_an_mode(struct xgbe_prv_data *pdata); + static int xgbe_phy_i2c_xfer(struct xgbe_prv_data *pdata, + struct xgbe_i2c_op *i2c_op) + { +- struct xgbe_phy_data *phy_data = pdata->phy_data; +- +- /* Be sure we own the bus */ +- if (WARN_ON(!phy_data->comm_owned)) +- return -EIO; +- + return pdata->i2c_if.i2c_xfer(pdata, i2c_op); + } + +@@ -549,10 +541,6 @@ static int xgbe_phy_sfp_get_mux(struct xgbe_prv_data *pdata) + + static void xgbe_phy_put_comm_ownership(struct xgbe_prv_data *pdata) + { +- struct xgbe_phy_data *phy_data = pdata->phy_data; +- +- phy_data->comm_owned = 0; +- + mutex_unlock(&xgbe_phy_comm_lock); + } + +@@ -562,9 +550,6 @@ static int xgbe_phy_get_comm_ownership(struct xgbe_prv_data *pdata) + unsigned long timeout; + unsigned int mutex_id; + +- if (phy_data->comm_owned) +- return 0; +- + /* The I2C and MDIO/GPIO bus is multiplexed between multiple devices, + * the driver needs to take the software mutex and then the hardware + * mutexes before being able to use the busses. +@@ -593,7 +578,6 @@ static int xgbe_phy_get_comm_ownership(struct xgbe_prv_data *pdata) + XP_IOWRITE(pdata, XP_I2C_MUTEX, mutex_id); + XP_IOWRITE(pdata, XP_MDIO_MUTEX, mutex_id); + +- phy_data->comm_owned = 1; + return 0; + } + +-- +2.16.4 + diff --git a/patches.suse/0010-amd-xgbe-Remove-field-that-indicates-SFP-diagnostic-.patch b/patches.suse/0010-amd-xgbe-Remove-field-that-indicates-SFP-diagnostic-.patch new file mode 100644 index 0000000..39cada1 --- /dev/null +++ b/patches.suse/0010-amd-xgbe-Remove-field-that-indicates-SFP-diagnostic-.patch @@ -0,0 +1,59 @@ +From 283bae5b4c4b1470b8a9f1874126ccaa74783fa8 Mon Sep 17 00:00:00 2001 +From: Tom Lendacky +Date: Wed, 23 May 2018 11:38:38 -0500 +Subject: [PATCH 10/59] amd-xgbe: Remove field that indicates SFP diagnostic + support +References: git-fixes +Patch-mainline: v4.18-rc1 +Git-commit: 67cea0c92264a657230ba14e1956c34132ca6161 + +The driver currently sets an indication of whether the SFP supports, and +that the driver can obtain, diagnostics data. This isn't currently used +by the driver and the logic to set this indicator is flawed because the +field is cleared each time the SFP is checked and only set when a new SFP +is detected. Remove this field and the logic supporting it. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index 1823c5533e37..da130a80abf2 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -343,7 +343,6 @@ struct xgbe_phy_data { + unsigned int sfp_rx_los; + unsigned int sfp_tx_fault; + unsigned int sfp_mod_absent; +- unsigned int sfp_diags; + unsigned int sfp_changed; + unsigned int sfp_phy_avail; + unsigned int sfp_cable_len; +@@ -1181,13 +1180,6 @@ static int xgbe_phy_sfp_read_eeprom(struct xgbe_prv_data *pdata) + + memcpy(&phy_data->sfp_eeprom, &sfp_eeprom, sizeof(sfp_eeprom)); + +- if (sfp_eeprom.extd[XGBE_SFP_EXTD_SFF_8472]) { +- u8 diag_type = sfp_eeprom.extd[XGBE_SFP_EXTD_DIAG]; +- +- if (!(diag_type & XGBE_SFP_EXTD_DIAG_ADDR_CHANGE)) +- phy_data->sfp_diags = 1; +- } +- + xgbe_phy_free_phy_device(pdata); + } else { + phy_data->sfp_changed = 0; +@@ -1236,7 +1228,6 @@ static void xgbe_phy_sfp_reset(struct xgbe_phy_data *phy_data) + phy_data->sfp_rx_los = 0; + phy_data->sfp_tx_fault = 0; + phy_data->sfp_mod_absent = 1; +- phy_data->sfp_diags = 0; + phy_data->sfp_base = XGBE_SFP_BASE_UNKNOWN; + phy_data->sfp_cable = XGBE_SFP_CABLE_UNKNOWN; + phy_data->sfp_speed = XGBE_SFP_SPEED_UNKNOWN; +-- +2.16.4 + diff --git a/patches.suse/0011-amd-xgbe-Always-attempt-link-training-in-KR-mode.patch b/patches.suse/0011-amd-xgbe-Always-attempt-link-training-in-KR-mode.patch new file mode 100644 index 0000000..effa4cd --- /dev/null +++ b/patches.suse/0011-amd-xgbe-Always-attempt-link-training-in-KR-mode.patch @@ -0,0 +1,164 @@ +From 5d72e21adfa273c1d1fc3d9024ad093c48cafbda Mon Sep 17 00:00:00 2001 +From: Tom Lendacky +Date: Wed, 23 May 2018 11:39:21 -0500 +Subject: [PATCH 11/59] amd-xgbe: Always attempt link training in KR mode +References: git-fixes +Patch-mainline: v4.18-rc1 +Git-commit: eca282b8418b0b5a55b70e42f684e882d3fb9654 + +Link training is always attempted when in KR mode, but the code is +structured to check if link training has been enabled before attempting +to perform it. Since that check will always be true, simplify the code +to always enable and start link training during KR auto-negotiation. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 69 +++++++------------------------ + 1 file changed, 16 insertions(+), 53 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +index b2d6a94986f8..c7b3f1b0bcc6 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +@@ -198,31 +198,8 @@ static void xgbe_an_clear_interrupts_all(struct xgbe_prv_data *pdata) + xgbe_an37_clear_interrupts(pdata); + } + +-static void xgbe_an73_enable_kr_training(struct xgbe_prv_data *pdata) +-{ +- unsigned int reg; +- +- reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL); +- +- reg |= XGBE_KR_TRAINING_ENABLE; +- XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg); +-} +- +-static void xgbe_an73_disable_kr_training(struct xgbe_prv_data *pdata) +-{ +- unsigned int reg; +- +- reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL); +- +- reg &= ~XGBE_KR_TRAINING_ENABLE; +- XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg); +-} +- + static void xgbe_kr_mode(struct xgbe_prv_data *pdata) + { +- /* Enable KR training */ +- xgbe_an73_enable_kr_training(pdata); +- + /* Set MAC to 10G speed */ + pdata->hw_if.set_speed(pdata, SPEED_10000); + +@@ -232,9 +209,6 @@ static void xgbe_kr_mode(struct xgbe_prv_data *pdata) + + static void xgbe_kx_2500_mode(struct xgbe_prv_data *pdata) + { +- /* Disable KR training */ +- xgbe_an73_disable_kr_training(pdata); +- + /* Set MAC to 2.5G speed */ + pdata->hw_if.set_speed(pdata, SPEED_2500); + +@@ -244,9 +218,6 @@ static void xgbe_kx_2500_mode(struct xgbe_prv_data *pdata) + + static void xgbe_kx_1000_mode(struct xgbe_prv_data *pdata) + { +- /* Disable KR training */ +- xgbe_an73_disable_kr_training(pdata); +- + /* Set MAC to 1G speed */ + pdata->hw_if.set_speed(pdata, SPEED_1000); + +@@ -260,9 +231,6 @@ static void xgbe_sfi_mode(struct xgbe_prv_data *pdata) + if (pdata->kr_redrv) + return xgbe_kr_mode(pdata); + +- /* Disable KR training */ +- xgbe_an73_disable_kr_training(pdata); +- + /* Set MAC to 10G speed */ + pdata->hw_if.set_speed(pdata, SPEED_10000); + +@@ -272,9 +240,6 @@ static void xgbe_sfi_mode(struct xgbe_prv_data *pdata) + + static void xgbe_x_mode(struct xgbe_prv_data *pdata) + { +- /* Disable KR training */ +- xgbe_an73_disable_kr_training(pdata); +- + /* Set MAC to 1G speed */ + pdata->hw_if.set_speed(pdata, SPEED_1000); + +@@ -284,9 +249,6 @@ static void xgbe_x_mode(struct xgbe_prv_data *pdata) + + static void xgbe_sgmii_1000_mode(struct xgbe_prv_data *pdata) + { +- /* Disable KR training */ +- xgbe_an73_disable_kr_training(pdata); +- + /* Set MAC to 1G speed */ + pdata->hw_if.set_speed(pdata, SPEED_1000); + +@@ -296,9 +258,6 @@ static void xgbe_sgmii_1000_mode(struct xgbe_prv_data *pdata) + + static void xgbe_sgmii_100_mode(struct xgbe_prv_data *pdata) + { +- /* Disable KR training */ +- xgbe_an73_disable_kr_training(pdata); +- + /* Set MAC to 1G speed */ + pdata->hw_if.set_speed(pdata, SPEED_1000); + +@@ -407,6 +366,12 @@ static void xgbe_an73_set(struct xgbe_prv_data *pdata, bool enable, + { + unsigned int reg; + ++ /* Disable KR training for now */ ++ reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL); ++ reg &= ~XGBE_KR_TRAINING_ENABLE; ++ XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg); ++ ++ /* Update AN settings */ + reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1); + reg &= ~MDIO_AN_CTRL1_ENABLE; + +@@ -504,21 +469,19 @@ static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata, + XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECCTRL, reg); + + /* Start KR training */ +- reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL); +- if (reg & XGBE_KR_TRAINING_ENABLE) { +- if (pdata->phy_if.phy_impl.kr_training_pre) +- pdata->phy_if.phy_impl.kr_training_pre(pdata); ++ if (pdata->phy_if.phy_impl.kr_training_pre) ++ pdata->phy_if.phy_impl.kr_training_pre(pdata); + +- reg |= XGBE_KR_TRAINING_START; +- XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, +- reg); ++ reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL); ++ reg |= XGBE_KR_TRAINING_ENABLE; ++ reg |= XGBE_KR_TRAINING_START; ++ XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg); + +- netif_dbg(pdata, link, pdata->netdev, +- "KR training initiated\n"); ++ netif_dbg(pdata, link, pdata->netdev, ++ "KR training initiated\n"); + +- if (pdata->phy_if.phy_impl.kr_training_post) +- pdata->phy_if.phy_impl.kr_training_post(pdata); +- } ++ if (pdata->phy_if.phy_impl.kr_training_post) ++ pdata->phy_if.phy_impl.kr_training_post(pdata); + + return XGBE_AN_PAGE_RECEIVED; + } +-- +2.16.4 + diff --git a/patches.suse/0012-amd-xgbe-Fix-SFP-PHY-supported-advertised-settings.patch b/patches.suse/0012-amd-xgbe-Fix-SFP-PHY-supported-advertised-settings.patch new file mode 100644 index 0000000..0d64da8 --- /dev/null +++ b/patches.suse/0012-amd-xgbe-Fix-SFP-PHY-supported-advertised-settings.patch @@ -0,0 +1,171 @@ +From 87a16c2ce073a6240de61632aa2eb5e15073e5cf Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Wed, 28 Jun 2017 13:41:40 -0500 +Subject: [PATCH 12/59] amd-xgbe: Fix SFP PHY supported/advertised settings +References: git-fixes +Patch-mainline: v4.13-rc1 +Git-commit: 56503d55cc8b843096a5f51355712ca837f3757b + +When using SFPs, the supported and advertised settings should be initially +based on the SFP that has been detected. The code currently indicates the +overall support of the device as opposed to what the SFP is capable of. +Update the code to change the supported link modes, auto-negotiation, etc. +to be based on the installed SFP. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 69 ++++++++++++++++++++--------- + 1 file changed, 47 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index da130a80abf2..dbb2cd948398 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -711,23 +711,39 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) + { + struct xgbe_phy_data *phy_data = pdata->phy_data; + ++ if (!phy_data->sfp_mod_absent && !phy_data->sfp_changed) ++ return; ++ ++ pdata->phy.supported &= ~SUPPORTED_Autoneg; ++ pdata->phy.supported &= ~(SUPPORTED_Pause | SUPPORTED_Asym_Pause); ++ pdata->phy.supported &= ~SUPPORTED_TP; ++ pdata->phy.supported &= ~SUPPORTED_FIBRE; ++ pdata->phy.supported &= ~SUPPORTED_100baseT_Full; ++ pdata->phy.supported &= ~SUPPORTED_1000baseT_Full; ++ pdata->phy.supported &= ~SUPPORTED_10000baseT_Full; ++ + if (phy_data->sfp_mod_absent) { + pdata->phy.speed = SPEED_UNKNOWN; + pdata->phy.duplex = DUPLEX_UNKNOWN; + pdata->phy.autoneg = AUTONEG_ENABLE; ++ pdata->phy.pause_autoneg = AUTONEG_ENABLE; ++ ++ pdata->phy.supported |= SUPPORTED_Autoneg; ++ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; ++ pdata->phy.supported |= SUPPORTED_TP; ++ pdata->phy.supported |= SUPPORTED_FIBRE; ++ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ++ pdata->phy.supported |= SUPPORTED_100baseT_Full; ++ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) ++ pdata->phy.supported |= SUPPORTED_1000baseT_Full; ++ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) ++ pdata->phy.supported |= SUPPORTED_10000baseT_Full; ++ + pdata->phy.advertising = pdata->phy.supported; + + return; + } + +- pdata->phy.advertising &= ~ADVERTISED_Autoneg; +- pdata->phy.advertising &= ~ADVERTISED_TP; +- pdata->phy.advertising &= ~ADVERTISED_FIBRE; +- pdata->phy.advertising &= ~ADVERTISED_100baseT_Full; +- pdata->phy.advertising &= ~ADVERTISED_1000baseT_Full; +- pdata->phy.advertising &= ~ADVERTISED_10000baseT_Full; +- pdata->phy.advertising &= ~ADVERTISED_10000baseR_FEC; +- + switch (phy_data->sfp_base) { + case XGBE_SFP_BASE_1000_T: + case XGBE_SFP_BASE_1000_SX: +@@ -736,17 +752,25 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) + pdata->phy.speed = SPEED_UNKNOWN; + pdata->phy.duplex = DUPLEX_UNKNOWN; + pdata->phy.autoneg = AUTONEG_ENABLE; +- pdata->phy.advertising |= ADVERTISED_Autoneg; ++ pdata->phy.pause_autoneg = AUTONEG_ENABLE; ++ pdata->phy.supported |= SUPPORTED_Autoneg; ++ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + break; + case XGBE_SFP_BASE_10000_SR: + case XGBE_SFP_BASE_10000_LR: + case XGBE_SFP_BASE_10000_LRM: + case XGBE_SFP_BASE_10000_ER: + case XGBE_SFP_BASE_10000_CR: +- default: + pdata->phy.speed = SPEED_10000; + pdata->phy.duplex = DUPLEX_FULL; + pdata->phy.autoneg = AUTONEG_DISABLE; ++ pdata->phy.pause_autoneg = AUTONEG_DISABLE; ++ break; ++ default: ++ pdata->phy.speed = SPEED_UNKNOWN; ++ pdata->phy.duplex = DUPLEX_UNKNOWN; ++ pdata->phy.autoneg = AUTONEG_DISABLE; ++ pdata->phy.pause_autoneg = AUTONEG_DISABLE; + break; + } + +@@ -754,36 +778,38 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) + case XGBE_SFP_BASE_1000_T: + case XGBE_SFP_BASE_1000_CX: + case XGBE_SFP_BASE_10000_CR: +- pdata->phy.advertising |= ADVERTISED_TP; ++ pdata->phy.supported |= SUPPORTED_TP; + break; + default: +- pdata->phy.advertising |= ADVERTISED_FIBRE; ++ pdata->phy.supported |= SUPPORTED_FIBRE; + } + + switch (phy_data->sfp_speed) { + case XGBE_SFP_SPEED_100_1000: + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) +- pdata->phy.advertising |= ADVERTISED_100baseT_Full; ++ pdata->phy.supported |= SUPPORTED_100baseT_Full; + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) +- pdata->phy.advertising |= ADVERTISED_1000baseT_Full; ++ pdata->phy.supported |= SUPPORTED_1000baseT_Full; + break; + case XGBE_SFP_SPEED_1000: + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) +- pdata->phy.advertising |= ADVERTISED_1000baseT_Full; ++ pdata->phy.supported |= SUPPORTED_1000baseT_Full; + break; + case XGBE_SFP_SPEED_10000: + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) +- pdata->phy.advertising |= ADVERTISED_10000baseT_Full; ++ pdata->phy.supported |= SUPPORTED_10000baseT_Full; + break; + default: + /* Choose the fastest supported speed */ + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) +- pdata->phy.advertising |= ADVERTISED_10000baseT_Full; ++ pdata->phy.supported |= SUPPORTED_10000baseT_Full; + else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) +- pdata->phy.advertising |= ADVERTISED_1000baseT_Full; ++ pdata->phy.supported |= SUPPORTED_1000baseT_Full; + else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) +- pdata->phy.advertising |= ADVERTISED_100baseT_Full; ++ pdata->phy.supported |= SUPPORTED_100baseT_Full; + } ++ ++ pdata->phy.advertising = pdata->phy.supported; + } + + static bool xgbe_phy_sfp_bit_rate(struct xgbe_sfp_eeprom *sfp_eeprom, +@@ -2234,6 +2260,8 @@ static bool xgbe_phy_use_sfp_mode(struct xgbe_prv_data *pdata, + return xgbe_phy_check_mode(pdata, mode, + ADVERTISED_1000baseT_Full); + case XGBE_MODE_SFI: ++ if (phy_data->sfp_mod_absent) ++ return true; + return xgbe_phy_check_mode(pdata, mode, + ADVERTISED_10000baseT_Full); + default: +@@ -3130,9 +3158,6 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) { + pdata->phy.supported |= SUPPORTED_10000baseT_Full; + phy_data->start_mode = XGBE_MODE_SFI; +- if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) +- pdata->phy.supported |= +- SUPPORTED_10000baseR_FEC; + } + + phy_data->phydev_mode = XGBE_MDIO_MODE_CL22; +-- +2.16.4 + diff --git a/patches.suse/0013-amd-xgbe-Use-the-proper-register-during-PTP-initiali.patch b/patches.suse/0013-amd-xgbe-Use-the-proper-register-during-PTP-initiali.patch new file mode 100644 index 0000000..46129b5 --- /dev/null +++ b/patches.suse/0013-amd-xgbe-Use-the-proper-register-during-PTP-initiali.patch @@ -0,0 +1,38 @@ +From 66f1376624ba6af392d4c41dd1a54305c12dff96 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Wed, 28 Jun 2017 13:41:49 -0500 +Subject: [PATCH 13/59] amd-xgbe: Use the proper register during PTP + initialization +References: git-fixes +Patch-mainline: v4.13-rc1 +Git-commit: 3abc7cff671a15f797f2baca9ba6b406508757b8 + +During PTP initialization, the Timestamp Control register should be +cleared and not the Tx Configuration register. While this typo causes +the wrong register to be cleared, the default value of each register and +and the fact that the Tx Configuration register is programmed afterwards +doesn't result in a bug, hence only fixing in net-next. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c +index a533a6cc2d53..d06d260cf1e2 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c +@@ -267,7 +267,7 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata) + ktime_to_ns(ktime_get_real())); + + /* Disable all timestamping to start */ +- XGMAC_IOWRITE(pdata, MAC_TCR, 0); ++ XGMAC_IOWRITE(pdata, MAC_TSCR, 0); + pdata->tstamp_config.tx_type = HWTSTAMP_TX_OFF; + pdata->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; + } +-- +2.16.4 + diff --git a/patches.suse/0014-amd-xgbe-Add-a-check-for-an-skb-in-the-timestamp-pat.patch b/patches.suse/0014-amd-xgbe-Add-a-check-for-an-skb-in-the-timestamp-pat.patch new file mode 100644 index 0000000..72e2b43 --- /dev/null +++ b/patches.suse/0014-amd-xgbe-Add-a-check-for-an-skb-in-the-timestamp-pat.patch @@ -0,0 +1,48 @@ +From 5ab6e1c9dd99a17fc47705cc612a37dcdda3f3e6 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Wed, 28 Jun 2017 13:41:58 -0500 +Subject: [PATCH 14/59] amd-xgbe: Add a check for an skb in the timestamp path +References: git-fixes +Patch-mainline: v4.13-rc1 +Git-commit: 93845d5f1b3c3878fdeb6275f1928217ec0c9ff2 + +Spurious Tx timestamp interrupts can cause an oops in the Tx timestamp +processing function if a Tx timestamp skb is NULL. Add a check to insure +a Tx timestamp skb is present before attempting to use it. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index 6a0a50c8d516..d08b0f7127b1 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -1211,6 +1211,10 @@ static void xgbe_tx_tstamp(struct work_struct *work) + u64 nsec; + unsigned long flags; + ++ spin_lock_irqsave(&pdata->tstamp_lock, flags); ++ if (!pdata->tx_tstamp_skb) ++ goto unlock; ++ + if (pdata->tx_tstamp) { + nsec = timecounter_cyc2time(&pdata->tstamp_tc, + pdata->tx_tstamp); +@@ -1222,8 +1226,9 @@ static void xgbe_tx_tstamp(struct work_struct *work) + + dev_kfree_skb_any(pdata->tx_tstamp_skb); + +- spin_lock_irqsave(&pdata->tstamp_lock, flags); + pdata->tx_tstamp_skb = NULL; ++ ++unlock: + spin_unlock_irqrestore(&pdata->tstamp_lock, flags); + } + +-- +2.16.4 + diff --git a/patches.suse/0015-amd-xgbe-Prevent-looping-forever-if-timestamp-update.patch b/patches.suse/0015-amd-xgbe-Prevent-looping-forever-if-timestamp-update.patch new file mode 100644 index 0000000..c6d299a --- /dev/null +++ b/patches.suse/0015-amd-xgbe-Prevent-looping-forever-if-timestamp-update.patch @@ -0,0 +1,67 @@ +From 8b8bd1e2636b2cd7de5fc518095e851dfffb9cea Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Wed, 28 Jun 2017 13:42:07 -0500 +Subject: [PATCH 15/59] amd-xgbe: Prevent looping forever if timestamp update + fails +References: git-fixes +Patch-mainline: v4.13-rc1 +Git-commit: 9018ff5331a64aa9e6dd600345bb1d087684fdff + +Just to be on the safe side, should the update of the timestamp registers +not complete, issue a warning rather than looping forever waiting for the +update to complete. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +index 3ad7c1f2bb24..b449c3526090 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +@@ -1507,26 +1507,37 @@ static void xgbe_rx_desc_init(struct xgbe_channel *channel) + static void xgbe_update_tstamp_addend(struct xgbe_prv_data *pdata, + unsigned int addend) + { ++ unsigned int count = 10000; ++ + /* Set the addend register value and tell the device */ + XGMAC_IOWRITE(pdata, MAC_TSAR, addend); + XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSADDREG, 1); + + /* Wait for addend update to complete */ +- while (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSADDREG)) ++ while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSADDREG)) + udelay(5); ++ ++ if (!count) ++ netdev_err(pdata->netdev, ++ "timed out updating timestamp addend register\n"); + } + + static void xgbe_set_tstamp_time(struct xgbe_prv_data *pdata, unsigned int sec, + unsigned int nsec) + { ++ unsigned int count = 10000; ++ + /* Set the time values and tell the device */ + XGMAC_IOWRITE(pdata, MAC_STSUR, sec); + XGMAC_IOWRITE(pdata, MAC_STNUR, nsec); + XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSINIT, 1); + + /* Wait for time update to complete */ +- while (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSINIT)) ++ while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSINIT)) + udelay(5); ++ ++ if (!count) ++ netdev_err(pdata->netdev, "timed out initializing timestamp\n"); + } + + static u64 xgbe_get_tstamp_time(struct xgbe_prv_data *pdata) +-- +2.16.4 + diff --git a/patches.suse/0016-amd-xgbe-Handle-return-code-from-software-reset-func.patch b/patches.suse/0016-amd-xgbe-Handle-return-code-from-software-reset-func.patch new file mode 100644 index 0000000..4003720 --- /dev/null +++ b/patches.suse/0016-amd-xgbe-Handle-return-code-from-software-reset-func.patch @@ -0,0 +1,40 @@ +From bc69d61300499b0fc80ef650a786ef415a1cb497 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Wed, 28 Jun 2017 13:42:16 -0500 +Subject: [PATCH 16/59] amd-xgbe: Handle return code from software reset + function +References: git-fixes +Patch-mainline: v4.13-rc1 +Git-commit: 42d452dc4a3674bbe53fa80f00f31f72385252dd + +Currently the function that performs a software reset of the hardware +provides a return code. During driver probe check this return code and +exit with an error if the software reset fails. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-main.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +index 4468ac1378f3..17787346e0bc 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +@@ -277,7 +277,11 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata) + pdata->desc_ded_period = jiffies; + + /* Issue software reset to device */ +- pdata->hw_if.exit(pdata); ++ ret = pdata->hw_if.exit(pdata); ++ if (ret) { ++ dev_err(dev, "software reset failed\n"); ++ return ret; ++ } + + /* Set default configuration data */ + xgbe_default_config(pdata); +-- +2.16.4 + diff --git a/patches.suse/0017-amd-xgbe-Fixes-for-working-with-PHYs-that-support-2..patch b/patches.suse/0017-amd-xgbe-Fixes-for-working-with-PHYs-that-support-2..patch new file mode 100644 index 0000000..277e033 --- /dev/null +++ b/patches.suse/0017-amd-xgbe-Fixes-for-working-with-PHYs-that-support-2..patch @@ -0,0 +1,54 @@ +From d61432d26dc7ac148ed851fc762edb5b3ec64758 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Wed, 28 Jun 2017 13:42:25 -0500 +Subject: [PATCH 17/59] amd-xgbe: Fixes for working with PHYs that support + 2.5GbE +References: git-fixes +Patch-mainline: v4.13-rc1 +Git-commit: ed3333fa6fc21b4191601367a5ea4f0f198f100d + +The driver has some missing functionality when operating in the mode that +supports 2.5GbE. Fix the driver to fully recognize and support this speed. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index dbb2cd948398..c24f5a4b1ae3 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -2087,6 +2087,8 @@ static enum xgbe_mode xgbe_phy_get_baset_mode(struct xgbe_phy_data *phy_data, + return XGBE_MODE_SGMII_100; + case SPEED_1000: + return XGBE_MODE_SGMII_1000; ++ case SPEED_2500: ++ return XGBE_MODE_KX_2500; + case SPEED_10000: + return XGBE_MODE_KR; + default: +@@ -2230,6 +2232,9 @@ static bool xgbe_phy_use_baset_mode(struct xgbe_prv_data *pdata, + case XGBE_MODE_SGMII_1000: + return xgbe_phy_check_mode(pdata, mode, + ADVERTISED_1000baseT_Full); ++ case XGBE_MODE_KX_2500: ++ return xgbe_phy_check_mode(pdata, mode, ++ ADVERTISED_2500baseX_Full); + case XGBE_MODE_KR: + return xgbe_phy_check_mode(pdata, mode, + ADVERTISED_10000baseT_Full); +@@ -2339,6 +2344,8 @@ static bool xgbe_phy_valid_speed_baset_mode(struct xgbe_phy_data *phy_data, + case SPEED_100: + case SPEED_1000: + return true; ++ case SPEED_2500: ++ return (phy_data->port_mode == XGBE_PORT_MODE_NBASE_T); + case SPEED_10000: + return (phy_data->port_mode == XGBE_PORT_MODE_10GBASE_T); + default: +-- +2.16.4 + diff --git a/patches.suse/0018-amd-xgbe-Limit-the-I2C-error-messages-that-are-outpu.patch b/patches.suse/0018-amd-xgbe-Limit-the-I2C-error-messages-that-are-outpu.patch new file mode 100644 index 0000000..282b65a --- /dev/null +++ b/patches.suse/0018-amd-xgbe-Limit-the-I2C-error-messages-that-are-outpu.patch @@ -0,0 +1,56 @@ +From a5171d415982b82afcbc7dade7f41bd3261141d6 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Wed, 28 Jun 2017 13:42:35 -0500 +Subject: [PATCH 18/59] amd-xgbe: Limit the I2C error messages that are output +References: git-fixes +Patch-mainline: v4.13-rc1 +Git-commit: 45a2005e9354f8bcf2333a8bc8cc4b26a927d042 + +When I2C communication fails, it tends to always fail. Rather than +continuously issue an error message (once per second in most cases), +change the message to be issued just once. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index c24f5a4b1ae3..070eeb979a1a 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -1168,7 +1168,8 @@ static int xgbe_phy_sfp_read_eeprom(struct xgbe_prv_data *pdata) + + ret = xgbe_phy_sfp_get_mux(pdata); + if (ret) { +- netdev_err(pdata->netdev, "I2C error setting SFP MUX\n"); ++ dev_err_once(pdata->dev, "%s: I2C error setting SFP MUX\n", ++ netdev_name(pdata->netdev)); + return ret; + } + +@@ -1178,7 +1179,8 @@ static int xgbe_phy_sfp_read_eeprom(struct xgbe_prv_data *pdata) + &eeprom_addr, sizeof(eeprom_addr), + &sfp_eeprom, sizeof(sfp_eeprom)); + if (ret) { +- netdev_err(pdata->netdev, "I2C error reading SFP EEPROM\n"); ++ dev_err_once(pdata->dev, "%s: I2C error reading SFP EEPROM\n", ++ netdev_name(pdata->netdev)); + goto put; + } + +@@ -1229,7 +1231,8 @@ static void xgbe_phy_sfp_signals(struct xgbe_prv_data *pdata) + &gpio_reg, sizeof(gpio_reg), + gpio_ports, sizeof(gpio_ports)); + if (ret) { +- netdev_err(pdata->netdev, "I2C error reading SFP GPIOs\n"); ++ dev_err_once(pdata->dev, "%s: I2C error reading SFP GPIOs\n", ++ netdev_name(pdata->netdev)); + return; + } + +-- +2.16.4 + diff --git a/patches.suse/0019-amd-xgbe-Re-issue-interrupt-if-interrupt-status-not-.patch b/patches.suse/0019-amd-xgbe-Re-issue-interrupt-if-interrupt-status-not-.patch new file mode 100644 index 0000000..5ad3900 --- /dev/null +++ b/patches.suse/0019-amd-xgbe-Re-issue-interrupt-if-interrupt-status-not-.patch @@ -0,0 +1,370 @@ +From e3806237d61e8e628b52fdac819c3df3ba20547c Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Wed, 28 Jun 2017 13:42:42 -0500 +Subject: [PATCH 19/59] amd-xgbe: Re-issue interrupt if interrupt status not + cleared +References: git-fixes +Patch-mainline: v4.13-rc1 +Git-commit: 85b85c853401da56e15ef500552c1c2e795122ed + +Some of the device interrupts should function as level interrupts. For +some hardware configurations this requires setting some control bits +so that if the interrupt status has not been cleared the interrupt +should be reissued. + +Additionally, when using MSI or MSI-X interrupts, run the interrupt +service routine as a tasklet so that the re-issuance of the interrupt +is handled properly. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-common.h | 1 + + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 53 +++++++++++++++++++++++++---- + drivers/net/ethernet/amd/xgbe/xgbe-i2c.c | 30 +++++++++++++--- + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 33 ++++++++++++++++-- + drivers/net/ethernet/amd/xgbe/xgbe-pci.c | 4 +++ + drivers/net/ethernet/amd/xgbe/xgbe.h | 11 ++++-- + 6 files changed, 115 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +index bc79e871677c..2c68832dada9 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +@@ -957,6 +957,7 @@ + #define XP_DRIVER_INT_RO 0x0064 + #define XP_DRIVER_SCRATCH_0 0x0068 + #define XP_DRIVER_SCRATCH_1 0x006c ++#define XP_INT_REISSUE_EN 0x0074 + #define XP_INT_EN 0x0078 + #define XP_I2C_MUTEX 0x0080 + #define XP_MDIO_MUTEX 0x0084 +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index d08b0f7127b1..73953e5a8e82 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -381,9 +381,9 @@ static bool xgbe_ecc_ded(struct xgbe_prv_data *pdata, unsigned long *period, + return false; + } + +-static irqreturn_t xgbe_ecc_isr(int irq, void *data) ++static void xgbe_ecc_isr_task(unsigned long data) + { +- struct xgbe_prv_data *pdata = data; ++ struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; + unsigned int ecc_isr; + bool stop = false; + +@@ -434,12 +434,26 @@ static irqreturn_t xgbe_ecc_isr(int irq, void *data) + /* Clear all ECC interrupts */ + XP_IOWRITE(pdata, XP_ECC_ISR, ecc_isr); + +- return IRQ_HANDLED; ++ /* Reissue interrupt if status is not clear */ ++ if (pdata->vdata->irq_reissue_support) ++ XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 1); + } + +-static irqreturn_t xgbe_isr(int irq, void *data) ++static irqreturn_t xgbe_ecc_isr(int irq, void *data) + { + struct xgbe_prv_data *pdata = data; ++ ++ if (pdata->isr_as_tasklet) ++ tasklet_schedule(&pdata->tasklet_ecc); ++ else ++ xgbe_ecc_isr_task((unsigned long)pdata); ++ ++ return IRQ_HANDLED; ++} ++ ++static void xgbe_isr_task(unsigned long data) ++{ ++ struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; + struct xgbe_hw_if *hw_if = &pdata->hw_if; + struct xgbe_channel *channel; + unsigned int dma_isr, dma_ch_isr; +@@ -542,15 +556,36 @@ static irqreturn_t xgbe_isr(int irq, void *data) + isr_done: + /* If there is not a separate AN irq, handle it here */ + if (pdata->dev_irq == pdata->an_irq) +- pdata->phy_if.an_isr(irq, pdata); ++ pdata->phy_if.an_isr(pdata); + + /* If there is not a separate ECC irq, handle it here */ + if (pdata->vdata->ecc_support && (pdata->dev_irq == pdata->ecc_irq)) +- xgbe_ecc_isr(irq, pdata); ++ xgbe_ecc_isr_task((unsigned long)pdata); + + /* If there is not a separate I2C irq, handle it here */ + if (pdata->vdata->i2c_support && (pdata->dev_irq == pdata->i2c_irq)) +- pdata->i2c_if.i2c_isr(irq, pdata); ++ pdata->i2c_if.i2c_isr(pdata); ++ ++ /* Reissue interrupt if status is not clear */ ++ if (pdata->vdata->irq_reissue_support) { ++ unsigned int reissue_mask; ++ ++ reissue_mask = 1 << 0; ++ if (!pdata->per_channel_irq) ++ reissue_mask |= 0xffff < 4; ++ ++ XP_IOWRITE(pdata, XP_INT_REISSUE_EN, reissue_mask); ++ } ++} ++ ++static irqreturn_t xgbe_isr(int irq, void *data) ++{ ++ struct xgbe_prv_data *pdata = data; ++ ++ if (pdata->isr_as_tasklet) ++ tasklet_schedule(&pdata->tasklet_dev); ++ else ++ xgbe_isr_task((unsigned long)pdata); + + return IRQ_HANDLED; + } +@@ -825,6 +860,10 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata) + unsigned int i; + int ret; + ++ tasklet_init(&pdata->tasklet_dev, xgbe_isr_task, (unsigned long)pdata); ++ tasklet_init(&pdata->tasklet_ecc, xgbe_ecc_isr_task, ++ (unsigned long)pdata); ++ + ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0, + netdev->name, pdata); + if (ret) { +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c +index 417bdb5982a9..4d9062d35930 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c +@@ -274,13 +274,16 @@ static void xgbe_i2c_clear_isr_interrupts(struct xgbe_prv_data *pdata, + XI2C_IOREAD(pdata, IC_CLR_STOP_DET); + } + +-static irqreturn_t xgbe_i2c_isr(int irq, void *data) ++static void xgbe_i2c_isr_task(unsigned long data) + { + struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; + struct xgbe_i2c_op_state *state = &pdata->i2c.op_state; + unsigned int isr; + + isr = XI2C_IOREAD(pdata, IC_RAW_INTR_STAT); ++ if (!isr) ++ goto reissue_check; ++ + netif_dbg(pdata, intr, pdata->netdev, + "I2C interrupt received: status=%#010x\n", isr); + +@@ -308,6 +311,21 @@ static irqreturn_t xgbe_i2c_isr(int irq, void *data) + if (state->ret || XI2C_GET_BITS(isr, IC_RAW_INTR_STAT, STOP_DET)) + complete(&pdata->i2c_complete); + ++reissue_check: ++ /* Reissue interrupt if status is not clear */ ++ if (pdata->vdata->irq_reissue_support) ++ XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 2); ++} ++ ++static irqreturn_t xgbe_i2c_isr(int irq, void *data) ++{ ++ struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; ++ ++ if (pdata->isr_as_tasklet) ++ tasklet_schedule(&pdata->tasklet_i2c); ++ else ++ xgbe_i2c_isr_task((unsigned long)pdata); ++ + return IRQ_HANDLED; + } + +@@ -349,12 +367,11 @@ static void xgbe_i2c_set_target(struct xgbe_prv_data *pdata, unsigned int addr) + XI2C_IOWRITE(pdata, IC_TAR, addr); + } + +-static irqreturn_t xgbe_i2c_combined_isr(int irq, struct xgbe_prv_data *pdata) ++static irqreturn_t xgbe_i2c_combined_isr(struct xgbe_prv_data *pdata) + { +- if (!XI2C_IOREAD(pdata, IC_RAW_INTR_STAT)) +- return IRQ_HANDLED; ++ xgbe_i2c_isr_task((unsigned long)pdata); + +- return xgbe_i2c_isr(irq, pdata); ++ return IRQ_HANDLED; + } + + static int xgbe_i2c_xfer(struct xgbe_prv_data *pdata, struct xgbe_i2c_op *op) +@@ -445,6 +462,9 @@ static int xgbe_i2c_start(struct xgbe_prv_data *pdata) + + /* If we have a separate I2C irq, enable it */ + if (pdata->dev_irq != pdata->i2c_irq) { ++ tasklet_init(&pdata->tasklet_i2c, xgbe_i2c_isr_task, ++ (unsigned long)pdata); ++ + ret = devm_request_irq(pdata->dev, pdata->i2c_irq, + xgbe_i2c_isr, 0, pdata->i2c_name, + pdata); +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +index c7b3f1b0bcc6..f1746eea4dca 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +@@ -636,6 +636,10 @@ static void xgbe_an37_isr(struct xgbe_prv_data *pdata) + } else { + /* Enable AN interrupts */ + xgbe_an37_enable_interrupts(pdata); ++ ++ /* Reissue interrupt if status is not clear */ ++ if (pdata->vdata->irq_reissue_support) ++ XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3); + } + } + +@@ -655,10 +659,14 @@ static void xgbe_an73_isr(struct xgbe_prv_data *pdata) + } else { + /* Enable AN interrupts */ + xgbe_an73_enable_interrupts(pdata); ++ ++ /* Reissue interrupt if status is not clear */ ++ if (pdata->vdata->irq_reissue_support) ++ XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3); + } + } + +-static irqreturn_t xgbe_an_isr(int irq, void *data) ++static void xgbe_an_isr_task(unsigned long data) + { + struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; + +@@ -676,13 +684,25 @@ static irqreturn_t xgbe_an_isr(int irq, void *data) + default: + break; + } ++} ++ ++static irqreturn_t xgbe_an_isr(int irq, void *data) ++{ ++ struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; ++ ++ if (pdata->isr_as_tasklet) ++ tasklet_schedule(&pdata->tasklet_an); ++ else ++ xgbe_an_isr_task((unsigned long)pdata); + + return IRQ_HANDLED; + } + +-static irqreturn_t xgbe_an_combined_isr(int irq, struct xgbe_prv_data *pdata) ++static irqreturn_t xgbe_an_combined_isr(struct xgbe_prv_data *pdata) + { +- return xgbe_an_isr(irq, pdata); ++ xgbe_an_isr_task((unsigned long)pdata); ++ ++ return IRQ_HANDLED; + } + + static void xgbe_an_irq_work(struct work_struct *work) +@@ -892,6 +912,10 @@ static void xgbe_an_state_machine(struct work_struct *work) + break; + } + ++ /* Reissue interrupt if status is not clear */ ++ if (pdata->vdata->irq_reissue_support) ++ XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3); ++ + mutex_unlock(&pdata->an_mutex); + } + +@@ -1356,6 +1380,9 @@ static int xgbe_phy_start(struct xgbe_prv_data *pdata) + + /* If we have a separate AN irq, enable it */ + if (pdata->dev_irq != pdata->an_irq) { ++ tasklet_init(&pdata->tasklet_an, xgbe_an_isr_task, ++ (unsigned long)pdata); ++ + ret = devm_request_irq(pdata->dev, pdata->an_irq, + xgbe_an_isr, 0, pdata->an_name, + pdata); +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +index bd1eb9de2f34..4be490505c7f 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +@@ -139,6 +139,7 @@ static int xgbe_config_multi_msi(struct xgbe_prv_data *pdata) + return ret; + } + ++ pdata->isr_as_tasklet = 1; + pdata->irq_count = ret; + + pdata->dev_irq = pci_irq_vector(pdata->pcidev, 0); +@@ -175,6 +176,7 @@ static int xgbe_config_irqs(struct xgbe_prv_data *pdata) + return ret; + } + ++ pdata->isr_as_tasklet = pdata->pcidev->msi_enabled ? 1 : 0; + pdata->irq_count = 1; + pdata->channel_irq_count = 1; + +@@ -445,6 +445,7 @@ static const struct xgbe_version_data xg + .tx_tstamp_workaround = 1, + .ecc_support = 1, + .i2c_support = 1, ++ .irq_reissue_support = 1, + }; + + static const struct xgbe_version_data xgbe_v2b = { +@@ -456,6 +457,7 @@ static const struct xgbe_version_data xg + .tx_tstamp_workaround = 1, + .ecc_support = 1, + .i2c_support = 1, ++ .irq_reissue_support = 1, + }; + + static const struct pci_device_id xgbe_pci_table[] = { +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index 7df3e12aa200..27d77bb1c84b 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -842,7 +842,7 @@ struct xgbe_phy_if { + bool (*phy_valid_speed)(struct xgbe_prv_data *, int); + + /* For single interrupt support */ +- irqreturn_t (*an_isr)(int, struct xgbe_prv_data *); ++ irqreturn_t (*an_isr)(struct xgbe_prv_data *); + + /* PHY implementation specific services */ + struct xgbe_phy_impl_if phy_impl; +@@ -860,7 +860,7 @@ struct xgbe_i2c_if { + int (*i2c_xfer)(struct xgbe_prv_data *, struct xgbe_i2c_op *); + + /* For single interrupt support */ +- irqreturn_t (*i2c_isr)(int, struct xgbe_prv_data *); ++ irqreturn_t (*i2c_isr)(struct xgbe_prv_data *); + }; + + struct xgbe_desc_if { +@@ -924,6 +924,7 @@ struct xgbe_version_data { + unsigned int tx_tstamp_workaround; + unsigned int ecc_support; + unsigned int i2c_support; ++ unsigned int irq_reissue_support; + }; + + struct xgbe_prv_data { +@@ -1172,6 +1173,12 @@ struct xgbe_prv_data { + + unsigned int lpm_ctrl; /* CTRL1 for resume */ + ++ unsigned int isr_as_tasklet; ++ struct tasklet_struct tasklet_dev; ++ struct tasklet_struct tasklet_ecc; ++ struct tasklet_struct tasklet_i2c; ++ struct tasklet_struct tasklet_an; ++ + #ifdef CONFIG_DEBUG_FS + struct dentry *xgbe_debugfs; + +-- +2.16.4 + diff --git a/patches.suse/0020-amd-xgbe-Add-NUMA-affinity-support-for-memory-alloca.patch b/patches.suse/0020-amd-xgbe-Add-NUMA-affinity-support-for-memory-alloca.patch new file mode 100644 index 0000000..239a7fb --- /dev/null +++ b/patches.suse/0020-amd-xgbe-Add-NUMA-affinity-support-for-memory-alloca.patch @@ -0,0 +1,935 @@ +From 5e2e6e16f4bef0e8c5a77bfbbee5cd93dd5bec3b Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Wed, 28 Jun 2017 13:42:51 -0500 +Subject: [PATCH 20/59] amd-xgbe: Add NUMA affinity support for memory + allocations +References: git-fixes +Patch-mainline: v4.13-rc1 +Git-commit: 18f9f0ac55629b298b1e975c4ed1c86aa21eafb0 + +Add support to perform memory allocations on the node of the device. The +original allocation or the ring structure and Tx/Rx queues allocated all +of the memory at once and then carved it up for each channel and queue. +To best ensure that we get as much memory from the NUMA node as we can, +break the channel and ring allocations into individual allocations. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 94 +++++++++++----- + drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 135 +++++++++-------------- + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 177 ++++++++++++++++-------------- + drivers/net/ethernet/amd/xgbe/xgbe.h | 5 +- + 4 files changed, 217 insertions(+), 194 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c +index 1347318689c1..cc1e4f820e64 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c +@@ -176,8 +176,8 @@ static void xgbe_free_ring_resources(struct xgbe_prv_data *pdata) + + DBGPR("-->xgbe_free_ring_resources\n"); + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { ++ for (i = 0; i < pdata->channel_count; i++) { ++ channel = pdata->channel[i]; + xgbe_free_ring(pdata, channel->tx_ring); + xgbe_free_ring(pdata, channel->rx_ring); + } +@@ -185,34 +185,60 @@ static void xgbe_free_ring_resources(struct xgbe_prv_data *pdata) + DBGPR("<--xgbe_free_ring_resources\n"); + } + ++static void *xgbe_alloc_node(size_t size, int node) ++{ ++ void *mem; ++ ++ mem = kzalloc_node(size, GFP_KERNEL, node); ++ if (!mem) ++ mem = kzalloc(size, GFP_KERNEL); ++ ++ return mem; ++} ++ ++static void *xgbe_dma_alloc_node(struct device *dev, size_t size, ++ dma_addr_t *dma, int node) ++{ ++ void *mem; ++ int cur_node = dev_to_node(dev); ++ ++ set_dev_node(dev, node); ++ mem = dma_alloc_coherent(dev, size, dma, GFP_KERNEL); ++ set_dev_node(dev, cur_node); ++ ++ if (!mem) ++ mem = dma_alloc_coherent(dev, size, dma, GFP_KERNEL); ++ ++ return mem; ++} ++ + static int xgbe_init_ring(struct xgbe_prv_data *pdata, + struct xgbe_ring *ring, unsigned int rdesc_count) + { +- DBGPR("-->xgbe_init_ring\n"); ++ size_t size; + + if (!ring) + return 0; + + /* Descriptors */ ++ size = rdesc_count * sizeof(struct xgbe_ring_desc); ++ + ring->rdesc_count = rdesc_count; +- ring->rdesc = dma_alloc_coherent(pdata->dev, +- (sizeof(struct xgbe_ring_desc) * +- rdesc_count), &ring->rdesc_dma, +- GFP_KERNEL); ++ ring->rdesc = xgbe_dma_alloc_node(pdata->dev, size, &ring->rdesc_dma, ++ ring->node); + if (!ring->rdesc) + return -ENOMEM; + + /* Descriptor information */ +- ring->rdata = kcalloc(rdesc_count, sizeof(struct xgbe_ring_data), +- GFP_KERNEL); ++ size = rdesc_count * sizeof(struct xgbe_ring_data); ++ ++ ring->rdata = xgbe_alloc_node(size, ring->node); + if (!ring->rdata) + return -ENOMEM; + + netif_dbg(pdata, drv, pdata->netdev, +- "rdesc=%p, rdesc_dma=%pad, rdata=%p\n", +- ring->rdesc, &ring->rdesc_dma, ring->rdata); +- +- DBGPR("<--xgbe_init_ring\n"); ++ "rdesc=%p, rdesc_dma=%pad, rdata=%p, node=%d\n", ++ ring->rdesc, &ring->rdesc_dma, ring->rdata, ring->node); + + return 0; + } +@@ -223,10 +249,8 @@ static int xgbe_alloc_ring_resources(struct xgbe_prv_data *pdata) + unsigned int i; + int ret; + +- DBGPR("-->xgbe_alloc_ring_resources\n"); +- +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { ++ for (i = 0; i < pdata->channel_count; i++) { ++ channel = pdata->channel[i]; + netif_dbg(pdata, drv, pdata->netdev, "%s - Tx ring:\n", + channel->name); + +@@ -250,8 +274,6 @@ static int xgbe_alloc_ring_resources(struct xgbe_prv_data *pdata) + } + } + +- DBGPR("<--xgbe_alloc_ring_resources\n"); +- + return 0; + + err_ring: +@@ -261,21 +261,33 @@ err_ring: + } + + static int xgbe_alloc_pages(struct xgbe_prv_data *pdata, +- struct xgbe_page_alloc *pa, gfp_t gfp, int order) ++ struct xgbe_page_alloc *pa, int alloc_order, ++ int node) + { + struct page *pages = NULL; + dma_addr_t pages_dma; +- int ret; ++ gfp_t gfp; ++ int order, ret; ++ ++again: ++ order = alloc_order; + + /* Try to obtain pages, decreasing order if necessary */ +- gfp |= __GFP_COLD | __GFP_COMP | __GFP_NOWARN; ++ gfp = GFP_ATOMIC | __GFP_COMP | __GFP_NOWARN; + while (order >= 0) { +- pages = alloc_pages(gfp, order); ++ pages = alloc_pages_node(node, gfp, order); + if (pages) + break; + + order--; + } ++ ++ /* If we couldn't get local pages, try getting from anywhere */ ++ if (!pages && (node != NUMA_NO_NODE)) { ++ node = NUMA_NO_NODE; ++ goto again; ++ } ++ + if (!pages) + return -ENOMEM; + +@@ -327,14 +361,14 @@ static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata, + int ret; + + if (!ring->rx_hdr_pa.pages) { +- ret = xgbe_alloc_pages(pdata, &ring->rx_hdr_pa, GFP_ATOMIC, 0); ++ ret = xgbe_alloc_pages(pdata, &ring->rx_hdr_pa, 0, ring->node); + if (ret) + return ret; + } + + if (!ring->rx_buf_pa.pages) { +- ret = xgbe_alloc_pages(pdata, &ring->rx_buf_pa, GFP_ATOMIC, +- PAGE_ALLOC_COSTLY_ORDER); ++ ret = xgbe_alloc_pages(pdata, &ring->rx_buf_pa, ++ PAGE_ALLOC_COSTLY_ORDER, ring->node); + if (ret) + return ret; + } +@@ -362,8 +396,8 @@ static void xgbe_wrapper_tx_descriptor_init(struct xgbe_prv_data *pdata) + + DBGPR("-->xgbe_wrapper_tx_descriptor_init\n"); + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { ++ for (i = 0; i < pdata->channel_count; i++) { ++ channel = pdata->channel[i]; + ring = channel->tx_ring; + if (!ring) + break; +@@ -403,8 +437,8 @@ static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata) + + DBGPR("-->xgbe_wrapper_rx_descriptor_init\n"); + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { ++ for (i = 0; i < pdata->channel_count; i++) { ++ channel = pdata->channel[i]; + ring = channel->rx_ring; + if (!ring) + break; +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +index b449c3526090..801e16a9b51c 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +@@ -176,12 +176,10 @@ static unsigned int xgbe_riwt_to_usec(struct xgbe_prv_data *pdata, + + static int xgbe_config_pblx8(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_CR, PBLX8, ++ for (i = 0; i < pdata->channel_count; i++) ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_CR, PBLX8, + pdata->pblx8); + + return 0; +@@ -189,20 +187,18 @@ static int xgbe_config_pblx8(struct xgbe_prv_data *pdata) + + static int xgbe_get_tx_pbl_val(struct xgbe_prv_data *pdata) + { +- return XGMAC_DMA_IOREAD_BITS(pdata->channel, DMA_CH_TCR, PBL); ++ return XGMAC_DMA_IOREAD_BITS(pdata->channel[0], DMA_CH_TCR, PBL); + } + + static int xgbe_config_tx_pbl_val(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- if (!channel->tx_ring) ++ for (i = 0; i < pdata->channel_count; i++) { ++ if (!pdata->channel[i]->tx_ring) + break; + +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, PBL, ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, PBL, + pdata->tx_pbl); + } + +@@ -211,20 +207,18 @@ static int xgbe_config_tx_pbl_val(struct xgbe_prv_data *pdata) + + static int xgbe_get_rx_pbl_val(struct xgbe_prv_data *pdata) + { +- return XGMAC_DMA_IOREAD_BITS(pdata->channel, DMA_CH_RCR, PBL); ++ return XGMAC_DMA_IOREAD_BITS(pdata->channel[0], DMA_CH_RCR, PBL); + } + + static int xgbe_config_rx_pbl_val(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- if (!channel->rx_ring) ++ for (i = 0; i < pdata->channel_count; i++) { ++ if (!pdata->channel[i]->rx_ring) + break; + +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, PBL, ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR, PBL, + pdata->rx_pbl); + } + +@@ -233,15 +227,13 @@ static int xgbe_config_rx_pbl_val(struct xgbe_prv_data *pdata) + + static int xgbe_config_osp_mode(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- if (!channel->tx_ring) ++ for (i = 0; i < pdata->channel_count; i++) { ++ if (!pdata->channel[i]->tx_ring) + break; + +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, OSP, ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, OSP, + pdata->tx_osp_mode); + } + +@@ -292,15 +284,13 @@ static int xgbe_config_tx_threshold(struct xgbe_prv_data *pdata, + + static int xgbe_config_rx_coalesce(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- if (!channel->rx_ring) ++ for (i = 0; i < pdata->channel_count; i++) { ++ if (!pdata->channel[i]->rx_ring) + break; + +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RIWT, RWT, ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RIWT, RWT, + pdata->rx_riwt); + } + +@@ -314,44 +304,38 @@ static int xgbe_config_tx_coalesce(struct xgbe_prv_data *pdata) + + static void xgbe_config_rx_buffer_size(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- if (!channel->rx_ring) ++ for (i = 0; i < pdata->channel_count; i++) { ++ if (!pdata->channel[i]->rx_ring) + break; + +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, RBSZ, ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR, RBSZ, + pdata->rx_buf_size); + } + } + + static void xgbe_config_tso_mode(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- if (!channel->tx_ring) ++ for (i = 0; i < pdata->channel_count; i++) { ++ if (!pdata->channel[i]->tx_ring) + break; + +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, TSE, 1); ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, TSE, 1); + } + } + + static void xgbe_config_sph_mode(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- if (!channel->rx_ring) ++ for (i = 0; i < pdata->channel_count; i++) { ++ if (!pdata->channel[i]->rx_ring) + break; + +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_CR, SPH, 1); ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_CR, SPH, 1); + } + + XGMAC_IOWRITE_BITS(pdata, MAC_RCR, HDSMS, XGBE_SPH_HDSMS_SIZE); +@@ -651,8 +635,9 @@ static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata) + XGMAC_IOWRITE_BITS(pdata, DMA_MR, INTM, + pdata->channel_irq_mode); + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { ++ for (i = 0; i < pdata->channel_count; i++) { ++ channel = pdata->channel[i]; ++ + /* Clear all the interrupts which are set */ + dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR); + XGMAC_DMA_IOWRITE(channel, DMA_CH_SR, dma_ch_isr); +@@ -3223,16 +3208,14 @@ static void xgbe_prepare_tx_stop(struct xgbe_prv_data *pdata, + + static void xgbe_enable_tx(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + + /* Enable each Tx DMA channel */ +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- if (!channel->tx_ring) ++ for (i = 0; i < pdata->channel_count; i++) { ++ if (!pdata->channel[i]->tx_ring) + break; + +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, ST, 1); ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, ST, 1); + } + + /* Enable each Tx queue */ +@@ -3246,7 +3229,6 @@ static void xgbe_enable_tx(struct xgbe_prv_data *pdata) + + static void xgbe_disable_tx(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + + /* Prepare for Tx DMA channel stop */ +@@ -3261,12 +3243,11 @@ static void xgbe_disable_tx(struct xgbe_prv_data *pdata) + XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TXQEN, 0); + + /* Disable each Tx DMA channel */ +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- if (!channel->tx_ring) ++ for (i = 0; i < pdata->channel_count; i++) { ++ if (!pdata->channel[i]->tx_ring) + break; + +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, ST, 0); ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, ST, 0); + } + } + +@@ -3298,16 +3279,14 @@ static void xgbe_prepare_rx_stop(struct xgbe_prv_data *pdata, + + static void xgbe_enable_rx(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int reg_val, i; + + /* Enable each Rx DMA channel */ +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- if (!channel->rx_ring) ++ for (i = 0; i < pdata->channel_count; i++) { ++ if (!pdata->channel[i]->rx_ring) + break; + +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, SR, 1); ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR, SR, 1); + } + + /* Enable each Rx queue */ +@@ -3325,7 +3304,6 @@ static void xgbe_enable_rx(struct xgbe_prv_data *pdata) + + static void xgbe_disable_rx(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + + /* Disable MAC Rx */ +@@ -3342,27 +3320,24 @@ static void xgbe_disable_rx(struct xgbe_prv_data *pdata) + XGMAC_IOWRITE(pdata, MAC_RQC0R, 0); + + /* Disable each Rx DMA channel */ +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- if (!channel->rx_ring) ++ for (i = 0; i < pdata->channel_count; i++) { ++ if (!pdata->channel[i]->rx_ring) + break; + +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, SR, 0); ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR, SR, 0); + } + } + + static void xgbe_powerup_tx(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + + /* Enable each Tx DMA channel */ +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- if (!channel->tx_ring) ++ for (i = 0; i < pdata->channel_count; i++) { ++ if (!pdata->channel[i]->tx_ring) + break; + +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, ST, 1); ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, ST, 1); + } + + /* Enable MAC Tx */ +@@ -3371,7 +3346,6 @@ static void xgbe_powerup_tx(struct xgbe_prv_data *pdata) + + static void xgbe_powerdown_tx(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + + /* Prepare for Tx DMA channel stop */ +@@ -3382,42 +3356,37 @@ static void xgbe_powerdown_tx(struct xgbe_prv_data *pdata) + XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0); + + /* Disable each Tx DMA channel */ +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- if (!channel->tx_ring) ++ for (i = 0; i < pdata->channel_count; i++) { ++ if (!pdata->channel[i]->tx_ring) + break; + +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, ST, 0); ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, ST, 0); + } + } + + static void xgbe_powerup_rx(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + + /* Enable each Rx DMA channel */ +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- if (!channel->rx_ring) ++ for (i = 0; i < pdata->channel_count; i++) { ++ if (!pdata->channel[i]->rx_ring) + break; + +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, SR, 1); ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR, SR, 1); + } + } + + static void xgbe_powerdown_rx(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + + /* Disable each Rx DMA channel */ +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- if (!channel->rx_ring) ++ for (i = 0; i < pdata->channel_count; i++) { ++ if (!pdata->channel[i]->rx_ring) + break; + +- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, SR, 0); ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR, SR, 0); + } + } + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index 73953e5a8e82..d691e6ec1fdc 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -157,81 +157,100 @@ static int xgbe_one_poll(struct napi_struct *, int); + static int xgbe_all_poll(struct napi_struct *, int); + static void xgbe_stop(struct xgbe_prv_data *); + +-static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) ++static void *xgbe_alloc_node(size_t size, int node) + { +- struct xgbe_channel *channel_mem, *channel; +- struct xgbe_ring *tx_ring, *rx_ring; +- unsigned int count, i; +- int ret = -ENOMEM; ++ void *mem; + +- count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count); ++ mem = kzalloc_node(size, GFP_KERNEL, node); ++ if (!mem) ++ mem = kzalloc(size, GFP_KERNEL); ++ ++ return mem; ++} ++ ++static void xgbe_free_channels(struct xgbe_prv_data *pdata) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(pdata->channel); i++) { ++ if (!pdata->channel[i]) ++ continue; ++ ++ kfree(pdata->channel[i]->rx_ring); ++ kfree(pdata->channel[i]->tx_ring); ++ kfree(pdata->channel[i]); ++ ++ pdata->channel[i] = NULL; ++ } + +- channel_mem = kcalloc(count, sizeof(struct xgbe_channel), GFP_KERNEL); +- if (!channel_mem) +- goto err_channel; ++ pdata->channel_count = 0; ++} ++ ++static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) ++{ ++ struct xgbe_channel *channel; ++ struct xgbe_ring *ring; ++ unsigned int count, i; ++ int node; + +- tx_ring = kcalloc(pdata->tx_ring_count, sizeof(struct xgbe_ring), +- GFP_KERNEL); +- if (!tx_ring) +- goto err_tx_ring; ++ node = dev_to_node(pdata->dev); + +- rx_ring = kcalloc(pdata->rx_ring_count, sizeof(struct xgbe_ring), +- GFP_KERNEL); +- if (!rx_ring) +- goto err_rx_ring; ++ count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count); ++ for (i = 0; i < count; i++) { ++ channel = xgbe_alloc_node(sizeof(*channel), node); ++ if (!channel) ++ goto err_mem; ++ pdata->channel[i] = channel; + +- for (i = 0, channel = channel_mem; i < count; i++, channel++) { + snprintf(channel->name, sizeof(channel->name), "channel-%u", i); + channel->pdata = pdata; + channel->queue_index = i; + channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE + + (DMA_CH_INC * i); ++ channel->node = node; + + if (pdata->per_channel_irq) + channel->dma_irq = pdata->channel_irq[i]; + + if (i < pdata->tx_ring_count) { +- spin_lock_init(&tx_ring->lock); +- channel->tx_ring = tx_ring++; ++ ring = xgbe_alloc_node(sizeof(*ring), node); ++ if (!ring) ++ goto err_mem; ++ ++ spin_lock_init(&ring->lock); ++ ring->node = node; ++ ++ channel->tx_ring = ring; + } + + if (i < pdata->rx_ring_count) { +- spin_lock_init(&rx_ring->lock); +- channel->rx_ring = rx_ring++; ++ ring = xgbe_alloc_node(sizeof(*ring), node); ++ if (!ring) ++ goto err_mem; ++ ++ spin_lock_init(&ring->lock); ++ ring->node = node; ++ ++ channel->rx_ring = ring; + } + ++ netif_dbg(pdata, drv, pdata->netdev, ++ "%s: node=%d\n", channel->name, node); ++ + netif_dbg(pdata, drv, pdata->netdev, + "%s: dma_regs=%p, dma_irq=%d, tx=%p, rx=%p\n", + channel->name, channel->dma_regs, channel->dma_irq, + channel->tx_ring, channel->rx_ring); + } + +- pdata->channel = channel_mem; + pdata->channel_count = count; + + return 0; + +-err_rx_ring: +- kfree(tx_ring); +- +-err_tx_ring: +- kfree(channel_mem); +- +-err_channel: +- return ret; +-} +- +-static void xgbe_free_channels(struct xgbe_prv_data *pdata) +-{ +- if (!pdata->channel) +- return; +- +- kfree(pdata->channel->rx_ring); +- kfree(pdata->channel->tx_ring); +- kfree(pdata->channel); ++err_mem: ++ xgbe_free_channels(pdata); + +- pdata->channel = NULL; +- pdata->channel_count = 0; ++ return -ENOMEM; + } + + static inline unsigned int xgbe_tx_avail_desc(struct xgbe_ring *ring) +@@ -300,12 +319,10 @@ static void xgbe_enable_rx_tx_int(struct xgbe_prv_data *pdata, + + static void xgbe_enable_rx_tx_ints(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) +- xgbe_enable_rx_tx_int(pdata, channel); ++ for (i = 0; i < pdata->channel_count; i++) ++ xgbe_enable_rx_tx_int(pdata, pdata->channel[i]); + } + + static void xgbe_disable_rx_tx_int(struct xgbe_prv_data *pdata, +@@ -328,12 +345,10 @@ static void xgbe_disable_rx_tx_int(struct xgbe_prv_data *pdata, + + static void xgbe_disable_rx_tx_ints(struct xgbe_prv_data *pdata) + { +- struct xgbe_channel *channel; + unsigned int i; + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) +- xgbe_disable_rx_tx_int(pdata, channel); ++ for (i = 0; i < pdata->channel_count; i++) ++ xgbe_disable_rx_tx_int(pdata, pdata->channel[i]); + } + + static bool xgbe_ecc_sec(struct xgbe_prv_data *pdata, unsigned long *period, +@@ -474,7 +489,7 @@ static void xgbe_isr_task(unsigned long data) + if (!(dma_isr & (1 << i))) + continue; + +- channel = pdata->channel + i; ++ channel = pdata->channel[i]; + + dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR); + netif_dbg(pdata, intr, pdata->netdev, "DMA_CH%u_ISR=%#010x\n", +@@ -674,8 +689,8 @@ static void xgbe_init_timers(struct xgbe_prv_data *pdata) + setup_timer(&pdata->service_timer, xgbe_service_timer, + (unsigned long)pdata); + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { ++ for (i = 0; i < pdata->channel_count; i++) { ++ channel = pdata->channel[i]; + if (!channel->tx_ring) + break; + +@@ -696,8 +711,8 @@ static void xgbe_stop_timers(struct xgbe_prv_data *pdata) + + del_timer_sync(&pdata->service_timer); + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { ++ for (i = 0; i < pdata->channel_count; i++) { ++ channel = pdata->channel[i]; + if (!channel->tx_ring) + break; + +@@ -815,8 +830,8 @@ static void xgbe_napi_enable(struct xgbe_prv_data *pdata, unsigned int add) + unsigned int i; + + if (pdata->per_channel_irq) { +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { ++ for (i = 0; i < pdata->channel_count; i++) { ++ channel = pdata->channel[i]; + if (add) + netif_napi_add(pdata->netdev, &channel->napi, + xgbe_one_poll, NAPI_POLL_WEIGHT); +@@ -838,8 +853,8 @@ static void xgbe_napi_disable(struct xgbe_prv_data *pdata, unsigned int del) + unsigned int i; + + if (pdata->per_channel_irq) { +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { ++ for (i = 0; i < pdata->channel_count; i++) { ++ channel = pdata->channel[i]; + napi_disable(&channel->napi); + + if (del) +@@ -885,8 +900,8 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata) + if (!pdata->per_channel_irq) + return 0; + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { ++ for (i = 0; i < pdata->channel_count; i++) { ++ channel = pdata->channel[i]; + snprintf(channel->dma_irq_name, + sizeof(channel->dma_irq_name) - 1, + "%s-TxRx-%u", netdev_name(netdev), +@@ -906,8 +921,11 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata) + + err_dma_irq: + /* Using an unsigned int, 'i' will go to UINT_MAX and exit */ +- for (i--, channel--; i < pdata->channel_count; i--, channel--) ++ for (i--; i < pdata->channel_count; i--) { ++ channel = pdata->channel[i]; ++ + devm_free_irq(pdata->dev, channel->dma_irq, channel); ++ } + + if (pdata->vdata->ecc_support && (pdata->dev_irq != pdata->ecc_irq)) + devm_free_irq(pdata->dev, pdata->ecc_irq, pdata); +@@ -931,9 +949,10 @@ static void xgbe_free_irqs(struct xgbe_prv_data *pdata) + if (!pdata->per_channel_irq) + return; + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) ++ for (i = 0; i < pdata->channel_count; i++) { ++ channel = pdata->channel[i]; + devm_free_irq(pdata->dev, channel->dma_irq, channel); ++ } + } + + void xgbe_init_tx_coalesce(struct xgbe_prv_data *pdata) +@@ -968,16 +987,14 @@ void xgbe_init_rx_coalesce(struct xgbe_prv_data *pdata) + static void xgbe_free_tx_data(struct xgbe_prv_data *pdata) + { + struct xgbe_desc_if *desc_if = &pdata->desc_if; +- struct xgbe_channel *channel; + struct xgbe_ring *ring; + struct xgbe_ring_data *rdata; + unsigned int i, j; + + DBGPR("-->xgbe_free_tx_data\n"); + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- ring = channel->tx_ring; ++ for (i = 0; i < pdata->channel_count; i++) { ++ ring = pdata->channel[i]->tx_ring; + if (!ring) + break; + +@@ -993,16 +1010,14 @@ static void xgbe_free_tx_data(struct xgbe_prv_data *pdata) + static void xgbe_free_rx_data(struct xgbe_prv_data *pdata) + { + struct xgbe_desc_if *desc_if = &pdata->desc_if; +- struct xgbe_channel *channel; + struct xgbe_ring *ring; + struct xgbe_ring_data *rdata; + unsigned int i, j; + + DBGPR("-->xgbe_free_rx_data\n"); + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { +- ring = channel->rx_ring; ++ for (i = 0; i < pdata->channel_count; i++) { ++ ring = pdata->channel[i]->rx_ring; + if (!ring) + break; + +@@ -1178,8 +1193,8 @@ static void xgbe_stop(struct xgbe_prv_data *pdata) + + hw_if->exit(pdata); + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { ++ for (i = 0; i < pdata->channel_count; i++) { ++ channel = pdata->channel[i]; + if (!channel->tx_ring) + continue; + +@@ -1666,7 +1681,7 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev) + + DBGPR("-->xgbe_xmit: skb->len = %d\n", skb->len); + +- channel = pdata->channel + skb->queue_mapping; ++ channel = pdata->channel[skb->queue_mapping]; + txq = netdev_get_tx_queue(netdev, channel->queue_index); + ring = channel->tx_ring; + packet = &ring->packet_data; +@@ -1876,9 +1891,10 @@ static void xgbe_poll_controller(struct net_device *netdev) + DBGPR("-->xgbe_poll_controller\n"); + + if (pdata->per_channel_irq) { +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) ++ for (i = 0; i < pdata->channel_count; i++) { ++ channel = pdata->channel[i]; + xgbe_dma_isr(channel->dma_irq, channel); ++ } + } else { + disable_irq(pdata->dev_irq); + xgbe_isr(pdata->dev_irq, pdata); +@@ -2371,8 +2387,9 @@ static int xgbe_all_poll(struct napi_struct *napi, int budget) + do { + last_processed = processed; + +- channel = pdata->channel; +- for (i = 0; i < pdata->channel_count; i++, channel++) { ++ for (i = 0; i < pdata->channel_count; i++) { ++ channel = pdata->channel[i]; ++ + /* Cleanup Tx ring first */ + xgbe_tx_poll(channel); + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index 27d77bb1c84b..2f634be93f3c 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -412,6 +412,7 @@ struct xgbe_ring { + /* Page allocation for RX buffers */ + struct xgbe_page_alloc rx_hdr_pa; + struct xgbe_page_alloc rx_buf_pa; ++ int node; + + /* Ring index values + * cur - Tx: index of descriptor to be used for current transfer +@@ -462,6 +463,8 @@ struct xgbe_channel { + + struct xgbe_ring *tx_ring; + struct xgbe_ring *rx_ring; ++ ++ int node; + } ____cacheline_aligned; + + enum xgbe_state { +@@ -1025,7 +1028,7 @@ struct xgbe_prv_data { + struct timer_list service_timer; + + /* Rings for Tx/Rx on a DMA channel */ +- struct xgbe_channel *channel; ++ struct xgbe_channel *channel[XGBE_MAX_DMA_CHANNELS]; + unsigned int tx_max_channel_count; + unsigned int rx_max_channel_count; + unsigned int channel_count; +-- +2.16.4 + diff --git a/patches.suse/0021-amd-xgbe-Add-NUMA-affinity-support-for-IRQ-hints.patch b/patches.suse/0021-amd-xgbe-Add-NUMA-affinity-support-for-IRQ-hints.patch new file mode 100644 index 0000000..2e8d20b --- /dev/null +++ b/patches.suse/0021-amd-xgbe-Add-NUMA-affinity-support-for-IRQ-hints.patch @@ -0,0 +1,110 @@ +From f88fc06fa74917680b50b3cfd609d659a188acc1 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Wed, 28 Jun 2017 13:43:00 -0500 +Subject: [PATCH 21/59] amd-xgbe: Add NUMA affinity support for IRQ hints +References: git-fixes +Patch-mainline: v4.13-rc1 +Git-commit: f00ba49d8ef9b7a8a9f17be4128fad397e42683b + +For IRQ affinity, set the affinity hints for the IRQs to be (initially) on +the processors corresponding to the NUMA node of the device. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 18 +++++++++++++++--- + drivers/net/ethernet/amd/xgbe/xgbe.h | 2 ++ + 2 files changed, 17 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index d691e6ec1fdc..4cf58558ece4 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -191,12 +191,17 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) + struct xgbe_channel *channel; + struct xgbe_ring *ring; + unsigned int count, i; ++ unsigned int cpu; + int node; + +- node = dev_to_node(pdata->dev); +- + count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count); + for (i = 0; i < count; i++) { ++ /* Attempt to use a CPU on the node the device is on */ ++ cpu = cpumask_local_spread(i, dev_to_node(pdata->dev)); ++ ++ /* Set the allocation node based on the returned CPU */ ++ node = cpu_to_node(cpu); ++ + channel = xgbe_alloc_node(sizeof(*channel), node); + if (!channel) + goto err_mem; +@@ -208,6 +213,7 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) + channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE + + (DMA_CH_INC * i); + channel->node = node; ++ cpumask_set_cpu(cpu, &channel->affinity_mask); + + if (pdata->per_channel_irq) + channel->dma_irq = pdata->channel_irq[i]; +@@ -235,7 +241,7 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) + } + + netif_dbg(pdata, drv, pdata->netdev, +- "%s: node=%d\n", channel->name, node); ++ "%s: cpu=%u, node=%d\n", channel->name, cpu, node); + + netif_dbg(pdata, drv, pdata->netdev, + "%s: dma_regs=%p, dma_irq=%d, tx=%p, rx=%p\n", +@@ -915,6 +921,9 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata) + channel->dma_irq); + goto err_dma_irq; + } ++ ++ irq_set_affinity_hint(channel->dma_irq, ++ &channel->affinity_mask); + } + + return 0; +@@ -924,6 +933,7 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata) + for (i--; i < pdata->channel_count; i--) { + channel = pdata->channel[i]; + ++ irq_set_affinity_hint(channel->dma_irq, NULL); + devm_free_irq(pdata->dev, channel->dma_irq, channel); + } + +@@ -951,6 +961,8 @@ static void xgbe_free_irqs(struct xgbe_prv_data *pdata) + + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; ++ ++ irq_set_affinity_hint(channel->dma_irq, NULL); + devm_free_irq(pdata->dev, channel->dma_irq, channel); + } + } +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index 2f634be93f3c..d434d38b9303 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -128,6 +128,7 @@ + #include + #include + #include ++#include + + #define XGBE_DRV_NAME "amd-xgbe" + #define XGBE_DRV_VERSION "1.0.3" +@@ -465,6 +466,7 @@ struct xgbe_channel { + struct xgbe_ring *rx_ring; + + int node; ++ cpumask_t affinity_mask; + } ____cacheline_aligned; + + enum xgbe_state { +-- +2.16.4 + diff --git a/patches.suse/0022-amd-xgbe-Prepare-for-more-fine-grained-cache-coheren.patch b/patches.suse/0022-amd-xgbe-Prepare-for-more-fine-grained-cache-coheren.patch new file mode 100644 index 0000000..85d456b --- /dev/null +++ b/patches.suse/0022-amd-xgbe-Prepare-for-more-fine-grained-cache-coheren.patch @@ -0,0 +1,173 @@ +From 8143bdde85938fecf38f36fc3de5869cbef62302 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Wed, 28 Jun 2017 13:43:09 -0500 +Subject: [PATCH 22/59] amd-xgbe: Prepare for more fine grained cache coherency + controls +References: git-fixes +Patch-mainline: v4.13-rc1 +Git-commit: 9916716a1bb677be8371f602f53989bf04a70d7f + +In prep for setting fine grained read and write DMA cache coherency +controls, allow specific values to be used to set the cache coherency +registers. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-common.h | 28 --------------------------- + drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 23 ++-------------------- + drivers/net/ethernet/amd/xgbe/xgbe-pci.c | 5 ++--- + drivers/net/ethernet/amd/xgbe/xgbe-platform.c | 10 ++++------ + drivers/net/ethernet/amd/xgbe/xgbe.h | 15 ++++++-------- + 5 files changed, 14 insertions(+), 67 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +index 2c68832dada9..bd9e6a631db9 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +@@ -127,34 +127,6 @@ + #define DMA_DSR1 0x3024 + + /* DMA register entry bit positions and sizes */ +-#define DMA_AXIARCR_DRC_INDEX 0 +-#define DMA_AXIARCR_DRC_WIDTH 4 +-#define DMA_AXIARCR_DRD_INDEX 4 +-#define DMA_AXIARCR_DRD_WIDTH 2 +-#define DMA_AXIARCR_TEC_INDEX 8 +-#define DMA_AXIARCR_TEC_WIDTH 4 +-#define DMA_AXIARCR_TED_INDEX 12 +-#define DMA_AXIARCR_TED_WIDTH 2 +-#define DMA_AXIARCR_THC_INDEX 16 +-#define DMA_AXIARCR_THC_WIDTH 4 +-#define DMA_AXIARCR_THD_INDEX 20 +-#define DMA_AXIARCR_THD_WIDTH 2 +-#define DMA_AXIAWCR_DWC_INDEX 0 +-#define DMA_AXIAWCR_DWC_WIDTH 4 +-#define DMA_AXIAWCR_DWD_INDEX 4 +-#define DMA_AXIAWCR_DWD_WIDTH 2 +-#define DMA_AXIAWCR_RPC_INDEX 8 +-#define DMA_AXIAWCR_RPC_WIDTH 4 +-#define DMA_AXIAWCR_RPD_INDEX 12 +-#define DMA_AXIAWCR_RPD_WIDTH 2 +-#define DMA_AXIAWCR_RHC_INDEX 16 +-#define DMA_AXIAWCR_RHC_WIDTH 4 +-#define DMA_AXIAWCR_RHD_INDEX 20 +-#define DMA_AXIAWCR_RHD_WIDTH 2 +-#define DMA_AXIAWCR_TDC_INDEX 24 +-#define DMA_AXIAWCR_TDC_WIDTH 4 +-#define DMA_AXIAWCR_TDD_INDEX 28 +-#define DMA_AXIAWCR_TDD_WIDTH 2 + #define DMA_ISR_MACIS_INDEX 17 + #define DMA_ISR_MACIS_WIDTH 1 + #define DMA_ISR_MTLIS_INDEX 16 +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +index 801e16a9b51c..405707cc1307 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +@@ -2156,27 +2156,8 @@ static void xgbe_config_dma_bus(struct xgbe_prv_data *pdata) + + static void xgbe_config_dma_cache(struct xgbe_prv_data *pdata) + { +- unsigned int arcache, awcache; +- +- arcache = 0; +- XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRC, pdata->arcache); +- XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRD, pdata->axdomain); +- XGMAC_SET_BITS(arcache, DMA_AXIARCR, TEC, pdata->arcache); +- XGMAC_SET_BITS(arcache, DMA_AXIARCR, TED, pdata->axdomain); +- XGMAC_SET_BITS(arcache, DMA_AXIARCR, THC, pdata->arcache); +- XGMAC_SET_BITS(arcache, DMA_AXIARCR, THD, pdata->axdomain); +- XGMAC_IOWRITE(pdata, DMA_AXIARCR, arcache); +- +- awcache = 0; +- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWC, pdata->awcache); +- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWD, pdata->axdomain); +- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPC, pdata->awcache); +- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPD, pdata->axdomain); +- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHC, pdata->awcache); +- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHD, pdata->axdomain); +- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDC, pdata->awcache); +- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDD, pdata->axdomain); +- XGMAC_IOWRITE(pdata, DMA_AXIAWCR, awcache); ++ XGMAC_IOWRITE(pdata, DMA_AXIARCR, pdata->arcr); ++ XGMAC_IOWRITE(pdata, DMA_AXIAWCR, pdata->awcr); + } + + static void xgbe_config_mtl_mode(struct xgbe_prv_data *pdata) +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +index 4be490505c7f..761fc96597f3 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +@@ -327,9 +327,8 @@ static int xgbe_pci_probe(struct pci_dev + + /* Set the DMA coherency values */ + pdata->coherent = 1; +- pdata->axdomain = XGBE_DMA_OS_AXDOMAIN; +- pdata->arcache = XGBE_DMA_OS_ARCACHE; +- pdata->awcache = XGBE_DMA_OS_AWCACHE; ++ pdata->arcr = XGBE_DMA_OS_ARCR; ++ pdata->awcr = XGBE_DMA_OS_AWCR; + + /* Set the maximum channels and queues */ + reg = XP_IOREAD(pdata, XP_PROP_1); +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c +index 84d4c51cab8c..d0f3dfb88202 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c +@@ -448,13 +448,11 @@ static int xgbe_platform_probe(struct platform_device *pdev) + } + pdata->coherent = (attr == DEV_DMA_COHERENT); + if (pdata->coherent) { +- pdata->axdomain = XGBE_DMA_OS_AXDOMAIN; +- pdata->arcache = XGBE_DMA_OS_ARCACHE; +- pdata->awcache = XGBE_DMA_OS_AWCACHE; ++ pdata->arcr = XGBE_DMA_OS_ARCR; ++ pdata->awcr = XGBE_DMA_OS_AWCR; + } else { +- pdata->axdomain = XGBE_DMA_SYS_AXDOMAIN; +- pdata->arcache = XGBE_DMA_SYS_ARCACHE; +- pdata->awcache = XGBE_DMA_SYS_AWCACHE; ++ pdata->arcr = XGBE_DMA_SYS_ARCR; ++ pdata->awcr = XGBE_DMA_SYS_AWCR; + } + + /* Set the maximum fifo amounts */ +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index d434d38b9303..2f075e00642b 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -164,14 +164,12 @@ + #define XGBE_DMA_STOP_TIMEOUT 1 + + /* DMA cache settings - Outer sharable, write-back, write-allocate */ +-#define XGBE_DMA_OS_AXDOMAIN 0x2 +-#define XGBE_DMA_OS_ARCACHE 0xb +-#define XGBE_DMA_OS_AWCACHE 0xf ++#define XGBE_DMA_OS_ARCR 0x002b2b2b ++#define XGBE_DMA_OS_AWCR 0x2f2f2f2f + + /* DMA cache settings - System, no caches used */ +-#define XGBE_DMA_SYS_AXDOMAIN 0x3 +-#define XGBE_DMA_SYS_ARCACHE 0x0 +-#define XGBE_DMA_SYS_AWCACHE 0x0 ++#define XGBE_DMA_SYS_ARCR 0x00303030 ++#define XGBE_DMA_SYS_AWCR 0x30303030 + + /* DMA channel interrupt modes */ + #define XGBE_IRQ_MODE_EDGE 0 +@@ -1020,9 +1018,8 @@ struct xgbe_prv_data { + + /* AXI DMA settings */ + unsigned int coherent; +- unsigned int axdomain; +- unsigned int arcache; +- unsigned int awcache; ++ unsigned int arcr; ++ unsigned int awcr; + + /* Service routine support */ + struct workqueue_struct *dev_workqueue; +-- +2.16.4 + diff --git a/patches.suse/0023-amd-xgbe-Simplify-the-burst-length-settings.patch b/patches.suse/0023-amd-xgbe-Simplify-the-burst-length-settings.patch new file mode 100644 index 0000000..1147cc7 --- /dev/null +++ b/patches.suse/0023-amd-xgbe-Simplify-the-burst-length-settings.patch @@ -0,0 +1,224 @@ +From 44d6a8a118d07cf003c6ec699926a8ee5dc85ff6 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Wed, 28 Jun 2017 13:43:18 -0500 +Subject: [PATCH 23/59] amd-xgbe: Simplify the burst length settings +References: git-fixes +Patch-mainline: v4.13-rc1 +Git-commit: 7e1e6b86a5d96ca13834fbc6b6e54a9228f308e1 + +Currently the driver hardcodes the PBLx8 setting. Remove the need for +specifying the PBLx8 setting and automatically calculate based on the +specified PBL value. Since the PBLx8 setting applies to both Tx and Rx +use the same PBL value for both of them. + +Also, the driver currently uses a bit field to set the AXI master burst +len setting. Change to the full bit field range and set the burst length +based on the specified value. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-common.h | 11 ++++- + drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 67 ++++++++--------------------- + drivers/net/ethernet/amd/xgbe/xgbe-main.c | 5 +-- + drivers/net/ethernet/amd/xgbe/xgbe.h | 12 +----- + 4 files changed, 31 insertions(+), 64 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +index bd9e6a631db9..c888505aa8f0 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +@@ -137,12 +137,19 @@ + #define DMA_MR_SWR_WIDTH 1 + #define DMA_SBMR_EAME_INDEX 11 + #define DMA_SBMR_EAME_WIDTH 1 +-#define DMA_SBMR_BLEN_256_INDEX 7 +-#define DMA_SBMR_BLEN_256_WIDTH 1 ++#define DMA_SBMR_BLEN_INDEX 1 ++#define DMA_SBMR_BLEN_WIDTH 7 + #define DMA_SBMR_UNDEF_INDEX 0 + #define DMA_SBMR_UNDEF_WIDTH 1 + + /* DMA register values */ ++#define DMA_SBMR_BLEN_256 256 ++#define DMA_SBMR_BLEN_128 128 ++#define DMA_SBMR_BLEN_64 64 ++#define DMA_SBMR_BLEN_32 32 ++#define DMA_SBMR_BLEN_16 16 ++#define DMA_SBMR_BLEN_8 8 ++#define DMA_SBMR_BLEN_4 4 + #define DMA_DSR_RPS_WIDTH 4 + #define DMA_DSR_TPS_WIDTH 4 + #define DMA_DSR_Q_WIDTH (DMA_DSR_RPS_WIDTH + DMA_DSR_TPS_WIDTH) +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +index 405707cc1307..bb30e09f99be 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +@@ -174,52 +174,30 @@ static unsigned int xgbe_riwt_to_usec(struct xgbe_prv_data *pdata, + return ret; + } + +-static int xgbe_config_pblx8(struct xgbe_prv_data *pdata) ++static int xgbe_config_pbl_val(struct xgbe_prv_data *pdata) + { ++ unsigned int pblx8, pbl; + unsigned int i; + +- for (i = 0; i < pdata->channel_count; i++) +- XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_CR, PBLX8, +- pdata->pblx8); +- +- return 0; +-} +- +-static int xgbe_get_tx_pbl_val(struct xgbe_prv_data *pdata) +-{ +- return XGMAC_DMA_IOREAD_BITS(pdata->channel[0], DMA_CH_TCR, PBL); +-} +- +-static int xgbe_config_tx_pbl_val(struct xgbe_prv_data *pdata) +-{ +- unsigned int i; +- +- for (i = 0; i < pdata->channel_count; i++) { +- if (!pdata->channel[i]->tx_ring) +- break; ++ pblx8 = DMA_PBL_X8_DISABLE; ++ pbl = pdata->pbl; + +- XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, PBL, +- pdata->tx_pbl); ++ if (pdata->pbl > 32) { ++ pblx8 = DMA_PBL_X8_ENABLE; ++ pbl >>= 3; + } + +- return 0; +-} +- +-static int xgbe_get_rx_pbl_val(struct xgbe_prv_data *pdata) +-{ +- return XGMAC_DMA_IOREAD_BITS(pdata->channel[0], DMA_CH_RCR, PBL); +-} +- +-static int xgbe_config_rx_pbl_val(struct xgbe_prv_data *pdata) +-{ +- unsigned int i; +- + for (i = 0; i < pdata->channel_count; i++) { +- if (!pdata->channel[i]->rx_ring) +- break; ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_CR, PBLX8, ++ pblx8); ++ ++ if (pdata->channel[i]->tx_ring) ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, ++ PBL, pbl); + +- XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR, PBL, +- pdata->rx_pbl); ++ if (pdata->channel[i]->rx_ring) ++ XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR, ++ PBL, pbl); + } + + return 0; +@@ -2151,7 +2129,7 @@ static void xgbe_config_dma_bus(struct xgbe_prv_data *pdata) + + /* Set the System Bus mode */ + XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, UNDEF, 1); +- XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, BLEN_256, 1); ++ XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, BLEN, pdata->blen >> 2); + } + + static void xgbe_config_dma_cache(struct xgbe_prv_data *pdata) +@@ -3391,9 +3369,7 @@ static int xgbe_init(struct xgbe_prv_data *pdata) + xgbe_config_dma_bus(pdata); + xgbe_config_dma_cache(pdata); + xgbe_config_osp_mode(pdata); +- xgbe_config_pblx8(pdata); +- xgbe_config_tx_pbl_val(pdata); +- xgbe_config_rx_pbl_val(pdata); ++ xgbe_config_pbl_val(pdata); + xgbe_config_rx_coalesce(pdata); + xgbe_config_tx_coalesce(pdata); + xgbe_config_rx_buffer_size(pdata); +@@ -3521,13 +3497,6 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if) + /* For TX DMA Operating on Second Frame config */ + hw_if->config_osp_mode = xgbe_config_osp_mode; + +- /* For RX and TX PBL config */ +- hw_if->config_rx_pbl_val = xgbe_config_rx_pbl_val; +- hw_if->get_rx_pbl_val = xgbe_get_rx_pbl_val; +- hw_if->config_tx_pbl_val = xgbe_config_tx_pbl_val; +- hw_if->get_tx_pbl_val = xgbe_get_tx_pbl_val; +- hw_if->config_pblx8 = xgbe_config_pblx8; +- + /* For MMC statistics support */ + hw_if->tx_mmc_int = xgbe_tx_mmc_int; + hw_if->rx_mmc_int = xgbe_rx_mmc_int; +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +index 17787346e0bc..a9deb4cf1eb6 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +@@ -140,14 +140,13 @@ static void xgbe_default_config(struct xgbe_prv_data *pdata) + { + DBGPR("-->xgbe_default_config\n"); + +- pdata->pblx8 = DMA_PBL_X8_ENABLE; ++ pdata->blen = DMA_SBMR_BLEN_256; ++ pdata->pbl = DMA_PBL_128; + pdata->tx_sf_mode = MTL_TSF_ENABLE; + pdata->tx_threshold = MTL_TX_THRESHOLD_64; +- pdata->tx_pbl = DMA_PBL_16; + pdata->tx_osp_mode = DMA_OSP_ENABLE; + pdata->rx_sf_mode = MTL_RSF_DISABLE; + pdata->rx_threshold = MTL_RX_THRESHOLD_64; +- pdata->rx_pbl = DMA_PBL_16; + pdata->pause_autoneg = 1; + pdata->tx_pause = 1; + pdata->rx_pause = 1; +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index 2f075e00642b..f4176a004756 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -737,13 +737,6 @@ struct xgbe_hw_if { + /* For TX DMA Operate on Second Frame config */ + int (*config_osp_mode)(struct xgbe_prv_data *); + +- /* For RX and TX PBL config */ +- int (*config_rx_pbl_val)(struct xgbe_prv_data *); +- int (*get_rx_pbl_val)(struct xgbe_prv_data *); +- int (*config_tx_pbl_val)(struct xgbe_prv_data *); +- int (*get_tx_pbl_val)(struct xgbe_prv_data *); +- int (*config_pblx8)(struct xgbe_prv_data *); +- + /* For MMC statistics */ + void (*rx_mmc_int)(struct xgbe_prv_data *); + void (*tx_mmc_int)(struct xgbe_prv_data *); +@@ -1042,19 +1035,18 @@ struct xgbe_prv_data { + unsigned int rx_q_count; + + /* Tx/Rx common settings */ +- unsigned int pblx8; ++ unsigned int blen; ++ unsigned int pbl; + + /* Tx settings */ + unsigned int tx_sf_mode; + unsigned int tx_threshold; +- unsigned int tx_pbl; + unsigned int tx_osp_mode; + unsigned int tx_max_fifo_size; + + /* Rx settings */ + unsigned int rx_sf_mode; + unsigned int rx_threshold; +- unsigned int rx_pbl; + unsigned int rx_max_fifo_size; + + /* Tx coalescing settings */ +-- +2.16.4 + diff --git a/patches.suse/0024-amd-xgbe-Adjust-register-settings-to-improve-perform.patch b/patches.suse/0024-amd-xgbe-Adjust-register-settings-to-improve-perform.patch new file mode 100644 index 0000000..1d594b1 --- /dev/null +++ b/patches.suse/0024-amd-xgbe-Adjust-register-settings-to-improve-perform.patch @@ -0,0 +1,214 @@ +From 52f8a1946b18a5b813c8cb2ea50f6290919953f1 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Wed, 28 Jun 2017 13:43:26 -0500 +Subject: [PATCH 24/59] amd-xgbe: Adjust register settings to improve + performance +References: git-fixes +Patch-mainline: v4.13-rc1 +Git-commit: 6f595959c095d8923b19196fea3e983dcb299f22 + +Add support to change some general performance settings and to provide +some performance settings based on the device that is probed. + +This includes: + +- Setting the maximum read/write outstanding request limit +- Reducing the AXI interface burst length size +- Selectively setting the Tx and Rx descriptor pre-fetch threshold +- Selectively setting additional cache coherency controls + +Tested and verified on all versions of the hardware. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-common.h | 13 +++++++++++++ + drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 26 +++++++++++++++++++++++--- + drivers/net/ethernet/amd/xgbe/xgbe-main.c | 5 ++++- + drivers/net/ethernet/amd/xgbe/xgbe-pci.c | 9 +++++++-- + drivers/net/ethernet/amd/xgbe/xgbe.h | 11 +++++++++++ + 5 files changed, 58 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +index c888505aa8f0..c271a49369db 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +@@ -123,8 +123,11 @@ + #define DMA_ISR 0x3008 + #define DMA_AXIARCR 0x3010 + #define DMA_AXIAWCR 0x3018 ++#define DMA_AXIAWARCR 0x301c + #define DMA_DSR0 0x3020 + #define DMA_DSR1 0x3024 ++#define DMA_TXEDMACR 0x3040 ++#define DMA_RXEDMACR 0x3044 + + /* DMA register entry bit positions and sizes */ + #define DMA_ISR_MACIS_INDEX 17 +@@ -135,12 +138,22 @@ + #define DMA_MR_INTM_WIDTH 2 + #define DMA_MR_SWR_INDEX 0 + #define DMA_MR_SWR_WIDTH 1 ++#define DMA_RXEDMACR_RDPS_INDEX 0 ++#define DMA_RXEDMACR_RDPS_WIDTH 3 ++#define DMA_SBMR_AAL_INDEX 12 ++#define DMA_SBMR_AAL_WIDTH 1 + #define DMA_SBMR_EAME_INDEX 11 + #define DMA_SBMR_EAME_WIDTH 1 + #define DMA_SBMR_BLEN_INDEX 1 + #define DMA_SBMR_BLEN_WIDTH 7 ++#define DMA_SBMR_RD_OSR_LMT_INDEX 16 ++#define DMA_SBMR_RD_OSR_LMT_WIDTH 6 + #define DMA_SBMR_UNDEF_INDEX 0 + #define DMA_SBMR_UNDEF_WIDTH 1 ++#define DMA_SBMR_WR_OSR_LMT_INDEX 24 ++#define DMA_SBMR_WR_OSR_LMT_WIDTH 6 ++#define DMA_TXEDMACR_TDPS_INDEX 0 ++#define DMA_TXEDMACR_TDPS_WIDTH 3 + + /* DMA register values */ + #define DMA_SBMR_BLEN_256 256 +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +index bb30e09f99be..e269933dc030 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +@@ -2124,18 +2124,38 @@ static int xgbe_flush_tx_queues(struct xgbe_prv_data *pdata) + + static void xgbe_config_dma_bus(struct xgbe_prv_data *pdata) + { ++ unsigned int sbmr; ++ ++ sbmr = XGMAC_IOREAD(pdata, DMA_SBMR); ++ + /* Set enhanced addressing mode */ +- XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, EAME, 1); ++ XGMAC_SET_BITS(sbmr, DMA_SBMR, EAME, 1); + + /* Set the System Bus mode */ +- XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, UNDEF, 1); +- XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, BLEN, pdata->blen >> 2); ++ XGMAC_SET_BITS(sbmr, DMA_SBMR, UNDEF, 1); ++ XGMAC_SET_BITS(sbmr, DMA_SBMR, BLEN, pdata->blen >> 2); ++ XGMAC_SET_BITS(sbmr, DMA_SBMR, AAL, pdata->aal); ++ XGMAC_SET_BITS(sbmr, DMA_SBMR, RD_OSR_LMT, pdata->rd_osr_limit - 1); ++ XGMAC_SET_BITS(sbmr, DMA_SBMR, WR_OSR_LMT, pdata->wr_osr_limit - 1); ++ ++ XGMAC_IOWRITE(pdata, DMA_SBMR, sbmr); ++ ++ /* Set descriptor fetching threshold */ ++ if (pdata->vdata->tx_desc_prefetch) ++ XGMAC_IOWRITE_BITS(pdata, DMA_TXEDMACR, TDPS, ++ pdata->vdata->tx_desc_prefetch); ++ ++ if (pdata->vdata->rx_desc_prefetch) ++ XGMAC_IOWRITE_BITS(pdata, DMA_RXEDMACR, RDPS, ++ pdata->vdata->rx_desc_prefetch); + } + + static void xgbe_config_dma_cache(struct xgbe_prv_data *pdata) + { + XGMAC_IOWRITE(pdata, DMA_AXIARCR, pdata->arcr); + XGMAC_IOWRITE(pdata, DMA_AXIAWCR, pdata->awcr); ++ if (pdata->awarcr) ++ XGMAC_IOWRITE(pdata, DMA_AXIAWARCR, pdata->awarcr); + } + + static void xgbe_config_mtl_mode(struct xgbe_prv_data *pdata) +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +index a9deb4cf1eb6..9ff12ef0f16e 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +@@ -140,8 +140,11 @@ static void xgbe_default_config(struct xgbe_prv_data *pdata) + { + DBGPR("-->xgbe_default_config\n"); + +- pdata->blen = DMA_SBMR_BLEN_256; ++ pdata->blen = DMA_SBMR_BLEN_64; + pdata->pbl = DMA_PBL_128; ++ pdata->aal = 1; ++ pdata->rd_osr_limit = 8; ++ pdata->wr_osr_limit = 8; + pdata->tx_sf_mode = MTL_TSF_ENABLE; + pdata->tx_threshold = MTL_TX_THRESHOLD_64; + pdata->tx_osp_mode = DMA_OSP_ENABLE; +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +index 761fc96597f3..74d50d989354 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +@@ -327,8 +327,9 @@ static int xgbe_pci_probe(struct pci_dev + + /* Set the DMA coherency values */ + pdata->coherent = 1; +- pdata->arcr = XGBE_DMA_OS_ARCR; +- pdata->awcr = XGBE_DMA_OS_AWCR; ++ pdata->arcr = XGBE_DMA_PCI_ARCR; ++ pdata->awcr = XGBE_DMA_PCI_AWCR; ++ pdata->awarcr = XGBE_DMA_PCI_AWARCR; + + /* Set the maximum channels and queues */ + reg = XP_IOREAD(pdata, XP_PROP_1); +@@ -447,6 +448,8 @@ static const struct xgbe_version_data xg + .ecc_support = 1, + .i2c_support = 1, + .irq_reissue_support = 1, ++ .tx_desc_prefetch = 5, ++ .rx_desc_prefetch = 5, + }; + + static const struct xgbe_version_data xgbe_v2b = { +@@ -459,6 +462,8 @@ static const struct xgbe_version_data xg + .ecc_support = 1, + .i2c_support = 1, + .irq_reissue_support = 1, ++ .tx_desc_prefetch = 5, ++ .rx_desc_prefetch = 5, + }; + + static const struct pci_device_id xgbe_pci_table[] = { +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index f4176a004756..bdad7f99b4f0 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -171,6 +171,11 @@ + #define XGBE_DMA_SYS_ARCR 0x00303030 + #define XGBE_DMA_SYS_AWCR 0x30303030 + ++/* DMA cache settings - PCI device */ ++#define XGBE_DMA_PCI_ARCR 0x00000003 ++#define XGBE_DMA_PCI_AWCR 0x13131313 ++#define XGBE_DMA_PCI_AWARCR 0x00000313 ++ + /* DMA channel interrupt modes */ + #define XGBE_IRQ_MODE_EDGE 0 + #define XGBE_IRQ_MODE_LEVEL 1 +@@ -921,6 +921,8 @@ struct xgbe_version_data { + unsigned int ecc_support; + unsigned int i2c_support; + unsigned int irq_reissue_support; ++ unsigned int tx_desc_prefetch; ++ unsigned int rx_desc_prefetch; + }; + + struct xgbe_prv_data { +@@ -1013,6 +1020,7 @@ struct xgbe_prv_data { + unsigned int coherent; + unsigned int arcr; + unsigned int awcr; ++ unsigned int awarcr; + + /* Service routine support */ + struct workqueue_struct *dev_workqueue; +@@ -1037,6 +1045,9 @@ struct xgbe_prv_data { + /* Tx/Rx common settings */ + unsigned int blen; + unsigned int pbl; ++ unsigned int aal; ++ unsigned int rd_osr_limit; ++ unsigned int wr_osr_limit; + + /* Tx settings */ + unsigned int tx_sf_mode; +-- +2.16.4 + diff --git a/patches.suse/0025-amd-xgbe-fix-spelling-mistake-avialable-available.patch b/patches.suse/0025-amd-xgbe-fix-spelling-mistake-avialable-available.patch new file mode 100644 index 0000000..deb6802 --- /dev/null +++ b/patches.suse/0025-amd-xgbe-fix-spelling-mistake-avialable-available.patch @@ -0,0 +1,34 @@ +From e48c69f8e8bbd96b7cbea4efc871202b01ff36b7 Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Wed, 28 Jun 2017 17:51:10 +0100 +Subject: [PATCH 25/59] amd-xgbe: fix spelling mistake: "avialable" -> + "available" +References: git-fixes +Patch-mainline: v4.13-rc1 +Git-commit: beef8516a4540b61ebb16d94ca0430b8f6760a54 + +Trivial fix to spelling mistake in netdev_err message + +Signed-off-by: Colin Ian King +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +index 920566a3a599..67a2e52ad25d 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +@@ -247,7 +247,7 @@ static int xgbe_set_pauseparam(struct net_device *netdev, + + if (pause->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE)) { + netdev_err(netdev, +- "autoneg disabled, pause autoneg not avialable\n"); ++ "autoneg disabled, pause autoneg not available\n"); + return -EINVAL; + } + +-- +2.16.4 + diff --git a/patches.suse/0026-drivers-net-add-missing-interrupt.h-include.patch b/patches.suse/0026-drivers-net-add-missing-interrupt.h-include.patch new file mode 100644 index 0000000..b98de5f --- /dev/null +++ b/patches.suse/0026-drivers-net-add-missing-interrupt.h-include.patch @@ -0,0 +1,74 @@ +From d025e62d267561d7e4fa266f7254f104644e3781 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Mon, 17 Jul 2017 13:57:18 +0200 +Subject: [PATCH 26/59] drivers: net: add missing interrupt.h include +References: git-fixes +Patch-mainline: v4.14-rc1 +Git-commit: 0ab10314747364e621ab95b528c2bd874ff3f528 + +these drivers use tasklets or irq apis, but don't include interrupt.h. +Once flow cache is removed the implicit interrupt.h inclusion goes away +which will break the build. + +Signed-off-by: Florian Westphal +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/arcnet/arcdevice.h | 2 +- + drivers/net/ethernet/amd/xgbe/xgbe.h | 1 + + drivers/net/ethernet/synopsys/dwc-xlgmac-net.c | 1 + + drivers/net/ieee802154/ca8210.c | 1 + + 4 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h +index 20bfb9ba83ea..258084d4a495 100644 +--- a/drivers/net/arcnet/arcdevice.h ++++ b/drivers/net/arcnet/arcdevice.h +@@ -20,7 +20,7 @@ + #include + + #ifdef __KERNEL__ +-#include ++#include + + /* + * RECON_THRESHOLD is the maximum number of RECON messages to receive +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index bdad7f99b4f0..34080e6e0811 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -129,6 +129,7 @@ + #include + #include + #include ++#include + + #define XGBE_DRV_NAME "amd-xgbe" + #define XGBE_DRV_VERSION "1.0.3" +diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c +index 3b91257683bc..e1b55b8fb8e0 100644 +--- a/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c ++++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c +@@ -17,6 +17,7 @@ + + #include + #include ++#include + + #include "dwc-xlgmac.h" + #include "dwc-xlgmac-reg.h" +diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c +index 61e3b96fc460..1ca2ad503d05 100644 +--- a/drivers/net/ieee802154/ca8210.c ++++ b/drivers/net/ieee802154/ca8210.c +@@ -66,6 +66,7 @@ + #include + #include + #include ++#include + + #include + #include +-- +2.16.4 + diff --git a/patches.suse/0027-amd-xgbe-Set-the-MDIO-mode-for-10000Base-T-configura.patch b/patches.suse/0027-amd-xgbe-Set-the-MDIO-mode-for-10000Base-T-configura.patch new file mode 100644 index 0000000..d5922bc --- /dev/null +++ b/patches.suse/0027-amd-xgbe-Set-the-MDIO-mode-for-10000Base-T-configura.patch @@ -0,0 +1,36 @@ +From a75b1e18bc709461488a7b49574cdbfc5182de4e Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Fri, 18 Aug 2017 09:02:18 -0500 +Subject: [PATCH 27/59] amd-xgbe: Set the MDIO mode for 10000Base-T + configuration +References: git-fixes +Patch-mainline: v4.14-rc1 +Git-commit: 3b1ded4e0b5118040d44b3b85391aa8865b0d05c + +Currently the MDIO mode is set to none for the 10000Base-T, which is +incorrect. The MDIO mode should for this configuration should be +clause 45. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index 070eeb979a1a..0bc599180665 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -3135,7 +3135,7 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) + phy_data->start_mode = XGBE_MODE_KR; + } + +- phy_data->phydev_mode = XGBE_MDIO_MODE_NONE; ++ phy_data->phydev_mode = XGBE_MDIO_MODE_CL45; + break; + + /* 10GBase-R support */ +-- +2.16.4 + diff --git a/patches.suse/0028-amd-xgbe-Set-the-MII-control-width-for-the-MAC-inter.patch b/patches.suse/0028-amd-xgbe-Set-the-MII-control-width-for-the-MAC-inter.patch new file mode 100644 index 0000000..362a6f5 --- /dev/null +++ b/patches.suse/0028-amd-xgbe-Set-the-MII-control-width-for-the-MAC-inter.patch @@ -0,0 +1,49 @@ +From cfd2a25cd85dcc070173748debbc4604c07f4989 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Fri, 18 Aug 2017 09:02:27 -0500 +Subject: [PATCH 28/59] amd-xgbe: Set the MII control width for the MAC + interface +References: git-fixes +Patch-mainline: v4.14-rc1 +Git-commit: f087b506ff5c38e0f2873651dba4e2b73a1b2d67 + +When running in SGMII mode at speeds below 1000Mbps, the auto-negotition +control register must set the MII control width for the MAC interface +to be 8-bits wide. By default the width is 4-bits. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-common.h | 1 + + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 2 ++ + 2 files changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +index c271a49369db..c13069ed0535 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +@@ -1339,6 +1339,7 @@ + #define XGBE_AN_CL37_PCS_MODE_BASEX 0x00 + #define XGBE_AN_CL37_PCS_MODE_SGMII 0x04 + #define XGBE_AN_CL37_TX_CONFIG_MASK 0x08 ++#define XGBE_AN_CL37_MII_CTRL_8BIT 0x0100 + + /* Bit setting and getting macros + * The get macro will extract the current bit field value from within +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +index f1746eea4dca..90eedd65dd3c 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +@@ -959,6 +959,8 @@ static void xgbe_an37_init(struct xgbe_prv_data *pdata) + break; + } + ++ reg |= XGBE_AN_CL37_MII_CTRL_8BIT; ++ + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg); + + netif_dbg(pdata, link, pdata->netdev, "CL37 AN (%s) initialized\n", +-- +2.16.4 + diff --git a/patches.suse/0029-amd-xgbe-Be-sure-driver-shuts-down-cleanly-on-module.patch b/patches.suse/0029-amd-xgbe-Be-sure-driver-shuts-down-cleanly-on-module.patch new file mode 100644 index 0000000..5e0f6da --- /dev/null +++ b/patches.suse/0029-amd-xgbe-Be-sure-driver-shuts-down-cleanly-on-module.patch @@ -0,0 +1,62 @@ +From c74642579e39ddb3fa59868967f04e2137c12201 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Fri, 18 Aug 2017 09:02:40 -0500 +Subject: [PATCH 29/59] amd-xgbe: Be sure driver shuts down cleanly on module + removal +References: git-fixes +Patch-mainline: v4.14-rc1 +Git-commit: 25ff96a9dc9c6a5a21778c36cb1e7175128d2071 + +Sometimes when the driver is being unloaded while the devices are still +up the driver can issue errors. This is based on timing and the double +invocation of some routines. The phy_exit() call needs to be run after +the network device has been closed and unregistered from the system. +Also, the phy_exit() does not need to invoke phy_stop() since that will +be called as part of the device closing, so remove that call. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-main.c | 4 ++-- + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 2 -- + 2 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +index 9ff12ef0f16e..ff12d11071e3 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +@@ -459,6 +459,8 @@ void xgbe_deconfig_netdev(struct xgbe_prv_data *pdata) + if (IS_REACHABLE(CONFIG_PTP_1588_CLOCK)) + xgbe_ptp_unregister(pdata); + ++ unregister_netdev(netdev); ++ + pdata->phy_if.phy_exit(pdata); + + flush_workqueue(pdata->an_workqueue); +@@ -466,8 +468,6 @@ void xgbe_deconfig_netdev(struct xgbe_prv_data *pdata) + + flush_workqueue(pdata->dev_workqueue); + destroy_workqueue(pdata->dev_workqueue); +- +- unregister_netdev(netdev); + } + + static int __init xgbe_mod_init(void) +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +index 90eedd65dd3c..cd8a62233956 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +@@ -1510,8 +1510,6 @@ static int xgbe_phy_best_advertised_speed(struct xgbe_prv_data *pdata) + + static void xgbe_phy_exit(struct xgbe_prv_data *pdata) + { +- xgbe_phy_stop(pdata); +- + pdata->phy_if.phy_impl.exit(pdata); + } + +-- +2.16.4 + diff --git a/patches.suse/0030-amd-xgbe-Update-TSO-packet-statistics-accuracy.patch b/patches.suse/0030-amd-xgbe-Update-TSO-packet-statistics-accuracy.patch new file mode 100644 index 0000000..fea9543 --- /dev/null +++ b/patches.suse/0030-amd-xgbe-Update-TSO-packet-statistics-accuracy.patch @@ -0,0 +1,36 @@ +From 3a406c60008c84240d5f81150076f3c00a58fa53 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Fri, 18 Aug 2017 09:02:49 -0500 +Subject: [PATCH 30/59] amd-xgbe: Update TSO packet statistics accuracy +References: git-fixes +Patch-mainline: v4.14-rc1 +Git-commit: 1b631424e8244722419ebf6ba1fa5a7d72e675c2 + +When transmitting a TSO packet, the driver only increments the TSO packet +statistic by one rather than the number of total packets that were sent. +Update the driver to record the total number of packets that resulted from +TSO transmit. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +index e269933dc030..a8598552efc7 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +@@ -1750,7 +1750,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) + XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, TCPHDRLEN, + packet->tcp_header_len / 4); + +- pdata->ext_stats.tx_tso_packets++; ++ pdata->ext_stats.tx_tso_packets += packet->tx_packets; + } else { + /* Enable CRC and Pad Insertion */ + XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CPC, 0); +-- +2.16.4 + diff --git a/patches.suse/0031-amd-xgbe-Add-support-to-handle-device-renaming.patch b/patches.suse/0031-amd-xgbe-Add-support-to-handle-device-renaming.patch new file mode 100644 index 0000000..394d876 --- /dev/null +++ b/patches.suse/0031-amd-xgbe-Add-support-to-handle-device-renaming.patch @@ -0,0 +1,306 @@ +From ee8caec4fa8493bdd99a9516ee236037ba08db4f Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Fri, 18 Aug 2017 09:02:57 -0500 +Subject: [PATCH 31/59] amd-xgbe: Add support to handle device renaming +References: git-fixes +Patch-mainline: v4.14-rc1 +Git-commit: efbaa828330aed8cfa9529451abfea4a465303ec + +Many of the names used by the driver are based upon the name of the device +found during device probe. Move the formatting of the names into the +device open function so that any renaming that occurs before the device is +brought up will be accounted for. This also means moving the creation of +some named workqueues into the device open path. + +Add support to register for net events so that if a device is renamed +the corresponding debugfs directory can be renamed. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c | 25 ++++++++++ + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 44 +++++++++++++++-- + drivers/net/ethernet/amd/xgbe/xgbe-main.c | 72 ++++++++++++---------------- + drivers/net/ethernet/amd/xgbe/xgbe.h | 5 +- + 4 files changed, 100 insertions(+), 46 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c +index 33a7f2a72f80..b91143947ed2 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c +@@ -543,3 +543,28 @@ void xgbe_debugfs_exit(struct xgbe_prv_data *pdata) + debugfs_remove_recursive(pdata->xgbe_debugfs); + pdata->xgbe_debugfs = NULL; + } ++ ++void xgbe_debugfs_rename(struct xgbe_prv_data *pdata) ++{ ++ struct dentry *pfile; ++ char *buf; ++ ++ if (!pdata->xgbe_debugfs) ++ return; ++ ++ buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name); ++ if (!buf) ++ return; ++ ++ if (!strcmp(pdata->xgbe_debugfs->d_name.name, buf)) ++ goto out; ++ ++ pfile = debugfs_rename(pdata->xgbe_debugfs->d_parent, ++ pdata->xgbe_debugfs, ++ pdata->xgbe_debugfs->d_parent, buf); ++ if (!pfile) ++ netdev_err(pdata->netdev, "debugfs_rename failed\n"); ++ ++out: ++ kfree(buf); ++} +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index 4cf58558ece4..c455a5f8b75e 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -886,7 +886,7 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata) + (unsigned long)pdata); + + ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0, +- netdev->name, pdata); ++ netdev_name(netdev), pdata); + if (ret) { + netdev_alert(netdev, "error requesting irq %d\n", + pdata->dev_irq); +@@ -1588,16 +1588,42 @@ static int xgbe_open(struct net_device *netdev) + + DBGPR("-->xgbe_open\n"); + ++ /* Create the various names based on netdev name */ ++ snprintf(pdata->an_name, sizeof(pdata->an_name) - 1, "%s-pcs", ++ netdev_name(netdev)); ++ ++ snprintf(pdata->ecc_name, sizeof(pdata->ecc_name) - 1, "%s-ecc", ++ netdev_name(netdev)); ++ ++ snprintf(pdata->i2c_name, sizeof(pdata->i2c_name) - 1, "%s-i2c", ++ netdev_name(netdev)); ++ ++ /* Create workqueues */ ++ pdata->dev_workqueue = ++ create_singlethread_workqueue(netdev_name(netdev)); ++ if (!pdata->dev_workqueue) { ++ netdev_err(netdev, "device workqueue creation failed\n"); ++ return -ENOMEM; ++ } ++ ++ pdata->an_workqueue = ++ create_singlethread_workqueue(pdata->an_name); ++ if (!pdata->an_workqueue) { ++ netdev_err(netdev, "phy workqueue creation failed\n"); ++ ret = -ENOMEM; ++ goto err_dev_wq; ++ } ++ + /* Reset the phy settings */ + ret = xgbe_phy_reset(pdata); + if (ret) +- return ret; ++ goto err_an_wq; + + /* Enable the clocks */ + ret = clk_prepare_enable(pdata->sysclk); + if (ret) { + netdev_alert(netdev, "dma clk_prepare_enable failed\n"); +- return ret; ++ goto err_an_wq; + } + + ret = clk_prepare_enable(pdata->ptpclk); +@@ -1650,6 +1676,12 @@ static int xgbe_open(struct net_device *netdev) + err_sysclk: + clk_disable_unprepare(pdata->sysclk); + ++err_an_wq: ++ destroy_workqueue(pdata->an_workqueue); ++ ++err_dev_wq: ++ destroy_workqueue(pdata->dev_workqueue); ++ + return ret; + } + +@@ -1673,6 +1705,12 @@ static int xgbe_close(struct net_device *netdev) + clk_disable_unprepare(pdata->ptpclk); + clk_disable_unprepare(pdata->sysclk); + ++ flush_workqueue(pdata->an_workqueue); ++ destroy_workqueue(pdata->an_workqueue); ++ ++ flush_workqueue(pdata->dev_workqueue); ++ destroy_workqueue(pdata->dev_workqueue); ++ + set_bit(XGBE_DOWN, &pdata->dev_state); + + DBGPR("<--xgbe_close\n"); +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +index ff12d11071e3..798d281f8eac 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +@@ -120,6 +120,7 @@ + #include + #include + #include ++#include + + #include "xgbe.h" + #include "xgbe-common.h" +@@ -400,35 +401,6 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata) + return ret; + } + +- /* Create the PHY/ANEG name based on netdev name */ +- snprintf(pdata->an_name, sizeof(pdata->an_name) - 1, "%s-pcs", +- netdev_name(netdev)); +- +- /* Create the ECC name based on netdev name */ +- snprintf(pdata->ecc_name, sizeof(pdata->ecc_name) - 1, "%s-ecc", +- netdev_name(netdev)); +- +- /* Create the I2C name based on netdev name */ +- snprintf(pdata->i2c_name, sizeof(pdata->i2c_name) - 1, "%s-i2c", +- netdev_name(netdev)); +- +- /* Create workqueues */ +- pdata->dev_workqueue = +- create_singlethread_workqueue(netdev_name(netdev)); +- if (!pdata->dev_workqueue) { +- netdev_err(netdev, "device workqueue creation failed\n"); +- ret = -ENOMEM; +- goto err_netdev; +- } +- +- pdata->an_workqueue = +- create_singlethread_workqueue(pdata->an_name); +- if (!pdata->an_workqueue) { +- netdev_err(netdev, "phy workqueue creation failed\n"); +- ret = -ENOMEM; +- goto err_wq; +- } +- + if (IS_REACHABLE(CONFIG_PTP_1588_CLOCK)) + xgbe_ptp_register(pdata); + +@@ -440,14 +412,6 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata) + pdata->rx_ring_count); + + return 0; +- +-err_wq: +- destroy_workqueue(pdata->dev_workqueue); +- +-err_netdev: +- unregister_netdev(netdev); +- +- return ret; + } + + void xgbe_deconfig_netdev(struct xgbe_prv_data *pdata) +@@ -462,18 +426,42 @@ void xgbe_deconfig_netdev(struct xgbe_prv_data *pdata) + unregister_netdev(netdev); + + pdata->phy_if.phy_exit(pdata); ++} + +- flush_workqueue(pdata->an_workqueue); +- destroy_workqueue(pdata->an_workqueue); ++static int xgbe_netdev_event(struct notifier_block *nb, unsigned long event, ++ void *data) ++{ ++ struct net_device *netdev = netdev_notifier_info_to_dev(data); ++ struct xgbe_prv_data *pdata = netdev_priv(netdev); + +- flush_workqueue(pdata->dev_workqueue); +- destroy_workqueue(pdata->dev_workqueue); ++ if (netdev->netdev_ops != xgbe_get_netdev_ops()) ++ goto out; ++ ++ switch (event) { ++ case NETDEV_CHANGENAME: ++ xgbe_debugfs_rename(pdata); ++ break; ++ ++ default: ++ break; ++ } ++ ++out: ++ return NOTIFY_DONE; + } + ++static struct notifier_block xgbe_netdev_notifier = { ++ .notifier_call = xgbe_netdev_event, ++}; ++ + static int __init xgbe_mod_init(void) + { + int ret; + ++ ret = register_netdevice_notifier(&xgbe_netdev_notifier); ++ if (ret) ++ return ret; ++ + ret = xgbe_platform_init(); + if (ret) + return ret; +@@ -490,6 +478,8 @@ static void __exit xgbe_mod_exit(void) + xgbe_pci_exit(); + + xgbe_platform_exit(); ++ ++ unregister_netdevice_notifier(&xgbe_netdev_notifier); + } + + module_init(xgbe_mod_init); +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index 34080e6e0811..6f7e8019261e 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -130,6 +130,7 @@ + #include + #include + #include ++#include + + #define XGBE_DRV_NAME "amd-xgbe" + #define XGBE_DRV_VERSION "1.0.3" +@@ -1185,7 +1186,6 @@ struct xgbe_prv_data { + struct tasklet_struct tasklet_i2c; + struct tasklet_struct tasklet_an; + +-#ifdef CONFIG_DEBUG_FS + struct dentry *xgbe_debugfs; + + unsigned int debugfs_xgmac_reg; +@@ -1183,7 +1183,6 @@ struct xgbe_prv_data { + unsigned int debugfs_xprop_reg; + + unsigned int debugfs_xi2c_reg; +-#endif + }; + + /* Function prototypes*/ +@@ -1248,9 +1247,11 @@ void xgbe_init_tx_coalesce(struct xgbe_prv_data *); + #ifdef CONFIG_DEBUG_FS + void xgbe_debugfs_init(struct xgbe_prv_data *); + void xgbe_debugfs_exit(struct xgbe_prv_data *); ++void xgbe_debugfs_rename(struct xgbe_prv_data *pdata); + #else + static inline void xgbe_debugfs_init(struct xgbe_prv_data *pdata) {} + static inline void xgbe_debugfs_exit(struct xgbe_prv_data *pdata) {} ++static inline void xgbe_debugfs_rename(struct xgbe_prv_data *pdata) {} + #endif /* CONFIG_DEBUG_FS */ + + /* NOTE: Uncomment for function trace log messages in KERNEL LOG */ +-- +2.16.4 + diff --git a/patches.suse/0032-amd-xgbe-Add-additional-dynamic-debug-messages.patch b/patches.suse/0032-amd-xgbe-Add-additional-dynamic-debug-messages.patch new file mode 100644 index 0000000..e90ac0d --- /dev/null +++ b/patches.suse/0032-amd-xgbe-Add-additional-dynamic-debug-messages.patch @@ -0,0 +1,36 @@ +From 951ad64f73ef5df006ca75ad0eb34084e2f40776 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Fri, 18 Aug 2017 09:03:08 -0500 +Subject: [PATCH 32/59] amd-xgbe: Add additional dynamic debug messages +References: git-fixes +Patch-mainline: v4.14-rc1 +Git-commit: 40452f0ec84a3b7082a934404783a121d378b990 + +Add some additional dynamic debug message to the driver. The new messages +will provide additional information about the PCS window calculation. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +index 74d50d989354..a878ceb8766f 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +@@ -292,6 +292,10 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + pdata->xpcs_window_size = 1 << (pdata->xpcs_window_size + 7); + pdata->xpcs_window_mask = pdata->xpcs_window_size - 1; + if (netif_msg_probe(pdata)) { ++ dev_dbg(dev, "xpcs window def = %#010x\n", ++ pdata->xpcs_window_def_reg); ++ dev_dbg(dev, "xpcs window sel = %#010x\n", ++ pdata->xpcs_window_sel_reg); + dev_dbg(dev, "xpcs window = %#010x\n", + pdata->xpcs_window); + dev_dbg(dev, "xpcs window size = %#010x\n", +-- +2.16.4 + diff --git a/patches.suse/0033-amd-xgbe-Optimize-DMA-channel-interrupt-enablement.patch b/patches.suse/0033-amd-xgbe-Optimize-DMA-channel-interrupt-enablement.patch new file mode 100644 index 0000000..f1c5ce0 --- /dev/null +++ b/patches.suse/0033-amd-xgbe-Optimize-DMA-channel-interrupt-enablement.patch @@ -0,0 +1,231 @@ +From 94626d17caf6dd81c05ef352cafc77e8dfae4201 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Fri, 18 Aug 2017 09:03:17 -0500 +Subject: [PATCH 33/59] amd-xgbe: Optimize DMA channel interrupt enablement +References: git-fixes +Patch-mainline: v4.14-rc1 +Git-commit: caa575afad73ce1a40848543461667c57a1ad989 + +Currently whenever the driver needs to enable or disable interrupts for +a DMA channel it reads the interrupt enable register (IER), updates the +value and then writes the new value back to the IER. Since the hardware +does not change the IER, software can track this value and elimiate the +need to read it each time. + +Add the IER value to the channel related data structure and use that as +the base for enabling and disabling interrupts, thus removing the need +for the MMIO read. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 77 +++++++++++++++----------------- + drivers/net/ethernet/amd/xgbe/xgbe.h | 4 +- + 2 files changed, 37 insertions(+), 44 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +index a8598552efc7..2f5ca2e1ec5d 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +@@ -605,7 +605,6 @@ static void xgbe_config_flow_control(struct xgbe_prv_data *pdata) + static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata) + { + struct xgbe_channel *channel; +- unsigned int dma_ch_isr, dma_ch_ier; + unsigned int i; + + /* Set the interrupt mode if supported */ +@@ -617,20 +616,20 @@ static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata) + channel = pdata->channel[i]; + + /* Clear all the interrupts which are set */ +- dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR); +- XGMAC_DMA_IOWRITE(channel, DMA_CH_SR, dma_ch_isr); ++ XGMAC_DMA_IOWRITE(channel, DMA_CH_SR, ++ XGMAC_DMA_IOREAD(channel, DMA_CH_SR)); + + /* Clear all interrupt enable bits */ +- dma_ch_ier = 0; ++ channel->curr_ier = 0; + + /* Enable following interrupts + * NIE - Normal Interrupt Summary Enable + * AIE - Abnormal Interrupt Summary Enable + * FBEE - Fatal Bus Error Enable + */ +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, NIE, 1); +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, AIE, 1); +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, FBEE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, NIE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, AIE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, FBEE, 1); + + if (channel->tx_ring) { + /* Enable the following Tx interrupts +@@ -639,7 +638,8 @@ static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata) + * mode) + */ + if (!pdata->per_channel_irq || pdata->channel_irq_mode) +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, ++ DMA_CH_IER, TIE, 1); + } + if (channel->rx_ring) { + /* Enable following Rx interrupts +@@ -648,12 +648,13 @@ static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata) + * per channel interrupts in edge triggered + * mode) + */ +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, RBUE, 1); + if (!pdata->per_channel_irq || pdata->channel_irq_mode) +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, ++ DMA_CH_IER, RIE, 1); + } + +- XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier); ++ XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, channel->curr_ier); + } + } + +@@ -1974,44 +1975,40 @@ static int xgbe_is_last_desc(struct xgbe_ring_desc *rdesc) + static int xgbe_enable_int(struct xgbe_channel *channel, + enum xgbe_int int_id) + { +- unsigned int dma_ch_ier; +- +- dma_ch_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER); +- + switch (int_id) { + case XGMAC_INT_DMA_CH_SR_TI: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, TIE, 1); + break; + case XGMAC_INT_DMA_CH_SR_TPS: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TXSE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, TXSE, 1); + break; + case XGMAC_INT_DMA_CH_SR_TBU: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TBUE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, TBUE, 1); + break; + case XGMAC_INT_DMA_CH_SR_RI: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, RIE, 1); + break; + case XGMAC_INT_DMA_CH_SR_RBU: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, RBUE, 1); + break; + case XGMAC_INT_DMA_CH_SR_RPS: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RSE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, RSE, 1); + break; + case XGMAC_INT_DMA_CH_SR_TI_RI: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1); +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, TIE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, RIE, 1); + break; + case XGMAC_INT_DMA_CH_SR_FBE: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, FBEE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, FBEE, 1); + break; + case XGMAC_INT_DMA_ALL: +- dma_ch_ier |= channel->saved_ier; ++ channel->curr_ier |= channel->saved_ier; + break; + default: + return -1; + } + +- XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier); ++ XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, channel->curr_ier); + + return 0; + } +@@ -2019,45 +2016,41 @@ static int xgbe_enable_int(struct xgbe_channel *channel, + static int xgbe_disable_int(struct xgbe_channel *channel, + enum xgbe_int int_id) + { +- unsigned int dma_ch_ier; +- +- dma_ch_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER); +- + switch (int_id) { + case XGMAC_INT_DMA_CH_SR_TI: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 0); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, TIE, 0); + break; + case XGMAC_INT_DMA_CH_SR_TPS: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TXSE, 0); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, TXSE, 0); + break; + case XGMAC_INT_DMA_CH_SR_TBU: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TBUE, 0); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, TBUE, 0); + break; + case XGMAC_INT_DMA_CH_SR_RI: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 0); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, RIE, 0); + break; + case XGMAC_INT_DMA_CH_SR_RBU: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 0); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, RBUE, 0); + break; + case XGMAC_INT_DMA_CH_SR_RPS: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RSE, 0); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, RSE, 0); + break; + case XGMAC_INT_DMA_CH_SR_TI_RI: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 0); +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 0); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, TIE, 0); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, RIE, 0); + break; + case XGMAC_INT_DMA_CH_SR_FBE: +- XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, FBEE, 0); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, FBEE, 0); + break; + case XGMAC_INT_DMA_ALL: +- channel->saved_ier = dma_ch_ier & XGBE_DMA_INTERRUPT_MASK; +- dma_ch_ier &= ~XGBE_DMA_INTERRUPT_MASK; ++ channel->saved_ier = channel->curr_ier; ++ channel->curr_ier = 0; + break; + default: + return -1; + } + +- XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier); ++ XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, channel->curr_ier); + + return 0; + } +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index 6f7e8019261e..c7595644f3b3 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -182,8 +182,6 @@ + #define XGBE_IRQ_MODE_EDGE 0 + #define XGBE_IRQ_MODE_LEVEL 1 + +-#define XGBE_DMA_INTERRUPT_MASK 0x31c7 +- + #define XGMAC_MIN_PACKET 60 + #define XGMAC_STD_PACKET_MTU 1500 + #define XGMAC_MAX_STD_PACKET 1518 +@@ -462,6 +460,8 @@ struct xgbe_channel { + /* Netdev related settings */ + struct napi_struct napi; + ++ /* Per channel interrupt enablement tracker */ ++ unsigned int curr_ier; + unsigned int saved_ier; + + unsigned int tx_timer_active; +-- +2.16.4 + diff --git a/patches.suse/0034-amd-xgbe-Add-hardware-features-debug-output.patch b/patches.suse/0034-amd-xgbe-Add-hardware-features-debug-output.patch new file mode 100644 index 0000000..451e04f --- /dev/null +++ b/patches.suse/0034-amd-xgbe-Add-hardware-features-debug-output.patch @@ -0,0 +1,117 @@ +From 635103061366f053096950ec5511b49a93162243 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Fri, 18 Aug 2017 09:03:26 -0500 +Subject: [PATCH 34/59] amd-xgbe: Add hardware features debug output +References: git-fixes +Patch-mainline: v4.14-rc1 +Git-commit: 3be95872e89eeabc83ddd6011c988d85c94df050 + +Use the dynamic debug support to output information about the hardware +features reported by the device. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 78 ++++++++++++++++++++++++++++++-- + 1 file changed, 75 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index c455a5f8b75e..352b67f3d651 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -731,8 +731,6 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata) + unsigned int mac_hfr0, mac_hfr1, mac_hfr2; + struct xgbe_hw_features *hw_feat = &pdata->hw_feat; + +- DBGPR("-->xgbe_get_all_hw_features\n"); +- + mac_hfr0 = XGMAC_IOREAD(pdata, MAC_HWF0R); + mac_hfr1 = XGMAC_IOREAD(pdata, MAC_HWF1R); + mac_hfr2 = XGMAC_IOREAD(pdata, MAC_HWF2R); +@@ -827,7 +825,81 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata) + hw_feat->rx_fifo_size = 1 << (hw_feat->rx_fifo_size + 7); + hw_feat->tx_fifo_size = 1 << (hw_feat->tx_fifo_size + 7); + +- DBGPR("<--xgbe_get_all_hw_features\n"); ++ if (netif_msg_probe(pdata)) { ++ dev_dbg(pdata->dev, "Hardware features:\n"); ++ ++ /* Hardware feature register 0 */ ++ dev_dbg(pdata->dev, " 1GbE support : %s\n", ++ hw_feat->gmii ? "yes" : "no"); ++ dev_dbg(pdata->dev, " VLAN hash filter : %s\n", ++ hw_feat->vlhash ? "yes" : "no"); ++ dev_dbg(pdata->dev, " MDIO interface : %s\n", ++ hw_feat->sma ? "yes" : "no"); ++ dev_dbg(pdata->dev, " Wake-up packet support : %s\n", ++ hw_feat->rwk ? "yes" : "no"); ++ dev_dbg(pdata->dev, " Magic packet support : %s\n", ++ hw_feat->mgk ? "yes" : "no"); ++ dev_dbg(pdata->dev, " Management counters : %s\n", ++ hw_feat->mmc ? "yes" : "no"); ++ dev_dbg(pdata->dev, " ARP offload : %s\n", ++ hw_feat->aoe ? "yes" : "no"); ++ dev_dbg(pdata->dev, " IEEE 1588-2008 Timestamp : %s\n", ++ hw_feat->ts ? "yes" : "no"); ++ dev_dbg(pdata->dev, " Energy Efficient Ethernet : %s\n", ++ hw_feat->eee ? "yes" : "no"); ++ dev_dbg(pdata->dev, " TX checksum offload : %s\n", ++ hw_feat->tx_coe ? "yes" : "no"); ++ dev_dbg(pdata->dev, " RX checksum offload : %s\n", ++ hw_feat->rx_coe ? "yes" : "no"); ++ dev_dbg(pdata->dev, " Additional MAC addresses : %u\n", ++ hw_feat->addn_mac); ++ dev_dbg(pdata->dev, " Timestamp source : %s\n", ++ (hw_feat->ts_src == 1) ? "internal" : ++ (hw_feat->ts_src == 2) ? "external" : ++ (hw_feat->ts_src == 3) ? "internal/external" : "n/a"); ++ dev_dbg(pdata->dev, " SA/VLAN insertion : %s\n", ++ hw_feat->sa_vlan_ins ? "yes" : "no"); ++ ++ /* Hardware feature register 1 */ ++ dev_dbg(pdata->dev, " RX fifo size : %u\n", ++ hw_feat->rx_fifo_size); ++ dev_dbg(pdata->dev, " TX fifo size : %u\n", ++ hw_feat->tx_fifo_size); ++ dev_dbg(pdata->dev, " IEEE 1588 high word : %s\n", ++ hw_feat->adv_ts_hi ? "yes" : "no"); ++ dev_dbg(pdata->dev, " DMA width : %u\n", ++ hw_feat->dma_width); ++ dev_dbg(pdata->dev, " Data Center Bridging : %s\n", ++ hw_feat->dcb ? "yes" : "no"); ++ dev_dbg(pdata->dev, " Split header : %s\n", ++ hw_feat->sph ? "yes" : "no"); ++ dev_dbg(pdata->dev, " TCP Segmentation Offload : %s\n", ++ hw_feat->tso ? "yes" : "no"); ++ dev_dbg(pdata->dev, " Debug memory interface : %s\n", ++ hw_feat->dma_debug ? "yes" : "no"); ++ dev_dbg(pdata->dev, " Receive Side Scaling : %s\n", ++ hw_feat->rss ? "yes" : "no"); ++ dev_dbg(pdata->dev, " Traffic Class count : %u\n", ++ hw_feat->tc_cnt); ++ dev_dbg(pdata->dev, " Hash table size : %u\n", ++ hw_feat->hash_table_size); ++ dev_dbg(pdata->dev, " L3/L4 Filters : %u\n", ++ hw_feat->l3l4_filter_num); ++ ++ /* Hardware feature register 2 */ ++ dev_dbg(pdata->dev, " RX queue count : %u\n", ++ hw_feat->rx_q_cnt); ++ dev_dbg(pdata->dev, " TX queue count : %u\n", ++ hw_feat->tx_q_cnt); ++ dev_dbg(pdata->dev, " RX DMA channel count : %u\n", ++ hw_feat->rx_ch_cnt); ++ dev_dbg(pdata->dev, " TX DMA channel count : %u\n", ++ hw_feat->rx_ch_cnt); ++ dev_dbg(pdata->dev, " PPS outputs : %u\n", ++ hw_feat->pps_out_num); ++ dev_dbg(pdata->dev, " Auxiliary snapshot inputs : %u\n", ++ hw_feat->aux_snap_num); ++ } + } + + static void xgbe_napi_enable(struct xgbe_prv_data *pdata, unsigned int add) +-- +2.16.4 + diff --git a/patches.suse/0035-amd-xgbe-Add-per-queue-Tx-and-Rx-statistics.patch b/patches.suse/0035-amd-xgbe-Add-per-queue-Tx-and-Rx-statistics.patch new file mode 100644 index 0000000..6c6ba5e --- /dev/null +++ b/patches.suse/0035-amd-xgbe-Add-per-queue-Tx-and-Rx-statistics.patch @@ -0,0 +1,169 @@ +From 0e8787bf498093fcc053f54f82c33b859c89d984 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Fri, 18 Aug 2017 09:03:35 -0500 +Subject: [PATCH 35/59] amd-xgbe: Add per queue Tx and Rx statistics +References: git-fixes +Patch-mainline: v4.14-rc1 +Git-commit: 80a788c94e6c0aa29dfbb43eae4a0d4144992c5d + +Add per queue Tx and Rx packet and byte counts. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 23 ++++++++++++++++------- + drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 26 +++++++++++++++++++++++++- + drivers/net/ethernet/amd/xgbe/xgbe.h | 5 +++++ + 3 files changed, 46 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +index 2f5ca2e1ec5d..1cf2b3a04401 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +@@ -1619,6 +1619,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) + struct xgbe_ring_data *rdata; + struct xgbe_ring_desc *rdesc; + struct xgbe_packet_data *packet = &ring->packet_data; ++ unsigned int tx_packets, tx_bytes; + unsigned int csum, tso, vlan; + unsigned int tso_context, vlan_context; + unsigned int tx_set_ic; +@@ -1628,6 +1629,9 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) + + DBGPR("-->xgbe_dev_xmit\n"); + ++ tx_packets = packet->tx_packets; ++ tx_bytes = packet->tx_bytes; ++ + csum = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, + CSUM_ENABLE); + tso = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, +@@ -1655,13 +1659,12 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) + * - Addition of Tx frame count to the frame count since the + * last interrupt was set does not exceed the frame count setting + */ +- ring->coalesce_count += packet->tx_packets; ++ ring->coalesce_count += tx_packets; + if (!pdata->tx_frames) + tx_set_ic = 0; +- else if (packet->tx_packets > pdata->tx_frames) ++ else if (tx_packets > pdata->tx_frames) + tx_set_ic = 1; +- else if ((ring->coalesce_count % pdata->tx_frames) < +- packet->tx_packets) ++ else if ((ring->coalesce_count % pdata->tx_frames) < tx_packets) + tx_set_ic = 1; + else + tx_set_ic = 0; +@@ -1751,7 +1754,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) + XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, TCPHDRLEN, + packet->tcp_header_len / 4); + +- pdata->ext_stats.tx_tso_packets += packet->tx_packets; ++ pdata->ext_stats.tx_tso_packets += tx_packets; + } else { + /* Enable CRC and Pad Insertion */ + XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CPC, 0); +@@ -1799,8 +1802,11 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) + XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1); + + /* Save the Tx info to report back during cleanup */ +- rdata->tx.packets = packet->tx_packets; +- rdata->tx.bytes = packet->tx_bytes; ++ rdata->tx.packets = tx_packets; ++ rdata->tx.bytes = tx_bytes; ++ ++ pdata->ext_stats.txq_packets[channel->queue_index] += tx_packets; ++ pdata->ext_stats.txq_bytes[channel->queue_index] += tx_bytes; + + /* In case the Tx DMA engine is running, make sure everything + * is written to the descriptor(s) before setting the OWN bit +@@ -1954,6 +1960,9 @@ static int xgbe_dev_read(struct xgbe_channel *channel) + FRAME, 1); + } + ++ pdata->ext_stats.rxq_packets[channel->queue_index]++; ++ pdata->ext_stats.rxq_bytes[channel->queue_index] += rdata->rx.len; ++ + DBGPR("<--xgbe_dev_read: %s - descriptor=%u (cur=%d)\n", channel->name, + ring->cur & (ring->rdesc_count - 1), ring->cur); + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +index 67a2e52ad25d..f80b186779b7 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +@@ -186,6 +186,7 @@ static const struct xgbe_stats xgbe_gstring_stats[] = { + + static void xgbe_get_strings(struct net_device *netdev, u32 stringset, u8 *data) + { ++ struct xgbe_prv_data *pdata = netdev_priv(netdev); + int i; + + switch (stringset) { +@@ -195,6 +196,18 @@ static void xgbe_get_strings(struct net_device *netdev, u32 stringset, u8 *data) + ETH_GSTRING_LEN); + data += ETH_GSTRING_LEN; + } ++ for (i = 0; i < pdata->tx_ring_count; i++) { ++ sprintf(data, "txq_%u_packets", i); ++ data += ETH_GSTRING_LEN; ++ sprintf(data, "txq_%u_bytes", i); ++ data += ETH_GSTRING_LEN; ++ } ++ for (i = 0; i < pdata->rx_ring_count; i++) { ++ sprintf(data, "rxq_%u_packets", i); ++ data += ETH_GSTRING_LEN; ++ sprintf(data, "rxq_%u_bytes", i); ++ data += ETH_GSTRING_LEN; ++ } + break; + } + } +@@ -211,15 +224,26 @@ static void xgbe_get_ethtool_stats(struct net_device *netdev, + stat = (u8 *)pdata + xgbe_gstring_stats[i].stat_offset; + *data++ = *(u64 *)stat; + } ++ for (i = 0; i < pdata->tx_ring_count; i++) { ++ *data++ = pdata->ext_stats.txq_packets[i]; ++ *data++ = pdata->ext_stats.txq_bytes[i]; ++ } ++ for (i = 0; i < pdata->rx_ring_count; i++) { ++ *data++ = pdata->ext_stats.rxq_packets[i]; ++ *data++ = pdata->ext_stats.rxq_bytes[i]; ++ } + } + + static int xgbe_get_sset_count(struct net_device *netdev, int stringset) + { ++ struct xgbe_prv_data *pdata = netdev_priv(netdev); + int ret; + + switch (stringset) { + case ETH_SS_STATS: +- ret = XGBE_STATS_COUNT; ++ ret = XGBE_STATS_COUNT + ++ (pdata->tx_ring_count * 2) + ++ (pdata->rx_ring_count * 2); + break; + + default: +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index c7595644f3b3..89f3f30784fb 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -668,6 +668,11 @@ struct xgbe_ext_stats { + u64 tx_tso_packets; + u64 rx_split_header_packets; + u64 rx_buffer_unavailable; ++ ++ u64 txq_packets[XGBE_MAX_DMA_CHANNELS]; ++ u64 txq_bytes[XGBE_MAX_DMA_CHANNELS]; ++ u64 rxq_packets[XGBE_MAX_DMA_CHANNELS]; ++ u64 rxq_bytes[XGBE_MAX_DMA_CHANNELS]; + }; + + struct xgbe_hw_if { +-- +2.16.4 + diff --git a/patches.suse/0036-amd-xgbe-Convert-to-using-the-new-link-mode-settings.patch b/patches.suse/0036-amd-xgbe-Convert-to-using-the-new-link-mode-settings.patch new file mode 100644 index 0000000..ce11db0 --- /dev/null +++ b/patches.suse/0036-amd-xgbe-Convert-to-using-the-new-link-mode-settings.patch @@ -0,0 +1,1350 @@ +From 6eda839b5d3b42137f3c9f8f3fd3b36fabe74f02 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Fri, 18 Aug 2017 09:03:55 -0500 +Subject: [PATCH 36/59] amd-xgbe: Convert to using the new link mode settings +References: git-fixes +Patch-mainline: v4.14-rc1 +Git-commit: 85f9feb64bd5cfd6412258be15f90b517b4b40fc + +Convert from using the old u32 supported, advertising, etc. link settings +to the new link mode settings that support bit positions / settings +greater than 32 bits. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 56 +++-- + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 77 +++--- + drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c | 54 +++-- + drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 350 +++++++++++++++------------ + drivers/net/ethernet/amd/xgbe/xgbe.h | 50 +++- + 5 files changed, 345 insertions(+), 242 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +index f80b186779b7..cea25acd5de2 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +@@ -267,6 +267,7 @@ static int xgbe_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) + { + struct xgbe_prv_data *pdata = netdev_priv(netdev); ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + int ret = 0; + + if (pause->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE)) { +@@ -279,16 +280,21 @@ static int xgbe_set_pauseparam(struct net_device *netdev, + pdata->phy.tx_pause = pause->tx_pause; + pdata->phy.rx_pause = pause->rx_pause; + +- pdata->phy.advertising &= ~ADVERTISED_Pause; +- pdata->phy.advertising &= ~ADVERTISED_Asym_Pause; ++ XGBE_CLR_ADV(lks, Pause); ++ XGBE_CLR_ADV(lks, Asym_Pause); + + if (pause->rx_pause) { +- pdata->phy.advertising |= ADVERTISED_Pause; +- pdata->phy.advertising |= ADVERTISED_Asym_Pause; ++ XGBE_SET_ADV(lks, Pause); ++ XGBE_SET_ADV(lks, Asym_Pause); + } + +- if (pause->tx_pause) +- pdata->phy.advertising ^= ADVERTISED_Asym_Pause; ++ if (pause->tx_pause) { ++ /* Equivalent to XOR of Asym_Pause */ ++ if (XGBE_ADV(lks, Asym_Pause)) ++ XGBE_CLR_ADV(lks, Asym_Pause); ++ else ++ XGBE_SET_ADV(lks, Asym_Pause); ++ } + + if (netif_running(netdev)) + ret = pdata->phy_if.phy_config_aneg(pdata); +@@ -300,22 +306,20 @@ static int xgbe_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *cmd) + { + struct xgbe_prv_data *pdata = netdev_priv(netdev); ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + + cmd->base.phy_address = pdata->phy.address; + +- ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, +- pdata->phy.supported); +- ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, +- pdata->phy.advertising); +- ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, +- pdata->phy.lp_advertising); +- + cmd->base.autoneg = pdata->phy.autoneg; + cmd->base.speed = pdata->phy.speed; + cmd->base.duplex = pdata->phy.duplex; + + cmd->base.port = PORT_NONE; + ++ XGBE_LM_COPY(cmd, supported, lks, supported); ++ XGBE_LM_COPY(cmd, advertising, lks, advertising); ++ XGBE_LM_COPY(cmd, lp_advertising, lks, lp_advertising); ++ + return 0; + } + +@@ -323,7 +327,8 @@ static int xgbe_set_link_ksettings(struct net_device *netdev, + const struct ethtool_link_ksettings *cmd) + { + struct xgbe_prv_data *pdata = netdev_priv(netdev); +- u32 advertising; ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); + u32 speed; + int ret; + +@@ -355,15 +360,17 @@ static int xgbe_set_link_ksettings(struct net_device *netdev, + } + } + +- ethtool_convert_link_mode_to_legacy_u32(&advertising, +- cmd->link_modes.advertising); +- + netif_dbg(pdata, link, netdev, +- "requested advertisement %#x, phy supported %#x\n", +- advertising, pdata->phy.supported); ++ "requested advertisement 0x%*pb, phy supported 0x%*pb\n", ++ __ETHTOOL_LINK_MODE_MASK_NBITS, cmd->link_modes.advertising, ++ __ETHTOOL_LINK_MODE_MASK_NBITS, lks->link_modes.supported); ++ ++ bitmap_and(advertising, ++ cmd->link_modes.advertising, lks->link_modes.supported, ++ __ETHTOOL_LINK_MODE_MASK_NBITS); + +- advertising &= pdata->phy.supported; +- if ((cmd->base.autoneg == AUTONEG_ENABLE) && !advertising) { ++ if ((cmd->base.autoneg == AUTONEG_ENABLE) && ++ bitmap_empty(advertising, __ETHTOOL_LINK_MODE_MASK_NBITS)) { + netdev_err(netdev, + "unsupported requested advertisement\n"); + return -EINVAL; +@@ -373,12 +380,13 @@ static int xgbe_set_link_ksettings(struct net_device *netdev, + pdata->phy.autoneg = cmd->base.autoneg; + pdata->phy.speed = speed; + pdata->phy.duplex = cmd->base.duplex; +- pdata->phy.advertising = advertising; ++ bitmap_copy(lks->link_modes.advertising, advertising, ++ __ETHTOOL_LINK_MODE_MASK_NBITS); + + if (cmd->base.autoneg == AUTONEG_ENABLE) +- pdata->phy.advertising |= ADVERTISED_Autoneg; ++ XGBE_SET_ADV(lks, Autoneg); + else +- pdata->phy.advertising &= ~ADVERTISED_Autoneg; ++ XGBE_CLR_ADV(lks, Autoneg); + + if (netif_running(netdev)) + ret = pdata->phy_if.phy_config_aneg(pdata); +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +index cd8a62233956..b47ef6443ea3 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +@@ -586,12 +586,14 @@ static enum xgbe_an xgbe_an73_page_received(struct xgbe_prv_data *pdata) + + static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; ++ + /* Be sure we aren't looping trying to negotiate */ + if (xgbe_in_kr_mode(pdata)) { + pdata->kr_state = XGBE_RX_ERROR; + +- if (!(pdata->phy.advertising & ADVERTISED_1000baseKX_Full) && +- !(pdata->phy.advertising & ADVERTISED_2500baseX_Full)) ++ if (!XGBE_ADV(lks, 1000baseKX_Full) && ++ !XGBE_ADV(lks, 2500baseX_Full)) + return XGBE_AN_NO_LINK; + + if (pdata->kx_state != XGBE_RX_BPA) +@@ -599,7 +601,7 @@ static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata) + } else { + pdata->kx_state = XGBE_RX_ERROR; + +- if (!(pdata->phy.advertising & ADVERTISED_10000baseKR_Full)) ++ if (!XGBE_ADV(lks, 10000baseKR_Full)) + return XGBE_AN_NO_LINK; + + if (pdata->kr_state != XGBE_RX_BPA) +@@ -921,18 +923,19 @@ static void xgbe_an_state_machine(struct work_struct *work) + + static void xgbe_an37_init(struct xgbe_prv_data *pdata) + { +- unsigned int advertising, reg; ++ struct ethtool_link_ksettings lks; ++ unsigned int reg; + +- advertising = pdata->phy_if.phy_impl.an_advertising(pdata); ++ pdata->phy_if.phy_impl.an_advertising(pdata, &lks); + + /* Set up Advertisement register */ + reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE); +- if (advertising & ADVERTISED_Pause) ++ if (XGBE_ADV(&lks, Pause)) + reg |= 0x100; + else + reg &= ~0x100; + +- if (advertising & ADVERTISED_Asym_Pause) ++ if (XGBE_ADV(&lks, Asym_Pause)) + reg |= 0x80; + else + reg &= ~0x80; +@@ -969,13 +972,14 @@ static void xgbe_an37_init(struct xgbe_prv_data *pdata) + + static void xgbe_an73_init(struct xgbe_prv_data *pdata) + { +- unsigned int advertising, reg; ++ struct ethtool_link_ksettings lks; ++ unsigned int reg; + +- advertising = pdata->phy_if.phy_impl.an_advertising(pdata); ++ pdata->phy_if.phy_impl.an_advertising(pdata, &lks); + + /* Set up Advertisement register 3 first */ + reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); +- if (advertising & ADVERTISED_10000baseR_FEC) ++ if (XGBE_ADV(&lks, 10000baseR_FEC)) + reg |= 0xc000; + else + reg &= ~0xc000; +@@ -984,13 +988,13 @@ static void xgbe_an73_init(struct xgbe_prv_data *pdata) + + /* Set up Advertisement register 2 next */ + reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); +- if (advertising & ADVERTISED_10000baseKR_Full) ++ if (XGBE_ADV(&lks, 10000baseKR_Full)) + reg |= 0x80; + else + reg &= ~0x80; + +- if ((advertising & ADVERTISED_1000baseKX_Full) || +- (advertising & ADVERTISED_2500baseX_Full)) ++ if (XGBE_ADV(&lks, 1000baseKX_Full) || ++ XGBE_ADV(&lks, 2500baseX_Full)) + reg |= 0x20; + else + reg &= ~0x20; +@@ -999,12 +1003,12 @@ static void xgbe_an73_init(struct xgbe_prv_data *pdata) + + /* Set up Advertisement register 1 last */ + reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE); +- if (advertising & ADVERTISED_Pause) ++ if (XGBE_ADV(&lks, Pause)) + reg |= 0x400; + else + reg &= ~0x400; + +- if (advertising & ADVERTISED_Asym_Pause) ++ if (XGBE_ADV(&lks, Asym_Pause)) + reg |= 0x800; + else + reg &= ~0x800; +@@ -1260,9 +1264,10 @@ static enum xgbe_mode xgbe_phy_status_aneg(struct xgbe_prv_data *pdata) + + static void xgbe_phy_status_result(struct xgbe_prv_data *pdata) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + enum xgbe_mode mode; + +- pdata->phy.lp_advertising = 0; ++ XGBE_ZERO_LP_ADV(lks); + + if ((pdata->phy.autoneg != AUTONEG_ENABLE) || pdata->parallel_detect) + mode = xgbe_cur_mode(pdata); +@@ -1492,17 +1497,21 @@ static void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata) + + static int xgbe_phy_best_advertised_speed(struct xgbe_prv_data *pdata) + { +- if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full) ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; ++ ++ if (XGBE_ADV(lks, 10000baseKR_Full)) + return SPEED_10000; +- else if (pdata->phy.advertising & ADVERTISED_10000baseT_Full) ++ else if (XGBE_ADV(lks, 10000baseT_Full)) + return SPEED_10000; +- else if (pdata->phy.advertising & ADVERTISED_2500baseX_Full) ++ else if (XGBE_ADV(lks, 2500baseX_Full)) + return SPEED_2500; +- else if (pdata->phy.advertising & ADVERTISED_1000baseKX_Full) ++ else if (XGBE_ADV(lks, 2500baseT_Full)) ++ return SPEED_2500; ++ else if (XGBE_ADV(lks, 1000baseKX_Full)) + return SPEED_1000; +- else if (pdata->phy.advertising & ADVERTISED_1000baseT_Full) ++ else if (XGBE_ADV(lks, 1000baseT_Full)) + return SPEED_1000; +- else if (pdata->phy.advertising & ADVERTISED_100baseT_Full) ++ else if (XGBE_ADV(lks, 100baseT_Full)) + return SPEED_100; + + return SPEED_UNKNOWN; +@@ -1515,6 +1524,7 @@ static void xgbe_phy_exit(struct xgbe_prv_data *pdata) + + static int xgbe_phy_init(struct xgbe_prv_data *pdata) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + int ret; + + mutex_init(&pdata->an_mutex); +@@ -1532,11 +1542,13 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) + ret = pdata->phy_if.phy_impl.init(pdata); + if (ret) + return ret; +- pdata->phy.advertising = pdata->phy.supported; ++ ++ /* Copy supported link modes to advertising link modes */ ++ XGBE_LM_COPY(lks, advertising, lks, supported); + + pdata->phy.address = 0; + +- if (pdata->phy.advertising & ADVERTISED_Autoneg) { ++ if (XGBE_ADV(lks, Autoneg)) { + pdata->phy.autoneg = AUTONEG_ENABLE; + pdata->phy.speed = SPEED_UNKNOWN; + pdata->phy.duplex = DUPLEX_UNKNOWN; +@@ -1553,16 +1565,21 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) + pdata->phy.rx_pause = pdata->rx_pause; + + /* Fix up Flow Control advertising */ +- pdata->phy.advertising &= ~ADVERTISED_Pause; +- pdata->phy.advertising &= ~ADVERTISED_Asym_Pause; ++ XGBE_CLR_ADV(lks, Pause); ++ XGBE_CLR_ADV(lks, Asym_Pause); + + if (pdata->rx_pause) { +- pdata->phy.advertising |= ADVERTISED_Pause; +- pdata->phy.advertising |= ADVERTISED_Asym_Pause; ++ XGBE_SET_ADV(lks, Pause); ++ XGBE_SET_ADV(lks, Asym_Pause); + } + +- if (pdata->tx_pause) +- pdata->phy.advertising ^= ADVERTISED_Asym_Pause; ++ if (pdata->tx_pause) { ++ /* Equivalent to XOR of Asym_Pause */ ++ if (XGBE_ADV(lks, Asym_Pause)) ++ XGBE_CLR_ADV(lks, Asym_Pause); ++ else ++ XGBE_SET_ADV(lks, Asym_Pause); ++ } + + if (netif_msg_drv(pdata)) + xgbe_dump_phy_registers(pdata); +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c +index c75edcac5e0a..d16eae415f72 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c +@@ -231,20 +231,21 @@ static void xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata) + + static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + struct xgbe_phy_data *phy_data = pdata->phy_data; + enum xgbe_mode mode; + unsigned int ad_reg, lp_reg; + +- pdata->phy.lp_advertising |= ADVERTISED_Autoneg; +- pdata->phy.lp_advertising |= ADVERTISED_Backplane; ++ XGBE_SET_LP_ADV(lks, Autoneg); ++ XGBE_SET_LP_ADV(lks, Backplane); + + /* Compare Advertisement and Link Partner register 1 */ + ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE); + lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA); + if (lp_reg & 0x400) +- pdata->phy.lp_advertising |= ADVERTISED_Pause; ++ XGBE_SET_LP_ADV(lks, Pause); + if (lp_reg & 0x800) +- pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause; ++ XGBE_SET_LP_ADV(lks, Asym_Pause); + + if (pdata->phy.pause_autoneg) { + /* Set flow control based on auto-negotiation result */ +@@ -266,12 +267,12 @@ static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata) + ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); + lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1); + if (lp_reg & 0x80) +- pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full; ++ XGBE_SET_LP_ADV(lks, 10000baseKR_Full); + if (lp_reg & 0x20) { + if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000) +- pdata->phy.lp_advertising |= ADVERTISED_2500baseX_Full; ++ XGBE_SET_LP_ADV(lks, 2500baseX_Full); + else +- pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full; ++ XGBE_SET_LP_ADV(lks, 1000baseKX_Full); + } + + ad_reg &= lp_reg; +@@ -290,14 +291,17 @@ static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata) + ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); + lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2); + if (lp_reg & 0xc000) +- pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC; ++ XGBE_SET_LP_ADV(lks, 10000baseR_FEC); + + return mode; + } + +-static unsigned int xgbe_phy_an_advertising(struct xgbe_prv_data *pdata) ++static void xgbe_phy_an_advertising(struct xgbe_prv_data *pdata, ++ struct ethtool_link_ksettings *dlks) + { +- return pdata->phy.advertising; ++ struct ethtool_link_ksettings *slks = &pdata->phy.lks; ++ ++ XGBE_LM_COPY(dlks, advertising, slks, advertising); + } + + static int xgbe_phy_an_config(struct xgbe_prv_data *pdata) +@@ -565,11 +569,10 @@ static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode) + } + + static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata, +- enum xgbe_mode mode, u32 advert) ++ enum xgbe_mode mode, bool advert) + { + if (pdata->phy.autoneg == AUTONEG_ENABLE) { +- if (pdata->phy.advertising & advert) +- return true; ++ return advert; + } else { + enum xgbe_mode cur_mode; + +@@ -583,16 +586,18 @@ static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata, + + static bool xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; ++ + switch (mode) { + case XGBE_MODE_KX_1000: + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_1000baseKX_Full); ++ XGBE_ADV(lks, 1000baseKX_Full)); + case XGBE_MODE_KX_2500: + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_2500baseX_Full); ++ XGBE_ADV(lks, 2500baseX_Full)); + case XGBE_MODE_KR: + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_10000baseKR_Full); ++ XGBE_ADV(lks, 10000baseKR_Full)); + default: + return false; + } +@@ -672,6 +677,7 @@ static void xgbe_phy_exit(struct xgbe_prv_data *pdata) + + static int xgbe_phy_init(struct xgbe_prv_data *pdata) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + struct xgbe_phy_data *phy_data; + int ret; + +@@ -790,21 +796,23 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) + } + + /* Initialize supported features */ +- pdata->phy.supported = SUPPORTED_Autoneg; +- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; +- pdata->phy.supported |= SUPPORTED_Backplane; +- pdata->phy.supported |= SUPPORTED_10000baseKR_Full; ++ XGBE_ZERO_SUP(lks); ++ XGBE_SET_SUP(lks, Autoneg); ++ XGBE_SET_SUP(lks, Pause); ++ XGBE_SET_SUP(lks, Asym_Pause); ++ XGBE_SET_SUP(lks, Backplane); ++ XGBE_SET_SUP(lks, 10000baseKR_Full); + switch (phy_data->speed_set) { + case XGBE_SPEEDSET_1000_10000: +- pdata->phy.supported |= SUPPORTED_1000baseKX_Full; ++ XGBE_SET_SUP(lks, 1000baseKX_Full); + break; + case XGBE_SPEEDSET_2500_10000: +- pdata->phy.supported |= SUPPORTED_2500baseX_Full; ++ XGBE_SET_SUP(lks, 2500baseX_Full); + break; + } + + if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) +- pdata->phy.supported |= SUPPORTED_10000baseR_FEC; ++ XGBE_SET_SUP(lks, 10000baseR_FEC); + + pdata->phy_data = phy_data; + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index 0bc599180665..f8a11c6c8dcb 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -709,18 +709,13 @@ static int xgbe_phy_mii_read(struct mii_bus *mii, int addr, int reg) + + static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + struct xgbe_phy_data *phy_data = pdata->phy_data; + + if (!phy_data->sfp_mod_absent && !phy_data->sfp_changed) + return; + +- pdata->phy.supported &= ~SUPPORTED_Autoneg; +- pdata->phy.supported &= ~(SUPPORTED_Pause | SUPPORTED_Asym_Pause); +- pdata->phy.supported &= ~SUPPORTED_TP; +- pdata->phy.supported &= ~SUPPORTED_FIBRE; +- pdata->phy.supported &= ~SUPPORTED_100baseT_Full; +- pdata->phy.supported &= ~SUPPORTED_1000baseT_Full; +- pdata->phy.supported &= ~SUPPORTED_10000baseT_Full; ++ XGBE_ZERO_SUP(lks); + + if (phy_data->sfp_mod_absent) { + pdata->phy.speed = SPEED_UNKNOWN; +@@ -728,18 +723,13 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) + pdata->phy.autoneg = AUTONEG_ENABLE; + pdata->phy.pause_autoneg = AUTONEG_ENABLE; + +- pdata->phy.supported |= SUPPORTED_Autoneg; +- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; +- pdata->phy.supported |= SUPPORTED_TP; +- pdata->phy.supported |= SUPPORTED_FIBRE; +- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) +- pdata->phy.supported |= SUPPORTED_100baseT_Full; +- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) +- pdata->phy.supported |= SUPPORTED_1000baseT_Full; +- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) +- pdata->phy.supported |= SUPPORTED_10000baseT_Full; ++ XGBE_SET_SUP(lks, Autoneg); ++ XGBE_SET_SUP(lks, Pause); ++ XGBE_SET_SUP(lks, Asym_Pause); ++ XGBE_SET_SUP(lks, TP); ++ XGBE_SET_SUP(lks, FIBRE); + +- pdata->phy.advertising = pdata->phy.supported; ++ XGBE_LM_COPY(lks, advertising, lks, supported); + + return; + } +@@ -753,8 +743,18 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) + pdata->phy.duplex = DUPLEX_UNKNOWN; + pdata->phy.autoneg = AUTONEG_ENABLE; + pdata->phy.pause_autoneg = AUTONEG_ENABLE; +- pdata->phy.supported |= SUPPORTED_Autoneg; +- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; ++ XGBE_SET_SUP(lks, Autoneg); ++ XGBE_SET_SUP(lks, Pause); ++ XGBE_SET_SUP(lks, Asym_Pause); ++ if (phy_data->sfp_base == XGBE_SFP_BASE_1000_T) { ++ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ++ XGBE_SET_SUP(lks, 100baseT_Full); ++ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) ++ XGBE_SET_SUP(lks, 1000baseT_Full); ++ } else { ++ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) ++ XGBE_SET_SUP(lks, 1000baseX_Full); ++ } + break; + case XGBE_SFP_BASE_10000_SR: + case XGBE_SFP_BASE_10000_LR: +@@ -765,6 +765,27 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) + pdata->phy.duplex = DUPLEX_FULL; + pdata->phy.autoneg = AUTONEG_DISABLE; + pdata->phy.pause_autoneg = AUTONEG_DISABLE; ++ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) { ++ switch (phy_data->sfp_base) { ++ case XGBE_SFP_BASE_10000_SR: ++ XGBE_SET_SUP(lks, 10000baseSR_Full); ++ break; ++ case XGBE_SFP_BASE_10000_LR: ++ XGBE_SET_SUP(lks, 10000baseLR_Full); ++ break; ++ case XGBE_SFP_BASE_10000_LRM: ++ XGBE_SET_SUP(lks, 10000baseLRM_Full); ++ break; ++ case XGBE_SFP_BASE_10000_ER: ++ XGBE_SET_SUP(lks, 10000baseER_Full); ++ break; ++ case XGBE_SFP_BASE_10000_CR: ++ XGBE_SET_SUP(lks, 10000baseCR_Full); ++ break; ++ default: ++ break; ++ } ++ } + break; + default: + pdata->phy.speed = SPEED_UNKNOWN; +@@ -778,38 +799,14 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) + case XGBE_SFP_BASE_1000_T: + case XGBE_SFP_BASE_1000_CX: + case XGBE_SFP_BASE_10000_CR: +- pdata->phy.supported |= SUPPORTED_TP; ++ XGBE_SET_SUP(lks, TP); + break; + default: +- pdata->phy.supported |= SUPPORTED_FIBRE; +- } +- +- switch (phy_data->sfp_speed) { +- case XGBE_SFP_SPEED_100_1000: +- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) +- pdata->phy.supported |= SUPPORTED_100baseT_Full; +- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) +- pdata->phy.supported |= SUPPORTED_1000baseT_Full; +- break; +- case XGBE_SFP_SPEED_1000: +- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) +- pdata->phy.supported |= SUPPORTED_1000baseT_Full; ++ XGBE_SET_SUP(lks, FIBRE); + break; +- case XGBE_SFP_SPEED_10000: +- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) +- pdata->phy.supported |= SUPPORTED_10000baseT_Full; +- break; +- default: +- /* Choose the fastest supported speed */ +- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) +- pdata->phy.supported |= SUPPORTED_10000baseT_Full; +- else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) +- pdata->phy.supported |= SUPPORTED_1000baseT_Full; +- else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) +- pdata->phy.supported |= SUPPORTED_100baseT_Full; + } + +- pdata->phy.advertising = pdata->phy.supported; ++ XGBE_LM_COPY(lks, advertising, lks, supported); + } + + static bool xgbe_phy_sfp_bit_rate(struct xgbe_sfp_eeprom *sfp_eeprom, +@@ -886,8 +883,10 @@ static void xgbe_phy_external_phy_quirks(struct xgbe_prv_data *pdata) + + static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + struct xgbe_phy_data *phy_data = pdata->phy_data; + struct phy_device *phydev; ++ u32 advertising; + int ret; + + /* If we already have a PHY, just return */ +@@ -943,7 +942,10 @@ static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata) + phy_data->phydev = phydev; + + xgbe_phy_external_phy_quirks(pdata); +- phydev->advertising &= pdata->phy.advertising; ++ ++ ethtool_convert_link_mode_to_legacy_u32(&advertising, ++ lks->link_modes.advertising); ++ phydev->advertising &= advertising; + + phy_start_aneg(phy_data->phydev); + +@@ -1301,6 +1303,7 @@ static void xgbe_phy_sfp_detect(struct xgbe_prv_data *pdata) + + static void xgbe_phy_phydev_flowctrl(struct xgbe_prv_data *pdata) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + struct xgbe_phy_data *phy_data = pdata->phy_data; + u16 lcl_adv = 0, rmt_adv = 0; + u8 fc; +@@ -1317,11 +1320,11 @@ static void xgbe_phy_phydev_flowctrl(struct xgbe_prv_data *pdata) + lcl_adv |= ADVERTISE_PAUSE_ASYM; + + if (phy_data->phydev->pause) { +- pdata->phy.lp_advertising |= ADVERTISED_Pause; ++ XGBE_SET_LP_ADV(lks, Pause); + rmt_adv |= LPA_PAUSE_CAP; + } + if (phy_data->phydev->asym_pause) { +- pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause; ++ XGBE_SET_LP_ADV(lks, Asym_Pause); + rmt_adv |= LPA_PAUSE_ASYM; + } + +@@ -1334,10 +1337,11 @@ static void xgbe_phy_phydev_flowctrl(struct xgbe_prv_data *pdata) + + static enum xgbe_mode xgbe_phy_an37_sgmii_outcome(struct xgbe_prv_data *pdata) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + enum xgbe_mode mode; + +- pdata->phy.lp_advertising |= ADVERTISED_Autoneg; +- pdata->phy.lp_advertising |= ADVERTISED_TP; ++ XGBE_SET_LP_ADV(lks, Autoneg); ++ XGBE_SET_LP_ADV(lks, TP); + + /* Use external PHY to determine flow control */ + if (pdata->phy.pause_autoneg) +@@ -1346,21 +1350,21 @@ static enum xgbe_mode xgbe_phy_an37_sgmii_outcome(struct xgbe_prv_data *pdata) + switch (pdata->an_status & XGBE_SGMII_AN_LINK_SPEED) { + case XGBE_SGMII_AN_LINK_SPEED_100: + if (pdata->an_status & XGBE_SGMII_AN_LINK_DUPLEX) { +- pdata->phy.lp_advertising |= ADVERTISED_100baseT_Full; ++ XGBE_SET_LP_ADV(lks, 100baseT_Full); + mode = XGBE_MODE_SGMII_100; + } else { + /* Half-duplex not supported */ +- pdata->phy.lp_advertising |= ADVERTISED_100baseT_Half; ++ XGBE_SET_LP_ADV(lks, 100baseT_Half); + mode = XGBE_MODE_UNKNOWN; + } + break; + case XGBE_SGMII_AN_LINK_SPEED_1000: + if (pdata->an_status & XGBE_SGMII_AN_LINK_DUPLEX) { +- pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full; ++ XGBE_SET_LP_ADV(lks, 1000baseT_Full); + mode = XGBE_MODE_SGMII_1000; + } else { + /* Half-duplex not supported */ +- pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Half; ++ XGBE_SET_LP_ADV(lks, 1000baseT_Half); + mode = XGBE_MODE_UNKNOWN; + } + break; +@@ -1373,19 +1377,20 @@ static enum xgbe_mode xgbe_phy_an37_sgmii_outcome(struct xgbe_prv_data *pdata) + + static enum xgbe_mode xgbe_phy_an37_outcome(struct xgbe_prv_data *pdata) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + enum xgbe_mode mode; + unsigned int ad_reg, lp_reg; + +- pdata->phy.lp_advertising |= ADVERTISED_Autoneg; +- pdata->phy.lp_advertising |= ADVERTISED_FIBRE; ++ XGBE_SET_LP_ADV(lks, Autoneg); ++ XGBE_SET_LP_ADV(lks, FIBRE); + + /* Compare Advertisement and Link Partner register */ + ad_reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE); + lp_reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_LP_ABILITY); + if (lp_reg & 0x100) +- pdata->phy.lp_advertising |= ADVERTISED_Pause; ++ XGBE_SET_LP_ADV(lks, Pause); + if (lp_reg & 0x80) +- pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause; ++ XGBE_SET_LP_ADV(lks, Asym_Pause); + + if (pdata->phy.pause_autoneg) { + /* Set flow control based on auto-negotiation result */ +@@ -1403,10 +1408,8 @@ static enum xgbe_mode xgbe_phy_an37_outcome(struct xgbe_prv_data *pdata) + } + } + +- if (lp_reg & 0x40) +- pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Half; + if (lp_reg & 0x20) +- pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full; ++ XGBE_SET_LP_ADV(lks, 1000baseX_Full); + + /* Half duplex is not supported */ + ad_reg &= lp_reg; +@@ -1417,12 +1420,13 @@ static enum xgbe_mode xgbe_phy_an37_outcome(struct xgbe_prv_data *pdata) + + static enum xgbe_mode xgbe_phy_an73_redrv_outcome(struct xgbe_prv_data *pdata) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + struct xgbe_phy_data *phy_data = pdata->phy_data; + enum xgbe_mode mode; + unsigned int ad_reg, lp_reg; + +- pdata->phy.lp_advertising |= ADVERTISED_Autoneg; +- pdata->phy.lp_advertising |= ADVERTISED_Backplane; ++ XGBE_SET_LP_ADV(lks, Autoneg); ++ XGBE_SET_LP_ADV(lks, Backplane); + + /* Use external PHY to determine flow control */ + if (pdata->phy.pause_autoneg) +@@ -1432,9 +1436,9 @@ static enum xgbe_mode xgbe_phy_an73_redrv_outcome(struct xgbe_prv_data *pdata) + ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); + lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1); + if (lp_reg & 0x80) +- pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full; ++ XGBE_SET_LP_ADV(lks, 10000baseKR_Full); + if (lp_reg & 0x20) +- pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full; ++ XGBE_SET_LP_ADV(lks, 1000baseKX_Full); + + ad_reg &= lp_reg; + if (ad_reg & 0x80) { +@@ -1487,26 +1491,27 @@ static enum xgbe_mode xgbe_phy_an73_redrv_outcome(struct xgbe_prv_data *pdata) + ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); + lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2); + if (lp_reg & 0xc000) +- pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC; ++ XGBE_SET_LP_ADV(lks, 10000baseR_FEC); + + return mode; + } + + static enum xgbe_mode xgbe_phy_an73_outcome(struct xgbe_prv_data *pdata) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + enum xgbe_mode mode; + unsigned int ad_reg, lp_reg; + +- pdata->phy.lp_advertising |= ADVERTISED_Autoneg; +- pdata->phy.lp_advertising |= ADVERTISED_Backplane; ++ XGBE_SET_LP_ADV(lks, Autoneg); ++ XGBE_SET_LP_ADV(lks, Backplane); + + /* Compare Advertisement and Link Partner register 1 */ + ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE); + lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA); + if (lp_reg & 0x400) +- pdata->phy.lp_advertising |= ADVERTISED_Pause; ++ XGBE_SET_LP_ADV(lks, Pause); + if (lp_reg & 0x800) +- pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause; ++ XGBE_SET_LP_ADV(lks, Asym_Pause); + + if (pdata->phy.pause_autoneg) { + /* Set flow control based on auto-negotiation result */ +@@ -1528,9 +1533,9 @@ static enum xgbe_mode xgbe_phy_an73_outcome(struct xgbe_prv_data *pdata) + ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); + lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1); + if (lp_reg & 0x80) +- pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full; ++ XGBE_SET_LP_ADV(lks, 10000baseKR_Full); + if (lp_reg & 0x20) +- pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full; ++ XGBE_SET_LP_ADV(lks, 1000baseKX_Full); + + ad_reg &= lp_reg; + if (ad_reg & 0x80) +@@ -1544,7 +1549,7 @@ static enum xgbe_mode xgbe_phy_an73_outcome(struct xgbe_prv_data *pdata) + ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); + lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2); + if (lp_reg & 0xc000) +- pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC; ++ XGBE_SET_LP_ADV(lks, 10000baseR_FEC); + + return mode; + } +@@ -1565,41 +1570,43 @@ static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata) + } + } + +-static unsigned int xgbe_phy_an_advertising(struct xgbe_prv_data *pdata) ++static void xgbe_phy_an_advertising(struct xgbe_prv_data *pdata, ++ struct ethtool_link_ksettings *dlks) + { ++ struct ethtool_link_ksettings *slks = &pdata->phy.lks; + struct xgbe_phy_data *phy_data = pdata->phy_data; +- unsigned int advertising; ++ ++ XGBE_LM_COPY(dlks, advertising, slks, advertising); + + /* Without a re-driver, just return current advertising */ + if (!phy_data->redrv) +- return pdata->phy.advertising; ++ return; + + /* With the KR re-driver we need to advertise a single speed */ +- advertising = pdata->phy.advertising; +- advertising &= ~ADVERTISED_1000baseKX_Full; +- advertising &= ~ADVERTISED_10000baseKR_Full; ++ XGBE_CLR_ADV(dlks, 1000baseKX_Full); ++ XGBE_CLR_ADV(dlks, 10000baseKR_Full); + + switch (phy_data->port_mode) { + case XGBE_PORT_MODE_BACKPLANE: +- advertising |= ADVERTISED_10000baseKR_Full; ++ XGBE_SET_ADV(dlks, 10000baseKR_Full); + break; + case XGBE_PORT_MODE_BACKPLANE_2500: +- advertising |= ADVERTISED_1000baseKX_Full; ++ XGBE_SET_ADV(dlks, 1000baseKX_Full); + break; + case XGBE_PORT_MODE_1000BASE_T: + case XGBE_PORT_MODE_1000BASE_X: + case XGBE_PORT_MODE_NBASE_T: +- advertising |= ADVERTISED_1000baseKX_Full; ++ XGBE_SET_ADV(dlks, 1000baseKX_Full); + break; + case XGBE_PORT_MODE_10GBASE_T: + if (phy_data->phydev && + (phy_data->phydev->speed == SPEED_10000)) +- advertising |= ADVERTISED_10000baseKR_Full; ++ XGBE_SET_ADV(dlks, 10000baseKR_Full); + else +- advertising |= ADVERTISED_1000baseKX_Full; ++ XGBE_SET_ADV(dlks, 1000baseKX_Full); + break; + case XGBE_PORT_MODE_10GBASE_R: +- advertising |= ADVERTISED_10000baseKR_Full; ++ XGBE_SET_ADV(dlks, 10000baseKR_Full); + break; + case XGBE_PORT_MODE_SFP: + switch (phy_data->sfp_base) { +@@ -1607,24 +1614,24 @@ static unsigned int xgbe_phy_an_advertising(struct xgbe_prv_data *pdata) + case XGBE_SFP_BASE_1000_SX: + case XGBE_SFP_BASE_1000_LX: + case XGBE_SFP_BASE_1000_CX: +- advertising |= ADVERTISED_1000baseKX_Full; ++ XGBE_SET_ADV(dlks, 1000baseKX_Full); + break; + default: +- advertising |= ADVERTISED_10000baseKR_Full; ++ XGBE_SET_ADV(dlks, 10000baseKR_Full); + break; + } + break; + default: +- advertising |= ADVERTISED_10000baseKR_Full; ++ XGBE_SET_ADV(dlks, 10000baseKR_Full); + break; + } +- +- return advertising; + } + + static int xgbe_phy_an_config(struct xgbe_prv_data *pdata) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + struct xgbe_phy_data *phy_data = pdata->phy_data; ++ u32 advertising; + int ret; + + ret = xgbe_phy_find_phy_device(pdata); +@@ -1634,9 +1641,12 @@ static int xgbe_phy_an_config(struct xgbe_prv_data *pdata) + if (!phy_data->phydev) + return 0; + ++ ethtool_convert_link_mode_to_legacy_u32(&advertising, ++ lks->link_modes.advertising); ++ + phy_data->phydev->autoneg = pdata->phy.autoneg; + phy_data->phydev->advertising = phy_data->phydev->supported & +- pdata->phy.advertising; ++ advertising; + + if (pdata->phy.autoneg != AUTONEG_ENABLE) { + phy_data->phydev->speed = pdata->phy.speed; +@@ -2194,11 +2204,10 @@ static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode) + } + + static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata, +- enum xgbe_mode mode, u32 advert) ++ enum xgbe_mode mode, bool advert) + { + if (pdata->phy.autoneg == AUTONEG_ENABLE) { +- if (pdata->phy.advertising & advert) +- return true; ++ return advert; + } else { + enum xgbe_mode cur_mode; + +@@ -2213,13 +2222,15 @@ static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata, + static bool xgbe_phy_use_basex_mode(struct xgbe_prv_data *pdata, + enum xgbe_mode mode) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; ++ + switch (mode) { + case XGBE_MODE_X: + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_1000baseT_Full); ++ XGBE_ADV(lks, 1000baseX_Full)); + case XGBE_MODE_KR: + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_10000baseT_Full); ++ XGBE_ADV(lks, 10000baseKR_Full)); + default: + return false; + } +@@ -2228,19 +2239,21 @@ static bool xgbe_phy_use_basex_mode(struct xgbe_prv_data *pdata, + static bool xgbe_phy_use_baset_mode(struct xgbe_prv_data *pdata, + enum xgbe_mode mode) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; ++ + switch (mode) { + case XGBE_MODE_SGMII_100: + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_100baseT_Full); ++ XGBE_ADV(lks, 100baseT_Full)); + case XGBE_MODE_SGMII_1000: + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_1000baseT_Full); ++ XGBE_ADV(lks, 1000baseT_Full)); + case XGBE_MODE_KX_2500: + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_2500baseX_Full); ++ XGBE_ADV(lks, 2500baseT_Full)); + case XGBE_MODE_KR: + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_10000baseT_Full); ++ XGBE_ADV(lks, 10000baseT_Full)); + default: + return false; + } +@@ -2249,6 +2262,7 @@ static bool xgbe_phy_use_baset_mode(struct xgbe_prv_data *pdata, + static bool xgbe_phy_use_sfp_mode(struct xgbe_prv_data *pdata, + enum xgbe_mode mode) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + struct xgbe_phy_data *phy_data = pdata->phy_data; + + switch (mode) { +@@ -2256,22 +2270,26 @@ static bool xgbe_phy_use_sfp_mode(struct xgbe_prv_data *pdata, + if (phy_data->sfp_base == XGBE_SFP_BASE_1000_T) + return false; + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_1000baseT_Full); ++ XGBE_ADV(lks, 1000baseX_Full)); + case XGBE_MODE_SGMII_100: + if (phy_data->sfp_base != XGBE_SFP_BASE_1000_T) + return false; + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_100baseT_Full); ++ XGBE_ADV(lks, 100baseT_Full)); + case XGBE_MODE_SGMII_1000: + if (phy_data->sfp_base != XGBE_SFP_BASE_1000_T) + return false; + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_1000baseT_Full); ++ XGBE_ADV(lks, 1000baseT_Full)); + case XGBE_MODE_SFI: + if (phy_data->sfp_mod_absent) + return true; + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_10000baseT_Full); ++ XGBE_ADV(lks, 10000baseSR_Full) || ++ XGBE_ADV(lks, 10000baseLR_Full) || ++ XGBE_ADV(lks, 10000baseLRM_Full) || ++ XGBE_ADV(lks, 10000baseER_Full) || ++ XGBE_ADV(lks, 10000baseCR_Full)); + default: + return false; + } +@@ -2280,10 +2298,12 @@ static bool xgbe_phy_use_sfp_mode(struct xgbe_prv_data *pdata, + static bool xgbe_phy_use_bp_2500_mode(struct xgbe_prv_data *pdata, + enum xgbe_mode mode) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; ++ + switch (mode) { + case XGBE_MODE_KX_2500: + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_2500baseX_Full); ++ XGBE_ADV(lks, 2500baseX_Full)); + default: + return false; + } +@@ -2292,13 +2312,15 @@ static bool xgbe_phy_use_bp_2500_mode(struct xgbe_prv_data *pdata, + static bool xgbe_phy_use_bp_mode(struct xgbe_prv_data *pdata, + enum xgbe_mode mode) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; ++ + switch (mode) { + case XGBE_MODE_KX_1000: + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_1000baseKX_Full); ++ XGBE_ADV(lks, 1000baseKX_Full)); + case XGBE_MODE_KR: + return xgbe_phy_check_mode(pdata, mode, +- ADVERTISED_10000baseKR_Full); ++ XGBE_ADV(lks, 10000baseKR_Full)); + default: + return false; + } +@@ -2841,6 +2841,7 @@ static void xgbe_phy_exit(struct xgbe_pr + + static int xgbe_phy_init(struct xgbe_prv_data *pdata) + { ++ struct ethtool_link_ksettings *lks = &pdata->phy.lks; + struct xgbe_phy_data *phy_data; + struct mii_bus *mii; + unsigned int reg; +@@ -3037,32 +3060,33 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) + phy_data->cur_mode = XGBE_MODE_UNKNOWN; + + /* Initialize supported features */ +- pdata->phy.supported = 0; ++ XGBE_ZERO_SUP(lks); + + switch (phy_data->port_mode) { + /* Backplane support */ + case XGBE_PORT_MODE_BACKPLANE: +- pdata->phy.supported |= SUPPORTED_Autoneg; +- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; +- pdata->phy.supported |= SUPPORTED_Backplane; ++ XGBE_SET_SUP(lks, Autoneg); ++ XGBE_SET_SUP(lks, Pause); ++ XGBE_SET_SUP(lks, Asym_Pause); ++ XGBE_SET_SUP(lks, Backplane); + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) { +- pdata->phy.supported |= SUPPORTED_1000baseKX_Full; ++ XGBE_SET_SUP(lks, 1000baseKX_Full); + phy_data->start_mode = XGBE_MODE_KX_1000; + } + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) { +- pdata->phy.supported |= SUPPORTED_10000baseKR_Full; ++ XGBE_SET_SUP(lks, 10000baseKR_Full); + if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) +- pdata->phy.supported |= +- SUPPORTED_10000baseR_FEC; ++ XGBE_SET_SUP(lks, 10000baseR_FEC); + phy_data->start_mode = XGBE_MODE_KR; + } + + phy_data->phydev_mode = XGBE_MDIO_MODE_NONE; + break; + case XGBE_PORT_MODE_BACKPLANE_2500: +- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; +- pdata->phy.supported |= SUPPORTED_Backplane; +- pdata->phy.supported |= SUPPORTED_2500baseX_Full; ++ XGBE_SET_SUP(lks, Pause); ++ XGBE_SET_SUP(lks, Asym_Pause); ++ XGBE_SET_SUP(lks, Backplane); ++ XGBE_SET_SUP(lks, 2500baseX_Full); + phy_data->start_mode = XGBE_MODE_KX_2500; + + phy_data->phydev_mode = XGBE_MDIO_MODE_NONE; +@@ -3070,15 +3094,16 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) + + /* MDIO 1GBase-T support */ + case XGBE_PORT_MODE_1000BASE_T: +- pdata->phy.supported |= SUPPORTED_Autoneg; +- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; +- pdata->phy.supported |= SUPPORTED_TP; ++ XGBE_SET_SUP(lks, Autoneg); ++ XGBE_SET_SUP(lks, Pause); ++ XGBE_SET_SUP(lks, Asym_Pause); ++ XGBE_SET_SUP(lks, TP); + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) { +- pdata->phy.supported |= SUPPORTED_100baseT_Full; ++ XGBE_SET_SUP(lks, 100baseT_Full); + phy_data->start_mode = XGBE_MODE_SGMII_100; + } + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) { +- pdata->phy.supported |= SUPPORTED_1000baseT_Full; ++ XGBE_SET_SUP(lks, 1000baseT_Full); + phy_data->start_mode = XGBE_MODE_SGMII_1000; + } + +@@ -3087,10 +3112,11 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) + + /* MDIO Base-X support */ + case XGBE_PORT_MODE_1000BASE_X: +- pdata->phy.supported |= SUPPORTED_Autoneg; +- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; +- pdata->phy.supported |= SUPPORTED_FIBRE; +- pdata->phy.supported |= SUPPORTED_1000baseT_Full; ++ XGBE_SET_SUP(lks, Autoneg); ++ XGBE_SET_SUP(lks, Pause); ++ XGBE_SET_SUP(lks, Asym_Pause); ++ XGBE_SET_SUP(lks, FIBRE); ++ XGBE_SET_SUP(lks, 1000baseX_Full); + phy_data->start_mode = XGBE_MODE_X; + + phy_data->phydev_mode = XGBE_MDIO_MODE_CL22; +@@ -3098,19 +3124,20 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) + + /* MDIO NBase-T support */ + case XGBE_PORT_MODE_NBASE_T: +- pdata->phy.supported |= SUPPORTED_Autoneg; +- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; +- pdata->phy.supported |= SUPPORTED_TP; ++ XGBE_SET_SUP(lks, Autoneg); ++ XGBE_SET_SUP(lks, Pause); ++ XGBE_SET_SUP(lks, Asym_Pause); ++ XGBE_SET_SUP(lks, TP); + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) { +- pdata->phy.supported |= SUPPORTED_100baseT_Full; ++ XGBE_SET_SUP(lks, 100baseT_Full); + phy_data->start_mode = XGBE_MODE_SGMII_100; + } + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) { +- pdata->phy.supported |= SUPPORTED_1000baseT_Full; ++ XGBE_SET_SUP(lks, 1000baseT_Full); + phy_data->start_mode = XGBE_MODE_SGMII_1000; + } + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_2500) { +- pdata->phy.supported |= SUPPORTED_2500baseX_Full; ++ XGBE_SET_SUP(lks, 2500baseT_Full); + phy_data->start_mode = XGBE_MODE_KX_2500; + } + +@@ -3119,19 +3146,20 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) + + /* 10GBase-T support */ + case XGBE_PORT_MODE_10GBASE_T: +- pdata->phy.supported |= SUPPORTED_Autoneg; +- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; +- pdata->phy.supported |= SUPPORTED_TP; ++ XGBE_SET_SUP(lks, Autoneg); ++ XGBE_SET_SUP(lks, Pause); ++ XGBE_SET_SUP(lks, Asym_Pause); ++ XGBE_SET_SUP(lks, TP); + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) { +- pdata->phy.supported |= SUPPORTED_100baseT_Full; ++ XGBE_SET_SUP(lks, 100baseT_Full); + phy_data->start_mode = XGBE_MODE_SGMII_100; + } + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) { +- pdata->phy.supported |= SUPPORTED_1000baseT_Full; ++ XGBE_SET_SUP(lks, 1000baseT_Full); + phy_data->start_mode = XGBE_MODE_SGMII_1000; + } + if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) { +- pdata->phy.supported |= SUPPORTED_10000baseT_Full; ++ XGBE_SET_SUP(lks, 10000baseT_Full); + phy_data->start_mode = XGBE_MODE_KR; + } + +@@ -3140,12 +3168,16 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) + + /* 10GBase-R support */ + case XGBE_PORT_MODE_10GBASE_R: +- pdata->phy.supported |= SUPPORTED_Autoneg; +- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; +- pdata->phy.supported |= SUPPORTED_TP; +- pdata->phy.supported |= SUPPORTED_10000baseT_Full; ++ XGBE_SET_SUP(lks, Autoneg); ++ XGBE_SET_SUP(lks, Pause); ++ XGBE_SET_SUP(lks, Asym_Pause); ++ XGBE_SET_SUP(lks, FIBRE); ++ XGBE_SET_SUP(lks, 10000baseSR_Full); ++ XGBE_SET_SUP(lks, 10000baseLR_Full); ++ XGBE_SET_SUP(lks, 10000baseLRM_Full); ++ XGBE_SET_SUP(lks, 10000baseER_Full); + if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) +- pdata->phy.supported |= SUPPORTED_10000baseR_FEC; ++ XGBE_SET_SUP(lks, 10000baseR_FEC); + phy_data->start_mode = XGBE_MODE_SFI; + + phy_data->phydev_mode = XGBE_MDIO_MODE_NONE; +@@ -3153,22 +3185,17 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) + + /* SFP support */ + case XGBE_PORT_MODE_SFP: +- pdata->phy.supported |= SUPPORTED_Autoneg; +- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; +- pdata->phy.supported |= SUPPORTED_TP; +- pdata->phy.supported |= SUPPORTED_FIBRE; +- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) { +- pdata->phy.supported |= SUPPORTED_100baseT_Full; ++ XGBE_SET_SUP(lks, Autoneg); ++ XGBE_SET_SUP(lks, Pause); ++ XGBE_SET_SUP(lks, Asym_Pause); ++ XGBE_SET_SUP(lks, TP); ++ XGBE_SET_SUP(lks, FIBRE); ++ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) + phy_data->start_mode = XGBE_MODE_SGMII_100; +- } +- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) { +- pdata->phy.supported |= SUPPORTED_1000baseT_Full; ++ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) + phy_data->start_mode = XGBE_MODE_SGMII_1000; +- } +- if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) { +- pdata->phy.supported |= SUPPORTED_10000baseT_Full; ++ if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) + phy_data->start_mode = XGBE_MODE_SFI; +- } + + phy_data->phydev_mode = XGBE_MDIO_MODE_CL22; + +@@ -3179,8 +3206,9 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) + } + + if (netif_msg_probe(pdata)) +- dev_dbg(pdata->dev, "phy supported=%#x\n", +- pdata->phy.supported); ++ dev_dbg(pdata->dev, "phy supported=0x%*pb\n", ++ __ETHTOOL_LINK_MODE_MASK_NBITS, ++ lks->link_modes.supported); + + if ((phy_data->conn_type & XGBE_CONN_TYPE_MDIO) && + (phy_data->phydev_mode != XGBE_MDIO_MODE_NONE)) { +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index 89f3f30784fb..1040860c747c 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -131,6 +131,7 @@ + #include + #include + #include ++#include + + #define XGBE_DRV_NAME "amd-xgbe" + #define XGBE_DRV_VERSION "1.0.3" +@@ -296,6 +297,48 @@ + /* MDIO port types */ + #define XGMAC_MAX_C22_PORT 3 + ++/* Link mode bit operations */ ++#define XGBE_ZERO_SUP(_ls) \ ++ ethtool_link_ksettings_zero_link_mode((_ls), supported) ++ ++#define XGBE_SET_SUP(_ls, _mode) \ ++ ethtool_link_ksettings_add_link_mode((_ls), supported, _mode) ++ ++#define XGBE_CLR_SUP(_ls, _mode) \ ++ ethtool_link_ksettings_del_link_mode((_ls), supported, _mode) ++ ++#define XGBE_IS_SUP(_ls, _mode) \ ++ ethtool_link_ksettings_test_link_mode((_ls), supported, _mode) ++ ++#define XGBE_ZERO_ADV(_ls) \ ++ ethtool_link_ksettings_zero_link_mode((_ls), advertising) ++ ++#define XGBE_SET_ADV(_ls, _mode) \ ++ ethtool_link_ksettings_add_link_mode((_ls), advertising, _mode) ++ ++#define XGBE_CLR_ADV(_ls, _mode) \ ++ ethtool_link_ksettings_del_link_mode((_ls), advertising, _mode) ++ ++#define XGBE_ADV(_ls, _mode) \ ++ ethtool_link_ksettings_test_link_mode((_ls), advertising, _mode) ++ ++#define XGBE_ZERO_LP_ADV(_ls) \ ++ ethtool_link_ksettings_zero_link_mode((_ls), lp_advertising) ++ ++#define XGBE_SET_LP_ADV(_ls, _mode) \ ++ ethtool_link_ksettings_add_link_mode((_ls), lp_advertising, _mode) ++ ++#define XGBE_CLR_LP_ADV(_ls, _mode) \ ++ ethtool_link_ksettings_del_link_mode((_ls), lp_advertising, _mode) ++ ++#define XGBE_LP_ADV(_ls, _mode) \ ++ ethtool_link_ksettings_test_link_mode((_ls), lp_advertising, _mode) ++ ++#define XGBE_LM_COPY(_dst, _dname, _src, _sname) \ ++ bitmap_copy((_dst)->link_modes._dname, \ ++ (_src)->link_modes._sname, \ ++ __ETHTOOL_LINK_MODE_MASK_NBITS) ++ + struct xgbe_prv_data; + + struct xgbe_packet_data { +@@ -563,9 +606,7 @@ enum xgbe_mdio_mode { + }; + + struct xgbe_phy { +- u32 supported; +- u32 advertising; +- u32 lp_advertising; ++ struct ethtool_link_ksettings lks; + + int address; + +@@ -818,7 +859,8 @@ struct xgbe_phy_impl_if { + int (*an_config)(struct xgbe_prv_data *); + + /* Set/override auto-negotiation advertisement settings */ +- unsigned int (*an_advertising)(struct xgbe_prv_data *); ++ void (*an_advertising)(struct xgbe_prv_data *, ++ struct ethtool_link_ksettings *); + + /* Process results of auto-negotiation */ + enum xgbe_mode (*an_outcome)(struct xgbe_prv_data *); +-- +2.16.4 + diff --git a/patches.suse/0037-amd-xgbe-Add-support-for-VXLAN-offload-capabilities.patch b/patches.suse/0037-amd-xgbe-Add-support-for-VXLAN-offload-capabilities.patch new file mode 100644 index 0000000..e8f017c --- /dev/null +++ b/patches.suse/0037-amd-xgbe-Add-support-for-VXLAN-offload-capabilities.patch @@ -0,0 +1,858 @@ +From d1f3a7e8286216f0ebc9bdc2111caaf04a52a93f Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Fri, 18 Aug 2017 09:04:04 -0500 +Subject: [PATCH 37/59] amd-xgbe: Add support for VXLAN offload capabilities +References: git-fixes +Patch-mainline: v4.14-rc1 +Git-commit: 1a510ccf5869a95c0ff324c61518e42e95712844 + +The hardware has the capability to perform checksum offload support +(both Tx and Rx) and TSO support for VXLAN packets. Add the support +required to enable this. + +The hardware can only support a single VXLAN port for offload. If more +than one VXLAN port is added then the offload capabilities have to be +disabled and can no longer be advertised. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-common.h | 24 ++ + drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 92 ++++++- + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 365 +++++++++++++++++++++++++++- + drivers/net/ethernet/amd/xgbe/xgbe-main.c | 23 ++ + drivers/net/ethernet/amd/xgbe/xgbe.h | 22 ++ + 5 files changed, 520 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +index c13069ed0535..5742f15d710c 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +@@ -298,6 +298,7 @@ + #define MAC_RWKPFR 0x00c4 + #define MAC_LPICSR 0x00d0 + #define MAC_LPITCR 0x00d4 ++#define MAC_TIR 0x00e0 + #define MAC_VR 0x0110 + #define MAC_DR 0x0114 + #define MAC_HWF0R 0x011c +@@ -364,6 +365,8 @@ + #define MAC_HWF0R_TXCOESEL_WIDTH 1 + #define MAC_HWF0R_VLHASH_INDEX 4 + #define MAC_HWF0R_VLHASH_WIDTH 1 ++#define MAC_HWF0R_VXN_INDEX 29 ++#define MAC_HWF0R_VXN_WIDTH 1 + #define MAC_HWF1R_ADDR64_INDEX 14 + #define MAC_HWF1R_ADDR64_WIDTH 2 + #define MAC_HWF1R_ADVTHWORD_INDEX 13 +@@ -446,6 +449,8 @@ + #define MAC_PFR_PR_WIDTH 1 + #define MAC_PFR_VTFE_INDEX 16 + #define MAC_PFR_VTFE_WIDTH 1 ++#define MAC_PFR_VUCC_INDEX 22 ++#define MAC_PFR_VUCC_WIDTH 1 + #define MAC_PMTCSR_MGKPKTEN_INDEX 1 + #define MAC_PMTCSR_MGKPKTEN_WIDTH 1 + #define MAC_PMTCSR_PWRDWN_INDEX 0 +@@ -508,6 +513,12 @@ + #define MAC_TCR_SS_WIDTH 2 + #define MAC_TCR_TE_INDEX 0 + #define MAC_TCR_TE_WIDTH 1 ++#define MAC_TCR_VNE_INDEX 24 ++#define MAC_TCR_VNE_WIDTH 1 ++#define MAC_TCR_VNM_INDEX 25 ++#define MAC_TCR_VNM_WIDTH 1 ++#define MAC_TIR_TNID_INDEX 0 ++#define MAC_TIR_TNID_WIDTH 16 + #define MAC_TSCR_AV8021ASMEN_INDEX 28 + #define MAC_TSCR_AV8021ASMEN_WIDTH 1 + #define MAC_TSCR_SNAPTYPSEL_INDEX 16 +@@ -1151,11 +1162,17 @@ + #define RX_PACKET_ATTRIBUTES_RSS_HASH_WIDTH 1 + #define RX_PACKET_ATTRIBUTES_FIRST_INDEX 7 + #define RX_PACKET_ATTRIBUTES_FIRST_WIDTH 1 ++#define RX_PACKET_ATTRIBUTES_TNP_INDEX 8 ++#define RX_PACKET_ATTRIBUTES_TNP_WIDTH 1 ++#define RX_PACKET_ATTRIBUTES_TNPCSUM_DONE_INDEX 9 ++#define RX_PACKET_ATTRIBUTES_TNPCSUM_DONE_WIDTH 1 + + #define RX_NORMAL_DESC0_OVT_INDEX 0 + #define RX_NORMAL_DESC0_OVT_WIDTH 16 + #define RX_NORMAL_DESC2_HL_INDEX 0 + #define RX_NORMAL_DESC2_HL_WIDTH 10 ++#define RX_NORMAL_DESC2_TNP_INDEX 11 ++#define RX_NORMAL_DESC2_TNP_WIDTH 1 + #define RX_NORMAL_DESC3_CDA_INDEX 27 + #define RX_NORMAL_DESC3_CDA_WIDTH 1 + #define RX_NORMAL_DESC3_CTXT_INDEX 30 +@@ -1182,9 +1199,11 @@ + #define RX_DESC3_L34T_IPV4_TCP 1 + #define RX_DESC3_L34T_IPV4_UDP 2 + #define RX_DESC3_L34T_IPV4_ICMP 3 ++#define RX_DESC3_L34T_IPV4_UNKNOWN 7 + #define RX_DESC3_L34T_IPV6_TCP 9 + #define RX_DESC3_L34T_IPV6_UDP 10 + #define RX_DESC3_L34T_IPV6_ICMP 11 ++#define RX_DESC3_L34T_IPV6_UNKNOWN 15 + + #define RX_CONTEXT_DESC3_TSA_INDEX 4 + #define RX_CONTEXT_DESC3_TSA_WIDTH 1 +@@ -1199,6 +1218,8 @@ + #define TX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH 1 + #define TX_PACKET_ATTRIBUTES_PTP_INDEX 3 + #define TX_PACKET_ATTRIBUTES_PTP_WIDTH 1 ++#define TX_PACKET_ATTRIBUTES_VXLAN_INDEX 4 ++#define TX_PACKET_ATTRIBUTES_VXLAN_WIDTH 1 + + #define TX_CONTEXT_DESC2_MSS_INDEX 0 + #define TX_CONTEXT_DESC2_MSS_WIDTH 15 +@@ -1239,8 +1260,11 @@ + #define TX_NORMAL_DESC3_TCPPL_WIDTH 18 + #define TX_NORMAL_DESC3_TSE_INDEX 18 + #define TX_NORMAL_DESC3_TSE_WIDTH 1 ++#define TX_NORMAL_DESC3_VNP_INDEX 23 ++#define TX_NORMAL_DESC3_VNP_WIDTH 3 + + #define TX_NORMAL_DESC2_VLAN_INSERT 0x2 ++#define TX_NORMAL_DESC3_VXLAN_PACKET 0x3 + + /* MDIO undefined or vendor specific registers */ + #ifndef MDIO_PMA_10GBR_PMD_CTRL +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +index 1cf2b3a04401..dfe2fcd1a9fe 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +@@ -479,6 +479,50 @@ static bool xgbe_is_pfc_queue(struct xgbe_prv_data *pdata, + return false; + } + ++static void xgbe_set_vxlan_id(struct xgbe_prv_data *pdata) ++{ ++ /* Program the VXLAN port */ ++ XGMAC_IOWRITE_BITS(pdata, MAC_TIR, TNID, pdata->vxlan_port); ++ ++ netif_dbg(pdata, drv, pdata->netdev, "VXLAN tunnel id set to %hx\n", ++ pdata->vxlan_port); ++} ++ ++static void xgbe_enable_vxlan(struct xgbe_prv_data *pdata) ++{ ++ if (!pdata->hw_feat.vxn) ++ return; ++ ++ /* Program the VXLAN port */ ++ xgbe_set_vxlan_id(pdata); ++ ++ /* Allow for IPv6/UDP zero-checksum VXLAN packets */ ++ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VUCC, 1); ++ ++ /* Enable VXLAN tunneling mode */ ++ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, VNM, 0); ++ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, VNE, 1); ++ ++ netif_dbg(pdata, drv, pdata->netdev, "VXLAN acceleration enabled\n"); ++} ++ ++static void xgbe_disable_vxlan(struct xgbe_prv_data *pdata) ++{ ++ if (!pdata->hw_feat.vxn) ++ return; ++ ++ /* Disable tunneling mode */ ++ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, VNE, 0); ++ ++ /* Clear IPv6/UDP zero-checksum VXLAN packets setting */ ++ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VUCC, 0); ++ ++ /* Clear the VXLAN port */ ++ XGMAC_IOWRITE_BITS(pdata, MAC_TIR, TNID, 0); ++ ++ netif_dbg(pdata, drv, pdata->netdev, "VXLAN acceleration disabled\n"); ++} ++ + static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata) + { + unsigned int max_q_count, q_count; +@@ -1620,7 +1664,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) + struct xgbe_ring_desc *rdesc; + struct xgbe_packet_data *packet = &ring->packet_data; + unsigned int tx_packets, tx_bytes; +- unsigned int csum, tso, vlan; ++ unsigned int csum, tso, vlan, vxlan; + unsigned int tso_context, vlan_context; + unsigned int tx_set_ic; + int start_index = ring->cur; +@@ -1638,6 +1682,8 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) + TSO_ENABLE); + vlan = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, + VLAN_CTAG); ++ vxlan = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, ++ VXLAN); + + if (tso && (packet->mss != ring->tx.cur_mss)) + tso_context = 1; +@@ -1769,6 +1815,10 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) + packet->length); + } + ++ if (vxlan) ++ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, VNP, ++ TX_NORMAL_DESC3_VXLAN_PACKET); ++ + for (i = cur_index - start_index + 1; i < packet->rdesc_count; i++) { + cur_index++; + rdata = XGBE_GET_DESC_DATA(ring, cur_index); +@@ -1930,9 +1980,27 @@ static int xgbe_dev_read(struct xgbe_channel *channel) + rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL); + + /* Set checksum done indicator as appropriate */ +- if (netdev->features & NETIF_F_RXCSUM) ++ if (netdev->features & NETIF_F_RXCSUM) { + XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, + CSUM_DONE, 1); ++ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, ++ TNPCSUM_DONE, 1); ++ } ++ ++ /* Set the tunneled packet indicator */ ++ if (XGMAC_GET_BITS_LE(rdesc->desc2, RX_NORMAL_DESC2, TNP)) { ++ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, ++ TNP, 1); ++ ++ l34t = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, L34T); ++ switch (l34t) { ++ case RX_DESC3_L34T_IPV4_UNKNOWN: ++ case RX_DESC3_L34T_IPV6_UNKNOWN: ++ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, ++ TNPCSUM_DONE, 0); ++ break; ++ } ++ } + + /* Check for errors (only valid in last descriptor) */ + err = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, ES); +@@ -1952,12 +2020,23 @@ static int xgbe_dev_read(struct xgbe_channel *channel) + packet->vlan_ctag); + } + } else { +- if ((etlt == 0x05) || (etlt == 0x06)) ++ unsigned int tnp = XGMAC_GET_BITS(packet->attributes, ++ RX_PACKET_ATTRIBUTES, TNP); ++ ++ if ((etlt == 0x05) || (etlt == 0x06)) { + XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, + CSUM_DONE, 0); +- else ++ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, ++ TNPCSUM_DONE, 0); ++ } else if (tnp && ((etlt == 0x09) || (etlt == 0x0a))) { ++ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, ++ CSUM_DONE, 0); ++ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, ++ TNPCSUM_DONE, 0); ++ } else { + XGMAC_SET_BITS(packet->errors, RX_PACKET_ERRORS, + FRAME, 1); ++ } + } + + pdata->ext_stats.rxq_packets[channel->queue_index]++; +@@ -3546,5 +3625,10 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if) + hw_if->disable_ecc_ded = xgbe_disable_ecc_ded; + hw_if->disable_ecc_sec = xgbe_disable_ecc_sec; + ++ /* For VXLAN */ ++ hw_if->enable_vxlan = xgbe_enable_vxlan; ++ hw_if->disable_vxlan = xgbe_disable_vxlan; ++ hw_if->set_vxlan_id = xgbe_set_vxlan_id; ++ + DBGPR("<--xgbe_init_function_ptrs\n"); + } +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index 352b67f3d651..27d26c1e3c48 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -123,6 +123,7 @@ + #include + #include + #include ++#include + + #include "xgbe.h" + #include "xgbe-common.h" +@@ -755,6 +756,7 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata) + ADDMACADRSEL); + hw_feat->ts_src = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, TSSTSSEL); + hw_feat->sa_vlan_ins = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, SAVLANINS); ++ hw_feat->vxn = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, VXN); + + /* Hardware feature register 1 */ + hw_feat->rx_fifo_size = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, +@@ -859,6 +861,8 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata) + (hw_feat->ts_src == 3) ? "internal/external" : "n/a"); + dev_dbg(pdata->dev, " SA/VLAN insertion : %s\n", + hw_feat->sa_vlan_ins ? "yes" : "no"); ++ dev_dbg(pdata->dev, " VXLAN/NVGRE support : %s\n", ++ hw_feat->vxn ? "yes" : "no"); + + /* Hardware feature register 1 */ + dev_dbg(pdata->dev, " RX fifo size : %u\n", +@@ -902,6 +906,116 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata) + } + } + ++static void xgbe_disable_vxlan_offloads(struct xgbe_prv_data *pdata) ++{ ++ struct net_device *netdev = pdata->netdev; ++ ++ if (!pdata->vxlan_offloads_set) ++ return; ++ ++ netdev_info(netdev, "disabling VXLAN offloads\n"); ++ ++ netdev->hw_enc_features &= ~(NETIF_F_SG | ++ NETIF_F_IP_CSUM | ++ NETIF_F_IPV6_CSUM | ++ NETIF_F_RXCSUM | ++ NETIF_F_TSO | ++ NETIF_F_TSO6 | ++ NETIF_F_GRO | ++ NETIF_F_GSO_UDP_TUNNEL | ++ NETIF_F_GSO_UDP_TUNNEL_CSUM); ++ ++ netdev->features &= ~(NETIF_F_GSO_UDP_TUNNEL | ++ NETIF_F_GSO_UDP_TUNNEL_CSUM); ++ ++ pdata->vxlan_offloads_set = 0; ++} ++ ++static void xgbe_disable_vxlan_hw(struct xgbe_prv_data *pdata) ++{ ++ if (!pdata->vxlan_port_set) ++ return; ++ ++ pdata->hw_if.disable_vxlan(pdata); ++ ++ pdata->vxlan_port_set = 0; ++ pdata->vxlan_port = 0; ++} ++ ++static void xgbe_disable_vxlan_accel(struct xgbe_prv_data *pdata) ++{ ++ xgbe_disable_vxlan_offloads(pdata); ++ ++ xgbe_disable_vxlan_hw(pdata); ++} ++ ++static void xgbe_enable_vxlan_offloads(struct xgbe_prv_data *pdata) ++{ ++ struct net_device *netdev = pdata->netdev; ++ ++ if (pdata->vxlan_offloads_set) ++ return; ++ ++ netdev_info(netdev, "enabling VXLAN offloads\n"); ++ ++ netdev->hw_enc_features |= NETIF_F_SG | ++ NETIF_F_IP_CSUM | ++ NETIF_F_IPV6_CSUM | ++ NETIF_F_RXCSUM | ++ NETIF_F_TSO | ++ NETIF_F_TSO6 | ++ NETIF_F_GRO | ++ pdata->vxlan_features; ++ ++ netdev->features |= pdata->vxlan_features; ++ ++ pdata->vxlan_offloads_set = 1; ++} ++ ++static void xgbe_enable_vxlan_hw(struct xgbe_prv_data *pdata) ++{ ++ struct xgbe_vxlan_data *vdata; ++ ++ if (pdata->vxlan_port_set) ++ return; ++ ++ if (list_empty(&pdata->vxlan_ports)) ++ return; ++ ++ vdata = list_first_entry(&pdata->vxlan_ports, ++ struct xgbe_vxlan_data, list); ++ ++ pdata->vxlan_port_set = 1; ++ pdata->vxlan_port = be16_to_cpu(vdata->port); ++ ++ pdata->hw_if.enable_vxlan(pdata); ++} ++ ++static void xgbe_enable_vxlan_accel(struct xgbe_prv_data *pdata) ++{ ++ /* VXLAN acceleration desired? */ ++ if (!pdata->vxlan_features) ++ return; ++ ++ /* VXLAN acceleration possible? */ ++ if (pdata->vxlan_force_disable) ++ return; ++ ++ xgbe_enable_vxlan_hw(pdata); ++ ++ xgbe_enable_vxlan_offloads(pdata); ++} ++ ++static void xgbe_reset_vxlan_accel(struct xgbe_prv_data *pdata) ++{ ++ xgbe_disable_vxlan_hw(pdata); ++ ++ if (pdata->vxlan_features) ++ xgbe_enable_vxlan_offloads(pdata); ++ ++ pdata->vxlan_force_disable = 0; ++} ++ + static void xgbe_napi_enable(struct xgbe_prv_data *pdata, unsigned int add) + { + struct xgbe_channel *channel; +@@ -1225,6 +1339,8 @@ static int xgbe_start(struct xgbe_prv_data *pdata) + hw_if->enable_tx(pdata); + hw_if->enable_rx(pdata); + ++ udp_tunnel_get_rx_info(netdev); ++ + netif_tx_start_all_queues(netdev); + + xgbe_start_timers(pdata); +@@ -1266,6 +1382,8 @@ static void xgbe_stop(struct xgbe_prv_data *pdata) + xgbe_stop_timers(pdata); + flush_workqueue(pdata->dev_workqueue); + ++ xgbe_reset_vxlan_accel(pdata); ++ + hw_if->disable_tx(pdata); + hw_if->disable_rx(pdata); + +@@ -1554,10 +1672,18 @@ static int xgbe_prep_tso(struct sk_buff *skb, struct xgbe_packet_data *packet) + if (ret) + return ret; + +- packet->header_len = skb_transport_offset(skb) + tcp_hdrlen(skb); +- packet->tcp_header_len = tcp_hdrlen(skb); ++ if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, VXLAN)) { ++ packet->header_len = skb_inner_transport_offset(skb) + ++ inner_tcp_hdrlen(skb); ++ packet->tcp_header_len = inner_tcp_hdrlen(skb); ++ } else { ++ packet->header_len = skb_transport_offset(skb) + ++ tcp_hdrlen(skb); ++ packet->tcp_header_len = tcp_hdrlen(skb); ++ } + packet->tcp_payload_len = skb->len - packet->header_len; + packet->mss = skb_shinfo(skb)->gso_size; ++ + DBGPR(" packet->header_len=%u\n", packet->header_len); + DBGPR(" packet->tcp_header_len=%u, packet->tcp_payload_len=%u\n", + packet->tcp_header_len, packet->tcp_payload_len); +@@ -1572,6 +1698,49 @@ static int xgbe_prep_tso(struct sk_buff *skb, struct xgbe_packet_data *packet) + return 0; + } + ++static bool xgbe_is_vxlan(struct xgbe_prv_data *pdata, struct sk_buff *skb) ++{ ++ struct xgbe_vxlan_data *vdata; ++ ++ if (pdata->vxlan_force_disable) ++ return false; ++ ++ if (!skb->encapsulation) ++ return false; ++ ++ if (skb->ip_summed != CHECKSUM_PARTIAL) ++ return false; ++ ++ switch (skb->protocol) { ++ case htons(ETH_P_IP): ++ if (ip_hdr(skb)->protocol != IPPROTO_UDP) ++ return false; ++ break; ++ ++ case htons(ETH_P_IPV6): ++ if (ipv6_hdr(skb)->nexthdr != IPPROTO_UDP) ++ return false; ++ break; ++ ++ default: ++ return false; ++ } ++ ++ /* See if we have the UDP port in our list */ ++ list_for_each_entry(vdata, &pdata->vxlan_ports, list) { ++ if ((skb->protocol == htons(ETH_P_IP)) && ++ (vdata->sa_family == AF_INET) && ++ (vdata->port == udp_hdr(skb)->dest)) ++ return true; ++ else if ((skb->protocol == htons(ETH_P_IPV6)) && ++ (vdata->sa_family == AF_INET6) && ++ (vdata->port == udp_hdr(skb)->dest)) ++ return true; ++ } ++ ++ return false; ++} ++ + static int xgbe_is_tso(struct sk_buff *skb) + { + if (skb->ip_summed != CHECKSUM_PARTIAL) +@@ -1620,6 +1789,10 @@ static void xgbe_packet_info(struct xgbe_prv_data *pdata, + XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, + CSUM_ENABLE, 1); + ++ if (xgbe_is_vxlan(pdata, skb)) ++ XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, ++ VXLAN, 1); ++ + if (skb_vlan_tag_present(skb)) { + /* VLAN requires an extra descriptor if tag is different */ + if (skb_vlan_tag_get(skb) != ring->tx.cur_vlan_ctag) +@@ -2049,18 +2222,83 @@ static int xgbe_setup_tc(struct net_device *netdev, enum tc_setup_type type, + return 0; + } + ++static netdev_features_t xgbe_fix_features(struct net_device *netdev, ++ netdev_features_t features) ++{ ++ struct xgbe_prv_data *pdata = netdev_priv(netdev); ++ netdev_features_t vxlan_base, vxlan_mask; ++ ++ vxlan_base = NETIF_F_GSO_UDP_TUNNEL | NETIF_F_RX_UDP_TUNNEL_PORT; ++ vxlan_mask = vxlan_base | NETIF_F_GSO_UDP_TUNNEL_CSUM; ++ ++ pdata->vxlan_features = features & vxlan_mask; ++ ++ /* Only fix VXLAN-related features */ ++ if (!pdata->vxlan_features) ++ return features; ++ ++ /* If VXLAN isn't supported then clear any features: ++ * This is needed because NETIF_F_RX_UDP_TUNNEL_PORT gets ++ * automatically set if ndo_udp_tunnel_add is set. ++ */ ++ if (!pdata->hw_feat.vxn) ++ return features & ~vxlan_mask; ++ ++ /* VXLAN CSUM requires VXLAN base */ ++ if ((features & NETIF_F_GSO_UDP_TUNNEL_CSUM) && ++ !(features & NETIF_F_GSO_UDP_TUNNEL)) { ++ netdev_notice(netdev, ++ "forcing tx udp tunnel support\n"); ++ features |= NETIF_F_GSO_UDP_TUNNEL; ++ } ++ ++ /* Can't do one without doing the other */ ++ if ((features & vxlan_base) != vxlan_base) { ++ netdev_notice(netdev, ++ "forcing both tx and rx udp tunnel support\n"); ++ features |= vxlan_base; ++ } ++ ++ if (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) { ++ if (!(features & NETIF_F_GSO_UDP_TUNNEL_CSUM)) { ++ netdev_notice(netdev, ++ "forcing tx udp tunnel checksumming on\n"); ++ features |= NETIF_F_GSO_UDP_TUNNEL_CSUM; ++ } ++ } else { ++ if (features & NETIF_F_GSO_UDP_TUNNEL_CSUM) { ++ netdev_notice(netdev, ++ "forcing tx udp tunnel checksumming off\n"); ++ features &= ~NETIF_F_GSO_UDP_TUNNEL_CSUM; ++ } ++ } ++ ++ pdata->vxlan_features = features & vxlan_mask; ++ ++ /* Adjust UDP Tunnel based on current state */ ++ if (pdata->vxlan_force_disable) { ++ netdev_notice(netdev, ++ "VXLAN acceleration disabled, turning off udp tunnel features\n"); ++ features &= ~vxlan_mask; ++ } ++ ++ return features; ++} ++ + static int xgbe_set_features(struct net_device *netdev, + netdev_features_t features) + { + struct xgbe_prv_data *pdata = netdev_priv(netdev); + struct xgbe_hw_if *hw_if = &pdata->hw_if; + netdev_features_t rxhash, rxcsum, rxvlan, rxvlan_filter; ++ netdev_features_t udp_tunnel; + int ret = 0; + + rxhash = pdata->netdev_features & NETIF_F_RXHASH; + rxcsum = pdata->netdev_features & NETIF_F_RXCSUM; + rxvlan = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_RX; + rxvlan_filter = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_FILTER; ++ udp_tunnel = pdata->netdev_features & NETIF_F_GSO_UDP_TUNNEL; + + if ((features & NETIF_F_RXHASH) && !rxhash) + ret = hw_if->enable_rss(pdata); +@@ -2084,6 +2322,11 @@ static int xgbe_set_features(struct net_device *netdev, + else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) && rxvlan_filter) + hw_if->disable_rx_vlan_filtering(pdata); + ++ if ((features & NETIF_F_GSO_UDP_TUNNEL) && !udp_tunnel) ++ xgbe_enable_vxlan_accel(pdata); ++ else if (!(features & NETIF_F_GSO_UDP_TUNNEL) && udp_tunnel) ++ xgbe_disable_vxlan_accel(pdata); ++ + pdata->netdev_features = features; + + DBGPR("<--xgbe_set_features\n"); +@@ -2091,6 +2334,111 @@ static int xgbe_set_features(struct net_device *netdev, + return 0; + } + ++static void xgbe_udp_tunnel_add(struct net_device *netdev, ++ struct udp_tunnel_info *ti) ++{ ++ struct xgbe_prv_data *pdata = netdev_priv(netdev); ++ struct xgbe_vxlan_data *vdata; ++ ++ if (!pdata->hw_feat.vxn) ++ return; ++ ++ if (ti->type != UDP_TUNNEL_TYPE_VXLAN) ++ return; ++ ++ pdata->vxlan_port_count++; ++ ++ netif_dbg(pdata, drv, netdev, ++ "adding VXLAN tunnel, family=%hx/port=%hx\n", ++ ti->sa_family, be16_to_cpu(ti->port)); ++ ++ if (pdata->vxlan_force_disable) ++ return; ++ ++ vdata = kzalloc(sizeof(*vdata), GFP_ATOMIC); ++ if (!vdata) { ++ /* Can no longer properly track VXLAN ports */ ++ pdata->vxlan_force_disable = 1; ++ netif_dbg(pdata, drv, netdev, ++ "internal error, disabling VXLAN accelerations\n"); ++ ++ xgbe_disable_vxlan_accel(pdata); ++ ++ return; ++ } ++ vdata->sa_family = ti->sa_family; ++ vdata->port = ti->port; ++ ++ list_add_tail(&vdata->list, &pdata->vxlan_ports); ++ ++ /* First port added? */ ++ if (pdata->vxlan_port_count == 1) { ++ xgbe_enable_vxlan_accel(pdata); ++ ++ return; ++ } ++} ++ ++static void xgbe_udp_tunnel_del(struct net_device *netdev, ++ struct udp_tunnel_info *ti) ++{ ++ struct xgbe_prv_data *pdata = netdev_priv(netdev); ++ struct xgbe_vxlan_data *vdata; ++ ++ if (!pdata->hw_feat.vxn) ++ return; ++ ++ if (ti->type != UDP_TUNNEL_TYPE_VXLAN) ++ return; ++ ++ netif_dbg(pdata, drv, netdev, ++ "deleting VXLAN tunnel, family=%hx/port=%hx\n", ++ ti->sa_family, be16_to_cpu(ti->port)); ++ ++ /* Don't need safe version since loop terminates with deletion */ ++ list_for_each_entry(vdata, &pdata->vxlan_ports, list) { ++ if (vdata->sa_family != ti->sa_family) ++ continue; ++ ++ if (vdata->port != ti->port) ++ continue; ++ ++ list_del(&vdata->list); ++ kfree(vdata); ++ ++ break; ++ } ++ ++ pdata->vxlan_port_count--; ++ if (!pdata->vxlan_port_count) { ++ xgbe_reset_vxlan_accel(pdata); ++ ++ return; ++ } ++ ++ if (pdata->vxlan_force_disable) ++ return; ++ ++ /* See if VXLAN tunnel id needs to be changed */ ++ vdata = list_first_entry(&pdata->vxlan_ports, ++ struct xgbe_vxlan_data, list); ++ if (pdata->vxlan_port == be16_to_cpu(vdata->port)) ++ return; ++ ++ pdata->vxlan_port = be16_to_cpu(vdata->port); ++ pdata->hw_if.set_vxlan_id(pdata); ++} ++ ++static netdev_features_t xgbe_features_check(struct sk_buff *skb, ++ struct net_device *netdev, ++ netdev_features_t features) ++{ ++ features = vlan_features_check(skb, features); ++ features = vxlan_features_check(skb, features); ++ ++ return features; ++} ++ + static const struct net_device_ops xgbe_netdev_ops = { + .ndo_open = xgbe_open, + .ndo_stop = xgbe_close, +@@ -2108,7 +2456,11 @@ static const struct net_device_ops xgbe_netdev_ops = { + .ndo_poll_controller = xgbe_poll_controller, + #endif + .ndo_setup_tc = xgbe_setup_tc, ++ .ndo_fix_features = xgbe_fix_features, + .ndo_set_features = xgbe_set_features, ++ .ndo_udp_tunnel_add = xgbe_udp_tunnel_add, ++ .ndo_udp_tunnel_del = xgbe_udp_tunnel_del, ++ .ndo_features_check = xgbe_features_check, + }; + + const struct net_device_ops *xgbe_get_netdev_ops(void) +@@ -2420,6 +2772,15 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) + RX_PACKET_ATTRIBUTES, CSUM_DONE)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + ++ if (XGMAC_GET_BITS(packet->attributes, ++ RX_PACKET_ATTRIBUTES, TNP)) { ++ skb->encapsulation = 1; ++ ++ if (XGMAC_GET_BITS(packet->attributes, ++ RX_PACKET_ATTRIBUTES, TNPCSUM_DONE)) ++ skb->csum_level = 1; ++ } ++ + if (XGMAC_GET_BITS(packet->attributes, + RX_PACKET_ATTRIBUTES, VLAN_CTAG)) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +index 798d281f8eac..441d0973957b 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +@@ -193,6 +193,7 @@ struct xgbe_prv_data *xgbe_alloc_pdata(struct device *dev) + mutex_init(&pdata->i2c_mutex); + init_completion(&pdata->i2c_complete); + init_completion(&pdata->mdio_complete); ++ INIT_LIST_HEAD(&pdata->vxlan_ports); + + pdata->msg_enable = netif_msg_init(debug, default_msg_level); + +@@ -375,6 +376,28 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata) + if (pdata->hw_feat.rss) + netdev->hw_features |= NETIF_F_RXHASH; + ++ if (pdata->hw_feat.vxn) { ++ netdev->hw_enc_features = NETIF_F_SG | ++ NETIF_F_IP_CSUM | ++ NETIF_F_IPV6_CSUM | ++ NETIF_F_RXCSUM | ++ NETIF_F_TSO | ++ NETIF_F_TSO6 | ++ NETIF_F_GRO | ++ NETIF_F_GSO_UDP_TUNNEL | ++ NETIF_F_GSO_UDP_TUNNEL_CSUM | ++ NETIF_F_RX_UDP_TUNNEL_PORT; ++ ++ netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL | ++ NETIF_F_GSO_UDP_TUNNEL_CSUM | ++ NETIF_F_RX_UDP_TUNNEL_PORT; ++ ++ pdata->vxlan_offloads_set = 1; ++ pdata->vxlan_features = NETIF_F_GSO_UDP_TUNNEL | ++ NETIF_F_GSO_UDP_TUNNEL_CSUM | ++ NETIF_F_RX_UDP_TUNNEL_PORT; ++ } ++ + netdev->vlan_features |= NETIF_F_SG | + NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index 1040860c747c..4b5159aa181f 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -132,6 +132,7 @@ + #include + #include + #include ++#include + + #define XGBE_DRV_NAME "amd-xgbe" + #define XGBE_DRV_VERSION "1.0.3" +@@ -817,6 +818,11 @@ struct xgbe_hw_if { + /* For ECC */ + void (*disable_ecc_ded)(struct xgbe_prv_data *); + void (*disable_ecc_sec)(struct xgbe_prv_data *, enum xgbe_ecc_sec); ++ ++ /* For VXLAN */ ++ void (*enable_vxlan)(struct xgbe_prv_data *); ++ void (*disable_vxlan)(struct xgbe_prv_data *); ++ void (*set_vxlan_id)(struct xgbe_prv_data *); + }; + + /* This structure represents implementation specific routines for an +@@ -946,6 +952,7 @@ struct xgbe_hw_features { + unsigned int addn_mac; /* Additional MAC Addresses */ + unsigned int ts_src; /* Timestamp Source */ + unsigned int sa_vlan_ins; /* Source Address or VLAN Insertion */ ++ unsigned int vxn; /* VXLAN/NVGRE */ + + /* HW Feature Register1 */ + unsigned int rx_fifo_size; /* MTL Receive FIFO Size */ +@@ -985,6 +992,12 @@ struct xgbe_version_data { + unsigned int rx_desc_prefetch; + }; + ++struct xgbe_vxlan_data { ++ struct list_head list; ++ sa_family_t sa_family; ++ __be16 port; ++}; ++ + struct xgbe_prv_data { + struct net_device *netdev; + struct pci_dev *pcidev; +@@ -1133,6 +1146,15 @@ struct xgbe_prv_data { + u32 rss_table[XGBE_RSS_MAX_TABLE_SIZE]; + u32 rss_options; + ++ /* VXLAN settings */ ++ unsigned int vxlan_port_set; ++ unsigned int vxlan_offloads_set; ++ unsigned int vxlan_force_disable; ++ unsigned int vxlan_port_count; ++ struct list_head vxlan_ports; ++ u16 vxlan_port; ++ netdev_features_t vxlan_features; ++ + /* Netdev related settings */ + unsigned char mac_addr[ETH_ALEN]; + netdev_features_t netdev_features; +-- +2.16.4 + diff --git a/patches.suse/0038-amd-xgbe-Add-additional-ethtool-statistics.patch b/patches.suse/0038-amd-xgbe-Add-additional-ethtool-statistics.patch new file mode 100644 index 0000000..50f9aff --- /dev/null +++ b/patches.suse/0038-amd-xgbe-Add-additional-ethtool-statistics.patch @@ -0,0 +1,109 @@ +From 18e37d2612983fcce366492e8e0f3b16409da935 Mon Sep 17 00:00:00 2001 +From: "Lendacky, Thomas" +Date: Fri, 18 Aug 2017 09:04:14 -0500 +Subject: [PATCH 38/59] amd-xgbe: Add additional ethtool statistics +References: git-fixes +Patch-mainline: v4.14-rc1 +Git-commit: 3010608d033c7cae73d1662493c85b4c3b27015a + +Add some additional statistics for tracking VXLAN packets and checksum +errors. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 8 +++++++- + drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 4 ++++ + drivers/net/ethernet/amd/xgbe/xgbe.h | 5 +++++ + 3 files changed, 16 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +index dfe2fcd1a9fe..01be8791bda7 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +@@ -1815,10 +1815,13 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) + packet->length); + } + +- if (vxlan) ++ if (vxlan) { + XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, VNP, + TX_NORMAL_DESC3_VXLAN_PACKET); + ++ pdata->ext_stats.tx_vxlan_packets += packet->tx_packets; ++ } ++ + for (i = cur_index - start_index + 1; i < packet->rdesc_count; i++) { + cur_index++; + rdata = XGBE_GET_DESC_DATA(ring, cur_index); +@@ -1991,6 +1994,7 @@ static int xgbe_dev_read(struct xgbe_channel *channel) + if (XGMAC_GET_BITS_LE(rdesc->desc2, RX_NORMAL_DESC2, TNP)) { + XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, + TNP, 1); ++ pdata->ext_stats.rx_vxlan_packets++; + + l34t = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, L34T); + switch (l34t) { +@@ -2028,11 +2032,13 @@ static int xgbe_dev_read(struct xgbe_channel *channel) + CSUM_DONE, 0); + XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, + TNPCSUM_DONE, 0); ++ pdata->ext_stats.rx_csum_errors++; + } else if (tnp && ((etlt == 0x09) || (etlt == 0x0a))) { + XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, + CSUM_DONE, 0); + XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, + TNPCSUM_DONE, 0); ++ pdata->ext_stats.rx_vxlan_csum_errors++; + } else { + XGMAC_SET_BITS(packet->errors, RX_PACKET_ERRORS, + FRAME, 1); +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +index cea25acd5de2..ff397bb25042 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +@@ -146,6 +146,7 @@ static const struct xgbe_stats xgbe_gstring_stats[] = { + XGMAC_MMC_STAT("tx_broadcast_packets", txbroadcastframes_gb), + XGMAC_MMC_STAT("tx_multicast_packets", txmulticastframes_gb), + XGMAC_MMC_STAT("tx_vlan_packets", txvlanframes_g), ++ XGMAC_EXT_STAT("tx_vxlan_packets", tx_vxlan_packets), + XGMAC_EXT_STAT("tx_tso_packets", tx_tso_packets), + XGMAC_MMC_STAT("tx_64_byte_packets", tx64octets_gb), + XGMAC_MMC_STAT("tx_65_to_127_byte_packets", tx65to127octets_gb), +@@ -162,6 +163,7 @@ static const struct xgbe_stats xgbe_gstring_stats[] = { + XGMAC_MMC_STAT("rx_broadcast_packets", rxbroadcastframes_g), + XGMAC_MMC_STAT("rx_multicast_packets", rxmulticastframes_g), + XGMAC_MMC_STAT("rx_vlan_packets", rxvlanframes_gb), ++ XGMAC_EXT_STAT("rx_vxlan_packets", rx_vxlan_packets), + XGMAC_MMC_STAT("rx_64_byte_packets", rx64octets_gb), + XGMAC_MMC_STAT("rx_65_to_127_byte_packets", rx65to127octets_gb), + XGMAC_MMC_STAT("rx_128_to_255_byte_packets", rx128to255octets_gb), +@@ -177,6 +179,8 @@ static const struct xgbe_stats xgbe_gstring_stats[] = { + XGMAC_MMC_STAT("rx_out_of_range_errors", rxoutofrangetype), + XGMAC_MMC_STAT("rx_fifo_overflow_errors", rxfifooverflow), + XGMAC_MMC_STAT("rx_watchdog_errors", rxwatchdogerror), ++ XGMAC_EXT_STAT("rx_csum_errors", rx_csum_errors), ++ XGMAC_EXT_STAT("rx_vxlan_csum_errors", rx_vxlan_csum_errors), + XGMAC_MMC_STAT("rx_pause_frames", rxpauseframes), + XGMAC_EXT_STAT("rx_split_header_packets", rx_split_header_packets), + XGMAC_EXT_STAT("rx_buffer_unavailable", rx_buffer_unavailable), +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index 4b5159aa181f..214e65d73e6c 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -715,6 +715,11 @@ struct xgbe_ext_stats { + u64 txq_bytes[XGBE_MAX_DMA_CHANNELS]; + u64 rxq_packets[XGBE_MAX_DMA_CHANNELS]; + u64 rxq_bytes[XGBE_MAX_DMA_CHANNELS]; ++ ++ u64 tx_vxlan_packets; ++ u64 rx_vxlan_packets; ++ u64 rx_csum_errors; ++ u64 rx_vxlan_csum_errors; + }; + + struct xgbe_hw_if { +-- +2.16.4 + diff --git a/patches.suse/0039-amd-xgbe-Interrupt-summary-bits-are-h-w-version-depe.patch b/patches.suse/0039-amd-xgbe-Interrupt-summary-bits-are-h-w-version-depe.patch new file mode 100644 index 0000000..d5f73aa --- /dev/null +++ b/patches.suse/0039-amd-xgbe-Interrupt-summary-bits-are-h-w-version-depe.patch @@ -0,0 +1,92 @@ +From 4bf1a11ca29a3e953498c66102d0195bc5eb5916 Mon Sep 17 00:00:00 2001 +From: Tom Lendacky +Date: Mon, 28 Aug 2017 15:29:34 -0500 +Subject: [PATCH 39/59] amd-xgbe: Interrupt summary bits are h/w version + dependent +References: git-fixes +Patch-mainline: v4.14-rc1 +Git-commit: f602b976b6b0eab8de59e438f9313da72b47a8e4 + +There is a difference in the bit position of the normal interrupt summary +enable (NIE) and abnormal interrupt summary enable (AIE) between revisions +of the hardware. For older revisions the NIE and AIE bits are positions +16 and 15 respectively. For newer revisions the NIE and AIE bits are +positions 15 and 14. The effect in changing the bit position is that +newer hardware won't receive AIE interrupts in the current version of the +driver. Specifically, the driver uses this interrupt to collect +statistics on when a receive buffer unavailable event occurs and to +restart the driver/device when a fatal bus error occurs. + +Update the driver to set the interrupt enable bit based on the reported +version of the hardware. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-common.h | 8 ++++++-- + drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 13 ++++++++++--- + 2 files changed, 16 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +index 5742f15d710c..b40d4377cc71 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +@@ -210,11 +210,15 @@ + #define DMA_CH_CR_PBLX8_WIDTH 1 + #define DMA_CH_CR_SPH_INDEX 24 + #define DMA_CH_CR_SPH_WIDTH 1 +-#define DMA_CH_IER_AIE_INDEX 15 ++#define DMA_CH_IER_AIE20_INDEX 15 ++#define DMA_CH_IER_AIE20_WIDTH 1 ++#define DMA_CH_IER_AIE_INDEX 14 + #define DMA_CH_IER_AIE_WIDTH 1 + #define DMA_CH_IER_FBEE_INDEX 12 + #define DMA_CH_IER_FBEE_WIDTH 1 +-#define DMA_CH_IER_NIE_INDEX 16 ++#define DMA_CH_IER_NIE20_INDEX 16 ++#define DMA_CH_IER_NIE20_WIDTH 1 ++#define DMA_CH_IER_NIE_INDEX 15 + #define DMA_CH_IER_NIE_WIDTH 1 + #define DMA_CH_IER_RBUE_INDEX 7 + #define DMA_CH_IER_RBUE_WIDTH 1 +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +index 01be8791bda7..1e4bb33925e6 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +@@ -649,13 +649,15 @@ static void xgbe_config_flow_control(struct xgbe_prv_data *pdata) + static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata) + { + struct xgbe_channel *channel; +- unsigned int i; ++ unsigned int i, ver; + + /* Set the interrupt mode if supported */ + if (pdata->channel_irq_mode) + XGMAC_IOWRITE_BITS(pdata, DMA_MR, INTM, + pdata->channel_irq_mode); + ++ ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER); ++ + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel[i]; + +@@ -671,8 +673,13 @@ static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata) + * AIE - Abnormal Interrupt Summary Enable + * FBEE - Fatal Bus Error Enable + */ +- XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, NIE, 1); +- XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, AIE, 1); ++ if (ver < 0x21) { ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, NIE20, 1); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, AIE20, 1); ++ } else { ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, NIE, 1); ++ XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, AIE, 1); ++ } + XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, FBEE, 1); + + if (channel->tx_ring) { +-- +2.16.4 + diff --git a/patches.suse/0040-net-amd-xgbe-Get-rid-of-custom-hex_dump_to_buffer.patch b/patches.suse/0040-net-amd-xgbe-Get-rid-of-custom-hex_dump_to_buffer.patch new file mode 100644 index 0000000..586ccb1 --- /dev/null +++ b/patches.suse/0040-net-amd-xgbe-Get-rid-of-custom-hex_dump_to_buffer.patch @@ -0,0 +1,70 @@ +From 3972d733a5664fbf3a8ffec548e410566d92385e Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Tue, 19 Dec 2017 23:22:15 +0200 +Subject: [PATCH 40/59] net: amd-xgbe: Get rid of custom hex_dump_to_buffer() +References: git-fixes +Patch-mainline: v4.16-rc1 +Git-commit: 9a07ae68932b81c5666035aec3f7cb3017e5b13e + +Get rid of yet another custom hex_dump_to_buffer(). + +The output is slightly changed, i.e. each byte followed by white space. + +Note, we don't use print_hex_dump() here since the original code uses +nedev_dbg(). + +Acked-by: Tom Lendacky +Signed-off-by: Andy Shevchenko +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 24 +++++++----------------- + 1 file changed, 7 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index 27d26c1e3c48..b80b9d588448 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -2931,9 +2931,8 @@ void xgbe_dump_rx_desc(struct xgbe_prv_data *pdata, struct xgbe_ring *ring, + void xgbe_print_pkt(struct net_device *netdev, struct sk_buff *skb, bool tx_rx) + { + struct ethhdr *eth = (struct ethhdr *)skb->data; +- unsigned char *buf = skb->data; + unsigned char buffer[128]; +- unsigned int i, j; ++ unsigned int i; + + netdev_dbg(netdev, "\n************** SKB dump ****************\n"); + +@@ -2944,22 +2943,13 @@ void xgbe_print_pkt(struct net_device *netdev, struct sk_buff *skb, bool tx_rx) + netdev_dbg(netdev, "Src MAC addr: %pM\n", eth->h_source); + netdev_dbg(netdev, "Protocol: %#06hx\n", ntohs(eth->h_proto)); + +- for (i = 0, j = 0; i < skb->len;) { +- j += snprintf(buffer + j, sizeof(buffer) - j, "%02hhx", +- buf[i++]); +- +- if ((i % 32) == 0) { +- netdev_dbg(netdev, " %#06x: %s\n", i - 32, buffer); +- j = 0; +- } else if ((i % 16) == 0) { +- buffer[j++] = ' '; +- buffer[j++] = ' '; +- } else if ((i % 4) == 0) { +- buffer[j++] = ' '; +- } ++ for (i = 0; i < skb->len; i += 32) { ++ unsigned int len = min(skb->len - i, 32U); ++ ++ hex_dump_to_buffer(&skb->data[i], len, 32, 1, ++ buffer, sizeof(buffer), false); ++ netdev_dbg(netdev, " %#06x: %s\n", i, buffer); + } +- if (i % 32) +- netdev_dbg(netdev, " %#06x: %s\n", i - (i % 32), buffer); + + netdev_dbg(netdev, "\n************** SKB dump ****************\n"); + } +-- +2.16.4 + diff --git a/patches.suse/0041-net-amd-xgbe-fix-comparison-to-bitshift-when-dealing.patch b/patches.suse/0041-net-amd-xgbe-fix-comparison-to-bitshift-when-dealing.patch new file mode 100644 index 0000000..e8eb8cf --- /dev/null +++ b/patches.suse/0041-net-amd-xgbe-fix-comparison-to-bitshift-when-dealing.patch @@ -0,0 +1,36 @@ +From 0a890287aec1b1d1b589e753bb7b5119fa9850d9 Mon Sep 17 00:00:00 2001 +From: Wolfram Sang +Date: Mon, 5 Feb 2018 21:10:01 +0100 +Subject: [PATCH 41/59] net: amd-xgbe: fix comparison to bitshift when dealing + with a mask +References: git-fixes +Patch-mainline: v4.16-rc1 +Git-commit: a3276892db7a588bedc33168e502572008f714a9 + +Due to a typo, the mask was destroyed by a comparison instead of a bit +shift. + +Signed-off-by: Wolfram Sang +Acked-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index b80b9d588448..5070c87e65aa 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -594,7 +594,7 @@ static void xgbe_isr_task(unsigned long data) + + reissue_mask = 1 << 0; + if (!pdata->per_channel_irq) +- reissue_mask |= 0xffff < 4; ++ reissue_mask |= 0xffff << 4; + + XP_IOWRITE(pdata, XP_INT_REISSUE_EN, reissue_mask); + } +-- +2.16.4 + diff --git a/patches.suse/0042-amd-xgbe-Add-ethtool-support-to-retrieve-SFP-module-.patch b/patches.suse/0042-amd-xgbe-Add-ethtool-support-to-retrieve-SFP-module-.patch new file mode 100644 index 0000000..d206fd9 --- /dev/null +++ b/patches.suse/0042-amd-xgbe-Add-ethtool-support-to-retrieve-SFP-module-.patch @@ -0,0 +1,302 @@ +From 5d22a8c5e1114031c413a31c9a5c45e382c15f27 Mon Sep 17 00:00:00 2001 +From: Tom Lendacky +Date: Wed, 23 May 2018 11:38:46 -0500 +Subject: [PATCH 42/59] amd-xgbe: Add ethtool support to retrieve SFP module + info +References: git-fixes +Patch-mainline: v4.18-rc1 +Git-commit: 53a1024abf3e4cb3310a54b08c48323649158c13 + +Add support to get SFP module information using ethtool. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 18 ++++ + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 21 ++++ + drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 137 +++++++++++++++++++++++++++ + drivers/net/ethernet/amd/xgbe/xgbe.h | 13 +++ + 4 files changed, 189 insertions(+) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +index ff397bb25042..57394b77b2d3 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +@@ -626,6 +626,22 @@ static int xgbe_get_ts_info(struct net_device *netdev, + return 0; + } + ++static int xgbe_get_module_info(struct net_device *netdev, ++ struct ethtool_modinfo *modinfo) ++{ ++ struct xgbe_prv_data *pdata = netdev_priv(netdev); ++ ++ return pdata->phy_if.module_info(pdata, modinfo); ++} ++ ++static int xgbe_get_module_eeprom(struct net_device *netdev, ++ struct ethtool_eeprom *eeprom, u8 *data) ++{ ++ struct xgbe_prv_data *pdata = netdev_priv(netdev); ++ ++ return pdata->phy_if.module_eeprom(pdata, eeprom, data); ++} ++ + static const struct ethtool_ops xgbe_ethtool_ops = { + .get_drvinfo = xgbe_get_drvinfo, + .get_msglevel = xgbe_get_msglevel, +@@ -646,6 +662,8 @@ static const struct ethtool_ops xgbe_ethtool_ops = { + .get_ts_info = xgbe_get_ts_info, + .get_link_ksettings = xgbe_get_link_ksettings, + .set_link_ksettings = xgbe_set_link_ksettings, ++ .get_module_info = xgbe_get_module_info, ++ .get_module_eeprom = xgbe_get_module_eeprom, + }; + + const struct ethtool_ops *xgbe_get_ethtool_ops(void) +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +index b47ef6443ea3..eba757e934e5 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +@@ -126,6 +126,24 @@ + #include "xgbe.h" + #include "xgbe-common.h" + ++static int xgbe_phy_module_eeprom(struct xgbe_prv_data *pdata, ++ struct ethtool_eeprom *eeprom, u8 *data) ++{ ++ if (!pdata->phy_if.phy_impl.module_eeprom) ++ return -ENXIO; ++ ++ return pdata->phy_if.phy_impl.module_eeprom(pdata, eeprom, data); ++} ++ ++static int xgbe_phy_module_info(struct xgbe_prv_data *pdata, ++ struct ethtool_modinfo *modinfo) ++{ ++ if (!pdata->phy_if.phy_impl.module_info) ++ return -ENXIO; ++ ++ return pdata->phy_if.phy_impl.module_info(pdata, modinfo); ++} ++ + static void xgbe_an37_clear_interrupts(struct xgbe_prv_data *pdata) + { + int reg; +@@ -1602,4 +1620,7 @@ void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *phy_if) + phy_if->phy_valid_speed = xgbe_phy_valid_speed; + + phy_if->an_isr = xgbe_an_combined_isr; ++ ++ phy_if->module_info = xgbe_phy_module_info; ++ phy_if->module_eeprom = xgbe_phy_module_eeprom; + } +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index f8a11c6c8dcb..61b279dc2acf 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -119,6 +119,7 @@ + #include + #include + #include ++#include + + #include "xgbe.h" + #include "xgbe-common.h" +@@ -270,6 +271,15 @@ struct xgbe_sfp_eeprom { + u8 vendor[32]; + }; + ++#define XGBE_SFP_DIAGS_SUPPORTED(_x) \ ++ ((_x)->extd[XGBE_SFP_EXTD_SFF_8472] && \ ++ !((_x)->extd[XGBE_SFP_EXTD_DIAG] & XGBE_SFP_EXTD_DIAG_ADDR_CHANGE)) ++ ++#define XGBE_SFP_EEPROM_BASE_LEN 256 ++#define XGBE_SFP_EEPROM_DIAG_LEN 256 ++#define XGBE_SFP_EEPROM_MAX (XGBE_SFP_EEPROM_BASE_LEN + \ ++ XGBE_SFP_EEPROM_DIAG_LEN) ++ + #define XGBE_BEL_FUSE_VENDOR "BEL-FUSE " + #define XGBE_BEL_FUSE_PARTNO "1GBT-SFP06 " + +@@ -1301,6 +1311,130 @@ static void xgbe_phy_sfp_detect(struct xgbe_prv_data *pdata) + xgbe_phy_put_comm_ownership(pdata); + } + ++static int xgbe_phy_module_eeprom(struct xgbe_prv_data *pdata, ++ struct ethtool_eeprom *eeprom, u8 *data) ++{ ++ struct xgbe_phy_data *phy_data = pdata->phy_data; ++ u8 eeprom_addr, eeprom_data[XGBE_SFP_EEPROM_MAX]; ++ struct xgbe_sfp_eeprom *sfp_eeprom; ++ unsigned int i, j, rem; ++ int ret; ++ ++ rem = eeprom->len; ++ ++ if (!eeprom->len) { ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ if ((eeprom->offset + eeprom->len) > XGBE_SFP_EEPROM_MAX) { ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ if (phy_data->port_mode != XGBE_PORT_MODE_SFP) { ++ ret = -ENXIO; ++ goto done; ++ } ++ ++ if (!netif_running(pdata->netdev)) { ++ ret = -EIO; ++ goto done; ++ } ++ ++ if (phy_data->sfp_mod_absent) { ++ ret = -EIO; ++ goto done; ++ } ++ ++ ret = xgbe_phy_get_comm_ownership(pdata); ++ if (ret) { ++ ret = -EIO; ++ goto done; ++ } ++ ++ ret = xgbe_phy_sfp_get_mux(pdata); ++ if (ret) { ++ netdev_err(pdata->netdev, "I2C error setting SFP MUX\n"); ++ ret = -EIO; ++ goto put_own; ++ } ++ ++ /* Read the SFP serial ID eeprom */ ++ eeprom_addr = 0; ++ ret = xgbe_phy_i2c_read(pdata, XGBE_SFP_SERIAL_ID_ADDRESS, ++ &eeprom_addr, sizeof(eeprom_addr), ++ eeprom_data, XGBE_SFP_EEPROM_BASE_LEN); ++ if (ret) { ++ netdev_err(pdata->netdev, ++ "I2C error reading SFP EEPROM\n"); ++ ret = -EIO; ++ goto put_mux; ++ } ++ ++ sfp_eeprom = (struct xgbe_sfp_eeprom *)eeprom_data; ++ ++ if (XGBE_SFP_DIAGS_SUPPORTED(sfp_eeprom)) { ++ /* Read the SFP diagnostic eeprom */ ++ eeprom_addr = 0; ++ ret = xgbe_phy_i2c_read(pdata, XGBE_SFP_DIAG_INFO_ADDRESS, ++ &eeprom_addr, sizeof(eeprom_addr), ++ eeprom_data + XGBE_SFP_EEPROM_BASE_LEN, ++ XGBE_SFP_EEPROM_DIAG_LEN); ++ if (ret) { ++ netdev_err(pdata->netdev, ++ "I2C error reading SFP DIAGS\n"); ++ ret = -EIO; ++ goto put_mux; ++ } ++ } ++ ++ for (i = 0, j = eeprom->offset; i < eeprom->len; i++, j++) { ++ if ((j >= XGBE_SFP_EEPROM_BASE_LEN) && ++ !XGBE_SFP_DIAGS_SUPPORTED(sfp_eeprom)) ++ break; ++ ++ data[i] = eeprom_data[j]; ++ rem--; ++ } ++ ++put_mux: ++ xgbe_phy_sfp_put_mux(pdata); ++ ++put_own: ++ xgbe_phy_put_comm_ownership(pdata); ++ ++done: ++ eeprom->len -= rem; ++ ++ return ret; ++} ++ ++static int xgbe_phy_module_info(struct xgbe_prv_data *pdata, ++ struct ethtool_modinfo *modinfo) ++{ ++ struct xgbe_phy_data *phy_data = pdata->phy_data; ++ ++ if (phy_data->port_mode != XGBE_PORT_MODE_SFP) ++ return -ENXIO; ++ ++ if (!netif_running(pdata->netdev)) ++ return -EIO; ++ ++ if (phy_data->sfp_mod_absent) ++ return -EIO; ++ ++ if (XGBE_SFP_DIAGS_SUPPORTED(&phy_data->sfp_eeprom)) { ++ modinfo->type = ETH_MODULE_SFF_8472; ++ modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; ++ } else { ++ modinfo->type = ETH_MODULE_SFF_8079; ++ modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; ++ } ++ ++ return 0; ++} ++ + static void xgbe_phy_phydev_flowctrl(struct xgbe_prv_data *pdata) + { + struct ethtool_link_ksettings *lks = &pdata->phy.lks; +@@ -3293,4 +3427,7 @@ void xgbe_init_function_ptrs_phy_v2(struct xgbe_phy_if *phy_if) + + phy_impl->kr_training_pre = xgbe_phy_kr_training_pre; + phy_impl->kr_training_post = xgbe_phy_kr_training_post; ++ ++ phy_impl->module_info = xgbe_phy_module_info; ++ phy_impl->module_eeprom = xgbe_phy_module_eeprom; + } +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index 214e65d73e6c..4754bd96e7b6 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -835,6 +835,7 @@ struct xgbe_hw_if { + * Optional routines: + * an_pre, an_post + * kr_training_pre, kr_training_post ++ * module_info, module_eeprom + */ + struct xgbe_phy_impl_if { + /* Perform Setup/teardown actions */ +@@ -883,6 +884,12 @@ struct xgbe_phy_impl_if { + /* Pre/Post KR training enablement support */ + void (*kr_training_pre)(struct xgbe_prv_data *); + void (*kr_training_post)(struct xgbe_prv_data *); ++ ++ /* SFP module related info */ ++ int (*module_info)(struct xgbe_prv_data *pdata, ++ struct ethtool_modinfo *modinfo); ++ int (*module_eeprom)(struct xgbe_prv_data *pdata, ++ struct ethtool_eeprom *eeprom, u8 *data); + }; + + struct xgbe_phy_if { +@@ -905,6 +912,12 @@ struct xgbe_phy_if { + /* For single interrupt support */ + irqreturn_t (*an_isr)(struct xgbe_prv_data *); + ++ /* For ethtool PHY support */ ++ int (*module_info)(struct xgbe_prv_data *pdata, ++ struct ethtool_modinfo *modinfo); ++ int (*module_eeprom)(struct xgbe_prv_data *pdata, ++ struct ethtool_eeprom *eeprom, u8 *data); ++ + /* PHY implementation specific services */ + struct xgbe_phy_impl_if phy_impl; + }; +-- +2.16.4 + diff --git a/patches.suse/0043-amd-xgbe-Add-ethtool-show-set-ring-parameter-support.patch b/patches.suse/0043-amd-xgbe-Add-ethtool-show-set-ring-parameter-support.patch new file mode 100644 index 0000000..ae10532 --- /dev/null +++ b/patches.suse/0043-amd-xgbe-Add-ethtool-show-set-ring-parameter-support.patch @@ -0,0 +1,156 @@ +From 541121a664854aa59106bdfc69f3db2d31221ce1 Mon Sep 17 00:00:00 2001 +From: Tom Lendacky +Date: Wed, 23 May 2018 11:38:56 -0500 +Subject: [PATCH 43/59] amd-xgbe: Add ethtool show/set ring parameter support +References: git-fixes +Patch-mainline: v4.18-rc1 +Git-commit: bab748de986d786cbbef31d550bea3bc616304cb + +Add ethtool support to show and set the number of the Rx and Tx ring +descriptors. Changing the ring configuration will result in a device +restart. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 6 +-- + drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 65 ++++++++++++++++++++++++++++ + drivers/net/ethernet/amd/xgbe/xgbe.h | 6 +++ + 3 files changed, 72 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index 5070c87e65aa..ae2ddaa58319 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -1427,10 +1427,8 @@ static void xgbe_stopdev(struct work_struct *work) + netdev_alert(pdata->netdev, "device stopped\n"); + } + +-static void xgbe_restart_dev(struct xgbe_prv_data *pdata) ++void xgbe_restart_dev(struct xgbe_prv_data *pdata) + { +- DBGPR("-->xgbe_restart_dev\n"); +- + /* If not running, "restart" will happen on open */ + if (!netif_running(pdata->netdev)) + return; +@@ -1441,8 +1439,6 @@ static void xgbe_restart_dev(struct xgbe_prv_data *pdata) + xgbe_free_rx_data(pdata); + + xgbe_start(pdata); +- +- DBGPR("<--xgbe_restart_dev\n"); + } + + static void xgbe_restart(struct work_struct *work) +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +index 57394b77b2d3..d12f982d73b4 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +@@ -642,6 +642,69 @@ static int xgbe_get_module_eeprom(struct net_device *netdev, + return pdata->phy_if.module_eeprom(pdata, eeprom, data); + } + ++static void xgbe_get_ringparam(struct net_device *netdev, ++ struct ethtool_ringparam *ringparam) ++{ ++ struct xgbe_prv_data *pdata = netdev_priv(netdev); ++ ++ ringparam->rx_max_pending = XGBE_RX_DESC_CNT_MAX; ++ ringparam->tx_max_pending = XGBE_TX_DESC_CNT_MAX; ++ ringparam->rx_pending = pdata->rx_desc_count; ++ ringparam->tx_pending = pdata->tx_desc_count; ++} ++ ++static int xgbe_set_ringparam(struct net_device *netdev, ++ struct ethtool_ringparam *ringparam) ++{ ++ struct xgbe_prv_data *pdata = netdev_priv(netdev); ++ unsigned int rx, tx; ++ ++ if (ringparam->rx_mini_pending || ringparam->rx_jumbo_pending) { ++ netdev_err(netdev, "unsupported ring parameter\n"); ++ return -EINVAL; ++ } ++ ++ if ((ringparam->rx_pending < XGBE_RX_DESC_CNT_MIN) || ++ (ringparam->rx_pending > XGBE_RX_DESC_CNT_MAX)) { ++ netdev_err(netdev, ++ "rx ring parameter must be between %u and %u\n", ++ XGBE_RX_DESC_CNT_MIN, XGBE_RX_DESC_CNT_MAX); ++ return -EINVAL; ++ } ++ ++ if ((ringparam->tx_pending < XGBE_TX_DESC_CNT_MIN) || ++ (ringparam->tx_pending > XGBE_TX_DESC_CNT_MAX)) { ++ netdev_err(netdev, ++ "tx ring parameter must be between %u and %u\n", ++ XGBE_TX_DESC_CNT_MIN, XGBE_TX_DESC_CNT_MAX); ++ return -EINVAL; ++ } ++ ++ rx = __rounddown_pow_of_two(ringparam->rx_pending); ++ if (rx != ringparam->rx_pending) ++ netdev_notice(netdev, ++ "rx ring parameter rounded to power of two: %u\n", ++ rx); ++ ++ tx = __rounddown_pow_of_two(ringparam->tx_pending); ++ if (tx != ringparam->tx_pending) ++ netdev_notice(netdev, ++ "tx ring parameter rounded to power of two: %u\n", ++ tx); ++ ++ if ((rx == pdata->rx_desc_count) && ++ (tx == pdata->tx_desc_count)) ++ goto out; ++ ++ pdata->rx_desc_count = rx; ++ pdata->tx_desc_count = tx; ++ ++ xgbe_restart_dev(pdata); ++ ++out: ++ return 0; ++} ++ + static const struct ethtool_ops xgbe_ethtool_ops = { + .get_drvinfo = xgbe_get_drvinfo, + .get_msglevel = xgbe_get_msglevel, +@@ -664,6 +727,8 @@ static const struct ethtool_ops xgbe_ethtool_ops = { + .set_link_ksettings = xgbe_set_link_ksettings, + .get_module_info = xgbe_get_module_info, + .get_module_eeprom = xgbe_get_module_eeprom, ++ .get_ringparam = xgbe_get_ringparam, ++ .set_ringparam = xgbe_set_ringparam, + }; + + const struct ethtool_ops *xgbe_get_ethtool_ops(void) +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index 4754bd96e7b6..7b523e32eae3 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -144,6 +144,11 @@ + #define XGBE_TX_DESC_MAX_PROC (XGBE_TX_DESC_CNT >> 1) + #define XGBE_RX_DESC_CNT 512 + ++#define XGBE_TX_DESC_CNT_MIN 64 ++#define XGBE_TX_DESC_CNT_MAX 4096 ++#define XGBE_RX_DESC_CNT_MIN 64 ++#define XGBE_RX_DESC_CNT_MAX 4096 ++ + #define XGBE_TX_MAX_BUF_SIZE (0x3fff & ~(64 - 1)) + + /* Descriptors required for maximum contiguous TSO/GSO packet */ +@@ -1330,6 +1335,7 @@ int xgbe_powerup(struct net_device *, unsigned int); + int xgbe_powerdown(struct net_device *, unsigned int); + void xgbe_init_rx_coalesce(struct xgbe_prv_data *); + void xgbe_init_tx_coalesce(struct xgbe_prv_data *); ++void xgbe_restart_dev(struct xgbe_prv_data *pdata); + + #ifdef CONFIG_DEBUG_FS + void xgbe_debugfs_init(struct xgbe_prv_data *); +-- +2.16.4 + diff --git a/patches.suse/0044-amd-xgbe-Prepare-for-ethtool-set-channel-support.patch b/patches.suse/0044-amd-xgbe-Prepare-for-ethtool-set-channel-support.patch new file mode 100644 index 0000000..f679198 --- /dev/null +++ b/patches.suse/0044-amd-xgbe-Prepare-for-ethtool-set-channel-support.patch @@ -0,0 +1,244 @@ +From 148bd5f2f3c16f4c0f01f9aea5c069e751d2b2ef Mon Sep 17 00:00:00 2001 +From: Tom Lendacky +Date: Wed, 23 May 2018 11:39:04 -0500 +Subject: [PATCH 44/59] amd-xgbe: Prepare for ethtool set-channel support +References: git-fixes +Patch-mainline: v4.18-rc1 +Git-commit: 2244753409f5bc3e2eae4e2ec6f4ced239993f33 + +In order to support being able to dynamically set/change the number of +Rx and Tx channels, update the code to: + - Move alloc and free of device memory into callable functions + - Move setting of the real number of Rx and Tx channels to device startup + - Move mapping of the RSS channels to device startup + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 108 ++++++++++++++++++------------ + drivers/net/ethernet/amd/xgbe/xgbe-main.c | 20 +----- + 2 files changed, 68 insertions(+), 60 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index ae2ddaa58319..85d76336c5e1 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -1313,14 +1313,72 @@ int xgbe_powerup(struct net_device *netdev, unsigned int caller) + return 0; + } + ++static void xgbe_free_memory(struct xgbe_prv_data *pdata) ++{ ++ struct xgbe_desc_if *desc_if = &pdata->desc_if; ++ ++ /* Free the ring descriptors and buffers */ ++ desc_if->free_ring_resources(pdata); ++ ++ /* Free the channel and ring structures */ ++ xgbe_free_channels(pdata); ++} ++ ++static int xgbe_alloc_memory(struct xgbe_prv_data *pdata) ++{ ++ struct xgbe_desc_if *desc_if = &pdata->desc_if; ++ struct net_device *netdev = pdata->netdev; ++ int ret; ++ ++ /* Calculate the Rx buffer size before allocating rings */ ++ pdata->rx_buf_size = xgbe_calc_rx_buf_size(netdev, netdev->mtu); ++ ++ /* Allocate the channel and ring structures */ ++ ret = xgbe_alloc_channels(pdata); ++ if (ret) ++ return ret; ++ ++ /* Allocate the ring descriptors and buffers */ ++ ret = desc_if->alloc_ring_resources(pdata); ++ if (ret) ++ goto err_channels; ++ ++ /* Initialize the service and Tx timers */ ++ xgbe_init_timers(pdata); ++ ++ return 0; ++ ++err_channels: ++ xgbe_free_memory(pdata); ++ ++ return ret; ++} ++ + static int xgbe_start(struct xgbe_prv_data *pdata) + { + struct xgbe_hw_if *hw_if = &pdata->hw_if; + struct xgbe_phy_if *phy_if = &pdata->phy_if; + struct net_device *netdev = pdata->netdev; ++ unsigned int i; + int ret; + +- DBGPR("-->xgbe_start\n"); ++ /* Set the number of queues */ ++ ret = netif_set_real_num_tx_queues(netdev, pdata->tx_ring_count); ++ if (ret) { ++ netdev_err(netdev, "error setting real tx queue count\n"); ++ return ret; ++ } ++ ++ ret = netif_set_real_num_rx_queues(netdev, pdata->rx_ring_count); ++ if (ret) { ++ netdev_err(netdev, "error setting real rx queue count\n"); ++ return ret; ++ } ++ ++ /* Set RSS lookup table data for programming */ ++ for (i = 0; i < XGBE_RSS_MAX_TABLE_SIZE; i++) ++ XGMAC_SET_BITS(pdata->rss_table[i], MAC_RSSDR, DMCH, ++ i % pdata->rx_ring_count); + + ret = hw_if->init(pdata); + if (ret) +@@ -1348,8 +1406,6 @@ static int xgbe_start(struct xgbe_prv_data *pdata) + + clear_bit(XGBE_STOPPED, &pdata->dev_state); + +- DBGPR("<--xgbe_start\n"); +- + return 0; + + err_irqs: +@@ -1824,11 +1880,8 @@ static void xgbe_packet_info(struct xgbe_prv_data *pdata, + static int xgbe_open(struct net_device *netdev) + { + struct xgbe_prv_data *pdata = netdev_priv(netdev); +- struct xgbe_desc_if *desc_if = &pdata->desc_if; + int ret; + +- DBGPR("-->xgbe_open\n"); +- + /* Create the various names based on netdev name */ + snprintf(pdata->an_name, sizeof(pdata->an_name) - 1, "%s-pcs", + netdev_name(netdev)); +@@ -1873,43 +1926,25 @@ static int xgbe_open(struct net_device *netdev) + goto err_sysclk; + } + +- /* Calculate the Rx buffer size before allocating rings */ +- ret = xgbe_calc_rx_buf_size(netdev, netdev->mtu); +- if (ret < 0) +- goto err_ptpclk; +- pdata->rx_buf_size = ret; +- +- /* Allocate the channel and ring structures */ +- ret = xgbe_alloc_channels(pdata); +- if (ret) +- goto err_ptpclk; +- +- /* Allocate the ring descriptors and buffers */ +- ret = desc_if->alloc_ring_resources(pdata); +- if (ret) +- goto err_channels; +- + INIT_WORK(&pdata->service_work, xgbe_service); + INIT_WORK(&pdata->restart_work, xgbe_restart); + INIT_WORK(&pdata->stopdev_work, xgbe_stopdev); + INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp); +- xgbe_init_timers(pdata); ++ ++ ret = xgbe_alloc_memory(pdata); ++ if (ret) ++ goto err_ptpclk; + + ret = xgbe_start(pdata); + if (ret) +- goto err_rings; ++ goto err_mem; + + clear_bit(XGBE_DOWN, &pdata->dev_state); + +- DBGPR("<--xgbe_open\n"); +- + return 0; + +-err_rings: +- desc_if->free_ring_resources(pdata); +- +-err_channels: +- xgbe_free_channels(pdata); ++err_mem: ++ xgbe_free_memory(pdata); + + err_ptpclk: + clk_disable_unprepare(pdata->ptpclk); +@@ -1929,18 +1964,11 @@ static int xgbe_open(struct net_device *netdev) + static int xgbe_close(struct net_device *netdev) + { + struct xgbe_prv_data *pdata = netdev_priv(netdev); +- struct xgbe_desc_if *desc_if = &pdata->desc_if; +- +- DBGPR("-->xgbe_close\n"); + + /* Stop the device */ + xgbe_stop(pdata); + +- /* Free the ring descriptors and buffers */ +- desc_if->free_ring_resources(pdata); +- +- /* Free the channel and ring structures */ +- xgbe_free_channels(pdata); ++ xgbe_free_memory(pdata); + + /* Disable the clocks */ + clk_disable_unprepare(pdata->ptpclk); +@@ -1954,8 +1982,6 @@ static int xgbe_close(struct net_device *netdev) + + set_bit(XGBE_DOWN, &pdata->dev_state); + +- DBGPR("<--xgbe_close\n"); +- + return 0; + } + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +index 441d0973957b..b41f23679a08 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +@@ -265,7 +265,6 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata) + { + struct net_device *netdev = pdata->netdev; + struct device *dev = pdata->dev; +- unsigned int i; + int ret; + + netdev->irq = pdata->dev_irq; +@@ -324,26 +323,9 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata) + pdata->tx_ring_count, pdata->rx_ring_count); + } + +- /* Set the number of queues */ +- ret = netif_set_real_num_tx_queues(netdev, pdata->tx_ring_count); +- if (ret) { +- dev_err(dev, "error setting real tx queue count\n"); +- return ret; +- } +- +- ret = netif_set_real_num_rx_queues(netdev, pdata->rx_ring_count); +- if (ret) { +- dev_err(dev, "error setting real rx queue count\n"); +- return ret; +- } +- +- /* Initialize RSS hash key and lookup table */ ++ /* Initialize RSS hash key */ + netdev_rss_key_fill(pdata->rss_key, sizeof(pdata->rss_key)); + +- for (i = 0; i < XGBE_RSS_MAX_TABLE_SIZE; i++) +- XGMAC_SET_BITS(pdata->rss_table[i], MAC_RSSDR, DMCH, +- i % pdata->rx_ring_count); +- + XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, IP2TE, 1); + XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, TCP4TE, 1); + XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1); +-- +2.16.4 + diff --git a/patches.suse/0045-amd-xgbe-Add-ethtool-show-set-channels-support.patch b/patches.suse/0045-amd-xgbe-Add-ethtool-show-set-channels-support.patch new file mode 100644 index 0000000..4c6938d --- /dev/null +++ b/patches.suse/0045-amd-xgbe-Add-ethtool-show-set-channels-support.patch @@ -0,0 +1,240 @@ +From b0ac8f5575827abdbb7753c637ad698de24b35b5 Mon Sep 17 00:00:00 2001 +From: Tom Lendacky +Date: Wed, 23 May 2018 11:39:13 -0500 +Subject: [PATCH 45/59] amd-xgbe: Add ethtool show/set channels support +References: git-fixes +Patch-mainline: v4.18-rc1 +Git-commit: 01b5277fc9984d9fb9156afa0b1be70b3b475825 + +Add ethtool support to show and set the device channel configuration. +Changing the channel configuration will result in a device restart. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 25 +++++ + drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 134 +++++++++++++++++++++++++++ + drivers/net/ethernet/amd/xgbe/xgbe.h | 4 + + 3 files changed, 163 insertions(+) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index 85d76336c5e1..ba13c6746b9c 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -1330,6 +1330,17 @@ static int xgbe_alloc_memory(struct xgbe_prv_data *pdata) + struct net_device *netdev = pdata->netdev; + int ret; + ++ if (pdata->new_tx_ring_count) { ++ pdata->tx_ring_count = pdata->new_tx_ring_count; ++ pdata->tx_q_count = pdata->tx_ring_count; ++ pdata->new_tx_ring_count = 0; ++ } ++ ++ if (pdata->new_rx_ring_count) { ++ pdata->rx_ring_count = pdata->new_rx_ring_count; ++ pdata->new_rx_ring_count = 0; ++ } ++ + /* Calculate the Rx buffer size before allocating rings */ + pdata->rx_buf_size = xgbe_calc_rx_buf_size(netdev, netdev->mtu); + +@@ -1483,6 +1494,20 @@ static void xgbe_stopdev(struct work_struct *work) + netdev_alert(pdata->netdev, "device stopped\n"); + } + ++void xgbe_full_restart_dev(struct xgbe_prv_data *pdata) ++{ ++ /* If not running, "restart" will happen on open */ ++ if (!netif_running(pdata->netdev)) ++ return; ++ ++ xgbe_stop(pdata); ++ ++ xgbe_free_memory(pdata); ++ xgbe_alloc_memory(pdata); ++ ++ xgbe_start(pdata); ++} ++ + void xgbe_restart_dev(struct xgbe_prv_data *pdata) + { + /* If not running, "restart" will happen on open */ +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +index d12f982d73b4..a880f10e3e70 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +@@ -705,6 +705,138 @@ static int xgbe_set_ringparam(struct net_device *netdev, + return 0; + } + ++static void xgbe_get_channels(struct net_device *netdev, ++ struct ethtool_channels *channels) ++{ ++ struct xgbe_prv_data *pdata = netdev_priv(netdev); ++ unsigned int rx, tx, combined; ++ ++ /* Calculate maximums allowed: ++ * - Take into account the number of available IRQs ++ * - Do not take into account the number of online CPUs so that ++ * the user can over-subscribe if desired ++ * - Tx is additionally limited by the number of hardware queues ++ */ ++ rx = min(pdata->hw_feat.rx_ch_cnt, pdata->rx_max_channel_count); ++ rx = min(rx, pdata->channel_irq_count); ++ tx = min(pdata->hw_feat.tx_ch_cnt, pdata->tx_max_channel_count); ++ tx = min(tx, pdata->channel_irq_count); ++ tx = min(tx, pdata->tx_max_q_count); ++ ++ combined = min(rx, tx); ++ ++ channels->max_combined = combined; ++ channels->max_rx = rx ? rx - 1 : 0; ++ channels->max_tx = tx ? tx - 1 : 0; ++ ++ /* Get current settings based on device state */ ++ rx = pdata->new_rx_ring_count ? : pdata->rx_ring_count; ++ tx = pdata->new_tx_ring_count ? : pdata->tx_ring_count; ++ ++ combined = min(rx, tx); ++ rx -= combined; ++ tx -= combined; ++ ++ channels->combined_count = combined; ++ channels->rx_count = rx; ++ channels->tx_count = tx; ++} ++ ++static void xgbe_print_set_channels_input(struct net_device *netdev, ++ struct ethtool_channels *channels) ++{ ++ netdev_err(netdev, "channel inputs: combined=%u, rx-only=%u, tx-only=%u\n", ++ channels->combined_count, channels->rx_count, ++ channels->tx_count); ++} ++ ++static int xgbe_set_channels(struct net_device *netdev, ++ struct ethtool_channels *channels) ++{ ++ struct xgbe_prv_data *pdata = netdev_priv(netdev); ++ unsigned int rx, rx_curr, tx, tx_curr, combined; ++ ++ /* Calculate maximums allowed: ++ * - Take into account the number of available IRQs ++ * - Do not take into account the number of online CPUs so that ++ * the user can over-subscribe if desired ++ * - Tx is additionally limited by the number of hardware queues ++ */ ++ rx = min(pdata->hw_feat.rx_ch_cnt, pdata->rx_max_channel_count); ++ rx = min(rx, pdata->channel_irq_count); ++ tx = min(pdata->hw_feat.tx_ch_cnt, pdata->tx_max_channel_count); ++ tx = min(tx, pdata->tx_max_q_count); ++ tx = min(tx, pdata->channel_irq_count); ++ ++ combined = min(rx, tx); ++ ++ /* Should not be setting other count */ ++ if (channels->other_count) { ++ netdev_err(netdev, ++ "other channel count must be zero\n"); ++ return -EINVAL; ++ } ++ ++ /* Require at least one Combined (Rx and Tx) channel */ ++ if (!channels->combined_count) { ++ netdev_err(netdev, ++ "at least one combined Rx/Tx channel is required\n"); ++ xgbe_print_set_channels_input(netdev, channels); ++ return -EINVAL; ++ } ++ ++ /* Check combined channels */ ++ if (channels->combined_count > combined) { ++ netdev_err(netdev, ++ "combined channel count cannot exceed %u\n", ++ combined); ++ xgbe_print_set_channels_input(netdev, channels); ++ return -EINVAL; ++ } ++ ++ /* Can have some Rx-only or Tx-only channels, but not both */ ++ if (channels->rx_count && channels->tx_count) { ++ netdev_err(netdev, ++ "cannot specify both Rx-only and Tx-only channels\n"); ++ xgbe_print_set_channels_input(netdev, channels); ++ return -EINVAL; ++ } ++ ++ /* Check that we don't exceed the maximum number of channels */ ++ if ((channels->combined_count + channels->rx_count) > rx) { ++ netdev_err(netdev, ++ "total Rx channels (%u) requested exceeds maximum available (%u)\n", ++ channels->combined_count + channels->rx_count, rx); ++ xgbe_print_set_channels_input(netdev, channels); ++ return -EINVAL; ++ } ++ ++ if ((channels->combined_count + channels->tx_count) > tx) { ++ netdev_err(netdev, ++ "total Tx channels (%u) requested exceeds maximum available (%u)\n", ++ channels->combined_count + channels->tx_count, tx); ++ xgbe_print_set_channels_input(netdev, channels); ++ return -EINVAL; ++ } ++ ++ rx = channels->combined_count + channels->rx_count; ++ tx = channels->combined_count + channels->tx_count; ++ ++ rx_curr = pdata->new_rx_ring_count ? : pdata->rx_ring_count; ++ tx_curr = pdata->new_tx_ring_count ? : pdata->tx_ring_count; ++ ++ if ((rx == rx_curr) && (tx == tx_curr)) ++ goto out; ++ ++ pdata->new_rx_ring_count = rx; ++ pdata->new_tx_ring_count = tx; ++ ++ xgbe_full_restart_dev(pdata); ++ ++out: ++ return 0; ++} ++ + static const struct ethtool_ops xgbe_ethtool_ops = { + .get_drvinfo = xgbe_get_drvinfo, + .get_msglevel = xgbe_get_msglevel, +@@ -729,6 +861,8 @@ static const struct ethtool_ops xgbe_ethtool_ops = { + .get_module_eeprom = xgbe_get_module_eeprom, + .get_ringparam = xgbe_get_ringparam, + .set_ringparam = xgbe_set_ringparam, ++ .get_channels = xgbe_get_channels, ++ .set_channels = xgbe_set_channels, + }; + + const struct ethtool_ops *xgbe_get_ethtool_ops(void) +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index 7b523e32eae3..fa58e82f0b56 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -1122,6 +1122,9 @@ struct xgbe_prv_data { + unsigned int rx_ring_count; + unsigned int rx_desc_count; + ++ unsigned int new_tx_ring_count; ++ unsigned int new_rx_ring_count; ++ + unsigned int tx_max_q_count; + unsigned int rx_max_q_count; + unsigned int tx_q_count; +@@ -1336,6 +1339,7 @@ int xgbe_powerdown(struct net_device *, unsigned int); + void xgbe_init_rx_coalesce(struct xgbe_prv_data *); + void xgbe_init_tx_coalesce(struct xgbe_prv_data *); + void xgbe_restart_dev(struct xgbe_prv_data *pdata); ++void xgbe_full_restart_dev(struct xgbe_prv_data *pdata); + + #ifdef CONFIG_DEBUG_FS + void xgbe_debugfs_init(struct xgbe_prv_data *); +-- +2.16.4 + diff --git a/patches.suse/0046-amd-xgbe-Advertise-FEC-support-with-the-KR-re-driver.patch b/patches.suse/0046-amd-xgbe-Advertise-FEC-support-with-the-KR-re-driver.patch new file mode 100644 index 0000000..62e6058 --- /dev/null +++ b/patches.suse/0046-amd-xgbe-Advertise-FEC-support-with-the-KR-re-driver.patch @@ -0,0 +1,36 @@ +From c77038bea11eab307b05e2eef5701156fbcb81f3 Mon Sep 17 00:00:00 2001 +From: Tom Lendacky +Date: Wed, 23 May 2018 11:39:31 -0500 +Subject: [PATCH 46/59] amd-xgbe: Advertise FEC support with the KR re-driver +References: git-fixes +Patch-mainline: v4.18-rc1 +Git-commit: 418746298e586c88edf3a7c340c8d19a0c13df77 + +When a KR re-driver is present, indicate the FEC support is available +during auto-negotiation. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index 61b279dc2acf..c58dd3f89a4d 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -1720,6 +1720,10 @@ static void xgbe_phy_an_advertising(struct xgbe_prv_data *pdata, + XGBE_CLR_ADV(dlks, 1000baseKX_Full); + XGBE_CLR_ADV(dlks, 10000baseKR_Full); + ++ /* Advertise FEC support is present */ ++ if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) ++ XGBE_SET_ADV(dlks, 10000baseR_FEC); ++ + switch (phy_data->port_mode) { + case XGBE_PORT_MODE_BACKPLANE: + XGBE_SET_ADV(dlks, 10000baseKR_Full); +-- +2.16.4 + diff --git a/patches.suse/0047-amd-xgbe-Update-the-BelFuse-quirk-to-support-SGMII.patch b/patches.suse/0047-amd-xgbe-Update-the-BelFuse-quirk-to-support-SGMII.patch new file mode 100644 index 0000000..ef98017 --- /dev/null +++ b/patches.suse/0047-amd-xgbe-Update-the-BelFuse-quirk-to-support-SGMII.patch @@ -0,0 +1,165 @@ +From 6d10876971d63694f5d9ffdd71265b1ef2921137 Mon Sep 17 00:00:00 2001 +From: Tom Lendacky +Date: Wed, 23 May 2018 11:39:39 -0500 +Subject: [PATCH 47/59] amd-xgbe: Update the BelFuse quirk to support SGMII +References: git-fixes +Patch-mainline: v4.18-rc1 +Git-commit: e722ec82374b7a0c0cfa954e4f780221139c5f93 + +Instead of using a quirk to make the BelFuse 1GBT-SFP06 part look like +a 1000baseX part, program the SFP PHY to support SGMII and 10/100/1000 +baseT. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 109 +++++++++++++++++++--------- + 1 file changed, 75 insertions(+), 34 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index c58dd3f89a4d..a3404d7f5823 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -860,6 +860,9 @@ static bool xgbe_phy_finisar_phy_quirks(struct xgbe_prv_data *pdata) + struct xgbe_phy_data *phy_data = pdata->phy_data; + unsigned int phy_id = phy_data->phydev->phy_id; + ++ if (phy_data->port_mode != XGBE_PORT_MODE_SFP) ++ return false; ++ + if ((phy_id & 0xfffffff0) != 0x01ff0cc0) + return false; + +@@ -885,8 +888,80 @@ static bool xgbe_phy_finisar_phy_quirks(struct xgbe_prv_data *pdata) + return true; + } + ++static bool xgbe_phy_belfuse_phy_quirks(struct xgbe_prv_data *pdata) ++{ ++ struct xgbe_phy_data *phy_data = pdata->phy_data; ++ struct xgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom; ++ unsigned int phy_id = phy_data->phydev->phy_id; ++ int reg; ++ ++ if (phy_data->port_mode != XGBE_PORT_MODE_SFP) ++ return false; ++ ++ if (memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME], ++ XGBE_BEL_FUSE_VENDOR, XGBE_SFP_BASE_VENDOR_NAME_LEN)) ++ return false; ++ ++ if (memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_PN], ++ XGBE_BEL_FUSE_PARTNO, XGBE_SFP_BASE_VENDOR_PN_LEN)) ++ return false; ++ ++ if ((phy_id & 0xfffffff0) != 0x03625d10) ++ return false; ++ ++ /* Disable RGMII mode */ ++ phy_write(phy_data->phydev, 0x18, 0x7007); ++ reg = phy_read(phy_data->phydev, 0x18); ++ phy_write(phy_data->phydev, 0x18, reg & ~0x0080); ++ ++ /* Enable fiber register bank */ ++ phy_write(phy_data->phydev, 0x1c, 0x7c00); ++ reg = phy_read(phy_data->phydev, 0x1c); ++ reg &= 0x03ff; ++ reg &= ~0x0001; ++ phy_write(phy_data->phydev, 0x1c, 0x8000 | 0x7c00 | reg | 0x0001); ++ ++ /* Power down SerDes */ ++ reg = phy_read(phy_data->phydev, 0x00); ++ phy_write(phy_data->phydev, 0x00, reg | 0x00800); ++ ++ /* Configure SGMII-to-Copper mode */ ++ phy_write(phy_data->phydev, 0x1c, 0x7c00); ++ reg = phy_read(phy_data->phydev, 0x1c); ++ reg &= 0x03ff; ++ reg &= ~0x0006; ++ phy_write(phy_data->phydev, 0x1c, 0x8000 | 0x7c00 | reg | 0x0004); ++ ++ /* Power up SerDes */ ++ reg = phy_read(phy_data->phydev, 0x00); ++ phy_write(phy_data->phydev, 0x00, reg & ~0x00800); ++ ++ /* Enable copper register bank */ ++ phy_write(phy_data->phydev, 0x1c, 0x7c00); ++ reg = phy_read(phy_data->phydev, 0x1c); ++ reg &= 0x03ff; ++ reg &= ~0x0001; ++ phy_write(phy_data->phydev, 0x1c, 0x8000 | 0x7c00 | reg); ++ ++ /* Power up SerDes */ ++ reg = phy_read(phy_data->phydev, 0x00); ++ phy_write(phy_data->phydev, 0x00, reg & ~0x00800); ++ ++ phy_data->phydev->supported = PHY_GBIT_FEATURES; ++ phy_data->phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; ++ phy_data->phydev->advertising = phy_data->phydev->supported; ++ ++ netif_dbg(pdata, drv, pdata->netdev, ++ "BelFuse PHY quirk in place\n"); ++ ++ return true; ++} ++ + static void xgbe_phy_external_phy_quirks(struct xgbe_prv_data *pdata) + { ++ if (xgbe_phy_belfuse_phy_quirks(pdata)) ++ return; ++ + if (xgbe_phy_finisar_phy_quirks(pdata)) + return; + } +@@ -1027,37 +1102,6 @@ static bool xgbe_phy_check_sfp_mod_absent(struct xgbe_phy_data *phy_data) + return false; + } + +-static bool xgbe_phy_belfuse_parse_quirks(struct xgbe_prv_data *pdata) +-{ +- struct xgbe_phy_data *phy_data = pdata->phy_data; +- struct xgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom; +- +- if (memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME], +- XGBE_BEL_FUSE_VENDOR, XGBE_SFP_BASE_VENDOR_NAME_LEN)) +- return false; +- +- if (!memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_PN], +- XGBE_BEL_FUSE_PARTNO, XGBE_SFP_BASE_VENDOR_PN_LEN)) { +- phy_data->sfp_base = XGBE_SFP_BASE_1000_SX; +- phy_data->sfp_cable = XGBE_SFP_CABLE_ACTIVE; +- phy_data->sfp_speed = XGBE_SFP_SPEED_1000; +- if (phy_data->sfp_changed) +- netif_dbg(pdata, drv, pdata->netdev, +- "Bel-Fuse SFP quirk in place\n"); +- return true; +- } +- +- return false; +-} +- +-static bool xgbe_phy_sfp_parse_quirks(struct xgbe_prv_data *pdata) +-{ +- if (xgbe_phy_belfuse_parse_quirks(pdata)) +- return true; +- +- return false; +-} +- + static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata) + { + struct xgbe_phy_data *phy_data = pdata->phy_data; +@@ -1076,9 +1120,6 @@ static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata) + phy_data->sfp_tx_fault = xgbe_phy_check_sfp_tx_fault(phy_data); + phy_data->sfp_rx_los = xgbe_phy_check_sfp_rx_los(phy_data); + +- if (xgbe_phy_sfp_parse_quirks(pdata)) +- return; +- + /* Assume ACTIVE cable unless told it is PASSIVE */ + if (sfp_base[XGBE_SFP_BASE_CABLE] & XGBE_SFP_BASE_CABLE_PASSIVE) { + phy_data->sfp_cable = XGBE_SFP_CABLE_PASSIVE; +-- +2.16.4 + diff --git a/patches.suse/0048-amd-xgbe-Improve-SFP-100Mbps-auto-negotiation.patch b/patches.suse/0048-amd-xgbe-Improve-SFP-100Mbps-auto-negotiation.patch new file mode 100644 index 0000000..49a88a7 --- /dev/null +++ b/patches.suse/0048-amd-xgbe-Improve-SFP-100Mbps-auto-negotiation.patch @@ -0,0 +1,204 @@ +From 5cc146e9c8b0fa9eb5f5326d724da4d39a156497 Mon Sep 17 00:00:00 2001 +From: Tom Lendacky +Date: Wed, 23 May 2018 11:39:47 -0500 +Subject: [PATCH 48/59] amd-xgbe: Improve SFP 100Mbps auto-negotiation +References: git-fixes +Patch-mainline: v4.18-rc1 +Git-commit: 76cce0af85a0d5d8abef8b60eece5798ea7eea5a + +After changing speed to 100Mbps as a result of auto-negotiation (AN), +some 10/100/1000Mbps SFPs indicate a successful link (no faults or loss +of signal), but cannot successfully transmit or receive data. These +SFPs required an extra auto-negotiation (AN) after the speed change in +order to operate properly. Add a quirk for these SFPs so that if the +outcome of the AN actually results in changing to a new speed, re-initiate +AN at that new speed. + +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 77 ++++++++++++++++------------- + drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 6 +++ + drivers/net/ethernet/amd/xgbe/xgbe.h | 1 + + 3 files changed, 50 insertions(+), 34 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +index eba757e934e5..8a3a60bb2688 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +@@ -331,13 +331,15 @@ static void xgbe_switch_mode(struct xgbe_prv_data *pdata) + xgbe_change_mode(pdata, pdata->phy_if.phy_impl.switch_mode(pdata)); + } + +-static void xgbe_set_mode(struct xgbe_prv_data *pdata, ++static bool xgbe_set_mode(struct xgbe_prv_data *pdata, + enum xgbe_mode mode) + { + if (mode == xgbe_cur_mode(pdata)) +- return; ++ return false; + + xgbe_change_mode(pdata, mode); ++ ++ return true; + } + + static bool xgbe_use_mode(struct xgbe_prv_data *pdata, +@@ -1178,21 +1180,23 @@ static int xgbe_phy_config_fixed(struct xgbe_prv_data *pdata) + return 0; + } + +-static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) ++static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata, bool set_mode) + { + int ret; + ++ mutex_lock(&pdata->an_mutex); ++ + set_bit(XGBE_LINK_INIT, &pdata->dev_state); + pdata->link_check = jiffies; + + ret = pdata->phy_if.phy_impl.an_config(pdata); + if (ret) +- return ret; ++ goto out; + + if (pdata->phy.autoneg != AUTONEG_ENABLE) { + ret = xgbe_phy_config_fixed(pdata); + if (ret || !pdata->kr_redrv) +- return ret; ++ goto out; + + netif_dbg(pdata, link, pdata->netdev, "AN redriver support\n"); + } else { +@@ -1202,24 +1206,27 @@ static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) + /* Disable auto-negotiation interrupt */ + disable_irq(pdata->an_irq); + +- /* Start auto-negotiation in a supported mode */ +- if (xgbe_use_mode(pdata, XGBE_MODE_KR)) { +- xgbe_set_mode(pdata, XGBE_MODE_KR); +- } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) { +- xgbe_set_mode(pdata, XGBE_MODE_KX_2500); +- } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) { +- xgbe_set_mode(pdata, XGBE_MODE_KX_1000); +- } else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) { +- xgbe_set_mode(pdata, XGBE_MODE_SFI); +- } else if (xgbe_use_mode(pdata, XGBE_MODE_X)) { +- xgbe_set_mode(pdata, XGBE_MODE_X); +- } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) { +- xgbe_set_mode(pdata, XGBE_MODE_SGMII_1000); +- } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) { +- xgbe_set_mode(pdata, XGBE_MODE_SGMII_100); +- } else { +- enable_irq(pdata->an_irq); +- return -EINVAL; ++ if (set_mode) { ++ /* Start auto-negotiation in a supported mode */ ++ if (xgbe_use_mode(pdata, XGBE_MODE_KR)) { ++ xgbe_set_mode(pdata, XGBE_MODE_KR); ++ } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) { ++ xgbe_set_mode(pdata, XGBE_MODE_KX_2500); ++ } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) { ++ xgbe_set_mode(pdata, XGBE_MODE_KX_1000); ++ } else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) { ++ xgbe_set_mode(pdata, XGBE_MODE_SFI); ++ } else if (xgbe_use_mode(pdata, XGBE_MODE_X)) { ++ xgbe_set_mode(pdata, XGBE_MODE_X); ++ } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) { ++ xgbe_set_mode(pdata, XGBE_MODE_SGMII_1000); ++ } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) { ++ xgbe_set_mode(pdata, XGBE_MODE_SGMII_100); ++ } else { ++ enable_irq(pdata->an_irq); ++ ret = -EINVAL; ++ goto out; ++ } + } + + /* Disable and stop any in progress auto-negotiation */ +@@ -1239,16 +1246,7 @@ static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) + xgbe_an_init(pdata); + xgbe_an_restart(pdata); + +- return 0; +-} +- +-static int xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) +-{ +- int ret; +- +- mutex_lock(&pdata->an_mutex); +- +- ret = __xgbe_phy_config_aneg(pdata); ++out: + if (ret) + set_bit(XGBE_LINK_ERR, &pdata->dev_state); + else +@@ -1259,6 +1257,16 @@ static int xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) + return ret; + } + ++static int xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) ++{ ++ return __xgbe_phy_config_aneg(pdata, true); ++} ++ ++static int xgbe_phy_reconfig_aneg(struct xgbe_prv_data *pdata) ++{ ++ return __xgbe_phy_config_aneg(pdata, false); ++} ++ + static bool xgbe_phy_aneg_done(struct xgbe_prv_data *pdata) + { + return (pdata->an_result == XGBE_AN_COMPLETE); +@@ -1315,7 +1323,8 @@ static void xgbe_phy_status_result(struct xgbe_prv_data *pdata) + + pdata->phy.duplex = DUPLEX_FULL; + +- xgbe_set_mode(pdata, mode); ++ if (xgbe_set_mode(pdata, mode) && pdata->an_again) ++ xgbe_phy_reconfig_aneg(pdata); + } + + static void xgbe_phy_status(struct xgbe_prv_data *pdata) +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index a3404d7f5823..7048fb08faaf 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -902,6 +902,9 @@ static bool xgbe_phy_belfuse_phy_quirks(struct xgbe_prv_data *pdata) + XGBE_BEL_FUSE_VENDOR, XGBE_SFP_BASE_VENDOR_NAME_LEN)) + return false; + ++ /* For Bel-Fuse, use the extra AN flag */ ++ pdata->an_again = 1; ++ + if (memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_PN], + XGBE_BEL_FUSE_PARTNO, XGBE_SFP_BASE_VENDOR_PN_LEN)) + return false; +@@ -978,6 +981,9 @@ static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata) + if (phy_data->phydev) + return 0; + ++ /* Clear the extra AN flag */ ++ pdata->an_again = 0; ++ + /* Check for the use of an external PHY */ + if (phy_data->phydev_mode == XGBE_MDIO_MODE_NONE) + return 0; +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index fa58e82f0b56..d3c476531518 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -1261,6 +1261,7 @@ struct xgbe_prv_data { + enum xgbe_rx kr_state; + enum xgbe_rx kx_state; + struct work_struct an_work; ++ unsigned int an_again; + unsigned int an_supported; + unsigned int parallel_detect; + unsigned int fec_ability; +-- +2.16.4 + diff --git a/patches.suse/0049-amd-xgbe-use-dma_mapping_error-to-check-map-errors.patch b/patches.suse/0049-amd-xgbe-use-dma_mapping_error-to-check-map-errors.patch new file mode 100644 index 0000000..7ed78f1 --- /dev/null +++ b/patches.suse/0049-amd-xgbe-use-dma_mapping_error-to-check-map-errors.patch @@ -0,0 +1,48 @@ +From a97898080f88e86ec4359a2f407995ec6547f707 Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Thu, 26 Jul 2018 09:51:27 +0800 +Subject: [PATCH 49/59] amd-xgbe: use dma_mapping_error to check map errors +References: git-fixes +Patch-mainline: v4.19-rc1 +Git-commit: b24dbfe9ce03d9f83306616f22fb0e04e8960abe + +The dma_mapping_error() returns true or false, but we want +to return -ENOMEM if there was an error. + +Fixes: 174fd2597b0b ("amd-xgbe: Implement split header receive support") +Signed-off-by: YueHaibing +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c +index cc1e4f820e64..533094233659 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c +@@ -289,7 +289,7 @@ static int xgbe_alloc_pages(struct xgbe_prv_data *pdata, + struct page *pages = NULL; + dma_addr_t pages_dma; + gfp_t gfp; +- int order, ret; ++ int order; + + again: + order = alloc_order; +@@ -316,10 +316,9 @@ static int xgbe_alloc_pages(struct xgbe_prv_data *pdata, + /* Map the pages */ + pages_dma = dma_map_page(pdata->dev, pages, 0, + PAGE_SIZE << order, DMA_FROM_DEVICE); +- ret = dma_mapping_error(pdata->dev, pages_dma); +- if (ret) { ++ if (dma_mapping_error(pdata->dev, pages_dma)) { + put_page(pages); +- return ret; ++ return -ENOMEM; + } + + pa->pages = pages; +-- +2.16.4 + diff --git a/patches.suse/0050-net-amd-fix-return-type-of-ndo_start_xmit-function.patch b/patches.suse/0050-net-amd-fix-return-type-of-ndo_start_xmit-function.patch new file mode 100644 index 0000000..96515d1 --- /dev/null +++ b/patches.suse/0050-net-amd-fix-return-type-of-ndo_start_xmit-function.patch @@ -0,0 +1,139 @@ +From 281908c267cb8da163763f629ae9cf43840240af Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Wed, 19 Sep 2018 18:50:17 +0800 +Subject: [PATCH 50/59] net: amd: fix return type of ndo_start_xmit function +References: git-fixes +Patch-mainline: v4.19-rc1 +Git-commit: fe72352e37ae8478f4c97975a9831f0c50f22e73 + +The method ndo_start_xmit() is defined as returning an 'netdev_tx_t', +which is a typedef for an enum type, so make sure the implementation in +this driver has returns 'netdev_tx_t' value, and change the function +return type to netdev_tx_t. + +Found by coccinelle. + +Signed-off-by: YueHaibing +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/am79c961a.c | 2 +- + drivers/net/ethernet/amd/atarilance.c | 6 ++++-- + drivers/net/ethernet/amd/declance.c | 2 +- + drivers/net/ethernet/amd/sun3lance.c | 6 ++++-- + drivers/net/ethernet/amd/sunlance.c | 2 +- + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 4 ++-- + 6 files changed, 13 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/amd/am79c961a.c b/drivers/net/ethernet/amd/am79c961a.c +index b11e910850f7..78d1e5385a3e 100644 +--- a/drivers/net/ethernet/amd/am79c961a.c ++++ b/drivers/net/ethernet/amd/am79c961a.c +@@ -440,7 +440,7 @@ static void am79c961_timeout(struct net_device *dev) + /* + * Transmit a packet + */ +-static int ++static netdev_tx_t + am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev) + { + struct dev_priv *priv = netdev_priv(dev); +diff --git a/drivers/net/ethernet/amd/atarilance.c b/drivers/net/ethernet/amd/atarilance.c +index c5b81268c284..d3d44e07afbc 100644 +--- a/drivers/net/ethernet/amd/atarilance.c ++++ b/drivers/net/ethernet/amd/atarilance.c +@@ -339,7 +339,8 @@ static unsigned long lance_probe1( struct net_device *dev, struct lance_addr + *init_rec ); + static int lance_open( struct net_device *dev ); + static void lance_init_ring( struct net_device *dev ); +-static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ); ++static netdev_tx_t lance_start_xmit(struct sk_buff *skb, ++ struct net_device *dev); + static irqreturn_t lance_interrupt( int irq, void *dev_id ); + static int lance_rx( struct net_device *dev ); + static int lance_close( struct net_device *dev ); +@@ -769,7 +770,8 @@ static void lance_tx_timeout (struct net_device *dev) + + /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ + +-static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) ++static netdev_tx_t ++lance_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct lance_private *lp = netdev_priv(dev); + struct lance_ioreg *IO = lp->iobase; +diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c +index c7cde58feaf7..290d070b293b 100644 +--- a/drivers/net/ethernet/amd/declance.c ++++ b/drivers/net/ethernet/amd/declance.c +@@ -893,7 +893,7 @@ static void lance_tx_timeout(struct net_device *dev) + netif_wake_queue(dev); + } + +-static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t lance_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct lance_private *lp = netdev_priv(dev); + volatile struct lance_regs *ll = lp->ll; +diff --git a/drivers/net/ethernet/amd/sun3lance.c b/drivers/net/ethernet/amd/sun3lance.c +index 77b1db267730..da7e3d4f4166 100644 +--- a/drivers/net/ethernet/amd/sun3lance.c ++++ b/drivers/net/ethernet/amd/sun3lance.c +@@ -236,7 +236,8 @@ struct lance_private { + static int lance_probe( struct net_device *dev); + static int lance_open( struct net_device *dev ); + static void lance_init_ring( struct net_device *dev ); +-static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ); ++static netdev_tx_t lance_start_xmit(struct sk_buff *skb, ++ struct net_device *dev); + static irqreturn_t lance_interrupt( int irq, void *dev_id); + static int lance_rx( struct net_device *dev ); + static int lance_close( struct net_device *dev ); +@@ -511,7 +512,8 @@ static void lance_init_ring( struct net_device *dev ) + } + + +-static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) ++static netdev_tx_t ++lance_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct lance_private *lp = netdev_priv(dev); + int entry, len; +diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c +index 291ca5187f12..7d1c07f33504 100644 +--- a/drivers/net/ethernet/amd/sunlance.c ++++ b/drivers/net/ethernet/amd/sunlance.c +@@ -1106,7 +1106,7 @@ static void lance_tx_timeout(struct net_device *dev) + netif_wake_queue(dev); + } + +-static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t lance_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct lance_private *lp = netdev_priv(dev); + int entry, skblen, len; +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index ba13c6746b9c..b73b4615c0f5 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -2010,7 +2010,7 @@ static int xgbe_close(struct net_device *netdev) + return 0; + } + +-static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev) ++static netdev_tx_t xgbe_xmit(struct sk_buff *skb, struct net_device *netdev) + { + struct xgbe_prv_data *pdata = netdev_priv(netdev); + struct xgbe_hw_if *hw_if = &pdata->hw_if; +@@ -2019,7 +2019,7 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev) + struct xgbe_ring *ring; + struct xgbe_packet_data *packet; + struct netdev_queue *txq; +- int ret; ++ netdev_tx_t ret; + + DBGPR("-->xgbe_xmit: skb->len = %d\n", skb->len); + +-- +2.16.4 + diff --git a/patches.suse/0051-amd-xgbe-Mark-expected-switch-fall-throughs.patch b/patches.suse/0051-amd-xgbe-Mark-expected-switch-fall-throughs.patch new file mode 100644 index 0000000..fd53f91 --- /dev/null +++ b/patches.suse/0051-amd-xgbe-Mark-expected-switch-fall-throughs.patch @@ -0,0 +1,103 @@ +From e2996a9396cc70413473f5cfccde43d8c594e2c7 Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Wed, 24 Apr 2019 11:08:24 -0500 +Subject: [PATCH 51/59] amd-xgbe: Mark expected switch fall-throughs +References: git-fixes +Patch-mainline: v5.2-rc1 +Git-commit: a36de5b7752ae1a9b5a5ca46c067dc232b085136 + +In preparation to enabling -Wimplicit-fallthrough, mark switch +cases where we are expecting to fall through. + +This patch fixes the following warnings: + +In file included from drivers/net/ethernet/amd/xgbe/xgbe-drv.c:129: +drivers/net/ethernet/amd/xgbe/xgbe-drv.c: In function ‘xgbe_set_hwtstamp_settings’: +drivers/net/ethernet/amd/xgbe/xgbe-common.h:1392:9: warning: this statement may fall through [-Wimplicit-fallthrough=] + (_var) |= (((_val) & ((0x1 << (_width)) - 1)) << (_index)); \ + ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +drivers/net/ethernet/amd/xgbe/xgbe-common.h:1419:2: note: in expansion of macro ‘SET_BITS’ + SET_BITS((_var), \ + ^~~~~~~~ +drivers/net/ethernet/amd/xgbe/xgbe-drv.c:1614:3: note: in expansion of macro ‘XGMAC_SET_BITS’ + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); + ^~~~~~~~~~~~~~ +drivers/net/ethernet/amd/xgbe/xgbe-drv.c:1616:2: note: here + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + ^~~~ +In file included from drivers/net/ethernet/amd/xgbe/xgbe-drv.c:129: +drivers/net/ethernet/amd/xgbe/xgbe-common.h:1392:9: warning: this statement may fall through [-Wimplicit-fallthrough=] + (_var) |= (((_val) & ((0x1 << (_width)) - 1)) << (_index)); \ + ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +drivers/net/ethernet/amd/xgbe/xgbe-common.h:1419:2: note: in expansion of macro ‘SET_BITS’ + SET_BITS((_var), \ + ^~~~~~~~ +drivers/net/ethernet/amd/xgbe/xgbe-drv.c:1625:3: note: in expansion of macro ‘XGMAC_SET_BITS’ + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); + ^~~~~~~~~~~~~~ +drivers/net/ethernet/amd/xgbe/xgbe-drv.c:1627:2: note: here + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + ^~~~ +In file included from drivers/net/ethernet/amd/xgbe/xgbe-drv.c:129: +drivers/net/ethernet/amd/xgbe/xgbe-common.h:1392:9: warning: this statement may fall through [-Wimplicit-fallthrough=] + (_var) |= (((_val) & ((0x1 << (_width)) - 1)) << (_index)); \ + ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +drivers/net/ethernet/amd/xgbe/xgbe-common.h:1419:2: note: in expansion of macro ‘SET_BITS’ + SET_BITS((_var), \ + ^~~~~~~~ +drivers/net/ethernet/amd/xgbe/xgbe-drv.c:1636:3: note: in expansion of macro ‘XGMAC_SET_BITS’ + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); + ^~~~~~~~~~~~~~ +drivers/net/ethernet/amd/xgbe/xgbe-drv.c:1638:2: note: here + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + ^~~~ + +Warning level 3 was used: -Wimplicit-fallthrough=3 + +Notice that, in this particular case, the code comments are modified +in accordance with what GCC is expecting to find. + +This patch is part of the ongoing efforts to enable +-Wimplicit-fallthrough. + +Signed-off-by: Gustavo A. R. Silva +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index b73b4615c0f5..2809b58bdabe 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -1614,7 +1614,7 @@ static int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata, + /* PTP v2, UDP, any kind of event packet */ + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); +- /* PTP v1, UDP, any kind of event packet */ ++ /* Fall through - to PTP v1, UDP, any kind of event packet */ + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); +@@ -1625,7 +1625,7 @@ static int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata, + /* PTP v2, UDP, Sync packet */ + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); +- /* PTP v1, UDP, Sync packet */ ++ /* Fall through - to PTP v1, UDP, Sync packet */ + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); +@@ -1636,7 +1636,7 @@ static int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata, + /* PTP v2, UDP, Delay_req packet */ + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); +- /* PTP v1, UDP, Delay_req packet */ ++ /* Fall through - to PTP v1, UDP, Delay_req packet */ + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); +-- +2.16.4 + diff --git a/patches.suse/0052-xgbe-no-need-to-check-return-value-of-debugfs_create.patch b/patches.suse/0052-xgbe-no-need-to-check-return-value-of-debugfs_create.patch new file mode 100644 index 0000000..f677c38 --- /dev/null +++ b/patches.suse/0052-xgbe-no-need-to-check-return-value-of-debugfs_create.patch @@ -0,0 +1,181 @@ +From 5309a1df8f2661cedca492d607bdef68c3d6653c Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Sat, 10 Aug 2019 12:17:19 +0200 +Subject: [PATCH 52/59] xgbe: no need to check return value of debugfs_create + functions +References: git-fixes +Patch-mainline: v5.4-rc1 +Git-commit: 9e3926df8779a69f8541c9983c6d19b097671abd + +When calling debugfs functions, there is no need to ever check the +return value. The function can work or not, but the code logic should +never do something different based on this. + +This cleans up a lot of unneeded code and logic around the debugfs +files, making all of this much simpler and easier to understand. + +Cc: Tom Lendacky +Cc: "David S. Miller" +Cc: netdev@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c | 107 ++++++++------------------- + 1 file changed, 31 insertions(+), 76 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c +index b91143947ed2..b0a6c96b6ef4 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c +@@ -438,7 +438,6 @@ static const struct file_operations xi2c_reg_value_fops = { + + void xgbe_debugfs_init(struct xgbe_prv_data *pdata) + { +- struct dentry *pfile; + char *buf; + + /* Set defaults */ +@@ -451,88 +450,48 @@ void xgbe_debugfs_init(struct xgbe_prv_data *pdata) + return; + + pdata->xgbe_debugfs = debugfs_create_dir(buf, NULL); +- if (!pdata->xgbe_debugfs) { +- netdev_err(pdata->netdev, "debugfs_create_dir failed\n"); +- kfree(buf); +- return; +- } + +- pfile = debugfs_create_file("xgmac_register", 0600, +- pdata->xgbe_debugfs, pdata, +- &xgmac_reg_addr_fops); +- if (!pfile) +- netdev_err(pdata->netdev, "debugfs_create_file failed\n"); ++ debugfs_create_file("xgmac_register", 0600, pdata->xgbe_debugfs, pdata, ++ &xgmac_reg_addr_fops); + +- pfile = debugfs_create_file("xgmac_register_value", 0600, +- pdata->xgbe_debugfs, pdata, +- &xgmac_reg_value_fops); +- if (!pfile) +- netdev_err(pdata->netdev, "debugfs_create_file failed\n"); ++ debugfs_create_file("xgmac_register_value", 0600, pdata->xgbe_debugfs, ++ pdata, &xgmac_reg_value_fops); + +- pfile = debugfs_create_file("xpcs_mmd", 0600, +- pdata->xgbe_debugfs, pdata, +- &xpcs_mmd_fops); +- if (!pfile) +- netdev_err(pdata->netdev, "debugfs_create_file failed\n"); ++ debugfs_create_file("xpcs_mmd", 0600, pdata->xgbe_debugfs, pdata, ++ &xpcs_mmd_fops); + +- pfile = debugfs_create_file("xpcs_register", 0600, +- pdata->xgbe_debugfs, pdata, +- &xpcs_reg_addr_fops); +- if (!pfile) +- netdev_err(pdata->netdev, "debugfs_create_file failed\n"); ++ debugfs_create_file("xpcs_register", 0600, pdata->xgbe_debugfs, pdata, ++ &xpcs_reg_addr_fops); + +- pfile = debugfs_create_file("xpcs_register_value", 0600, +- pdata->xgbe_debugfs, pdata, +- &xpcs_reg_value_fops); +- if (!pfile) +- netdev_err(pdata->netdev, "debugfs_create_file failed\n"); ++ debugfs_create_file("xpcs_register_value", 0600, pdata->xgbe_debugfs, ++ pdata, &xpcs_reg_value_fops); + + if (pdata->xprop_regs) { +- pfile = debugfs_create_file("xprop_register", 0600, +- pdata->xgbe_debugfs, pdata, +- &xprop_reg_addr_fops); +- if (!pfile) +- netdev_err(pdata->netdev, +- "debugfs_create_file failed\n"); +- +- pfile = debugfs_create_file("xprop_register_value", 0600, +- pdata->xgbe_debugfs, pdata, +- &xprop_reg_value_fops); +- if (!pfile) +- netdev_err(pdata->netdev, +- "debugfs_create_file failed\n"); ++ debugfs_create_file("xprop_register", 0600, pdata->xgbe_debugfs, ++ pdata, &xprop_reg_addr_fops); ++ ++ debugfs_create_file("xprop_register_value", 0600, ++ pdata->xgbe_debugfs, pdata, ++ &xprop_reg_value_fops); + } + + if (pdata->xi2c_regs) { +- pfile = debugfs_create_file("xi2c_register", 0600, +- pdata->xgbe_debugfs, pdata, +- &xi2c_reg_addr_fops); +- if (!pfile) +- netdev_err(pdata->netdev, +- "debugfs_create_file failed\n"); +- +- pfile = debugfs_create_file("xi2c_register_value", 0600, +- pdata->xgbe_debugfs, pdata, +- &xi2c_reg_value_fops); +- if (!pfile) +- netdev_err(pdata->netdev, +- "debugfs_create_file failed\n"); ++ debugfs_create_file("xi2c_register", 0600, pdata->xgbe_debugfs, ++ pdata, &xi2c_reg_addr_fops); ++ ++ debugfs_create_file("xi2c_register_value", 0600, ++ pdata->xgbe_debugfs, pdata, ++ &xi2c_reg_value_fops); + } + + if (pdata->vdata->an_cdr_workaround) { +- pfile = debugfs_create_bool("an_cdr_workaround", 0600, +- pdata->xgbe_debugfs, +- &pdata->debugfs_an_cdr_workaround); +- if (!pfile) +- netdev_err(pdata->netdev, +- "debugfs_create_bool failed\n"); +- +- pfile = debugfs_create_bool("an_cdr_track_early", 0600, +- pdata->xgbe_debugfs, +- &pdata->debugfs_an_cdr_track_early); +- if (!pfile) +- netdev_err(pdata->netdev, +- "debugfs_create_bool failed\n"); ++ debugfs_create_bool("an_cdr_workaround", 0600, ++ pdata->xgbe_debugfs, ++ &pdata->debugfs_an_cdr_workaround); ++ ++ debugfs_create_bool("an_cdr_track_early", 0600, ++ pdata->xgbe_debugfs, ++ &pdata->debugfs_an_cdr_track_early); + } + + kfree(buf); +@@ -546,7 +505,6 @@ void xgbe_debugfs_exit(struct xgbe_prv_data *pdata) + + void xgbe_debugfs_rename(struct xgbe_prv_data *pdata) + { +- struct dentry *pfile; + char *buf; + + if (!pdata->xgbe_debugfs) +@@ -559,11 +517,8 @@ void xgbe_debugfs_rename(struct xgbe_prv_data *pdata) + if (!strcmp(pdata->xgbe_debugfs->d_name.name, buf)) + goto out; + +- pfile = debugfs_rename(pdata->xgbe_debugfs->d_parent, +- pdata->xgbe_debugfs, +- pdata->xgbe_debugfs->d_parent, buf); +- if (!pfile) +- netdev_err(pdata->netdev, "debugfs_rename failed\n"); ++ debugfs_rename(pdata->xgbe_debugfs->d_parent, pdata->xgbe_debugfs, ++ pdata->xgbe_debugfs->d_parent, buf); + + out: + kfree(buf); +-- +2.16.4 + diff --git a/patches.suse/0053-amd-xgbe-use-devm_platform_ioremap_resource-to-simpl.patch b/patches.suse/0053-amd-xgbe-use-devm_platform_ioremap_resource-to-simpl.patch new file mode 100644 index 0000000..5f3cd16 --- /dev/null +++ b/patches.suse/0053-amd-xgbe-use-devm_platform_ioremap_resource-to-simpl.patch @@ -0,0 +1,89 @@ +From aa430eae34a832eb26a08a003ea8517da7913d78 Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Wed, 21 Aug 2019 20:32:03 +0800 +Subject: [PATCH 53/59] amd-xgbe: use devm_platform_ioremap_resource() to + simplify code +References: git-fixes +Patch-mainline: v5.4-rc1 +Git-commit: eba39fd6fe310710f011130e46e6d13e5c87d6f9 + +Use devm_platform_ioremap_resource() to simplify the code a bit. +This is detected by coccinelle. + +Reported-by: Hulk Robot +Signed-off-by: YueHaibing +Acked-by: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-platform.c | 19 ++++++++----------- + 1 file changed, 8 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c +index d0f3dfb88202..362e7e644c6c 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c +@@ -301,7 +301,6 @@ static int xgbe_platform_probe(struct platform_device *pdev) + struct xgbe_prv_data *pdata; + struct device *dev = &pdev->dev; + struct platform_device *phy_pdev; +- struct resource *res; + const char *phy_mode; + unsigned int phy_memnum, phy_irqnum; + unsigned int dma_irqnum, dma_irqend; +@@ -353,8 +352,7 @@ static int xgbe_platform_probe(struct platform_device *pdev) + } + + /* Obtain the mmio areas for the device */ +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- pdata->xgmac_regs = devm_ioremap_resource(dev, res); ++ pdata->xgmac_regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(pdata->xgmac_regs)) { + dev_err(dev, "xgmac ioremap failed\n"); + ret = PTR_ERR(pdata->xgmac_regs); +@@ -363,8 +361,7 @@ static int xgbe_platform_probe(struct platform_device *pdev) + if (netif_msg_probe(pdata)) + dev_dbg(dev, "xgmac_regs = %p\n", pdata->xgmac_regs); + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 1); +- pdata->xpcs_regs = devm_ioremap_resource(dev, res); ++ pdata->xpcs_regs = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(pdata->xpcs_regs)) { + dev_err(dev, "xpcs ioremap failed\n"); + ret = PTR_ERR(pdata->xpcs_regs); +@@ -373,8 +370,8 @@ static int xgbe_platform_probe(struct platform_device *pdev) + if (netif_msg_probe(pdata)) + dev_dbg(dev, "xpcs_regs = %p\n", pdata->xpcs_regs); + +- res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++); +- pdata->rxtx_regs = devm_ioremap_resource(dev, res); ++ pdata->rxtx_regs = devm_platform_ioremap_resource(phy_pdev, ++ phy_memnum++); + if (IS_ERR(pdata->rxtx_regs)) { + dev_err(dev, "rxtx ioremap failed\n"); + ret = PTR_ERR(pdata->rxtx_regs); +@@ -383,8 +380,8 @@ static int xgbe_platform_probe(struct platform_device *pdev) + if (netif_msg_probe(pdata)) + dev_dbg(dev, "rxtx_regs = %p\n", pdata->rxtx_regs); + +- res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++); +- pdata->sir0_regs = devm_ioremap_resource(dev, res); ++ pdata->sir0_regs = devm_platform_ioremap_resource(phy_pdev, ++ phy_memnum++); + if (IS_ERR(pdata->sir0_regs)) { + dev_err(dev, "sir0 ioremap failed\n"); + ret = PTR_ERR(pdata->sir0_regs); +@@ -393,8 +390,8 @@ static int xgbe_platform_probe(struct platform_device *pdev) + if (netif_msg_probe(pdata)) + dev_dbg(dev, "sir0_regs = %p\n", pdata->sir0_regs); + +- res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++); +- pdata->sir1_regs = devm_ioremap_resource(dev, res); ++ pdata->sir1_regs = devm_platform_ioremap_resource(phy_pdev, ++ phy_memnum++); + if (IS_ERR(pdata->sir1_regs)) { + dev_err(dev, "sir1 ioremap failed\n"); + ret = PTR_ERR(pdata->sir1_regs); +-- +2.16.4 + diff --git a/patches.suse/0054-amd-xgbe-Fix-error-path-in-xgbe_mod_init.patch b/patches.suse/0054-amd-xgbe-Fix-error-path-in-xgbe_mod_init.patch new file mode 100644 index 0000000..e33563e --- /dev/null +++ b/patches.suse/0054-amd-xgbe-Fix-error-path-in-xgbe_mod_init.patch @@ -0,0 +1,49 @@ +From 4d474e5b6feddc670a62391efe006878c460c7b7 Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Thu, 29 Aug 2019 10:46:00 +0800 +Subject: [PATCH 54/59] amd-xgbe: Fix error path in xgbe_mod_init() +References: git-fixes +Patch-mainline: v5.3-rc7 +Git-commit: b6b4dc4c1fa7f1c99398e7dc85758049645e9588 + +In xgbe_mod_init(), we should do cleanup if some error occurs + +Reported-by: Hulk Robot +Fixes: efbaa828330a ("amd-xgbe: Add support to handle device renaming") +Fixes: 47f164deab22 ("amd-xgbe: Add PCI device support") +Signed-off-by: YueHaibing +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-main.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +index b41f23679a08..7ce9c69e9c44 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +@@ -469,13 +469,19 @@ static int __init xgbe_mod_init(void) + + ret = xgbe_platform_init(); + if (ret) +- return ret; ++ goto err_platform_init; + + ret = xgbe_pci_init(); + if (ret) +- return ret; ++ goto err_pci_init; + + return 0; ++ ++err_pci_init: ++ xgbe_platform_exit(); ++err_platform_init: ++ unregister_netdevice_notifier(&xgbe_netdev_notifier); ++ return ret; + } + + static void __exit xgbe_mod_exit(void) +-- +2.16.4 + diff --git a/patches.suse/0055-amd-xgbe-remove-unnecessary-conversion-to-bool.patch b/patches.suse/0055-amd-xgbe-remove-unnecessary-conversion-to-bool.patch new file mode 100644 index 0000000..fb2b1cb --- /dev/null +++ b/patches.suse/0055-amd-xgbe-remove-unnecessary-conversion-to-bool.patch @@ -0,0 +1,33 @@ +From 763f6234e03a4619b79c3deb0bff1b9661570a86 Mon Sep 17 00:00:00 2001 +From: Chen Zhou +Date: Mon, 13 Jan 2020 21:15:16 +0800 +Subject: [PATCH 55/59] amd-xgbe: remove unnecessary conversion to bool +References: git-fixes +Patch-mainline: v5.6-rc1 +Git-commit: ab9837b5ed51f128f898a93d873ba7198abc1140 + +The conversion to bool is not needed, remove it. + +Signed-off-by: Chen Zhou +Signed-off-by: Jakub Kicinski +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index 7048fb08faaf..b2e98e83639c 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -1215,7 +1215,7 @@ static bool xgbe_phy_sfp_verify_eeprom(u8 cc_in, u8 *buf, unsigned int len) + for (cc = 0; len; buf++, len--) + cc += *buf; + +- return (cc == cc_in) ? true : false; ++ return cc == cc_in; + } + + static int xgbe_phy_sfp_read_eeprom(struct xgbe_prv_data *pdata) +-- +2.16.4 + diff --git a/patches.suse/0056-net-amd-Remove-useless-driver-version.patch b/patches.suse/0056-net-amd-Remove-useless-driver-version.patch new file mode 100644 index 0000000..f027f27 --- /dev/null +++ b/patches.suse/0056-net-amd-Remove-useless-driver-version.patch @@ -0,0 +1,258 @@ +From b39911d3279fa6f1a458499ffeda34f1949d75fc Mon Sep 17 00:00:00 2001 +From: Leon Romanovsky +Date: Mon, 24 Feb 2020 10:53:06 +0200 +Subject: [PATCH 56/59] net/amd: Remove useless driver version +References: git-fixes +Patch-mainline: v5.7-rc1 +Git-commit: 7f4d2537f0b9630dbe1a7d7c4ea1b9479f4451e9 + +Convert AMD drivers to respect universal linux kernel version. + +Signed-off-by: Leon Romanovsky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/amd8111e.c | 5 +---- + drivers/net/ethernet/amd/au1000_eth.c | 5 ----- + drivers/net/ethernet/amd/nmclan_cs.c | 9 +++------ + drivers/net/ethernet/amd/pcnet32.c | 7 ------- + drivers/net/ethernet/amd/sunlance.c | 10 ---------- + drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 1 - + drivers/net/ethernet/amd/xgbe/xgbe-main.c | 1 - + drivers/net/ethernet/amd/xgbe/xgbe.h | 1 - + 8 files changed, 4 insertions(+), 35 deletions(-) + +diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c +index 7b5df562f30f..194ae9a343e8 100644 +--- a/drivers/net/ethernet/amd/amd8111e.c ++++ b/drivers/net/ethernet/amd/amd8111e.c +@@ -97,9 +97,8 @@ Revision History: + + #include "amd8111e.h" + #define MODULE_NAME "amd8111e" +-#define MODULE_VERS "3.0.7" + MODULE_AUTHOR("Advanced Micro Devices, Inc."); +-MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version "MODULE_VERS); ++MODULE_DESCRIPTION("AMD8111 based 10/100 Ethernet Controller."); + MODULE_LICENSE("GPL"); + module_param_array(speed_duplex, int, NULL, 0); + MODULE_PARM_DESC(speed_duplex, "Set device speed and duplex modes, 0: Auto Negotiate, 1: 10Mbps Half Duplex, 2: 10Mbps Full Duplex, 3: 100Mbps Half Duplex, 4: 100Mbps Full Duplex"); +@@ -1383,7 +1382,6 @@ static void amd8111e_get_drvinfo(struct net_device *dev, + struct amd8111e_priv *lp = netdev_priv(dev); + struct pci_dev *pci_dev = lp->pci_dev; + strlcpy(info->driver, MODULE_NAME, sizeof(info->driver)); +- strlcpy(info->version, MODULE_VERS, sizeof(info->version)); + snprintf(info->fw_version, sizeof(info->fw_version), + "%u", chip_version); + strlcpy(info->bus_info, pci_name(pci_dev), sizeof(info->bus_info)); +@@ -1894,7 +1892,6 @@ static int amd8111e_probe_one(struct pci_dev *pdev, + + /* display driver and device information */ + chip_version = (readl(lp->mmio + CHIPID) & 0xf0000000)>>28; +- dev_info(&pdev->dev, "AMD-8111e Driver Version: %s\n", MODULE_VERS); + dev_info(&pdev->dev, "[ Rev %x ] PCI 10/100BaseT Ethernet %pM\n", + chip_version, dev->dev_addr); + if (lp->ext_phy_id) +diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c +index a3c90fe5de00..f7e3fba46600 100644 +--- a/drivers/net/ethernet/amd/au1000_eth.c ++++ b/drivers/net/ethernet/amd/au1000_eth.c +@@ -80,14 +80,12 @@ static int au1000_debug = 3; + NETIF_MSG_LINK) + + #define DRV_NAME "au1000_eth" +-#define DRV_VERSION "1.7" + #define DRV_AUTHOR "Pete Popov " + #define DRV_DESC "Au1xxx on-chip Ethernet driver" + + MODULE_AUTHOR(DRV_AUTHOR); + MODULE_DESCRIPTION(DRV_DESC); + MODULE_LICENSE("GPL"); +-MODULE_VERSION(DRV_VERSION); + + /* AU1000 MAC registers and bits */ + #define MAC_CONTROL 0x0 +@@ -683,7 +681,6 @@ au1000_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) + struct au1000_private *aup = netdev_priv(dev); + + strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); +- strlcpy(info->version, DRV_VERSION, sizeof(info->version)); + snprintf(info->bus_info, sizeof(info->bus_info), "%s %d", DRV_NAME, + aup->mac_id); + } +@@ -1331,8 +1328,6 @@ static int au1000_probe(struct platform_device *pdev) + netdev_info(dev, "Au1xx0 Ethernet found at 0x%lx, irq %d\n", + (unsigned long)base->start, irq); + +- pr_info_once("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR); +- + return 0; + + err_out: +diff --git a/drivers/net/ethernet/amd/nmclan_cs.c b/drivers/net/ethernet/amd/nmclan_cs.c +index 9c152d85840d..3902609d4198 100644 +--- a/drivers/net/ethernet/amd/nmclan_cs.c ++++ b/drivers/net/ethernet/amd/nmclan_cs.c +@@ -114,8 +114,6 @@ Log: nmclan_cs.c,v + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #define DRV_NAME "nmclan_cs" +-#define DRV_VERSION "0.16" +- + + /* ---------------------------------------------------------------------------- + Conditional Compilation Options +@@ -367,7 +365,7 @@ typedef struct _mace_private { + + char tx_free_frames; /* Number of free transmit frame buffers */ + char tx_irq_disabled; /* MACE TX interrupt disabled */ +- ++ + spinlock_t bank_lock; /* Must be held if you step off bank 0 */ + } mace_private; + +@@ -444,7 +442,7 @@ static int nmclan_probe(struct pcmcia_device *link) + lp = netdev_priv(dev); + lp->p_dev = link; + link->priv = dev; +- ++ + spin_lock_init(&lp->bank_lock); + link->resource[0]->end = 32; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; +@@ -817,7 +815,6 @@ static void netdev_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) + { + strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); +- strlcpy(info->version, DRV_VERSION, sizeof(info->version)); + snprintf(info->bus_info, sizeof(info->bus_info), + "PCMCIA 0x%lx", dev->base_addr); + } +@@ -1110,7 +1107,7 @@ static int mace_rx(struct net_device *dev, unsigned char RxCnt) + if (pkt_len & 1) + *(skb_tail_pointer(skb) - 1) = inb(ioaddr + AM2150_RCV); + skb->protocol = eth_type_trans(skb, dev); +- ++ + netif_rx(skb); /* Send the packet to the upper (protocol) layers. */ + + dev->stats.rx_packets++; +diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c +index 7f60d17819ce..583b0b0c0968 100644 +--- a/drivers/net/ethernet/amd/pcnet32.c ++++ b/drivers/net/ethernet/amd/pcnet32.c +@@ -24,13 +24,9 @@ + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #define DRV_NAME "pcnet32" +-#define DRV_VERSION "1.35" + #define DRV_RELDATE "21.Apr.2008" + #define PFX DRV_NAME ": " + +-static const char *const version = +- DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n"; +- + #include + #include + #include +@@ -809,7 +805,6 @@ static void pcnet32_get_drvinfo(struct net_device *dev, + struct pcnet32_private *lp = netdev_priv(dev); + + strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); +- strlcpy(info->version, DRV_VERSION, sizeof(info->version)); + if (lp->pci_dev) + strlcpy(info->bus_info, pci_name(lp->pci_dev), + sizeof(info->bus_info)); +@@ -3003,8 +2998,6 @@ MODULE_LICENSE("GPL"); + + static int __init pcnet32_init_module(void) + { +- pr_info("%s", version); +- + pcnet32_debug = netif_msg_init(debug, PCNET32_MSG_DEFAULT); + + if ((tx_start_pt >= 0) && (tx_start_pt <= 3)) +diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c +index 7d1c07f33504..0fec99ac13f0 100644 +--- a/drivers/net/ethernet/amd/sunlance.c ++++ b/drivers/net/ethernet/amd/sunlance.c +@@ -104,14 +104,9 @@ static char lancestr[] = "LANCE"; + #include + + #define DRV_NAME "sunlance" +-#define DRV_VERSION "2.02" + #define DRV_RELDATE "8/24/03" + #define DRV_AUTHOR "Miguel de Icaza (miguel@nuclecu.unam.mx)" + +-static char version[] = +- DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; +- +-MODULE_VERSION(DRV_VERSION); + MODULE_AUTHOR(DRV_AUTHOR); + MODULE_DESCRIPTION("Sun Lance ethernet driver"); + MODULE_LICENSE("GPL"); +@@ -1280,7 +1275,6 @@ static void lance_free_hwresources(struct lance_private *lp) + static void sparc_lance_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) + { + strlcpy(info->driver, "sunlance", sizeof(info->driver)); +- strlcpy(info->version, "2.02", sizeof(info->version)); + } + + static const struct ethtool_ops sparc_lance_ethtool_ops = { +@@ -1303,7 +1297,6 @@ static int sparc_lance_probe_one(struct platform_device *op, + struct platform_device *lebuffer) + { + struct device_node *dp = op->dev.of_node; +- static unsigned version_printed; + struct lance_private *lp; + struct net_device *dev; + int i; +@@ -1314,9 +1307,6 @@ static int sparc_lance_probe_one(struct platform_device *op, + + lp = netdev_priv(dev); + +- if (sparc_lance_debug && version_printed++ == 0) +- printk (KERN_INFO "%s", version); +- + spin_lock_init(&lp->lock); + + /* Copy the IDPROM ethernet address to the device structure, later we +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +index a880f10e3e70..33423aaec23d 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +@@ -405,7 +405,6 @@ static void xgbe_get_drvinfo(struct net_device *netdev, + struct xgbe_hw_features *hw_feat = &pdata->hw_feat; + + strlcpy(drvinfo->driver, XGBE_DRV_NAME, sizeof(drvinfo->driver)); +- strlcpy(drvinfo->version, XGBE_DRV_VERSION, sizeof(drvinfo->version)); + strlcpy(drvinfo->bus_info, dev_name(pdata->dev), + sizeof(drvinfo->bus_info)); + snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d.%d.%d", +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +index 7ce9c69e9c44..2a70714a791d 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c +@@ -127,7 +127,6 @@ + + MODULE_AUTHOR("Tom Lendacky "); + MODULE_LICENSE("Dual BSD/GPL"); +-MODULE_VERSION(XGBE_DRV_VERSION); + MODULE_DESCRIPTION(XGBE_DRV_DESC); + + static int debug = -1; +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h +index d3c476531518..c4608b40f5d5 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h +@@ -135,7 +135,6 @@ + #include + + #define XGBE_DRV_NAME "amd-xgbe" +-#define XGBE_DRV_VERSION "1.0.3" + #define XGBE_DRV_DESC "AMD 10 Gigabit Ethernet Driver" + + /* Descriptor related defines */ +-- +2.16.4 + diff --git a/patches.suse/0057-amd-xgbe-Use-__napi_schedule-in-BH-context.patch b/patches.suse/0057-amd-xgbe-Use-__napi_schedule-in-BH-context.patch new file mode 100644 index 0000000..e1f3d1b --- /dev/null +++ b/patches.suse/0057-amd-xgbe-Use-__napi_schedule-in-BH-context.patch @@ -0,0 +1,42 @@ +From 1136d9ed1f9fddd7038d37631440a629600a6a29 Mon Sep 17 00:00:00 2001 +From: Sebastian Andrzej Siewior +Date: Thu, 16 Apr 2020 17:57:40 +0200 +Subject: [PATCH 57/59] amd-xgbe: Use __napi_schedule() in BH context +References: git-fixes +Patch-mainline: v5.7-rc2 +Git-commit: d518691cbd3be3dae218e05cca3f3fc9b2f1aa77 + +The driver uses __napi_schedule_irqoff() which is fine as long as it is +invoked with disabled interrupts by everybody. Since the commit +mentioned below the driver may invoke xgbe_isr_task() in tasklet/softirq +context. This may lead to list corruption if another driver uses +__napi_schedule_irqoff() in IRQ context. + +Use __napi_schedule() which safe to use from IRQ and softirq context. + +Fixes: 85b85c853401d ("amd-xgbe: Re-issue interrupt if interrupt status not cleared") +Signed-off-by: Sebastian Andrzej Siewior +Acked-by: Tom Lendacky +Cc: Tom Lendacky +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index 2809b58bdabe..0d2438d8a791 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -514,7 +514,7 @@ static void xgbe_isr_task(unsigned long data) + xgbe_disable_rx_tx_ints(pdata); + + /* Turn on polling */ +- __napi_schedule_irqoff(&pdata->napi); ++ __napi_schedule(&pdata->napi); + } + } else { + /* Don't clear Rx/Tx status if doing per channel DMA +-- +2.16.4 + diff --git a/patches.suse/0058-amd-xgbe-Convert-to-generic-power-management.patch b/patches.suse/0058-amd-xgbe-Convert-to-generic-power-management.patch new file mode 100644 index 0000000..edd859a --- /dev/null +++ b/patches.suse/0058-amd-xgbe-Convert-to-generic-power-management.patch @@ -0,0 +1,84 @@ +From 782c2604bb40b8922f2e36101e7f2bc9cce6cb02 Mon Sep 17 00:00:00 2001 +From: Vaibhav Gupta +Date: Mon, 22 Jun 2020 16:44:00 +0530 +Subject: [PATCH 58/59] amd-xgbe: Convert to generic power management +References: git-fixes +Patch-mainline: v5.9-rc1 +Git-commit: c6f0fb5dfea02024ed8d45784a4f2f231aba9c65 + +Use dev_pm_ops structure to call generic suspend() and resume() callbacks. + +Drivers should avoid saving device register and/or change power states +using PCI helper functions. With the generic approach, all these are handled +by PCI core. + +Compile-tested only. + +Signed-off-by: Vaibhav Gupta +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-pci.c | 19 +++++++++---------- + 1 file changed, 9 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +index a878ceb8766f..c63270577219 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +@@ -421,10 +421,9 @@ static void xgbe_pci_remove(struct pci_dev *pdev) + xgbe_free_pdata(pdata); + } + +-#ifdef CONFIG_PM +-static int xgbe_pci_suspend(struct pci_dev *pdev, pm_message_t state) ++static int __maybe_unused xgbe_pci_suspend(struct device *dev) + { +- struct xgbe_prv_data *pdata = pci_get_drvdata(pdev); ++ struct xgbe_prv_data *pdata = dev_get_drvdata(dev); + struct net_device *netdev = pdata->netdev; + int ret = 0; + +@@ -438,9 +437,9 @@ static int xgbe_pci_suspend(struct pci_dev *pdev, pm_message_t state) + return ret; + } + +-static int xgbe_pci_resume(struct pci_dev *pdev) ++static int __maybe_unused xgbe_pci_resume(struct device *dev) + { +- struct xgbe_prv_data *pdata = pci_get_drvdata(pdev); ++ struct xgbe_prv_data *pdata = dev_get_drvdata(dev); + struct net_device *netdev = pdata->netdev; + int ret = 0; + +@@ -460,7 +459,6 @@ static int xgbe_pci_resume(struct pci_dev *pdev) + + return ret; + } +-#endif /* CONFIG_PM */ + + static const struct xgbe_version_data xgbe_v2a = { + .init_function_ptrs_phy_impl = xgbe_init_function_ptrs_phy_v2, +@@ -502,15 +500,16 @@ static const struct pci_device_id xgbe_pci_table[] = { + }; + MODULE_DEVICE_TABLE(pci, xgbe_pci_table); + ++static SIMPLE_DEV_PM_OPS(xgbe_pci_pm_ops, xgbe_pci_suspend, xgbe_pci_resume); ++ + static struct pci_driver xgbe_driver = { + .name = XGBE_DRV_NAME, + .id_table = xgbe_pci_table, + .probe = xgbe_pci_probe, + .remove = xgbe_pci_remove, +-#ifdef CONFIG_PM +- .suspend = xgbe_pci_suspend, +- .resume = xgbe_pci_resume, +-#endif ++ .driver = { ++ .pm = &xgbe_pci_pm_ops, ++ } + }; + + int xgbe_pci_init(void) +-- +2.16.4 + diff --git a/patches.suse/0059-xgbe-switch-to-more-generic-VxLAN-detection.patch b/patches.suse/0059-xgbe-switch-to-more-generic-VxLAN-detection.patch new file mode 100644 index 0000000..cd70154 --- /dev/null +++ b/patches.suse/0059-xgbe-switch-to-more-generic-VxLAN-detection.patch @@ -0,0 +1,78 @@ +From b28341c3d069b5a0e5e2a932d5953b124f9539af Mon Sep 17 00:00:00 2001 +From: Jakub Kicinski +Date: Tue, 14 Jul 2020 12:18:21 -0700 +Subject: [PATCH 59/59] xgbe: switch to more generic VxLAN detection +References: git-fixes +Patch-mainline: v5.9-rc1 +Git-commit: b5c5f8d06292e2dd9961c4b88fde9ae0ea458d97 + +Instead of looping though the list of ports just check +if the geometry of the packet is correct for VxLAN. +HW most likely doesn't care about the exact port, anyway, +since only first port is actually offloaded, and this way +we won't have to maintain the port list at all. + +Signed-off-by: Jakub Kicinski +Signed-off-by: David S. Miller +Acked-by: Denis Kirjanov +--- + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 27 ++++++++------------------- + 1 file changed, 8 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index 0d2438d8a791..4f12e5232650 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -1775,13 +1775,8 @@ static int xgbe_prep_tso(struct sk_buff *skb, struct xgbe_packet_data *packet) + return 0; + } + +-static bool xgbe_is_vxlan(struct xgbe_prv_data *pdata, struct sk_buff *skb) ++static bool xgbe_is_vxlan(struct sk_buff *skb) + { +- struct xgbe_vxlan_data *vdata; +- +- if (pdata->vxlan_force_disable) +- return false; +- + if (!skb->encapsulation) + return false; + +@@ -1803,19 +1798,13 @@ static bool xgbe_is_vxlan(struct xgbe_prv_data *pdata, struct sk_buff *skb) + return false; + } + +- /* See if we have the UDP port in our list */ +- list_for_each_entry(vdata, &pdata->vxlan_ports, list) { +- if ((skb->protocol == htons(ETH_P_IP)) && +- (vdata->sa_family == AF_INET) && +- (vdata->port == udp_hdr(skb)->dest)) +- return true; +- else if ((skb->protocol == htons(ETH_P_IPV6)) && +- (vdata->sa_family == AF_INET6) && +- (vdata->port == udp_hdr(skb)->dest)) +- return true; +- } ++ if (skb->inner_protocol_type != ENCAP_TYPE_ETHER || ++ skb->inner_protocol != htons(ETH_P_TEB) || ++ (skb_inner_mac_header(skb) - skb_transport_header(skb) != ++ sizeof(struct udphdr) + sizeof(struct vxlanhdr))) ++ return false; + +- return false; ++ return true; + } + + static int xgbe_is_tso(struct sk_buff *skb) +@@ -1866,7 +1855,7 @@ static void xgbe_packet_info(struct xgbe_prv_data *pdata, + XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, + CSUM_ENABLE, 1); + +- if (xgbe_is_vxlan(pdata, skb)) ++ if (xgbe_is_vxlan(skb)) + XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, + VXLAN, 1); + +-- +2.16.4 + diff --git a/patches.suse/NFS-On-fatal-writeback-errors-we-need-to-call-nfs_in.patch b/patches.suse/NFS-On-fatal-writeback-errors-we-need-to-call-nfs_in.patch new file mode 100644 index 0000000..7eb36a0 --- /dev/null +++ b/patches.suse/NFS-On-fatal-writeback-errors-we-need-to-call-nfs_in.patch @@ -0,0 +1,40 @@ +From: Trond Myklebust +Date: Wed, 14 Aug 2019 15:42:43 -0400 +Subject: [PATCH] NFS: On fatal writeback errors, we need to call + nfs_inode_remove_request() +Git-commit: 06c9fdf3b9f1acc6e53753c99c54c39764cc979f +Patch-mainline: v5.3 +References: bsc#1177340 + +If the writeback error is fatal, we need to remove the tracking structures +(i.e. the nfs_page) from the inode. + +Fixes: 6fbda89b257f ("NFS: Replace custom error reporting mechanism...") +Signed-off-by: Trond Myklebust +Acked-by: NeilBrown + +--- + fs/nfs/write.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/nfs/write.c ++++ b/fs/nfs/write.c +@@ -55,6 +55,7 @@ static const struct rpc_call_ops nfs_com + static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops; + static const struct nfs_commit_completion_ops nfs_commit_completion_ops; + static const struct nfs_rw_ops nfs_rw_write_ops; ++static void nfs_inode_remove_request(struct nfs_page *req); + static void nfs_clear_request_commit(struct nfs_page *req); + static void nfs_init_cinfo_from_inode(struct nfs_commit_info *cinfo, + struct inode *inode); +@@ -612,8 +613,10 @@ try_again: + + static void nfs_write_error_remove_page(struct nfs_page *req) + { ++ nfs_set_pageerror(page_file_mapping(req->wb_page)); + nfs_unlock_request(req); + SetPageError(req->wb_page); ++ nfs_inode_remove_request(req); + nfs_end_page_writeback(req); + nfs_release_request(req); + } diff --git a/patches.suse/NFS-Revalidate-the-file-mapping-on-all-fatal-writeba.patch b/patches.suse/NFS-Revalidate-the-file-mapping-on-all-fatal-writeba.patch new file mode 100644 index 0000000..fc6b4cb --- /dev/null +++ b/patches.suse/NFS-Revalidate-the-file-mapping-on-all-fatal-writeba.patch @@ -0,0 +1,33 @@ +From: Trond Myklebust +Date: Mon, 6 Jan 2020 15:25:01 -0500 +Subject: [PATCH] NFS: Revalidate the file mapping on all fatal writeback + errors +Git-commit: b8946d7bfb9417ec171693d4478a831420aead5f +Patch-mainline: v5.6 +References: bsc#1177340 + +If a write or commit failed, and the mapping sees a fatal error, we +need to revalidate the contents of that mapping. + +Fixes: 06c9fdf3b9f1 ("NFS: On fatal writeback errors, we need to call nfs_inode_remove_request()") +Signed-off-by: Trond Myklebust +Signed-off-by: Anna Schumaker +Acked-by: NeilBrown + +--- + fs/nfs/write.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfs/write.c ++++ b/fs/nfs/write.c +@@ -613,9 +613,9 @@ try_again: + + static void nfs_write_error_remove_page(struct nfs_page *req) + { +- nfs_set_pageerror(page_file_mapping(req->wb_page)); + nfs_unlock_request(req); + SetPageError(req->wb_page); ++ nfs_set_pageerror(page_file_mapping(req->wb_page)); + nfs_inode_remove_request(req); + nfs_end_page_writeback(req); + nfs_release_request(req); diff --git a/patches.suse/amd-xgbe-Improve-KR-auto-negotiation-and-training.patch b/patches.suse/amd-xgbe-Improve-KR-auto-negotiation-and-training.patch index 92107a0..4d2e636 100644 --- a/patches.suse/amd-xgbe-Improve-KR-auto-negotiation-and-training.patch +++ b/patches.suse/amd-xgbe-Improve-KR-auto-negotiation-and-training.patch @@ -52,9 +52,9 @@ Signed-off-by: Jiri Slaby #ifndef MDIO_CTRL1_SPEED1G #define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100) #endif -@@ -1347,6 +1351,10 @@ - #define XGBE_AN_CL37_PCS_MODE_SGMII 0x04 +@@ -1341,6 +1341,10 @@ #define XGBE_AN_CL37_TX_CONFIG_MASK 0x08 + #define XGBE_AN_CL37_MII_CTRL_8BIT 0x0100 +#define XGBE_PMA_CDR_TRACK_EN_MASK 0x01 +#define XGBE_PMA_CDR_TRACK_EN_OFF 0x00 @@ -126,19 +126,19 @@ Signed-off-by: Jiri Slaby return XGBE_AN_PAGE_RECEIVED; --- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c -@@ -447,6 +447,7 @@ static const struct xgbe_version_data xg - .tx_tstamp_workaround = 1, - .ecc_support = 1, - .i2c_support = 1, -+ .an_cdr_workaround = 1, +@@ -452,6 +452,7 @@ static const struct xgbe_version_data xg + .irq_reissue_support = 1, + .tx_desc_prefetch = 5, + .rx_desc_prefetch = 5, ++ .an_cdr_workaround = 1, }; static const struct xgbe_version_data xgbe_v2b = { -@@ -458,6 +459,7 @@ static const struct xgbe_version_data xg - .tx_tstamp_workaround = 1, - .ecc_support = 1, - .i2c_support = 1, -+ .an_cdr_workaround = 1, +@@ -466,6 +467,7 @@ static const struct xgbe_version_data xg + .irq_reissue_support = 1, + .tx_desc_prefetch = 5, + .rx_desc_prefetch = 5, ++ .an_cdr_workaround = 1, }; static const struct pci_device_id xgbe_pci_table[] = { @@ -325,21 +325,21 @@ Signed-off-by: Jiri Slaby } --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h -@@ -929,6 +929,7 @@ struct xgbe_version_data { - unsigned int tx_tstamp_workaround; - unsigned int ecc_support; - unsigned int i2c_support; +@@ -989,6 +989,7 @@ struct xgbe_version_data { + unsigned int irq_reissue_support; + unsigned int tx_desc_prefetch; + unsigned int rx_desc_prefetch; + unsigned int an_cdr_workaround; }; - struct xgbe_prv_data { -@@ -1175,6 +1176,9 @@ struct xgbe_prv_data { + struct xgbe_vxlan_data { +@@ -1188,6 +1188,9 @@ struct xgbe_prv_data { unsigned int debugfs_xprop_reg; unsigned int debugfs_xi2c_reg; + + bool debugfs_an_cdr_workaround; + bool debugfs_an_cdr_track_early; - #endif }; + /* Function prototypes*/ diff --git a/patches.suse/crypto-dh-check-validity-of-z-before-export b/patches.suse/crypto-dh-check-validity-of-z-before-export new file mode 100644 index 0000000..c2a5748 --- /dev/null +++ b/patches.suse/crypto-dh-check-validity-of-z-before-export @@ -0,0 +1,64 @@ +From: =?UTF-8?q?Stephan=20M=C3=BCller?= +Date: Mon, 20 Jul 2020 19:08:32 +0200 +Subject: crypto: dh - check validity of Z before export +Git-commit: 90fa9ae51c1f2fa932bfa0a4d19163d49f0c1c46 +Patch-mainline: v5.9-rc1 +References: bsc#1175716 + +SP800-56A rev3 section 5.7.1.1 step 2 mandates that the validity of the +calculated shared secret is verified before the data is returned to the +caller. This patch adds the validation check. + +Signed-off-by: Stephan Mueller +Acked-by: Neil Horman +Signed-off-by: Herbert Xu +Acked-by: Petr Tesarik +--- + crypto/dh.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +--- a/crypto/dh.c ++++ b/crypto/dh.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + + struct dh_ctx { +@@ -186,6 +187,34 @@ static int dh_compute_value(struct kpp_r + if (ret) + goto err_free_base; + ++ /* SP800-56A rev3 5.7.1.1 check: Validation of shared secret */ ++ if (fips_enabled && req->src) { ++ MPI pone; ++ ++ /* z <= 1 */ ++ if (mpi_cmp_ui(val, 1) < 1) { ++ ret = -EBADMSG; ++ goto err_free_base; ++ } ++ ++ /* z == p - 1 */ ++ pone = mpi_alloc(0); ++ ++ if (!pone) { ++ ret = -ENOMEM; ++ goto err_free_base; ++ } ++ ++ ret = mpi_sub_ui(pone, ctx->p, 1); ++ if (!ret && !mpi_cmp(pone, val)) ++ ret = -EBADMSG; ++ ++ mpi_free(pone); ++ ++ if (ret) ++ goto err_free_base; ++ } ++ + ret = mpi_write_to_sgl(val, req->dst, req->dst_len, &sign); + if (ret) + goto err_free_base; diff --git a/patches.suse/crypto-dh-sp800-56a-rev-3-local-public-key-validation b/patches.suse/crypto-dh-sp800-56a-rev-3-local-public-key-validation new file mode 100644 index 0000000..10d9ed3 --- /dev/null +++ b/patches.suse/crypto-dh-sp800-56a-rev-3-local-public-key-validation @@ -0,0 +1,89 @@ +From: =?UTF-8?q?Stephan=20M=C3=BCller?= +Date: Mon, 20 Jul 2020 19:08:52 +0200 +Subject: crypto: dh - SP800-56A rev 3 local public key validation +Git-commit: 2ed5ba61cc78f102656eedc0b4c80fd14a5e8c7c +Patch-mainline: v5.9-rc1 +References: bsc#1175716 + +After the generation of a local public key, SP800-56A rev 3 section +5.6.2.1.3 mandates a validation of that key with a full validation +compliant to section 5.6.2.3.1. + +Only if the full validation passes, the key is allowed to be used. + +Signed-off-by: Stephan Mueller +Signed-off-by: Herbert Xu +Acked-by: Petr Tesarik +--- + crypto/dh.c | 59 ++++++++++++++++++++++++++++++++++------------------------- + 1 file changed, 34 insertions(+), 25 deletions(-) + +--- a/crypto/dh.c ++++ b/crypto/dh.c +@@ -187,32 +187,41 @@ static int dh_compute_value(struct kpp_r + if (ret) + goto err_free_base; + +- /* SP800-56A rev3 5.7.1.1 check: Validation of shared secret */ +- if (fips_enabled && req->src) { +- MPI pone; +- +- /* z <= 1 */ +- if (mpi_cmp_ui(val, 1) < 1) { +- ret = -EBADMSG; +- goto err_free_base; ++ if (fips_enabled) { ++ /* SP800-56A rev3 5.7.1.1 check: Validation of shared secret */ ++ if (req->src) { ++ MPI pone; ++ ++ /* z <= 1 */ ++ if (mpi_cmp_ui(val, 1) < 1) { ++ ret = -EBADMSG; ++ goto err_free_base; ++ } ++ ++ /* z == p - 1 */ ++ pone = mpi_alloc(0); ++ ++ if (!pone) { ++ ret = -ENOMEM; ++ goto err_free_base; ++ } ++ ++ ret = mpi_sub_ui(pone, ctx->p, 1); ++ if (!ret && !mpi_cmp(pone, val)) ++ ret = -EBADMSG; ++ ++ mpi_free(pone); ++ ++ if (ret) ++ goto err_free_base; ++ ++ /* SP800-56A rev 3 5.6.2.1.3 key check */ ++ } else { ++ if (dh_is_pubkey_valid(ctx, val)) { ++ ret = -EAGAIN; ++ goto err_free_val; ++ } + } +- +- /* z == p - 1 */ +- pone = mpi_alloc(0); +- +- if (!pone) { +- ret = -ENOMEM; +- goto err_free_base; +- } +- +- ret = mpi_sub_ui(pone, ctx->p, 1); +- if (!ret && !mpi_cmp(pone, val)) +- ret = -EBADMSG; +- +- mpi_free(pone); +- +- if (ret) +- goto err_free_base; + } + + ret = mpi_write_to_sgl(val, req->dst, req->dst_len, &sign); diff --git a/patches.suse/crypto-ecc-sp800-56a-rev-3-local-public-key-validation b/patches.suse/crypto-ecc-sp800-56a-rev-3-local-public-key-validation new file mode 100644 index 0000000..fbe6c13 --- /dev/null +++ b/patches.suse/crypto-ecc-sp800-56a-rev-3-local-public-key-validation @@ -0,0 +1,83 @@ +From: =?UTF-8?q?Stephan=20M=C3=BCller?= +Date: Mon, 20 Jul 2020 19:09:23 +0200 +Subject: crypto: ecc - SP800-56A rev 3 local public key validation +Git-commit: 6914dd53eb7af7cbc66edf7992d600b1e952c40d +Patch-mainline: v5.9-rc1 +References: bsc#1175716 + +After the generation of a local public key, SP800-56A rev 3 section +5.6.2.1.3 mandates a validation of that key with a full validation +compliant to section 5.6.2.3.3. + +Only if the full validation passes, the key is allowed to be used. + +The patch adds the full key validation compliant to 5.6.2.3.3 and +performs the required check on the generated public key. + +Signed-off-by: Stephan Mueller +Signed-off-by: Herbert Xu +[ ptesarik: The export is needed only to share the routines with ecrdsa. + SLE15 does not have the ecrdsa module, so the added function should be + local to crypto/ecc.c. ] +Signed-off-by: Petr Tesarik +--- + crypto/ecc.c | 34 +++++++++++++++++++++++++++++++++- + 1 file changed, 33 insertions(+), 1 deletion(-) + +--- a/crypto/ecc.c ++++ b/crypto/ecc.c +@@ -38,6 +38,9 @@ typedef struct { + u64 m_high; + } uint128_t; + ++static int ecc_is_pubkey_valid_full(const struct ecc_curve *curve, ++ struct ecc_point *pk); ++ + static inline const struct ecc_curve *ecc_get_curve(unsigned int curve_id) + { + switch (curve_id) { +@@ -952,7 +955,9 @@ int ecdh_make_pub_key(unsigned int curve + } + + ecc_point_mult(pk, &curve->g, priv, NULL, curve->p, ndigits); +- if (ecc_point_is_zero(pk)) { ++ ++ /* SP800-56A rev 3 5.6.2.1.3 key check */ ++ if (ecc_is_pubkey_valid_full(curve, pk)) { + ret = -EAGAIN; + goto err_free_point; + } +@@ -997,6 +1002,33 @@ static int ecc_is_pubkey_valid_partial(c + + } + ++/* SP800-56A section 5.6.2.3.3 full verification */ ++static int ecc_is_pubkey_valid_full(const struct ecc_curve *curve, ++ struct ecc_point *pk) ++{ ++ struct ecc_point *nQ; ++ ++ /* Checks 1 through 3 */ ++ int ret = ecc_is_pubkey_valid_partial(curve, pk); ++ ++ if (ret) ++ return ret; ++ ++ /* Check 4: Verify that nQ is the zero point. */ ++ nQ = ecc_alloc_point(pk->ndigits); ++ if (!nQ) ++ return -ENOMEM; ++ ++ ecc_point_mult(nQ, pk, curve->n, NULL, curve->p, pk->ndigits); ++ if (!ecc_point_is_zero(nQ)) ++ ret = -EINVAL; ++ ++ ecc_free_point(nQ); ++ ++ return ret; ++} ++EXPORT_SYMBOL(ecc_is_pubkey_valid_full); ++ + int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits, + const u8 *private_key, unsigned int private_key_len, + const u8 *public_key, unsigned int public_key_len, diff --git a/patches.suse/crypto-ecdh-check-validity-of-z-before-export b/patches.suse/crypto-ecdh-check-validity-of-z-before-export new file mode 100644 index 0000000..6445767 --- /dev/null +++ b/patches.suse/crypto-ecdh-check-validity-of-z-before-export @@ -0,0 +1,44 @@ +From: =?UTF-8?q?Stephan=20M=C3=BCller?= +Date: Mon, 20 Jul 2020 19:07:48 +0200 +Subject: crypto: ecdh - check validity of Z before export +Git-commit: e7d2b41e5c773c1e00f0f30519b9790ba7e4a58c +Patch-mainline: v5.9-rc1 +References: bsc#1175716 + +SP800-56A rev3 section 5.7.1.2 step 2 mandates that the validity of the +calculated shared secret is verified before the data is returned to the +caller. Thus, the export function and the validity check functions are +reversed. In addition, the sensitive variables of priv and rand_z are +zeroized. + +Signed-off-by: Stephan Mueller +Reviewed-by: Vitaly Chikunov +Acked-by: Neil Horman +Signed-off-by: Herbert Xu +Acked-by: Petr Tesarik +--- + crypto/ecc.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/crypto/ecc.c ++++ b/crypto/ecc.c +@@ -1040,11 +1040,16 @@ int crypto_ecdh_shared_secret(unsigned i + + ecc_point_mult(product, pk, priv, rand_z, curve->p, ndigits); + +- ecc_swap_digits(product->x, (u64 *)secret, ndigits); +- +- if (ecc_point_is_zero(product)) ++ if (ecc_point_is_zero(product)) { + ret = -EFAULT; ++ goto err_validity; ++ } ++ ++ ecc_swap_digits(product->x, (u64 *)secret, ndigits); + ++err_validity: ++ memzero_explicit(priv, sizeof(priv)); ++ memzero_explicit(rand_z, sizeof(rand_z)); + ecc_free_point(product); + err_alloc_product: + ecc_free_point(pk); diff --git a/patches.suse/drm-sun4i-mixer-Extend-regmap-max_register.patch b/patches.suse/drm-sun4i-mixer-Extend-regmap-max_register.patch new file mode 100644 index 0000000..8ce460b --- /dev/null +++ b/patches.suse/drm-sun4i-mixer-Extend-regmap-max_register.patch @@ -0,0 +1,36 @@ +From 74ea06164cda81dc80e97790164ca533fd7e3087 Mon Sep 17 00:00:00 2001 +From: Martin Cerveny +Date: Sun, 6 Sep 2020 18:21:40 +0200 +Subject: [PATCH] drm/sun4i: mixer: Extend regmap max_register +Git-commit: 74ea06164cda81dc80e97790164ca533fd7e3087 +Patch-mainline: v5.9-rc7 +References: git-fixes + +Better guess. Secondary CSC registers are from 0xF0000. + +Signed-off-by: Martin Cerveny +Reviewed-by: Jernej Skrabec +Signed-off-by: Maxime Ripard +Link: https://patchwork.freedesktop.org/patch/msgid/20200906162140.5584-3-m.cerveny@computer.org +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/sun4i/sun8i_mixer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c +index cc4fb916318f..c3304028e3dc 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c +@@ -307,7 +307,7 @@ static struct regmap_config sun8i_mixer_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +- .max_register = 0xbfffc, /* guessed */ ++ .max_register = 0xffffc, /* guessed */ + }; + + static int sun8i_mixer_of_get_id(struct device_node *node) +-- +2.16.4 + diff --git a/patches.suse/geneve-add-transport-ports-in-route-lookup-for-genev.patch b/patches.suse/geneve-add-transport-ports-in-route-lookup-for-genev.patch new file mode 100644 index 0000000..d36aefe --- /dev/null +++ b/patches.suse/geneve-add-transport-ports-in-route-lookup-for-genev.patch @@ -0,0 +1,178 @@ +From 34beb21594519ce64a55a498c2fe7d567bc1ca20 Mon Sep 17 00:00:00 2001 +From: Mark Gray +Date: Wed, 16 Sep 2020 05:19:35 -0400 +Subject: [PATCH] geneve: add transport ports in route lookup for geneve +Git-commit: 34beb21594519ce64a55a498c2fe7d567bc1ca20 +Patch-mainline: v5.9-rc7 +References: CVE-2020-25645 bsc#1177511 + +This patch adds transport ports information for route lookup so that +IPsec can select Geneve tunnel traffic to do encryption. This is +needed for OVS/OVN IPsec with encrypted Geneve tunnels. + +This can be tested by configuring a host-host VPN using an IKE +daemon and specifying port numbers. For example, for an +Openswan-type configuration, the following parameters should be +configured on both hosts and IPsec set up as-per normal: + +$ cat /etc/ipsec.conf + +conn in +... +left=$IP1 +right=$IP2 +... +leftprotoport=udp/6081 +rightprotoport=udp +... +conn out +... +left=$IP1 +right=$IP2 +... +leftprotoport=udp +rightprotoport=udp/6081 +... + +The tunnel can then be setup using "ip" on both hosts (but +changing the relevant IP addresses): + +$ ip link add tun type geneve id 1000 remote $IP2 +$ ip addr add 192.168.0.1/24 dev tun +$ ip link set tun up + +This can then be tested by pinging from $IP1: + +$ ping 192.168.0.2 + +Without this patch the traffic is unencrypted on the wire. + +Fixes: 2d07dc79fe04 ("geneve: add initial netdev driver for GENEVE tunnels") +Signed-off-by: Qiuyu Xiao +Signed-off-by: Mark Gray +Reviewed-by: Greg Rose +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + drivers/net/geneve.c | 37 +++++++++++++++++++++++++++---------- + 1 file changed, 27 insertions(+), 10 deletions(-) + +--- a/drivers/net/geneve.c ++++ b/drivers/net/geneve.c +@@ -705,7 +705,8 @@ free_dst: + static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, + struct net_device *dev, + struct flowi4 *fl4, +- const struct ip_tunnel_info *info) ++ const struct ip_tunnel_info *info, ++ __be16 dport, __be16 sport) + { + bool use_cache = ip_tunnel_dst_cache_usable(skb, info); + struct geneve_dev *geneve = netdev_priv(dev); +@@ -721,6 +722,8 @@ static struct rtable *geneve_get_v4_rt(s + fl4->flowi4_proto = IPPROTO_UDP; + fl4->daddr = info->key.u.ipv4.dst; + fl4->saddr = info->key.u.ipv4.src; ++ fl4->fl4_dport = dport; ++ fl4->fl4_sport = sport; + + tos = info->key.tos; + if ((tos == 1) && !geneve->collect_md) { +@@ -754,7 +757,8 @@ static struct rtable *geneve_get_v4_rt(s + static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, + struct net_device *dev, + struct flowi6 *fl6, +- const struct ip_tunnel_info *info) ++ const struct ip_tunnel_info *info, ++ __be16 dport, __be16 sport) + { + bool use_cache = ip_tunnel_dst_cache_usable(skb, info); + struct geneve_dev *geneve = netdev_priv(dev); +@@ -772,6 +776,9 @@ static struct dst_entry *geneve_get_v6_d + fl6->flowi6_proto = IPPROTO_UDP; + fl6->daddr = info->key.u.ipv6.dst; + fl6->saddr = info->key.u.ipv6.src; ++ fl6->fl6_dport = dport; ++ fl6->fl6_sport = sport; ++ + prio = info->key.tos; + if ((prio == 1) && !geneve->collect_md) { + prio = ip_tunnel_get_dsfield(ip_hdr(skb), skb); +@@ -818,14 +825,15 @@ static int geneve_xmit_skb(struct sk_buf + __be16 df; + int err; + +- rt = geneve_get_v4_rt(skb, dev, &fl4, info); ++ sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); ++ rt = geneve_get_v4_rt(skb, dev, &fl4, info, ++ geneve->info.key.tp_dst, sport); + if (IS_ERR(rt)) + return PTR_ERR(rt); + + skb_tunnel_check_pmtu(skb, &rt->dst, + GENEVE_IPV4_HLEN + info->options_len); + +- sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); + if (geneve->collect_md) { + tos = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb); + ttl = key->ttl; +@@ -860,13 +868,14 @@ static int geneve6_xmit_skb(struct sk_bu + __be16 sport; + int err; + +- dst = geneve_get_v6_dst(skb, dev, &fl6, info); ++ sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); ++ dst = geneve_get_v6_dst(skb, dev, &fl6, info, ++ geneve->info.key.tp_dst, sport); + if (IS_ERR(dst)) + return PTR_ERR(dst); + + skb_tunnel_check_pmtu(skb, dst, GENEVE_IPV6_HLEN + info->options_len); + +- sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); + if (geneve->collect_md) { + prio = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb); + ttl = key->ttl; +@@ -943,12 +952,17 @@ static int geneve_fill_metadata_dst(stru + { + struct ip_tunnel_info *info = skb_tunnel_info(skb); + struct geneve_dev *geneve = netdev_priv(dev); ++ __be16 sport; + + if (ip_tunnel_info_af(info) == AF_INET) { + struct rtable *rt; + struct flowi4 fl4; + +- rt = geneve_get_v4_rt(skb, dev, &fl4, info); ++ sport = udp_flow_src_port(geneve->net, skb, ++ 1, USHRT_MAX, true); ++ ++ rt = geneve_get_v4_rt(skb, dev, &fl4, info, ++ geneve->info.key.tp_dst, sport); + if (IS_ERR(rt)) + return PTR_ERR(rt); + +@@ -959,7 +973,11 @@ static int geneve_fill_metadata_dst(stru + struct dst_entry *dst; + struct flowi6 fl6; + +- dst = geneve_get_v6_dst(skb, dev, &fl6, info); ++ sport = udp_flow_src_port(geneve->net, skb, ++ 1, USHRT_MAX, true); ++ ++ dst = geneve_get_v6_dst(skb, dev, &fl6, info, ++ geneve->info.key.tp_dst, sport); + if (IS_ERR(dst)) + return PTR_ERR(dst); + +@@ -970,8 +988,7 @@ static int geneve_fill_metadata_dst(stru + return -EINVAL; + } + +- info->key.tp_src = udp_flow_src_port(geneve->net, skb, +- 1, USHRT_MAX, true); ++ info->key.tp_src = sport; + info->key.tp_dst = geneve->info.key.tp_dst; + return 0; + } diff --git a/patches.suse/i2c-meson-fix-clock-setting-overwrite.patch b/patches.suse/i2c-meson-fix-clock-setting-overwrite.patch new file mode 100644 index 0000000..8cfa2fb --- /dev/null +++ b/patches.suse/i2c-meson-fix-clock-setting-overwrite.patch @@ -0,0 +1,81 @@ +From 28683e847e2f20eed22cdd24f185d7783db396d3 Mon Sep 17 00:00:00 2001 +From: Jerome Brunet +Date: Wed, 7 Oct 2020 10:07:49 +0200 +Subject: [PATCH] i2c: meson: fix clock setting overwrite +Git-commit: 28683e847e2f20eed22cdd24f185d7783db396d3 +Patch-mainline: v5.9 +References: git-fixes + +When the slave address is written in do_start(), SLAVE_ADDR is written +completely. This may overwrite some setting related to the clock rate +or signal filtering. + +Fix this by writing only the bits related to slave address. To avoid +causing unexpected changed, explicitly disable filtering or high/low +clock mode which may have been left over by the bootloader. + +Fixes: 30021e3707a7 ("i2c: add support for Amlogic Meson I2C controller") +Signed-off-by: Jerome Brunet +Signed-off-by: Wolfram Sang +Acked-by: Takashi Iwai + +--- + drivers/i2c/busses/i2c-meson.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +--- a/drivers/i2c/busses/i2c-meson.c ++++ b/drivers/i2c/busses/i2c-meson.c +@@ -8,6 +8,7 @@ + * published by the Free Software Foundation. + */ + ++#include + #include + #include + #include +@@ -39,6 +40,12 @@ + #define REG_CTRL_CLKDIVEXT_SHIFT 28 + #define REG_CTRL_CLKDIVEXT_MASK GENMASK(29, 28) + ++#define REG_SLV_ADDR GENMASK(7, 0) ++#define REG_SLV_SDA_FILTER GENMASK(10, 8) ++#define REG_SLV_SCL_FILTER GENMASK(13, 11) ++#define REG_SLV_SCL_LOW GENMASK(27, 16) ++#define REG_SLV_SCL_LOW_EN BIT(28) ++ + #define I2C_TIMEOUT_MS 500 + + enum { +@@ -142,6 +149,9 @@ static void meson_i2c_set_clk_div(struct + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT_MASK, + (div >> 10) << REG_CTRL_CLKDIVEXT_SHIFT); + ++ /* Disable HIGH/LOW mode */ ++ meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_SCL_LOW_EN, 0); ++ + dev_dbg(i2c->dev, "%s: clk %lu, freq %u, div %u\n", __func__, + clk_rate, freq, div); + } +@@ -269,7 +279,10 @@ static void meson_i2c_do_start(struct me + token = (msg->flags & I2C_M_RD) ? TOKEN_SLAVE_ADDR_READ : + TOKEN_SLAVE_ADDR_WRITE; + +- writel(msg->addr << 1, i2c->regs + REG_SLAVE_ADDR); ++ ++ meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_ADDR, ++ FIELD_PREP(REG_SLV_ADDR, msg->addr << 1)); ++ + meson_i2c_add_token(i2c, TOKEN_START); + meson_i2c_add_token(i2c, token); + } +@@ -425,6 +438,10 @@ static int meson_i2c_probe(struct platfo + return ret; + } + ++ /* Disable filtering */ ++ meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, ++ REG_SLV_SDA_FILTER | REG_SLV_SCL_FILTER, 0); ++ + meson_i2c_set_clk_div(i2c, timings.bus_freq_hz); + + return 0; diff --git a/patches.suse/lib-mpi-add-mpi_sub_ui b/patches.suse/lib-mpi-add-mpi_sub_ui new file mode 100644 index 0000000..6b635c1 --- /dev/null +++ b/patches.suse/lib-mpi-add-mpi_sub_ui @@ -0,0 +1,128 @@ +From: Marcelo Henrique Cerri +Date: Mon, 20 Jul 2020 19:08:09 +0200 +Subject: lib/mpi: Add mpi_sub_ui() +Git-commit: 4278e9d99e38938a7611b927fa4d73e6c86cb4fc +Patch-mainline: v5.9-rc1 +References: bsc#1175716 + +Add mpi_sub_ui() based on Gnu MP mpz_sub_ui() function from file +mpz/aors_ui.h[1] from change id 510b83519d1c adapting the code to the +kernel's data structures, helper functions and coding style and also +removing the defines used to produce mpz_sub_ui() and mpz_add_ui() +from the same code. + +[1] https://gmplib.org/repo/gmp-6.2/file/510b83519d1c/mpz/aors.h + +Signed-off-by: Marcelo Henrique Cerri +Signed-off-by: Stephan Mueller +Signed-off-by: Herbert Xu +Acked-by: Petr Tesarik +--- + include/linux/mpi.h | 3 + + lib/mpi/Makefile | 1 + lib/mpi/mpi-sub-ui.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 82 insertions(+) + +--- a/include/linux/mpi.h ++++ b/include/linux/mpi.h +@@ -123,6 +123,9 @@ int mpi_mulpowm(MPI res, MPI *basearray, + int mpi_cmp_ui(MPI u, ulong v); + int mpi_cmp(MPI u, MPI v); + ++/*-- mpi-sub-ui.c --*/ ++int mpi_sub_ui(MPI w, MPI u, unsigned long vval); ++ + /*-- mpi-scan.c --*/ + int mpi_getbyte(MPI a, unsigned idx); + void mpi_putbyte(MPI a, unsigned idx, int value); +--- a/lib/mpi/Makefile ++++ b/lib/mpi/Makefile +@@ -15,6 +15,7 @@ mpi-y = \ + mpicoder.o \ + mpi-bit.o \ + mpi-cmp.o \ ++ mpi-sub-ui.o \ + mpih-cmp.o \ + mpih-div.o \ + mpih-mul.o \ +--- /dev/null ++++ b/lib/mpi/mpi-sub-ui.c +@@ -0,0 +1,78 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* mpi-sub-ui.c - Subtract an unsigned integer from an MPI. ++ * ++ * Copyright 1991, 1993, 1994, 1996, 1999-2002, 2004, 2012, 2013, 2015 ++ * Free Software Foundation, Inc. ++ * ++ * This file was based on the GNU MP Library source file: ++ * https://gmplib.org/repo/gmp-6.2/file/510b83519d1c/mpz/aors_ui.h ++ * ++ * The GNU MP Library is free software; you can redistribute it and/or modify ++ * it under the terms of either: ++ * ++ * * the GNU Lesser General Public License as published by the Free ++ * Software Foundation; either version 3 of the License, or (at your ++ * option) any later version. ++ * ++ * or ++ * ++ * * the GNU General Public License as published by the Free Software ++ * Foundation; either version 2 of the License, or (at your option) any ++ * later version. ++ * ++ * or both in parallel, as here. ++ * ++ * The GNU MP Library is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * You should have received copies of the GNU General Public License and the ++ * GNU Lesser General Public License along with the GNU MP Library. If not, ++ * see https://www.gnu.org/licenses/. ++ */ ++ ++#include "mpi-internal.h" ++ ++int mpi_sub_ui(MPI w, MPI u, unsigned long vval) ++{ ++ if (u->nlimbs == 0) { ++ if (mpi_resize(w, 1) < 0) ++ return -ENOMEM; ++ w->d[0] = vval; ++ w->nlimbs = (vval != 0); ++ w->sign = (vval != 0); ++ return 0; ++ } ++ ++ /* If not space for W (and possible carry), increase space. */ ++ if (mpi_resize(w, u->nlimbs + 1)) ++ return -ENOMEM; ++ ++ if (u->sign) { ++ mpi_limb_t cy; ++ ++ cy = mpihelp_add_1(w->d, u->d, u->nlimbs, (mpi_limb_t) vval); ++ w->d[u->nlimbs] = cy; ++ w->nlimbs = u->nlimbs + cy; ++ w->sign = 1; ++ } else { ++ /* The signs are different. Need exact comparison to determine ++ * which operand to subtract from which. ++ */ ++ if (u->nlimbs == 1 && u->d[0] < vval) { ++ w->d[0] = vval - u->d[0]; ++ w->nlimbs = 1; ++ w->sign = 1; ++ } else { ++ mpihelp_sub_1(w->d, u->d, u->nlimbs, (mpi_limb_t) vval); ++ /* Size can decrease with at most one limb. */ ++ w->nlimbs = (u->nlimbs - (w->d[u->nlimbs - 1] == 0)); ++ w->sign = 0; ++ } ++ } ++ ++ mpi_normalize(w); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(mpi_sub_ui); diff --git a/patches.suse/mac80211-do-not-allow-bigger-VHT-MPDUs-than-the-hard.patch b/patches.suse/mac80211-do-not-allow-bigger-VHT-MPDUs-than-the-hard.patch new file mode 100644 index 0000000..101ffdb --- /dev/null +++ b/patches.suse/mac80211-do-not-allow-bigger-VHT-MPDUs-than-the-hard.patch @@ -0,0 +1,48 @@ +From 3bd5c7a28a7c3aba07a2d300d43f8e988809e147 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 17 Sep 2020 14:50:31 +0200 +Subject: [PATCH] mac80211: do not allow bigger VHT MPDUs than the hardware supports +Git-commit: 3bd5c7a28a7c3aba07a2d300d43f8e988809e147 +Patch-mainline: v5.9-rc7 +References: git-fixes + +Limit maximum VHT MPDU size by local capability. + +Signed-off-by: Felix Fietkau +Link: https://lore.kernel.org/r/20200917125031.45009-1-nbd@nbd.name +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + net/mac80211/vht.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c +index 9c6045f9c24d..d1b64d0751f2 100644 +--- a/net/mac80211/vht.c ++++ b/net/mac80211/vht.c +@@ -168,10 +168,7 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, + /* take some capabilities as-is */ + cap_info = le32_to_cpu(vht_cap_ie->vht_cap_info); + vht_cap->cap = cap_info; +- vht_cap->cap &= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 | +- IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | +- IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | +- IEEE80211_VHT_CAP_RXLDPC | ++ vht_cap->cap &= IEEE80211_VHT_CAP_RXLDPC | + IEEE80211_VHT_CAP_VHT_TXOP_PS | + IEEE80211_VHT_CAP_HTC_VHT | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | +@@ -180,6 +177,9 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, + IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | + IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; + ++ vht_cap->cap |= min_t(u32, cap_info & IEEE80211_VHT_CAP_MAX_MPDU_MASK, ++ own_cap.cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK); ++ + /* and some based on our own capabilities */ + switch (own_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { + case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: +-- +2.16.4 + diff --git a/patches.suse/macsec-avoid-use-after-free-in-macsec_handle_frame.patch b/patches.suse/macsec-avoid-use-after-free-in-macsec_handle_frame.patch new file mode 100644 index 0000000..1b8aadb --- /dev/null +++ b/patches.suse/macsec-avoid-use-after-free-in-macsec_handle_frame.patch @@ -0,0 +1,44 @@ +From c7cc9200e9b4a2ac172e990ef1975cd42975dad6 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 7 Oct 2020 01:42:46 -0700 +Subject: [PATCH] macsec: avoid use-after-free in macsec_handle_frame() +Git-commit: c7cc9200e9b4a2ac172e990ef1975cd42975dad6 +Patch-mainline: v5.9 +References: git-fixes + +De-referencing skb after call to gro_cells_receive() is not allowed. +We need to fetch skb->len earlier. + +Fixes: 5491e7c6b1a9 ("macsec: enable GRO and RPS on macsec devices") +Signed-off-by: Eric Dumazet +Cc: Paolo Abeni +Acked-by: Paolo Abeni +Signed-off-by: Jakub Kicinski +Acked-by: Takashi Iwai + +--- + drivers/net/macsec.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/net/macsec.c ++++ b/drivers/net/macsec.c +@@ -1084,6 +1084,7 @@ static rx_handler_result_t macsec_handle + struct macsec_rx_sa *rx_sa; + struct macsec_rxh_data *rxd; + struct macsec_dev *macsec; ++ unsigned int len; + sci_t sci; + u32 pn; + bool cbit; +@@ -1239,9 +1240,10 @@ deliver: + macsec_rxsc_put(rx_sc); + + skb_orphan(skb); ++ len = skb->len; + ret = gro_cells_receive(&macsec->gro_cells, skb); + if (ret == NET_RX_SUCCESS) +- count_rx(dev, skb->len); ++ count_rx(dev, len); + else + macsec->secy.netdev->stats.rx_dropped++; + diff --git a/patches.suse/mm-remove-__GFP_COLD.patch b/patches.suse/mm-remove-__GFP_COLD.patch index 2d02c64..bf45f42 100644 --- a/patches.suse/mm-remove-__GFP_COLD.patch +++ b/patches.suse/mm-remove-__GFP_COLD.patch @@ -40,7 +40,6 @@ Cc: Vlastimil Babka Signed-off-by: Andrew Morton --- drivers/net/ethernet/amazon/ena/ena_netdev.c | 2 - - drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 2 - drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 3 -- drivers/net/ethernet/cavium/liquidio/octeon_network.h | 2 - drivers/net/ethernet/mellanox/mlx4/en_rx.c | 5 +--- @@ -78,17 +77,6 @@ Signed-off-by: Andrew Morton if (unlikely(rc < 0)) { netif_warn(rx_ring->adapter, rx_err, rx_ring->netdev, "failed to alloc buffer for rx queue %d\n", ---- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c -+++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c -@@ -268,7 +268,7 @@ static int xgbe_alloc_pages(struct xgbe_ - int ret; - - /* Try to obtain pages, decreasing order if necessary */ -- gfp |= __GFP_COLD | __GFP_COMP | __GFP_NOWARN; -+ gfp |= __GFP_COMP | __GFP_NOWARN; - while (order >= 0) { - pages = alloc_pages(gfp, order); - if (pages) --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c @@ -265,8 +265,7 @@ int aq_ring_rx_fill(struct aq_ring_s *se diff --git a/patches.suse/mmc-core-don-t-set-limits.discard_granularity-as-0.patch b/patches.suse/mmc-core-don-t-set-limits.discard_granularity-as-0.patch new file mode 100644 index 0000000..1dad544 --- /dev/null +++ b/patches.suse/mmc-core-don-t-set-limits.discard_granularity-as-0.patch @@ -0,0 +1,71 @@ +From 4243219141b67d7c2fdb2d8073c17c539b9263eb Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Fri, 2 Oct 2020 09:38:52 +0800 +Subject: [PATCH] mmc: core: don't set limits.discard_granularity as 0 +Git-commit: 4243219141b67d7c2fdb2d8073c17c539b9263eb +Patch-mainline: v5.9 +References: git-fixes + +In mmc_queue_setup_discard() the mmc driver queue's discard_granularity +might be set as 0 (when card->pref_erase > max_discard) while the mmc +device still declares to support discard operation. This is buggy and +triggered the following kernel warning message, + +Warning: CPU: 0 PID: 135 at __blkdev_issue_discard+0x200/0x294 +Cpu: 0 PID: 135 Comm: f2fs_discard-17 Not tainted 5.9.0-rc6 #1 +Hardware name: Google Kevin (DT) +Pstate: 00000005 (nzcv daif -PAN -UAO BTYPE=--) +pc : __blkdev_issue_discard+0x200/0x294 +lr : __blkdev_issue_discard+0x54/0x294 +sp : ffff800011dd3b10 +X29: ffff800011dd3b10 x28: 0000000000000000 x27: ffff800011dd3cc4 x26: ffff800011dd3e18 x25: 000000000004e69b x24: 0000000000000c40 x23: ffff0000f1deaaf0 x22: ffff0000f2849200 x21: 00000000002734d8 x20: 0000000000000008 x19: 0000000000000000 x18: 0000000000000000 x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 x14: 0000000000000394 x13: 0000000000000000 x12: 0000000000000000 x11: 0000000000000000 x10: 00000000000008b0 x9 : ffff800011dd3cb0 x8 : 000000000004e69b x7 : 0000000000000000 x6 : ffff0000f1926400 x5 : ffff0000f1940800 x4 : 0000000000000000 x3 : 0000000000000c40 x2 : 0000000000000008 x1 : 00000000002734d8 x0 : 0000000000000000 Call trace: +__blkdev_issue_discard+0x200/0x294 +__submit_discard_cmd+0x128/0x374 +__issue_discard_cmd_orderly+0x188/0x244 +__issue_discard_cmd+0x2e8/0x33c +issue_discard_thread+0xe8/0x2f0 +kthread+0x11c/0x120 +ret_from_fork+0x10/0x1c + +Acked-by: Takashi Iwai + +---[ end trace e4c8023d33dfe77a ]--- + +This patch fixes the issue by setting discard_granularity as SECTOR_SIZE +instead of 0 when (card->pref_erase > max_discard) is true. Now no more +complain from __blkdev_issue_discard() for the improper value of discard +granularity. + +This issue is exposed after commit b35fd7422c2f ("block: check queue's +limits.discard_granularity in __blkdev_issue_discard()"), a "Fixes:" tag +is also added for the commit to make sure people won't miss this patch +after applying the change of __blkdev_issue_discard(). + +Fixes: e056a1b5b67b ("mmc: queue: let host controllers specify maximum discard timeout") +Fixes: b35fd7422c2f ("block: check queue's limits.discard_granularity in __blkdev_issue_discard()"). +Reported-and-tested-by: Vicente Bergas +Signed-off-by: Coly Li +Acked-by: Adrian Hunter +Cc: Ulf Hansson +Link: https://lore.kernel.org/r/20201002013852.51968-1-colyli@suse.de +Signed-off-by: Ulf Hansson +--- + drivers/mmc/core/queue.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c +index 6c022ef0f84d..350d0cc4ee62 100644 +--- a/drivers/mmc/core/queue.c ++++ b/drivers/mmc/core/queue.c +@@ -190,7 +190,7 @@ static void mmc_queue_setup_discard(struct request_queue *q, + q->limits.discard_granularity = card->pref_erase << 9; + /* granularity must not be greater than max. discard */ + if (card->pref_erase > max_discard) +- q->limits.discard_granularity = 0; ++ q->limits.discard_granularity = SECTOR_SIZE; + if (mmc_can_secure_erase_trim(card)) + blk_queue_flag_set(QUEUE_FLAG_SECERASE, q); + } +-- +2.16.4 + diff --git a/patches.suse/nfs-Fix-getxattr-kernel-panic-and-memory-overflow.patch b/patches.suse/nfs-Fix-getxattr-kernel-panic-and-memory-overflow.patch index d1500ca..83bca25 100644 --- a/patches.suse/nfs-Fix-getxattr-kernel-panic-and-memory-overflow.patch +++ b/patches.suse/nfs-Fix-getxattr-kernel-panic-and-memory-overflow.patch @@ -3,7 +3,7 @@ Date: Wed, 5 Aug 2020 12:23:19 -0500 Subject: [PATCH] nfs: Fix getxattr kernel panic and memory overflow Git-commit: b4487b93545214a9db8cbf32e86411677b0cca21 Patch-mainline: v5.9 -References: bsc#1176381 CVE-2020-2521 +References: bsc#1176381 CVE-2020-25212 Move the buffer size check to decode_attr_security_label() before memcpy() Only call memcpy() if the buffer is large enough diff --git a/patches.suse/nfs-Fix-security-label-length-not-being-reset.patch b/patches.suse/nfs-Fix-security-label-length-not-being-reset.patch new file mode 100644 index 0000000..6222e82 --- /dev/null +++ b/patches.suse/nfs-Fix-security-label-length-not-being-reset.patch @@ -0,0 +1,44 @@ +From: Jeffrey Mitchell +Date: Tue, 15 Sep 2020 16:42:52 -0500 +Subject: [PATCH] nfs: Fix security label length not being reset +Git-commit: d33030e2ee3508d65db5644551435310df86010e +Patch-mainline: v5.9 +References: bsc#1176381 CVE-2020-25212 + +nfs_readdir_page_filler() iterates over entries in a directory, reusing +the same security label buffer, but does not reset the buffer's length. +This causes decode_attr_security_label() to return -ERANGE if an entry's +security label is longer than the previous one's. This error, in +nfs4_decode_dirent(), only gets passed up as -EAGAIN, which causes another +failed attempt to copy into the buffer. The second error is ignored and +the remaining entries do not show up in ls, specifically the getdents64() +syscall. + +Reproduce by creating multiple files in NFS and giving one of the later +files a longer security label. ls will not see that file nor any that are +added afterwards, though they will exist on the backend. + +In nfs_readdir_page_filler(), reset security label buffer length before +every reuse + +Signed-off-by: Jeffrey Mitchell +Fixes: b4487b935452 ("nfs: Fix getxattr kernel panic and memory overflow") +Signed-off-by: Trond Myklebust +Acked-by: NeilBrown + +--- + fs/nfs/dir.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -548,6 +548,9 @@ int nfs_readdir_page_filler(nfs_readdir_ + xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); + + do { ++ if (entry->label) ++ entry->label->len = NFS4_MAXLABELLEN; ++ + status = xdr_decode(desc, entry, &stream); + if (status != 0) { + if (status == -EAGAIN) diff --git a/patches.suse/scsi-iscsi-iscsi_tcp-avoid-holding-spinlock-while-calling-getpeername b/patches.suse/scsi-iscsi-iscsi_tcp-avoid-holding-spinlock-while-calling-getpeername new file mode 100644 index 0000000..512e394 --- /dev/null +++ b/patches.suse/scsi-iscsi-iscsi_tcp-avoid-holding-spinlock-while-calling-getpeername @@ -0,0 +1,103 @@ +From: Mark Mielke +Date: Mon, 28 Sep 2020 00:33:29 -0400 +Subject: scsi: iscsi: iscsi_tcp: Avoid holding spinlock while calling + getpeername() [REFRESHED] +Git-commit: bcf3a2953d36bbfb9bd44ccb3db0897d935cc485 +Patch-mainline: v5.9 or v5.9-rc8 (next release) +References: bsc#1177258 + +The kernel may fail to boot or devices may fail to come up when +initializing iscsi_tcp devices starting with Linux 5.8. + +Commit a79af8a64d39 ("[SCSI] iscsi_tcp: use iscsi_conn_get_addr_param +libiscsi function") introduced getpeername() within the session spinlock. + +Commit 1b66d253610c ("bpf: Add get{peer, sock}name attach types for +sock_addr") introduced BPF_CGROUP_RUN_SA_PROG_LOCK() within getpeername(), +which acquires a mutex and when used from iscsi_tcp devices can now lead to +"BUG: scheduling while atomic:" and subsequent damage. + +Ensure that the spinlock is released before calling getpeername() or +getsockname(). sock_hold() and sock_put() are used to ensure that the +socket reference is preserved until after the getpeername() or +getsockname() complete. + +Link: https://bugzilla.redhat.com/show_bug.cgi?id=1877345 +Link: https://lkml.org/lkml/2020/7/28/1085 +Link: https://lkml.org/lkml/2020/8/31/459 +Link: https://lore.kernel.org/r/20200928043329.606781-1-mark.mielke@gmail.com +Fixes: a79af8a64d39 ("[SCSI] iscsi_tcp: use iscsi_conn_get_addr_param libiscsi function") +Fixes: 1b66d253610c ("bpf: Add get{peer, sock}name attach types for sock_addr") +Cc: stable@vger.kernel.org +Reported-by: Marc Dionne +Tested-by: Marc Dionne +Reviewed-by: Mike Christie +Signed-off-by: Mark Mielke +Signed-off-by: Martin K. Petersen +Acked-by: Lee Duncan +--- + drivers/scsi/iscsi_tcp.c | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +--- a/drivers/scsi/iscsi_tcp.c ++++ b/drivers/scsi/iscsi_tcp.c +@@ -733,6 +733,7 @@ static int iscsi_sw_tcp_conn_get_param(s + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; + struct sockaddr_in6 addr; ++ struct socket *sock; + int rc, len; + + switch(param) { +@@ -744,13 +745,17 @@ static int iscsi_sw_tcp_conn_get_param(s + spin_unlock_bh(&conn->session->frwd_lock); + return -ENOTCONN; + } ++ sock = tcp_sw_conn->sock; ++ sock_hold(sock->sk); ++ spin_unlock_bh(&conn->session->frwd_lock); ++ + if (param == ISCSI_PARAM_LOCAL_PORT) +- rc = kernel_getsockname(tcp_sw_conn->sock, ++ rc = kernel_getsockname(sock, + (struct sockaddr *)&addr, &len); + else +- rc = kernel_getpeername(tcp_sw_conn->sock, ++ rc = kernel_getpeername(sock, + (struct sockaddr *)&addr, &len); +- spin_unlock_bh(&conn->session->frwd_lock); ++ sock_put(sock->sk); + if (rc) + return rc; + +@@ -772,6 +777,7 @@ static int iscsi_sw_tcp_host_get_param(s + struct iscsi_tcp_conn *tcp_conn; + struct iscsi_sw_tcp_conn *tcp_sw_conn; + struct sockaddr_in6 addr; ++ struct socket *sock; + int rc, len; + + switch (param) { +@@ -786,16 +792,18 @@ static int iscsi_sw_tcp_host_get_param(s + return -ENOTCONN; + } + tcp_conn = conn->dd_data; +- + tcp_sw_conn = tcp_conn->dd_data; +- if (!tcp_sw_conn->sock) { ++ sock = tcp_sw_conn->sock; ++ if (!sock) { + spin_unlock_bh(&session->frwd_lock); + return -ENOTCONN; + } ++ sock_hold(sock->sk); ++ spin_unlock_bh(&session->frwd_lock); + +- rc = kernel_getsockname(tcp_sw_conn->sock, ++ rc = kernel_getsockname(sock, + (struct sockaddr *)&addr, &len); +- spin_unlock_bh(&session->frwd_lock); ++ sock_put(sock->sk); + if (rc) + return rc; + diff --git a/patches.suse/scsi-qla2xxx-Add-IOCB-resource-tracking.patch b/patches.suse/scsi-qla2xxx-Add-IOCB-resource-tracking.patch new file mode 100644 index 0000000..4c22b5a --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Add-IOCB-resource-tracking.patch @@ -0,0 +1,358 @@ +From: Quinn Tran +Date: Thu, 3 Sep 2020 21:51:26 -0700 +Subject: scsi: qla2xxx: Add IOCB resource tracking +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 89c72f4245a8510ffdb0d1980944210b8bc6e49f +References: bsc#1176946 bsc#1175520 bsc#1172538 + +This patch tracks number of IOCB resources used in the I/O fast path. If +the number of used IOCBs reach a high water limit, driver would return the +I/O as busy and let upper layer retry. This prevents over subscription of +IOCB resources where any future error recovery command is unable to cut +through. Enable IOCB throttling by default. + +Link: https://lore.kernel.org/r/20200904045128.23631-12-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Arun Easi +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +[dwagner: context updated] +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_def.h | 17 +++++++++++ + drivers/scsi/qla2xxx/qla_dfs.c | 14 +++++++++ + drivers/scsi/qla2xxx/qla_gbl.h | 3 ++ + drivers/scsi/qla2xxx/qla_init.c | 26 +++++++++++++++++ + drivers/scsi/qla2xxx/qla_inline.h | 55 ++++++++++++++++++++++++++++++++++++++ + drivers/scsi/qla2xxx/qla_iocb.c | 28 +++++++++++++++++++ + drivers/scsi/qla2xxx/qla_isr.c | 2 + + drivers/scsi/qla2xxx/qla_os.c | 6 ++++ + 8 files changed, 151 insertions(+) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -624,6 +624,12 @@ enum { + TYPE_TGT_TMCMD, /* task management */ + }; + ++struct iocb_resource { ++ u8 res_type; ++ u8 pad; ++ u16 iocb_cnt; ++}; ++ + typedef struct srb { + /* + * Do not move cmd_type field, it needs to +@@ -631,6 +637,7 @@ typedef struct srb { + */ + uint8_t cmd_type; + uint8_t pad[3]; ++ struct iocb_resource iores; + struct kref cmd_kref; /* need to migrate ref_count over to this */ + void *priv; + wait_queue_head_t nvme_ls_waitq; +@@ -3577,6 +3584,15 @@ struct req_que { + uint8_t req_pkt[REQUEST_ENTRY_SIZE]; + }; + ++struct qla_fw_resources { ++ u16 iocbs_total; ++ u16 iocbs_limit; ++ u16 iocbs_qp_limit; ++ u16 iocbs_used; ++}; ++ ++#define QLA_IOCB_PCT_LIMIT 95 ++ + /*Queue pair data structure */ + struct qla_qpair { + spinlock_t qp_lock; +@@ -3629,6 +3645,7 @@ struct qla_qpair { + uint64_t retry_term_jiff; + struct qla_tgt_counters tgt_counters; + uint16_t cpuid; ++ struct qla_fw_resources fwres ____cacheline_aligned; + }; + + /* Place holder for FW buffer parameters */ +--- a/drivers/scsi/qla2xxx/qla_dfs.c ++++ b/drivers/scsi/qla2xxx/qla_dfs.c +@@ -261,6 +261,8 @@ qla_dfs_fw_resource_cnt_show(struct seq_ + struct scsi_qla_host *vha = s->private; + uint16_t mb[MAX_IOCB_MB_REG]; + int rc; ++ struct qla_hw_data *ha = vha->hw; ++ u16 iocbs_used, i; + + rc = qla24xx_res_count_wait(vha, mb, SIZEOF_IOCB_MB_REG); + if (rc != QLA_SUCCESS) { +@@ -285,6 +287,18 @@ qla_dfs_fw_resource_cnt_show(struct seq_ + mb[23]); + } + ++ if (ql2xenforce_iocb_limit) { ++ /* lock is not require. It's an estimate. */ ++ iocbs_used = ha->base_qpair->fwres.iocbs_used; ++ for (i = 0; i < ha->max_qpairs; i++) { ++ if (ha->queue_pair_map[i]) ++ iocbs_used += ha->queue_pair_map[i]->fwres.iocbs_used; ++ } ++ ++ seq_printf(s, "Driver: estimate iocb used [%d] high water limit [%d]\n", ++ iocbs_used, ha->base_qpair->fwres.iocbs_limit); ++ } ++ + return 0; + } + +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -129,6 +129,8 @@ int qla2x00_reserve_mgmt_server_loop_id( + void qla_rscn_replay(fc_port_t *fcport); + void qla24xx_free_purex_item(struct purex_item *item); + extern bool qla24xx_risc_firmware_invalid(uint32_t *); ++void qla_init_iocb_limit(scsi_qla_host_t *); ++ + + /* + * Global Data in qla_os.c source file. +@@ -175,6 +177,7 @@ extern int qla2xuseresexchforels; + extern int ql2xexlogins; + extern int ql2xdifbundlinginternalbuffers; + extern int ql2xfulldump_on_mpifail; ++extern int ql2xenforce_iocb_limit; + + extern int qla2x00_loop_reset(scsi_qla_host_t *); + extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -3632,6 +3632,31 @@ qla24xx_detect_sfp(scsi_qla_host_t *vha) + return ha->flags.lr_detected; + } + ++void qla_init_iocb_limit(scsi_qla_host_t *vha) ++{ ++ u16 i, num_qps; ++ u32 limit; ++ struct qla_hw_data *ha = vha->hw; ++ ++ num_qps = ha->num_qpairs + 1; ++ limit = (ha->orig_fw_iocb_count * QLA_IOCB_PCT_LIMIT) / 100; ++ ++ ha->base_qpair->fwres.iocbs_total = ha->orig_fw_iocb_count; ++ ha->base_qpair->fwres.iocbs_limit = limit; ++ ha->base_qpair->fwres.iocbs_qp_limit = limit / num_qps; ++ ha->base_qpair->fwres.iocbs_used = 0; ++ for (i = 0; i < ha->max_qpairs; i++) { ++ if (ha->queue_pair_map[i]) { ++ ha->queue_pair_map[i]->fwres.iocbs_total = ++ ha->orig_fw_iocb_count; ++ ha->queue_pair_map[i]->fwres.iocbs_limit = limit; ++ ha->queue_pair_map[i]->fwres.iocbs_qp_limit = ++ limit / num_qps; ++ ha->queue_pair_map[i]->fwres.iocbs_used = 0; ++ } ++ } ++} ++ + /** + * qla2x00_setup_chip() - Load and start RISC firmware. + * @vha: HA context +@@ -3731,6 +3756,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) + MIN_MULTI_ID_FABRIC - 1; + } + qla2x00_get_resource_cnts(vha); ++ qla_init_iocb_limit(vha); + + /* + * Allocate the array of outstanding commands +--- a/drivers/scsi/qla2xxx/qla_inline.h ++++ b/drivers/scsi/qla2xxx/qla_inline.h +@@ -378,3 +378,58 @@ qla2xxx_get_fc4_priority(struct scsi_qla + + return (data >> 6) & BIT_0 ? FC4_PRIORITY_FCP : FC4_PRIORITY_NVME; + } ++ ++enum { ++ RESOURCE_NONE, ++ RESOURCE_INI, ++}; ++ ++static inline int ++qla_get_iocbs(struct qla_qpair *qp, struct iocb_resource *iores) ++{ ++ u16 iocbs_used, i; ++ struct qla_hw_data *ha = qp->vha->hw; ++ ++ if (!ql2xenforce_iocb_limit) { ++ iores->res_type = RESOURCE_NONE; ++ return 0; ++ } ++ ++ if ((iores->iocb_cnt + qp->fwres.iocbs_used) < qp->fwres.iocbs_qp_limit) { ++ qp->fwres.iocbs_used += iores->iocb_cnt; ++ return 0; ++ } else { ++ /* no need to acquire qpair lock. It's just rough calculation */ ++ iocbs_used = ha->base_qpair->fwres.iocbs_used; ++ for (i = 0; i < ha->max_qpairs; i++) { ++ if (ha->queue_pair_map[i]) ++ iocbs_used += ha->queue_pair_map[i]->fwres.iocbs_used; ++ } ++ ++ if ((iores->iocb_cnt + iocbs_used) < qp->fwres.iocbs_limit) { ++ qp->fwres.iocbs_used += iores->iocb_cnt; ++ return 0; ++ } else { ++ iores->res_type = RESOURCE_NONE; ++ return -ENOSPC; ++ } ++ } ++} ++ ++static inline void ++qla_put_iocbs(struct qla_qpair *qp, struct iocb_resource *iores) ++{ ++ switch (iores->res_type) { ++ case RESOURCE_NONE: ++ break; ++ default: ++ if (qp->fwres.iocbs_used >= iores->iocb_cnt) { ++ qp->fwres.iocbs_used -= iores->iocb_cnt; ++ } else { ++ // should not happen ++ qp->fwres.iocbs_used = 0; ++ } ++ break; ++ } ++ iores->res_type = RESOURCE_NONE; ++} +--- a/drivers/scsi/qla2xxx/qla_iocb.c ++++ b/drivers/scsi/qla2xxx/qla_iocb.c +@@ -1637,6 +1637,12 @@ qla24xx_start_scsi(srb_t *sp) + + tot_dsds = nseg; + req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); ++ ++ sp->iores.res_type = RESOURCE_INI; ++ sp->iores.iocb_cnt = req_cnt; ++ if (qla_get_iocbs(sp->qpair, &sp->iores)) ++ goto queuing_error; ++ + if (req->cnt < (req_cnt + 2)) { + cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr : + rd_reg_dword_relaxed(req->req_q_out); +@@ -1709,6 +1715,7 @@ qla24xx_start_scsi(srb_t *sp) + if (tot_dsds) + scsi_dma_unmap(cmd); + ++ qla_put_iocbs(sp->qpair, &sp->iores); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return QLA_FUNCTION_FAILED; +@@ -1822,6 +1829,12 @@ qla24xx_dif_start_scsi(srb_t *sp) + /* Total Data and protection sg segment(s) */ + tot_prot_dsds = nseg; + tot_dsds += nseg; ++ ++ sp->iores.res_type = RESOURCE_INI; ++ sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds); ++ if (qla_get_iocbs(sp->qpair, &sp->iores)) ++ goto queuing_error; ++ + if (req->cnt < (req_cnt + 2)) { + cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr : + rd_reg_dword_relaxed(req->req_q_out); +@@ -1896,6 +1909,7 @@ qla24xx_dif_start_scsi(srb_t *sp) + } + /* Cleanup will be performed by the caller (queuecommand) */ + ++ qla_put_iocbs(sp->qpair, &sp->iores); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return QLA_FUNCTION_FAILED; + } +@@ -1957,6 +1971,12 @@ qla2xxx_start_scsi_mq(srb_t *sp) + + tot_dsds = nseg; + req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); ++ ++ sp->iores.res_type = RESOURCE_INI; ++ sp->iores.iocb_cnt = req_cnt; ++ if (qla_get_iocbs(sp->qpair, &sp->iores)) ++ goto queuing_error; ++ + if (req->cnt < (req_cnt + 2)) { + cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr : + rd_reg_dword_relaxed(req->req_q_out); +@@ -2029,6 +2049,7 @@ qla2xxx_start_scsi_mq(srb_t *sp) + if (tot_dsds) + scsi_dma_unmap(cmd); + ++ qla_put_iocbs(sp->qpair, &sp->iores); + spin_unlock_irqrestore(&qpair->qp_lock, flags); + + return QLA_FUNCTION_FAILED; +@@ -2157,6 +2178,12 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) + /* Total Data and protection sg segment(s) */ + tot_prot_dsds = nseg; + tot_dsds += nseg; ++ ++ sp->iores.res_type = RESOURCE_INI; ++ sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds); ++ if (qla_get_iocbs(sp->qpair, &sp->iores)) ++ goto queuing_error; ++ + if (req->cnt < (req_cnt + 2)) { + cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr : + rd_reg_dword_relaxed(req->req_q_out); +@@ -2234,6 +2261,7 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) + } + /* Cleanup will be performed by the caller (queuecommand) */ + ++ qla_put_iocbs(sp->qpair, &sp->iores); + spin_unlock_irqrestore(&qpair->qp_lock, flags); + return QLA_FUNCTION_FAILED; + } +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -2901,6 +2901,7 @@ qla2x00_status_entry(scsi_qla_host_t *vh + } + return; + } ++ qla_put_iocbs(sp->qpair, &sp->iores); + + if (sp->cmd_type != TYPE_SRB) { + req->outstanding_cmds[handle] = NULL; +@@ -3313,6 +3314,7 @@ qla2x00_error_entry(scsi_qla_host_t *vha + default: + sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); + if (sp) { ++ qla_put_iocbs(sp->qpair, &sp->iores); + sp->done(sp, res); + return 0; + } +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -40,6 +40,11 @@ module_param(ql2xfulldump_on_mpifail, in + MODULE_PARM_DESC(ql2xfulldump_on_mpifail, + "Set this to take full dump on MPI hang."); + ++int ql2xenforce_iocb_limit = 1; ++module_param(ql2xenforce_iocb_limit, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(ql2xenforce_iocb_limit, ++ "Enforce IOCB throttling, to avoid FW congestion. (default: 0)"); ++ + /* + * CT6 CTX allocation cache + */ +@@ -3330,6 +3335,7 @@ qla2x00_probe_one(struct pci_dev *pdev, + qla2xxx_create_qpair(base_vha, 5, 0, startit); + } + } ++ qla_init_iocb_limit(base_vha); + + if (ha->flags.running_gold_fw) + goto skip_dpc; diff --git a/patches.suse/scsi-qla2xxx-Add-SLER-and-PI-control-support.patch b/patches.suse/scsi-qla2xxx-Add-SLER-and-PI-control-support.patch new file mode 100644 index 0000000..ad3e855 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Add-SLER-and-PI-control-support.patch @@ -0,0 +1,199 @@ +From: Saurav Kashyap +Date: Thu, 3 Sep 2020 21:51:27 -0700 +Subject: scsi: qla2xxx: Add SLER and PI control support +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: cf3c54fb49a4eb5b5b83ddab0b25df47b2e958af +References: bsc#1176946 bsc#1175520 bsc#1172538 + +BIT_13 of extended FW attribute informs about NVMe-2 support. Set BIT_15 +of special feature control block for enabling SLER in FW. Set bit 8 (SLER +supported) to 1 for the service parameter information when sending NVMe +PRLI request. Set BIT_14 of special feature control block for enabling PI +Control in FW. Driver should set bit 9 (PI Control supported) to 1 for the +service parameter information when sending NVMe PRLI request. Set BIT_13 +for NVMe Async events. + +Link: https://lore.kernel.org/r/20200904045128.23631-13-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Saurav Kashyap +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_dbg.c | 2 +- + drivers/scsi/qla2xxx/qla_def.h | 4 ++++ + drivers/scsi/qla2xxx/qla_iocb.c | 8 ++++++++ + drivers/scsi/qla2xxx/qla_mbx.c | 18 ++++++++++++++++-- + drivers/scsi/qla2xxx/qla_nvme.c | 16 ++++++++++++++-- + drivers/scsi/qla2xxx/qla_nvme.h | 1 + + drivers/scsi/qla2xxx/qla_os.c | 1 + + 7 files changed, 45 insertions(+), 5 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_dbg.c ++++ b/drivers/scsi/qla2xxx/qla_dbg.c +@@ -16,7 +16,7 @@ + * | Device Discovery | 0x2134 | 0x210e-0x2116 | + * | | | 0x211a | + * | | | 0x211c-0x2128 | +- * | | | 0x212a-0x2134 | ++ * | | | 0x212c-0x2134 | + * | Queue Command and IO tracing | 0x3074 | 0x300b | + * | | | 0x3027-0x3028 | + * | | | 0x303d-0x3041 | +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -2476,6 +2476,8 @@ typedef struct fc_port { + + struct completion nvme_del_done; + uint32_t nvme_prli_service_param; ++#define NVME_PRLI_SP_PI_CTRL BIT_9 ++#define NVME_PRLI_SP_SLER BIT_8 + #define NVME_PRLI_SP_CONF BIT_7 + #define NVME_PRLI_SP_INITIATOR BIT_5 + #define NVME_PRLI_SP_TARGET BIT_4 +@@ -4309,6 +4311,7 @@ struct qla_hw_data { + #define FW_ATTR_EXT0_SCM_BROCADE 0x00001000 + /* Cisco fabric attached */ + #define FW_ATTR_EXT0_SCM_CISCO 0x00002000 ++#define FW_ATTR_EXT0_NVME2 BIT_13 + uint16_t fw_attributes_ext[2]; + uint32_t fw_memory_size; + uint32_t fw_transfer_size; +@@ -4658,6 +4661,7 @@ typedef struct scsi_qla_host { + uint32_t qpairs_rsp_created:1; + uint32_t nvme_enabled:1; + uint32_t nvme_first_burst:1; ++ uint32_t nvme2_enabled:1; + } flags; + + atomic_t loop_state; +--- a/drivers/scsi/qla2xxx/qla_iocb.c ++++ b/drivers/scsi/qla2xxx/qla_iocb.c +@@ -2378,6 +2378,14 @@ qla24xx_prli_iocb(srb_t *sp, struct logi + if (sp->vha->flags.nvme_first_burst) + logio->io_parameter[0] = + cpu_to_le32(NVME_PRLI_SP_FIRST_BURST); ++ if (sp->vha->flags.nvme2_enabled) { ++ /* Set service parameter BIT_8 for SLER support */ ++ logio->io_parameter[0] |= ++ cpu_to_le32(NVME_PRLI_SP_SLER); ++ /* Set service parameter BIT_9 for PI control support */ ++ logio->io_parameter[0] |= ++ cpu_to_le32(NVME_PRLI_SP_PI_CTRL); ++ } + } + + logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -1093,6 +1093,14 @@ qla2x00_get_fw_version(scsi_qla_host_t * + "%s: FC-NVMe is Enabled (0x%x)\n", + __func__, ha->fw_attributes_h); + } ++ ++ /* BIT_13 of Extended FW Attributes informs about NVMe2 support */ ++ if (ha->fw_attributes_ext[0] & FW_ATTR_EXT0_NVME2) { ++ ql_log(ql_log_info, vha, 0xd302, ++ "Firmware supports NVMe2 0x%x\n", ++ ha->fw_attributes_ext[0]); ++ vha->flags.nvme2_enabled = 1; ++ } + } + + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { +@@ -1122,12 +1130,18 @@ qla2x00_get_fw_version(scsi_qla_host_t * + if (ha->flags.scm_supported_a && + (ha->fw_attributes_ext[0] & FW_ATTR_EXT0_SCM_SUPPORTED)) { + ha->flags.scm_supported_f = 1; +- memset(ha->sf_init_cb, 0, sizeof(struct init_sf_cb)); + ha->sf_init_cb->flags |= BIT_13; + } + ql_log(ql_log_info, vha, 0x11a3, "SCM in FW: %s\n", + (ha->flags.scm_supported_f) ? "Supported" : + "Not Supported"); ++ ++ if (vha->flags.nvme2_enabled) { ++ /* set BIT_15 of special feature control block for SLER */ ++ ha->sf_init_cb->flags |= BIT_15; ++ /* set BIT_14 of special feature control block for PI CTRL*/ ++ ha->sf_init_cb->flags |= BIT_14; ++ } + } + + failed: +@@ -1823,7 +1837,7 @@ qla2x00_init_firmware(scsi_qla_host_t *v + mcp->out_mb |= MBX_14|MBX_13|MBX_12|MBX_11|MBX_10; + } + +- if (ha->flags.scm_supported_f) { ++ if (ha->flags.scm_supported_f || vha->flags.nvme2_enabled) { + mcp->mb[1] |= BIT_1; + mcp->mb[16] = MSW(ha->sf_init_cb_dma); + mcp->mb[17] = LSW(ha->sf_init_cb_dma); +--- a/drivers/scsi/qla2xxx/qla_nvme.c ++++ b/drivers/scsi/qla2xxx/qla_nvme.c +@@ -69,6 +69,14 @@ int qla_nvme_register_remote(struct scsi + return ret; + } + ++ if (fcport->nvme_prli_service_param & NVME_PRLI_SP_SLER) ++ ql_log(ql_log_info, vha, 0x212a, ++ "PortID:%06x Supports SLER\n", req.port_id); ++ ++ if (fcport->nvme_prli_service_param & NVME_PRLI_SP_PI_CTRL) ++ ql_log(ql_log_info, vha, 0x212b, ++ "PortID:%06x Supports PI control\n", req.port_id); ++ + rport = fcport->nvme_remote_port->private; + rport->fcport = fcport; + +@@ -379,6 +387,7 @@ static inline int qla2x00_start_nvme_mq( + struct srb_iocb *nvme = &sp->u.iocb_cmd; + struct scatterlist *sgl, *sg; + struct nvmefc_fcp_req *fd = nvme->u.nvme.desc; ++ struct nvme_fc_cmd_iu *cmd = fd->cmdaddr; + uint32_t rval = QLA_SUCCESS; + + /* Setup qpair pointers */ +@@ -410,8 +419,6 @@ static inline int qla2x00_start_nvme_mq( + } + + if (unlikely(!fd->sqid)) { +- struct nvme_fc_cmd_iu *cmd = fd->cmdaddr; +- + if (cmd->sqe.common.opcode == nvme_admin_async_event) { + nvme->u.nvme.aen_op = 1; + atomic_inc(&ha->nvme_active_aen_cnt); +@@ -457,6 +464,11 @@ static inline int qla2x00_start_nvme_mq( + } else if (fd->io_dir == 0) { + cmd_pkt->control_flags = 0; + } ++ /* Set BIT_13 of control flags for Async event */ ++ if (vha->flags.nvme2_enabled && ++ cmd->sqe.common.opcode == nvme_admin_async_event) { ++ cmd_pkt->control_flags |= cpu_to_le16(CF_ADMIN_ASYNC_EVENT); ++ } + + /* Set NPORT-ID */ + cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id); +--- a/drivers/scsi/qla2xxx/qla_nvme.h ++++ b/drivers/scsi/qla2xxx/qla_nvme.h +@@ -54,6 +54,7 @@ struct cmd_nvme { + uint64_t rsvd; + + __le16 control_flags; /* Control Flags */ ++#define CF_ADMIN_ASYNC_EVENT BIT_13 + #define CF_NVME_FIRST_BURST_ENABLE BIT_11 + #define CF_DIF_SEG_DESCR_ENABLE BIT_3 + #define CF_DATA_SEG_DESCR_ENABLE BIT_2 +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -4245,6 +4245,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha + &ha->sf_init_cb_dma); + if (!ha->sf_init_cb) + goto fail_sf_init_cb; ++ memset(ha->sf_init_cb, 0, sizeof(struct init_sf_cb)); + ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0199, + "sf_init_cb=%p.\n", ha->sf_init_cb); + } diff --git a/patches.suse/scsi-qla2xxx-Add-rport-fields-in-debugfs.patch b/patches.suse/scsi-qla2xxx-Add-rport-fields-in-debugfs.patch new file mode 100644 index 0000000..b3ca5b4 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Add-rport-fields-in-debugfs.patch @@ -0,0 +1,96 @@ +From: Arun Easi +Date: Thu, 3 Sep 2020 21:51:25 -0700 +Subject: scsi: qla2xxx: Add rport fields in debugfs +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 6152d20fa6703cf364253efc4eab31151558cb01 +References: bsc#1176946 bsc#1175520 bsc#1172538 + +This patch adds rport fields in debugfs. + +Link: https://lore.kernel.org/r/20200904045128.23631-11-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Arun Easi +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_dfs.c | 53 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + +--- a/drivers/scsi/qla2xxx/qla_dfs.c ++++ b/drivers/scsi/qla2xxx/qla_dfs.c +@@ -65,13 +65,53 @@ DEFINE_DEBUGFS_ATTRIBUTE(qla_dfs_rport_# + qla_dfs_rport_##_attr##_get, \ + qla_dfs_rport_##_attr##_set, "%llu\n") + ++/* ++ * Wrapper for getting fc_port fields. ++ * ++ * _attr : Attribute name. ++ * _get_val : Accessor macro to retrieve the value. ++ */ ++#define DEFINE_QLA_DFS_RPORT_FIELD_GET(_attr, _get_val) \ ++static int qla_dfs_rport_field_##_attr##_get(void *data, u64 *val) \ ++{ \ ++ struct fc_port *fp = data; \ ++ *val = _get_val; \ ++ return 0; \ ++} \ ++DEFINE_DEBUGFS_ATTRIBUTE(qla_dfs_rport_field_##_attr##_fops, \ ++ qla_dfs_rport_field_##_attr##_get, \ ++ NULL, "%llu\n") ++ ++#define DEFINE_QLA_DFS_RPORT_ACCESS(_attr, _get_val) \ ++ DEFINE_QLA_DFS_RPORT_FIELD_GET(_attr, _get_val) ++ ++#define DEFINE_QLA_DFS_RPORT_FIELD(_attr) \ ++ DEFINE_QLA_DFS_RPORT_FIELD_GET(_attr, fp->_attr) ++ + DEFINE_QLA_DFS_RPORT_RW_ATTR(QLA_DFS_RPORT_DEVLOSS_TMO, dev_loss_tmo); + ++DEFINE_QLA_DFS_RPORT_FIELD(disc_state); ++DEFINE_QLA_DFS_RPORT_FIELD(scan_state); ++DEFINE_QLA_DFS_RPORT_FIELD(fw_login_state); ++DEFINE_QLA_DFS_RPORT_FIELD(login_pause); ++DEFINE_QLA_DFS_RPORT_FIELD(flags); ++DEFINE_QLA_DFS_RPORT_FIELD(nvme_flag); ++DEFINE_QLA_DFS_RPORT_FIELD(last_rscn_gen); ++DEFINE_QLA_DFS_RPORT_FIELD(rscn_gen); ++DEFINE_QLA_DFS_RPORT_FIELD(login_gen); ++DEFINE_QLA_DFS_RPORT_FIELD(loop_id); ++DEFINE_QLA_DFS_RPORT_FIELD_GET(port_id, fp->d_id.b24); ++DEFINE_QLA_DFS_RPORT_FIELD_GET(sess_kref, kref_read(&fp->sess_kref)); ++ + void + qla2x00_dfs_create_rport(scsi_qla_host_t *vha, struct fc_port *fp) + { + char wwn[32]; + ++#define QLA_CREATE_RPORT_FIELD_ATTR(_attr) \ ++ debugfs_create_file(#_attr, 0400, fp->dfs_rport_dir, \ ++ fp, &qla_dfs_rport_field_##_attr##_fops) ++ + if (!vha->dfs_rport_root || fp->dfs_rport_dir) + return; + +@@ -82,6 +122,19 @@ qla2x00_dfs_create_rport(scsi_qla_host_t + if (NVME_TARGET(vha->hw, fp)) + debugfs_create_file("dev_loss_tmo", 0600, fp->dfs_rport_dir, + fp, &qla_dfs_rport_dev_loss_tmo_fops); ++ ++ QLA_CREATE_RPORT_FIELD_ATTR(disc_state); ++ QLA_CREATE_RPORT_FIELD_ATTR(scan_state); ++ QLA_CREATE_RPORT_FIELD_ATTR(fw_login_state); ++ QLA_CREATE_RPORT_FIELD_ATTR(login_pause); ++ QLA_CREATE_RPORT_FIELD_ATTR(flags); ++ QLA_CREATE_RPORT_FIELD_ATTR(nvme_flag); ++ QLA_CREATE_RPORT_FIELD_ATTR(last_rscn_gen); ++ QLA_CREATE_RPORT_FIELD_ATTR(rscn_gen); ++ QLA_CREATE_RPORT_FIELD_ATTR(login_gen); ++ QLA_CREATE_RPORT_FIELD_ATTR(loop_id); ++ QLA_CREATE_RPORT_FIELD_ATTR(port_id); ++ QLA_CREATE_RPORT_FIELD_ATTR(sess_kref); + } + + void diff --git a/patches.suse/scsi-qla2xxx-Allow-dev_loss_tmo-setting-for-FC-NVMe-.patch b/patches.suse/scsi-qla2xxx-Allow-dev_loss_tmo-setting-for-FC-NVMe-.patch new file mode 100644 index 0000000..23d57e9 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Allow-dev_loss_tmo-setting-for-FC-NVMe-.patch @@ -0,0 +1,96 @@ +From: Arun Easi +Date: Thu, 3 Sep 2020 21:51:18 -0700 +Subject: scsi: qla2xxx: Allow dev_loss_tmo setting for FC-NVMe devices +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 27c8aa5e1b069b7629e41bba83b522f99132a6b6 +References: bsc#1176946 bsc#1175520 bsc#1172538 + +Add a remote port debugfs entry to get/set dev_loss_tmo for NVMe devices. + +Link: https://lore.kernel.org/r/20200904045128.23631-4-njavali@marvell.com +Reported-by: kernel test robot +Reviewed-by: Himanshu Madhani +Signed-off-by: Arun Easi +Signed-off-by: Himanshu Madhani +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_dfs.c | 58 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 58 insertions(+) + +--- a/drivers/scsi/qla2xxx/qla_dfs.c ++++ b/drivers/scsi/qla2xxx/qla_dfs.c +@@ -12,6 +12,61 @@ + static struct dentry *qla2x00_dfs_root; + static atomic_t qla2x00_dfs_root_count; + ++#define QLA_DFS_RPORT_DEVLOSS_TMO 1 ++ ++static int ++qla_dfs_rport_get(struct fc_port *fp, int attr_id, u64 *val) ++{ ++ switch (attr_id) { ++ case QLA_DFS_RPORT_DEVLOSS_TMO: ++ /* Only supported for FC-NVMe devices that are registered. */ ++ if (!(fp->nvme_flag & NVME_FLAG_REGISTERED)) ++ return -EIO; ++ *val = fp->nvme_remote_port->dev_loss_tmo; ++ break; ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int ++qla_dfs_rport_set(struct fc_port *fp, int attr_id, u64 val) ++{ ++ switch (attr_id) { ++ case QLA_DFS_RPORT_DEVLOSS_TMO: ++ /* Only supported for FC-NVMe devices that are registered. */ ++ if (!(fp->nvme_flag & NVME_FLAG_REGISTERED)) ++ return -EIO; ++#if (IS_ENABLED(CONFIG_NVME_FC)) ++ return nvme_fc_set_remoteport_devloss(fp->nvme_remote_port, ++ val); ++#else /* CONFIG_NVME_FC */ ++ return -EINVAL; ++#endif /* CONFIG_NVME_FC */ ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++#define DEFINE_QLA_DFS_RPORT_RW_ATTR(_attr_id, _attr) \ ++static int qla_dfs_rport_##_attr##_get(void *data, u64 *val) \ ++{ \ ++ struct fc_port *fp = data; \ ++ return qla_dfs_rport_get(fp, _attr_id, val); \ ++} \ ++static int qla_dfs_rport_##_attr##_set(void *data, u64 val) \ ++{ \ ++ struct fc_port *fp = data; \ ++ return qla_dfs_rport_set(fp, _attr_id, val); \ ++} \ ++DEFINE_DEBUGFS_ATTRIBUTE(qla_dfs_rport_##_attr##_fops, \ ++ qla_dfs_rport_##_attr##_get, \ ++ qla_dfs_rport_##_attr##_set, "%llu\n") ++ ++DEFINE_QLA_DFS_RPORT_RW_ATTR(QLA_DFS_RPORT_DEVLOSS_TMO, dev_loss_tmo); ++ + void + qla2x00_dfs_create_rport(scsi_qla_host_t *vha, struct fc_port *fp) + { +@@ -24,6 +79,9 @@ qla2x00_dfs_create_rport(scsi_qla_host_t + fp->dfs_rport_dir = debugfs_create_dir(wwn, vha->dfs_rport_root); + if (!fp->dfs_rport_dir) + return; ++ if (NVME_TARGET(vha->hw, fp)) ++ debugfs_create_file("dev_loss_tmo", 0600, fp->dfs_rport_dir, ++ fp, &qla_dfs_rport_dev_loss_tmo_fops); + } + + void diff --git a/patches.suse/scsi-qla2xxx-Correct-the-check-for-sscanf-return-val.patch b/patches.suse/scsi-qla2xxx-Correct-the-check-for-sscanf-return-val.patch new file mode 100644 index 0000000..d39e98f --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Correct-the-check-for-sscanf-return-val.patch @@ -0,0 +1,34 @@ +From: Saurav Kashyap +Date: Tue, 29 Sep 2020 03:21:46 -0700 +Subject: scsi: qla2xxx: Correct the check for sscanf() return value +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 7dc0f671d89c03db95db3d4cd57257790d7a4b80 +References: bsc#1176946 bsc#1175520 bsc#1172538 + +Since the version string has been modified, sscanf() returns 4 instead of +6. + +Link: https://lore.kernel.org/r/20200929102152.32278-2-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Saurav Kashyap +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_tmpl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_tmpl.c ++++ b/drivers/scsi/qla2xxx/qla_tmpl.c +@@ -906,8 +906,8 @@ qla27xx_driver_info(struct qla27xx_fwdt_ + uint8_t v[] = { 0, 0, 0, 0, 0, 0 }; + + WARN_ON_ONCE(sscanf(qla2x00_version_str, +- "%hhu.%hhu.%hhu.%hhu.%hhu.%hhu", +- v+0, v+1, v+2, v+3, v+4, v+5) != 6); ++ "%hhu.%hhu.%hhu.%hhu", ++ v + 0, v + 1, v + 2, v + 3) != 4); + + tmp->driver_info[0] = cpu_to_le32( + v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0]); diff --git a/patches.suse/scsi-qla2xxx-Fix-I-O-errors-during-LIP-reset-tests.patch b/patches.suse/scsi-qla2xxx-Fix-I-O-errors-during-LIP-reset-tests.patch new file mode 100644 index 0000000..5427dad --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-I-O-errors-during-LIP-reset-tests.patch @@ -0,0 +1,39 @@ +From: Arun Easi +Date: Thu, 3 Sep 2020 21:51:23 -0700 +Subject: scsi: qla2xxx: Fix I/O errors during LIP reset tests +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: a35f87bdcc0615c5a3a695d13dd1ccf827826368 +References: bsc#1176946 bsc#1175520 bsc#1172538 + +In .fcp_io(), returning ENODEV as soon as remote port delete has started +can cause I/O errors. Fix this by returning EBUSY until the remote port +delete finishes. + +Link: https://lore.kernel.org/r/20200904045128.23631-9-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Arun Easi +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_nvme.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/scsi/qla2xxx/qla_nvme.c ++++ b/drivers/scsi/qla2xxx/qla_nvme.c +@@ -559,6 +559,14 @@ static int qla_nvme_post_cmd(struct nvme + return rval; + + vha = fcport->vha; ++ ++ if (!(fcport->nvme_flag & NVME_FLAG_REGISTERED)) ++ return rval; ++ ++ if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || ++ (qpair && !qpair->fw_started) || fcport->deleted) ++ return -EBUSY; ++ + /* + * If we know the dev is going away while the transport is still sending + * IO's return busy back to stall the IO Q. This happens when the diff --git a/patches.suse/scsi-qla2xxx-Fix-I-O-failures-during-remote-port-tog.patch b/patches.suse/scsi-qla2xxx-Fix-I-O-failures-during-remote-port-tog.patch new file mode 100644 index 0000000..aa2ef9b --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-I-O-failures-during-remote-port-tog.patch @@ -0,0 +1,48 @@ +From: Arun Easi +Date: Thu, 3 Sep 2020 21:51:16 -0700 +Subject: scsi: qla2xxx: Fix I/O failures during remote port toggle testing +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: dd8d0bf6fb72bc73dc534d0d222e769e71d2202c +References: bsc#1176946 bsc#1175520 bsc#1172538 + +Driver was using a lower value for dev_loss_tmo making it more prone to I/O +failures during remote port toggle testing. Set dev_loss_tmo to zero during +remote port registration to allow nvme-fc default dev_loss_tmo to be used, +which is higher than what driver was using. + +Link: https://lore.kernel.org/r/20200904045128.23631-2-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Arun Easi +Signed-off-by: Himanshu Madhani +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_nvme.c | 2 +- + drivers/scsi/qla2xxx/qla_nvme.h | 3 --- + 2 files changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_nvme.c ++++ b/drivers/scsi/qla2xxx/qla_nvme.c +@@ -42,7 +42,7 @@ int qla_nvme_register_remote(struct scsi + req.port_name = wwn_to_u64(fcport->port_name); + req.node_name = wwn_to_u64(fcport->node_name); + req.port_role = 0; +- req.dev_loss_tmo = NVME_FC_DEV_LOSS_TMO; ++ req.dev_loss_tmo = 0; + + if (fcport->nvme_prli_service_param & NVME_PRLI_SP_INITIATOR) + req.port_role = FC_PORT_ROLE_NVME_INITIATOR; +--- a/drivers/scsi/qla2xxx/qla_nvme.h ++++ b/drivers/scsi/qla2xxx/qla_nvme.h +@@ -14,9 +14,6 @@ + #include "qla_def.h" + #include "qla_dsd.h" + +-/* default dev loss time (seconds) before transport tears down ctrl */ +-#define NVME_FC_DEV_LOSS_TMO 30 +- + #define NVME_ATIO_CMD_OFF 32 + #define NVME_FIRST_PACKET_CMDLEN (64 - NVME_ATIO_CMD_OFF) + #define Q2T_NVME_NUM_TAGS 2048 diff --git a/patches.suse/scsi-qla2xxx-Fix-MPI-reset-needed-message.patch b/patches.suse/scsi-qla2xxx-Fix-MPI-reset-needed-message.patch new file mode 100644 index 0000000..ffb5d2e --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-MPI-reset-needed-message.patch @@ -0,0 +1,38 @@ +From: Arun Easi +Date: Tue, 29 Sep 2020 03:21:48 -0700 +Subject: scsi: qla2xxx: Fix MPI reset needed message +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 7a6cdbd5e87515ebf6231b762ad903c7cff87b9c +References: bsc#1176946 bsc#1175520 bsc#1172538 + +When printing the message: + + "MPI Heartbeat stop. MPI reset is not needed.." + +..the wrong register was checked leading to always printing that MPI reset +is not needed, even when it is needed. Fix the MPI reset message. + +Link: https://lore.kernel.org/r/20200929102152.32278-4-njavali@marvell.com +Fixes: cbb01c2f2f63 ("scsi: qla2xxx: Fix MPI failure AEN (8200) handling") +Cc: stable@vger.kernel.org +Reviewed-by: Himanshu Madhani +Signed-off-by: Arun Easi +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_isr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -767,7 +767,7 @@ qla27xx_handle_8200_aen(scsi_qla_host_t + ql_log(ql_log_warn, vha, 0x02f0, + "MPI Heartbeat stop. MPI reset is%s needed. " + "MB0[%xh] MB1[%xh] MB2[%xh] MB3[%xh]\n", +- mb[0] & BIT_8 ? "" : " not", ++ mb[1] & BIT_8 ? "" : " not", + mb[0], mb[1], mb[2], mb[3]); + + if ((mb[1] & BIT_8) == 0) diff --git a/patches.suse/scsi-qla2xxx-Fix-buffer-buffer-credit-extraction-err.patch b/patches.suse/scsi-qla2xxx-Fix-buffer-buffer-credit-extraction-err.patch new file mode 100644 index 0000000..d9f74ae --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-buffer-buffer-credit-extraction-err.patch @@ -0,0 +1,242 @@ +From: Quinn Tran +Date: Tue, 29 Sep 2020 03:21:47 -0700 +Subject: scsi: qla2xxx: Fix buffer-buffer credit extraction error +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 44f5a37d1e3e4e392412318666f8477601ae3024 +References: bsc#1176946 bsc#1175520 bsc#1172538 + +Current code uses wrong mailbox option to extract bbc from firmware. This +field is nested inside of PLOGI payload. Extract bbc from PLOGI template +payload. + +Link: https://lore.kernel.org/r/20200929102152.32278-3-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_def.h | 4 ++- + drivers/scsi/qla2xxx/qla_init.c | 50 ++++++++++++++++++++-------------------- + drivers/scsi/qla2xxx/qla_iocb.c | 3 -- + drivers/scsi/qla2xxx/qla_mbx.c | 39 ------------------------------- + drivers/scsi/qla2xxx/qla_os.c | 19 +++------------ + 5 files changed, 34 insertions(+), 81 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -3915,6 +3915,7 @@ struct qla_hw_data { + /* Enabled in Driver */ + uint32_t scm_enabled:1; + uint32_t max_req_queue_warned:1; ++ uint32_t plogi_template_valid:1; + } flags; + + uint16_t max_exchg; +@@ -4263,7 +4264,8 @@ struct qla_hw_data { + int exchoffld_count; + + /* n2n */ +- struct els_plogi_payload plogi_els_payld; ++ struct fc_els_flogi plogi_els_payld; ++#define LOGIN_TEMPLATE_SIZE (sizeof(struct fc_els_flogi) - 4) + + void *swl; + +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -4991,6 +4991,29 @@ qla2x00_free_fcport(fc_port_t *fcport) + kfree(fcport); + } + ++static void qla_get_login_template(scsi_qla_host_t *vha) ++{ ++ struct qla_hw_data *ha = vha->hw; ++ int rval; ++ u32 *bp, sz; ++ __be32 *q; ++ ++ memset(ha->init_cb, 0, ha->init_cb_size); ++ sz = min_t(int, sizeof(struct fc_els_flogi), ha->init_cb_size); ++ rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma, ++ ha->init_cb, sz); ++ if (rval != QLA_SUCCESS) { ++ ql_dbg(ql_dbg_init, vha, 0x00d1, ++ "PLOGI ELS param read fail.\n"); ++ return; ++ } ++ q = (__be32 *)&ha->plogi_els_payld.fl_csp; ++ ++ bp = (uint32_t *)ha->init_cb; ++ cpu_to_be32_array(q, bp, sz / 4); ++ ha->flags.plogi_template_valid = 1; ++} ++ + /* + * qla2x00_configure_loop + * Updates Fibre Channel Device Database with what is actually on loop. +@@ -5034,6 +5057,7 @@ qla2x00_configure_loop(scsi_qla_host_t * + clear_bit(RSCN_UPDATE, &vha->dpc_flags); + + qla2x00_get_data_rate(vha); ++ qla_get_login_template(vha); + + /* Determine what we need to do */ + if ((ha->current_topology == ISP_CFG_FL || +@@ -5118,32 +5142,11 @@ qla2x00_configure_loop(scsi_qla_host_t * + + static int qla2x00_configure_n2n_loop(scsi_qla_host_t *vha) + { +- struct qla_hw_data *ha = vha->hw; + unsigned long flags; + fc_port_t *fcport; +- int rval; + +- if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) { +- /* borrowing */ +- u32 *bp, sz; +- +- memset(ha->init_cb, 0, ha->init_cb_size); +- sz = min_t(int, sizeof(struct els_plogi_payload), +- ha->init_cb_size); +- rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma, +- ha->init_cb, sz); +- if (rval == QLA_SUCCESS) { +- __be32 *q = &ha->plogi_els_payld.data[0]; +- +- bp = (uint32_t *)ha->init_cb; +- cpu_to_be32_array(q, bp, sz / 4); +- memcpy(bp, q, sizeof(ha->plogi_els_payld.data)); +- } else { +- ql_dbg(ql_dbg_init, vha, 0x00d1, +- "PLOGI ELS param read fail.\n"); +- goto skip_login; +- } +- } ++ if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) ++ set_bit(RELOGIN_NEEDED, &vha->dpc_flags); + + list_for_each_entry(fcport, &vha->vp_fcports, list) { + if (fcport->n2n_flag) { +@@ -5152,7 +5155,6 @@ static int qla2x00_configure_n2n_loop(sc + } + } + +-skip_login: + spin_lock_irqsave(&vha->work_lock, flags); + vha->scan.scan_retry++; + spin_unlock_irqrestore(&vha->work_lock, flags); +--- a/drivers/scsi/qla2xxx/qla_iocb.c ++++ b/drivers/scsi/qla2xxx/qla_iocb.c +@@ -3016,8 +3016,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t * + memset(ptr, 0, sizeof(struct els_plogi_payload)); + memset(resp_ptr, 0, sizeof(struct els_plogi_payload)); + memcpy(elsio->u.els_plogi.els_plogi_pyld->data, +- &ha->plogi_els_payld.data, +- sizeof(elsio->u.els_plogi.els_plogi_pyld->data)); ++ &ha->plogi_els_payld.fl_csp, LOGIN_TEMPLATE_SIZE); + + elsio->u.els_plogi.els_cmd = els_opcode; + elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode; +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -4977,45 +4977,6 @@ qla25xx_set_els_cmds_supported(scsi_qla_ + return rval; + } + +-int +-qla24xx_get_buffer_credits(scsi_qla_host_t *vha, struct buffer_credit_24xx *bbc, +- dma_addr_t bbc_dma) +-{ +- mbx_cmd_t mc; +- mbx_cmd_t *mcp = &mc; +- int rval; +- +- if (!IS_FWI2_CAPABLE(vha->hw)) +- return QLA_FUNCTION_FAILED; +- +- ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118e, +- "Entered %s.\n", __func__); +- +- mcp->mb[0] = MBC_GET_RNID_PARAMS; +- mcp->mb[1] = RNID_BUFFER_CREDITS << 8; +- mcp->mb[2] = MSW(LSD(bbc_dma)); +- mcp->mb[3] = LSW(LSD(bbc_dma)); +- mcp->mb[6] = MSW(MSD(bbc_dma)); +- mcp->mb[7] = LSW(MSD(bbc_dma)); +- mcp->mb[8] = sizeof(*bbc) / sizeof(*bbc->parameter); +- mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; +- mcp->in_mb = MBX_1|MBX_0; +- mcp->buf_size = sizeof(*bbc); +- mcp->flags = MBX_DMA_IN; +- mcp->tov = MBX_TOV_SECONDS; +- rval = qla2x00_mailbox_command(vha, mcp); +- +- if (rval != QLA_SUCCESS) { +- ql_dbg(ql_dbg_mbx, vha, 0x118f, +- "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]); +- } else { +- ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1190, +- "Done %s.\n", __func__); +- } +- +- return rval; +-} +- + static int + qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp) + { +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -5850,12 +5850,10 @@ void qla24xx_process_purex_rdp(struct sc + dma_addr_t rsp_els_dma; + dma_addr_t rsp_payload_dma; + dma_addr_t stat_dma; +- dma_addr_t bbc_dma; + dma_addr_t sfp_dma; + struct els_entry_24xx *rsp_els = NULL; + struct rdp_rsp_payload *rsp_payload = NULL; + struct link_statistics *stat = NULL; +- struct buffer_credit_24xx *bbc = NULL; + uint8_t *sfp = NULL; + uint16_t sfp_flags = 0; + uint rsp_payload_length = sizeof(*rsp_payload); +@@ -5899,9 +5897,6 @@ void qla24xx_process_purex_rdp(struct sc + stat = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stat), + &stat_dma, GFP_KERNEL); + +- bbc = dma_alloc_coherent(&ha->pdev->dev, sizeof(*bbc), +- &bbc_dma, GFP_KERNEL); +- + /* Prepare Response IOCB */ + rsp_els->entry_type = ELS_IOCB_TYPE; + rsp_els->entry_count = 1; +@@ -6055,13 +6050,10 @@ void qla24xx_process_purex_rdp(struct sc + rsp_payload->buffer_credit_desc.attached_fcport_b2b = cpu_to_be32(0); + rsp_payload->buffer_credit_desc.fcport_rtt = cpu_to_be32(0); + +- if (bbc) { +- memset(bbc, 0, sizeof(*bbc)); +- rval = qla24xx_get_buffer_credits(vha, bbc, bbc_dma); +- if (!rval) { +- rsp_payload->buffer_credit_desc.fcport_b2b = +- cpu_to_be32(LSW(bbc->parameter[0])); +- } ++ if (ha->flags.plogi_template_valid) { ++ uint32_t tmp = ++ be16_to_cpu(ha->plogi_els_payld.fl_csp.sp_bb_cred); ++ rsp_payload->buffer_credit_desc.fcport_b2b = cpu_to_be32(tmp); + } + + if (rsp_payload_length < sizeof(*rsp_payload)) +@@ -6239,9 +6231,6 @@ void qla24xx_process_purex_rdp(struct sc + } + + dealloc: +- if (bbc) +- dma_free_coherent(&ha->pdev->dev, sizeof(*bbc), +- bbc, bbc_dma); + if (stat) + dma_free_coherent(&ha->pdev->dev, sizeof(*stat), + stat, stat_dma); diff --git a/patches.suse/scsi-qla2xxx-Fix-crash-on-session-cleanup-with-unloa.patch b/patches.suse/scsi-qla2xxx-Fix-crash-on-session-cleanup-with-unloa.patch new file mode 100644 index 0000000..c10b7e0 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-crash-on-session-cleanup-with-unloa.patch @@ -0,0 +1,47 @@ +From: Quinn Tran +Date: Tue, 29 Sep 2020 03:21:50 -0700 +Subject: scsi: qla2xxx: Fix crash on session cleanup with unload +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 50457dab670f396557e60c07f086358460876353 +References: bsc#1176946 bsc#1175520 bsc#1172538 + +On unload, session cleanup prematurely gave the signal for driver unload +path to advance. + +Link: https://lore.kernel.org/r/20200929102152.32278-6-njavali@marvell.com +Fixes: 726b85487067 ("qla2xxx: Add framework for async fabric discovery") +Cc: stable@vger.kernel.org +Reviewed-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_target.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -1240,14 +1240,15 @@ void qlt_schedule_sess_for_deletion(stru + case DSC_DELETE_PEND: + return; + case DSC_DELETED: +- if (tgt && tgt->tgt_stop && (tgt->sess_count == 0)) +- wake_up_all(&tgt->waitQ); +- if (sess->vha->fcport_count == 0) +- wake_up_all(&sess->vha->fcport_waitQ); +- + if (!sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN] && +- !sess->plogi_link[QLT_PLOGI_LINK_CONFLICT]) ++ !sess->plogi_link[QLT_PLOGI_LINK_CONFLICT]) { ++ if (tgt && tgt->tgt_stop && tgt->sess_count == 0) ++ wake_up_all(&tgt->waitQ); ++ ++ if (sess->vha->fcport_count == 0) ++ wake_up_all(&sess->vha->fcport_waitQ); + return; ++ } + break; + case DSC_UPD_FCPORT: + /* diff --git a/patches.suse/scsi-qla2xxx-Fix-inconsistent-format-argument-type-i-250bd009.patch b/patches.suse/scsi-qla2xxx-Fix-inconsistent-format-argument-type-i-250bd009.patch new file mode 100644 index 0000000..2f57405 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-inconsistent-format-argument-type-i-250bd009.patch @@ -0,0 +1,46 @@ +From: Ye Bin +Date: Wed, 30 Sep 2020 10:25:14 +0800 +Subject: scsi: qla2xxx: Fix inconsistent format argument type in qla_os.c +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 250bd00923c72c846092271a9e51ee373db081b6 +References: bsc#1176946 bsc#1175520 bsc#1172538 + +Fix the following warnings: + +[drivers/scsi/qla2xxx/qla_os.c:4882]: (warning) %ld in format string (no. 2) + requires 'long' but the argument type is 'unsigned long'. +[drivers/scsi/qla2xxx/qla_os.c:5011]: (warning) %ld in format string (no. 1) + requires 'long' but the argument type is 'unsigned long'. + +Link: https://lore.kernel.org/r/20200930022515.2862532-3-yebin10@huawei.com +Reported-by: Hulk Robot +Reviewed-by: Himanshu Madhani +Reviewed-by: Nilesh Javali +Signed-off-by: Ye Bin +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_os.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -4893,7 +4893,7 @@ struct scsi_qla_host *qla2x00_create_hos + } + INIT_DELAYED_WORK(&vha->scan.scan_work, qla_scan_work_fn); + +- sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no); ++ sprintf(vha->host_str, "%s_%lu", QLA2XXX_DRIVER_NAME, vha->host_no); + ql_dbg(ql_dbg_init, vha, 0x0041, + "Allocated the host=%p hw=%p vha=%p dev_name=%s", + vha->host, vha->hw, vha, +@@ -5022,7 +5022,7 @@ qla2x00_uevent_emit(struct scsi_qla_host + + switch (code) { + case QLA_UEVENT_CODE_FW_DUMP: +- snprintf(event_string, sizeof(event_string), "FW_DUMP=%ld", ++ snprintf(event_string, sizeof(event_string), "FW_DUMP=%lu", + vha->host_no); + break; + default: diff --git a/patches.suse/scsi-qla2xxx-Fix-inconsistent-format-argument-type-i-72e813d9.patch b/patches.suse/scsi-qla2xxx-Fix-inconsistent-format-argument-type-i-72e813d9.patch new file mode 100644 index 0000000..2bad916 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-inconsistent-format-argument-type-i-72e813d9.patch @@ -0,0 +1,35 @@ +From: Ye Bin +Date: Wed, 30 Sep 2020 10:25:15 +0800 +Subject: scsi: qla2xxx: Fix inconsistent format argument type in qla_dbg.c +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 72e813d9a1b7a0a6dc6b27b563c389fbdb50cee2 +References: bsc#1176946 bsc#1175520 bsc#1172538 + +Fix the following warning: + +[drivers/scsi/qla2xxx/qla_dbg.c:2451]: (warning) %ld in format string (no. 4) + requires 'long' but the argument type is 'unsigned long'. + +Link: https://lore.kernel.org/r/20200930022515.2862532-4-yebin10@huawei.com +Reported-by: Hulk Robot +Reviewed-by: Himanshu Madhani +Reviewed-by: Nilesh Javali +Signed-off-by: Ye Bin +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_dbg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/qla2xxx/qla_dbg.c ++++ b/drivers/scsi/qla2xxx/qla_dbg.c +@@ -2449,7 +2449,7 @@ static void ql_dbg_prefix(char *pbuf, in + const struct pci_dev *pdev = vha->hw->pdev; + + /* []-:: */ +- snprintf(pbuf, pbuf_size, "%s [%s]-%04x:%ld: ", QL_MSGHDR, ++ snprintf(pbuf, pbuf_size, "%s [%s]-%04x:%lu: ", QL_MSGHDR, + dev_name(&(pdev->dev)), msg_id, vha->host_no); + } else { + /* []-: : */ diff --git a/patches.suse/scsi-qla2xxx-Fix-inconsistent-format-argument-type-i.patch b/patches.suse/scsi-qla2xxx-Fix-inconsistent-format-argument-type-i.patch new file mode 100644 index 0000000..7fb3700 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-inconsistent-format-argument-type-i.patch @@ -0,0 +1,43 @@ +From: Ye Bin +Date: Wed, 30 Sep 2020 10:25:13 +0800 +Subject: scsi: qla2xxx: Fix inconsistent format argument type in tcm_qla2xxx.c +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 7f5523f6970932e982d3da51ce0208b74c437140 +References: bsc#1176946 bsc#1175520 bsc#1172538 + +Fix the following warnings: + +[drivers/scsi/qla2xxx/tcm_qla2xxx.c:884]: (warning) %u in format string (no. 1) + requires 'unsigned int' but the argument type is 'signed int'. +[drivers/scsi/qla2xxx/tcm_qla2xxx.c:885]: (warning) %u in format string (no. 1) + requires 'unsigned int' but the argument type is 'signed int'. +[drivers/scsi/qla2xxx/tcm_qla2xxx.c:886]: (warning) %u in format string (no. 1) + requires 'unsigned int' but the argument type is 'signed int'. +[drivers/scsi/qla2xxx/tcm_qla2xxx.c:887]: (warning) %u in format string (no. 1) + requires 'unsigned int' but the argument type is 'signed int'. +[drivers/scsi/qla2xxx/tcm_qla2xxx.c:888]: (warning) %u in format string (no. 1) + requires 'unsigned int' but the argument type is 'signed int'. + +Link: https://lore.kernel.org/r/20200930022515.2862532-2-yebin10@huawei.com +Reported-by: Hulk Robot +Reviewed-by: Himanshu Madhani +Reviewed-by: Nilesh Javali +Signed-off-by: Ye Bin +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/tcm_qla2xxx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c ++++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c +@@ -898,7 +898,7 @@ static ssize_t tcm_qla2xxx_tpg_attrib_## + struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, \ + struct tcm_qla2xxx_tpg, se_tpg); \ + \ +- return sprintf(page, "%u\n", tpg->tpg_attrib.name); \ ++ return sprintf(page, "%d\n", tpg->tpg_attrib.name); \ + } \ + \ + static ssize_t tcm_qla2xxx_tpg_attrib_##name##_store( \ diff --git a/patches.suse/scsi-qla2xxx-Fix-memory-size-truncation.patch b/patches.suse/scsi-qla2xxx-Fix-memory-size-truncation.patch new file mode 100644 index 0000000..ace01ba --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-memory-size-truncation.patch @@ -0,0 +1,74 @@ +From: Quinn Tran +Date: Thu, 3 Sep 2020 21:51:21 -0700 +Subject: scsi: qla2xxx: Fix memory size truncation +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: d38cb849e17a34637b97ce57c550ec70d63dd39a +References: bsc#1176946 bsc#1175520 bsc#1172538 + +Memory size calculations for Extended Login used in hardware offload got +truncated. Fix this by changing definition of exlogin_size to use uint32_t. + +Link: https://lore.kernel.org/r/20200904045128.23631-7-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_def.h | 2 +- + drivers/scsi/qla2xxx/qla_mbx.c | 7 ++++--- + drivers/scsi/qla2xxx/qla_os.c | 5 +++-- + 3 files changed, 8 insertions(+), 6 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -4216,7 +4216,7 @@ struct qla_hw_data { + /* Extended Logins */ + void *exlogin_buf; + dma_addr_t exlogin_buf_dma; +- int exlogin_size; ++ uint32_t exlogin_size; + + #define ENABLE_EXCHANGE_OFFLD BIT_2 + +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -845,7 +845,7 @@ qla_get_exlogin_status(scsi_qla_host_t * + * Context: + * Kernel context. + */ +-#define CONFIG_XLOGINS_MEM 0x3 ++#define CONFIG_XLOGINS_MEM 0x9 + int + qla_set_exlogin_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr) + { +@@ -872,8 +872,9 @@ qla_set_exlogin_mem_cfg(scsi_qla_host_t + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + if (rval != QLA_SUCCESS) { +- /*EMPTY*/ +- ql_dbg(ql_dbg_mbx, vha, 0x111b, "Failed=%x.\n", rval); ++ ql_dbg(ql_dbg_mbx, vha, 0x111b, ++ "EXlogin Failed=%x. MB0=%x MB11=%x\n", ++ rval, mcp->mb[0], mcp->mb[11]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118c, + "Done %s.\n", __func__); +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -4392,11 +4392,12 @@ int + qla2x00_set_exlogins_buffer(scsi_qla_host_t *vha) + { + int rval; +- uint16_t size, max_cnt, temp; ++ uint16_t size, max_cnt; ++ uint32_t temp; + struct qla_hw_data *ha = vha->hw; + + /* Return if we don't need to alloacate any extended logins */ +- if (!ql2xexlogins) ++ if (ql2xexlogins <= MAX_FIBRE_DEVICES_2400) + return QLA_SUCCESS; + + if (!IS_EXLOGIN_OFFLD_CAPABLE(ha)) diff --git a/patches.suse/scsi-qla2xxx-Fix-point-to-point-N2N-device-discovery.patch b/patches.suse/scsi-qla2xxx-Fix-point-to-point-N2N-device-discovery.patch new file mode 100644 index 0000000..58fa106 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-point-to-point-N2N-device-discovery.patch @@ -0,0 +1,61 @@ +From: Arun Easi +Date: Tue, 29 Sep 2020 03:21:51 -0700 +Subject: scsi: qla2xxx: Fix point-to-point (N2N) device discovery issue +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 94eda2717826015a80ca271394c4378747de8936 +References: bsc#1176946 bsc#1175520 bsc#1172538 + +Driver was using a shorter timeout waiting for PLOGI from the peer in +point-to-point configurations. Some devices takes some time (~4 seconds) to +initiate the PLOGI. This peer initiating PLOGI is when the peer has a +higher P-WWN. + +Increase the wait time based on N2N R_A_TOV. + +Link: https://lore.kernel.org/r/20200929102152.32278-7-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Arun Easi +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_def.h | 2 ++ + drivers/scsi/qla2xxx/qla_mbx.c | 3 ++- + drivers/scsi/qla2xxx/qla_os.c | 2 ++ + 3 files changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -5147,6 +5147,8 @@ struct sff_8247_a0 { + ha->current_topology == ISP_CFG_N || \ + !ha->current_topology) + ++#define QLA_N2N_WAIT_TIME 5 /* 2 * ra_tov(n2n) + 1 */ ++ + #define NVME_TYPE(fcport) \ + (fcport->fc4_type & FS_FC4TYPE_NVME) \ + +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -3994,7 +3994,8 @@ qla24xx_report_id_acquisition(scsi_qla_h + + if (fcport) { + fcport->plogi_nack_done_deadline = jiffies + HZ; +- fcport->dm_login_expire = jiffies + 2*HZ; ++ fcport->dm_login_expire = jiffies + ++ QLA_N2N_WAIT_TIME * HZ; + fcport->scan_state = QLA_FCPORT_FOUND; + fcport->n2n_flag = 1; + fcport->keep_nport_handle = 1; +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -5110,6 +5110,8 @@ void qla24xx_create_new_sess(struct scsi + + fcport->fc4_type = e->u.new_sess.fc4_type; + if (e->u.new_sess.fc4_type & FS_FCP_IS_N2N) { ++ fcport->dm_login_expire = jiffies + ++ QLA_N2N_WAIT_TIME * HZ; + fcport->fc4_type = FS_FC4TYPE_FCP; + fcport->n2n_flag = 1; + if (vha->flags.nvme_enabled) diff --git a/patches.suse/scsi-qla2xxx-Fix-reset-of-MPI-firmware.patch b/patches.suse/scsi-qla2xxx-Fix-reset-of-MPI-firmware.patch new file mode 100644 index 0000000..68f2410 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-reset-of-MPI-firmware.patch @@ -0,0 +1,169 @@ +From: Arun Easi +Date: Tue, 29 Sep 2020 03:21:49 -0700 +Subject: scsi: qla2xxx: Fix reset of MPI firmware +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 3e6efab865ac943f4ec43913eb665695737112b0 +References: bsc#1176946 bsc#1175520 bsc#1172538 + +Normally, the MPI firmware is reset when an MPI dump is collected. If an +unsaved MPI dump exists in the driver, though, an alternate mechanism is +used. This mechanism, which was not fully correct, is not recommended and +instead an MPI dump template walk is suggested to perform the MPI reset. + +To allow for the MPI dump template walk, extra space is reserved in the MPI +dump buffer which gets used only when there is already an MPI dump in +place. + +Link: https://lore.kernel.org/r/20200929102152.32278-5-njavali@marvell.com +Fixes: cbb01c2f2f63 ("scsi: qla2xxx: Fix MPI failure AEN (8200) handling") +Cc: stable@vger.kernel.org +Reviewed-by: Himanshu Madhani +Signed-off-by: Arun Easi +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_attr.c | 10 ++++++-- + drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_init.c | 2 + + drivers/scsi/qla2xxx/qla_tmpl.c | 49 ++++++++++------------------------------ + 4 files changed, 23 insertions(+), 39 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_attr.c ++++ b/drivers/scsi/qla2xxx/qla_attr.c +@@ -157,6 +157,14 @@ qla2x00_sysfs_write_fw_dump(struct file + vha->host_no); + } + break; ++ case 10: ++ if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { ++ ql_log(ql_log_info, vha, 0x70e9, ++ "Issuing MPI firmware dump on host#%ld.\n", ++ vha->host_no); ++ ha->isp_ops->mpi_fw_dump(vha, 0); ++ } ++ break; + } + return count; + } +@@ -744,8 +752,6 @@ qla2x00_sysfs_write_reset(struct file *f + qla83xx_idc_audit(vha, IDC_AUDIT_TIMESTAMP); + qla83xx_idc_unlock(vha, 0); + break; +- } else if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { +- qla27xx_reset_mpi(vha); + } else { + /* Make sure FC side is not in reset */ + WARN_ON_ONCE(qla2x00_wait_for_hba_online(vha) != +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -945,6 +945,5 @@ extern void qla2x00_dfs_remove_rport(scs + + /* nvme.c */ + void qla_nvme_unregister_remote_port(struct fc_port *fcport); +-void qla27xx_reset_mpi(scsi_qla_host_t *vha); + void qla_handle_els_plogi_done(scsi_qla_host_t *vha, struct event_arg *ea); + #endif /* _QLA_GBL_H */ +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -3300,6 +3300,8 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *v + j, fwdt->dump_size); + dump_size += fwdt->dump_size; + } ++ /* Add space for spare MPI fw dump. */ ++ dump_size += ha->fwdt[1].dump_size; + } else { + req_q_size = req->length * sizeof(request_t); + rsp_q_size = rsp->length * sizeof(response_t); +--- a/drivers/scsi/qla2xxx/qla_tmpl.c ++++ b/drivers/scsi/qla2xxx/qla_tmpl.c +@@ -12,33 +12,6 @@ + #define IOBASE(vha) IOBAR(ISPREG(vha)) + #define INVALID_ENTRY ((struct qla27xx_fwdt_entry *)0xffffffffffffffffUL) + +-/* hardware_lock assumed held. */ +-static void +-qla27xx_write_remote_reg(struct scsi_qla_host *vha, +- u32 addr, u32 data) +-{ +- struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24; +- +- ql_dbg(ql_dbg_misc, vha, 0xd300, +- "%s: addr/data = %xh/%xh\n", __func__, addr, data); +- +- wrt_reg_dword(®->iobase_addr, 0x40); +- wrt_reg_dword(®->iobase_c4, data); +- wrt_reg_dword(®->iobase_window, addr); +-} +- +-void +-qla27xx_reset_mpi(scsi_qla_host_t *vha) +-{ +- ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd301, +- "Entered %s.\n", __func__); +- +- qla27xx_write_remote_reg(vha, 0x104050, 0x40004); +- qla27xx_write_remote_reg(vha, 0x10405c, 0x4); +- +- vha->hw->stat.num_mpi_reset++; +-} +- + static inline void + qla27xx_insert16(uint16_t value, void *buf, ulong *len) + { +@@ -1028,7 +1001,6 @@ void + qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked) + { + ulong flags = 0; +- bool need_mpi_reset = true; + + #ifndef __CHECKER__ + if (!hardware_locked) +@@ -1036,14 +1008,20 @@ qla27xx_mpi_fwdump(scsi_qla_host_t *vha, + #endif + if (!vha->hw->mpi_fw_dump) { + ql_log(ql_log_warn, vha, 0x02f3, "-> mpi_fwdump no buffer\n"); +- } else if (vha->hw->mpi_fw_dumped) { +- ql_log(ql_log_warn, vha, 0x02f4, +- "-> MPI firmware already dumped (%p) -- ignoring request\n", +- vha->hw->mpi_fw_dump); + } else { + struct fwdt *fwdt = &vha->hw->fwdt[1]; + ulong len; + void *buf = vha->hw->mpi_fw_dump; ++ bool walk_template_only = false; ++ ++ if (vha->hw->mpi_fw_dumped) { ++ /* Use the spare area for any further dumps. */ ++ buf += fwdt->dump_size; ++ walk_template_only = true; ++ ql_log(ql_log_warn, vha, 0x02f4, ++ "-> MPI firmware already dumped -- dump saving to temporary buffer %p.\n", ++ buf); ++ } + + ql_log(ql_log_warn, vha, 0x02f5, "-> fwdt1 running...\n"); + if (!fwdt->template) { +@@ -1058,9 +1036,10 @@ qla27xx_mpi_fwdump(scsi_qla_host_t *vha, + ql_log(ql_log_warn, vha, 0x02f7, + "-> fwdt1 fwdump residual=%+ld\n", + fwdt->dump_size - len); +- } else { +- need_mpi_reset = false; + } ++ vha->hw->stat.num_mpi_reset++; ++ if (walk_template_only) ++ goto bailout; + + vha->hw->mpi_fw_dump_len = len; + vha->hw->mpi_fw_dumped = 1; +@@ -1072,8 +1051,6 @@ qla27xx_mpi_fwdump(scsi_qla_host_t *vha, + } + + bailout: +- if (need_mpi_reset) +- qla27xx_reset_mpi(vha); + #ifndef __CHECKER__ + if (!hardware_locked) + spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); diff --git a/patches.suse/scsi-qla2xxx-Honor-status-qualifier-in-FCP_RSP-per-s.patch b/patches.suse/scsi-qla2xxx-Honor-status-qualifier-in-FCP_RSP-per-s.patch new file mode 100644 index 0000000..8539d5c --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Honor-status-qualifier-in-FCP_RSP-per-s.patch @@ -0,0 +1,133 @@ +From: Arun Easi +Date: Thu, 3 Sep 2020 21:51:19 -0700 +Subject: scsi: qla2xxx: Honor status qualifier in FCP_RSP per spec +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 3aac0c0fde17d2fdb65c7840bdf057a681f1e035 +References: bsc#1176946 bsc#1175520 bsc#1172538 + +FCP-4 (referred FCP-4 rev-2b) identifies the earlier known "retry delay +timer" field as "status qualifier", which is described in SAM-5 and later +specs. This fix makes appropriate driver side modifications to honor the +new definition. The SAM document referred was SAM-6 rev-5. + +Link: https://lore.kernel.org/r/20200904045128.23631-5-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Arun Easi +Signed-off-by: Himanshu Madhani +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_fw.h | 2 +- + drivers/scsi/qla2xxx/qla_inline.h | 38 ++++++++++++++++++++++++++++++++++---- + drivers/scsi/qla2xxx/qla_isr.c | 18 +++++------------- + 3 files changed, 40 insertions(+), 18 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_fw.h ++++ b/drivers/scsi/qla2xxx/qla_fw.h +@@ -619,7 +619,7 @@ struct sts_entry_24xx { + #define SF_NVME_ERSP BIT_6 + #define SF_FCP_RSP_DMA BIT_0 + +- __le16 retry_delay; ++ __le16 status_qualifier; + __le16 scsi_status; /* SCSI status. */ + #define SS_CONFIRMATION_REQ BIT_12 + +--- a/drivers/scsi/qla2xxx/qla_inline.h ++++ b/drivers/scsi/qla2xxx/qla_inline.h +@@ -271,11 +271,41 @@ qla2x00_handle_mbx_completion(struct qla + } + + static inline void +-qla2x00_set_retry_delay_timestamp(fc_port_t *fcport, uint16_t retry_delay) ++qla2x00_set_retry_delay_timestamp(fc_port_t *fcport, uint16_t sts_qual) + { +- if (retry_delay) +- fcport->retry_delay_timestamp = jiffies + +- (retry_delay * HZ / 10); ++ u8 scope; ++ u16 qual; ++#define SQ_SCOPE_MASK 0xc000 /* SAM-6 rev5 5.3.2 */ ++#define SQ_SCOPE_SHIFT 14 ++#define SQ_QUAL_MASK 0x3fff ++ ++#define SQ_MAX_WAIT_SEC 60 /* Max I/O hold off time in seconds. */ ++#define SQ_MAX_WAIT_TIME (SQ_MAX_WAIT_SEC * 10) /* in 100ms. */ ++ ++ if (!sts_qual) /* Common case. */ ++ return; ++ ++ scope = (sts_qual & SQ_SCOPE_MASK) >> SQ_SCOPE_SHIFT; ++ /* Handle only scope 1 or 2, which is for I-T nexus. */ ++ if (scope != 1 && scope != 2) ++ return; ++ ++ /* Skip processing, if retry delay timer is already in effect. */ ++ if (fcport->retry_delay_timestamp && ++ time_before(jiffies, fcport->retry_delay_timestamp)) ++ return; ++ ++ qual = sts_qual & SQ_QUAL_MASK; ++ if (qual < 1 || qual > 0x3fef) ++ return; ++ qual = min(qual, (u16)SQ_MAX_WAIT_TIME); ++ ++ /* qual is expressed in 100ms increments. */ ++ fcport->retry_delay_timestamp = jiffies + (qual * HZ / 10); ++ ++ ql_log(ql_log_warn, fcport->vha, 0x5101, ++ "%8phC: I/O throttling requested (status qualifier = %04xh), holding off I/Os for %ums.\n", ++ fcport->port_name, sts_qual, qual * 100); + } + + static inline bool +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -2855,7 +2855,7 @@ qla2x00_status_entry(scsi_qla_host_t *vh + int logit = 1; + int res = 0; + uint16_t state_flags = 0; +- uint16_t retry_delay = 0; ++ uint16_t sts_qual = 0; + + if (IS_FWI2_CAPABLE(ha)) { + comp_status = le16_to_cpu(sts24->comp_status); +@@ -2953,8 +2953,6 @@ qla2x00_status_entry(scsi_qla_host_t *vh + sense_len = par_sense_len = rsp_info_len = resid_len = + fw_resid_len = 0; + if (IS_FWI2_CAPABLE(ha)) { +- u16 sts24_retry_delay = le16_to_cpu(sts24->retry_delay); +- + if (scsi_status & SS_SENSE_LEN_VALID) + sense_len = le32_to_cpu(sts24->sense_len); + if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) +@@ -2968,13 +2966,7 @@ qla2x00_status_entry(scsi_qla_host_t *vh + host_to_fcp_swap(sts24->data, sizeof(sts24->data)); + ox_id = le16_to_cpu(sts24->ox_id); + par_sense_len = sizeof(sts24->data); +- /* Valid values of the retry delay timer are 0x1-0xffef */ +- if (sts24_retry_delay > 0 && sts24_retry_delay < 0xfff1) { +- retry_delay = sts24_retry_delay & 0x3fff; +- ql_dbg(ql_dbg_io, sp->vha, 0x3033, +- "%s: scope=%#x retry_delay=%#x\n", __func__, +- sts24_retry_delay >> 14, retry_delay); +- } ++ sts_qual = le16_to_cpu(sts24->status_qualifier); + } else { + if (scsi_status & SS_SENSE_LEN_VALID) + sense_len = le16_to_cpu(sts->req_sense_length); +@@ -3012,9 +3004,9 @@ qla2x00_status_entry(scsi_qla_host_t *vh + * Check retry_delay_timer value if we receive a busy or + * queue full. + */ +- if (lscsi_status == SAM_STAT_TASK_SET_FULL || +- lscsi_status == SAM_STAT_BUSY) +- qla2x00_set_retry_delay_timestamp(fcport, retry_delay); ++ if (unlikely(lscsi_status == SAM_STAT_TASK_SET_FULL || ++ lscsi_status == SAM_STAT_BUSY)) ++ qla2x00_set_retry_delay_timestamp(fcport, sts_qual); + + /* + * Based on Host and scsi status generate status code for Linux diff --git a/patches.suse/scsi-qla2xxx-Make-tgt_port_database-available-in-ini.patch b/patches.suse/scsi-qla2xxx-Make-tgt_port_database-available-in-ini.patch new file mode 100644 index 0000000..5989746 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Make-tgt_port_database-available-in-ini.patch @@ -0,0 +1,113 @@ +From: Arun Easi +Date: Thu, 3 Sep 2020 21:51:24 -0700 +Subject: scsi: qla2xxx: Make tgt_port_database available in initiator mode +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 4e5a05d1ecd92cec59b11c33821b5407984df81d +References: bsc#1176946 bsc#1175520 bsc#1172538 + +tgt_port_database data is today exported only in target mode, allow it to +be shown in initiator mode as well. + +Link: https://lore.kernel.org/r/20200904045128.23631-10-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Arun Easi +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_dfs.c | 76 ++++++++++++++++++++--------------------- + 1 file changed, 38 insertions(+), 38 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_dfs.c ++++ b/drivers/scsi/qla2xxx/qla_dfs.c +@@ -138,51 +138,51 @@ qla2x00_dfs_tgt_port_database_show(struc + { + scsi_qla_host_t *vha = s->private; + struct qla_hw_data *ha = vha->hw; +- struct gid_list_info *gid_list, *gid; ++ struct gid_list_info *gid_list; + dma_addr_t gid_list_dma; + fc_port_t fc_port; ++ char *id_iter; + int rc, i; + uint16_t entries, loop_id; +- struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; + + seq_printf(s, "%s\n", vha->host_str); +- if (tgt) { +- gid_list = dma_alloc_coherent(&ha->pdev->dev, +- qla2x00_gid_list_size(ha), +- &gid_list_dma, GFP_KERNEL); +- if (!gid_list) { +- ql_dbg(ql_dbg_user, vha, 0x7018, +- "DMA allocation failed for %u\n", +- qla2x00_gid_list_size(ha)); +- return 0; +- } +- +- rc = qla24xx_gidlist_wait(vha, gid_list, gid_list_dma, +- &entries); +- if (rc != QLA_SUCCESS) +- goto out_free_id_list; +- +- gid = gid_list; +- +- seq_puts(s, "Port Name Port ID Loop ID\n"); +- +- for (i = 0; i < entries; i++) { +- loop_id = le16_to_cpu(gid->loop_id); +- memset(&fc_port, 0, sizeof(fc_port_t)); +- +- fc_port.loop_id = loop_id; +- +- rc = qla24xx_gpdb_wait(vha, &fc_port, 0); +- seq_printf(s, "%8phC %02x%02x%02x %d\n", +- fc_port.port_name, fc_port.d_id.b.domain, +- fc_port.d_id.b.area, fc_port.d_id.b.al_pa, +- fc_port.loop_id); +- gid = (void *)gid + ha->gid_list_info_size; +- } +-out_free_id_list: +- dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha), +- gid_list, gid_list_dma); ++ gid_list = dma_alloc_coherent(&ha->pdev->dev, ++ qla2x00_gid_list_size(ha), ++ &gid_list_dma, GFP_KERNEL); ++ if (!gid_list) { ++ ql_dbg(ql_dbg_user, vha, 0x7018, ++ "DMA allocation failed for %u\n", ++ qla2x00_gid_list_size(ha)); ++ return 0; ++ } ++ ++ rc = qla24xx_gidlist_wait(vha, gid_list, gid_list_dma, ++ &entries); ++ if (rc != QLA_SUCCESS) ++ goto out_free_id_list; ++ ++ id_iter = (char *)gid_list; ++ ++ seq_puts(s, "Port Name Port ID Loop ID\n"); ++ ++ for (i = 0; i < entries; i++) { ++ struct gid_list_info *gid = ++ (struct gid_list_info *)id_iter; ++ loop_id = le16_to_cpu(gid->loop_id); ++ memset(&fc_port, 0, sizeof(fc_port_t)); ++ ++ fc_port.loop_id = loop_id; ++ ++ rc = qla24xx_gpdb_wait(vha, &fc_port, 0); ++ seq_printf(s, "%8phC %02x%02x%02x %d\n", ++ fc_port.port_name, fc_port.d_id.b.domain, ++ fc_port.d_id.b.area, fc_port.d_id.b.al_pa, ++ fc_port.loop_id); ++ id_iter += ha->gid_list_info_size; + } ++out_free_id_list: ++ dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha), ++ gid_list, gid_list_dma); + + return 0; + } diff --git a/patches.suse/scsi-qla2xxx-Performance-tweak.patch b/patches.suse/scsi-qla2xxx-Performance-tweak.patch new file mode 100644 index 0000000..9f253e1 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Performance-tweak.patch @@ -0,0 +1,361 @@ +From: Quinn Tran +Date: Thu, 3 Sep 2020 21:51:22 -0700 +Subject: scsi: qla2xxx: Performance tweak +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 49db4d4e02aabcd4fa2f60142ef42e50fb2dd526 +References: bsc#1176946 bsc#1175520 bsc#1172538 + +Move statistics fields from vha struct to qpair to reduce memory thrashing. + +Link: https://lore.kernel.org/r/20200904045128.23631-8-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_attr.c | 46 ++++++++++++++++++++++++++++++++++------ + drivers/scsi/qla2xxx/qla_def.h | 33 +++++++++++++++++++++------- + drivers/scsi/qla2xxx/qla_init.c | 4 --- + drivers/scsi/qla2xxx/qla_iocb.c | 18 ++++++++------- + drivers/scsi/qla2xxx/qla_isr.c | 8 ++++-- + drivers/scsi/qla2xxx/qla_mid.c | 4 --- + drivers/scsi/qla2xxx/qla_nvme.c | 8 +++--- + drivers/scsi/qla2xxx/qla_os.c | 9 ++++--- + 8 files changed, 91 insertions(+), 39 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_attr.c ++++ b/drivers/scsi/qla2xxx/qla_attr.c +@@ -2726,6 +2726,9 @@ qla2x00_get_fc_host_stats(struct Scsi_Ho + struct link_statistics *stats; + dma_addr_t stats_dma; + struct fc_host_statistics *p = &vha->fc_host_stat; ++ struct qla_qpair *qpair; ++ int i; ++ u64 ib = 0, ob = 0, ir = 0, or = 0; + + memset(p, -1, sizeof(*p)); + +@@ -2762,6 +2765,27 @@ qla2x00_get_fc_host_stats(struct Scsi_Ho + if (rval != QLA_SUCCESS) + goto done_free; + ++ /* --- */ ++ for (i = 0; i < vha->hw->max_qpairs; i++) { ++ qpair = vha->hw->queue_pair_map[i]; ++ if (!qpair) ++ continue; ++ ir += qpair->counters.input_requests; ++ or += qpair->counters.output_requests; ++ ib += qpair->counters.input_bytes; ++ ob += qpair->counters.output_bytes; ++ } ++ ir += ha->base_qpair->counters.input_requests; ++ or += ha->base_qpair->counters.output_requests; ++ ib += ha->base_qpair->counters.input_bytes; ++ ob += ha->base_qpair->counters.output_bytes; ++ ++ ir += vha->qla_stats.input_requests; ++ or += vha->qla_stats.output_requests; ++ ib += vha->qla_stats.input_bytes; ++ ob += vha->qla_stats.output_bytes; ++ /* --- */ ++ + p->link_failure_count = le32_to_cpu(stats->link_fail_cnt); + p->loss_of_sync_count = le32_to_cpu(stats->loss_sync_cnt); + p->loss_of_signal_count = le32_to_cpu(stats->loss_sig_cnt); +@@ -2781,15 +2805,16 @@ qla2x00_get_fc_host_stats(struct Scsi_Ho + p->rx_words = le64_to_cpu(stats->fpm_recv_word_cnt); + p->tx_words = le64_to_cpu(stats->fpm_xmit_word_cnt); + } else { +- p->rx_words = vha->qla_stats.input_bytes; +- p->tx_words = vha->qla_stats.output_bytes; ++ p->rx_words = ib >> 2; ++ p->tx_words = ob >> 2; + } + } ++ + p->fcp_control_requests = vha->qla_stats.control_requests; +- p->fcp_input_requests = vha->qla_stats.input_requests; +- p->fcp_output_requests = vha->qla_stats.output_requests; +- p->fcp_input_megabytes = vha->qla_stats.input_bytes >> 20; +- p->fcp_output_megabytes = vha->qla_stats.output_bytes >> 20; ++ p->fcp_input_requests = ir; ++ p->fcp_output_requests = or; ++ p->fcp_input_megabytes = ib >> 20; ++ p->fcp_output_megabytes = ob >> 20; + p->seconds_since_last_reset = + get_jiffies_64() - vha->qla_stats.jiffies_at_last_reset; + do_div(p->seconds_since_last_reset, HZ); +@@ -2809,9 +2834,18 @@ qla2x00_reset_host_stats(struct Scsi_Hos + struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); + struct link_statistics *stats; + dma_addr_t stats_dma; ++ int i; ++ struct qla_qpair *qpair; + + memset(&vha->qla_stats, 0, sizeof(vha->qla_stats)); + memset(&vha->fc_host_stat, 0, sizeof(vha->fc_host_stat)); ++ for (i = 0; i < vha->hw->max_qpairs; i++) { ++ qpair = vha->hw->queue_pair_map[i]; ++ if (!qpair) ++ continue; ++ memset(&qpair->counters, 0, sizeof(qpair->counters)); ++ } ++ memset(&ha->base_qpair->counters, 0, sizeof(qpair->counters)); + + vha->qla_stats.jiffies_at_last_reset = get_jiffies_64(); + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -2443,12 +2443,6 @@ typedef struct fc_port { + struct list_head list; + struct scsi_qla_host *vha; + +- uint8_t node_name[WWN_SIZE]; +- uint8_t port_name[WWN_SIZE]; +- port_id_t d_id; +- uint16_t loop_id; +- uint16_t old_loop_id; +- + unsigned int conf_compl_supported:1; + unsigned int deleted:2; + unsigned int free_pending:1; +@@ -2465,6 +2459,13 @@ typedef struct fc_port { + unsigned int n2n_flag:1; + unsigned int explicit_logout:1; + unsigned int prli_pend_timer:1; ++ uint8_t nvme_flag; ++ ++ uint8_t node_name[WWN_SIZE]; ++ uint8_t port_name[WWN_SIZE]; ++ port_id_t d_id; ++ uint16_t loop_id; ++ uint16_t old_loop_id; + + struct completion nvme_del_done; + uint32_t nvme_prli_service_param; +@@ -2473,7 +2474,7 @@ typedef struct fc_port { + #define NVME_PRLI_SP_TARGET BIT_4 + #define NVME_PRLI_SP_DISCOVERY BIT_3 + #define NVME_PRLI_SP_FIRST_BURST BIT_0 +- uint8_t nvme_flag; ++ + uint32_t nvme_first_burst_size; + #define NVME_FLAG_REGISTERED 4 + #define NVME_FLAG_DELETING 2 +@@ -3510,6 +3511,14 @@ struct qla_tgt_counters { + uint64_t num_term_xchg_sent; + }; + ++struct qla_counters { ++ uint64_t input_bytes; ++ uint64_t input_requests; ++ uint64_t output_bytes; ++ uint64_t output_requests; ++ ++}; ++ + struct qla_qpair; + + /* Response queue data structure */ +@@ -3594,6 +3603,7 @@ struct qla_qpair { + uint32_t enable_class_2:1; + uint32_t enable_explicit_conf:1; + uint32_t use_shadow_reg:1; ++ uint32_t rcv_intr:1; + + uint16_t id; /* qp number used with FW */ + uint16_t vp_idx; /* vport ID */ +@@ -3609,13 +3619,16 @@ struct qla_qpair { + struct qla_msix_entry *msix; /* point to &ha->msix_entries[x] */ + struct qla_hw_data *hw; + struct work_struct q_work; ++ struct qla_counters counters; ++ + struct list_head qp_list_elem; /* vha->qp_list */ + struct list_head hints_list; +- uint16_t cpuid; ++ + uint16_t retry_term_cnt; + __le32 retry_term_exchg_addr; + uint64_t retry_term_jiff; + struct qla_tgt_counters tgt_counters; ++ uint16_t cpuid; + }; + + /* Place holder for FW buffer parameters */ +@@ -4129,6 +4142,10 @@ struct qla_hw_data { + #define USE_ASYNC_SCAN(ha) (IS_QLA25XX(ha) || IS_QLA81XX(ha) ||\ + IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) + ++#define IS_ZIO_THRESHOLD_CAPABLE(ha) \ ++ ((IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&\ ++ (ha->zio_mode == QLA_ZIO_MODE_6)) ++ + /* HBA serial number */ + uint8_t serial0; + uint8_t serial1; +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -3700,9 +3700,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) + goto execute_fw_with_lr; + } + +- if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) || +- IS_QLA28XX(ha)) && +- (ha->zio_mode == QLA_ZIO_MODE_6)) ++ if (IS_ZIO_THRESHOLD_CAPABLE(ha)) + qla27xx_set_zio_threshold(vha, + ha->last_zio_threshold); + +--- a/drivers/scsi/qla2xxx/qla_iocb.c ++++ b/drivers/scsi/qla2xxx/qla_iocb.c +@@ -594,6 +594,7 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *s + uint32_t dsd_list_len; + struct dsd_dma *dsd_ptr; + struct ct6_dsd *ctx; ++ struct qla_qpair *qpair = sp->qpair; + + cmd = GET_CMD_SP(sp); + +@@ -612,12 +613,12 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *s + /* Set transfer direction */ + if (cmd->sc_data_direction == DMA_TO_DEVICE) { + cmd_pkt->control_flags = cpu_to_le16(CF_WRITE_DATA); +- vha->qla_stats.output_bytes += scsi_bufflen(cmd); +- vha->qla_stats.output_requests++; ++ qpair->counters.output_bytes += scsi_bufflen(cmd); ++ qpair->counters.output_requests++; + } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { + cmd_pkt->control_flags = cpu_to_le16(CF_READ_DATA); +- vha->qla_stats.input_bytes += scsi_bufflen(cmd); +- vha->qla_stats.input_requests++; ++ qpair->counters.input_bytes += scsi_bufflen(cmd); ++ qpair->counters.input_requests++; + } + + cur_seg = scsi_sglist(cmd); +@@ -704,6 +705,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, stru + struct scsi_cmnd *cmd; + struct scatterlist *sg; + int i; ++ struct qla_qpair *qpair = sp->qpair; + + cmd = GET_CMD_SP(sp); + +@@ -721,12 +723,12 @@ qla24xx_build_scsi_iocbs(srb_t *sp, stru + /* Set transfer direction */ + if (cmd->sc_data_direction == DMA_TO_DEVICE) { + cmd_pkt->task_mgmt_flags = cpu_to_le16(TMF_WRITE_DATA); +- vha->qla_stats.output_bytes += scsi_bufflen(cmd); +- vha->qla_stats.output_requests++; ++ qpair->counters.output_bytes += scsi_bufflen(cmd); ++ qpair->counters.output_requests++; + } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { + cmd_pkt->task_mgmt_flags = cpu_to_le16(TMF_READ_DATA); +- vha->qla_stats.input_bytes += scsi_bufflen(cmd); +- vha->qla_stats.input_requests++; ++ qpair->counters.input_bytes += scsi_bufflen(cmd); ++ qpair->counters.input_requests++; + } + + /* One DSD is available in the Command Type 3 IOCB */ +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -3414,8 +3414,10 @@ void qla24xx_process_response_queue(stru + if (!ha->flags.fw_started) + return; + +- if (rsp->qpair->cpuid != smp_processor_id()) ++ if (rsp->qpair->cpuid != smp_processor_id() || !rsp->qpair->rcv_intr) { ++ rsp->qpair->rcv_intr = 1; + qla_cpu_update(rsp->qpair, smp_processor_id()); ++ } + + while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) { + pkt = (struct sts_entry_24xx *)rsp->ring_ptr; +@@ -3865,7 +3867,7 @@ qla2xxx_msix_rsp_q(int irq, void *dev_id + } + ha = qpair->hw; + +- queue_work(ha->wq, &qpair->q_work); ++ queue_work_on(smp_processor_id(), ha->wq, &qpair->q_work); + + return IRQ_HANDLED; + } +@@ -3891,7 +3893,7 @@ qla2xxx_msix_rsp_q_hs(int irq, void *dev + wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + +- queue_work(ha->wq, &qpair->q_work); ++ queue_work_on(smp_processor_id(), ha->wq, &qpair->q_work); + + return IRQ_HANDLED; + } +--- a/drivers/scsi/qla2xxx/qla_mid.c ++++ b/drivers/scsi/qla2xxx/qla_mid.c +@@ -808,11 +808,9 @@ static void qla_do_work(struct work_stru + { + unsigned long flags; + struct qla_qpair *qpair = container_of(work, struct qla_qpair, q_work); +- struct scsi_qla_host *vha; +- struct qla_hw_data *ha = qpair->hw; ++ struct scsi_qla_host *vha = qpair->vha; + + spin_lock_irqsave(&qpair->qp_lock, flags); +- vha = pci_get_drvdata(ha->pdev); + qla24xx_process_response_queue(vha, qpair->rsp); + spin_unlock_irqrestore(&qpair->qp_lock, flags); + +--- a/drivers/scsi/qla2xxx/qla_nvme.c ++++ b/drivers/scsi/qla2xxx/qla_nvme.c +@@ -439,8 +439,8 @@ static inline int qla2x00_start_nvme_mq( + /* No data transfer how do we check buffer len == 0?? */ + if (fd->io_dir == NVMEFC_FCP_READ) { + cmd_pkt->control_flags = cpu_to_le16(CF_READ_DATA); +- vha->qla_stats.input_bytes += fd->payload_length; +- vha->qla_stats.input_requests++; ++ qpair->counters.input_bytes += fd->payload_length; ++ qpair->counters.input_requests++; + } else if (fd->io_dir == NVMEFC_FCP_WRITE) { + cmd_pkt->control_flags = cpu_to_le16(CF_WRITE_DATA); + if ((vha->flags.nvme_first_burst) && +@@ -452,8 +452,8 @@ static inline int qla2x00_start_nvme_mq( + cmd_pkt->control_flags |= + cpu_to_le16(CF_NVME_FIRST_BURST_ENABLE); + } +- vha->qla_stats.output_bytes += fd->payload_length; +- vha->qla_stats.output_requests++; ++ qpair->counters.output_bytes += fd->payload_length; ++ qpair->counters.output_requests++; + } else if (fd->io_dir == 0) { + cmd_pkt->control_flags = 0; + } +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -7210,8 +7210,10 @@ qla2x00_timer(scsi_qla_host_t *vha) + * FC-NVME + * see if the active AEN count has changed from what was last reported. + */ ++ index = atomic_read(&ha->nvme_active_aen_cnt); + if (!vha->vp_idx && +- (atomic_read(&ha->nvme_active_aen_cnt) != ha->nvme_last_rptd_aen) && ++ (index != ha->nvme_last_rptd_aen) && ++ (index >= DEFAULT_ZIO_THRESHOLD) && + ha->zio_mode == QLA_ZIO_MODE_6 && + !ha->flags.host_shutting_down) { + ql_log(ql_log_info, vha, 0x3002, +@@ -7223,9 +7225,8 @@ qla2x00_timer(scsi_qla_host_t *vha) + } + + if (!vha->vp_idx && +- (atomic_read(&ha->zio_threshold) != ha->last_zio_threshold) && +- (ha->zio_mode == QLA_ZIO_MODE_6) && +- (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))) { ++ atomic_read(&ha->zio_threshold) != ha->last_zio_threshold && ++ IS_ZIO_THRESHOLD_CAPABLE(ha)) { + ql_log(ql_log_info, vha, 0x3002, + "Sched: Set ZIO exchange threshold to %d.\n", + ha->last_zio_threshold); diff --git a/patches.suse/scsi-qla2xxx-Reduce-duplicate-code-in-reporting-spee.patch b/patches.suse/scsi-qla2xxx-Reduce-duplicate-code-in-reporting-spee.patch new file mode 100644 index 0000000..4c03c04 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Reduce-duplicate-code-in-reporting-spee.patch @@ -0,0 +1,227 @@ +From: Quinn Tran +Date: Thu, 3 Sep 2020 21:51:20 -0700 +Subject: scsi: qla2xxx: Reduce duplicate code in reporting speed +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: d68930bae477e864e016aeb8d557f099b4636aac +References: bsc#1176946 bsc#1175520 bsc#1172538 + +Indicate correct speed for 16G Mezz card. + +Link: https://lore.kernel.org/r/20200904045128.23631-6-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_attr.c | 41 ----------------- + drivers/scsi/qla2xxx/qla_gbl.h | 2 + drivers/scsi/qla2xxx/qla_gs.c | 7 +- + drivers/scsi/qla2xxx/qla_os.c | 96 ---------------------------------------- + 4 files changed, 9 insertions(+), 137 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_attr.c ++++ b/drivers/scsi/qla2xxx/qla_attr.c +@@ -3213,46 +3213,7 @@ qla2x00_init_host_attr(scsi_qla_host_t * + fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports; + fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count; + +- if (IS_CNA_CAPABLE(ha)) +- speeds = FC_PORTSPEED_10GBIT; +- else if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) { +- if (ha->max_supported_speed == 2) { +- if (ha->min_supported_speed <= 6) +- speeds |= FC_PORTSPEED_64GBIT; +- } +- if (ha->max_supported_speed == 2 || +- ha->max_supported_speed == 1) { +- if (ha->min_supported_speed <= 5) +- speeds |= FC_PORTSPEED_32GBIT; +- } +- if (ha->max_supported_speed == 2 || +- ha->max_supported_speed == 1 || +- ha->max_supported_speed == 0) { +- if (ha->min_supported_speed <= 4) +- speeds |= FC_PORTSPEED_16GBIT; +- } +- if (ha->max_supported_speed == 1 || +- ha->max_supported_speed == 0) { +- if (ha->min_supported_speed <= 3) +- speeds |= FC_PORTSPEED_8GBIT; +- } +- if (ha->max_supported_speed == 0) { +- if (ha->min_supported_speed <= 2) +- speeds |= FC_PORTSPEED_4GBIT; +- } +- } else if (IS_QLA2031(ha)) +- speeds = FC_PORTSPEED_16GBIT|FC_PORTSPEED_8GBIT| +- FC_PORTSPEED_4GBIT; +- else if (IS_QLA25XX(ha) || IS_QLAFX00(ha)) +- speeds = FC_PORTSPEED_8GBIT|FC_PORTSPEED_4GBIT| +- FC_PORTSPEED_2GBIT|FC_PORTSPEED_1GBIT; +- else if (IS_QLA24XX_TYPE(ha)) +- speeds = FC_PORTSPEED_4GBIT|FC_PORTSPEED_2GBIT| +- FC_PORTSPEED_1GBIT; +- else if (IS_QLA23XX(ha)) +- speeds = FC_PORTSPEED_2GBIT|FC_PORTSPEED_1GBIT; +- else +- speeds = FC_PORTSPEED_1GBIT; ++ speeds = qla25xx_fdmi_port_speed_capability(ha); + + fc_host_supported_speeds(vha->host) = speeds; + } +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -704,6 +704,8 @@ int qla24xx_async_gfpnid(scsi_qla_host_t + void qla24xx_handle_gfpnid_event(scsi_qla_host_t *, struct event_arg *); + void qla24xx_sp_unmap(scsi_qla_host_t *, srb_t *); + void qla_scan_work_fn(struct work_struct *); ++uint qla25xx_fdmi_port_speed_capability(struct qla_hw_data *); ++uint qla25xx_fdmi_port_speed_currently(struct qla_hw_data *); + + /* + * Global Function Prototypes in qla_attr.c source file. +--- a/drivers/scsi/qla2xxx/qla_gs.c ++++ b/drivers/scsi/qla2xxx/qla_gs.c +@@ -1502,7 +1502,7 @@ qla2x00_prep_ct_fdmi_req(struct ct_sns_p + return &p->p.req; + } + +-static uint ++uint + qla25xx_fdmi_port_speed_capability(struct qla_hw_data *ha) + { + uint speeds = 0; +@@ -1546,7 +1546,7 @@ qla25xx_fdmi_port_speed_capability(struc + } + return speeds; + } +- if (IS_QLA25XX(ha)) ++ if (IS_QLA25XX(ha) || IS_QLAFX00(ha)) + return FDMI_PORT_SPEED_8GB|FDMI_PORT_SPEED_4GB| + FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB; + if (IS_QLA24XX_TYPE(ha)) +@@ -1556,7 +1556,8 @@ qla25xx_fdmi_port_speed_capability(struc + return FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB; + return FDMI_PORT_SPEED_1GB; + } +-static uint ++ ++uint + qla25xx_fdmi_port_speed_currently(struct qla_hw_data *ha) + { + switch (ha->link_data_rate) { +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -5823,98 +5823,6 @@ qla25xx_rdp_rsp_reduce_size(struct scsi_ + return true; + } + +-static uint +-qla25xx_rdp_port_speed_capability(struct qla_hw_data *ha) +-{ +- if (IS_CNA_CAPABLE(ha)) +- return RDP_PORT_SPEED_10GB; +- +- if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { +- unsigned int speeds = 0; +- +- if (ha->max_supported_speed == 2) { +- if (ha->min_supported_speed <= 6) +- speeds |= RDP_PORT_SPEED_64GB; +- } +- +- if (ha->max_supported_speed == 2 || +- ha->max_supported_speed == 1) { +- if (ha->min_supported_speed <= 5) +- speeds |= RDP_PORT_SPEED_32GB; +- } +- +- if (ha->max_supported_speed == 2 || +- ha->max_supported_speed == 1 || +- ha->max_supported_speed == 0) { +- if (ha->min_supported_speed <= 4) +- speeds |= RDP_PORT_SPEED_16GB; +- } +- +- if (ha->max_supported_speed == 1 || +- ha->max_supported_speed == 0) { +- if (ha->min_supported_speed <= 3) +- speeds |= RDP_PORT_SPEED_8GB; +- } +- +- if (ha->max_supported_speed == 0) { +- if (ha->min_supported_speed <= 2) +- speeds |= RDP_PORT_SPEED_4GB; +- } +- +- return speeds; +- } +- +- if (IS_QLA2031(ha)) +- return RDP_PORT_SPEED_16GB|RDP_PORT_SPEED_8GB| +- RDP_PORT_SPEED_4GB; +- +- if (IS_QLA25XX(ha)) +- return RDP_PORT_SPEED_8GB|RDP_PORT_SPEED_4GB| +- RDP_PORT_SPEED_2GB|RDP_PORT_SPEED_1GB; +- +- if (IS_QLA24XX_TYPE(ha)) +- return RDP_PORT_SPEED_4GB|RDP_PORT_SPEED_2GB| +- RDP_PORT_SPEED_1GB; +- +- if (IS_QLA23XX(ha)) +- return RDP_PORT_SPEED_2GB|RDP_PORT_SPEED_1GB; +- +- return RDP_PORT_SPEED_1GB; +-} +- +-static uint +-qla25xx_rdp_port_speed_currently(struct qla_hw_data *ha) +-{ +- switch (ha->link_data_rate) { +- case PORT_SPEED_1GB: +- return RDP_PORT_SPEED_1GB; +- +- case PORT_SPEED_2GB: +- return RDP_PORT_SPEED_2GB; +- +- case PORT_SPEED_4GB: +- return RDP_PORT_SPEED_4GB; +- +- case PORT_SPEED_8GB: +- return RDP_PORT_SPEED_8GB; +- +- case PORT_SPEED_10GB: +- return RDP_PORT_SPEED_10GB; +- +- case PORT_SPEED_16GB: +- return RDP_PORT_SPEED_16GB; +- +- case PORT_SPEED_32GB: +- return RDP_PORT_SPEED_32GB; +- +- case PORT_SPEED_64GB: +- return RDP_PORT_SPEED_64GB; +- +- default: +- return RDP_PORT_SPEED_UNKNOWN; +- } +-} +- + /* + * Function Name: qla24xx_process_purex_iocb + * +@@ -6081,9 +5989,9 @@ void qla24xx_process_purex_rdp(struct sc + rsp_payload->port_speed_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_speed_desc)); + rsp_payload->port_speed_desc.speed_capab = cpu_to_be16( +- qla25xx_rdp_port_speed_capability(ha)); ++ qla25xx_fdmi_port_speed_capability(ha)); + rsp_payload->port_speed_desc.operating_speed = cpu_to_be16( +- qla25xx_rdp_port_speed_currently(ha)); ++ qla25xx_fdmi_port_speed_currently(ha)); + + /* Link Error Status Descriptor */ + rsp_payload->ls_err_desc.desc_tag = cpu_to_be32(0x10002); diff --git a/patches.suse/scsi-qla2xxx-Remove-unneeded-variable-rval.patch b/patches.suse/scsi-qla2xxx-Remove-unneeded-variable-rval.patch new file mode 100644 index 0000000..96d838b --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Remove-unneeded-variable-rval.patch @@ -0,0 +1,46 @@ +From: Jason Yan +Date: Fri, 11 Sep 2020 17:10:21 +0800 +Subject: scsi: qla2xxx: Remove unneeded variable 'rval' +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 34eb5ccf35daea082b6bc3857f82f23155fb266f +References: bsc#1176946 bsc#1175520 bsc#1172538 + +This addresses the following coccinelle warning: + +drivers/scsi/qla2xxx/qla_init.c:7112:5-9: Unneeded variable: "rval". +Return "QLA_SUCCESS" on line 7115 + +Link: https://lore.kernel.org/r/20200911091021.2937708-1-yanaijie@huawei.com +Reported-by: Hulk Robot +Reviewed-by: Himanshu Madhani +Signed-off-by: Jason Yan +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_init.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -7119,10 +7119,9 @@ qla24xx_reset_adapter(scsi_qla_host_t *v + unsigned long flags = 0; + struct qla_hw_data *ha = vha->hw; + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; +- int rval = QLA_SUCCESS; + + if (IS_P3P_TYPE(ha)) +- return rval; ++ return QLA_SUCCESS; + + vha->flags.online = 0; + ha->isp_ops->disable_intrs(ha); +@@ -7137,7 +7136,7 @@ qla24xx_reset_adapter(scsi_qla_host_t *v + if (IS_NOPOLLING_TYPE(ha)) + ha->isp_ops->enable_intrs(ha); + +- return rval; ++ return QLA_SUCCESS; + } + + /* On sparc systems, obtain port and node WWN from firmware diff --git a/patches.suse/scsi-qla2xxx-Setup-debugfs-entries-for-remote-ports.patch b/patches.suse/scsi-qla2xxx-Setup-debugfs-entries-for-remote-ports.patch new file mode 100644 index 0000000..1659a53 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Setup-debugfs-entries-for-remote-ports.patch @@ -0,0 +1,146 @@ +From: Arun Easi +Date: Thu, 3 Sep 2020 21:51:17 -0700 +Subject: scsi: qla2xxx: Setup debugfs entries for remote ports +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 1e98fb0f9208da058e2b6627f9f19fa0a95d05cd +References: bsc#1176946 bsc#1175520 bsc#1172538 + +Create a base for adding remote port related entries in debugfs. + +Link: https://lore.kernel.org/r/20200904045128.23631-3-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Arun Easi +Signed-off-by: Himanshu Madhani +Signed-off-by: Saurav Kashyap +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_def.h | 4 +++ + drivers/scsi/qla2xxx/qla_dfs.c | 42 +++++++++++++++++++++++++++++++++++++- + drivers/scsi/qla2xxx/qla_gbl.h | 2 + + drivers/scsi/qla2xxx/qla_init.c | 2 + + drivers/scsi/qla2xxx/qla_target.c | 2 + + 5 files changed, 51 insertions(+), 1 deletion(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -2544,6 +2544,8 @@ typedef struct fc_port { + u8 last_login_state; + u16 n2n_link_reset_cnt; + u16 n2n_chip_reset; ++ ++ struct dentry *dfs_rport_dir; + } fc_port_t; + + enum { +@@ -4780,6 +4782,8 @@ typedef struct scsi_qla_host { + uint16_t ql2xexchoffld; + uint16_t ql2xiniexchg; + ++ struct dentry *dfs_rport_root; ++ + struct purex_list { + struct list_head head; + spinlock_t lock; +--- a/drivers/scsi/qla2xxx/qla_dfs.c ++++ b/drivers/scsi/qla2xxx/qla_dfs.c +@@ -12,6 +12,29 @@ + static struct dentry *qla2x00_dfs_root; + static atomic_t qla2x00_dfs_root_count; + ++void ++qla2x00_dfs_create_rport(scsi_qla_host_t *vha, struct fc_port *fp) ++{ ++ char wwn[32]; ++ ++ if (!vha->dfs_rport_root || fp->dfs_rport_dir) ++ return; ++ ++ sprintf(wwn, "pn-%016llx", wwn_to_u64(fp->port_name)); ++ fp->dfs_rport_dir = debugfs_create_dir(wwn, vha->dfs_rport_root); ++ if (!fp->dfs_rport_dir) ++ return; ++} ++ ++void ++qla2x00_dfs_remove_rport(scsi_qla_host_t *vha, struct fc_port *fp) ++{ ++ if (!vha->dfs_rport_root || !fp->dfs_rport_dir) ++ return; ++ debugfs_remove_recursive(fp->dfs_rport_dir); ++ fp->dfs_rport_dir = NULL; ++} ++ + static int + qla2x00_dfs_tgt_sess_show(struct seq_file *s, void *unused) + { +@@ -473,9 +496,21 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha) + ha->tgt.dfs_tgt_sess = debugfs_create_file("tgt_sess", + S_IRUSR, ha->dfs_dir, vha, &dfs_tgt_sess_ops); + +- if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) ++ if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) { + ha->tgt.dfs_naqp = debugfs_create_file("naqp", + 0400, ha->dfs_dir, vha, &dfs_naqp_ops); ++ if (!ha->tgt.dfs_naqp) { ++ ql_log(ql_log_warn, vha, 0xd011, ++ "Unable to create debugFS naqp node.\n"); ++ goto out; ++ } ++ } ++ vha->dfs_rport_root = debugfs_create_dir("rports", ha->dfs_dir); ++ if (!vha->dfs_rport_root) { ++ ql_log(ql_log_warn, vha, 0xd012, ++ "Unable to create debugFS rports node.\n"); ++ goto out; ++ } + out: + return 0; + } +@@ -515,6 +550,11 @@ qla2x00_dfs_remove(scsi_qla_host_t *vha) + ha->dfs_fce = NULL; + } + ++ if (vha->dfs_rport_root) { ++ debugfs_remove_recursive(vha->dfs_rport_root); ++ vha->dfs_rport_root = NULL; ++ } ++ + if (ha->dfs_dir) { + debugfs_remove(ha->dfs_dir); + ha->dfs_dir = NULL; +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -935,6 +935,8 @@ void qlt_clr_qp_table(struct scsi_qla_ho + void qlt_set_mode(struct scsi_qla_host *); + int qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode); + extern void qla24xx_process_purex_list(struct purex_list *); ++extern void qla2x00_dfs_create_rport(scsi_qla_host_t *vha, struct fc_port *fp); ++extern void qla2x00_dfs_remove_rport(scsi_qla_host_t *vha, struct fc_port *fp); + + /* nvme.c */ + void qla_nvme_unregister_remote_port(struct fc_port *fcport); +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -5496,6 +5496,8 @@ qla2x00_update_fcport(scsi_qla_host_t *v + + qla2x00_iidma_fcport(vha, fcport); + ++ qla2x00_dfs_create_rport(vha, fcport); ++ + if (NVME_TARGET(vha->hw, fcport)) { + qla_nvme_register_remote(vha, fcport); + qla2x00_set_fcport_disc_state(fcport, DSC_LOGIN_COMPLETE); +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -1120,6 +1120,8 @@ void qlt_free_session_done(struct work_s + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + sess->free_pending = 0; + ++ qla2x00_dfs_remove_rport(vha, sess); ++ + ql_dbg(ql_dbg_disc, vha, 0xf001, + "Unregistration of sess %p %8phC finished fcp_cnt %d\n", + sess, sess->port_name, vha->fcport_count); diff --git a/patches.suse/scsi-qla2xxx-Update-version-to-10.02.00.102-k.patch b/patches.suse/scsi-qla2xxx-Update-version-to-10.02.00.102-k.patch new file mode 100644 index 0000000..fc3b8b7 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Update-version-to-10.02.00.102-k.patch @@ -0,0 +1,45 @@ +From: Nilesh Javali +Date: Thu, 3 Sep 2020 21:51:28 -0700 +Subject: scsi: qla2xxx: Update version to 10.02.00.102-k +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 767c8457b729e774f5a4646f60a0598ab868c798 +References: bsc#1176946 bsc#1175520 bsc#1172538 + +Update internal driver version and remove module version macro. + +Link: https://lore.kernel.org/r/20200904045128.23631-14-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_os.c | 1 - + drivers/scsi/qla2xxx/qla_version.h | 6 +++--- + 2 files changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -7975,7 +7975,6 @@ module_exit(qla2x00_module_exit); + MODULE_AUTHOR("QLogic Corporation"); + MODULE_DESCRIPTION("QLogic Fibre Channel HBA Driver"); + MODULE_LICENSE("GPL"); +-MODULE_VERSION(QLA2XXX_VERSION); + MODULE_FIRMWARE(FW_FILE_ISP21XX); + MODULE_FIRMWARE(FW_FILE_ISP22XX); + MODULE_FIRMWARE(FW_FILE_ISP2300); +--- a/drivers/scsi/qla2xxx/qla_version.h ++++ b/drivers/scsi/qla2xxx/qla_version.h +@@ -7,9 +7,9 @@ + /* + * Driver version + */ +-#define QLA2XXX_VERSION "10.01.00.25-k" ++#define QLA2XXX_VERSION "10.02.00.102-k" + + #define QLA_DRIVER_MAJOR_VER 10 +-#define QLA_DRIVER_MINOR_VER 1 ++#define QLA_DRIVER_MINOR_VER 2 + #define QLA_DRIVER_PATCH_VER 0 +-#define QLA_DRIVER_BETA_VER 0 ++#define QLA_DRIVER_BETA_VER 102 diff --git a/patches.suse/scsi-qla2xxx-Update-version-to-10.02.00.103-k.patch b/patches.suse/scsi-qla2xxx-Update-version-to-10.02.00.103-k.patch new file mode 100644 index 0000000..d3135a1 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Update-version-to-10.02.00.103-k.patch @@ -0,0 +1,31 @@ +From: Nilesh Javali +Date: Tue, 29 Sep 2020 03:21:52 -0700 +Subject: scsi: qla2xxx: Update version to 10.02.00.103-k +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 718c2fe92b208415fa76550975dc5d7708448f7c +References: bsc#1176946 bsc#1175520 bsc#1172538 + +Link: https://lore.kernel.org/r/20200929102152.32278-8-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_version.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_version.h ++++ b/drivers/scsi/qla2xxx/qla_version.h +@@ -7,9 +7,9 @@ + /* + * Driver version + */ +-#define QLA2XXX_VERSION "10.02.00.102-k" ++#define QLA2XXX_VERSION "10.02.00.103-k" + + #define QLA_DRIVER_MAJOR_VER 10 + #define QLA_DRIVER_MINOR_VER 2 + #define QLA_DRIVER_PATCH_VER 0 +-#define QLA_DRIVER_BETA_VER 102 ++#define QLA_DRIVER_BETA_VER 103 diff --git a/rpm/kernel-binary.spec.in b/rpm/kernel-binary.spec.in index 68dac04..d33d8be 100644 --- a/rpm/kernel-binary.spec.in +++ b/rpm/kernel-binary.spec.in @@ -824,7 +824,7 @@ if [ %CONFIG_MODULES = y ]; then fi done - tar -cf - -T %my_builddir/obj-files | \ + tar --exclude=\*.ipa-clones -cf - -T %my_builddir/obj-files | \ tar -xf - -C %rpm_install_dir/%cpu_arch_flavor # bnc#507084 find %rpm_install_dir/%cpu_arch_flavor/scripts -type f -perm -111 | \ @@ -874,6 +874,9 @@ for file in %buildroot/boot/symtypes* %buildroot/lib/modules/*/{build,source}; d f=${file##%buildroot} echo "$f" done | add_dirs_to_filelist >%my_builddir/kernel-devel.files +( cd %buildroot ; find .%obj_install_dir/%cpu_arch_flavor -type f ; ) | \ +sed -e 's/^[.]//' | grep -v -e '[.]ipa-clones$' -e '/Symbols[.]list$' -e '/ipa-clones[.]list$'| \ +add_dirs_to_filelist >> %my_builddir/kernel-devel.files { cd %buildroot for f in boot/*; do @@ -1088,13 +1091,9 @@ kernel module packages) against the %build_flavor flavor of the kernel. %files devel -f kernel-devel.files %defattr(-,root,root) -%dir %obj_install_dir -%dir %obj_install_dir/%cpu_arch %dir /usr/src/linux-obj %dir /usr/src/linux-obj/%cpu_arch %ghost /usr/src/linux-obj/%cpu_arch_flavor -%obj_install_dir/%cpu_arch_flavor -%exclude %obj_install_dir/%cpu_arch_flavor/Symbols.list %if %kmp_target_cpu != %cpu_arch %obj_install_dir/%kmp_target_cpu /usr/src/linux-obj/%kmp_target_cpu diff --git a/series.conf b/series.conf index 413c7f0..61032f1 100644 --- a/series.conf +++ b/series.conf @@ -2740,6 +2740,20 @@ patches.suse/net-mlx5e-IPSec-Add-IPSec-ethtool-stats.patch patches.suse/bpf-Add-syscall-lookup-support-for-fd-array-and-htab.patch patches.suse/bpf-Add-test-for-syscall-on-fd-array-htab-lookup.patch + patches.suse/0012-amd-xgbe-Fix-SFP-PHY-supported-advertised-settings.patch + patches.suse/0013-amd-xgbe-Use-the-proper-register-during-PTP-initiali.patch + patches.suse/0014-amd-xgbe-Add-a-check-for-an-skb-in-the-timestamp-pat.patch + patches.suse/0015-amd-xgbe-Prevent-looping-forever-if-timestamp-update.patch + patches.suse/0016-amd-xgbe-Handle-return-code-from-software-reset-func.patch + patches.suse/0017-amd-xgbe-Fixes-for-working-with-PHYs-that-support-2..patch + patches.suse/0018-amd-xgbe-Limit-the-I2C-error-messages-that-are-outpu.patch + patches.suse/0019-amd-xgbe-Re-issue-interrupt-if-interrupt-status-not-.patch + patches.suse/0020-amd-xgbe-Add-NUMA-affinity-support-for-memory-alloca.patch + patches.suse/0021-amd-xgbe-Add-NUMA-affinity-support-for-IRQ-hints.patch + patches.suse/0022-amd-xgbe-Prepare-for-more-fine-grained-cache-coheren.patch + patches.suse/0023-amd-xgbe-Simplify-the-burst-length-settings.patch + patches.suse/0024-amd-xgbe-Adjust-register-settings-to-improve-perform.patch + patches.suse/0025-amd-xgbe-fix-spelling-mistake-avialable-available.patch patches.suse/bpf-Fix-out-of-bound-access-on-interpreters.patch patches.suse/ibmvnic-102-Fix-assignment-of-RX-TX-IRQ-s.patch patches.suse/net-ibm-ibmveth-constify-dev_pm_ops-structures.patch @@ -8310,6 +8324,7 @@ patches.suse/net-Kill-NETIF_F_UFO-and-SKB_GSO_UDP.patch patches.suse/samples-bpf-add-option-for-native-and-skb-mode-for-r.patch patches.suse/net-fix-build-error-in-devmap-helper-calls.patch + patches.suse/0026-drivers-net-add-missing-interrupt.h-include.patch patches.suse/mlxsw-spectrum_router-Enable-IPv6-router.patch patches.suse/mlxsw-reg-Enable-IPv6-on-router-interfaces.patch patches.suse/mlxsw-spectrum-Add-support-for-IPv6-traps.patch @@ -8844,7 +8859,19 @@ patches.suse/xdp-adjust-xdp-redirect-tracepoint-to-include-return.patch patches.suse/bpf-Fix-map-in-map-checking-in-the-verifier.patch patches.suse/mlx5-ensure-0-is-returned-when-vport-is-zero.patch + patches.suse/0027-amd-xgbe-Set-the-MDIO-mode-for-10000Base-T-configura.patch + patches.suse/0028-amd-xgbe-Set-the-MII-control-width-for-the-MAC-inter.patch + patches.suse/0029-amd-xgbe-Be-sure-driver-shuts-down-cleanly-on-module.patch + patches.suse/0030-amd-xgbe-Update-TSO-packet-statistics-accuracy.patch + patches.suse/0031-amd-xgbe-Add-support-to-handle-device-renaming.patch + patches.suse/0032-amd-xgbe-Add-additional-dynamic-debug-messages.patch + patches.suse/0033-amd-xgbe-Optimize-DMA-channel-interrupt-enablement.patch + patches.suse/0034-amd-xgbe-Add-hardware-features-debug-output.patch + patches.suse/0035-amd-xgbe-Add-per-queue-Tx-and-Rx-statistics.patch patches.suse/net-ethtool-Add-macro-to-clear-a-link-mode-setting.patch + patches.suse/0036-amd-xgbe-Convert-to-using-the-new-link-mode-settings.patch + patches.suse/0037-amd-xgbe-Add-support-for-VXLAN-offload-capabilities.patch + patches.suse/0038-amd-xgbe-Add-additional-ethtool-statistics.patch patches.suse/net-don-t-decrement-kobj-reference-count-on-init-fai.patch patches.suse/net-constify-netdev_class_file.patch patches.suse/net-make-net_class-ro_after_init.patch @@ -9128,6 +9155,7 @@ patches.suse/net-mlx4-Add-user-mac-FW-update-support.patch patches.suse/if_ether-add-forces-ife-lfb-type.patch patches.suse/act_ife-use-registered-ife_type-as-fallback.patch + patches.suse/0039-amd-xgbe-Interrupt-summary-bits-are-h-w-version-depe.patch patches.suse/liquidio-show-NIC-s-U-Boot-version-in-a-dev_info-mes.patch patches.suse/net-remove-dmaengine.h-inclusion-from-netdevice.h.patch patches.suse/idr-Add-new-APIs-to-support-unsigned-long.patch @@ -21121,6 +21149,7 @@ patches.suse/ip6_vti-adjust-vti-mtu-according-to-mtu-of-lower-dev.patch patches.suse/netdevsim-declare-struct-device_type-as-static.patch patches.suse/netdevsim-bpf-remove-unused-variable.patch + patches.suse/0040-net-amd-xgbe-Get-rid-of-custom-hex_dump_to_buffer.patch patches.suse/netdevsim-correctly-check-return-value-of-debugfs_cr.patch patches.suse/s390-sles15sp1-00-08-93-qeth-convert-qeth_reply-refcnt-from-atomic_t-to-refc.patch patches.suse/s390-sles15sp1-00-08-15-s390-qeth-use-ip-_eth_mc_map-helpers.patch @@ -24025,6 +24054,7 @@ patches.suse/sctp-fix-dst-refcnt-leak-in-sctp_v4_get_dst.patch patches.suse/ibmvnic-fix-empty-firmware-version-and-errors-cleanu.patch patches.suse/net-phy-Handle-not-having-GPIO-enabled-in-the-kernel.patch + patches.suse/0041-net-amd-xgbe-fix-comparison-to-bitshift-when-dealing.patch patches.suse/cls_u32-fix-use-after-free-in-u32_destroy_key.patch patches.suse/sample-bpf-fix-erspan-metadata.patch patches.suse/nfp-fix-kdoc-warnings-on-nested-structures.patch @@ -33424,6 +33454,18 @@ patches.suse/s390-sles15sp1-00-11-106-net-smc-lock-smc_lgr_list-in-port_terminate.patch patches.suse/s390-sles15sp1-00-11-107-net-smc-urgent-data-support.patch patches.suse/s390-sles15sp1-00-11-108-net-smc-longer-delay-when-freeing-client-link-groups.patch + patches.suse/0007-amd-xgbe-Fix-debug-output-of-max-channel-counts.patch + patches.suse/0008-amd-xgbe-Read-and-save-the-port-property-registers-d.patch + patches.suse/0009-amd-xgbe-Remove-use-of-comm_owned-field.patch + patches.suse/0010-amd-xgbe-Remove-field-that-indicates-SFP-diagnostic-.patch + patches.suse/0042-amd-xgbe-Add-ethtool-support-to-retrieve-SFP-module-.patch + patches.suse/0043-amd-xgbe-Add-ethtool-show-set-ring-parameter-support.patch + patches.suse/0044-amd-xgbe-Prepare-for-ethtool-set-channel-support.patch + patches.suse/0045-amd-xgbe-Add-ethtool-show-set-channels-support.patch + patches.suse/0011-amd-xgbe-Always-attempt-link-training-in-KR-mode.patch + patches.suse/0046-amd-xgbe-Advertise-FEC-support-with-the-KR-re-driver.patch + patches.suse/0047-amd-xgbe-Update-the-BelFuse-quirk-to-support-SGMII.patch + patches.suse/0048-amd-xgbe-Improve-SFP-100Mbps-auto-negotiation.patch patches.suse/netfilter-ip6t_rpfilter-provide-input-interface-for-.patch patches.suse/cxgb4-Check-for-kvzalloc-allocation-failure.patch patches.suse/ibmvnic-Mark-NAPI-flag-as-disabled-when-released.patch @@ -37065,6 +37107,7 @@ patches.suse/mlxsw-spectrum_acl-Pass-C-TCAM-region-and-entry-to-i.patch patches.suse/mlxsw-spectrum_acl-Add-A-TCAM-rule-insertion-and-del.patch patches.suse/mlxsw-spectrum_acl-Start-using-A-TCAM.patch + patches.suse/0049-amd-xgbe-use-dma_mapping_error-to-check-map-errors.patch patches.suse/nfp-don-t-fail-probe-on-pci_sriov_set_totalvfs-error.patch patches.suse/nfp-use-kvcalloc-to-allocate-SW-buffer-descriptor-ar.patch patches.suse/nfp-restore-correct-ordering-of-fields-in-rx-ring-st.patch @@ -41631,6 +41674,7 @@ patches.suse/net-phy-phylink-ensure-the-carrier-is-off-when-start.patch patches.suse/net-mvpp2-do-not-explicitly-set-the-carrier-state-in.patch patches.suse/net-marvell-fix-return-type-of-ndo_start_xmit-functi.patch + patches.suse/0050-net-amd-fix-return-type-of-ndo_start_xmit-function.patch patches.suse/net-hns3-Add-default-irq-affinity.patch patches.suse/net-hns3-Add-unlikely-for-buf_num-check.patch patches.suse/net-hns3-Remove-tx-budget-to-clean-more-TX-descripto.patch @@ -48879,6 +48923,7 @@ patches.suse/Bluetooth-hidp-fix-buffer-overflow.patch patches.suse/6lowpan-Off-by-one-handling-nexthdr.patch patches.suse/Bluetooth-Align-minimum-encryption-key-size-for-LE-a.patch + patches.suse/0051-amd-xgbe-Mark-expected-switch-fall-throughs.patch patches.suse/cxgb4-cxgb4vf_main-Mark-expected-switch-fall-through.patch patches.suse/net-hns3-fix-data-race-between-ring-next_to_clean.patch patches.suse/net-hns3-fix-for-TX-clean-num-when-cleaning-TX-BD.patch @@ -50507,6 +50552,7 @@ patches.suse/net-tls-fix-socket-wmem-accounting-on-fallback-with-.patch patches.suse/dt-bindings-allow-up-to-four-clocks-for-orion-mdio.patch patches.suse/net-mvmdio-allow-up-to-four-clocks-to-be-specified-f.patch + patches.suse/0004-net-mvmdio-defer-probe-of-orion-mdio-if-a-clock-is-n.patch patches.suse/irqchip-gic-v3-its-Fix-misuse-of-GENMASK-macro.patch patches.suse/stacktrace-use-pf_kthread-to-check-for-kernel-threads.patch patches.suse/x86-alternatives-fix-int3_emulate_call-selftest-stack-corruption.patch @@ -51111,6 +51157,9 @@ patches.suse/mac80211_hwsim-Fix-possible-null-pointer-dereference.patch patches.suse/isdn-hfcsusb-Fix-mISDN-driver-crash-caused-by-transf.patch patches.suse/net-bridge-mcast-don-t-delete-permanent-entries-when.patch + patches.suse/0001-net-8390-Fix-manufacturer-name-in-Kconfig-help-text.patch + patches.suse/0002-net-apple-Fix-manufacturer-name-in-Kconfig-help-text.patch + patches.suse/0003-net-broadcom-Fix-manufacturer-name-in-Kconfig-help-t.patch patches.suse/tipc-compat-allow-tipc-commands-without-arguments.patch patches.suse/net-usb-pegasus-fix-improper-read-if-get_registers-f.patch patches.suse/atm-iphase-Fix-Spectre-v1-vulnerability.patch @@ -51118,6 +51167,7 @@ patches.suse/net-fix-bpf_xdp_adjust_head-regression-for-generic-X.patch patches.suse/net-smc-do-not-schedule-tx_work-in-smc_closed-state.patch patches.suse/net-smc-avoid-fallback-in-case-of-non-blocking-connect + patches.suse/0005-drivers-net-ethernet-marvell-mvmdio.c-Fix-non-OF-cas.patch patches.suse/can-sja1000-force-the-string-buffer-NULL-terminated.patch patches.suse/can-peak_usb-force-the-string-buffer-NULL-terminated.patch patches.suse/0005-can-peak_usb-pcan_usb_fd-Fix-info-leaks-to-USB-devic.patch @@ -51222,6 +51272,7 @@ patches.suse/net-mlx5e-Only-support-tx-rx-pause-setting-for-port-.patch patches.suse/msft-hv-1910-hv_netvsc-Fix-a-warning-of-suspicious-RCU-usage.patch patches.suse/tools-bpftool-fix-error-message-prog-object.patch + patches.suse/0006-net-tc35815-Explicitly-check-NET_IP_ALIGN-is-not-zer.patch patches.suse/sctp-fix-the-transport-error_count-check.patch patches.suse/ibmveth-Convert-multicast-list-size-for-little-endia.patch patches.suse/net-mlx4_en-fix-a-memory-leak-bug.patch @@ -51302,6 +51353,7 @@ patches.suse/ALSA-seq-Fix-potential-concurrent-access-to-the-dele.patch patches.suse/NFSv4-pnfs-Fix-a-page-lock-leak-in-nfs_pageio_resend.patch patches.suse/NFS-Ensure-O_DIRECT-reports-an-error-if-the-bytes-re.patch + patches.suse/NFS-On-fatal-writeback-errors-we-need-to-call-nfs_in.patch patches.suse/pNFS-flexfiles-Turn-off-soft-RPC-calls.patch patches.suse/SUNRPC-Handle-connection-breakages-correctly-in-call.patch patches.suse/cifs-set-domainName-when-a-domain-key-is-used-in-multiuser.patch @@ -51337,6 +51389,7 @@ patches.suse/sky2-Disable-MSI-on-yet-another-ASUS-boards-P6Xxxx.patch patches.suse/mac80211-Don-t-memset-RXCB-prior-to-PAE-intercept.patch patches.suse/mac80211-Correctly-set-noencrypt-for-PAE-frames.patch + patches.suse/0054-amd-xgbe-Fix-error-path-in-xgbe_mod_init.patch patches.suse/net-stmmac-dwmac-rk-Don-t-fail-if-phy-regulator-is-a.patch patches.suse/batman-adv-Only-read-OGM-tvlv_len-after-buffer-len-c.patch patches.suse/batman-adv-Only-read-OGM2-tvlv_len-after-buffer-len-.patch @@ -51620,6 +51673,7 @@ patches.suse/net-hns3-fix-some-reset-handshake-issue.patch patches.suse/cxgb4-smt-Add-lock-for-atomic_dec_and_test.patch patches.suse/net-hns3-fix-GFP-flag-error-in-hclge_mac_update_stat.patch + patches.suse/0052-xgbe-no-need-to-check-return-value-of-debugfs_create.patch patches.suse/netfilter-connlabels-prefer-static-lock-initialiser.patch patches.suse/can-xilinx_can-xcan_probe-skip-error-message-on-defe.patch patches.suse/net-hns3-prevent-unnecessary-MAC-TNL-interrupt.patch @@ -51628,6 +51682,7 @@ patches.suse/Revert-mwifiex-fix-system-hang-problem-after-resume.patch patches.suse/can-mcp251x-mcp251x_hw_reset-allow-more-time-after-a.patch patches.suse/mac80211-minstrel_ht-fix-per-group-max-throughput-ra.patch + patches.suse/0053-amd-xgbe-use-devm_platform_ioremap_resource-to-simpl.patch patches.suse/i40e-reduce-stack-usage-in-i40e_set_fc.patch patches.suse/IB-mlx5-Support-MLX5_CMD_OP_QUERY_LAG-as-a-DEVX-gene.patch patches.suse/net-mlx5e-ethtool-Fix-a-typo-in-WOL-function-names.patch @@ -53614,6 +53669,7 @@ patches.suse/net-ena-remove-set-but-not-used-variable-rx_ring.patch patches.suse/vmxnet3-Remove-always-false-conditional-statement.patch patches.suse/ptr_ring-add-include-of-linux-mm.h.patch + patches.suse/0055-amd-xgbe-remove-unnecessary-conversion-to-bool.patch patches.suse/net_sched-ematch-reject-invalid-TCF_EM_SIMPLE.patch patches.suse/Bluetooth-Fix-race-condition-in-hci_release_sock.patch patches.suse/mwifiex-drop-most-magic-numbers-from-mwifiex_process.patch @@ -53875,6 +53931,7 @@ patches.suse/drm-amd-display-Retrain-dongles-when-SINK_COUNT-beco.patch patches.suse/0001-drm-amd-dm-mst-Ignore-payload-update-failures.patch patches.suse/NFS-Revalidate-the-file-size-on-a-fatal-write-error.patch + patches.suse/NFS-Revalidate-the-file-mapping-on-all-fatal-writeba.patch patches.suse/NFS-pnfs-Fix-pnfs_generic_prepare_to_resend_writes.patch patches.suse/NFS-Fix-memory-leaks-and-corruption-in-readdir.patch patches.suse/NFS-Directory-page-cache-pages-need-to-be-locked-whe.patch @@ -54361,6 +54418,7 @@ patches.suse/mac80211-add-ieee80211_is_any_nullfunc.patch patches.suse/net-ena-remove-set-but-not-used-variable-hash_key.patch patches.suse/net-ena-ethtool-remove-redundant-non-zero-check-on-r.patch + patches.suse/0056-net-amd-Remove-useless-driver-version.patch patches.suse/hsr-use-netdev_err-instead-of-WARN_ONCE.patch patches.suse/ethtool-Factored-out-similar-ethtool-link-settings-f.patch patches.suse/net-ethtool-Introduce-link_ksettings-API-for-virtual.patch @@ -54675,6 +54733,7 @@ patches.suse/net-cxgb4-Check-the-return-from-t4_query_params-prop.patch patches.suse/mac80211_hwsim-Use-kstrndup-in-place-of-kasprintf.patch patches.suse/xsk-Add-missing-check-on-user-supplied-headroom-size.patch + patches.suse/0057-amd-xgbe-Use-__napi_schedule-in-BH-context.patch patches.suse/ALSA-ctxfi-Remove-unnecessary-cast-in-kfree.patch patches.suse/ALSA-hda-realtek-Enable-the-headset-mic-on-Asus-FX50.patch patches.suse/ALSA-usb-audio-Filter-error-from-connector-kctl-ops-.patch @@ -55532,6 +55591,11 @@ patches.suse/crypto-cpt-don-t-sleep-of-CRYPTO_TFM_REQ_MAY_SLEEP-w.patch patches.suse/crypto-ccp-Fix-use-of-merged-scatterlists.patch patches.suse/crypto-qat-fix-double-free-in-qat_uclo_create_batch_.patch + patches.suse/crypto-ecdh-check-validity-of-z-before-export + patches.suse/lib-mpi-add-mpi_sub_ui + patches.suse/crypto-dh-check-validity-of-z-before-export + patches.suse/crypto-dh-sp800-56a-rev-3-local-public-key-validation + patches.suse/crypto-ecc-sp800-56a-rev-3-local-public-key-validation patches.suse/mtd-properly-check-all-write-ioctls-for-permissions.patch patches.suse/0012-block-add-docs-for-gendisk-request_queue-refcount-he.patch patches.suse/0013-block-revert-back-to-synchronous-request_queue-remov.patch @@ -55618,9 +55682,11 @@ patches.suse/drm-nouveau-Fix-reference-count-leak-in-nouveau_conn.patch patches.suse/drm-ttm-nouveau-don-t-call-tt-destroy-callback-on-al.patch patches.suse/drm-msm-ratelimit-crtc-event-overflow-error.patch + patches.suse/0058-amd-xgbe-Convert-to-generic-power-management.patch patches.suse/0014-net-mlx5e-vxlan-Use-RCU-for-vxlan-table-lookup.patch patches.suse/0005-ipvs-allow-connection-reuse-for-unconfirmed-conntrac.patch patches.suse/0004-net-make-symbol-flush_works-static.patch + patches.suse/0059-xgbe-switch-to-more-generic-VxLAN-detection.patch patches.suse/net-ena-Fix-using-plain-integer-as-NULL-pointer-in-e.patch patches.suse/brcmfmac-keep-SDIO-watchdog-running-when-console_int.patch patches.suse/brcmfmac-To-fix-Bss-Info-flag-definition-Bug.patch @@ -56019,21 +56085,26 @@ patches.suse/ieee802154-adf7242-check-status-of-adf7242_read_reg.patch patches.suse/mac802154-tx-fix-use-after-free.patch patches.suse/hdlc_ppp-add-range-checks-in-ppp_cp_parse_cr.patch + patches.suse/geneve-add-transport-ports-in-route-lookup-for-genev.patch patches.suse/batman-adv-bla-fix-type-misuse-for-backbone_gw-hash-.patch patches.suse/batman-adv-mcast-TT-fix-wrongly-dropped-or-rerouted-.patch patches.suse/batman-adv-Add-missing-include-for-in_interrupt.patch patches.suse/batman-adv-mcast-fix-duplicate-mcast-packets-in-BLA-.patch + patches.suse/mac80211-do-not-allow-bigger-VHT-MPDUs-than-the-hard.patch patches.suse/ALSA-asihpi-fix-iounmap-in-error-handler.patch patches.suse/Revert-ALSA-usb-audio-Disable-Lenovo-P620-Rear-line-.patch patches.suse/drm-vc4-vc4_hdmi-fill-ASoC-card-owner.patch patches.suse/drm-sun4i-sun8i-csc-Secondary-CSC-register-correctio.patch + patches.suse/drm-sun4i-mixer-Extend-regmap-max_register.patch patches.suse/kvm-svm-add-a-dedicated-invd-intercept-routine.patch patches.suse/clocksource-drivers-h8300_timer8-Fix-wrong-return-va.patch + patches.suse/nfs-Fix-security-label-length-not-being-reset.patch patches.suse/clk-samsung-exynos4-mark-chipid-clock-as-CLK_IGNORE_.patch patches.suse/ftrace-move-rcu-is-watching-check-after-recursion-check.patch patches.suse/iommu-exynos-add-missing-put_device-call-in-exynos_iommu_of_xlate patches.suse/mmc-sdhci-Workaround-broken-command-queuing-on-Intel.patch patches.suse/gpio-tc35894-fix-up-tc35894-interrupt-configuration.patch + patches.suse/scsi-iscsi-iscsi_tcp-avoid-holding-spinlock-while-calling-getpeername patches.suse/pinctrl-mvebu-Fix-i2c-sda-definition-for-98DX3236.patch patches.suse/i2c-cpm-Fix-i2c_ram-structure.patch patches.suse/USB-gadget-f_ncm-Fix-NDP16-datagram-validation.patch @@ -56042,6 +56113,9 @@ patches.suse/platform-x86-thinkpad_acpi-initialize-tp_nvram_state.patch patches.suse/platform-x86-fix-kconfig-dependency-warning-for-FUJI.patch patches.suse/platform-x86-thinkpad_acpi-re-initialize-ACPI-buffer.patch + patches.suse/macsec-avoid-use-after-free-in-macsec_handle_frame.patch + patches.suse/mmc-core-don-t-set-limits.discard_granularity-as-0.patch + patches.suse/i2c-meson-fix-clock-setting-overwrite.patch # jejb/scsi for-next patches.suse/scsi-smartpqi-identify-physical-devices-without-issuing-inquiry.patch @@ -56062,7 +56136,31 @@ patches.suse/scsi-qla2xxx-Warn-if-done-or-free-are-called-on-an-a.patch patches.suse/scsi-qla2xxx-Simplify-return-value-logic-in-qla2x00_.patch patches.suse/scsi-qla2xxx-Log-calling-function-name-in-qla2x00_ge.patch + patches.suse/scsi-qla2xxx-Remove-unneeded-variable-rval.patch patches.suse/scsi-ibmvfc-Avoid-link-down-on-FS9100-canister-reboo.patch + patches.suse/scsi-qla2xxx-Fix-I-O-failures-during-remote-port-tog.patch + patches.suse/scsi-qla2xxx-Setup-debugfs-entries-for-remote-ports.patch + patches.suse/scsi-qla2xxx-Allow-dev_loss_tmo-setting-for-FC-NVMe-.patch + patches.suse/scsi-qla2xxx-Honor-status-qualifier-in-FCP_RSP-per-s.patch + patches.suse/scsi-qla2xxx-Reduce-duplicate-code-in-reporting-spee.patch + patches.suse/scsi-qla2xxx-Fix-memory-size-truncation.patch + patches.suse/scsi-qla2xxx-Performance-tweak.patch + patches.suse/scsi-qla2xxx-Fix-I-O-errors-during-LIP-reset-tests.patch + patches.suse/scsi-qla2xxx-Make-tgt_port_database-available-in-ini.patch + patches.suse/scsi-qla2xxx-Add-rport-fields-in-debugfs.patch + patches.suse/scsi-qla2xxx-Add-IOCB-resource-tracking.patch + patches.suse/scsi-qla2xxx-Add-SLER-and-PI-control-support.patch + patches.suse/scsi-qla2xxx-Update-version-to-10.02.00.102-k.patch + patches.suse/scsi-qla2xxx-Correct-the-check-for-sscanf-return-val.patch + patches.suse/scsi-qla2xxx-Fix-buffer-buffer-credit-extraction-err.patch + patches.suse/scsi-qla2xxx-Fix-MPI-reset-needed-message.patch + patches.suse/scsi-qla2xxx-Fix-reset-of-MPI-firmware.patch + patches.suse/scsi-qla2xxx-Fix-crash-on-session-cleanup-with-unloa.patch + patches.suse/scsi-qla2xxx-Fix-point-to-point-N2N-device-discovery.patch + patches.suse/scsi-qla2xxx-Update-version-to-10.02.00.103-k.patch + patches.suse/scsi-qla2xxx-Fix-inconsistent-format-argument-type-i.patch + patches.suse/scsi-qla2xxx-Fix-inconsistent-format-argument-type-i-250bd009.patch + patches.suse/scsi-qla2xxx-Fix-inconsistent-format-argument-type-i-72e813d9.patch # dhowells/linux-fs keys-uefi patches.suse/0001-KEYS-Allow-unrestricted-boot-time-addition-of-keys-t.patch