~ubuntu-branches/ubuntu/trusty/linux-armadaxp/trusty

« back to all changes in this revision

Viewing changes to drivers/net/ethernet/emulex/benet/be_ethtool.c

  • Committer: Package Import Robot
  • Author(s): Michael Casadevall, Bryan Wu, Dann Frazier, Michael Casadeall
  • Date: 2012-03-10 15:00:54 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20120310150054-flugb39zon8vvgwe
Tags: 3.2.0-1600.1
[ Bryan Wu ]
* UBUNTU: import debian/debian.env and debian.armadaxp

[ Dann Frazier ]
* ARM: Armada XP: remove trailing '/' in dirnames in mvRules.mk

[ Michael Casadeall ]
* tools: add some tools for Marvell Armada XP processor
* kernel: timer tick hacking from Marvell
* kernel: Sheeva Errata: add delay on Sheeva when powering down
* net: add Marvell NFP netfilter
* net: socket and skb modifications made by Marvell
* miscdevice: add minor IDs for some Marvell Armada drivers
* fs: introduce memory pool for splice()
* video: EDID detection updates from Marvell Armada XP patchset
* video: backlight: add Marvell Dove LCD backlight driver
* video: display: add THS8200 display driver
* video: framebuffer: add Marvell Dove and Armada XP processor onchip LCD controller driver
* usbtest: add Interrupt transfer testing by Marvell Armada XP code
* usb: ehci: add support for Marvell EHCI controler
* tty/serial: 8250: add support for Marvell Armada XP processor and DeviceTree work
* rtc: add support for Marvell Armada XP onchip RTC controller
* net: pppoe: add Marvell ethernet NFP hook in PPPoE networking driver
* mtd: nand: add support for Marvell Armada XP Nand Flash Controller
* mtd: maps: add Marvell Armada XP specific map driver
* mmc: add support for Marvell Armada XP MMC/SD host controller
* i2c: add support for Marvell Armada XP onchip i2c bus controller
* hwmon: add Kconfig option for Armada XP onchip thermal sensor driver
* dmaengine: add Net DMA support for splice and update Marvell XOR DMA engine driver
* ata: add support for Marvell Armada XP SATA controller and update some quirks
* ARM: add Marvell Armada XP machine to mach-types
* ARM: oprofile: add support for Marvell PJ4B core
* ARM: mm: more ARMv6 switches for Marvell Armada XP
* ARM: remove static declaration to allow compilation
* ARM: alignment access fault trick
* ARM: mm: skip some fault fixing when run on NONE SMP ARMv6 mode during early abort event
* ARM: mm: add Marvell Sheeva CPU Architecture for PJ4B
* ARM: introduce optimized copy operation for Marvell Armada XP
* ARM: SAUCE: hardware breakpoint trick for Marvell Armada XP
* ARM: big endian and little endian tricks for Marvell Armada XP
* ARM: SAUCE: Add Marvell Armada XP build rules to arch/arm/kernel/Makefile
* ARM: vfp: add special handling for Marvell Armada XP
* ARM: add support for Marvell U-Boot
* ARM: add mv_controller_num for ARM PCI drivers
* ARM: add support for local PMUs, general SMP tweaks and cache flushing
* ARM: add Marvell device identifies in glue-proc.h
* ARM: add IPC driver support for Marvell platforms
* ARM: add DMA mapping for Marvell platforms
* ARM: add Sheeva errata and PJ4B code for booting
* ARM: update Kconfig and Makefile to include Marvell Armada XP platforms
* ARM: Armada XP: import LSP from Marvell for Armada XP 3.2 kernel enablement

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2005 - 2011 Emulex
 
3
 * All rights reserved.
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU General Public License version 2
 
7
 * as published by the Free Software Foundation.  The full GNU General
 
8
 * Public License is included in this distribution in the file called COPYING.
 
9
 *
 
10
 * Contact Information:
 
11
 * linux-drivers@emulex.com
 
12
 *
 
13
 * Emulex
 
14
 * 3333 Susan Street
 
15
 * Costa Mesa, CA 92626
 
16
 */
 
17
 
 
18
#include "be.h"
 
19
#include "be_cmds.h"
 
20
#include <linux/ethtool.h>
 
21
 
 
22
struct be_ethtool_stat {
 
23
        char desc[ETH_GSTRING_LEN];
 
24
        int type;
 
25
        int size;
 
26
        int offset;
 
27
};
 
28
 
 
29
enum {DRVSTAT_TX, DRVSTAT_RX, DRVSTAT};
 
30
#define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \
 
31
                                        offsetof(_struct, field)
 
