mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00
kernel: bump to 4.14.167, 4.19.98 (#2871)
* kernel: bump to 4.14.167, 4.19.98 * ipq40xx: fix error patch * bcm2708: sh: use /bin/sh * kernel: sfp: add Nokia SFP fix from net-next
This commit is contained in:
parent
c7cfa84287
commit
06dc25a010
@ -7,12 +7,12 @@ ifdef CONFIG_TESTING_KERNEL
|
||||
endif
|
||||
|
||||
LINUX_VERSION-4.9 = .208
|
||||
LINUX_VERSION-4.14 = .162
|
||||
LINUX_VERSION-4.19 = .93
|
||||
LINUX_VERSION-4.14 = .167
|
||||
LINUX_VERSION-4.19 = .98
|
||||
|
||||
LINUX_KERNEL_HASH-4.9.208 = b7ad1c9841d671d026c55a4c91c77205f8b488ca5f980f838591c68662e0525a
|
||||
LINUX_KERNEL_HASH-4.14.162 = f65170224cd4359ce8b2793b492bd8127abdd0b91350484e001bce13f0c98b4b
|
||||
LINUX_KERNEL_HASH-4.19.93 = 2af5d23f82a8bf69a6e4d8407579293b7beeebd3054dc464d48bdb5d2d7f5834
|
||||
LINUX_KERNEL_HASH-4.14.167 = 2bb78fc7a902faf4f5dad47fdbc2f4bf3df3cf9b41f408e7260f36656659fe43
|
||||
LINUX_KERNEL_HASH-4.19.98 = 91feb13bc22d60d69596ab1d01dfecbec13ef70f00c89a483e0733af94dd2937
|
||||
|
||||
remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1))))
|
||||
sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1)))))))
|
||||
|
64
package/boot/uboot-tegra/Makefile
Normal file
64
package/boot/uboot-tegra/Makefile
Normal file
@ -0,0 +1,64 @@
|
||||
#
|
||||
# Copyright (C) 2017-2019 Tomasz Maciej Nowak <tomek_n@o2.pl>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION := 2019.04
|
||||
PKG_RELEASE := 1
|
||||
|
||||
PKG_HASH := 76b7772d156b3ddd7644c8a1736081e55b78828537ff714065d21dbade229bef
|
||||
|
||||
PKG_MAINTAINER := Tomasz Maciej Nowak <tomek_n@o2.pl>
|
||||
|
||||
include $(INCLUDE_DIR)/u-boot.mk
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define U-Boot/Default
|
||||
BUILD_TARGET := tegra
|
||||
HIDDEN := y
|
||||
endef
|
||||
|
||||
define U-Boot/trimslice
|
||||
NAME := CompuLab TrimSlice
|
||||
BUILD_DEVICES := compulab_trimslice
|
||||
UBOOT_IMAGE := trimslice-mmc.img trimslice-spi.img
|
||||
SOC := tegra20
|
||||
VENDOR := compulab
|
||||
endef
|
||||
|
||||
UBOOT_TARGETS := trimslice
|
||||
|
||||
define Build/bct-image
|
||||
$(CP) $(PKG_BUILD_DIR)/u-boot-dtb-tegra.bin $(PKG_BUILD_DIR)/u-boot.bin
|
||||
$(foreach bct,$(basename $(UBOOT_IMAGE)), \
|
||||
cd $(PKG_BUILD_DIR); \
|
||||
cbootimage -s $(SOC) -gbct \
|
||||
$(STAGING_DIR_HOST)/share/cbootimage-configs/$(SOC)/$(VENDOR)/$(VARIANT)/$(bct).bct.cfg \
|
||||
$(bct).bct; \
|
||||
cbootimage -s $(SOC) \
|
||||
$(STAGING_DIR_HOST)/share/cbootimage-configs/$(SOC)/$(VENDOR)/$(VARIANT)/$(bct).img.cfg \
|
||||
$(PKG_BUILD_DIR)/$(bct).img; \
|
||||
rm -f $(bct).bct; \
|
||||
)
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
sed '/select BINMAN/d' -i $(PKG_BUILD_DIR)/arch/arm/mach-tegra/Kconfig
|
||||
$(call Build/Configure/U-Boot)
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(call Build/Compile/U-Boot)
|
||||
$(call Build/bct-image)
|
||||
endef
|
||||
|
||||
define Build/InstallDev
|
||||
$(INSTALL_DIR) $(STAGING_DIR_IMAGE)
|
||||
$(foreach img,$(UBOOT_IMAGE), \
|
||||
$(CP) $(PKG_BUILD_DIR)/$(img) $(STAGING_DIR_IMAGE)/;)
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage/U-Boot))
|
@ -35,7 +35,7 @@
|
||||
|
||||
/* Atmel chips don't use the same PRI format as AMD chips */
|
||||
static void fixup_convert_atmel_pri(struct mtd_info *mtd)
|
||||
@@ -1800,6 +1804,7 @@ static int cfi_amdstd_write_words(struct
|
||||
@@ -1798,6 +1802,7 @@ static int cfi_amdstd_write_words(struct
|
||||
/*
|
||||
* FIXME: interleaved mode not tested, and probably not supported!
|
||||
*/
|
||||
@ -43,7 +43,7 @@
|
||||
static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
|
||||
unsigned long adr, const u_char *buf,
|
||||
int len)
|
||||
@@ -1928,7 +1933,6 @@ static int __xipram do_write_buffer(stru
|
||||
@@ -1926,7 +1931,6 @@ static int __xipram do_write_buffer(stru
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@
|
||||
static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
|
||||
size_t *retlen, const u_char *buf)
|
||||
{
|
||||
@@ -2003,6 +2007,7 @@ static int cfi_amdstd_write_buffers(stru
|
||||
@@ -2001,6 +2005,7 @@ static int cfi_amdstd_write_buffers(stru
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
gpiod_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(gpiod_reset))
|
||||
return PTR_ERR(gpiod_reset);
|
||||
@@ -411,15 +418,23 @@ static void at803x_link_change_notify(st
|
||||
@@ -402,15 +409,23 @@ static void at803x_link_change_notify(st
|
||||
* cannot recover from by software.
|
||||
*/
|
||||
if (phydev->state == PHY_NOLINK) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/phy/at803x.c
|
||||
+++ b/drivers/net/phy/at803x.c
|
||||
@@ -478,12 +478,15 @@ static void at803x_link_change_notify(st
|
||||
@@ -458,12 +458,15 @@ static void at803x_link_change_notify(st
|
||||
|
||||
static int at803x_aneg_done(struct phy_device *phydev)
|
||||
{
|
||||
@ -16,7 +16,7 @@
|
||||
/*
|
||||
* in SGMII mode, if copper side autoneg is successful,
|
||||
* also check SGMII side autoneg result
|
||||
@@ -498,7 +501,8 @@ static int at803x_aneg_done(struct phy_d
|
||||
@@ -478,7 +481,8 @@ static int at803x_aneg_done(struct phy_d
|
||||
/* check if the SGMII link is OK. */
|
||||
if (!(phy_read(phydev, AT803X_PSSR) & AT803X_PSSR_MR_AN_COMPLETE)) {
|
||||
pr_warn("803x_aneg_done: SGMII link is not ok\n");
|
||||
|
@ -757,7 +757,7 @@
|
||||
EXPORT_SYMBOL(xfrm_parse_spi);
|
||||
--- a/net/ipv4/tcp_input.c
|
||||
+++ b/net/ipv4/tcp_input.c
|
||||
@@ -3874,14 +3874,16 @@ static bool tcp_parse_aligned_timestamp(
|
||||
@@ -3878,14 +3878,16 @@ static bool tcp_parse_aligned_timestamp(
|
||||
{
|
||||
const __be32 *ptr = (const __be32 *)(th + 1);
|
||||
|
||||
|
@ -0,0 +1,90 @@
|
||||
From 60efe35257b063ce584968f9f80b437030ce6ba6 Mon Sep 17 00:00:00 2001
|
||||
From: David Bauer <mail@david-bauer.net>
|
||||
Date: Mon, 18 Mar 2019 00:54:06 +0100
|
||||
Subject: [PATCH] MIPS: ath79: add missing QCA955x GMAC registers
|
||||
|
||||
This adds missing GMAC register definitions for the Qualcomm Atheros
|
||||
QCA955X series MIPS SoCs.
|
||||
|
||||
They originate from the platforms U-Boot code and the AVM FRITZ!WLAN
|
||||
Repeater 450E's GPL tarball.
|
||||
|
||||
Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
---
|
||||
.../mips/include/asm/mach-ath79/ar71xx_regs.h | 54 +++++++++++++++++++
|
||||
1 file changed, 54 insertions(+)
|
||||
|
||||
--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
|
||||
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
|
||||
@@ -1249,7 +1249,12 @@
|
||||
*/
|
||||
|
||||
#define QCA955X_GMAC_REG_ETH_CFG 0x00
|
||||
+#define QCA955X_GMAC_REG_SGMII_RESET 0x14
|
||||
#define QCA955X_GMAC_REG_SGMII_SERDES 0x18
|
||||
+#define QCA955X_GMAC_REG_MR_AN_CONTROL 0x1c
|
||||
+#define QCA955X_GMAC_REG_MR_AN_STATUS 0x20
|
||||
+#define QCA955X_GMAC_REG_SGMII_CONFIG 0x34
|
||||
+#define QCA955X_GMAC_REG_SGMII_DEBUG 0x58
|
||||
|
||||
#define QCA955X_ETH_CFG_RGMII_EN BIT(0)
|
||||
#define QCA955X_ETH_CFG_MII_GE0 BIT(1)
|
||||
@@ -1271,9 +1276,58 @@
|
||||
#define QCA955X_ETH_CFG_TXE_DELAY_MASK 0x3
|
||||
#define QCA955X_ETH_CFG_TXE_DELAY_SHIFT 20
|
||||
|
||||
+#define QCA955X_SGMII_RESET_RX_CLK_N_RESET 0
|
||||
+#define QCA955X_SGMII_RESET_RX_CLK_N BIT(0)
|
||||
+#define QCA955X_SGMII_RESET_TX_CLK_N BIT(1)
|
||||
+#define QCA955X_SGMII_RESET_RX_125M_N BIT(2)
|
||||
+#define QCA955X_SGMII_RESET_TX_125M_N BIT(3)
|
||||
+#define QCA955X_SGMII_RESET_HW_RX_125M_N BIT(4)
|
||||
+
|
||||
#define QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS BIT(15)
|
||||
#define QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT 23
|
||||
#define QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK 0xf
|
||||
+
|
||||
+#define QCA955X_MR_AN_CONTROL_SPEED_SEL1 BIT(6)
|
||||
+#define QCA955X_MR_AN_CONTROL_DUPLEX_MODE BIT(8)
|
||||
+#define QCA955X_MR_AN_CONTROL_RESTART_AN BIT(9)
|
||||
+#define QCA955X_MR_AN_CONTROL_POWER_DOWN BIT(11)
|
||||
+#define QCA955X_MR_AN_CONTROL_AN_ENABLE BIT(12)
|
||||
+#define QCA955X_MR_AN_CONTROL_SPEED_SEL0 BIT(13)
|
||||
+#define QCA955X_MR_AN_CONTROL_LOOPBACK BIT(14)
|
||||
+#define QCA955X_MR_AN_CONTROL_PHY_RESET BIT(15)
|
||||
+
|
||||
+#define QCA955X_MR_AN_STATUS_EXT_CAP BIT(0)
|
||||
+#define QCA955X_MR_AN_STATUS_LINK_UP BIT(2)
|
||||
+#define QCA955X_MR_AN_STATUS_AN_ABILITY BIT(3)
|
||||
+#define QCA955X_MR_AN_STATUS_REMOTE_FAULT BIT(4)
|
||||
+#define QCA955X_MR_AN_STATUS_AN_COMPLETE BIT(5)
|
||||
+#define QCA955X_MR_AN_STATUS_NO_PREAMBLE BIT(6)
|
||||
+#define QCA955X_MR_AN_STATUS_BASE_PAGE BIT(7)
|
||||
+
|
||||
+#define QCA955X_SGMII_CONFIG_MODE_CTRL_SHIFT 0
|
||||
+#define QCA955X_SGMII_CONFIG_MODE_CTRL_MASK 0x7
|
||||
+#define QCA955X_SGMII_CONFIG_ENABLE_SGMII_TX_PAUSE BIT(3)
|
||||
+#define QCA955X_SGMII_CONFIG_MR_REG4_CHANGED BIT(4)
|
||||
+#define QCA955X_SGMII_CONFIG_FORCE_SPEED BIT(5)
|
||||
+#define QCA955X_SGMII_CONFIG_SPEED_SHIFT 6
|
||||
+#define QCA955X_SGMII_CONFIG_SPEED_MASK 0xc0
|
||||
+#define QCA955X_SGMII_CONFIG_REMOTE_PHY_LOOPBACK BIT(8)
|
||||
+#define QCA955X_SGMII_CONFIG_NEXT_PAGE_LOADED BIT(9)
|
||||
+#define QCA955X_SGMII_CONFIG_MDIO_ENABLE BIT(10)
|
||||
+#define QCA955X_SGMII_CONFIG_MDIO_PULSE BIT(11)
|
||||
+#define QCA955X_SGMII_CONFIG_MDIO_COMPLETE BIT(12)
|
||||
+#define QCA955X_SGMII_CONFIG_PRBS_ENABLE BIT(13)
|
||||
+#define QCA955X_SGMII_CONFIG_BERT_ENABLE BIT(14)
|
||||
+
|
||||
+#define QCA955X_SGMII_DEBUG_TX_STATE_MASK 0xff
|
||||
+#define QCA955X_SGMII_DEBUG_TX_STATE_SHIFT 0
|
||||
+#define QCA955X_SGMII_DEBUG_RX_STATE_MASK 0xff00
|
||||
+#define QCA955X_SGMII_DEBUG_RX_STATE_SHIFT 8
|
||||
+#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_MASK 0xff0000
|
||||
+#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_SHIFT 16
|
||||
+#define QCA955X_SGMII_DEBUG_ARB_STATE_MASK 0xf000000
|
||||
+#define QCA955X_SGMII_DEBUG_ARB_STATE_SHIFT 24
|
||||
+
|
||||
/*
|
||||
* QCA956X GMAC Interface
|
||||
*/
|
@ -1,62 +0,0 @@
|
||||
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
|
||||
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
|
||||
@@ -1641,7 +1641,7 @@ static int __xipram do_write_oneword(str
|
||||
}
|
||||
|
||||
if (chip_good(map, adr, datum))
|
||||
- break;
|
||||
+ goto enable_xip;
|
||||
|
||||
/* Latency issues. Drop the lock, wait a while and retry */
|
||||
UDELAY(map, chip, adr, 1);
|
||||
@@ -1658,6 +1658,8 @@ static int __xipram do_write_oneword(str
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ enable_xip:
|
||||
xip_enable(map, chip, adr);
|
||||
op_done:
|
||||
if (mode == FL_OTP_WRITE)
|
||||
@@ -2236,7 +2238,6 @@ static int cfi_amdstd_panic_write(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
-
|
||||
/*
|
||||
* Handle devices with one erase region, that only implement
|
||||
* the chip erase command.
|
||||
@@ -2304,7 +2305,7 @@ static int __xipram do_erase_chip(struct
|
||||
}
|
||||
|
||||
if (chip_good(map, adr, map_word_ff(map)))
|
||||
- break;
|
||||
+ goto op_done;
|
||||
|
||||
if (time_after(jiffies, timeo)) {
|
||||
printk(KERN_WARNING "MTD %s(): software timeout\n",
|
||||
@@ -2328,6 +2329,7 @@ static int __xipram do_erase_chip(struct
|
||||
}
|
||||
}
|
||||
|
||||
+ op_done:
|
||||
chip->state = FL_READY;
|
||||
xip_enable(map, chip, adr);
|
||||
DISABLE_VPP(map);
|
||||
@@ -2401,7 +2403,7 @@ static int __xipram do_erase_oneblock(st
|
||||
|
||||
if (chip_good(map, adr, map_word_ff(map))) {
|
||||
xip_enable(map, chip, adr);
|
||||
- break;
|
||||
+ goto op_done;
|
||||
}
|
||||
|
||||
if (time_after(jiffies, timeo)) {
|
||||
@@ -2427,6 +2429,7 @@ static int __xipram do_erase_oneblock(st
|
||||
}
|
||||
}
|
||||
|
||||
+ op_done:
|
||||
chip->state = FL_READY;
|
||||
DISABLE_VPP(map);
|
||||
put_chip(map, chip, adr);
|
@ -0,0 +1,16 @@
|
||||
--- a/drivers/net/phy/at803x.c
|
||||
+++ b/drivers/net/phy/at803x.c
|
||||
@@ -472,6 +472,13 @@ static int at803x_aneg_done(struct phy_d
|
||||
if (!(phy_read(phydev, AT803X_PSSR) & AT803X_PSSR_MR_AN_COMPLETE)) {
|
||||
pr_warn("803x_aneg_done: SGMII link is not ok\n");
|
||||
aneg_done = 0;
|
||||
+#ifdef CONFIG_OF_MDIO
|
||||
+ if (phydev->mdio.dev.of_node &&
|
||||
+ of_property_read_bool(phydev->mdio.dev.of_node,
|
||||
+ "at803x-override-sgmii-link-check")) {
|
||||
+ aneg_done = 1;
|
||||
+ }
|
||||
+#endif
|
||||
}
|
||||
/* switch back to copper page */
|
||||
phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);
|
@ -1,103 +0,0 @@
|
||||
--- a/drivers/usb/host/ehci-hcd.c
|
||||
+++ b/drivers/usb/host/ehci-hcd.c
|
||||
@@ -252,6 +252,37 @@ int ehci_reset(struct ehci_hcd *ehci)
|
||||
command |= CMD_RESET;
|
||||
dbg_cmd (ehci, "reset", command);
|
||||
ehci_writel(ehci, command, &ehci->regs->command);
|
||||
+
|
||||
+ if (ehci->qca_force_host_mode) {
|
||||
+ u32 usbmode;
|
||||
+
|
||||
+ udelay(1000);
|
||||
+
|
||||
+ usbmode = ehci_readl(ehci, &ehci->regs->usbmode);
|
||||
+ usbmode |= USBMODE_CM_HC | (1 << 4);
|
||||
+ ehci_writel(ehci, usbmode, &ehci->regs->usbmode);
|
||||
+
|
||||
+ ehci_dbg(ehci, "forced host mode, usbmode: %08x\n",
|
||||
+ ehci_readl(ehci, &ehci->regs->usbmode));
|
||||
+ }
|
||||
+
|
||||
+ if (ehci->qca_force_16bit_ptw) {
|
||||
+ u32 port_status;
|
||||
+
|
||||
+ udelay(1000);
|
||||
+
|
||||
+ /* enable 16-bit UTMI interface */
|
||||
+ port_status = ehci_readl(ehci, &ehci->regs->port_status[0]);
|
||||
+ port_status |= BIT(28);
|
||||
+ ehci_writel(ehci, port_status, &ehci->regs->port_status[0]);
|
||||
+
|
||||
+ ehci_dbg(ehci, "16-bit UTMI interface enabled, status: %08x\n",
|
||||
+ ehci_readl(ehci, &ehci->regs->port_status[0]));
|
||||
+ }
|
||||
+
|
||||
+ if (ehci->reset_notifier)
|
||||
+ ehci->reset_notifier(ehci_to_hcd(ehci));
|
||||
+
|
||||
ehci->rh_state = EHCI_RH_HALTED;
|
||||
ehci->next_statechange = jiffies;
|
||||
retval = ehci_handshake(ehci, &ehci->regs->command,
|
||||
--- a/drivers/usb/host/ehci.h
|
||||
+++ b/drivers/usb/host/ehci.h
|
||||
@@ -232,6 +232,10 @@ struct ehci_hcd { /* one per controlle
|
||||
unsigned need_oc_pp_cycle:1; /* MPC834X port power */
|
||||
unsigned imx28_write_fix:1; /* For Freescale i.MX28 */
|
||||
unsigned ignore_oc:1;
|
||||
+ unsigned qca_force_host_mode:1;
|
||||
+ unsigned qca_force_16bit_ptw:1; /* force 16 bit UTMI */
|
||||
+
|
||||
+ void (*reset_notifier)(struct usb_hcd *hcd);
|
||||
|
||||
/* required for usb32 quirk */
|
||||
#define OHCI_CTRL_HCFS (3 << 6)
|
||||
--- a/include/linux/usb/ehci_pdriver.h
|
||||
+++ b/include/linux/usb/ehci_pdriver.h
|
||||
@@ -50,6 +50,8 @@ struct usb_ehci_pdata {
|
||||
unsigned reset_on_resume:1;
|
||||
unsigned dma_mask_64:1;
|
||||
unsigned ignore_oc:1;
|
||||
+ unsigned qca_force_host_mode:1;
|
||||
+ unsigned qca_force_16bit_ptw:1;
|
||||
|
||||
/* Turn on all power and clocks */
|
||||
int (*power_on)(struct platform_device *pdev);
|
||||
@@ -59,6 +61,7 @@ struct usb_ehci_pdata {
|
||||
* turn off everything else */
|
||||
void (*power_suspend)(struct platform_device *pdev);
|
||||
int (*pre_setup)(struct usb_hcd *hcd);
|
||||
+ void (*reset_notifier)(struct platform_device *pdev);
|
||||
};
|
||||
|
||||
#endif /* __USB_CORE_EHCI_PDRIVER_H */
|
||||
--- a/drivers/usb/host/ehci-platform.c
|
||||
+++ b/drivers/usb/host/ehci-platform.c
|
||||
@@ -53,6 +53,14 @@ struct ehci_platform_priv {
|
||||
|
||||
static const char hcd_name[] = "ehci-platform";
|
||||
|
||||
+static void ehci_platform_reset_notifier(struct usb_hcd *hcd)
|
||||
+{
|
||||
+ struct platform_device *pdev = to_platform_device(hcd->self.controller);
|
||||
+ struct usb_ehci_pdata *pdata = pdev->dev.platform_data;
|
||||
+
|
||||
+ pdata->reset_notifier(pdev);
|
||||
+}
|
||||
+
|
||||
static int ehci_platform_reset(struct usb_hcd *hcd)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(hcd->self.controller);
|
||||
@@ -270,6 +278,13 @@ static int ehci_platform_probe(struct pl
|
||||
priv->reset_on_resume = true;
|
||||
if (pdata->ignore_oc)
|
||||
ehci->ignore_oc = 1;
|
||||
+ if (pdata->qca_force_host_mode)
|
||||
+ ehci->qca_force_host_mode = 1;
|
||||
+ if (pdata->qca_force_16bit_ptw)
|
||||
+ ehci->qca_force_16bit_ptw = 1;
|
||||
+
|
||||
+ if (pdata->reset_notifier)
|
||||
+ ehci->reset_notifier = ehci_platform_reset_notifier;
|
||||
|
||||
#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
|
||||
if (ehci->big_endian_mmio) {
|
@ -737,7 +737,7 @@
|
||||
EXPORT_SYMBOL(xfrm_parse_spi);
|
||||
--- a/net/ipv4/tcp_input.c
|
||||
+++ b/net/ipv4/tcp_input.c
|
||||
@@ -3874,14 +3874,16 @@ static bool tcp_parse_aligned_timestamp(
|
||||
@@ -3878,14 +3878,16 @@ static bool tcp_parse_aligned_timestamp(
|
||||
{
|
||||
const __be32 *ptr = (const __be32 *)(th + 1);
|
||||
|
||||
|
@ -194,7 +194,7 @@ Signed-off-by: John Crispin <john@phrozen.org>
|
||||
+MODULE_LICENSE("GPL");
|
||||
--- /dev/null
|
||||
+++ b/drivers/phy/phy-ar7200-usb.c
|
||||
@@ -0,0 +1,123 @@
|
||||
@@ -0,0 +1,135 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2015 Alban Bedel <albeu@free.fr>
|
||||
+ *
|
||||
@ -212,6 +212,7 @@ Signed-off-by: John Crispin <john@phrozen.org>
|
||||
+
|
||||
+struct ar7200_usb_phy {
|
||||
+ struct reset_control *rst_phy;
|
||||
+ struct reset_control *rst_phy_analog;
|
||||
+ struct reset_control *suspend_override;
|
||||
+ struct phy *phy;
|
||||
+ int gpio;
|
||||
@ -222,12 +223,12 @@ Signed-off-by: John Crispin <john@phrozen.org>
|
||||
+ struct ar7200_usb_phy *priv = phy_get_drvdata(phy);
|
||||
+ int err = 0;
|
||||
+
|
||||
+ if (priv->rst_phy)
|
||||
+ err = reset_control_deassert(priv->rst_phy);
|
||||
+ if (!err && priv->suspend_override)
|
||||
+ if (priv->suspend_override)
|
||||
+ err = reset_control_assert(priv->suspend_override);
|
||||
+ if (err && priv->rst_phy)
|
||||
+ err = reset_control_assert(priv->rst_phy);
|
||||
+ if (priv->rst_phy)
|
||||
+ err |= reset_control_deassert(priv->rst_phy);
|
||||
+ if (priv->rst_phy_analog)
|
||||
+ err |= reset_control_deassert(priv->rst_phy_analog);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
@ -241,6 +242,8 @@ Signed-off-by: John Crispin <john@phrozen.org>
|
||||
+ err = reset_control_deassert(priv->suspend_override);
|
||||
+ if (priv->rst_phy)
|
||||
+ err |= reset_control_assert(priv->rst_phy);
|
||||
+ if (priv->rst_phy_analog)
|
||||
+ err |= reset_control_assert(priv->rst_phy_analog);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
@ -266,6 +269,15 @@ Signed-off-by: John Crispin <john@phrozen.org>
|
||||
+ return PTR_ERR(priv->rst_phy);
|
||||
+ }
|
||||
+
|
||||
+ priv->rst_phy_analog = devm_reset_control_get_optional(
|
||||
+ &pdev->dev, "usb-phy-analog");
|
||||
+ if (IS_ERR(priv->rst_phy_analog)) {
|
||||
+ if (PTR_ERR(priv->rst_phy_analog) == -ENOENT)
|
||||
+ priv->rst_phy_analog = NULL;
|
||||
+ else
|
||||
+ return PTR_ERR(priv->rst_phy_analog);
|
||||
+ }
|
||||
+
|
||||
+ priv->suspend_override = devm_reset_control_get_optional(
|
||||
+ &pdev->dev, "usb-suspend-override");
|
||||
+ if (IS_ERR(priv->suspend_override)) {
|
||||
|
@ -0,0 +1,90 @@
|
||||
From 60efe35257b063ce584968f9f80b437030ce6ba6 Mon Sep 17 00:00:00 2001
|
||||
From: David Bauer <mail@david-bauer.net>
|
||||
Date: Mon, 18 Mar 2019 00:54:06 +0100
|
||||
Subject: [PATCH] MIPS: ath79: add missing QCA955x GMAC registers
|
||||
|
||||
This adds missing GMAC register definitions for the Qualcomm Atheros
|
||||
QCA955X series MIPS SoCs.
|
||||
|
||||
They originate from the platforms U-Boot code and the AVM FRITZ!WLAN
|
||||
Repeater 450E's GPL tarball.
|
||||
|
||||
Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
---
|
||||
.../mips/include/asm/mach-ath79/ar71xx_regs.h | 54 +++++++++++++++++++
|
||||
1 file changed, 54 insertions(+)
|
||||
|
||||
--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
|
||||
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
|
||||
@@ -1249,7 +1249,12 @@
|
||||
*/
|
||||
|
||||
#define QCA955X_GMAC_REG_ETH_CFG 0x00
|
||||
+#define QCA955X_GMAC_REG_SGMII_RESET 0x14
|
||||
#define QCA955X_GMAC_REG_SGMII_SERDES 0x18
|
||||
+#define QCA955X_GMAC_REG_MR_AN_CONTROL 0x1c
|
||||
+#define QCA955X_GMAC_REG_MR_AN_STATUS 0x20
|
||||
+#define QCA955X_GMAC_REG_SGMII_CONFIG 0x34
|
||||
+#define QCA955X_GMAC_REG_SGMII_DEBUG 0x58
|
||||
|
||||
#define QCA955X_ETH_CFG_RGMII_EN BIT(0)
|
||||
#define QCA955X_ETH_CFG_MII_GE0 BIT(1)
|
||||
@@ -1271,9 +1276,58 @@
|
||||
#define QCA955X_ETH_CFG_TXE_DELAY_MASK 0x3
|
||||
#define QCA955X_ETH_CFG_TXE_DELAY_SHIFT 20
|
||||
|
||||
+#define QCA955X_SGMII_RESET_RX_CLK_N_RESET 0
|
||||
+#define QCA955X_SGMII_RESET_RX_CLK_N BIT(0)
|
||||
+#define QCA955X_SGMII_RESET_TX_CLK_N BIT(1)
|
||||
+#define QCA955X_SGMII_RESET_RX_125M_N BIT(2)
|
||||
+#define QCA955X_SGMII_RESET_TX_125M_N BIT(3)
|
||||
+#define QCA955X_SGMII_RESET_HW_RX_125M_N BIT(4)
|
||||
+
|
||||
#define QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS BIT(15)
|
||||
#define QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT 23
|
||||
#define QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK 0xf
|
||||
+
|
||||
+#define QCA955X_MR_AN_CONTROL_SPEED_SEL1 BIT(6)
|
||||
+#define QCA955X_MR_AN_CONTROL_DUPLEX_MODE BIT(8)
|
||||
+#define QCA955X_MR_AN_CONTROL_RESTART_AN BIT(9)
|
||||
+#define QCA955X_MR_AN_CONTROL_POWER_DOWN BIT(11)
|
||||
+#define QCA955X_MR_AN_CONTROL_AN_ENABLE BIT(12)
|
||||
+#define QCA955X_MR_AN_CONTROL_SPEED_SEL0 BIT(13)
|
||||
+#define QCA955X_MR_AN_CONTROL_LOOPBACK BIT(14)
|
||||
+#define QCA955X_MR_AN_CONTROL_PHY_RESET BIT(15)
|
||||
+
|
||||
+#define QCA955X_MR_AN_STATUS_EXT_CAP BIT(0)
|
||||
+#define QCA955X_MR_AN_STATUS_LINK_UP BIT(2)
|
||||
+#define QCA955X_MR_AN_STATUS_AN_ABILITY BIT(3)
|
||||
+#define QCA955X_MR_AN_STATUS_REMOTE_FAULT BIT(4)
|
||||
+#define QCA955X_MR_AN_STATUS_AN_COMPLETE BIT(5)
|
||||
+#define QCA955X_MR_AN_STATUS_NO_PREAMBLE BIT(6)
|
||||
+#define QCA955X_MR_AN_STATUS_BASE_PAGE BIT(7)
|
||||
+
|
||||
+#define QCA955X_SGMII_CONFIG_MODE_CTRL_SHIFT 0
|
||||
+#define QCA955X_SGMII_CONFIG_MODE_CTRL_MASK 0x7
|
||||
+#define QCA955X_SGMII_CONFIG_ENABLE_SGMII_TX_PAUSE BIT(3)
|
||||
+#define QCA955X_SGMII_CONFIG_MR_REG4_CHANGED BIT(4)
|
||||
+#define QCA955X_SGMII_CONFIG_FORCE_SPEED BIT(5)
|
||||
+#define QCA955X_SGMII_CONFIG_SPEED_SHIFT 6
|
||||
+#define QCA955X_SGMII_CONFIG_SPEED_MASK 0xc0
|
||||
+#define QCA955X_SGMII_CONFIG_REMOTE_PHY_LOOPBACK BIT(8)
|
||||
+#define QCA955X_SGMII_CONFIG_NEXT_PAGE_LOADED BIT(9)
|
||||
+#define QCA955X_SGMII_CONFIG_MDIO_ENABLE BIT(10)
|
||||
+#define QCA955X_SGMII_CONFIG_MDIO_PULSE BIT(11)
|
||||
+#define QCA955X_SGMII_CONFIG_MDIO_COMPLETE BIT(12)
|
||||
+#define QCA955X_SGMII_CONFIG_PRBS_ENABLE BIT(13)
|
||||
+#define QCA955X_SGMII_CONFIG_BERT_ENABLE BIT(14)
|
||||
+
|
||||
+#define QCA955X_SGMII_DEBUG_TX_STATE_MASK 0xff
|
||||
+#define QCA955X_SGMII_DEBUG_TX_STATE_SHIFT 0
|
||||
+#define QCA955X_SGMII_DEBUG_RX_STATE_MASK 0xff00
|
||||
+#define QCA955X_SGMII_DEBUG_RX_STATE_SHIFT 8
|
||||
+#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_MASK 0xff0000
|
||||
+#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_SHIFT 16
|
||||
+#define QCA955X_SGMII_DEBUG_ARB_STATE_MASK 0xf000000
|
||||
+#define QCA955X_SGMII_DEBUG_ARB_STATE_SHIFT 24
|
||||
+
|
||||
/*
|
||||
* QCA956X GMAC Interface
|
||||
*/
|
@ -10,7 +10,7 @@ with kernel 5.1 and higher. It can be safely dropped with kernel 5.1.
|
||||
|
||||
--- a/drivers/net/phy/at803x.c
|
||||
+++ b/drivers/net/phy/at803x.c
|
||||
@@ -295,6 +295,14 @@ static int at803x_config_init(struct phy
|
||||
@@ -279,6 +279,14 @@ static int at803x_config_init(struct phy
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -1,62 +0,0 @@
|
||||
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
|
||||
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
|
||||
@@ -1640,7 +1640,7 @@ static int __xipram do_write_oneword(str
|
||||
}
|
||||
|
||||
if (chip_good(map, adr, datum))
|
||||
- break;
|
||||
+ goto enable_xip;
|
||||
|
||||
/* Latency issues. Drop the lock, wait a while and retry */
|
||||
UDELAY(map, chip, adr, 1);
|
||||
@@ -1657,6 +1657,8 @@ static int __xipram do_write_oneword(str
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ enable_xip:
|
||||
xip_enable(map, chip, adr);
|
||||
op_done:
|
||||
if (mode == FL_OTP_WRITE)
|
||||
@@ -2235,7 +2237,6 @@ static int cfi_amdstd_panic_write(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
-
|
||||
/*
|
||||
* Handle devices with one erase region, that only implement
|
||||
* the chip erase command.
|
||||
@@ -2303,7 +2304,7 @@ static int __xipram do_erase_chip(struct
|
||||
}
|
||||
|
||||
if (chip_good(map, adr, map_word_ff(map)))
|
||||
- break;
|
||||
+ goto op_done;
|
||||
|
||||
if (time_after(jiffies, timeo)) {
|
||||
printk(KERN_WARNING "MTD %s(): software timeout\n",
|
||||
@@ -2327,6 +2328,7 @@ static int __xipram do_erase_chip(struct
|
||||
}
|
||||
}
|
||||
|
||||
+ op_done:
|
||||
chip->state = FL_READY;
|
||||
xip_enable(map, chip, adr);
|
||||
DISABLE_VPP(map);
|
||||
@@ -2399,7 +2401,7 @@ static int __xipram do_erase_oneblock(st
|
||||
}
|
||||
|
||||
if (chip_good(map, adr, map_word_ff(map)))
|
||||
- break;
|
||||
+ goto op_done;
|
||||
|
||||
if (time_after(jiffies, timeo)) {
|
||||
printk(KERN_WARNING "MTD %s(): software timeout\n",
|
||||
@@ -2423,6 +2425,7 @@ static int __xipram do_erase_oneblock(st
|
||||
}
|
||||
}
|
||||
|
||||
+ op_done:
|
||||
chip->state = FL_READY;
|
||||
xip_enable(map, chip, adr);
|
||||
DISABLE_VPP(map);
|
@ -0,0 +1,16 @@
|
||||
--- a/drivers/net/phy/at803x.c
|
||||
+++ b/drivers/net/phy/at803x.c
|
||||
@@ -391,6 +391,13 @@ static int at803x_aneg_done(struct phy_d
|
||||
if (!(phy_read(phydev, AT803X_PSSR) & AT803X_PSSR_MR_AN_COMPLETE)) {
|
||||
pr_warn("803x_aneg_done: SGMII link is not ok\n");
|
||||
aneg_done = 0;
|
||||
+#ifdef CONFIG_OF_MDIO
|
||||
+ if (phydev->mdio.dev.of_node &&
|
||||
+ of_property_read_bool(phydev->mdio.dev.of_node,
|
||||
+ "at803x-override-sgmii-link-check")) {
|
||||
+ aneg_done = 1;
|
||||
+ }
|
||||
+#endif
|
||||
}
|
||||
/* switch back to copper page */
|
||||
phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);
|
@ -1,103 +0,0 @@
|
||||
--- a/drivers/usb/host/ehci-hcd.c
|
||||
+++ b/drivers/usb/host/ehci-hcd.c
|
||||
@@ -239,6 +239,37 @@ int ehci_reset(struct ehci_hcd *ehci)
|
||||
command |= CMD_RESET;
|
||||
dbg_cmd (ehci, "reset", command);
|
||||
ehci_writel(ehci, command, &ehci->regs->command);
|
||||
+
|
||||
+ if (ehci->qca_force_host_mode) {
|
||||
+ u32 usbmode;
|
||||
+
|
||||
+ udelay(1000);
|
||||
+
|
||||
+ usbmode = ehci_readl(ehci, &ehci->regs->usbmode);
|
||||
+ usbmode |= USBMODE_CM_HC | (1 << 4);
|
||||
+ ehci_writel(ehci, usbmode, &ehci->regs->usbmode);
|
||||
+
|
||||
+ ehci_dbg(ehci, "forced host mode, usbmode: %08x\n",
|
||||
+ ehci_readl(ehci, &ehci->regs->usbmode));
|
||||
+ }
|
||||
+
|
||||
+ if (ehci->qca_force_16bit_ptw) {
|
||||
+ u32 port_status;
|
||||
+
|
||||
+ udelay(1000);
|
||||
+
|
||||
+ /* enable 16-bit UTMI interface */
|
||||
+ port_status = ehci_readl(ehci, &ehci->regs->port_status[0]);
|
||||
+ port_status |= BIT(28);
|
||||
+ ehci_writel(ehci, port_status, &ehci->regs->port_status[0]);
|
||||
+
|
||||
+ ehci_dbg(ehci, "16-bit UTMI interface enabled, status: %08x\n",
|
||||
+ ehci_readl(ehci, &ehci->regs->port_status[0]));
|
||||
+ }
|
||||
+
|
||||
+ if (ehci->reset_notifier)
|
||||
+ ehci->reset_notifier(ehci_to_hcd(ehci));
|
||||
+
|
||||
ehci->rh_state = EHCI_RH_HALTED;
|
||||
ehci->next_statechange = jiffies;
|
||||
retval = ehci_handshake(ehci, &ehci->regs->command,
|
||||
--- a/drivers/usb/host/ehci.h
|
||||
+++ b/drivers/usb/host/ehci.h
|
||||
@@ -219,6 +219,10 @@ struct ehci_hcd { /* one per controlle
|
||||
unsigned need_oc_pp_cycle:1; /* MPC834X port power */
|
||||
unsigned imx28_write_fix:1; /* For Freescale i.MX28 */
|
||||
unsigned ignore_oc:1;
|
||||
+ unsigned qca_force_host_mode:1;
|
||||
+ unsigned qca_force_16bit_ptw:1; /* force 16 bit UTMI */
|
||||
+
|
||||
+ void (*reset_notifier)(struct usb_hcd *hcd);
|
||||
|
||||
/* required for usb32 quirk */
|
||||
#define OHCI_CTRL_HCFS (3 << 6)
|
||||
--- a/include/linux/usb/ehci_pdriver.h
|
||||
+++ b/include/linux/usb/ehci_pdriver.h
|
||||
@@ -51,6 +51,8 @@ struct usb_ehci_pdata {
|
||||
unsigned reset_on_resume:1;
|
||||
unsigned dma_mask_64:1;
|
||||
unsigned ignore_oc:1;
|
||||
+ unsigned qca_force_host_mode:1;
|
||||
+ unsigned qca_force_16bit_ptw:1;
|
||||
|
||||
/* Turn on all power and clocks */
|
||||
int (*power_on)(struct platform_device *pdev);
|
||||
@@ -60,6 +62,7 @@ struct usb_ehci_pdata {
|
||||
* turn off everything else */
|
||||
void (*power_suspend)(struct platform_device *pdev);
|
||||
int (*pre_setup)(struct usb_hcd *hcd);
|
||||
+ void (*reset_notifier)(struct platform_device *pdev);
|
||||
};
|
||||
|
||||
#endif /* __USB_CORE_EHCI_PDRIVER_H */
|
||||
--- a/drivers/usb/host/ehci-platform.c
|
||||
+++ b/drivers/usb/host/ehci-platform.c
|
||||
@@ -48,6 +48,14 @@ struct ehci_platform_priv {
|
||||
|
||||
static const char hcd_name[] = "ehci-platform";
|
||||
|
||||
+static void ehci_platform_reset_notifier(struct usb_hcd *hcd)
|
||||
+{
|
||||
+ struct platform_device *pdev = to_platform_device(hcd->self.controller);
|
||||
+ struct usb_ehci_pdata *pdata = pdev->dev.platform_data;
|
||||
+
|
||||
+ pdata->reset_notifier(pdev);
|
||||
+}
|
||||
+
|
||||
static int ehci_platform_reset(struct usb_hcd *hcd)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(hcd->self.controller);
|
||||
@@ -215,6 +223,13 @@ static int ehci_platform_probe(struct pl
|
||||
priv->reset_on_resume = true;
|
||||
if (pdata->ignore_oc)
|
||||
ehci->ignore_oc = 1;
|
||||
+ if (pdata->qca_force_host_mode)
|
||||
+ ehci->qca_force_host_mode = 1;
|
||||
+ if (pdata->qca_force_16bit_ptw)
|
||||
+ ehci->qca_force_16bit_ptw = 1;
|
||||
+
|
||||
+ if (pdata->reset_notifier)
|
||||
+ ehci->reset_notifier = ehci_platform_reset_notifier;
|
||||
|
||||
#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
|
||||
if (ehci->big_endian_mmio) {
|
@ -728,7 +728,7 @@
|
||||
EXPORT_SYMBOL(xfrm_parse_spi);
|
||||
--- a/net/ipv4/tcp_input.c
|
||||
+++ b/net/ipv4/tcp_input.c
|
||||
@@ -3891,14 +3891,16 @@ static bool tcp_parse_aligned_timestamp(
|
||||
@@ -3895,14 +3895,16 @@ static bool tcp_parse_aligned_timestamp(
|
||||
{
|
||||
const __be32 *ptr = (const __be32 *)(th + 1);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/sh
|
||||
|
||||
set -x
|
||||
set -x
|
||||
[ $# -eq 5 ] || {
|
||||
echo "SYNTAX: $0 <file> <bootfs image> <rootfs image> <bootfs size> <rootfs size>"
|
||||
exit 1
|
||||
@ -24,6 +24,3 @@ ROOTFSSIZE="$(($4 / 512))"
|
||||
|
||||
dd bs=512 if="$BOOTFS" of="$OUTPUT" seek="$BOOTOFFSET" conv=notrunc
|
||||
dd bs=512 if="$ROOTFS" of="$OUTPUT" seek="$ROOTFSOFFSET" conv=notrunc
|
||||
|
||||
|
||||
|
||||
|
@ -917,7 +917,7 @@ Fixes https://github.com/raspberrypi/linux/issues/2408
|
||||
}
|
||||
--- a/drivers/usb/core/hub.c
|
||||
+++ b/drivers/usb/core/hub.c
|
||||
@@ -5221,7 +5221,7 @@ static void port_event(struct usb_hub *h
|
||||
@@ -5222,7 +5222,7 @@ static void port_event(struct usb_hub *h
|
||||
u16 status = 0, unused;
|
||||
port_dev->over_current_count++;
|
||||
|
||||
|
@ -26,7 +26,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
/* Device and char device-related information */
|
||||
static DEFINE_IDA(gpio_ida);
|
||||
static dev_t gpio_devt;
|
||||
@@ -2654,7 +2656,7 @@ int gpiod_direction_output(struct gpio_d
|
||||
@@ -2662,7 +2664,7 @@ int gpiod_direction_output(struct gpio_d
|
||||
value = !!value;
|
||||
|
||||
/* GPIOs used for IRQs shall not be set as output */
|
||||
@ -35,7 +35,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
gpiod_err(desc,
|
||||
"%s: tried to set a GPIO tied to an IRQ as output\n",
|
||||
__func__);
|
||||
@@ -3353,7 +3355,7 @@ int gpiochip_lock_as_irq(struct gpio_chi
|
||||
@@ -3361,7 +3363,7 @@ int gpiochip_lock_as_irq(struct gpio_chi
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data)
|
||||
{
|
||||
u32 *buf = kmalloc(sizeof(u32), GFP_KERNEL);
|
||||
@@ -3012,8 +3021,14 @@ static int lan78xx_bind(struct lan78xx_n
|
||||
@@ -3009,8 +3018,14 @@ static int lan78xx_bind(struct lan78xx_n
|
||||
if (DEFAULT_RX_CSUM_ENABLE)
|
||||
dev->net->features |= NETIF_F_RXCSUM;
|
||||
|
||||
|
@ -28,7 +28,7 @@ See: https://github.com/raspberrypi/linux/issues/2447
|
||||
static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data)
|
||||
{
|
||||
u32 *buf = kmalloc(sizeof(u32), GFP_KERNEL);
|
||||
@@ -3825,7 +3830,12 @@ static int lan78xx_probe(struct usb_inte
|
||||
@@ -3823,7 +3828,12 @@ static int lan78xx_probe(struct usb_inte
|
||||
dev->pipe_intr = usb_rcvintpipe(dev->udev,
|
||||
dev->ep_intr->desc.bEndpointAddress &
|
||||
USB_ENDPOINT_NUMBER_MASK);
|
||||
|
@ -12,7 +12,7 @@ in both dwc_otg and in ipv6 processing.
|
||||
|
||||
--- a/drivers/net/usb/lan78xx.c
|
||||
+++ b/drivers/net/usb/lan78xx.c
|
||||
@@ -3259,7 +3259,7 @@ static int rx_submit(struct lan78xx_net
|
||||
@@ -3256,7 +3256,7 @@ static int rx_submit(struct lan78xx_net
|
||||
size_t size = dev->rx_urb_size;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -21,7 +21,7 @@ Cc: stable@vger.kernel.org
|
||||
|
||||
--- a/net/bluetooth/hci_conn.c
|
||||
+++ b/net/bluetooth/hci_conn.c
|
||||
@@ -1280,8 +1280,13 @@ int hci_conn_check_link_mode(struct hci_
|
||||
@@ -1282,8 +1282,13 @@ int hci_conn_check_link_mode(struct hci_
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ Link: https://patchwork.freedesktop.org/patch/msgid/18443e0c3bdbbd16cea4ec63bc7f
|
||||
mode->rb ? " reduced blanking" : "",
|
||||
--- a/drivers/gpu/drm/drm_fb_helper.c
|
||||
+++ b/drivers/gpu/drm/drm_fb_helper.c
|
||||
@@ -2099,6 +2099,10 @@ struct drm_display_mode *drm_pick_cmdlin
|
||||
@@ -2104,6 +2104,10 @@ struct drm_display_mode *drm_pick_cmdlin
|
||||
prefer_non_interlace = !cmdline_mode->interlace;
|
||||
again:
|
||||
list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
|
||||
|
@ -52,7 +52,7 @@ Link: https://patchwork.freedesktop.org/patch/msgid/777da16e42db757c1f5b414b5ca3
|
||||
What is the VESA(TM) Coordinated Video Timings (CVT)?
|
||||
--- a/drivers/gpu/drm/drm_fb_helper.c
|
||||
+++ b/drivers/gpu/drm/drm_fb_helper.c
|
||||
@@ -2464,6 +2464,7 @@ static void drm_setup_crtc_rotation(stru
|
||||
@@ -2469,6 +2469,7 @@ static void drm_setup_crtc_rotation(stru
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_plane *plane = fb_crtc->mode_set.crtc->primary;
|
||||
@ -60,7 +60,7 @@ Link: https://patchwork.freedesktop.org/patch/msgid/777da16e42db757c1f5b414b5ca3
|
||||
uint64_t valid_mask = 0;
|
||||
int i, rotation;
|
||||
|
||||
@@ -2483,6 +2484,35 @@ static void drm_setup_crtc_rotation(stru
|
||||
@@ -2488,6 +2489,35 @@ static void drm_setup_crtc_rotation(stru
|
||||
rotation = DRM_MODE_ROTATE_0;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
|
||||
--- a/drivers/gpu/drm/drm_fb_helper.c
|
||||
+++ b/drivers/gpu/drm/drm_fb_helper.c
|
||||
@@ -2497,7 +2497,7 @@ static void drm_setup_crtc_rotation(stru
|
||||
@@ -2502,7 +2502,7 @@ static void drm_setup_crtc_rotation(stru
|
||||
* simple XOR between the two handle the addition nicely.
|
||||
*/
|
||||
cmdline = &connector->cmdline_mode;
|
||||
|
@ -41,7 +41,7 @@ Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
|
||||
--- a/drivers/gpio/gpiolib.c
|
||||
+++ b/drivers/gpio/gpiolib.c
|
||||
@@ -3979,8 +3979,23 @@ struct gpio_desc *__must_check gpiod_get
|
||||
@@ -3988,8 +3988,23 @@ struct gpio_desc *__must_check gpiod_get
|
||||
* the device name as label
|
||||
*/
|
||||
status = gpiod_request(desc, con_id ? con_id : devname);
|
||||
|
@ -23,7 +23,7 @@ Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
|
||||
--- a/drivers/gpio/gpiolib.c
|
||||
+++ b/drivers/gpio/gpiolib.c
|
||||
@@ -4053,6 +4053,8 @@ struct gpio_desc *gpiod_get_from_of_node
|
||||
@@ -4062,6 +4062,8 @@ struct gpio_desc *gpiod_get_from_of_node
|
||||
transitory = flags & OF_GPIO_TRANSITORY;
|
||||
|
||||
ret = gpiod_request(desc, label);
|
||||
|
@ -89,7 +89,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
|
||||
--- a/drivers/gpio/gpiolib.c
|
||||
+++ b/drivers/gpio/gpiolib.c
|
||||
@@ -1950,7 +1950,8 @@ int gpiochip_add_pingroup_range(struct g
|
||||
@@ -1958,7 +1958,8 @@ int gpiochip_add_pingroup_range(struct g
|
||||
|
||||
list_add_tail(&pin_range->node, &gdev->pin_ranges);
|
||||
|
||||
@ -99,7 +99,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range);
|
||||
|
||||
@@ -2002,7 +2003,7 @@ int gpiochip_add_pin_range(struct gpio_c
|
||||
@@ -2010,7 +2011,7 @@ int gpiochip_add_pin_range(struct gpio_c
|
||||
|
||||
list_add_tail(&pin_range->node, &gdev->pin_ranges);
|
||||
|
||||
|
@ -89,7 +89,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
|
||||
--- a/drivers/gpio/gpiolib.c
|
||||
+++ b/drivers/gpio/gpiolib.c
|
||||
@@ -2197,7 +2197,8 @@ int gpiochip_add_pingroup_range(struct g
|
||||
@@ -2205,7 +2205,8 @@ int gpiochip_add_pingroup_range(struct g
|
||||
|
||||
list_add_tail(&pin_range->node, &gdev->pin_ranges);
|
||||
|
||||
@ -99,7 +99,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range);
|
||||
|
||||
@@ -2254,7 +2255,7 @@ int gpiochip_add_pin_range(struct gpio_c
|
||||
@@ -2262,7 +2263,7 @@ int gpiochip_add_pin_range(struct gpio_c
|
||||
|
||||
list_add_tail(&pin_range->node, &gdev->pin_ranges);
|
||||
|
||||
|
@ -30,7 +30,7 @@ Signed-off-by: Johan Hovold <johan@kernel.org>
|
||||
|
||||
--- a/drivers/usb/serial/option.c
|
||||
+++ b/drivers/usb/serial/option.c
|
||||
@@ -1968,7 +1968,8 @@ static const struct usb_device_id option
|
||||
@@ -1981,7 +1981,8 @@ static const struct usb_device_id option
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d01, 0xff) }, /* D-Link DWM-156 (variant) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d02, 0xff) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d03, 0xff) },
|
||||
|
@ -264,7 +264,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
}
|
||||
nft_chain_release_hook(&hook);
|
||||
}
|
||||
@@ -5156,10 +5144,9 @@ static int nf_tables_commit(struct net *
|
||||
@@ -5162,10 +5150,9 @@ static int nf_tables_commit(struct net *
|
||||
case NFT_MSG_DELCHAIN:
|
||||
list_del_rcu(&trans->ctx.chain->list);
|
||||
nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN);
|
||||
@ -278,7 +278,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
break;
|
||||
case NFT_MSG_NEWRULE:
|
||||
nft_clear(trans->ctx.net, nft_trans_rule(trans));
|
||||
@@ -5296,10 +5283,9 @@ static int nf_tables_abort(struct net *n
|
||||
@@ -5302,10 +5289,9 @@ static int nf_tables_abort(struct net *n
|
||||
} else {
|
||||
trans->ctx.table->use--;
|
||||
list_del_rcu(&trans->ctx.chain->list);
|
||||
@ -292,7 +292,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
}
|
||||
break;
|
||||
case NFT_MSG_DELCHAIN:
|
||||
@@ -5402,7 +5388,7 @@ int nft_chain_validate_hooks(const struc
|
||||
@@ -5408,7 +5394,7 @@ int nft_chain_validate_hooks(const struc
|
||||
if (nft_is_base_chain(chain)) {
|
||||
basechain = nft_base_chain(chain);
|
||||
|
||||
@ -301,7 +301,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
return 0;
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
@@ -5884,8 +5870,7 @@ int __nft_release_basechain(struct nft_c
|
||||
@@ -5890,8 +5876,7 @@ int __nft_release_basechain(struct nft_c
|
||||
|
||||
BUG_ON(!nft_is_base_chain(ctx->chain));
|
||||
|
||||
@ -311,7 +311,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) {
|
||||
list_del(&rule->list);
|
||||
ctx->chain->use--;
|
||||
@@ -5914,8 +5899,7 @@ static void __nft_release_afinfo(struct
|
||||
@@ -5920,8 +5905,7 @@ static void __nft_release_afinfo(struct
|
||||
|
||||
list_for_each_entry_safe(table, nt, &afi->tables, list) {
|
||||
list_for_each_entry(chain, &table->chains, list)
|
||||
|
@ -292,7 +292,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
list_for_each_entry_safe(obj, ne, &ctx->table->objects, list) {
|
||||
err = nft_delobj(ctx, obj);
|
||||
if (err < 0)
|
||||
@@ -4856,6 +4900,605 @@ static void nf_tables_obj_notify(const s
|
||||
@@ -4862,6 +4906,605 @@ static void nf_tables_obj_notify(const s
|
||||
ctx->afi->family, ctx->report, GFP_KERNEL);
|
||||
}
|
||||
|
||||
@ -898,7 +898,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,
|
||||
u32 portid, u32 seq)
|
||||
{
|
||||
@@ -4886,6 +5529,49 @@ nla_put_failure:
|
||||
@@ -4892,6 +5535,49 @@ nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
@ -948,7 +948,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
static void nf_tables_gen_notify(struct net *net, struct sk_buff *skb,
|
||||
int event)
|
||||
{
|
||||
@@ -5038,6 +5724,21 @@ static const struct nfnl_callback nf_tab
|
||||
@@ -5044,6 +5730,21 @@ static const struct nfnl_callback nf_tab
|
||||
.attr_count = NFTA_OBJ_MAX,
|
||||
.policy = nft_obj_policy,
|
||||
},
|
||||
@ -970,7 +970,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
};
|
||||
|
||||
static void nft_chain_commit_update(struct nft_trans *trans)
|
||||
@@ -5086,6 +5787,9 @@ static void nf_tables_commit_release(str
|
||||
@@ -5092,6 +5793,9 @@ static void nf_tables_commit_release(str
|
||||
case NFT_MSG_DELOBJ:
|
||||
nft_obj_destroy(nft_trans_obj(trans));
|
||||
break;
|
||||
@ -980,7 +980,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
}
|
||||
kfree(trans);
|
||||
}
|
||||
@@ -5205,6 +5909,21 @@ static int nf_tables_commit(struct net *
|
||||
@@ -5211,6 +5915,21 @@ static int nf_tables_commit(struct net *
|
||||
nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans),
|
||||
NFT_MSG_DELOBJ);
|
||||
break;
|
||||
@ -1002,7 +1002,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5242,6 +5961,9 @@ static void nf_tables_abort_release(stru
|
||||
@@ -5248,6 +5967,9 @@ static void nf_tables_abort_release(stru
|
||||
case NFT_MSG_NEWOBJ:
|
||||
nft_obj_destroy(nft_trans_obj(trans));
|
||||
break;
|
||||
@ -1012,7 +1012,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
}
|
||||
kfree(trans);
|
||||
}
|
||||
@@ -5333,6 +6055,17 @@ static int nf_tables_abort(struct net *n
|
||||
@@ -5339,6 +6061,17 @@ static int nf_tables_abort(struct net *n
|
||||
nft_clear(trans->ctx.net, nft_trans_obj(trans));
|
||||
nft_trans_destroy(trans);
|
||||
break;
|
||||
@ -1030,7 +1030,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5883,6 +6616,7 @@ EXPORT_SYMBOL_GPL(__nft_release_basechai
|
||||
@@ -5889,6 +6622,7 @@ EXPORT_SYMBOL_GPL(__nft_release_basechai
|
||||
/* Called by nft_unregister_afinfo() from __net_exit path, nfnl_lock is held. */
|
||||
static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi)
|
||||
{
|
||||
@ -1038,7 +1038,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
struct nft_table *table, *nt;
|
||||
struct nft_chain *chain, *nc;
|
||||
struct nft_object *obj, *ne;
|
||||
@@ -5896,6 +6630,9 @@ static void __nft_release_afinfo(struct
|
||||
@@ -5902,6 +6636,9 @@ static void __nft_release_afinfo(struct
|
||||
list_for_each_entry_safe(table, nt, &afi->tables, list) {
|
||||
list_for_each_entry(chain, &table->chains, list)
|
||||
nf_tables_unregister_hook(net, table, chain);
|
||||
@ -1048,7 +1048,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
/* No packets are walking on these chains anymore. */
|
||||
ctx.table = table;
|
||||
list_for_each_entry(chain, &table->chains, list) {
|
||||
@@ -5906,6 +6643,11 @@ static void __nft_release_afinfo(struct
|
||||
@@ -5912,6 +6649,11 @@ static void __nft_release_afinfo(struct
|
||||
nf_tables_rule_release(&ctx, rule);
|
||||
}
|
||||
}
|
||||
@ -1060,7 +1060,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
list_for_each_entry_safe(set, ns, &table->sets, list) {
|
||||
list_del(&set->list);
|
||||
table->use--;
|
||||
@@ -5949,6 +6691,8 @@ static int __init nf_tables_module_init(
|
||||
@@ -5955,6 +6697,8 @@ static int __init nf_tables_module_init(
|
||||
if (err < 0)
|
||||
goto err3;
|
||||
|
||||
@ -1069,7 +1069,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
pr_info("nf_tables: (c) 2007-2009 Patrick McHardy <kaber@trash.net>\n");
|
||||
return register_pernet_subsys(&nf_tables_net_ops);
|
||||
err3:
|
||||
@@ -5963,6 +6707,7 @@ static void __exit nf_tables_module_exit
|
||||
@@ -5969,6 +6713,7 @@ static void __exit nf_tables_module_exit
|
||||
{
|
||||
unregister_pernet_subsys(&nf_tables_net_ops);
|
||||
nfnetlink_subsys_unregister(&nf_tables_subsys);
|
||||
|
@ -82,7 +82,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
hook->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY]));
|
||||
|
||||
type = chain_type[afi->family][NFT_CHAIN_T_DEFAULT];
|
||||
@@ -5008,7 +5005,7 @@ static int nf_tables_flowtable_parse_hoo
|
||||
@@ -5014,7 +5011,7 @@ static int nf_tables_flowtable_parse_hoo
|
||||
return -EINVAL;
|
||||
|
||||
hooknum = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_NUM]));
|
||||
|
@ -11,7 +11,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
--- a/net/netfilter/nf_tables_api.c
|
||||
+++ b/net/netfilter/nf_tables_api.c
|
||||
@@ -5432,7 +5432,7 @@ static int nf_tables_getflowtable(struct
|
||||
@@ -5438,7 +5438,7 @@ static int nf_tables_getflowtable(struct
|
||||
|
||||
flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME],
|
||||
genmask);
|
||||
|
@ -62,7 +62,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (ret >= 0) {
|
||||
ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
|
||||
nft_trans_table_enable(trans) = true;
|
||||
@@ -5813,7 +5806,6 @@ static int nf_tables_commit(struct net *
|
||||
@@ -5819,7 +5812,6 @@ static int nf_tables_commit(struct net *
|
||||
if (nft_trans_table_update(trans)) {
|
||||
if (!nft_trans_table_enable(trans)) {
|
||||
nf_tables_table_disable(net,
|
||||
@ -70,7 +70,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
trans->ctx.table);
|
||||
trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
|
||||
}
|
||||
@@ -5977,7 +5969,6 @@ static int nf_tables_abort(struct net *n
|
||||
@@ -5983,7 +5975,6 @@ static int nf_tables_abort(struct net *n
|
||||
if (nft_trans_table_update(trans)) {
|
||||
if (nft_trans_table_enable(trans)) {
|
||||
nf_tables_table_disable(net,
|
||||
|
@ -15,7 +15,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
--- a/net/netfilter/nf_tables_api.c
|
||||
+++ b/net/netfilter/nf_tables_api.c
|
||||
@@ -5351,8 +5351,10 @@ static int nf_tables_dump_flowtable_done
|
||||
@@ -5357,8 +5357,10 @@ static int nf_tables_dump_flowtable_done
|
||||
if (!filter)
|
||||
return 0;
|
||||
|
||||
|
@ -859,7 +859,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff);
|
||||
|
||||
@@ -3996,7 +3982,7 @@ static int nft_add_set_elem(struct nft_c
|
||||
@@ -4002,7 +3988,7 @@ static int nft_add_set_elem(struct nft_c
|
||||
list_for_each_entry(binding, &set->bindings, list) {
|
||||
struct nft_ctx bind_ctx = {
|
||||
.net = ctx->net,
|
||||
@ -868,7 +868,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
.table = ctx->table,
|
||||
.chain = (struct nft_chain *)binding->chain,
|
||||
};
|
||||
@@ -4548,7 +4534,8 @@ static int nf_tables_newobj(struct net *
|
||||
@@ -4554,7 +4540,8 @@ static int nf_tables_newobj(struct net *
|
||||
if (IS_ERR(afi))
|
||||
return PTR_ERR(afi);
|
||||
|
||||
@ -878,7 +878,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (IS_ERR(table))
|
||||
return PTR_ERR(table);
|
||||
|
||||
@@ -4566,7 +4553,7 @@ static int nf_tables_newobj(struct net *
|
||||
@@ -4572,7 +4559,7 @@ static int nf_tables_newobj(struct net *
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -887,7 +887,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
type = nft_obj_type_get(objtype);
|
||||
if (IS_ERR(type))
|
||||
@@ -4643,7 +4630,6 @@ struct nft_obj_filter {
|
||||
@@ -4649,7 +4636,6 @@ struct nft_obj_filter {
|
||||
static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
|
||||
@ -895,7 +895,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
const struct nft_table *table;
|
||||
unsigned int idx = 0, s_idx = cb->args[0];
|
||||
struct nft_obj_filter *filter = cb->data;
|
||||
@@ -4658,38 +4644,37 @@ static int nf_tables_dump_obj(struct sk_
|
||||
@@ -4664,38 +4650,37 @@ static int nf_tables_dump_obj(struct sk_
|
||||
rcu_read_lock();
|
||||
cb->seq = net->nft.base_seq;
|
||||
|
||||
@ -960,7 +960,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
}
|
||||
}
|
||||
done:
|
||||
@@ -4776,7 +4761,8 @@ static int nf_tables_getobj(struct net *
|
||||
@@ -4782,7 +4767,8 @@ static int nf_tables_getobj(struct net *
|
||||
if (IS_ERR(afi))
|
||||
return PTR_ERR(afi);
|
||||
|
||||
@ -970,7 +970,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (IS_ERR(table))
|
||||
return PTR_ERR(table);
|
||||
|
||||
@@ -4836,7 +4822,8 @@ static int nf_tables_delobj(struct net *
|
||||
@@ -4842,7 +4828,8 @@ static int nf_tables_delobj(struct net *
|
||||
if (IS_ERR(afi))
|
||||
return PTR_ERR(afi);
|
||||
|
||||
@ -980,7 +980,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (IS_ERR(table))
|
||||
return PTR_ERR(table);
|
||||
|
||||
@@ -4847,7 +4834,7 @@ static int nf_tables_delobj(struct net *
|
||||
@@ -4853,7 +4840,7 @@ static int nf_tables_delobj(struct net *
|
||||
if (obj->use > 0)
|
||||
return -EBUSY;
|
||||
|
||||
@ -989,7 +989,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
return nft_delobj(&ctx, obj);
|
||||
}
|
||||
@@ -4885,7 +4872,7 @@ static void nf_tables_obj_notify(const s
|
||||
@@ -4891,7 +4878,7 @@ static void nf_tables_obj_notify(const s
|
||||
struct nft_object *obj, int event)
|
||||
{
|
||||
nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event,
|
||||
@ -998,7 +998,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5075,7 +5062,7 @@ void nft_flow_table_iterate(struct net *
|
||||
@@ -5081,7 +5068,7 @@ void nft_flow_table_iterate(struct net *
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
|
||||
@ -1007,7 +1007,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
list_for_each_entry_rcu(flowtable, &table->flowtables, list) {
|
||||
iter(&flowtable->data, data);
|
||||
}
|
||||
@@ -5123,7 +5110,8 @@ static int nf_tables_newflowtable(struct
|
||||
@@ -5129,7 +5116,8 @@ static int nf_tables_newflowtable(struct
|
||||
if (IS_ERR(afi))
|
||||
return PTR_ERR(afi);
|
||||
|
||||
@ -1017,7 +1017,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (IS_ERR(table))
|
||||
return PTR_ERR(table);
|
||||
|
||||
@@ -5140,7 +5128,7 @@ static int nf_tables_newflowtable(struct
|
||||
@@ -5146,7 +5134,7 @@ static int nf_tables_newflowtable(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1026,7 +1026,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL);
|
||||
if (!flowtable)
|
||||
@@ -5221,7 +5209,8 @@ static int nf_tables_delflowtable(struct
|
||||
@@ -5227,7 +5215,8 @@ static int nf_tables_delflowtable(struct
|
||||
if (IS_ERR(afi))
|
||||
return PTR_ERR(afi);
|
||||
|
||||
@ -1036,7 +1036,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (IS_ERR(table))
|
||||
return PTR_ERR(table);
|
||||
|
||||
@@ -5232,7 +5221,7 @@ static int nf_tables_delflowtable(struct
|
||||
@@ -5238,7 +5227,7 @@ static int nf_tables_delflowtable(struct
|
||||
if (flowtable->use > 0)
|
||||
return -EBUSY;
|
||||
|
||||
@ -1045,7 +1045,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
return nft_delflowtable(&ctx, flowtable);
|
||||
}
|
||||
@@ -5301,40 +5290,37 @@ static int nf_tables_dump_flowtable(stru
|
||||
@@ -5307,40 +5296,37 @@ static int nf_tables_dump_flowtable(stru
|
||||
struct net *net = sock_net(skb->sk);
|
||||
int family = nfmsg->nfgen_family;
|
||||
struct nft_flowtable *flowtable;
|
||||
@ -1107,7 +1107,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
}
|
||||
}
|
||||
done:
|
||||
@@ -5419,7 +5405,8 @@ static int nf_tables_getflowtable(struct
|
||||
@@ -5425,7 +5411,8 @@ static int nf_tables_getflowtable(struct
|
||||
if (IS_ERR(afi))
|
||||
return PTR_ERR(afi);
|
||||
|
||||
@ -1117,7 +1117,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (IS_ERR(table))
|
||||
return PTR_ERR(table);
|
||||
|
||||
@@ -5462,7 +5449,7 @@ static void nf_tables_flowtable_notify(s
|
||||
@@ -5468,7 +5455,7 @@ static void nf_tables_flowtable_notify(s
|
||||
|
||||
err = nf_tables_fill_flowtable_info(skb, ctx->net, ctx->portid,
|
||||
ctx->seq, event, 0,
|
||||
@ -1126,7 +1126,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (err < 0) {
|
||||
kfree_skb(skb);
|
||||
goto err;
|
||||
@@ -5540,17 +5527,14 @@ static int nf_tables_flowtable_event(str
|
||||
@@ -5546,17 +5533,14 @@ static int nf_tables_flowtable_event(str
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
struct nft_flowtable *flowtable;
|
||||
struct nft_table *table;
|
||||
@ -1147,7 +1147,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
}
|
||||
}
|
||||
nfnl_unlock(NFNL_SUBSYS_NFTABLES);
|
||||
@@ -6576,6 +6560,7 @@ EXPORT_SYMBOL_GPL(nft_data_dump);
|
||||
@@ -6582,6 +6566,7 @@ EXPORT_SYMBOL_GPL(nft_data_dump);
|
||||
static int __net_init nf_tables_init_net(struct net *net)
|
||||
{
|
||||
INIT_LIST_HEAD(&net->nft.af_info);
|
||||
@ -1155,7 +1155,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
INIT_LIST_HEAD(&net->nft.commit_list);
|
||||
net->nft.base_seq = 1;
|
||||
return 0;
|
||||
@@ -6612,10 +6597,10 @@ static void __nft_release_afinfo(struct
|
||||
@@ -6618,10 +6603,10 @@ static void __nft_release_afinfo(struct
|
||||
struct nft_set *set, *ns;
|
||||
struct nft_ctx ctx = {
|
||||
.net = net,
|
||||
|
@ -21,7 +21,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
static struct pernet_operations clusterip_net_ops = {
|
||||
--- a/net/netfilter/nf_tables_api.c
|
||||
+++ b/net/netfilter/nf_tables_api.c
|
||||
@@ -6566,6 +6566,12 @@ static int __net_init nf_tables_init_net
|
||||
@@ -6572,6 +6572,12 @@ static int __net_init nf_tables_init_net
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
int __nft_release_basechain(struct nft_ctx *ctx)
|
||||
{
|
||||
struct nft_rule *rule, *nr;
|
||||
@@ -6643,6 +6649,7 @@ static void __nft_release_afinfo(struct
|
||||
@@ -6649,6 +6655,7 @@ static void __nft_release_afinfo(struct
|
||||
|
||||
static struct pernet_operations nf_tables_net_ops = {
|
||||
.init = nf_tables_init_net,
|
||||
|
@ -364,7 +364,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (afi->family == family)
|
||||
return afi;
|
||||
}
|
||||
@@ -5057,15 +5055,12 @@ void nft_flow_table_iterate(struct net *
|
||||
@@ -5063,15 +5061,12 @@ void nft_flow_table_iterate(struct net *
|
||||
void *data)
|
||||
{
|
||||
struct nft_flowtable *flowtable;
|
||||
@ -383,7 +383,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
@@ -6557,21 +6552,6 @@ int nft_data_dump(struct sk_buff *skb, i
|
||||
@@ -6563,21 +6558,6 @@ int nft_data_dump(struct sk_buff *skb, i
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_data_dump);
|
||||
|
||||
@ -405,7 +405,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
int __nft_release_basechain(struct nft_ctx *ctx)
|
||||
{
|
||||
struct nft_rule *rule, *nr;
|
||||
@@ -6592,8 +6572,7 @@ int __nft_release_basechain(struct nft_c
|
||||
@@ -6598,8 +6578,7 @@ int __nft_release_basechain(struct nft_c
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__nft_release_basechain);
|
||||
|
||||
@ -415,7 +415,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
{
|
||||
struct nft_flowtable *flowtable, *nf;
|
||||
struct nft_table *table, *nt;
|
||||
@@ -6603,10 +6582,11 @@ static void __nft_release_afinfo(struct
|
||||
@@ -6609,10 +6588,11 @@ static void __nft_release_afinfo(struct
|
||||
struct nft_set *set, *ns;
|
||||
struct nft_ctx ctx = {
|
||||
.net = net,
|
||||
@ -428,7 +428,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
list_for_each_entry(chain, &table->chains, list)
|
||||
nf_tables_unregister_hook(net, table, chain);
|
||||
list_for_each_entry(flowtable, &table->flowtables, list)
|
||||
@@ -6647,6 +6627,21 @@ static void __nft_release_afinfo(struct
|
||||
@@ -6653,6 +6633,21 @@ static void __nft_release_afinfo(struct
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -817,7 +817,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
|
||||
|
||||
@@ -4516,7 +4383,6 @@ static int nf_tables_newobj(struct net *
|
||||
@@ -4522,7 +4389,6 @@ static int nf_tables_newobj(struct net *
|
||||
const struct nft_object_type *type;
|
||||
u8 genmask = nft_genmask_next(net);
|
||||
int family = nfmsg->nfgen_family;
|
||||
@ -825,7 +825,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
struct nft_table *table;
|
||||
struct nft_object *obj;
|
||||
struct nft_ctx ctx;
|
||||
@@ -4528,11 +4394,7 @@ static int nf_tables_newobj(struct net *
|
||||
@@ -4534,11 +4400,7 @@ static int nf_tables_newobj(struct net *
|
||||
!nla[NFTA_OBJ_DATA])
|
||||
return -EINVAL;
|
||||
|
||||
@ -838,7 +838,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
genmask);
|
||||
if (IS_ERR(table))
|
||||
return PTR_ERR(table);
|
||||
@@ -4551,7 +4413,7 @@ static int nf_tables_newobj(struct net *
|
||||
@@ -4557,7 +4419,7 @@ static int nf_tables_newobj(struct net *
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -847,7 +847,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
type = nft_obj_type_get(objtype);
|
||||
if (IS_ERR(type))
|
||||
@@ -4643,7 +4505,7 @@ static int nf_tables_dump_obj(struct sk_
|
||||
@@ -4649,7 +4511,7 @@ static int nf_tables_dump_obj(struct sk_
|
||||
cb->seq = net->nft.base_seq;
|
||||
|
||||
list_for_each_entry_rcu(table, &net->nft.tables, list) {
|
||||
@ -856,7 +856,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
continue;
|
||||
|
||||
list_for_each_entry_rcu(obj, &table->objects, list) {
|
||||
@@ -4666,7 +4528,7 @@ static int nf_tables_dump_obj(struct sk_
|
||||
@@ -4672,7 +4534,7 @@ static int nf_tables_dump_obj(struct sk_
|
||||
cb->nlh->nlmsg_seq,
|
||||
NFT_MSG_NEWOBJ,
|
||||
NLM_F_MULTI | NLM_F_APPEND,
|
||||
@ -865,7 +865,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
obj, reset) < 0)
|
||||
goto done;
|
||||
|
||||
@@ -4724,7 +4586,6 @@ static int nf_tables_getobj(struct net *
|
||||
@@ -4730,7 +4592,6 @@ static int nf_tables_getobj(struct net *
|
||||
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
||||
u8 genmask = nft_genmask_cur(net);
|
||||
int family = nfmsg->nfgen_family;
|
||||
@ -873,7 +873,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
const struct nft_table *table;
|
||||
struct nft_object *obj;
|
||||
struct sk_buff *skb2;
|
||||
@@ -4755,11 +4616,7 @@ static int nf_tables_getobj(struct net *
|
||||
@@ -4761,11 +4622,7 @@ static int nf_tables_getobj(struct net *
|
||||
!nla[NFTA_OBJ_TYPE])
|
||||
return -EINVAL;
|
||||
|
||||
@ -886,7 +886,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
genmask);
|
||||
if (IS_ERR(table))
|
||||
return PTR_ERR(table);
|
||||
@@ -4806,7 +4663,6 @@ static int nf_tables_delobj(struct net *
|
||||
@@ -4812,7 +4669,6 @@ static int nf_tables_delobj(struct net *
|
||||
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
||||
u8 genmask = nft_genmask_next(net);
|
||||
int family = nfmsg->nfgen_family;
|
||||
@ -894,7 +894,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
struct nft_table *table;
|
||||
struct nft_object *obj;
|
||||
struct nft_ctx ctx;
|
||||
@@ -4816,11 +4672,7 @@ static int nf_tables_delobj(struct net *
|
||||
@@ -4822,11 +4678,7 @@ static int nf_tables_delobj(struct net *
|
||||
!nla[NFTA_OBJ_NAME])
|
||||
return -EINVAL;
|
||||
|
||||
@ -907,7 +907,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
genmask);
|
||||
if (IS_ERR(table))
|
||||
return PTR_ERR(table);
|
||||
@@ -4832,7 +4684,7 @@ static int nf_tables_delobj(struct net *
|
||||
@@ -4838,7 +4690,7 @@ static int nf_tables_delobj(struct net *
|
||||
if (obj->use > 0)
|
||||
return -EBUSY;
|
||||
|
||||
@ -916,7 +916,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
return nft_delobj(&ctx, obj);
|
||||
}
|
||||
@@ -5017,33 +4869,31 @@ err1:
|
||||
@@ -5023,33 +4875,31 @@ err1:
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -956,7 +956,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
return ERR_PTR(-EAGAIN);
|
||||
}
|
||||
#endif
|
||||
@@ -5091,7 +4941,6 @@ static int nf_tables_newflowtable(struct
|
||||
@@ -5097,7 +4947,6 @@ static int nf_tables_newflowtable(struct
|
||||
u8 genmask = nft_genmask_next(net);
|
||||
int family = nfmsg->nfgen_family;
|
||||
struct nft_flowtable *flowtable;
|
||||
@ -964,7 +964,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
struct nft_table *table;
|
||||
struct nft_ctx ctx;
|
||||
int err, i, k;
|
||||
@@ -5101,12 +4950,8 @@ static int nf_tables_newflowtable(struct
|
||||
@@ -5107,12 +4956,8 @@ static int nf_tables_newflowtable(struct
|
||||
!nla[NFTA_FLOWTABLE_HOOK])
|
||||
return -EINVAL;
|
||||
|
||||
@ -978,7 +978,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (IS_ERR(table))
|
||||
return PTR_ERR(table);
|
||||
|
||||
@@ -5123,7 +4968,7 @@ static int nf_tables_newflowtable(struct
|
||||
@@ -5129,7 +4974,7 @@ static int nf_tables_newflowtable(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -987,7 +987,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL);
|
||||
if (!flowtable)
|
||||
@@ -5136,7 +4981,7 @@ static int nf_tables_newflowtable(struct
|
||||
@@ -5142,7 +4987,7 @@ static int nf_tables_newflowtable(struct
|
||||
goto err1;
|
||||
}
|
||||
|
||||
@ -996,7 +996,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (IS_ERR(type)) {
|
||||
err = PTR_ERR(type);
|
||||
goto err2;
|
||||
@@ -5196,16 +5041,11 @@ static int nf_tables_delflowtable(struct
|
||||
@@ -5202,16 +5047,11 @@ static int nf_tables_delflowtable(struct
|
||||
u8 genmask = nft_genmask_next(net);
|
||||
int family = nfmsg->nfgen_family;
|
||||
struct nft_flowtable *flowtable;
|
||||
@ -1014,7 +1014,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (IS_ERR(table))
|
||||
return PTR_ERR(table);
|
||||
|
||||
@@ -5216,7 +5056,7 @@ static int nf_tables_delflowtable(struct
|
||||
@@ -5222,7 +5062,7 @@ static int nf_tables_delflowtable(struct
|
||||
if (flowtable->use > 0)
|
||||
return -EBUSY;
|
||||
|
||||
@ -1023,7 +1023,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
return nft_delflowtable(&ctx, flowtable);
|
||||
}
|
||||
@@ -5291,7 +5131,7 @@ static int nf_tables_dump_flowtable(stru
|
||||
@@ -5297,7 +5137,7 @@ static int nf_tables_dump_flowtable(stru
|
||||
cb->seq = net->nft.base_seq;
|
||||
|
||||
list_for_each_entry_rcu(table, &net->nft.tables, list) {
|
||||
@ -1032,7 +1032,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
continue;
|
||||
|
||||
list_for_each_entry_rcu(flowtable, &table->flowtables, list) {
|
||||
@@ -5310,7 +5150,7 @@ static int nf_tables_dump_flowtable(stru
|
||||
@@ -5316,7 +5156,7 @@ static int nf_tables_dump_flowtable(stru
|
||||
cb->nlh->nlmsg_seq,
|
||||
NFT_MSG_NEWFLOWTABLE,
|
||||
NLM_F_MULTI | NLM_F_APPEND,
|
||||
@ -1041,7 +1041,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
goto done;
|
||||
|
||||
nl_dump_check_consistent(cb, nlmsg_hdr(skb));
|
||||
@@ -5370,7 +5210,6 @@ static int nf_tables_getflowtable(struct
|
||||
@@ -5376,7 +5216,6 @@ static int nf_tables_getflowtable(struct
|
||||
u8 genmask = nft_genmask_cur(net);
|
||||
int family = nfmsg->nfgen_family;
|
||||
struct nft_flowtable *flowtable;
|
||||
@ -1049,7 +1049,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
const struct nft_table *table;
|
||||
struct sk_buff *skb2;
|
||||
int err;
|
||||
@@ -5396,12 +5235,8 @@ static int nf_tables_getflowtable(struct
|
||||
@@ -5402,12 +5241,8 @@ static int nf_tables_getflowtable(struct
|
||||
if (!nla[NFTA_FLOWTABLE_NAME])
|
||||
return -EINVAL;
|
||||
|
||||
@ -1063,7 +1063,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (IS_ERR(table))
|
||||
return PTR_ERR(table);
|
||||
|
||||
@@ -6572,7 +6407,7 @@ int __nft_release_basechain(struct nft_c
|
||||
@@ -6578,7 +6413,7 @@ int __nft_release_basechain(struct nft_c
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__nft_release_basechain);
|
||||
|
||||
@ -1072,7 +1072,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
{
|
||||
struct nft_flowtable *flowtable, *nf;
|
||||
struct nft_table *table, *nt;
|
||||
@@ -6585,7 +6420,7 @@ static void __nft_release_afinfo(struct
|
||||
@@ -6591,7 +6426,7 @@ static void __nft_release_afinfo(struct
|
||||
};
|
||||
|
||||
list_for_each_entry_safe(table, nt, &net->nft.tables, list) {
|
||||
@ -1081,7 +1081,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
list_for_each_entry(chain, &table->chains, list)
|
||||
nf_tables_unregister_hook(net, table, chain);
|
||||
@@ -6637,7 +6472,7 @@ static int __net_init nf_tables_init_net
|
||||
@@ -6643,7 +6478,7 @@ static int __net_init nf_tables_init_net
|
||||
|
||||
static void __net_exit nf_tables_exit_net(struct net *net)
|
||||
{
|
||||
|
@ -17,7 +17,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
--- a/net/netfilter/nf_tables_api.c
|
||||
+++ b/net/netfilter/nf_tables_api.c
|
||||
@@ -4907,13 +4907,13 @@ void nft_flow_table_iterate(struct net *
|
||||
@@ -4913,13 +4913,13 @@ void nft_flow_table_iterate(struct net *
|
||||
struct nft_flowtable *flowtable;
|
||||
const struct nft_table *table;
|
||||
|
||||
|
@ -118,7 +118,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
};
|
||||
--- a/net/netfilter/nf_tables_api.c
|
||||
+++ b/net/netfilter/nf_tables_api.c
|
||||
@@ -5292,17 +5292,12 @@ err:
|
||||
@@ -5298,17 +5298,12 @@ err:
|
||||
nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
|
||||
}
|
||||
|
||||
|
@ -327,7 +327,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (IS_ERR(set))
|
||||
return PTR_ERR(set);
|
||||
|
||||
@@ -4271,6 +4343,21 @@ struct nft_object *nf_tables_obj_lookup(
|
||||
@@ -4277,6 +4349,21 @@ struct nft_object *nf_tables_obj_lookup(
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_tables_obj_lookup);
|
||||
|
||||
@ -349,7 +349,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = {
|
||||
[NFTA_OBJ_TABLE] = { .type = NLA_STRING,
|
||||
.len = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
@@ -4278,6 +4365,7 @@ static const struct nla_policy nft_obj_p
|
||||
@@ -4284,6 +4371,7 @@ static const struct nla_policy nft_obj_p
|
||||
.len = NFT_OBJ_MAXNAMELEN - 1 },
|
||||
[NFTA_OBJ_TYPE] = { .type = NLA_U32 },
|
||||
[NFTA_OBJ_DATA] = { .type = NLA_NESTED },
|
||||
@ -357,7 +357,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
};
|
||||
|
||||
static struct nft_object *nft_obj_init(const struct nft_ctx *ctx,
|
||||
@@ -4425,6 +4513,8 @@ static int nf_tables_newobj(struct net *
|
||||
@@ -4431,6 +4519,8 @@ static int nf_tables_newobj(struct net *
|
||||
goto err1;
|
||||
}
|
||||
obj->table = table;
|
||||
@ -366,7 +366,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
obj->name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL);
|
||||
if (!obj->name) {
|
||||
err = -ENOMEM;
|
||||
@@ -4471,7 +4561,9 @@ static int nf_tables_fill_obj_info(struc
|
||||
@@ -4477,7 +4567,9 @@ static int nf_tables_fill_obj_info(struc
|
||||
nla_put_string(skb, NFTA_OBJ_NAME, obj->name) ||
|
||||
nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) ||
|
||||
nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) ||
|
||||
@ -377,7 +377,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
goto nla_put_failure;
|
||||
|
||||
nlmsg_end(skb, nlh);
|
||||
@@ -4669,7 +4761,7 @@ static int nf_tables_delobj(struct net *
|
||||
@@ -4675,7 +4767,7 @@ static int nf_tables_delobj(struct net *
|
||||
u32 objtype;
|
||||
|
||||
if (!nla[NFTA_OBJ_TYPE] ||
|
||||
@ -386,7 +386,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
return -EINVAL;
|
||||
|
||||
table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family,
|
||||
@@ -4678,7 +4770,12 @@ static int nf_tables_delobj(struct net *
|
||||
@@ -4684,7 +4776,12 @@ static int nf_tables_delobj(struct net *
|
||||
return PTR_ERR(table);
|
||||
|
||||
objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
|
||||
@ -400,7 +400,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (IS_ERR(obj))
|
||||
return PTR_ERR(obj);
|
||||
if (obj->use > 0)
|
||||
@@ -4750,6 +4847,7 @@ static const struct nla_policy nft_flowt
|
||||
@@ -4756,6 +4853,7 @@ static const struct nla_policy nft_flowt
|
||||
[NFTA_FLOWTABLE_NAME] = { .type = NLA_STRING,
|
||||
.len = NFT_NAME_MAXLEN - 1 },
|
||||
[NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED },
|
||||
@ -408,7 +408,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
};
|
||||
|
||||
struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table,
|
||||
@@ -4767,6 +4865,20 @@ struct nft_flowtable *nf_tables_flowtabl
|
||||
@@ -4773,6 +4871,20 @@ struct nft_flowtable *nf_tables_flowtabl
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_tables_flowtable_lookup);
|
||||
|
||||
@ -429,7 +429,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
#define NFT_FLOWTABLE_DEVICE_MAX 8
|
||||
|
||||
static int nf_tables_parse_devices(const struct nft_ctx *ctx,
|
||||
@@ -4975,6 +5087,8 @@ static int nf_tables_newflowtable(struct
|
||||
@@ -4981,6 +5093,8 @@ static int nf_tables_newflowtable(struct
|
||||
return -ENOMEM;
|
||||
|
||||
flowtable->table = table;
|
||||
@ -438,7 +438,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL);
|
||||
if (!flowtable->name) {
|
||||
err = -ENOMEM;
|
||||
@@ -5049,8 +5163,14 @@ static int nf_tables_delflowtable(struct
|
||||
@@ -5055,8 +5169,14 @@ static int nf_tables_delflowtable(struct
|
||||
if (IS_ERR(table))
|
||||
return PTR_ERR(table);
|
||||
|
||||
@ -455,7 +455,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
if (IS_ERR(flowtable))
|
||||
return PTR_ERR(flowtable);
|
||||
if (flowtable->use > 0)
|
||||
@@ -5083,7 +5203,9 @@ static int nf_tables_fill_flowtable_info
|
||||
@@ -5089,7 +5209,9 @@ static int nf_tables_fill_flowtable_info
|
||||
|
||||
if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) ||
|
||||
nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) ||
|
||||
|
@ -236,7 +236,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
.owner = THIS_MODULE,
|
||||
--- a/net/netfilter/nf_tables_api.c
|
||||
+++ b/net/netfilter/nf_tables_api.c
|
||||
@@ -5102,40 +5102,38 @@ static int nf_tables_newflowtable(struct
|
||||
@@ -5108,40 +5108,38 @@ static int nf_tables_newflowtable(struct
|
||||
}
|
||||
|
||||
flowtable->data.type = type;
|
||||
@ -285,7 +285,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
err3:
|
||||
module_put(type->owner);
|
||||
err2:
|
||||
@@ -5416,10 +5414,8 @@ err:
|
||||
@@ -5422,10 +5420,8 @@ err:
|
||||
|
||||
static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable)
|
||||
{
|
||||
|
@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/net/netfilter/nf_tables_api.c
|
||||
+++ b/net/netfilter/nf_tables_api.c
|
||||
@@ -4968,7 +4968,7 @@ static int nf_tables_flowtable_parse_hoo
|
||||
@@ -4974,7 +4974,7 @@ static int nf_tables_flowtable_parse_hoo
|
||||
flowtable->ops[i].pf = NFPROTO_NETDEV;
|
||||
flowtable->ops[i].hooknum = hooknum;
|
||||
flowtable->ops[i].priority = priority;
|
||||
|
@ -88,7 +88,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
WARN_ON(!nf_flow_offload_gc_step(flow_table));
|
||||
--- a/net/netfilter/nf_tables_api.c
|
||||
+++ b/net/netfilter/nf_tables_api.c
|
||||
@@ -5012,23 +5012,6 @@ static const struct nf_flowtable_type *n
|
||||
@@ -5018,23 +5018,6 @@ static const struct nf_flowtable_type *n
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 147b0d133b53635db0cc572294840652c9c7b662 Mon Sep 17 00:00:00 2001
|
||||
From 85fc2a6db8279c5e43c38ef7e715d14e57287997 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
Date: Wed, 13 Mar 2019 20:54:49 +0000
|
||||
Subject: [PATCH] net: sched: Backport Introduce act_ctinfo action
|
||||
@ -112,8 +112,8 @@ Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
include/uapi/linux/tc_act/tc_ctinfo.h | 29 ++
|
||||
net/sched/Kconfig | 13 +
|
||||
net/sched/Makefile | 1 +
|
||||
net/sched/act_ctinfo.c | 394 ++++++++++++++++++++++++++
|
||||
6 files changed, 472 insertions(+), 1 deletion(-)
|
||||
net/sched/act_ctinfo.c | 405 ++++++++++++++++++++++++++
|
||||
6 files changed, 482 insertions(+), 1 deletion(-)
|
||||
create mode 100644 include/net/tc_act/tc_ctinfo.h
|
||||
create mode 100644 include/uapi/linux/tc_act/tc_ctinfo.h
|
||||
create mode 100644 net/sched/act_ctinfo.c
|
||||
@ -232,7 +232,7 @@ Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
obj-$(CONFIG_NET_IFE_SKBMARK) += act_meta_mark.o
|
||||
--- /dev/null
|
||||
+++ b/net/sched/act_ctinfo.c
|
||||
@@ -0,0 +1,394 @@
|
||||
@@ -0,0 +1,405 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0+
|
||||
+/* net/sched/act_ctinfo.c netfilter ctinfo connmark actions
|
||||
+ *
|
||||
@ -579,6 +579,16 @@ Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
+ return tcf_idr_search(tn, a, index);
|
||||
+}
|
||||
+
|
||||
+static void tcf_ctinfo_cleanup(struct tc_action *a, int bind)
|
||||
+{
|
||||
+ struct tcf_ctinfo *ci = to_ctinfo(a);
|
||||
+ struct tcf_ctinfo_params *cp;
|
||||
+
|
||||
+ cp = rcu_dereference_protected(ci->params, 1);
|
||||
+ if (cp)
|
||||
+ kfree_rcu(cp, rcu);
|
||||
+}
|
||||
+
|
||||
+static struct tc_action_ops act_ctinfo_ops = {
|
||||
+ .kind = "ctinfo",
|
||||
+ .type = TCA_ID_CTINFO,
|
||||
@ -586,6 +596,7 @@ Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
+ .act = tcf_ctinfo_act,
|
||||
+ .dump = tcf_ctinfo_dump,
|
||||
+ .init = tcf_ctinfo_init,
|
||||
+ .cleanup= tcf_ctinfo_cleanup,
|
||||
+ .walk = tcf_ctinfo_walker,
|
||||
+ .lookup = tcf_ctinfo_search,
|
||||
+ .size = sizeof(struct tcf_ctinfo),
|
||||
@ -595,7 +606,7 @@ Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
+{
|
||||
+ struct tc_action_net *tn = net_generic(net, ctinfo_net_id);
|
||||
+
|
||||
+ return tc_action_net_init(tn, &act_ctinfo_ops);
|
||||
+ return tc_action_net_init(net, tn, &act_ctinfo_ops);
|
||||
+}
|
||||
+
|
||||
+static void __net_exit ctinfo_exit_net(struct net *net)
|
||||
|
@ -0,0 +1,37 @@
|
||||
From: Gabor Juhos <juhosg@openwrt.org>
|
||||
Subject: fs: ubifs: fix default compression selection in ubifs
|
||||
|
||||
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||
---
|
||||
fs/ubifs/sb.c | 13 ++++++++++++-
|
||||
1 file changed, 12 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/fs/ubifs/sb.c
|
||||
+++ b/fs/ubifs/sb.c
|
||||
@@ -63,6 +63,17 @@
|
||||
/* Default time granularity in nanoseconds */
|
||||
#define DEFAULT_TIME_GRAN 1000000000
|
||||
|
||||
+static int get_default_compressor(void)
|
||||
+{
|
||||
+ if (ubifs_compr_present(UBIFS_COMPR_LZO))
|
||||
+ return UBIFS_COMPR_LZO;
|
||||
+
|
||||
+ if (ubifs_compr_present(UBIFS_COMPR_ZLIB))
|
||||
+ return UBIFS_COMPR_ZLIB;
|
||||
+
|
||||
+ return UBIFS_COMPR_NONE;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* create_default_filesystem - format empty UBI volume.
|
||||
* @c: UBIFS file-system description object
|
||||
@@ -186,7 +197,7 @@ static int create_default_filesystem(str
|
||||
if (c->mount_opts.override_compr)
|
||||
sup->default_compr = cpu_to_le16(c->mount_opts.compr_type);
|
||||
else
|
||||
- sup->default_compr = cpu_to_le16(UBIFS_COMPR_LZO);
|
||||
+ sup->default_compr = cpu_to_le16(get_default_compressor());
|
||||
|
||||
generate_random_uuid(sup->uuid);
|
||||
|
@ -0,0 +1,57 @@
|
||||
From b23908d3c48a37c46c6a26df2cdeab1610b360ba Mon Sep 17 00:00:00 2001
|
||||
From: Simon Glass <sjg@chromium.org>
|
||||
Date: Sun, 17 Jun 2018 14:09:42 +0200
|
||||
Subject: [PATCH] firmware: dmi: Add access to the SKU ID string
|
||||
|
||||
This is used in some systems from user space for determining the identity
|
||||
of the device.
|
||||
|
||||
Expose this as a file so that that user-space tools don't need to read
|
||||
from /sys/firmware/dmi/tables/DMI
|
||||
|
||||
Signed-off-by: Simon Glass <sjg@chromium.org>
|
||||
Signed-off-by: Jean Delvare <jdelvare@suse.de>
|
||||
---
|
||||
drivers/firmware/dmi-id.c | 2 ++
|
||||
drivers/firmware/dmi_scan.c | 1 +
|
||||
include/linux/mod_devicetable.h | 1 +
|
||||
3 files changed, 4 insertions(+)
|
||||
|
||||
--- a/drivers/firmware/dmi-id.c
|
||||
+++ b/drivers/firmware/dmi-id.c
|
||||
@@ -47,6 +47,7 @@ DEFINE_DMI_ATTR_WITH_SHOW(product_name,
|
||||
DEFINE_DMI_ATTR_WITH_SHOW(product_version, 0444, DMI_PRODUCT_VERSION);
|
||||
DEFINE_DMI_ATTR_WITH_SHOW(product_serial, 0400, DMI_PRODUCT_SERIAL);
|
||||
DEFINE_DMI_ATTR_WITH_SHOW(product_uuid, 0400, DMI_PRODUCT_UUID);
|
||||
+DEFINE_DMI_ATTR_WITH_SHOW(product_sku, 0444, DMI_PRODUCT_SKU);
|
||||
DEFINE_DMI_ATTR_WITH_SHOW(product_family, 0444, DMI_PRODUCT_FAMILY);
|
||||
DEFINE_DMI_ATTR_WITH_SHOW(board_vendor, 0444, DMI_BOARD_VENDOR);
|
||||
DEFINE_DMI_ATTR_WITH_SHOW(board_name, 0444, DMI_BOARD_NAME);
|
||||
@@ -193,6 +194,7 @@ static void __init dmi_id_init_attr_tabl
|
||||
ADD_DMI_ATTR(product_serial, DMI_PRODUCT_SERIAL);
|
||||
ADD_DMI_ATTR(product_uuid, DMI_PRODUCT_UUID);
|
||||
ADD_DMI_ATTR(product_family, DMI_PRODUCT_FAMILY);
|
||||
+ ADD_DMI_ATTR(product_sku, DMI_PRODUCT_SKU);
|
||||
ADD_DMI_ATTR(board_vendor, DMI_BOARD_VENDOR);
|
||||
ADD_DMI_ATTR(board_name, DMI_BOARD_NAME);
|
||||
ADD_DMI_ATTR(board_version, DMI_BOARD_VERSION);
|
||||
--- a/drivers/firmware/dmi_scan.c
|
||||
+++ b/drivers/firmware/dmi_scan.c
|
||||
@@ -435,6 +435,7 @@ static void __init dmi_decode(const stru
|
||||
dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
|
||||
dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
|
||||
dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8);
|
||||
+ dmi_save_ident(dm, DMI_PRODUCT_SKU, 25);
|
||||
dmi_save_ident(dm, DMI_PRODUCT_FAMILY, 26);
|
||||
break;
|
||||
case 2: /* Base Board Information */
|
||||
--- a/include/linux/mod_devicetable.h
|
||||
+++ b/include/linux/mod_devicetable.h
|
||||
@@ -471,6 +471,7 @@ enum dmi_field {
|
||||
DMI_PRODUCT_VERSION,
|
||||
DMI_PRODUCT_SERIAL,
|
||||
DMI_PRODUCT_UUID,
|
||||
+ DMI_PRODUCT_SKU,
|
||||
DMI_PRODUCT_FAMILY,
|
||||
DMI_BOARD_VENDOR,
|
||||
DMI_BOARD_NAME,
|
@ -0,0 +1,75 @@
|
||||
From 9d9398944488cd3a3e1e0912b26fbc4d5921e547 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Mon, 4 Jun 2018 23:33:07 +0200
|
||||
Subject: [PATCH] tty: serial: exar: generalize RS485 setup
|
||||
|
||||
Move the non-board-specific part of the RS485 initialization from
|
||||
iot2040_rs485_config function to a new generic function used also for
|
||||
other boards.
|
||||
This allows using TIOCGRS485 and TIOCSRS485 on boards (such as mPCIe
|
||||
serial IO modules) which are hard-wired to RS485 or have jumpers for
|
||||
their configurations.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Reviewed-by: Jan Kiszka <jan.kiszka@siemens.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/tty/serial/8250/8250_exar.c | 38 +++++++++++++++++++----------
|
||||
1 file changed, 25 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/tty/serial/8250/8250_exar.c
|
||||
+++ b/drivers/tty/serial/8250/8250_exar.c
|
||||
@@ -275,8 +275,32 @@ static int xr17v35x_register_gpio(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int generic_rs485_config(struct uart_port *port,
|
||||
+ struct serial_rs485 *rs485)
|
||||
+{
|
||||
+ bool is_rs485 = !!(rs485->flags & SER_RS485_ENABLED);
|
||||
+ u8 __iomem *p = port->membase;
|
||||
+ u8 value;
|
||||
+
|
||||
+ value = readb(p + UART_EXAR_FCTR);
|
||||
+ if (is_rs485)
|
||||
+ value |= UART_FCTR_EXAR_485;
|
||||
+ else
|
||||
+ value &= ~UART_FCTR_EXAR_485;
|
||||
+
|
||||
+ writeb(value, p + UART_EXAR_FCTR);
|
||||
+
|
||||
+ if (is_rs485)
|
||||
+ writeb(UART_EXAR_RS485_DLY(4), p + UART_MSR);
|
||||
+
|
||||
+ port->rs485 = *rs485;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const struct exar8250_platform exar8250_default_platform = {
|
||||
.register_gpio = xr17v35x_register_gpio,
|
||||
+ .rs485_config = generic_rs485_config,
|
||||
};
|
||||
|
||||
static int iot2040_rs485_config(struct uart_port *port,
|
||||
@@ -309,19 +333,7 @@ static int iot2040_rs485_config(struct u
|
||||
value |= mode;
|
||||
writeb(value, p + UART_EXAR_MPIOLVL_7_0);
|
||||
|
||||
- value = readb(p + UART_EXAR_FCTR);
|
||||
- if (is_rs485)
|
||||
- value |= UART_FCTR_EXAR_485;
|
||||
- else
|
||||
- value &= ~UART_FCTR_EXAR_485;
|
||||
- writeb(value, p + UART_EXAR_FCTR);
|
||||
-
|
||||
- if (is_rs485)
|
||||
- writeb(UART_EXAR_RS485_DLY(4), p + UART_MSR);
|
||||
-
|
||||
- port->rs485 = *rs485;
|
||||
-
|
||||
- return 0;
|
||||
+ return generic_rs485_config(port, rs485);
|
||||
}
|
||||
|
||||
static const struct property_entry iot2040_gpio_properties[] = {
|
@ -0,0 +1,280 @@
|
||||
From 9966a05c7b80f075f2bc7e48dbb108d3f2927234 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Martin <Dave.Martin@arm.com>
|
||||
Date: Fri, 4 Jan 2019 13:09:51 +0000
|
||||
Subject: [PATCH] arm64/sve: Disentangle <uapi/asm/ptrace.h> from
|
||||
<uapi/asm/sigcontext.h>
|
||||
|
||||
Currently, <uapi/asm/sigcontext.h> provides common definitions for
|
||||
describing SVE context structures that are also used by the ptrace
|
||||
definitions in <uapi/asm/ptrace.h>.
|
||||
|
||||
For this reason, a #include of <asm/sigcontext.h> was added in
|
||||
ptrace.h, but it this turns out that this can interact badly with
|
||||
userspace code that tries to include ptrace.h on top of the libc
|
||||
headers (which may provide their own shadow definitions for
|
||||
sigcontext.h).
|
||||
|
||||
To make the headers easier for userspace to consume, this patch
|
||||
bounces the common definitions into an __SVE_* namespace and moves
|
||||
them to a backend header <uapi/asm/sve_context.h> that can be
|
||||
included by the other headers as appropriate. This should allow
|
||||
ptrace.h to be used alongside libc's sigcontext.h (if any) without
|
||||
ill effects.
|
||||
|
||||
This should make the situation unambiguous: <asm/sigcontext.h> is
|
||||
the header to include for the sigframe-specific definitions, while
|
||||
<asm/ptrace.h> is the header to include for ptrace-specific
|
||||
definitions.
|
||||
|
||||
To avoid conflicting with existing usage, <asm/sigcontext.h>
|
||||
remains the canonical way to get the common definitions for
|
||||
SVE_VQ_MIN, sve_vq_from_vl() etc., both in userspace and in the
|
||||
kernel: relying on these being defined as a side effect of
|
||||
including just <asm/ptrace.h> was never intended to be safe.
|
||||
|
||||
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
|
||||
Signed-off-by: Will Deacon <will.deacon@arm.com>
|
||||
---
|
||||
arch/arm64/include/uapi/asm/ptrace.h | 39 ++++++++--------
|
||||
arch/arm64/include/uapi/asm/sigcontext.h | 56 +++++++++++------------
|
||||
arch/arm64/include/uapi/asm/sve_context.h | 53 +++++++++++++++++++++
|
||||
3 files changed, 99 insertions(+), 49 deletions(-)
|
||||
create mode 100644 arch/arm64/include/uapi/asm/sve_context.h
|
||||
|
||||
--- a/arch/arm64/include/uapi/asm/ptrace.h
|
||||
+++ b/arch/arm64/include/uapi/asm/ptrace.h
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/hwcap.h>
|
||||
-#include <asm/sigcontext.h>
|
||||
+#include <asm/sve_context.h>
|
||||
|
||||
|
||||
/*
|
||||
@@ -128,9 +128,9 @@ struct user_sve_header {
|
||||
*/
|
||||
|
||||
/* Offset from the start of struct user_sve_header to the register data */
|
||||
-#define SVE_PT_REGS_OFFSET \
|
||||
- ((sizeof(struct user_sve_header) + (SVE_VQ_BYTES - 1)) \
|
||||
- / SVE_VQ_BYTES * SVE_VQ_BYTES)
|
||||
+#define SVE_PT_REGS_OFFSET \
|
||||
+ ((sizeof(struct user_sve_header) + (__SVE_VQ_BYTES - 1)) \
|
||||
+ / __SVE_VQ_BYTES * __SVE_VQ_BYTES)
|
||||
|
||||
/*
|
||||
* The register data content and layout depends on the value of the
|
||||
@@ -176,39 +176,36 @@ struct user_sve_header {
|
||||
* Additional data might be appended in the future.
|
||||
*/
|
||||
|
||||
-#define SVE_PT_SVE_ZREG_SIZE(vq) SVE_SIG_ZREG_SIZE(vq)
|
||||
-#define SVE_PT_SVE_PREG_SIZE(vq) SVE_SIG_PREG_SIZE(vq)
|
||||
-#define SVE_PT_SVE_FFR_SIZE(vq) SVE_SIG_FFR_SIZE(vq)
|
||||
+#define SVE_PT_SVE_ZREG_SIZE(vq) __SVE_ZREG_SIZE(vq)
|
||||
+#define SVE_PT_SVE_PREG_SIZE(vq) __SVE_PREG_SIZE(vq)
|
||||
+#define SVE_PT_SVE_FFR_SIZE(vq) __SVE_FFR_SIZE(vq)
|
||||
#define SVE_PT_SVE_FPSR_SIZE sizeof(__u32)
|
||||
#define SVE_PT_SVE_FPCR_SIZE sizeof(__u32)
|
||||
|
||||
-#define __SVE_SIG_TO_PT(offset) \
|
||||
- ((offset) - SVE_SIG_REGS_OFFSET + SVE_PT_REGS_OFFSET)
|
||||
-
|
||||
#define SVE_PT_SVE_OFFSET SVE_PT_REGS_OFFSET
|
||||
|
||||
#define SVE_PT_SVE_ZREGS_OFFSET \
|
||||
- __SVE_SIG_TO_PT(SVE_SIG_ZREGS_OFFSET)
|
||||
+ (SVE_PT_REGS_OFFSET + __SVE_ZREGS_OFFSET)
|
||||
#define SVE_PT_SVE_ZREG_OFFSET(vq, n) \
|
||||
- __SVE_SIG_TO_PT(SVE_SIG_ZREG_OFFSET(vq, n))
|
||||
+ (SVE_PT_REGS_OFFSET + __SVE_ZREG_OFFSET(vq, n))
|
||||
#define SVE_PT_SVE_ZREGS_SIZE(vq) \
|
||||
- (SVE_PT_SVE_ZREG_OFFSET(vq, SVE_NUM_ZREGS) - SVE_PT_SVE_ZREGS_OFFSET)
|
||||
+ (SVE_PT_SVE_ZREG_OFFSET(vq, __SVE_NUM_ZREGS) - SVE_PT_SVE_ZREGS_OFFSET)
|
||||
|
||||
#define SVE_PT_SVE_PREGS_OFFSET(vq) \
|
||||
- __SVE_SIG_TO_PT(SVE_SIG_PREGS_OFFSET(vq))
|
||||
+ (SVE_PT_REGS_OFFSET + __SVE_PREGS_OFFSET(vq))
|
||||
#define SVE_PT_SVE_PREG_OFFSET(vq, n) \
|
||||
- __SVE_SIG_TO_PT(SVE_SIG_PREG_OFFSET(vq, n))
|
||||
+ (SVE_PT_REGS_OFFSET + __SVE_PREG_OFFSET(vq, n))
|
||||
#define SVE_PT_SVE_PREGS_SIZE(vq) \
|
||||
- (SVE_PT_SVE_PREG_OFFSET(vq, SVE_NUM_PREGS) - \
|
||||
+ (SVE_PT_SVE_PREG_OFFSET(vq, __SVE_NUM_PREGS) - \
|
||||
SVE_PT_SVE_PREGS_OFFSET(vq))
|
||||
|
||||
#define SVE_PT_SVE_FFR_OFFSET(vq) \
|
||||
- __SVE_SIG_TO_PT(SVE_SIG_FFR_OFFSET(vq))
|
||||
+ (SVE_PT_REGS_OFFSET + __SVE_FFR_OFFSET(vq))
|
||||
|
||||
#define SVE_PT_SVE_FPSR_OFFSET(vq) \
|
||||
((SVE_PT_SVE_FFR_OFFSET(vq) + SVE_PT_SVE_FFR_SIZE(vq) + \
|
||||
- (SVE_VQ_BYTES - 1)) \
|
||||
- / SVE_VQ_BYTES * SVE_VQ_BYTES)
|
||||
+ (__SVE_VQ_BYTES - 1)) \
|
||||
+ / __SVE_VQ_BYTES * __SVE_VQ_BYTES)
|
||||
#define SVE_PT_SVE_FPCR_OFFSET(vq) \
|
||||
(SVE_PT_SVE_FPSR_OFFSET(vq) + SVE_PT_SVE_FPSR_SIZE)
|
||||
|
||||
@@ -219,8 +216,8 @@ struct user_sve_header {
|
||||
|
||||
#define SVE_PT_SVE_SIZE(vq, flags) \
|
||||
((SVE_PT_SVE_FPCR_OFFSET(vq) + SVE_PT_SVE_FPCR_SIZE \
|
||||
- - SVE_PT_SVE_OFFSET + (SVE_VQ_BYTES - 1)) \
|
||||
- / SVE_VQ_BYTES * SVE_VQ_BYTES)
|
||||
+ - SVE_PT_SVE_OFFSET + (__SVE_VQ_BYTES - 1)) \
|
||||
+ / __SVE_VQ_BYTES * __SVE_VQ_BYTES)
|
||||
|
||||
#define SVE_PT_SIZE(vq, flags) \
|
||||
(((flags) & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE ? \
|
||||
--- a/arch/arm64/include/uapi/asm/sigcontext.h
|
||||
+++ b/arch/arm64/include/uapi/asm/sigcontext.h
|
||||
@@ -130,6 +130,8 @@ struct sve_context {
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
+#include <asm/sve_context.h>
|
||||
+
|
||||
/*
|
||||
* The SVE architecture leaves space for future expansion of the
|
||||
* vector length beyond its initial architectural limit of 2048 bits
|
||||
@@ -138,21 +140,20 @@ struct sve_context {
|
||||
* See linux/Documentation/arm64/sve.txt for a description of the VL/VQ
|
||||
* terminology.
|
||||
*/
|
||||
-#define SVE_VQ_BYTES 16 /* number of bytes per quadword */
|
||||
+#define SVE_VQ_BYTES __SVE_VQ_BYTES /* bytes per quadword */
|
||||
|
||||
-#define SVE_VQ_MIN 1
|
||||
-#define SVE_VQ_MAX 512
|
||||
+#define SVE_VQ_MIN __SVE_VQ_MIN
|
||||
+#define SVE_VQ_MAX __SVE_VQ_MAX
|
||||
|
||||
-#define SVE_VL_MIN (SVE_VQ_MIN * SVE_VQ_BYTES)
|
||||
-#define SVE_VL_MAX (SVE_VQ_MAX * SVE_VQ_BYTES)
|
||||
+#define SVE_VL_MIN __SVE_VL_MIN
|
||||
+#define SVE_VL_MAX __SVE_VL_MAX
|
||||
|
||||
-#define SVE_NUM_ZREGS 32
|
||||
-#define SVE_NUM_PREGS 16
|
||||
+#define SVE_NUM_ZREGS __SVE_NUM_ZREGS
|
||||
+#define SVE_NUM_PREGS __SVE_NUM_PREGS
|
||||
|
||||
-#define sve_vl_valid(vl) \
|
||||
- ((vl) % SVE_VQ_BYTES == 0 && (vl) >= SVE_VL_MIN && (vl) <= SVE_VL_MAX)
|
||||
-#define sve_vq_from_vl(vl) ((vl) / SVE_VQ_BYTES)
|
||||
-#define sve_vl_from_vq(vq) ((vq) * SVE_VQ_BYTES)
|
||||
+#define sve_vl_valid(vl) __sve_vl_valid(vl)
|
||||
+#define sve_vq_from_vl(vl) __sve_vq_from_vl(vl)
|
||||
+#define sve_vl_from_vq(vq) __sve_vl_from_vq(vq)
|
||||
|
||||
/*
|
||||
* If the SVE registers are currently live for the thread at signal delivery,
|
||||
@@ -205,34 +206,33 @@ struct sve_context {
|
||||
* Additional data might be appended in the future.
|
||||
*/
|
||||
|
||||
-#define SVE_SIG_ZREG_SIZE(vq) ((__u32)(vq) * SVE_VQ_BYTES)
|
||||
-#define SVE_SIG_PREG_SIZE(vq) ((__u32)(vq) * (SVE_VQ_BYTES / 8))
|
||||
-#define SVE_SIG_FFR_SIZE(vq) SVE_SIG_PREG_SIZE(vq)
|
||||
+#define SVE_SIG_ZREG_SIZE(vq) __SVE_ZREG_SIZE(vq)
|
||||
+#define SVE_SIG_PREG_SIZE(vq) __SVE_PREG_SIZE(vq)
|
||||
+#define SVE_SIG_FFR_SIZE(vq) __SVE_FFR_SIZE(vq)
|
||||
|
||||
#define SVE_SIG_REGS_OFFSET \
|
||||
- ((sizeof(struct sve_context) + (SVE_VQ_BYTES - 1)) \
|
||||
- / SVE_VQ_BYTES * SVE_VQ_BYTES)
|
||||
+ ((sizeof(struct sve_context) + (__SVE_VQ_BYTES - 1)) \
|
||||
+ / __SVE_VQ_BYTES * __SVE_VQ_BYTES)
|
||||
|
||||
-#define SVE_SIG_ZREGS_OFFSET SVE_SIG_REGS_OFFSET
|
||||
+#define SVE_SIG_ZREGS_OFFSET \
|
||||
+ (SVE_SIG_REGS_OFFSET + __SVE_ZREGS_OFFSET)
|
||||
#define SVE_SIG_ZREG_OFFSET(vq, n) \
|
||||
- (SVE_SIG_ZREGS_OFFSET + SVE_SIG_ZREG_SIZE(vq) * (n))
|
||||
-#define SVE_SIG_ZREGS_SIZE(vq) \
|
||||
- (SVE_SIG_ZREG_OFFSET(vq, SVE_NUM_ZREGS) - SVE_SIG_ZREGS_OFFSET)
|
||||
+ (SVE_SIG_REGS_OFFSET + __SVE_ZREG_OFFSET(vq, n))
|
||||
+#define SVE_SIG_ZREGS_SIZE(vq) __SVE_ZREGS_SIZE(vq)
|
||||
|
||||
#define SVE_SIG_PREGS_OFFSET(vq) \
|
||||
- (SVE_SIG_ZREGS_OFFSET + SVE_SIG_ZREGS_SIZE(vq))
|
||||
+ (SVE_SIG_REGS_OFFSET + __SVE_PREGS_OFFSET(vq))
|
||||
#define SVE_SIG_PREG_OFFSET(vq, n) \
|
||||
- (SVE_SIG_PREGS_OFFSET(vq) + SVE_SIG_PREG_SIZE(vq) * (n))
|
||||
-#define SVE_SIG_PREGS_SIZE(vq) \
|
||||
- (SVE_SIG_PREG_OFFSET(vq, SVE_NUM_PREGS) - SVE_SIG_PREGS_OFFSET(vq))
|
||||
+ (SVE_SIG_REGS_OFFSET + __SVE_PREG_OFFSET(vq, n))
|
||||
+#define SVE_SIG_PREGS_SIZE(vq) __SVE_PREGS_SIZE(vq)
|
||||
|
||||
#define SVE_SIG_FFR_OFFSET(vq) \
|
||||
- (SVE_SIG_PREGS_OFFSET(vq) + SVE_SIG_PREGS_SIZE(vq))
|
||||
+ (SVE_SIG_REGS_OFFSET + __SVE_FFR_OFFSET(vq))
|
||||
|
||||
#define SVE_SIG_REGS_SIZE(vq) \
|
||||
- (SVE_SIG_FFR_OFFSET(vq) + SVE_SIG_FFR_SIZE(vq) - SVE_SIG_REGS_OFFSET)
|
||||
-
|
||||
-#define SVE_SIG_CONTEXT_SIZE(vq) (SVE_SIG_REGS_OFFSET + SVE_SIG_REGS_SIZE(vq))
|
||||
+ (__SVE_FFR_OFFSET(vq) + __SVE_FFR_SIZE(vq))
|
||||
|
||||
+#define SVE_SIG_CONTEXT_SIZE(vq) \
|
||||
+ (SVE_SIG_REGS_OFFSET + SVE_SIG_REGS_SIZE(vq))
|
||||
|
||||
#endif /* _UAPI__ASM_SIGCONTEXT_H */
|
||||
--- /dev/null
|
||||
+++ b/arch/arm64/include/uapi/asm/sve_context.h
|
||||
@@ -0,0 +1,53 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
+/* Copyright (C) 2017-2018 ARM Limited */
|
||||
+
|
||||
+/*
|
||||
+ * For use by other UAPI headers only.
|
||||
+ * Do not make direct use of header or its definitions.
|
||||
+ */
|
||||
+
|
||||
+#ifndef _UAPI__ASM_SVE_CONTEXT_H
|
||||
+#define _UAPI__ASM_SVE_CONTEXT_H
|
||||
+
|
||||
+#include <linux/types.h>
|
||||
+
|
||||
+#define __SVE_VQ_BYTES 16 /* number of bytes per quadword */
|
||||
+
|
||||
+#define __SVE_VQ_MIN 1
|
||||
+#define __SVE_VQ_MAX 512
|
||||
+
|
||||
+#define __SVE_VL_MIN (__SVE_VQ_MIN * __SVE_VQ_BYTES)
|
||||
+#define __SVE_VL_MAX (__SVE_VQ_MAX * __SVE_VQ_BYTES)
|
||||
+
|
||||
+#define __SVE_NUM_ZREGS 32
|
||||
+#define __SVE_NUM_PREGS 16
|
||||
+
|
||||
+#define __sve_vl_valid(vl) \
|
||||
+ ((vl) % __SVE_VQ_BYTES == 0 && \
|
||||
+ (vl) >= __SVE_VL_MIN && \
|
||||
+ (vl) <= __SVE_VL_MAX)
|
||||
+
|
||||
+#define __sve_vq_from_vl(vl) ((vl) / __SVE_VQ_BYTES)
|
||||
+#define __sve_vl_from_vq(vq) ((vq) * __SVE_VQ_BYTES)
|
||||
+
|
||||
+#define __SVE_ZREG_SIZE(vq) ((__u32)(vq) * __SVE_VQ_BYTES)
|
||||
+#define __SVE_PREG_SIZE(vq) ((__u32)(vq) * (__SVE_VQ_BYTES / 8))
|
||||
+#define __SVE_FFR_SIZE(vq) __SVE_PREG_SIZE(vq)
|
||||
+
|
||||
+#define __SVE_ZREGS_OFFSET 0
|
||||
+#define __SVE_ZREG_OFFSET(vq, n) \
|
||||
+ (__SVE_ZREGS_OFFSET + __SVE_ZREG_SIZE(vq) * (n))
|
||||
+#define __SVE_ZREGS_SIZE(vq) \
|
||||
+ (__SVE_ZREG_OFFSET(vq, __SVE_NUM_ZREGS) - __SVE_ZREGS_OFFSET)
|
||||
+
|
||||
+#define __SVE_PREGS_OFFSET(vq) \
|
||||
+ (__SVE_ZREGS_OFFSET + __SVE_ZREGS_SIZE(vq))
|
||||
+#define __SVE_PREG_OFFSET(vq, n) \
|
||||
+ (__SVE_PREGS_OFFSET(vq) + __SVE_PREG_SIZE(vq) * (n))
|
||||
+#define __SVE_PREGS_SIZE(vq) \
|
||||
+ (__SVE_PREG_OFFSET(vq, __SVE_NUM_PREGS) - __SVE_PREGS_OFFSET(vq))
|
||||
+
|
||||
+#define __SVE_FFR_OFFSET(vq) \
|
||||
+ (__SVE_PREGS_OFFSET(vq) + __SVE_PREGS_SIZE(vq))
|
||||
+
|
||||
+#endif /* ! _UAPI__ASM_SVE_CONTEXT_H */
|
@ -1,4 +1,4 @@
|
||||
From 6d8071bbbdcd9d3a2fbb49e55b51617906e3b816 Mon Sep 17 00:00:00 2001
|
||||
From d129a72f465dab2d9fc8f1580c38600a8b808327 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
Date: Wed, 13 Mar 2019 20:54:49 +0000
|
||||
Subject: [PATCH] net: sched: Backport Introduce act_ctinfo action
|
||||
@ -112,9 +112,9 @@ Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
include/uapi/linux/tc_act/tc_ctinfo.h | 29 ++
|
||||
net/sched/Kconfig | 17 +
|
||||
net/sched/Makefile | 1 +
|
||||
net/sched/act_ctinfo.c | 409 ++++++++++++++++++++++
|
||||
net/sched/act_ctinfo.c | 420 ++++++++++++++++++++++
|
||||
tools/testing/selftests/tc-testing/config | 1 +
|
||||
7 files changed, 492 insertions(+), 1 deletion(-)
|
||||
7 files changed, 503 insertions(+), 1 deletion(-)
|
||||
create mode 100644 include/net/tc_act/tc_ctinfo.h
|
||||
create mode 100644 include/uapi/linux/tc_act/tc_ctinfo.h
|
||||
create mode 100644 net/sched/act_ctinfo.c
|
||||
@ -237,7 +237,7 @@ Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
obj-$(CONFIG_NET_IFE_SKBMARK) += act_meta_mark.o
|
||||
--- /dev/null
|
||||
+++ b/net/sched/act_ctinfo.c
|
||||
@@ -0,0 +1,409 @@
|
||||
@@ -0,0 +1,420 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0+
|
||||
+/* net/sched/act_ctinfo.c netfilter ctinfo connmark actions
|
||||
+ *
|
||||
@ -601,6 +601,16 @@ Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
+ return tcf_idr_search(tn, a, index);
|
||||
+}
|
||||
+
|
||||
+static void tcf_ctinfo_cleanup(struct tc_action *a)
|
||||
+{
|
||||
+ struct tcf_ctinfo *ci = to_ctinfo(a);
|
||||
+ struct tcf_ctinfo_params *cp;
|
||||
+
|
||||
+ cp = rcu_dereference_protected(ci->params, 1);
|
||||
+ if (cp)
|
||||
+ kfree_rcu(cp, rcu);
|
||||
+}
|
||||
+
|
||||
+static struct tc_action_ops act_ctinfo_ops = {
|
||||
+ .kind = "ctinfo",
|
||||
+ .type = TCA_ID_CTINFO,
|
||||
@ -609,6 +619,7 @@ Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
+ .dump = tcf_ctinfo_dump,
|
||||
+ .init = tcf_ctinfo_init,
|
||||
+ .walk = tcf_ctinfo_walker,
|
||||
+ .cleanup= tcf_ctinfo_cleanup,
|
||||
+ .lookup = tcf_ctinfo_search,
|
||||
+ .size = sizeof(struct tcf_ctinfo),
|
||||
+};
|
||||
|
@ -0,0 +1,37 @@
|
||||
From 9a4d83074769d6ecf1f5c3fef0f183b09abf3726 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robimarko@gmail.com>
|
||||
Date: Sat, 6 Oct 2018 17:36:42 +0200
|
||||
Subject: [PATCH 1/8] mtd: spinand: winbond: Add support for W25N01GV
|
||||
|
||||
W25N01GV is a single die version of the already supported
|
||||
W25M02GV with half the capacity. Everything else is the
|
||||
same so introduce support for W25N01GV.
|
||||
|
||||
Datasheet:http://www.winbond.com/resource-files/w25n01gv%20revl%20050918%20unsecured.pdf
|
||||
|
||||
Tested on 8devices Jalapeno dev board under OpenWrt running 4.19-rc5.
|
||||
|
||||
Signed-off-by: Robert Marko <robimarko@gmail.com>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
---
|
||||
drivers/mtd/nand/spi/winbond.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/nand/spi/winbond.c
|
||||
+++ b/drivers/mtd/nand/spi/winbond.c
|
||||
@@ -84,6 +84,14 @@ static const struct spinand_info winbond
|
||||
0,
|
||||
SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
|
||||
SPINAND_SELECT_TARGET(w25m02gv_select_target)),
|
||||
+ SPINAND_INFO("W25N01GV", 0xAA,
|
||||
+ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
|
||||
+ NAND_ECCREQ(1, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ 0,
|
||||
+ SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
|
||||
};
|
||||
|
||||
/**
|
@ -0,0 +1,188 @@
|
||||
From 10949af1681d5bb5cdbcc012815c6e40eec17d02 Mon Sep 17 00:00:00 2001
|
||||
From: Schrempf Frieder <frieder.schrempf@kontron.De>
|
||||
Date: Thu, 8 Nov 2018 08:32:11 +0000
|
||||
Subject: [PATCH 2/8] mtd: spinand: Add initial support for Toshiba TC58CVG2S0H
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Add minimal support for the Toshiba TC58CVG2S0H SPI NAND chip.
|
||||
|
||||
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
|
||||
Acked-by: Clément Péron <peron.clem@gmail.com>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
---
|
||||
drivers/mtd/nand/spi/Makefile | 2 +-
|
||||
drivers/mtd/nand/spi/core.c | 1 +
|
||||
drivers/mtd/nand/spi/toshiba.c | 137 +++++++++++++++++++++++++++++++++
|
||||
include/linux/mtd/spinand.h | 1 +
|
||||
4 files changed, 140 insertions(+), 1 deletion(-)
|
||||
create mode 100644 drivers/mtd/nand/spi/toshiba.c
|
||||
|
||||
--- a/drivers/mtd/nand/spi/Makefile
|
||||
+++ b/drivers/mtd/nand/spi/Makefile
|
||||
@@ -1,3 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
-spinand-objs := core.o macronix.o micron.o winbond.o
|
||||
+spinand-objs := core.o macronix.o micron.o toshiba.o winbond.o
|
||||
obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
|
||||
--- a/drivers/mtd/nand/spi/core.c
|
||||
+++ b/drivers/mtd/nand/spi/core.c
|
||||
@@ -764,6 +764,7 @@ static const struct nand_ops spinand_ops
|
||||
static const struct spinand_manufacturer *spinand_manufacturers[] = {
|
||||
¯onix_spinand_manufacturer,
|
||||
µn_spinand_manufacturer,
|
||||
+ &toshiba_spinand_manufacturer,
|
||||
&winbond_spinand_manufacturer,
|
||||
};
|
||||
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/nand/spi/toshiba.c
|
||||
@@ -0,0 +1,137 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright (c) 2018 exceet electronics GmbH
|
||||
+ * Copyright (c) 2018 Kontron Electronics GmbH
|
||||
+ *
|
||||
+ * Author: Frieder Schrempf <frieder.schrempf@kontron.de>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/mtd/spinand.h>
|
||||
+
|
||||
+#define SPINAND_MFR_TOSHIBA 0x98
|
||||
+#define TOSH_STATUS_ECC_HAS_BITFLIPS_T (3 << 4)
|
||||
+
|
||||
+static SPINAND_OP_VARIANTS(read_cache_variants,
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
|
||||
+
|
||||
+static SPINAND_OP_VARIANTS(write_cache_variants,
|
||||
+ SPINAND_PROG_LOAD(true, 0, NULL, 0));
|
||||
+
|
||||
+static SPINAND_OP_VARIANTS(update_cache_variants,
|
||||
+ SPINAND_PROG_LOAD(false, 0, NULL, 0));
|
||||
+
|
||||
+static int tc58cvg2s0h_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
+ struct mtd_oob_region *region)
|
||||
+{
|
||||
+ if (section > 7)
|
||||
+ return -ERANGE;
|
||||
+
|
||||
+ region->offset = 128 + 16 * section;
|
||||
+ region->length = 16;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int tc58cvg2s0h_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
+ struct mtd_oob_region *region)
|
||||
+{
|
||||
+ if (section > 0)
|
||||
+ return -ERANGE;
|
||||
+
|
||||
+ /* 2 bytes reserved for BBM */
|
||||
+ region->offset = 2;
|
||||
+ region->length = 126;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct mtd_ooblayout_ops tc58cvg2s0h_ooblayout = {
|
||||
+ .ecc = tc58cvg2s0h_ooblayout_ecc,
|
||||
+ .free = tc58cvg2s0h_ooblayout_free,
|
||||
+};
|
||||
+
|
||||
+static int tc58cvg2s0h_ecc_get_status(struct spinand_device *spinand,
|
||||
+ u8 status)
|
||||
+{
|
||||
+ struct nand_device *nand = spinand_to_nand(spinand);
|
||||
+ u8 mbf = 0;
|
||||
+ struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf);
|
||||
+
|
||||
+ switch (status & STATUS_ECC_MASK) {
|
||||
+ case STATUS_ECC_NO_BITFLIPS:
|
||||
+ return 0;
|
||||
+
|
||||
+ case STATUS_ECC_UNCOR_ERROR:
|
||||
+ return -EBADMSG;
|
||||
+
|
||||
+ case STATUS_ECC_HAS_BITFLIPS:
|
||||
+ case TOSH_STATUS_ECC_HAS_BITFLIPS_T:
|
||||
+ /*
|
||||
+ * Let's try to retrieve the real maximum number of bitflips
|
||||
+ * in order to avoid forcing the wear-leveling layer to move
|
||||
+ * data around if it's not necessary.
|
||||
+ */
|
||||
+ if (spi_mem_exec_op(spinand->spimem, &op))
|
||||
+ return nand->eccreq.strength;
|
||||
+
|
||||
+ mbf >>= 4;
|
||||
+
|
||||
+ if (WARN_ON(mbf > nand->eccreq.strength || !mbf))
|
||||
+ return nand->eccreq.strength;
|
||||
+
|
||||
+ return mbf;
|
||||
+
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static const struct spinand_info toshiba_spinand_table[] = {
|
||||
+ SPINAND_INFO("TC58CVG2S0H", 0xCD,
|
||||
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&tc58cvg2s0h_ooblayout,
|
||||
+ tc58cvg2s0h_ecc_get_status)),
|
||||
+};
|
||||
+
|
||||
+static int toshiba_spinand_detect(struct spinand_device *spinand)
|
||||
+{
|
||||
+ u8 *id = spinand->id.data;
|
||||
+ int ret;
|
||||
+
|
||||
+ /*
|
||||
+ * Toshiba SPI NAND read ID needs a dummy byte,
|
||||
+ * so the first byte in id is garbage.
|
||||
+ */
|
||||
+ if (id[1] != SPINAND_MFR_TOSHIBA)
|
||||
+ return 0;
|
||||
+
|
||||
+ ret = spinand_match_and_init(spinand, toshiba_spinand_table,
|
||||
+ ARRAY_SIZE(toshiba_spinand_table),
|
||||
+ id[2]);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = {
|
||||
+ .detect = toshiba_spinand_detect,
|
||||
+};
|
||||
+
|
||||
+const struct spinand_manufacturer toshiba_spinand_manufacturer = {
|
||||
+ .id = SPINAND_MFR_TOSHIBA,
|
||||
+ .name = "Toshiba",
|
||||
+ .ops = &toshiba_spinand_manuf_ops,
|
||||
+};
|
||||
--- a/include/linux/mtd/spinand.h
|
||||
+++ b/include/linux/mtd/spinand.h
|
||||
@@ -196,6 +196,7 @@ struct spinand_manufacturer {
|
||||
/* SPI NAND manufacturers */
|
||||
extern const struct spinand_manufacturer macronix_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer micron_spinand_manufacturer;
|
||||
+extern const struct spinand_manufacturer toshiba_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer winbond_spinand_manufacturer;
|
||||
|
||||
/**
|
@ -1,7 +1,7 @@
|
||||
From c93c613214ac70c87beab5422a60077bf126b855 Mon Sep 17 00:00:00 2001
|
||||
From: Chuanhong Guo <gch981213@gmail.com>
|
||||
Date: Wed, 28 Nov 2018 21:07:25 +0800
|
||||
Subject: [PATCH] mtd: spinand: add support for GigaDevice GD5FxGQ4xA
|
||||
Subject: [PATCH 3/8] mtd: spinand: add support for GigaDevice GD5FxGQ4xA
|
||||
|
||||
Add support for GigaDevice GD5F1G/2G/4GQ4xA SPI NAND.
|
||||
|
||||
@ -11,7 +11,7 @@ Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
---
|
||||
drivers/mtd/nand/spi/Makefile | 2 +-
|
||||
drivers/mtd/nand/spi/core.c | 1 +
|
||||
drivers/mtd/nand/spi/gigadevice.c | 148 ++++++++++++++++++++++++++++++++++++++
|
||||
drivers/mtd/nand/spi/gigadevice.c | 148 ++++++++++++++++++++++++++++++
|
||||
include/linux/mtd/spinand.h | 1 +
|
||||
4 files changed, 151 insertions(+), 1 deletion(-)
|
||||
create mode 100644 drivers/mtd/nand/spi/gigadevice.c
|
||||
@ -20,8 +20,8 @@ Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
+++ b/drivers/mtd/nand/spi/Makefile
|
||||
@@ -1,3 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
-spinand-objs := core.o macronix.o micron.o winbond.o
|
||||
+spinand-objs := core.o gigadevice.o macronix.o micron.o winbond.o
|
||||
-spinand-objs := core.o macronix.o micron.o toshiba.o winbond.o
|
||||
+spinand-objs := core.o gigadevice.o macronix.o micron.o toshiba.o winbond.o
|
||||
obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
|
||||
--- a/drivers/mtd/nand/spi/core.c
|
||||
+++ b/drivers/mtd/nand/spi/core.c
|
||||
@ -32,7 +32,7 @@ Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
+ &gigadevice_spinand_manufacturer,
|
||||
¯onix_spinand_manufacturer,
|
||||
µn_spinand_manufacturer,
|
||||
&winbond_spinand_manufacturer,
|
||||
&toshiba_spinand_manufacturer,
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/nand/spi/gigadevice.c
|
||||
@@ -0,0 +1,148 @@
|
||||
@ -193,4 +193,4 @@ Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
+extern const struct spinand_manufacturer gigadevice_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer macronix_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer micron_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer winbond_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer toshiba_spinand_manufacturer;
|
@ -0,0 +1,136 @@
|
||||
From db214513f62fd13c0a9af3bd5c5d634dba37e65d Mon Sep 17 00:00:00 2001
|
||||
From: Yoshio Furuyama <tmcmc-mb-yfuruyama7@ml.toshiba.co.jp>
|
||||
Date: Wed, 16 Jan 2019 14:53:19 +0900
|
||||
Subject: [PATCH 7/8] mtd: spinand: Add support for all Toshiba Memory products
|
||||
|
||||
Add device table for Toshiba Memory products.
|
||||
Also, generalize OOB layout structure and function names.
|
||||
|
||||
Signed-off-by: Yoshio Furuyama <tmcmc-mb-yfuruyama7@ml.toshiba.co.jp>
|
||||
Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
---
|
||||
drivers/mtd/nand/spi/toshiba.c | 79 ++++++++++++++++++++++++++++------
|
||||
1 file changed, 65 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/nand/spi/toshiba.c
|
||||
+++ b/drivers/mtd/nand/spi/toshiba.c
|
||||
@@ -25,19 +25,19 @@ static SPINAND_OP_VARIANTS(write_cache_v
|
||||
static SPINAND_OP_VARIANTS(update_cache_variants,
|
||||
SPINAND_PROG_LOAD(false, 0, NULL, 0));
|
||||
|
||||
-static int tc58cvg2s0h_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
+static int tc58cxgxsx_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
- if (section > 7)
|
||||
+ if (section > 0)
|
||||
return -ERANGE;
|
||||
|
||||
- region->offset = 128 + 16 * section;
|
||||
- region->length = 16;
|
||||
+ region->offset = mtd->oobsize / 2;
|
||||
+ region->length = mtd->oobsize / 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int tc58cvg2s0h_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
+static int tc58cxgxsx_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
if (section > 0)
|
||||
@@ -45,17 +45,17 @@ static int tc58cvg2s0h_ooblayout_free(st
|
||||
|
||||
/* 2 bytes reserved for BBM */
|
||||
region->offset = 2;
|
||||
- region->length = 126;
|
||||
+ region->length = (mtd->oobsize / 2) - 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static const struct mtd_ooblayout_ops tc58cvg2s0h_ooblayout = {
|
||||
- .ecc = tc58cvg2s0h_ooblayout_ecc,
|
||||
- .free = tc58cvg2s0h_ooblayout_free,
|
||||
+static const struct mtd_ooblayout_ops tc58cxgxsx_ooblayout = {
|
||||
+ .ecc = tc58cxgxsx_ooblayout_ecc,
|
||||
+ .free = tc58cxgxsx_ooblayout_free,
|
||||
};
|
||||
|
||||
-static int tc58cvg2s0h_ecc_get_status(struct spinand_device *spinand,
|
||||
+static int tc58cxgxsx_ecc_get_status(struct spinand_device *spinand,
|
||||
u8 status)
|
||||
{
|
||||
struct nand_device *nand = spinand_to_nand(spinand);
|
||||
@@ -94,15 +94,66 @@ static int tc58cvg2s0h_ecc_get_status(st
|
||||
}
|
||||
|
||||
static const struct spinand_info toshiba_spinand_table[] = {
|
||||
- SPINAND_INFO("TC58CVG2S0H", 0xCD,
|
||||
+ /* 3.3V 1Gb */
|
||||
+ SPINAND_INFO("TC58CVG0S3", 0xC2,
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ 0,
|
||||
+ SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
|
||||
+ tc58cxgxsx_ecc_get_status)),
|
||||
+ /* 3.3V 2Gb */
|
||||
+ SPINAND_INFO("TC58CVG1S3", 0xCB,
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ 0,
|
||||
+ SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
|
||||
+ tc58cxgxsx_ecc_get_status)),
|
||||
+ /* 3.3V 4Gb */
|
||||
+ SPINAND_INFO("TC58CVG2S0", 0xCD,
|
||||
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ 0,
|
||||
+ SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
|
||||
+ tc58cxgxsx_ecc_get_status)),
|
||||
+ /* 1.8V 1Gb */
|
||||
+ SPINAND_INFO("TC58CYG0S3", 0xB2,
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ 0,
|
||||
+ SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
|
||||
+ tc58cxgxsx_ecc_get_status)),
|
||||
+ /* 1.8V 2Gb */
|
||||
+ SPINAND_INFO("TC58CYG1S3", 0xBB,
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ 0,
|
||||
+ SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
|
||||
+ tc58cxgxsx_ecc_get_status)),
|
||||
+ /* 1.8V 4Gb */
|
||||
+ SPINAND_INFO("TC58CYG2S0", 0xBD,
|
||||
NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
|
||||
NAND_ECCREQ(8, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
- SPINAND_HAS_QE_BIT,
|
||||
- SPINAND_ECCINFO(&tc58cvg2s0h_ooblayout,
|
||||
- tc58cvg2s0h_ecc_get_status)),
|
||||
+ 0,
|
||||
+ SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
|
||||
+ tc58cxgxsx_ecc_get_status)),
|
||||
};
|
||||
|
||||
static int toshiba_spinand_detect(struct spinand_device *spinand)
|
@ -1,7 +1,7 @@
|
||||
From c40c7a990a46e5102a1cc4190557bf315d32d80d Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Roese <sr@denx.de>
|
||||
Date: Thu, 24 Jan 2019 13:48:06 +0100
|
||||
Subject: [PATCH] mtd: spinand: Add support for GigaDevice GD5F1GQ4UExxG
|
||||
Subject: [PATCH 8/8] mtd: spinand: Add support for GigaDevice GD5F1GQ4UExxG
|
||||
|
||||
Add support for GigaDevice GD5F1GQ4UExxG SPI NAND chip.
|
||||
|
||||
@ -13,7 +13,7 @@ Cc: Boris Brezillon <bbrezillon@kernel.org>
|
||||
Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
---
|
||||
drivers/mtd/nand/spi/gigadevice.c | 83 +++++++++++++++++++++++++++++++++++++++
|
||||
drivers/mtd/nand/spi/gigadevice.c | 83 +++++++++++++++++++++++++++++++
|
||||
1 file changed, 83 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/nand/spi/gigadevice.c
|
@ -0,0 +1,81 @@
|
||||
From d014717d50b1efd011a3a028ce92563a4dc9bae5 Mon Sep 17 00:00:00 2001
|
||||
From: Jeff Kletsky <git-commits@allycomm.com>
|
||||
Date: Wed, 22 May 2019 15:05:53 -0700
|
||||
Subject: [PATCH 1/3] mtd: spinand: Define macros for page-read ops with
|
||||
three-byte addresses
|
||||
|
||||
The GigaDevice GD5F1GQ4UFxxG SPI NAND utilizes three-byte addresses
|
||||
for its page-read ops.
|
||||
|
||||
http://www.gigadevice.com/datasheet/gd5f1gq4xfxxg/
|
||||
|
||||
Signed-off-by: Jeff Kletsky <git-commits@allycomm.com>
|
||||
Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
---
|
||||
include/linux/mtd/spinand.h | 30 ++++++++++++++++++++++++++++++
|
||||
1 file changed, 30 insertions(+)
|
||||
|
||||
--- a/include/linux/mtd/spinand.h
|
||||
+++ b/include/linux/mtd/spinand.h
|
||||
@@ -68,30 +68,60 @@
|
||||
SPI_MEM_OP_DUMMY(ndummy, 1), \
|
||||
SPI_MEM_OP_DATA_IN(len, buf, 1))
|
||||
|
||||
+#define SPINAND_PAGE_READ_FROM_CACHE_OP_3A(fast, addr, ndummy, buf, len) \
|
||||
+ SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1), \
|
||||
+ SPI_MEM_OP_ADDR(3, addr, 1), \
|
||||
+ SPI_MEM_OP_DUMMY(ndummy, 1), \
|
||||
+ SPI_MEM_OP_DATA_IN(len, buf, 1))
|
||||
+
|
||||
#define SPINAND_PAGE_READ_FROM_CACHE_X2_OP(addr, ndummy, buf, len) \
|
||||
SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \
|
||||
SPI_MEM_OP_ADDR(2, addr, 1), \
|
||||
SPI_MEM_OP_DUMMY(ndummy, 1), \
|
||||
SPI_MEM_OP_DATA_IN(len, buf, 2))
|
||||
|
||||
+#define SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(addr, ndummy, buf, len) \
|
||||
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \
|
||||
+ SPI_MEM_OP_ADDR(3, addr, 1), \
|
||||
+ SPI_MEM_OP_DUMMY(ndummy, 1), \
|
||||
+ SPI_MEM_OP_DATA_IN(len, buf, 2))
|
||||
+
|
||||
#define SPINAND_PAGE_READ_FROM_CACHE_X4_OP(addr, ndummy, buf, len) \
|
||||
SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \
|
||||
SPI_MEM_OP_ADDR(2, addr, 1), \
|
||||
SPI_MEM_OP_DUMMY(ndummy, 1), \
|
||||
SPI_MEM_OP_DATA_IN(len, buf, 4))
|
||||
|
||||
+#define SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(addr, ndummy, buf, len) \
|
||||
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \
|
||||
+ SPI_MEM_OP_ADDR(3, addr, 1), \
|
||||
+ SPI_MEM_OP_DUMMY(ndummy, 1), \
|
||||
+ SPI_MEM_OP_DATA_IN(len, buf, 4))
|
||||
+
|
||||
#define SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(addr, ndummy, buf, len) \
|
||||
SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \
|
||||
SPI_MEM_OP_ADDR(2, addr, 2), \
|
||||
SPI_MEM_OP_DUMMY(ndummy, 2), \
|
||||
SPI_MEM_OP_DATA_IN(len, buf, 2))
|
||||
|
||||
+#define SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP_3A(addr, ndummy, buf, len) \
|
||||
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \
|
||||
+ SPI_MEM_OP_ADDR(3, addr, 2), \
|
||||
+ SPI_MEM_OP_DUMMY(ndummy, 2), \
|
||||
+ SPI_MEM_OP_DATA_IN(len, buf, 2))
|
||||
+
|
||||
#define SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(addr, ndummy, buf, len) \
|
||||
SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1), \
|
||||
SPI_MEM_OP_ADDR(2, addr, 4), \
|
||||
SPI_MEM_OP_DUMMY(ndummy, 4), \
|
||||
SPI_MEM_OP_DATA_IN(len, buf, 4))
|
||||
|
||||
+#define SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP_3A(addr, ndummy, buf, len) \
|
||||
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1), \
|
||||
+ SPI_MEM_OP_ADDR(3, addr, 4), \
|
||||
+ SPI_MEM_OP_DUMMY(ndummy, 4), \
|
||||
+ SPI_MEM_OP_DATA_IN(len, buf, 4))
|
||||
+
|
||||
#define SPINAND_PROG_EXEC_OP(addr) \
|
||||
SPI_MEM_OP(SPI_MEM_OP_CMD(0x10, 1), \
|
||||
SPI_MEM_OP_ADDR(3, addr, 1), \
|
@ -0,0 +1,48 @@
|
||||
From 53dd94a79d3bfdaae30e5a4ebf474ea1af1d572e Mon Sep 17 00:00:00 2001
|
||||
From: Jeff Kletsky <git-commits@allycomm.com>
|
||||
Date: Wed, 22 May 2019 15:05:54 -0700
|
||||
Subject: [PATCH 2/3] mtd: spinand: Add support for two-byte device IDs
|
||||
|
||||
The GigaDevice GD5F1GQ4UFxxG SPI NAND utilizes two-byte device IDs.
|
||||
|
||||
http://www.gigadevice.com/datasheet/gd5f1gq4xfxxg/
|
||||
|
||||
Signed-off-by: Jeff Kletsky <git-commits@allycomm.com>
|
||||
Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
---
|
||||
drivers/mtd/nand/spi/core.c | 2 +-
|
||||
include/linux/mtd/spinand.h | 4 ++--
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/nand/spi/core.c
|
||||
+++ b/drivers/mtd/nand/spi/core.c
|
||||
@@ -853,7 +853,7 @@ spinand_select_op_variant(struct spinand
|
||||
*/
|
||||
int spinand_match_and_init(struct spinand_device *spinand,
|
||||
const struct spinand_info *table,
|
||||
- unsigned int table_size, u8 devid)
|
||||
+ unsigned int table_size, u16 devid)
|
||||
{
|
||||
struct nand_device *nand = spinand_to_nand(spinand);
|
||||
unsigned int i;
|
||||
--- a/include/linux/mtd/spinand.h
|
||||
+++ b/include/linux/mtd/spinand.h
|
||||
@@ -290,7 +290,7 @@ struct spinand_ecc_info {
|
||||
*/
|
||||
struct spinand_info {
|
||||
const char *model;
|
||||
- u8 devid;
|
||||
+ u16 devid;
|
||||
u32 flags;
|
||||
struct nand_memory_organization memorg;
|
||||
struct nand_ecc_req eccreq;
|
||||
@@ -445,7 +445,7 @@ static inline void spinand_set_of_node(s
|
||||
|
||||
int spinand_match_and_init(struct spinand_device *dev,
|
||||
const struct spinand_info *table,
|
||||
- unsigned int table_size, u8 devid);
|
||||
+ unsigned int table_size, u16 devid);
|
||||
|
||||
int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val);
|
||||
int spinand_select_target(struct spinand_device *spinand, unsigned int target);
|
@ -0,0 +1,197 @@
|
||||
|
||||
IMPORTANT NOTE
|
||||
==============
|
||||
|
||||
The content of this patch has been adapted for Linux 4.19
|
||||
|
||||
Changes were made in Linux 5.x to add the bad-block limit
|
||||
to the metadata available to the driver, adding a parameter
|
||||
|
||||
NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
|
||||
^- New bad-block limit
|
||||
|
||||
This patch omits that parameter from the upstream patch
|
||||
for compatibility with the Linux 4.19 driver.
|
||||
|
||||
=====
|
||||
|
||||
From 049df13c4e63884fe6634db5568e08f65922256e Mon Sep 17 00:00:00 2001
|
||||
From: Jeff Kletsky <git-commits@allycomm.com>
|
||||
Date: Wed, 22 May 2019 15:05:55 -0700
|
||||
Subject: [PATCH 3/3] mtd: spinand: Add support for GigaDevice GD5F1GQ4UFxxG
|
||||
|
||||
The GigaDevice GD5F1GQ4UFxxG SPI NAND is in current production devices
|
||||
and, while it has the same logical layout as the E-series devices,
|
||||
it differs in the SPI interfacing in significant ways.
|
||||
|
||||
This support is contingent on previous commits to:
|
||||
|
||||
* Add support for two-byte device IDs
|
||||
* Define macros for page-read ops with three-byte addresses
|
||||
|
||||
http://www.gigadevice.com/datasheet/gd5f1gq4xfxxg/
|
||||
|
||||
Signed-off-by: Jeff Kletsky <git-commits@allycomm.com>
|
||||
Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
---
|
||||
drivers/mtd/nand/spi/gigadevice.c | 79 +++++++++++++++++++++++++------
|
||||
1 file changed, 64 insertions(+), 15 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/nand/spi/gigadevice.c
|
||||
+++ b/drivers/mtd/nand/spi/gigadevice.c
|
||||
@@ -9,11 +9,17 @@
|
||||
#include <linux/mtd/spinand.h>
|
||||
|
||||
#define SPINAND_MFR_GIGADEVICE 0xC8
|
||||
+
|
||||
#define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS (1 << 4)
|
||||
#define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS (3 << 4)
|
||||
|
||||
#define GD5FXGQ4UEXXG_REG_STATUS2 0xf0
|
||||
|
||||
+#define GD5FXGQ4UXFXXG_STATUS_ECC_MASK (7 << 4)
|
||||
+#define GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS (0 << 4)
|
||||
+#define GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS (1 << 4)
|
||||
+#define GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR (7 << 4)
|
||||
+
|
||||
static SPINAND_OP_VARIANTS(read_cache_variants,
|
||||
SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
|
||||
SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
|
||||
@@ -22,6 +28,14 @@ static SPINAND_OP_VARIANTS(read_cache_va
|
||||
SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
|
||||
SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
|
||||
|
||||
+static SPINAND_OP_VARIANTS(read_cache_variants_f,
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_OP_3A(true, 0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_OP_3A(false, 0, 0, NULL, 0));
|
||||
+
|
||||
static SPINAND_OP_VARIANTS(write_cache_variants,
|
||||
SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
|
||||
SPINAND_PROG_LOAD(true, 0, NULL, 0));
|
||||
@@ -59,6 +73,11 @@ static int gd5fxgq4xa_ooblayout_free(str
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = {
|
||||
+ .ecc = gd5fxgq4xa_ooblayout_ecc,
|
||||
+ .free = gd5fxgq4xa_ooblayout_free,
|
||||
+};
|
||||
+
|
||||
static int gd5fxgq4xa_ecc_get_status(struct spinand_device *spinand,
|
||||
u8 status)
|
||||
{
|
||||
@@ -83,7 +102,7 @@ static int gd5fxgq4xa_ecc_get_status(str
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
-static int gd5fxgq4uexxg_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
+static int gd5fxgq4_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
if (section)
|
||||
@@ -95,7 +114,7 @@ static int gd5fxgq4uexxg_ooblayout_ecc(s
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int gd5fxgq4uexxg_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
+static int gd5fxgq4_variant2_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
if (section)
|
||||
@@ -108,6 +127,11 @@ static int gd5fxgq4uexxg_ooblayout_free(
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static const struct mtd_ooblayout_ops gd5fxgq4_variant2_ooblayout = {
|
||||
+ .ecc = gd5fxgq4_variant2_ooblayout_ecc,
|
||||
+ .free = gd5fxgq4_variant2_ooblayout_free,
|
||||
+};
|
||||
+
|
||||
static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
|
||||
u8 status)
|
||||
{
|
||||
@@ -150,15 +174,25 @@ static int gd5fxgq4uexxg_ecc_get_status(
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
-static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = {
|
||||
- .ecc = gd5fxgq4xa_ooblayout_ecc,
|
||||
- .free = gd5fxgq4xa_ooblayout_free,
|
||||
-};
|
||||
+static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand,
|
||||
+ u8 status)
|
||||
+{
|
||||
+ switch (status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) {
|
||||
+ case GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS:
|
||||
+ return 0;
|
||||
|
||||
-static const struct mtd_ooblayout_ops gd5fxgq4uexxg_ooblayout = {
|
||||
- .ecc = gd5fxgq4uexxg_ooblayout_ecc,
|
||||
- .free = gd5fxgq4uexxg_ooblayout_free,
|
||||
-};
|
||||
+ case GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS:
|
||||
+ return 3;
|
||||
+
|
||||
+ case GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR:
|
||||
+ return -EBADMSG;
|
||||
+
|
||||
+ default: /* (2 << 4) through (6 << 4) are 4-8 corrected errors */
|
||||
+ return ((status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) >> 4) + 2;
|
||||
+ }
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
|
||||
static const struct spinand_info gigadevice_spinand_table[] = {
|
||||
SPINAND_INFO("GD5F1GQ4xA", 0xF1,
|
||||
@@ -195,25 +229,40 @@ static const struct spinand_info gigadev
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
0,
|
||||
- SPINAND_ECCINFO(&gd5fxgq4uexxg_ooblayout,
|
||||
+ SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
|
||||
gd5fxgq4uexxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F1GQ4UFxxG", 0xb148,
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ 0,
|
||||
+ SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
|
||||
+ gd5fxgq4ufxxg_ecc_get_status)),
|
||||
};
|
||||
|
||||
static int gigadevice_spinand_detect(struct spinand_device *spinand)
|
||||
{
|
||||
u8 *id = spinand->id.data;
|
||||
+ u16 did;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
- * For GD NANDs, There is an address byte needed to shift in before IDs
|
||||
- * are read out, so the first byte in raw_id is dummy.
|
||||
+ * Earlier GDF5-series devices (A,E) return [0][MID][DID]
|
||||
+ * Later (F) devices return [MID][DID1][DID2]
|
||||
*/
|
||||
- if (id[1] != SPINAND_MFR_GIGADEVICE)
|
||||
+
|
||||
+ if (id[0] == SPINAND_MFR_GIGADEVICE)
|
||||
+ did = (id[1] << 8) + id[2];
|
||||
+ else if (id[0] == 0 && id[1] == SPINAND_MFR_GIGADEVICE)
|
||||
+ did = id[2];
|
||||
+ else
|
||||
return 0;
|
||||
|
||||
ret = spinand_match_and_init(spinand, gigadevice_spinand_table,
|
||||
ARRAY_SIZE(gigadevice_spinand_table),
|
||||
- id[2]);
|
||||
+ did);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -0,0 +1,203 @@
|
||||
From 3552691616c940a7c4125c2678ba816653cd725e Mon Sep 17 00:00:00 2001
|
||||
From: Jeff Kletsky <git-commits@allycomm.com>
|
||||
Date: Tue, 18 Jun 2019 10:08:05 -0700
|
||||
Subject: [PATCH] mtd: spinand: Add initial support for Paragon PN26G0xA
|
||||
|
||||
Add initial support for Paragon Technology
|
||||
PN26G01Axxxxx and PN26G02Axxxxx SPI NAND
|
||||
|
||||
Datasheets available at
|
||||
http://www.xtxtech.com/upfile/2016082517274590.pdf
|
||||
http://www.xtxtech.com/upfile/2016082517282329.pdf
|
||||
|
||||
Signed-off-by: Jeff Kletsky <git-commits@allycomm.com>
|
||||
Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
|
||||
ADOPTED FROM UPSTREAM due to upstream commit 377e517b5fa5 in Linux 5.2
|
||||
which added another parameter to NAND_MEMORG
|
||||
---
|
||||
drivers/mtd/nand/spi/Makefile | 2 +-
|
||||
drivers/mtd/nand/spi/core.c | 1 +
|
||||
drivers/mtd/nand/spi/paragon.c | 147 +++++++++++++++++++++++++++++++++
|
||||
include/linux/mtd/spinand.h | 1 +
|
||||
4 files changed, 150 insertions(+), 1 deletion(-)
|
||||
create mode 100644 drivers/mtd/nand/spi/paragon.c
|
||||
|
||||
--- a/drivers/mtd/nand/spi/Makefile
|
||||
+++ b/drivers/mtd/nand/spi/Makefile
|
||||
@@ -1,3 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
-spinand-objs := core.o gigadevice.o macronix.o micron.o toshiba.o winbond.o
|
||||
+spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o
|
||||
obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
|
||||
--- a/drivers/mtd/nand/spi/core.c
|
||||
+++ b/drivers/mtd/nand/spi/core.c
|
||||
@@ -765,6 +765,7 @@ static const struct spinand_manufacturer
|
||||
&gigadevice_spinand_manufacturer,
|
||||
¯onix_spinand_manufacturer,
|
||||
µn_spinand_manufacturer,
|
||||
+ ¶gon_spinand_manufacturer,
|
||||
&toshiba_spinand_manufacturer,
|
||||
&winbond_spinand_manufacturer,
|
||||
};
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/nand/spi/paragon.c
|
||||
@@ -0,0 +1,147 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright (C) 2019 Jeff Kletsky
|
||||
+ *
|
||||
+ * Author: Jeff Kletsky <git-commits@allycomm.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/mtd/spinand.h>
|
||||
+
|
||||
+
|
||||
+#define SPINAND_MFR_PARAGON 0xa1
|
||||
+
|
||||
+
|
||||
+#define PN26G0XA_STATUS_ECC_BITMASK (3 << 4)
|
||||
+
|
||||
+#define PN26G0XA_STATUS_ECC_NONE_DETECTED (0 << 4)
|
||||
+#define PN26G0XA_STATUS_ECC_1_7_CORRECTED (1 << 4)
|
||||
+#define PN26G0XA_STATUS_ECC_ERRORED (2 << 4)
|
||||
+#define PN26G0XA_STATUS_ECC_8_CORRECTED (3 << 4)
|
||||
+
|
||||
+
|
||||
+static SPINAND_OP_VARIANTS(read_cache_variants,
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
|
||||
+
|
||||
+static SPINAND_OP_VARIANTS(write_cache_variants,
|
||||
+ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
|
||||
+ SPINAND_PROG_LOAD(true, 0, NULL, 0));
|
||||
+
|
||||
+static SPINAND_OP_VARIANTS(update_cache_variants,
|
||||
+ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
|
||||
+ SPINAND_PROG_LOAD(false, 0, NULL, 0));
|
||||
+
|
||||
+
|
||||
+static int pn26g0xa_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
+ struct mtd_oob_region *region)
|
||||
+{
|
||||
+ if (section > 3)
|
||||
+ return -ERANGE;
|
||||
+
|
||||
+ region->offset = 6 + (15 * section); /* 4 BBM + 2 user bytes */
|
||||
+ region->length = 13;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int pn26g0xa_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
+ struct mtd_oob_region *region)
|
||||
+{
|
||||
+ if (section > 4)
|
||||
+ return -ERANGE;
|
||||
+
|
||||
+ if (section == 4) {
|
||||
+ region->offset = 64;
|
||||
+ region->length = 64;
|
||||
+ } else {
|
||||
+ region->offset = 4 + (15 * section);
|
||||
+ region->length = 2;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int pn26g0xa_ecc_get_status(struct spinand_device *spinand,
|
||||
+ u8 status)
|
||||
+{
|
||||
+ switch (status & PN26G0XA_STATUS_ECC_BITMASK) {
|
||||
+ case PN26G0XA_STATUS_ECC_NONE_DETECTED:
|
||||
+ return 0;
|
||||
+
|
||||
+ case PN26G0XA_STATUS_ECC_1_7_CORRECTED:
|
||||
+ return 7; /* Return upper limit by convention */
|
||||
+
|
||||
+ case PN26G0XA_STATUS_ECC_8_CORRECTED:
|
||||
+ return 8;
|
||||
+
|
||||
+ case PN26G0XA_STATUS_ECC_ERRORED:
|
||||
+ return -EBADMSG;
|
||||
+
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static const struct mtd_ooblayout_ops pn26g0xa_ooblayout = {
|
||||
+ .ecc = pn26g0xa_ooblayout_ecc,
|
||||
+ .free = pn26g0xa_ooblayout_free,
|
||||
+};
|
||||
+
|
||||
+
|
||||
+static const struct spinand_info paragon_spinand_table[] = {
|
||||
+ SPINAND_INFO("PN26G01A", 0xe1,
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ 0,
|
||||
+ SPINAND_ECCINFO(&pn26g0xa_ooblayout,
|
||||
+ pn26g0xa_ecc_get_status)),
|
||||
+ SPINAND_INFO("PN26G02A", 0xe2,
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ 0,
|
||||
+ SPINAND_ECCINFO(&pn26g0xa_ooblayout,
|
||||
+ pn26g0xa_ecc_get_status)),
|
||||
+};
|
||||
+
|
||||
+static int paragon_spinand_detect(struct spinand_device *spinand)
|
||||
+{
|
||||
+ u8 *id = spinand->id.data;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Read ID returns [0][MID][DID] */
|
||||
+
|
||||
+ if (id[1] != SPINAND_MFR_PARAGON)
|
||||
+ return 0;
|
||||
+
|
||||
+ ret = spinand_match_and_init(spinand, paragon_spinand_table,
|
||||
+ ARRAY_SIZE(paragon_spinand_table),
|
||||
+ id[2]);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static const struct spinand_manufacturer_ops paragon_spinand_manuf_ops = {
|
||||
+ .detect = paragon_spinand_detect,
|
||||
+};
|
||||
+
|
||||
+const struct spinand_manufacturer paragon_spinand_manufacturer = {
|
||||
+ .id = SPINAND_MFR_PARAGON,
|
||||
+ .name = "Paragon",
|
||||
+ .ops = ¶gon_spinand_manuf_ops,
|
||||
+};
|
||||
--- a/include/linux/mtd/spinand.h
|
||||
+++ b/include/linux/mtd/spinand.h
|
||||
@@ -227,6 +227,7 @@ struct spinand_manufacturer {
|
||||
extern const struct spinand_manufacturer gigadevice_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer macronix_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer micron_spinand_manufacturer;
|
||||
+extern const struct spinand_manufacturer paragon_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer toshiba_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer winbond_spinand_manufacturer;
|
||||
|
@ -0,0 +1,49 @@
|
||||
From 1da223db3a0c522300b519ecbe1dc45927e28088 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Lunn <andrew@lunn.ch>
|
||||
Date: Wed, 12 Sep 2018 01:53:15 +0200
|
||||
Subject: [PATCH 600/660] net: ethernet: Add helper for MACs which support asym
|
||||
pause
|
||||
|
||||
Rather than have the MAC drivers manipulate phydev members to indicate
|
||||
they support Asym Pause, add a helper function.
|
||||
|
||||
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/phy_device.c | 13 +++++++++++++
|
||||
include/linux/phy.h | 1 +
|
||||
2 files changed, 14 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/phy_device.c
|
||||
+++ b/drivers/net/phy/phy_device.c
|
||||
@@ -1776,6 +1776,19 @@ int phy_set_max_speed(struct phy_device
|
||||
}
|
||||
EXPORT_SYMBOL(phy_set_max_speed);
|
||||
|
||||
+/**
|
||||
+ * phy_support_asym_pause - Enable support of asym pause
|
||||
+ * @phydev: target phy_device struct
|
||||
+ *
|
||||
+ * Description: Called by the MAC to indicate is supports Asym Pause.
|
||||
+ */
|
||||
+void phy_support_asym_pause(struct phy_device *phydev)
|
||||
+{
|
||||
+ phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
|
||||
+ phydev->advertising = phydev->supported;
|
||||
+}
|
||||
+EXPORT_SYMBOL(phy_support_asym_pause);
|
||||
+
|
||||
static void of_set_phy_supported(struct phy_device *phydev)
|
||||
{
|
||||
struct device_node *node = phydev->mdio.dev.of_node;
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -1049,6 +1049,7 @@ int phy_mii_ioctl(struct phy_device *phy
|
||||
int phy_start_interrupts(struct phy_device *phydev);
|
||||
void phy_print_status(struct phy_device *phydev);
|
||||
int phy_set_max_speed(struct phy_device *phydev, u32 max_speed);
|
||||
+void phy_support_asym_pause(struct phy_device *phydev);
|
||||
|
||||
int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
|
||||
int (*run)(struct phy_device *));
|
@ -0,0 +1,66 @@
|
||||
From ce825df56e0480a2cbb296e38976babafb57e503 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Lunn <andrew@lunn.ch>
|
||||
Date: Wed, 12 Sep 2018 01:53:17 +0200
|
||||
Subject: [PATCH 601/660] net: ethernet: Add helper for set_pauseparam for Asym
|
||||
Pause
|
||||
|
||||
ethtool can be used to enable/disable pause. Add a helper to configure
|
||||
the PHY when asym pause is supported.
|
||||
|
||||
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/phy_device.c | 30 ++++++++++++++++++++++++++++++
|
||||
include/linux/phy.h | 1 +
|
||||
2 files changed, 31 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/phy_device.c
|
||||
+++ b/drivers/net/phy/phy_device.c
|
||||
@@ -1789,6 +1789,36 @@ void phy_support_asym_pause(struct phy_d
|
||||
}
|
||||
EXPORT_SYMBOL(phy_support_asym_pause);
|
||||
|
||||
+/**
|
||||
+ * phy_set_asym_pause - Configure Pause and Asym Pause
|
||||
+ * @phydev: target phy_device struct
|
||||
+ * @rx: Receiver Pause is supported
|
||||
+ * @tx: Transmit Pause is supported
|
||||
+ *
|
||||
+ * Description: Configure advertised Pause support depending on if
|
||||
+ * transmit and receiver pause is supported. If there has been a
|
||||
+ * change in adverting, trigger a new autoneg. Generally called from
|
||||
+ * the set_pauseparam .ndo.
|
||||
+ */
|
||||
+void phy_set_asym_pause(struct phy_device *phydev, bool rx, bool tx)
|
||||
+{
|
||||
+ u16 oldadv = phydev->advertising;
|
||||
+ u16 newadv = oldadv &= ~(SUPPORTED_Pause | SUPPORTED_Asym_Pause);
|
||||
+
|
||||
+ if (rx)
|
||||
+ newadv |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
|
||||
+ if (tx)
|
||||
+ newadv ^= SUPPORTED_Asym_Pause;
|
||||
+
|
||||
+ if (oldadv != newadv) {
|
||||
+ phydev->advertising = newadv;
|
||||
+
|
||||
+ if (phydev->autoneg)
|
||||
+ phy_start_aneg(phydev);
|
||||
+ }
|
||||
+}
|
||||
+EXPORT_SYMBOL(phy_set_asym_pause);
|
||||
+
|
||||
static void of_set_phy_supported(struct phy_device *phydev)
|
||||
{
|
||||
struct device_node *node = phydev->mdio.dev.of_node;
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -1050,6 +1050,7 @@ int phy_start_interrupts(struct phy_devi
|
||||
void phy_print_status(struct phy_device *phydev);
|
||||
int phy_set_max_speed(struct phy_device *phydev, u32 max_speed);
|
||||
void phy_support_asym_pause(struct phy_device *phydev);
|
||||
+void phy_set_asym_pause(struct phy_device *phydev, bool rx, bool tx);
|
||||
|
||||
int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
|
||||
int (*run)(struct phy_device *));
|
@ -0,0 +1,40 @@
|
||||
From 1541649a9dd79e9b941d399de564475e426a2d0b Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Date: Tue, 25 Sep 2018 11:28:45 -0700
|
||||
Subject: [PATCH 602/660] net: phy: Stop with excessive soft reset
|
||||
|
||||
While consolidating the PHY reset in phy_init_hw() an unconditionaly
|
||||
BMCR soft-reset I became quite trigger happy with those. This was later
|
||||
on deactivated for the Generic PHY driver on the premise that a prior
|
||||
software entity (e.g: bootloader) might have applied workarounds in
|
||||
commit 0878fff1f42c ("net: phy: Do not perform software reset for
|
||||
Generic PHY").
|
||||
|
||||
Since we have a hook to wire-up a soft_reset callback, just use that and
|
||||
get rid of the call to genphy_soft_reset() entirely. This speeds up
|
||||
initialization and link establishment for most PHYs out there that do
|
||||
not require a reset.
|
||||
|
||||
Fixes: 87aa9f9c61ad ("net: phy: consolidate PHY reset in phy_init_hw()")
|
||||
Tested-by: Wang, Dongsheng <dongsheng.wang@hxt-semitech.com>
|
||||
Tested-by: Chris Healy <cphealy@gmail.com>
|
||||
Tested-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Tested-by: Clemens Gruber <clemens.gruber@pqgruber.com>
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/phy_device.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phy_device.c
|
||||
+++ b/drivers/net/phy/phy_device.c
|
||||
@@ -885,8 +885,6 @@ int phy_init_hw(struct phy_device *phyde
|
||||
|
||||
if (phydev->drv->soft_reset)
|
||||
ret = phydev->drv->soft_reset(phydev);
|
||||
- else
|
||||
- ret = genphy_soft_reset(phydev);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
@ -0,0 +1,375 @@
|
||||
From 80758d9542205cd2e9fa730067bc3888d4f5a096 Mon Sep 17 00:00:00 2001
|
||||
From: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
|
||||
Date: Wed, 6 Feb 2019 07:36:40 +0100
|
||||
Subject: [PATCH 603/660] net: phy: provide full set of accessor functions to
|
||||
MMD registers
|
||||
|
||||
This adds full set of locked and unlocked accessor functions to read and
|
||||
write PHY MMD registers and/or bitfields.
|
||||
|
||||
Set of functions exactly matches what is already available for PHY
|
||||
legacy registers.
|
||||
|
||||
Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
|
||||
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/phy-core.c | 116 ++++++++++++++++++++++++++++----
|
||||
include/linux/phy.h | 134 ++++++++++++++++++++++++++++++-------
|
||||
2 files changed, 214 insertions(+), 36 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phy-core.c
|
||||
+++ b/drivers/net/phy/phy-core.c
|
||||
@@ -247,15 +247,15 @@ static void mmd_phy_indirect(struct mii_
|
||||
}
|
||||
|
||||
/**
|
||||
- * phy_read_mmd - Convenience function for reading a register
|
||||
+ * __phy_read_mmd - Convenience function for reading a register
|
||||
* from an MMD on a given PHY.
|
||||
* @phydev: The phy_device struct
|
||||
* @devad: The MMD to read from (0..31)
|
||||
* @regnum: The register on the MMD to read (0..65535)
|
||||
*
|
||||
- * Same rules as for phy_read();
|
||||
+ * Same rules as for __phy_read();
|
||||
*/
|
||||
-int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
|
||||
+int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
|
||||
{
|
||||
int val;
|
||||
|
||||
@@ -267,33 +267,52 @@ int phy_read_mmd(struct phy_device *phyd
|
||||
} else if (phydev->is_c45) {
|
||||
u32 addr = MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff);
|
||||
|
||||
- val = mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, addr);
|
||||
+ val = __mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, addr);
|
||||
} else {
|
||||
struct mii_bus *bus = phydev->mdio.bus;
|
||||
int phy_addr = phydev->mdio.addr;
|
||||
|
||||
- mutex_lock(&bus->mdio_lock);
|
||||
mmd_phy_indirect(bus, phy_addr, devad, regnum);
|
||||
|
||||
/* Read the content of the MMD's selected register */
|
||||
val = __mdiobus_read(bus, phy_addr, MII_MMD_DATA);
|
||||
- mutex_unlock(&bus->mdio_lock);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
+EXPORT_SYMBOL(__phy_read_mmd);
|
||||
+
|
||||
+/**
|
||||
+ * phy_read_mmd - Convenience function for reading a register
|
||||
+ * from an MMD on a given PHY.
|
||||
+ * @phydev: The phy_device struct
|
||||
+ * @devad: The MMD to read from
|
||||
+ * @regnum: The register on the MMD to read
|
||||
+ *
|
||||
+ * Same rules as for phy_read();
|
||||
+ */
|
||||
+int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ mutex_lock(&phydev->mdio.bus->mdio_lock);
|
||||
+ ret = __phy_read_mmd(phydev, devad, regnum);
|
||||
+ mutex_unlock(&phydev->mdio.bus->mdio_lock);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
EXPORT_SYMBOL(phy_read_mmd);
|
||||
|
||||
/**
|
||||
- * phy_write_mmd - Convenience function for writing a register
|
||||
+ * __phy_write_mmd - Convenience function for writing a register
|
||||
* on an MMD on a given PHY.
|
||||
* @phydev: The phy_device struct
|
||||
* @devad: The MMD to read from
|
||||
* @regnum: The register on the MMD to read
|
||||
* @val: value to write to @regnum
|
||||
*
|
||||
- * Same rules as for phy_write();
|
||||
+ * Same rules as for __phy_write();
|
||||
*/
|
||||
-int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
|
||||
+int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -305,23 +324,43 @@ int phy_write_mmd(struct phy_device *phy
|
||||
} else if (phydev->is_c45) {
|
||||
u32 addr = MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff);
|
||||
|
||||
- ret = mdiobus_write(phydev->mdio.bus, phydev->mdio.addr,
|
||||
- addr, val);
|
||||
+ ret = __mdiobus_write(phydev->mdio.bus, phydev->mdio.addr,
|
||||
+ addr, val);
|
||||
} else {
|
||||
struct mii_bus *bus = phydev->mdio.bus;
|
||||
int phy_addr = phydev->mdio.addr;
|
||||
|
||||
- mutex_lock(&bus->mdio_lock);
|
||||
mmd_phy_indirect(bus, phy_addr, devad, regnum);
|
||||
|
||||
/* Write the data into MMD's selected register */
|
||||
__mdiobus_write(bus, phy_addr, MII_MMD_DATA, val);
|
||||
- mutex_unlock(&bus->mdio_lock);
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
+EXPORT_SYMBOL(__phy_write_mmd);
|
||||
+
|
||||
+/**
|
||||
+ * phy_write_mmd - Convenience function for writing a register
|
||||
+ * on an MMD on a given PHY.
|
||||
+ * @phydev: The phy_device struct
|
||||
+ * @devad: The MMD to read from
|
||||
+ * @regnum: The register on the MMD to read
|
||||
+ * @val: value to write to @regnum
|
||||
+ *
|
||||
+ * Same rules as for phy_write();
|
||||
+ */
|
||||
+int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ mutex_lock(&phydev->mdio.bus->mdio_lock);
|
||||
+ ret = __phy_write_mmd(phydev, devad, regnum, val);
|
||||
+ mutex_unlock(&phydev->mdio.bus->mdio_lock);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
EXPORT_SYMBOL(phy_write_mmd);
|
||||
|
||||
/**
|
||||
@@ -371,6 +410,57 @@ int phy_modify(struct phy_device *phydev
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phy_modify);
|
||||
|
||||
+/**
|
||||
+ * __phy_modify_mmd - Convenience function for modifying a register on MMD
|
||||
+ * @phydev: the phy_device struct
|
||||
+ * @devad: the MMD containing register to modify
|
||||
+ * @regnum: register number to modify
|
||||
+ * @mask: bit mask of bits to clear
|
||||
+ * @set: new value of bits set in mask to write to @regnum
|
||||
+ *
|
||||
+ * Unlocked helper function which allows a MMD register to be modified as
|
||||
+ * new register value = (old register value & ~mask) | set
|
||||
+ */
|
||||
+int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
|
||||
+ u16 mask, u16 set)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = __phy_read_mmd(phydev, devad, regnum);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = __phy_write_mmd(phydev, devad, regnum, (ret & ~mask) | set);
|
||||
+
|
||||
+ return ret < 0 ? ret : 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(__phy_modify_mmd);
|
||||
+
|
||||
+/**
|
||||
+ * phy_modify_mmd - Convenience function for modifying a register on MMD
|
||||
+ * @phydev: the phy_device struct
|
||||
+ * @devad: the MMD containing register to modify
|
||||
+ * @regnum: register number to modify
|
||||
+ * @mask: bit mask of bits to clear
|
||||
+ * @set: new value of bits set in mask to write to @regnum
|
||||
+ *
|
||||
+ * NOTE: MUST NOT be called from interrupt context,
|
||||
+ * because the bus read/write functions may wait for an interrupt
|
||||
+ * to conclude the operation.
|
||||
+ */
|
||||
+int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
|
||||
+ u16 mask, u16 set)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ mutex_lock(&phydev->mdio.bus->mdio_lock);
|
||||
+ ret = __phy_modify_mmd(phydev, devad, regnum, mask, set);
|
||||
+ mutex_unlock(&phydev->mdio.bus->mdio_lock);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(phy_modify_mmd);
|
||||
+
|
||||
static int __phy_read_page(struct phy_device *phydev)
|
||||
{
|
||||
return phydev->drv->read_page(phydev);
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -695,17 +695,6 @@ size_t phy_speeds(unsigned int *speeds,
|
||||
void phy_resolve_aneg_linkmode(struct phy_device *phydev);
|
||||
|
||||
/**
|
||||
- * phy_read_mmd - Convenience function for reading a register
|
||||
- * from an MMD on a given PHY.
|
||||
- * @phydev: The phy_device struct
|
||||
- * @devad: The MMD to read from
|
||||
- * @regnum: The register on the MMD to read
|
||||
- *
|
||||
- * Same rules as for phy_read();
|
||||
- */
|
||||
-int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum);
|
||||
-
|
||||
-/**
|
||||
* phy_read - Convenience function for reading a given PHY register
|
||||
* @phydev: the phy_device struct
|
||||
* @regnum: register number to read
|
||||
@@ -760,9 +749,60 @@ static inline int __phy_write(struct phy
|
||||
val);
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * phy_read_mmd - Convenience function for reading a register
|
||||
+ * from an MMD on a given PHY.
|
||||
+ * @phydev: The phy_device struct
|
||||
+ * @devad: The MMD to read from
|
||||
+ * @regnum: The register on the MMD to read
|
||||
+ *
|
||||
+ * Same rules as for phy_read();
|
||||
+ */
|
||||
+int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum);
|
||||
+
|
||||
+/**
|
||||
+ * __phy_read_mmd - Convenience function for reading a register
|
||||
+ * from an MMD on a given PHY.
|
||||
+ * @phydev: The phy_device struct
|
||||
+ * @devad: The MMD to read from
|
||||
+ * @regnum: The register on the MMD to read
|
||||
+ *
|
||||
+ * Same rules as for __phy_read();
|
||||
+ */
|
||||
+int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum);
|
||||
+
|
||||
+/**
|
||||
+ * phy_write_mmd - Convenience function for writing a register
|
||||
+ * on an MMD on a given PHY.
|
||||
+ * @phydev: The phy_device struct
|
||||
+ * @devad: The MMD to write to
|
||||
+ * @regnum: The register on the MMD to read
|
||||
+ * @val: value to write to @regnum
|
||||
+ *
|
||||
+ * Same rules as for phy_write();
|
||||
+ */
|
||||
+int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
|
||||
+
|
||||
+/**
|
||||
+ * __phy_write_mmd - Convenience function for writing a register
|
||||
+ * on an MMD on a given PHY.
|
||||
+ * @phydev: The phy_device struct
|
||||
+ * @devad: The MMD to write to
|
||||
+ * @regnum: The register on the MMD to read
|
||||
+ * @val: value to write to @regnum
|
||||
+ *
|
||||
+ * Same rules as for __phy_write();
|
||||
+ */
|
||||
+int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
|
||||
+
|
||||
int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set);
|
||||
int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set);
|
||||
|
||||
+int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
|
||||
+ u16 mask, u16 set);
|
||||
+int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
|
||||
+ u16 mask, u16 set);
|
||||
+
|
||||
/**
|
||||
* __phy_set_bits - Convenience function for setting bits in a PHY register
|
||||
* @phydev: the phy_device struct
|
||||
@@ -813,6 +853,66 @@ static inline int phy_clear_bits(struct
|
||||
}
|
||||
|
||||
/**
|
||||
+ * __phy_set_bits_mmd - Convenience function for setting bits in a register
|
||||
+ * on MMD
|
||||
+ * @phydev: the phy_device struct
|
||||
+ * @devad: the MMD containing register to modify
|
||||
+ * @regnum: register number to modify
|
||||
+ * @val: bits to set
|
||||
+ *
|
||||
+ * The caller must have taken the MDIO bus lock.
|
||||
+ */
|
||||
+static inline int __phy_set_bits_mmd(struct phy_device *phydev, int devad,
|
||||
+ u32 regnum, u16 val)
|
||||
+{
|
||||
+ return __phy_modify_mmd(phydev, devad, regnum, 0, val);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * __phy_clear_bits_mmd - Convenience function for clearing bits in a register
|
||||
+ * on MMD
|
||||
+ * @phydev: the phy_device struct
|
||||
+ * @devad: the MMD containing register to modify
|
||||
+ * @regnum: register number to modify
|
||||
+ * @val: bits to clear
|
||||
+ *
|
||||
+ * The caller must have taken the MDIO bus lock.
|
||||
+ */
|
||||
+static inline int __phy_clear_bits_mmd(struct phy_device *phydev, int devad,
|
||||
+ u32 regnum, u16 val)
|
||||
+{
|
||||
+ return __phy_modify_mmd(phydev, devad, regnum, val, 0);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * phy_set_bits_mmd - Convenience function for setting bits in a register
|
||||
+ * on MMD
|
||||
+ * @phydev: the phy_device struct
|
||||
+ * @devad: the MMD containing register to modify
|
||||
+ * @regnum: register number to modify
|
||||
+ * @val: bits to set
|
||||
+ */
|
||||
+static inline int phy_set_bits_mmd(struct phy_device *phydev, int devad,
|
||||
+ u32 regnum, u16 val)
|
||||
+{
|
||||
+ return phy_modify_mmd(phydev, devad, regnum, 0, val);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * phy_clear_bits_mmd - Convenience function for clearing bits in a register
|
||||
+ * on MMD
|
||||
+ * @phydev: the phy_device struct
|
||||
+ * @devad: the MMD containing register to modify
|
||||
+ * @regnum: register number to modify
|
||||
+ * @val: bits to clear
|
||||
+ */
|
||||
+static inline int phy_clear_bits_mmd(struct phy_device *phydev, int devad,
|
||||
+ u32 regnum, u16 val)
|
||||
+{
|
||||
+ return phy_modify_mmd(phydev, devad, regnum, val, 0);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
* phy_interrupt_is_valid - Convenience function for testing a given PHY irq
|
||||
* @phydev: the phy_device struct
|
||||
*
|
||||
@@ -888,18 +988,6 @@ static inline bool phy_is_pseudo_fixed_l
|
||||
return phydev->is_pseudo_fixed_link;
|
||||
}
|
||||
|
||||
-/**
|
||||
- * phy_write_mmd - Convenience function for writing a register
|
||||
- * on an MMD on a given PHY.
|
||||
- * @phydev: The phy_device struct
|
||||
- * @devad: The MMD to read from
|
||||
- * @regnum: The register on the MMD to read
|
||||
- * @val: value to write to @regnum
|
||||
- *
|
||||
- * Same rules as for phy_write();
|
||||
- */
|
||||
-int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
|
||||
-
|
||||
int phy_save_page(struct phy_device *phydev);
|
||||
int phy_select_page(struct phy_device *phydev, int page);
|
||||
int phy_restore_page(struct phy_device *phydev, int oldpage, int ret);
|
@ -0,0 +1,217 @@
|
||||
From c1e3f753f6b85d7636024159bb78f764e09492f1 Mon Sep 17 00:00:00 2001
|
||||
From: Heiner Kallweit <hkallweit1@gmail.com>
|
||||
Date: Sun, 10 Feb 2019 19:57:56 +0100
|
||||
Subject: [PATCH 604/660] net: phy: add register modifying helpers returning 1
|
||||
on change
|
||||
|
||||
When modifying registers there are scenarios where we need to know
|
||||
whether the register content actually changed. This patch adds
|
||||
new helpers to not break users of the current ones, phy_modify() etc.
|
||||
|
||||
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/phy-core.c | 127 ++++++++++++++++++++++++++++++++++---
|
||||
include/linux/phy.h | 12 +++-
|
||||
2 files changed, 128 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phy-core.c
|
||||
+++ b/drivers/net/phy/phy-core.c
|
||||
@@ -364,7 +364,7 @@ int phy_write_mmd(struct phy_device *phy
|
||||
EXPORT_SYMBOL(phy_write_mmd);
|
||||
|
||||
/**
|
||||
- * __phy_modify() - Convenience function for modifying a PHY register
|
||||
+ * __phy_modify_changed() - Convenience function for modifying a PHY register
|
||||
* @phydev: a pointer to a &struct phy_device
|
||||
* @regnum: register number
|
||||
* @mask: bit mask of bits to clear
|
||||
@@ -372,16 +372,69 @@ EXPORT_SYMBOL(phy_write_mmd);
|
||||
*
|
||||
* Unlocked helper function which allows a PHY register to be modified as
|
||||
* new register value = (old register value & ~mask) | set
|
||||
+ *
|
||||
+ * Returns negative errno, 0 if there was no change, and 1 in case of change
|
||||
*/
|
||||
-int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
|
||||
+int __phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask,
|
||||
+ u16 set)
|
||||
{
|
||||
- int ret;
|
||||
+ int new, ret;
|
||||
|
||||
ret = __phy_read(phydev, regnum);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- ret = __phy_write(phydev, regnum, (ret & ~mask) | set);
|
||||
+ new = (ret & ~mask) | set;
|
||||
+ if (new == ret)
|
||||
+ return 0;
|
||||
+
|
||||
+ ret = __phy_write(phydev, regnum, new);
|
||||
+
|
||||
+ return ret < 0 ? ret : 1;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(__phy_modify_changed);
|
||||
+
|
||||
+/**
|
||||
+ * phy_modify_changed - Function for modifying a PHY register
|
||||
+ * @phydev: the phy_device struct
|
||||
+ * @regnum: register number to modify
|
||||
+ * @mask: bit mask of bits to clear
|
||||
+ * @set: new value of bits set in mask to write to @regnum
|
||||
+ *
|
||||
+ * NOTE: MUST NOT be called from interrupt context,
|
||||
+ * because the bus read/write functions may wait for an interrupt
|
||||
+ * to conclude the operation.
|
||||
+ *
|
||||
+ * Returns negative errno, 0 if there was no change, and 1 in case of change
|
||||
+ */
|
||||
+int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ mutex_lock(&phydev->mdio.bus->mdio_lock);
|
||||
+ ret = __phy_modify_changed(phydev, regnum, mask, set);
|
||||
+ mutex_unlock(&phydev->mdio.bus->mdio_lock);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(phy_modify_changed);
|
||||
+
|
||||
+/**
|
||||
+ * __phy_modify - Convenience function for modifying a PHY register
|
||||
+ * @phydev: the phy_device struct
|
||||
+ * @regnum: register number to modify
|
||||
+ * @mask: bit mask of bits to clear
|
||||
+ * @set: new value of bits set in mask to write to @regnum
|
||||
+ *
|
||||
+ * NOTE: MUST NOT be called from interrupt context,
|
||||
+ * because the bus read/write functions may wait for an interrupt
|
||||
+ * to conclude the operation.
|
||||
+ */
|
||||
+int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = __phy_modify_changed(phydev, regnum, mask, set);
|
||||
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
@@ -411,7 +464,7 @@ int phy_modify(struct phy_device *phydev
|
||||
EXPORT_SYMBOL_GPL(phy_modify);
|
||||
|
||||
/**
|
||||
- * __phy_modify_mmd - Convenience function for modifying a register on MMD
|
||||
+ * __phy_modify_mmd_changed - Function for modifying a register on MMD
|
||||
* @phydev: the phy_device struct
|
||||
* @devad: the MMD containing register to modify
|
||||
* @regnum: register number to modify
|
||||
@@ -420,17 +473,73 @@ EXPORT_SYMBOL_GPL(phy_modify);
|
||||
*
|
||||
* Unlocked helper function which allows a MMD register to be modified as
|
||||
* new register value = (old register value & ~mask) | set
|
||||
+ *
|
||||
+ * Returns negative errno, 0 if there was no change, and 1 in case of change
|
||||
*/
|
||||
-int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
|
||||
- u16 mask, u16 set)
|
||||
+int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
|
||||
+ u16 mask, u16 set)
|
||||
{
|
||||
- int ret;
|
||||
+ int new, ret;
|
||||
|
||||
ret = __phy_read_mmd(phydev, devad, regnum);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- ret = __phy_write_mmd(phydev, devad, regnum, (ret & ~mask) | set);
|
||||
+ new = (ret & ~mask) | set;
|
||||
+ if (new == ret)
|
||||
+ return 0;
|
||||
+
|
||||
+ ret = __phy_write_mmd(phydev, devad, regnum, new);
|
||||
+
|
||||
+ return ret < 0 ? ret : 1;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(__phy_modify_mmd_changed);
|
||||
+
|
||||
+/**
|
||||
+ * phy_modify_mmd_changed - Function for modifying a register on MMD
|
||||
+ * @phydev: the phy_device struct
|
||||
+ * @devad: the MMD containing register to modify
|
||||
+ * @regnum: register number to modify
|
||||
+ * @mask: bit mask of bits to clear
|
||||
+ * @set: new value of bits set in mask to write to @regnum
|
||||
+ *
|
||||
+ * NOTE: MUST NOT be called from interrupt context,
|
||||
+ * because the bus read/write functions may wait for an interrupt
|
||||
+ * to conclude the operation.
|
||||
+ *
|
||||
+ * Returns negative errno, 0 if there was no change, and 1 in case of change
|
||||
+ */
|
||||
+int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
|
||||
+ u16 mask, u16 set)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ mutex_lock(&phydev->mdio.bus->mdio_lock);
|
||||
+ ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
|
||||
+ mutex_unlock(&phydev->mdio.bus->mdio_lock);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(phy_modify_mmd_changed);
|
||||
+
|
||||
+/**
|
||||
+ * __phy_modify_mmd - Convenience function for modifying a register on MMD
|
||||
+ * @phydev: the phy_device struct
|
||||
+ * @devad: the MMD containing register to modify
|
||||
+ * @regnum: register number to modify
|
||||
+ * @mask: bit mask of bits to clear
|
||||
+ * @set: new value of bits set in mask to write to @regnum
|
||||
+ *
|
||||
+ * NOTE: MUST NOT be called from interrupt context,
|
||||
+ * because the bus read/write functions may wait for an interrupt
|
||||
+ * to conclude the operation.
|
||||
+ */
|
||||
+int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
|
||||
+ u16 mask, u16 set)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
|
||||
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -795,13 +795,21 @@ int phy_write_mmd(struct phy_device *phy
|
||||
*/
|
||||
int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
|
||||
|
||||
+int __phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask,
|
||||
+ u16 set);
|
||||
+int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask,
|
||||
+ u16 set);
|
||||
int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set);
|
||||
int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set);
|
||||
|
||||
+int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
|
||||
+ u16 mask, u16 set);
|
||||
+int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
|
||||
+ u16 mask, u16 set);
|
||||
int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
|
||||
- u16 mask, u16 set);
|
||||
+ u16 mask, u16 set);
|
||||
int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
|
||||
- u16 mask, u16 set);
|
||||
+ u16 mask, u16 set);
|
||||
|
||||
/**
|
||||
* __phy_set_bits - Convenience function for setting bits in a PHY register
|
@ -0,0 +1,64 @@
|
||||
From 2c3db705737cf52d7d24c993f0889b25b956c718 Mon Sep 17 00:00:00 2001
|
||||
From: Heiner Kallweit <hkallweit1@gmail.com>
|
||||
Date: Mon, 18 Feb 2019 21:27:18 +0100
|
||||
Subject: [PATCH 605/660] net: phy: add genphy_c45_check_and_restart_aneg
|
||||
|
||||
This function will be used by config_aneg callback implementations of
|
||||
PHY drivers and allows to reduce boilerplate code.
|
||||
|
||||
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/phy-c45.c | 30 ++++++++++++++++++++++++++++++
|
||||
include/linux/phy.h | 1 +
|
||||
2 files changed, 31 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/phy-c45.c
|
||||
+++ b/drivers/net/phy/phy-c45.c
|
||||
@@ -110,6 +110,36 @@ int genphy_c45_restart_aneg(struct phy_d
|
||||
EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg);
|
||||
|
||||
/**
|
||||
+ * genphy_c45_check_and_restart_aneg - Enable and restart auto-negotiation
|
||||
+ * @phydev: target phy_device struct
|
||||
+ * @restart: whether aneg restart is requested
|
||||
+ *
|
||||
+ * This assumes that the auto-negotiation MMD is present.
|
||||
+ *
|
||||
+ * Check, and restart auto-negotiation if needed.
|
||||
+ */
|
||||
+int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (!restart) {
|
||||
+ /* Configure and restart aneg if it wasn't set before */
|
||||
+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (!(ret & MDIO_AN_CTRL1_ENABLE))
|
||||
+ restart = true;
|
||||
+ }
|
||||
+
|
||||
+ if (restart)
|
||||
+ ret = genphy_c45_restart_aneg(phydev);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(genphy_c45_check_and_restart_aneg);
|
||||
+
|
||||
+/**
|
||||
* genphy_c45_aneg_done - return auto-negotiation complete status
|
||||
* @phydev: target phy_device struct
|
||||
*
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -1098,6 +1098,7 @@ int genphy_write_mmd_unsupported(struct
|
||||
|
||||
/* Clause 45 PHY */
|
||||
int genphy_c45_restart_aneg(struct phy_device *phydev);
|
||||
+int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart);
|
||||
int genphy_c45_aneg_done(struct phy_device *phydev);
|
||||
int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask);
|
||||
int genphy_c45_read_lpa(struct phy_device *phydev);
|
@ -0,0 +1,59 @@
|
||||
From 4c4323084e9a67210c8d269dceba1be99356c414 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 28 May 2019 10:57:18 +0100
|
||||
Subject: [PATCH 606/660] net: phylink: remove netdev from phylink mii ioctl
|
||||
emulation
|
||||
|
||||
The netdev used in the phylink ioctl emulation is never used, so let's
|
||||
remove it.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 12 ++++--------
|
||||
1 file changed, 4 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1360,8 +1360,8 @@ EXPORT_SYMBOL_GPL(phylink_ethtool_set_ee
|
||||
*
|
||||
* FIXME: should deal with negotiation state too.
|
||||
*/
|
||||
-static int phylink_mii_emul_read(struct net_device *ndev, unsigned int reg,
|
||||
- struct phylink_link_state *state, bool aneg)
|
||||
+static int phylink_mii_emul_read(unsigned int reg,
|
||||
+ struct phylink_link_state *state)
|
||||
{
|
||||
struct fixed_phy_status fs;
|
||||
int val;
|
||||
@@ -1376,8 +1376,6 @@ static int phylink_mii_emul_read(struct
|
||||
if (reg == MII_BMSR) {
|
||||
if (!state->an_complete)
|
||||
val &= ~BMSR_ANEGCOMPLETE;
|
||||
- if (!aneg)
|
||||
- val &= ~BMSR_ANEGCAPABLE;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
@@ -1473,8 +1471,7 @@ static int phylink_mii_read(struct phyli
|
||||
case MLO_AN_FIXED:
|
||||
if (phy_id == 0) {
|
||||
phylink_get_fixed_state(pl, &state);
|
||||
- val = phylink_mii_emul_read(pl->netdev, reg, &state,
|
||||
- true);
|
||||
+ val = phylink_mii_emul_read(reg, &state);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1487,8 +1484,7 @@ static int phylink_mii_read(struct phyli
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
- val = phylink_mii_emul_read(pl->netdev, reg, &state,
|
||||
- true);
|
||||
+ val = phylink_mii_emul_read(reg, &state);
|
||||
}
|
||||
break;
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
From cba0aba37d2228556e0d1f776d403435868cdbfa Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 28 May 2019 10:57:23 +0100
|
||||
Subject: [PATCH 607/660] net: phylink: support for link gpio interrupt
|
||||
|
||||
Add support for using GPIO interrupts with a fixed-link GPIO rather than
|
||||
polling the GPIO every second and invoking the phylink resolution. This
|
||||
avoids unnecessary calls to mac_config().
|
||||
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 36 ++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 32 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -59,6 +59,7 @@ struct phylink {
|
||||
phy_interface_t cur_interface;
|
||||
|
||||
struct gpio_desc *link_gpio;
|
||||
+ unsigned int link_irq;
|
||||
struct timer_list link_poll;
|
||||
void (*get_fixed_state)(struct net_device *dev,
|
||||
struct phylink_link_state *s);
|
||||
@@ -645,7 +646,7 @@ void phylink_destroy(struct phylink *pl)
|
||||
{
|
||||
if (pl->sfp_bus)
|
||||
sfp_unregister_upstream(pl->sfp_bus);
|
||||
- if (!IS_ERR_OR_NULL(pl->link_gpio))
|
||||
+ if (pl->link_gpio)
|
||||
gpiod_put(pl->link_gpio);
|
||||
|
||||
cancel_work_sync(&pl->resolve);
|
||||
@@ -912,6 +913,15 @@ void phylink_mac_change(struct phylink *
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phylink_mac_change);
|
||||
|
||||
+static irqreturn_t phylink_link_handler(int irq, void *data)
|
||||
+{
|
||||
+ struct phylink *pl = data;
|
||||
+
|
||||
+ phylink_run_resolve(pl);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* phylink_start() - start a phylink instance
|
||||
* @pl: a pointer to a &struct phylink returned from phylink_create()
|
||||
@@ -947,7 +957,22 @@ void phylink_start(struct phylink *pl)
|
||||
clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
|
||||
phylink_run_resolve(pl);
|
||||
|
||||
- if (pl->link_an_mode == MLO_AN_FIXED && !IS_ERR(pl->link_gpio))
|
||||
+ if (pl->link_an_mode == MLO_AN_FIXED && pl->link_gpio) {
|
||||
+ int irq = gpiod_to_irq(pl->link_gpio);
|
||||
+
|
||||
+ if (irq > 0) {
|
||||
+ if (!request_irq(irq, phylink_link_handler,
|
||||
+ IRQF_TRIGGER_RISING |
|
||||
+ IRQF_TRIGGER_FALLING,
|
||||
+ "netdev link", pl))
|
||||
+ pl->link_irq = irq;
|
||||
+ else
|
||||
+ irq = 0;
|
||||
+ }
|
||||
+ if (irq <= 0)
|
||||
+ mod_timer(&pl->link_poll, jiffies + HZ);
|
||||
+ }
|
||||
+ if (pl->link_an_mode == MLO_AN_FIXED && pl->get_fixed_state)
|
||||
mod_timer(&pl->link_poll, jiffies + HZ);
|
||||
if (pl->sfp_bus)
|
||||
sfp_upstream_start(pl->sfp_bus);
|
||||
@@ -973,8 +998,11 @@ void phylink_stop(struct phylink *pl)
|
||||
phy_stop(pl->phydev);
|
||||
if (pl->sfp_bus)
|
||||
sfp_upstream_stop(pl->sfp_bus);
|
||||
- if (pl->link_an_mode == MLO_AN_FIXED && !IS_ERR(pl->link_gpio))
|
||||
- del_timer_sync(&pl->link_poll);
|
||||
+ del_timer_sync(&pl->link_poll);
|
||||
+ if (pl->link_irq) {
|
||||
+ free_irq(pl->link_irq, pl);
|
||||
+ pl->link_irq = 0;
|
||||
+ }
|
||||
|
||||
phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED);
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
From eb5df3d026824832831376bbdf04e01a52776eea Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 28 May 2019 10:57:29 +0100
|
||||
Subject: [PATCH 608/660] net: phy: allow Clause 45 access via mii ioctl
|
||||
|
||||
Allow userspace to generate Clause 45 MII access cycles via phylib.
|
||||
This is useful for tools such as mii-diag to be able to inspect Clause
|
||||
45 PHYs.
|
||||
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/phy.c | 33 ++++++++++++++++++++++++---------
|
||||
1 file changed, 24 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phy.c
|
||||
+++ b/drivers/net/phy/phy.c
|
||||
@@ -397,6 +397,7 @@ int phy_mii_ioctl(struct phy_device *phy
|
||||
struct mii_ioctl_data *mii_data = if_mii(ifr);
|
||||
u16 val = mii_data->val_in;
|
||||
bool change_autoneg = false;
|
||||
+ int prtad, devad;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCGMIIPHY:
|
||||
@@ -404,14 +405,29 @@ int phy_mii_ioctl(struct phy_device *phy
|
||||
/* fall through */
|
||||
|
||||
case SIOCGMIIREG:
|
||||
- mii_data->val_out = mdiobus_read(phydev->mdio.bus,
|
||||
- mii_data->phy_id,
|
||||
- mii_data->reg_num);
|
||||
+ if (mdio_phy_id_is_c45(mii_data->phy_id)) {
|
||||
+ prtad = mdio_phy_id_prtad(mii_data->phy_id);
|
||||
+ devad = mdio_phy_id_devad(mii_data->phy_id);
|
||||
+ devad = MII_ADDR_C45 | devad << 16 | mii_data->reg_num;
|
||||
+ } else {
|
||||
+ prtad = mii_data->phy_id;
|
||||
+ devad = mii_data->reg_num;
|
||||
+ }
|
||||
+ mii_data->val_out = mdiobus_read(phydev->mdio.bus, prtad,
|
||||
+ devad);
|
||||
return 0;
|
||||
|
||||
case SIOCSMIIREG:
|
||||
- if (mii_data->phy_id == phydev->mdio.addr) {
|
||||
- switch (mii_data->reg_num) {
|
||||
+ if (mdio_phy_id_is_c45(mii_data->phy_id)) {
|
||||
+ prtad = mdio_phy_id_prtad(mii_data->phy_id);
|
||||
+ devad = mdio_phy_id_devad(mii_data->phy_id);
|
||||
+ devad = MII_ADDR_C45 | devad << 16 | mii_data->reg_num;
|
||||
+ } else {
|
||||
+ prtad = mii_data->phy_id;
|
||||
+ devad = mii_data->reg_num;
|
||||
+ }
|
||||
+ if (prtad == phydev->mdio.addr) {
|
||||
+ switch (devad) {
|
||||
case MII_BMCR:
|
||||
if ((val & (BMCR_RESET | BMCR_ANENABLE)) == 0) {
|
||||
if (phydev->autoneg == AUTONEG_ENABLE)
|
||||
@@ -443,11 +459,10 @@ int phy_mii_ioctl(struct phy_device *phy
|
||||
}
|
||||
}
|
||||
|
||||
- mdiobus_write(phydev->mdio.bus, mii_data->phy_id,
|
||||
- mii_data->reg_num, val);
|
||||
+ mdiobus_write(phydev->mdio.bus, prtad, devad, val);
|
||||
|
||||
- if (mii_data->phy_id == phydev->mdio.addr &&
|
||||
- mii_data->reg_num == MII_BMCR &&
|
||||
+ if (prtad == phydev->mdio.addr &&
|
||||
+ devad == MII_BMCR &&
|
||||
val & BMCR_RESET)
|
||||
return phy_init_hw(phydev);
|
||||
|
@ -0,0 +1,94 @@
|
||||
From aeabfaa63285470e81fa341e14f92d68880aa160 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 28 May 2019 10:57:34 +0100
|
||||
Subject: [PATCH 609/660] net: sfp: add mandatory attach/detach methods for sfp
|
||||
buses
|
||||
|
||||
Add attach and detach methods for SFP buses, which will allow us to get
|
||||
rid of the netdev storage in sfp-bus.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 16 ++++++++++++++++
|
||||
drivers/net/phy/sfp-bus.c | 4 ++--
|
||||
include/linux/sfp.h | 6 ++++++
|
||||
3 files changed, 24 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1615,6 +1615,20 @@ int phylink_mii_ioctl(struct phylink *pl
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phylink_mii_ioctl);
|
||||
|
||||
+static void phylink_sfp_attach(void *upstream, struct sfp_bus *bus)
|
||||
+{
|
||||
+ struct phylink *pl = upstream;
|
||||
+
|
||||
+ pl->netdev->sfp_bus = bus;
|
||||
+}
|
||||
+
|
||||
+static void phylink_sfp_detach(void *upstream, struct sfp_bus *bus)
|
||||
+{
|
||||
+ struct phylink *pl = upstream;
|
||||
+
|
||||
+ pl->netdev->sfp_bus = NULL;
|
||||
+}
|
||||
+
|
||||
static int phylink_sfp_module_insert(void *upstream,
|
||||
const struct sfp_eeprom_id *id)
|
||||
{
|
||||
@@ -1733,6 +1747,8 @@ static void phylink_sfp_disconnect_phy(v
|
||||
}
|
||||
|
||||
static const struct sfp_upstream_ops sfp_phylink_ops = {
|
||||
+ .attach = phylink_sfp_attach,
|
||||
+ .detach = phylink_sfp_detach,
|
||||
.module_insert = phylink_sfp_module_insert,
|
||||
.link_up = phylink_sfp_link_up,
|
||||
.link_down = phylink_sfp_link_down,
|
||||
--- a/drivers/net/phy/sfp-bus.c
|
||||
+++ b/drivers/net/phy/sfp-bus.c
|
||||
@@ -350,7 +350,7 @@ static int sfp_register_bus(struct sfp_b
|
||||
bus->socket_ops->attach(bus->sfp);
|
||||
if (bus->started)
|
||||
bus->socket_ops->start(bus->sfp);
|
||||
- bus->netdev->sfp_bus = bus;
|
||||
+ bus->upstream_ops->attach(bus->upstream, bus);
|
||||
bus->registered = true;
|
||||
return 0;
|
||||
}
|
||||
@@ -359,8 +359,8 @@ static void sfp_unregister_bus(struct sf
|
||||
{
|
||||
const struct sfp_upstream_ops *ops = bus->upstream_ops;
|
||||
|
||||
- bus->netdev->sfp_bus = NULL;
|
||||
if (bus->registered) {
|
||||
+ bus->upstream_ops->detach(bus->upstream, bus);
|
||||
if (bus->started)
|
||||
bus->socket_ops->stop(bus->sfp);
|
||||
bus->socket_ops->detach(bus->sfp);
|
||||
--- a/include/linux/sfp.h
|
||||
+++ b/include/linux/sfp.h
|
||||
@@ -469,6 +469,10 @@ struct sfp_bus;
|
||||
|
||||
/**
|
||||
* struct sfp_upstream_ops - upstream operations structure
|
||||
+ * @attach: called when the sfp socket driver is bound to the upstream
|
||||
+ * (mandatory).
|
||||
+ * @detach: called when the sfp socket driver is unbound from the upstream
|
||||
+ * (mandatory).
|
||||
* @module_insert: called after a module has been detected to determine
|
||||
* whether the module is supported for the upstream device.
|
||||
* @module_remove: called after the module has been removed.
|
||||
@@ -481,6 +485,8 @@ struct sfp_bus;
|
||||
* been removed.
|
||||
*/
|
||||
struct sfp_upstream_ops {
|
||||
+ void (*attach)(void *priv, struct sfp_bus *bus);
|
||||
+ void (*detach)(void *priv, struct sfp_bus *bus);
|
||||
int (*module_insert)(void *priv, const struct sfp_eeprom_id *id);
|
||||
void (*module_remove)(void *priv);
|
||||
void (*link_down)(void *priv);
|
@ -0,0 +1,118 @@
|
||||
From 60d756717d772be90d07a07cd2cc140c76da3e4a Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 28 May 2019 10:57:39 +0100
|
||||
Subject: [PATCH 610/660] net: sfp: remove sfp-bus use of netdevs
|
||||
|
||||
The sfp-bus code now no longer has any use for the network device
|
||||
structure, so remove its use.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 3 +--
|
||||
drivers/net/phy/sfp-bus.c | 10 +++-------
|
||||
include/linux/sfp.h | 6 ++----
|
||||
3 files changed, 6 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -555,8 +555,7 @@ static int phylink_register_sfp(struct p
|
||||
return ret;
|
||||
}
|
||||
|
||||
- pl->sfp_bus = sfp_register_upstream(ref.fwnode, pl->netdev, pl,
|
||||
- &sfp_phylink_ops);
|
||||
+ pl->sfp_bus = sfp_register_upstream(ref.fwnode, pl, &sfp_phylink_ops);
|
||||
if (!pl->sfp_bus)
|
||||
return -ENOMEM;
|
||||
|
||||
--- a/drivers/net/phy/sfp-bus.c
|
||||
+++ b/drivers/net/phy/sfp-bus.c
|
||||
@@ -23,7 +23,6 @@ struct sfp_bus {
|
||||
|
||||
const struct sfp_upstream_ops *upstream_ops;
|
||||
void *upstream;
|
||||
- struct net_device *netdev;
|
||||
struct phy_device *phydev;
|
||||
|
||||
bool registered;
|
||||
@@ -442,13 +441,11 @@ static void sfp_upstream_clear(struct sf
|
||||
{
|
||||
bus->upstream_ops = NULL;
|
||||
bus->upstream = NULL;
|
||||
- bus->netdev = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* sfp_register_upstream() - Register the neighbouring device
|
||||
* @fwnode: firmware node for the SFP bus
|
||||
- * @ndev: network device associated with the interface
|
||||
* @upstream: the upstream private data
|
||||
* @ops: the upstream's &struct sfp_upstream_ops
|
||||
*
|
||||
@@ -459,7 +456,7 @@ static void sfp_upstream_clear(struct sf
|
||||
* On error, returns %NULL.
|
||||
*/
|
||||
struct sfp_bus *sfp_register_upstream(struct fwnode_handle *fwnode,
|
||||
- struct net_device *ndev, void *upstream,
|
||||
+ void *upstream,
|
||||
const struct sfp_upstream_ops *ops)
|
||||
{
|
||||
struct sfp_bus *bus = sfp_bus_get(fwnode);
|
||||
@@ -469,7 +466,6 @@ struct sfp_bus *sfp_register_upstream(st
|
||||
rtnl_lock();
|
||||
bus->upstream_ops = ops;
|
||||
bus->upstream = upstream;
|
||||
- bus->netdev = ndev;
|
||||
|
||||
if (bus->sfp) {
|
||||
ret = sfp_register_bus(bus);
|
||||
@@ -591,7 +587,7 @@ struct sfp_bus *sfp_register_socket(stru
|
||||
bus->sfp = sfp;
|
||||
bus->socket_ops = ops;
|
||||
|
||||
- if (bus->netdev) {
|
||||
+ if (bus->upstream_ops) {
|
||||
ret = sfp_register_bus(bus);
|
||||
if (ret)
|
||||
sfp_socket_clear(bus);
|
||||
@@ -611,7 +607,7 @@ EXPORT_SYMBOL_GPL(sfp_register_socket);
|
||||
void sfp_unregister_socket(struct sfp_bus *bus)
|
||||
{
|
||||
rtnl_lock();
|
||||
- if (bus->netdev)
|
||||
+ if (bus->upstream_ops)
|
||||
sfp_unregister_bus(bus);
|
||||
sfp_socket_clear(bus);
|
||||
rtnl_unlock();
|
||||
--- a/include/linux/sfp.h
|
||||
+++ b/include/linux/sfp.h
|
||||
@@ -464,7 +464,6 @@ enum {
|
||||
struct fwnode_handle;
|
||||
struct ethtool_eeprom;
|
||||
struct ethtool_modinfo;
|
||||
-struct net_device;
|
||||
struct sfp_bus;
|
||||
|
||||
/**
|
||||
@@ -510,7 +509,7 @@ int sfp_get_module_eeprom(struct sfp_bus
|
||||
void sfp_upstream_start(struct sfp_bus *bus);
|
||||
void sfp_upstream_stop(struct sfp_bus *bus);
|
||||
struct sfp_bus *sfp_register_upstream(struct fwnode_handle *fwnode,
|
||||
- struct net_device *ndev, void *upstream,
|
||||
+ void *upstream,
|
||||
const struct sfp_upstream_ops *ops);
|
||||
void sfp_unregister_upstream(struct sfp_bus *bus);
|
||||
#else
|
||||
@@ -555,8 +554,7 @@ static inline void sfp_upstream_stop(str
|
||||
}
|
||||
|
||||
static inline struct sfp_bus *sfp_register_upstream(
|
||||
- struct fwnode_handle *fwnode,
|
||||
- struct net_device *ndev, void *upstream,
|
||||
+ struct fwnode_handle *fwnode, void *upstream,
|
||||
const struct sfp_upstream_ops *ops)
|
||||
{
|
||||
return (struct sfp_bus *)-1;
|
@ -0,0 +1,84 @@
|
||||
From 8ac1d3e5cf7d277769ba3403d99f643fab1e3fae Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Sat, 23 Nov 2019 14:19:54 +0000
|
||||
Subject: [PATCH 611/660] net: phylink: avoid reducing support mask
|
||||
|
||||
Avoid reducing the support mask as a result of the interface type
|
||||
selected for SFP modules, or when setting the link settings through
|
||||
ethtool - this should only change when the supported link modes of
|
||||
the hardware combination change.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 13 +++++++++----
|
||||
1 file changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1137,6 +1137,7 @@ EXPORT_SYMBOL_GPL(phylink_ethtool_ksetti
|
||||
int phylink_ethtool_ksettings_set(struct phylink *pl,
|
||||
const struct ethtool_link_ksettings *kset)
|
||||
{
|
||||
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(support);
|
||||
struct ethtool_link_ksettings our_kset;
|
||||
struct phylink_link_state config;
|
||||
int ret;
|
||||
@@ -1147,11 +1148,12 @@ int phylink_ethtool_ksettings_set(struct
|
||||
kset->base.autoneg != AUTONEG_ENABLE)
|
||||
return -EINVAL;
|
||||
|
||||
+ linkmode_copy(support, pl->supported);
|
||||
config = pl->link_config;
|
||||
|
||||
/* Mask out unsupported advertisements */
|
||||
linkmode_and(config.advertising, kset->link_modes.advertising,
|
||||
- pl->supported);
|
||||
+ support);
|
||||
|
||||
/* FIXME: should we reject autoneg if phy/mac does not support it? */
|
||||
if (kset->base.autoneg == AUTONEG_DISABLE) {
|
||||
@@ -1161,7 +1163,7 @@ int phylink_ethtool_ksettings_set(struct
|
||||
* duplex.
|
||||
*/
|
||||
s = phy_lookup_setting(kset->base.speed, kset->base.duplex,
|
||||
- pl->supported,
|
||||
+ support,
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS, false);
|
||||
if (!s)
|
||||
return -EINVAL;
|
||||
@@ -1191,7 +1193,7 @@ int phylink_ethtool_ksettings_set(struct
|
||||
__set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, config.advertising);
|
||||
}
|
||||
|
||||
- if (phylink_validate(pl, pl->supported, &config))
|
||||
+ if (phylink_validate(pl, support, &config))
|
||||
return -EINVAL;
|
||||
|
||||
/* If autonegotiation is enabled, we must have an advertisement */
|
||||
@@ -1633,6 +1635,7 @@ static int phylink_sfp_module_insert(voi
|
||||
{
|
||||
struct phylink *pl = upstream;
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
|
||||
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(support1);
|
||||
struct phylink_link_state config;
|
||||
phy_interface_t iface;
|
||||
int ret = 0;
|
||||
@@ -1660,6 +1663,8 @@ static int phylink_sfp_module_insert(voi
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ linkmode_copy(support1, support);
|
||||
+
|
||||
iface = sfp_select_interface(pl->sfp_bus, id, config.advertising);
|
||||
if (iface == PHY_INTERFACE_MODE_NA) {
|
||||
netdev_err(pl->netdev,
|
||||
@@ -1669,7 +1674,7 @@ static int phylink_sfp_module_insert(voi
|
||||
}
|
||||
|
||||
config.interface = iface;
|
||||
- ret = phylink_validate(pl, support, &config);
|
||||
+ ret = phylink_validate(pl, support1, &config);
|
||||
if (ret) {
|
||||
netdev_err(pl->netdev, "validation of %s/%s with support %*pb failed: %d\n",
|
||||
phylink_an_mode_str(MLO_AN_INBAND),
|
@ -0,0 +1,94 @@
|
||||
From 254236a22109efa84c9e9f5a9c76a1719439e309 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Hancock <hancock@sedsystems.ca>
|
||||
Date: Fri, 7 Jun 2019 10:42:35 -0600
|
||||
Subject: [PATCH 612/660] net: sfp: Stop SFP polling and interrupt handling
|
||||
during shutdown
|
||||
|
||||
SFP device polling can cause problems during the shutdown process if the
|
||||
parent devices of the network controller have been shut down already.
|
||||
This problem was seen on the iMX6 platform with PCIe devices, where
|
||||
accessing the device after the bus is shut down causes a hang.
|
||||
|
||||
Free any acquired GPIO interrupts and stop all delayed work in the SFP
|
||||
driver during the shutdown process, so that we ensure that no pending
|
||||
operations are still occurring after the SFP shutdown completes.
|
||||
|
||||
Signed-off-by: Robert Hancock <hancock@sedsystems.ca>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 31 ++++++++++++++++++++++++++-----
|
||||
1 file changed, 26 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -183,6 +183,7 @@ struct sfp {
|
||||
int (*write)(struct sfp *, bool, u8, void *, size_t);
|
||||
|
||||
struct gpio_desc *gpio[GPIO_MAX];
|
||||
+ int gpio_irq[GPIO_MAX];
|
||||
|
||||
bool attached;
|
||||
struct mutex st_mutex; /* Protects state */
|
||||
@@ -1803,7 +1804,7 @@ static int sfp_probe(struct platform_dev
|
||||
const struct sff_data *sff;
|
||||
struct sfp *sfp;
|
||||
bool poll = false;
|
||||
- int irq, err, i;
|
||||
+ int err, i;
|
||||
|
||||
sfp = sfp_alloc(&pdev->dev);
|
||||
if (IS_ERR(sfp))
|
||||
@@ -1885,19 +1886,22 @@ static int sfp_probe(struct platform_dev
|
||||
if (gpio_flags[i] != GPIOD_IN || !sfp->gpio[i])
|
||||
continue;
|
||||
|
||||
- irq = gpiod_to_irq(sfp->gpio[i]);
|
||||
- if (!irq) {
|
||||
+ sfp->gpio_irq[i] = gpiod_to_irq(sfp->gpio[i]);
|
||||
+ if (!sfp->gpio_irq[i]) {
|
||||
poll = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
- err = devm_request_threaded_irq(sfp->dev, irq, NULL, sfp_irq,
|
||||
+ err = devm_request_threaded_irq(sfp->dev, sfp->gpio_irq[i],
|
||||
+ NULL, sfp_irq,
|
||||
IRQF_ONESHOT |
|
||||
IRQF_TRIGGER_RISING |
|
||||
IRQF_TRIGGER_FALLING,
|
||||
dev_name(sfp->dev), sfp);
|
||||
- if (err)
|
||||
+ if (err) {
|
||||
+ sfp->gpio_irq[i] = 0;
|
||||
poll = true;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (poll)
|
||||
@@ -1928,9 +1932,26 @@ static int sfp_remove(struct platform_de
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void sfp_shutdown(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct sfp *sfp = platform_get_drvdata(pdev);
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < GPIO_MAX; i++) {
|
||||
+ if (!sfp->gpio_irq[i])
|
||||
+ continue;
|
||||
+
|
||||
+ devm_free_irq(sfp->dev, sfp->gpio_irq[i], sfp);
|
||||
+ }
|
||||
+
|
||||
+ cancel_delayed_work_sync(&sfp->poll);
|
||||
+ cancel_delayed_work_sync(&sfp->timeout);
|
||||
+}
|
||||
+
|
||||
static struct platform_driver sfp_driver = {
|
||||
.probe = sfp_probe,
|
||||
.remove = sfp_remove,
|
||||
+ .shutdown = sfp_shutdown,
|
||||
.driver = {
|
||||
.name = "sfp",
|
||||
.of_match_table = sfp_of_match,
|
@ -0,0 +1,141 @@
|
||||
From b8803113537a1c1f457eba6270d46e3af305031f Mon Sep 17 00:00:00 2001
|
||||
From: Arseny Solokha <asolokha@kb.kras.ru>
|
||||
Date: Wed, 24 Jul 2019 20:31:39 +0700
|
||||
Subject: [PATCH 613/660] net: phylink: don't start and stop SGMII PHYs in SFP
|
||||
modules twice
|
||||
|
||||
SFP modules connected using the SGMII interface have their own PHYs which
|
||||
are handled by the struct phylink's phydev field. On the other hand, for
|
||||
the modules connected using 1000Base-X interface that field is not set.
|
||||
|
||||
Since commit ce0aa27ff3f6 ("sfp: add sfp-bus to bridge between network
|
||||
devices and sfp cages") phylink_start() ends up setting the phydev field
|
||||
using the sfp-bus infrastructure, which eventually calls phy_start() on it,
|
||||
and then calling phy_start() again on the same phydev from phylink_start()
|
||||
itself. Similar call sequence holds for phylink_stop(), only in the reverse
|
||||
order. This results in WARNs during network interface bringup and shutdown
|
||||
when a copper SFP module is connected, as phy_start() and phy_stop() are
|
||||
called twice in a row for the same phy_device:
|
||||
|
||||
% ip link set up dev eth0
|
||||
------------[ cut here ]------------
|
||||
called from state UP
|
||||
WARNING: CPU: 1 PID: 155 at drivers/net/phy/phy.c:895 phy_start+0x74/0xc0
|
||||
Modules linked in:
|
||||
CPU: 1 PID: 155 Comm: backend Not tainted 5.2.0+ #1
|
||||
NIP: c0227bf0 LR: c0227bf0 CTR: c004d224
|
||||
REGS: df547720 TRAP: 0700 Not tainted (5.2.0+)
|
||||
MSR: 00029000 <CE,EE,ME> CR: 24002822 XER: 00000000
|
||||
|
||||
GPR00: c0227bf0 df5477d8 df5d7080 00000014 df9d2370 df9d5ac4 1f4eb000 00000001
|
||||
GPR08: c061fe58 00000000 00000000 df5477d8 0000003c 100c8768 00000000 00000000
|
||||
GPR16: df486a00 c046f1c8 c046eea0 00000000 c046e904 c0239604 db68449c 00000000
|
||||
GPR24: e9083204 00000000 00000001 db684460 e9083404 00000000 db6dce00 db6dcc00
|
||||
NIP [c0227bf0] phy_start+0x74/0xc0
|
||||
LR [c0227bf0] phy_start+0x74/0xc0
|
||||
Call Trace:
|
||||
[df5477d8] [c0227bf0] phy_start+0x74/0xc0 (unreliable)
|
||||
[df5477e8] [c023cad0] startup_gfar+0x398/0x3f4
|
||||
[df547828] [c023cf08] gfar_enet_open+0x364/0x374
|
||||
[df547898] [c029d870] __dev_open+0xe4/0x140
|
||||
[df5478c8] [c029db70] __dev_change_flags+0xf0/0x188
|
||||
[df5478f8] [c029dc28] dev_change_flags+0x20/0x54
|
||||
[df547918] [c02ae304] do_setlink+0x310/0x818
|
||||
[df547a08] [c02b1eb8] __rtnl_newlink+0x384/0x6b0
|
||||
[df547c28] [c02b222c] rtnl_newlink+0x48/0x68
|
||||
[df547c48] [c02ad7c8] rtnetlink_rcv_msg+0x240/0x27c
|
||||
[df547c98] [c02cc068] netlink_rcv_skb+0x8c/0xf0
|
||||
[df547cd8] [c02cba3c] netlink_unicast+0x114/0x19c
|
||||
[df547d08] [c02cbd74] netlink_sendmsg+0x2b0/0x2c0
|
||||
[df547d58] [c027b668] sock_sendmsg_nosec+0x20/0x40
|
||||
[df547d68] [c027d080] ___sys_sendmsg+0x17c/0x1dc
|
||||
[df547e98] [c027df7c] __sys_sendmsg+0x68/0x84
|
||||
[df547ef8] [c027e430] sys_socketcall+0x1a0/0x204
|
||||
[df547f38] [c000d1d8] ret_from_syscall+0x0/0x38
|
||||
--- interrupt: c01 at 0xfd4e030
|
||||
LR = 0xfd4e010
|
||||
Instruction dump:
|
||||
813f0188 38800000 2b890005 419d0014 3d40c046 5529103a 394aa208 7c8a482e
|
||||
3c60c046 3863a1b8 4cc63182 4be009a1 <0fe00000> 48000030 3c60c046 3863a1d0
|
||||
---[ end trace d4c095aeaf6ea998 ]---
|
||||
|
||||
and
|
||||
|
||||
% ip link set down dev eth0
|
||||
------------[ cut here ]------------
|
||||
called from state HALTED
|
||||
WARNING: CPU: 1 PID: 184 at drivers/net/phy/phy.c:858 phy_stop+0x3c/0x88
|
||||
|
||||
<...>
|
||||
|
||||
Call Trace:
|
||||
[df581788] [c0228450] phy_stop+0x3c/0x88 (unreliable)
|
||||
[df581798] [c022d548] sfp_sm_phy_detach+0x1c/0x44
|
||||
[df5817a8] [c022e8cc] sfp_sm_event+0x4b0/0x87c
|
||||
[df581848] [c022f04c] sfp_upstream_stop+0x34/0x44
|
||||
[df581858] [c0225608] phylink_stop+0x7c/0xe4
|
||||
[df581868] [c023c57c] stop_gfar+0x7c/0x94
|
||||
[df581888] [c023c5b8] gfar_close+0x24/0x94
|
||||
[df5818a8] [c0298688] __dev_close_many+0xdc/0xf8
|
||||
[df5818c8] [c029db58] __dev_change_flags+0xd8/0x188
|
||||
[df5818f8] [c029dc28] dev_change_flags+0x20/0x54
|
||||
[df581918] [c02ae304] do_setlink+0x310/0x818
|
||||
[df581a08] [c02b1eb8] __rtnl_newlink+0x384/0x6b0
|
||||
[df581c28] [c02b222c] rtnl_newlink+0x48/0x68
|
||||
[df581c48] [c02ad7c8] rtnetlink_rcv_msg+0x240/0x27c
|
||||
[df581c98] [c02cc068] netlink_rcv_skb+0x8c/0xf0
|
||||
[df581cd8] [c02cba3c] netlink_unicast+0x114/0x19c
|
||||
[df581d08] [c02cbd74] netlink_sendmsg+0x2b0/0x2c0
|
||||
[df581d58] [c027b668] sock_sendmsg_nosec+0x20/0x40
|
||||
[df581d68] [c027d080] ___sys_sendmsg+0x17c/0x1dc
|
||||
[df581e98] [c027df7c] __sys_sendmsg+0x68/0x84
|
||||
[df581ef8] [c027e430] sys_socketcall+0x1a0/0x204
|
||||
[df581f38] [c000d1d8] ret_from_syscall+0x0/0x38
|
||||
|
||||
<...>
|
||||
|
||||
---[ end trace d4c095aeaf6ea999 ]---
|
||||
|
||||
SFP modules with the 1000Base-X interface are not affected.
|
||||
|
||||
Place explicit calls to phy_start() and phy_stop() before enabling or after
|
||||
disabling an attached SFP module, where phydev is not yet set (or is
|
||||
already unset), so they will be made only from the inside of sfp-bus, if
|
||||
needed.
|
||||
|
||||
Fixes: 217962615662 ("net: phy: warn if phy_start is called from invalid state")
|
||||
Signed-off-by: Arseny Solokha <asolokha@kb.kras.ru>
|
||||
Acked-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -973,10 +973,10 @@ void phylink_start(struct phylink *pl)
|
||||
}
|
||||
if (pl->link_an_mode == MLO_AN_FIXED && pl->get_fixed_state)
|
||||
mod_timer(&pl->link_poll, jiffies + HZ);
|
||||
- if (pl->sfp_bus)
|
||||
- sfp_upstream_start(pl->sfp_bus);
|
||||
if (pl->phydev)
|
||||
phy_start(pl->phydev);
|
||||
+ if (pl->sfp_bus)
|
||||
+ sfp_upstream_start(pl->sfp_bus);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phylink_start);
|
||||
|
||||
@@ -993,10 +993,10 @@ void phylink_stop(struct phylink *pl)
|
||||
{
|
||||
ASSERT_RTNL();
|
||||
|
||||
- if (pl->phydev)
|
||||
- phy_stop(pl->phydev);
|
||||
if (pl->sfp_bus)
|
||||
sfp_upstream_stop(pl->sfp_bus);
|
||||
+ if (pl->phydev)
|
||||
+ phy_stop(pl->phydev);
|
||||
del_timer_sync(&pl->link_poll);
|
||||
if (pl->link_irq) {
|
||||
free_irq(pl->link_irq, pl);
|
@ -0,0 +1,179 @@
|
||||
From 4054955f0da08c81d42220cb445820d474f1ac92 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Sat, 14 Sep 2019 14:21:22 +0100
|
||||
Subject: [PATCH 614/660] net: sfp: move fwnode parsing into sfp-bus layer
|
||||
|
||||
Rather than parsing the sfp firmware node in phylink, parse it in the
|
||||
sfp-bus code, so we can re-use this code for PHYs without having to
|
||||
duplicate the parsing.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 21 ++++---------
|
||||
drivers/net/phy/sfp-bus.c | 65 +++++++++++++++++++++++++--------------
|
||||
include/linux/sfp.h | 10 +++---
|
||||
3 files changed, 53 insertions(+), 43 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -538,26 +538,17 @@ static const struct sfp_upstream_ops sfp
|
||||
static int phylink_register_sfp(struct phylink *pl,
|
||||
struct fwnode_handle *fwnode)
|
||||
{
|
||||
- struct fwnode_reference_args ref;
|
||||
+ struct sfp_bus *bus;
|
||||
int ret;
|
||||
|
||||
- if (!fwnode)
|
||||
- return 0;
|
||||
-
|
||||
- ret = fwnode_property_get_reference_args(fwnode, "sfp", NULL,
|
||||
- 0, 0, &ref);
|
||||
- if (ret < 0) {
|
||||
- if (ret == -ENOENT)
|
||||
- return 0;
|
||||
-
|
||||
- netdev_err(pl->netdev, "unable to parse \"sfp\" node: %d\n",
|
||||
- ret);
|
||||
+ bus = sfp_register_upstream_node(fwnode, pl, &sfp_phylink_ops);
|
||||
+ if (IS_ERR(bus)) {
|
||||
+ ret = PTR_ERR(bus);
|
||||
+ netdev_err(pl->netdev, "unable to attach SFP bus: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
- pl->sfp_bus = sfp_register_upstream(ref.fwnode, pl, &sfp_phylink_ops);
|
||||
- if (!pl->sfp_bus)
|
||||
- return -ENOMEM;
|
||||
+ pl->sfp_bus = bus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
--- a/drivers/net/phy/sfp-bus.c
|
||||
+++ b/drivers/net/phy/sfp-bus.c
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/phylink.h>
|
||||
+#include <linux/property.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@@ -444,45 +445,63 @@ static void sfp_upstream_clear(struct sf
|
||||
}
|
||||
|
||||
/**
|
||||
- * sfp_register_upstream() - Register the neighbouring device
|
||||
- * @fwnode: firmware node for the SFP bus
|
||||
+ * sfp_register_upstream_node() - parse and register the neighbouring device
|
||||
+ * @fwnode: firmware node for the parent device (MAC or PHY)
|
||||
* @upstream: the upstream private data
|
||||
* @ops: the upstream's &struct sfp_upstream_ops
|
||||
*
|
||||
- * Register the upstream device (eg, PHY) with the SFP bus. MAC drivers
|
||||
- * should use phylink, which will call this function for them. Returns
|
||||
- * a pointer to the allocated &struct sfp_bus.
|
||||
+ * Parse the parent device's firmware node for a SFP bus, and register the
|
||||
+ * SFP bus using sfp_register_upstream().
|
||||
*
|
||||
- * On error, returns %NULL.
|
||||
+ * Returns: on success, a pointer to the sfp_bus structure,
|
||||
+ * %NULL if no SFP is specified,
|
||||
+ * on failure, an error pointer value:
|
||||
+ * corresponding to the errors detailed for
|
||||
+ * fwnode_property_get_reference_args().
|
||||
+ * %-ENOMEM if we failed to allocate the bus.
|
||||
+ * an error from the upstream's connect_phy() method.
|
||||
*/
|
||||
-struct sfp_bus *sfp_register_upstream(struct fwnode_handle *fwnode,
|
||||
- void *upstream,
|
||||
- const struct sfp_upstream_ops *ops)
|
||||
-{
|
||||
- struct sfp_bus *bus = sfp_bus_get(fwnode);
|
||||
- int ret = 0;
|
||||
-
|
||||
- if (bus) {
|
||||
- rtnl_lock();
|
||||
- bus->upstream_ops = ops;
|
||||
- bus->upstream = upstream;
|
||||
+struct sfp_bus *sfp_register_upstream_node(struct fwnode_handle *fwnode,
|
||||
+ void *upstream,
|
||||
+ const struct sfp_upstream_ops *ops)
|
||||
+{
|
||||
+ struct fwnode_reference_args ref;
|
||||
+ struct sfp_bus *bus;
|
||||
+ int ret;
|
||||
|
||||
- if (bus->sfp) {
|
||||
- ret = sfp_register_bus(bus);
|
||||
- if (ret)
|
||||
- sfp_upstream_clear(bus);
|
||||
- }
|
||||
- rtnl_unlock();
|
||||
+ ret = fwnode_property_get_reference_args(fwnode, "sfp", NULL,
|
||||
+ 0, 0, &ref);
|
||||
+ if (ret == -ENOENT)
|
||||
+ return NULL;
|
||||
+ else if (ret < 0)
|
||||
+ return ERR_PTR(ret);
|
||||
+
|
||||
+ bus = sfp_bus_get(ref.fwnode);
|
||||
+ fwnode_handle_put(ref.fwnode);
|
||||
+ if (!bus)
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
+
|
||||
+ rtnl_lock();
|
||||
+ bus->upstream_ops = ops;
|
||||
+ bus->upstream = upstream;
|
||||
+
|
||||
+ if (bus->sfp) {
|
||||
+ ret = sfp_register_bus(bus);
|
||||
+ if (ret)
|
||||
+ sfp_upstream_clear(bus);
|
||||
+ } else {
|
||||
+ ret = 0;
|
||||
}
|
||||
+ rtnl_unlock();
|
||||
|
||||
if (ret) {
|
||||
sfp_bus_put(bus);
|
||||
- bus = NULL;
|
||||
+ bus = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return bus;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(sfp_register_upstream);
|
||||
+EXPORT_SYMBOL_GPL(sfp_register_upstream_node);
|
||||
|
||||
/**
|
||||
* sfp_unregister_upstream() - Unregister sfp bus
|
||||
--- a/include/linux/sfp.h
|
||||
+++ b/include/linux/sfp.h
|
||||
@@ -508,9 +508,9 @@ int sfp_get_module_eeprom(struct sfp_bus
|
||||
u8 *data);
|
||||
void sfp_upstream_start(struct sfp_bus *bus);
|
||||
void sfp_upstream_stop(struct sfp_bus *bus);
|
||||
-struct sfp_bus *sfp_register_upstream(struct fwnode_handle *fwnode,
|
||||
- void *upstream,
|
||||
- const struct sfp_upstream_ops *ops);
|
||||
+struct sfp_bus *sfp_register_upstream_node(struct fwnode_handle *fwnode,
|
||||
+ void *upstream,
|
||||
+ const struct sfp_upstream_ops *ops);
|
||||
void sfp_unregister_upstream(struct sfp_bus *bus);
|
||||
#else
|
||||
static inline int sfp_parse_port(struct sfp_bus *bus,
|
||||
@@ -553,11 +553,11 @@ static inline void sfp_upstream_stop(str
|
||||
{
|
||||
}
|
||||
|
||||
-static inline struct sfp_bus *sfp_register_upstream(
|
||||
+static inline struct sfp_bus *sfp_register_upstream_node(
|
||||
struct fwnode_handle *fwnode, void *upstream,
|
||||
const struct sfp_upstream_ops *ops)
|
||||
{
|
||||
- return (struct sfp_bus *)-1;
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
static inline void sfp_unregister_upstream(struct sfp_bus *bus)
|
@ -0,0 +1,254 @@
|
||||
From 863b5b6941f9f43b924393b6ba2b36647e7dee42 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Thu, 7 Nov 2019 17:06:08 +0000
|
||||
Subject: [PATCH 615/660] net: sfp: rework upstream interface
|
||||
|
||||
The current upstream interface is an all-or-nothing, which is
|
||||
sub-optimal for future changes, as it doesn't allow the upstream driver
|
||||
to prepare for the SFP module becoming available, as it is at boot.
|
||||
|
||||
Switch to a find-sfp-bus, add-upstream, del-upstream, put-sfp-bus
|
||||
interface structure instead, which allows the upstream driver to
|
||||
prepare for a module being available as soon as add-upstream is called.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 10 +++--
|
||||
drivers/net/phy/sfp-bus.c | 92 +++++++++++++++++++++++++++------------
|
||||
include/linux/sfp.h | 25 +++++++----
|
||||
3 files changed, 88 insertions(+), 39 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -541,7 +541,7 @@ static int phylink_register_sfp(struct p
|
||||
struct sfp_bus *bus;
|
||||
int ret;
|
||||
|
||||
- bus = sfp_register_upstream_node(fwnode, pl, &sfp_phylink_ops);
|
||||
+ bus = sfp_bus_find_fwnode(fwnode);
|
||||
if (IS_ERR(bus)) {
|
||||
ret = PTR_ERR(bus);
|
||||
netdev_err(pl->netdev, "unable to attach SFP bus: %d\n", ret);
|
||||
@@ -550,7 +550,10 @@ static int phylink_register_sfp(struct p
|
||||
|
||||
pl->sfp_bus = bus;
|
||||
|
||||
- return 0;
|
||||
+ ret = sfp_bus_add_upstream(bus, pl, &sfp_phylink_ops);
|
||||
+ sfp_bus_put(bus);
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -634,8 +637,7 @@ EXPORT_SYMBOL_GPL(phylink_create);
|
||||
*/
|
||||
void phylink_destroy(struct phylink *pl)
|
||||
{
|
||||
- if (pl->sfp_bus)
|
||||
- sfp_unregister_upstream(pl->sfp_bus);
|
||||
+ sfp_bus_del_upstream(pl->sfp_bus);
|
||||
if (pl->link_gpio)
|
||||
gpiod_put(pl->link_gpio);
|
||||
|
||||
--- a/drivers/net/phy/sfp-bus.c
|
||||
+++ b/drivers/net/phy/sfp-bus.c
|
||||
@@ -328,10 +328,19 @@ static void sfp_bus_release(struct kref
|
||||
kfree(bus);
|
||||
}
|
||||
|
||||
-static void sfp_bus_put(struct sfp_bus *bus)
|
||||
+/**
|
||||
+ * sfp_bus_put() - put a reference on the &struct sfp_bus
|
||||
+ * bus: the &struct sfp_bus found via sfp_bus_find_fwnode()
|
||||
+ *
|
||||
+ * Put a reference on the &struct sfp_bus and free the underlying structure
|
||||
+ * if this was the last reference.
|
||||
+ */
|
||||
+void sfp_bus_put(struct sfp_bus *bus)
|
||||
{
|
||||
- kref_put_mutex(&bus->kref, sfp_bus_release, &sfp_mutex);
|
||||
+ if (bus)
|
||||
+ kref_put_mutex(&bus->kref, sfp_bus_release, &sfp_mutex);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(sfp_bus_put);
|
||||
|
||||
static int sfp_register_bus(struct sfp_bus *bus)
|
||||
{
|
||||
@@ -347,11 +356,11 @@ static int sfp_register_bus(struct sfp_b
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
+ bus->registered = true;
|
||||
bus->socket_ops->attach(bus->sfp);
|
||||
if (bus->started)
|
||||
bus->socket_ops->start(bus->sfp);
|
||||
bus->upstream_ops->attach(bus->upstream, bus);
|
||||
- bus->registered = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -445,13 +454,12 @@ static void sfp_upstream_clear(struct sf
|
||||
}
|
||||
|
||||
/**
|
||||
- * sfp_register_upstream_node() - parse and register the neighbouring device
|
||||
+ * sfp_bus_find_fwnode() - parse and locate the SFP bus from fwnode
|
||||
* @fwnode: firmware node for the parent device (MAC or PHY)
|
||||
- * @upstream: the upstream private data
|
||||
- * @ops: the upstream's &struct sfp_upstream_ops
|
||||
*
|
||||
- * Parse the parent device's firmware node for a SFP bus, and register the
|
||||
- * SFP bus using sfp_register_upstream().
|
||||
+ * Parse the parent device's firmware node for a SFP bus, and locate
|
||||
+ * the sfp_bus structure, incrementing its reference count. This must
|
||||
+ * be put via sfp_bus_put() when done.
|
||||
*
|
||||
* Returns: on success, a pointer to the sfp_bus structure,
|
||||
* %NULL if no SFP is specified,
|
||||
@@ -461,9 +469,7 @@ static void sfp_upstream_clear(struct sf
|
||||
* %-ENOMEM if we failed to allocate the bus.
|
||||
* an error from the upstream's connect_phy() method.
|
||||
*/
|
||||
-struct sfp_bus *sfp_register_upstream_node(struct fwnode_handle *fwnode,
|
||||
- void *upstream,
|
||||
- const struct sfp_upstream_ops *ops)
|
||||
+struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct fwnode_reference_args ref;
|
||||
struct sfp_bus *bus;
|
||||
@@ -481,7 +487,39 @@ struct sfp_bus *sfp_register_upstream_no
|
||||
if (!bus)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
+ return bus;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(sfp_bus_find_fwnode);
|
||||
+
|
||||
+/**
|
||||
+ * sfp_bus_add_upstream() - parse and register the neighbouring device
|
||||
+ * @bus: the &struct sfp_bus found via sfp_bus_find_fwnode()
|
||||
+ * @upstream: the upstream private data
|
||||
+ * @ops: the upstream's &struct sfp_upstream_ops
|
||||
+ *
|
||||
+ * Add upstream driver for the SFP bus, and if the bus is complete, register
|
||||
+ * the SFP bus using sfp_register_upstream(). This takes a reference on the
|
||||
+ * bus, so it is safe to put the bus after this call.
|
||||
+ *
|
||||
+ * Returns: on success, a pointer to the sfp_bus structure,
|
||||
+ * %NULL if no SFP is specified,
|
||||
+ * on failure, an error pointer value:
|
||||
+ * corresponding to the errors detailed for
|
||||
+ * fwnode_property_get_reference_args().
|
||||
+ * %-ENOMEM if we failed to allocate the bus.
|
||||
+ * an error from the upstream's connect_phy() method.
|
||||
+ */
|
||||
+int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
|
||||
+ const struct sfp_upstream_ops *ops)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ /* If no bus, return success */
|
||||
+ if (!bus)
|
||||
+ return 0;
|
||||
+
|
||||
rtnl_lock();
|
||||
+ kref_get(&bus->kref);
|
||||
bus->upstream_ops = ops;
|
||||
bus->upstream = upstream;
|
||||
|
||||
@@ -494,33 +532,33 @@ struct sfp_bus *sfp_register_upstream_no
|
||||
}
|
||||
rtnl_unlock();
|
||||
|
||||
- if (ret) {
|
||||
+ if (ret)
|
||||
sfp_bus_put(bus);
|
||||
- bus = ERR_PTR(ret);
|
||||
- }
|
||||
|
||||
- return bus;
|
||||
+ return ret;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(sfp_register_upstream_node);
|
||||
+EXPORT_SYMBOL_GPL(sfp_bus_add_upstream);
|
||||
|
||||
/**
|
||||
- * sfp_unregister_upstream() - Unregister sfp bus
|
||||
+ * sfp_bus_del_upstream() - Delete a sfp bus
|
||||
* @bus: a pointer to the &struct sfp_bus structure for the sfp module
|
||||
*
|
||||
- * Unregister a previously registered upstream connection for the SFP
|
||||
- * module. @bus is returned from sfp_register_upstream().
|
||||
+ * Delete a previously registered upstream connection for the SFP
|
||||
+ * module. @bus should have been added by sfp_bus_add_upstream().
|
||||
*/
|
||||
-void sfp_unregister_upstream(struct sfp_bus *bus)
|
||||
+void sfp_bus_del_upstream(struct sfp_bus *bus)
|
||||
{
|
||||
- rtnl_lock();
|
||||
- if (bus->sfp)
|
||||
- sfp_unregister_bus(bus);
|
||||
- sfp_upstream_clear(bus);
|
||||
- rtnl_unlock();
|
||||
+ if (bus) {
|
||||
+ rtnl_lock();
|
||||
+ if (bus->sfp)
|
||||
+ sfp_unregister_bus(bus);
|
||||
+ sfp_upstream_clear(bus);
|
||||
+ rtnl_unlock();
|
||||
|
||||
- sfp_bus_put(bus);
|
||||
+ sfp_bus_put(bus);
|
||||
+ }
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(sfp_unregister_upstream);
|
||||
+EXPORT_SYMBOL_GPL(sfp_bus_del_upstream);
|
||||
|
||||
/* Socket driver entry points */
|
||||
int sfp_add_phy(struct sfp_bus *bus, struct phy_device *phydev)
|
||||
--- a/include/linux/sfp.h
|
||||
+++ b/include/linux/sfp.h
|
||||
@@ -508,10 +508,11 @@ int sfp_get_module_eeprom(struct sfp_bus
|
||||
u8 *data);
|
||||
void sfp_upstream_start(struct sfp_bus *bus);
|
||||
void sfp_upstream_stop(struct sfp_bus *bus);
|
||||
-struct sfp_bus *sfp_register_upstream_node(struct fwnode_handle *fwnode,
|
||||
- void *upstream,
|
||||
- const struct sfp_upstream_ops *ops);
|
||||
-void sfp_unregister_upstream(struct sfp_bus *bus);
|
||||
+void sfp_bus_put(struct sfp_bus *bus);
|
||||
+struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode);
|
||||
+int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
|
||||
+ const struct sfp_upstream_ops *ops);
|
||||
+void sfp_bus_del_upstream(struct sfp_bus *bus);
|
||||
#else
|
||||
static inline int sfp_parse_port(struct sfp_bus *bus,
|
||||
const struct sfp_eeprom_id *id,
|
||||
@@ -553,14 +554,22 @@ static inline void sfp_upstream_stop(str
|
||||
{
|
||||
}
|
||||
|
||||
-static inline struct sfp_bus *sfp_register_upstream_node(
|
||||
- struct fwnode_handle *fwnode, void *upstream,
|
||||
- const struct sfp_upstream_ops *ops)
|
||||
+static inline void sfp_bus_put(struct sfp_bus *bus)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static inline struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static inline void sfp_unregister_upstream(struct sfp_bus *bus)
|
||||
+static int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
|
||||
+ const struct sfp_upstream_ops *ops)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline void sfp_bus_del_upstream(struct sfp_bus *bus)
|
||||
{
|
||||
}
|
||||
#endif
|
@ -0,0 +1,27 @@
|
||||
From ea7bfd81921827d334c2a23bd11ef0e4e2abafd2 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Sat, 9 Nov 2019 08:13:50 +0000
|
||||
Subject: [PATCH 616/660] net: sfp: fix sfp_bus_put() kernel documentation
|
||||
|
||||
The kbuild test robot found a problem with htmldocs with the recent
|
||||
change to the SFP interfaces. Fix the kernel documentation for
|
||||
sfp_bus_put() which was missing an '@' before the argument name
|
||||
description.
|
||||
|
||||
Fixes: 727b3668b730 ("net: sfp: rework upstream interface")
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp-bus.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp-bus.c
|
||||
+++ b/drivers/net/phy/sfp-bus.c
|
||||
@@ -330,7 +330,7 @@ static void sfp_bus_release(struct kref
|
||||
|
||||
/**
|
||||
* sfp_bus_put() - put a reference on the &struct sfp_bus
|
||||
- * bus: the &struct sfp_bus found via sfp_bus_find_fwnode()
|
||||
+ * @bus: the &struct sfp_bus found via sfp_bus_find_fwnode()
|
||||
*
|
||||
* Put a reference on the &struct sfp_bus and free the underlying structure
|
||||
* if this was the last reference.
|
@ -0,0 +1,27 @@
|
||||
From f76d84cd85f8bd3f083495f7ca723822cba8abc9 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Mon, 11 Nov 2019 10:23:35 +0000
|
||||
Subject: [PATCH 617/660] net: sfp: fix sfp_bus_add_upstream() warning
|
||||
|
||||
When building with SFP disabled, the stub for sfp_bus_add_upstream()
|
||||
missed "inline". Add it.
|
||||
|
||||
Fixes: 727b3668b730 ("net: sfp: rework upstream interface")
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
include/linux/sfp.h | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/include/linux/sfp.h
|
||||
+++ b/include/linux/sfp.h
|
||||
@@ -563,8 +563,8 @@ static inline struct sfp_bus *sfp_bus_fi
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
|
||||
- const struct sfp_upstream_ops *ops)
|
||||
+static inline int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
|
||||
+ const struct sfp_upstream_ops *ops)
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
From b9d6ed5cdb67533feda7f221eb06f2f9f1ff5047 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 11 Oct 2019 19:33:58 +0100
|
||||
Subject: [PATCH 618/660] net: sfp: move sfp sub-state machines into separate
|
||||
functions
|
||||
|
||||
Move the SFP sub-state machines out of the main state machine function,
|
||||
in preparation for it doing a bit more with the device state. By doing
|
||||
so, we ensure that our debug after the main state machine is always
|
||||
printed.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 74 +++++++++++++++++++++++++------------------
|
||||
1 file changed, 43 insertions(+), 31 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -1479,19 +1479,34 @@ static void sfp_sm_mod_remove(struct sfp
|
||||
dev_info(sfp->dev, "module removed\n");
|
||||
}
|
||||
|
||||
-static void sfp_sm_event(struct sfp *sfp, unsigned int event)
|
||||
+/* This state machine tracks the netdev up/down state */
|
||||
+static void sfp_sm_device(struct sfp *sfp, unsigned int event)
|
||||
{
|
||||
- mutex_lock(&sfp->sm_mutex);
|
||||
+ switch (sfp->sm_dev_state) {
|
||||
+ default:
|
||||
+ if (event == SFP_E_DEV_UP)
|
||||
+ sfp->sm_dev_state = SFP_DEV_UP;
|
||||
+ break;
|
||||
|
||||
- dev_dbg(sfp->dev, "SM: enter %s:%s:%s event %s\n",
|
||||
- mod_state_to_str(sfp->sm_mod_state),
|
||||
- dev_state_to_str(sfp->sm_dev_state),
|
||||
- sm_state_to_str(sfp->sm_state),
|
||||
- event_to_str(event));
|
||||
+ case SFP_DEV_UP:
|
||||
+ if (event == SFP_E_DEV_DOWN) {
|
||||
+ /* If the module has a PHY, avoid raising TX disable
|
||||
+ * as this resets the PHY. Otherwise, raise it to
|
||||
+ * turn the laser off.
|
||||
+ */
|
||||
+ if (!sfp->mod_phy)
|
||||
+ sfp_module_tx_disable(sfp);
|
||||
+ sfp->sm_dev_state = SFP_DEV_DOWN;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
|
||||
- /* This state machine tracks the insert/remove state of
|
||||
- * the module, and handles probing the on-board EEPROM.
|
||||
- */
|
||||
+/* This state machine tracks the insert/remove state of
|
||||
+ * the module, and handles probing the on-board EEPROM.
|
||||
+ */
|
||||
+static void sfp_sm_module(struct sfp *sfp, unsigned int event)
|
||||
+{
|
||||
switch (sfp->sm_mod_state) {
|
||||
default:
|
||||
if (event == SFP_E_INSERT && sfp->attached) {
|
||||
@@ -1531,27 +1546,10 @@ static void sfp_sm_event(struct sfp *sfp
|
||||
}
|
||||
break;
|
||||
}
|
||||
+}
|
||||
|
||||
- /* This state machine tracks the netdev up/down state */
|
||||
- switch (sfp->sm_dev_state) {
|
||||
- default:
|
||||
- if (event == SFP_E_DEV_UP)
|
||||
- sfp->sm_dev_state = SFP_DEV_UP;
|
||||
- break;
|
||||
-
|
||||
- case SFP_DEV_UP:
|
||||
- if (event == SFP_E_DEV_DOWN) {
|
||||
- /* If the module has a PHY, avoid raising TX disable
|
||||
- * as this resets the PHY. Otherwise, raise it to
|
||||
- * turn the laser off.
|
||||
- */
|
||||
- if (!sfp->mod_phy)
|
||||
- sfp_module_tx_disable(sfp);
|
||||
- sfp->sm_dev_state = SFP_DEV_DOWN;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
+static void sfp_sm_main(struct sfp *sfp, unsigned int event)
|
||||
+{
|
||||
/* Some events are global */
|
||||
if (sfp->sm_state != SFP_S_DOWN &&
|
||||
(sfp->sm_mod_state != SFP_MOD_PRESENT ||
|
||||
@@ -1562,7 +1560,6 @@ static void sfp_sm_event(struct sfp *sfp
|
||||
if (sfp->mod_phy)
|
||||
sfp_sm_phy_detach(sfp);
|
||||
sfp_sm_next(sfp, SFP_S_DOWN, 0);
|
||||
- mutex_unlock(&sfp->sm_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1617,6 +1614,21 @@ static void sfp_sm_event(struct sfp *sfp
|
||||
case SFP_S_TX_DISABLE:
|
||||
break;
|
||||
}
|
||||
+}
|
||||
+
|
||||
+static void sfp_sm_event(struct sfp *sfp, unsigned int event)
|
||||
+{
|
||||
+ mutex_lock(&sfp->sm_mutex);
|
||||
+
|
||||
+ dev_dbg(sfp->dev, "SM: enter %s:%s:%s event %s\n",
|
||||
+ mod_state_to_str(sfp->sm_mod_state),
|
||||
+ dev_state_to_str(sfp->sm_dev_state),
|
||||
+ sm_state_to_str(sfp->sm_state),
|
||||
+ event_to_str(event));
|
||||
+
|
||||
+ sfp_sm_module(sfp, event);
|
||||
+ sfp_sm_device(sfp, event);
|
||||
+ sfp_sm_main(sfp, event);
|
||||
|
||||
dev_dbg(sfp->dev, "SM: exit %s:%s:%s\n",
|
||||
mod_state_to_str(sfp->sm_mod_state),
|
@ -0,0 +1,41 @@
|
||||
From 7e89b737c97a9e7a81dd1584000bc136b92f12fd Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 11 Oct 2019 22:14:47 +0100
|
||||
Subject: [PATCH 619/660] net: sfp: move tx disable on device down to main
|
||||
state machine
|
||||
|
||||
Move the tx disable assertion on device down to the main state
|
||||
machine.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 10 ++--------
|
||||
1 file changed, 2 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -1489,15 +1489,8 @@ static void sfp_sm_device(struct sfp *sf
|
||||
break;
|
||||
|
||||
case SFP_DEV_UP:
|
||||
- if (event == SFP_E_DEV_DOWN) {
|
||||
- /* If the module has a PHY, avoid raising TX disable
|
||||
- * as this resets the PHY. Otherwise, raise it to
|
||||
- * turn the laser off.
|
||||
- */
|
||||
- if (!sfp->mod_phy)
|
||||
- sfp_module_tx_disable(sfp);
|
||||
+ if (event == SFP_E_DEV_DOWN)
|
||||
sfp->sm_dev_state = SFP_DEV_DOWN;
|
||||
- }
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1559,6 +1552,7 @@ static void sfp_sm_main(struct sfp *sfp,
|
||||
sfp_sm_link_down(sfp);
|
||||
if (sfp->mod_phy)
|
||||
sfp_sm_phy_detach(sfp);
|
||||
+ sfp_module_tx_disable(sfp);
|
||||
sfp_sm_next(sfp, SFP_S_DOWN, 0);
|
||||
return;
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
From f2a1ccfc4ad4f97c98c3cc18eb32992151ce089a Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 11 Oct 2019 22:27:21 +0100
|
||||
Subject: [PATCH 620/660] net: sfp: rename sfp_sm_ins_next() as
|
||||
sfp_sm_mod_next()
|
||||
|
||||
sfp_sm_ins_next() modifies the module state machine. Change it's name
|
||||
to reflect this.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 16 ++++++++--------
|
||||
1 file changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -1180,7 +1180,7 @@ static void sfp_sm_next(struct sfp *sfp,
|
||||
sfp_sm_set_timer(sfp, timeout);
|
||||
}
|
||||
|
||||
-static void sfp_sm_ins_next(struct sfp *sfp, unsigned int state,
|
||||
+static void sfp_sm_mod_next(struct sfp *sfp, unsigned int state,
|
||||
unsigned int timeout)
|
||||
{
|
||||
sfp->sm_mod_state = state;
|
||||
@@ -1504,22 +1504,22 @@ static void sfp_sm_module(struct sfp *sf
|
||||
default:
|
||||
if (event == SFP_E_INSERT && sfp->attached) {
|
||||
sfp_module_tx_disable(sfp);
|
||||
- sfp_sm_ins_next(sfp, SFP_MOD_PROBE, T_PROBE_INIT);
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_PROBE, T_PROBE_INIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case SFP_MOD_PROBE:
|
||||
if (event == SFP_E_REMOVE) {
|
||||
- sfp_sm_ins_next(sfp, SFP_MOD_EMPTY, 0);
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
|
||||
} else if (event == SFP_E_TIMEOUT) {
|
||||
int val = sfp_sm_mod_probe(sfp);
|
||||
|
||||
if (val == 0)
|
||||
- sfp_sm_ins_next(sfp, SFP_MOD_PRESENT, 0);
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_PRESENT, 0);
|
||||
else if (val > 0)
|
||||
- sfp_sm_ins_next(sfp, SFP_MOD_HPOWER, val);
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_HPOWER, val);
|
||||
else if (val != -EAGAIN)
|
||||
- sfp_sm_ins_next(sfp, SFP_MOD_ERROR, 0);
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
|
||||
else
|
||||
sfp_sm_set_timer(sfp, T_PROBE_RETRY);
|
||||
}
|
||||
@@ -1527,7 +1527,7 @@ static void sfp_sm_module(struct sfp *sf
|
||||
|
||||
case SFP_MOD_HPOWER:
|
||||
if (event == SFP_E_TIMEOUT) {
|
||||
- sfp_sm_ins_next(sfp, SFP_MOD_PRESENT, 0);
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_PRESENT, 0);
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
@@ -1535,7 +1535,7 @@ static void sfp_sm_module(struct sfp *sf
|
||||
case SFP_MOD_ERROR:
|
||||
if (event == SFP_E_REMOVE) {
|
||||
sfp_sm_mod_remove(sfp);
|
||||
- sfp_sm_ins_next(sfp, SFP_MOD_EMPTY, 0);
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
|
||||
}
|
||||
break;
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
From d2591ea5520e2ee8fa557f96bb64c23cafac4b20 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 15 Oct 2019 10:33:13 +0100
|
||||
Subject: [PATCH 621/660] net: sfp: handle module remove outside state machine
|
||||
|
||||
Removing a module resets the module state machine back to its initial
|
||||
state. Rather than explicitly handling this in every state, handle it
|
||||
early on outside of the state machine.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 16 +++++++++-------
|
||||
1 file changed, 9 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -1500,6 +1500,14 @@ static void sfp_sm_device(struct sfp *sf
|
||||
*/
|
||||
static void sfp_sm_module(struct sfp *sfp, unsigned int event)
|
||||
{
|
||||
+ /* Handle remove event globally, it resets this state machine */
|
||||
+ if (event == SFP_E_REMOVE) {
|
||||
+ if (sfp->sm_mod_state > SFP_MOD_PROBE)
|
||||
+ sfp_sm_mod_remove(sfp);
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
switch (sfp->sm_mod_state) {
|
||||
default:
|
||||
if (event == SFP_E_INSERT && sfp->attached) {
|
||||
@@ -1509,9 +1517,7 @@ static void sfp_sm_module(struct sfp *sf
|
||||
break;
|
||||
|
||||
case SFP_MOD_PROBE:
|
||||
- if (event == SFP_E_REMOVE) {
|
||||
- sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
|
||||
- } else if (event == SFP_E_TIMEOUT) {
|
||||
+ if (event == SFP_E_TIMEOUT) {
|
||||
int val = sfp_sm_mod_probe(sfp);
|
||||
|
||||
if (val == 0)
|
||||
@@ -1533,10 +1539,6 @@ static void sfp_sm_module(struct sfp *sf
|
||||
/* fallthrough */
|
||||
case SFP_MOD_PRESENT:
|
||||
case SFP_MOD_ERROR:
|
||||
- if (event == SFP_E_REMOVE) {
|
||||
- sfp_sm_mod_remove(sfp);
|
||||
- sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
|
||||
- }
|
||||
break;
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
From 615090acb3c0b41691f3a03522ea38350387c0e4 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 15 Oct 2019 10:54:15 +0100
|
||||
Subject: [PATCH 622/660] net: sfp: rename T_PROBE_WAIT to T_SERIAL
|
||||
|
||||
SFF-8472 rev 12.2 defines the time for the serial bus to become ready
|
||||
using t_serial. Use this as our identifier for this timeout to make
|
||||
it clear what we are referring to.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 13 ++++++-------
|
||||
1 file changed, 6 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -147,11 +147,10 @@ static const enum gpiod_flags gpio_flags
|
||||
* the same length on the PCB, which means it's possible for MOD DEF 0 to
|
||||
* connect before the I2C bus on MOD DEF 1/2.
|
||||
*
|
||||
- * The SFP MSA specifies 300ms as t_init (the time taken for TX_FAULT to
|
||||
- * be deasserted) but makes no mention of the earliest time before we can
|
||||
- * access the I2C EEPROM. However, Avago modules require 300ms.
|
||||
+ * The SFF-8472 specifies t_serial ("Time from power on until module is
|
||||
+ * ready for data transmission over the two wire serial bus.") as 300ms.
|
||||
*/
|
||||
-#define T_PROBE_INIT msecs_to_jiffies(300)
|
||||
+#define T_SERIAL msecs_to_jiffies(300)
|
||||
#define T_HPOWER_LEVEL msecs_to_jiffies(300)
|
||||
#define T_PROBE_RETRY msecs_to_jiffies(100)
|
||||
|
||||
@@ -1495,8 +1494,8 @@ static void sfp_sm_device(struct sfp *sf
|
||||
}
|
||||
}
|
||||
|
||||
-/* This state machine tracks the insert/remove state of
|
||||
- * the module, and handles probing the on-board EEPROM.
|
||||
+/* This state machine tracks the insert/remove state of the module, probes
|
||||
+ * the on-board EEPROM, and sets up the power level.
|
||||
*/
|
||||
static void sfp_sm_module(struct sfp *sfp, unsigned int event)
|
||||
{
|
||||
@@ -1512,7 +1511,7 @@ static void sfp_sm_module(struct sfp *sf
|
||||
default:
|
||||
if (event == SFP_E_INSERT && sfp->attached) {
|
||||
sfp_module_tx_disable(sfp);
|
||||
- sfp_sm_mod_next(sfp, SFP_MOD_PROBE, T_PROBE_INIT);
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_PROBE, T_SERIAL);
|
||||
}
|
||||
break;
|
||||
|
@ -0,0 +1,115 @@
|
||||
From d4b8746219e8c0361e5ed6e440ab3a8a600d1f76 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 11 Oct 2019 17:24:40 +0100
|
||||
Subject: [PATCH 623/660] net: sfp: parse SFP power requirement earlier
|
||||
|
||||
Parse the SFP power requirement earlier, in preparation for moving the
|
||||
power level setup code.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 42 +++++++++++++++++++++++++++++-------------
|
||||
1 file changed, 29 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -196,6 +196,8 @@ struct sfp {
|
||||
unsigned int sm_retries;
|
||||
|
||||
struct sfp_eeprom_id id;
|
||||
+ unsigned int module_power_mW;
|
||||
+
|
||||
#if IS_ENABLED(CONFIG_HWMON)
|
||||
struct sfp_diag diag;
|
||||
struct device *hwmon_dev;
|
||||
@@ -1309,17 +1311,14 @@ static void sfp_sm_mod_init(struct sfp *
|
||||
sfp_sm_probe_phy(sfp);
|
||||
}
|
||||
|
||||
-static int sfp_sm_mod_hpower(struct sfp *sfp)
|
||||
+static int sfp_module_parse_power(struct sfp *sfp)
|
||||
{
|
||||
- u32 power;
|
||||
- u8 val;
|
||||
- int err;
|
||||
+ u32 power_mW = 1000;
|
||||
|
||||
- power = 1000;
|
||||
if (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_POWER_DECL))
|
||||
- power = 1500;
|
||||
+ power_mW = 1500;
|
||||
if (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_HIGH_POWER_LEVEL))
|
||||
- power = 2000;
|
||||
+ power_mW = 2000;
|
||||
|
||||
if (sfp->id.ext.sff8472_compliance == SFP_SFF8472_COMPLIANCE_NONE &&
|
||||
(sfp->id.ext.diagmon & (SFP_DIAGMON_DDM | SFP_DIAGMON_ADDRMODE)) !=
|
||||
@@ -1328,23 +1327,33 @@ static int sfp_sm_mod_hpower(struct sfp
|
||||
* or requires an address change sequence, so assume that
|
||||
* the module powers up in the indicated power mode.
|
||||
*/
|
||||
- if (power > sfp->max_power_mW) {
|
||||
+ if (power_mW > sfp->max_power_mW) {
|
||||
dev_err(sfp->dev,
|
||||
"Host does not support %u.%uW modules\n",
|
||||
- power / 1000, (power / 100) % 10);
|
||||
+ power_mW / 1000, (power_mW / 100) % 10);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (power > sfp->max_power_mW) {
|
||||
+ if (power_mW > sfp->max_power_mW) {
|
||||
dev_warn(sfp->dev,
|
||||
"Host does not support %u.%uW modules, module left in power mode 1\n",
|
||||
- power / 1000, (power / 100) % 10);
|
||||
+ power_mW / 1000, (power_mW / 100) % 10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (power <= 1000)
|
||||
+ sfp->module_power_mW = power_mW;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sfp_sm_mod_hpower(struct sfp *sfp)
|
||||
+{
|
||||
+ u8 val;
|
||||
+ int err;
|
||||
+
|
||||
+ if (sfp->module_power_mW <= 1000)
|
||||
return 0;
|
||||
|
||||
err = sfp_read(sfp, true, SFP_EXT_STATUS, &val, sizeof(val));
|
||||
@@ -1364,7 +1373,8 @@ static int sfp_sm_mod_hpower(struct sfp
|
||||
}
|
||||
|
||||
dev_info(sfp->dev, "Module switched to %u.%uW power level\n",
|
||||
- power / 1000, (power / 100) % 10);
|
||||
+ sfp->module_power_mW / 1000,
|
||||
+ (sfp->module_power_mW / 100) % 10);
|
||||
return T_HPOWER_LEVEL;
|
||||
|
||||
err:
|
||||
@@ -1451,6 +1461,11 @@ static int sfp_sm_mod_probe(struct sfp *
|
||||
dev_warn(sfp->dev,
|
||||
"module address swap to access page 0xA2 is not supported.\n");
|
||||
|
||||
+ /* Parse the module power requirement */
|
||||
+ ret = sfp_module_parse_power(sfp);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
ret = sfp_hwmon_insert(sfp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -1474,6 +1489,7 @@ static void sfp_sm_mod_remove(struct sfp
|
||||
sfp_module_tx_disable(sfp);
|
||||
|
||||
memset(&sfp->id, 0, sizeof(sfp->id));
|
||||
+ sfp->module_power_mW = 0;
|
||||
|
||||
dev_info(sfp->dev, "module removed\n");
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
From dca678b8838945572cf50584cb33a7199c1fd397 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Thu, 17 Oct 2019 00:24:18 +0100
|
||||
Subject: [PATCH 624/660] net: sfp: avoid power switch on address-change
|
||||
modules
|
||||
|
||||
If the module indicates that it requires an address change sequence to
|
||||
switch between address 0x50 and 0x51, which we don't support, we can't
|
||||
write to the register that controls the power mode to switch to high
|
||||
power mode. Warn the user that the module may not be functional in
|
||||
this case, and don't try to change the power mode.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 31 ++++++++++++++++++++-----------
|
||||
1 file changed, 20 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -1320,25 +1320,34 @@ static int sfp_module_parse_power(struct
|
||||
if (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_HIGH_POWER_LEVEL))
|
||||
power_mW = 2000;
|
||||
|
||||
- if (sfp->id.ext.sff8472_compliance == SFP_SFF8472_COMPLIANCE_NONE &&
|
||||
- (sfp->id.ext.diagmon & (SFP_DIAGMON_DDM | SFP_DIAGMON_ADDRMODE)) !=
|
||||
- SFP_DIAGMON_DDM) {
|
||||
- /* The module appears not to implement bus address 0xa2,
|
||||
- * or requires an address change sequence, so assume that
|
||||
- * the module powers up in the indicated power mode.
|
||||
- */
|
||||
- if (power_mW > sfp->max_power_mW) {
|
||||
+ if (power_mW > sfp->max_power_mW) {
|
||||
+ /* Module power specification exceeds the allowed maximum. */
|
||||
+ if (sfp->id.ext.sff8472_compliance ==
|
||||
+ SFP_SFF8472_COMPLIANCE_NONE &&
|
||||
+ !(sfp->id.ext.diagmon & SFP_DIAGMON_DDM)) {
|
||||
+ /* The module appears not to implement bus address
|
||||
+ * 0xa2, so assume that the module powers up in the
|
||||
+ * indicated mode.
|
||||
+ */
|
||||
dev_err(sfp->dev,
|
||||
"Host does not support %u.%uW modules\n",
|
||||
power_mW / 1000, (power_mW / 100) % 10);
|
||||
return -EINVAL;
|
||||
+ } else {
|
||||
+ dev_warn(sfp->dev,
|
||||
+ "Host does not support %u.%uW modules, module left in power mode 1\n",
|
||||
+ power_mW / 1000, (power_mW / 100) % 10);
|
||||
+ return 0;
|
||||
}
|
||||
- return 0;
|
||||
}
|
||||
|
||||
- if (power_mW > sfp->max_power_mW) {
|
||||
+ /* If the module requires a higher power mode, but also requires
|
||||
+ * an address change sequence, warn the user that the module may
|
||||
+ * not be functional.
|
||||
+ */
|
||||
+ if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE && power_mW > 1000) {
|
||||
dev_warn(sfp->dev,
|
||||
- "Host does not support %u.%uW modules, module left in power mode 1\n",
|
||||
+ "Address Change Sequence not supported but module requies %u.%uW, module may not be functional\n",
|
||||
power_mW / 1000, (power_mW / 100) % 10);
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
From df5c4d93c5a59cba0f7479a4cd4e22b50726ce88 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Thu, 17 Oct 2019 11:12:42 +0100
|
||||
Subject: [PATCH 625/660] net: sfp: control TX_DISABLE and phy only from main
|
||||
state machine
|
||||
|
||||
We initialise TX_DISABLE when the sfp cage is probed, and then
|
||||
maintain its state in the main state machine. However, the module
|
||||
state machine:
|
||||
- negates it when detecting a newly inserted module when it's already
|
||||
guaranteed to be negated.
|
||||
- negates it when the module is removed, but the main state machine
|
||||
will do this anyway.
|
||||
|
||||
Make TX_DISABLE entirely controlled by the main state machine.
|
||||
|
||||
The main state machine also probes the module for a PHY, and removes
|
||||
the PHY when the the module is removed. Hence, removing the PHY in
|
||||
sfp_sm_module_remove() is also redundant, and is a left-over from
|
||||
when we tried to probe for the PHY from the module state machine.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 9 +--------
|
||||
1 file changed, 1 insertion(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -1492,11 +1492,6 @@ static void sfp_sm_mod_remove(struct sfp
|
||||
|
||||
sfp_hwmon_remove(sfp);
|
||||
|
||||
- if (sfp->mod_phy)
|
||||
- sfp_sm_phy_detach(sfp);
|
||||
-
|
||||
- sfp_module_tx_disable(sfp);
|
||||
-
|
||||
memset(&sfp->id, 0, sizeof(sfp->id));
|
||||
sfp->module_power_mW = 0;
|
||||
|
||||
@@ -1534,10 +1529,8 @@ static void sfp_sm_module(struct sfp *sf
|
||||
|
||||
switch (sfp->sm_mod_state) {
|
||||
default:
|
||||
- if (event == SFP_E_INSERT && sfp->attached) {
|
||||
- sfp_module_tx_disable(sfp);
|
||||
+ if (event == SFP_E_INSERT && sfp->attached)
|
||||
sfp_sm_mod_next(sfp, SFP_MOD_PROBE, T_SERIAL);
|
||||
- }
|
||||
break;
|
||||
|
||||
case SFP_MOD_PROBE:
|
@ -0,0 +1,53 @@
|
||||
From 5ed0bd49b2d3ac4439c2d7f44e5a82b7cf6f409a Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 18 Oct 2019 10:09:02 +0100
|
||||
Subject: [PATCH 626/660] net: sfp: split the PHY probe from sfp_sm_mod_init()
|
||||
|
||||
Move the PHY probe into a separate function, splitting it from
|
||||
sfp_sm_mod_init(). This will allow us to eliminate the 50ms mdelay()
|
||||
inside the state machine.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 21 +++++++++++++--------
|
||||
1 file changed, 13 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -1288,14 +1288,10 @@ static void sfp_sm_fault(struct sfp *sfp
|
||||
static void sfp_sm_mod_init(struct sfp *sfp)
|
||||
{
|
||||
sfp_module_tx_enable(sfp);
|
||||
+}
|
||||
|
||||
- /* Wait t_init before indicating that the link is up, provided the
|
||||
- * current state indicates no TX_FAULT. If TX_FAULT clears before
|
||||
- * this time, that's fine too.
|
||||
- */
|
||||
- sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES);
|
||||
- sfp->sm_retries = 5;
|
||||
-
|
||||
+static void sfp_sm_probe_for_phy(struct sfp *sfp)
|
||||
+{
|
||||
/* Setting the serdes link mode is guesswork: there's no
|
||||
* field in the EEPROM which indicates what mode should
|
||||
* be used.
|
||||
@@ -1580,8 +1576,17 @@ static void sfp_sm_main(struct sfp *sfp,
|
||||
switch (sfp->sm_state) {
|
||||
case SFP_S_DOWN:
|
||||
if (sfp->sm_mod_state == SFP_MOD_PRESENT &&
|
||||
- sfp->sm_dev_state == SFP_DEV_UP)
|
||||
+ sfp->sm_dev_state == SFP_DEV_UP) {
|
||||
sfp_sm_mod_init(sfp);
|
||||
+ sfp_sm_probe_for_phy(sfp);
|
||||
+
|
||||
+ /* Wait t_init before indicating that the link is up,
|
||||
+ * provided the current state indicates no TX_FAULT. If
|
||||
+ * TX_FAULT clears before this time, that's fine too.
|
||||
+ */
|
||||
+ sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES);
|
||||
+ sfp->sm_retries = 5;
|
||||
+ }
|
||||
break;
|
||||
|
||||
case SFP_S_INIT:
|
@ -0,0 +1,130 @@
|
||||
From 0fe72afaa31f98ebd71bd6683fc47021105d0157 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 18 Oct 2019 10:21:46 +0100
|
||||
Subject: [PATCH 627/660] net: sfp: eliminate mdelay() from PHY probe
|
||||
|
||||
Rather than using mdelay() to wait before probing the PHY (which holds
|
||||
several locks, including the rtnl lock), add an extra wait state to
|
||||
the state machine to introduce the 50ms delay without holding any
|
||||
locks.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 52 +++++++++++++++++++++++++++++++++----------
|
||||
1 file changed, 40 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -52,6 +52,7 @@ enum {
|
||||
SFP_DEV_UP,
|
||||
|
||||
SFP_S_DOWN = 0,
|
||||
+ SFP_S_WAIT,
|
||||
SFP_S_INIT,
|
||||
SFP_S_WAIT_LOS,
|
||||
SFP_S_LINK_UP,
|
||||
@@ -108,6 +109,7 @@ static const char *event_to_str(unsigned
|
||||
|
||||
static const char * const sm_state_strings[] = {
|
||||
[SFP_S_DOWN] = "down",
|
||||
+ [SFP_S_WAIT] = "wait",
|
||||
[SFP_S_INIT] = "init",
|
||||
[SFP_S_WAIT_LOS] = "wait_los",
|
||||
[SFP_S_LINK_UP] = "link_up",
|
||||
@@ -139,6 +141,7 @@ static const enum gpiod_flags gpio_flags
|
||||
GPIOD_ASIS,
|
||||
};
|
||||
|
||||
+#define T_WAIT msecs_to_jiffies(50)
|
||||
#define T_INIT_JIFFIES msecs_to_jiffies(300)
|
||||
#define T_RESET_US 10
|
||||
#define T_FAULT_RECOVER msecs_to_jiffies(1000)
|
||||
@@ -159,9 +162,6 @@ static const enum gpiod_flags gpio_flags
|
||||
*/
|
||||
#define SFP_PHY_ADDR 22
|
||||
|
||||
-/* Give this long for the PHY to reset. */
|
||||
-#define T_PHY_RESET_MS 50
|
||||
-
|
||||
struct sff_data {
|
||||
unsigned int gpios;
|
||||
bool (*module_supported)(const struct sfp_eeprom_id *id);
|
||||
@@ -1202,8 +1202,6 @@ static void sfp_sm_probe_phy(struct sfp
|
||||
struct phy_device *phy;
|
||||
int err;
|
||||
|
||||
- msleep(T_PHY_RESET_MS);
|
||||
-
|
||||
phy = mdiobus_scan(sfp->i2c_mii, SFP_PHY_ADDR);
|
||||
if (phy == ERR_PTR(-ENODEV)) {
|
||||
dev_info(sfp->dev, "no PHY detected\n");
|
||||
@@ -1558,6 +1556,8 @@ static void sfp_sm_module(struct sfp *sf
|
||||
|
||||
static void sfp_sm_main(struct sfp *sfp, unsigned int event)
|
||||
{
|
||||
+ unsigned long timeout;
|
||||
+
|
||||
/* Some events are global */
|
||||
if (sfp->sm_state != SFP_S_DOWN &&
|
||||
(sfp->sm_mod_state != SFP_MOD_PRESENT ||
|
||||
@@ -1575,17 +1575,45 @@ static void sfp_sm_main(struct sfp *sfp,
|
||||
/* The main state machine */
|
||||
switch (sfp->sm_state) {
|
||||
case SFP_S_DOWN:
|
||||
- if (sfp->sm_mod_state == SFP_MOD_PRESENT &&
|
||||
- sfp->sm_dev_state == SFP_DEV_UP) {
|
||||
- sfp_sm_mod_init(sfp);
|
||||
- sfp_sm_probe_for_phy(sfp);
|
||||
+ if (sfp->sm_mod_state != SFP_MOD_PRESENT ||
|
||||
+ sfp->sm_dev_state != SFP_DEV_UP)
|
||||
+ break;
|
||||
+
|
||||
+ sfp_sm_mod_init(sfp);
|
||||
+
|
||||
+ /* Initialise the fault clearance retries */
|
||||
+ sfp->sm_retries = 5;
|
||||
+
|
||||
+ /* We need to check the TX_FAULT state, which is not defined
|
||||
+ * while TX_DISABLE is asserted. The earliest we want to do
|
||||
+ * anything (such as probe for a PHY) is 50ms.
|
||||
+ */
|
||||
+ sfp_sm_next(sfp, SFP_S_WAIT, T_WAIT);
|
||||
+ break;
|
||||
+
|
||||
+ case SFP_S_WAIT:
|
||||
+ if (event != SFP_E_TIMEOUT)
|
||||
+ break;
|
||||
+
|
||||
+ sfp_sm_probe_for_phy(sfp);
|
||||
|
||||
+ if (sfp->state & SFP_F_TX_FAULT) {
|
||||
/* Wait t_init before indicating that the link is up,
|
||||
* provided the current state indicates no TX_FAULT. If
|
||||
* TX_FAULT clears before this time, that's fine too.
|
||||
*/
|
||||
- sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES);
|
||||
- sfp->sm_retries = 5;
|
||||
+ timeout = T_INIT_JIFFIES;
|
||||
+ if (timeout > T_WAIT)
|
||||
+ timeout -= T_WAIT;
|
||||
+ else
|
||||
+ timeout = 1;
|
||||
+
|
||||
+ sfp_sm_next(sfp, SFP_S_INIT, timeout);
|
||||
+ } else {
|
||||
+ /* TX_FAULT is not asserted, assume the module has
|
||||
+ * finished initialising.
|
||||
+ */
|
||||
+ goto init_done;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1593,7 +1621,7 @@ static void sfp_sm_main(struct sfp *sfp,
|
||||
if (event == SFP_E_TIMEOUT && sfp->state & SFP_F_TX_FAULT)
|
||||
sfp_sm_fault(sfp, true);
|
||||
else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR)
|
||||
- sfp_sm_link_check_los(sfp);
|
||||
+ init_done: sfp_sm_link_check_los(sfp);
|
||||
break;
|
||||
|
||||
case SFP_S_WAIT_LOS:
|
@ -0,0 +1,69 @@
|
||||
From 2aa424ee7fbe43e2cd24e28c2f6388c4e1796bd2 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 18 Oct 2019 09:58:33 +0100
|
||||
Subject: [PATCH 628/660] net: sfp: allow fault processing to transition to
|
||||
other states
|
||||
|
||||
Add the next state to sfp_sm_fault() so that it can branch to other
|
||||
states. This will be necessary to improve the initialisation path.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 12 ++++++------
|
||||
1 file changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -1269,7 +1269,7 @@ static bool sfp_los_event_inactive(struc
|
||||
event == SFP_E_LOS_LOW);
|
||||
}
|
||||
|
||||
-static void sfp_sm_fault(struct sfp *sfp, bool warn)
|
||||
+static void sfp_sm_fault(struct sfp *sfp, unsigned int next_state, bool warn)
|
||||
{
|
||||
if (sfp->sm_retries && !--sfp->sm_retries) {
|
||||
dev_err(sfp->dev,
|
||||
@@ -1279,7 +1279,7 @@ static void sfp_sm_fault(struct sfp *sfp
|
||||
if (warn)
|
||||
dev_err(sfp->dev, "module transmit fault indicated\n");
|
||||
|
||||
- sfp_sm_next(sfp, SFP_S_TX_FAULT, T_FAULT_RECOVER);
|
||||
+ sfp_sm_next(sfp, next_state, T_FAULT_RECOVER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1619,14 +1619,14 @@ static void sfp_sm_main(struct sfp *sfp,
|
||||
|
||||
case SFP_S_INIT:
|
||||
if (event == SFP_E_TIMEOUT && sfp->state & SFP_F_TX_FAULT)
|
||||
- sfp_sm_fault(sfp, true);
|
||||
+ sfp_sm_fault(sfp, SFP_S_TX_FAULT, true);
|
||||
else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR)
|
||||
init_done: sfp_sm_link_check_los(sfp);
|
||||
break;
|
||||
|
||||
case SFP_S_WAIT_LOS:
|
||||
if (event == SFP_E_TX_FAULT)
|
||||
- sfp_sm_fault(sfp, true);
|
||||
+ sfp_sm_fault(sfp, SFP_S_TX_FAULT, true);
|
||||
else if (sfp_los_event_inactive(sfp, event))
|
||||
sfp_sm_link_up(sfp);
|
||||
break;
|
||||
@@ -1634,7 +1634,7 @@ static void sfp_sm_main(struct sfp *sfp,
|
||||
case SFP_S_LINK_UP:
|
||||
if (event == SFP_E_TX_FAULT) {
|
||||
sfp_sm_link_down(sfp);
|
||||
- sfp_sm_fault(sfp, true);
|
||||
+ sfp_sm_fault(sfp, SFP_S_TX_FAULT, true);
|
||||
} else if (sfp_los_event_active(sfp, event)) {
|
||||
sfp_sm_link_down(sfp);
|
||||
sfp_sm_next(sfp, SFP_S_WAIT_LOS, 0);
|
||||
@@ -1650,7 +1650,7 @@ static void sfp_sm_main(struct sfp *sfp,
|
||||
|
||||
case SFP_S_REINIT:
|
||||
if (event == SFP_E_TIMEOUT && sfp->state & SFP_F_TX_FAULT) {
|
||||
- sfp_sm_fault(sfp, false);
|
||||
+ sfp_sm_fault(sfp, SFP_S_TX_FAULT, false);
|
||||
} else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR) {
|
||||
dev_info(sfp->dev, "module transmit fault recovered\n");
|
||||
sfp_sm_link_check_los(sfp);
|
@ -0,0 +1,80 @@
|
||||
From 38b62a12231be4b86fc5ca5477579d29831c02a5 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 18 Oct 2019 10:31:07 +0100
|
||||
Subject: [PATCH 629/660] net: sfp: ensure TX_FAULT has deasserted before
|
||||
probing the PHY
|
||||
|
||||
TX_FAULT should be deasserted to indicate that the module has completed
|
||||
its initialisation. This may include the on-board PHY, so wait until
|
||||
the module has deasserted TX_FAULT before probing the PHY.
|
||||
|
||||
This means that we need an extra state to handle a TX_FAULT that
|
||||
remains set for longer than t_init, since using the existing handling
|
||||
state would bypass the PHY probe.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 31 +++++++++++++++++++++++++------
|
||||
1 file changed, 25 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -54,6 +54,7 @@ enum {
|
||||
SFP_S_DOWN = 0,
|
||||
SFP_S_WAIT,
|
||||
SFP_S_INIT,
|
||||
+ SFP_S_INIT_TX_FAULT,
|
||||
SFP_S_WAIT_LOS,
|
||||
SFP_S_LINK_UP,
|
||||
SFP_S_TX_FAULT,
|
||||
@@ -111,6 +112,7 @@ static const char * const sm_state_strin
|
||||
[SFP_S_DOWN] = "down",
|
||||
[SFP_S_WAIT] = "wait",
|
||||
[SFP_S_INIT] = "init",
|
||||
+ [SFP_S_INIT_TX_FAULT] = "init_tx_fault",
|
||||
[SFP_S_WAIT_LOS] = "wait_los",
|
||||
[SFP_S_LINK_UP] = "link_up",
|
||||
[SFP_S_TX_FAULT] = "tx_fault",
|
||||
@@ -1595,8 +1597,6 @@ static void sfp_sm_main(struct sfp *sfp,
|
||||
if (event != SFP_E_TIMEOUT)
|
||||
break;
|
||||
|
||||
- sfp_sm_probe_for_phy(sfp);
|
||||
-
|
||||
if (sfp->state & SFP_F_TX_FAULT) {
|
||||
/* Wait t_init before indicating that the link is up,
|
||||
* provided the current state indicates no TX_FAULT. If
|
||||
@@ -1618,10 +1618,29 @@ static void sfp_sm_main(struct sfp *sfp,
|
||||
break;
|
||||
|
||||
case SFP_S_INIT:
|
||||
- if (event == SFP_E_TIMEOUT && sfp->state & SFP_F_TX_FAULT)
|
||||
- sfp_sm_fault(sfp, SFP_S_TX_FAULT, true);
|
||||
- else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR)
|
||||
- init_done: sfp_sm_link_check_los(sfp);
|
||||
+ if (event == SFP_E_TIMEOUT && sfp->state & SFP_F_TX_FAULT) {
|
||||
+ /* TX_FAULT is still asserted after t_init, so assume
|
||||
+ * there is a fault.
|
||||
+ */
|
||||
+ sfp_sm_fault(sfp, SFP_S_INIT_TX_FAULT,
|
||||
+ sfp->sm_retries == 5);
|
||||
+ } else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR) {
|
||||
+ init_done: /* TX_FAULT deasserted or we timed out with TX_FAULT
|
||||
+ * clear. Probe for the PHY and check the LOS state.
|
||||
+ */
|
||||
+ sfp_sm_probe_for_phy(sfp);
|
||||
+ sfp_sm_link_check_los(sfp);
|
||||
+
|
||||
+ /* Reset the fault retry count */
|
||||
+ sfp->sm_retries = 5;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case SFP_S_INIT_TX_FAULT:
|
||||
+ if (event == SFP_E_TIMEOUT) {
|
||||
+ sfp_module_tx_fault_reset(sfp);
|
||||
+ sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES);
|
||||
+ }
|
||||
break;
|
||||
|
||||
case SFP_S_WAIT_LOS:
|
@ -0,0 +1,153 @@
|
||||
From ec6036a58f979c66bbd5cd9d0d1c783a98c2c644 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 5 Nov 2019 12:57:40 +0000
|
||||
Subject: [PATCH 630/660] net: sfp: track upstream's attachment state in state
|
||||
machine
|
||||
|
||||
Track the upstream's attachment state in the state machine rather than
|
||||
maintaining a boolean, which ensures that we have a strict order of
|
||||
ATTACH followed by an UP event - we can never believe that a newly
|
||||
attached upstream will be anything but down.
|
||||
|
||||
Rearrange the order of state machines so we run the module state
|
||||
machine after the upstream device's state machine, so the module state
|
||||
machine can check the current state of the device and take action to
|
||||
e.g. reset back to empty state when the upstream is detached.
|
||||
|
||||
This is to allow the module detection to run independently of the
|
||||
network device becoming available.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 42 +++++++++++++++++++++++++++++-------------
|
||||
1 file changed, 29 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -34,6 +34,8 @@ enum {
|
||||
|
||||
SFP_E_INSERT = 0,
|
||||
SFP_E_REMOVE,
|
||||
+ SFP_E_DEV_ATTACH,
|
||||
+ SFP_E_DEV_DETACH,
|
||||
SFP_E_DEV_DOWN,
|
||||
SFP_E_DEV_UP,
|
||||
SFP_E_TX_FAULT,
|
||||
@@ -48,7 +50,8 @@ enum {
|
||||
SFP_MOD_PRESENT,
|
||||
SFP_MOD_ERROR,
|
||||
|
||||
- SFP_DEV_DOWN = 0,
|
||||
+ SFP_DEV_DETACHED = 0,
|
||||
+ SFP_DEV_DOWN,
|
||||
SFP_DEV_UP,
|
||||
|
||||
SFP_S_DOWN = 0,
|
||||
@@ -78,6 +81,7 @@ static const char *mod_state_to_str(unsi
|
||||
}
|
||||
|
||||
static const char * const dev_state_strings[] = {
|
||||
+ [SFP_DEV_DETACHED] = "detached",
|
||||
[SFP_DEV_DOWN] = "down",
|
||||
[SFP_DEV_UP] = "up",
|
||||
};
|
||||
@@ -92,6 +96,8 @@ static const char *dev_state_to_str(unsi
|
||||
static const char * const event_strings[] = {
|
||||
[SFP_E_INSERT] = "insert",
|
||||
[SFP_E_REMOVE] = "remove",
|
||||
+ [SFP_E_DEV_ATTACH] = "dev_attach",
|
||||
+ [SFP_E_DEV_DETACH] = "dev_detach",
|
||||
[SFP_E_DEV_DOWN] = "dev_down",
|
||||
[SFP_E_DEV_UP] = "dev_up",
|
||||
[SFP_E_TX_FAULT] = "tx_fault",
|
||||
@@ -186,7 +192,6 @@ struct sfp {
|
||||
struct gpio_desc *gpio[GPIO_MAX];
|
||||
int gpio_irq[GPIO_MAX];
|
||||
|
||||
- bool attached;
|
||||
struct mutex st_mutex; /* Protects state */
|
||||
unsigned int state;
|
||||
struct delayed_work poll;
|
||||
@@ -1494,17 +1499,26 @@ static void sfp_sm_mod_remove(struct sfp
|
||||
dev_info(sfp->dev, "module removed\n");
|
||||
}
|
||||
|
||||
-/* This state machine tracks the netdev up/down state */
|
||||
+/* This state machine tracks the upstream's state */
|
||||
static void sfp_sm_device(struct sfp *sfp, unsigned int event)
|
||||
{
|
||||
switch (sfp->sm_dev_state) {
|
||||
default:
|
||||
- if (event == SFP_E_DEV_UP)
|
||||
+ if (event == SFP_E_DEV_ATTACH)
|
||||
+ sfp->sm_dev_state = SFP_DEV_DOWN;
|
||||
+ break;
|
||||
+
|
||||
+ case SFP_DEV_DOWN:
|
||||
+ if (event == SFP_E_DEV_DETACH)
|
||||
+ sfp->sm_dev_state = SFP_DEV_DETACHED;
|
||||
+ else if (event == SFP_E_DEV_UP)
|
||||
sfp->sm_dev_state = SFP_DEV_UP;
|
||||
break;
|
||||
|
||||
case SFP_DEV_UP:
|
||||
- if (event == SFP_E_DEV_DOWN)
|
||||
+ if (event == SFP_E_DEV_DETACH)
|
||||
+ sfp->sm_dev_state = SFP_DEV_DETACHED;
|
||||
+ else if (event == SFP_E_DEV_DOWN)
|
||||
sfp->sm_dev_state = SFP_DEV_DOWN;
|
||||
break;
|
||||
}
|
||||
@@ -1515,17 +1529,20 @@ static void sfp_sm_device(struct sfp *sf
|
||||
*/
|
||||
static void sfp_sm_module(struct sfp *sfp, unsigned int event)
|
||||
{
|
||||
- /* Handle remove event globally, it resets this state machine */
|
||||
- if (event == SFP_E_REMOVE) {
|
||||
+ /* Handle remove event globally, it resets this state machine.
|
||||
+ * Also deal with upstream detachment.
|
||||
+ */
|
||||
+ if (event == SFP_E_REMOVE || sfp->sm_dev_state < SFP_DEV_DOWN) {
|
||||
if (sfp->sm_mod_state > SFP_MOD_PROBE)
|
||||
sfp_sm_mod_remove(sfp);
|
||||
- sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
|
||||
+ if (sfp->sm_mod_state != SFP_MOD_EMPTY)
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (sfp->sm_mod_state) {
|
||||
default:
|
||||
- if (event == SFP_E_INSERT && sfp->attached)
|
||||
+ if (event == SFP_E_INSERT)
|
||||
sfp_sm_mod_next(sfp, SFP_MOD_PROBE, T_SERIAL);
|
||||
break;
|
||||
|
||||
@@ -1691,8 +1708,8 @@ static void sfp_sm_event(struct sfp *sfp
|
||||
sm_state_to_str(sfp->sm_state),
|
||||
event_to_str(event));
|
||||
|
||||
- sfp_sm_module(sfp, event);
|
||||
sfp_sm_device(sfp, event);
|
||||
+ sfp_sm_module(sfp, event);
|
||||
sfp_sm_main(sfp, event);
|
||||
|
||||
dev_dbg(sfp->dev, "SM: exit %s:%s:%s\n",
|
||||
@@ -1705,15 +1722,14 @@ static void sfp_sm_event(struct sfp *sfp
|
||||
|
||||
static void sfp_attach(struct sfp *sfp)
|
||||
{
|
||||
- sfp->attached = true;
|
||||
+ sfp_sm_event(sfp, SFP_E_DEV_ATTACH);
|
||||
if (sfp->state & SFP_F_PRESENT)
|
||||
sfp_sm_event(sfp, SFP_E_INSERT);
|
||||
}
|
||||
|
||||
static void sfp_detach(struct sfp *sfp)
|
||||
{
|
||||
- sfp->attached = false;
|
||||
- sfp_sm_event(sfp, SFP_E_REMOVE);
|
||||
+ sfp_sm_event(sfp, SFP_E_DEV_DETACH);
|
||||
}
|
||||
|
||||
static void sfp_start(struct sfp *sfp)
|
@ -0,0 +1,184 @@
|
||||
From fdff863a4ce3677907f64396e34c45025abb6600 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 5 Nov 2019 12:59:36 +0000
|
||||
Subject: [PATCH 631/660] net: sfp: split power mode switching from probe
|
||||
|
||||
Switch the power mode switching from the probe, so that we don't
|
||||
repeatedly re-probe the SFP device if there is a problem accessing
|
||||
the registers at I2C address 0x51.
|
||||
|
||||
In splitting this out, we can also fix a bug where we leave the module
|
||||
in high-power mode when the upstream device is detached but the module
|
||||
is still inserted.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 101 ++++++++++++++++++++++++++----------------
|
||||
1 file changed, 64 insertions(+), 37 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -47,6 +47,7 @@ enum {
|
||||
SFP_MOD_EMPTY = 0,
|
||||
SFP_MOD_PROBE,
|
||||
SFP_MOD_HPOWER,
|
||||
+ SFP_MOD_WAITPWR,
|
||||
SFP_MOD_PRESENT,
|
||||
SFP_MOD_ERROR,
|
||||
|
||||
@@ -69,6 +70,7 @@ static const char * const mod_state_str
|
||||
[SFP_MOD_EMPTY] = "empty",
|
||||
[SFP_MOD_PROBE] = "probe",
|
||||
[SFP_MOD_HPOWER] = "hpower",
|
||||
+ [SFP_MOD_WAITPWR] = "waitpwr",
|
||||
[SFP_MOD_PRESENT] = "present",
|
||||
[SFP_MOD_ERROR] = "error",
|
||||
};
|
||||
@@ -1358,37 +1360,34 @@ static int sfp_module_parse_power(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int sfp_sm_mod_hpower(struct sfp *sfp)
|
||||
+static int sfp_sm_mod_hpower(struct sfp *sfp, bool enable)
|
||||
{
|
||||
u8 val;
|
||||
int err;
|
||||
|
||||
- if (sfp->module_power_mW <= 1000)
|
||||
- return 0;
|
||||
-
|
||||
err = sfp_read(sfp, true, SFP_EXT_STATUS, &val, sizeof(val));
|
||||
if (err != sizeof(val)) {
|
||||
dev_err(sfp->dev, "Failed to read EEPROM: %d\n", err);
|
||||
- err = -EAGAIN;
|
||||
- goto err;
|
||||
+ return -EAGAIN;
|
||||
}
|
||||
|
||||
- val |= BIT(0);
|
||||
+ if (enable)
|
||||
+ val |= BIT(0);
|
||||
+ else
|
||||
+ val &= ~BIT(0);
|
||||
|
||||
err = sfp_write(sfp, true, SFP_EXT_STATUS, &val, sizeof(val));
|
||||
if (err != sizeof(val)) {
|
||||
dev_err(sfp->dev, "Failed to write EEPROM: %d\n", err);
|
||||
- err = -EAGAIN;
|
||||
- goto err;
|
||||
+ return -EAGAIN;
|
||||
}
|
||||
|
||||
- dev_info(sfp->dev, "Module switched to %u.%uW power level\n",
|
||||
- sfp->module_power_mW / 1000,
|
||||
- (sfp->module_power_mW / 100) % 10);
|
||||
- return T_HPOWER_LEVEL;
|
||||
+ if (enable)
|
||||
+ dev_info(sfp->dev, "Module switched to %u.%uW power level\n",
|
||||
+ sfp->module_power_mW / 1000,
|
||||
+ (sfp->module_power_mW / 100) % 10);
|
||||
|
||||
-err:
|
||||
- return err;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static int sfp_sm_mod_probe(struct sfp *sfp)
|
||||
@@ -1484,7 +1483,7 @@ static int sfp_sm_mod_probe(struct sfp *
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- return sfp_sm_mod_hpower(sfp);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static void sfp_sm_mod_remove(struct sfp *sfp)
|
||||
@@ -1529,13 +1528,22 @@ static void sfp_sm_device(struct sfp *sf
|
||||
*/
|
||||
static void sfp_sm_module(struct sfp *sfp, unsigned int event)
|
||||
{
|
||||
- /* Handle remove event globally, it resets this state machine.
|
||||
- * Also deal with upstream detachment.
|
||||
- */
|
||||
- if (event == SFP_E_REMOVE || sfp->sm_dev_state < SFP_DEV_DOWN) {
|
||||
+ int err;
|
||||
+
|
||||
+ /* Handle remove event globally, it resets this state machine */
|
||||
+ if (event == SFP_E_REMOVE) {
|
||||
if (sfp->sm_mod_state > SFP_MOD_PROBE)
|
||||
sfp_sm_mod_remove(sfp);
|
||||
- if (sfp->sm_mod_state != SFP_MOD_EMPTY)
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Handle device detach globally */
|
||||
+ if (sfp->sm_dev_state < SFP_DEV_DOWN) {
|
||||
+ if (sfp->module_power_mW > 1000 &&
|
||||
+ sfp->sm_mod_state > SFP_MOD_HPOWER)
|
||||
+ sfp_sm_mod_hpower(sfp, false);
|
||||
+ if (sfp->sm_mod_state > SFP_MOD_EMPTY)
|
||||
sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
|
||||
return;
|
||||
}
|
||||
@@ -1547,26 +1555,45 @@ static void sfp_sm_module(struct sfp *sf
|
||||
break;
|
||||
|
||||
case SFP_MOD_PROBE:
|
||||
- if (event == SFP_E_TIMEOUT) {
|
||||
- int val = sfp_sm_mod_probe(sfp);
|
||||
+ if (event != SFP_E_TIMEOUT)
|
||||
+ break;
|
||||
|
||||
- if (val == 0)
|
||||
- sfp_sm_mod_next(sfp, SFP_MOD_PRESENT, 0);
|
||||
- else if (val > 0)
|
||||
- sfp_sm_mod_next(sfp, SFP_MOD_HPOWER, val);
|
||||
- else if (val != -EAGAIN)
|
||||
- sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
|
||||
- else
|
||||
- sfp_sm_set_timer(sfp, T_PROBE_RETRY);
|
||||
+ err = sfp_sm_mod_probe(sfp);
|
||||
+ if (err == -EAGAIN) {
|
||||
+ sfp_sm_set_timer(sfp, T_PROBE_RETRY);
|
||||
+ break;
|
||||
}
|
||||
- break;
|
||||
+ if (err < 0) {
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* If this is a power level 1 module, we are done */
|
||||
+ if (sfp->module_power_mW <= 1000)
|
||||
+ goto insert;
|
||||
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_HPOWER, 0);
|
||||
+ /* fall through */
|
||||
case SFP_MOD_HPOWER:
|
||||
- if (event == SFP_E_TIMEOUT) {
|
||||
- sfp_sm_mod_next(sfp, SFP_MOD_PRESENT, 0);
|
||||
+ /* Enable high power mode */
|
||||
+ err = sfp_sm_mod_hpower(sfp, true);
|
||||
+ if (err == 0)
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_WAITPWR, T_HPOWER_LEVEL);
|
||||
+ else if (err != -EAGAIN)
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
|
||||
+ else
|
||||
+ sfp_sm_set_timer(sfp, T_PROBE_RETRY);
|
||||
+ break;
|
||||
+
|
||||
+ case SFP_MOD_WAITPWR:
|
||||
+ /* Wait for T_HPOWER_LEVEL to time out */
|
||||
+ if (event != SFP_E_TIMEOUT)
|
||||
break;
|
||||
- }
|
||||
- /* fallthrough */
|
||||
+
|
||||
+ insert:
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_PRESENT, 0);
|
||||
+ break;
|
||||
+
|
||||
case SFP_MOD_PRESENT:
|
||||
case SFP_MOD_ERROR:
|
||||
break;
|
@ -0,0 +1,159 @@
|
||||
From 57cbf7453551db1df619b79410d79fc418d862d5 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 5 Nov 2019 13:00:45 +0000
|
||||
Subject: [PATCH 632/660] net: sfp: move module insert reporting out of probe
|
||||
|
||||
Move the module insertion reporting out of the probe handling, but
|
||||
after we have detected that the upstream has attached (since that is
|
||||
whom we are reporting insertion to.)
|
||||
|
||||
Only report module removal if we had previously reported a module
|
||||
insertion.
|
||||
|
||||
This gives cleaner semantics, and means we can probe the module before
|
||||
we have an upstream attached.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 58 +++++++++++++++++++++++++++++--------------
|
||||
1 file changed, 40 insertions(+), 18 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -45,11 +45,12 @@ enum {
|
||||
SFP_E_TIMEOUT,
|
||||
|
||||
SFP_MOD_EMPTY = 0,
|
||||
+ SFP_MOD_ERROR,
|
||||
SFP_MOD_PROBE,
|
||||
+ SFP_MOD_WAITDEV,
|
||||
SFP_MOD_HPOWER,
|
||||
SFP_MOD_WAITPWR,
|
||||
SFP_MOD_PRESENT,
|
||||
- SFP_MOD_ERROR,
|
||||
|
||||
SFP_DEV_DETACHED = 0,
|
||||
SFP_DEV_DOWN,
|
||||
@@ -68,11 +69,12 @@ enum {
|
||||
|
||||
static const char * const mod_state_strings[] = {
|
||||
[SFP_MOD_EMPTY] = "empty",
|
||||
+ [SFP_MOD_ERROR] = "error",
|
||||
[SFP_MOD_PROBE] = "probe",
|
||||
+ [SFP_MOD_WAITDEV] = "waitdev",
|
||||
[SFP_MOD_HPOWER] = "hpower",
|
||||
[SFP_MOD_WAITPWR] = "waitpwr",
|
||||
[SFP_MOD_PRESENT] = "present",
|
||||
- [SFP_MOD_ERROR] = "error",
|
||||
};
|
||||
|
||||
static const char *mod_state_to_str(unsigned short mod_state)
|
||||
@@ -1479,16 +1481,13 @@ static int sfp_sm_mod_probe(struct sfp *
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- ret = sfp_module_insert(sfp->sfp_bus, &sfp->id);
|
||||
- if (ret < 0)
|
||||
- return ret;
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sfp_sm_mod_remove(struct sfp *sfp)
|
||||
{
|
||||
- sfp_module_remove(sfp->sfp_bus);
|
||||
+ if (sfp->sm_mod_state > SFP_MOD_WAITDEV)
|
||||
+ sfp_module_remove(sfp->sfp_bus);
|
||||
|
||||
sfp_hwmon_remove(sfp);
|
||||
|
||||
@@ -1539,12 +1538,12 @@ static void sfp_sm_module(struct sfp *sf
|
||||
}
|
||||
|
||||
/* Handle device detach globally */
|
||||
- if (sfp->sm_dev_state < SFP_DEV_DOWN) {
|
||||
+ if (sfp->sm_dev_state < SFP_DEV_DOWN &&
|
||||
+ sfp->sm_mod_state > SFP_MOD_WAITDEV) {
|
||||
if (sfp->module_power_mW > 1000 &&
|
||||
sfp->sm_mod_state > SFP_MOD_HPOWER)
|
||||
sfp_sm_mod_hpower(sfp, false);
|
||||
- if (sfp->sm_mod_state > SFP_MOD_EMPTY)
|
||||
- sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_WAITDEV, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1555,6 +1554,7 @@ static void sfp_sm_module(struct sfp *sf
|
||||
break;
|
||||
|
||||
case SFP_MOD_PROBE:
|
||||
+ /* Wait for T_PROBE_INIT to time out */
|
||||
if (event != SFP_E_TIMEOUT)
|
||||
break;
|
||||
|
||||
@@ -1568,6 +1568,20 @@ static void sfp_sm_module(struct sfp *sf
|
||||
break;
|
||||
}
|
||||
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_WAITDEV, 0);
|
||||
+ /* fall through */
|
||||
+ case SFP_MOD_WAITDEV:
|
||||
+ /* Ensure that the device is attached before proceeding */
|
||||
+ if (sfp->sm_dev_state < SFP_DEV_DOWN)
|
||||
+ break;
|
||||
+
|
||||
+ /* Report the module insertion to the upstream device */
|
||||
+ err = sfp_module_insert(sfp->sfp_bus, &sfp->id);
|
||||
+ if (err < 0) {
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
/* If this is a power level 1 module, we are done */
|
||||
if (sfp->module_power_mW <= 1000)
|
||||
goto insert;
|
||||
@@ -1577,12 +1591,17 @@ static void sfp_sm_module(struct sfp *sf
|
||||
case SFP_MOD_HPOWER:
|
||||
/* Enable high power mode */
|
||||
err = sfp_sm_mod_hpower(sfp, true);
|
||||
- if (err == 0)
|
||||
- sfp_sm_mod_next(sfp, SFP_MOD_WAITPWR, T_HPOWER_LEVEL);
|
||||
- else if (err != -EAGAIN)
|
||||
- sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
|
||||
- else
|
||||
- sfp_sm_set_timer(sfp, T_PROBE_RETRY);
|
||||
+ if (err < 0) {
|
||||
+ if (err != -EAGAIN) {
|
||||
+ sfp_module_remove(sfp->sfp_bus);
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
|
||||
+ } else {
|
||||
+ sfp_sm_set_timer(sfp, T_PROBE_RETRY);
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ sfp_sm_mod_next(sfp, SFP_MOD_WAITPWR, T_HPOWER_LEVEL);
|
||||
break;
|
||||
|
||||
case SFP_MOD_WAITPWR:
|
||||
@@ -1750,8 +1769,6 @@ static void sfp_sm_event(struct sfp *sfp
|
||||
static void sfp_attach(struct sfp *sfp)
|
||||
{
|
||||
sfp_sm_event(sfp, SFP_E_DEV_ATTACH);
|
||||
- if (sfp->state & SFP_F_PRESENT)
|
||||
- sfp_sm_event(sfp, SFP_E_INSERT);
|
||||
}
|
||||
|
||||
static void sfp_detach(struct sfp *sfp)
|
||||
@@ -2001,6 +2018,11 @@ static int sfp_probe(struct platform_dev
|
||||
sfp->state |= SFP_F_RATE_SELECT;
|
||||
sfp_set_state(sfp, sfp->state);
|
||||
sfp_module_tx_disable(sfp);
|
||||
+ if (sfp->state & SFP_F_PRESENT) {
|
||||
+ rtnl_lock();
|
||||
+ sfp_sm_event(sfp, SFP_E_INSERT);
|
||||
+ rtnl_unlock();
|
||||
+ }
|
||||
|
||||
for (i = 0; i < GPIO_MAX; i++) {
|
||||
if (gpio_flags[i] != GPIOD_IN || !sfp->gpio[i])
|
@ -0,0 +1,110 @@
|
||||
From fb56cd08880aff8fb030e684fa4311bef712a499 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 5 Nov 2019 13:02:30 +0000
|
||||
Subject: [PATCH 633/660] net: sfp: allow sfp to probe slow to initialise GPON
|
||||
modules
|
||||
|
||||
Some GPON modules (e.g. Huawei MA5671A) take a significant amount of
|
||||
time to start responding on the I2C bus, contary to the SFF
|
||||
specifications.
|
||||
|
||||
Work around this by implementing a two-level timeout strategy, where
|
||||
we initially quickly retry for the module, and then use a slower retry
|
||||
after we exceed a maximum number of quick attempts.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 38 ++++++++++++++++++++++++++++----------
|
||||
1 file changed, 28 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -165,9 +165,12 @@ static const enum gpiod_flags gpio_flags
|
||||
* The SFF-8472 specifies t_serial ("Time from power on until module is
|
||||
* ready for data transmission over the two wire serial bus.") as 300ms.
|
||||
*/
|
||||
-#define T_SERIAL msecs_to_jiffies(300)
|
||||
-#define T_HPOWER_LEVEL msecs_to_jiffies(300)
|
||||
-#define T_PROBE_RETRY msecs_to_jiffies(100)
|
||||
+#define T_SERIAL msecs_to_jiffies(300)
|
||||
+#define T_HPOWER_LEVEL msecs_to_jiffies(300)
|
||||
+#define T_PROBE_RETRY_INIT msecs_to_jiffies(100)
|
||||
+#define R_PROBE_RETRY_INIT 10
|
||||
+#define T_PROBE_RETRY_SLOW msecs_to_jiffies(5000)
|
||||
+#define R_PROBE_RETRY_SLOW 12
|
||||
|
||||
/* SFP modules appear to always have their PHY configured for bus address
|
||||
* 0x56 (which with mdio-i2c, translates to a PHY address of 22).
|
||||
@@ -202,6 +205,8 @@ struct sfp {
|
||||
struct delayed_work timeout;
|
||||
struct mutex sm_mutex; /* Protects state machine */
|
||||
unsigned char sm_mod_state;
|
||||
+ unsigned char sm_mod_tries_init;
|
||||
+ unsigned char sm_mod_tries;
|
||||
unsigned char sm_dev_state;
|
||||
unsigned short sm_state;
|
||||
unsigned int sm_retries;
|
||||
@@ -1392,7 +1397,7 @@ static int sfp_sm_mod_hpower(struct sfp
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int sfp_sm_mod_probe(struct sfp *sfp)
|
||||
+static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
|
||||
{
|
||||
/* SFP module inserted - read I2C data */
|
||||
struct sfp_eeprom_id id;
|
||||
@@ -1402,7 +1407,8 @@ static int sfp_sm_mod_probe(struct sfp *
|
||||
|
||||
ret = sfp_read(sfp, false, 0, &id, sizeof(id));
|
||||
if (ret < 0) {
|
||||
- dev_err(sfp->dev, "failed to read EEPROM: %d\n", ret);
|
||||
+ if (report)
|
||||
+ dev_err(sfp->dev, "failed to read EEPROM: %d\n", ret);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
@@ -1549,8 +1555,11 @@ static void sfp_sm_module(struct sfp *sf
|
||||
|
||||
switch (sfp->sm_mod_state) {
|
||||
default:
|
||||
- if (event == SFP_E_INSERT)
|
||||
+ if (event == SFP_E_INSERT) {
|
||||
sfp_sm_mod_next(sfp, SFP_MOD_PROBE, T_SERIAL);
|
||||
+ sfp->sm_mod_tries_init = R_PROBE_RETRY_INIT;
|
||||
+ sfp->sm_mod_tries = R_PROBE_RETRY_SLOW;
|
||||
+ }
|
||||
break;
|
||||
|
||||
case SFP_MOD_PROBE:
|
||||
@@ -1558,10 +1567,19 @@ static void sfp_sm_module(struct sfp *sf
|
||||
if (event != SFP_E_TIMEOUT)
|
||||
break;
|
||||
|
||||
- err = sfp_sm_mod_probe(sfp);
|
||||
+ err = sfp_sm_mod_probe(sfp, sfp->sm_mod_tries == 1);
|
||||
if (err == -EAGAIN) {
|
||||
- sfp_sm_set_timer(sfp, T_PROBE_RETRY);
|
||||
- break;
|
||||
+ if (sfp->sm_mod_tries_init &&
|
||||
+ --sfp->sm_mod_tries_init) {
|
||||
+ sfp_sm_set_timer(sfp, T_PROBE_RETRY_INIT);
|
||||
+ break;
|
||||
+ } else if (sfp->sm_mod_tries && --sfp->sm_mod_tries) {
|
||||
+ if (sfp->sm_mod_tries == R_PROBE_RETRY_SLOW - 1)
|
||||
+ dev_warn(sfp->dev,
|
||||
+ "please wait, module slow to respond\n");
|
||||
+ sfp_sm_set_timer(sfp, T_PROBE_RETRY_SLOW);
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
if (err < 0) {
|
||||
sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
|
||||
@@ -1596,7 +1614,7 @@ static void sfp_sm_module(struct sfp *sf
|
||||
sfp_module_remove(sfp->sfp_bus);
|
||||
sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
|
||||
} else {
|
||||
- sfp_sm_set_timer(sfp, T_PROBE_RETRY);
|
||||
+ sfp_sm_set_timer(sfp, T_PROBE_RETRY_INIT);
|
||||
}
|
||||
break;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user