diff options
author | Vipul Pandya <vipul.pandya@samsung.com> | 2014-03-25 15:11:02 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-03-26 16:49:31 -0400 |
commit | 25f72a746aca07d0d9cae7e093fe15613fc62ee3 (patch) | |
tree | b6c2a8775c76332d9faf14c7c9f3dfe9c6b85a61 /drivers/net/ethernet/samsung | |
parent | 8f7807ae41bb57e003b7dc07e83e186d11747bde (diff) |
net: sxgbe: add ethtool related functions support Samsung sxgbe
This patch adds ethtool related functions.
Signed-off-by: Vipul Pandya <vipul.pandya@samsung.com>
Neatening-by: Joe Perches <joe@perches.com>
Signed-off-by: Byungho An <bh74.an@samsung.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/samsung')
-rw-r--r-- | drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h | 16 | ||||
-rw-r--r-- | drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c | 433 | ||||
-rw-r--r-- | drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h | 6 |
4 files changed, 458 insertions, 1 deletions
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h index 4893cfd298a7..6203c7d8550f 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h | |||
@@ -197,6 +197,20 @@ enum dma_irq_status { | |||
197 | #define SXGBE_FOR_EACH_QUEUE(max_queues, queue_num) \ | 197 | #define SXGBE_FOR_EACH_QUEUE(max_queues, queue_num) \ |
198 | for (queue_num = 0; queue_num < max_queues; queue_num++) | 198 | for (queue_num = 0; queue_num < max_queues; queue_num++) |
199 | 199 | ||
200 | #define DRV_VERSION "1.0.0" | ||
201 | |||
202 | #define SXGBE_MAX_RX_CHANNELS 16 | ||
203 | #define SXGBE_MAX_TX_CHANNELS 16 | ||
204 | |||
205 | #define START_MAC_REG_OFFSET 0x0000 | ||
206 | #define MAX_MAC_REG_OFFSET 0x0DFC | ||
207 | #define START_MTL_REG_OFFSET 0x1000 | ||
208 | #define MAX_MTL_REG_OFFSET 0x18FC | ||
209 | #define START_DMA_REG_OFFSET 0x3000 | ||
210 | #define MAX_DMA_REG_OFFSET 0x38FC | ||
211 | |||
212 | #define REG_SPACE_SIZE 0x2000 | ||
213 | |||
200 | /* sxgbe statistics counters */ | 214 | /* sxgbe statistics counters */ |
201 | struct sxgbe_extra_stats { | 215 | struct sxgbe_extra_stats { |
202 | /* TX/RX IRQ events */ | 216 | /* TX/RX IRQ events */ |
@@ -482,6 +496,7 @@ struct sxgbe_priv_data { | |||
482 | /* advanced time stamp support */ | 496 | /* advanced time stamp support */ |
483 | u32 adv_ts; | 497 | u32 adv_ts; |
484 | int use_riwt; | 498 | int use_riwt; |
499 | struct ptp_clock *ptp_clock; | ||
485 | 500 | ||
486 | /* tc control */ | 501 | /* tc control */ |
487 | int tx_tc; | 502 | int tx_tc; |
@@ -517,5 +532,4 @@ const struct sxgbe_mtl_ops *sxgbe_get_mtl_ops(void); | |||
517 | 532 | ||
518 | void sxgbe_disable_eee_mode(struct sxgbe_priv_data * const priv); | 533 | void sxgbe_disable_eee_mode(struct sxgbe_priv_data * const priv); |
519 | bool sxgbe_eee_init(struct sxgbe_priv_data * const priv); | 534 | bool sxgbe_eee_init(struct sxgbe_priv_data * const priv); |
520 | |||
521 | #endif /* __SXGBE_COMMON_H__ */ | 535 | #endif /* __SXGBE_COMMON_H__ */ |
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c index ca95f1daefd8..0415fa50eeb7 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c | |||
@@ -12,11 +12,17 @@ | |||
12 | 12 | ||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
14 | 14 | ||
15 | #include <linux/clk.h> | ||
16 | #include <linux/interrupt.h> | ||
15 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
16 | #include <linux/netdevice.h> | 18 | #include <linux/netdevice.h> |
19 | #include <linux/net_tstamp.h> | ||
17 | #include <linux/phy.h> | 20 | #include <linux/phy.h> |
21 | #include <linux/ptp_clock_kernel.h> | ||
18 | 22 | ||
19 | #include "sxgbe_common.h" | 23 | #include "sxgbe_common.h" |
24 | #include "sxgbe_reg.h" | ||
25 | #include "sxgbe_dma.h" | ||
20 | 26 | ||
21 | struct sxgbe_stats { | 27 | struct sxgbe_stats { |
22 | char stat_string[ETH_GSTRING_LEN]; | 28 | char stat_string[ETH_GSTRING_LEN]; |
@@ -32,11 +38,100 @@ struct sxgbe_stats { | |||
32 | } | 38 | } |
33 | 39 | ||
34 | static const struct sxgbe_stats sxgbe_gstrings_stats[] = { | 40 | static const struct sxgbe_stats sxgbe_gstrings_stats[] = { |
41 | /* TX/RX IRQ events */ | ||
42 | SXGBE_STAT(tx_process_stopped_irq), | ||
43 | SXGBE_STAT(tx_ctxt_desc_err), | ||
44 | SXGBE_STAT(tx_threshold), | ||
45 | SXGBE_STAT(rx_threshold), | ||
46 | SXGBE_STAT(tx_pkt_n), | ||
47 | SXGBE_STAT(rx_pkt_n), | ||
48 | SXGBE_STAT(normal_irq_n), | ||
49 | SXGBE_STAT(tx_normal_irq_n), | ||
50 | SXGBE_STAT(rx_normal_irq_n), | ||
51 | SXGBE_STAT(napi_poll), | ||
52 | SXGBE_STAT(tx_clean), | ||
53 | SXGBE_STAT(tx_reset_ic_bit), | ||
54 | SXGBE_STAT(rx_process_stopped_irq), | ||
55 | SXGBE_STAT(rx_underflow_irq), | ||
56 | |||
57 | /* Bus access errors */ | ||
58 | SXGBE_STAT(fatal_bus_error_irq), | ||
59 | SXGBE_STAT(tx_read_transfer_err), | ||
60 | SXGBE_STAT(tx_write_transfer_err), | ||
61 | SXGBE_STAT(tx_desc_access_err), | ||
62 | SXGBE_STAT(tx_buffer_access_err), | ||
63 | SXGBE_STAT(tx_data_transfer_err), | ||
64 | SXGBE_STAT(rx_read_transfer_err), | ||
65 | SXGBE_STAT(rx_write_transfer_err), | ||
66 | SXGBE_STAT(rx_desc_access_err), | ||
67 | SXGBE_STAT(rx_buffer_access_err), | ||
68 | SXGBE_STAT(rx_data_transfer_err), | ||
69 | |||
70 | /* EEE-LPI stats */ | ||
35 | SXGBE_STAT(tx_lpi_entry_n), | 71 | SXGBE_STAT(tx_lpi_entry_n), |
36 | SXGBE_STAT(tx_lpi_exit_n), | 72 | SXGBE_STAT(tx_lpi_exit_n), |
37 | SXGBE_STAT(rx_lpi_entry_n), | 73 | SXGBE_STAT(rx_lpi_entry_n), |
38 | SXGBE_STAT(rx_lpi_exit_n), | 74 | SXGBE_STAT(rx_lpi_exit_n), |
39 | SXGBE_STAT(eee_wakeup_error_n), | 75 | SXGBE_STAT(eee_wakeup_error_n), |
76 | |||
77 | /* RX specific */ | ||
78 | /* L2 error */ | ||
79 | SXGBE_STAT(rx_code_gmii_err), | ||
80 | SXGBE_STAT(rx_watchdog_err), | ||
81 | SXGBE_STAT(rx_crc_err), | ||
82 | SXGBE_STAT(rx_gaint_pkt_err), | ||
83 | SXGBE_STAT(ip_hdr_err), | ||
84 | SXGBE_STAT(ip_payload_err), | ||
85 | SXGBE_STAT(overflow_error), | ||
86 | |||
87 | /* L2 Pkt type */ | ||
88 | SXGBE_STAT(len_pkt), | ||
89 | SXGBE_STAT(mac_ctl_pkt), | ||
90 | SXGBE_STAT(dcb_ctl_pkt), | ||
91 | SXGBE_STAT(arp_pkt), | ||
92 | SXGBE_STAT(oam_pkt), | ||
93 | SXGBE_STAT(untag_okt), | ||
94 | SXGBE_STAT(other_pkt), | ||
95 | SXGBE_STAT(svlan_tag_pkt), | ||
96 | SXGBE_STAT(cvlan_tag_pkt), | ||
97 | SXGBE_STAT(dvlan_ocvlan_icvlan_pkt), | ||
98 | SXGBE_STAT(dvlan_osvlan_isvlan_pkt), | ||
99 | SXGBE_STAT(dvlan_osvlan_icvlan_pkt), | ||
100 | SXGBE_STAT(dvan_ocvlan_icvlan_pkt), | ||
101 | |||
102 | /* L3/L4 Pkt type */ | ||
103 | SXGBE_STAT(not_ip_pkt), | ||
104 | SXGBE_STAT(ip4_tcp_pkt), | ||
105 | SXGBE_STAT(ip4_udp_pkt), | ||
106 | SXGBE_STAT(ip4_icmp_pkt), | ||
107 | SXGBE_STAT(ip4_unknown_pkt), | ||
108 | SXGBE_STAT(ip6_tcp_pkt), | ||
109 | SXGBE_STAT(ip6_udp_pkt), | ||
110 | SXGBE_STAT(ip6_icmp_pkt), | ||
111 | SXGBE_STAT(ip6_unknown_pkt), | ||
112 | |||
113 | /* Filter specific */ | ||
114 | SXGBE_STAT(vlan_filter_match), | ||
115 | SXGBE_STAT(sa_filter_fail), | ||
116 | SXGBE_STAT(da_filter_fail), | ||
117 | SXGBE_STAT(hash_filter_pass), | ||
118 | SXGBE_STAT(l3_filter_match), | ||
119 | SXGBE_STAT(l4_filter_match), | ||
120 | |||
121 | /* RX context specific */ | ||
122 | SXGBE_STAT(timestamp_dropped), | ||
123 | SXGBE_STAT(rx_msg_type_no_ptp), | ||
124 | SXGBE_STAT(rx_ptp_type_sync), | ||
125 | SXGBE_STAT(rx_ptp_type_follow_up), | ||
126 | SXGBE_STAT(rx_ptp_type_delay_req), | ||
127 | SXGBE_STAT(rx_ptp_type_delay_resp), | ||
128 | SXGBE_STAT(rx_ptp_type_pdelay_req), | ||
129 | SXGBE_STAT(rx_ptp_type_pdelay_resp), | ||
130 | SXGBE_STAT(rx_ptp_type_pdelay_follow_up), | ||
131 | SXGBE_STAT(rx_ptp_announce), | ||
132 | SXGBE_STAT(rx_ptp_mgmt), | ||
133 | SXGBE_STAT(rx_ptp_signal), | ||
134 | SXGBE_STAT(rx_ptp_resv_msg_type), | ||
40 | }; | 135 | }; |
41 | #define SXGBE_STATS_LEN ARRAY_SIZE(sxgbe_gstrings_stats) | 136 | #define SXGBE_STATS_LEN ARRAY_SIZE(sxgbe_gstrings_stats) |
42 | 137 | ||
@@ -80,7 +175,345 @@ static int sxgbe_set_eee(struct net_device *dev, | |||
80 | return phy_ethtool_set_eee(priv->phydev, edata); | 175 | return phy_ethtool_set_eee(priv->phydev, edata); |
81 | } | 176 | } |
82 | 177 | ||
178 | static void sxgbe_getdrvinfo(struct net_device *dev, | ||
179 | struct ethtool_drvinfo *info) | ||
180 | { | ||
181 | strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); | ||
182 | strlcpy(info->version, DRV_VERSION, sizeof(info->version)); | ||
183 | } | ||
184 | |||
185 | static int sxgbe_getsettings(struct net_device *dev, | ||
186 | struct ethtool_cmd *cmd) | ||
187 | { | ||
188 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
189 | |||
190 | if (priv->phydev) | ||
191 | return phy_ethtool_gset(priv->phydev, cmd); | ||
192 | |||
193 | return -EOPNOTSUPP; | ||
194 | } | ||
195 | |||
196 | static int sxgbe_setsettings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
197 | { | ||
198 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
199 | |||
200 | if (priv->phydev) | ||
201 | return phy_ethtool_sset(priv->phydev, cmd); | ||
202 | |||
203 | return -EOPNOTSUPP; | ||
204 | } | ||
205 | |||
206 | static u32 sxgbe_getmsglevel(struct net_device *dev) | ||
207 | { | ||
208 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
209 | return priv->msg_enable; | ||
210 | } | ||
211 | |||
212 | static void sxgbe_setmsglevel(struct net_device *dev, u32 level) | ||
213 | { | ||
214 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
215 | priv->msg_enable = level; | ||
216 | } | ||
217 | |||
218 | static void sxgbe_get_strings(struct net_device *dev, u32 stringset, u8 *data) | ||
219 | { | ||
220 | int i; | ||
221 | u8 *p = data; | ||
222 | |||
223 | switch (stringset) { | ||
224 | case ETH_SS_STATS: | ||
225 | for (i = 0; i < SXGBE_STATS_LEN; i++) { | ||
226 | memcpy(p, sxgbe_gstrings_stats[i].stat_string, | ||
227 | ETH_GSTRING_LEN); | ||
228 | p += ETH_GSTRING_LEN; | ||
229 | } | ||
230 | break; | ||
231 | default: | ||
232 | WARN_ON(1); | ||
233 | break; | ||
234 | } | ||
235 | } | ||
236 | |||
237 | static int sxgbe_get_sset_count(struct net_device *netdev, int sset) | ||
238 | { | ||
239 | int len; | ||
240 | |||
241 | switch (sset) { | ||
242 | case ETH_SS_STATS: | ||
243 | len = SXGBE_STATS_LEN; | ||
244 | return len; | ||
245 | default: | ||
246 | return -EINVAL; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | static void sxgbe_get_ethtool_stats(struct net_device *dev, | ||
251 | struct ethtool_stats *dummy, u64 *data) | ||
252 | { | ||
253 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
254 | int i; | ||
255 | char *p; | ||
256 | |||
257 | if (priv->eee_enabled) { | ||
258 | int val = phy_get_eee_err(priv->phydev); | ||
259 | |||
260 | if (val) | ||
261 | priv->xstats.eee_wakeup_error_n = val; | ||
262 | } | ||
263 | |||
264 | for (i = 0; i < SXGBE_STATS_LEN; i++) { | ||
265 | p = (char *)priv + sxgbe_gstrings_stats[i].stat_offset; | ||
266 | data[i] = (sxgbe_gstrings_stats[i].sizeof_stat == sizeof(u64)) | ||
267 | ? (*(u64 *)p) : (*(u32 *)p); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | static void sxgbe_get_channels(struct net_device *dev, | ||
272 | struct ethtool_channels *channel) | ||
273 | { | ||
274 | channel->max_rx = SXGBE_MAX_RX_CHANNELS; | ||
275 | channel->max_tx = SXGBE_MAX_TX_CHANNELS; | ||
276 | channel->rx_count = SXGBE_RX_QUEUES; | ||
277 | channel->tx_count = SXGBE_TX_QUEUES; | ||
278 | } | ||
279 | |||
280 | static u32 sxgbe_riwt2usec(u32 riwt, struct sxgbe_priv_data *priv) | ||
281 | { | ||
282 | unsigned long clk = clk_get_rate(priv->sxgbe_clk); | ||
283 | |||
284 | if (!clk) | ||
285 | return 0; | ||
286 | |||
287 | return (riwt * 256) / (clk / 1000000); | ||
288 | } | ||
289 | |||
290 | static u32 sxgbe_usec2riwt(u32 usec, struct sxgbe_priv_data *priv) | ||
291 | { | ||
292 | unsigned long clk = clk_get_rate(priv->sxgbe_clk); | ||
293 | |||
294 | if (!clk) | ||
295 | return 0; | ||
296 | |||
297 | return (usec * (clk / 1000000)) / 256; | ||
298 | } | ||
299 | |||
300 | static int sxgbe_get_coalesce(struct net_device *dev, | ||
301 | struct ethtool_coalesce *ec) | ||
302 | { | ||
303 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
304 | |||
305 | if (priv->use_riwt) | ||
306 | ec->rx_coalesce_usecs = sxgbe_riwt2usec(priv->rx_riwt, priv); | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | static int sxgbe_set_coalesce(struct net_device *dev, | ||
312 | struct ethtool_coalesce *ec) | ||
313 | { | ||
314 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
315 | unsigned int rx_riwt; | ||
316 | |||
317 | if (!ec->rx_coalesce_usecs) | ||
318 | return -EINVAL; | ||
319 | |||
320 | rx_riwt = sxgbe_usec2riwt(ec->rx_coalesce_usecs, priv); | ||
321 | |||
322 | if ((rx_riwt > SXGBE_MAX_DMA_RIWT) || (rx_riwt < SXGBE_MIN_DMA_RIWT)) | ||
323 | return -EINVAL; | ||
324 | else if (!priv->use_riwt) | ||
325 | return -EOPNOTSUPP; | ||
326 | |||
327 | priv->rx_riwt = rx_riwt; | ||
328 | priv->hw->dma->rx_watchdog(priv->ioaddr, priv->rx_riwt); | ||
329 | |||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | static int sxgbe_get_rss_hash_opts(struct sxgbe_priv_data *priv, | ||
334 | struct ethtool_rxnfc *cmd) | ||
335 | { | ||
336 | cmd->data = 0; | ||
337 | |||
338 | /* Report default options for RSS on sxgbe */ | ||
339 | switch (cmd->flow_type) { | ||
340 | case TCP_V4_FLOW: | ||
341 | case UDP_V4_FLOW: | ||
342 | cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; | ||
343 | case SCTP_V4_FLOW: | ||
344 | case AH_ESP_V4_FLOW: | ||
345 | case AH_V4_FLOW: | ||
346 | case ESP_V4_FLOW: | ||
347 | case IPV4_FLOW: | ||
348 | cmd->data |= RXH_IP_SRC | RXH_IP_DST; | ||
349 | break; | ||
350 | case TCP_V6_FLOW: | ||
351 | case UDP_V6_FLOW: | ||
352 | cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; | ||
353 | case SCTP_V6_FLOW: | ||
354 | case AH_ESP_V6_FLOW: | ||
355 | case AH_V6_FLOW: | ||
356 | case ESP_V6_FLOW: | ||
357 | case IPV6_FLOW: | ||
358 | cmd->data |= RXH_IP_SRC | RXH_IP_DST; | ||
359 | break; | ||
360 | default: | ||
361 | return -EINVAL; | ||
362 | } | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static int sxgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, | ||
368 | u32 *rule_locs) | ||
369 | { | ||
370 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
371 | int ret = -EOPNOTSUPP; | ||
372 | |||
373 | switch (cmd->cmd) { | ||
374 | case ETHTOOL_GRXFH: | ||
375 | ret = sxgbe_get_rss_hash_opts(priv, cmd); | ||
376 | break; | ||
377 | default: | ||
378 | break; | ||
379 | } | ||
380 | |||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | static int sxgbe_set_rss_hash_opt(struct sxgbe_priv_data *priv, | ||
385 | struct ethtool_rxnfc *cmd) | ||
386 | { | ||
387 | u32 reg_val = 0; | ||
388 | |||
389 | /* RSS does not support anything other than hashing | ||
390 | * to queues on src and dst IPs and ports | ||
391 | */ | ||
392 | if (cmd->data & ~(RXH_IP_SRC | RXH_IP_DST | | ||
393 | RXH_L4_B_0_1 | RXH_L4_B_2_3)) | ||
394 | return -EINVAL; | ||
395 | |||
396 | switch (cmd->flow_type) { | ||
397 | case TCP_V4_FLOW: | ||
398 | case TCP_V6_FLOW: | ||
399 | if (!(cmd->data & RXH_IP_SRC) || | ||
400 | !(cmd->data & RXH_IP_DST) || | ||
401 | !(cmd->data & RXH_L4_B_0_1) || | ||
402 | !(cmd->data & RXH_L4_B_2_3)) | ||
403 | return -EINVAL; | ||
404 | reg_val = SXGBE_CORE_RSS_CTL_TCP4TE; | ||
405 | break; | ||
406 | case UDP_V4_FLOW: | ||
407 | case UDP_V6_FLOW: | ||
408 | if (!(cmd->data & RXH_IP_SRC) || | ||
409 | !(cmd->data & RXH_IP_DST) || | ||
410 | !(cmd->data & RXH_L4_B_0_1) || | ||
411 | !(cmd->data & RXH_L4_B_2_3)) | ||
412 | return -EINVAL; | ||
413 | reg_val = SXGBE_CORE_RSS_CTL_UDP4TE; | ||
414 | break; | ||
415 | case SCTP_V4_FLOW: | ||
416 | case AH_ESP_V4_FLOW: | ||
417 | case AH_V4_FLOW: | ||
418 | case ESP_V4_FLOW: | ||
419 | case AH_ESP_V6_FLOW: | ||
420 | case AH_V6_FLOW: | ||
421 | case ESP_V6_FLOW: | ||
422 | case SCTP_V6_FLOW: | ||
423 | case IPV4_FLOW: | ||
424 | case IPV6_FLOW: | ||
425 | if (!(cmd->data & RXH_IP_SRC) || | ||
426 | !(cmd->data & RXH_IP_DST) || | ||
427 | (cmd->data & RXH_L4_B_0_1) || | ||
428 | (cmd->data & RXH_L4_B_2_3)) | ||
429 | return -EINVAL; | ||
430 | reg_val = SXGBE_CORE_RSS_CTL_IP2TE; | ||
431 | break; | ||
432 | default: | ||
433 | return -EINVAL; | ||
434 | } | ||
435 | |||
436 | /* Read SXGBE RSS control register and update */ | ||
437 | reg_val |= readl(priv->ioaddr + SXGBE_CORE_RSS_CTL_REG); | ||
438 | writel(reg_val, priv->ioaddr + SXGBE_CORE_RSS_CTL_REG); | ||
439 | readl(priv->ioaddr + SXGBE_CORE_RSS_CTL_REG); | ||
440 | |||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | static int sxgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) | ||
445 | { | ||
446 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
447 | int ret = -EOPNOTSUPP; | ||
448 | |||
449 | switch (cmd->cmd) { | ||
450 | case ETHTOOL_SRXFH: | ||
451 | ret = sxgbe_set_rss_hash_opt(priv, cmd); | ||
452 | break; | ||
453 | default: | ||
454 | break; | ||
455 | } | ||
456 | |||
457 | return ret; | ||
458 | } | ||
459 | |||
460 | static void sxgbe_get_regs(struct net_device *dev, | ||
461 | struct ethtool_regs *regs, void *space) | ||
462 | { | ||
463 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
464 | u32 *reg_space = (u32 *)space; | ||
465 | int reg_offset; | ||
466 | int reg_ix = 0; | ||
467 | void __iomem *ioaddr = priv->ioaddr; | ||
468 | |||
469 | memset(reg_space, 0x0, REG_SPACE_SIZE); | ||
470 | |||
471 | /* MAC registers */ | ||
472 | for (reg_offset = START_MAC_REG_OFFSET; | ||
473 | reg_offset <= MAX_MAC_REG_OFFSET; reg_offset += 4) { | ||
474 | reg_space[reg_ix] = readl(ioaddr + reg_offset); | ||
475 | reg_ix++; | ||
476 | } | ||
477 | |||
478 | /* MTL registers */ | ||
479 | for (reg_offset = START_MTL_REG_OFFSET; | ||
480 | reg_offset <= MAX_MTL_REG_OFFSET; reg_offset += 4) { | ||
481 | reg_space[reg_ix] = readl(ioaddr + reg_offset); | ||
482 | reg_ix++; | ||
483 | } | ||
484 | |||
485 | /* DMA registers */ | ||
486 | for (reg_offset = START_DMA_REG_OFFSET; | ||
487 | reg_offset <= MAX_DMA_REG_OFFSET; reg_offset += 4) { | ||
488 | reg_space[reg_ix] = readl(ioaddr + reg_offset); | ||
489 | reg_ix++; | ||
490 | } | ||
491 | |||
492 | BUG_ON(reg_ix * 4 > REG_SPACE_SIZE); | ||
493 | } | ||
494 | |||
495 | static int sxgbe_get_regs_len(struct net_device *dev) | ||
496 | { | ||
497 | return REG_SPACE_SIZE; | ||
498 | } | ||
499 | |||
83 | static const struct ethtool_ops sxgbe_ethtool_ops = { | 500 | static const struct ethtool_ops sxgbe_ethtool_ops = { |
501 | .get_drvinfo = sxgbe_getdrvinfo, | ||
502 | .get_settings = sxgbe_getsettings, | ||
503 | .set_settings = sxgbe_setsettings, | ||
504 | .get_msglevel = sxgbe_getmsglevel, | ||
505 | .set_msglevel = sxgbe_setmsglevel, | ||
506 | .get_link = ethtool_op_get_link, | ||
507 | .get_strings = sxgbe_get_strings, | ||
508 | .get_ethtool_stats = sxgbe_get_ethtool_stats, | ||
509 | .get_sset_count = sxgbe_get_sset_count, | ||
510 | .get_channels = sxgbe_get_channels, | ||
511 | .get_coalesce = sxgbe_get_coalesce, | ||
512 | .set_coalesce = sxgbe_set_coalesce, | ||
513 | .get_rxnfc = sxgbe_get_rxnfc, | ||
514 | .set_rxnfc = sxgbe_set_rxnfc, | ||
515 | .get_regs = sxgbe_get_regs, | ||
516 | .get_regs_len = sxgbe_get_regs_len, | ||
84 | .get_eee = sxgbe_get_eee, | 517 | .get_eee = sxgbe_get_eee, |
85 | .set_eee = sxgbe_set_eee, | 518 | .set_eee = sxgbe_set_eee, |
86 | }; | 519 | }; |
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c index 96b4b2c25b16..1869d4c6e454 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c | |||
@@ -2139,6 +2139,10 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device, | |||
2139 | priv->rxcsum_insertion = true; | 2139 | priv->rxcsum_insertion = true; |
2140 | } | 2140 | } |
2141 | 2141 | ||
2142 | /* Initialise pause frame settings */ | ||
2143 | priv->rx_pause = 1; | ||
2144 | priv->tx_pause = 1; | ||
2145 | |||
2142 | /* Rx Watchdog is available, enable depend on platform data */ | 2146 | /* Rx Watchdog is available, enable depend on platform data */ |
2143 | if (!priv->plat->riwt_off) { | 2147 | if (!priv->plat->riwt_off) { |
2144 | priv->use_riwt = 1; | 2148 | priv->use_riwt = 1; |
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h index 85a7b3104a1a..5a89acb4c505 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h | |||
@@ -195,6 +195,12 @@ | |||
195 | #define SXGBE_CORE_RSS_ADD_REG 0x0C88 | 195 | #define SXGBE_CORE_RSS_ADD_REG 0x0C88 |
196 | #define SXGBE_CORE_RSS_DATA_REG 0x0C8C | 196 | #define SXGBE_CORE_RSS_DATA_REG 0x0C8C |
197 | 197 | ||
198 | /* RSS control register bits */ | ||
199 | #define SXGBE_CORE_RSS_CTL_UDP4TE BIT(3) | ||
200 | #define SXGBE_CORE_RSS_CTL_TCP4TE BIT(2) | ||
201 | #define SXGBE_CORE_RSS_CTL_IP2TE BIT(1) | ||
202 | #define SXGBE_CORE_RSS_CTL_RSSE BIT(0) | ||
203 | |||
198 | /* IEEE 1588 registers */ | 204 | /* IEEE 1588 registers */ |
199 | #define SXGBE_CORE_TSTAMP_CTL_REG 0x0D00 | 205 | #define SXGBE_CORE_TSTAMP_CTL_REG 0x0D00 |
200 | #define SXGBE_CORE_SUBSEC_INC_REG 0x0D04 | 206 | #define SXGBE_CORE_SUBSEC_INC_REG 0x0D04 |