2 * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 #include <linux/kernel.h>
34 #include <linux/ethtool.h>
35 #include <linux/netdevice.h>
40 char stat_string
[ETH_GSTRING_LEN
];
44 #define IPOIB_NETDEV_STAT(m) { \
46 .stat_offset = offsetof(struct rtnl_link_stats64, m) }
48 static const struct ipoib_stats ipoib_gstrings_stats
[] = {
49 IPOIB_NETDEV_STAT(rx_packets
),
50 IPOIB_NETDEV_STAT(tx_packets
),
51 IPOIB_NETDEV_STAT(rx_bytes
),
52 IPOIB_NETDEV_STAT(tx_bytes
),
53 IPOIB_NETDEV_STAT(tx_errors
),
54 IPOIB_NETDEV_STAT(rx_dropped
),
55 IPOIB_NETDEV_STAT(tx_dropped
)
58 #define IPOIB_GLOBAL_STATS_LEN ARRAY_SIZE(ipoib_gstrings_stats)
60 static void ipoib_get_drvinfo(struct net_device
*netdev
,
61 struct ethtool_drvinfo
*drvinfo
)
63 struct ipoib_dev_priv
*priv
= netdev_priv(netdev
);
65 ib_get_device_fw_str(priv
->ca
, drvinfo
->fw_version
,
66 sizeof(drvinfo
->fw_version
));
68 strlcpy(drvinfo
->bus_info
, dev_name(priv
->ca
->dma_device
),
69 sizeof(drvinfo
->bus_info
));
71 strlcpy(drvinfo
->version
, ipoib_driver_version
,
72 sizeof(drvinfo
->version
));
74 strlcpy(drvinfo
->driver
, "ib_ipoib", sizeof(drvinfo
->driver
));
77 static int ipoib_get_coalesce(struct net_device
*dev
,
78 struct ethtool_coalesce
*coal
)
80 struct ipoib_dev_priv
*priv
= netdev_priv(dev
);
82 coal
->rx_coalesce_usecs
= priv
->ethtool
.coalesce_usecs
;
83 coal
->rx_max_coalesced_frames
= priv
->ethtool
.max_coalesced_frames
;
88 static int ipoib_set_coalesce(struct net_device
*dev
,
89 struct ethtool_coalesce
*coal
)
91 struct ipoib_dev_priv
*priv
= netdev_priv(dev
);
95 * These values are saved in the private data and returned
96 * when ipoib_get_coalesce() is called
98 if (coal
->rx_coalesce_usecs
> 0xffff ||
99 coal
->rx_max_coalesced_frames
> 0xffff)
102 ret
= ib_modify_cq(priv
->recv_cq
, coal
->rx_max_coalesced_frames
,
103 coal
->rx_coalesce_usecs
);
104 if (ret
&& ret
!= -ENOSYS
) {
105 ipoib_warn(priv
, "failed modifying CQ (%d)\n", ret
);
109 priv
->ethtool
.coalesce_usecs
= coal
->rx_coalesce_usecs
;
110 priv
->ethtool
.max_coalesced_frames
= coal
->rx_max_coalesced_frames
;
114 static void ipoib_get_ethtool_stats(struct net_device
*dev
,
115 struct ethtool_stats __always_unused
*stats
,
119 struct net_device_stats
*net_stats
= &dev
->stats
;
120 u8
*p
= (u8
*)net_stats
;
122 for (i
= 0; i
< IPOIB_GLOBAL_STATS_LEN
; i
++)
123 data
[i
] = *(u64
*)(p
+ ipoib_gstrings_stats
[i
].stat_offset
);
126 static void ipoib_get_strings(struct net_device __always_unused
*dev
,
127 u32 stringset
, u8
*data
)
134 for (i
= 0; i
< IPOIB_GLOBAL_STATS_LEN
; i
++) {
135 memcpy(p
, ipoib_gstrings_stats
[i
].stat_string
,
137 p
+= ETH_GSTRING_LEN
;
145 static int ipoib_get_sset_count(struct net_device __always_unused
*dev
,
150 return IPOIB_GLOBAL_STATS_LEN
;
158 static const struct ethtool_ops ipoib_ethtool_ops
= {
159 .get_drvinfo
= ipoib_get_drvinfo
,
160 .get_coalesce
= ipoib_get_coalesce
,
161 .set_coalesce
= ipoib_set_coalesce
,
162 .get_strings
= ipoib_get_strings
,
163 .get_ethtool_stats
= ipoib_get_ethtool_stats
,
164 .get_sset_count
= ipoib_get_sset_count
,
167 void ipoib_set_ethtool_ops(struct net_device
*dev
)
169 dev
->ethtool_ops
= &ipoib_ethtool_ops
;