From fa795f452541ce07b33be603de36cac3c5d7dfcf Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Wed, 4 Nov 2020 14:45:14 +0100 Subject: [PATCH 01/11] net: eth-uclass: avoid running start() twice without stop() Running the start() handler twice without a stop() inbetween completely breaks communication for some ethernet drivers like fec_mxc. eth_halt() is called before each eth_init(). Due to the switch to eth_is_active() in commit 68acb51f442f ("net: Only call halt on a driver that has been init'ed"), this is not sufficient anymore when netconsole is active: eth_init_state_only()/eth_halt_state_only() manipulate the state check that is performed by eth_is_active() without actually calling into the driver. The issue can be triggered by starting a network operation (e.g. ping or tftp) while netconsole is active. Add an additional "running" flag that reflects the actual state of the driver and use it to ensure that eth_halt() actually stops the device as it is supposed to. Fixes: 68acb51f442f ("net: Only call halt on a driver that has been init'ed") Signed-off-by: Matthias Schiffer --- net/eth-uclass.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/net/eth-uclass.c b/net/eth-uclass.c index 0156324032..7c2454f5ae 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -26,6 +26,7 @@ DECLARE_GLOBAL_DATA_PTR; */ struct eth_device_priv { enum eth_state_t state; + bool running; }; /** @@ -290,6 +291,7 @@ int eth_init(void) dev_get_uclass_priv(current); priv->state = ETH_STATE_ACTIVE; + priv->running = true; return 0; } } else { @@ -319,13 +321,16 @@ void eth_halt(void) struct eth_device_priv *priv; current = eth_get_dev(); - if (!current || !eth_is_active(current)) + if (!current) + return; + + priv = dev_get_uclass_priv(current); + if (!priv || !priv->running) return; eth_get_ops(current)->stop(current); - priv = dev_get_uclass_priv(current); - if (priv) - priv->state = ETH_STATE_PASSIVE; + priv->state = ETH_STATE_PASSIVE; + priv->running = false; } int eth_is_active(struct udevice *dev) @@ -534,6 +539,7 @@ static int eth_post_probe(struct udevice *dev) #endif priv->state = ETH_STATE_INIT; + priv->running = false; /* Check if the device has a valid MAC address in device tree */ if (!eth_dev_get_mac_address(dev, pdata->enetaddr) || From 3f8905ade23bcfc6d8d852178993d321da2d02db Mon Sep 17 00:00:00 2001 From: Ian Ray Date: Wed, 4 Nov 2020 17:26:01 +0100 Subject: [PATCH 02/11] net: e1000: implement eth_write_hwaddr for DM_ETH Implement programming MAC address to the hardware also for device model configuration. Fixes: b565b18a294f ("board: ge: bx50v3: Enable DM for PCI and ethernet") Signed-off-by: Ian Ray Signed-off-by: Sebastian Reichel --- drivers/net/e1000.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 3b3dd104cd..733588302d 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -869,7 +869,6 @@ e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset, return E1000_SUCCESS; } -#ifndef CONFIG_DM_ETH /****************************************************************************** * e1000_write_eeprom_srwr - Write to Shadow Ram using EEWR * @hw: pointer to the HW structure @@ -1035,7 +1034,6 @@ static int32_t e1000_update_eeprom_checksum_i210(struct e1000_hw *hw) out: return ret_val; } -#endif /****************************************************************************** * Verifies that the EEPROM has a valid checksum @@ -5660,13 +5658,24 @@ e1000_poll(struct eth_device *nic) return len ? 1 : 0; } +#endif /* !CONFIG_DM_ETH */ +#ifdef CONFIG_DM_ETH +static int e1000_write_hwaddr(struct udevice *dev) +#else static int e1000_write_hwaddr(struct eth_device *dev) +#endif { #ifndef CONFIG_E1000_NO_NVM - unsigned char *mac = dev->enetaddr; unsigned char current_mac[6]; +#ifdef CONFIG_DM_ETH + struct eth_pdata *plat = dev_get_plat(dev); + struct e1000_hw *hw = dev_get_priv(dev); + u8 *mac = plat->enetaddr; +#else struct e1000_hw *hw = dev->priv; + u8 *mac = dev->enetaddr; +#endif uint16_t data[3]; int ret_val, i; @@ -5700,6 +5709,7 @@ static int e1000_write_hwaddr(struct eth_device *dev) #endif } +#ifndef CONFIG_DM_ETH /************************************************************************** PROBE - Look for an adapter, this routine's visible to the outside You should omit the last argument struct pci_device * for a non-PCI NIC @@ -5926,6 +5936,7 @@ static const struct eth_ops e1000_eth_ops = { .recv = e1000_eth_recv, .stop = e1000_eth_stop, .free_pkt = e1000_free_pkt, + .write_hwaddr = e1000_write_hwaddr, }; static const struct udevice_id e1000_eth_ids[] = { From 51723c5581241a3886a5adaa780c09138163d0b2 Mon Sep 17 00:00:00 2001 From: David Rivshin Date: Sat, 14 Nov 2020 22:12:47 -0500 Subject: [PATCH 03/11] net: Do not respond to ICMP_ECHO_REQUEST if we do not have an IP address While doing DHCP the interface IP is set to 0.0.0.0. This causes the check in net.c on dst_ip to be effectively skipped, and all IP datagrams are accepted up the IP stack. In the case of an ICMP_ECHO_REQUEST for the matching MAC address (regardless of destination IP), the result is that an ICMP_ECHO_REPLY is sent. The source address of the ICMP_ECHO_REPLY is 0.0.0.0, which is an illegal source address. This can happen in common practice with the following sequence: DHCP (U-Boot or OS) acquires IP address 10.0.0.1 System reboots U-Boot starts DHCP and send DHCP DISCOVER DHCP server decides to OFFER 10.0.0.1 again (perhaps because of existing lease or manual configuration) DHCP server tries to PING 10.0.0.1 to see if anyone is squatting on it DHCP server still has our MAC address in its ARP table for 10.0.0.1 U-Boot receives PING, and responds with an illegal source address This may further result in a the DHCP server seeing the response as confirmation that someone is squatting on 10.0.0.1, and picking a new IP address from the pool to try again Signed-off-by: David Rivshin --- net/ping.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ping.c b/net/ping.c index 0e33660f6c..075df3663f 100644 --- a/net/ping.c +++ b/net/ping.c @@ -90,6 +90,9 @@ void ping_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) net_set_state(NETLOOP_SUCCESS); return; case ICMP_ECHO_REQUEST: + if (net_ip.s_addr == 0) + return; + eth_hdr_size = net_update_ether(et, et->et_src, PROT_IP); debug_cond(DEBUG_DEV_PKT, From beb61e13b8134c9aeaf1b2c0a2e13ed71d3be59e Mon Sep 17 00:00:00 2001 From: Harm Berntsen Date: Fri, 27 Nov 2020 21:45:56 +0000 Subject: [PATCH 04/11] net: tftp: Fix incorrect tftp_next_ack on no OACK When the tftp server did not send any OACK, the tftp_next_ack variable was not set to the correct value . As the server was transmitting blocks we generated a lot of 'Received unexpected block: $n, expected $n+1' error messages. Depending on the timeout setting the transfer could still complete though. Signed-off-by: Harm Berntsen CC: Ramon Fried Reviewed-By: Ramon Fried --- net/tftp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/tftp.c b/net/tftp.c index 2cfa0b1486..03079ded34 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -630,8 +630,10 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, tftp_cur_block++; tftp_cur_block %= TFTP_SEQUENCE_SIZE; - if (tftp_state == STATE_SEND_RRQ) + if (tftp_state == STATE_SEND_RRQ) { debug("Server did not acknowledge any options!\n"); + tftp_next_ack = tftp_windowsize; + } if (tftp_state == STATE_SEND_RRQ || tftp_state == STATE_OACK || tftp_state == STATE_RECV_WRQ) { From c1ab73814515c865896b0abc54d3071a1a273537 Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Fri, 4 Dec 2020 20:59:58 +0100 Subject: [PATCH 05/11] net: eth_legacy - fix build CMD_PCAP Fix typo which would cause a build error. Fixes: 3eaac6307df ("net: introduce packet capture support") Signed-off-by: Jorge Ramirez-Ortiz --- net/eth_legacy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/eth_legacy.c b/net/eth_legacy.c index 6e0c058761..6870afb505 100644 --- a/net/eth_legacy.c +++ b/net/eth_legacy.c @@ -365,7 +365,7 @@ int eth_send(void *packet, int length) ret = eth_current->send(eth_current, packet, length); #if defined(CONFIG_CMD_PCAP) if (ret >= 0) - pcap_post(packet, lengeth, true); + pcap_post(packet, length, true); #endif return ret; } From 0be3d1fafb54bc2fd3d5862304528d7a21e500d9 Mon Sep 17 00:00:00 2001 From: Hongwei Zhang Date: Thu, 10 Dec 2020 18:11:09 -0500 Subject: [PATCH 06/11] net: ftgmac100: Read and retain MAC address Read and retain MAC address across flash and QEMU support. Signed-off-by: Hongwei Zhang --- drivers/net/ftgmac100.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c index 69e299d6a3..0687230b4b 100644 --- a/drivers/net/ftgmac100.c +++ b/drivers/net/ftgmac100.c @@ -270,6 +270,28 @@ static int ftgmac100_set_mac(struct ftgmac100_data *priv, return 0; } +/* + * Get MAC address + */ +static int ftgmac100_get_mac(struct ftgmac100_data *priv, + unsigned char *mac) +{ + struct ftgmac100 *ftgmac100 = priv->iobase; + unsigned int maddr = readl(&ftgmac100->mac_madr); + unsigned int laddr = readl(&ftgmac100->mac_ladr); + + debug("%s(%x %x)\n", __func__, maddr, laddr); + + mac[0] = (maddr >> 8) & 0xff; + mac[1] = maddr & 0xff; + mac[2] = (laddr >> 24) & 0xff; + mac[3] = (laddr >> 16) & 0xff; + mac[4] = (laddr >> 8) & 0xff; + mac[5] = laddr & 0xff; + + return 0; +} + /* * disable transmitter, receiver */ @@ -511,6 +533,14 @@ static int ftgmac100_write_hwaddr(struct udevice *dev) return ftgmac100_set_mac(priv, pdata->enetaddr); } +static int ftgmac_read_hwaddr(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct ftgmac100_data *priv = dev_get_priv(dev); + + return ftgmac100_get_mac(priv, pdata->enetaddr); +} + static int ftgmac100_of_to_plat(struct udevice *dev) { struct eth_pdata *pdata = dev_get_plat(dev); @@ -571,6 +601,8 @@ static int ftgmac100_probe(struct udevice *dev) goto out; } + ftgmac_read_hwaddr(dev); + out: if (ret) clk_release_bulk(&priv->clks); From 92fdad28cfdf078fe34c198ef430933e7b2825a1 Mon Sep 17 00:00:00 2001 From: Matthias Brugger Date: Fri, 18 Dec 2020 10:28:03 +0100 Subject: [PATCH 07/11] lib: uuid: use RNG device if present When calculating a random UUID we use a weak seed. Use a RNG device if present to increase entropy. Signed-off-by: Matthias Brugger Reviewed-by: Torsten Duwe --- lib/uuid.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/uuid.c b/lib/uuid.c index 54a93aacc9..5bc68674d0 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include /* * UUID - Universally Unique IDentifier - 128 bits unique number. @@ -249,9 +251,22 @@ void gen_rand_uuid(unsigned char *uuid_bin) { u32 ptr[4]; struct uuid *uuid = (struct uuid *)ptr; - int i; + int i, ret; + struct udevice *devp; + u32 randv = 0; - srand(get_ticks() + rand()); + if (IS_ENABLED(CONFIG_DM_RNG)) { + ret = uclass_get_device(UCLASS_RNG, 0, &devp); + if (ret) { + ret = dm_rng_read(devp, &randv, sizeof(randv)); + if (ret < 0) + randv = 0; + } + } + if (randv) + srand(randv); + else + srand(get_ticks() + rand()); /* Set all fields randomly */ for (i = 0; i < 4; i++) From ea707dc0aaafad34bba436b206af340c410dfb1b Mon Sep 17 00:00:00 2001 From: Matthias Brugger Date: Fri, 18 Dec 2020 10:28:04 +0100 Subject: [PATCH 08/11] net: Use NDRNG device in srand_mac() When calling srand_mac we use a weak seed dependent on the mac address. If present, use a RNG device instead to incerase entropy. Signed-off-by: Matthias Brugger Reviewed-by: Torsten Duwe --- net/net_rand.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/net/net_rand.h b/net/net_rand.h index 4bf9bd817e..6a52cda85e 100644 --- a/net/net_rand.h +++ b/net/net_rand.h @@ -10,6 +10,8 @@ #define __NET_RAND_H__ #include +#include +#include /* * Return a seed for the PRNG derived from the eth0 MAC address. @@ -37,7 +39,22 @@ static inline unsigned int seed_mac(void) */ static inline void srand_mac(void) { - srand(seed_mac()); + int ret; + struct udevice *devp; + u32 randv = 0; + + if (IS_ENABLED(CONFIG_DM_RNG)) { + ret = uclass_get_device(UCLASS_RNG, 0, &devp); + if (ret) { + ret = dm_rng_read(devp, &randv, sizeof(randv)); + if (ret < 0) + randv = 0; + } + } + if (randv) + srand(randv); + else + srand(seed_mac()); } #endif /* __NET_RAND_H__ */ From dd70ff481526a87f69bec732fcc402c60441560c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 6 Jan 2021 15:16:01 +0100 Subject: [PATCH 09/11] net: ks8851: Reset internal RXFC count on bad packet A sporadic condition occurs when the "bad packet" error is triggered repeatedly, which results in "bad packet" messages scrolling on the console during transfer. To avoid triggering this, reset the internal RXFC count on the first occurance of the "bad packet", which forces the code to re-read the RX packet count from the MAC, and prevents any additional "bad packet" messages if there are no more packets in the MAC. Also print better debug information if this condition occurs. Signed-off-by: Marek Vasut Cc: Eugen Hristev Cc: Joe Hershberger Cc: Tom Rini --- drivers/net/ks8851_mll.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c index 91c2d10ffc..9dd9b33955 100644 --- a/drivers/net/ks8851_mll.c +++ b/drivers/net/ks8851_mll.c @@ -251,7 +251,8 @@ static int ks_rcv(struct ks_net *ks, uchar *data) } ks_wrreg16(ks, KS_RXQCR, RXQCR_CMD_CNTL | RXQCR_RRXEF); - printf(DRIVERNAME ": bad packet\n"); + printf(DRIVERNAME ": bad packet (sts=0x%04x len=0x%04x)\n", sts, len); + ks->rxfc = 0; return 0; } From 6f1e668d964ebd3244a99288ea4bda7b7b8627c3 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 7 Jan 2021 11:12:16 +0100 Subject: [PATCH 10/11] net: dwc_eth_qos: Pad descriptors to cacheline size The DWMAC4 IP has the possibility to skip up to 7 AXI bus width size words after the descriptor. Use this to pad the descriptors to cacheline size and remove the need for noncached memory altogether. Moreover, this lets Tegra use the generic cache flush / invalidate operations. Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Patrice Chotard Cc: Patrick Delaunay Cc: Ramon Fried Cc: Stephen Warren Tested-by: Stephen Warren Reviewed-by: Stephen Warren Tested-by: Patrice Chotard --- drivers/net/dwc_eth_qos.c | 129 +++++++++++++++---------------------- include/configs/stm32mp1.h | 1 - 2 files changed, 51 insertions(+), 79 deletions(-) diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 45a1648ad5..944412958d 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -209,6 +209,7 @@ struct eqos_dma_regs { #define EQOS_DMA_SYSBUS_MODE_BLEN8 BIT(2) #define EQOS_DMA_SYSBUS_MODE_BLEN4 BIT(1) +#define EQOS_DMA_CH0_CONTROL_DSL_SHIFT 18 #define EQOS_DMA_CH0_CONTROL_PBLX8 BIT(16) #define EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT 16 @@ -239,37 +240,15 @@ struct eqos_tegra186_regs { #define EQOS_AUTO_CAL_STATUS_ACTIVE BIT(31) /* Descriptors */ - -#define EQOS_DESCRIPTOR_WORDS 4 -#define EQOS_DESCRIPTOR_SIZE (EQOS_DESCRIPTOR_WORDS * 4) /* We assume ARCH_DMA_MINALIGN >= 16; 16 is the EQOS HW minimum */ #define EQOS_DESCRIPTOR_ALIGN ARCH_DMA_MINALIGN #define EQOS_DESCRIPTORS_TX 4 #define EQOS_DESCRIPTORS_RX 4 #define EQOS_DESCRIPTORS_NUM (EQOS_DESCRIPTORS_TX + EQOS_DESCRIPTORS_RX) -#define EQOS_DESCRIPTORS_SIZE ALIGN(EQOS_DESCRIPTORS_NUM * \ - EQOS_DESCRIPTOR_SIZE, ARCH_DMA_MINALIGN) #define EQOS_BUFFER_ALIGN ARCH_DMA_MINALIGN #define EQOS_MAX_PACKET_SIZE ALIGN(1568, ARCH_DMA_MINALIGN) #define EQOS_RX_BUFFER_SIZE (EQOS_DESCRIPTORS_RX * EQOS_MAX_PACKET_SIZE) -/* - * Warn if the cache-line size is larger than the descriptor size. In such - * cases the driver will likely fail because the CPU needs to flush the cache - * when requeuing RX buffers, therefore descriptors written by the hardware - * may be discarded. Architectures with full IO coherence, such as x86, do not - * experience this issue, and hence are excluded from this condition. - * - * This can be fixed by defining CONFIG_SYS_NONCACHED_MEMORY which will cause - * the driver to allocate descriptors from a pool of non-cached memory. - */ -#if EQOS_DESCRIPTOR_SIZE < ARCH_DMA_MINALIGN -#if !defined(CONFIG_SYS_NONCACHED_MEMORY) && \ - !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) && !defined(CONFIG_X86) -#warning Cache line size is larger than descriptor size -#endif -#endif - struct eqos_desc { u32 des0; u32 des1; @@ -282,12 +261,17 @@ struct eqos_desc { #define EQOS_DESC3_LD BIT(28) #define EQOS_DESC3_BUF1V BIT(24) +#define EQOS_AXI_WIDTH_32 4 +#define EQOS_AXI_WIDTH_64 8 +#define EQOS_AXI_WIDTH_128 16 + struct eqos_config { bool reg_access_always_ok; int mdio_wait; int swr_wait; int config_mac; int config_mac_mdio; + unsigned int axi_bus_width; phy_interface_t (*interface)(struct udevice *dev); struct eqos_ops *ops; }; @@ -330,9 +314,8 @@ struct eqos_priv { int phyaddr; u32 max_speed; void *descs; - struct eqos_desc *tx_descs; - struct eqos_desc *rx_descs; int tx_desc_idx, rx_desc_idx; + unsigned int desc_size; void *tx_dma_buf; void *rx_dma_buf; void *rx_pkt; @@ -358,63 +341,42 @@ struct eqos_priv { * not have the same constraints since they are 1536 bytes large, so they * are unlikely to share cache-lines. */ -static void *eqos_alloc_descs(unsigned int num) +static void *eqos_alloc_descs(struct eqos_priv *eqos, unsigned int num) { -#ifdef CONFIG_SYS_NONCACHED_MEMORY - return (void *)noncached_alloc(EQOS_DESCRIPTORS_SIZE, - EQOS_DESCRIPTOR_ALIGN); -#else - return memalign(EQOS_DESCRIPTOR_ALIGN, EQOS_DESCRIPTORS_SIZE); -#endif + eqos->desc_size = ALIGN(sizeof(struct eqos_desc), + (unsigned int)ARCH_DMA_MINALIGN); + + return memalign(eqos->desc_size, num * eqos->desc_size); } static void eqos_free_descs(void *descs) { -#ifdef CONFIG_SYS_NONCACHED_MEMORY - /* FIXME: noncached_alloc() has no opposite */ -#else free(descs); -#endif } -static void eqos_inval_desc_tegra186(void *desc) +static struct eqos_desc *eqos_get_desc(struct eqos_priv *eqos, + unsigned int num, bool rx) { -#ifndef CONFIG_SYS_NONCACHED_MEMORY - unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1); - unsigned long end = ALIGN(start + EQOS_DESCRIPTOR_SIZE, - ARCH_DMA_MINALIGN); - - invalidate_dcache_range(start, end); -#endif + return eqos->descs + + ((rx ? EQOS_DESCRIPTORS_TX : 0) + num) * eqos->desc_size; } static void eqos_inval_desc_generic(void *desc) { -#ifndef CONFIG_SYS_NONCACHED_MEMORY - unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN); - unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE, - ARCH_DMA_MINALIGN); + unsigned long start = (unsigned long)desc; + unsigned long end = ALIGN(start + sizeof(struct eqos_desc), + ARCH_DMA_MINALIGN); invalidate_dcache_range(start, end); -#endif -} - -static void eqos_flush_desc_tegra186(void *desc) -{ -#ifndef CONFIG_SYS_NONCACHED_MEMORY - flush_cache((unsigned long)desc, EQOS_DESCRIPTOR_SIZE); -#endif } static void eqos_flush_desc_generic(void *desc) { -#ifndef CONFIG_SYS_NONCACHED_MEMORY - unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN); - unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE, - ARCH_DMA_MINALIGN); + unsigned long start = (unsigned long)desc; + unsigned long end = ALIGN(start + sizeof(struct eqos_desc), + ARCH_DMA_MINALIGN); flush_dcache_range(start, end); -#endif } static void eqos_inval_buffer_tegra186(void *buf, size_t size) @@ -1167,6 +1129,7 @@ static int eqos_start(struct udevice *dev) ulong rate; u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl; ulong last_rx_desc; + ulong desc_pad; debug("%s(dev=%p):\n", __func__, dev); @@ -1405,8 +1368,12 @@ static int eqos_start(struct udevice *dev) EQOS_MAX_PACKET_SIZE << EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT); + desc_pad = (eqos->desc_size - sizeof(struct eqos_desc)) / + eqos->config->axi_bus_width; + setbits_le32(&eqos->dma_regs->ch0_control, - EQOS_DMA_CH0_CONTROL_PBLX8); + EQOS_DMA_CH0_CONTROL_PBLX8 | + (desc_pad << EQOS_DMA_CH0_CONTROL_DSL_SHIFT)); /* * Burst length must be < 1/2 FIFO size. @@ -1435,9 +1402,15 @@ static int eqos_start(struct udevice *dev) /* Set up descriptors */ - memset(eqos->descs, 0, EQOS_DESCRIPTORS_SIZE); + memset(eqos->descs, 0, eqos->desc_size * EQOS_DESCRIPTORS_NUM); + + for (i = 0; i < EQOS_DESCRIPTORS_TX; i++) { + struct eqos_desc *tx_desc = eqos_get_desc(eqos, i, false); + eqos->config->ops->eqos_flush_desc(tx_desc); + } + for (i = 0; i < EQOS_DESCRIPTORS_RX; i++) { - struct eqos_desc *rx_desc = &(eqos->rx_descs[i]); + struct eqos_desc *rx_desc = eqos_get_desc(eqos, i, true); rx_desc->des0 = (u32)(ulong)(eqos->rx_dma_buf + (i * EQOS_MAX_PACKET_SIZE)); rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; @@ -1449,12 +1422,14 @@ static int eqos_start(struct udevice *dev) } writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress); - writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address); + writel((ulong)eqos_get_desc(eqos, 0, false), + &eqos->dma_regs->ch0_txdesc_list_address); writel(EQOS_DESCRIPTORS_TX - 1, &eqos->dma_regs->ch0_txdesc_ring_length); writel(0, &eqos->dma_regs->ch0_rxdesc_list_haddress); - writel((ulong)eqos->rx_descs, &eqos->dma_regs->ch0_rxdesc_list_address); + writel((ulong)eqos_get_desc(eqos, 0, true), + &eqos->dma_regs->ch0_rxdesc_list_address); writel(EQOS_DESCRIPTORS_RX - 1, &eqos->dma_regs->ch0_rxdesc_ring_length); @@ -1473,7 +1448,7 @@ static int eqos_start(struct udevice *dev) * that's not distinguishable from none of the descriptors being * available. */ - last_rx_desc = (ulong)&(eqos->rx_descs[(EQOS_DESCRIPTORS_RX - 1)]); + last_rx_desc = (ulong)eqos_get_desc(eqos, EQOS_DESCRIPTORS_RX - 1, true); writel(last_rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); eqos->started = true; @@ -1558,7 +1533,7 @@ static int eqos_send(struct udevice *dev, void *packet, int length) memcpy(eqos->tx_dma_buf, packet, length); eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length); - tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]); + tx_desc = eqos_get_desc(eqos, eqos->tx_desc_idx, false); eqos->tx_desc_idx++; eqos->tx_desc_idx %= EQOS_DESCRIPTORS_TX; @@ -1573,7 +1548,7 @@ static int eqos_send(struct udevice *dev, void *packet, int length) tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length; eqos->config->ops->eqos_flush_desc(tx_desc); - writel((ulong)(&(eqos->tx_descs[eqos->tx_desc_idx])), + writel((ulong)eqos_get_desc(eqos, eqos->tx_desc_idx, false), &eqos->dma_regs->ch0_txdesc_tail_pointer); for (i = 0; i < 1000000; i++) { @@ -1596,7 +1571,7 @@ static int eqos_recv(struct udevice *dev, int flags, uchar **packetp) debug("%s(dev=%p, flags=%x):\n", __func__, dev, flags); - rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); + rx_desc = eqos_get_desc(eqos, eqos->rx_desc_idx, true); eqos->config->ops->eqos_inval_desc(rx_desc); if (rx_desc->des3 & EQOS_DESC3_OWN) { debug("%s: RX packet not available\n", __func__); @@ -1631,7 +1606,7 @@ static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) eqos->config->ops->eqos_inval_buffer(packet, length); - rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); + rx_desc = eqos_get_desc(eqos, eqos->rx_desc_idx, true); rx_desc->des0 = 0; mb(); @@ -1663,17 +1638,12 @@ static int eqos_probe_resources_core(struct udevice *dev) debug("%s(dev=%p):\n", __func__, dev); - eqos->descs = eqos_alloc_descs(EQOS_DESCRIPTORS_TX + - EQOS_DESCRIPTORS_RX); + eqos->descs = eqos_alloc_descs(eqos, EQOS_DESCRIPTORS_NUM); if (!eqos->descs) { debug("%s: eqos_alloc_descs() failed\n", __func__); ret = -ENOMEM; goto err; } - eqos->tx_descs = (struct eqos_desc *)eqos->descs; - eqos->rx_descs = (eqos->tx_descs + EQOS_DESCRIPTORS_TX); - debug("%s: tx_descs=%p, rx_descs=%p\n", __func__, eqos->tx_descs, - eqos->rx_descs); eqos->tx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_MAX_PACKET_SIZE); if (!eqos->tx_dma_buf) { @@ -2083,8 +2053,8 @@ static const struct eth_ops eqos_ops = { }; static struct eqos_ops eqos_tegra186_ops = { - .eqos_inval_desc = eqos_inval_desc_tegra186, - .eqos_flush_desc = eqos_flush_desc_tegra186, + .eqos_inval_desc = eqos_inval_desc_generic, + .eqos_flush_desc = eqos_flush_desc_generic, .eqos_inval_buffer = eqos_inval_buffer_tegra186, .eqos_flush_buffer = eqos_flush_buffer_tegra186, .eqos_probe_resources = eqos_probe_resources_tegra186, @@ -2105,6 +2075,7 @@ static const struct eqos_config __maybe_unused eqos_tegra186_config = { .swr_wait = 10, .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35, + .axi_bus_width = EQOS_AXI_WIDTH_128, .interface = eqos_get_interface_tegra186, .ops = &eqos_tegra186_ops }; @@ -2132,6 +2103,7 @@ static const struct eqos_config __maybe_unused eqos_stm32_config = { .swr_wait = 50, .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV, .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, + .axi_bus_width = EQOS_AXI_WIDTH_64, .interface = eqos_get_interface_stm32, .ops = &eqos_stm32_ops }; @@ -2159,6 +2131,7 @@ struct eqos_config __maybe_unused eqos_imx_config = { .swr_wait = 50, .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, + .axi_bus_width = EQOS_AXI_WIDTH_64, .interface = eqos_get_interface_imx, .ops = &eqos_imx_ops }; diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h index 1aa7514ac7..863b652ca4 100644 --- a/include/configs/stm32mp1.h +++ b/include/configs/stm32mp1.h @@ -69,7 +69,6 @@ /* Ethernet need */ #ifdef CONFIG_DWC_ETH_QOS -#define CONFIG_SYS_NONCACHED_MEMORY (1 * SZ_1M) /* 1M */ #define CONFIG_SERVERIP 192.168.1.1 #define CONFIG_BOOTP_SERVERIP #define CONFIG_SYS_AUTOLOAD "no" From 1231184caacad32c180d7e2338a645f7dfe9571a Mon Sep 17 00:00:00 2001 From: David Wu Date: Fri, 8 Jan 2021 10:53:05 +0800 Subject: [PATCH 11/11] net: eth-uclass: Change uclass driver name to ethernet dev_read_alias_seq() used uc_drv->name compared to alias stem string, Ethernet's alias stem uses "ethernet", which does not match the eth-uclass driver name "eth", can not get the correct index of ethernet alias namer. So it seems change uclass driver name to match the alias stem is a more reasonable way. Signed-off-by: David Wu Reviewed-by: Simon Glass --- net/eth-uclass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/eth-uclass.c b/net/eth-uclass.c index 7c2454f5ae..8a22d8bf59 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -597,8 +597,8 @@ static int eth_pre_remove(struct udevice *dev) return 0; } -UCLASS_DRIVER(eth) = { - .name = "eth", +UCLASS_DRIVER(ethernet) = { + .name = "ethernet", .id = UCLASS_ETH, .post_bind = eth_post_bind, .pre_unbind = eth_pre_unbind,