~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise-security

« back to all changes in this revision

Viewing changes to drivers/net/mlx4/en_ethtool.c

  • Committer: Package Import Robot
  • Author(s): Paolo Pisati, Paolo Pisati
  • Date: 2011-12-06 15:56:07 UTC
  • Revision ID: package-import@ubuntu.com-20111206155607-pcf44kv5fmhk564f
Tags: 3.2.0-1401.1
[ Paolo Pisati ]

* Rebased on top of Ubuntu-3.2.0-3.8
* Tilt-tracking @ ef2487af4bb15bdd0689631774b5a5e3a59f74e2
* Delete debian.ti-omap4/control, it shoudln't be tracked
* Fix architecture spelling (s/armel/armhf/)
* [Config] Update configs following 3.2 import
* [Config] Fix compilation: disable CODA and ARCH_OMAP3
* [Config] Fix compilation: disable Ethernet Faraday
* Update series to precise

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
3
 
 *
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:
9
 
 *
10
 
 *     Redistribution and use in source and binary forms, with or
11
 
 *     without modification, are permitted provided that the following
12
 
 *     conditions are met:
13
 
 *
14
 
 *      - Redistributions of source code must retain the above
15
 
 *        copyright notice, this list of conditions and the following
16
 
 *        disclaimer.
17
 
 *
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.
22
 
 *
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
30
 
 * SOFTWARE.
31
 
 *
32
 
 */
33
 
 
34
 
#include <linux/kernel.h>
35
 
#include <linux/ethtool.h>
36
 
#include <linux/netdevice.h>
37
 
 
38
 
#include "mlx4_en.h"
39
 
#include "en_port.h"
40
 
 
41
 
 
42
 
static void
43
 
mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
44
 
{
45
 
        struct mlx4_en_priv *priv = netdev_priv(dev);
46
 
        struct mlx4_en_dev *mdev = priv->mdev;
47
 
 
48
 
        strncpy(drvinfo->driver, DRV_NAME, 32);
49
 
        strncpy(drvinfo->version, DRV_VERSION " (" DRV_RELDATE ")", 32);
50
 
        sprintf(drvinfo->fw_version, "%d.%d.%d",
51
 
                (u16) (mdev->dev->caps.fw_ver >> 32),
52
 
                (u16) ((mdev->dev->caps.fw_ver >> 16) & 0xffff),
53
 
                (u16) (mdev->dev->caps.fw_ver & 0xffff));
54
 
        strncpy(drvinfo->bus_info, pci_name(mdev->dev->pdev), 32);
55
 
        drvinfo->n_stats = 0;
56
 
        drvinfo->regdump_len = 0;
57
 
        drvinfo->eedump_len = 0;
58
 
}
59
 
 
60
 
static const char main_strings[][ETH_GSTRING_LEN] = {
61
 
        "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
62
 
        "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
63
 
        "rx_length_errors", "rx_over_errors", "rx_crc_errors",
64
 
        "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
65
 
        "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
66
 
        "tx_heartbeat_errors", "tx_window_errors",
67
 
 
68
 
        /* port statistics */
69
 
        "tso_packets",
70
 
        "queue_stopped", "wake_queue", "tx_timeout", "rx_alloc_failed",
71
 
        "rx_csum_good", "rx_csum_none", "tx_chksum_offload",
72
 
 
73
 
        /* packet statistics */
74
 
        "broadcast", "rx_prio_0", "rx_prio_1", "rx_prio_2", "rx_prio_3",
75
 
        "rx_prio_4", "rx_prio_5", "rx_prio_6", "rx_prio_7", "tx_prio_0",
76
 
        "tx_prio_1", "tx_prio_2", "tx_prio_3", "tx_prio_4", "tx_prio_5",
77
 
        "tx_prio_6", "tx_prio_7",
78
 
};
79
 
#define NUM_MAIN_STATS  21
80
 
#define NUM_ALL_STATS   (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS)
81
 
 
82
 
static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= {
83
 
        "Interupt Test",
84
 
        "Link Test",
85
 
        "Speed Test",
86
 
        "Register Test",
87
 
        "Loopback Test",
88
 
};
89
 
 
90
 
static u32 mlx4_en_get_msglevel(struct net_device *dev)
91
 
{
92
 
        return ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable;
93
 
}
94
 
 
95
 
static void mlx4_en_set_msglevel(struct net_device *dev, u32 val)
96
 
{
97
 
        ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable = val;
98
 
}
99
 
 
100
 
