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>
41*3d40aed8SRob Herring #include <linux/of.h>
427349a74eSYangbo Lu #include <linux/of_platform.h>
43*3d40aed8SRob 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 *) ®s->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(®s->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(®s->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(®s->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(®s->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(®s->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(®s->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 ethtool_ts_info * info)145066636287SRichard Cochran static int gfar_get_ts_info(struct net_device *dev,
145166636287SRichard Cochran struct 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
14587349a74eSYangbo Lu info->phc_index = -1;
145966636287SRichard Cochran
146066636287SRichard Cochran if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)) {
1461cbfc6071SJan Ceuleers info->so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE |
1462c7e5c423SVladimir Oltean SOF_TIMESTAMPING_TX_SOFTWARE |
146366636287SRichard Cochran SOF_TIMESTAMPING_SOFTWARE;
146466636287SRichard Cochran return 0;
146566636287SRichard Cochran }
14667349a74eSYangbo Lu
14677349a74eSYangbo Lu ptp_node = of_find_compatible_node(NULL, NULL, "fsl,etsec-ptp");
14687349a74eSYangbo Lu if (ptp_node) {
14697349a74eSYangbo Lu ptp_dev = of_find_device_by_node(ptp_node);
14702ac5b58eSMiaoqian Lin of_node_put(ptp_node);
14717349a74eSYangbo Lu if (ptp_dev)
14727349a74eSYangbo Lu ptp = platform_get_drvdata(ptp_dev);
14737349a74eSYangbo Lu }
14747349a74eSYangbo Lu
14757349a74eSYangbo Lu if (ptp)
14767349a74eSYangbo Lu info->phc_index = ptp->phc_index;
14777349a74eSYangbo Lu
1478cbfc6071SJan Ceuleers info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
147966636287SRichard Cochran SOF_TIMESTAMPING_RX_HARDWARE |
1480c7e5c423SVladimir Oltean SOF_TIMESTAMPING_RAW_HARDWARE |
1481c7e5c423SVladimir Oltean SOF_TIMESTAMPING_RX_SOFTWARE |
1482c7e5c423SVladimir Oltean SOF_TIMESTAMPING_TX_SOFTWARE |
1483c7e5c423SVladimir Oltean SOF_TIMESTAMPING_SOFTWARE;
1484cbfc6071SJan Ceuleers info->tx_types = (1 << HWTSTAMP_TX_OFF) |
148566636287SRichard Cochran (1 << HWTSTAMP_TX_ON);
1486cbfc6071SJan Ceuleers info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
148766636287SRichard Cochran (1 << HWTSTAMP_FILTER_ALL);
148866636287SRichard Cochran return 0;
148966636287SRichard Cochran }
149066636287SRichard Cochran
1491ec21e2ecSJeff Kirsher const struct ethtool_ops gfar_ethtool_ops = {
14924db08693SJakub Kicinski .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
14934db08693SJakub Kicinski ETHTOOL_COALESCE_MAX_FRAMES,
1494ec21e2ecSJeff Kirsher .get_drvinfo = gfar_gdrvinfo,
1495ec21e2ecSJeff Kirsher .get_regs_len = gfar_reglen,
1496ec21e2ecSJeff Kirsher .get_regs = gfar_get_regs,
1497ec21e2ecSJeff Kirsher .get_link = ethtool_op_get_link,
1498ec21e2ecSJeff Kirsher .get_coalesce = gfar_gcoalesce,
1499ec21e2ecSJeff Kirsher .set_coalesce = gfar_scoalesce,
1500ec21e2ecSJeff Kirsher .get_ringparam = gfar_gringparam,
1501ec21e2ecSJeff Kirsher .set_ringparam = gfar_sringparam,
150223402bddSClaudiu Manoil .get_pauseparam = gfar_gpauseparam,
150323402bddSClaudiu Manoil .set_pauseparam = gfar_spauseparam,
1504ec21e2ecSJeff Kirsher .get_strings = gfar_gstrings,
1505ec21e2ecSJeff Kirsher .get_sset_count = gfar_sset_count,
1506ec21e2ecSJeff Kirsher .get_ethtool_stats = gfar_fill_stats,
1507ec21e2ecSJeff Kirsher .get_msglevel = gfar_get_msglevel,
1508ec21e2ecSJeff Kirsher .set_msglevel = gfar_set_msglevel,
1509ec21e2ecSJeff Kirsher #ifdef CONFIG_PM
1510ec21e2ecSJeff Kirsher .get_wol = gfar_get_wol,
1511ec21e2ecSJeff Kirsher .set_wol = gfar_set_wol,
1512ec21e2ecSJeff Kirsher #endif
1513ec21e2ecSJeff Kirsher .set_rxnfc = gfar_set_nfc,
1514ec21e2ecSJeff Kirsher .get_rxnfc = gfar_get_nfc,
151566636287SRichard Cochran .get_ts_info = gfar_get_ts_info,
1516cd5f9bb4SPhilippe Reynes .get_link_ksettings = phy_ethtool_get_link_ksettings,
1517cd5f9bb4SPhilippe Reynes .set_link_ksettings = phy_ethtool_set_link_ksettings,
1518ec21e2ecSJeff Kirsher };
1519