32
#define DRVSTAT_TX_INFO(field)  #field, DRVSTAT_TX,\
 
33
                                        FIELDINFO(struct be_tx_stats, field)
 
34
#define DRVSTAT_RX_INFO(field)  #field, DRVSTAT_RX,\
 
35
                                        FIELDINFO(struct be_rx_stats, field)
 
36
#define DRVSTAT_INFO(field)     #field, DRVSTAT,\
 
37
                                        FIELDINFO(struct be_drv_stats, field)
 
38
 
 
39
static const struct be_ethtool_stat et_stats[] = {
 
40
        {DRVSTAT_INFO(tx_events)},
 
41
        {DRVSTAT_INFO(rx_crc_errors)},
 
42
        {DRVSTAT_INFO(rx_alignment_symbol_errors)},
 
43
        {DRVSTAT_INFO(rx_pause_frames)},
 
44
        {DRVSTAT_INFO(rx_control_frames)},
 
45
        {DRVSTAT_INFO(rx_in_range_errors)},
 
46
        {DRVSTAT_INFO(rx_out_range_errors)},
 
47
        {DRVSTAT_INFO(rx_frame_too_long)},
 
48
        {DRVSTAT_INFO(rx_address_match_errors)},
 
49
        {DRVSTAT_INFO(rx_dropped_too_small)},
 
50
        {DRVSTAT_INFO(rx_dropped_too_short)},
 
51
        {DRVSTAT_INFO(rx_dropped_header_too_small)},
 
52
        {DRVSTAT_INFO(rx_dropped_tcp_length)},
 
53
        {DRVSTAT_INFO(rx_dropped_runt)},
 
54
        {DRVSTAT_INFO(rxpp_fifo_overflow_drop)},
 
55
        {DRVSTAT_INFO(rx_input_fifo_overflow_drop)},
 
56
        {DRVSTAT_INFO(rx_ip_checksum_errs)},
 
57
        {DRVSTAT_INFO(rx_tcp_checksum_errs)},
 
58
        {DRVSTAT_INFO(rx_udp_checksum_errs)},
 
59
        {DRVSTAT_INFO(tx_pauseframes)},
 
60
        {DRVSTAT_INFO(tx_controlframes)},
 
61
        {DRVSTAT_INFO(rx_priority_pause_frames)},
 
62
        {DRVSTAT_INFO(pmem_fifo_overflow_drop)},
 
63
        {DRVSTAT_INFO(jabber_events)},
 
64
        {DRVSTAT_INFO(rx_drops_no_pbuf)},
 
65
        {DRVSTAT_INFO(rx_drops_no_txpb)},
 
66
        {DRVSTAT_INFO(rx_drops_no_erx_descr)},
 
67
        {DRVSTAT_INFO(rx_drops_no_tpre_descr)},
 
68
        {DRVSTAT_INFO(rx_drops_too_many_frags)},
 
69
        {DRVSTAT_INFO(rx_drops_invalid_ring)},
 
70
        {DRVSTAT_INFO(forwarded_packets)},
 
71
        {DRVSTAT_INFO(rx_drops_mtu)},
 
72
        {DRVSTAT_INFO(eth_red_drops)},
 
73
        {DRVSTAT_INFO(be_on_die_temperature)}
 
74
};
 
75
#define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats)
 
76
 
 
77
/* Stats related to multi RX queues: get_stats routine assumes bytes, pkts
 
78
 * are first and second members respectively.
 
79
 */
 
80
static const struct be_ethtool_stat et_rx_stats[] = {
 
81
        {DRVSTAT_RX_INFO(rx_bytes)},/* If moving this member see above note */
 
82
        {DRVSTAT_RX_INFO(rx_pkts)}, /* If moving this member see above note */
 
83
        {DRVSTAT_RX_INFO(rx_polls)},
 
84
        {DRVSTAT_RX_INFO(rx_events)},
 
85
        {DRVSTAT_RX_INFO(rx_compl)},
 
86
        {DRVSTAT_RX_INFO(rx_mcast_pkts)},
 
87
        {DRVSTAT_RX_INFO(rx_post_fail)},
 
88
        {DRVSTAT_RX_INFO(rx_drops_no_skbs)},
 
89
        {DRVSTAT_RX_INFO(rx_drops_no_frags)}
 
90
};
 
91
#define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats))
 
92
 
 
93
/* Stats related to multi TX queues: get_stats routine assumes compl is the
 
94
 * first member
 
95
 */
 