static void mlx4_en_get_wol(struct net_device *netdev,
101
 
                            struct ethtool_wolinfo *wol)
102
 
{
103
 
        struct mlx4_en_priv *priv = netdev_priv(netdev);
104
 
        int err = 0;
105
 
        u64 config = 0;
106
 
 
107
 
        if (!priv->mdev->dev->caps.wol) {
108
 
                wol->supported = 0;
109
 
                wol->wolopts = 0;
110
 
                return;
111
 
        }
112
 
 
113
 
        err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
114
 
        if (err) {
115
 
                en_err(priv, "Failed to get WoL information\n");
116
 
                return;
117
 
        }
118
 
 
119
 
        if (config & MLX4_EN_WOL_MAGIC)
120
 
                wol->supported = WAKE_MAGIC;
121
 
        else
122
 
                wol->supported = 0;
123
 
 
124
 
        if (config & MLX4_EN_WOL_ENABLED)
125
 
                wol->wolopts = WAKE_MAGIC;
126
 
        else
127
 
                wol->wolopts = 0;
128
 
}
129
 
 
130
 
static int mlx4_en_set_wol(struct net_device *netdev,
131
 
                            struct ethtool_wolinfo *wol)
132
 
{
133
 
        struct mlx4_en_priv *priv = netdev_priv(netdev);
134
 
        u64 config = 0;
135
 
        int err = 0;
136
 
 
137
 
        if (!priv->mdev->dev->caps.wol)
138
 
                return -EOPNOTSUPP;
139
 
 
140
 
        if (wol->supported & ~WAKE_MAGIC)
141
 
                return -EINVAL;
142
 
 
143
 
        err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
144
 
        if (err) {
145
 
                en_err(priv, "Failed to get WoL info, unable to modify\n");
146
 
                return err;
147
 
        }
148
 
 
149
 
        if (wol->wolopts & WAKE_MAGIC) {
150
 
                config |= MLX4_EN_WOL_DO_MODIFY | MLX4_EN_WOL_ENABLED |
151
 
                                MLX4_EN_WOL_MAGIC;
152
 
        } else {
153
 
                config &= ~(MLX4_EN_WOL_ENABLED | MLX4_EN_WOL_MAGIC);
154
 
                config |= MLX4_EN_WOL_DO_MODIFY;
155
 
        }
156
 
 
157
 
        err = mlx4_wol_write(priv->mdev->dev, config, priv->port);
158
 
        if (err)
159
 
                en_err(priv, "Failed to set WoL information\n");
160
 
 
161
 
        return err;
162
 
}
163
 
 
164
 
static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
165
 
{
166
 
        struct mlx4_en_priv *priv = netdev_priv(dev);
167
 
 
168
 
        switch (sset) {
169
 
        case ETH_SS_STATS:
170
 
                return NUM_ALL_STATS +
171
 
                        (priv->tx_ring_num + priv->rx_ring_num) * 2;
172
 
        case ETH_SS_TEST:
173
 
                return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.loopback_support) * 2;
174
 
        default:
175
 
                return -EOPNOTSUPP;
176
 
        }
177
 
}
178
 
 
179
 
static void mlx4_en_get_ethtool_stats(struct net_device *dev,
180
 
                struct ethtool_stats *stats, uint64_t *data)
181
 
{
182
 
        struct mlx4_en_priv *priv = netdev_priv(dev);
183
 
        int index = 0;
184
 
        int i;
185
 
 
186
 
        spin_lock_bh(&priv->stats_lock);
187
 
 
188
 
        for (i = 0; i < NUM_MAIN_STATS; i++)
189
 
                data[index++] = ((unsigned long *) &priv->stats)[i];
190
 
        for (i = 0; i < NUM_PORT_STATS; i++)
191
 
                data[index++] = ((unsigned long *) &priv->port_stats)[i];
192
 
        for (i = 0; i < priv->tx_ring_num; i++) {
193
 
                data[index++] = priv->tx_ring[i].packets;
194
 
                data[index++] = priv->tx_ring[i].bytes;
195
 
        }
196
 
        for (i = 0; i < priv->rx_ring_num; i++) {
197
 
                data[index++] = priv->rx_ring[i].packets;
198
 
                data[index++] = priv->rx_ring[i].bytes;
199
 
        }
200
 
        for (i = 0; i < NUM_PKT_STATS; i++)
201
 
                data[index++] = ((unsigned long *) &priv->pkstats)[i];
202
 
        spin_unlock_bh(&priv->stats_lock);
203
 
 
204
 
}
205
 
 
206
 
