From patchwork Sun May 17 16:24:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 245916 List-Id: U-Boot discussion From: marek.vasut at gmail.com (Marek Vasut) Date: Sun, 17 May 2020 18:24:11 +0200 Subject: [PATCH 01/15] net: pcnet: Drop typedef struct pcnet_priv_t Message-ID: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> Use struct pcnet_priv all over the place instead. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index f97e7f8c6a..f34fc4abbf 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -73,15 +73,15 @@ struct pcnet_uncached_priv { struct pcnet_init_block init_block; }; -typedef struct pcnet_priv { +struct pcnet_priv { struct pcnet_uncached_priv *uc; /* Receive Buffer space */ unsigned char (*rx_buf)[RX_RING_SIZE][PKT_BUF_SZ + 4]; int cur_rx; int cur_tx; -} pcnet_priv_t; +}; -static pcnet_priv_t *lp; +static struct pcnet_priv *lp; /* Offsets from base I/O address for WIO mode */ #define PCNET_RDP 0x10 @@ -337,9 +337,9 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) * must be aligned on 16-byte boundaries. */ if (lp == NULL) { - addr = (unsigned long)malloc(sizeof(pcnet_priv_t) + 0x10); + addr = (unsigned long)malloc(sizeof(*lp) + 0x10); addr = (addr + 0xf) & ~0xf; - lp = (pcnet_priv_t *)addr; + lp = (struct pcnet_priv *)addr; addr = (unsigned long)memalign(ARCH_DMA_MINALIGN, sizeof(*lp->uc)); From patchwork Sun May 17 16:24:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 245915 List-Id: U-Boot discussion From: marek.vasut at gmail.com (Marek Vasut) Date: Sun, 17 May 2020 18:24:12 +0200 Subject: [PATCH 02/15] net: pcnet: Drop PCNET_HAS_PROM In-Reply-To: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> References: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> Message-ID: <20200517162425.76584-2-marek.vasut+renesas@gmail.com> All of one PCNET users has this option set, make this default and drop this config option. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 5 ----- include/configs/malta.h | 1 - 2 files changed, 6 deletions(-) diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index f34fc4abbf..15d102d3a9 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -238,10 +238,7 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) { int chip_version; char *chipname; - -#ifdef PCNET_HAS_PROM int i; -#endif /* Reset the PCnet controller */ pcnet_reset(dev); @@ -276,7 +273,6 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) PCNET_DEBUG1("AMD %s\n", chipname); -#ifdef PCNET_HAS_PROM /* * In most chips, after a chip reset, the ethernet address is read from * the station address PROM at the base address and programmed into the @@ -290,7 +286,6 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) dev->enetaddr[2 * i] = val & 0x0ff; dev->enetaddr[2 * i + 1] = (val >> 8) & 0x0ff; } -#endif /* PCNET_HAS_PROM */ return 0; } diff --git a/include/configs/malta.h b/include/configs/malta.h index 773d7c23ed..82c90042d9 100644 --- a/include/configs/malta.h +++ b/include/configs/malta.h @@ -16,7 +16,6 @@ #define CONFIG_PCI_GT64120 #define CONFIG_PCI_MSC01 #define CONFIG_PCNET -#define PCNET_HAS_PROM #define CONFIG_SYS_ISA_IO_BASE_ADDRESS 0 From patchwork Sun May 17 16:24:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 245917 List-Id: U-Boot discussion From: marek.vasut at gmail.com (Marek Vasut) Date: Sun, 17 May 2020 18:24:13 +0200 Subject: [PATCH 03/15] net: pcnet: Use PCI_DEVICE() to define PCI device compat list In-Reply-To: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> References: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> Message-ID: <20200517162425.76584-3-marek.vasut+renesas@gmail.com> Use this macro to fully fill the PCI device ID table. This is mandatory for the DM PCI support, which checks all the fields. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 15d102d3a9..d3f3297e12 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -152,7 +152,7 @@ static inline pci_addr_t pcnet_virt_to_mem(const struct eth_device *dev, } static struct pci_device_id supported[] = { - {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE}, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE) }, {} }; From patchwork Sun May 17 16:24:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 245918 List-Id: U-Boot discussion From: marek.vasut at gmail.com (Marek Vasut) Date: Sun, 17 May 2020 18:24:14 +0200 Subject: [PATCH 04/15] net: pcnet: Simplify private data allocation In-Reply-To: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> References: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> Message-ID: <20200517162425.76584-4-marek.vasut+renesas@gmail.com> The current code is horribly complex. Both the RX and TX buffer descriptors are 16 bytes in size, the init block is 32 bytes in size, so simplify the code such that the entire private data of the driver are allocated cache aligned and the RX and TX buffer descriptors are part of the private data. This removes multiple malloc calls and cache flushes. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index d3f3297e12..5bbd290eec 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -71,12 +72,13 @@ struct pcnet_uncached_priv { struct pcnet_rx_head rx_ring[RX_RING_SIZE]; struct pcnet_tx_head tx_ring[TX_RING_SIZE]; struct pcnet_init_block init_block; -}; +} __aligned(ARCH_DMA_MINALIGN); struct pcnet_priv { - struct pcnet_uncached_priv *uc; + struct pcnet_uncached_priv ucp; /* Receive Buffer space */ - unsigned char (*rx_buf)[RX_RING_SIZE][PKT_BUF_SZ + 4]; + unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; + struct pcnet_uncached_priv *uc; int cur_rx; int cur_tx; }; @@ -332,22 +334,11 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) * must be aligned on 16-byte boundaries. */ if (lp == NULL) { - addr = (unsigned long)malloc(sizeof(*lp) + 0x10); - addr = (addr + 0xf) & ~0xf; - lp = (struct pcnet_priv *)addr; - - addr = (unsigned long)memalign(ARCH_DMA_MINALIGN, - sizeof(*lp->uc)); - flush_dcache_range(addr, addr + sizeof(*lp->uc)); - addr = (unsigned long)map_physmem(addr, - roundup(sizeof(*lp->uc), ARCH_DMA_MINALIGN), - MAP_NOCACHE); - lp->uc = (struct pcnet_uncached_priv *)addr; - - addr = (unsigned long)memalign(ARCH_DMA_MINALIGN, - sizeof(*lp->rx_buf)); - flush_dcache_range(addr, addr + sizeof(*lp->rx_buf)); - lp->rx_buf = (void *)addr; + lp = malloc_cache_aligned(sizeof(*lp)); + lp->uc = map_physmem((phys_addr_t)&lp->ucp, + sizeof(lp->ucp), MAP_NOCACHE); + flush_dcache_range((unsigned long)lp, + (unsigned long)lp + sizeof(*lp)); } uc = lp->uc; @@ -361,7 +352,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) */ lp->cur_rx = 0; for (i = 0; i < RX_RING_SIZE; i++) { - addr = pcnet_virt_to_mem(dev, (*lp->rx_buf)[i]); + addr = pcnet_virt_to_mem(dev, lp->rx_buf[i]); uc->rx_ring[i].base = cpu_to_le32(addr); uc->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ); uc->rx_ring[i].status = cpu_to_le16(0x8000); @@ -518,7 +509,7 @@ static int pcnet_recv (struct eth_device *dev) printf("%s: Rx%d: invalid packet length %d\n", dev->name, lp->cur_rx, pkt_len); } else { - buf = (*lp->rx_buf)[lp->cur_rx]; + buf = lp->rx_buf[lp->cur_rx]; invalidate_dcache_range((unsigned long)buf, (unsigned long)buf + pkt_len); net_process_received_packet(buf, pkt_len); From patchwork Sun May 17 16:24:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 245919 List-Id: U-Boot discussion From: marek.vasut at gmail.com (Marek Vasut) Date: Sun, 17 May 2020 18:24:15 +0200 Subject: [PATCH 05/15] net: pcnet: Replace memset+malloc with calloc In-Reply-To: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> References: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> Message-ID: <20200517162425.76584-5-marek.vasut+renesas@gmail.com> This combination of functions can be replaced with calloc(), make it so. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 5bbd290eec..f5e14ca60d 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -181,12 +181,11 @@ int pcnet_initialize(bd_t *bis) /* * Allocate and pre-fill the device structure. */ - dev = (struct eth_device *)malloc(sizeof(*dev)); + dev = calloc(1, sizeof(*dev)); if (!dev) { printf("pcnet: Can not allocate memory\n"); break; } - memset(dev, 0, sizeof(*dev)); dev->priv = (void *)(unsigned long)devbusfn; sprintf(dev->name, "pcnet#%d", dev_nr); From patchwork Sun May 17 16:24:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 245920 List-Id: U-Boot discussion From: marek.vasut at gmail.com (Marek Vasut) Date: Sun, 17 May 2020 18:24:16 +0200 Subject: [PATCH 06/15] net: pcnet: Move private data allocation to initialize In-Reply-To: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> References: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> Message-ID: <20200517162425.76584-6-marek.vasut+renesas@gmail.com> The private data allocation does not have to be done every time the NIC is initialized at run time, move the allocation to initialize function, which means it will be done only once when the driver starts. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index f5e14ca60d..3a9f20a7f0 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -186,6 +186,20 @@ int pcnet_initialize(bd_t *bis) printf("pcnet: Can not allocate memory\n"); break; } + + /* + * We only maintain one structure because the drivers will + * never be used concurrently. In 32bit mode the RX and TX + * ring entries must be aligned on 16-byte boundaries. + */ + if (!lp) { + lp = malloc_cache_aligned(sizeof(*lp)); + lp->uc = map_physmem((phys_addr_t)&lp->ucp, + sizeof(lp->ucp), MAP_NOCACHE); + flush_dcache_range((unsigned long)lp, + (unsigned long)lp + sizeof(*lp)); + } + dev->priv = (void *)(unsigned long)devbusfn; sprintf(dev->name, "pcnet#%d", dev_nr); @@ -327,19 +341,6 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) val |= 0x3 << 10; pcnet_write_csr(dev, 80, val); - /* - * We only maintain one structure because the drivers will never - * be used concurrently. In 32bit mode the RX and TX ring entries - * must be aligned on 16-byte boundaries. - */ - if (lp == NULL) { - lp = malloc_cache_aligned(sizeof(*lp)); - lp->uc = map_physmem((phys_addr_t)&lp->ucp, - sizeof(lp->ucp), MAP_NOCACHE); - flush_dcache_range((unsigned long)lp, - (unsigned long)lp + sizeof(*lp)); - } - uc = lp->uc; uc->init_block.mode = cpu_to_le16(0x0000); From patchwork Sun May 17 16:24:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 245921 List-Id: U-Boot discussion From: marek.vasut at gmail.com (Marek Vasut) Date: Sun, 17 May 2020 18:24:17 +0200 Subject: [PATCH 07/15] net: pcnet: Move initialize function at the end In-Reply-To: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> References: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> Message-ID: <20200517162425.76584-7-marek.vasut+renesas@gmail.com> Move the function at the end of the driver, so we could drop various forward declarations later. No functional change. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 180 ++++++++++++++++++++++---------------------- 1 file changed, 89 insertions(+), 91 deletions(-) diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 3a9f20a7f0..ec8d080794 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -158,97 +158,6 @@ static struct pci_device_id supported[] = { {} }; - -int pcnet_initialize(bd_t *bis) -{ - pci_dev_t devbusfn; - struct eth_device *dev; - u16 command, status; - int dev_nr = 0; - u32 bar; - - PCNET_DEBUG1("\npcnet_initialize...\n"); - - for (dev_nr = 0;; dev_nr++) { - - /* - * Find the PCnet PCI device(s). - */ - devbusfn = pci_find_devices(supported, dev_nr); - if (devbusfn < 0) - break; - - /* - * Allocate and pre-fill the device structure. - */ - dev = calloc(1, sizeof(*dev)); - if (!dev) { - printf("pcnet: Can not allocate memory\n"); - break; - } - - /* - * We only maintain one structure because the drivers will - * never be used concurrently. In 32bit mode the RX and TX - * ring entries must be aligned on 16-byte boundaries. - */ - if (!lp) { - lp = malloc_cache_aligned(sizeof(*lp)); - lp->uc = map_physmem((phys_addr_t)&lp->ucp, - sizeof(lp->ucp), MAP_NOCACHE); - flush_dcache_range((unsigned long)lp, - (unsigned long)lp + sizeof(*lp)); - } - - dev->priv = (void *)(unsigned long)devbusfn; - sprintf(dev->name, "pcnet#%d", dev_nr); - - /* - * Setup the PCI device. - */ - pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &bar); - dev->iobase = pci_mem_to_phys(devbusfn, bar); - dev->iobase &= ~0xf; - - PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%lx: ", - dev->name, devbusfn, (unsigned long)dev->iobase); - - command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - pci_write_config_word(devbusfn, PCI_COMMAND, command); - pci_read_config_word(devbusfn, PCI_COMMAND, &status); - if ((status & command) != command) { - printf("%s: Couldn't enable IO access or Bus Mastering\n", - dev->name); - free(dev); - continue; - } - - pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x40); - - /* - * Probe the PCnet chip. - */ - if (pcnet_probe(dev, bis, dev_nr) < 0) { - free(dev); - continue; - } - - /* - * Setup device structure and register the driver. - */ - dev->init = pcnet_init; - dev->halt = pcnet_halt; - dev->send = pcnet_send; - dev->recv = pcnet_recv; - - eth_register(dev); - } - - udelay(10 * 1000); - - return dev_nr; -} - static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) { int chip_version; @@ -545,3 +454,92 @@ static void pcnet_halt(struct eth_device *dev) if (i <= 0) printf("%s: TIMEOUT: controller reset failed\n", dev->name); } + +int pcnet_initialize(bd_t *bis) +{ + pci_dev_t devbusfn; + struct eth_device *dev; + u16 command, status; + int dev_nr = 0; + u32 bar; + + PCNET_DEBUG1("\npcnet_initialize...\n"); + + for (dev_nr = 0; ; dev_nr++) { + /* + * Find the PCnet PCI device(s). + */ + devbusfn = pci_find_devices(supported, dev_nr); + if (devbusfn < 0) + break; + + /* + * Allocate and pre-fill the device structure. + */ + dev = calloc(1, sizeof(*dev)); + if (!dev) { + printf("pcnet: Can not allocate memory\n"); + break; + } + + /* + * We only maintain one structure because the drivers will + * never be used concurrently. In 32bit mode the RX and TX + * ring entries must be aligned on 16-byte boundaries. + */ + if (!lp) { + lp = malloc_cache_aligned(sizeof(*lp)); + lp->uc = map_physmem((phys_addr_t)&lp->ucp, + sizeof(lp->ucp), MAP_NOCACHE); + flush_dcache_range((unsigned long)lp, + (unsigned long)lp + sizeof(*lp)); + } + + dev->priv = (void *)(unsigned long)devbusfn; + sprintf(dev->name, "pcnet#%d", dev_nr); + + /* + * Setup the PCI device. + */ + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &bar); + dev->iobase = pci_mem_to_phys(devbusfn, bar); + dev->iobase &= ~0xf; + + PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%lx: ", + dev->name, devbusfn, (unsigned long)dev->iobase); + + command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + pci_write_config_word(devbusfn, PCI_COMMAND, command); + pci_read_config_word(devbusfn, PCI_COMMAND, &status); + if ((status & command) != command) { + printf("%s: Couldn't enable IO access or Bus Mastering\n", + dev->name); + free(dev); + continue; + } + + pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x40); + + /* + * Probe the PCnet chip. + */ + if (pcnet_probe(dev, bis, dev_nr) < 0) { + free(dev); + continue; + } + + /* + * Setup device structure and register the driver. + */ + dev->init = pcnet_init; + dev->halt = pcnet_halt; + dev->send = pcnet_send; + dev->recv = pcnet_recv; + + eth_register(dev); + } + + udelay(10 * 1000); + + return dev_nr; +} From patchwork Sun May 17 16:24:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 245922 List-Id: U-Boot discussion From: marek.vasut at gmail.com (Marek Vasut) Date: Sun, 17 May 2020 18:24:18 +0200 Subject: [PATCH 08/15] net: pcnet: Drop useless forward declarations In-Reply-To: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> References: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> Message-ID: <20200517162425.76584-8-marek.vasut+renesas@gmail.com> Remove those as they are not needed anymore. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index ec8d080794..3e04781aa4 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -138,12 +138,6 @@ static int pcnet_check(struct eth_device *dev) return readw(base + PCNET_RAP) == 88; } -static int pcnet_init (struct eth_device *dev, bd_t * bis); -static int pcnet_send(struct eth_device *dev, void *packet, int length); -static int pcnet_recv (struct eth_device *dev); -static void pcnet_halt (struct eth_device *dev); -static int pcnet_probe (struct eth_device *dev, bd_t * bis, int dev_num); - static inline pci_addr_t pcnet_virt_to_mem(const struct eth_device *dev, void *addr) { From patchwork Sun May 17 16:24:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 245923 List-Id: U-Boot discussion From: marek.vasut at gmail.com (Marek Vasut) Date: Sun, 17 May 2020 18:24:19 +0200 Subject: [PATCH 09/15] net: pcnet: Wrap devbusfn into private data In-Reply-To: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> References: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> Message-ID: <20200517162425.76584-9-marek.vasut+renesas@gmail.com> Instead of using eth_device priv for this PCI devbusfn, free it so it could be used for driver private data, and wrap devbusfn into those driver private data. Note that using the name dev for the variable is a trick left for later, when DM support is in place, so dm_pci_virt_to_mem() can be used with minimal ifdeffery. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 3e04781aa4..c8f93ae2a5 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -79,6 +79,7 @@ struct pcnet_priv { /* Receive Buffer space */ unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; struct pcnet_uncached_priv *uc; + pci_dev_t dev; int cur_rx; int cur_tx; }; @@ -138,13 +139,11 @@ static int pcnet_check(struct eth_device *dev) return readw(base + PCNET_RAP) == 88; } -static inline pci_addr_t pcnet_virt_to_mem(const struct eth_device *dev, - void *addr) +static inline pci_addr_t pcnet_virt_to_mem(struct pcnet_priv *lp, void *addr) { - pci_dev_t devbusfn = (pci_dev_t)(unsigned long)dev->priv; void *virt_addr = addr; - return pci_virt_to_mem(devbusfn, virt_addr); + return pci_virt_to_mem(lp->dev, virt_addr); } static struct pci_device_id supported[] = { @@ -255,7 +254,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) */ lp->cur_rx = 0; for (i = 0; i < RX_RING_SIZE; i++) { - addr = pcnet_virt_to_mem(dev, lp->rx_buf[i]); + addr = pcnet_virt_to_mem(lp, lp->rx_buf[i]); uc->rx_ring[i].base = cpu_to_le32(addr); uc->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ); uc->rx_ring[i].status = cpu_to_le16(0x8000); @@ -287,9 +286,9 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) uc->init_block.tlen_rlen = cpu_to_le16(TX_RING_LEN_BITS | RX_RING_LEN_BITS); - addr = pcnet_virt_to_mem(dev, uc->rx_ring); + addr = pcnet_virt_to_mem(lp, uc->rx_ring); uc->init_block.rx_ring = cpu_to_le32(addr); - addr = pcnet_virt_to_mem(dev, uc->tx_ring); + addr = pcnet_virt_to_mem(lp, uc->tx_ring); uc->init_block.tx_ring = cpu_to_le32(addr); PCNET_DEBUG1("\ntlen_rlen=0x%x rx_ring=0x%x tx_ring=0x%x\n", @@ -300,7 +299,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) * Tell the controller where the Init Block is located. */ barrier(); - addr = pcnet_virt_to_mem(dev, &lp->uc->init_block); + addr = pcnet_virt_to_mem(lp, &lp->uc->init_block); pcnet_write_csr(dev, 1, addr & 0xffff); pcnet_write_csr(dev, 2, (addr >> 16) & 0xffff); @@ -358,7 +357,7 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) * Setup Tx ring. Caution: the write order is important here, * set the status with the "ownership" bits last. */ - addr = pcnet_virt_to_mem(dev, packet); + addr = pcnet_virt_to_mem(lp, packet); writew(-pkt_len, &entry->length); writel(0, &entry->misc); writel(addr, &entry->base); @@ -489,7 +488,7 @@ int pcnet_initialize(bd_t *bis) (unsigned long)lp + sizeof(*lp)); } - dev->priv = (void *)(unsigned long)devbusfn; + lp->dev = devbusfn; sprintf(dev->name, "pcnet#%d", dev_nr); /* From patchwork Sun May 17 16:24:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 245924 List-Id: U-Boot discussion From: marek.vasut at gmail.com (Marek Vasut) Date: Sun, 17 May 2020 18:24:20 +0200 Subject: [PATCH 10/15] net: pcnet: Pass private data through dev->priv In-Reply-To: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> References: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> Message-ID: <20200517162425.76584-10-marek.vasut+renesas@gmail.com> Get rid of the global point to private data, and rather pass it thought dev->priv. Also remove the unnecessary check for lp being non-NULL, since it is always NULL at this point. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index c8f93ae2a5..ced025c1a5 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -84,8 +84,6 @@ struct pcnet_priv { int cur_tx; }; -static struct pcnet_priv *lp; - /* Offsets from base I/O address for WIO mode */ #define PCNET_RDP 0x10 #define PCNET_RAP 0x12 @@ -209,6 +207,7 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) static int pcnet_init(struct eth_device *dev, bd_t *bis) { + struct pcnet_priv *lp = dev->priv; struct pcnet_uncached_priv *uc; int i, val; unsigned long addr; @@ -328,6 +327,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) { + struct pcnet_priv *lp = dev->priv; int i, status; u32 addr; struct pcnet_tx_head *entry = &lp->uc->tx_ring[lp->cur_tx]; @@ -376,6 +376,7 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) static int pcnet_recv (struct eth_device *dev) { + struct pcnet_priv *lp = dev->priv; struct pcnet_rx_head *entry; unsigned char *buf; int pkt_len = 0; @@ -452,6 +453,7 @@ int pcnet_initialize(bd_t *bis) { pci_dev_t devbusfn; struct eth_device *dev; + struct pcnet_priv *lp; u16 command, status; int dev_nr = 0; u32 bar; @@ -480,15 +482,13 @@ int pcnet_initialize(bd_t *bis) * never be used concurrently. In 32bit mode the RX and TX * ring entries must be aligned on 16-byte boundaries. */ - if (!lp) { - lp = malloc_cache_aligned(sizeof(*lp)); - lp->uc = map_physmem((phys_addr_t)&lp->ucp, - sizeof(lp->ucp), MAP_NOCACHE); - flush_dcache_range((unsigned long)lp, - (unsigned long)lp + sizeof(*lp)); - } - + lp = malloc_cache_aligned(sizeof(*lp)); + lp->uc = map_physmem((phys_addr_t)&lp->ucp, + sizeof(lp->ucp), MAP_NOCACHE); lp->dev = devbusfn; + flush_dcache_range((unsigned long)lp, + (unsigned long)lp + sizeof(*lp)); + dev->priv = lp; sprintf(dev->name, "pcnet#%d", dev_nr); /* From patchwork Sun May 17 16:24:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 245926 List-Id: U-Boot discussion From: marek.vasut at gmail.com (Marek Vasut) Date: Sun, 17 May 2020 18:24:21 +0200 Subject: [PATCH 11/15] net: pcnet: Wrap iobase into private data In-Reply-To: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> References: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> Message-ID: <20200517162425.76584-11-marek.vasut+renesas@gmail.com> Instead of using the non-DM-only iobase in struct eth_device, add one into the private data to make DM and non-DM operation possible. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 103 ++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 57 deletions(-) diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index ced025c1a5..fb38d3b7a3 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -80,6 +80,7 @@ struct pcnet_priv { unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; struct pcnet_uncached_priv *uc; pci_dev_t dev; + void __iomem *iobase; int cur_rx; int cur_tx; }; @@ -90,51 +91,39 @@ struct pcnet_priv { #define PCNET_RESET 0x14 #define PCNET_BDP 0x16 -static u16 pcnet_read_csr(struct eth_device *dev, int index) +static u16 pcnet_read_csr(struct pcnet_priv *lp, int index) { - void __iomem *base = (void __iomem *)dev->iobase; - - writew(index, base + PCNET_RAP); - return readw(base + PCNET_RDP); + writew(index, lp->iobase + PCNET_RAP); + return readw(lp->iobase + PCNET_RDP); } -static void pcnet_write_csr(struct eth_device *dev, int index, u16 val) +static void pcnet_write_csr(struct pcnet_priv *lp, int index, u16 val) { - void __iomem *base = (void __iomem *)dev->iobase; - - writew(index, base + PCNET_RAP); - writew(val, base + PCNET_RDP); + writew(index, lp->iobase + PCNET_RAP); + writew(val, lp->iobase + PCNET_RDP); } -static u16 pcnet_read_bcr(struct eth_device *dev, int index) +static u16 pcnet_read_bcr(struct pcnet_priv *lp, int index) { - void __iomem *base = (void __iomem *)dev->iobase; - - writew(index, base + PCNET_RAP); - return readw(base + PCNET_BDP); + writew(index, lp->iobase + PCNET_RAP); + return readw(lp->iobase + PCNET_BDP); } -static void pcnet_write_bcr(struct eth_device *dev, int index, u16 val) +static void pcnet_write_bcr(struct pcnet_priv *lp, int index, u16 val) { - void __iomem *base = (void __iomem *)dev->iobase; - - writew(index, base + PCNET_RAP); - writew(val, base + PCNET_BDP); + writew(index, lp->iobase + PCNET_RAP); + writew(val, lp->iobase + PCNET_BDP); } -static void pcnet_reset(struct eth_device *dev) +static void pcnet_reset(struct pcnet_priv *lp) { - void __iomem *base = (void __iomem *)dev->iobase; - - readw(base + PCNET_RESET); + readw(lp->iobase + PCNET_RESET); } -static int pcnet_check(struct eth_device *dev) +static int pcnet_check(struct pcnet_priv *lp) { - void __iomem *base = (void __iomem *)dev->iobase; - - writew(88, base + PCNET_RAP); - return readw(base + PCNET_RAP) == 88; + writew(88, lp->iobase + PCNET_RAP); + return readw(lp->iobase + PCNET_RAP) == 88; } static inline pci_addr_t pcnet_virt_to_mem(struct pcnet_priv *lp, void *addr) @@ -151,22 +140,22 @@ static struct pci_device_id supported[] = { static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) { + struct pcnet_priv *lp = dev->priv; int chip_version; char *chipname; int i; /* Reset the PCnet controller */ - pcnet_reset(dev); + pcnet_reset(lp); /* Check if register access is working */ - if (pcnet_read_csr(dev, 0) != 4 || !pcnet_check(dev)) { + if (pcnet_read_csr(lp, 0) != 4 || !pcnet_check(lp)) { printf("%s: CSR register access check failed\n", dev->name); return -1; } /* Identify the chip */ - chip_version = - pcnet_read_csr(dev, 88) | (pcnet_read_csr(dev, 89) << 16); + chip_version = pcnet_read_csr(lp, 88) | (pcnet_read_csr(lp, 89) << 16); if ((chip_version & 0xfff) != 0x003) return -1; chip_version = (chip_version >> 12) & 0xffff; @@ -196,7 +185,7 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) for (i = 0; i < 3; i++) { unsigned int val; - val = pcnet_read_csr(dev, i + 12) & 0x0ffff; + val = pcnet_read_csr(lp, i + 12) & 0x0ffff; /* There may be endianness issues here. */ dev->enetaddr[2 * i] = val & 0x0ff; dev->enetaddr[2 * i + 1] = (val >> 8) & 0x0ff; @@ -215,17 +204,17 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) PCNET_DEBUG1("%s: pcnet_init...\n", dev->name); /* Switch pcnet to 32bit mode */ - pcnet_write_bcr(dev, 20, 2); + pcnet_write_bcr(lp, 20, 2); /* Set/reset autoselect bit */ - val = pcnet_read_bcr(dev, 2) & ~2; + val = pcnet_read_bcr(lp, 2) & ~2; val |= 2; - pcnet_write_bcr(dev, 2, val); + pcnet_write_bcr(lp, 2, val); /* Enable auto negotiate, setup, disable fd */ - val = pcnet_read_bcr(dev, 32) & ~0x98; + val = pcnet_read_bcr(lp, 32) & ~0x98; val |= 0x20; - pcnet_write_bcr(dev, 32, val); + pcnet_write_bcr(lp, 32, val); /* * Enable NOUFLO on supported controllers, with the transmit @@ -235,12 +224,12 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) * slower devices. Controllers which do not support NOUFLO will * simply be left with a larger transmit FIFO threshold. */ - val = pcnet_read_bcr(dev, 18); + val = pcnet_read_bcr(lp, 18); val |= 1 << 11; - pcnet_write_bcr(dev, 18, val); - val = pcnet_read_csr(dev, 80); + pcnet_write_bcr(lp, 18, val); + val = pcnet_read_csr(lp, 80); val |= 0x3 << 10; - pcnet_write_csr(dev, 80, val); + pcnet_write_csr(lp, 80, val); uc = lp->uc; @@ -299,28 +288,28 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) */ barrier(); addr = pcnet_virt_to_mem(lp, &lp->uc->init_block); - pcnet_write_csr(dev, 1, addr & 0xffff); - pcnet_write_csr(dev, 2, (addr >> 16) & 0xffff); + pcnet_write_csr(lp, 1, addr & 0xffff); + pcnet_write_csr(lp, 2, (addr >> 16) & 0xffff); - pcnet_write_csr(dev, 4, 0x0915); - pcnet_write_csr(dev, 0, 0x0001); /* start */ + pcnet_write_csr(lp, 4, 0x0915); + pcnet_write_csr(lp, 0, 0x0001); /* start */ /* Wait for Init Done bit */ for (i = 10000; i > 0; i--) { - if (pcnet_read_csr(dev, 0) & 0x0100) + if (pcnet_read_csr(lp, 0) & 0x0100) break; udelay(10); } if (i <= 0) { printf("%s: TIMEOUT: controller init failed\n", dev->name); - pcnet_reset(dev); + pcnet_reset(lp); return -1; } /* * Finally start network controller operation. */ - pcnet_write_csr(dev, 0, 0x0002); + pcnet_write_csr(lp, 0, 0x0002); return 0; } @@ -364,7 +353,7 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) writew(0x8300, &entry->status); /* Trigger an immediate send poll. */ - pcnet_write_csr(dev, 0, 0x0008); + pcnet_write_csr(lp, 0, 0x0008); failure: if (++lp->cur_tx >= TX_RING_SIZE) @@ -432,16 +421,17 @@ static int pcnet_recv (struct eth_device *dev) static void pcnet_halt(struct eth_device *dev) { + struct pcnet_priv *lp = dev->priv; int i; PCNET_DEBUG1("%s: pcnet_halt...\n", dev->name); /* Reset the PCnet controller */ - pcnet_reset(dev); + pcnet_reset(lp); /* Wait for Stop bit */ for (i = 1000; i > 0; i--) { - if (pcnet_read_csr(dev, 0) & 0x4) + if (pcnet_read_csr(lp, 0) & 0x4) break; udelay(10); } @@ -495,11 +485,10 @@ int pcnet_initialize(bd_t *bis) * Setup the PCI device. */ pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &bar); - dev->iobase = pci_mem_to_phys(devbusfn, bar); - dev->iobase &= ~0xf; + lp->iobase = (void *)(pci_mem_to_phys(devbusfn, bar) & ~0xf); - PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%lx: ", - dev->name, devbusfn, (unsigned long)dev->iobase); + PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%p: ", + dev->name, devbusfn, lp->iobase); command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; pci_write_config_word(devbusfn, PCI_COMMAND, command); From patchwork Sun May 17 16:24:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 245925 List-Id: U-Boot discussion From: marek.vasut at gmail.com (Marek Vasut) Date: Sun, 17 May 2020 18:24:22 +0200 Subject: [PATCH 12/15] net: pcnet: Wrap name and enetaddr into private data In-Reply-To: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> References: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> Message-ID: <20200517162425.76584-12-marek.vasut+renesas@gmail.com> Instead of using the non-DM-only name and enetaddr in struct eth_device, add pointers into the private data which can either point to that non-DM name or a DM one later on. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index fb38d3b7a3..8e99e41863 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -81,6 +81,8 @@ struct pcnet_priv { struct pcnet_uncached_priv *uc; pci_dev_t dev; void __iomem *iobase; + char *name; + u8 *enetaddr; int cur_rx; int cur_tx; }; @@ -150,7 +152,7 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) /* Check if register access is working */ if (pcnet_read_csr(lp, 0) != 4 || !pcnet_check(lp)) { - printf("%s: CSR register access check failed\n", dev->name); + printf("%s: CSR register access check failed\n", lp->name); return -1; } @@ -171,7 +173,7 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) break; default: printf("%s: PCnet version %#x not supported\n", - dev->name, chip_version); + lp->name, chip_version); return -1; } @@ -187,8 +189,8 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) val = pcnet_read_csr(lp, i + 12) & 0x0ffff; /* There may be endianness issues here. */ - dev->enetaddr[2 * i] = val & 0x0ff; - dev->enetaddr[2 * i + 1] = (val >> 8) & 0x0ff; + lp->enetaddr[2 * i] = val & 0x0ff; + lp->enetaddr[2 * i + 1] = (val >> 8) & 0x0ff; } return 0; @@ -201,7 +203,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) int i, val; unsigned long addr; - PCNET_DEBUG1("%s: pcnet_init...\n", dev->name); + PCNET_DEBUG1("%s: %s...\n", lp->name, __func__); /* Switch pcnet to 32bit mode */ pcnet_write_bcr(lp, 20, 2); @@ -268,7 +270,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) PCNET_DEBUG1("Init block at 0x%p: MAC", &lp->uc->init_block); for (i = 0; i < 6; i++) { - lp->uc->init_block.phys_addr[i] = dev->enetaddr[i]; + lp->uc->init_block.phys_addr[i] = lp->enetaddr[i]; PCNET_DEBUG1(" %02x", lp->uc->init_block.phys_addr[i]); } @@ -301,7 +303,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) udelay(10); } if (i <= 0) { - printf("%s: TIMEOUT: controller init failed\n", dev->name); + printf("%s: TIMEOUT: controller init failed\n", lp->name); pcnet_reset(lp); return -1; } @@ -337,7 +339,7 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) } if (i <= 0) { printf("%s: TIMEOUT: Tx%d failed (status = 0x%x)\n", - dev->name, lp->cur_tx, status); + lp->name, lp->cur_tx, status); pkt_len = 0; goto failure; } @@ -382,7 +384,7 @@ static int pcnet_recv (struct eth_device *dev) err_status = status >> 8; if (err_status != 0x03) { /* There was an error. */ - printf("%s: Rx%d", dev->name, lp->cur_rx); + printf("%s: Rx%d", lp->name, lp->cur_rx); PCNET_DEBUG1(" (status=0x%x)", err_status); if (err_status & 0x20) printf(" Frame"); @@ -399,7 +401,7 @@ static int pcnet_recv (struct eth_device *dev) pkt_len = (readl(&entry->msg_length) & 0xfff) - 4; if (pkt_len < 60) { printf("%s: Rx%d: invalid packet length %d\n", - dev->name, lp->cur_rx, pkt_len); + lp->name, lp->cur_rx, pkt_len); } else { buf = lp->rx_buf[lp->cur_rx]; invalidate_dcache_range((unsigned long)buf, @@ -424,7 +426,7 @@ static void pcnet_halt(struct eth_device *dev) struct pcnet_priv *lp = dev->priv; int i; - PCNET_DEBUG1("%s: pcnet_halt...\n", dev->name); + PCNET_DEBUG1("%s: %s...\n", lp->name, __func__); /* Reset the PCnet controller */ pcnet_reset(lp); @@ -436,7 +438,7 @@ static void pcnet_halt(struct eth_device *dev) udelay(10); } if (i <= 0) - printf("%s: TIMEOUT: controller reset failed\n", dev->name); + printf("%s: TIMEOUT: controller reset failed\n", lp->name); } int pcnet_initialize(bd_t *bis) @@ -448,7 +450,7 @@ int pcnet_initialize(bd_t *bis) int dev_nr = 0; u32 bar; - PCNET_DEBUG1("\npcnet_initialize...\n"); + PCNET_DEBUG1("\n%s...\n", __func__); for (dev_nr = 0; ; dev_nr++) { /* @@ -480,6 +482,8 @@ int pcnet_initialize(bd_t *bis) (unsigned long)lp + sizeof(*lp)); dev->priv = lp; sprintf(dev->name, "pcnet#%d", dev_nr); + lp->name = dev->name; + lp->enetaddr = dev->enetaddr; /* * Setup the PCI device. @@ -488,14 +492,14 @@ int pcnet_initialize(bd_t *bis) lp->iobase = (void *)(pci_mem_to_phys(devbusfn, bar) & ~0xf); PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%p: ", - dev->name, devbusfn, lp->iobase); + lp->name, devbusfn, lp->iobase); command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; pci_write_config_word(devbusfn, PCI_COMMAND, command); pci_read_config_word(devbusfn, PCI_COMMAND, &status); if ((status & command) != command) { printf("%s: Couldn't enable IO access or Bus Mastering\n", - dev->name); + lp->name); free(dev); continue; } From patchwork Sun May 17 16:24:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 245927 List-Id: U-Boot discussion From: marek.vasut at gmail.com (Marek Vasut) Date: Sun, 17 May 2020 18:24:23 +0200 Subject: [PATCH 13/15] net: pcnet: Split common and non-DM functions In-Reply-To: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> References: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> Message-ID: <20200517162425.76584-13-marek.vasut+renesas@gmail.com> Pull the common parts of functions out so they can be reused by both DM and non-DM code paths. The recv() function had to be reworked to fit into this scheme and this means it now only receives one packet at a time instead of spinning in an endless loop. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 149 ++++++++++++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 55 deletions(-) diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 8e99e41863..8292b0bacb 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -83,6 +83,7 @@ struct pcnet_priv { void __iomem *iobase; char *name; u8 *enetaddr; + u16 status; int cur_rx; int cur_tx; }; @@ -140,9 +141,8 @@ static struct pci_device_id supported[] = { {} }; -static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) +static int pcnet_probe_common(struct pcnet_priv *lp) { - struct pcnet_priv *lp = dev->priv; int chip_version; char *chipname; int i; @@ -196,9 +196,8 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) return 0; } -static int pcnet_init(struct eth_device *dev, bd_t *bis) +static int pcnet_init_common(struct pcnet_priv *lp) { - struct pcnet_priv *lp = dev->priv; struct pcnet_uncached_priv *uc; int i, val; unsigned long addr; @@ -316,9 +315,8 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) return 0; } -static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) +static int pcnet_send_common(struct pcnet_priv *lp, void *packet, int pkt_len) { - struct pcnet_priv *lp = dev->priv; int i, status; u32 addr; struct pcnet_tx_head *entry = &lp->uc->tx_ring[lp->cur_tx]; @@ -365,65 +363,70 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) return pkt_len; } -static int pcnet_recv (struct eth_device *dev) +static int pcnet_recv_common(struct pcnet_priv *lp, unsigned char **bufp) { - struct pcnet_priv *lp = dev->priv; struct pcnet_rx_head *entry; unsigned char *buf; int pkt_len = 0; - u16 status, err_status; + u16 err_status; - while (1) { - entry = &lp->uc->rx_ring[lp->cur_rx]; - /* - * If we own the next entry, it's a new packet. Send it up. - */ - status = readw(&entry->status); - if ((status & 0x8000) != 0) - break; - err_status = status >> 8; - - if (err_status != 0x03) { /* There was an error. */ - printf("%s: Rx%d", lp->name, lp->cur_rx); - PCNET_DEBUG1(" (status=0x%x)", err_status); - if (err_status & 0x20) - printf(" Frame"); - if (err_status & 0x10) - printf(" Overflow"); - if (err_status & 0x08) - printf(" CRC"); - if (err_status & 0x04) - printf(" Fifo"); - printf(" Error\n"); - status &= 0x03ff; - - } else { - pkt_len = (readl(&entry->msg_length) & 0xfff) - 4; - if (pkt_len < 60) { - printf("%s: Rx%d: invalid packet length %d\n", - lp->name, lp->cur_rx, pkt_len); - } else { - buf = lp->rx_buf[lp->cur_rx]; - invalidate_dcache_range((unsigned long)buf, - (unsigned long)buf + pkt_len); - net_process_received_packet(buf, pkt_len); - PCNET_DEBUG2("Rx%d: %d bytes from 0x%p\n", - lp->cur_rx, pkt_len, buf); - } - } - - status |= 0x8000; - writew(status, &entry->status); + entry = &lp->uc->rx_ring[lp->cur_rx]; + /* + * If we own the next entry, it's a new packet. Send it up. + */ + lp->status = readw(&entry->status); + if ((lp->status & 0x8000) != 0) + return 0; + err_status = lp->status >> 8; + + if (err_status != 0x03) { /* There was an error. */ + printf("%s: Rx%d", lp->name, lp->cur_rx); + PCNET_DEBUG1(" (status=0x%x)", err_status); + if (err_status & 0x20) + printf(" Frame"); + if (err_status & 0x10) + printf(" Overflow"); + if (err_status & 0x08) + printf(" CRC"); + if (err_status & 0x04) + printf(" Fifo"); + printf(" Error\n"); + lp->status &= 0x03ff; + return 0; + } - if (++lp->cur_rx >= RX_RING_SIZE) - lp->cur_rx = 0; + pkt_len = (readl(&entry->msg_length) & 0xfff) - 4; + if (pkt_len < 60) { + printf("%s: Rx%d: invalid packet length %d\n", + lp->name, lp->cur_rx, pkt_len); + return 0; } + + *bufp = lp->rx_buf[lp->cur_rx]; + invalidate_dcache_range((unsigned long)*bufp, + (unsigned long)*bufp + pkt_len); + + PCNET_DEBUG2("Rx%d: %d bytes from 0x%p\n", + lp->cur_rx, pkt_len, buf); + return pkt_len; } -static void pcnet_halt(struct eth_device *dev) +static void pcnet_free_pkt_common(struct pcnet_priv *lp, unsigned int len) +{ + struct pcnet_rx_head *entry; + + entry = &lp->uc->rx_ring[lp->cur_rx]; + + lp->status |= 0x8000; + writew(lp->status, &entry->status); + + if (++lp->cur_rx >= RX_RING_SIZE) + lp->cur_rx = 0; +} + +static void pcnet_halt_common(struct pcnet_priv *lp) { - struct pcnet_priv *lp = dev->priv; int i; PCNET_DEBUG1("%s: %s...\n", lp->name, __func__); @@ -441,6 +444,42 @@ static void pcnet_halt(struct eth_device *dev) printf("%s: TIMEOUT: controller reset failed\n", lp->name); } +static int pcnet_init(struct eth_device *dev, bd_t *bis) +{ + struct pcnet_priv *lp = dev->priv; + + return pcnet_init_common(lp); +} + +static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) +{ + struct pcnet_priv *lp = dev->priv; + + return pcnet_send_common(lp, packet, pkt_len); +} + +static int pcnet_recv(struct eth_device *dev) +{ + struct pcnet_priv *lp = dev->priv; + uchar *packet; + int ret; + + ret = pcnet_recv_common(lp, &packet); + if (ret > 0) + net_process_received_packet(packet, ret); + if (ret) + pcnet_free_pkt_common(lp, ret); + + return ret; +} + +static void pcnet_halt(struct eth_device *dev) +{ + struct pcnet_priv *lp = dev->priv; + + pcnet_halt_common(lp); +} + int pcnet_initialize(bd_t *bis) { pci_dev_t devbusfn; @@ -509,7 +548,7 @@ int pcnet_initialize(bd_t *bis) /* * Probe the PCnet chip. */ - if (pcnet_probe(dev, bis, dev_nr) < 0) { + if (pcnet_probe_common(lp) < 0) { free(dev); continue; } From patchwork Sun May 17 16:24:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 245928 List-Id: U-Boot discussion From: marek.vasut at gmail.com (Marek Vasut) Date: Sun, 17 May 2020 18:24:24 +0200 Subject: [PATCH 14/15] net: pcnet: Add DM support In-Reply-To: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> References: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> Message-ID: <20200517162425.76584-14-marek.vasut+renesas@gmail.com> With all the changes in place, add support for DM into the pcnet driver. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 127 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 8292b0bacb..0222f91a5d 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -79,9 +80,14 @@ struct pcnet_priv { /* Receive Buffer space */ unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; struct pcnet_uncached_priv *uc; +#ifdef CONFIG_DM_ETH + struct udevice *dev; + const char *name; +#else pci_dev_t dev; - void __iomem *iobase; char *name; +#endif + void __iomem *iobase; u8 *enetaddr; u16 status; int cur_rx; @@ -133,7 +139,11 @@ static inline pci_addr_t pcnet_virt_to_mem(struct pcnet_priv *lp, void *addr) { void *virt_addr = addr; +#ifdef CONFIG_DM_ETH + return dm_pci_virt_to_mem(lp->dev, virt_addr); +#else return pci_virt_to_mem(lp->dev, virt_addr); +#endif } static struct pci_device_id supported[] = { @@ -444,6 +454,7 @@ static void pcnet_halt_common(struct pcnet_priv *lp) printf("%s: TIMEOUT: controller reset failed\n", lp->name); } +#ifndef CONFIG_DM_ETH static int pcnet_init(struct eth_device *dev, bd_t *bis) { struct pcnet_priv *lp = dev->priv; @@ -568,3 +579,117 @@ int pcnet_initialize(bd_t *bis) return dev_nr; } +#else /* DM_ETH */ +static int pcnet_start(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct pcnet_priv *priv = dev_get_priv(dev); + + memcpy(priv->enetaddr, plat->enetaddr, sizeof(plat->enetaddr)); + + return pcnet_init_common(priv); +} + +static void pcnet_stop(struct udevice *dev) +{ + struct pcnet_priv *priv = dev_get_priv(dev); + + pcnet_halt_common(priv); +} + +static int pcnet_send(struct udevice *dev, void *packet, int length) +{ + struct pcnet_priv *priv = dev_get_priv(dev); + int ret; + + ret = pcnet_send_common(priv, packet, length); + + return ret ? 0 : -ETIMEDOUT; +} + +static int pcnet_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct pcnet_priv *priv = dev_get_priv(dev); + + return pcnet_recv_common(priv, packetp); +} + +static int pcnet_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct pcnet_priv *priv = dev_get_priv(dev); + + pcnet_free_pkt_common(priv, length); + + return 0; +} + +static int pcnet_bind(struct udevice *dev) +{ + static int card_number; + char name[16]; + + sprintf(name, "pcnet#%u", card_number++); + + return device_set_name(dev, name); +} + +static int pcnet_probe(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct pcnet_priv *lp = dev_get_priv(dev); + u16 command, status; + u32 iobase; + int ret; + + dm_pci_read_config32(dev, PCI_BASE_ADDRESS_1, &iobase); + iobase &= ~0xf; + + lp->uc = map_physmem((phys_addr_t)&lp->ucp, + sizeof(lp->ucp), MAP_NOCACHE); + lp->dev = dev; + lp->name = dev->name; + lp->enetaddr = plat->enetaddr; + lp->iobase = (void *)dm_pci_mem_to_phys(dev, iobase); + + flush_dcache_range((unsigned long)lp, + (unsigned long)lp + sizeof(*lp)); + + command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + dm_pci_write_config16(dev, PCI_COMMAND, command); + dm_pci_read_config16(dev, PCI_COMMAND, &status); + if ((status & command) != command) { + printf("%s: Couldn't enable IO access or Bus Mastering\n", + lp->name); + return -EINVAL; + } + + dm_pci_write_config8(dev, PCI_LATENCY_TIMER, 0x20); + + ret = pcnet_probe_common(lp); + if (ret) + return ret; + + return 0; +} + +static const struct eth_ops pcnet_ops = { + .start = pcnet_start, + .send = pcnet_send, + .recv = pcnet_recv, + .stop = pcnet_stop, + .free_pkt = pcnet_free_pkt, +}; + +U_BOOT_DRIVER(eth_pcnet) = { + .name = "eth_pcnet", + .id = UCLASS_ETH, + .bind = pcnet_bind, + .probe = pcnet_probe, + .ops = &pcnet_ops, + .priv_auto_alloc_size = sizeof(struct pcnet_priv), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), + .flags = DM_UC_FLAG_ALLOC_PRIV_DMA, +}; + +U_BOOT_PCI_DEVICE(eth_pcnet, supported); +#endif From patchwork Sun May 17 16:24:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 245929 List-Id: U-Boot discussion From: marek.vasut at gmail.com (Marek Vasut) Date: Sun, 17 May 2020 18:24:25 +0200 Subject: [PATCH 15/15] net: pcnet: Add Kconfig entries In-Reply-To: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> References: <20200517162425.76584-1-marek.vasut+renesas@gmail.com> Message-ID: <20200517162425.76584-15-marek.vasut+renesas@gmail.com> Add Kconfig entries for the pcnet driver and convert MIPS malta to use those. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- configs/malta_defconfig | 1 + drivers/net/Kconfig | 6 ++++++ include/configs/malta.h | 1 - 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/configs/malta_defconfig b/configs/malta_defconfig index 2b43818c81..0680f595db 100644 --- a/configs/malta_defconfig +++ b/configs/malta_defconfig @@ -26,6 +26,7 @@ CONFIG_MTD_NOR_FLASH=y CONFIG_FLASH_CFI_DRIVER=y CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y CONFIG_SYS_FLASH_CFI=y +CONFIG_PCNET=y CONFIG_PCI=y CONFIG_RTC_MC146818=y CONFIG_SYS_NS16550=y diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f7855c92d3..cef3b5c0de 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -377,6 +377,12 @@ config MII help Enable support of the Media-Independent Interface (MII) +config PCNET + bool "AMD PCnet series Ethernet controller driver" + help + This driver supports AMD PCnet series fast ethernet family of + PCI chipsets/adapters. + config RTL8139 bool "Realtek 8139 series Ethernet controller driver" help diff --git a/include/configs/malta.h b/include/configs/malta.h index 82c90042d9..9602773ff9 100644 --- a/include/configs/malta.h +++ b/include/configs/malta.h @@ -15,7 +15,6 @@ #define CONFIG_PCI_GT64120 #define CONFIG_PCI_MSC01 -#define CONFIG_PCNET #define CONFIG_SYS_ISA_IO_BASE_ADDRESS 0