96
static const struct be_ethtool_stat et_tx_stats[] = {
 
97
        {DRVSTAT_TX_INFO(tx_compl)}, /* If moving this member see above note */
 
98
        {DRVSTAT_TX_INFO(tx_bytes)},
 
99
        {DRVSTAT_TX_INFO(tx_pkts)},
 
100
        {DRVSTAT_TX_INFO(tx_reqs)},
 
101
        {DRVSTAT_TX_INFO(tx_wrbs)},
 
102
        {DRVSTAT_TX_INFO(tx_compl)},
 
103
        {DRVSTAT_TX_INFO(tx_stops)}
 
104
};
 
105
#define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats))
 
106
 
 
107
static const char et_self_tests[][ETH_GSTRING_LEN] = {
 
108
        "MAC Loopback test",
 
109
        "PHY Loopback test",
 
110
        "External Loopback test",
 
111
        "DDR DMA test",
 
112
        "Link test"
 
113
};
 
114
 
 
115
#define ETHTOOL_TESTS_NUM ARRAY_SIZE(et_self_tests)
 
116
#define BE_MAC_LOOPBACK 0x0
 
117
#define BE_PHY_LOOPBACK 0x1
 
118
#define BE_ONE_PORT_EXT_LOOPBACK 0x2
 
119
#define BE_NO_LOOPBACK 0xff
 
120
 
 
121
static void be_get_drvinfo(struct net_device *netdev,
 
122
                                struct ethtool_drvinfo *drvinfo)
 
123
{
 
124
        struct be_adapter *adapter = netdev_priv(netdev);
 
125
        char fw_on_flash[FW_VER_LEN];
 
126
 
 
127
        memset(fw_on_flash, 0 , sizeof(fw_on_flash));
 
128
        be_cmd_get_fw_ver(adapter, adapter->fw_ver, fw_on_flash);
 
129
 
 
130
        strcpy(drvinfo->driver, DRV_NAME);
 
131
        strcpy(drvinfo->version, DRV_VER);
 
132
        strncpy(drvinfo->fw_version, adapter->fw_ver, FW_VER_LEN);
 
133
        if (memcmp(adapter->fw_ver, fw_on_flash, FW_VER_LEN) != 0) {
 
134
                strcat(drvinfo->fw_version, " [");
 
135
                strcat(drvinfo->fw_version, fw_on_flash);
 
136
                strcat(drvinfo->fw_version, "]");
 
137
        }
 
138
 
 
139
        strcpy(drvinfo->bus_info, pci_name(adapter->pdev));
 
140
        drvinfo->testinfo_len = 0;
 
141
        drvinfo->regdump_len = 0;
 
142
        drvinfo->eedump_len = 0;
 
143
}
 
144
 
 
145
static int
 
146
be_get_reg_len(struct net_device *netdev)
 
147
{
 
148
        struct be_adapter *adapter = netdev_priv(netdev);
 
149
        u32 log_size = 0;
 
150
 
 
151
        if (be_physfn(adapter))
 
152
                be_cmd_get_reg_len(adapter, &log_size);
 
153
 
 
154
        return log_size;
 
155
}
 
156
 
 
157
static void
 
158
be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
 
159
{
 
160
        struct be_adapter *adapter = netdev_priv(netdev);
 
161
 
 
162
        if (be_physfn(adapter)) {
 
163
                memset(buf, 0, regs->len);
 
164
                be_cmd_get_regs(adapter, regs->len, buf);
 
165
        }
 
166
}
 
167
 
 
168
static int
 
169
be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
 
170
{
 
171
        struct be_adapter *adapter = netdev_priv(netdev);
 
172
        struct be_eq_obj *rx_eq = &adapter->rx_obj[0].rx_eq;
 
173
        struct be_eq_obj *tx_eq = &adapter->tx_eq;
 
174
 
 
175
        coalesce->rx_coalesce_usecs = rx_eq->cur_eqd;
 
176
        coalesce->rx_coalesce_usecs_high = rx_eq->max_eqd;
 
177
        coalesce->rx_coalesce_usecs_low = rx_eq->min_eqd;
 
178
 
 
179
        coalesce->tx_coalesce_usecs = tx_eq->cur_eqd;
 
180
        coalesce->tx_coalesce_usecs_high = tx_eq->max_eqd;
 
181
        coalesce->tx_coalesce_usecs_low = tx_eq->min_eqd;
 
182
 
 
183
        coalesce->use_adaptive_rx_coalesce = rx_eq->enable_aic;
 
184
        coalesce->use_adaptive_tx_coalesce = tx_eq->enable_aic;
 
185
 
 
186
        return 0;
 
187
}
 
188
 
 
189
/*
 
190
 * This routine is used to set interrup coalescing delay
 
191
 */
 
192
static int
 
193
be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
 
