From b9c52c50905cfd5973418e925e72c3bbefc7eb34 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:11 +0200 Subject: net: pcnet: Drop typedef struct pcnet_priv_t 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(-) (limited to 'drivers/net/pcnet.c') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 260a5a38cff..c6f080d956b 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -76,15 +76,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 @@ -340,9 +340,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)); -- cgit v1.2.3 From b92b8f48fb47c48b3f9df91ea1009b5789d55e19 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:12 +0200 Subject: net: pcnet: Drop PCNET_HAS_PROM 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 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/net/pcnet.c') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index c6f080d956b..edc4dba24cb 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -241,10 +241,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); @@ -279,7 +276,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 @@ -293,7 +289,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; } -- cgit v1.2.3 From d3b1df0f396adb2b5c25ff655c3dae8624c41e50 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:13 +0200 Subject: net: pcnet: Use PCI_DEVICE() to define PCI device compat list 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(-) (limited to 'drivers/net/pcnet.c') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index edc4dba24cb..e7ce79e952d 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -155,7 +155,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) }, {} }; -- cgit v1.2.3 From 89369b0ac2ca0621bfc30baed739bb9d9e7fdcad Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:14 +0200 Subject: net: pcnet: Simplify private data allocation 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(-) (limited to 'drivers/net/pcnet.c') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index e7ce79e952d..72b93806244 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -74,12 +75,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; }; @@ -335,22 +337,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; @@ -364,7 +355,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); @@ -521,7 +512,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); -- cgit v1.2.3 From 0e11d79a533e3c874be1c5975abbc52aaba94d93 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:15 +0200 Subject: net: pcnet: Replace memset+malloc with calloc 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(-) (limited to 'drivers/net/pcnet.c') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 72b93806244..b670cff2aae 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -184,12 +184,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); -- cgit v1.2.3 From ada6a2cea5a0d44c3bd64713babd9d73eaf64863 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:16 +0200 Subject: net: pcnet: Move private data allocation to initialize 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(-) (limited to 'drivers/net/pcnet.c') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index b670cff2aae..073ffca6b62 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -189,6 +189,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); @@ -330,19 +344,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); -- cgit v1.2.3 From 54c6067486e576eea70020d743a0a19d5ad1e603 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:17 +0200 Subject: net: pcnet: Move initialize function at the end 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(-) (limited to 'drivers/net/pcnet.c') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 073ffca6b62..6d464cd0a4e 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -161,97 +161,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; @@ -548,3 +457,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; +} -- cgit v1.2.3 From 553286a63ca5e60beb4cf5af68795c7d78a19ceb Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:18 +0200 Subject: net: pcnet: Drop useless forward declarations 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(-) (limited to 'drivers/net/pcnet.c') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 6d464cd0a4e..d8249f0a1cf 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -141,12 +141,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) { -- cgit v1.2.3 From ab6ecbdc3c25761756538129c26d1396dd5b02a9 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:19 +0200 Subject: net: pcnet: Wrap devbusfn into private data 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(-) (limited to 'drivers/net/pcnet.c') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index d8249f0a1cf..f7f1b8fc21f 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -82,6 +82,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; }; @@ -141,13 +142,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[] = { @@ -258,7 +257,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); @@ -290,9 +289,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", @@ -303,7 +302,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); @@ -361,7 +360,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); @@ -492,7 +491,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); /* -- cgit v1.2.3 From 834d5cebe582eb71a2c76fc5c9078a3a85b1cafe Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:20 +0200 Subject: net: pcnet: Pass private data through dev->priv 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(-) (limited to 'drivers/net/pcnet.c') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index f7f1b8fc21f..dab08c07add 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -87,8 +87,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 @@ -212,6 +210,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; @@ -331,6 +330,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]; @@ -379,6 +379,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; @@ -455,6 +456,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; @@ -483,15 +485,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); /* -- cgit v1.2.3 From deca77382114364ca476482ad3e8bd431578fea8 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:21 +0200 Subject: net: pcnet: Wrap iobase into private data 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(-) (limited to 'drivers/net/pcnet.c') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index dab08c07add..b0bd4af2039 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -83,6 +83,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; }; @@ -93,51 +94,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) @@ -154,22 +143,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; @@ -199,7 +188,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; @@ -218,17 +207,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 @@ -238,12 +227,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; @@ -302,28 +291,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; } @@ -367,7 +356,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) @@ -435,16 +424,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); } @@ -498,11 +488,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); -- cgit v1.2.3 From 6d76c9f1e6df5338aeaa8699e16ea3bb755f858d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:22 +0200 Subject: net: pcnet: Wrap name and enetaddr into private data 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(-) (limited to 'drivers/net/pcnet.c') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index b0bd4af2039..669b2561789 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -84,6 +84,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; }; @@ -153,7 +155,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; } @@ -174,7 +176,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; } @@ -190,8 +192,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; @@ -204,7 +206,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); @@ -271,7 +273,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]); } @@ -304,7 +306,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; } @@ -340,7 +342,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; } @@ -385,7 +387,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"); @@ -402,7 +404,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, @@ -427,7 +429,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); @@ -439,7 +441,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) @@ -451,7 +453,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++) { /* @@ -483,6 +485,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. @@ -491,14 +495,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; } -- cgit v1.2.3 From f5e7df58e0b96f97e1d8ef49415401a51e9f18b8 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:23 +0200 Subject: net: pcnet: Split common and non-DM functions 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(-) (limited to 'drivers/net/pcnet.c') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 669b2561789..0a4cab82087 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -86,6 +86,7 @@ struct pcnet_priv { void __iomem *iobase; char *name; u8 *enetaddr; + u16 status; int cur_rx; int cur_tx; }; @@ -143,9 +144,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; @@ -199,9 +199,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; @@ -319,9 +318,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]; @@ -368,65 +366,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__); @@ -444,6 +447,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; @@ -512,7 +551,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; } -- cgit v1.2.3 From 53019cf35b5ccf9cb5ad8269acab494b99a3dc0c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 May 2020 18:24:24 +0200 Subject: net: pcnet: Add DM support 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(-) (limited to 'drivers/net/pcnet.c') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 0a4cab82087..8e3e3dbbcee 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -82,9 +83,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; @@ -136,7 +142,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[] = { @@ -447,6 +457,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; @@ -571,3 +582,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 -- cgit v1.2.3