diff --git a/arch/sandbox/include/asm/eth.h b/arch/sandbox/include/asm/eth.h index bfcd11b..477fa00 100644 --- a/arch/sandbox/include/asm/eth.h +++ b/arch/sandbox/include/asm/eth.h @@ -13,4 +13,97 @@ void sandbox_eth_disable_response(int index, bool disable); void sandbox_eth_skip_timeout(void); +/* + * sandbox_eth_arp_req_to_reply() + * + * Check for an arp request to be sent. If so, inject a reply + * + * @dev: device that received the packet + * @packet: pointer to the received pacaket buffer + * @len: length of received packet + * @return 0 if injected, -EAGAIN if not + */ +int sandbox_eth_arp_req_to_reply(struct udevice *dev, void *packet, + unsigned int len); + +/* + * sandbox_eth_ping_req_to_reply() + * + * Check for a ping request to be sent. If so, inject a reply + * + * @dev: device that received the packet + * @packet: pointer to the received pacaket buffer + * @len: length of received packet + * @return 0 if injected, -EAGAIN if not + */ +int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet, + unsigned int len); + +/* + * sandbox_eth_recv_arp_req() + * + * Inject an ARP request for this target + * + * @dev: device that received the packet + * @return 0 if injected, -EOVERFLOW if not + */ +int sandbox_eth_recv_arp_req(struct udevice *dev); + +/* + * sandbox_eth_recv_ping_req() + * + * Inject a ping request for this target + * + * @dev: device that received the packet + * @return 0 if injected, -EOVERFLOW if not + */ +int sandbox_eth_recv_ping_req(struct udevice *dev); + +/** + * A packet handler + * + * dev - device pointer + * pkt - pointer to the "sent" packet + * len - packet length + */ +typedef int sandbox_eth_tx_hand_f(struct udevice *dev, void *pkt, + unsigned int len); + +/** + * struct eth_sandbox_priv - memory for sandbox mock driver + * + * fake_host_hwaddr - MAC address of mocked machine + * fake_host_ipaddr - IP address of mocked machine + * disabled - Will not respond + * recv_packet_buffer - buffers of the packet returned as received + * recv_packet_length - lengths of the packet returned as received + * recv_packets - number of packets returned + * tx_handler - function to generate responses to sent packets + * priv - a pointer to some structure a test may want to keep track of + */ +struct eth_sandbox_priv { + uchar fake_host_hwaddr[ARP_HLEN]; + struct in_addr fake_host_ipaddr; + bool disabled; + uchar * recv_packet_buffer[PKTBUFSRX]; + int recv_packet_length[PKTBUFSRX]; + int recv_packets; + sandbox_eth_tx_hand_f *tx_handler; + void *priv; +}; + +/* + * Set packet handler + * + * handler - The func ptr to call on send. If NULL, set to default handler + */ +void sandbox_eth_set_tx_handler(int index, sandbox_eth_tx_hand_f *handler); + +/* + * Set priv ptr + * + * priv - priv void ptr to store in the device + */ +void sandbox_eth_set_priv(int index, void *priv); + #endif /* __ETH_H */ diff --git a/board/Synology/ds414/cmd_syno.c b/board/Synology/ds414/cmd_syno.c index 34643ff..59e6fe0 100644 --- a/board/Synology/ds414/cmd_syno.c +++ b/board/Synology/ds414/cmd_syno.c @@ -14,7 +14,6 @@ #include #include "../drivers/ddr/marvell/axp/ddr3_init.h" -#define ETH_ALEN 6 #define ETHADDR_MAX 4 #define SYNO_SN_TAG "SN=" #define SYNO_CHKSUM_TAG "CHK=" diff --git a/board/freescale/ls1088a/eth_ls1088aqds.c b/board/freescale/ls1088a/eth_ls1088aqds.c index 40b1a0e..f16b78c 100644 --- a/board/freescale/ls1088a/eth_ls1088aqds.c +++ b/board/freescale/ls1088a/eth_ls1088aqds.c @@ -487,16 +487,16 @@ void ls1088a_handle_phy_interface_sgmii(int dpmac_id) case 0x3A: switch (dpmac_id) { case 1: - wriop_set_phy_address(dpmac_id, riser_phy_addr[1]); + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[1]); break; case 2: - wriop_set_phy_address(dpmac_id, riser_phy_addr[0]); + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[0]); break; case 3: - wriop_set_phy_address(dpmac_id, riser_phy_addr[3]); + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[3]); break; case 7: - wriop_set_phy_address(dpmac_id, riser_phy_addr[2]); + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[2]); break; default: printf("WRIOP: Wrong DPMAC%d set to SGMII", dpmac_id); @@ -532,13 +532,13 @@ void ls1088a_handle_phy_interface_qsgmii(int dpmac_id) case 4: case 5: case 6: - wriop_set_phy_address(dpmac_id, dpmac_id + 9); + wriop_set_phy_address(dpmac_id, 0, dpmac_id + 9); break; case 7: case 8: case 9: case 10: - wriop_set_phy_address(dpmac_id, dpmac_id + 1); + wriop_set_phy_address(dpmac_id, 0, dpmac_id + 1); break; } @@ -567,7 +567,7 @@ void ls1088a_handle_phy_interface_xsgmii(int i) case 0x15: case 0x1D: case 0x1E: - wriop_set_phy_address(i, i + 26); + wriop_set_phy_address(i, 0, i + 26); ls1088a_qds_enable_SFP_TX(SFP_TX); break; default: @@ -590,13 +590,13 @@ static void ls1088a_handle_phy_interface_rgmii(int dpmac_id) switch (dpmac_id) { case 4: - wriop_set_phy_address(dpmac_id, RGMII_PHY1_ADDR); + wriop_set_phy_address(dpmac_id, 0, RGMII_PHY1_ADDR); dpmac_info[dpmac_id].board_mux = EMI1_RGMII1; bus = mii_dev_for_muxval(EMI1_RGMII1); wriop_set_mdio(dpmac_id, bus); break; case 5: - wriop_set_phy_address(dpmac_id, RGMII_PHY2_ADDR); + wriop_set_phy_address(dpmac_id, 0, RGMII_PHY2_ADDR); dpmac_info[dpmac_id].board_mux = EMI1_RGMII2; bus = mii_dev_for_muxval(EMI1_RGMII2); wriop_set_mdio(dpmac_id, bus); diff --git a/board/freescale/ls1088a/eth_ls1088ardb.c b/board/freescale/ls1088a/eth_ls1088ardb.c index 418f362..a2b52a8 100644 --- a/board/freescale/ls1088a/eth_ls1088ardb.c +++ b/board/freescale/ls1088a/eth_ls1088ardb.c @@ -55,16 +55,17 @@ int board_eth_init(bd_t *bis) * a MAC has no PHY address, we give a PHY address to XFI * MAC error. */ - wriop_set_phy_address(WRIOP1_DPMAC1, 0x0a); - wriop_set_phy_address(WRIOP1_DPMAC2, AQ_PHY_ADDR1); - wriop_set_phy_address(WRIOP1_DPMAC3, QSGMII1_PORT1_PHY_ADDR); - wriop_set_phy_address(WRIOP1_DPMAC4, QSGMII1_PORT2_PHY_ADDR); - wriop_set_phy_address(WRIOP1_DPMAC5, QSGMII1_PORT3_PHY_ADDR); - wriop_set_phy_address(WRIOP1_DPMAC6, QSGMII1_PORT4_PHY_ADDR); - wriop_set_phy_address(WRIOP1_DPMAC7, QSGMII2_PORT1_PHY_ADDR); - wriop_set_phy_address(WRIOP1_DPMAC8, QSGMII2_PORT2_PHY_ADDR); - wriop_set_phy_address(WRIOP1_DPMAC9, QSGMII2_PORT3_PHY_ADDR); - wriop_set_phy_address(WRIOP1_DPMAC10, QSGMII2_PORT4_PHY_ADDR); + wriop_set_phy_address(WRIOP1_DPMAC1, 0, 0x0a); + wriop_set_phy_address(WRIOP1_DPMAC2, 0, AQ_PHY_ADDR1); + wriop_set_phy_address(WRIOP1_DPMAC3, 0, QSGMII1_PORT1_PHY_ADDR); + wriop_set_phy_address(WRIOP1_DPMAC4, 0, QSGMII1_PORT2_PHY_ADDR); + wriop_set_phy_address(WRIOP1_DPMAC5, 0, QSGMII1_PORT3_PHY_ADDR); + wriop_set_phy_address(WRIOP1_DPMAC6, 0, QSGMII1_PORT4_PHY_ADDR); + wriop_set_phy_address(WRIOP1_DPMAC7, 0, QSGMII2_PORT1_PHY_ADDR); + wriop_set_phy_address(WRIOP1_DPMAC8, 0, QSGMII2_PORT2_PHY_ADDR); + wriop_set_phy_address(WRIOP1_DPMAC9, 0, QSGMII2_PORT3_PHY_ADDR); + wriop_set_phy_address(WRIOP1_DPMAC10, 0, + QSGMII2_PORT4_PHY_ADDR); break; default: diff --git a/board/freescale/ls2080aqds/eth.c b/board/freescale/ls2080aqds/eth.c index 989d57e..f706fd4 100644 --- a/board/freescale/ls2080aqds/eth.c +++ b/board/freescale/ls2080aqds/eth.c @@ -623,7 +623,7 @@ void ls2080a_handle_phy_interface_sgmii(int dpmac_id) switch (++slot) { case 1: /* Slot housing a SGMII riser card? */ - wriop_set_phy_address(dpmac_id, + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[dpmac_id - 1]); dpmac_info[dpmac_id].board_mux = EMI1_SLOT1; bus = mii_dev_for_muxval(EMI1_SLOT1); @@ -631,7 +631,7 @@ void ls2080a_handle_phy_interface_sgmii(int dpmac_id) break; case 2: /* Slot housing a SGMII riser card? */ - wriop_set_phy_address(dpmac_id, + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[dpmac_id - 1]); dpmac_info[dpmac_id].board_mux = EMI1_SLOT2; bus = mii_dev_for_muxval(EMI1_SLOT2); @@ -641,18 +641,18 @@ void ls2080a_handle_phy_interface_sgmii(int dpmac_id) if (slot == EMI_NONE) return; if (serdes1_prtcl == 0x39) { - wriop_set_phy_address(dpmac_id, + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[dpmac_id - 2]); if (dpmac_id >= 6 && hwconfig_f("xqsgmii", env_hwconfig)) - wriop_set_phy_address(dpmac_id, + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[dpmac_id - 3]); } else { - wriop_set_phy_address(dpmac_id, + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[dpmac_id - 2]); if (dpmac_id >= 7 && hwconfig_f("xqsgmii", env_hwconfig)) - wriop_set_phy_address(dpmac_id, + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[dpmac_id - 3]); } dpmac_info[dpmac_id].board_mux = EMI1_SLOT3; @@ -691,7 +691,7 @@ serdes2: break; case 4: /* Slot housing a SGMII riser card? */ - wriop_set_phy_address(dpmac_id, + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[dpmac_id - 9]); dpmac_info[dpmac_id].board_mux = EMI1_SLOT4; bus = mii_dev_for_muxval(EMI1_SLOT4); @@ -701,14 +701,14 @@ serdes2: if (slot == EMI_NONE) return; if (serdes2_prtcl == 0x47) { - wriop_set_phy_address(dpmac_id, + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[dpmac_id - 10]); if (dpmac_id >= 14 && hwconfig_f("xqsgmii", env_hwconfig)) - wriop_set_phy_address(dpmac_id, + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[dpmac_id - 11]); } else { - wriop_set_phy_address(dpmac_id, + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[dpmac_id - 11]); } dpmac_info[dpmac_id].board_mux = EMI1_SLOT5; @@ -717,7 +717,7 @@ serdes2: break; case 6: /* Slot housing a SGMII riser card? */ - wriop_set_phy_address(dpmac_id, + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[dpmac_id - 13]); dpmac_info[dpmac_id].board_mux = EMI1_SLOT6; bus = mii_dev_for_muxval(EMI1_SLOT6); @@ -775,7 +775,7 @@ void ls2080a_handle_phy_interface_qsgmii(int dpmac_id) switch (++slot) { case 1: /* Slot housing a QSGMII riser card? */ - wriop_set_phy_address(dpmac_id, dpmac_id - 1); + wriop_set_phy_address(dpmac_id, 0, dpmac_id - 1); dpmac_info[dpmac_id].board_mux = EMI1_SLOT1; bus = mii_dev_for_muxval(EMI1_SLOT1); wriop_set_mdio(dpmac_id, bus); @@ -819,7 +819,7 @@ void ls2080a_handle_phy_interface_xsgmii(int i) * the XAUI card is used for the XFI MAC, which will cause * error. */ - wriop_set_phy_address(i, i + 4); + wriop_set_phy_address(i, 0, i + 4); ls2080a_qds_enable_SFP_TX(SFP_TX); break; diff --git a/board/freescale/ls2080ardb/eth_ls2080rdb.c b/board/freescale/ls2080ardb/eth_ls2080rdb.c index 45f1d60..62c7a7a 100644 --- a/board/freescale/ls2080ardb/eth_ls2080rdb.c +++ b/board/freescale/ls2080ardb/eth_ls2080rdb.c @@ -50,21 +50,21 @@ int board_eth_init(bd_t *bis) switch (srds_s1) { case 0x2A: - wriop_set_phy_address(WRIOP1_DPMAC1, CORTINA_PHY_ADDR1); - wriop_set_phy_address(WRIOP1_DPMAC2, CORTINA_PHY_ADDR2); - wriop_set_phy_address(WRIOP1_DPMAC3, CORTINA_PHY_ADDR3); - wriop_set_phy_address(WRIOP1_DPMAC4, CORTINA_PHY_ADDR4); - wriop_set_phy_address(WRIOP1_DPMAC5, AQ_PHY_ADDR1); - wriop_set_phy_address(WRIOP1_DPMAC6, AQ_PHY_ADDR2); - wriop_set_phy_address(WRIOP1_DPMAC7, AQ_PHY_ADDR3); - wriop_set_phy_address(WRIOP1_DPMAC8, AQ_PHY_ADDR4); + wriop_set_phy_address(WRIOP1_DPMAC1, 0, CORTINA_PHY_ADDR1); + wriop_set_phy_address(WRIOP1_DPMAC2, 0, CORTINA_PHY_ADDR2); + wriop_set_phy_address(WRIOP1_DPMAC3, 0, CORTINA_PHY_ADDR3); + wriop_set_phy_address(WRIOP1_DPMAC4, 0, CORTINA_PHY_ADDR4); + wriop_set_phy_address(WRIOP1_DPMAC5, 0, AQ_PHY_ADDR1); + wriop_set_phy_address(WRIOP1_DPMAC6, 0, AQ_PHY_ADDR2); + wriop_set_phy_address(WRIOP1_DPMAC7, 0, AQ_PHY_ADDR3); + wriop_set_phy_address(WRIOP1_DPMAC8, 0, AQ_PHY_ADDR4); break; case 0x4B: - wriop_set_phy_address(WRIOP1_DPMAC1, CORTINA_PHY_ADDR1); - wriop_set_phy_address(WRIOP1_DPMAC2, CORTINA_PHY_ADDR2); - wriop_set_phy_address(WRIOP1_DPMAC3, CORTINA_PHY_ADDR3); - wriop_set_phy_address(WRIOP1_DPMAC4, CORTINA_PHY_ADDR4); + wriop_set_phy_address(WRIOP1_DPMAC1, 0, CORTINA_PHY_ADDR1); + wriop_set_phy_address(WRIOP1_DPMAC2, 0, CORTINA_PHY_ADDR2); + wriop_set_phy_address(WRIOP1_DPMAC3, 0, CORTINA_PHY_ADDR3); + wriop_set_phy_address(WRIOP1_DPMAC4, 0, CORTINA_PHY_ADDR4); break; default: diff --git a/doc/device-tree-bindings/net/ti,dp83867.txt b/doc/device-tree-bindings/net/ti,dp83867.txt index cb77fdf..034146f 100644 --- a/doc/device-tree-bindings/net/ti,dp83867.txt +++ b/doc/device-tree-bindings/net/ti,dp83867.txt @@ -8,6 +8,12 @@ Required properties: for applicable values - ti,fifo-depth - Transmitt FIFO depth- see dt-bindings/net/ti-dp83867.h for applicable values + - enet-phy-lane-swap - Indicates that PHY will swap the TX/RX lanes to + compensate for the board being designed with the lanes swapped. + - enet-phy-no-lane-swap - Indicates that PHY will disable swap of the + TX/RX lanes. + - ti,clk-output-sel - Clock output select - see dt-bindings/net/ti-dp83867.h + for applicable values Default child nodes are standard Ethernet PHY device nodes as described in doc/devicetree/bindings/net/ethernet.txt @@ -19,6 +25,8 @@ Example: ti,rx-internal-delay = ; ti,tx-internal-delay = ; ti,fifo-depth = ; + enet-phy-lane-no-swap; + ti,clk-output-sel = ; }; Datasheet can be found: diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index 8d7c271..e3c403c 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -123,7 +123,6 @@ #define TOUT_LOOP 1000000 #define SETUP_FRAME_LEN 192 -#define ETH_ALEN 6 struct de4x5_desc { volatile s32 status; diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index ae65b64..2fe0ba6 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -193,8 +193,6 @@ struct descriptor { /* A generic descriptor. */ #define TOUT_LOOP 1000000 -#define ETH_ALEN 6 - static struct RxFD rx_ring[NUM_RX_DESC]; /* RX descriptor ring */ static struct TxFD tx_ring[NUM_TX_DESC]; /* TX descriptor ring */ static int rx_next; /* RX descriptor ring pointer */ diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c index d9a897d..b245fbc 100644 --- a/drivers/net/fsl-mc/mc.c +++ b/drivers/net/fsl-mc/mc.c @@ -363,8 +363,7 @@ static int mc_fixup_mac_addrs(void *blob, enum mc_fixup_type type) for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) { /* port not enabled */ - if ((wriop_is_enabled_dpmac(i) != 1) || - (wriop_get_phy_address(i) == -1)) + if (wriop_is_enabled_dpmac(i) != 1) continue; snprintf(ethname, ETH_NAME_LEN, "DPMAC%d@%s", i, @@ -886,8 +885,7 @@ int fsl_mc_ldpaa_init(bd_t *bis) int i; for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) - if ((wriop_is_enabled_dpmac(i) == 1) && - (wriop_get_phy_address(i) != -1)) + if (wriop_is_enabled_dpmac(i) == 1) ldpaa_eth_init(i, wriop_get_enet_if(i)); return 0; } diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index a25b7cd..fe1c03e 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -23,21 +23,43 @@ static int init_phy(struct eth_device *dev) struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv; struct phy_device *phydev = NULL; struct mii_dev *bus; + int phy_addr, phy_num; + int ret = 0; bus = wriop_get_mdio(priv->dpmac_id); if (bus == NULL) return 0; - phydev = phy_connect(bus, wriop_get_phy_address(priv->dpmac_id), - dev, wriop_get_enet_if(priv->dpmac_id)); - if (!phydev) { - printf("Failed to connect\n"); - return -1; + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + phy_addr = wriop_get_phy_address(priv->dpmac_id, phy_num); + if (phy_addr < 0) + continue; + + phydev = phy_connect(bus, phy_addr, dev, + wriop_get_enet_if(priv->dpmac_id)); + if (!phydev) { + printf("Failed to connect\n"); + ret = -ENODEV; + break; + } + wriop_set_phy_dev(priv->dpmac_id, phy_num, phydev); + ret = phy_config(phydev); + if (ret) + break; } - priv->phydev = phydev; + if (ret) { + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num); + if (!phydev) + continue; - return phy_config(phydev); + free(phydev); + wriop_set_phy_dev(priv->dpmac_id, phy_num, NULL); + } + } + + return ret; } #endif @@ -377,6 +399,68 @@ error: return err; } +static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv, + struct dpmac_link_state *state) +{ + struct phy_device *phydev = NULL; + phy_interface_t enet_if; + int phy_num, phys_detected; + int err; + + /* let's start off with maximum capabilities */ + enet_if = wriop_get_enet_if(priv->dpmac_id); + switch (enet_if) { + case PHY_INTERFACE_MODE_XGMII: + state->rate = SPEED_10000; + break; + default: + state->rate = SPEED_1000; + break; + } + state->up = 1; + + phys_detected = 0; +#ifdef CONFIG_PHYLIB + state->options |= DPMAC_LINK_OPT_AUTONEG; + + /* start the phy devices one by one and update the dpmac state */ + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num); + if (!phydev) + continue; + + phys_detected++; + err = phy_startup(phydev); + if (err) { + printf("%s: Could not initialize\n", phydev->dev->name); + state->up = 0; + break; + } + if (phydev->link) { + state->rate = min(state->rate, (uint32_t)phydev->speed); + if (!phydev->duplex) + state->options |= DPMAC_LINK_OPT_HALF_DUPLEX; + if (!phydev->autoneg) + state->options &= ~DPMAC_LINK_OPT_AUTONEG; + } else { + /* break out of loop even if one phy is down */ + state->up = 0; + break; + } + } +#endif + if (!phys_detected) + state->options &= ~DPMAC_LINK_OPT_AUTONEG; + + if (!state->up) { + state->rate = 0; + state->options = 0; + return -ENOLINK; + } + + return 0; +} + static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; @@ -385,8 +469,6 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) struct dpni_link_state link_state; #endif int err = 0; - struct mii_dev *bus; - phy_interface_t enet_if; struct dpni_queue d_queue; if (net_dev->state == ETH_STATE_ACTIVE) @@ -407,47 +489,14 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) if (err < 0) goto err_dpmac_setup; -#ifdef CONFIG_PHYLIB - if (priv->phydev) { - err = phy_startup(priv->phydev); - if (err) { - printf("%s: Could not initialize\n", - priv->phydev->dev->name); - goto err_dpamc_bind; - } - } -#else - priv->phydev = (struct phy_device *)malloc(sizeof(struct phy_device)); - memset(priv->phydev, 0, sizeof(struct phy_device)); - - priv->phydev->speed = SPEED_1000; - priv->phydev->link = 1; - priv->phydev->duplex = DUPLEX_FULL; -#endif - - bus = wriop_get_mdio(priv->dpmac_id); - enet_if = wriop_get_enet_if(priv->dpmac_id); - if ((bus == NULL) && - (enet_if == PHY_INTERFACE_MODE_XGMII)) { - priv->phydev = (struct phy_device *) - malloc(sizeof(struct phy_device)); - memset(priv->phydev, 0, sizeof(struct phy_device)); - - priv->phydev->speed = SPEED_10000; - priv->phydev->link = 1; - priv->phydev->duplex = DUPLEX_FULL; - } - - if (!priv->phydev->link) { - printf("%s: No link.\n", priv->phydev->dev->name); - err = -1; - goto err_dpamc_bind; - } + err = ldpaa_get_dpmac_state(priv, &dpmac_link_state); + if (err < 0) + goto err_dpmac_bind; /* DPMAC binding DPNI */ err = ldpaa_dpmac_bind(priv); if (err) - goto err_dpamc_bind; + goto err_dpmac_bind; /* DPNI initialization */ err = ldpaa_dpni_setup(priv); @@ -476,18 +525,6 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) return err; } - dpmac_link_state.rate = priv->phydev->speed; - - if (priv->phydev->autoneg == AUTONEG_DISABLE) - dpmac_link_state.options &= ~DPMAC_LINK_OPT_AUTONEG; - else - dpmac_link_state.options |= DPMAC_LINK_OPT_AUTONEG; - - if (priv->phydev->duplex == DUPLEX_HALF) - dpmac_link_state.options |= DPMAC_LINK_OPT_HALF_DUPLEX; - - dpmac_link_state.up = priv->phydev->link; - err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle, &dpmac_link_state); if (err < 0) { @@ -530,7 +567,7 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) goto err_qdid; } - return priv->phydev->link; + return dpmac_link_state.up; err_qdid: err_get_queue: @@ -540,7 +577,7 @@ err_dpni_bind: err_dpbp_setup: dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); err_dpni_setup: -err_dpamc_bind: +err_dpmac_bind: dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle); dpmac_destroy(dflt_mc_io, dflt_dprc_handle, @@ -553,9 +590,8 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; int err = 0; -#ifdef CONFIG_PHYLIB - struct mii_dev *bus = wriop_get_mdio(priv->dpmac_id); -#endif + struct phy_device *phydev = NULL; + int phy_num; if ((net_dev->state == ETH_STATE_PASSIVE) || (net_dev->state == ETH_STATE_INIT)) @@ -588,11 +624,10 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) printf("dpni_disable() failed\n"); #ifdef CONFIG_PHYLIB - if (priv->phydev && bus != NULL) - phy_shutdown(priv->phydev); - else { - free(priv->phydev); - priv->phydev = NULL; + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num); + if (phydev) + phy_shutdown(phydev); } #endif diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.h b/drivers/net/ldpaa_eth/ldpaa_eth.h index ee784a5..3f9154b 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.h +++ b/drivers/net/ldpaa_eth/ldpaa_eth.h @@ -127,7 +127,6 @@ struct ldpaa_eth_priv { uint16_t tx_flow_id; enum ldpaa_eth_type type; /* 1G or 10G ethernet */ - struct phy_device *phydev; }; struct dprc_endpoint dpmac_endpoint; diff --git a/drivers/net/ldpaa_eth/ldpaa_wriop.c b/drivers/net/ldpaa_eth/ldpaa_wriop.c index 0731a79..06a284a 100644 --- a/drivers/net/ldpaa_eth/ldpaa_wriop.c +++ b/drivers/net/ldpaa_eth/ldpaa_wriop.c @@ -22,10 +22,10 @@ __weak phy_interface_t wriop_dpmac_enet_if(int dpmac_id, int lane_prtc) void wriop_init_dpmac(int sd, int dpmac_id, int lane_prtcl) { phy_interface_t enet_if; + int phy_num; dpmac_info[dpmac_id].enabled = 0; dpmac_info[dpmac_id].id = 0; - dpmac_info[dpmac_id].phy_addr = -1; dpmac_info[dpmac_id].enet_if = PHY_INTERFACE_MODE_NONE; enet_if = wriop_dpmac_enet_if(dpmac_id, lane_prtcl); @@ -34,14 +34,23 @@ void wriop_init_dpmac(int sd, int dpmac_id, int lane_prtcl) dpmac_info[dpmac_id].id = dpmac_id; dpmac_info[dpmac_id].enet_if = enet_if; } + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + dpmac_info[dpmac_id].phydev[phy_num] = NULL; + dpmac_info[dpmac_id].phy_addr[phy_num] = -1; + } } void wriop_init_dpmac_enet_if(int dpmac_id, phy_interface_t enet_if) { + int phy_num; + dpmac_info[dpmac_id].enabled = 1; dpmac_info[dpmac_id].id = dpmac_id; - dpmac_info[dpmac_id].phy_addr = -1; dpmac_info[dpmac_id].enet_if = enet_if; + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + dpmac_info[dpmac_id].phydev[phy_num] = NULL; + dpmac_info[dpmac_id].phy_addr[phy_num] = -1; + } } @@ -58,47 +67,53 @@ static int wriop_dpmac_to_index(int dpmac_id) return -1; } -void wriop_disable_dpmac(int dpmac_id) +int wriop_disable_dpmac(int dpmac_id) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return; + return -ENODEV; dpmac_info[i].enabled = 0; wriop_dpmac_disable(dpmac_id); + + return 0; } -void wriop_enable_dpmac(int dpmac_id) +int wriop_enable_dpmac(int dpmac_id) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return; + return -ENODEV; dpmac_info[i].enabled = 1; wriop_dpmac_enable(dpmac_id); + + return 0; } -u8 wriop_is_enabled_dpmac(int dpmac_id) +int wriop_is_enabled_dpmac(int dpmac_id) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return -1; + return -ENODEV; return dpmac_info[i].enabled; } -void wriop_set_mdio(int dpmac_id, struct mii_dev *bus) +int wriop_set_mdio(int dpmac_id, struct mii_dev *bus) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return; + return -ENODEV; dpmac_info[i].bus = bus; + + return 0; } struct mii_dev *wriop_get_mdio(int dpmac_id) @@ -111,44 +126,56 @@ struct mii_dev *wriop_get_mdio(int dpmac_id) return dpmac_info[i].bus; } -void wriop_set_phy_address(int dpmac_id, int address) +int wriop_set_phy_address(int dpmac_id, int phy_num, int address) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return; + return -ENODEV; + if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM) + return -EINVAL; + + dpmac_info[i].phy_addr[phy_num] = address; - dpmac_info[i].phy_addr = address; + return 0; } -int wriop_get_phy_address(int dpmac_id) +int wriop_get_phy_address(int dpmac_id, int phy_num) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return -1; + return -ENODEV; + if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM) + return -EINVAL; - return dpmac_info[i].phy_addr; + return dpmac_info[i].phy_addr[phy_num]; } -void wriop_set_phy_dev(int dpmac_id, struct phy_device *phydev) +int wriop_set_phy_dev(int dpmac_id, int phy_num, struct phy_device *phydev) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return; + return -ENODEV; + if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM) + return -EINVAL; - dpmac_info[i].phydev = phydev; + dpmac_info[i].phydev[phy_num] = phydev; + + return 0; } -struct phy_device *wriop_get_phy_dev(int dpmac_id) +struct phy_device *wriop_get_phy_dev(int dpmac_id, int phy_num) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) return NULL; + if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM) + return NULL; - return dpmac_info[i].phydev; + return dpmac_info[i].phydev[phy_num]; } phy_interface_t wriop_get_enet_if(int dpmac_id) diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c index ab697b9..8cb04b5 100644 --- a/drivers/net/mvneta.c +++ b/drivers/net/mvneta.c @@ -34,14 +34,6 @@ DECLARE_GLOBAL_DATA_PTR; # error Marvell mvneta requires PHYLIB #endif -/* Some linux -> U-Boot compatibility stuff */ -#define netdev_err(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_warn(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_info(dev, fmt, args...) \ - printf(fmt, ##args) - #define CONFIG_NR_CPUS 1 #define ETH_HLEN 14 /* Total octets in header */ diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 62c0c2b..f34245b 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -35,18 +35,6 @@ DECLARE_GLOBAL_DATA_PTR; -/* Some linux -> U-Boot compatibility stuff */ -#define netdev_err(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_warn(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_info(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_dbg(dev, fmt, args...) \ - printf(fmt, ##args) - -#define ETH_ALEN 6 /* Octets in one ethernet addr */ - #define __verify_pcpu_ptr(ptr) \ do { \ const void __percpu *__vpp_verify = (typeof((ptr) + 0))NULL; \ @@ -68,7 +56,6 @@ do { \ #define NET_SKB_PAD max(32, MVPP2_CPU_D_CACHE_LINE_SIZE) #define CONFIG_NR_CPUS 1 -#define ETH_HLEN ETHER_HDR_SIZE /* Total octets in header */ /* 2(HW hdr) 14(MAC hdr) 4(CRC) 32(extra for cache prefetch) */ #define WRAP (2 + ETH_HLEN + 4 + 32) diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 0ed9bb5..86f6898 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -61,7 +61,6 @@ #define EEPROM_SIZE 0xb /*12 16-bit chunks, or 24 bytes*/ #define DSIZE 0x00000FFF -#define ETH_ALEN 6 #define CRC_SIZE 4 #define TOUT_LOOP 500000 #define TX_BUF_SIZE 1536 diff --git a/drivers/net/ns8382x.c b/drivers/net/ns8382x.c index f941c15..ea7ece5 100644 --- a/drivers/net/ns8382x.c +++ b/drivers/net/ns8382x.c @@ -59,7 +59,6 @@ /* defines */ #define DSIZE 0x00000FFF -#define ETH_ALEN 6 #define CRC_SIZE 4 #define TOUT_LOOP 500000 #define TX_BUF_SIZE 1536 diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c index d31c45f..2286dd0 100644 --- a/drivers/net/pch_gbe.c +++ b/drivers/net/pch_gbe.c @@ -429,7 +429,7 @@ static int pch_gbe_phy_init(struct udevice *dev) return 0; } -int pch_gbe_probe(struct udevice *dev) +static int pch_gbe_probe(struct udevice *dev) { struct pch_gbe_priv *priv; struct eth_pdata *plat = dev_get_platdata(dev); @@ -464,7 +464,7 @@ int pch_gbe_probe(struct udevice *dev) return pch_gbe_phy_init(dev); } -int pch_gbe_remove(struct udevice *dev) +static int pch_gbe_remove(struct udevice *dev) { struct pch_gbe_priv *priv = dev_get_priv(dev); diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c index f870e6d..6db6edd 100644 --- a/drivers/net/phy/ti.c +++ b/drivers/net/phy/ti.c @@ -24,6 +24,7 @@ /* Extended Registers */ #define DP83867_CFG4 0x0031 #define DP83867_RGMIICTL 0x0032 +#define DP83867_STRAP_STS1 0x006E #define DP83867_RGMIIDCTL 0x0086 #define DP83867_IO_MUX_CFG 0x0170 @@ -48,8 +49,12 @@ #define DP83867_RGMII_TX_CLK_DELAY_EN BIT(1) #define DP83867_RGMII_RX_CLK_DELAY_EN BIT(0) +/* STRAP_STS1 bits */ +#define DP83867_STRAP_STS1_RESERVED BIT(11) + /* PHY CTRL bits */ #define DP83867_PHYCR_FIFO_DEPTH_SHIFT 14 +#define DP83867_PHYCR_RESERVED_MASK BIT(11) #define DP83867_MDI_CROSSOVER 5 #define DP83867_MDI_CROSSOVER_AUTO 2 #define DP83867_MDI_CROSSOVER_MDIX 2 @@ -88,6 +93,18 @@ #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0 #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f +#define DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT 8 +#define DP83867_IO_MUX_CFG_CLK_O_SEL_MASK \ + GENMASK(0x1f, DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT) + +/* CFG4 bits */ +#define DP83867_CFG4_PORT_MIRROR_EN BIT(0) + +enum { + DP83867_PORT_MIRRORING_KEEP, + DP83867_PORT_MIRRORING_EN, + DP83867_PORT_MIRRORING_DIS, +}; struct dp83867_private { int rx_id_delay; @@ -95,6 +112,8 @@ struct dp83867_private { int fifo_depth; int io_impedance; bool rxctrl_strap_quirk; + int port_mirroring; + int clk_output_sel; }; /** @@ -163,6 +182,26 @@ void phy_write_mmd_indirect(struct phy_device *phydev, int prtad, phy_write(phydev, addr, MII_MMD_DATA, data); } +static int dp83867_config_port_mirroring(struct phy_device *phydev) +{ + struct dp83867_private *dp83867 = + (struct dp83867_private *)phydev->priv; + u16 val; + + val = phy_read_mmd_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR, + phydev->addr); + + if (dp83867->port_mirroring == DP83867_PORT_MIRRORING_EN) + val |= DP83867_CFG4_PORT_MIRROR_EN; + else + val &= ~DP83867_CFG4_PORT_MIRROR_EN; + + phy_write_mmd_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR, + phydev->addr, val); + + return 0; +} + #if defined(CONFIG_DM_ETH) /** * dp83867_data_init - Convenience function for setting PHY specific data @@ -173,6 +212,18 @@ static int dp83867_of_init(struct phy_device *phydev) { struct dp83867_private *dp83867 = phydev->priv; ofnode node; + u16 val; + + /* Optional configuration */ + + /* + * Keep the default value if ti,clk-output-sel is not set + * or to high + */ + + dp83867->clk_output_sel = + ofnode_read_u32_default(node, "ti,clk-output-sel", + DP83867_CLK_O_SEL_REF_CLK); node = phy_get_ofnode(phydev); if (!ofnode_valid(node)) @@ -197,6 +248,23 @@ static int dp83867_of_init(struct phy_device *phydev) dp83867->fifo_depth = ofnode_read_u32_default(node, "ti,fifo-depth", -1); + if (ofnode_read_bool(node, "enet-phy-lane-swap")) + dp83867->port_mirroring = DP83867_PORT_MIRRORING_EN; + + if (ofnode_read_bool(node, "enet-phy-lane-no-swap")) + dp83867->port_mirroring = DP83867_PORT_MIRRORING_DIS; + + + /* Clock output selection if muxing property is set */ + if (dp83867->clk_output_sel != DP83867_CLK_O_SEL_REF_CLK) { + val = phy_read_mmd_indirect(phydev, DP83867_IO_MUX_CFG, + DP83867_DEVADDR, phydev->addr); + val &= ~DP83867_IO_MUX_CFG_CLK_O_SEL_MASK; + val |= (dp83867->clk_output_sel << + DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT); + phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG, + DP83867_DEVADDR, phydev->addr, val); + } return 0; } @@ -218,7 +286,7 @@ static int dp83867_config(struct phy_device *phydev) { struct dp83867_private *dp83867; unsigned int val, delay, cfg2; - int ret; + int ret, bs; if (!phydev->priv) { dp83867 = kzalloc(sizeof(*dp83867), GFP_KERNEL); @@ -253,6 +321,26 @@ static int dp83867_config(struct phy_device *phydev) (dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT)); if (ret) goto err_out; + + /* The code below checks if "port mirroring" N/A MODE4 has been + * enabled during power on bootstrap. + * + * Such N/A mode enabled by mistake can put PHY IC in some + * internal testing mode and disable RGMII transmission. + * + * In this particular case one needs to check STRAP_STS1 + * register's bit 11 (marked as RESERVED). + */ + + bs = phy_read_mmd_indirect(phydev, DP83867_STRAP_STS1, + DP83867_DEVADDR, phydev->addr); + val = phy_read(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL); + if (bs & DP83867_STRAP_STS1_RESERVED) { + val &= ~DP83867_PHYCR_RESERVED_MASK; + phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL, + val); + } + } else if (phy_interface_is_sgmii(phydev)) { phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000)); @@ -315,6 +403,9 @@ static int dp83867_config(struct phy_device *phydev) } } + if (dp83867->port_mirroring != DP83867_PORT_MIRRORING_KEEP) + dp83867_config_port_mirroring(phydev); + genphy_config_aneg(phydev); return 0; diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index ea52343..590f8ce 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -80,10 +80,6 @@ #define RTL_TIMEOUT 100000 -#define ETH_FRAME_LEN 1514 -#define ETH_ALEN 6 -#define ETH_ZLEN 60 - /* PCI Tuning Parameters Threshold is bytes transferred to chip before transmission starts. */ #define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index e0e3a6d..a78f3d2 100644 --- a/drivers/net/rtl8169.c +++ b/drivers/net/rtl8169.c @@ -102,10 +102,6 @@ static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; #define RTL_R16(reg) readw(ioaddr + (reg)) #define RTL_R32(reg) readl(ioaddr + (reg)) -#define ETH_FRAME_LEN MAX_ETH_FRAME_SIZE -#define ETH_ALEN MAC_ADDR_LEN -#define ETH_ZLEN 60 - #define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)(unsigned long)dev->priv, \ (pci_addr_t)(unsigned long)a) #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)(unsigned long)dev->priv, \ diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c index b71c8f8..decce2f 100644 --- a/drivers/net/sandbox.c +++ b/drivers/net/sandbox.c @@ -10,26 +10,11 @@ #include #include #include +#include #include DECLARE_GLOBAL_DATA_PTR; -/** - * struct eth_sandbox_priv - memory for sandbox mock driver - * - * fake_host_hwaddr: MAC address of mocked machine - * fake_host_ipaddr: IP address of mocked machine - * recv_packet_buffer: buffer of the packet returned as received - * recv_packet_length: length of the packet returned as received - */ -struct eth_sandbox_priv { - uchar fake_host_hwaddr[ARP_HLEN]; - struct in_addr fake_host_ipaddr; - uchar *recv_packet_buffer; - int recv_packet_length; -}; - -static bool disabled[8] = {false}; static bool skip_timeout; /* @@ -40,7 +25,16 @@ static bool skip_timeout; */ void sandbox_eth_disable_response(int index, bool disable) { - disabled[index] = disable; + struct udevice *dev; + struct eth_sandbox_priv *priv; + int ret; + + ret = uclass_get_device(UCLASS_ETH, index, &dev); + if (ret) + return; + + priv = dev_get_priv(dev); + priv->disabled = disable; } /* @@ -53,103 +47,304 @@ void sandbox_eth_skip_timeout(void) skip_timeout = true; } -static int sb_eth_start(struct udevice *dev) +/* + * sandbox_eth_arp_req_to_reply() + * + * Check for an arp request to be sent. If so, inject a reply + * + * returns 0 if injected, -EAGAIN if not + */ +int sandbox_eth_arp_req_to_reply(struct udevice *dev, void *packet, + unsigned int len) { struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth = packet; + struct arp_hdr *arp; + struct ethernet_hdr *eth_recv; + struct arp_hdr *arp_recv; - debug("eth_sandbox: Start\n"); + if (ntohs(eth->et_protlen) != PROT_ARP) + return -EAGAIN; - priv->recv_packet_buffer = net_rx_packets[0]; + arp = packet + ETHER_HDR_SIZE; + + if (ntohs(arp->ar_op) != ARPOP_REQUEST) + return -EAGAIN; + + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return 0; + + /* store this as the assumed IP of the fake host */ + priv->fake_host_ipaddr = net_read_ip(&arp->ar_tpa); + + /* Formulate a fake response */ + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; + memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + eth_recv->et_protlen = htons(PROT_ARP); + + arp_recv = (void *)eth_recv + ETHER_HDR_SIZE; + arp_recv->ar_hrd = htons(ARP_ETHER); + arp_recv->ar_pro = htons(PROT_IP); + arp_recv->ar_hln = ARP_HLEN; + arp_recv->ar_pln = ARP_PLEN; + arp_recv->ar_op = htons(ARPOP_REPLY); + memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr, ARP_HLEN); + net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr); + memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN); + net_copy_ip(&arp_recv->ar_tpa, &arp->ar_spa); + + priv->recv_packet_length[priv->recv_packets] = + ETHER_HDR_SIZE + ARP_HDR_SIZE; + ++priv->recv_packets; return 0; } -static int sb_eth_send(struct udevice *dev, void *packet, int length) +/* + * sandbox_eth_ping_req_to_reply() + * + * Check for a ping request to be sent. If so, inject a reply + * + * returns 0 if injected, -EAGAIN if not + */ +int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet, + unsigned int len) { struct eth_sandbox_priv *priv = dev_get_priv(dev); struct ethernet_hdr *eth = packet; + struct ip_udp_hdr *ip; + struct icmp_hdr *icmp; + struct ethernet_hdr *eth_recv; + struct ip_udp_hdr *ipr; + struct icmp_hdr *icmpr; - debug("eth_sandbox: Send packet %d\n", length); + if (ntohs(eth->et_protlen) != PROT_IP) + return -EAGAIN; + + ip = packet + ETHER_HDR_SIZE; + + if (ip->ip_p != IPPROTO_ICMP) + return -EAGAIN; + + icmp = (struct icmp_hdr *)&ip->udp_src; + + if (icmp->type != ICMP_ECHO_REQUEST) + return -EAGAIN; + + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return 0; + + /* reply to the ping */ + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; + memcpy(eth_recv, packet, len); + ipr = (void *)eth_recv + ETHER_HDR_SIZE; + icmpr = (struct icmp_hdr *)&ipr->udp_src; + memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + ipr->ip_sum = 0; + ipr->ip_off = 0; + net_copy_ip((void *)&ipr->ip_dst, &ip->ip_src); + net_write_ip((void *)&ipr->ip_src, priv->fake_host_ipaddr); + ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE); + + icmpr->type = ICMP_ECHO_REPLY; + icmpr->checksum = 0; + icmpr->checksum = compute_ip_checksum(icmpr, ICMP_HDR_SIZE); + + priv->recv_packet_length[priv->recv_packets] = len; + ++priv->recv_packets; + + return 0; +} + +/* + * sandbox_eth_recv_arp_req() + * + * Inject an ARP request for this target + * + * returns 0 if injected, -EOVERFLOW if not + */ +int sandbox_eth_recv_arp_req(struct udevice *dev) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth_recv; + struct arp_hdr *arp_recv; + + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return -EOVERFLOW; + + /* Formulate a fake request */ + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; + memcpy(eth_recv->et_dest, net_bcast_ethaddr, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + eth_recv->et_protlen = htons(PROT_ARP); + + arp_recv = (void *)eth_recv + ETHER_HDR_SIZE; + arp_recv->ar_hrd = htons(ARP_ETHER); + arp_recv->ar_pro = htons(PROT_IP); + arp_recv->ar_hln = ARP_HLEN; + arp_recv->ar_pln = ARP_PLEN; + arp_recv->ar_op = htons(ARPOP_REQUEST); + memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr, ARP_HLEN); + net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr); + memcpy(&arp_recv->ar_tha, net_null_ethaddr, ARP_HLEN); + net_write_ip(&arp_recv->ar_tpa, net_ip); + + priv->recv_packet_length[priv->recv_packets] = + ETHER_HDR_SIZE + ARP_HDR_SIZE; + ++priv->recv_packets; + + return 0; +} + +/* + * sandbox_eth_recv_ping_req() + * + * Inject a ping request for this target + * + * returns 0 if injected, -EOVERFLOW if not + */ +int sandbox_eth_recv_ping_req(struct udevice *dev) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth_recv; + struct ip_udp_hdr *ipr; + struct icmp_hdr *icmpr; + + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return -EOVERFLOW; + + /* Formulate a fake ping */ + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; + + memcpy(eth_recv->et_dest, net_ethaddr, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + eth_recv->et_protlen = htons(PROT_IP); + + ipr = (void *)eth_recv + ETHER_HDR_SIZE; + ipr->ip_hl_v = 0x45; + ipr->ip_len = htons(IP_ICMP_HDR_SIZE); + ipr->ip_off = htons(IP_FLAGS_DFRAG); + ipr->ip_p = IPPROTO_ICMP; + ipr->ip_sum = 0; + net_write_ip(&ipr->ip_src, priv->fake_host_ipaddr); + net_write_ip(&ipr->ip_dst, net_ip); + ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE); + + icmpr = (struct icmp_hdr *)&ipr->udp_src; + + icmpr->type = ICMP_ECHO_REQUEST; + icmpr->code = 0; + icmpr->checksum = 0; + icmpr->un.echo.id = 0; + icmpr->un.echo.sequence = htons(1); + icmpr->checksum = compute_ip_checksum(icmpr, ICMP_HDR_SIZE); + + priv->recv_packet_length[priv->recv_packets] = + ETHER_HDR_SIZE + IP_ICMP_HDR_SIZE; + ++priv->recv_packets; + + return 0; +} - if (dev->seq >= 0 && dev->seq < ARRAY_SIZE(disabled) && - disabled[dev->seq]) +/* + * sb_default_handler() + * + * perform typical responses to simple ping + * + * dev - device pointer + * pkt - "sent" packet buffer + * len - length of packet + */ +static int sb_default_handler(struct udevice *dev, void *packet, + unsigned int len) +{ + if (!sandbox_eth_arp_req_to_reply(dev, packet, len)) + return 0; + if (!sandbox_eth_ping_req_to_reply(dev, packet, len)) return 0; - if (ntohs(eth->et_protlen) == PROT_ARP) { - struct arp_hdr *arp = packet + ETHER_HDR_SIZE; - - if (ntohs(arp->ar_op) == ARPOP_REQUEST) { - struct ethernet_hdr *eth_recv; - struct arp_hdr *arp_recv; - - /* store this as the assumed IP of the fake host */ - priv->fake_host_ipaddr = net_read_ip(&arp->ar_tpa); - /* Formulate a fake response */ - eth_recv = (void *)priv->recv_packet_buffer; - memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN); - memcpy(eth_recv->et_src, priv->fake_host_hwaddr, - ARP_HLEN); - eth_recv->et_protlen = htons(PROT_ARP); - - arp_recv = (void *)priv->recv_packet_buffer + - ETHER_HDR_SIZE; - arp_recv->ar_hrd = htons(ARP_ETHER); - arp_recv->ar_pro = htons(PROT_IP); - arp_recv->ar_hln = ARP_HLEN; - arp_recv->ar_pln = ARP_PLEN; - arp_recv->ar_op = htons(ARPOP_REPLY); - memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr, - ARP_HLEN); - net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr); - memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN); - net_copy_ip(&arp_recv->ar_tpa, &arp->ar_spa); - - priv->recv_packet_length = ETHER_HDR_SIZE + - ARP_HDR_SIZE; - } - } else if (ntohs(eth->et_protlen) == PROT_IP) { - struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE; - - if (ip->ip_p == IPPROTO_ICMP) { - struct icmp_hdr *icmp = (struct icmp_hdr *)&ip->udp_src; - - if (icmp->type == ICMP_ECHO_REQUEST) { - struct ethernet_hdr *eth_recv; - struct ip_udp_hdr *ipr; - struct icmp_hdr *icmpr; - - /* reply to the ping */ - memcpy(priv->recv_packet_buffer, packet, - length); - eth_recv = (void *)priv->recv_packet_buffer; - ipr = (void *)priv->recv_packet_buffer + - ETHER_HDR_SIZE; - icmpr = (struct icmp_hdr *)&ipr->udp_src; - memcpy(eth_recv->et_dest, eth->et_src, - ARP_HLEN); - memcpy(eth_recv->et_src, priv->fake_host_hwaddr, - ARP_HLEN); - ipr->ip_sum = 0; - ipr->ip_off = 0; - net_copy_ip((void *)&ipr->ip_dst, &ip->ip_src); - net_write_ip((void *)&ipr->ip_src, - priv->fake_host_ipaddr); - ipr->ip_sum = compute_ip_checksum(ipr, - IP_HDR_SIZE); - - icmpr->type = ICMP_ECHO_REPLY; - icmpr->checksum = 0; - icmpr->checksum = compute_ip_checksum(icmpr, - ICMP_HDR_SIZE); - - priv->recv_packet_length = length; - } - } + return 0; +} + +/* + * sandbox_eth_set_tx_handler() + * + * Set a custom response to a packet being sent through the sandbox eth test + * driver + * + * index - interface to set the handler for + * handler - The func ptr to call on send. If NULL, set to default handler + */ +void sandbox_eth_set_tx_handler(int index, sandbox_eth_tx_hand_f *handler) +{ + struct udevice *dev; + struct eth_sandbox_priv *priv; + int ret; + + ret = uclass_get_device(UCLASS_ETH, index, &dev); + if (ret) + return; + + priv = dev_get_priv(dev); + if (handler) + priv->tx_handler = handler; + else + priv->tx_handler = sb_default_handler; +} + +/* + * Set priv ptr + * + * priv - priv void ptr to store in the device + */ +void sandbox_eth_set_priv(int index, void *priv) +{ + struct udevice *dev; + struct eth_sandbox_priv *dev_priv; + int ret; + + ret = uclass_get_device(UCLASS_ETH, index, &dev); + if (ret) + return; + + dev_priv = dev_get_priv(dev); + + dev_priv->priv = priv; +} + +static int sb_eth_start(struct udevice *dev) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + + debug("eth_sandbox: Start\n"); + + priv->recv_packets = 0; + for (int i = 0; i < PKTBUFSRX; i++) { + priv->recv_packet_buffer[i] = net_rx_packets[i]; + priv->recv_packet_length[i] = 0; } return 0; } +static int sb_eth_send(struct udevice *dev, void *packet, int length) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + + debug("eth_sandbox: Send packet %d\n", length); + + if (priv->disabled) + return 0; + + return priv->tx_handler(dev, packet, length); +} + static int sb_eth_recv(struct udevice *dev, int flags, uchar **packetp) { struct eth_sandbox_priv *priv = dev_get_priv(dev); @@ -159,18 +354,37 @@ static int sb_eth_recv(struct udevice *dev, int flags, uchar **packetp) skip_timeout = false; } - if (priv->recv_packet_length) { - int lcl_recv_packet_length = priv->recv_packet_length; + if (priv->recv_packets) { + int lcl_recv_packet_length = priv->recv_packet_length[0]; - debug("eth_sandbox: received packet %d\n", - priv->recv_packet_length); - priv->recv_packet_length = 0; - *packetp = priv->recv_packet_buffer; + debug("eth_sandbox: received packet[%d], %d waiting\n", + lcl_recv_packet_length, priv->recv_packets - 1); + *packetp = priv->recv_packet_buffer[0]; return lcl_recv_packet_length; } return 0; } +static int sb_eth_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + int i; + + if (!priv->recv_packets) + return 0; + + --priv->recv_packets; + for (i = 0; i < priv->recv_packets; i++) { + priv->recv_packet_length[i] = priv->recv_packet_length[i + 1]; + memcpy(priv->recv_packet_buffer[i], + priv->recv_packet_buffer[i + 1], + priv->recv_packet_length[i + 1]); + } + priv->recv_packet_length[priv->recv_packets] = 0; + + return 0; +} + static void sb_eth_stop(struct udevice *dev) { debug("eth_sandbox: Stop\n"); @@ -189,6 +403,7 @@ static const struct eth_ops sb_eth_ops = { .start = sb_eth_start, .send = sb_eth_send, .recv = sb_eth_recv, + .free_pkt = sb_eth_free_pkt, .stop = sb_eth_stop, .write_hwaddr = sb_eth_write_hwaddr, }; @@ -212,6 +427,8 @@ static int sb_eth_ofdata_to_platdata(struct udevice *dev) return -EINVAL; } memcpy(priv->fake_host_hwaddr, mac, ARP_HLEN); + priv->disabled = false; + priv->tx_handler = sb_default_handler; return 0; } diff --git a/drivers/usb/eth/lan7x.h b/drivers/usb/eth/lan7x.h index d1b1047..7af610b 100644 --- a/drivers/usb/eth/lan7x.h +++ b/drivers/usb/eth/lan7x.h @@ -94,7 +94,7 @@ #define LAN7X_MAC_RX_MAX_SIZE(mtu) \ ((mtu) << 16) /* Max frame size */ #define LAN7X_MAC_RX_MAX_SIZE_DEFAULT \ - LAN7X_MAC_RX_MAX_SIZE(ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */) + LAN7X_MAC_RX_MAX_SIZE(PKTSIZE_ALIGN + 4 /* VLAN */ + 4 /* CRC */) /* Timeouts */ #define USB_CTRL_SET_TIMEOUT_MS 5000 diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 8ab9b9f..90ef1f0 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -71,11 +71,6 @@ unsigned packet_received, packet_sent; * RNDIS specs are ambiguous and appear to be incomplete, and are also * needlessly complex. They borrow more from CDC ACM than CDC ECM. */ -#define ETH_ALEN 6 /* Octets in one ethernet addr */ -#define ETH_HLEN 14 /* Total octets in header. */ -#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ -#define ETH_DATA_LEN 1500 /* Max. octets in payload */ -#define ETH_FRAME_LEN PKTSIZE_ALIGN /* Max. octets in frame sans FCS */ #define DRIVER_DESC "Ethernet Gadget" /* Based on linux 2.6.27 version */ @@ -529,7 +524,7 @@ static const struct usb_cdc_ether_desc ether_desc = { /* this descriptor actually adds value, surprise! */ .iMACAddress = STRING_ETHADDR, .bmEthernetStatistics = __constant_cpu_to_le32(0), /* no statistics */ - .wMaxSegmentSize = __constant_cpu_to_le16(ETH_FRAME_LEN), + .wMaxSegmentSize = __constant_cpu_to_le16(PKTSIZE_ALIGN), .wNumberMCFilters = __constant_cpu_to_le16(0), .bNumberPowerFilters = 0, }; @@ -1575,7 +1570,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req) req->length -= length; req->actual -= length; } - if (req->actual < ETH_HLEN || ETH_FRAME_LEN < req->actual) { + if (req->actual < ETH_HLEN || PKTSIZE_ALIGN < req->actual) { length_err: dev->stats.rx_errors++; dev->stats.rx_length_errors++; diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index d47e29e..eec639f 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -35,12 +35,6 @@ #include "rndis.h" -#define ETH_ALEN 6 /* Octets in one ethernet addr */ -#define ETH_HLEN 14 /* Total octets in header. */ -#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ -#define ETH_DATA_LEN 1500 /* Max. octets in payload */ -#define ETH_FRAME_LEN PKTSIZE_ALIGN /* Max. octets in frame sans FCS */ - /* * The driver for your USB chip needs to support ep0 OUT to work with * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional). diff --git a/include/dt-bindings/net/ti-dp83867.h b/include/dt-bindings/net/ti-dp83867.h index b8e5df6..85d08f6 100644 --- a/include/dt-bindings/net/ti-dp83867.h +++ b/include/dt-bindings/net/ti-dp83867.h @@ -31,4 +31,19 @@ #define DP83867_RGMIIDCTL_3_75_NS 0xe #define DP83867_RGMIIDCTL_4_00_NS 0xf +/* IO_MUX_CFG - Clock output selection */ +#define DP83867_CLK_O_SEL_CHN_A_RCLK 0x0 +#define DP83867_CLK_O_SEL_CHN_B_RCLK 0x1 +#define DP83867_CLK_O_SEL_CHN_C_RCLK 0x2 +#define DP83867_CLK_O_SEL_CHN_D_RCLK 0x3 +#define DP83867_CLK_O_SEL_CHN_A_RCLK_DIV5 0x4 +#define DP83867_CLK_O_SEL_CHN_B_RCLK_DIV5 0x5 +#define DP83867_CLK_O_SEL_CHN_C_RCLK_DIV5 0x6 +#define DP83867_CLK_O_SEL_CHN_D_RCLK_DIV5 0x7 +#define DP83867_CLK_O_SEL_CHN_A_TCLK 0x8 +#define DP83867_CLK_O_SEL_CHN_B_TCLK 0x9 +#define DP83867_CLK_O_SEL_CHN_C_TCLK 0xA +#define DP83867_CLK_O_SEL_CHN_D_TCLK 0xB +#define DP83867_CLK_O_SEL_REF_CLK 0xC + #endif diff --git a/include/fsl-mc/ldpaa_wriop.h b/include/fsl-mc/ldpaa_wriop.h index 07e5130..b55c39c 100644 --- a/include/fsl-mc/ldpaa_wriop.h +++ b/include/fsl-mc/ldpaa_wriop.h @@ -6,7 +6,11 @@ #ifndef __LDPAA_WRIOP_H #define __LDPAA_WRIOP_H - #include +#include + +#define DEFAULT_WRIOP_MDIO1_NAME "FSL_MDIO0" +#define DEFAULT_WRIOP_MDIO2_NAME "FSL_MDIO1" +#define WRIOP_MAX_PHY_NUM 2 enum wriop_port { WRIOP1_DPMAC1 = 1, @@ -40,34 +44,30 @@ struct wriop_dpmac_info { u8 enabled; u8 id; u8 board_mux; - int phy_addr; - void *phy_regs; + int phy_addr[WRIOP_MAX_PHY_NUM]; phy_interface_t enet_if; - struct phy_device *phydev; + struct phy_device *phydev[WRIOP_MAX_PHY_NUM]; struct mii_dev *bus; }; extern struct wriop_dpmac_info dpmac_info[NUM_WRIOP_PORTS]; -#define DEFAULT_WRIOP_MDIO1_NAME "FSL_MDIO0" -#define DEFAULT_WRIOP_MDIO2_NAME "FSL_MDIO1" - -void wriop_init_dpmac(int, int, int); -void wriop_disable_dpmac(int); -void wriop_enable_dpmac(int); -u8 wriop_is_enabled_dpmac(int dpmac_id); -void wriop_set_mdio(int, struct mii_dev *); -struct mii_dev *wriop_get_mdio(int); -void wriop_set_phy_address(int, int); -int wriop_get_phy_address(int); -void wriop_set_phy_dev(int, struct phy_device *); -struct phy_device *wriop_get_phy_dev(int); -phy_interface_t wriop_get_enet_if(int); +void wriop_init_dpmac(int sd, int dpmac_id, int lane_prtcl); +void wriop_init_dpmac_enet_if(int dpmac_id, phy_interface_t enet_if); +int wriop_disable_dpmac(int dpmac_id); +int wriop_enable_dpmac(int dpmac_id); +int wriop_is_enabled_dpmac(int dpmac_id); +int wriop_set_mdio(int dpmac_id, struct mii_dev *bus); +struct mii_dev *wriop_get_mdio(int dpmac_id); +int wriop_set_phy_address(int dpmac_id, int phy_num, int address); +int wriop_get_phy_address(int dpmac_id, int phy_num); +int wriop_set_phy_dev(int dpmac_id, int phy_num, struct phy_device *phydev); +struct phy_device *wriop_get_phy_dev(int dpmac_id, int phy_num); +phy_interface_t wriop_get_enet_if(int dpmac_id); -void wriop_dpmac_disable(int); -void wriop_dpmac_enable(int); -phy_interface_t wriop_dpmac_enet_if(int, int); -void wriop_init_dpmac_qsgmii(int, int); +void wriop_dpmac_disable(int dpmac_id); +void wriop_dpmac_enable(int dpmac_id); +phy_interface_t wriop_dpmac_enet_if(int dpmac_id, int lane_prtcl); +void wriop_init_dpmac_qsgmii(int sd, int lane_prtcl); void wriop_init_rgmii(void); -void wriop_init_dpmac_enet_if(int , phy_interface_t); #endif /* __LDPAA_WRIOP_H */ diff --git a/include/linux/compat.h b/include/linux/compat.h index 6e3feb6..d0f51ba 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -43,6 +43,25 @@ extern struct p_current *current; #define dev_warn(dev, fmt, args...) \ printf(fmt, ##args) +#define netdev_emerg(dev, fmt, args...) \ + printf(fmt, ##args) +#define netdev_alert(dev, fmt, args...) \ + printf(fmt, ##args) +#define netdev_crit(dev, fmt, args...) \ + printf(fmt, ##args) +#define netdev_err(dev, fmt, args...) \ + printf(fmt, ##args) +#define netdev_warn(dev, fmt, args...) \ + printf(fmt, ##args) +#define netdev_notice(dev, fmt, args...) \ + printf(fmt, ##args) +#define netdev_info(dev, fmt, args...) \ + printf(fmt, ##args) +#define netdev_dbg(dev, fmt, args...) \ + debug(fmt, ##args) +#define netdev_vdbg(dev, fmt, args...) \ + debug(fmt, ##args) + #define GFP_ATOMIC ((gfp_t) 0) #define GFP_KERNEL ((gfp_t) 0) #define GFP_NOFS ((gfp_t) 0) diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h new file mode 100644 index 0000000..0d62aef --- /dev/null +++ b/include/linux/if_ether.h @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Global definitions for the Ethernet IEEE 802.3 interface. + * + * Version: @(#)if_ether.h 1.0.1a 02/08/94 + * + * Author: Fred N. van Kempen, + * Donald Becker, + * Alan Cox, + * Steve Whitehouse, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _UAPI_LINUX_IF_ETHER_H +#define _UAPI_LINUX_IF_ETHER_H + +#include + +/* + * IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble + * and FCS/CRC (frame check sequence). + */ + +#define ETH_ALEN 6 /* Octets in one ethernet addr */ +#define ETH_TLEN 2 /* Octets in ethernet type field */ +#define ETH_HLEN 14 /* Total octets in header. */ +#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ +#define ETH_DATA_LEN 1500 /* Max. octets in payload */ +#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ +#define ETH_FCS_LEN 4 /* Octets in the FCS */ + +#define ETH_MIN_MTU 68 /* Min IPv4 MTU per RFC791 */ +#define ETH_MAX_MTU 0xFFFFU /* 65535, same as IP_MAX_MTU */ + +/* + * These are the defined Ethernet Protocol ID's. + */ + +#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */ +#define ETH_P_PUP 0x0200 /* Xerox PUP packet */ +#define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */ +#define ETH_P_TSN 0x22F0 /* TSN (IEEE 1722) packet */ +#define ETH_P_ERSPAN2 0x22EB /* ERSPAN version 2 (type III) */ +#define ETH_P_IP 0x0800 /* Internet Protocol packet */ +#define ETH_P_X25 0x0805 /* CCITT X.25 */ +#define ETH_P_ARP 0x0806 /* Address Resolution packet */ +#define ETH_P_BPQ 0x08FF /* G8BPQ AX.25 Ethernet Packet */ + /* [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_IEEEPUP 0x0a00 /* Xerox IEEE802.3 PUP packet */ +#define ETH_P_IEEEPUPAT 0x0a01 /* Xerox IEEE802.3 PUP Addr Trans packet */ +#define ETH_P_BATMAN 0x4305 /* B.A.T.M.A.N.-Advanced packet */ + /* [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_DEC 0x6000 /* DEC Assigned proto */ +#define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */ +#define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */ +#define ETH_P_DNA_RT 0x6003 /* DEC DNA Routing */ +#define ETH_P_LAT 0x6004 /* DEC LAT */ +#define ETH_P_DIAG 0x6005 /* DEC Diagnostics */ +#define ETH_P_CUST 0x6006 /* DEC Customer use */ +#define ETH_P_SCA 0x6007 /* DEC Systems Comms Arch */ +#define ETH_P_TEB 0x6558 /* Trans Ether Bridging */ +#define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */ +#define ETH_P_ATALK 0x809B /* Appletalk DDP */ +#define ETH_P_AARP 0x80F3 /* Appletalk AARP */ +#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ +#define ETH_P_ERSPAN 0x88BE /* ERSPAN type II */ +#define ETH_P_IPX 0x8137 /* IPX over DIX */ +#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ +#define ETH_P_PAUSE 0x8808 /* IEEE Pause frames. See 802.3 31B */ +#define ETH_P_SLOW 0x8809 /* Slow Protocol. See 802.3ad 43B */ +#define ETH_P_WCCP 0x883E /* Web-cache coordination */ + /* protocol defined in */ + /* draft-wilson-wrec-wccp-v2-00.txt */ +#define ETH_P_MPLS_UC 0x8847 /* MPLS Unicast traffic */ +#define ETH_P_MPLS_MC 0x8848 /* MPLS Multicast traffic */ +#define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */ +#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ +#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */ +#define ETH_P_LINK_CTL 0x886c /* HPNA, wlan link local tunnel */ +#define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport over Ethernet */ +#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ +#define ETH_P_8021AD 0x88A8 /* 802.1ad Service VLAN */ +#define ETH_P_802_EX1 0x88B5 /* 802.1 Local Experimental 1. */ +#define ETH_P_PREAUTH 0x88C7 /* 802.11 Preauthentication */ +#define ETH_P_TIPC 0x88CA /* TIPC */ +#define ETH_P_MACSEC 0x88E5 /* 802.1ae MACsec */ +#define ETH_P_8021AH 0x88E7 /* 802.1ah Backbone Service Tag */ +#define ETH_P_MVRP 0x88F5 /* 802.1Q MVRP */ +#define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */ +#define ETH_P_NCSI 0x88F8 /* NCSI protocol */ +#define ETH_P_PRP 0x88FB /* IEC 62439-3 PRP/HSRv0 */ +#define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */ +#define ETH_P_IBOE 0x8915 /* Infiniband over Ethernet */ +#define ETH_P_TDLS 0x890D /* TDLS */ +#define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */ +#define ETH_P_80221 0x8917 /* IEEE 802.21 Media Independent */ + /* Handover Protocol */ +#define ETH_P_HSR 0x892F /* IEC 62439-3 HSRv1 */ +#define ETH_P_NSH 0x894F /* Network Service Header */ +#define ETH_P_LOOPBACK 0x9000 /* Ethernet loopback packet, per IEEE 802.3 */ +#define ETH_P_QINQ1 0x9100 /* deprecated QinQ VLAN */ + /* [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_QINQ2 0x9200 /* deprecated QinQ VLAN */ + /* [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_QINQ3 0x9300 /* deprecated QinQ VLAN] */ + /* [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_EDSA 0xDADA /* Ethertype DSA */ + /* [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_IFE 0xED3E /* ForCES inter-FE LFB type */ +#define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv */ + /* [ NOT AN OFFICIALLY REGISTERED ID ] */ + +#define ETH_P_802_3_MIN 0x0600 /* If the value in the ethernet type is less */ + /* than this value then the frame is Ethernet */ + /* II. Else it is 802.3 */ + +/* + * Non DIX types. Won't clash for 1500 types. + */ + +#define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */ +#define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */ +#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */ +#define ETH_P_802_2 0x0004 /* 802.2 frames */ +#define ETH_P_SNAP 0x0005 /* Internal only */ +#define ETH_P_DDCMP 0x0006 /* DEC DDCMP: Internal only */ +#define ETH_P_WAN_PPP 0x0007 /* Dummy type for WAN PPP frames*/ +#define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */ +#define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudo type */ +#define ETH_P_CAN 0x000C /* CAN: Controller Area Network */ +#define ETH_P_CANFD 0x000D /* CANFD: CAN flexible data rate*/ +#define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/ +#define ETH_P_TR_802_2 0x0011 /* 802.2 frames */ +#define ETH_P_MOBITEX 0x0015 /* Mobitex (kaz@cafe.net) */ +#define ETH_P_CONTROL 0x0016 /* Card specific control frames */ +#define ETH_P_IRDA 0x0017 /* Linux-IrDA */ +#define ETH_P_ECONET 0x0018 /* Acorn Econet */ +#define ETH_P_HDLC 0x0019 /* HDLC frames */ +#define ETH_P_ARCNET 0x001A /* 1A for ArcNet :-) */ +#define ETH_P_DSA 0x001B /* Distributed Switch Arch */ +#define ETH_P_TRAILER 0x001C /* Trailer switch tagging */ +#define ETH_P_PHONET 0x00F5 /* Nokia Phonet frames */ +#define ETH_P_IEEE802154 0x00F6 /* IEEE802.15.4 frame */ +#define ETH_P_CAIF 0x00F7 /* ST-Ericsson CAIF protocol */ +#define ETH_P_XDSA 0x00F8 /* Multiplexed DSA protocol */ +#define ETH_P_MAP 0x00F9 /* Qualcomm multiplexing and */ + /* aggregation protocol */ + +/* The following macros come from Linux kernel include/linux/if_vlan.h */ + +#define VLAN_HLEN 4 /* The additional bytes required by VLAN */ + /* (in addition to the Ethernet header) */ +#define VLAN_ETH_HLEN 18 /* Total octets in header. */ +#define VLAN_ETH_ZLEN 64 /* Min. octets in frame sans FCS */ + +/* + * According to 802.3ac, the packet can be 4 bytes longer. --Klika Jan + */ +#define VLAN_ETH_DATA_LEN 1500 /* Max. octets in payload */ +#define VLAN_ETH_FRAME_LEN 1518 /* Max. octets in frame sans FCS */ + +#define VLAN_PRIO_MASK 0xe000 /* Priority Code Point */ +#define VLAN_PRIO_SHIFT 13 +#define VLAN_CFI_MASK 0x1000 /* Canonical Format Indicator */ +#define VLAN_TAG_PRESENT VLAN_CFI_MASK +#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */ +#define VLAN_N_VID 4096 + +#endif /* _UAPI_LINUX_IF_ETHER_H */ diff --git a/include/linux/mdio.h b/include/linux/mdio.h index ea20608..6e821d9 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * linux/mdio.h: definitions for MDIO (clause 45) transceivers * Copyright 2006-2009 Solarflare Communications Inc. @@ -42,7 +43,11 @@ #define MDIO_PKGID2 15 #define MDIO_AN_ADVERTISE 16 /* AN advertising (base page) */ #define MDIO_AN_LPA 19 /* AN LP abilities (base page) */ +#define MDIO_PCS_EEE_ABLE 20 /* EEE Capability register */ +#define MDIO_PCS_EEE_WK_ERR 22 /* EEE wake error counter */ #define MDIO_PHYXS_LNSTAT 24 /* PHY XGXS lane state */ +#define MDIO_AN_EEE_ADV 60 /* EEE advertisement */ +#define MDIO_AN_EEE_LPABLE 61 /* EEE link partner ability */ /* Media-dependent registers. */ #define MDIO_PMA_10GBT_SWAPPOL 130 /* 10GBASE-T pair swap & polarity */ @@ -55,7 +60,6 @@ #define MDIO_PCS_10GBRT_STAT2 33 /* 10GBASE-R/-T PCS status 2 */ #define MDIO_AN_10GBT_CTRL 32 /* 10GBASE-T auto-negotiation control */ #define MDIO_AN_10GBT_STAT 33 /* 10GBASE-T auto-negotiation status */ -#define MDIO_AN_EEE_ADV 60 /* EEE advertisement */ /* LASI (Link Alarm Status Interrupt) registers, defined by XENPAK MSA. */ #define MDIO_PMA_LASI_RXCTRL 0x9000 /* RX_ALARM control */ @@ -81,6 +85,7 @@ #define MDIO_AN_CTRL1_RESTART BMCR_ANRESTART #define MDIO_AN_CTRL1_ENABLE BMCR_ANENABLE #define MDIO_AN_CTRL1_XNP 0x2000 /* Enable extended next page */ +#define MDIO_PCS_CTRL1_CLKSTOP_EN 0x400 /* Stop the clock during LPI */ /* 10 Gb/s */ #define MDIO_CTRL1_SPEED10G (MDIO_CTRL1_SPEEDSELEXT | 0x00) @@ -245,9 +250,25 @@ #define MDIO_AN_10GBT_STAT_MS 0x4000 /* Master/slave config */ #define MDIO_AN_10GBT_STAT_MSFLT 0x8000 /* Master/slave config fault */ -/* AN EEE Advertisement register. */ -#define MDIO_AN_EEE_ADV_100TX 0x0002 /* Advertise 100TX EEE cap */ -#define MDIO_AN_EEE_ADV_1000T 0x0004 /* Advertise 1000T EEE cap */ +/* EEE Supported/Advertisement/LP Advertisement registers. + * + * EEE capability Register (3.20), Advertisement (7.60) and + * Link partner ability (7.61) registers have and can use the same identical + * bit masks. + */ +#define MDIO_AN_EEE_ADV_100TX 0x0002 /* Advertise 100TX EEE cap */ +#define MDIO_AN_EEE_ADV_1000T 0x0004 /* Advertise 1000T EEE cap */ +/* Note: the two defines above can be potentially used by the user-land + * and cannot remove them now. + * So, we define the new generic MDIO_EEE_100TX and MDIO_EEE_1000T macros + * using the previous ones (that can be considered obsolete). + */ +#define MDIO_EEE_100TX MDIO_AN_EEE_ADV_100TX /* 100TX EEE cap */ +#define MDIO_EEE_1000T MDIO_AN_EEE_ADV_1000T /* 1000T EEE cap */ +#define MDIO_EEE_10GT 0x0008 /* 10GT EEE cap */ +#define MDIO_EEE_1000KX 0x0010 /* 1000KX EEE cap */ +#define MDIO_EEE_10GKX4 0x0020 /* 10G KX4 EEE cap */ +#define MDIO_EEE_10GKR 0x0040 /* 10G KR EEE cap */ /* LASI RX_ALARM control/status registers. */ #define MDIO_PMA_LASI_RX_PHYXSLFLT 0x0001 /* PHY XS RX local fault */ @@ -281,4 +302,9 @@ #define MDIO_DEVAD_NONE (-1) #define MDIO_EMULATE_C22 4 +static inline __u16 mdio_phy_id_c45(int prtad, int devad) +{ + return MDIO_PHY_ID_C45 | (prtad << 5) | devad; +} + #endif /* __LINUX_MDIO_H__ */ diff --git a/include/linux/mii.h b/include/linux/mii.h index 19afb74..21db032 100644 --- a/include/linux/mii.h +++ b/include/linux/mii.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * linux/mii.h: definitions for MII-compatible transceivers * Originally drivers/net/sunhme.h. @@ -9,53 +10,55 @@ #define __LINUX_MII_H__ /* Generic MII registers. */ - -#define MII_BMCR 0x00 /* Basic mode control register */ -#define MII_BMSR 0x01 /* Basic mode status register */ -#define MII_PHYSID1 0x02 /* PHYS ID 1 */ -#define MII_PHYSID2 0x03 /* PHYS ID 2 */ -#define MII_ADVERTISE 0x04 /* Advertisement control reg */ -#define MII_LPA 0x05 /* Link partner ability reg */ -#define MII_EXPANSION 0x06 /* Expansion register */ -#define MII_CTRL1000 0x09 /* 1000BASE-T control */ -#define MII_STAT1000 0x0a /* 1000BASE-T status */ -#define MII_ESTATUS 0x0f /* Extended Status */ -#define MII_DCOUNTER 0x12 /* Disconnect counter */ -#define MII_FCSCOUNTER 0x13 /* False carrier counter */ -#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */ -#define MII_RERRCOUNTER 0x15 /* Receive error counter */ -#define MII_SREVISION 0x16 /* Silicon revision */ -#define MII_RESV1 0x17 /* Reserved... */ -#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */ -#define MII_PHYADDR 0x19 /* PHY address */ -#define MII_RESV2 0x1a /* Reserved... */ -#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */ -#define MII_NCONFIG 0x1c /* Network interface config */ +#define MII_BMCR 0x00 /* Basic mode control register */ +#define MII_BMSR 0x01 /* Basic mode status register */ +#define MII_PHYSID1 0x02 /* PHYS ID 1 */ +#define MII_PHYSID2 0x03 /* PHYS ID 2 */ +#define MII_ADVERTISE 0x04 /* Advertisement control reg */ +#define MII_LPA 0x05 /* Link partner ability reg */ +#define MII_EXPANSION 0x06 /* Expansion register */ +#define MII_CTRL1000 0x09 /* 1000BASE-T control */ +#define MII_STAT1000 0x0a /* 1000BASE-T status */ +#define MII_MMD_CTRL 0x0d /* MMD Access Control Register */ +#define MII_MMD_DATA 0x0e /* MMD Access Data Register */ +#define MII_ESTATUS 0x0f /* Extended Status */ +#define MII_DCOUNTER 0x12 /* Disconnect counter */ +#define MII_FCSCOUNTER 0x13 /* False carrier counter */ +#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */ +#define MII_RERRCOUNTER 0x15 /* Receive error counter */ +#define MII_SREVISION 0x16 /* Silicon revision */ +#define MII_RESV1 0x17 /* Reserved... */ +#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */ +#define MII_PHYADDR 0x19 /* PHY address */ +#define MII_RESV2 0x1a /* Reserved... */ +#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */ +#define MII_NCONFIG 0x1c /* Network interface config */ /* Basic mode control register. */ -#define BMCR_RESV 0x003f /* Unused... */ -#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */ -#define BMCR_CTST 0x0080 /* Collision test */ -#define BMCR_FULLDPLX 0x0100 /* Full duplex */ +#define BMCR_RESV 0x003f /* Unused... */ +#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */ +#define BMCR_CTST 0x0080 /* Collision test */ +#define BMCR_FULLDPLX 0x0100 /* Full duplex */ #define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */ -#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */ -#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */ +#define BMCR_ISOLATE 0x0400 /* Isolate data paths from MII */ +#define BMCR_PDOWN 0x0800 /* Enable low power state */ #define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */ -#define BMCR_SPEED100 0x2000 /* Select 100Mbps */ -#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */ -#define BMCR_RESET 0x8000 /* Reset the DP83840 */ +#define BMCR_SPEED100 0x2000 /* Select 100Mbps */ +#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */ +#define BMCR_RESET 0x8000 /* Reset to default state */ +#define BMCR_SPEED10 0x0000 /* Select 10Mbps */ /* Basic mode status register. */ -#define BMSR_ERCAP 0x0001 /* Ext-reg capability */ -#define BMSR_JCD 0x0002 /* Jabber detected */ -#define BMSR_LSTATUS 0x0004 /* Link status */ +#define BMSR_ERCAP 0x0001 /* Ext-reg capability */ +#define BMSR_JCD 0x0002 /* Jabber detected */ +#define BMSR_LSTATUS 0x0004 /* Link status */ #define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */ #define BMSR_RFAULT 0x0010 /* Remote fault detected */ #define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */ -#define BMSR_RESV 0x00c0 /* Unused... */ -#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */ -#define BMSR_100HALF2 0x0200 /* Can do 100BASE-T2 HDX */ -#define BMSR_100FULL2 0x0400 /* Can do 100BASE-T2 FDX */ +#define BMSR_RESV 0x00c0 /* Unused... */ +#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */ +#define BMSR_100HALF2 0x0200 /* Can do 100BASE-T2 HDX */ +#define BMSR_100FULL2 0x0400 /* Can do 100BASE-T2 FDX */ #define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */ #define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */ #define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */ @@ -63,7 +66,7 @@ #define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */ /* Advertisement control register. */ -#define ADVERTISE_SLCT 0x001f /* Selector bits */ +#define ADVERTISE_SLCT 0x001f /* Selector bits */ #define ADVERTISE_CSMA 0x0001 /* Only selector supported */ #define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ #define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */ @@ -72,19 +75,19 @@ #define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ #define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */ #define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ -#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */ +#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */ #define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */ -#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */ +#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */ #define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */ -#define ADVERTISE_RESV 0x1000 /* Unused... */ +#define ADVERTISE_RESV 0x1000 /* Unused... */ #define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */ #define ADVERTISE_LPACK 0x4000 /* Ack link partners response */ -#define ADVERTISE_NPAGE 0x8000 /* Next page bit */ +#define ADVERTISE_NPAGE 0x8000 /* Next page bit */ -#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \ - ADVERTISE_CSMA) -#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \ - ADVERTISE_100HALF | ADVERTISE_100FULL) +#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \ + ADVERTISE_CSMA) +#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \ + ADVERTISE_100HALF | ADVERTISE_100FULL) /* Link partner ability register. */ #define LPA_SLCT 0x001f /* Same as advertise selector */ @@ -97,12 +100,12 @@ #define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */ #define LPA_1000XPAUSE_ASYM 0x0100 /* Can do 1000BASE-X pause asym*/ #define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */ -#define LPA_PAUSE_CAP 0x0400 /* Can pause */ +#define LPA_PAUSE_CAP 0x0400 /* Can pause */ #define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */ -#define LPA_RESV 0x1000 /* Unused... */ +#define LPA_RESV 0x1000 /* Unused... */ #define LPA_RFAULT 0x2000 /* Link partner faulted */ #define LPA_LPACK 0x4000 /* Link partner acked us */ -#define LPA_NPAGE 0x8000 /* Next page bit */ +#define LPA_NPAGE 0x8000 /* Next page bit */ #define LPA_DUPLEX (LPA_10FULL | LPA_100FULL) #define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4) @@ -113,21 +116,23 @@ #define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */ #define EXPANSION_NPCAPABLE 0x0008 /* Link partner supports npage */ #define EXPANSION_MFAULTS 0x0010 /* Multiple faults detected */ -#define EXPANSION_RESV 0xffe0 /* Unused... */ +#define EXPANSION_RESV 0xffe0 /* Unused... */ #define ESTATUS_1000_XFULL 0x8000 /* Can do 1000BX Full */ #define ESTATUS_1000_XHALF 0x4000 /* Can do 1000BX Half */ -#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */ -#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */ +#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */ +#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */ /* N-way test register. */ -#define NWAYTEST_RESV1 0x00ff /* Unused... */ +#define NWAYTEST_RESV1 0x00ff /* Unused... */ #define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */ -#define NWAYTEST_RESV2 0xfe00 /* Unused... */ +#define NWAYTEST_RESV2 0xfe00 /* Unused... */ /* 1000BASE-T Control register */ -#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */ -#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */ +#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */ +#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */ +#define CTL1000_AS_MASTER 0x0800 +#define CTL1000_ENABLE_MASTER 0x1000 /* 1000BASE-T Status register */ #define LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */ @@ -139,6 +144,13 @@ #define FLOW_CTRL_TX 0x01 #define FLOW_CTRL_RX 0x02 +/* MMD Access Control register fields */ +#define MII_MMD_CTRL_DEVAD_MASK 0x1f /* Mask MMD DEVAD*/ +#define MII_MMD_CTRL_ADDR 0x0000 /* Address */ +#define MII_MMD_CTRL_NOINCR 0x4000 /* no post increment */ +#define MII_MMD_CTRL_INCR_RDWT 0x8000 /* post increment on reads & writes */ +#define MII_MMD_CTRL_INCR_ON_WT 0xC000 /* post increment on writes only */ + /** * mii_nway_result * @negotiated: value of MII ANAR and'd with ANLPAR diff --git a/include/net.h b/include/net.h index 2b2deb5..51c099d 100644 --- a/include/net.h +++ b/include/net.h @@ -14,6 +14,7 @@ #include #include /* for nton* / ntoh* stuff */ +#include #define DEBUG_LL_STATE 0 /* Link local state machine changes */ #define DEBUG_DEV_PKT 0 /* Packets or info directed to the device */ @@ -596,7 +597,8 @@ int net_set_ether(uchar *xet, const uchar *dest_ethaddr, uint prot); int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot); /* Set IP header */ -void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source); +void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source, + u16 pkt_len, u8 proto); void net_set_udp_header(uchar *pkt, struct in_addr dest, int dport, int sport, int len); @@ -635,6 +637,7 @@ rxhand_f *net_get_udp_handler(void); /* Get UDP RX packet handler */ void net_set_udp_handler(rxhand_f *); /* Set UDP RX packet handler */ rxhand_f *net_get_arp_handler(void); /* Get ARP RX packet handler */ void net_set_arp_handler(rxhand_f *); /* Set ARP RX packet handler */ +bool arp_is_waiting(void); /* Waiting for ARP reply? */ void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */ void net_set_timeout_handler(ulong, thand_f *);/* Set timeout handler */ @@ -653,6 +656,14 @@ static inline void net_set_state(enum net_loop_state state) net_state = state; } +/* + * net_get_async_tx_pkt_buf - Get a packet buffer that is not in use for + * sending an asynchronous reply + * + * returns - ptr to packet buffer + */ +uchar * net_get_async_tx_pkt_buf(void); + /* Transmit a packet */ static inline void net_send_packet(uchar *pkt, int len) { @@ -670,6 +681,9 @@ static inline void net_send_packet(uchar *pkt, int len) * @param sport Source UDP port * @param payload_len Length of data after the UDP header */ +int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, + int payload_len, int proto, u8 action, u32 tcp_seq_num, + u32 tcp_ack_num); int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport, int payload_len); diff --git a/include/phy_interface.h b/include/phy_interface.h index 0760d65..c682318 100644 --- a/include/phy_interface.h +++ b/include/phy_interface.h @@ -27,6 +27,10 @@ typedef enum { PHY_INTERFACE_MODE_RXAUI, PHY_INTERFACE_MODE_SFI, PHY_INTERFACE_MODE_INTERNAL, + PHY_INTERFACE_MODE_25G_AUI, + PHY_INTERFACE_MODE_XLAUI, + PHY_INTERFACE_MODE_CAUI2, + PHY_INTERFACE_MODE_CAUI4, PHY_INTERFACE_MODE_NONE, /* Must be last */ PHY_INTERFACE_MODE_COUNT, @@ -50,6 +54,10 @@ static const char * const phy_interface_strings[] = { [PHY_INTERFACE_MODE_RXAUI] = "rxaui", [PHY_INTERFACE_MODE_SFI] = "sfi", [PHY_INTERFACE_MODE_INTERNAL] = "internal", + [PHY_INTERFACE_MODE_25G_AUI] = "25g-aui", + [PHY_INTERFACE_MODE_XLAUI] = "xlaui4", + [PHY_INTERFACE_MODE_CAUI2] = "caui2", + [PHY_INTERFACE_MODE_CAUI4] = "caui4", [PHY_INTERFACE_MODE_NONE] = "", }; diff --git a/include/usb_ether.h b/include/usb_ether.h index 49f47d3..e85acad 100644 --- a/include/usb_ether.h +++ b/include/usb_ether.h @@ -8,16 +8,6 @@ #include -/* - * IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble - * and FCS/CRC (frame check sequence). - */ -#define ETH_ALEN 6 /* Octets in one ethernet addr */ -#define ETH_HLEN 14 /* Total octets in header. */ -#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ -#define ETH_DATA_LEN 1500 /* Max. octets in payload */ -#define ETH_FRAME_LEN PKTSIZE_ALIGN /* Max. octets in frame sans FCS */ - /* TODO(sjg@chromium.org): Remove @pusb_dev when all boards use CONFIG_DM_ETH */ struct ueth_data { /* eth info */ diff --git a/net/arp.c b/net/arp.c index b8a7168..b49c3d3 100644 --- a/net/arp.c +++ b/net/arp.c @@ -34,8 +34,7 @@ uchar *arp_wait_packet_ethaddr; int arp_wait_tx_packet_size; ulong arp_wait_timer_start; int arp_wait_try; - -static uchar *arp_tx_packet; /* THE ARP transmit packet */ +uchar *arp_tx_packet; /* THE ARP transmit packet */ static uchar arp_tx_packet_buf[PKTSIZE_ALIGN + PKTALIGN]; void arp_init(void) @@ -100,7 +99,7 @@ int arp_timeout_check(void) { ulong t; - if (!net_arp_wait_packet_ip.s_addr) + if (!arp_is_waiting()) return 0; t = get_timer(0); @@ -126,6 +125,7 @@ void arp_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) struct arp_hdr *arp; struct in_addr reply_ip_addr; int eth_hdr_size; + uchar *tx_packet; /* * We have to deal with two types of ARP packets: @@ -182,13 +182,14 @@ void arp_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) (net_read_ip(&arp->ar_spa).s_addr & net_netmask.s_addr)) udelay(5000); #endif - memcpy(net_tx_packet, et, eth_hdr_size + ARP_HDR_SIZE); - net_send_packet(net_tx_packet, eth_hdr_size + ARP_HDR_SIZE); + tx_packet = net_get_async_tx_pkt_buf(); + memcpy(tx_packet, et, eth_hdr_size + ARP_HDR_SIZE); + net_send_packet(tx_packet, eth_hdr_size + ARP_HDR_SIZE); return; case ARPOP_REPLY: /* arp reply */ - /* are we waiting for a reply */ - if (!net_arp_wait_packet_ip.s_addr) + /* are we waiting for a reply? */ + if (!arp_is_waiting()) break; #ifdef CONFIG_KEEP_SERVERADDR @@ -233,3 +234,8 @@ void arp_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) return; } } + +bool arp_is_waiting(void) +{ + return !!net_arp_wait_packet_ip.s_addr; +} diff --git a/net/arp.h b/net/arp.h index afb8695..25b3c00 100644 --- a/net/arp.h +++ b/net/arp.h @@ -20,6 +20,7 @@ extern uchar *arp_wait_packet_ethaddr; extern int arp_wait_tx_packet_size; extern ulong arp_wait_timer_start; extern int arp_wait_try; +extern uchar *arp_tx_packet; void arp_init(void); void arp_request(void); diff --git a/net/net.c b/net/net.c index 31cf306..a5a216c 100644 --- a/net/net.c +++ b/net/net.c @@ -799,9 +799,25 @@ void net_set_timeout_handler(ulong iv, thand_f *f) } } +uchar *net_get_async_tx_pkt_buf(void) +{ + if (arp_is_waiting()) + return arp_tx_packet; /* If we are waiting, we already sent */ + else + return net_tx_packet; +} + int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport, int payload_len) { + return net_send_ip_packet(ether, dest, dport, sport, payload_len, + IPPROTO_UDP, 0, 0, 0); +} + +int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, + int payload_len, int proto, u8 action, u32 tcp_seq_num, + u32 tcp_ack_num) +{ uchar *pkt; int eth_hdr_size; int pkt_hdr_size; @@ -822,9 +838,16 @@ int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport, pkt = (uchar *)net_tx_packet; eth_hdr_size = net_set_ether(pkt, ether, PROT_IP); - pkt += eth_hdr_size; - net_set_udp_header(pkt, dest, dport, sport, payload_len); - pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE; + + switch (proto) { + case IPPROTO_UDP: + net_set_udp_header(pkt + eth_hdr_size, dest, dport, sport, + payload_len); + pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE; + break; + default: + return -EINVAL; + } /* if MAC address was not discovered yet, do an ARP request */ if (memcmp(ether, net_null_ethaddr, 6) == 0) { @@ -1455,7 +1478,8 @@ int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot) } } -void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source) +void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source, + u16 pkt_len, u8 proto) { struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt; @@ -1465,7 +1489,8 @@ void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source) /* IP_HDR_SIZE / 4 (not including UDP) */ ip->ip_hl_v = 0x45; ip->ip_tos = 0; - ip->ip_len = htons(IP_HDR_SIZE); + ip->ip_len = htons(pkt_len); + ip->ip_p = proto; ip->ip_id = htons(net_ip_id++); ip->ip_off = htons(IP_FLAGS_DFRAG); /* Don't fragment */ ip->ip_ttl = 255; @@ -1474,6 +1499,8 @@ void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source) net_copy_ip((void *)&ip->ip_src, &source); /* already in network byte order */ net_copy_ip((void *)&ip->ip_dst, &dest); + + ip->ip_sum = compute_ip_checksum(ip, IP_HDR_SIZE); } void net_set_udp_header(uchar *pkt, struct in_addr dest, int dport, int sport, @@ -1489,10 +1516,8 @@ void net_set_udp_header(uchar *pkt, struct in_addr dest, int dport, int sport, if (len & 1) pkt[IP_UDP_HDR_SIZE + len] = 0; - net_set_ip_header(pkt, dest, net_ip); - ip->ip_len = htons(IP_UDP_HDR_SIZE + len); - ip->ip_p = IPPROTO_UDP; - ip->ip_sum = compute_ip_checksum(ip, IP_HDR_SIZE); + net_set_ip_header(pkt, dest, net_ip, IP_UDP_HDR_SIZE + len, + IPPROTO_UDP); ip->udp_src = htons(sport); ip->udp_dst = htons(dport); diff --git a/net/ping.c b/net/ping.c index 3e5461a..633c942 100644 --- a/net/ping.c +++ b/net/ping.c @@ -22,14 +22,9 @@ static void set_icmp_header(uchar *pkt, struct in_addr dest) /* * Construct an IP and ICMP header. */ - struct ip_hdr *ip = (struct ip_hdr *)pkt; struct icmp_hdr *icmp = (struct icmp_hdr *)(pkt + IP_HDR_SIZE); - net_set_ip_header(pkt, dest, net_ip); - - ip->ip_len = htons(IP_ICMP_HDR_SIZE); - ip->ip_p = IPPROTO_ICMP; - ip->ip_sum = compute_ip_checksum(ip, IP_HDR_SIZE); + net_set_ip_header(pkt, dest, net_ip, IP_ICMP_HDR_SIZE, IPPROTO_ICMP); icmp->type = ICMP_ECHO_REQUEST; icmp->code = 0; @@ -84,6 +79,7 @@ void ping_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) struct icmp_hdr *icmph = (struct icmp_hdr *)&ip->udp_src; struct in_addr src_ip; int eth_hdr_size; + uchar *tx_packet; switch (icmph->type) { case ICMP_ECHO_REPLY: @@ -107,8 +103,10 @@ void ping_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) icmph->type = ICMP_ECHO_REPLY; icmph->checksum = 0; icmph->checksum = compute_ip_checksum(icmph, len - IP_HDR_SIZE); - memcpy(net_tx_packet, et, eth_hdr_size + len); - net_send_packet(net_tx_packet, eth_hdr_size + len); + + tx_packet = net_get_async_tx_pkt_buf(); + memcpy(tx_packet, et, eth_hdr_size + len); + net_send_packet(tx_packet, eth_hdr_size + len); return; /* default: return;*/ diff --git a/test/dm/eth.c b/test/dm/eth.c index 1a7684a..850eabb 100644 --- a/test/dm/eth.c +++ b/test/dm/eth.c @@ -258,3 +258,173 @@ static int dm_test_net_retry(struct unit_test_state *uts) return retval; } DM_TEST(dm_test_net_retry, DM_TESTF_SCAN_FDT); + +static int sb_check_arp_reply(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth = packet; + struct arp_hdr *arp; + /* Used by all of the ut_assert macros */ + struct unit_test_state *uts = priv->priv; + + if (ntohs(eth->et_protlen) != PROT_ARP) + return 0; + + arp = packet + ETHER_HDR_SIZE; + + if (ntohs(arp->ar_op) != ARPOP_REPLY) + return 0; + + /* This test would be worthless if we are not waiting */ + ut_assert(arp_is_waiting()); + + /* Validate response */ + ut_assert(memcmp(eth->et_src, net_ethaddr, ARP_HLEN) == 0); + ut_assert(memcmp(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN) == 0); + ut_assert(eth->et_protlen == htons(PROT_ARP)); + + ut_assert(arp->ar_hrd == htons(ARP_ETHER)); + ut_assert(arp->ar_pro == htons(PROT_IP)); + ut_assert(arp->ar_hln == ARP_HLEN); + ut_assert(arp->ar_pln == ARP_PLEN); + ut_assert(memcmp(&arp->ar_sha, net_ethaddr, ARP_HLEN) == 0); + ut_assert(net_read_ip(&arp->ar_spa).s_addr == net_ip.s_addr); + ut_assert(memcmp(&arp->ar_tha, priv->fake_host_hwaddr, ARP_HLEN) == 0); + ut_assert(net_read_ip(&arp->ar_tpa).s_addr == + string_to_ip("1.1.2.4").s_addr); + + return 0; +} + +static int sb_with_async_arp_handler(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth = packet; + struct arp_hdr *arp = packet + ETHER_HDR_SIZE; + int ret; + + /* + * If we are about to generate a reply to ARP, first inject a request + * from another host + */ + if (ntohs(eth->et_protlen) == PROT_ARP && + ntohs(arp->ar_op) == ARPOP_REQUEST) { + /* Make sure sandbox_eth_recv_arp_req() knows who is asking */ + priv->fake_host_ipaddr = string_to_ip("1.1.2.4"); + + ret = sandbox_eth_recv_arp_req(dev); + if (ret) + return ret; + } + + sandbox_eth_arp_req_to_reply(dev, packet, len); + sandbox_eth_ping_req_to_reply(dev, packet, len); + + return sb_check_arp_reply(dev, packet, len); +} + +static int dm_test_eth_async_arp_reply(struct unit_test_state *uts) +{ + net_ping_ip = string_to_ip("1.1.2.2"); + + sandbox_eth_set_tx_handler(0, sb_with_async_arp_handler); + /* Used by all of the ut_assert macros in the tx_handler */ + sandbox_eth_set_priv(0, uts); + + env_set("ethact", "eth@10002000"); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10002000", env_get("ethact")); + + sandbox_eth_set_tx_handler(0, NULL); + + return 0; +} + +DM_TEST(dm_test_eth_async_arp_reply, DM_TESTF_SCAN_FDT); + +static int sb_check_ping_reply(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth = packet; + struct ip_udp_hdr *ip; + struct icmp_hdr *icmp; + /* Used by all of the ut_assert macros */ + struct unit_test_state *uts = priv->priv; + + if (ntohs(eth->et_protlen) != PROT_IP) + return 0; + + ip = packet + ETHER_HDR_SIZE; + + if (ip->ip_p != IPPROTO_ICMP) + return 0; + + icmp = (struct icmp_hdr *)&ip->udp_src; + + if (icmp->type != ICMP_ECHO_REPLY) + return 0; + + /* This test would be worthless if we are not waiting */ + ut_assert(arp_is_waiting()); + + /* Validate response */ + ut_assert(memcmp(eth->et_src, net_ethaddr, ARP_HLEN) == 0); + ut_assert(memcmp(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN) == 0); + ut_assert(eth->et_protlen == htons(PROT_IP)); + + ut_assert(net_read_ip(&ip->ip_src).s_addr == net_ip.s_addr); + ut_assert(net_read_ip(&ip->ip_dst).s_addr == + string_to_ip("1.1.2.4").s_addr); + + return 0; +} + +static int sb_with_async_ping_handler(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth = packet; + struct arp_hdr *arp = packet + ETHER_HDR_SIZE; + int ret; + + /* + * If we are about to generate a reply to ARP, first inject a request + * from another host + */ + if (ntohs(eth->et_protlen) == PROT_ARP && + ntohs(arp->ar_op) == ARPOP_REQUEST) { + /* Make sure sandbox_eth_recv_arp_req() knows who is asking */ + priv->fake_host_ipaddr = string_to_ip("1.1.2.4"); + + ret = sandbox_eth_recv_ping_req(dev); + if (ret) + return ret; + } + + sandbox_eth_arp_req_to_reply(dev, packet, len); + sandbox_eth_ping_req_to_reply(dev, packet, len); + + return sb_check_ping_reply(dev, packet, len); +} + +static int dm_test_eth_async_ping_reply(struct unit_test_state *uts) +{ + net_ping_ip = string_to_ip("1.1.2.2"); + + sandbox_eth_set_tx_handler(0, sb_with_async_ping_handler); + /* Used by all of the ut_assert macros in the tx_handler */ + sandbox_eth_set_priv(0, uts); + + env_set("ethact", "eth@10002000"); + ut_assertok(net_loop(PING)); + ut_asserteq_str("eth@10002000", env_get("ethact")); + + sandbox_eth_set_tx_handler(0, NULL); + + return 0; +} + +DM_TEST(dm_test_eth_async_ping_reply, DM_TESTF_SCAN_FDT);