194
{
 
195
        struct be_adapter *adapter = netdev_priv(netdev);
 
196
        struct be_rx_obj *rxo;
 
197
        struct be_eq_obj *rx_eq;
 
198
        struct be_eq_obj *tx_eq = &adapter->tx_eq;
 
199
        u32 rx_max, rx_min, rx_cur;
 
200
        int status = 0, i;
 
201
        u32 tx_cur;
 
202
 
 
203
        if (coalesce->use_adaptive_tx_coalesce == 1)
 
204
                return -EINVAL;
 
205
 
 
206
        for_all_rx_queues(adapter, rxo, i) {
 
207
                rx_eq = &rxo->rx_eq;
 
208
 
 
209
                if (!rx_eq->enable_aic && coalesce->use_adaptive_rx_coalesce)
 
210
                        rx_eq->cur_eqd = 0;
 
211
                rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce;
 
212
 
 
213
                rx_max = coalesce->rx_coalesce_usecs_high;
 
214
                rx_min = coalesce->rx_coalesce_usecs_low;
 
215
                rx_cur = coalesce->rx_coalesce_usecs;
 
216
 
 
217
                if (rx_eq->enable_aic) {
 
218
                        if (rx_max > BE_MAX_EQD)
 
219
                                rx_max = BE_MAX_EQD;
 
220
                        if (rx_min > rx_max)
 
221
                                rx_min = rx_max;
 
222
                        rx_eq->max_eqd = rx_max;
 
223
                        rx_eq->min_eqd = rx_min;
 
224
                        if (rx_eq->cur_eqd > rx_max)
 
225
                                rx_eq->cur_eqd = rx_max;
 
226
                        if (rx_eq->cur_eqd < rx_min)
 
227
                                rx_eq->cur_eqd = rx_min;
 
228
                } else {
 
229
                        if (rx_cur > BE_MAX_EQD)
 
230
                                rx_cur = BE_MAX_EQD;
 
231
                        if (rx_eq->cur_eqd != rx_cur) {
 
232
                                status = be_cmd_modify_eqd(adapter, rx_eq->q.id,
 
233
                                                rx_cur);
 
234
                                if (!status)
 
235
                                        rx_eq->cur_eqd = rx_cur;
 
236
                        }
 
237
                }
 
238
        }
 
239
 
 
240
        tx_cur = coalesce->tx_coalesce_usecs;
 
241
 
 
242
        if (tx_cur > BE_MAX_EQD)
 
243
                tx_cur = BE_MAX_EQD;
 
244
        if (tx_eq->cur_eqd != tx_cur) {
 
245
                status = be_cmd_modify_eqd(adapter, tx_eq->q.id, tx_cur);
 
246
                if (!status)
 
247
                        tx_eq->cur_eqd = tx_cur;
 
248
        }
 
249
 
 
250
        return 0;
 
251
}
 
252
 
 
253
static void
 
254
be_get_ethtool_stats(struct net_device *netdev,
 
255
                struct ethtool_stats *stats, uint64_t *data)
 
256
{
 
257
        struct be_adapter *adapter = netdev_priv(netdev);
 
258
        struct be_rx_obj *rxo;
 
259
        struct be_tx_obj *txo;
 
260
        void *p;
 
261
        unsigned int i, j, base = 0, start;
 
262
 
 
263
        for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
 
264
                p = (u8 *)&adapter->drv_stats + et_stats[i].offset;
 
265
                data[i] = *(u32 *)p;
 
266
        }
 
267
        base += ETHTOOL_STATS_NUM;
 
268
 
 
269
        for_all_rx_queues(adapter, rxo, j) {
 
270
                struct be_rx_stats *stats = rx_stats(rxo);
 
271
 
 
272
                do {
 
273
                        start = u64_stats_fetch_begin_bh(&stats->sync);
 
274
                        data[base] = stats->rx_bytes;
 
275
                        data[base + 1] = stats->rx_pkts;
 
276
                } while (u64_stats_fetch_retry_bh(&stats->sync, start));
 
277
 
 
278
                for (i = 2; i < ETHTOOL_RXSTATS_NUM; i++) {
 
279
                        p = (u8 *)stats + et_rx_stats[i].offset;
 
280
                        data[base + i] = *(u32 *)p;
 
281
                }
 
282
                base += ETHTOOL_RXSTATS_NUM;
 
283
        }
 