static void mlx4_en_self_test(struct net_device *dev,
207
 
                              struct ethtool_test *etest, u64 *buf)
208
 
{
209
 
        mlx4_en_ex_selftest(dev, &etest->flags, buf);
210
 
}
211
 
 
212
 
static void mlx4_en_get_strings(struct net_device *dev,
213
 
                                uint32_t stringset, uint8_t *data)
214
 
{
215
 
        struct mlx4_en_priv *priv = netdev_priv(dev);
216
 
        int index = 0;
217
 
        int i;
218
 
 
219
 
        switch (stringset) {
220
 
        case ETH_SS_TEST:
221
 
                for (i = 0; i < MLX4_EN_NUM_SELF_TEST - 2; i++)
222
 
                        strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
223
 
                if (priv->mdev->dev->caps.loopback_support)
224
 
                        for (; i < MLX4_EN_NUM_SELF_TEST; i++)
225
 
                                strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
226
 
                break;
227
 
 
228
 
        case ETH_SS_STATS:
229
 
                /* Add main counters */
230
 
                for (i = 0; i < NUM_MAIN_STATS; i++)
231
 
                        strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]);
232
 
                for (i = 0; i< NUM_PORT_STATS; i++)
233
 
                        strcpy(data + (index++) * ETH_GSTRING_LEN,
234
 
                        main_strings[i + NUM_MAIN_STATS]);
235
 
                for (i = 0; i < priv->tx_ring_num; i++) {
236
 
                        sprintf(data + (index++) * ETH_GSTRING_LEN,
237
 
                                "tx%d_packets", i);
238
 
                        sprintf(data + (index++) * ETH_GSTRING_LEN,
239
 
                                "tx%d_bytes", i);
240
 
                }
241
 
                for (i = 0; i < priv->rx_ring_num; i++) {
242
 
                        sprintf(data + (index++) * ETH_GSTRING_LEN,
243
 
                                "rx%d_packets", i);
244
 
                        sprintf(data + (index++) * ETH_GSTRING_LEN,
245
 
                                "rx%d_bytes", i);
246
 
                }
247
 
                for (i = 0; i< NUM_PKT_STATS; i++)
248
 
                        strcpy(data + (index++) * ETH_GSTRING_LEN,
249
 
                        main_strings[i + NUM_MAIN_STATS + NUM_PORT_STATS]);
250
 
                break;
251
 
        }
252
 
}
253
 
 
254
 
static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
255
 
{
256
 
        struct mlx4_en_priv *priv = netdev_priv(dev);
257
 
        int trans_type;
258
 
 
259
 
        cmd->autoneg = AUTONEG_DISABLE;
260
 
        cmd->supported = SUPPORTED_10000baseT_Full;
261
 
        cmd->advertising = ADVERTISED_10000baseT_Full;
262
 
 
263
 
        if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
264
 
                return -ENOMEM;
265
 
 
266
 
        trans_type = priv->port_state.transciver;
267
 
        if (netif_carrier_ok(dev)) {
268
 
                ethtool_cmd_speed_set(cmd, priv->port_state.link_speed);
269
 
                cmd->duplex = DUPLEX_FULL;
270
 
        } else {
271
 
                ethtool_cmd_speed_set(cmd, -1);
272
 
                cmd->duplex = -1;
273
 
        }
274
 
 
275
 
        if (trans_type > 0 && trans_type <= 0xC) {
276
 
                cmd->port = PORT_FIBRE;
277
 
                cmd->transceiver = XCVR_EXTERNAL;
278
 
                cmd->supported |= SUPPORTED_FIBRE;
279
 
                cmd->advertising |= ADVERTISED_FIBRE;
280
 
        } else if (trans_type == 0x80 || trans_type == 0) {
281
 
                cmd->port = PORT_TP;
282
 
                cmd->transceiver = XCVR_INTERNAL;
283
 
                cmd->supported |= SUPPORTED_TP;
284
 
                cmd->advertising |= ADVERTISED_TP;
285
 
        } else  {
286
 
                cmd->port = -1;
287
 
                cmd->transceiver = -1;
288
 
        }
289
 
        return 0;
290
 
}
291
 
 
292
 
static int mlx4_en_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
293
 
