/****************************************************************************
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2006-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation, incorporated herein by reference.
*/
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/rtnetlink.h>
#include <linux/in.h>
#include "net_driver.h"
#include "workarounds.h"
#include "selftest.h"
#include "efx.h"
#include "filter.h"
#include "nic.h"
struct ef4_sw_stat_desc {
const char *name;
enum {
EF4_ETHTOOL_STAT_SOURCE_nic,
EF4_ETHTOOL_STAT_SOURCE_channel,
EF4_ETHTOOL_STAT_SOURCE_tx_queue
} source;
unsigned offset;
u64(*get_stat) (void *field); /* Reader function */
};
/* Initialiser for a struct ef4_sw_stat_desc with type-checking */
#define EF4_ETHTOOL_STAT(stat_name, source_name, field, field_type, \
get_stat_function) { \
.name = #stat_name, \
.source = EF4_ETHTOOL_STAT_SOURCE_##source_name, \
.offset = ((((field_type *) 0) == \
&((struct ef4_##source_name *)0)->field) ? \
offsetof(struct ef4_##source_name, field) : \
offsetof(struct ef4_##source_name, field)), \
.get_stat = get_stat_function, \
}
static u64 ef4_get_uint_stat(void *field)
{
return *(unsigned int *)field;
}
static u64 ef4_get_atomic_stat(void *field)
{
return atomic_read((atomic_t *) field);
}
#define EF4_ETHTOOL_ATOMIC_NIC_ERROR_STAT(field) \
EF4_ETHTOOL_STAT(field, nic, field, \
atomic_t, ef4_get_atomic_stat)
#define EF4_ETHTOOL_UINT_CHANNEL_STAT(field) \
EF4_ETHTOOL_STAT(field, channel, n_##field, \
unsigned int, ef4_get_uint_stat)
#define EF4_ETHTOOL_UINT_TXQ_STAT(field) \
EF4_ETHTOOL_STAT(tx_##field, tx_queue, field, \
unsigned int, ef4_get_uint_stat)
static const struct ef4_sw_stat_desc ef4_sw_stat_desc[] = {
EF4_ETHTOOL_UINT_TXQ_STAT(merge_events),
EF4_ETHTOOL_UINT_TXQ_STAT(pushes),
EF4_ETHTOOL_UINT_TXQ_STAT(cb_packets),
EF4_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset),
EF4_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc),
EF4_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err),
EF4_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err),
EF4_ETHTOOL_UINT_CHANNEL_STAT(rx_mcast_mismatch),
EF4_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc),
EF4_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_events),
EF4_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_packets),
};
#define EF4_ETHTOOL_SW_STAT_COUNT ARRAY_SIZE(ef4_sw_stat_desc)
#define EF4_ETHTOOL_EEPROM_MAGIC 0xEFAB
/**************************************************************************
*
* Ethtool operations
*
**************************************************************************
*/
/* Identify device by flashing LEDs */
static int ef4_ethtool_phys_id(struct net_device *net_dev,
enum ethtool_phys_id_state state)
{
struct ef4_nic *efx = netdev_priv(net_dev);
enum ef4_led_mode mode =