284
 
 
285
        for_all_tx_queues(adapter, txo, j) {
 
286
                struct be_tx_stats *stats = tx_stats(txo);
 
287
 
 
288
                do {
 
289
                        start = u64_stats_fetch_begin_bh(&stats->sync_compl);
 
290
                        data[base] = stats->tx_compl;
 
291
                } while (u64_stats_fetch_retry_bh(&stats->sync_compl, start));
 
292
 
 
293
                do {
 
294
                        start = u64_stats_fetch_begin_bh(&stats->sync);
 
295
                        for (i = 1; i < ETHTOOL_TXSTATS_NUM; i++) {
 
296
                                p = (u8 *)stats + et_tx_stats[i].offset;
 
297
                                data[base + i] =
 
298
                                        (et_tx_stats[i].size == sizeof(u64)) ?
 
299
                                                *(u64 *)p : *(u32 *)p;
 
300
                        }
 
301
                } while (u64_stats_fetch_retry_bh(&stats->sync, start));
 
302
                base += ETHTOOL_TXSTATS_NUM;
 
303
        }
 
304
}
 
305
 
 
306
static void
 
307
be_get_stat_strings(struct net_device *netdev, uint32_t stringset,
 
308
                uint8_t *data)
 
309
{
 
310
        struct be_adapter *adapter = netdev_priv(netdev);
 
311
        int i, j;
 
312
 
 
313
        switch (stringset) {
 
314
        case ETH_SS_STATS:
 
315
                for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
 
316
                        memcpy(data, et_stats[i].desc, ETH_GSTRING_LEN);
 
317
                        data += ETH_GSTRING_LEN;
 
318
                }
 
319
                for (i = 0; i < adapter->num_rx_qs; i++) {
 
320
                        for (j = 0; j < ETHTOOL_RXSTATS_NUM; j++) {
 
321
                                sprintf(data, "rxq%d: %s", i,
 
322
                                        et_rx_stats[j].desc);
 
323
                                data += ETH_GSTRING_LEN;
 
324
                        }
 
325
                }
 
326
                for (i = 0; i < adapter->num_tx_qs; i++) {
 
327
                        for (j = 0; j < ETHTOOL_TXSTATS_NUM; j++) {
 
328
                                sprintf(data, "txq%d: %s", i,
 
329
                                        et_tx_stats[j].desc);
 
330
                                data += ETH_GSTRING_LEN;
 
331
                        }
 
332
                }
 
333
                break;
 
334
        case ETH_SS_TEST:
 
335
                for (i = 0; i < ETHTOOL_TESTS_NUM; i++) {
 
336
                        memcpy(data, et_self_tests[i], ETH_GSTRING_LEN);
 
337
                        data += ETH_GSTRING_LEN;
 
338
                }
 
339
                break;
 
340
        }
 
341
}
 
342
 
 
343
static int be_get_sset_count(struct net_device *netdev, int stringset)
 
344
{
 
345
        struct be_adapter *adapter = netdev_priv(netdev);
 
346
 
 
347
        switch (stringset) {
 
348
        case ETH_SS_TEST:
 
349
                return ETHTOOL_TESTS_NUM;
 
350
        case ETH_SS_STATS:
 
351
                return ETHTOOL_STATS_NUM +
 
352
                        adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM +
 
353
                        adapter->num_tx_qs * ETHTOOL_TXSTATS_NUM;
 
354
        default:
 
355
                return -EINVAL;
 
356
        }
 
357
}
 