{
294
 
        if ((cmd->autoneg == AUTONEG_ENABLE) ||
295
 
            (ethtool_cmd_speed(cmd) != SPEED_10000) ||
296
 
            (cmd->duplex != DUPLEX_FULL))
297
 
                return -EINVAL;
298
 
 
299
 
        /* Nothing to change */
300
 
        return 0;
301
 
}
302
 
 
303
 
static int mlx4_en_get_coalesce(struct net_device *dev,
304
 
                              struct ethtool_coalesce *coal)
305
 
{
306
 
        struct mlx4_en_priv *priv = netdev_priv(dev);
307
 
 
308
 
        coal->tx_coalesce_usecs = 0;
309
 
        coal->tx_max_coalesced_frames = 0;
310
 
        coal->rx_coalesce_usecs = priv->rx_usecs;
311
 
        coal->rx_max_coalesced_frames = priv->rx_frames;
312
 
 
313
 
        coal->pkt_rate_low = priv->pkt_rate_low;
314
 
        coal->rx_coalesce_usecs_low = priv->rx_usecs_low;
315
 
        coal->pkt_rate_high = priv->pkt_rate_high;
316
 
        coal->rx_coalesce_usecs_high = priv->rx_usecs_high;
317
 
        coal->rate_sample_interval = priv->sample_interval;
318
 
        coal->use_adaptive_rx_coalesce = priv->adaptive_rx_coal;
319
 
        return 0;
320
 
}
321
 
 
322
 
static int mlx4_en_set_coalesce(struct net_device *dev,
323
 
                              struct ethtool_coalesce *coal)
324
 
{
325
 
        struct mlx4_en_priv *priv = netdev_priv(dev);
326
 
        int err, i;
327
 
 
328
 
        priv->rx_frames = (coal->rx_max_coalesced_frames ==
329
 
                           MLX4_EN_AUTO_CONF) ?
330
 
                                MLX4_EN_RX_COAL_TARGET :
331
 
                                coal->rx_max_coalesced_frames;
332
 
        priv->rx_usecs = (coal->rx_coalesce_usecs ==
333
 
                          MLX4_EN_AUTO_CONF) ?
334
 
                                MLX4_EN_RX_COAL_TIME :
335
 
                                coal->rx_coalesce_usecs;
336
 
 
337
 
        /* Set adaptive coalescing params */
338
 
        priv->pkt_rate_low = coal->pkt_rate_low;
339
 
        priv->rx_usecs_low = coal->rx_coalesce_usecs_low;
340
 
        priv->pkt_rate_high = coal->pkt_rate_high;
341
 
        priv->rx_usecs_high = coal->rx_coalesce_usecs_high;
342
 
        priv->sample_interval = coal->rate_sample_interval;
343
 
        priv->adaptive_rx_coal = coal->use_adaptive_rx_coalesce;
344
 
        priv->last_moder_time = MLX4_EN_AUTO_CONF;
345
 
        if (priv->adaptive_rx_coal)
346
 
                return 0;
347
 
 
348
 
        for (i = 0; i < priv->rx_ring_num; i++) {
349
 
                priv->rx_cq[i].moder_cnt = priv->rx_frames;
350
 
                priv->rx_cq[i].moder_time = priv->rx_usecs;
351
 
                err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
352
 
                if (err)
353
 
                        return err;
354
 
        }
355
 
        return 0;
356
 
}
357
 
 
358
 
static int mlx4_en_set_pauseparam(struct net_device *dev,
359
 
                                struct ethtool_pauseparam *pause)
360
 
{
361
 
        struct mlx4_en_priv *priv = netdev_priv(dev);
362
 
        struct mlx4_en_dev *mdev = priv->mdev;
363
 
        int err;
364
 
 
365
 
        priv->prof->tx_pause = pause->tx_pause != 0;
366
 
        priv->prof->rx_pause = pause->rx_pause != 0;
367
 
        err = mlx4_SET_PORT_general(mdev->dev, priv->port,
368
 
                                    priv->rx_skb_size + ETH_FCS_LEN,
369
 
                                    priv->prof->tx_pause,
370
 
                                    priv->prof->tx_ppp,
371
 
                                    priv->prof->rx_pause,
372
 
                                    priv->prof->rx_ppp);
373
 
        if (err)
374
 
                en_err(priv, "Failed setting pause params\n");
375
 
 
376
 
        return err;
377
 
}
378
 
 
379
 
static void mlx4_en_get_pauseparam(struct net_device *dev,
380
 
                                 struct ethtool_pauseparam *pause)
381
 
