diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 057abd2bc..7a0d5e107 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -80,6 +80,7 @@ config DRIVER_NET_EP93XX config DRIVER_NET_ETHOC bool "OpenCores ethernet MAC driver" + select PHYLIB help This option enables support for the OpenCores 10/100 Mbps Ethernet MAC core. diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c index 6978e2a2e..4bbf59558 100644 --- a/drivers/net/altera_tse.c +++ b/drivers/net/altera_tse.c @@ -402,7 +402,7 @@ static int tse_eth_rx(struct eth_device *edev) ALT_SGDMA_DESCRIPTOR_STATUS_TERMINATED_BY_EOP_MSK) { packet_length = rx_desc->actual_bytes_transferred; - net_receive(NetRxPackets[0], packet_length); + net_receive(edev, NetRxPackets[0], packet_length); /* Clear Run */ rx_sgdma->control = (rx_sgdma->control & (~ALT_SGDMA_CONTROL_RUN_MSK)); diff --git a/drivers/net/ar231x.c b/drivers/net/ar231x.c index 515de17b1..572008a83 100644 --- a/drivers/net/ar231x.c +++ b/drivers/net/ar231x.c @@ -217,7 +217,7 @@ static int ar231x_eth_recv(struct eth_device *edev) u16 length = ((status >> DMA_RX_LEN_SHIFT) & 0x3fff) - CRC_LEN; - net_receive((void *)rxdsc->buffer_ptr, length); + net_receive(edev, (void *)rxdsc->buffer_ptr, length); } /* Clean descriptor. now it is owned by DMA. */ priv->next_rxdsc = (struct ar231x_descr *)rxdsc->next_dsc_ptr; diff --git a/drivers/net/arc_emac.c b/drivers/net/arc_emac.c index 1f1e88919..8b74ea570 100644 --- a/drivers/net/arc_emac.c +++ b/drivers/net/arc_emac.c @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -209,9 +210,6 @@ static int arc_emac_open(struct eth_device *edev) arc_reg_set(priv, R_RX_RING, (unsigned int)priv->rxbd); arc_reg_set(priv, R_TX_RING, (unsigned int)priv->txbd); - /* Enable interrupts */ - arc_reg_set(priv, R_ENABLE, RXINT_MASK | ERR_MASK); - /* Set CONTROL */ arc_reg_set(priv, R_CTRL, (RX_BD_NUM << 24) | /* RX BD table length */ @@ -304,7 +302,7 @@ static int arc_emac_recv(struct eth_device *edev) dma_inv_range((unsigned long)rxbd->data, (unsigned long)rxbd->data + pktlen); - net_receive((unsigned char *)rxbd->data, pktlen); + net_receive(edev, (unsigned char *)rxbd->data, pktlen); rxbd->info = cpu_to_le32(FOR_EMAC | PKTSIZE); } @@ -316,9 +314,6 @@ static void arc_emac_halt(struct eth_device *edev) { struct arc_emac_priv *priv = edev->priv; - /* Disable interrupts */ - arc_reg_clr(priv, R_ENABLE, RXINT_MASK | ERR_MASK); - /* Disable EMAC */ arc_reg_clr(priv, R_CTRL, EN_MASK); } @@ -342,26 +337,18 @@ static int arc_emac_set_ethaddr(struct eth_device *edev, unsigned char *mac) return 0; } -/* Number of seconds we wait for "MDIO complete" flag to appear */ -#define ARC_MDIO_COMPLETE_POLL_COUNT 1 - static int arc_mdio_complete_wait(struct arc_emac_priv *priv) { - unsigned int i; + uint64_t start = get_time_ns(); - for (i = 0; i < ARC_MDIO_COMPLETE_POLL_COUNT * 40; i++) { - unsigned int status = arc_reg_get(priv, R_STATUS); - - status &= MDIO_MASK; - - if (status) { + while (!is_timeout(start, 1000 * MSECOND)) { + if (arc_reg_get(priv, R_STATUS) & MDIO_MASK) { /* Reset "MDIO complete" flag */ - arc_reg_set(priv, R_STATUS, status); + arc_reg_set(priv, R_STATUS, MDIO_MASK); return 0; } - - mdelay(25); } + return -ETIMEDOUT; } @@ -447,6 +434,9 @@ static int arc_emac_probe(struct device_d *dev) /* Set poll rate so that it polls every 1 ms */ arc_reg_set(priv, R_POLLRATE, clock_frequency / 1000000); + /* Disable interrupts */ + arc_reg_set(priv, R_ENABLE, 0); + mdiobus_register(miibus); eth_register(edev); diff --git a/drivers/net/at91_ether.c b/drivers/net/at91_ether.c index bf2f957a3..e09ea83f6 100644 --- a/drivers/net/at91_ether.c +++ b/drivers/net/at91_ether.c @@ -224,7 +224,7 @@ static int at91_ether_rx(struct eth_device *edev) size = rbfp->size & RBF_SIZE; - net_receive((unsigned char *)(rbfp->addr & RBF_ADDR), size); + net_receive(edev, (unsigned char *)(rbfp->addr & RBF_ADDR), size); rbfp->addr &= ~RBF_OWNER; if (rbfp->addr & RBF_WRAP) diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c index ec3263d4a..ccae5376c 100644 --- a/drivers/net/cpsw.c +++ b/drivers/net/cpsw.c @@ -178,11 +178,11 @@ struct cpsw_slave { struct cpsw_slave_regs *regs; struct cpsw_sliver_regs *sliver; int slave_num; - u32 mac_control; int phy_id; phy_interface_t phy_if; struct eth_device edev; struct cpsw_priv *cpsw; + struct device_d dev; }; struct cpdma_desc { @@ -540,9 +540,8 @@ static inline void soft_reset(struct cpsw_priv *priv, void *reg) static int cpsw_get_hwaddr(struct eth_device *edev, unsigned char *mac) { struct cpsw_slave *slave = edev->priv; - struct cpsw_priv *priv = slave->cpsw; - dev_dbg(priv->dev, "* %s\n", __func__); + dev_dbg(&slave->dev, "* %s\n", __func__); return -1; } @@ -552,7 +551,7 @@ static int cpsw_set_hwaddr(struct eth_device *edev, unsigned char *mac) struct cpsw_slave *slave = edev->priv; struct cpsw_priv *priv = slave->cpsw; - dev_dbg(priv->dev, "* %s\n", __func__); + dev_dbg(&slave->dev, "* %s\n", __func__); memcpy(&priv->mac_addr, mac, sizeof(priv->mac_addr)); @@ -568,14 +567,11 @@ static void cpsw_slave_update_link(struct cpsw_slave *slave, struct phy_device *phydev = slave->edev.phydev; u32 mac_control = 0; - dev_dbg(priv->dev, "* %s\n", __func__); + dev_dbg(&slave->dev, "* %s\n", __func__); if (!phydev) return; - if (slave->slave_num) - return; - if (phydev->link) { *link = 1; mac_control = BIT(5); /* MIIEN */ @@ -590,26 +586,22 @@ static void cpsw_slave_update_link(struct cpsw_slave *slave, mac_control |= BIT(0); /* FULLDUPLEXEN */ } - if (mac_control == slave->mac_control) - return; - if (mac_control) { - dev_dbg(priv->dev, "link up on port %d, speed %d, %s duplex\n", - slave->slave_num, phydev->speed, + dev_dbg(&slave->dev, "link up, speed %d, %s duplex\n", + phydev->speed, (phydev->duplex == DUPLEX_FULL) ? "full" : "half"); } else { - dev_dbg(priv->dev, "link down on port %d\n", slave->slave_num); + dev_dbg(&slave->dev, "link down\n"); } writel(mac_control, &slave->sliver->mac_control); - slave->mac_control = mac_control; } static int cpsw_update_link(struct cpsw_slave *slave, struct cpsw_priv *priv) { int link = 0; - dev_dbg(priv->dev, "* %s\n", __func__); + dev_dbg(&slave->dev, "* %s\n", __func__); cpsw_slave_update_link(slave, priv, &link); @@ -621,7 +613,7 @@ static void cpsw_adjust_link(struct eth_device *edev) struct cpsw_slave *slave = edev->priv; struct cpsw_priv *priv = slave->cpsw; - dev_dbg(priv->dev, "* %s\n", __func__); + dev_dbg(&slave->dev, "* %s\n", __func__); cpsw_update_link(slave, priv); } @@ -638,7 +630,7 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv) { u32 slave_port; - dev_dbg(priv->dev, "* %s\n", __func__); + dev_dbg(&slave->dev, "* %s\n", __func__); soft_reset(priv, &slave->sliver->soft_reset); @@ -649,8 +641,6 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv) /* setup max packet size, and mac address */ writel(PKT_MAX, &slave->sliver->rx_maxlen); - slave->mac_control = 0; /* no link yet */ - /* enable forwarding */ slave_port = cpsw_get_slave_port(priv, slave->slave_num); cpsw_ale_port_state(priv, slave_port, ALE_PORT_STATE_FORWARD); @@ -769,7 +759,7 @@ static int cpsw_open(struct eth_device *edev) struct cpsw_priv *priv = slave->cpsw; int i, ret; - dev_dbg(priv->dev, "* %s\n", __func__); + dev_dbg(&slave->dev, "* %s\n", __func__); ret = phy_device_connect(edev, &priv->miibus, slave->phy_id, cpsw_adjust_link, 0, slave->phy_if); @@ -801,8 +791,8 @@ static int cpsw_open(struct eth_device *edev) ALE_SECURE); cpsw_ale_add_mcast(priv, ethbdaddr, 1 << priv->host_port); - cpsw_slave_init(&priv->slaves[0], priv); - cpsw_update_link(&priv->slaves[0], priv); + cpsw_slave_init(slave, priv); + cpsw_update_link(slave, priv); /* init descriptor pool */ for (i = 0; i < NUM_DESCS; i++) { @@ -842,7 +832,7 @@ static int cpsw_open(struct eth_device *edev) ret = cpdma_submit(priv, &priv->rx_chan, NetRxPackets[i], PKTSIZE); if (ret < 0) { - dev_err(priv->dev, "error %d submitting rx desc\n", ret); + dev_err(&slave->dev, "error %d submitting rx desc\n", ret); break; } } @@ -855,6 +845,8 @@ static void cpsw_halt(struct eth_device *edev) struct cpsw_slave *slave = edev->priv; struct cpsw_priv *priv = slave->cpsw; + dev_dbg(priv->dev, "* %s slave %d\n", __func__, slave->slave_num); + writel(0, priv->dma_regs + CPDMA_TXCONTROL); writel(0, priv->dma_regs + CPDMA_RXCONTROL); @@ -872,12 +864,12 @@ static int cpsw_send(struct eth_device *edev, void *packet, int length) void *buffer; int ret, len; - dev_dbg(priv->dev, "* %s\n", __func__); + dev_dbg(&slave->dev, "* %s slave %d\n", __func__, slave->slave_num); /* first reap completed packets */ while (cpdma_process(priv, &priv->tx_chan, &buffer, &len) >= 0); - dev_dbg(priv->dev, "%s: %i bytes @ 0x%p\n", __func__, length, packet); + dev_dbg(&slave->dev, "%s: %i bytes @ 0x%p\n", __func__, length, packet); dma_flush_range((ulong) packet, (ulong)packet + length); @@ -895,7 +887,7 @@ static int cpsw_recv(struct eth_device *edev) while (cpdma_process(priv, &priv->rx_chan, &buffer, &len) >= 0) { dma_inv_range((ulong)buffer, (ulong)buffer + len); - net_receive(buffer, len); + net_receive(edev, buffer, len); cpdma_submit(priv, &priv->rx_chan, buffer, PKTSIZE); } @@ -916,8 +908,17 @@ static int cpsw_slave_setup(struct cpsw_slave *slave, int slave_num, { void *regs = priv->regs; struct eth_device *edev = &slave->edev; + struct device_d *dev = &slave->dev; + int ret; - dev_dbg(priv->dev, "* %s\n", __func__); + sprintf(dev->name, "cpsw-slave"); + dev->id = slave->slave_num; + dev->parent = priv->dev; + ret = register_device(dev); + if (ret) + return ret; + + dev_dbg(&slave->dev, "* %s\n", __func__); slave->slave_num = slave_num; slave->regs = regs + priv->slave_ofs + priv->slave_size * slave_num; @@ -932,7 +933,7 @@ static int cpsw_slave_setup(struct cpsw_slave *slave, int slave_num, edev->recv = cpsw_recv; edev->get_ethaddr = cpsw_get_hwaddr; edev->set_ethaddr = cpsw_set_hwaddr; - edev->parent = priv->dev; + edev->parent = dev; return eth_register(edev); } @@ -1077,6 +1078,7 @@ static int cpsw_probe_dt(struct cpsw_priv *priv) if (ret) return ret; + slave->dev.device_node = child; slave->phy_id = phy_id[1]; slave->phy_if = of_get_phy_mode(child); slave->slave_num = i; @@ -1091,9 +1093,6 @@ static int cpsw_probe_dt(struct cpsw_priv *priv) cpsw_gmii_sel_am335x(slave); } - /* Only one slave supported by this driver */ - priv->num_slaves = 1; - return 0; } @@ -1105,7 +1104,7 @@ int cpsw_probe(struct device_d *dev) uint64_t start; uint32_t phy_mask; struct cpsw_data *cpsw_data; - int ret; + int i, ret; dev_dbg(dev, "* %s\n", __func__); @@ -1197,9 +1196,11 @@ int cpsw_probe(struct device_d *dev) mdiobus_register(&priv->miibus); - ret = cpsw_slave_setup(&priv->slaves[0], 0, priv); - if (ret) - goto out; + for (i = 0; i < priv->num_slaves; i++) { + ret = cpsw_slave_setup(&priv->slaves[i], i, priv); + if (ret) + goto out; + } return 0; out: diff --git a/drivers/net/cs8900.c b/drivers/net/cs8900.c index aa9d9a079..dccb808f9 100644 --- a/drivers/net/cs8900.c +++ b/drivers/net/cs8900.c @@ -309,7 +309,7 @@ static int cs8900_recv(struct eth_device *dev) if (len & 1) { *addr++ = readw(priv->regs + CS8900_RTDATA0); } - net_receive(NetRxPackets[0], len); + net_receive(dev, NetRxPackets[0], len); return len; } diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 7848f50b9..ce367a365 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -462,7 +462,7 @@ static int davinci_emac_recv(struct eth_device *edev) dev_dbg(priv->dev, "| emac_recv got packet (length %i)\n", len); dma_inv_range((ulong)pkt, (ulong)readl(rx_curr_desc + EMAC_DESC_BUFFER) + len); - net_receive(pkt, len); + net_receive(edev, pkt, len); ret = len; } diff --git a/drivers/net/designware.c b/drivers/net/designware.c index e706f54b3..ac2eca5ae 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -356,7 +356,7 @@ static int dwc_ether_rx(struct eth_device *dev) dma_inv_range((unsigned long)desc_p->dmamac_addr, (unsigned long)desc_p->dmamac_addr + length); - net_receive(desc_p->dmamac_addr, length); + net_receive(dev, desc_p->dmamac_addr, length); desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA; diff --git a/drivers/net/dm9k.c b/drivers/net/dm9k.c index 7c706e515..3a4c6aacd 100644 --- a/drivers/net/dm9k.c +++ b/drivers/net/dm9k.c @@ -634,7 +634,7 @@ static int dm9k_eth_rx(struct eth_device *edev) dev_dbg(dev, "Receiving packet\n"); dm9k_rd(priv->buswidth, priv->iodata, priv->pckt, rx_len); dev_dbg(dev, "passing %u bytes packet to upper layer\n", rx_len); - net_receive(priv->pckt, rx_len); + net_receive(edev, priv->pckt, rx_len); return 0; } else { dev_dbg(dev, "Discarding packet\n"); diff --git a/drivers/net/ep93xx.c b/drivers/net/ep93xx.c index 1ecef1339..4b73abff3 100644 --- a/drivers/net/ep93xx.c +++ b/drivers/net/ep93xx.c @@ -344,7 +344,7 @@ static int ep93xx_eth_rcv_packet(struct eth_device *edev) * used when we pass the data off to the protocol * layer via net_receive(). */ - net_receive((uchar *)priv->rx_dq.current->word1, + net_receive(edev, (uchar *)priv->rx_dq.current->word1, RX_STATUS_FRAME_LEN(priv->rx_sq.current)); pr_debug("reporting %d bytes...\n", RX_STATUS_FRAME_LEN(priv->rx_sq.current)); diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index b00087578..679e1e552 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -178,6 +178,8 @@ struct ethoc { u32 num_rx; u32 cur_rx; + + struct mii_bus miibus; }; /** @@ -369,7 +371,7 @@ static int ethoc_rx(struct eth_device *edev, int limit) size -= 4; /* strip the CRC */ invalidate_dcache_range(bd.addr, bd.addr + PKTSIZE); - net_receive((unsigned char *)bd.addr, size); + net_receive(edev, (unsigned char *)bd.addr, size); } /* clear the buffer descriptor so it can be reused */ @@ -481,6 +483,54 @@ static int ethoc_send_packet(struct eth_device *edev, void *packet, int length) return 0; } +static int ethoc_mdio_read(struct mii_bus *bus, int phy, int reg) +{ + struct ethoc *priv = bus->priv; + u64 start; + u32 data; + + ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(phy, reg)); + ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ); + + start = get_time_ns(); + while (ethoc_read(priv, MIISTATUS) & MIISTATUS_BUSY) { + if (is_timeout(start, 2 * MSECOND)) { + dev_err(bus->parent, "PHY command timeout\n"); + return -EBUSY; + } + } + + data = ethoc_read(priv, MIIRX_DATA); + + /* reset MII command register */ + ethoc_write(priv, MIICOMMAND, 0); + + return data; +} + +static int ethoc_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val) +{ + struct ethoc *priv = bus->priv; + u64 start; + + ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(phy, reg)); + ethoc_write(priv, MIITX_DATA, val); + ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE); + + start = get_time_ns(); + while (ethoc_read(priv, MIISTATUS) & MIISTATUS_BUSY) { + if (is_timeout(start, 2 * MSECOND)) { + dev_err(bus->parent, "PHY command timeout\n"); + return -EBUSY; + } + } + + /* reset MII command register */ + ethoc_write(priv, MIICOMMAND, 0); + + return 0; +} + static int ethoc_probe(struct device_d *dev) { struct eth_device *edev; @@ -493,6 +543,11 @@ static int ethoc_probe(struct device_d *dev) priv = edev->priv; priv->iobase = dev_request_mem_region(dev, 0); + priv->miibus.read = ethoc_mdio_read; + priv->miibus.write = ethoc_mdio_write; + priv->miibus.priv = priv; + priv->miibus.parent = dev; + edev->init = ethoc_init_dev; edev->open = ethoc_open; edev->send = ethoc_send_packet; @@ -503,6 +558,8 @@ static int ethoc_probe(struct device_d *dev) edev->set_ethaddr = ethoc_set_ethaddr; edev->parent = dev; + mdiobus_register(&priv->miibus); + eth_register(edev); return 0; diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c index 808bf8f2a..2f0876e5f 100644 --- a/drivers/net/fec_imx.c +++ b/drivers/net/fec_imx.c @@ -581,7 +581,7 @@ static int fec_recv(struct eth_device *dev) */ frame = phys_to_virt(readl(&rbd->data_pointer)); frame_length = readw(&rbd->data_length) - 4; - net_receive(frame->data, frame_length); + net_receive(dev, frame->data, frame_length); len = frame_length; } else { if (bd_status & FEC_RBD_ERR) { diff --git a/drivers/net/fec_mpc5200.c b/drivers/net/fec_mpc5200.c index acad20c23..41a3b58d5 100644 --- a/drivers/net/fec_mpc5200.c +++ b/drivers/net/fec_mpc5200.c @@ -622,7 +622,7 @@ static int mpc5xxx_fec_recv(struct eth_device *dev) */ memcpy(buff, frame->head, 14); memcpy(buff + 14, frame->data, frame_length); - net_receive(buff, frame_length); + net_receive(dev, buff, frame_length); len = frame_length; } /* diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index f944c6c06..3370b5cdb 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -413,7 +413,7 @@ static int gfar_recv(struct eth_device *edev) /* Send the packet up if there were no errors */ if (!(priv->rxbd[priv->rxidx].status & RXBD_STATS)) { - net_receive(NetRxPackets[priv->rxidx], length - 4); + net_receive(edev, NetRxPackets[priv->rxidx], length - 4); } else { dev_err(dev, "Got error %x\n", (priv->rxbd[priv->rxidx].status & RXBD_STATS)); diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c index 9c0e5a7a1..83d1b0280 100644 --- a/drivers/net/ks8851_mll.c +++ b/drivers/net/ks8851_mll.c @@ -693,7 +693,7 @@ static int ks8851_rx_frame(struct ks_net *ks) if (RxStatus & RXFSHR_RXFV) { /* Pass to upper layer */ dev_dbg(dev, "passing packet to upper layer\n\n"); - net_receive(NetRxPackets[0], RxLen); + net_receive(&ks->edev, NetRxPackets[0], RxLen); return RxLen; } else if (RxStatus & RXFSHR_ERR) { dev_err(dev, "RxStatus error 0x%04x\n", RxStatus & RXFSHR_ERR); diff --git a/drivers/net/macb.c b/drivers/net/macb.c index d8523cee3..12a2a3c6c 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -187,7 +187,7 @@ static int gem_recv(struct eth_device *edev) status = macb->rx_ring[macb->rx_tail].ctrl; length = MACB_BFEXT(RX_FRMLEN, status); buffer = macb->rx_buffer + macb->rx_buffer_size * macb->rx_tail; - net_receive(buffer, length); + net_receive(edev, buffer, length); macb->rx_ring[macb->rx_tail].addr &= ~MACB_BIT(RX_USED); barrier(); @@ -237,7 +237,7 @@ static int macb_recv(struct eth_device *edev) buffer = (void *)NetRxPackets[0]; } - net_receive(buffer, length); + net_receive(edev, buffer, length); if (++rx_tail >= macb->rx_ring_size) rx_tail = 0; reclaim_rx_buffers(macb, rx_tail); diff --git a/drivers/net/netx_eth.c b/drivers/net/netx_eth.c index 309f4cb73..96dbc7c5d 100644 --- a/drivers/net/netx_eth.c +++ b/drivers/net/netx_eth.c @@ -110,7 +110,7 @@ static int netx_eth_rx (struct eth_device *edev) /* get data */ memcpy((void*)NetRxPackets[0], (void *)(SRAM_BASE(seg) + frameno * 1560), len); /* pass to barebox */ - net_receive(NetRxPackets[0], len); + net_receive(edev, NetRxPackets[0], len); PFIFO_REG(PFIFO_BASE(EMPTY_PTR_FIFO(xcno))) = FIFO_PTR_SEGMENT(seg) | diff --git a/drivers/net/orion-gbe.c b/drivers/net/orion-gbe.c index 00f5e543c..17497047a 100644 --- a/drivers/net/orion-gbe.c +++ b/drivers/net/orion-gbe.c @@ -303,7 +303,7 @@ static int port_recv(struct eth_device *edev) ALIGN(PKTSIZE, 8)); /* received packet is padded with two null bytes */ - net_receive(rxdesc->buf_ptr + 0x2, rxdesc->byte_cnt - 0x2); + net_receive(edev, rxdesc->buf_ptr + 0x2, rxdesc->byte_cnt - 0x2); ret = 0; recv_err: diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 879939d4a..5975637ff 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -49,7 +49,7 @@ int phy_update_status(struct phy_device *dev) dev->adjust_link(edev); if (dev->link) - pr_info("%dMbps %s duplex link detected\n", dev->speed, + dev_info(&edev->dev, "%dMbps %s duplex link detected\n", dev->speed, dev->duplex ? "full" : "half"); return 0; diff --git a/drivers/net/smc91111.c b/drivers/net/smc91111.c index ba81e2499..7baa7490f 100644 --- a/drivers/net/smc91111.c +++ b/drivers/net/smc91111.c @@ -1169,7 +1169,7 @@ static int smc91c111_eth_rx(struct eth_device *edev) if (!is_error) { /* Pass the packet up to the protocol layers. */ - net_receive(NetRxPackets[0], packet_length); + net_receive(edev, NetRxPackets[0], packet_length); return 0; } diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index e0d78d06e..9977ae3f3 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -478,7 +478,7 @@ static int smc911x_eth_rx(struct eth_device *edev) dev_err(&edev->dev, "dropped bad packet. Status: 0x%08x\n", status); else - net_receive(NetRxPackets[0], pktlen); + net_receive(edev, NetRxPackets[0], pktlen); } return 0; diff --git a/drivers/net/tap.c b/drivers/net/tap.c index 436b0e085..2458fb52c 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -45,7 +45,7 @@ int tap_eth_rx (struct eth_device *edev) length = linux_read_nonblock(priv->fd, NetRxPackets[0], PKTSIZE); if (length > 0) - net_receive(NetRxPackets[0], length); + net_receive(edev, NetRxPackets[0], length); return 0; } diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 2145d3f46..d6ac322b7 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -431,7 +431,7 @@ static int asix_rx_fixup(struct usbnet *dev, void *buf, int len) return 0; } - net_receive(buf, size); + net_receive(&dev->edev, buf, size); buf += ((size + 1) & 0xfffe); len -= ((size + 1) & 0xfffe); diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index eb8f0becc..053da1822 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -793,11 +793,11 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, void *buf, int len) /* last frame in this batch */ if (len == size) { - net_receive(buf, len - 4); + net_receive(&dev->edev, buf, len - 4); return 1; } - net_receive(packet, len - 4); + net_receive(&dev->edev, packet, len - 4); } len -= size; diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 80b4ae7b9..13f58e3ea 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -138,7 +138,7 @@ static int usbnet_recv(struct eth_device *edev) if (info->rx_fixup) return info->rx_fixup(dev, rx_buf, alen); else - net_receive(rx_buf, alen); + net_receive(edev, rx_buf, alen); } return 0; diff --git a/drivers/net/xgmac.c b/drivers/net/xgmac.c index b4bfd0899..cc22d0ea5 100644 --- a/drivers/net/xgmac.c +++ b/drivers/net/xgmac.c @@ -617,7 +617,7 @@ static int xgmac_recv(struct eth_device *edev) length = desc_get_rx_frame_len(rxdesc); - net_receive(desc_get_buf_addr(rxdesc), length); + net_receive(edev, desc_get_buf_addr(rxdesc), length); /* set descriptor back to owned by XGMAC */ desc_set_rx_owner(rxdesc); diff --git a/include/net.h b/include/net.h index 3b800b78f..c0f7517c3 100644 --- a/include/net.h +++ b/include/net.h @@ -68,7 +68,7 @@ struct eth_device { int eth_register(struct eth_device* dev); /* Register network device */ void eth_unregister(struct eth_device* dev); /* Unregister network device */ -int eth_send(void *packet, int length); /* Send a packet */ +int eth_send(struct eth_device *edev, void *packet, int length); /* Send a packet */ int eth_rx(void); /* Check for received packets */ /* associate a MAC address to a ethernet device. Should be called by @@ -413,12 +413,13 @@ struct eth_device *eth_get_byname(const char *name); * * Return 0 if the packet is successfully handled. Can be ignored */ -int net_receive(unsigned char *pkt, int len); +int net_receive(struct eth_device *edev, unsigned char *pkt, int len); struct net_connection { struct ethernet *et; struct iphdr *ip; struct udphdr *udp; + struct eth_device *edev; struct icmphdr *icmp; unsigned char *packet; struct list_head list; diff --git a/net/eth.c b/net/eth.c index 3ced3cddb..b830f7924 100644 --- a/net/eth.c +++ b/net/eth.c @@ -131,11 +131,6 @@ void of_eth_register_ethaddr(struct device_node *node, const char *ethaddr) void eth_set_current(struct eth_device *eth) { - if (eth_current && eth_current->active) { - eth_current->halt(eth_current); - eth_current->active = 0; - } - eth_current = eth; } @@ -178,83 +173,92 @@ int eth_complete(struct string_list *sl, char *instr) /* * Check for link if we haven't done so for longer. */ -static int eth_carrier_check(int force) +static int eth_carrier_check(struct eth_device *edev, int force) { int ret; if (!IS_ENABLED(CONFIG_PHYLIB)) return 0; - if (!eth_current->phydev) + if (!edev->phydev) return 0; if (force) - phy_wait_aneg_done(eth_current->phydev); + phy_wait_aneg_done(edev->phydev); if (force || is_timeout(last_link_check, 5 * SECOND) || - !eth_current->phydev->link) { - ret = phy_update_status(eth_current->phydev); + !edev->phydev->link) { + ret = phy_update_status(edev->phydev); if (ret) return ret; last_link_check = get_time_ns(); } - return eth_current->phydev->link ? 0 : -ENETDOWN; + return edev->phydev->link ? 0 : -ENETDOWN; } /* * Check if we have a current ethernet device and * eventually open it if we have to. */ -static int eth_check_open(void) +static int eth_check_open(struct eth_device *edev) { int ret; - if (!eth_current) - return -ENODEV; - - if (eth_current->active) + if (edev->active) return 0; - ret = eth_current->open(eth_current); + ret = edev->open(eth_current); if (ret) return ret; - eth_current->active = 1; + edev->active = 1; - return eth_carrier_check(1); + return eth_carrier_check(edev, 1); } -int eth_send(void *packet, int length) +int eth_send(struct eth_device *edev, void *packet, int length) { int ret; - ret = eth_check_open(); + ret = eth_check_open(edev); if (ret) return ret; - ret = eth_carrier_check(0); + ret = eth_carrier_check(edev, 0); if (ret) return ret; led_trigger_network(LED_TRIGGER_NET_TX); - return eth_current->send(eth_current, packet, length); + return edev->send(eth_current, packet, length); +} + +static int __eth_rx(struct eth_device *edev) +{ + int ret; + + ret = eth_check_open(edev); + if (ret) + return ret; + + ret = eth_carrier_check(edev, 0); + if (ret) + return ret; + + return edev->recv(eth_current); } int eth_rx(void) { - int ret; + struct eth_device *edev; - ret = eth_check_open(); - if (ret) - return ret; + list_for_each_entry(edev, &netdev_list, list) { + if (edev->active) + __eth_rx(edev); + } - ret = eth_carrier_check(0); - if (ret) - return ret; - - return eth_current->recv(eth_current); + return 0; } static int eth_set_ethaddr(struct param_d *param, void *priv) @@ -326,12 +330,21 @@ int eth_register(struct eth_device *edev) } strcpy(edev->dev.name, "eth"); - edev->dev.id = DEVICE_ID_DYNAMIC; if (edev->parent) edev->dev.parent = edev->parent; - register_device(&edev->dev); + if (edev->dev.parent && edev->dev.parent->device_node) { + edev->dev.id = of_alias_get_id(edev->dev.parent->device_node, "ethernet"); + if (edev->dev.id < 0) + edev->dev.id = DEVICE_ID_DYNAMIC; + } else { + edev->dev.id = DEVICE_ID_DYNAMIC; + } + + ret = register_device(&edev->dev); + if (ret) + return ret; dev_add_param_ip(dev, "ipaddr", NULL, NULL, &edev->ipaddr, edev); dev_add_param_ip(dev, "serverip", NULL, NULL, &edev->serverip, edev); diff --git a/net/ifup.c b/net/ifup.c index 2315952eb..2e5902503 100644 --- a/net/ifup.c +++ b/net/ifup.c @@ -58,6 +58,8 @@ int ifup(const char *name, unsigned flags) if (edev && edev->ipaddr && !(flags & IFUP_FLAG_FORCE)) return 0; + eth_set_current(edev); + env_push_context(); setenv("ip", ""); diff --git a/net/net.c b/net/net.c index 00bc73a03..07350ad8f 100644 --- a/net/net.c +++ b/net/net.c @@ -241,7 +241,7 @@ static int arp_request(IPaddr_t dest, unsigned char *ether) arp_ether = ether; - ret = eth_send(arp_packet, ETHER_HDR_SIZE + ARP_HDR_SIZE); + ret = eth_send(edev, arp_packet, ETHER_HDR_SIZE + ARP_HDR_SIZE); if (ret) return ret; arp_start = get_time_ns(); @@ -253,7 +253,7 @@ static int arp_request(IPaddr_t dest, unsigned char *ether) if (is_timeout(arp_start, 3 * SECOND)) { printf("T "); arp_start = get_time_ns(); - ret = eth_send(arp_packet, ETHER_HDR_SIZE + ARP_HDR_SIZE); + ret = eth_send(edev, arp_packet, ETHER_HDR_SIZE + ARP_HDR_SIZE); if (ret) return ret; retries++; @@ -358,6 +358,7 @@ static struct net_connection *net_new(IPaddr_t dest, rx_handler_f *handler, con = xzalloc(sizeof(*con)); con->packet = net_alloc_packet(); con->priv = ctx; + con->edev = edev; memset(con->packet, 0, PKTSIZE); con->et = (struct ethernet *)con->packet; @@ -437,7 +438,7 @@ static int net_ip_send(struct net_connection *con, int len) con->ip->check = 0; con->ip->check = ~net_checksum((unsigned char *)con->ip, sizeof(struct iphdr)); - return eth_send(con->packet, ETHER_HDR_SIZE + sizeof(struct iphdr) + len); + return eth_send(con->edev, con->packet, ETHER_HDR_SIZE + sizeof(struct iphdr) + len); } int net_udp_send(struct net_connection *con, int len) @@ -480,7 +481,7 @@ static int net_answer_arp(unsigned char *pkt, int len) if (!packet) return 0; memcpy(packet, pkt, ETHER_HDR_SIZE + ARP_HDR_SIZE); - ret = eth_send(packet, ETHER_HDR_SIZE + ARP_HDR_SIZE); + ret = eth_send(edev, packet, ETHER_HDR_SIZE + ARP_HDR_SIZE); free(packet); return ret; @@ -497,9 +498,8 @@ static void net_bad_packet(unsigned char *pkt, int len) #endif } -static int net_handle_arp(unsigned char *pkt, int len) +static int net_handle_arp(struct eth_device *edev, unsigned char *pkt, int len) { - struct eth_device *edev = eth_get_current(); struct arprequest *arp; debug("%s: got arp\n", __func__); @@ -580,10 +580,9 @@ static int net_handle_icmp(unsigned char *pkt, int len) return 0; } -static int net_handle_ip(unsigned char *pkt, int len) +static int net_handle_ip(struct eth_device *edev, unsigned char *pkt, int len) { struct iphdr *ip = (struct iphdr *)(pkt + ETHER_HDR_SIZE); - struct eth_device *edev = eth_get_current(); IPaddr_t tmp; debug("%s\n", __func__); @@ -619,7 +618,7 @@ bad: return 0; } -int net_receive(unsigned char *pkt, int len) +int net_receive(struct eth_device *edev, unsigned char *pkt, int len) { struct ethernet *et = (struct ethernet *)pkt; int et_protlen = ntohs(et->et_protlen); @@ -634,10 +633,10 @@ int net_receive(unsigned char *pkt, int len) switch (et_protlen) { case PROT_ARP: - ret = net_handle_arp(pkt, len); + ret = net_handle_arp(edev, pkt, len); break; case PROT_IP: - ret = net_handle_ip(pkt, len); + ret = net_handle_ip(edev, pkt, len); break; default: debug("%s: got unknown protocol type: %d\n", __func__, et_protlen);