xref: /linux/drivers/net/ethernet/freescale/gianfar_ethtool.c (revision 9410645520e9b820069761f3450ef6661418e279)
1754460a4SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2ec21e2ecSJeff Kirsher /*
33396c782SPaul Gortmaker  *  drivers/net/ethernet/freescale/gianfar_ethtool.c
4ec21e2ecSJeff Kirsher  *
5ec21e2ecSJeff Kirsher  *  Gianfar Ethernet Driver
6ec21e2ecSJeff Kirsher  *  Ethtool support for Gianfar Enet
7ec21e2ecSJeff Kirsher  *  Based on e1000 ethtool support
8ec21e2ecSJeff Kirsher  *
9ec21e2ecSJeff Kirsher  *  Author: Andy Fleming
10ec21e2ecSJeff Kirsher  *  Maintainer: Kumar Gala
11ec21e2ecSJeff Kirsher  *  Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
12ec21e2ecSJeff Kirsher  *
13ec21e2ecSJeff Kirsher  *  Copyright 2003-2006, 2008-2009, 2011 Freescale Semiconductor, Inc.
14ec21e2ecSJeff Kirsher  */
15ec21e2ecSJeff Kirsher 
16ec21e2ecSJeff Kirsher #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17ec21e2ecSJeff Kirsher 
18ec21e2ecSJeff Kirsher #include <linux/kernel.h>
19ec21e2ecSJeff Kirsher #include <linux/string.h>
20ec21e2ecSJeff Kirsher #include <linux/errno.h>
21ec21e2ecSJeff Kirsher #include <linux/interrupt.h>
22ec21e2ecSJeff Kirsher #include <linux/delay.h>
23ec21e2ecSJeff Kirsher #include <linux/netdevice.h>
24ec21e2ecSJeff Kirsher #include <linux/etherdevice.h>
2565a85a8dSDavid S. Miller #include <linux/net_tstamp.h>
26ec21e2ecSJeff Kirsher #include <linux/skbuff.h>
27ec21e2ecSJeff Kirsher #include <linux/spinlock.h>
28ec21e2ecSJeff Kirsher #include <linux/mm.h>
29ec21e2ecSJeff Kirsher 
30ec21e2ecSJeff Kirsher #include <asm/io.h>
31ec21e2ecSJeff Kirsher #include <asm/irq.h>
327c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
33ec21e2ecSJeff Kirsher #include <linux/module.h>
34ec21e2ecSJeff Kirsher #include <linux/crc32.h>
35ec21e2ecSJeff Kirsher #include <asm/types.h>
36ec21e2ecSJeff Kirsher #include <linux/ethtool.h>
37ec21e2ecSJeff Kirsher #include <linux/mii.h>
38ec21e2ecSJeff Kirsher #include <linux/phy.h>
39ec21e2ecSJeff Kirsher #include <linux/sort.h>
40ec21e2ecSJeff Kirsher #include <linux/if_vlan.h>
413d40aed8SRob Herring #include <linux/of.h>
427349a74eSYangbo Lu #include <linux/of_platform.h>
433d40aed8SRob Herring #include <linux/platform_device.h>
447349a74eSYangbo Lu #include <linux/fsl/ptp_qoriq.h>
45ec21e2ecSJeff Kirsher 
46ec21e2ecSJeff Kirsher #include "gianfar.h"
47ec21e2ecSJeff Kirsher 
48ec21e2ecSJeff Kirsher #define GFAR_MAX_COAL_USECS 0xffff
49ec21e2ecSJeff Kirsher #define GFAR_MAX_COAL_FRAMES 0xff
50ec21e2ecSJeff Kirsher 
5130f7e310SPaul Gortmaker static const char stat_gstrings[][ETH_GSTRING_LEN] = {
5276f31e8bSClaudiu Manoil 	/* extra stats */
5376f31e8bSClaudiu Manoil 	"rx-allocation-errors",
54ec21e2ecSJeff Kirsher 	"rx-large-frame-errors",
55ec21e2ecSJeff Kirsher 	"rx-short-frame-errors",
56ec21e2ecSJeff Kirsher 	"rx-non-octet-errors",
57ec21e2ecSJeff Kirsher 	"rx-crc-errors",
58ec21e2ecSJeff Kirsher 	"rx-overrun-errors",
59ec21e2ecSJeff Kirsher 	"rx-busy-errors",
60ec21e2ecSJeff Kirsher 	"rx-babbling-errors",
61ec21e2ecSJeff Kirsher 	"rx-truncated-frames",
62ec21e2ecSJeff Kirsher 	"ethernet-bus-error",
63ec21e2ecSJeff Kirsher 	"tx-babbling-errors",
64ec21e2ecSJeff Kirsher 	"tx-underrun-errors",
65ec21e2ecSJeff Kirsher 	"tx-timeout-errors",
6676f31e8bSClaudiu Manoil 	/* rmon stats */
67ec21e2ecSJeff Kirsher 	"tx-rx-64-frames",
68ec21e2ecSJeff Kirsher 	"tx-rx-65-127-frames",
69ec21e2ecSJeff Kirsher 	"tx-rx-128-255-frames",
70ec21e2ecSJeff Kirsher 	"tx-rx-256-511-frames",
71ec21e2ecSJeff Kirsher 	"tx-rx-512-1023-frames",
72ec21e2ecSJeff Kirsher 	"tx-rx-1024-1518-frames",
73ec21e2ecSJeff Kirsher 	"tx-rx-1519-1522-good-vlan",
74ec21e2ecSJeff Kirsher 	"rx-bytes",
75ec21e2ecSJeff Kirsher 	"rx-packets",
76ec21e2ecSJeff Kirsher 	"rx-fcs-errors",
77ec21e2ecSJeff Kirsher 	"receive-multicast-packet",
78ec21e2ecSJeff Kirsher 	"receive-broadcast-packet",
79ec21e2ecSJeff Kirsher 	"rx-control-frame-packets",
80ec21e2ecSJeff Kirsher 	"rx-pause-frame-packets",
81ec21e2ecSJeff Kirsher 	"rx-unknown-op-code",
82ec21e2ecSJeff Kirsher 	"rx-alignment-error",
83ec21e2ecSJeff Kirsher 	"rx-frame-length-error",
84ec21e2ecSJeff Kirsher 	"rx-code-error",
85ec21e2ecSJeff Kirsher 	"rx-carrier-sense-error",
86ec21e2ecSJeff Kirsher 	"rx-undersize-packets",
87ec21e2ecSJeff Kirsher 	"rx-oversize-packets",
88ec21e2ecSJeff Kirsher 	"rx-fragmented-frames",
89ec21e2ecSJeff Kirsher 	"rx-jabber-frames",
90ec21e2ecSJeff Kirsher 	"rx-dropped-frames",
91ec21e2ecSJeff Kirsher 	"tx-byte-counter",
92ec21e2ecSJeff Kirsher 	"tx-packets",
93ec21e2ecSJeff Kirsher 	"tx-multicast-packets",
94ec21e2ecSJeff Kirsher 	"tx-broadcast-packets",
95ec21e2ecSJeff Kirsher 	"tx-pause-control-frames",
96ec21e2ecSJeff Kirsher 	"tx-deferral-packets",
97ec21e2ecSJeff Kirsher 	"tx-excessive-deferral-packets",
98ec21e2ecSJeff Kirsher 	"tx-single-collision-packets",
99ec21e2ecSJeff Kirsher 	"tx-multiple-collision-packets",
100ec21e2ecSJeff Kirsher 	"tx-late-collision-packets",
101ec21e2ecSJeff Kirsher 	"tx-excessive-collision-packets",
102ec21e2ecSJeff Kirsher 	"tx-total-collision",
103ec21e2ecSJeff Kirsher 	"reserved",
104ec21e2ecSJeff Kirsher 	"tx-dropped-frames",
105ec21e2ecSJeff Kirsher 	"tx-jabber-frames",
106ec21e2ecSJeff Kirsher 	"tx-fcs-errors",
107ec21e2ecSJeff Kirsher 	"tx-control-frames",
108ec21e2ecSJeff Kirsher 	"tx-oversize-frames",
109ec21e2ecSJeff Kirsher 	"tx-undersize-frames",
110ec21e2ecSJeff Kirsher 	"tx-fragmented-frames",
111ec21e2ecSJeff Kirsher };
112ec21e2ecSJeff Kirsher 
113ec21e2ecSJeff Kirsher /* Fill in a buffer with the strings which correspond to the
114ec21e2ecSJeff Kirsher  * stats */
gfar_gstrings(struct net_device * dev,u32 stringset,u8 * buf)115ec21e2ecSJeff Kirsher static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf)
116ec21e2ecSJeff Kirsher {
117ec21e2ecSJeff Kirsher 	struct gfar_private *priv = netdev_priv(dev);
118ec21e2ecSJeff Kirsher 
119ec21e2ecSJeff Kirsher 	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON)
120ec21e2ecSJeff Kirsher 		memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN);
121ec21e2ecSJeff Kirsher 	else
122ec21e2ecSJeff Kirsher 		memcpy(buf, stat_gstrings,
123ec21e2ecSJeff Kirsher 		       GFAR_EXTRA_STATS_LEN * ETH_GSTRING_LEN);
124ec21e2ecSJeff Kirsher }
125ec21e2ecSJeff Kirsher 
126ec21e2ecSJeff Kirsher /* Fill in an array of 64-bit statistics from various sources.
127ec21e2ecSJeff Kirsher  * This array will be appended to the end of the ethtool_stats
128ec21e2ecSJeff Kirsher  * structure, and returned to user space
129ec21e2ecSJeff Kirsher  */
gfar_fill_stats(struct net_device * dev,struct ethtool_stats * dummy,u64 * buf)130cbfc6071SJan Ceuleers static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
131cbfc6071SJan Ceuleers 			    u64 *buf)
132ec21e2ecSJeff Kirsher {
133ec21e2ecSJeff Kirsher 	int i;
134ec21e2ecSJeff Kirsher 	struct gfar_private *priv = netdev_priv(dev);
135ec21e2ecSJeff Kirsher 	struct gfar __iomem *regs = priv->gfargrp[0].regs;
136212079dfSPaul Gortmaker 	atomic64_t *extra = (atomic64_t *)&priv->extra_stats;
137ec21e2ecSJeff Kirsher 
138ec21e2ecSJeff Kirsher 	for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++)
139212079dfSPaul Gortmaker 		buf[i] = atomic64_read(&extra[i]);
14068719786SPaul Gortmaker 
14168719786SPaul Gortmaker 	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
14268719786SPaul Gortmaker 		u32 __iomem *rmon = (u32 __iomem *) &regs->rmon;
14368719786SPaul Gortmaker 
14468719786SPaul Gortmaker 		for (; i < GFAR_STATS_LEN; i++, rmon++)
14568719786SPaul Gortmaker 			buf[i] = (u64) gfar_read(rmon);
14668719786SPaul Gortmaker 	}
147ec21e2ecSJeff Kirsher }
148ec21e2ecSJeff Kirsher 
gfar_sset_count(struct net_device * dev,int sset)149ec21e2ecSJeff Kirsher static int gfar_sset_count(struct net_device *dev, int sset)
150ec21e2ecSJeff Kirsher {
151ec21e2ecSJeff Kirsher 	struct gfar_private *priv = netdev_priv(dev);
152ec21e2ecSJeff Kirsher 
153ec21e2ecSJeff Kirsher 	switch (sset) {
154ec21e2ecSJeff Kirsher 	case ETH_SS_STATS:
155ec21e2ecSJeff Kirsher 		if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON)
156ec21e2ecSJeff Kirsher 			return GFAR_STATS_LEN;
157ec21e2ecSJeff Kirsher 		else
158ec21e2ecSJeff Kirsher 			return GFAR_EXTRA_STATS_LEN;
159ec21e2ecSJeff Kirsher 	default:
160ec21e2ecSJeff Kirsher 		return -EOPNOTSUPP;
161ec21e2ecSJeff Kirsher 	}
162ec21e2ecSJeff Kirsher }
163ec21e2ecSJeff Kirsher 
164ec21e2ecSJeff Kirsher /* Fills in the drvinfo structure with some basic info */
gfar_gdrvinfo(struct net_device * dev,struct ethtool_drvinfo * drvinfo)165cbfc6071SJan Ceuleers static void gfar_gdrvinfo(struct net_device *dev,
166cbfc6071SJan Ceuleers 			  struct ethtool_drvinfo *drvinfo)
167ec21e2ecSJeff Kirsher {
168f029c781SWolfram Sang 	strscpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
169ec21e2ecSJeff Kirsher }
170ec21e2ecSJeff Kirsher 
171ec21e2ecSJeff Kirsher /* Return the length of the register structure */
gfar_reglen(struct net_device * dev)172ec21e2ecSJeff Kirsher static int gfar_reglen(struct net_device *dev)
173ec21e2ecSJeff Kirsher {
174ec21e2ecSJeff Kirsher 	return sizeof (struct gfar);
175ec21e2ecSJeff Kirsher }
176ec21e2ecSJeff Kirsher 
177ec21e2ecSJeff Kirsher /* Return a dump of the GFAR register space */
gfar_get_regs(struct net_device * dev,struct ethtool_regs * regs,void * regbuf)178cbfc6071SJan Ceuleers static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs,
179cbfc6071SJan Ceuleers 			  void *regbuf)
180ec21e2ecSJeff Kirsher {
181ec21e2ecSJeff Kirsher 	int i;
182ec21e2ecSJeff Kirsher 	struct gfar_private *priv = netdev_priv(dev);
183ec21e2ecSJeff Kirsher 	u32 __iomem *theregs = (u32 __iomem *) priv->gfargrp[0].regs;
184ec21e2ecSJeff Kirsher 	u32 *buf = (u32 *) regbuf;
185ec21e2ecSJeff Kirsher 
186ec21e2ecSJeff Kirsher 	for (i = 0; i < sizeof (struct gfar) / sizeof (u32); i++)
187ec21e2ecSJeff Kirsher 		buf[i] = gfar_read(&theregs[i]);
188ec21e2ecSJeff Kirsher }
189ec21e2ecSJeff Kirsher 
190ec21e2ecSJeff Kirsher /* Convert microseconds to ethernet clock ticks, which changes
191ec21e2ecSJeff Kirsher  * depending on what speed the controller is running at */
gfar_usecs2ticks(struct gfar_private * priv,unsigned int usecs)192cbfc6071SJan Ceuleers static unsigned int gfar_usecs2ticks(struct gfar_private *priv,
193cbfc6071SJan Ceuleers 				     unsigned int usecs)
194ec21e2ecSJeff Kirsher {
1954c4a6b0eSPhilippe Reynes 	struct net_device *ndev = priv->ndev;
1964c4a6b0eSPhilippe Reynes 	struct phy_device *phydev = ndev->phydev;
197ec21e2ecSJeff Kirsher 	unsigned int count;
198ec21e2ecSJeff Kirsher 
199ec21e2ecSJeff Kirsher 	/* The timer is different, depending on the interface speed */
2004c4a6b0eSPhilippe Reynes 	switch (phydev->speed) {
201ec21e2ecSJeff Kirsher 	case SPEED_1000:
202ec21e2ecSJeff Kirsher 		count = GFAR_GBIT_TIME;
203ec21e2ecSJeff Kirsher 		break;
204ec21e2ecSJeff Kirsher 	case SPEED_100:
205ec21e2ecSJeff Kirsher 		count = GFAR_100_TIME;
206ec21e2ecSJeff Kirsher 		break;
207ec21e2ecSJeff Kirsher 	case SPEED_10:
208ec21e2ecSJeff Kirsher 	default:
209ec21e2ecSJeff Kirsher 		count = GFAR_10_TIME;
210ec21e2ecSJeff Kirsher 		break;
211ec21e2ecSJeff Kirsher 	}
212ec21e2ecSJeff Kirsher 
213ec21e2ecSJeff Kirsher 	/* Make sure we return a number greater than 0
214ec21e2ecSJeff Kirsher 	 * if usecs > 0 */
215f8a1988fSzhong jiang 	return DIV_ROUND_UP(usecs * 1000, count);
216ec21e2ecSJeff Kirsher }
217ec21e2ecSJeff Kirsher 
218ec21e2ecSJeff Kirsher /* Convert ethernet clock ticks to microseconds */
gfar_ticks2usecs(struct gfar_private * priv,unsigned int ticks)219cbfc6071SJan Ceuleers static unsigned int gfar_ticks2usecs(struct gfar_private *priv,
220cbfc6071SJan Ceuleers 				     unsigned int ticks)
221ec21e2ecSJeff Kirsher {
2224c4a6b0eSPhilippe Reynes 	struct net_device *ndev = priv->ndev;
2234c4a6b0eSPhilippe Reynes 	struct phy_device *phydev = ndev->phydev;
224ec21e2ecSJeff Kirsher 	unsigned int count;
225ec21e2ecSJeff Kirsher 
226ec21e2ecSJeff Kirsher 	/* The timer is different, depending on the interface speed */
2274c4a6b0eSPhilippe Reynes 	switch (phydev->speed) {
228ec21e2ecSJeff Kirsher 	case SPEED_1000:
229ec21e2ecSJeff Kirsher 		count = GFAR_GBIT_TIME;
230ec21e2ecSJeff Kirsher 		break;
231ec21e2ecSJeff Kirsher 	case SPEED_100:
232ec21e2ecSJeff Kirsher 		count = GFAR_100_TIME;
233ec21e2ecSJeff Kirsher 		break;
234ec21e2ecSJeff Kirsher 	case SPEED_10:
235ec21e2ecSJeff Kirsher 	default:
236ec21e2ecSJeff Kirsher 		count = GFAR_10_TIME;
237ec21e2ecSJeff Kirsher 		break;
238ec21e2ecSJeff Kirsher 	}
239ec21e2ecSJeff Kirsher 
240ec21e2ecSJeff Kirsher 	/* Make sure we return a number greater than 0 */
241ec21e2ecSJeff Kirsher 	/* if ticks is > 0 */
242ec21e2ecSJeff Kirsher 	return (ticks * count) / 1000;
243ec21e2ecSJeff Kirsher }
244ec21e2ecSJeff Kirsher 
245ec21e2ecSJeff Kirsher /* Get the coalescing parameters, and put them in the cvals
246ec21e2ecSJeff Kirsher  * structure.  */
gfar_gcoalesce(struct net_device * dev,struct ethtool_coalesce * cvals,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)247cbfc6071SJan Ceuleers static int gfar_gcoalesce(struct net_device *dev,
248f3ccfda1SYufeng Mo 			  struct ethtool_coalesce *cvals,
249f3ccfda1SYufeng Mo 			  struct kernel_ethtool_coalesce *kernel_coal,
250f3ccfda1SYufeng Mo 			  struct netlink_ext_ack *extack)
251ec21e2ecSJeff Kirsher {
252ec21e2ecSJeff Kirsher 	struct gfar_private *priv = netdev_priv(dev);
253ec21e2ecSJeff Kirsher 	struct gfar_priv_rx_q *rx_queue = NULL;
254ec21e2ecSJeff Kirsher 	struct gfar_priv_tx_q *tx_queue = NULL;
255ec21e2ecSJeff Kirsher 	unsigned long rxtime;
256ec21e2ecSJeff Kirsher 	unsigned long rxcount;
257ec21e2ecSJeff Kirsher 	unsigned long txtime;
258ec21e2ecSJeff Kirsher 	unsigned long txcount;
259ec21e2ecSJeff Kirsher 
260ec21e2ecSJeff Kirsher 	if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
261ec21e2ecSJeff Kirsher 		return -EOPNOTSUPP;
262ec21e2ecSJeff Kirsher 
2634c4a6b0eSPhilippe Reynes 	if (!dev->phydev)
264ec21e2ecSJeff Kirsher 		return -ENODEV;
265ec21e2ecSJeff Kirsher 
266ec21e2ecSJeff Kirsher 	rx_queue = priv->rx_queue[0];
267ec21e2ecSJeff Kirsher 	tx_queue = priv->tx_queue[0];
268ec21e2ecSJeff Kirsher 
269ec21e2ecSJeff Kirsher 	rxtime  = get_ictt_value(rx_queue->rxic);
270ec21e2ecSJeff Kirsher 	rxcount = get_icft_value(rx_queue->rxic);
271ec21e2ecSJeff Kirsher 	txtime  = get_ictt_value(tx_queue->txic);
272ec21e2ecSJeff Kirsher 	txcount = get_icft_value(tx_queue->txic);
273ec21e2ecSJeff Kirsher 	cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, rxtime);
274ec21e2ecSJeff Kirsher 	cvals->rx_max_coalesced_frames = rxcount;
275ec21e2ecSJeff Kirsher 
276ec21e2ecSJeff Kirsher 	cvals->tx_coalesce_usecs = gfar_ticks2usecs(priv, txtime);
277ec21e2ecSJeff Kirsher 	cvals->tx_max_coalesced_frames = txcount;
278ec21e2ecSJeff Kirsher 
279ec21e2ecSJeff Kirsher 	return 0;
280ec21e2ecSJeff Kirsher }
281ec21e2ecSJeff Kirsher 
282ec21e2ecSJeff Kirsher /* Change the coalescing values.
283ec21e2ecSJeff Kirsher  * Both cvals->*_usecs and cvals->*_frames have to be > 0
284ec21e2ecSJeff Kirsher  * in order for coalescing to be active
285ec21e2ecSJeff Kirsher  */
gfar_scoalesce(struct net_device * dev,struct ethtool_coalesce * cvals,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)286cbfc6071SJan Ceuleers static int gfar_scoalesce(struct net_device *dev,
287f3ccfda1SYufeng Mo 			  struct ethtool_coalesce *cvals,
288f3ccfda1SYufeng Mo 			  struct kernel_ethtool_coalesce *kernel_coal,
289f3ccfda1SYufeng Mo 			  struct netlink_ext_ack *extack)
290ec21e2ecSJeff Kirsher {
291ec21e2ecSJeff Kirsher 	struct gfar_private *priv = netdev_priv(dev);
292f19015baSClaudiu Manoil 	int i, err = 0;
293ec21e2ecSJeff Kirsher 
294ec21e2ecSJeff Kirsher 	if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
295ec21e2ecSJeff Kirsher 		return -EOPNOTSUPP;
296ec21e2ecSJeff Kirsher 
2974c4a6b0eSPhilippe Reynes 	if (!dev->phydev)
298ec21e2ecSJeff Kirsher 		return -ENODEV;
299ec21e2ecSJeff Kirsher 
300ec21e2ecSJeff Kirsher 	/* Check the bounds of the values */
301ec21e2ecSJeff Kirsher 	if (cvals->rx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
302375d6a1bSJoe Perches 		netdev_info(dev, "Coalescing is limited to %d microseconds\n",
303ec21e2ecSJeff Kirsher 			    GFAR_MAX_COAL_USECS);
304ec21e2ecSJeff Kirsher 		return -EINVAL;
305ec21e2ecSJeff Kirsher 	}
306ec21e2ecSJeff Kirsher 
307ec21e2ecSJeff Kirsher 	if (cvals->rx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
308375d6a1bSJoe Perches 		netdev_info(dev, "Coalescing is limited to %d frames\n",
309ec21e2ecSJeff Kirsher 			    GFAR_MAX_COAL_FRAMES);
310ec21e2ecSJeff Kirsher 		return -EINVAL;
311ec21e2ecSJeff Kirsher 	}
312ec21e2ecSJeff Kirsher 
313f19015baSClaudiu Manoil 	/* Check the bounds of the values */
314f19015baSClaudiu Manoil 	if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
315f19015baSClaudiu Manoil 		netdev_info(dev, "Coalescing is limited to %d microseconds\n",
316f19015baSClaudiu Manoil 			    GFAR_MAX_COAL_USECS);
317f19015baSClaudiu Manoil 		return -EINVAL;
318f19015baSClaudiu Manoil 	}
319f19015baSClaudiu Manoil 
320f19015baSClaudiu Manoil 	if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
321f19015baSClaudiu Manoil 		netdev_info(dev, "Coalescing is limited to %d frames\n",
322f19015baSClaudiu Manoil 			    GFAR_MAX_COAL_FRAMES);
323f19015baSClaudiu Manoil 		return -EINVAL;
324f19015baSClaudiu Manoil 	}
325f19015baSClaudiu Manoil 
326f19015baSClaudiu Manoil 	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
327f19015baSClaudiu Manoil 		cpu_relax();
328f19015baSClaudiu Manoil 
329f19015baSClaudiu Manoil 	/* Set up rx coalescing */
330f19015baSClaudiu Manoil 	if ((cvals->rx_coalesce_usecs == 0) ||
331f19015baSClaudiu Manoil 	    (cvals->rx_max_coalesced_frames == 0)) {
332f19015baSClaudiu Manoil 		for (i = 0; i < priv->num_rx_queues; i++)
333f19015baSClaudiu Manoil 			priv->rx_queue[i]->rxcoalescing = 0;
334f19015baSClaudiu Manoil 	} else {
335f19015baSClaudiu Manoil 		for (i = 0; i < priv->num_rx_queues; i++)
336f19015baSClaudiu Manoil 			priv->rx_queue[i]->rxcoalescing = 1;
337f19015baSClaudiu Manoil 	}
338f19015baSClaudiu Manoil 
339ec21e2ecSJeff Kirsher 	for (i = 0; i < priv->num_rx_queues; i++) {
340ec21e2ecSJeff Kirsher 		priv->rx_queue[i]->rxic = mk_ic_value(
341ec21e2ecSJeff Kirsher 			cvals->rx_max_coalesced_frames,
342ec21e2ecSJeff Kirsher 			gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs));
343ec21e2ecSJeff Kirsher 	}
344ec21e2ecSJeff Kirsher 
345ec21e2ecSJeff Kirsher 	/* Set up tx coalescing */
346ec21e2ecSJeff Kirsher 	if ((cvals->tx_coalesce_usecs == 0) ||
347ec21e2ecSJeff Kirsher 	    (cvals->tx_max_coalesced_frames == 0)) {
348ec21e2ecSJeff Kirsher 		for (i = 0; i < priv->num_tx_queues; i++)
349ec21e2ecSJeff Kirsher 			priv->tx_queue[i]->txcoalescing = 0;
350ec21e2ecSJeff Kirsher 	} else {
351ec21e2ecSJeff Kirsher 		for (i = 0; i < priv->num_tx_queues; i++)
352ec21e2ecSJeff Kirsher 			priv->tx_queue[i]->txcoalescing = 1;
353ec21e2ecSJeff Kirsher 	}
354ec21e2ecSJeff Kirsher 
355ec21e2ecSJeff Kirsher 	for (i = 0; i < priv->num_tx_queues; i++) {
356ec21e2ecSJeff Kirsher 		priv->tx_queue[i]->txic = mk_ic_value(
357ec21e2ecSJeff Kirsher 			cvals->tx_max_coalesced_frames,
358ec21e2ecSJeff Kirsher 			gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs));
359ec21e2ecSJeff Kirsher 	}
360ec21e2ecSJeff Kirsher 
361f19015baSClaudiu Manoil 	if (dev->flags & IFF_UP) {
362f19015baSClaudiu Manoil 		stop_gfar(dev);
363f19015baSClaudiu Manoil 		err = startup_gfar(dev);
364f19015baSClaudiu Manoil 	} else {
365f19015baSClaudiu Manoil 		gfar_mac_reset(priv);
366f19015baSClaudiu Manoil 	}
367ec21e2ecSJeff Kirsher 
368f19015baSClaudiu Manoil 	clear_bit_unlock(GFAR_RESETTING, &priv->state);
369f19015baSClaudiu Manoil 
370f19015baSClaudiu Manoil 	return err;
371ec21e2ecSJeff Kirsher }
372ec21e2ecSJeff Kirsher 
373ec21e2ecSJeff Kirsher /* Fills in rvals with the current ring parameters.  Currently,
374ec21e2ecSJeff Kirsher  * rx, rx_mini, and rx_jumbo rings are the same size, as mini and
375ec21e2ecSJeff Kirsher  * jumbo are ignored by the driver */
gfar_gringparam(struct net_device * dev,struct ethtool_ringparam * rvals,struct kernel_ethtool_ringparam * kernel_rvals,struct netlink_ext_ack * extack)376cbfc6071SJan Ceuleers static void gfar_gringparam(struct net_device *dev,
37774624944SHao Chen 			    struct ethtool_ringparam *rvals,
37874624944SHao Chen 			    struct kernel_ethtool_ringparam *kernel_rvals,
37974624944SHao Chen 			    struct netlink_ext_ack *extack)
380ec21e2ecSJeff Kirsher {
381ec21e2ecSJeff Kirsher 	struct gfar_private *priv = netdev_priv(dev);
382ec21e2ecSJeff Kirsher 	struct gfar_priv_tx_q *tx_queue = NULL;
383ec21e2ecSJeff Kirsher 	struct gfar_priv_rx_q *rx_queue = NULL;
384ec21e2ecSJeff Kirsher 
385ec21e2ecSJeff Kirsher 	tx_queue = priv->tx_queue[0];
386ec21e2ecSJeff Kirsher 	rx_queue = priv->rx_queue[0];
387ec21e2ecSJeff Kirsher 
388ec21e2ecSJeff Kirsher 	rvals->rx_max_pending = GFAR_RX_MAX_RING_SIZE;
389ec21e2ecSJeff Kirsher 	rvals->rx_mini_max_pending = GFAR_RX_MAX_RING_SIZE;
390ec21e2ecSJeff Kirsher 	rvals->rx_jumbo_max_pending = GFAR_RX_MAX_RING_SIZE;
391ec21e2ecSJeff Kirsher 	rvals->tx_max_pending = GFAR_TX_MAX_RING_SIZE;
392ec21e2ecSJeff Kirsher 
393ec21e2ecSJeff Kirsher 	/* Values changeable by the user.  The valid values are
394ec21e2ecSJeff Kirsher 	 * in the range 1 to the "*_max_pending" counterpart above.
395ec21e2ecSJeff Kirsher 	 */
396ec21e2ecSJeff Kirsher 	rvals->rx_pending = rx_queue->rx_ring_size;
397ec21e2ecSJeff Kirsher 	rvals->rx_mini_pending = rx_queue->rx_ring_size;
398ec21e2ecSJeff Kirsher 	rvals->rx_jumbo_pending = rx_queue->rx_ring_size;
399ec21e2ecSJeff Kirsher 	rvals->tx_pending = tx_queue->tx_ring_size;
400ec21e2ecSJeff Kirsher }
401ec21e2ecSJeff Kirsher 
402ec21e2ecSJeff Kirsher /* Change the current ring parameters, stopping the controller if
4037cca336aSClaudiu Manoil  * necessary so that we don't mess things up while we're in motion.
404cbfc6071SJan Ceuleers  */
gfar_sringparam(struct net_device * dev,struct ethtool_ringparam * rvals,struct kernel_ethtool_ringparam * kernel_rvals,struct netlink_ext_ack * extack)405cbfc6071SJan Ceuleers static int gfar_sringparam(struct net_device *dev,
40674624944SHao Chen 			   struct ethtool_ringparam *rvals,
40774624944SHao Chen 			   struct kernel_ethtool_ringparam *kernel_rvals,
40874624944SHao Chen 			   struct netlink_ext_ack *extack)
409ec21e2ecSJeff Kirsher {
410ec21e2ecSJeff Kirsher 	struct gfar_private *priv = netdev_priv(dev);
4117cca336aSClaudiu Manoil 	int err = 0, i;
412ec21e2ecSJeff Kirsher 
413ec21e2ecSJeff Kirsher 	if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE)
414ec21e2ecSJeff Kirsher 		return -EINVAL;
415ec21e2ecSJeff Kirsher 
416ec21e2ecSJeff Kirsher 	if (!is_power_of_2(rvals->rx_pending)) {
417ec21e2ecSJeff Kirsher 		netdev_err(dev, "Ring sizes must be a power of 2\n");
418ec21e2ecSJeff Kirsher 		return -EINVAL;
419ec21e2ecSJeff Kirsher 	}
420ec21e2ecSJeff Kirsher 
421ec21e2ecSJeff Kirsher 	if (rvals->tx_pending > GFAR_TX_MAX_RING_SIZE)
422ec21e2ecSJeff Kirsher 		return -EINVAL;
423ec21e2ecSJeff Kirsher 
424ec21e2ecSJeff Kirsher 	if (!is_power_of_2(rvals->tx_pending)) {
425ec21e2ecSJeff Kirsher 		netdev_err(dev, "Ring sizes must be a power of 2\n");
426ec21e2ecSJeff Kirsher 		return -EINVAL;
427ec21e2ecSJeff Kirsher 	}
428ec21e2ecSJeff Kirsher 
4290851133bSClaudiu Manoil 	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
4300851133bSClaudiu Manoil 		cpu_relax();
4310851133bSClaudiu Manoil 
4327cca336aSClaudiu Manoil 	if (dev->flags & IFF_UP)
433ec21e2ecSJeff Kirsher 		stop_gfar(dev);
434ec21e2ecSJeff Kirsher 
4357cca336aSClaudiu Manoil 	/* Change the sizes */
4367cca336aSClaudiu Manoil 	for (i = 0; i < priv->num_rx_queues; i++)
437ec21e2ecSJeff Kirsher 		priv->rx_queue[i]->rx_ring_size = rvals->rx_pending;
4387cca336aSClaudiu Manoil 
4397cca336aSClaudiu Manoil 	for (i = 0; i < priv->num_tx_queues; i++)
440ec21e2ecSJeff Kirsher 		priv->tx_queue[i]->tx_ring_size = rvals->tx_pending;
441ec21e2ecSJeff Kirsher 
442ec21e2ecSJeff Kirsher 	/* Rebuild the rings with the new size */
4430851133bSClaudiu Manoil 	if (dev->flags & IFF_UP)
444ec21e2ecSJeff Kirsher 		err = startup_gfar(dev);
4450851133bSClaudiu Manoil 
4460851133bSClaudiu Manoil 	clear_bit_unlock(GFAR_RESETTING, &priv->state);
4470851133bSClaudiu Manoil 
448ec21e2ecSJeff Kirsher 	return err;
449ec21e2ecSJeff Kirsher }
450ec21e2ecSJeff Kirsher 
gfar_gpauseparam(struct net_device * dev,struct ethtool_pauseparam * epause)45123402bddSClaudiu Manoil static void gfar_gpauseparam(struct net_device *dev,
45223402bddSClaudiu Manoil 			     struct ethtool_pauseparam *epause)
45323402bddSClaudiu Manoil {
45423402bddSClaudiu Manoil 	struct gfar_private *priv = netdev_priv(dev);
45523402bddSClaudiu Manoil 
45623402bddSClaudiu Manoil 	epause->autoneg = !!priv->pause_aneg_en;
45723402bddSClaudiu Manoil 	epause->rx_pause = !!priv->rx_pause_en;
45823402bddSClaudiu Manoil 	epause->tx_pause = !!priv->tx_pause_en;
45923402bddSClaudiu Manoil }
46023402bddSClaudiu Manoil 
gfar_spauseparam(struct net_device * dev,struct ethtool_pauseparam * epause)46123402bddSClaudiu Manoil static int gfar_spauseparam(struct net_device *dev,
46223402bddSClaudiu Manoil 			    struct ethtool_pauseparam *epause)
46323402bddSClaudiu Manoil {
46423402bddSClaudiu Manoil 	struct gfar_private *priv = netdev_priv(dev);
4654c4a6b0eSPhilippe Reynes 	struct phy_device *phydev = dev->phydev;
46623402bddSClaudiu Manoil 	struct gfar __iomem *regs = priv->gfargrp[0].regs;
46723402bddSClaudiu Manoil 
46898a46d46SClaudiu Manoil 	if (!phydev)
46998a46d46SClaudiu Manoil 		return -ENODEV;
47098a46d46SClaudiu Manoil 
47122b7d299SAndrew Lunn 	if (!phy_validate_pause(phydev, epause))
47223402bddSClaudiu Manoil 		return -EINVAL;
47323402bddSClaudiu Manoil 
47423402bddSClaudiu Manoil 	priv->rx_pause_en = priv->tx_pause_en = 0;
47570814e81SAndrew Lunn 	phy_set_asym_pause(phydev, epause->rx_pause, epause->tx_pause);
47623402bddSClaudiu Manoil 	if (epause->rx_pause) {
47723402bddSClaudiu Manoil 		priv->rx_pause_en = 1;
47823402bddSClaudiu Manoil 
47923402bddSClaudiu Manoil 		if (epause->tx_pause) {
48023402bddSClaudiu Manoil 			priv->tx_pause_en = 1;
48170814e81SAndrew Lunn 		}
48223402bddSClaudiu Manoil 	} else if (epause->tx_pause) {
48323402bddSClaudiu Manoil 		priv->tx_pause_en = 1;
48470814e81SAndrew Lunn 	}
48523402bddSClaudiu Manoil 
48623402bddSClaudiu Manoil 	if (epause->autoneg)
48723402bddSClaudiu Manoil 		priv->pause_aneg_en = 1;
48823402bddSClaudiu Manoil 	else
48923402bddSClaudiu Manoil 		priv->pause_aneg_en = 0;
49023402bddSClaudiu Manoil 
49123402bddSClaudiu Manoil 	if (!epause->autoneg) {
49270814e81SAndrew Lunn 		u32 tempval = gfar_read(&regs->maccfg1);
49370814e81SAndrew Lunn 
49423402bddSClaudiu Manoil 		tempval &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
49545b679c9SMatei Pavaluca 
49645b679c9SMatei Pavaluca 		priv->tx_actual_en = 0;
49745b679c9SMatei Pavaluca 		if (priv->tx_pause_en) {
49845b679c9SMatei Pavaluca 			priv->tx_actual_en = 1;
49923402bddSClaudiu Manoil 			tempval |= MACCFG1_TX_FLOW;
50045b679c9SMatei Pavaluca 		}
50145b679c9SMatei Pavaluca 
50223402bddSClaudiu Manoil 		if (priv->rx_pause_en)
50323402bddSClaudiu Manoil 			tempval |= MACCFG1_RX_FLOW;
50423402bddSClaudiu Manoil 		gfar_write(&regs->maccfg1, tempval);
50523402bddSClaudiu Manoil 	}
50623402bddSClaudiu Manoil 
50723402bddSClaudiu Manoil 	return 0;
50823402bddSClaudiu Manoil }
50923402bddSClaudiu Manoil 
gfar_set_features(struct net_device * dev,netdev_features_t features)510c8f44affSMichał Mirosław int gfar_set_features(struct net_device *dev, netdev_features_t features)
511ec21e2ecSJeff Kirsher {
512c8f44affSMichał Mirosław 	netdev_features_t changed = dev->features ^ features;
5130851133bSClaudiu Manoil 	struct gfar_private *priv = netdev_priv(dev);
5147cca336aSClaudiu Manoil 	int err = 0;
515ec21e2ecSJeff Kirsher 
51688302648SClaudiu Manoil 	if (!(changed & (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
51788302648SClaudiu Manoil 			 NETIF_F_RXCSUM)))
518ec21e2ecSJeff Kirsher 		return 0;
519ec21e2ecSJeff Kirsher 
5200851133bSClaudiu Manoil 	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
5210851133bSClaudiu Manoil 		cpu_relax();
5220851133bSClaudiu Manoil 
52388302648SClaudiu Manoil 	dev->features = features;
52488302648SClaudiu Manoil 
525ec21e2ecSJeff Kirsher 	if (dev->flags & IFF_UP) {
526ec21e2ecSJeff Kirsher 		/* Now we take down the rings to rebuild them */
527ec21e2ecSJeff Kirsher 		stop_gfar(dev);
528ec21e2ecSJeff Kirsher 		err = startup_gfar(dev);
5290851133bSClaudiu Manoil 	} else {
5300851133bSClaudiu Manoil 		gfar_mac_reset(priv);
531ec21e2ecSJeff Kirsher 	}
5320851133bSClaudiu Manoil 
5330851133bSClaudiu Manoil 	clear_bit_unlock(GFAR_RESETTING, &priv->state);
5340851133bSClaudiu Manoil 
535ec21e2ecSJeff Kirsher 	return err;
536ec21e2ecSJeff Kirsher }
537ec21e2ecSJeff Kirsher 
gfar_get_msglevel(struct net_device * dev)538ec21e2ecSJeff Kirsher static uint32_t gfar_get_msglevel(struct net_device *dev)
539ec21e2ecSJeff Kirsher {
540ec21e2ecSJeff Kirsher 	struct gfar_private *priv = netdev_priv(dev);
541cbfc6071SJan Ceuleers 
542ec21e2ecSJeff Kirsher 	return priv->msg_enable;
543ec21e2ecSJeff Kirsher }
544ec21e2ecSJeff Kirsher 
gfar_set_msglevel(struct net_device * dev,uint32_t data)545ec21e2ecSJeff Kirsher static void gfar_set_msglevel(struct net_device *dev, uint32_t data)
546ec21e2ecSJeff Kirsher {
547ec21e2ecSJeff Kirsher 	struct gfar_private *priv = netdev_priv(dev);
548cbfc6071SJan Ceuleers 
549ec21e2ecSJeff Kirsher 	priv->msg_enable = data;
550ec21e2ecSJeff Kirsher }
551ec21e2ecSJeff Kirsher 
552ec21e2ecSJeff Kirsher #ifdef CONFIG_PM
gfar_get_wol(struct net_device * dev,struct ethtool_wolinfo * wol)553ec21e2ecSJeff Kirsher static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
554ec21e2ecSJeff Kirsher {
555ec21e2ecSJeff Kirsher 	struct gfar_private *priv = netdev_priv(dev);
556ec21e2ecSJeff Kirsher 
5573e905b80SClaudiu Manoil 	wol->supported = 0;
5583e905b80SClaudiu Manoil 	wol->wolopts = 0;
5593e905b80SClaudiu Manoil 
5603e905b80SClaudiu Manoil 	if (priv->wol_supported & GFAR_WOL_MAGIC)
5613e905b80SClaudiu Manoil 		wol->supported |= WAKE_MAGIC;
5623e905b80SClaudiu Manoil 
5633e905b80SClaudiu Manoil 	if (priv->wol_supported & GFAR_WOL_FILER_UCAST)
5643e905b80SClaudiu Manoil 		wol->supported |= WAKE_UCAST;
5653e905b80SClaudiu Manoil 
5663e905b80SClaudiu Manoil 	if (priv->wol_opts & GFAR_WOL_MAGIC)
5673e905b80SClaudiu Manoil 		wol->wolopts |= WAKE_MAGIC;
5683e905b80SClaudiu Manoil 
5693e905b80SClaudiu Manoil 	if (priv->wol_opts & GFAR_WOL_FILER_UCAST)
5703e905b80SClaudiu Manoil 		wol->wolopts |= WAKE_UCAST;
571ec21e2ecSJeff Kirsher }
572ec21e2ecSJeff Kirsher 
gfar_set_wol(struct net_device * dev,struct ethtool_wolinfo * wol)573ec21e2ecSJeff Kirsher static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
574ec21e2ecSJeff Kirsher {
575ec21e2ecSJeff Kirsher 	struct gfar_private *priv = netdev_priv(dev);
5763e905b80SClaudiu Manoil 	u16 wol_opts = 0;
5773e905b80SClaudiu Manoil 	int err;
578ec21e2ecSJeff Kirsher 
5793e905b80SClaudiu Manoil 	if (!priv->wol_supported && wol->wolopts)
580ec21e2ecSJeff Kirsher 		return -EINVAL;
581ec21e2ecSJeff Kirsher 
5823e905b80SClaudiu Manoil 	if (wol->wolopts & ~(WAKE_MAGIC | WAKE_UCAST))
583ec21e2ecSJeff Kirsher 		return -EINVAL;
584ec21e2ecSJeff Kirsher 
5853e905b80SClaudiu Manoil 	if (wol->wolopts & WAKE_MAGIC) {
5863e905b80SClaudiu Manoil 		wol_opts |= GFAR_WOL_MAGIC;
5873e905b80SClaudiu Manoil 	} else {
5883e905b80SClaudiu Manoil 		if (wol->wolopts & WAKE_UCAST)
5893e905b80SClaudiu Manoil 			wol_opts |= GFAR_WOL_FILER_UCAST;
5903e905b80SClaudiu Manoil 	}
591ec21e2ecSJeff Kirsher 
5923e905b80SClaudiu Manoil 	wol_opts &= priv->wol_supported;
5933e905b80SClaudiu Manoil 	priv->wol_opts = 0;
5943e905b80SClaudiu Manoil 
5953e905b80SClaudiu Manoil 	err = device_set_wakeup_enable(priv->dev, wol_opts);
5963e905b80SClaudiu Manoil 	if (err)
5973e905b80SClaudiu Manoil 		return err;
5983e905b80SClaudiu Manoil 
5993e905b80SClaudiu Manoil 	priv->wol_opts = wol_opts;
600ec21e2ecSJeff Kirsher 
601ec21e2ecSJeff Kirsher 	return 0;
602ec21e2ecSJeff Kirsher }
603ec21e2ecSJeff Kirsher #endif
604ec21e2ecSJeff Kirsher 
ethflow_to_filer_rules(struct gfar_private * priv,u64 ethflow)605ec21e2ecSJeff Kirsher static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow)
606ec21e2ecSJeff Kirsher {
607ec21e2ecSJeff Kirsher 	u32 fcr = 0x0, fpr = FPR_FILER_MASK;
608ec21e2ecSJeff Kirsher 
609ec21e2ecSJeff Kirsher 	if (ethflow & RXH_L2DA) {
610ec21e2ecSJeff Kirsher 		fcr = RQFCR_PID_DAH | RQFCR_CMP_NOMATCH |
611ec21e2ecSJeff Kirsher 		      RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0;
612ec21e2ecSJeff Kirsher 		priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
613ec21e2ecSJeff Kirsher 		priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
614ec21e2ecSJeff Kirsher 		gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr);
615ec21e2ecSJeff Kirsher 		priv->cur_filer_idx = priv->cur_filer_idx - 1;
616ec21e2ecSJeff Kirsher 
6175188f7e5SClaudiu Manoil 		fcr = RQFCR_PID_DAL | RQFCR_CMP_NOMATCH |
618ec21e2ecSJeff Kirsher 		      RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0;
619ec21e2ecSJeff Kirsher 		priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
620ec21e2ecSJeff Kirsher 		priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
621ec21e2ecSJeff Kirsher 		gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr);
622ec21e2ecSJeff Kirsher 		priv->cur_filer_idx = priv->cur_filer_idx - 1;
623ec21e2ecSJeff Kirsher 	}
624ec21e2ecSJeff Kirsher 
625ec21e2ecSJeff Kirsher 	if (ethflow & RXH_VLAN) {
626ec21e2ecSJeff Kirsher 		fcr = RQFCR_PID_VID | RQFCR_CMP_NOMATCH | RQFCR_HASH |
627ec21e2ecSJeff Kirsher 		      RQFCR_AND | RQFCR_HASHTBL_0;
628ec21e2ecSJeff Kirsher 		gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr);
629ec21e2ecSJeff Kirsher 		priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
630ec21e2ecSJeff Kirsher 		priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
631ec21e2ecSJeff Kirsher 		priv->cur_filer_idx = priv->cur_filer_idx - 1;
632ec21e2ecSJeff Kirsher 	}
633ec21e2ecSJeff Kirsher 
634ec21e2ecSJeff Kirsher 	if (ethflow & RXH_IP_SRC) {
635ec21e2ecSJeff Kirsher 		fcr = RQFCR_PID_SIA | RQFCR_CMP_NOMATCH | RQFCR_HASH |
636ec21e2ecSJeff Kirsher 		      RQFCR_AND | RQFCR_HASHTBL_0;
637ec21e2ecSJeff Kirsher 		priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
638ec21e2ecSJeff Kirsher 		priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
639ec21e2ecSJeff Kirsher 		gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr);
640ec21e2ecSJeff Kirsher 		priv->cur_filer_idx = priv->cur_filer_idx - 1;
641ec21e2ecSJeff Kirsher 	}
642ec21e2ecSJeff Kirsher 
643ec21e2ecSJeff Kirsher 	if (ethflow & (RXH_IP_DST)) {
644ec21e2ecSJeff Kirsher 		fcr = RQFCR_PID_DIA | RQFCR_CMP_NOMATCH | RQFCR_HASH |
645ec21e2ecSJeff Kirsher 		      RQFCR_AND | RQFCR_HASHTBL_0;
646ec21e2ecSJeff Kirsher 		priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
647ec21e2ecSJeff Kirsher 		priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
648ec21e2ecSJeff Kirsher 		gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr);
649ec21e2ecSJeff Kirsher 		priv->cur_filer_idx = priv->cur_filer_idx - 1;
650ec21e2ecSJeff Kirsher 	}
651ec21e2ecSJeff Kirsher 
652ec21e2ecSJeff Kirsher 	if (ethflow & RXH_L3_PROTO) {
653ec21e2ecSJeff Kirsher 		fcr = RQFCR_PID_L4P | RQFCR_CMP_NOMATCH | RQFCR_HASH |
654ec21e2ecSJeff Kirsher 		      RQFCR_AND | RQFCR_HASHTBL_0;
655ec21e2ecSJeff Kirsher 		priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
656ec21e2ecSJeff Kirsher 		priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
657ec21e2ecSJeff Kirsher 		gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr);
658ec21e2ecSJeff Kirsher 		priv->cur_filer_idx = priv->cur_filer_idx - 1;
659ec21e2ecSJeff Kirsher 	}
660ec21e2ecSJeff Kirsher 
661ec21e2ecSJeff Kirsher 	if (ethflow & RXH_L4_B_0_1) {
662ec21e2ecSJeff Kirsher 		fcr = RQFCR_PID_SPT | RQFCR_CMP_NOMATCH | RQFCR_HASH |
663ec21e2ecSJeff Kirsher 		      RQFCR_AND | RQFCR_HASHTBL_0;
664ec21e2ecSJeff Kirsher 		priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
665ec21e2ecSJeff Kirsher 		priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
666ec21e2ecSJeff Kirsher 		gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr);
667ec21e2ecSJeff Kirsher 		priv->cur_filer_idx = priv->cur_filer_idx - 1;
668ec21e2ecSJeff Kirsher 	}
669ec21e2ecSJeff Kirsher 
670ec21e2ecSJeff Kirsher 	if (ethflow & RXH_L4_B_2_3) {
671ec21e2ecSJeff Kirsher 		fcr = RQFCR_PID_DPT | RQFCR_CMP_NOMATCH | RQFCR_HASH |
672ec21e2ecSJeff Kirsher 		      RQFCR_AND | RQFCR_HASHTBL_0;
673ec21e2ecSJeff Kirsher 		priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
674ec21e2ecSJeff Kirsher 		priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
675ec21e2ecSJeff Kirsher 		gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr);
676ec21e2ecSJeff Kirsher 		priv->cur_filer_idx = priv->cur_filer_idx - 1;
677ec21e2ecSJeff Kirsher 	}
678ec21e2ecSJeff Kirsher }
679ec21e2ecSJeff Kirsher 
gfar_ethflow_to_filer_table(struct gfar_private * priv,u64 ethflow,u64 class)680cbfc6071SJan Ceuleers static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow,
681cbfc6071SJan Ceuleers 				       u64 class)
682ec21e2ecSJeff Kirsher {
683ec21e2ecSJeff Kirsher 	unsigned int cmp_rqfpr;
684823dcd25SDavid S. Miller 	unsigned int *local_rqfpr;
685823dcd25SDavid S. Miller 	unsigned int *local_rqfcr;
686ec21e2ecSJeff Kirsher 	int i = 0x0, k = 0x0;
687ec21e2ecSJeff Kirsher 	int j = MAX_FILER_IDX, l = 0x0;
688823dcd25SDavid S. Miller 	int ret = 1;
689823dcd25SDavid S. Miller 
690b2adaca9SJoe Perches 	local_rqfpr = kmalloc_array(MAX_FILER_IDX + 1, sizeof(unsigned int),
691823dcd25SDavid S. Miller 				    GFP_KERNEL);
692b2adaca9SJoe Perches 	local_rqfcr = kmalloc_array(MAX_FILER_IDX + 1, sizeof(unsigned int),
693823dcd25SDavid S. Miller 				    GFP_KERNEL);
694823dcd25SDavid S. Miller 	if (!local_rqfpr || !local_rqfcr) {
695823dcd25SDavid S. Miller 		ret = 0;
696823dcd25SDavid S. Miller 		goto err;
697823dcd25SDavid S. Miller 	}
698ec21e2ecSJeff Kirsher 
699ec21e2ecSJeff Kirsher 	switch (class) {
700ec21e2ecSJeff Kirsher 	case TCP_V4_FLOW:
701ec21e2ecSJeff Kirsher 		cmp_rqfpr = RQFPR_IPV4 |RQFPR_TCP;
702ec21e2ecSJeff Kirsher 		break;
703ec21e2ecSJeff Kirsher 	case UDP_V4_FLOW:
704ec21e2ecSJeff Kirsher 		cmp_rqfpr = RQFPR_IPV4 |RQFPR_UDP;
705ec21e2ecSJeff Kirsher 		break;
706ec21e2ecSJeff Kirsher 	case TCP_V6_FLOW:
707ec21e2ecSJeff Kirsher 		cmp_rqfpr = RQFPR_IPV6 |RQFPR_TCP;
708ec21e2ecSJeff Kirsher 		break;
709ec21e2ecSJeff Kirsher 	case UDP_V6_FLOW:
710ec21e2ecSJeff Kirsher 		cmp_rqfpr = RQFPR_IPV6 |RQFPR_UDP;
711ec21e2ecSJeff Kirsher 		break;
712ec21e2ecSJeff Kirsher 	default:
713375d6a1bSJoe Perches 		netdev_err(priv->ndev,
714375d6a1bSJoe Perches 			   "Right now this class is not supported\n");
715823dcd25SDavid S. Miller 		ret = 0;
716823dcd25SDavid S. Miller 		goto err;
717ec21e2ecSJeff Kirsher 	}
718ec21e2ecSJeff Kirsher 
719ec21e2ecSJeff Kirsher 	for (i = 0; i < MAX_FILER_IDX + 1; i++) {
720ec21e2ecSJeff Kirsher 		local_rqfpr[j] = priv->ftp_rqfpr[i];
721ec21e2ecSJeff Kirsher 		local_rqfcr[j] = priv->ftp_rqfcr[i];
722ec21e2ecSJeff Kirsher 		j--;
723cbfc6071SJan Ceuleers 		if ((priv->ftp_rqfcr[i] ==
724cbfc6071SJan Ceuleers 		     (RQFCR_PID_PARSE | RQFCR_CLE | RQFCR_AND)) &&
725ec21e2ecSJeff Kirsher 		    (priv->ftp_rqfpr[i] == cmp_rqfpr))
726ec21e2ecSJeff Kirsher 			break;
727ec21e2ecSJeff Kirsher 	}
728ec21e2ecSJeff Kirsher 
729ec21e2ecSJeff Kirsher 	if (i == MAX_FILER_IDX + 1) {
730375d6a1bSJoe Perches 		netdev_err(priv->ndev,
731375d6a1bSJoe Perches 			   "No parse rule found, can't create hash rules\n");
732823dcd25SDavid S. Miller 		ret = 0;
733823dcd25SDavid S. Miller 		goto err;
734ec21e2ecSJeff Kirsher 	}
735ec21e2ecSJeff Kirsher 
736ec21e2ecSJeff Kirsher 	/* If a match was found, then it begins the starting of a cluster rule
737ec21e2ecSJeff Kirsher 	 * if it was already programmed, we need to overwrite these rules
738ec21e2ecSJeff Kirsher 	 */
739ec21e2ecSJeff Kirsher 	for (l = i+1; l < MAX_FILER_IDX; l++) {
740ec21e2ecSJeff Kirsher 		if ((priv->ftp_rqfcr[l] & RQFCR_CLE) &&
741ec21e2ecSJeff Kirsher 		    !(priv->ftp_rqfcr[l] & RQFCR_AND)) {
742ec21e2ecSJeff Kirsher 			priv->ftp_rqfcr[l] = RQFCR_CLE | RQFCR_CMP_EXACT |
743ec21e2ecSJeff Kirsher 					     RQFCR_HASHTBL_0 | RQFCR_PID_MASK;
744ec21e2ecSJeff Kirsher 			priv->ftp_rqfpr[l] = FPR_FILER_MASK;
745ec21e2ecSJeff Kirsher 			gfar_write_filer(priv, l, priv->ftp_rqfcr[l],
746ec21e2ecSJeff Kirsher 					 priv->ftp_rqfpr[l]);
747ec21e2ecSJeff Kirsher 			break;
748ec21e2ecSJeff Kirsher 		}
749ec21e2ecSJeff Kirsher 
750ec21e2ecSJeff Kirsher 		if (!(priv->ftp_rqfcr[l] & RQFCR_CLE) &&
751ec21e2ecSJeff Kirsher 			(priv->ftp_rqfcr[l] & RQFCR_AND))
752ec21e2ecSJeff Kirsher 			continue;
753ec21e2ecSJeff Kirsher 		else {
754ec21e2ecSJeff Kirsher 			local_rqfpr[j] = priv->ftp_rqfpr[l];
755ec21e2ecSJeff Kirsher 			local_rqfcr[j] = priv->ftp_rqfcr[l];
756ec21e2ecSJeff Kirsher 			j--;
757ec21e2ecSJeff Kirsher 		}
758ec21e2ecSJeff Kirsher 	}
759ec21e2ecSJeff Kirsher 
760ec21e2ecSJeff Kirsher 	priv->cur_filer_idx = l - 1;
761ec21e2ecSJeff Kirsher 
762ec21e2ecSJeff Kirsher 	/* hash rules */
763ec21e2ecSJeff Kirsher 	ethflow_to_filer_rules(priv, ethflow);
764ec21e2ecSJeff Kirsher 
765ec21e2ecSJeff Kirsher 	/* Write back the popped out rules again */
766ec21e2ecSJeff Kirsher 	for (k = j+1; k < MAX_FILER_IDX; k++) {
767ec21e2ecSJeff Kirsher 		priv->ftp_rqfpr[priv->cur_filer_idx] = local_rqfpr[k];
768ec21e2ecSJeff Kirsher 		priv->ftp_rqfcr[priv->cur_filer_idx] = local_rqfcr[k];
769ec21e2ecSJeff Kirsher 		gfar_write_filer(priv, priv->cur_filer_idx,
770ec21e2ecSJeff Kirsher 				 local_rqfcr[k], local_rqfpr[k]);
771ec21e2ecSJeff Kirsher 		if (!priv->cur_filer_idx)
772ec21e2ecSJeff Kirsher 			break;
773ec21e2ecSJeff Kirsher 		priv->cur_filer_idx = priv->cur_filer_idx - 1;
774ec21e2ecSJeff Kirsher 	}
775ec21e2ecSJeff Kirsher 
776823dcd25SDavid S. Miller err:
777823dcd25SDavid S. Miller 	kfree(local_rqfcr);
778823dcd25SDavid S. Miller 	kfree(local_rqfpr);
779823dcd25SDavid S. Miller 	return ret;
780ec21e2ecSJeff Kirsher }
781ec21e2ecSJeff Kirsher 
gfar_set_hash_opts(struct gfar_private * priv,struct ethtool_rxnfc * cmd)782cbfc6071SJan Ceuleers static int gfar_set_hash_opts(struct gfar_private *priv,
783cbfc6071SJan Ceuleers 			      struct ethtool_rxnfc *cmd)
784ec21e2ecSJeff Kirsher {
785ec21e2ecSJeff Kirsher 	/* write the filer rules here */
786ec21e2ecSJeff Kirsher 	if (!gfar_ethflow_to_filer_table(priv, cmd->data, cmd->flow_type))
787ec21e2ecSJeff Kirsher 		return -EINVAL;
788ec21e2ecSJeff Kirsher 
789ec21e2ecSJeff Kirsher 	return 0;
790ec21e2ecSJeff Kirsher }
791ec21e2ecSJeff Kirsher 
gfar_check_filer_hardware(struct gfar_private * priv)792ec21e2ecSJeff Kirsher static int gfar_check_filer_hardware(struct gfar_private *priv)
793ec21e2ecSJeff Kirsher {
79442851e88SClaudiu Manoil 	struct gfar __iomem *regs = priv->gfargrp[0].regs;
795ec21e2ecSJeff Kirsher 	u32 i;
796ec21e2ecSJeff Kirsher 
797ec21e2ecSJeff Kirsher 	/* Check if we are in FIFO mode */
798ec21e2ecSJeff Kirsher 	i = gfar_read(&regs->ecntrl);
799ec21e2ecSJeff Kirsher 	i &= ECNTRL_FIFM;
800ec21e2ecSJeff Kirsher 	if (i == ECNTRL_FIFM) {
801ec21e2ecSJeff Kirsher 		netdev_notice(priv->ndev, "Interface in FIFO mode\n");
802ec21e2ecSJeff Kirsher 		i = gfar_read(&regs->rctrl);
803ec21e2ecSJeff Kirsher 		i &= RCTRL_PRSDEP_MASK | RCTRL_PRSFM;
804ec21e2ecSJeff Kirsher 		if (i == (RCTRL_PRSDEP_MASK | RCTRL_PRSFM)) {
805ec21e2ecSJeff Kirsher 			netdev_info(priv->ndev,
806ec21e2ecSJeff Kirsher 				    "Receive Queue Filtering enabled\n");
807ec21e2ecSJeff Kirsher 		} else {
808ec21e2ecSJeff Kirsher 			netdev_warn(priv->ndev,
809ec21e2ecSJeff Kirsher 				    "Receive Queue Filtering disabled\n");
810ec21e2ecSJeff Kirsher 			return -EOPNOTSUPP;
811ec21e2ecSJeff Kirsher 		}
812ec21e2ecSJeff Kirsher 	}
813ec21e2ecSJeff Kirsher 	/* Or in standard mode */
814ec21e2ecSJeff Kirsher 	else {
815ec21e2ecSJeff Kirsher 		i = gfar_read(&regs->rctrl);
816ec21e2ecSJeff Kirsher 		i &= RCTRL_PRSDEP_MASK;
817ec21e2ecSJeff Kirsher 		if (i == RCTRL_PRSDEP_MASK) {
818ec21e2ecSJeff Kirsher 			netdev_info(priv->ndev,
819ec21e2ecSJeff Kirsher 				    "Receive Queue Filtering enabled\n");
820ec21e2ecSJeff Kirsher 		} else {
821ec21e2ecSJeff Kirsher 			netdev_warn(priv->ndev,
822ec21e2ecSJeff Kirsher 				    "Receive Queue Filtering disabled\n");
823ec21e2ecSJeff Kirsher 			return -EOPNOTSUPP;
824ec21e2ecSJeff Kirsher 		}
825ec21e2ecSJeff Kirsher 	}
826ec21e2ecSJeff Kirsher 
827ec21e2ecSJeff Kirsher 	/* Sets the properties for arbitrary filer rule
828cbfc6071SJan Ceuleers 	 * to the first 4 Layer 4 Bytes
829cbfc6071SJan Ceuleers 	 */
83042851e88SClaudiu Manoil 	gfar_write(&regs->rbifx, 0xC0C1C2C3);
831ec21e2ecSJeff Kirsher 	return 0;
832ec21e2ecSJeff Kirsher }
833ec21e2ecSJeff Kirsher 
834ec21e2ecSJeff Kirsher /* Write a mask to filer cache */
gfar_set_mask(u32 mask,struct filer_table * tab)835ec21e2ecSJeff Kirsher static void gfar_set_mask(u32 mask, struct filer_table *tab)
836ec21e2ecSJeff Kirsher {
837ec21e2ecSJeff Kirsher 	tab->fe[tab->index].ctrl = RQFCR_AND | RQFCR_PID_MASK | RQFCR_CMP_EXACT;
838ec21e2ecSJeff Kirsher 	tab->fe[tab->index].prop = mask;
839ec21e2ecSJeff Kirsher 	tab->index++;
840ec21e2ecSJeff Kirsher }
841ec21e2ecSJeff Kirsher 
842ec21e2ecSJeff Kirsher /* Sets parse bits (e.g. IP or TCP) */
gfar_set_parse_bits(u32 value,u32 mask,struct filer_table * tab)843ec21e2ecSJeff Kirsher static void gfar_set_parse_bits(u32 value, u32 mask, struct filer_table *tab)
844ec21e2ecSJeff Kirsher {
845ec21e2ecSJeff Kirsher 	gfar_set_mask(mask, tab);
846cbfc6071SJan Ceuleers 	tab->fe[tab->index].ctrl = RQFCR_CMP_EXACT | RQFCR_PID_PARSE |
847cbfc6071SJan Ceuleers 				   RQFCR_AND;
848ec21e2ecSJeff Kirsher 	tab->fe[tab->index].prop = value;
849ec21e2ecSJeff Kirsher 	tab->index++;
850ec21e2ecSJeff Kirsher }
851ec21e2ecSJeff Kirsher 
gfar_set_general_attribute(u32 value,u32 mask,u32 flag,struct filer_table * tab)852ec21e2ecSJeff Kirsher static void gfar_set_general_attribute(u32 value, u32 mask, u32 flag,
853ec21e2ecSJeff Kirsher 				       struct filer_table *tab)
854ec21e2ecSJeff Kirsher {
855ec21e2ecSJeff Kirsher 	gfar_set_mask(mask, tab);
856ec21e2ecSJeff Kirsher 	tab->fe[tab->index].ctrl = RQFCR_CMP_EXACT | RQFCR_AND | flag;
857ec21e2ecSJeff Kirsher 	tab->fe[tab->index].prop = value;
858ec21e2ecSJeff Kirsher 	tab->index++;
859ec21e2ecSJeff Kirsher }
860ec21e2ecSJeff Kirsher 
861cbfc6071SJan Ceuleers /* For setting a tuple of value and mask of type flag
862ec21e2ecSJeff Kirsher  * Example:
863ec21e2ecSJeff Kirsher  * IP-Src = 10.0.0.0/255.0.0.0
864ec21e2ecSJeff Kirsher  * value: 0x0A000000 mask: FF000000 flag: RQFPR_IPV4
865ec21e2ecSJeff Kirsher  *
866ec21e2ecSJeff Kirsher  * Ethtool gives us a value=0 and mask=~0 for don't care a tuple
867ec21e2ecSJeff Kirsher  * For a don't care mask it gives us a 0
868ec21e2ecSJeff Kirsher  *
869ec21e2ecSJeff Kirsher  * The check if don't care and the mask adjustment if mask=0 is done for VLAN
870ec21e2ecSJeff Kirsher  * and MAC stuff on an upper level (due to missing information on this level).
871ec21e2ecSJeff Kirsher  * For these guys we can discard them if they are value=0 and mask=0.
872ec21e2ecSJeff Kirsher  *
873ec21e2ecSJeff Kirsher  * Further the all masks are one-padded for better hardware efficiency.
874ec21e2ecSJeff Kirsher  */
gfar_set_attribute(u32 value,u32 mask,u32 flag,struct filer_table * tab)875ec21e2ecSJeff Kirsher static void gfar_set_attribute(u32 value, u32 mask, u32 flag,
876ec21e2ecSJeff Kirsher 			       struct filer_table *tab)
877ec21e2ecSJeff Kirsher {
878ec21e2ecSJeff Kirsher 	switch (flag) {
879ec21e2ecSJeff Kirsher 		/* 3bit */
880ec21e2ecSJeff Kirsher 	case RQFCR_PID_PRI:
881ec21e2ecSJeff Kirsher 		if (!(value | mask))
882ec21e2ecSJeff Kirsher 			return;
883ec21e2ecSJeff Kirsher 		mask |= RQFCR_PID_PRI_MASK;
884ec21e2ecSJeff Kirsher 		break;
885ec21e2ecSJeff Kirsher 		/* 8bit */
886ec21e2ecSJeff Kirsher 	case RQFCR_PID_L4P:
887ec21e2ecSJeff Kirsher 	case RQFCR_PID_TOS:
888ec21e2ecSJeff Kirsher 		if (!~(mask | RQFCR_PID_L4P_MASK))
889ec21e2ecSJeff Kirsher 			return;
890ec21e2ecSJeff Kirsher 		if (!mask)
891ec21e2ecSJeff Kirsher 			mask = ~0;
892ec21e2ecSJeff Kirsher 		else
893ec21e2ecSJeff Kirsher 			mask |= RQFCR_PID_L4P_MASK;
894ec21e2ecSJeff Kirsher 		break;
895ec21e2ecSJeff Kirsher 		/* 12bit */
896ec21e2ecSJeff Kirsher 	case RQFCR_PID_VID:
897ec21e2ecSJeff Kirsher 		if (!(value | mask))
898ec21e2ecSJeff Kirsher 			return;
899ec21e2ecSJeff Kirsher 		mask |= RQFCR_PID_VID_MASK;
900ec21e2ecSJeff Kirsher 		break;
901ec21e2ecSJeff Kirsher 		/* 16bit */
902ec21e2ecSJeff Kirsher 	case RQFCR_PID_DPT:
903ec21e2ecSJeff Kirsher 	case RQFCR_PID_SPT:
904ec21e2ecSJeff Kirsher 	case RQFCR_PID_ETY:
905ec21e2ecSJeff Kirsher 		if (!~(mask | RQFCR_PID_PORT_MASK))
906ec21e2ecSJeff Kirsher 			return;
907ec21e2ecSJeff Kirsher 		if (!mask)
908ec21e2ecSJeff Kirsher 			mask = ~0;
909ec21e2ecSJeff Kirsher 		else
910ec21e2ecSJeff Kirsher 			mask |= RQFCR_PID_PORT_MASK;
911ec21e2ecSJeff Kirsher 		break;
912ec21e2ecSJeff Kirsher 		/* 24bit */
913ec21e2ecSJeff Kirsher 	case RQFCR_PID_DAH:
914ec21e2ecSJeff Kirsher 	case RQFCR_PID_DAL:
915ec21e2ecSJeff Kirsher 	case RQFCR_PID_SAH:
916ec21e2ecSJeff Kirsher 	case RQFCR_PID_SAL:
917ec21e2ecSJeff Kirsher 		if (!(value | mask))
918ec21e2ecSJeff Kirsher 			return;
919ec21e2ecSJeff Kirsher 		mask |= RQFCR_PID_MAC_MASK;
920ec21e2ecSJeff Kirsher 		break;
921ec21e2ecSJeff Kirsher 		/* for all real 32bit masks */
922ec21e2ecSJeff Kirsher 	default:
923ec21e2ecSJeff Kirsher 		if (!~mask)
924ec21e2ecSJeff Kirsher 			return;
925ec21e2ecSJeff Kirsher 		if (!mask)
926ec21e2ecSJeff Kirsher 			mask = ~0;
927ec21e2ecSJeff Kirsher 		break;
928ec21e2ecSJeff Kirsher 	}
929ec21e2ecSJeff Kirsher 	gfar_set_general_attribute(value, mask, flag, tab);
930ec21e2ecSJeff Kirsher }
931ec21e2ecSJeff Kirsher 
932ec21e2ecSJeff Kirsher /* Translates value and mask for UDP, TCP or SCTP */
gfar_set_basic_ip(struct ethtool_tcpip4_spec * value,struct ethtool_tcpip4_spec * mask,struct filer_table * tab)933ec21e2ecSJeff Kirsher static void gfar_set_basic_ip(struct ethtool_tcpip4_spec *value,
934cbfc6071SJan Ceuleers 			      struct ethtool_tcpip4_spec *mask,
935cbfc6071SJan Ceuleers 			      struct filer_table *tab)
936ec21e2ecSJeff Kirsher {
93742851e88SClaudiu Manoil 	gfar_set_attribute(be32_to_cpu(value->ip4src),
93842851e88SClaudiu Manoil 			   be32_to_cpu(mask->ip4src),
93942851e88SClaudiu Manoil 			   RQFCR_PID_SIA, tab);
94042851e88SClaudiu Manoil 	gfar_set_attribute(be32_to_cpu(value->ip4dst),
94142851e88SClaudiu Manoil 			   be32_to_cpu(mask->ip4dst),
94242851e88SClaudiu Manoil 			   RQFCR_PID_DIA, tab);
94342851e88SClaudiu Manoil 	gfar_set_attribute(be16_to_cpu(value->pdst),
94442851e88SClaudiu Manoil 			   be16_to_cpu(mask->pdst),
94542851e88SClaudiu Manoil 			   RQFCR_PID_DPT, tab);
94642851e88SClaudiu Manoil 	gfar_set_attribute(be16_to_cpu(value->psrc),
94742851e88SClaudiu Manoil 			   be16_to_cpu(mask->psrc),
94842851e88SClaudiu Manoil 			   RQFCR_PID_SPT, tab);
949ec21e2ecSJeff Kirsher 	gfar_set_attribute(value->tos, mask->tos, RQFCR_PID_TOS, tab);
950ec21e2ecSJeff Kirsher }
951ec21e2ecSJeff Kirsher 
952ec21e2ecSJeff Kirsher /* Translates value and mask for RAW-IP4 */
gfar_set_user_ip(struct ethtool_usrip4_spec * value,struct ethtool_usrip4_spec * mask,struct filer_table * tab)953ec21e2ecSJeff Kirsher static void gfar_set_user_ip(struct ethtool_usrip4_spec *value,
954cbfc6071SJan Ceuleers 			     struct ethtool_usrip4_spec *mask,
955cbfc6071SJan Ceuleers 			     struct filer_table *tab)
956ec21e2ecSJeff Kirsher {
95742851e88SClaudiu Manoil 	gfar_set_attribute(be32_to_cpu(value->ip4src),
95842851e88SClaudiu Manoil 			   be32_to_cpu(mask->ip4src),
95942851e88SClaudiu Manoil 			   RQFCR_PID_SIA, tab);
96042851e88SClaudiu Manoil 	gfar_set_attribute(be32_to_cpu(value->ip4dst),
96142851e88SClaudiu Manoil 			   be32_to_cpu(mask->ip4dst),
96242851e88SClaudiu Manoil 			   RQFCR_PID_DIA, tab);
963ec21e2ecSJeff Kirsher 	gfar_set_attribute(value->tos, mask->tos, RQFCR_PID_TOS, tab);
964ec21e2ecSJeff Kirsher 	gfar_set_attribute(value->proto, mask->proto, RQFCR_PID_L4P, tab);
96542851e88SClaudiu Manoil 	gfar_set_attribute(be32_to_cpu(value->l4_4_bytes),
96642851e88SClaudiu Manoil 			   be32_to_cpu(mask->l4_4_bytes),
96742851e88SClaudiu Manoil 			   RQFCR_PID_ARB, tab);
968ec21e2ecSJeff Kirsher 
969ec21e2ecSJeff Kirsher }
970ec21e2ecSJeff Kirsher 
971ec21e2ecSJeff Kirsher /* Translates value and mask for ETHER spec */
gfar_set_ether(struct ethhdr * value,struct ethhdr * mask,struct filer_table * tab)972ec21e2ecSJeff Kirsher static void gfar_set_ether(struct ethhdr *value, struct ethhdr *mask,
973ec21e2ecSJeff Kirsher 			   struct filer_table *tab)
974ec21e2ecSJeff Kirsher {
975ec21e2ecSJeff Kirsher 	u32 upper_temp_mask = 0;
976ec21e2ecSJeff Kirsher 	u32 lower_temp_mask = 0;
977cbfc6071SJan Ceuleers 
978ec21e2ecSJeff Kirsher 	/* Source address */
979ec21e2ecSJeff Kirsher 	if (!is_broadcast_ether_addr(mask->h_source)) {
980ec21e2ecSJeff Kirsher 		if (is_zero_ether_addr(mask->h_source)) {
981ec21e2ecSJeff Kirsher 			upper_temp_mask = 0xFFFFFFFF;
982ec21e2ecSJeff Kirsher 			lower_temp_mask = 0xFFFFFFFF;
983ec21e2ecSJeff Kirsher 		} else {
984cbfc6071SJan Ceuleers 			upper_temp_mask = mask->h_source[0] << 16 |
985cbfc6071SJan Ceuleers 					  mask->h_source[1] << 8  |
986cbfc6071SJan Ceuleers 					  mask->h_source[2];
987cbfc6071SJan Ceuleers 			lower_temp_mask = mask->h_source[3] << 16 |
988cbfc6071SJan Ceuleers 					  mask->h_source[4] << 8  |
989cbfc6071SJan Ceuleers 					  mask->h_source[5];
990ec21e2ecSJeff Kirsher 		}
991ec21e2ecSJeff Kirsher 		/* Upper 24bit */
992cbfc6071SJan Ceuleers 		gfar_set_attribute(value->h_source[0] << 16 |
993cbfc6071SJan Ceuleers 				   value->h_source[1] << 8  |
994cbfc6071SJan Ceuleers 				   value->h_source[2],
995ec21e2ecSJeff Kirsher 				   upper_temp_mask, RQFCR_PID_SAH, tab);
996ec21e2ecSJeff Kirsher 		/* And the same for the lower part */
997cbfc6071SJan Ceuleers 		gfar_set_attribute(value->h_source[3] << 16 |
998cbfc6071SJan Ceuleers 				   value->h_source[4] << 8  |
999cbfc6071SJan Ceuleers 				   value->h_source[5],
1000ec21e2ecSJeff Kirsher 				   lower_temp_mask, RQFCR_PID_SAL, tab);
1001ec21e2ecSJeff Kirsher 	}
1002ec21e2ecSJeff Kirsher 	/* Destination address */
1003ec21e2ecSJeff Kirsher 	if (!is_broadcast_ether_addr(mask->h_dest)) {
1004ec21e2ecSJeff Kirsher 		/* Special for destination is limited broadcast */
1005cbfc6071SJan Ceuleers 		if ((is_broadcast_ether_addr(value->h_dest) &&
1006cbfc6071SJan Ceuleers 		    is_zero_ether_addr(mask->h_dest))) {
1007ec21e2ecSJeff Kirsher 			gfar_set_parse_bits(RQFPR_EBC, RQFPR_EBC, tab);
1008ec21e2ecSJeff Kirsher 		} else {
1009ec21e2ecSJeff Kirsher 			if (is_zero_ether_addr(mask->h_dest)) {
1010ec21e2ecSJeff Kirsher 				upper_temp_mask = 0xFFFFFFFF;
1011ec21e2ecSJeff Kirsher 				lower_temp_mask = 0xFFFFFFFF;
1012ec21e2ecSJeff Kirsher 			} else {
1013cbfc6071SJan Ceuleers 				upper_temp_mask = mask->h_dest[0] << 16 |
1014cbfc6071SJan Ceuleers 						  mask->h_dest[1] << 8  |
1015cbfc6071SJan Ceuleers 						  mask->h_dest[2];
1016cbfc6071SJan Ceuleers 				lower_temp_mask = mask->h_dest[3] << 16 |
1017cbfc6071SJan Ceuleers 						  mask->h_dest[4] << 8  |
1018cbfc6071SJan Ceuleers 						  mask->h_dest[5];
1019ec21e2ecSJeff Kirsher 			}
1020ec21e2ecSJeff Kirsher 
1021ec21e2ecSJeff Kirsher 			/* Upper 24bit */
1022cbfc6071SJan Ceuleers 			gfar_set_attribute(value->h_dest[0] << 16 |
1023cbfc6071SJan Ceuleers 					   value->h_dest[1] << 8  |
1024cbfc6071SJan Ceuleers 					   value->h_dest[2],
1025ec21e2ecSJeff Kirsher 					   upper_temp_mask, RQFCR_PID_DAH, tab);
1026ec21e2ecSJeff Kirsher 			/* And the same for the lower part */
1027cbfc6071SJan Ceuleers 			gfar_set_attribute(value->h_dest[3] << 16 |
1028cbfc6071SJan Ceuleers 					   value->h_dest[4] << 8  |
1029cbfc6071SJan Ceuleers 					   value->h_dest[5],
1030ec21e2ecSJeff Kirsher 					   lower_temp_mask, RQFCR_PID_DAL, tab);
1031ec21e2ecSJeff Kirsher 		}
1032ec21e2ecSJeff Kirsher 	}
1033ec21e2ecSJeff Kirsher 
103442851e88SClaudiu Manoil 	gfar_set_attribute(be16_to_cpu(value->h_proto),
103542851e88SClaudiu Manoil 			   be16_to_cpu(mask->h_proto),
103642851e88SClaudiu Manoil 			   RQFCR_PID_ETY, tab);
103742851e88SClaudiu Manoil }
103842851e88SClaudiu Manoil 
vlan_tci_vid(struct ethtool_rx_flow_spec * rule)103942851e88SClaudiu Manoil static inline u32 vlan_tci_vid(struct ethtool_rx_flow_spec *rule)
104042851e88SClaudiu Manoil {
104142851e88SClaudiu Manoil 	return be16_to_cpu(rule->h_ext.vlan_tci) & VLAN_VID_MASK;
104242851e88SClaudiu Manoil }
104342851e88SClaudiu Manoil 
vlan_tci_vidm(struct ethtool_rx_flow_spec * rule)104442851e88SClaudiu Manoil static inline u32 vlan_tci_vidm(struct ethtool_rx_flow_spec *rule)
104542851e88SClaudiu Manoil {
104642851e88SClaudiu Manoil 	return be16_to_cpu(rule->m_ext.vlan_tci) & VLAN_VID_MASK;
104742851e88SClaudiu Manoil }
104842851e88SClaudiu Manoil 
vlan_tci_cfi(struct ethtool_rx_flow_spec * rule)104942851e88SClaudiu Manoil static inline u32 vlan_tci_cfi(struct ethtool_rx_flow_spec *rule)
105042851e88SClaudiu Manoil {
105142851e88SClaudiu Manoil 	return be16_to_cpu(rule->h_ext.vlan_tci) & VLAN_CFI_MASK;
105242851e88SClaudiu Manoil }
105342851e88SClaudiu Manoil 
vlan_tci_cfim(struct ethtool_rx_flow_spec * rule)105442851e88SClaudiu Manoil static inline u32 vlan_tci_cfim(struct ethtool_rx_flow_spec *rule)
105542851e88SClaudiu Manoil {
105642851e88SClaudiu Manoil 	return be16_to_cpu(rule->m_ext.vlan_tci) & VLAN_CFI_MASK;
105742851e88SClaudiu Manoil }
105842851e88SClaudiu Manoil 
vlan_tci_prio(struct ethtool_rx_flow_spec * rule)105942851e88SClaudiu Manoil static inline u32 vlan_tci_prio(struct ethtool_rx_flow_spec *rule)
106042851e88SClaudiu Manoil {
106142851e88SClaudiu Manoil 	return (be16_to_cpu(rule->h_ext.vlan_tci) & VLAN_PRIO_MASK) >>
106242851e88SClaudiu Manoil 		VLAN_PRIO_SHIFT;
106342851e88SClaudiu Manoil }
106442851e88SClaudiu Manoil 
vlan_tci_priom(struct ethtool_rx_flow_spec * rule)106542851e88SClaudiu Manoil static inline u32 vlan_tci_priom(struct ethtool_rx_flow_spec *rule)
106642851e88SClaudiu Manoil {
106742851e88SClaudiu Manoil 	return (be16_to_cpu(rule->m_ext.vlan_tci) & VLAN_PRIO_MASK) >>
106842851e88SClaudiu Manoil 		VLAN_PRIO_SHIFT;
1069ec21e2ecSJeff Kirsher }
1070ec21e2ecSJeff Kirsher 
1071ec21e2ecSJeff Kirsher /* Convert a rule to binary filter format of gianfar */
gfar_convert_to_filer(struct ethtool_rx_flow_spec * rule,struct filer_table * tab)1072ec21e2ecSJeff Kirsher static int gfar_convert_to_filer(struct ethtool_rx_flow_spec *rule,
1073ec21e2ecSJeff Kirsher 				 struct filer_table *tab)
1074ec21e2ecSJeff Kirsher {
1075ec21e2ecSJeff Kirsher 	u32 vlan = 0, vlan_mask = 0;
1076ec21e2ecSJeff Kirsher 	u32 id = 0, id_mask = 0;
1077ec21e2ecSJeff Kirsher 	u32 cfi = 0, cfi_mask = 0;
1078ec21e2ecSJeff Kirsher 	u32 prio = 0, prio_mask = 0;
1079ec21e2ecSJeff Kirsher 	u32 old_index = tab->index;
1080ec21e2ecSJeff Kirsher 
1081ec21e2ecSJeff Kirsher 	/* Check if vlan is wanted */
108242851e88SClaudiu Manoil 	if ((rule->flow_type & FLOW_EXT) &&
108342851e88SClaudiu Manoil 	    (rule->m_ext.vlan_tci != cpu_to_be16(0xFFFF))) {
1084ec21e2ecSJeff Kirsher 		if (!rule->m_ext.vlan_tci)
108542851e88SClaudiu Manoil 			rule->m_ext.vlan_tci = cpu_to_be16(0xFFFF);
1086ec21e2ecSJeff Kirsher 
1087ec21e2ecSJeff Kirsher 		vlan = RQFPR_VLN;
1088ec21e2ecSJeff Kirsher 		vlan_mask = RQFPR_VLN;
1089ec21e2ecSJeff Kirsher 
1090ec21e2ecSJeff Kirsher 		/* Separate the fields */
109142851e88SClaudiu Manoil 		id = vlan_tci_vid(rule);
109242851e88SClaudiu Manoil 		id_mask = vlan_tci_vidm(rule);
109342851e88SClaudiu Manoil 		cfi = vlan_tci_cfi(rule);
109442851e88SClaudiu Manoil 		cfi_mask = vlan_tci_cfim(rule);
109542851e88SClaudiu Manoil 		prio = vlan_tci_prio(rule);
109642851e88SClaudiu Manoil 		prio_mask = vlan_tci_priom(rule);
1097ec21e2ecSJeff Kirsher 
1098f4f9a5e6SMichał Mirosław 		if (cfi_mask) {
1099f4f9a5e6SMichał Mirosław 			if (cfi)
1100ec21e2ecSJeff Kirsher 				vlan |= RQFPR_CFI;
1101ec21e2ecSJeff Kirsher 			vlan_mask |= RQFPR_CFI;
1102ec21e2ecSJeff Kirsher 		}
1103ec21e2ecSJeff Kirsher 	}
1104ec21e2ecSJeff Kirsher 
1105ec21e2ecSJeff Kirsher 	switch (rule->flow_type & ~FLOW_EXT) {
1106ec21e2ecSJeff Kirsher 	case TCP_V4_FLOW:
1107ec21e2ecSJeff Kirsher 		gfar_set_parse_bits(RQFPR_IPV4 | RQFPR_TCP | vlan,
1108ec21e2ecSJeff Kirsher 				    RQFPR_IPV4 | RQFPR_TCP | vlan_mask, tab);
1109ec21e2ecSJeff Kirsher 		gfar_set_basic_ip(&rule->h_u.tcp_ip4_spec,
1110ec21e2ecSJeff Kirsher 				  &rule->m_u.tcp_ip4_spec, tab);
1111ec21e2ecSJeff Kirsher 		break;
1112ec21e2ecSJeff Kirsher 	case UDP_V4_FLOW:
1113ec21e2ecSJeff Kirsher 		gfar_set_parse_bits(RQFPR_IPV4 | RQFPR_UDP | vlan,
1114ec21e2ecSJeff Kirsher 				    RQFPR_IPV4 | RQFPR_UDP | vlan_mask, tab);
1115ec21e2ecSJeff Kirsher 		gfar_set_basic_ip(&rule->h_u.udp_ip4_spec,
1116ec21e2ecSJeff Kirsher 				  &rule->m_u.udp_ip4_spec, tab);
1117ec21e2ecSJeff Kirsher 		break;
1118ec21e2ecSJeff Kirsher 	case SCTP_V4_FLOW:
1119ec21e2ecSJeff Kirsher 		gfar_set_parse_bits(RQFPR_IPV4 | vlan, RQFPR_IPV4 | vlan_mask,
1120ec21e2ecSJeff Kirsher 				    tab);
1121ec21e2ecSJeff Kirsher 		gfar_set_attribute(132, 0, RQFCR_PID_L4P, tab);
1122ec21e2ecSJeff Kirsher 		gfar_set_basic_ip((struct ethtool_tcpip4_spec *)&rule->h_u,
1123cbfc6071SJan Ceuleers 				  (struct ethtool_tcpip4_spec *)&rule->m_u,
1124cbfc6071SJan Ceuleers 				  tab);
1125ec21e2ecSJeff Kirsher 		break;
1126ec21e2ecSJeff Kirsher 	case IP_USER_FLOW:
1127ec21e2ecSJeff Kirsher 		gfar_set_parse_bits(RQFPR_IPV4 | vlan, RQFPR_IPV4 | vlan_mask,
1128ec21e2ecSJeff Kirsher 				    tab);
1129ec21e2ecSJeff Kirsher 		gfar_set_user_ip((struct ethtool_usrip4_spec *) &rule->h_u,
1130cbfc6071SJan Ceuleers 				 (struct ethtool_usrip4_spec *) &rule->m_u,
1131cbfc6071SJan Ceuleers 				 tab);
1132ec21e2ecSJeff Kirsher 		break;
1133ec21e2ecSJeff Kirsher 	case ETHER_FLOW:
1134ec21e2ecSJeff Kirsher 		if (vlan)
1135ec21e2ecSJeff Kirsher 			gfar_set_parse_bits(vlan, vlan_mask, tab);
1136ec21e2ecSJeff Kirsher 		gfar_set_ether((struct ethhdr *) &rule->h_u,
1137ec21e2ecSJeff Kirsher 			       (struct ethhdr *) &rule->m_u, tab);
1138ec21e2ecSJeff Kirsher 		break;
1139ec21e2ecSJeff Kirsher 	default:
1140ec21e2ecSJeff Kirsher 		return -1;
1141ec21e2ecSJeff Kirsher 	}
1142ec21e2ecSJeff Kirsher 
1143ec21e2ecSJeff Kirsher 	/* Set the vlan attributes in the end */
1144ec21e2ecSJeff Kirsher 	if (vlan) {
1145ec21e2ecSJeff Kirsher 		gfar_set_attribute(id, id_mask, RQFCR_PID_VID, tab);
1146ec21e2ecSJeff Kirsher 		gfar_set_attribute(prio, prio_mask, RQFCR_PID_PRI, tab);
1147ec21e2ecSJeff Kirsher 	}
1148ec21e2ecSJeff Kirsher 
1149ec21e2ecSJeff Kirsher 	/* If there has been nothing written till now, it must be a default */
1150ec21e2ecSJeff Kirsher 	if (tab->index == old_index) {
1151ec21e2ecSJeff Kirsher 		gfar_set_mask(0xFFFFFFFF, tab);
1152ec21e2ecSJeff Kirsher 		tab->fe[tab->index].ctrl = 0x20;
1153ec21e2ecSJeff Kirsher 		tab->fe[tab->index].prop = 0x0;
1154ec21e2ecSJeff Kirsher 		tab->index++;
1155ec21e2ecSJeff Kirsher 	}
1156ec21e2ecSJeff Kirsher 
1157ec21e2ecSJeff Kirsher 	/* Remove last AND */
1158ec21e2ecSJeff Kirsher 	tab->fe[tab->index - 1].ctrl &= (~RQFCR_AND);
1159ec21e2ecSJeff Kirsher 
1160ec21e2ecSJeff Kirsher 	/* Specify which queue to use or to drop */
1161ec21e2ecSJeff Kirsher 	if (rule->ring_cookie == RX_CLS_FLOW_DISC)
1162ec21e2ecSJeff Kirsher 		tab->fe[tab->index - 1].ctrl |= RQFCR_RJE;
1163ec21e2ecSJeff Kirsher 	else
1164ec21e2ecSJeff Kirsher 		tab->fe[tab->index - 1].ctrl |= (rule->ring_cookie << 10);
1165ec21e2ecSJeff Kirsher 
1166ec21e2ecSJeff Kirsher 	/* Only big enough entries can be clustered */
1167ec21e2ecSJeff Kirsher 	if (tab->index > (old_index + 2)) {
1168ec21e2ecSJeff Kirsher 		tab->fe[old_index + 1].ctrl |= RQFCR_CLE;
1169ec21e2ecSJeff Kirsher 		tab->fe[tab->index - 1].ctrl |= RQFCR_CLE;
1170ec21e2ecSJeff Kirsher 	}
1171ec21e2ecSJeff Kirsher 
1172cbfc6071SJan Ceuleers 	/* In rare cases the cache can be full while there is
1173cbfc6071SJan Ceuleers 	 * free space in hw
1174cbfc6071SJan Ceuleers 	 */
1175ec21e2ecSJeff Kirsher 	if (tab->index > MAX_FILER_CACHE_IDX - 1)
1176ec21e2ecSJeff Kirsher 		return -EBUSY;
1177ec21e2ecSJeff Kirsher 
1178ec21e2ecSJeff Kirsher 	return 0;
1179ec21e2ecSJeff Kirsher }
1180ec21e2ecSJeff Kirsher 
1181ec21e2ecSJeff Kirsher /* Write the bit-pattern from software's buffer to hardware registers */
gfar_write_filer_table(struct gfar_private * priv,struct filer_table * tab)1182ec21e2ecSJeff Kirsher static int gfar_write_filer_table(struct gfar_private *priv,
1183ec21e2ecSJeff Kirsher 				  struct filer_table *tab)
1184ec21e2ecSJeff Kirsher {
1185ec21e2ecSJeff Kirsher 	u32 i = 0;
1186ec21e2ecSJeff Kirsher 	if (tab->index > MAX_FILER_IDX - 1)
1187ec21e2ecSJeff Kirsher 		return -EBUSY;
1188ec21e2ecSJeff Kirsher 
1189ec21e2ecSJeff Kirsher 	/* Fill regular entries */
1190a898fe04SJakub Kicinski 	for (; i < MAX_FILER_IDX && (tab->fe[i].ctrl | tab->fe[i].prop); i++)
1191ec21e2ecSJeff Kirsher 		gfar_write_filer(priv, i, tab->fe[i].ctrl, tab->fe[i].prop);
1192ec21e2ecSJeff Kirsher 	/* Fill the rest with fall-troughs */
1193a898fe04SJakub Kicinski 	for (; i < MAX_FILER_IDX; i++)
1194ec21e2ecSJeff Kirsher 		gfar_write_filer(priv, i, 0x60, 0xFFFFFFFF);
1195ec21e2ecSJeff Kirsher 	/* Last entry must be default accept
1196cbfc6071SJan Ceuleers 	 * because that's what people expect
1197cbfc6071SJan Ceuleers 	 */
1198ec21e2ecSJeff Kirsher 	gfar_write_filer(priv, i, 0x20, 0x0);
1199ec21e2ecSJeff Kirsher 
1200ec21e2ecSJeff Kirsher 	return 0;
1201ec21e2ecSJeff Kirsher }
1202ec21e2ecSJeff Kirsher 
gfar_check_capability(struct ethtool_rx_flow_spec * flow,struct gfar_private * priv)1203ec21e2ecSJeff Kirsher static int gfar_check_capability(struct ethtool_rx_flow_spec *flow,
1204ec21e2ecSJeff Kirsher 				 struct gfar_private *priv)
1205ec21e2ecSJeff Kirsher {
1206ec21e2ecSJeff Kirsher 
1207ec21e2ecSJeff Kirsher 	if (flow->flow_type & FLOW_EXT)	{
1208ec21e2ecSJeff Kirsher 		if (~flow->m_ext.data[0] || ~flow->m_ext.data[1])
1209ec21e2ecSJeff Kirsher 			netdev_warn(priv->ndev,
1210ec21e2ecSJeff Kirsher 				    "User-specific data not supported!\n");
1211ec21e2ecSJeff Kirsher 		if (~flow->m_ext.vlan_etype)
1212ec21e2ecSJeff Kirsher 			netdev_warn(priv->ndev,
1213ec21e2ecSJeff Kirsher 				    "VLAN-etype not supported!\n");
1214ec21e2ecSJeff Kirsher 	}
1215ec21e2ecSJeff Kirsher 	if (flow->flow_type == IP_USER_FLOW)
1216ec21e2ecSJeff Kirsher 		if (flow->h_u.usr_ip4_spec.ip_ver != ETH_RX_NFC_IP4)
1217ec21e2ecSJeff Kirsher 			netdev_warn(priv->ndev,
1218ec21e2ecSJeff Kirsher 				    "IP-Version differing from IPv4 not supported!\n");
1219ec21e2ecSJeff Kirsher 
1220ec21e2ecSJeff Kirsher 	return 0;
1221ec21e2ecSJeff Kirsher }
1222ec21e2ecSJeff Kirsher 
gfar_process_filer_changes(struct gfar_private * priv)1223ec21e2ecSJeff Kirsher static int gfar_process_filer_changes(struct gfar_private *priv)
1224ec21e2ecSJeff Kirsher {
1225ec21e2ecSJeff Kirsher 	struct ethtool_flow_spec_container *j;
1226ec21e2ecSJeff Kirsher 	struct filer_table *tab;
1227ec21e2ecSJeff Kirsher 	s32 ret = 0;
1228ec21e2ecSJeff Kirsher 
1229ec21e2ecSJeff Kirsher 	/* So index is set to zero, too! */
1230ec21e2ecSJeff Kirsher 	tab = kzalloc(sizeof(*tab), GFP_KERNEL);
1231ec21e2ecSJeff Kirsher 	if (tab == NULL)
1232ec21e2ecSJeff Kirsher 		return -ENOMEM;
1233ec21e2ecSJeff Kirsher 
1234ec21e2ecSJeff Kirsher 	/* Now convert the existing filer data from flow_spec into
1235cbfc6071SJan Ceuleers 	 * filer tables binary format
1236cbfc6071SJan Ceuleers 	 */
1237ec21e2ecSJeff Kirsher 	list_for_each_entry(j, &priv->rx_list.list, list) {
1238ec21e2ecSJeff Kirsher 		ret = gfar_convert_to_filer(&j->fs, tab);
1239ec21e2ecSJeff Kirsher 		if (ret == -EBUSY) {
1240cbfc6071SJan Ceuleers 			netdev_err(priv->ndev,
1241cbfc6071SJan Ceuleers 				   "Rule not added: No free space!\n");
1242ec21e2ecSJeff Kirsher 			goto end;
1243ec21e2ecSJeff Kirsher 		}
1244ec21e2ecSJeff Kirsher 		if (ret == -1) {
1245cbfc6071SJan Ceuleers 			netdev_err(priv->ndev,
1246cbfc6071SJan Ceuleers 				   "Rule not added: Unsupported Flow-type!\n");
1247ec21e2ecSJeff Kirsher 			goto end;
1248ec21e2ecSJeff Kirsher 		}
1249ec21e2ecSJeff Kirsher 	}
1250ec21e2ecSJeff Kirsher 
1251ec21e2ecSJeff Kirsher 	/* Write everything to hardware */
1252ec21e2ecSJeff Kirsher 	ret = gfar_write_filer_table(priv, tab);
1253ec21e2ecSJeff Kirsher 	if (ret == -EBUSY) {
1254ec21e2ecSJeff Kirsher 		netdev_err(priv->ndev, "Rule not added: No free space!\n");
1255ec21e2ecSJeff Kirsher 		goto end;
1256ec21e2ecSJeff Kirsher 	}
1257ec21e2ecSJeff Kirsher 
1258cbfc6071SJan Ceuleers end:
1259cbfc6071SJan Ceuleers 	kfree(tab);
1260ec21e2ecSJeff Kirsher 	return ret;
1261ec21e2ecSJeff Kirsher }
1262ec21e2ecSJeff Kirsher 
gfar_invert_masks(struct ethtool_rx_flow_spec * flow)1263ec21e2ecSJeff Kirsher static void gfar_invert_masks(struct ethtool_rx_flow_spec *flow)
1264ec21e2ecSJeff Kirsher {
1265ec21e2ecSJeff Kirsher 	u32 i = 0;
1266ec21e2ecSJeff Kirsher 
1267ec21e2ecSJeff Kirsher 	for (i = 0; i < sizeof(flow->m_u); i++)
1268ec21e2ecSJeff Kirsher 		flow->m_u.hdata[i] ^= 0xFF;
1269ec21e2ecSJeff Kirsher 
127042851e88SClaudiu Manoil 	flow->m_ext.vlan_etype ^= cpu_to_be16(0xFFFF);
127142851e88SClaudiu Manoil 	flow->m_ext.vlan_tci ^= cpu_to_be16(0xFFFF);
127242851e88SClaudiu Manoil 	flow->m_ext.data[0] ^= cpu_to_be32(~0);
127342851e88SClaudiu Manoil 	flow->m_ext.data[1] ^= cpu_to_be32(~0);
1274ec21e2ecSJeff Kirsher }
1275ec21e2ecSJeff Kirsher 
gfar_add_cls(struct gfar_private * priv,struct ethtool_rx_flow_spec * flow)1276ec21e2ecSJeff Kirsher static int gfar_add_cls(struct gfar_private *priv,
1277ec21e2ecSJeff Kirsher 			struct ethtool_rx_flow_spec *flow)
1278ec21e2ecSJeff Kirsher {
1279ec21e2ecSJeff Kirsher 	struct ethtool_flow_spec_container *temp, *comp;
1280ec21e2ecSJeff Kirsher 	int ret = 0;
1281ec21e2ecSJeff Kirsher 
1282ec21e2ecSJeff Kirsher 	temp = kmalloc(sizeof(*temp), GFP_KERNEL);
1283ec21e2ecSJeff Kirsher 	if (temp == NULL)
1284ec21e2ecSJeff Kirsher 		return -ENOMEM;
1285ec21e2ecSJeff Kirsher 	memcpy(&temp->fs, flow, sizeof(temp->fs));
1286ec21e2ecSJeff Kirsher 
1287ec21e2ecSJeff Kirsher 	gfar_invert_masks(&temp->fs);
1288ec21e2ecSJeff Kirsher 	ret = gfar_check_capability(&temp->fs, priv);
1289ec21e2ecSJeff Kirsher 	if (ret)
1290ec21e2ecSJeff Kirsher 		goto clean_mem;
1291ec21e2ecSJeff Kirsher 	/* Link in the new element at the right @location */
1292ec21e2ecSJeff Kirsher 	if (list_empty(&priv->rx_list.list)) {
1293ec21e2ecSJeff Kirsher 		ret = gfar_check_filer_hardware(priv);
1294ec21e2ecSJeff Kirsher 		if (ret != 0)
1295ec21e2ecSJeff Kirsher 			goto clean_mem;
1296ec21e2ecSJeff Kirsher 		list_add(&temp->list, &priv->rx_list.list);
1297ec21e2ecSJeff Kirsher 		goto process;
1298ec21e2ecSJeff Kirsher 	} else {
1299ec21e2ecSJeff Kirsher 		list_for_each_entry(comp, &priv->rx_list.list, list) {
1300ec21e2ecSJeff Kirsher 			if (comp->fs.location > flow->location) {
1301ec21e2ecSJeff Kirsher 				list_add_tail(&temp->list, &comp->list);
1302ec21e2ecSJeff Kirsher 				goto process;
1303ec21e2ecSJeff Kirsher 			}
1304ec21e2ecSJeff Kirsher 			if (comp->fs.location == flow->location) {
1305ec21e2ecSJeff Kirsher 				netdev_err(priv->ndev,
1306ec21e2ecSJeff Kirsher 					   "Rule not added: ID %d not free!\n",
1307ec21e2ecSJeff Kirsher 					   flow->location);
1308ec21e2ecSJeff Kirsher 				ret = -EBUSY;
1309ec21e2ecSJeff Kirsher 				goto clean_mem;
1310ec21e2ecSJeff Kirsher 			}
1311ec21e2ecSJeff Kirsher 		}
1312ec21e2ecSJeff Kirsher 		list_add_tail(&temp->list, &priv->rx_list.list);
1313ec21e2ecSJeff Kirsher 	}
1314ec21e2ecSJeff Kirsher 
1315ec21e2ecSJeff Kirsher process:
1316b5c8c890SJakub Kicinski 	priv->rx_list.count++;
1317ec21e2ecSJeff Kirsher 	ret = gfar_process_filer_changes(priv);
1318ec21e2ecSJeff Kirsher 	if (ret)
1319ec21e2ecSJeff Kirsher 		goto clean_list;
1320ec21e2ecSJeff Kirsher 	return ret;
1321ec21e2ecSJeff Kirsher 
1322ec21e2ecSJeff Kirsher clean_list:
1323b5c8c890SJakub Kicinski 	priv->rx_list.count--;
1324ec21e2ecSJeff Kirsher 	list_del(&temp->list);
1325ec21e2ecSJeff Kirsher clean_mem:
1326ec21e2ecSJeff Kirsher 	kfree(temp);
1327ec21e2ecSJeff Kirsher 	return ret;
1328ec21e2ecSJeff Kirsher }
1329ec21e2ecSJeff Kirsher 
gfar_del_cls(struct gfar_private * priv,u32 loc)1330ec21e2ecSJeff Kirsher static int gfar_del_cls(struct gfar_private *priv, u32 loc)
1331ec21e2ecSJeff Kirsher {
1332ec21e2ecSJeff Kirsher 	struct ethtool_flow_spec_container *comp;
1333ec21e2ecSJeff Kirsher 	u32 ret = -EINVAL;
1334ec21e2ecSJeff Kirsher 
1335ec21e2ecSJeff Kirsher 	if (list_empty(&priv->rx_list.list))
1336ec21e2ecSJeff Kirsher 		return ret;
1337ec21e2ecSJeff Kirsher 
1338ec21e2ecSJeff Kirsher 	list_for_each_entry(comp, &priv->rx_list.list, list) {
1339ec21e2ecSJeff Kirsher 		if (comp->fs.location == loc) {
1340ec21e2ecSJeff Kirsher 			list_del(&comp->list);
1341ec21e2ecSJeff Kirsher 			kfree(comp);
1342ec21e2ecSJeff Kirsher 			priv->rx_list.count--;
1343ec21e2ecSJeff Kirsher 			gfar_process_filer_changes(priv);
1344ec21e2ecSJeff Kirsher 			ret = 0;
1345ec21e2ecSJeff Kirsher 			break;
1346ec21e2ecSJeff Kirsher 		}
1347ec21e2ecSJeff Kirsher 	}
1348ec21e2ecSJeff Kirsher 
1349ec21e2ecSJeff Kirsher 	return ret;
1350ec21e2ecSJeff Kirsher }
1351ec21e2ecSJeff Kirsher 
gfar_get_cls(struct gfar_private * priv,struct ethtool_rxnfc * cmd)1352ec21e2ecSJeff Kirsher static int gfar_get_cls(struct gfar_private *priv, struct ethtool_rxnfc *cmd)
1353ec21e2ecSJeff Kirsher {
1354ec21e2ecSJeff Kirsher 	struct ethtool_flow_spec_container *comp;
1355ec21e2ecSJeff Kirsher 	u32 ret = -EINVAL;
1356ec21e2ecSJeff Kirsher 
1357ec21e2ecSJeff Kirsher 	list_for_each_entry(comp, &priv->rx_list.list, list) {
1358ec21e2ecSJeff Kirsher 		if (comp->fs.location == cmd->fs.location) {
1359ec21e2ecSJeff Kirsher 			memcpy(&cmd->fs, &comp->fs, sizeof(cmd->fs));
1360ec21e2ecSJeff Kirsher 			gfar_invert_masks(&cmd->fs);
1361ec21e2ecSJeff Kirsher 			ret = 0;
1362ec21e2ecSJeff Kirsher 			break;
1363ec21e2ecSJeff Kirsher 		}
1364ec21e2ecSJeff Kirsher 	}
1365ec21e2ecSJeff Kirsher 
1366ec21e2ecSJeff Kirsher 	return ret;
1367ec21e2ecSJeff Kirsher }
1368ec21e2ecSJeff Kirsher 
gfar_get_cls_all(struct gfar_private * priv,struct ethtool_rxnfc * cmd,u32 * rule_locs)1369ec21e2ecSJeff Kirsher static int gfar_get_cls_all(struct gfar_private *priv,
1370ec21e2ecSJeff Kirsher 			    struct ethtool_rxnfc *cmd, u32 *rule_locs)
1371ec21e2ecSJeff Kirsher {
1372ec21e2ecSJeff Kirsher 	struct ethtool_flow_spec_container *comp;
1373ec21e2ecSJeff Kirsher 	u32 i = 0;
1374ec21e2ecSJeff Kirsher 
1375ec21e2ecSJeff Kirsher 	list_for_each_entry(comp, &priv->rx_list.list, list) {
13768decf868SDavid S. Miller 		if (i == cmd->rule_cnt)
13778decf868SDavid S. Miller 			return -EMSGSIZE;
1378ec21e2ecSJeff Kirsher 		rule_locs[i] = comp->fs.location;
1379ec21e2ecSJeff Kirsher 		i++;
1380ec21e2ecSJeff Kirsher 	}
1381ec21e2ecSJeff Kirsher 
1382ec21e2ecSJeff Kirsher 	cmd->data = MAX_FILER_IDX;
1383473e64eeSBen Hutchings 	cmd->rule_cnt = i;
1384ec21e2ecSJeff Kirsher 
1385ec21e2ecSJeff Kirsher 	return 0;
1386ec21e2ecSJeff Kirsher }
1387ec21e2ecSJeff Kirsher 
gfar_set_nfc(struct net_device * dev,struct ethtool_rxnfc * cmd)1388ec21e2ecSJeff Kirsher static int gfar_set_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
1389ec21e2ecSJeff Kirsher {
1390ec21e2ecSJeff Kirsher 	struct gfar_private *priv = netdev_priv(dev);
1391ec21e2ecSJeff Kirsher 	int ret = 0;
1392ec21e2ecSJeff Kirsher 
13930851133bSClaudiu Manoil 	if (test_bit(GFAR_RESETTING, &priv->state))
13940851133bSClaudiu Manoil 		return -EBUSY;
13950851133bSClaudiu Manoil 
1396ec21e2ecSJeff Kirsher 	mutex_lock(&priv->rx_queue_access);
1397ec21e2ecSJeff Kirsher 
1398ec21e2ecSJeff Kirsher 	switch (cmd->cmd) {
1399ec21e2ecSJeff Kirsher 	case ETHTOOL_SRXFH:
1400ec21e2ecSJeff Kirsher 		ret = gfar_set_hash_opts(priv, cmd);
1401ec21e2ecSJeff Kirsher 		break;
1402ec21e2ecSJeff Kirsher 	case ETHTOOL_SRXCLSRLINS:
14033a73e49cSBen Hutchings 		if ((cmd->fs.ring_cookie != RX_CLS_FLOW_DISC &&
14043a73e49cSBen Hutchings 		     cmd->fs.ring_cookie >= priv->num_rx_queues) ||
14053a73e49cSBen Hutchings 		    cmd->fs.location >= MAX_FILER_IDX) {
1406ec21e2ecSJeff Kirsher 			ret = -EINVAL;
1407ec21e2ecSJeff Kirsher 			break;
1408ec21e2ecSJeff Kirsher 		}
1409ec21e2ecSJeff Kirsher 		ret = gfar_add_cls(priv, &cmd->fs);
1410ec21e2ecSJeff Kirsher 		break;
1411ec21e2ecSJeff Kirsher 	case ETHTOOL_SRXCLSRLDEL:
1412ec21e2ecSJeff Kirsher 		ret = gfar_del_cls(priv, cmd->fs.location);
1413ec21e2ecSJeff Kirsher 		break;
1414ec21e2ecSJeff Kirsher 	default:
1415ec21e2ecSJeff Kirsher 		ret = -EINVAL;
1416ec21e2ecSJeff Kirsher 	}
1417ec21e2ecSJeff Kirsher 
1418ec21e2ecSJeff Kirsher 	mutex_unlock(&priv->rx_queue_access);
1419ec21e2ecSJeff Kirsher 
1420ec21e2ecSJeff Kirsher 	return ret;
1421ec21e2ecSJeff Kirsher }
1422ec21e2ecSJeff Kirsher 
gfar_get_nfc(struct net_device * dev,struct ethtool_rxnfc * cmd,u32 * rule_locs)1423ec21e2ecSJeff Kirsher static int gfar_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
1424815c7db5SBen Hutchings 			u32 *rule_locs)
1425ec21e2ecSJeff Kirsher {
1426ec21e2ecSJeff Kirsher 	struct gfar_private *priv = netdev_priv(dev);
1427ec21e2ecSJeff Kirsher 	int ret = 0;
1428ec21e2ecSJeff Kirsher 
1429ec21e2ecSJeff Kirsher 	switch (cmd->cmd) {
1430ec21e2ecSJeff Kirsher 	case ETHTOOL_GRXRINGS:
1431ec21e2ecSJeff Kirsher 		cmd->data = priv->num_rx_queues;
1432ec21e2ecSJeff Kirsher 		break;
1433ec21e2ecSJeff Kirsher 	case ETHTOOL_GRXCLSRLCNT:
1434ec21e2ecSJeff Kirsher 		cmd->rule_cnt = priv->rx_list.count;
1435ec21e2ecSJeff Kirsher 		break;
1436ec21e2ecSJeff Kirsher 	case ETHTOOL_GRXCLSRULE:
1437ec21e2ecSJeff Kirsher 		ret = gfar_get_cls(priv, cmd);
1438ec21e2ecSJeff Kirsher 		break;
1439ec21e2ecSJeff Kirsher 	case ETHTOOL_GRXCLSRLALL:
1440815c7db5SBen Hutchings 		ret = gfar_get_cls_all(priv, cmd, rule_locs);
1441ec21e2ecSJeff Kirsher 		break;
1442ec21e2ecSJeff Kirsher 	default:
1443ec21e2ecSJeff Kirsher 		ret = -EINVAL;
1444ec21e2ecSJeff Kirsher 		break;
1445ec21e2ecSJeff Kirsher 	}
1446ec21e2ecSJeff Kirsher 
1447ec21e2ecSJeff Kirsher 	return ret;
1448ec21e2ecSJeff Kirsher }
1449ec21e2ecSJeff Kirsher 
gfar_get_ts_info(struct net_device * dev,struct kernel_ethtool_ts_info * info)145066636287SRichard Cochran static int gfar_get_ts_info(struct net_device *dev,
14512111375bSKory Maincent 			    struct kernel_ethtool_ts_info *info)
145266636287SRichard Cochran {
145366636287SRichard Cochran 	struct gfar_private *priv = netdev_priv(dev);
14547349a74eSYangbo Lu 	struct platform_device *ptp_dev;
14557349a74eSYangbo Lu 	struct device_node *ptp_node;
14561e562c81SYangbo Lu 	struct ptp_qoriq *ptp = NULL;
14577349a74eSYangbo Lu 
145866636287SRichard Cochran 	if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)) {
1459*673ec22bSGal Pressman 		info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE;
146066636287SRichard Cochran 		return 0;
146166636287SRichard Cochran 	}
14627349a74eSYangbo Lu 
14637349a74eSYangbo Lu 	ptp_node = of_find_compatible_node(NULL, NULL, "fsl,etsec-ptp");
14647349a74eSYangbo Lu 	if (ptp_node) {
14657349a74eSYangbo Lu 		ptp_dev = of_find_device_by_node(ptp_node);
14662ac5b58eSMiaoqian Lin 		of_node_put(ptp_node);
14677349a74eSYangbo Lu 		if (ptp_dev)
14687349a74eSYangbo Lu 			ptp = platform_get_drvdata(ptp_dev);
14697349a74eSYangbo Lu 	}
14707349a74eSYangbo Lu 
14717349a74eSYangbo Lu 	if (ptp)
14727349a74eSYangbo Lu 		info->phc_index = ptp->phc_index;
14737349a74eSYangbo Lu 
1474cbfc6071SJan Ceuleers 	info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
147566636287SRichard Cochran 				SOF_TIMESTAMPING_RX_HARDWARE |
1476c7e5c423SVladimir Oltean 				SOF_TIMESTAMPING_RAW_HARDWARE |
1477*673ec22bSGal Pressman 				SOF_TIMESTAMPING_TX_SOFTWARE;
1478cbfc6071SJan Ceuleers 	info->tx_types = (1 << HWTSTAMP_TX_OFF) |
147966636287SRichard Cochran 			 (1 << HWTSTAMP_TX_ON);
1480cbfc6071SJan Ceuleers 	info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
148166636287SRichard Cochran 			   (1 << HWTSTAMP_FILTER_ALL);
148266636287SRichard Cochran 	return 0;
148366636287SRichard Cochran }
148466636287SRichard Cochran 
1485ec21e2ecSJeff Kirsher const struct ethtool_ops gfar_ethtool_ops = {
14864db08693SJakub Kicinski 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
14874db08693SJakub Kicinski 				     ETHTOOL_COALESCE_MAX_FRAMES,
1488ec21e2ecSJeff Kirsher 	.get_drvinfo = gfar_gdrvinfo,
1489ec21e2ecSJeff Kirsher 	.get_regs_len = gfar_reglen,
1490ec21e2ecSJeff Kirsher 	.get_regs = gfar_get_regs,
1491ec21e2ecSJeff Kirsher 	.get_link = ethtool_op_get_link,
1492ec21e2ecSJeff Kirsher 	.get_coalesce = gfar_gcoalesce,
1493ec21e2ecSJeff Kirsher 	.set_coalesce = gfar_scoalesce,
1494ec21e2ecSJeff Kirsher 	.get_ringparam = gfar_gringparam,
1495ec21e2ecSJeff Kirsher 	.set_ringparam = gfar_sringparam,
149623402bddSClaudiu Manoil 	.get_pauseparam = gfar_gpauseparam,
149723402bddSClaudiu Manoil 	.set_pauseparam = gfar_spauseparam,
1498ec21e2ecSJeff Kirsher 	.get_strings = gfar_gstrings,
1499ec21e2ecSJeff Kirsher 	.get_sset_count = gfar_sset_count,
1500ec21e2ecSJeff Kirsher 	.get_ethtool_stats = gfar_fill_stats,
1501ec21e2ecSJeff Kirsher 	.get_msglevel = gfar_get_msglevel,
1502ec21e2ecSJeff Kirsher 	.set_msglevel = gfar_set_msglevel,
1503ec21e2ecSJeff Kirsher #ifdef CONFIG_PM
1504ec21e2ecSJeff Kirsher 	.get_wol = gfar_get_wol,
1505ec21e2ecSJeff Kirsher 	.set_wol = gfar_set_wol,
1506ec21e2ecSJeff Kirsher #endif
1507ec21e2ecSJeff Kirsher 	.set_rxnfc = gfar_set_nfc,
1508ec21e2ecSJeff Kirsher 	.get_rxnfc = gfar_get_nfc,
150966636287SRichard Cochran 	.get_ts_info = gfar_get_ts_info,
1510cd5f9bb4SPhilippe Reynes 	.get_link_ksettings = phy_ethtool_get_link_ksettings,
1511cd5f9bb4SPhilippe Reynes 	.set_link_ksettings = phy_ethtool_set_link_ksettings,
1512ec21e2ecSJeff Kirsher };
1513