358
 
 
359
static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 
360
{
 
361
        struct be_adapter *adapter = netdev_priv(netdev);
 
362
        struct be_phy_info phy_info;
 
363
        u8 mac_speed = 0;
 
364
        u16 link_speed = 0;
 
365
        int status;
 
366
 
 
367
        if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) {
 
368
                status = be_cmd_link_status_query(adapter, &mac_speed,
 
369
                                                &link_speed, 0);
 
370
 
 
371
                /* link_speed is in units of 10 Mbps */
 
372
                if (link_speed) {
 
373
                        ethtool_cmd_speed_set(ecmd, link_speed*10);
 
374
                } else {
 
375
                        switch (mac_speed) {
 
376
                        case PHY_LINK_SPEED_10MBPS:
 
377
                                ethtool_cmd_speed_set(ecmd, SPEED_10);
 
378
                                break;
 
379
                        case PHY_LINK_SPEED_100MBPS:
 
380
                                ethtool_cmd_speed_set(ecmd, SPEED_100);
 
381
                                break;
 
382
                        case PHY_LINK_SPEED_1GBPS:
 
383
                                ethtool_cmd_speed_set(ecmd, SPEED_1000);
 
384
                                break;
 
385
                        case PHY_LINK_SPEED_10GBPS:
 
386
                                ethtool_cmd_speed_set(ecmd, SPEED_10000);
 
387
                                break;
 
388
                        case PHY_LINK_SPEED_ZERO:
 
389
                                ethtool_cmd_speed_set(ecmd, 0);
 
390
                                break;
 
391
                        }
 
392
                }
 
393
 
 
394
                status = be_cmd_get_phy_info(adapter, &phy_info);
 
395
                if (!status) {
 
396
                        switch (phy_info.interface_type) {
 
397
                        case PHY_TYPE_XFP_10GB:
 
398
                        case PHY_TYPE_SFP_1GB:
 
399
                        case PHY_TYPE_SFP_PLUS_10GB:
 
400
                                ecmd->port = PORT_FIBRE;
 
401
                                break;
 
402
                        default:
 
403
                                ecmd->port = PORT_TP;
 
404
                                break;
 
405
                        }
 
406
 
 
407
                        switch (phy_info.interface_type) {
 
408
                        case PHY_TYPE_KR_10GB:
 
409
                        case PHY_TYPE_KX4_10GB:
 
410
                                ecmd->autoneg = AUTONEG_ENABLE;
 
411
                        ecmd->transceiver = XCVR_INTERNAL;
 
412
                                break;
 
413
                        default:
 
414
                                ecmd->autoneg = AUTONEG_DISABLE;
 
415
                                ecmd->transceiver = XCVR_EXTERNAL;
 
416
                                break;
 
417
                        }
 
418
                }
 
419
 
 
420
                /* Save for future use */
 
421
                adapter->link_speed = ethtool_cmd_speed(ecmd);
 
422
                adapter->port_type = ecmd->port;
 
423
                adapter->transceiver = ecmd->transceiver;
 
424
                adapter->autoneg = ecmd->autoneg;
 
425
        } else {
 
426
                ethtool_cmd_speed_set(ecmd, adapter->link_speed);
 
427
                ecmd->port = adapter->port_type;
 
428
                ecmd->transceiver = adapter->transceiver;
 
429
                ecmd->autoneg = adapter->autoneg;
 
430
        }
 
431
 
 
432
        ecmd->duplex = DUPLEX_FULL;
 
433
        ecmd->phy_address = adapter->port_num;
 
434
        switch (ecmd->port) {
 
435
        case PORT_FIBRE:
 
436
                ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
 
437
                break;
 
438
        case PORT_TP:
 
439
                ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_TP);
 
440
                break;
 
441
        case PORT_AUI:
 
442
                ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_AUI);
 
443
                break;
 
444
        }
 
445
 
 
446
        if (ecmd->autoneg) {
 
447
                ecmd->supported |= SUPPORTED_1000baseT_Full;
 
448
                ecmd->supported |= SUPPORTED_Autoneg;
 
449
                ecmd->advertising |= (ADVERTISED_10000baseT_Full |
 
450
                                ADVERTISED_1000baseT_Full);
 
451
        }
 
452
 
 
453
        return 0;
 
454
}
 
455
 
 
456
static void
 
457
be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
 
458
{
 
459
        struct be_adapter *adapter = netdev_priv(netdev);
 
460
 
 
461
        ring->rx_max_pending = adapter->rx_obj[0].q.len;
 
462
        ring->tx_max_pending = adapter->tx_obj[0].q.len;
 
463
 
 
464
        ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used);
 
465
        ring->tx_pending = atomic_read(&adapter->tx_obj[0].q.used);
 
466
}
 
467
 
 
468
static void
 
469
be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
 
470
{
 
471
        struct be_adapter *adapter = netdev_priv(netdev);
 
472
 
 
473
        be_cmd_get_flow_control(adapter, &ecmd->tx_pause, &ecmd->rx_pause);
 
474
        ecmd->autoneg = 0;
 
475
}
 
476
 
 
477
static int
 
478
be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
 
479
{
 
480
        struct be_adapter *adapter = netdev_priv(netdev);
 
481
        int status;
 
482
 
 
483
        if (ecmd->autoneg != 0)
 
484
                return -EINVAL;
 
485
        adapter->tx_fc = ecmd->tx_pause;
 
486
        adapter->rx_fc = ecmd->rx_pause;
 
487
 
 
488
        status = be_cmd_set_flow_control(adapter,
 
489
                                        adapter->tx_fc, adapter->rx_fc);
 
490
        if (status)
 
491
                dev_warn(&adapter->pdev->dev, "Pause param set failed.\n");
 
492
 
 
493
        return status;
 
494
}
 
495
 
 
496
static int
 
497
be_set_phys_id(struct net_device *netdev,
 
498
               enum ethtool_phys_id_state state)
 
