bpf: also include toolchain standard header as system header
[openwrt/openwrt.git] / target / linux / ath79 / files / drivers / net / ethernet / atheros / ag71xx / ag71xx_ethtool.c
1 /*
2 * Atheros AR71xx built-in ethernet mac driver
3 *
4 * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6 *
7 * Based on Atheros' AG7100 driver
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 version 2 as published
11 * by the Free Software Foundation.
12 */
13
14 #include "ag71xx.h"
15
16 struct ag71xx_statistic {
17 unsigned short offset;
18 u32 mask;
19 const char name[ETH_GSTRING_LEN];
20 };
21
22 static const struct ag71xx_statistic ag71xx_statistics[] = {
23 { 0x0080, GENMASK(17, 0), "Tx/Rx 64 Byte", },
24 { 0x0084, GENMASK(17, 0), "Tx/Rx 65-127 Byte", },
25 { 0x0088, GENMASK(17, 0), "Tx/Rx 128-255 Byte", },
26 { 0x008C, GENMASK(17, 0), "Tx/Rx 256-511 Byte", },
27 { 0x0090, GENMASK(17, 0), "Tx/Rx 512-1023 Byte", },
28 { 0x0094, GENMASK(17, 0), "Tx/Rx 1024-1518 Byte", },
29 { 0x0098, GENMASK(17, 0), "Tx/Rx 1519-1522 Byte VLAN", },
30 { 0x009C, GENMASK(23, 0), "Rx Byte", },
31 { 0x00A0, GENMASK(17, 0), "Rx Packet", },
32 { 0x00A4, GENMASK(11, 0), "Rx FCS Error", },
33 { 0x00A8, GENMASK(17, 0), "Rx Multicast Packet", },
34 { 0x00AC, GENMASK(21, 0), "Rx Broadcast Packet", },
35 { 0x00B0, GENMASK(17, 0), "Rx Control Frame Packet", },
36 { 0x00B4, GENMASK(11, 0), "Rx Pause Frame Packet", },
37 { 0x00B8, GENMASK(11, 0), "Rx Unknown OPCode Packet", },
38 { 0x00BC, GENMASK(11, 0), "Rx Alignment Error", },
39 { 0x00C0, GENMASK(15, 0), "Rx Frame Length Error", },
40 { 0x00C4, GENMASK(11, 0), "Rx Code Error", },
41 { 0x00C8, GENMASK(11, 0), "Rx Carrier Sense Error", },
42 { 0x00CC, GENMASK(11, 0), "Rx Undersize Packet", },
43 { 0x00D0, GENMASK(11, 0), "Rx Oversize Packet", },
44 { 0x00D4, GENMASK(11, 0), "Rx Fragments", },
45 { 0x00D8, GENMASK(11, 0), "Rx Jabber", },
46 { 0x00DC, GENMASK(11, 0), "Rx Dropped Packet", },
47 { 0x00E0, GENMASK(23, 0), "Tx Byte", },
48 { 0x00E4, GENMASK(17, 0), "Tx Packet", },
49 { 0x00E8, GENMASK(17, 0), "Tx Multicast Packet", },
50 { 0x00EC, GENMASK(17, 0), "Tx Broadcast Packet", },
51 { 0x00F0, GENMASK(11, 0), "Tx Pause Control Frame", },
52 { 0x00F4, GENMASK(11, 0), "Tx Deferral Packet", },
53 { 0x00F8, GENMASK(11, 0), "Tx Excessive Deferral Packet", },
54 { 0x00FC, GENMASK(11, 0), "Tx Single Collision Packet", },
55 { 0x0100, GENMASK(11, 0), "Tx Multiple Collision", },
56 { 0x0104, GENMASK(11, 0), "Tx Late Collision Packet", },
57 { 0x0108, GENMASK(11, 0), "Tx Excessive Collision Packet", },
58 { 0x010C, GENMASK(12, 0), "Tx Total Collision", },
59 { 0x0110, GENMASK(11, 0), "Tx Pause Frames Honored", },
60 { 0x0114, GENMASK(11, 0), "Tx Drop Frame", },
61 { 0x0118, GENMASK(11, 0), "Tx Jabber Frame", },
62 { 0x011C, GENMASK(11, 0), "Tx FCS Error", },
63 { 0x0120, GENMASK(11, 0), "Tx Control Frame", },
64 { 0x0124, GENMASK(11, 0), "Tx Oversize Frame", },
65 { 0x0128, GENMASK(11, 0), "Tx Undersize Frame", },
66 { 0x012C, GENMASK(11, 0), "Tx Fragment", },
67 };
68
69 static u32 ag71xx_ethtool_get_msglevel(struct net_device *dev)
70 {
71 struct ag71xx *ag = netdev_priv(dev);
72
73 return ag->msg_enable;
74 }
75
76 static void ag71xx_ethtool_set_msglevel(struct net_device *dev, u32 msg_level)
77 {
78 struct ag71xx *ag = netdev_priv(dev);
79
80 ag->msg_enable = msg_level;
81 }
82
83 static void
84 ag71xx_ethtool_get_ringparam(struct net_device *dev,
85 struct ethtool_ringparam *er,
86 struct kernel_ethtool_ringparam *kernel_ring,
87 struct netlink_ext_ack *extack)
88 {
89 struct ag71xx *ag = netdev_priv(dev);
90
91 er->tx_max_pending = AG71XX_TX_RING_SIZE_MAX;
92 er->rx_max_pending = AG71XX_RX_RING_SIZE_MAX;
93 er->rx_mini_max_pending = 0;
94 er->rx_jumbo_max_pending = 0;
95
96 er->tx_pending = BIT(ag->tx_ring.order);
97 er->rx_pending = BIT(ag->rx_ring.order);
98 er->rx_mini_pending = 0;
99 er->rx_jumbo_pending = 0;
100
101 if (ag->tx_ring.desc_split)
102 er->tx_pending /= AG71XX_TX_RING_DS_PER_PKT;
103 }
104
105 static int
106 ag71xx_ethtool_set_ringparam(struct net_device *dev,
107 struct ethtool_ringparam *er,
108 struct kernel_ethtool_ringparam *kernel_ring,
109 struct netlink_ext_ack *extack)
110 {
111 struct ag71xx *ag = netdev_priv(dev);
112 unsigned tx_size;
113 unsigned rx_size;
114 int err = 0;
115
116 if (er->rx_mini_pending != 0||
117 er->rx_jumbo_pending != 0 ||
118 er->rx_pending == 0 ||
119 er->tx_pending == 0)
120 return -EINVAL;
121
122 tx_size = er->tx_pending < AG71XX_TX_RING_SIZE_MAX ?
123 er->tx_pending : AG71XX_TX_RING_SIZE_MAX;
124
125 rx_size = er->rx_pending < AG71XX_RX_RING_SIZE_MAX ?
126 er->rx_pending : AG71XX_RX_RING_SIZE_MAX;
127
128 if (netif_running(dev)) {
129 err = dev->netdev_ops->ndo_stop(dev);
130 if (err)
131 return err;
132 }
133
134 if (ag->tx_ring.desc_split)
135 tx_size *= AG71XX_TX_RING_DS_PER_PKT;
136
137 ag->tx_ring.order = ag71xx_ring_size_order(tx_size);
138 ag->rx_ring.order = ag71xx_ring_size_order(rx_size);
139
140 if (netif_running(dev))
141 err = dev->netdev_ops->ndo_open(dev);
142
143 return err;
144 }
145
146 static int ag71xx_ethtool_nway_reset(struct net_device *dev)
147 {
148 struct ag71xx *ag = netdev_priv(dev);
149 struct phy_device *phydev = ag->phy_dev;
150
151 if (!phydev)
152 return -ENODEV;
153
154 return genphy_restart_aneg(phydev);
155 }
156
157 static void ag71xx_ethtool_get_strings(struct net_device *netdev, u32 sset,
158 u8 *data)
159 {
160 if (sset == ETH_SS_STATS) {
161 int i;
162
163 for (i = 0; i < ARRAY_SIZE(ag71xx_statistics); i++)
164 ethtool_puts(&data, ag71xx_statistics[i].name);
165 }
166 }
167
168 static void ag71xx_ethtool_get_stats(struct net_device *ndev,
169 struct ethtool_stats *stats, u64 *data)
170 {
171 struct ag71xx *ag = netdev_priv(ndev);
172 int i;
173
174 for (i = 0; i < ARRAY_SIZE(ag71xx_statistics); i++)
175 *data++ = ag71xx_rr(ag, ag71xx_statistics[i].offset)
176 & ag71xx_statistics[i].mask;
177 }
178
179 static int ag71xx_ethtool_get_sset_count(struct net_device *ndev, int sset)
180 {
181 if (sset == ETH_SS_STATS)
182 return ARRAY_SIZE(ag71xx_statistics);
183 return -EOPNOTSUPP;
184 }
185
186 struct ethtool_ops ag71xx_ethtool_ops = {
187 .get_msglevel = ag71xx_ethtool_get_msglevel,
188 .set_msglevel = ag71xx_ethtool_set_msglevel,
189 .get_ringparam = ag71xx_ethtool_get_ringparam,
190 .set_ringparam = ag71xx_ethtool_set_ringparam,
191 .get_link_ksettings = phy_ethtool_get_link_ksettings,
192 .set_link_ksettings = phy_ethtool_set_link_ksettings,
193 .get_link = ethtool_op_get_link,
194 .get_ts_info = ethtool_op_get_ts_info,
195 .nway_reset = ag71xx_ethtool_nway_reset,
196 .get_strings = ag71xx_ethtool_get_strings,
197 .get_ethtool_stats = ag71xx_ethtool_get_stats,
198 .get_sset_count = ag71xx_ethtool_get_sset_count,
199 };