1fe267a55SPedro F. Giffuni /*-
2fe267a55SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3fe267a55SPedro F. Giffuni *
4aa0a1e58SJeff Roberson * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
5aa0a1e58SJeff Roberson *
6aa0a1e58SJeff Roberson * This software is available to you under a choice of one of two
7aa0a1e58SJeff Roberson * licenses. You may choose to be licensed under the terms of the GNU
8aa0a1e58SJeff Roberson * General Public License (GPL) Version 2, available from the file
9aa0a1e58SJeff Roberson * COPYING in the main directory of this source tree, or the
10aa0a1e58SJeff Roberson * OpenIB.org BSD license below:
11aa0a1e58SJeff Roberson *
12aa0a1e58SJeff Roberson * Redistribution and use in source and binary forms, with or
13aa0a1e58SJeff Roberson * without modification, are permitted provided that the following
14aa0a1e58SJeff Roberson * conditions are met:
15aa0a1e58SJeff Roberson *
16aa0a1e58SJeff Roberson * - Redistributions of source code must retain the above
17aa0a1e58SJeff Roberson * copyright notice, this list of conditions and the following
18aa0a1e58SJeff Roberson * disclaimer.
19aa0a1e58SJeff Roberson *
20aa0a1e58SJeff Roberson * - Redistributions in binary form must reproduce the above
21aa0a1e58SJeff Roberson * copyright notice, this list of conditions and the following
22aa0a1e58SJeff Roberson * disclaimer in the documentation and/or other materials
23aa0a1e58SJeff Roberson * provided with the distribution.
24aa0a1e58SJeff Roberson *
25aa0a1e58SJeff Roberson * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26aa0a1e58SJeff Roberson * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27aa0a1e58SJeff Roberson * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28aa0a1e58SJeff Roberson * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29aa0a1e58SJeff Roberson * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30aa0a1e58SJeff Roberson * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31aa0a1e58SJeff Roberson * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32aa0a1e58SJeff Roberson * SOFTWARE.
33aa0a1e58SJeff Roberson */
34aa0a1e58SJeff Roberson
35cda1e10cSHans Petter Selasky #include <sys/cdefs.h>
36aa0a1e58SJeff Roberson #include <linux/kernel.h>
37aa0a1e58SJeff Roberson #include <linux/netdevice.h>
38aa0a1e58SJeff Roberson
39aa0a1e58SJeff Roberson #include "ipoib.h"
40aa0a1e58SJeff Roberson
ipoib_get_drvinfo(if_t netdev,struct ethtool_drvinfo * drvinfo)413e142e07SJustin Hibbits static void ipoib_get_drvinfo(if_t netdev,
42aa0a1e58SJeff Roberson struct ethtool_drvinfo *drvinfo)
43aa0a1e58SJeff Roberson {
44aa0a1e58SJeff Roberson strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1);
45aa0a1e58SJeff Roberson }
46aa0a1e58SJeff Roberson
ipoib_get_rx_csum(if_t dev)473e142e07SJustin Hibbits static u32 ipoib_get_rx_csum(if_t dev)
48aa0a1e58SJeff Roberson {
49aa0a1e58SJeff Roberson struct ipoib_dev_priv *priv = dev->if_softc;
50aa0a1e58SJeff Roberson return test_bit(IPOIB_FLAG_CSUM, &priv->flags) &&
51aa0a1e58SJeff Roberson !test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
52aa0a1e58SJeff Roberson }
53aa0a1e58SJeff Roberson
ipoib_get_coalesce(if_t dev,struct ethtool_coalesce * coal)543e142e07SJustin Hibbits static int ipoib_get_coalesce(if_t dev,
55aa0a1e58SJeff Roberson struct ethtool_coalesce *coal)
56aa0a1e58SJeff Roberson {
57aa0a1e58SJeff Roberson struct ipoib_dev_priv *priv = dev->if_softc;
58aa0a1e58SJeff Roberson
59aa0a1e58SJeff Roberson coal->rx_coalesce_usecs = priv->ethtool.coalesce_usecs;
60aa0a1e58SJeff Roberson coal->tx_coalesce_usecs = priv->ethtool.coalesce_usecs;
61aa0a1e58SJeff Roberson coal->rx_max_coalesced_frames = priv->ethtool.max_coalesced_frames;
62aa0a1e58SJeff Roberson coal->tx_max_coalesced_frames = priv->ethtool.max_coalesced_frames;
63aa0a1e58SJeff Roberson
64aa0a1e58SJeff Roberson return 0;
65aa0a1e58SJeff Roberson }
66aa0a1e58SJeff Roberson
ipoib_set_coalesce(if_t dev,struct ethtool_coalesce * coal)673e142e07SJustin Hibbits static int ipoib_set_coalesce(if_t dev,
68aa0a1e58SJeff Roberson struct ethtool_coalesce *coal)
69aa0a1e58SJeff Roberson {
70aa0a1e58SJeff Roberson struct ipoib_dev_priv *priv = dev->if_softc;
71aa0a1e58SJeff Roberson int ret;
72aa0a1e58SJeff Roberson
73aa0a1e58SJeff Roberson /*
74aa0a1e58SJeff Roberson * Since IPoIB uses a single CQ for both rx and tx, we assume
75aa0a1e58SJeff Roberson * that rx params dictate the configuration. These values are
76aa0a1e58SJeff Roberson * saved in the private data and returned when ipoib_get_coalesce()
77aa0a1e58SJeff Roberson * is called.
78aa0a1e58SJeff Roberson */
79aa0a1e58SJeff Roberson if (coal->rx_coalesce_usecs > 0xffff ||
80aa0a1e58SJeff Roberson coal->rx_max_coalesced_frames > 0xffff)
81aa0a1e58SJeff Roberson return -EINVAL;
82aa0a1e58SJeff Roberson
83aa0a1e58SJeff Roberson if (coal->rx_max_coalesced_frames | coal->rx_coalesce_usecs) {
84aa0a1e58SJeff Roberson if (!coal->rx_max_coalesced_frames)
85aa0a1e58SJeff Roberson coal->rx_max_coalesced_frames = 0xffff;
86aa0a1e58SJeff Roberson else if (!coal->rx_coalesce_usecs)
87aa0a1e58SJeff Roberson coal->rx_coalesce_usecs = 0xffff;
88aa0a1e58SJeff Roberson }
89aa0a1e58SJeff Roberson
90aa0a1e58SJeff Roberson ret = ib_modify_cq(priv->recv_cq, coal->rx_max_coalesced_frames,
91aa0a1e58SJeff Roberson coal->rx_coalesce_usecs);
92aa0a1e58SJeff Roberson if (ret && ret != -ENOSYS) {
93aa0a1e58SJeff Roberson ipoib_warn(priv, "failed modifying CQ (%d)\n", ret);
94aa0a1e58SJeff Roberson return ret;
95aa0a1e58SJeff Roberson }
96aa0a1e58SJeff Roberson
97aa0a1e58SJeff Roberson coal->tx_coalesce_usecs = coal->rx_coalesce_usecs;
98aa0a1e58SJeff Roberson coal->tx_max_coalesced_frames = coal->rx_max_coalesced_frames;
99aa0a1e58SJeff Roberson priv->ethtool.coalesce_usecs = coal->rx_coalesce_usecs;
100aa0a1e58SJeff Roberson priv->ethtool.max_coalesced_frames = coal->rx_max_coalesced_frames;
101aa0a1e58SJeff Roberson
102aa0a1e58SJeff Roberson return 0;
103aa0a1e58SJeff Roberson }
104aa0a1e58SJeff Roberson
105aa0a1e58SJeff Roberson static const char ipoib_stats_keys[][ETH_GSTRING_LEN] = {
106aa0a1e58SJeff Roberson "LRO aggregated", "LRO flushed",
107aa0a1e58SJeff Roberson "LRO avg aggr", "LRO no desc"
108aa0a1e58SJeff Roberson };
109aa0a1e58SJeff Roberson
ipoib_get_strings(if_t netdev,u32 stringset,u8 * data)1103e142e07SJustin Hibbits static void ipoib_get_strings(if_t netdev, u32 stringset, u8 *data)
111aa0a1e58SJeff Roberson {
112aa0a1e58SJeff Roberson switch (stringset) {
113aa0a1e58SJeff Roberson case ETH_SS_STATS:
114aa0a1e58SJeff Roberson memcpy(data, *ipoib_stats_keys, sizeof(ipoib_stats_keys));
115aa0a1e58SJeff Roberson break;
116aa0a1e58SJeff Roberson }
117aa0a1e58SJeff Roberson }
118aa0a1e58SJeff Roberson
ipoib_get_sset_count(if_t dev,int sset)1193e142e07SJustin Hibbits static int ipoib_get_sset_count(if_t dev, int sset)
120aa0a1e58SJeff Roberson {
121aa0a1e58SJeff Roberson switch (sset) {
122aa0a1e58SJeff Roberson case ETH_SS_STATS:
123aa0a1e58SJeff Roberson return ARRAY_SIZE(ipoib_stats_keys);
124aa0a1e58SJeff Roberson default:
125aa0a1e58SJeff Roberson return -EOPNOTSUPP;
126aa0a1e58SJeff Roberson }
127aa0a1e58SJeff Roberson }
128aa0a1e58SJeff Roberson
ipoib_get_ethtool_stats(if_t dev,struct ethtool_stats * stats,uint64_t * data)1293e142e07SJustin Hibbits static void ipoib_get_ethtool_stats(if_t dev,
130aa0a1e58SJeff Roberson struct ethtool_stats *stats, uint64_t *data)
131aa0a1e58SJeff Roberson {
132aa0a1e58SJeff Roberson struct ipoib_dev_priv *priv = dev->if_softc;
133aa0a1e58SJeff Roberson int index = 0;
134aa0a1e58SJeff Roberson
135aa0a1e58SJeff Roberson /* Get LRO statistics */
136aa0a1e58SJeff Roberson data[index++] = priv->lro.lro_mgr.stats.aggregated;
137aa0a1e58SJeff Roberson data[index++] = priv->lro.lro_mgr.stats.flushed;
138aa0a1e58SJeff Roberson if (priv->lro.lro_mgr.stats.flushed)
139aa0a1e58SJeff Roberson data[index++] = priv->lro.lro_mgr.stats.aggregated /
140aa0a1e58SJeff Roberson priv->lro.lro_mgr.stats.flushed;
141aa0a1e58SJeff Roberson else
142aa0a1e58SJeff Roberson data[index++] = 0;
143aa0a1e58SJeff Roberson data[index++] = priv->lro.lro_mgr.stats.no_desc;
144aa0a1e58SJeff Roberson }
145aa0a1e58SJeff Roberson
146aa0a1e58SJeff Roberson static const struct ethtool_ops ipoib_ethtool_ops = {
147aa0a1e58SJeff Roberson .get_drvinfo = ipoib_get_drvinfo,
148aa0a1e58SJeff Roberson .get_rx_csum = ipoib_get_rx_csum,
149aa0a1e58SJeff Roberson .get_coalesce = ipoib_get_coalesce,
150aa0a1e58SJeff Roberson .set_coalesce = ipoib_set_coalesce,
151aa0a1e58SJeff Roberson .get_flags = ethtool_op_get_flags,
152aa0a1e58SJeff Roberson .set_flags = ethtool_op_set_flags,
153aa0a1e58SJeff Roberson .get_strings = ipoib_get_strings,
154aa0a1e58SJeff Roberson .get_sset_count = ipoib_get_sset_count,
155aa0a1e58SJeff Roberson .get_ethtool_stats = ipoib_get_ethtool_stats,
156aa0a1e58SJeff Roberson };
157aa0a1e58SJeff Roberson
ipoib_set_ethtool_ops(if_t dev)1583e142e07SJustin Hibbits void ipoib_set_ethtool_ops(if_t dev)
159aa0a1e58SJeff Roberson {
160aa0a1e58SJeff Roberson SET_ETHTOOL_OPS(dev, &ipoib_ethtool_ops);
161aa0a1e58SJeff Roberson }
162