499
{
 
500
        struct be_adapter *adapter = netdev_priv(netdev);
 
501
 
 
502
        switch (state) {
 
503
        case ETHTOOL_ID_ACTIVE:
 
504
                be_cmd_get_beacon_state(adapter, adapter->hba_port_num,
 
505
                                        &adapter->beacon_state);
 
506
                return 1;       /* cycle on/off once per second */
 
507
 
 
508
        case ETHTOOL_ID_ON:
 
509
                be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
 
510
                                        BEACON_STATE_ENABLED);
 
511
                break;
 
512
 
 
513
        case ETHTOOL_ID_OFF:
 
514
                be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
 
515
                                        BEACON_STATE_DISABLED);
 
516
                break;
 
517
 
 
518
        case ETHTOOL_ID_INACTIVE:
 
519
                be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
 
520
                                        adapter->beacon_state);
 
521
        }
 
522
 
 
523
        return 0;
 
524
}
 
525
 
 
526
static bool
 
527
be_is_wol_supported(struct be_adapter *adapter)
 
528
{
 
529
        if (!be_physfn(adapter))
 
530
                return false;
 
531
        else
 
532
                return true;
 
533
}
 
534
 
 
535
static void
 
536
be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 
537
{
 
538
        struct be_adapter *adapter = netdev_priv(netdev);
 
539
 
 
540
        if (be_is_wol_supported(adapter))
 
541
                wol->supported = WAKE_MAGIC;
 
542
 
 
543
        if (adapter->wol)
 
544
                wol->wolopts = WAKE_MAGIC;
 
545
        else
 
546
                wol->wolopts = 0;
 
547
        memset(&wol->sopass, 0, sizeof(wol->sopass));
 
548
}
 
549
 
 
550
static int
 
551
be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 
552
{
 
553
        struct be_adapter *adapter = netdev_priv(netdev);
 
554
 
 
555
        if (wol->wolopts & ~WAKE_MAGIC)
 
556
                return -EINVAL;
 
557
 
 
558
        if ((wol->wolopts & WAKE_MAGIC) && be_is_wol_supported(adapter))
 
559
                adapter->wol = true;
 
560
        else
 
561
                adapter->wol = false;
 
562
 
 
563
        return 0;
 
564
}
 
565
 
 
566
static int
 
567
be_test_ddr_dma(struct be_adapter *adapter)
 
568
{
 
569
        int ret, i;
 
570
        struct be_dma_mem ddrdma_cmd;
 
571
        static const u64 pattern[2] = {
 
572
                0x5a5a5a5a5a5a5a5aULL, 0xa5a5a5a5a5a5a5a5ULL
 
573
        };
 
574
 
 
575
        ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test);
 
576
        ddrdma_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, ddrdma_cmd.size,
 
577
                                           &ddrdma_cmd.dma, GFP_KERNEL);
 
578
        if (!ddrdma_cmd.va) {
 
579
                dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
 
580
                return -ENOMEM;
 
581
        }
 
582
 
 
583
        for (i = 0; i < 2; i++) {
 
584
                ret = be_cmd_ddr_dma_test(adapter, pattern[i],
 
585
                                        4096, &ddrdma_cmd);
 
586
                if (ret != 0)
 
587
                        goto err;
 
588
        }
 
589
 
 
590
err:
 
591
        dma_free_coherent(&adapter->pdev->dev, ddrdma_cmd.size, ddrdma_cmd.va,
 
592
                          ddrdma_cmd.dma);
 
593
        return ret;
 
594
}
 
595
 
 
596
static u64 be_loopback_test(struct be_adapter *adapter, u8 loopback_type,
 
597
                                u64 *status)
 
598
{
 
599
        be_cmd_set_loopback(adapter, adapter->hba_port_num,
 
600
                                loopback_type, 1);
 
601
        *status = be_cmd_loopback_test(adapter, adapter->hba_port_num,
 
602
                                loopback_type, 1500,
 
603
                                2, 0xabc);
 
604
        be_cmd_set_loopback(adapter, adapter->hba_port_num,
 
605
                                BE_NO_LOOPBACK, 1);
 
606
        return *status;
 
607
}
 
608
 
 
609
static void
 
610
be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
 