{
382
 
        struct mlx4_en_priv *priv = netdev_priv(dev);
383
 
 
384
 
        pause->tx_pause = priv->prof->tx_pause;
385
 
        pause->rx_pause = priv->prof->rx_pause;
386
 
}
387
 
 
388
 
static int mlx4_en_set_ringparam(struct net_device *dev,
389
 
                                 struct ethtool_ringparam *param)
390
 
{
391
 
        struct mlx4_en_priv *priv = netdev_priv(dev);
392
 
        struct mlx4_en_dev *mdev = priv->mdev;
393
 
        u32 rx_size, tx_size;
394
 
        int port_up = 0;
395
 
        int err = 0;
396
 
 
397
 
        if (param->rx_jumbo_pending || param->rx_mini_pending)
398
 
                return -EINVAL;
399
 
 
400
 
        rx_size = roundup_pow_of_two(param->rx_pending);
401
 
        rx_size = max_t(u32, rx_size, MLX4_EN_MIN_RX_SIZE);
402
 
        rx_size = min_t(u32, rx_size, MLX4_EN_MAX_RX_SIZE);
403
 
        tx_size = roundup_pow_of_two(param->tx_pending);
404
 
        tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE);
405
 
        tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE);
406
 
 
407
 
        if (rx_size == (priv->port_up ? priv->rx_ring[0].actual_size :
408
 
                                        priv->rx_ring[0].size) &&
409
 
            tx_size == priv->tx_ring[0].size)
410
 
                return 0;
411
 
 
412
 
        mutex_lock(&mdev->state_lock);
413
 
        if (priv->port_up) {
414
 
                port_up = 1;
415
 
                mlx4_en_stop_port(dev);
416
 
        }
417
 
 
418
 
        mlx4_en_free_resources(priv, true);
419
 
 
420
 
        priv->prof->tx_ring_size = tx_size;
421
 
        priv->prof->rx_ring_size = rx_size;
422
 
 
423
 
        err = mlx4_en_alloc_resources(priv);
424
 
        if (err) {
425
 
                en_err(priv, "Failed reallocating port resources\n");
426
 
                goto out;
427
 
        }
428
 
        if (port_up) {
429
 
                err = mlx4_en_start_port(dev);
430
 
                if (err)
431
 
                        en_err(priv, "Failed starting port\n");
432
 
        }
433
 
 
434
 
out:
435
 
        mutex_unlock(&mdev->state_lock);
436
 
        return err;
437
 
}
438
 
 
439
 
static void mlx4_en_get_ringparam(struct net_device *dev,
440
 
                                  struct ethtool_ringparam *param)
441
 
{
442
 
        struct mlx4_en_priv *priv = netdev_priv(dev);
443
 
 
444
 
        memset(param, 0, sizeof(*param));
445
 
        param->rx_max_pending = MLX4_EN_MAX_RX_SIZE;
446
 
        param->tx_max_pending = MLX4_EN_MAX_TX_SIZE;
447
 
        param->rx_pending = priv->port_up ?
448
 
                priv->rx_ring[0].actual_size : priv->rx_ring[0].size;
449
 
        param->tx_pending = priv->tx_ring[0].size;
450
 
}
451
 
 
452
 
const struct ethtool_ops mlx4_en_ethtool_ops = {
453
 
        .get_drvinfo = mlx4_en_get_drvinfo,
454
 
        .get_settings = mlx4_en_get_settings,
455
 
        .set_settings = mlx4_en_set_settings,
456
 
        .get_link = ethtool_op_get_link,
457
 
        .get_strings = mlx4_en_get_strings,
458
 
        .get_sset_count = mlx4_en_get_sset_count,
459
 
        .get_ethtool_stats = mlx4_en_get_ethtool_stats,
460
 
        .self_test = mlx4_en_self_test,
461
 
        .get_wol = mlx4_en_get_wol,
462
 
        .set_wol = mlx4_en_set_wol,
463
 
        .get_msglevel = mlx4_en_get_msglevel,
464
 
        .set_msglevel = mlx4_en_set_msglevel,
465
 
        .get_coalesce = mlx4_en_get_coalesce,
466
 
        .set_coalesce = mlx4_en_set_coalesce,
467
 
        .get_pauseparam = mlx4_en_get_pauseparam,
468
 
        .set_pauseparam = mlx4_en_set_pauseparam,
469
 
        .get_ringparam = mlx4_en_get_ringparam,
470
 
        .set_ringparam = mlx4_en_set_ringparam,
471
 
};
472
 
 
473
 
 
474
 
 
475
 
 
476