From b06d76f9ae2eae389ddaa74abeee7987bdf1b9d4 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 26 Jul 2018 03:15:58 -0700 Subject: linux/compat.h: Add netdev_### log macros Currently there are two ethernet drivers (mvneta.c and mvpp2.c) that has netdev_### (eg: netdev_dbg) log macros defined in its own driver file. This adds these log macros in a common place linux/compat.h. Signed-off-by: Bin Meng Acked-by: Joe Hershberger --- drivers/net/mvneta.c | 8 -------- drivers/net/mvpp2.c | 10 ---------- 2 files changed, 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c index ab697b9bc7..8cb04b52d7 100644 --- a/drivers/net/mvneta.c +++ b/drivers/net/mvneta.c @@ -34,14 +34,6 @@ DECLARE_GLOBAL_DATA_PTR; # error Marvell mvneta requires PHYLIB #endif -/* Some linux -> U-Boot compatibility stuff */ -#define netdev_err(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_warn(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_info(dev, fmt, args...) \ - printf(fmt, ##args) - #define CONFIG_NR_CPUS 1 #define ETH_HLEN 14 /* Total octets in header */ diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 62c0c2be06..5c1f5fcd56 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -35,16 +35,6 @@ DECLARE_GLOBAL_DATA_PTR; -/* Some linux -> U-Boot compatibility stuff */ -#define netdev_err(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_warn(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_info(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_dbg(dev, fmt, args...) \ - printf(fmt, ##args) - #define ETH_ALEN 6 /* Octets in one ethernet addr */ #define __verify_pcpu_ptr(ptr) \ -- cgit From 339613eba5fecb37d750c2192109f04fefbd5d43 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 29 Jul 2018 00:11:22 -0700 Subject: net: pch_gbe: Make probe/remove static These two routines are internal to pch_gbe driver. Signed-off-by: Bin Meng Acked-by: Joe Hershberger --- drivers/net/pch_gbe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c index d31c45f3b6..2286dd07e9 100644 --- a/drivers/net/pch_gbe.c +++ b/drivers/net/pch_gbe.c @@ -429,7 +429,7 @@ static int pch_gbe_phy_init(struct udevice *dev) return 0; } -int pch_gbe_probe(struct udevice *dev) +static int pch_gbe_probe(struct udevice *dev) { struct pch_gbe_priv *priv; struct eth_pdata *plat = dev_get_platdata(dev); @@ -464,7 +464,7 @@ int pch_gbe_probe(struct udevice *dev) return pch_gbe_phy_init(dev); } -int pch_gbe_remove(struct udevice *dev) +static int pch_gbe_remove(struct udevice *dev) { struct pch_gbe_priv *priv = dev_get_priv(dev); -- cgit From dda5251037008b3563ab0aaf443eb7be3213887c Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 31 Jul 2018 02:55:22 -0700 Subject: net.h: Include linux/if_ether.h to avoid duplication There are plenty of existing drivers that have macros like ETH_ALEN defined in their own source files. Now that we imported the kernel's if_ether.h to U-Boot we can reduce some duplication. Signed-off-by: Bin Meng Acked-by: Joe Hershberger --- drivers/net/dc2114x.c | 1 - drivers/net/eepro100.c | 2 -- drivers/net/mvpp2.c | 3 --- drivers/net/natsemi.c | 1 - drivers/net/ns8382x.c | 1 - drivers/net/rtl8139.c | 4 ---- drivers/net/rtl8169.c | 4 ---- 7 files changed, 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index 8d7c271038..e3c403c13f 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -123,7 +123,6 @@ #define TOUT_LOOP 1000000 #define SETUP_FRAME_LEN 192 -#define ETH_ALEN 6 struct de4x5_desc { volatile s32 status; diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index ae65b649bf..2fe0ba6e20 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -193,8 +193,6 @@ struct descriptor { /* A generic descriptor. */ #define TOUT_LOOP 1000000 -#define ETH_ALEN 6 - static struct RxFD rx_ring[NUM_RX_DESC]; /* RX descriptor ring */ static struct TxFD tx_ring[NUM_TX_DESC]; /* TX descriptor ring */ static int rx_next; /* RX descriptor ring pointer */ diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 5c1f5fcd56..f34245ba77 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -35,8 +35,6 @@ DECLARE_GLOBAL_DATA_PTR; -#define ETH_ALEN 6 /* Octets in one ethernet addr */ - #define __verify_pcpu_ptr(ptr) \ do { \ const void __percpu *__vpp_verify = (typeof((ptr) + 0))NULL; \ @@ -58,7 +56,6 @@ do { \ #define NET_SKB_PAD max(32, MVPP2_CPU_D_CACHE_LINE_SIZE) #define CONFIG_NR_CPUS 1 -#define ETH_HLEN ETHER_HDR_SIZE /* Total octets in header */ /* 2(HW hdr) 14(MAC hdr) 4(CRC) 32(extra for cache prefetch) */ #define WRAP (2 + ETH_HLEN + 4 + 32) diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 0ed9bb5765..86f689802e 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -61,7 +61,6 @@ #define EEPROM_SIZE 0xb /*12 16-bit chunks, or 24 bytes*/ #define DSIZE 0x00000FFF -#define ETH_ALEN 6 #define CRC_SIZE 4 #define TOUT_LOOP 500000 #define TX_BUF_SIZE 1536 diff --git a/drivers/net/ns8382x.c b/drivers/net/ns8382x.c index f941c15b27..ea7ece54b6 100644 --- a/drivers/net/ns8382x.c +++ b/drivers/net/ns8382x.c @@ -59,7 +59,6 @@ /* defines */ #define DSIZE 0x00000FFF -#define ETH_ALEN 6 #define CRC_SIZE 4 #define TOUT_LOOP 500000 #define TX_BUF_SIZE 1536 diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index ea523435f0..590f8ce154 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -80,10 +80,6 @@ #define RTL_TIMEOUT 100000 -#define ETH_FRAME_LEN 1514 -#define ETH_ALEN 6 -#define ETH_ZLEN 60 - /* PCI Tuning Parameters Threshold is bytes transferred to chip before transmission starts. */ #define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index e0e3a6d570..a78f3d233f 100644 --- a/drivers/net/rtl8169.c +++ b/drivers/net/rtl8169.c @@ -102,10 +102,6 @@ static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; #define RTL_R16(reg) readw(ioaddr + (reg)) #define RTL_R32(reg) readl(ioaddr + (reg)) -#define ETH_FRAME_LEN MAX_ETH_FRAME_SIZE -#define ETH_ALEN MAC_ADDR_LEN -#define ETH_ZLEN 60 - #define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)(unsigned long)dev->priv, \ (pci_addr_t)(unsigned long)a) #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)(unsigned long)dev->priv, \ -- cgit From fba725f41002e5035e601a7cfa9429b0c8184211 Mon Sep 17 00:00:00 2001 From: Janine Hagemann Date: Tue, 28 Aug 2018 08:25:37 +0200 Subject: net: phy: ti: Add lane swapping support in the DP83867 TI's PHY driver This patch adds support for enabling or disabling the lane swapping (called "port mirroring" in PHY's CFG4 register) feature of the DP83867 TI's PHY device. One use case is when bootstrap configuration enables this feature (because of e.g. LED_0 wrong wiring) so then one needs to disable it in software (at u-boot/Linux). Based on commit fc6d39c39581 ("net: phy: dp83867: Add lane swapping support in the DP83867 TI's PHY driver") of mainline linux kernel. Signed-off-by: Janine Hagemann Acked-by: Lukasz Majewski Acked-by: Joe Hershberger --- drivers/net/phy/ti.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c index f870e6d662..cef59420d2 100644 --- a/drivers/net/phy/ti.c +++ b/drivers/net/phy/ti.c @@ -89,12 +89,22 @@ #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0 #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f +/* CFG4 bits */ +#define DP83867_CFG4_PORT_MIRROR_EN BIT(0) + +enum { + DP83867_PORT_MIRRORING_KEEP, + DP83867_PORT_MIRRORING_EN, + DP83867_PORT_MIRRORING_DIS, +}; + struct dp83867_private { int rx_id_delay; int tx_id_delay; int fifo_depth; int io_impedance; bool rxctrl_strap_quirk; + int port_mirroring; }; /** @@ -163,6 +173,26 @@ void phy_write_mmd_indirect(struct phy_device *phydev, int prtad, phy_write(phydev, addr, MII_MMD_DATA, data); } +static int dp83867_config_port_mirroring(struct phy_device *phydev) +{ + struct dp83867_private *dp83867 = + (struct dp83867_private *)phydev->priv; + u16 val; + + val = phy_read_mmd_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR, + phydev->addr); + + if (dp83867->port_mirroring == DP83867_PORT_MIRRORING_EN) + val |= DP83867_CFG4_PORT_MIRROR_EN; + else + val &= ~DP83867_CFG4_PORT_MIRROR_EN; + + phy_write_mmd_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR, + phydev->addr, val); + + return 0; +} + #if defined(CONFIG_DM_ETH) /** * dp83867_data_init - Convenience function for setting PHY specific data @@ -197,6 +227,12 @@ static int dp83867_of_init(struct phy_device *phydev) dp83867->fifo_depth = ofnode_read_u32_default(node, "ti,fifo-depth", -1); + if (ofnode_read_bool(node, "enet-phy-lane-swap")) + dp83867->port_mirroring = DP83867_PORT_MIRRORING_EN; + + if (ofnode_read_bool(node, "enet-phy-lane-no-swap")) + dp83867->port_mirroring = DP83867_PORT_MIRRORING_DIS; + return 0; } @@ -315,6 +351,9 @@ static int dp83867_config(struct phy_device *phydev) } } + if (dp83867->port_mirroring != DP83867_PORT_MIRRORING_KEEP) + dp83867_config_port_mirroring(phydev); + genphy_config_aneg(phydev); return 0; -- cgit From be71a74c59b7f34e83f3f6ea4b1a838de356c654 Mon Sep 17 00:00:00 2001 From: Janine Hagemann Date: Tue, 28 Aug 2018 08:25:38 +0200 Subject: net: phy: ti: Recover from "port mirroring" N/A MODE4 The DP83867 when not properly bootstrapped - especially with LED_0 pin - can enter N/A MODE4 for "port mirroring" feature. To provide normal operation of the PHY, one needs not only to explicitly disable the port mirroring feature, but as well stop some IC internal testing (which disables RGMII communication). To do that the STRAP_STS1 (0x006E) register must be read and RESERVED bit 11 examined. When it is set, the another RESERVED bit (11) at PHYCR (0x0010) register must be clear to disable testing mode and enable RGMII communication. Thorough explanation of the problem can be found at following e2e thread: "DP83867IR: Problem with RESERVED bits in PHY Control Register (PHYCR) - Linux driver" https://e2e.ti.com/support/interface/ethernet/f/903/p/571313/2096954#2096954 Based on commit ac6e058b75be ("net: phy: dp83867: Recover from "port mirroring" N/A MODE4") of mainline linux kernel. Signed-off-by: Janine Hagemann Acked-by: Joe Hershberger Acked-by: Lukasz Majewski --- drivers/net/phy/ti.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c index cef59420d2..e27ee32bd1 100644 --- a/drivers/net/phy/ti.c +++ b/drivers/net/phy/ti.c @@ -24,6 +24,7 @@ /* Extended Registers */ #define DP83867_CFG4 0x0031 #define DP83867_RGMIICTL 0x0032 +#define DP83867_STRAP_STS1 0x006E #define DP83867_RGMIIDCTL 0x0086 #define DP83867_IO_MUX_CFG 0x0170 @@ -48,8 +49,12 @@ #define DP83867_RGMII_TX_CLK_DELAY_EN BIT(1) #define DP83867_RGMII_RX_CLK_DELAY_EN BIT(0) +/* STRAP_STS1 bits */ +#define DP83867_STRAP_STS1_RESERVED BIT(11) + /* PHY CTRL bits */ #define DP83867_PHYCR_FIFO_DEPTH_SHIFT 14 +#define DP83867_PHYCR_RESERVED_MASK BIT(11) #define DP83867_MDI_CROSSOVER 5 #define DP83867_MDI_CROSSOVER_AUTO 2 #define DP83867_MDI_CROSSOVER_MDIX 2 @@ -254,7 +259,7 @@ static int dp83867_config(struct phy_device *phydev) { struct dp83867_private *dp83867; unsigned int val, delay, cfg2; - int ret; + int ret, bs; if (!phydev->priv) { dp83867 = kzalloc(sizeof(*dp83867), GFP_KERNEL); @@ -289,6 +294,26 @@ static int dp83867_config(struct phy_device *phydev) (dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT)); if (ret) goto err_out; + + /* The code below checks if "port mirroring" N/A MODE4 has been + * enabled during power on bootstrap. + * + * Such N/A mode enabled by mistake can put PHY IC in some + * internal testing mode and disable RGMII transmission. + * + * In this particular case one needs to check STRAP_STS1 + * register's bit 11 (marked as RESERVED). + */ + + bs = phy_read_mmd_indirect(phydev, DP83867_STRAP_STS1, + DP83867_DEVADDR, phydev->addr); + val = phy_read(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL); + if (bs & DP83867_STRAP_STS1_RESERVED) { + val &= ~DP83867_PHYCR_RESERVED_MASK; + phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL, + val); + } + } else if (phy_interface_is_sgmii(phydev)) { phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000)); -- cgit From 0f347a0096ad0c1e56d1b18b7eb60731d40d49c2 Mon Sep 17 00:00:00 2001 From: Janine Hagemann Date: Tue, 28 Aug 2018 08:25:39 +0200 Subject: net: phy: ti: Add binding for the CLK_OUT pin muxing The DP83867 has a muxing option for the CLK_OUT pin. It is possible to set CLK_OUT for different channels. Create a binding to select a specific clock for CLK_OUT pin. Based on commit 9708fb630d19 ("net: phy: dp83867: Add binding for the CLK_OUT pin muxing option") of mainline linux kernel. Signed-off-by: Janine Hagemann Acked-by: Joe Hershberger --- drivers/net/phy/ti.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c index e27ee32bd1..6db6edd0d0 100644 --- a/drivers/net/phy/ti.c +++ b/drivers/net/phy/ti.c @@ -93,6 +93,9 @@ #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0 #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f +#define DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT 8 +#define DP83867_IO_MUX_CFG_CLK_O_SEL_MASK \ + GENMASK(0x1f, DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT) /* CFG4 bits */ #define DP83867_CFG4_PORT_MIRROR_EN BIT(0) @@ -110,6 +113,7 @@ struct dp83867_private { int io_impedance; bool rxctrl_strap_quirk; int port_mirroring; + int clk_output_sel; }; /** @@ -208,6 +212,18 @@ static int dp83867_of_init(struct phy_device *phydev) { struct dp83867_private *dp83867 = phydev->priv; ofnode node; + u16 val; + + /* Optional configuration */ + + /* + * Keep the default value if ti,clk-output-sel is not set + * or to high + */ + + dp83867->clk_output_sel = + ofnode_read_u32_default(node, "ti,clk-output-sel", + DP83867_CLK_O_SEL_REF_CLK); node = phy_get_ofnode(phydev); if (!ofnode_valid(node)) @@ -239,6 +255,17 @@ static int dp83867_of_init(struct phy_device *phydev) dp83867->port_mirroring = DP83867_PORT_MIRRORING_DIS; + /* Clock output selection if muxing property is set */ + if (dp83867->clk_output_sel != DP83867_CLK_O_SEL_REF_CLK) { + val = phy_read_mmd_indirect(phydev, DP83867_IO_MUX_CFG, + DP83867_DEVADDR, phydev->addr); + val &= ~DP83867_IO_MUX_CFG_CLK_O_SEL_MASK; + val |= (dp83867->clk_output_sel << + DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT); + phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG, + DP83867_DEVADDR, phydev->addr, val); + } + return 0; } #else -- cgit From e4ab9a65081f032495533af7474d52ff17dd5d27 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 26 Sep 2018 16:48:53 -0500 Subject: net: sandbox: Move disabled flag into priv struct Store the per-device data with the device. Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass Reviewed-by: Bin Meng --- drivers/net/sandbox.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c index b71c8f88d9..60fe065ee5 100644 --- a/drivers/net/sandbox.c +++ b/drivers/net/sandbox.c @@ -19,17 +19,18 @@ DECLARE_GLOBAL_DATA_PTR; * * fake_host_hwaddr: MAC address of mocked machine * fake_host_ipaddr: IP address of mocked machine + * disabled: Will not respond * recv_packet_buffer: buffer of the packet returned as received * recv_packet_length: length of the packet returned as received */ struct eth_sandbox_priv { uchar fake_host_hwaddr[ARP_HLEN]; struct in_addr fake_host_ipaddr; + bool disabled; uchar *recv_packet_buffer; int recv_packet_length; }; -static bool disabled[8] = {false}; static bool skip_timeout; /* @@ -40,7 +41,16 @@ static bool skip_timeout; */ void sandbox_eth_disable_response(int index, bool disable) { - disabled[index] = disable; + struct udevice *dev; + struct eth_sandbox_priv *priv; + int ret; + + ret = uclass_get_device(UCLASS_ETH, index, &dev); + if (ret) + return; + + priv = dev_get_priv(dev); + priv->disabled = disable; } /* @@ -71,8 +81,7 @@ static int sb_eth_send(struct udevice *dev, void *packet, int length) debug("eth_sandbox: Send packet %d\n", length); - if (dev->seq >= 0 && dev->seq < ARRAY_SIZE(disabled) && - disabled[dev->seq]) + if (priv->disabled) return 0; if (ntohs(eth->et_protlen) == PROT_ARP) { @@ -212,6 +221,7 @@ static int sb_eth_ofdata_to_platdata(struct udevice *dev) return -EINVAL; } memcpy(priv->fake_host_hwaddr, mac, ARP_HLEN); + priv->disabled = false; return 0; } -- cgit From e95bb1611043ff1ad5b63602e32bba302e402491 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 26 Sep 2018 16:48:54 -0500 Subject: net: sandbox: Refactor sandbox send function Make the behavior of the send function reusable. Signed-off-by: Joe Hershberger Reviewed-by: Bin Meng --- drivers/net/sandbox.c | 180 +++++++++++++++++++++++++++++--------------------- 1 file changed, 106 insertions(+), 74 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c index 60fe065ee5..c472261568 100644 --- a/drivers/net/sandbox.c +++ b/drivers/net/sandbox.c @@ -63,6 +63,108 @@ void sandbox_eth_skip_timeout(void) skip_timeout = true; } +/* + * sandbox_eth_arp_req_to_reply() + * + * Check for an arp request to be sent. If so, inject a reply + * + * returns 0 if injected, -EAGAIN if not + */ +int sandbox_eth_arp_req_to_reply(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth = packet; + struct arp_hdr *arp; + struct ethernet_hdr *eth_recv; + struct arp_hdr *arp_recv; + + if (ntohs(eth->et_protlen) != PROT_ARP) + return -EAGAIN; + + arp = packet + ETHER_HDR_SIZE; + + if (ntohs(arp->ar_op) != ARPOP_REQUEST) + return -EAGAIN; + + /* store this as the assumed IP of the fake host */ + priv->fake_host_ipaddr = net_read_ip(&arp->ar_tpa); + + /* Formulate a fake response */ + eth_recv = (void *)priv->recv_packet_buffer; + memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + eth_recv->et_protlen = htons(PROT_ARP); + + arp_recv = (void *)eth_recv + ETHER_HDR_SIZE; + arp_recv->ar_hrd = htons(ARP_ETHER); + arp_recv->ar_pro = htons(PROT_IP); + arp_recv->ar_hln = ARP_HLEN; + arp_recv->ar_pln = ARP_PLEN; + arp_recv->ar_op = htons(ARPOP_REPLY); + memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr, ARP_HLEN); + net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr); + memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN); + net_copy_ip(&arp_recv->ar_tpa, &arp->ar_spa); + + priv->recv_packet_length = ETHER_HDR_SIZE + ARP_HDR_SIZE; + + return 0; +} + +/* + * sandbox_eth_ping_req_to_reply() + * + * Check for a ping request to be sent. If so, inject a reply + * + * returns 0 if injected, -EAGAIN if not + */ +int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth = packet; + struct ip_udp_hdr *ip; + struct icmp_hdr *icmp; + struct ethernet_hdr *eth_recv; + struct ip_udp_hdr *ipr; + struct icmp_hdr *icmpr; + + if (ntohs(eth->et_protlen) != PROT_IP) + return -EAGAIN; + + ip = packet + ETHER_HDR_SIZE; + + if (ip->ip_p != IPPROTO_ICMP) + return -EAGAIN; + + icmp = (struct icmp_hdr *)&ip->udp_src; + + if (icmp->type != ICMP_ECHO_REQUEST) + return -EAGAIN; + + /* reply to the ping */ + eth_recv = (void *)priv->recv_packet_buffer; + memcpy(eth_recv, packet, len); + ipr = (void *)eth_recv + ETHER_HDR_SIZE; + icmpr = (struct icmp_hdr *)&ipr->udp_src; + memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + ipr->ip_sum = 0; + ipr->ip_off = 0; + net_copy_ip((void *)&ipr->ip_dst, &ip->ip_src); + net_write_ip((void *)&ipr->ip_src, priv->fake_host_ipaddr); + ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE); + + icmpr->type = ICMP_ECHO_REPLY; + icmpr->checksum = 0; + icmpr->checksum = compute_ip_checksum(icmpr, ICMP_HDR_SIZE); + + priv->recv_packet_length = len; + + return 0; +} + static int sb_eth_start(struct udevice *dev) { struct eth_sandbox_priv *priv = dev_get_priv(dev); @@ -77,86 +179,16 @@ static int sb_eth_start(struct udevice *dev) static int sb_eth_send(struct udevice *dev, void *packet, int length) { struct eth_sandbox_priv *priv = dev_get_priv(dev); - struct ethernet_hdr *eth = packet; debug("eth_sandbox: Send packet %d\n", length); if (priv->disabled) return 0; - if (ntohs(eth->et_protlen) == PROT_ARP) { - struct arp_hdr *arp = packet + ETHER_HDR_SIZE; - - if (ntohs(arp->ar_op) == ARPOP_REQUEST) { - struct ethernet_hdr *eth_recv; - struct arp_hdr *arp_recv; - - /* store this as the assumed IP of the fake host */ - priv->fake_host_ipaddr = net_read_ip(&arp->ar_tpa); - /* Formulate a fake response */ - eth_recv = (void *)priv->recv_packet_buffer; - memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN); - memcpy(eth_recv->et_src, priv->fake_host_hwaddr, - ARP_HLEN); - eth_recv->et_protlen = htons(PROT_ARP); - - arp_recv = (void *)priv->recv_packet_buffer + - ETHER_HDR_SIZE; - arp_recv->ar_hrd = htons(ARP_ETHER); - arp_recv->ar_pro = htons(PROT_IP); - arp_recv->ar_hln = ARP_HLEN; - arp_recv->ar_pln = ARP_PLEN; - arp_recv->ar_op = htons(ARPOP_REPLY); - memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr, - ARP_HLEN); - net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr); - memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN); - net_copy_ip(&arp_recv->ar_tpa, &arp->ar_spa); - - priv->recv_packet_length = ETHER_HDR_SIZE + - ARP_HDR_SIZE; - } - } else if (ntohs(eth->et_protlen) == PROT_IP) { - struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE; - - if (ip->ip_p == IPPROTO_ICMP) { - struct icmp_hdr *icmp = (struct icmp_hdr *)&ip->udp_src; - - if (icmp->type == ICMP_ECHO_REQUEST) { - struct ethernet_hdr *eth_recv; - struct ip_udp_hdr *ipr; - struct icmp_hdr *icmpr; - - /* reply to the ping */ - memcpy(priv->recv_packet_buffer, packet, - length); - eth_recv = (void *)priv->recv_packet_buffer; - ipr = (void *)priv->recv_packet_buffer + - ETHER_HDR_SIZE; - icmpr = (struct icmp_hdr *)&ipr->udp_src; - memcpy(eth_recv->et_dest, eth->et_src, - ARP_HLEN); - memcpy(eth_recv->et_src, priv->fake_host_hwaddr, - ARP_HLEN); - ipr->ip_sum = 0; - ipr->ip_off = 0; - net_copy_ip((void *)&ipr->ip_dst, &ip->ip_src); - net_write_ip((void *)&ipr->ip_src, - priv->fake_host_ipaddr); - ipr->ip_sum = compute_ip_checksum(ipr, - IP_HDR_SIZE); - - icmpr->type = ICMP_ECHO_REPLY; - icmpr->checksum = 0; - icmpr->checksum = compute_ip_checksum(icmpr, - ICMP_HDR_SIZE); - - priv->recv_packet_length = length; - } - } - } - - return 0; + if (!sandbox_eth_arp_req_to_reply(dev, packet, length)) + return 0; + if (!sandbox_eth_ping_req_to_reply(dev, packet, length)) + return 0; } static int sb_eth_recv(struct udevice *dev, int flags, uchar **packetp) -- cgit From c7eb733d606667508b69ee922e9738d55259304e Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 26 Sep 2018 16:48:55 -0500 Subject: net: sandbox: Make the fake eth driver response configurable Make the send handler registerable so tests can check for different things. Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass Reviewed-by: Bin Meng --- drivers/net/sandbox.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c index c472261568..db461b892e 100644 --- a/drivers/net/sandbox.c +++ b/drivers/net/sandbox.c @@ -10,6 +10,7 @@ #include #include #include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -22,6 +23,7 @@ DECLARE_GLOBAL_DATA_PTR; * disabled: Will not respond * recv_packet_buffer: buffer of the packet returned as received * recv_packet_length: length of the packet returned as received + * tx_handler - function to generate responses to sent packets */ struct eth_sandbox_priv { uchar fake_host_hwaddr[ARP_HLEN]; @@ -29,6 +31,7 @@ struct eth_sandbox_priv { bool disabled; uchar *recv_packet_buffer; int recv_packet_length; + sandbox_eth_tx_hand_f *tx_handler; }; static bool skip_timeout; @@ -165,6 +168,52 @@ int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet, return 0; } +/* + * sb_default_handler() + * + * perform typical responses to simple ping + * + * dev - device pointer + * pkt - "sent" packet buffer + * len - length of packet + */ +static int sb_default_handler(struct udevice *dev, void *packet, + unsigned int len) +{ + if (!sandbox_eth_arp_req_to_reply(dev, packet, len)) + return 0; + if (!sandbox_eth_ping_req_to_reply(dev, packet, len)) + return 0; + + return 0; +} + +/* + * sandbox_eth_set_tx_handler() + * + * Set a custom response to a packet being sent through the sandbox eth test + * driver + * + * index - interface to set the handler for + * handler - The func ptr to call on send. If NULL, set to default handler + */ +void sandbox_eth_set_tx_handler(int index, sandbox_eth_tx_hand_f *handler) +{ + struct udevice *dev; + struct eth_sandbox_priv *priv; + int ret; + + ret = uclass_get_device(UCLASS_ETH, index, &dev); + if (ret) + return; + + priv = dev_get_priv(dev); + if (handler) + priv->tx_handler = handler; + else + priv->tx_handler = sb_default_handler; +} + static int sb_eth_start(struct udevice *dev) { struct eth_sandbox_priv *priv = dev_get_priv(dev); @@ -185,10 +234,7 @@ static int sb_eth_send(struct udevice *dev, void *packet, int length) if (priv->disabled) return 0; - if (!sandbox_eth_arp_req_to_reply(dev, packet, length)) - return 0; - if (!sandbox_eth_ping_req_to_reply(dev, packet, length)) - return 0; + return priv->tx_handler(dev, packet, length); } static int sb_eth_recv(struct udevice *dev, int flags, uchar **packetp) @@ -254,6 +300,7 @@ static int sb_eth_ofdata_to_platdata(struct udevice *dev) } memcpy(priv->fake_host_hwaddr, mac, ARP_HLEN); priv->disabled = false; + priv->tx_handler = sb_default_handler; return 0; } -- cgit From 76a503439e38be9d4fe365bdf87a6d0e74ea41c9 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 26 Sep 2018 16:48:56 -0500 Subject: net: sandbox: Share the priv structure with tests If tests want to implement tx handlers, they will likely need access to the details in the priv structure. Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass Reviewed-by: Bin Meng --- drivers/net/sandbox.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c index db461b892e..6f0fe0ced5 100644 --- a/drivers/net/sandbox.c +++ b/drivers/net/sandbox.c @@ -15,25 +15,6 @@ DECLARE_GLOBAL_DATA_PTR; -/** - * struct eth_sandbox_priv - memory for sandbox mock driver - * - * fake_host_hwaddr: MAC address of mocked machine - * fake_host_ipaddr: IP address of mocked machine - * disabled: Will not respond - * recv_packet_buffer: buffer of the packet returned as received - * recv_packet_length: length of the packet returned as received - * tx_handler - function to generate responses to sent packets - */ -struct eth_sandbox_priv { - uchar fake_host_hwaddr[ARP_HLEN]; - struct in_addr fake_host_ipaddr; - bool disabled; - uchar *recv_packet_buffer; - int recv_packet_length; - sandbox_eth_tx_hand_f *tx_handler; -}; - static bool skip_timeout; /* -- cgit From c67a420781012abb5c888e2857efde12cf27284b Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 26 Sep 2018 16:48:57 -0500 Subject: net: sandbox: Allow fake eth to handle more than 1 packet response Use up to the max allocated receive buffers so as to be able to test more complex situations. Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass Reviewed-by: Bin Meng --- drivers/net/sandbox.c | 57 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c index 6f0fe0ced5..9c0e0d009e 100644 --- a/drivers/net/sandbox.c +++ b/drivers/net/sandbox.c @@ -71,11 +71,15 @@ int sandbox_eth_arp_req_to_reply(struct udevice *dev, void *packet, if (ntohs(arp->ar_op) != ARPOP_REQUEST) return -EAGAIN; + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return 0; + /* store this as the assumed IP of the fake host */ priv->fake_host_ipaddr = net_read_ip(&arp->ar_tpa); /* Formulate a fake response */ - eth_recv = (void *)priv->recv_packet_buffer; + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN); memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); eth_recv->et_protlen = htons(PROT_ARP); @@ -91,7 +95,9 @@ int sandbox_eth_arp_req_to_reply(struct udevice *dev, void *packet, memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN); net_copy_ip(&arp_recv->ar_tpa, &arp->ar_spa); - priv->recv_packet_length = ETHER_HDR_SIZE + ARP_HDR_SIZE; + priv->recv_packet_length[priv->recv_packets] = + ETHER_HDR_SIZE + ARP_HDR_SIZE; + ++priv->recv_packets; return 0; } @@ -127,8 +133,12 @@ int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet, if (icmp->type != ICMP_ECHO_REQUEST) return -EAGAIN; + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return 0; + /* reply to the ping */ - eth_recv = (void *)priv->recv_packet_buffer; + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; memcpy(eth_recv, packet, len); ipr = (void *)eth_recv + ETHER_HDR_SIZE; icmpr = (struct icmp_hdr *)&ipr->udp_src; @@ -144,7 +154,8 @@ int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet, icmpr->checksum = 0; icmpr->checksum = compute_ip_checksum(icmpr, ICMP_HDR_SIZE); - priv->recv_packet_length = len; + priv->recv_packet_length[priv->recv_packets] = len; + ++priv->recv_packets; return 0; } @@ -201,7 +212,11 @@ static int sb_eth_start(struct udevice *dev) debug("eth_sandbox: Start\n"); - priv->recv_packet_buffer = net_rx_packets[0]; + priv->recv_packets = 0; + for (int i = 0; i < PKTBUFSRX; i++) { + priv->recv_packet_buffer[i] = net_rx_packets[i]; + priv->recv_packet_length[i] = 0; + } return 0; } @@ -227,18 +242,37 @@ static int sb_eth_recv(struct udevice *dev, int flags, uchar **packetp) skip_timeout = false; } - if (priv->recv_packet_length) { - int lcl_recv_packet_length = priv->recv_packet_length; + if (priv->recv_packets) { + int lcl_recv_packet_length = priv->recv_packet_length[0]; - debug("eth_sandbox: received packet %d\n", - priv->recv_packet_length); - priv->recv_packet_length = 0; - *packetp = priv->recv_packet_buffer; + debug("eth_sandbox: received packet[%d], %d waiting\n", + lcl_recv_packet_length, priv->recv_packets - 1); + *packetp = priv->recv_packet_buffer[0]; return lcl_recv_packet_length; } return 0; } +static int sb_eth_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + int i; + + if (!priv->recv_packets) + return 0; + + --priv->recv_packets; + for (i = 0; i < priv->recv_packets; i++) { + priv->recv_packet_length[i] = priv->recv_packet_length[i + 1]; + memcpy(priv->recv_packet_buffer[i], + priv->recv_packet_buffer[i + 1], + priv->recv_packet_length[i + 1]); + } + priv->recv_packet_length[priv->recv_packets] = 0; + + return 0; +} + static void sb_eth_stop(struct udevice *dev) { debug("eth_sandbox: Stop\n"); @@ -257,6 +291,7 @@ static const struct eth_ops sb_eth_ops = { .start = sb_eth_start, .send = sb_eth_send, .recv = sb_eth_recv, + .free_pkt = sb_eth_free_pkt, .stop = sb_eth_stop, .write_hwaddr = sb_eth_write_hwaddr, }; -- cgit From 9cbe5972c3c00e974482181cd4062d9229a9b7d5 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 26 Sep 2018 16:48:59 -0500 Subject: net: sandbox: Add a priv ptr for tests to use Tests need to be able to pass their "unit test state" to the handlers where asserts are evaluated. Add a function that allows the tests to set this private data on the sandbox eth device. Signed-off-by: Joe Hershberger Reviewed-by: Bin Meng --- drivers/net/sandbox.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c index 9c0e0d009e..e26e72ecc1 100644 --- a/drivers/net/sandbox.c +++ b/drivers/net/sandbox.c @@ -206,6 +206,26 @@ void sandbox_eth_set_tx_handler(int index, sandbox_eth_tx_hand_f *handler) priv->tx_handler = sb_default_handler; } +/* + * Set priv ptr + * + * priv - priv void ptr to store in the device + */ +void sandbox_eth_set_priv(int index, void *priv) +{ + struct udevice *dev; + struct eth_sandbox_priv *dev_priv; + int ret; + + ret = uclass_get_device(UCLASS_ETH, index, &dev); + if (ret) + return; + + dev_priv = dev_get_priv(dev); + + dev_priv->priv = priv; +} + static int sb_eth_start(struct udevice *dev) { struct eth_sandbox_priv *priv = dev_get_priv(dev); -- cgit From 45988dae4cf05f783e40e027c83594a9dc6551cd Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 26 Sep 2018 16:49:00 -0500 Subject: test: eth: Add a test for ARP requests This tests that ARP requests made to this target's IP address are responded-to by the target when it is doing other networking operations. This currently corrupts the ongoing operation of the device if it happens to be awaiting an ARP reply of its own to whatever serverip it is attempting to communicate with. In the test, add an expectation that the user operation (ping, in this case) will fail. A later patch will address this problem. Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass Reviewed-by: Bin Meng --- drivers/net/sandbox.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c index e26e72ecc1..81f0764fa6 100644 --- a/drivers/net/sandbox.c +++ b/drivers/net/sandbox.c @@ -160,6 +160,47 @@ int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet, return 0; } +/* + * sandbox_eth_recv_arp_req() + * + * Inject an ARP request for this target + * + * returns 0 if injected, -EOVERFLOW if not + */ +int sandbox_eth_recv_arp_req(struct udevice *dev) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth_recv; + struct arp_hdr *arp_recv; + + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return -EOVERFLOW; + + /* Formulate a fake request */ + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; + memcpy(eth_recv->et_dest, net_bcast_ethaddr, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + eth_recv->et_protlen = htons(PROT_ARP); + + arp_recv = (void *)eth_recv + ETHER_HDR_SIZE; + arp_recv->ar_hrd = htons(ARP_ETHER); + arp_recv->ar_pro = htons(PROT_IP); + arp_recv->ar_hln = ARP_HLEN; + arp_recv->ar_pln = ARP_PLEN; + arp_recv->ar_op = htons(ARPOP_REQUEST); + memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr, ARP_HLEN); + net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr); + memcpy(&arp_recv->ar_tha, net_null_ethaddr, ARP_HLEN); + net_write_ip(&arp_recv->ar_tpa, net_ip); + + priv->recv_packet_length[priv->recv_packets] = + ETHER_HDR_SIZE + ARP_HDR_SIZE; + ++priv->recv_packets; + + return 0; +} + /* * sb_default_handler() * -- cgit From 72ff0042585bedab4364afbd7ecc935e48324ade Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 26 Sep 2018 16:49:01 -0500 Subject: test: eth: Add a test for the target being pinged The target will respond to pings while doing other network handling. Make sure that the response happens and is correct. This currently corrupts the ongoing operation of the device if it happens to be awaiting an ARP reply of its own to whatever serverip it is attempting to communicate with. In the test, add an expectation that the user operation (ping, in this case) will fail. A later patch will address this problem. Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass Reviewed-by: Bin Meng --- drivers/net/sandbox.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c index 81f0764fa6..decce2fa59 100644 --- a/drivers/net/sandbox.c +++ b/drivers/net/sandbox.c @@ -201,6 +201,57 @@ int sandbox_eth_recv_arp_req(struct udevice *dev) return 0; } +/* + * sandbox_eth_recv_ping_req() + * + * Inject a ping request for this target + * + * returns 0 if injected, -EOVERFLOW if not + */ +int sandbox_eth_recv_ping_req(struct udevice *dev) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth_recv; + struct ip_udp_hdr *ipr; + struct icmp_hdr *icmpr; + + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return -EOVERFLOW; + + /* Formulate a fake ping */ + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; + + memcpy(eth_recv->et_dest, net_ethaddr, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + eth_recv->et_protlen = htons(PROT_IP); + + ipr = (void *)eth_recv + ETHER_HDR_SIZE; + ipr->ip_hl_v = 0x45; + ipr->ip_len = htons(IP_ICMP_HDR_SIZE); + ipr->ip_off = htons(IP_FLAGS_DFRAG); + ipr->ip_p = IPPROTO_ICMP; + ipr->ip_sum = 0; + net_write_ip(&ipr->ip_src, priv->fake_host_ipaddr); + net_write_ip(&ipr->ip_dst, net_ip); + ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE); + + icmpr = (struct icmp_hdr *)&ipr->udp_src; + + icmpr->type = ICMP_ECHO_REQUEST; + icmpr->code = 0; + icmpr->checksum = 0; + icmpr->un.echo.id = 0; + icmpr->un.echo.sequence = htons(1); + icmpr->checksum = compute_ip_checksum(icmpr, ICMP_HDR_SIZE); + + priv->recv_packet_length[priv->recv_packets] = + ETHER_HDR_SIZE + IP_ICMP_HDR_SIZE; + ++priv->recv_packets; + + return 0; +} + /* * sb_default_handler() * -- cgit From afd6c6b4701d652a68f5d93ad26eba6793e36c81 Mon Sep 17 00:00:00 2001 From: Pankaj Bansal Date: Wed, 10 Oct 2018 14:08:29 +0530 Subject: driver: net: fsl-mc: modify the label name The goto label name is misspelled it should be DPMAC not DPAMC Signed-off-by: Pankaj Bansal Acked-by: Joe Hershberger --- drivers/net/ldpaa_eth/ldpaa_eth.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index a25b7cd906..82a684bea2 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -413,7 +413,7 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) if (err) { printf("%s: Could not initialize\n", priv->phydev->dev->name); - goto err_dpamc_bind; + goto err_dpmac_bind; } } #else @@ -441,13 +441,13 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) if (!priv->phydev->link) { printf("%s: No link.\n", priv->phydev->dev->name); err = -1; - goto err_dpamc_bind; + goto err_dpmac_bind; } /* DPMAC binding DPNI */ err = ldpaa_dpmac_bind(priv); if (err) - goto err_dpamc_bind; + goto err_dpmac_bind; /* DPNI initialization */ err = ldpaa_dpni_setup(priv); @@ -540,7 +540,7 @@ err_dpni_bind: err_dpbp_setup: dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); err_dpni_setup: -err_dpamc_bind: +err_dpmac_bind: dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle); dpmac_destroy(dflt_mc_io, dflt_dprc_handle, -- cgit From d75e81d9e05575e3f8471e618846565b15b30060 Mon Sep 17 00:00:00 2001 From: Pankaj Bansal Date: Wed, 10 Oct 2018 14:08:30 +0530 Subject: driver: net: fsl-mc: remove unused strcture elements The phydev structure is present in both ldpaa_eth_priv and wriop_dpmac_info. the phydev in wriop_dpmac_info is not being used As the phydev is created based on phy_addr and bus members of wriop_dpmac_info, it is appropriate to keep phydev in wriop_dpmac_info. Also phy_regs is not being used, therefore remove it Signed-off-by: Pankaj Bansal Acked-by: Joe Hershberger --- drivers/net/ldpaa_eth/ldpaa_eth.c | 58 ++++++++++++++++++++----------------- drivers/net/ldpaa_eth/ldpaa_eth.h | 1 - drivers/net/ldpaa_eth/ldpaa_wriop.c | 2 ++ 3 files changed, 34 insertions(+), 27 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index 82a684bea2..39f81daafd 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -35,7 +35,7 @@ static int init_phy(struct eth_device *dev) return -1; } - priv->phydev = phydev; + wriop_set_phy_dev(priv->dpmac_id, phydev); return phy_config(phydev); } @@ -388,6 +388,7 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) struct mii_dev *bus; phy_interface_t enet_if; struct dpni_queue d_queue; + struct phy_device *phydev = NULL; if (net_dev->state == ETH_STATE_ACTIVE) return 0; @@ -408,38 +409,41 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) goto err_dpmac_setup; #ifdef CONFIG_PHYLIB - if (priv->phydev) { - err = phy_startup(priv->phydev); + phydev = wriop_get_phy_dev(priv->dpmac_id); + if (phydev) { + err = phy_startup(phydev); if (err) { printf("%s: Could not initialize\n", - priv->phydev->dev->name); + phydev->dev->name); goto err_dpmac_bind; } } #else - priv->phydev = (struct phy_device *)malloc(sizeof(struct phy_device)); - memset(priv->phydev, 0, sizeof(struct phy_device)); + phydev = (struct phy_device *)malloc(sizeof(struct phy_device)); + memset(phydev, 0, sizeof(struct phy_device)); + wriop_set_phy_dev(priv->dpmac_id, phydev); - priv->phydev->speed = SPEED_1000; - priv->phydev->link = 1; - priv->phydev->duplex = DUPLEX_FULL; + phydev->speed = SPEED_1000; + phydev->link = 1; + phydev->duplex = DUPLEX_FULL; #endif bus = wriop_get_mdio(priv->dpmac_id); enet_if = wriop_get_enet_if(priv->dpmac_id); if ((bus == NULL) && (enet_if == PHY_INTERFACE_MODE_XGMII)) { - priv->phydev = (struct phy_device *) + phydev = (struct phy_device *) malloc(sizeof(struct phy_device)); - memset(priv->phydev, 0, sizeof(struct phy_device)); + memset(phydev, 0, sizeof(struct phy_device)); + wriop_set_phy_dev(priv->dpmac_id, phydev); - priv->phydev->speed = SPEED_10000; - priv->phydev->link = 1; - priv->phydev->duplex = DUPLEX_FULL; + phydev->speed = SPEED_10000; + phydev->link = 1; + phydev->duplex = DUPLEX_FULL; } - if (!priv->phydev->link) { - printf("%s: No link.\n", priv->phydev->dev->name); + if (!phydev->link) { + printf("%s: No link.\n", phydev->dev->name); err = -1; goto err_dpmac_bind; } @@ -476,17 +480,17 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) return err; } - dpmac_link_state.rate = priv->phydev->speed; + dpmac_link_state.rate = phydev->speed; - if (priv->phydev->autoneg == AUTONEG_DISABLE) + if (phydev->autoneg == AUTONEG_DISABLE) dpmac_link_state.options &= ~DPMAC_LINK_OPT_AUTONEG; else dpmac_link_state.options |= DPMAC_LINK_OPT_AUTONEG; - if (priv->phydev->duplex == DUPLEX_HALF) + if (phydev->duplex == DUPLEX_HALF) dpmac_link_state.options |= DPMAC_LINK_OPT_HALF_DUPLEX; - dpmac_link_state.up = priv->phydev->link; + dpmac_link_state.up = phydev->link; err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle, &dpmac_link_state); @@ -530,7 +534,7 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) goto err_qdid; } - return priv->phydev->link; + return phydev->link; err_qdid: err_get_queue: @@ -556,6 +560,7 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) #ifdef CONFIG_PHYLIB struct mii_dev *bus = wriop_get_mdio(priv->dpmac_id); #endif + struct phy_device *phydev = NULL; if ((net_dev->state == ETH_STATE_PASSIVE) || (net_dev->state == ETH_STATE_INIT)) @@ -588,11 +593,12 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) printf("dpni_disable() failed\n"); #ifdef CONFIG_PHYLIB - if (priv->phydev && bus != NULL) - phy_shutdown(priv->phydev); - else { - free(priv->phydev); - priv->phydev = NULL; + phydev = wriop_get_phy_dev(priv->dpmac_id); + if (phydev && bus) { + phy_shutdown(phydev); + } else { + free(phydev); + wriop_set_phy_dev(priv->dpmac_id, NULL); } #endif diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.h b/drivers/net/ldpaa_eth/ldpaa_eth.h index ee784a55ee..3f9154b5bb 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.h +++ b/drivers/net/ldpaa_eth/ldpaa_eth.h @@ -127,7 +127,6 @@ struct ldpaa_eth_priv { uint16_t tx_flow_id; enum ldpaa_eth_type type; /* 1G or 10G ethernet */ - struct phy_device *phydev; }; struct dprc_endpoint dpmac_endpoint; diff --git a/drivers/net/ldpaa_eth/ldpaa_wriop.c b/drivers/net/ldpaa_eth/ldpaa_wriop.c index 0731a795c8..afbb1ca91e 100644 --- a/drivers/net/ldpaa_eth/ldpaa_wriop.c +++ b/drivers/net/ldpaa_eth/ldpaa_wriop.c @@ -26,6 +26,7 @@ void wriop_init_dpmac(int sd, int dpmac_id, int lane_prtcl) dpmac_info[dpmac_id].enabled = 0; dpmac_info[dpmac_id].id = 0; dpmac_info[dpmac_id].phy_addr = -1; + dpmac_info[dpmac_id].phydev = NULL; dpmac_info[dpmac_id].enet_if = PHY_INTERFACE_MODE_NONE; enet_if = wriop_dpmac_enet_if(dpmac_id, lane_prtcl); @@ -42,6 +43,7 @@ void wriop_init_dpmac_enet_if(int dpmac_id, phy_interface_t enet_if) dpmac_info[dpmac_id].id = dpmac_id; dpmac_info[dpmac_id].phy_addr = -1; dpmac_info[dpmac_id].enet_if = enet_if; + dpmac_info[dpmac_id].phydev = NULL; } -- cgit From f259c43d893071e3a4f43536735c959dcf320d99 Mon Sep 17 00:00:00 2001 From: Pankaj Bansal Date: Wed, 10 Oct 2018 14:08:31 +0530 Subject: driver: net: fsl-mc: fix error handing in init_phy if an error occurs during init_phy, we should free the phydev structure which has been allocated by phy_connect. Signed-off-by: Pankaj Bansal Acked-by: Joe Hershberger --- drivers/net/ldpaa_eth/ldpaa_eth.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index 39f81daafd..ef5286c325 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -23,6 +23,7 @@ static int init_phy(struct eth_device *dev) struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv; struct phy_device *phydev = NULL; struct mii_dev *bus; + int ret; bus = wriop_get_mdio(priv->dpmac_id); if (bus == NULL) @@ -37,7 +38,14 @@ static int init_phy(struct eth_device *dev) wriop_set_phy_dev(priv->dpmac_id, phydev); - return phy_config(phydev); + ret = phy_config(phydev); + + if (ret) { + free(phydev); + wriop_set_phy_dev(priv->dpmac_id, NULL); + } + + return ret; } #endif -- cgit From a3cb5340f12425537d6c94d8e95d570f6d6a504b Mon Sep 17 00:00:00 2001 From: Pankaj Bansal Date: Wed, 10 Oct 2018 14:08:32 +0530 Subject: driver: net: fsl-mc: Modify the dpmac link detection method when there is no phy present for a dpmac, a dummy phy device is created. when we move to multiple phy method, we need to create as many dummy phy devices. Change this method so that we don't need to create dummy phy devices. We always report linkup if no phy is present. Signed-off-by: Pankaj Bansal Acked-by: Joe Hershberger --- drivers/net/ldpaa_eth/ldpaa_eth.c | 119 ++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 62 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index ef5286c325..4f0b977449 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -385,6 +385,59 @@ error: return err; } +static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv, + struct dpmac_link_state *state) +{ + struct phy_device *phydev = NULL; + phy_interface_t enet_if; + int err; + + /* let's start off with maximum capabilities + */ + enet_if = wriop_get_enet_if(priv->dpmac_id); + switch (enet_if) { + case PHY_INTERFACE_MODE_XGMII: + state->rate = SPEED_10000; + break; + default: + state->rate = SPEED_1000; + break; + } + state->up = 1; + +#ifdef CONFIG_PHYLIB + state->options |= DPMAC_LINK_OPT_AUTONEG; + + phydev = wriop_get_phy_dev(priv->dpmac_id); + if (phydev) { + err = phy_startup(phydev); + if (err) { + printf("%s: Could not initialize\n", phydev->dev->name); + state->up = 0; + } + if (phydev->link) { + state->rate = min(state->rate, (uint32_t)phydev->speed); + if (!phydev->duplex) + state->options |= DPMAC_LINK_OPT_HALF_DUPLEX; + if (!phydev->autoneg) + state->options &= ~DPMAC_LINK_OPT_AUTONEG; + } else { + state->up = 0; + } + } +#endif + if (!phydev) + state->options &= ~DPMAC_LINK_OPT_AUTONEG; + + if (!state->up) { + state->rate = 0; + state->options = 0; + return -ENOLINK; + } + + return 0; +} + static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; @@ -393,10 +446,7 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) struct dpni_link_state link_state; #endif int err = 0; - struct mii_dev *bus; - phy_interface_t enet_if; struct dpni_queue d_queue; - struct phy_device *phydev = NULL; if (net_dev->state == ETH_STATE_ACTIVE) return 0; @@ -416,45 +466,9 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) if (err < 0) goto err_dpmac_setup; -#ifdef CONFIG_PHYLIB - phydev = wriop_get_phy_dev(priv->dpmac_id); - if (phydev) { - err = phy_startup(phydev); - if (err) { - printf("%s: Could not initialize\n", - phydev->dev->name); - goto err_dpmac_bind; - } - } -#else - phydev = (struct phy_device *)malloc(sizeof(struct phy_device)); - memset(phydev, 0, sizeof(struct phy_device)); - wriop_set_phy_dev(priv->dpmac_id, phydev); - - phydev->speed = SPEED_1000; - phydev->link = 1; - phydev->duplex = DUPLEX_FULL; -#endif - - bus = wriop_get_mdio(priv->dpmac_id); - enet_if = wriop_get_enet_if(priv->dpmac_id); - if ((bus == NULL) && - (enet_if == PHY_INTERFACE_MODE_XGMII)) { - phydev = (struct phy_device *) - malloc(sizeof(struct phy_device)); - memset(phydev, 0, sizeof(struct phy_device)); - wriop_set_phy_dev(priv->dpmac_id, phydev); - - phydev->speed = SPEED_10000; - phydev->link = 1; - phydev->duplex = DUPLEX_FULL; - } - - if (!phydev->link) { - printf("%s: No link.\n", phydev->dev->name); - err = -1; + err = ldpaa_get_dpmac_state(priv, &dpmac_link_state); + if (err < 0) goto err_dpmac_bind; - } /* DPMAC binding DPNI */ err = ldpaa_dpmac_bind(priv); @@ -488,18 +502,6 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) return err; } - dpmac_link_state.rate = phydev->speed; - - if (phydev->autoneg == AUTONEG_DISABLE) - dpmac_link_state.options &= ~DPMAC_LINK_OPT_AUTONEG; - else - dpmac_link_state.options |= DPMAC_LINK_OPT_AUTONEG; - - if (phydev->duplex == DUPLEX_HALF) - dpmac_link_state.options |= DPMAC_LINK_OPT_HALF_DUPLEX; - - dpmac_link_state.up = phydev->link; - err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle, &dpmac_link_state); if (err < 0) { @@ -542,7 +544,7 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) goto err_qdid; } - return phydev->link; + return dpmac_link_state.up; err_qdid: err_get_queue: @@ -565,9 +567,6 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; int err = 0; -#ifdef CONFIG_PHYLIB - struct mii_dev *bus = wriop_get_mdio(priv->dpmac_id); -#endif struct phy_device *phydev = NULL; if ((net_dev->state == ETH_STATE_PASSIVE) || @@ -602,12 +601,8 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) #ifdef CONFIG_PHYLIB phydev = wriop_get_phy_dev(priv->dpmac_id); - if (phydev && bus) { + if (phydev) phy_shutdown(phydev); - } else { - free(phydev); - wriop_set_phy_dev(priv->dpmac_id, NULL); - } #endif /* Free DPBP handle and reset. */ -- cgit From 1ed19a1421691e0238b79f8ac14dc4a65ddd7ad0 Mon Sep 17 00:00:00 2001 From: Pankaj Bansal Date: Wed, 10 Oct 2018 14:08:33 +0530 Subject: driver: net: fsl-mc: initialize dpmac irrespective of phy The dpmac initalization should not depend on phy. As the phy is not necessary to be present for dpmac to function. Therefore, remove dpmac initialization dependency from phy. Signed-off-by: Pankaj Bansal Acked-by: Joe Hershberger --- drivers/net/fsl-mc/mc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c index d9a897dc86..b245fbc681 100644 --- a/drivers/net/fsl-mc/mc.c +++ b/drivers/net/fsl-mc/mc.c @@ -363,8 +363,7 @@ static int mc_fixup_mac_addrs(void *blob, enum mc_fixup_type type) for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) { /* port not enabled */ - if ((wriop_is_enabled_dpmac(i) != 1) || - (wriop_get_phy_address(i) == -1)) + if (wriop_is_enabled_dpmac(i) != 1) continue; snprintf(ethname, ETH_NAME_LEN, "DPMAC%d@%s", i, @@ -886,8 +885,7 @@ int fsl_mc_ldpaa_init(bd_t *bis) int i; for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) - if ((wriop_is_enabled_dpmac(i) == 1) && - (wriop_get_phy_address(i) != -1)) + if (wriop_is_enabled_dpmac(i) == 1) ldpaa_eth_init(i, wriop_get_enet_if(i)); return 0; } -- cgit From 1a048cd65645338069d591108031fa4ebe96d53f Mon Sep 17 00:00:00 2001 From: Pankaj Bansal Date: Wed, 10 Oct 2018 14:08:34 +0530 Subject: driver: net: fsl-mc: Add support of multiple phys for dpmac Till now we have had cases where we had one phy device per dpmac. Now, with the upcoming products (LX2160AQDS), we have cases, where there are sometimes two phy devices for one dpmac. One phy for TX lanes and one phy for RX lanes. to handle such cases, add the support for multiple phys in ethernet driver. The ethernet link is up if all the phy devices connected to one dpmac report link up. also the link capabilities are limited by the weakest phy device. i.e. say if there are two phys for one dpmac. one operates at 10G without autoneg and other operate at 1G with autoneg. Then the ethernet interface will operate at 1G without autoneg. Signed-off-by: Pankaj Bansal Acked-by: Joe Hershberger --- drivers/net/ldpaa_eth/ldpaa_eth.c | 66 +++++++++++++++++++++++----------- drivers/net/ldpaa_eth/ldpaa_wriop.c | 71 +++++++++++++++++++++++++------------ 2 files changed, 94 insertions(+), 43 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index 4f0b977449..fe1c03e9e4 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -23,26 +23,40 @@ static int init_phy(struct eth_device *dev) struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv; struct phy_device *phydev = NULL; struct mii_dev *bus; - int ret; + int phy_addr, phy_num; + int ret = 0; bus = wriop_get_mdio(priv->dpmac_id); if (bus == NULL) return 0; - phydev = phy_connect(bus, wriop_get_phy_address(priv->dpmac_id), - dev, wriop_get_enet_if(priv->dpmac_id)); - if (!phydev) { - printf("Failed to connect\n"); - return -1; - } - - wriop_set_phy_dev(priv->dpmac_id, phydev); + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + phy_addr = wriop_get_phy_address(priv->dpmac_id, phy_num); + if (phy_addr < 0) + continue; - ret = phy_config(phydev); + phydev = phy_connect(bus, phy_addr, dev, + wriop_get_enet_if(priv->dpmac_id)); + if (!phydev) { + printf("Failed to connect\n"); + ret = -ENODEV; + break; + } + wriop_set_phy_dev(priv->dpmac_id, phy_num, phydev); + ret = phy_config(phydev); + if (ret) + break; + } if (ret) { - free(phydev); - wriop_set_phy_dev(priv->dpmac_id, NULL); + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num); + if (!phydev) + continue; + + free(phydev); + wriop_set_phy_dev(priv->dpmac_id, phy_num, NULL); + } } return ret; @@ -390,10 +404,10 @@ static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv, { struct phy_device *phydev = NULL; phy_interface_t enet_if; + int phy_num, phys_detected; int err; - /* let's start off with maximum capabilities - */ + /* let's start off with maximum capabilities */ enet_if = wriop_get_enet_if(priv->dpmac_id); switch (enet_if) { case PHY_INTERFACE_MODE_XGMII: @@ -405,15 +419,22 @@ static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv, } state->up = 1; + phys_detected = 0; #ifdef CONFIG_PHYLIB state->options |= DPMAC_LINK_OPT_AUTONEG; - phydev = wriop_get_phy_dev(priv->dpmac_id); - if (phydev) { + /* start the phy devices one by one and update the dpmac state */ + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num); + if (!phydev) + continue; + + phys_detected++; err = phy_startup(phydev); if (err) { printf("%s: Could not initialize\n", phydev->dev->name); state->up = 0; + break; } if (phydev->link) { state->rate = min(state->rate, (uint32_t)phydev->speed); @@ -422,11 +443,13 @@ static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv, if (!phydev->autoneg) state->options &= ~DPMAC_LINK_OPT_AUTONEG; } else { + /* break out of loop even if one phy is down */ state->up = 0; + break; } } #endif - if (!phydev) + if (!phys_detected) state->options &= ~DPMAC_LINK_OPT_AUTONEG; if (!state->up) { @@ -568,6 +591,7 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; int err = 0; struct phy_device *phydev = NULL; + int phy_num; if ((net_dev->state == ETH_STATE_PASSIVE) || (net_dev->state == ETH_STATE_INIT)) @@ -600,9 +624,11 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) printf("dpni_disable() failed\n"); #ifdef CONFIG_PHYLIB - phydev = wriop_get_phy_dev(priv->dpmac_id); - if (phydev) - phy_shutdown(phydev); + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num); + if (phydev) + phy_shutdown(phydev); + } #endif /* Free DPBP handle and reset. */ diff --git a/drivers/net/ldpaa_eth/ldpaa_wriop.c b/drivers/net/ldpaa_eth/ldpaa_wriop.c index afbb1ca91e..06a284ad68 100644 --- a/drivers/net/ldpaa_eth/ldpaa_wriop.c +++ b/drivers/net/ldpaa_eth/ldpaa_wriop.c @@ -22,11 +22,10 @@ __weak phy_interface_t wriop_dpmac_enet_if(int dpmac_id, int lane_prtc) void wriop_init_dpmac(int sd, int dpmac_id, int lane_prtcl) { phy_interface_t enet_if; + int phy_num; dpmac_info[dpmac_id].enabled = 0; dpmac_info[dpmac_id].id = 0; - dpmac_info[dpmac_id].phy_addr = -1; - dpmac_info[dpmac_id].phydev = NULL; dpmac_info[dpmac_id].enet_if = PHY_INTERFACE_MODE_NONE; enet_if = wriop_dpmac_enet_if(dpmac_id, lane_prtcl); @@ -35,15 +34,23 @@ void wriop_init_dpmac(int sd, int dpmac_id, int lane_prtcl) dpmac_info[dpmac_id].id = dpmac_id; dpmac_info[dpmac_id].enet_if = enet_if; } + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + dpmac_info[dpmac_id].phydev[phy_num] = NULL; + dpmac_info[dpmac_id].phy_addr[phy_num] = -1; + } } void wriop_init_dpmac_enet_if(int dpmac_id, phy_interface_t enet_if) { + int phy_num; + dpmac_info[dpmac_id].enabled = 1; dpmac_info[dpmac_id].id = dpmac_id; - dpmac_info[dpmac_id].phy_addr = -1; dpmac_info[dpmac_id].enet_if = enet_if; - dpmac_info[dpmac_id].phydev = NULL; + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + dpmac_info[dpmac_id].phydev[phy_num] = NULL; + dpmac_info[dpmac_id].phy_addr[phy_num] = -1; + } } @@ -60,47 +67,53 @@ static int wriop_dpmac_to_index(int dpmac_id) return -1; } -void wriop_disable_dpmac(int dpmac_id) +int wriop_disable_dpmac(int dpmac_id) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return; + return -ENODEV; dpmac_info[i].enabled = 0; wriop_dpmac_disable(dpmac_id); + + return 0; } -void wriop_enable_dpmac(int dpmac_id) +int wriop_enable_dpmac(int dpmac_id) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return; + return -ENODEV; dpmac_info[i].enabled = 1; wriop_dpmac_enable(dpmac_id); + + return 0; } -u8 wriop_is_enabled_dpmac(int dpmac_id) +int wriop_is_enabled_dpmac(int dpmac_id) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return -1; + return -ENODEV; return dpmac_info[i].enabled; } -void wriop_set_mdio(int dpmac_id, struct mii_dev *bus) +int wriop_set_mdio(int dpmac_id, struct mii_dev *bus) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return; + return -ENODEV; dpmac_info[i].bus = bus; + + return 0; } struct mii_dev *wriop_get_mdio(int dpmac_id) @@ -113,44 +126,56 @@ struct mii_dev *wriop_get_mdio(int dpmac_id) return dpmac_info[i].bus; } -void wriop_set_phy_address(int dpmac_id, int address) +int wriop_set_phy_address(int dpmac_id, int phy_num, int address) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return; + return -ENODEV; + if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM) + return -EINVAL; + + dpmac_info[i].phy_addr[phy_num] = address; - dpmac_info[i].phy_addr = address; + return 0; } -int wriop_get_phy_address(int dpmac_id) +int wriop_get_phy_address(int dpmac_id, int phy_num) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return -1; + return -ENODEV; + if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM) + return -EINVAL; - return dpmac_info[i].phy_addr; + return dpmac_info[i].phy_addr[phy_num]; } -void wriop_set_phy_dev(int dpmac_id, struct phy_device *phydev) +int wriop_set_phy_dev(int dpmac_id, int phy_num, struct phy_device *phydev) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return; + return -ENODEV; + if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM) + return -EINVAL; - dpmac_info[i].phydev = phydev; + dpmac_info[i].phydev[phy_num] = phydev; + + return 0; } -struct phy_device *wriop_get_phy_dev(int dpmac_id) +struct phy_device *wriop_get_phy_dev(int dpmac_id, int phy_num) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) return NULL; + if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM) + return NULL; - return dpmac_info[i].phydev; + return dpmac_info[i].phydev[phy_num]; } phy_interface_t wriop_get_enet_if(int dpmac_id) -- cgit