.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Xilinx EmacLite Linux driver for the Xilinx Ethernet MAC Lite device. |
---|
3 | 4 | * |
---|
.. | .. |
---|
5 | 6 | * driver from John Williams <john.williams@xilinx.com>. |
---|
6 | 7 | * |
---|
7 | 8 | * 2007 - 2013 (c) Xilinx, Inc. |
---|
8 | | - * |
---|
9 | | - * This program is free software; you can redistribute it and/or modify it |
---|
10 | | - * under the terms of the GNU General Public License as published by the |
---|
11 | | - * Free Software Foundation; either version 2 of the License, or (at your |
---|
12 | | - * option) any later version. |
---|
13 | 9 | */ |
---|
14 | 10 | |
---|
15 | 11 | #include <linux/module.h> |
---|
.. | .. |
---|
17 | 13 | #include <linux/netdevice.h> |
---|
18 | 14 | #include <linux/etherdevice.h> |
---|
19 | 15 | #include <linux/skbuff.h> |
---|
| 16 | +#include <linux/ethtool.h> |
---|
20 | 17 | #include <linux/io.h> |
---|
21 | 18 | #include <linux/slab.h> |
---|
22 | 19 | #include <linux/of_address.h> |
---|
.. | .. |
---|
26 | 23 | #include <linux/of_net.h> |
---|
27 | 24 | #include <linux/phy.h> |
---|
28 | 25 | #include <linux/interrupt.h> |
---|
| 26 | +#include <linux/iopoll.h> |
---|
29 | 27 | |
---|
30 | 28 | #define DRIVER_NAME "xilinx_emaclite" |
---|
31 | 29 | |
---|
.. | .. |
---|
523 | 521 | * |
---|
524 | 522 | * This function is called when Tx time out occurs for Emaclite device. |
---|
525 | 523 | */ |
---|
526 | | -static void xemaclite_tx_timeout(struct net_device *dev) |
---|
| 524 | +static void xemaclite_tx_timeout(struct net_device *dev, unsigned int txqueue) |
---|
527 | 525 | { |
---|
528 | 526 | struct net_local *lp = netdev_priv(dev); |
---|
529 | 527 | unsigned long flags; |
---|
.. | .. |
---|
543 | 541 | xemaclite_enable_interrupts(lp); |
---|
544 | 542 | |
---|
545 | 543 | if (lp->deferred_skb) { |
---|
546 | | - dev_kfree_skb(lp->deferred_skb); |
---|
| 544 | + dev_kfree_skb_irq(lp->deferred_skb); |
---|
547 | 545 | lp->deferred_skb = NULL; |
---|
548 | 546 | dev->stats.tx_errors++; |
---|
549 | 547 | } |
---|
.. | .. |
---|
581 | 579 | return; |
---|
582 | 580 | |
---|
583 | 581 | dev->stats.tx_bytes += lp->deferred_skb->len; |
---|
584 | | - dev_kfree_skb_irq(lp->deferred_skb); |
---|
| 582 | + dev_consume_skb_irq(lp->deferred_skb); |
---|
585 | 583 | lp->deferred_skb = NULL; |
---|
586 | 584 | netif_trans_update(dev); /* prevent tx timeout */ |
---|
587 | 585 | netif_wake_queue(dev); |
---|
.. | .. |
---|
713 | 711 | |
---|
714 | 712 | static int xemaclite_mdio_wait(struct net_local *lp) |
---|
715 | 713 | { |
---|
716 | | - unsigned long end = jiffies + 2; |
---|
| 714 | + u32 val; |
---|
717 | 715 | |
---|
718 | 716 | /* wait for the MDIO interface to not be busy or timeout |
---|
719 | 717 | * after some time. |
---|
720 | 718 | */ |
---|
721 | | - while (xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) & |
---|
722 | | - XEL_MDIOCTRL_MDIOSTS_MASK) { |
---|
723 | | - if (time_before_eq(end, jiffies)) { |
---|
724 | | - WARN_ON(1); |
---|
725 | | - return -ETIMEDOUT; |
---|
726 | | - } |
---|
727 | | - msleep(1); |
---|
728 | | - } |
---|
729 | | - return 0; |
---|
| 719 | + return readx_poll_timeout(xemaclite_readl, |
---|
| 720 | + lp->base_addr + XEL_MDIOCTRL_OFFSET, |
---|
| 721 | + val, !(val & XEL_MDIOCTRL_MDIOSTS_MASK), |
---|
| 722 | + 1000, 20000); |
---|
730 | 723 | } |
---|
731 | 724 | |
---|
732 | 725 | /** |
---|
.. | .. |
---|
827 | 820 | static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) |
---|
828 | 821 | { |
---|
829 | 822 | struct mii_bus *bus; |
---|
830 | | - int rc; |
---|
831 | 823 | struct resource res; |
---|
832 | 824 | struct device_node *np = of_get_parent(lp->phy_node); |
---|
833 | 825 | struct device_node *npp; |
---|
| 826 | + int rc, ret; |
---|
834 | 827 | |
---|
835 | 828 | /* Don't register the MDIO bus if the phy_node or its parent node |
---|
836 | 829 | * can't be found. |
---|
.. | .. |
---|
840 | 833 | return -ENODEV; |
---|
841 | 834 | } |
---|
842 | 835 | npp = of_get_parent(np); |
---|
843 | | - |
---|
844 | | - of_address_to_resource(npp, 0, &res); |
---|
| 836 | + ret = of_address_to_resource(npp, 0, &res); |
---|
| 837 | + of_node_put(npp); |
---|
| 838 | + if (ret) { |
---|
| 839 | + dev_err(dev, "%s resource error!\n", |
---|
| 840 | + dev->of_node->full_name); |
---|
| 841 | + of_node_put(np); |
---|
| 842 | + return ret; |
---|
| 843 | + } |
---|
845 | 844 | if (lp->ndev->mem_start != res.start) { |
---|
846 | 845 | struct phy_device *phydev; |
---|
847 | 846 | phydev = of_phy_find_device(lp->phy_node); |
---|
.. | .. |
---|
850 | 849 | "MDIO of the phy is not registered yet\n"); |
---|
851 | 850 | else |
---|
852 | 851 | put_device(&phydev->mdio.dev); |
---|
| 852 | + of_node_put(np); |
---|
853 | 853 | return 0; |
---|
854 | 854 | } |
---|
855 | 855 | |
---|
.. | .. |
---|
862 | 862 | bus = mdiobus_alloc(); |
---|
863 | 863 | if (!bus) { |
---|
864 | 864 | dev_err(dev, "Failed to allocate mdiobus\n"); |
---|
| 865 | + of_node_put(np); |
---|
865 | 866 | return -ENOMEM; |
---|
866 | 867 | } |
---|
867 | 868 | |
---|
.. | .. |
---|
874 | 875 | bus->parent = dev; |
---|
875 | 876 | |
---|
876 | 877 | rc = of_mdiobus_register(bus, np); |
---|
| 878 | + of_node_put(np); |
---|
877 | 879 | if (rc) { |
---|
878 | 880 | dev_err(dev, "Failed to register mdio bus.\n"); |
---|
879 | 881 | goto err_register; |
---|
.. | .. |
---|
930 | 932 | xemaclite_disable_interrupts(lp); |
---|
931 | 933 | |
---|
932 | 934 | if (lp->phy_node) { |
---|
933 | | - u32 bmcr; |
---|
934 | | - |
---|
935 | 935 | lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node, |
---|
936 | 936 | xemaclite_adjust_link, 0, |
---|
937 | 937 | PHY_INTERFACE_MODE_MII); |
---|
.. | .. |
---|
941 | 941 | } |
---|
942 | 942 | |
---|
943 | 943 | /* EmacLite doesn't support giga-bit speeds */ |
---|
944 | | - lp->phy_dev->supported &= (PHY_BASIC_FEATURES); |
---|
945 | | - lp->phy_dev->advertising = lp->phy_dev->supported; |
---|
946 | | - |
---|
947 | | - /* Don't advertise 1000BASE-T Full/Half duplex speeds */ |
---|
948 | | - phy_write(lp->phy_dev, MII_CTRL1000, 0); |
---|
949 | | - |
---|
950 | | - /* Advertise only 10 and 100mbps full/half duplex speeds */ |
---|
951 | | - phy_write(lp->phy_dev, MII_ADVERTISE, ADVERTISE_ALL | |
---|
952 | | - ADVERTISE_CSMA); |
---|
953 | | - |
---|
954 | | - /* Restart auto negotiation */ |
---|
955 | | - bmcr = phy_read(lp->phy_dev, MII_BMCR); |
---|
956 | | - bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); |
---|
957 | | - phy_write(lp->phy_dev, MII_BMCR, bmcr); |
---|
958 | | - |
---|
| 944 | + phy_set_max_speed(lp->phy_dev, SPEED_100); |
---|
959 | 945 | phy_start(lp->phy_dev); |
---|
960 | 946 | } |
---|
961 | 947 | |
---|
.. | .. |
---|
1079 | 1065 | return (bool)*p; |
---|
1080 | 1066 | } |
---|
1081 | 1067 | |
---|
| 1068 | +/** |
---|
| 1069 | + * xemaclite_ethtools_get_drvinfo - Get various Axi Emac Lite driver info |
---|
| 1070 | + * @ndev: Pointer to net_device structure |
---|
| 1071 | + * @ed: Pointer to ethtool_drvinfo structure |
---|
| 1072 | + * |
---|
| 1073 | + * This implements ethtool command for getting the driver information. |
---|
| 1074 | + * Issue "ethtool -i ethX" under linux prompt to execute this function. |
---|
| 1075 | + */ |
---|
| 1076 | +static void xemaclite_ethtools_get_drvinfo(struct net_device *ndev, |
---|
| 1077 | + struct ethtool_drvinfo *ed) |
---|
| 1078 | +{ |
---|
| 1079 | + strlcpy(ed->driver, DRIVER_NAME, sizeof(ed->driver)); |
---|
| 1080 | +} |
---|
| 1081 | + |
---|
| 1082 | +static const struct ethtool_ops xemaclite_ethtool_ops = { |
---|
| 1083 | + .get_drvinfo = xemaclite_ethtools_get_drvinfo, |
---|
| 1084 | + .get_link = ethtool_op_get_link, |
---|
| 1085 | + .get_link_ksettings = phy_ethtool_get_link_ksettings, |
---|
| 1086 | + .set_link_ksettings = phy_ethtool_set_link_ksettings, |
---|
| 1087 | +}; |
---|
| 1088 | + |
---|
1082 | 1089 | static const struct net_device_ops xemaclite_netdev_ops; |
---|
1083 | 1090 | |
---|
1084 | 1091 | /** |
---|
.. | .. |
---|
1144 | 1151 | lp->rx_ping_pong = get_bool(ofdev, "xlnx,rx-ping-pong"); |
---|
1145 | 1152 | mac_address = of_get_mac_address(ofdev->dev.of_node); |
---|
1146 | 1153 | |
---|
1147 | | - if (mac_address) { |
---|
| 1154 | + if (!IS_ERR(mac_address)) { |
---|
1148 | 1155 | /* Set the MAC address. */ |
---|
1149 | | - memcpy(ndev->dev_addr, mac_address, ETH_ALEN); |
---|
| 1156 | + ether_addr_copy(ndev->dev_addr, mac_address); |
---|
1150 | 1157 | } else { |
---|
1151 | 1158 | dev_warn(dev, "No MAC address found, using random\n"); |
---|
1152 | 1159 | eth_hw_addr_random(ndev); |
---|
.. | .. |
---|
1165 | 1172 | dev_info(dev, "MAC address is now %pM\n", ndev->dev_addr); |
---|
1166 | 1173 | |
---|
1167 | 1174 | ndev->netdev_ops = &xemaclite_netdev_ops; |
---|
| 1175 | + ndev->ethtool_ops = &xemaclite_ethtool_ops; |
---|
1168 | 1176 | ndev->flags &= ~IFF_MULTICAST; |
---|
1169 | 1177 | ndev->watchdog_timeo = TX_TIMEOUT; |
---|
1170 | 1178 | |
---|
.. | .. |
---|
1173 | 1181 | if (rc) { |
---|
1174 | 1182 | dev_err(dev, |
---|
1175 | 1183 | "Cannot register network device, aborting\n"); |
---|
1176 | | - goto error; |
---|
| 1184 | + goto put_node; |
---|
1177 | 1185 | } |
---|
1178 | 1186 | |
---|
1179 | 1187 | dev_info(dev, |
---|
.. | .. |
---|
1181 | 1189 | (unsigned int __force)ndev->mem_start, lp->base_addr, ndev->irq); |
---|
1182 | 1190 | return 0; |
---|
1183 | 1191 | |
---|
| 1192 | +put_node: |
---|
| 1193 | + of_node_put(lp->phy_node); |
---|
1184 | 1194 | error: |
---|
1185 | 1195 | free_netdev(ndev); |
---|
1186 | 1196 | return rc; |
---|
.. | .. |
---|
1229 | 1239 | } |
---|
1230 | 1240 | #endif |
---|
1231 | 1241 | |
---|
| 1242 | +/* Ioctl MII Interface */ |
---|
| 1243 | +static int xemaclite_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) |
---|
| 1244 | +{ |
---|
| 1245 | + if (!dev->phydev || !netif_running(dev)) |
---|
| 1246 | + return -EINVAL; |
---|
| 1247 | + |
---|
| 1248 | + switch (cmd) { |
---|
| 1249 | + case SIOCGMIIPHY: |
---|
| 1250 | + case SIOCGMIIREG: |
---|
| 1251 | + case SIOCSMIIREG: |
---|
| 1252 | + return phy_mii_ioctl(dev->phydev, rq, cmd); |
---|
| 1253 | + default: |
---|
| 1254 | + return -EOPNOTSUPP; |
---|
| 1255 | + } |
---|
| 1256 | +} |
---|
| 1257 | + |
---|
1232 | 1258 | static const struct net_device_ops xemaclite_netdev_ops = { |
---|
1233 | 1259 | .ndo_open = xemaclite_open, |
---|
1234 | 1260 | .ndo_stop = xemaclite_close, |
---|
1235 | 1261 | .ndo_start_xmit = xemaclite_send, |
---|
1236 | 1262 | .ndo_set_mac_address = xemaclite_set_mac_address, |
---|
1237 | 1263 | .ndo_tx_timeout = xemaclite_tx_timeout, |
---|
| 1264 | + .ndo_do_ioctl = xemaclite_ioctl, |
---|
1238 | 1265 | #ifdef CONFIG_NET_POLL_CONTROLLER |
---|
1239 | 1266 | .ndo_poll_controller = xemaclite_poll_controller, |
---|
1240 | 1267 | #endif |
---|