611
{
 
612
        struct be_adapter *adapter = netdev_priv(netdev);
 
613
        u8 mac_speed = 0;
 
614
        u16 qos_link_speed = 0;
 
615
 
 
616
        memset(data, 0, sizeof(u64) * ETHTOOL_TESTS_NUM);
 
617
 
 
618
        if (test->flags & ETH_TEST_FL_OFFLINE) {
 
619
                if (be_loopback_test(adapter, BE_MAC_LOOPBACK,
 
620
                                                &data[0]) != 0) {
 
621
                        test->flags |= ETH_TEST_FL_FAILED;
 
622
                }
 
623
                if (be_loopback_test(adapter, BE_PHY_LOOPBACK,
 
624
                                                &data[1]) != 0) {
 
625
                        test->flags |= ETH_TEST_FL_FAILED;
 
626
                }
 
627
                if (be_loopback_test(adapter, BE_ONE_PORT_EXT_LOOPBACK,
 
628
                                                &data[2]) != 0) {
 
629
                        test->flags |= ETH_TEST_FL_FAILED;
 
630
                }
 
631
        }
 
632
 
 
633
        if (be_test_ddr_dma(adapter) != 0) {
 
634
                data[3] = 1;
 
635
                test->flags |= ETH_TEST_FL_FAILED;
 
636
        }
 
637
 
 
638
        if (be_cmd_link_status_query(adapter, &mac_speed,
 
639
                                &qos_link_speed, 0) != 0) {
 
640
                test->flags |= ETH_TEST_FL_FAILED;
 
641
                data[4] = -1;
 
642
        } else if (!mac_speed) {
 
643
                test->flags |= ETH_TEST_FL_FAILED;
 
644
                data[4] = 1;
 
645
        }
 
646
}
 
647
 
 
648
static int
 
649
be_do_flash(struct net_device *netdev, struct ethtool_flash *efl)
 
650
{
 
651
        struct be_adapter *adapter = netdev_priv(netdev);
 
652
        char file_name[ETHTOOL_FLASH_MAX_FILENAME];
 
653
 
 
654
        file_name[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0;
 
655
        strcpy(file_name, efl->data);
 
656
 
 
657
        return be_load_fw(adapter, file_name);
 
658
}
 
659
 
 
660
static int
 
661
be_get_eeprom_len(struct net_device *netdev)
 
662
{
 
663
        return BE_READ_SEEPROM_LEN;
 
664
}
 
665
 
 
666
static int
 
667
be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
 
668
                        uint8_t *data)
 
669
{
 
670
        struct be_adapter *adapter = netdev_priv(netdev);
 
671
        struct be_dma_mem eeprom_cmd;
 
672
        struct be_cmd_resp_seeprom_read *resp;
 
673
        int status;
 
674
 
 
675
        if (!eeprom->len)
 
676
                return -EINVAL;
 
677
 
 
678
        eeprom->magic = BE_VENDOR_ID | (adapter->pdev->device<<16);
 
679
 
 
680
        memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem));
 
681
        eeprom_cmd.size = sizeof(struct be_cmd_req_seeprom_read);
 
682
        eeprom_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, eeprom_cmd.size,
 
683
                                           &eeprom_cmd.dma, GFP_KERNEL);
 
684
 
 
685
        if (!eeprom_cmd.va) {
 
686
                dev_err(&adapter->pdev->dev,
 
687
                        "Memory allocation failure. Could not read eeprom\n");
 
688
                return -ENOMEM;
 
689
        }
 
690
 
 
691
        status = be_cmd_get_seeprom_data(adapter, &eeprom_cmd);
 
692
 
 
693
        if (!status) {
 
694
                resp = eeprom_cmd.va;
 
695
                memcpy(data, resp->seeprom_data + eeprom->offset, eeprom->len);
 
696
        }
 
697
        dma_free_coherent(&adapter->pdev->dev, eeprom_cmd.size, eeprom_cmd.va,
 
698
                          eeprom_cmd.dma);
 
699
 
 
700
        return status;
 
701
}
 
702
 
 
703
const struct ethtool_ops be_ethtool_ops = {
 
704
        .get_settings = be_get_settings,
 
705
        .get_drvinfo = be_get_drvinfo,
 
706
        .get_wol = be_get_wol,
 
707
        .set_wol = be_set_wol,
 
708
        .get_link = ethtool_op_get_link,
 
709
        .get_eeprom_len = be_get_eeprom_len,
 
710
        .get_eeprom = be_read_eeprom,
 
711
        .get_coalesce = be_get_coalesce,
 
712
        .set_coalesce = be_set_coalesce,
 
713
        .get_ringparam = be_get_ringparam,
 
714
        .get_pauseparam = be_get_pauseparam,
 
715
        .set_pauseparam = be_set_pauseparam,
 
716
        .get_strings = be_get_stat_strings,
 
717
        .set_phys_id = be_set_phys_id,
 
718
        .get_sset_count = be_get_sset_count,
 
719
        .get_ethtool_stats = be_get_ethtool_stats,
 
720
        .get_regs_len = be_get_reg_len,
 
721
        .get_regs = be_get_regs,
 
722
        .flash_device = be_do_flash,
 
723
        .self_test = be_self_test,
 
724
};