devices/e1000e/ethtool-3.6-orig.c
author Patrick Bruenn <p.bruenn@beckhoff.com>
Tue, 12 Apr 2016 11:17:36 +0200
branchstable-1.5
changeset 2654 b3f6b3e5ef29
parent 2546 2fa43746d972
permissions -rw-r--r--
devices/ccat: revert "limit rx processing to one frame per poll"

revert "limit rx processing to one frame per poll", which caused etherlab
frame timeouts in setups with more than one frame per cycle.
2546
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     1
/*******************************************************************************
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     2
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     3
  Intel PRO/1000 Linux driver
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     4
  Copyright(c) 1999 - 2012 Intel Corporation.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     5
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     6
  This program is free software; you can redistribute it and/or modify it
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     7
  under the terms and conditions of the GNU General Public License,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     8
  version 2, as published by the Free Software Foundation.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     9
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    10
  This program is distributed in the hope it will be useful, but WITHOUT
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    11
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    12
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    13
  more details.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    14
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    15
  You should have received a copy of the GNU General Public License along with
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    16
  this program; if not, write to the Free Software Foundation, Inc.,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    17
  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    18
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    19
  The full GNU General Public License is included in this distribution in
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    20
  the file called "COPYING".
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    21
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    22
  Contact Information:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    23
  Linux NICS <linux.nics@intel.com>
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    24
  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    25
  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    26
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    27
*******************************************************************************/
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    28
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    29
/* ethtool support for e1000 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    30
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    31
#include <linux/netdevice.h>
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    32
#include <linux/interrupt.h>
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    33
#include <linux/ethtool.h>
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    34
#include <linux/pci.h>
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    35
#include <linux/slab.h>
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    36
#include <linux/delay.h>
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    37
#include <linux/vmalloc.h>
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    38
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    39
#include "e1000.h"
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    40
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    41
enum {NETDEV_STATS, E1000_STATS};
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    42
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    43
struct e1000_stats {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    44
	char stat_string[ETH_GSTRING_LEN];
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    45
	int type;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    46
	int sizeof_stat;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    47
	int stat_offset;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    48
};
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    49
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    50
#define E1000_STAT(str, m) { \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    51
		.stat_string = str, \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    52
		.type = E1000_STATS, \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    53
		.sizeof_stat = sizeof(((struct e1000_adapter *)0)->m), \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    54
		.stat_offset = offsetof(struct e1000_adapter, m) }
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    55
#define E1000_NETDEV_STAT(str, m) { \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    56
		.stat_string = str, \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    57
		.type = NETDEV_STATS, \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    58
		.sizeof_stat = sizeof(((struct rtnl_link_stats64 *)0)->m), \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    59
		.stat_offset = offsetof(struct rtnl_link_stats64, m) }
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    60
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    61
static const struct e1000_stats e1000_gstrings_stats[] = {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    62
	E1000_STAT("rx_packets", stats.gprc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    63
	E1000_STAT("tx_packets", stats.gptc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    64
	E1000_STAT("rx_bytes", stats.gorc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    65
	E1000_STAT("tx_bytes", stats.gotc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    66
	E1000_STAT("rx_broadcast", stats.bprc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    67
	E1000_STAT("tx_broadcast", stats.bptc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    68
	E1000_STAT("rx_multicast", stats.mprc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    69
	E1000_STAT("tx_multicast", stats.mptc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    70
	E1000_NETDEV_STAT("rx_errors", rx_errors),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    71
	E1000_NETDEV_STAT("tx_errors", tx_errors),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    72
	E1000_NETDEV_STAT("tx_dropped", tx_dropped),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    73
	E1000_STAT("multicast", stats.mprc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    74
	E1000_STAT("collisions", stats.colc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    75
	E1000_NETDEV_STAT("rx_length_errors", rx_length_errors),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    76
	E1000_NETDEV_STAT("rx_over_errors", rx_over_errors),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    77
	E1000_STAT("rx_crc_errors", stats.crcerrs),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    78
	E1000_NETDEV_STAT("rx_frame_errors", rx_frame_errors),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    79
	E1000_STAT("rx_no_buffer_count", stats.rnbc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    80
	E1000_STAT("rx_missed_errors", stats.mpc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    81
	E1000_STAT("tx_aborted_errors", stats.ecol),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    82
	E1000_STAT("tx_carrier_errors", stats.tncrs),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    83
	E1000_NETDEV_STAT("tx_fifo_errors", tx_fifo_errors),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    84
	E1000_NETDEV_STAT("tx_heartbeat_errors", tx_heartbeat_errors),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    85
	E1000_STAT("tx_window_errors", stats.latecol),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    86
	E1000_STAT("tx_abort_late_coll", stats.latecol),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    87
	E1000_STAT("tx_deferred_ok", stats.dc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    88
	E1000_STAT("tx_single_coll_ok", stats.scc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    89
	E1000_STAT("tx_multi_coll_ok", stats.mcc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    90
	E1000_STAT("tx_timeout_count", tx_timeout_count),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    91
	E1000_STAT("tx_restart_queue", restart_queue),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    92
	E1000_STAT("rx_long_length_errors", stats.roc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    93
	E1000_STAT("rx_short_length_errors", stats.ruc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    94
	E1000_STAT("rx_align_errors", stats.algnerrc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    95
	E1000_STAT("tx_tcp_seg_good", stats.tsctc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    96
	E1000_STAT("tx_tcp_seg_failed", stats.tsctfc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    97
	E1000_STAT("rx_flow_control_xon", stats.xonrxc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    98
	E1000_STAT("rx_flow_control_xoff", stats.xoffrxc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    99
	E1000_STAT("tx_flow_control_xon", stats.xontxc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   100
	E1000_STAT("tx_flow_control_xoff", stats.xofftxc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   101
	E1000_STAT("rx_long_byte_count", stats.gorc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   102
	E1000_STAT("rx_csum_offload_good", hw_csum_good),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   103
	E1000_STAT("rx_csum_offload_errors", hw_csum_err),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   104
	E1000_STAT("rx_header_split", rx_hdr_split),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   105
	E1000_STAT("alloc_rx_buff_failed", alloc_rx_buff_failed),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   106
	E1000_STAT("tx_smbus", stats.mgptc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   107
	E1000_STAT("rx_smbus", stats.mgprc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   108
	E1000_STAT("dropped_smbus", stats.mgpdc),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   109
	E1000_STAT("rx_dma_failed", rx_dma_failed),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   110
	E1000_STAT("tx_dma_failed", tx_dma_failed),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   111
};
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   112
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   113
#define E1000_GLOBAL_STATS_LEN	ARRAY_SIZE(e1000_gstrings_stats)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   114
#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   115
static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   116
	"Register test  (offline)", "Eeprom test    (offline)",
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   117
	"Interrupt test (offline)", "Loopback test  (offline)",
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   118
	"Link test   (on/offline)"
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   119
};
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   120
#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   121
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   122
static int e1000_get_settings(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   123
			      struct ethtool_cmd *ecmd)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   124
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   125
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   126
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   127
	u32 speed;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   128
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   129
	if (hw->phy.media_type == e1000_media_type_copper) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   130
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   131
		ecmd->supported = (SUPPORTED_10baseT_Half |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   132
				   SUPPORTED_10baseT_Full |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   133
				   SUPPORTED_100baseT_Half |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   134
				   SUPPORTED_100baseT_Full |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   135
				   SUPPORTED_1000baseT_Full |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   136
				   SUPPORTED_Autoneg |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   137
				   SUPPORTED_TP);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   138
		if (hw->phy.type == e1000_phy_ife)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   139
			ecmd->supported &= ~SUPPORTED_1000baseT_Full;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   140
		ecmd->advertising = ADVERTISED_TP;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   141
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   142
		if (hw->mac.autoneg == 1) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   143
			ecmd->advertising |= ADVERTISED_Autoneg;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   144
			/* the e1000 autoneg seems to match ethtool nicely */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   145
			ecmd->advertising |= hw->phy.autoneg_advertised;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   146
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   147
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   148
		ecmd->port = PORT_TP;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   149
		ecmd->phy_address = hw->phy.addr;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   150
		ecmd->transceiver = XCVR_INTERNAL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   151
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   152
	} else {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   153
		ecmd->supported   = (SUPPORTED_1000baseT_Full |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   154
				     SUPPORTED_FIBRE |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   155
				     SUPPORTED_Autoneg);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   156
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   157
		ecmd->advertising = (ADVERTISED_1000baseT_Full |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   158
				     ADVERTISED_FIBRE |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   159
				     ADVERTISED_Autoneg);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   160
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   161
		ecmd->port = PORT_FIBRE;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   162
		ecmd->transceiver = XCVR_EXTERNAL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   163
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   164
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   165
	speed = -1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   166
	ecmd->duplex = -1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   167
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   168
	if (netif_running(netdev)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   169
		if (netif_carrier_ok(netdev)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   170
			speed = adapter->link_speed;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   171
			ecmd->duplex = adapter->link_duplex - 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   172
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   173
	} else {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   174
		u32 status = er32(STATUS);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   175
		if (status & E1000_STATUS_LU) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   176
			if (status & E1000_STATUS_SPEED_1000)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   177
				speed = SPEED_1000;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   178
			else if (status & E1000_STATUS_SPEED_100)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   179
				speed = SPEED_100;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   180
			else
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   181
				speed = SPEED_10;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   182
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   183
			if (status & E1000_STATUS_FD)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   184
				ecmd->duplex = DUPLEX_FULL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   185
			else
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   186
				ecmd->duplex = DUPLEX_HALF;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   187
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   188
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   189
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   190
	ethtool_cmd_speed_set(ecmd, speed);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   191
	ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) ||
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   192
			 hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   193
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   194
	/* MDI-X => 2; MDI =>1; Invalid =>0 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   195
	if ((hw->phy.media_type == e1000_media_type_copper) &&
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   196
	    netif_carrier_ok(netdev))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   197
		ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X :
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   198
		                                      ETH_TP_MDI;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   199
	else
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   200
		ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   201
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   202
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   203
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   204
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   205
static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   206
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   207
	struct e1000_mac_info *mac = &adapter->hw.mac;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   208
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   209
	mac->autoneg = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   210
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   211
	/* Make sure dplx is at most 1 bit and lsb of speed is not set
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   212
	 * for the switch() below to work */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   213
	if ((spd & 1) || (dplx & ~1))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   214
		goto err_inval;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   215
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   216
	/* Fiber NICs only allow 1000 gbps Full duplex */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   217
	if ((adapter->hw.phy.media_type == e1000_media_type_fiber) &&
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   218
	    spd != SPEED_1000 &&
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   219
	    dplx != DUPLEX_FULL) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   220
		goto err_inval;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   221
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   222
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   223
	switch (spd + dplx) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   224
	case SPEED_10 + DUPLEX_HALF:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   225
		mac->forced_speed_duplex = ADVERTISE_10_HALF;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   226
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   227
	case SPEED_10 + DUPLEX_FULL:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   228
		mac->forced_speed_duplex = ADVERTISE_10_FULL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   229
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   230
	case SPEED_100 + DUPLEX_HALF:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   231
		mac->forced_speed_duplex = ADVERTISE_100_HALF;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   232
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   233
	case SPEED_100 + DUPLEX_FULL:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   234
		mac->forced_speed_duplex = ADVERTISE_100_FULL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   235
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   236
	case SPEED_1000 + DUPLEX_FULL:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   237
		mac->autoneg = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   238
		adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   239
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   240
	case SPEED_1000 + DUPLEX_HALF: /* not supported */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   241
	default:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   242
		goto err_inval;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   243
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   244
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   245
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   246
err_inval:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   247
	e_err("Unsupported Speed/Duplex configuration\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   248
	return -EINVAL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   249
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   250
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   251
static int e1000_set_settings(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   252
			      struct ethtool_cmd *ecmd)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   253
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   254
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   255
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   256
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   257
	/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   258
	 * When SoL/IDER sessions are active, autoneg/speed/duplex
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   259
	 * cannot be changed
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   260
	 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   261
	if (hw->phy.ops.check_reset_block &&
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   262
	    hw->phy.ops.check_reset_block(hw)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   263
		e_err("Cannot change link characteristics when SoL/IDER is active.\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   264
		return -EINVAL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   265
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   266
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   267
	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   268
		usleep_range(1000, 2000);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   269
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   270
	if (ecmd->autoneg == AUTONEG_ENABLE) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   271
		hw->mac.autoneg = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   272
		if (hw->phy.media_type == e1000_media_type_fiber)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   273
			hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   274
						     ADVERTISED_FIBRE |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   275
						     ADVERTISED_Autoneg;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   276
		else
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   277
			hw->phy.autoneg_advertised = ecmd->advertising |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   278
						     ADVERTISED_TP |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   279
						     ADVERTISED_Autoneg;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   280
		ecmd->advertising = hw->phy.autoneg_advertised;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   281
		if (adapter->fc_autoneg)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   282
			hw->fc.requested_mode = e1000_fc_default;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   283
	} else {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   284
		u32 speed = ethtool_cmd_speed(ecmd);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   285
		if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   286
			clear_bit(__E1000_RESETTING, &adapter->state);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   287
			return -EINVAL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   288
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   289
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   290
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   291
	/* reset the link */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   292
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   293
	if (netif_running(adapter->netdev)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   294
		e1000e_down(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   295
		e1000e_up(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   296
	} else {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   297
		e1000e_reset(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   298
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   299
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   300
	clear_bit(__E1000_RESETTING, &adapter->state);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   301
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   302
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   303
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   304
static void e1000_get_pauseparam(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   305
				 struct ethtool_pauseparam *pause)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   306
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   307
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   308
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   309
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   310
	pause->autoneg =
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   311
		(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   312
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   313
	if (hw->fc.current_mode == e1000_fc_rx_pause) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   314
		pause->rx_pause = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   315
	} else if (hw->fc.current_mode == e1000_fc_tx_pause) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   316
		pause->tx_pause = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   317
	} else if (hw->fc.current_mode == e1000_fc_full) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   318
		pause->rx_pause = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   319
		pause->tx_pause = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   320
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   321
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   322
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   323
static int e1000_set_pauseparam(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   324
				struct ethtool_pauseparam *pause)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   325
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   326
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   327
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   328
	int retval = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   329
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   330
	adapter->fc_autoneg = pause->autoneg;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   331
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   332
	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   333
		usleep_range(1000, 2000);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   334
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   335
	if (adapter->fc_autoneg == AUTONEG_ENABLE) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   336
		hw->fc.requested_mode = e1000_fc_default;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   337
		if (netif_running(adapter->netdev)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   338
			e1000e_down(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   339
			e1000e_up(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   340
		} else {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   341
			e1000e_reset(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   342
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   343
	} else {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   344
		if (pause->rx_pause && pause->tx_pause)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   345
			hw->fc.requested_mode = e1000_fc_full;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   346
		else if (pause->rx_pause && !pause->tx_pause)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   347
			hw->fc.requested_mode = e1000_fc_rx_pause;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   348
		else if (!pause->rx_pause && pause->tx_pause)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   349
			hw->fc.requested_mode = e1000_fc_tx_pause;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   350
		else if (!pause->rx_pause && !pause->tx_pause)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   351
			hw->fc.requested_mode = e1000_fc_none;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   352
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   353
		hw->fc.current_mode = hw->fc.requested_mode;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   354
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   355
		if (hw->phy.media_type == e1000_media_type_fiber) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   356
			retval = hw->mac.ops.setup_link(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   357
			/* implicit goto out */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   358
		} else {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   359
			retval = e1000e_force_mac_fc(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   360
			if (retval)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   361
				goto out;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   362
			e1000e_set_fc_watermarks(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   363
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   364
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   365
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   366
out:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   367
	clear_bit(__E1000_RESETTING, &adapter->state);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   368
	return retval;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   369
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   370
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   371
static u32 e1000_get_msglevel(struct net_device *netdev)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   372
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   373
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   374
	return adapter->msg_enable;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   375
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   376
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   377
static void e1000_set_msglevel(struct net_device *netdev, u32 data)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   378
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   379
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   380
	adapter->msg_enable = data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   381
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   382
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   383
static int e1000_get_regs_len(struct net_device *netdev)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   384
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   385
#define E1000_REGS_LEN 32 /* overestimate */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   386
	return E1000_REGS_LEN * sizeof(u32);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   387
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   388
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   389
static void e1000_get_regs(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   390
			   struct ethtool_regs *regs, void *p)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   391
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   392
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   393
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   394
	u32 *regs_buff = p;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   395
	u16 phy_data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   396
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   397
	memset(p, 0, E1000_REGS_LEN * sizeof(u32));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   398
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   399
	regs->version = (1 << 24) | (adapter->pdev->revision << 16) |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   400
			adapter->pdev->device;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   401
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   402
	regs_buff[0]  = er32(CTRL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   403
	regs_buff[1]  = er32(STATUS);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   404
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   405
	regs_buff[2]  = er32(RCTL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   406
	regs_buff[3]  = er32(RDLEN(0));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   407
	regs_buff[4]  = er32(RDH(0));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   408
	regs_buff[5]  = er32(RDT(0));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   409
	regs_buff[6]  = er32(RDTR);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   410
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   411
	regs_buff[7]  = er32(TCTL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   412
	regs_buff[8]  = er32(TDLEN(0));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   413
	regs_buff[9]  = er32(TDH(0));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   414
	regs_buff[10] = er32(TDT(0));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   415
	regs_buff[11] = er32(TIDV);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   416
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   417
	regs_buff[12] = adapter->hw.phy.type;  /* PHY type (IGP=1, M88=0) */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   418
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   419
	/* ethtool doesn't use anything past this point, so all this
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   420
	 * code is likely legacy junk for apps that may or may not
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   421
	 * exist */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   422
	if (hw->phy.type == e1000_phy_m88) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   423
		e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   424
		regs_buff[13] = (u32)phy_data; /* cable length */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   425
		regs_buff[14] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   426
		regs_buff[15] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   427
		regs_buff[16] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   428
		e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   429
		regs_buff[17] = (u32)phy_data; /* extended 10bt distance */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   430
		regs_buff[18] = regs_buff[13]; /* cable polarity */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   431
		regs_buff[19] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   432
		regs_buff[20] = regs_buff[17]; /* polarity correction */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   433
		/* phy receive errors */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   434
		regs_buff[22] = adapter->phy_stats.receive_errors;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   435
		regs_buff[23] = regs_buff[13]; /* mdix mode */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   436
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   437
	regs_buff[21] = 0; /* was idle_errors */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   438
	e1e_rphy(hw, PHY_1000T_STATUS, &phy_data);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   439
	regs_buff[24] = (u32)phy_data;  /* phy local receiver status */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   440
	regs_buff[25] = regs_buff[24];  /* phy remote receiver status */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   441
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   442
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   443
static int e1000_get_eeprom_len(struct net_device *netdev)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   444
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   445
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   446
	return adapter->hw.nvm.word_size * 2;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   447
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   448
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   449
static int e1000_get_eeprom(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   450
			    struct ethtool_eeprom *eeprom, u8 *bytes)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   451
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   452
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   453
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   454
	u16 *eeprom_buff;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   455
	int first_word;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   456
	int last_word;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   457
	int ret_val = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   458
	u16 i;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   459
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   460
	if (eeprom->len == 0)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   461
		return -EINVAL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   462
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   463
	eeprom->magic = adapter->pdev->vendor | (adapter->pdev->device << 16);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   464
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   465
	first_word = eeprom->offset >> 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   466
	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   467
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   468
	eeprom_buff = kmalloc(sizeof(u16) *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   469
			(last_word - first_word + 1), GFP_KERNEL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   470
	if (!eeprom_buff)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   471
		return -ENOMEM;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   472
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   473
	if (hw->nvm.type == e1000_nvm_eeprom_spi) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   474
		ret_val = e1000_read_nvm(hw, first_word,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   475
					 last_word - first_word + 1,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   476
					 eeprom_buff);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   477
	} else {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   478
		for (i = 0; i < last_word - first_word + 1; i++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   479
			ret_val = e1000_read_nvm(hw, first_word + i, 1,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   480
						      &eeprom_buff[i]);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   481
			if (ret_val)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   482
				break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   483
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   484
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   485
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   486
	if (ret_val) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   487
		/* a read error occurred, throw away the result */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   488
		memset(eeprom_buff, 0xff, sizeof(u16) *
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   489
		       (last_word - first_word + 1));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   490
	} else {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   491
		/* Device's eeprom is always little-endian, word addressable */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   492
		for (i = 0; i < last_word - first_word + 1; i++)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   493
			le16_to_cpus(&eeprom_buff[i]);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   494
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   495
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   496
	memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   497
	kfree(eeprom_buff);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   498
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   499
	return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   500
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   501
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   502
static int e1000_set_eeprom(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   503
			    struct ethtool_eeprom *eeprom, u8 *bytes)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   504
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   505
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   506
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   507
	u16 *eeprom_buff;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   508
	void *ptr;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   509
	int max_len;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   510
	int first_word;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   511
	int last_word;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   512
	int ret_val = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   513
	u16 i;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   514
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   515
	if (eeprom->len == 0)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   516
		return -EOPNOTSUPP;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   517
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   518
	if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16)))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   519
		return -EFAULT;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   520
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   521
	if (adapter->flags & FLAG_READ_ONLY_NVM)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   522
		return -EINVAL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   523
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   524
	max_len = hw->nvm.word_size * 2;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   525
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   526
	first_word = eeprom->offset >> 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   527
	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   528
	eeprom_buff = kmalloc(max_len, GFP_KERNEL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   529
	if (!eeprom_buff)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   530
		return -ENOMEM;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   531
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   532
	ptr = (void *)eeprom_buff;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   533
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   534
	if (eeprom->offset & 1) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   535
		/* need read/modify/write of first changed EEPROM word */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   536
		/* only the second byte of the word is being modified */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   537
		ret_val = e1000_read_nvm(hw, first_word, 1, &eeprom_buff[0]);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   538
		ptr++;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   539
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   540
	if (((eeprom->offset + eeprom->len) & 1) && (!ret_val))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   541
		/* need read/modify/write of last changed EEPROM word */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   542
		/* only the first byte of the word is being modified */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   543
		ret_val = e1000_read_nvm(hw, last_word, 1,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   544
				  &eeprom_buff[last_word - first_word]);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   545
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   546
	if (ret_val)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   547
		goto out;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   548
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   549
	/* Device's eeprom is always little-endian, word addressable */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   550
	for (i = 0; i < last_word - first_word + 1; i++)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   551
		le16_to_cpus(&eeprom_buff[i]);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   552
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   553
	memcpy(ptr, bytes, eeprom->len);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   554
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   555
	for (i = 0; i < last_word - first_word + 1; i++)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   556
		cpu_to_le16s(&eeprom_buff[i]);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   557
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   558
	ret_val = e1000_write_nvm(hw, first_word,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   559
				  last_word - first_word + 1, eeprom_buff);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   560
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   561
	if (ret_val)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   562
		goto out;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   563
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   564
	/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   565
	 * Update the checksum over the first part of the EEPROM if needed
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   566
	 * and flush shadow RAM for applicable controllers
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   567
	 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   568
	if ((first_word <= NVM_CHECKSUM_REG) ||
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   569
	    (hw->mac.type == e1000_82583) ||
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   570
	    (hw->mac.type == e1000_82574) ||
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   571
	    (hw->mac.type == e1000_82573))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   572
		ret_val = e1000e_update_nvm_checksum(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   573
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   574
out:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   575
	kfree(eeprom_buff);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   576
	return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   577
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   578
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   579
static void e1000_get_drvinfo(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   580
			      struct ethtool_drvinfo *drvinfo)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   581
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   582
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   583
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   584
	strlcpy(drvinfo->driver,  e1000e_driver_name,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   585
		sizeof(drvinfo->driver));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   586
	strlcpy(drvinfo->version, e1000e_driver_version,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   587
		sizeof(drvinfo->version));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   588
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   589
	/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   590
	 * EEPROM image version # is reported as firmware version # for
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   591
	 * PCI-E controllers
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   592
	 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   593
	snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   594
		"%d.%d-%d",
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   595
		(adapter->eeprom_vers & 0xF000) >> 12,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   596
		(adapter->eeprom_vers & 0x0FF0) >> 4,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   597
		(adapter->eeprom_vers & 0x000F));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   598
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   599
	strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   600
		sizeof(drvinfo->bus_info));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   601
	drvinfo->regdump_len = e1000_get_regs_len(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   602
	drvinfo->eedump_len = e1000_get_eeprom_len(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   603
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   604
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   605
static void e1000_get_ringparam(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   606
				struct ethtool_ringparam *ring)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   607
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   608
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   609
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   610
	ring->rx_max_pending = E1000_MAX_RXD;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   611
	ring->tx_max_pending = E1000_MAX_TXD;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   612
	ring->rx_pending = adapter->rx_ring_count;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   613
	ring->tx_pending = adapter->tx_ring_count;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   614
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   615
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   616
static int e1000_set_ringparam(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   617
			       struct ethtool_ringparam *ring)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   618
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   619
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   620
	struct e1000_ring *temp_tx = NULL, *temp_rx = NULL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   621
	int err = 0, size = sizeof(struct e1000_ring);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   622
	bool set_tx = false, set_rx = false;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   623
	u16 new_rx_count, new_tx_count;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   624
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   625
	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   626
		return -EINVAL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   627
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   628
	new_rx_count = clamp_t(u32, ring->rx_pending, E1000_MIN_RXD,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   629
			       E1000_MAX_RXD);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   630
	new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   631
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   632
	new_tx_count = clamp_t(u32, ring->tx_pending, E1000_MIN_TXD,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   633
			       E1000_MAX_TXD);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   634
	new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   635
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   636
	if ((new_tx_count == adapter->tx_ring_count) &&
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   637
	    (new_rx_count == adapter->rx_ring_count))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   638
		/* nothing to do */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   639
		return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   640
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   641
	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   642
		usleep_range(1000, 2000);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   643
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   644
	if (!netif_running(adapter->netdev)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   645
		/* Set counts now and allocate resources during open() */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   646
		adapter->tx_ring->count = new_tx_count;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   647
		adapter->rx_ring->count = new_rx_count;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   648
		adapter->tx_ring_count = new_tx_count;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   649
		adapter->rx_ring_count = new_rx_count;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   650
		goto clear_reset;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   651
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   652
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   653
	set_tx = (new_tx_count != adapter->tx_ring_count);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   654
	set_rx = (new_rx_count != adapter->rx_ring_count);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   655
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   656
	/* Allocate temporary storage for ring updates */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   657
	if (set_tx) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   658
		temp_tx = vmalloc(size);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   659
		if (!temp_tx) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   660
			err = -ENOMEM;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   661
			goto free_temp;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   662
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   663
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   664
	if (set_rx) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   665
		temp_rx = vmalloc(size);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   666
		if (!temp_rx) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   667
			err = -ENOMEM;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   668
			goto free_temp;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   669
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   670
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   671
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   672
	e1000e_down(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   673
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   674
	/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   675
	 * We can't just free everything and then setup again, because the
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   676
	 * ISRs in MSI-X mode get passed pointers to the Tx and Rx ring
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   677
	 * structs.  First, attempt to allocate new resources...
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   678
	 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   679
	if (set_tx) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   680
		memcpy(temp_tx, adapter->tx_ring, size);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   681
		temp_tx->count = new_tx_count;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   682
		err = e1000e_setup_tx_resources(temp_tx);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   683
		if (err)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   684
			goto err_setup;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   685
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   686
	if (set_rx) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   687
		memcpy(temp_rx, adapter->rx_ring, size);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   688
		temp_rx->count = new_rx_count;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   689
		err = e1000e_setup_rx_resources(temp_rx);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   690
		if (err)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   691
			goto err_setup_rx;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   692
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   693
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   694
	/* ...then free the old resources and copy back any new ring data */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   695
	if (set_tx) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   696
		e1000e_free_tx_resources(adapter->tx_ring);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   697
		memcpy(adapter->tx_ring, temp_tx, size);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   698
		adapter->tx_ring_count = new_tx_count;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   699
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   700
	if (set_rx) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   701
		e1000e_free_rx_resources(adapter->rx_ring);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   702
		memcpy(adapter->rx_ring, temp_rx, size);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   703
		adapter->rx_ring_count = new_rx_count;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   704
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   705
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   706
err_setup_rx:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   707
	if (err && set_tx)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   708
		e1000e_free_tx_resources(temp_tx);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   709
err_setup:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   710
	e1000e_up(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   711
free_temp:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   712
	vfree(temp_tx);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   713
	vfree(temp_rx);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   714
clear_reset:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   715
	clear_bit(__E1000_RESETTING, &adapter->state);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   716
	return err;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   717
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   718
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   719
static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   720
			     int reg, int offset, u32 mask, u32 write)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   721
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   722
	u32 pat, val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   723
	static const u32 test[] = {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   724
		0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   725
	for (pat = 0; pat < ARRAY_SIZE(test); pat++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   726
		E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   727
				      (test[pat] & write));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   728
		val = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   729
		if (val != (test[pat] & write & mask)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   730
			e_err("pattern test reg %04X failed: got 0x%08X expected 0x%08X\n",
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   731
			      reg + offset, val, (test[pat] & write & mask));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   732
			*data = reg;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   733
			return 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   734
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   735
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   736
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   737
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   738
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   739
static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   740
			      int reg, u32 mask, u32 write)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   741
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   742
	u32 val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   743
	__ew32(&adapter->hw, reg, write & mask);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   744
	val = __er32(&adapter->hw, reg);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   745
	if ((write & mask) != (val & mask)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   746
		e_err("set/check reg %04X test failed: got 0x%08X expected 0x%08X\n",
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   747
		      reg, (val & mask), (write & mask));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   748
		*data = reg;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   749
		return 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   750
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   751
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   752
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   753
#define REG_PATTERN_TEST_ARRAY(reg, offset, mask, write)                       \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   754
	do {                                                                   \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   755
		if (reg_pattern_test(adapter, data, reg, offset, mask, write)) \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   756
			return 1;                                              \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   757
	} while (0)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   758
#define REG_PATTERN_TEST(reg, mask, write)                                     \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   759
	REG_PATTERN_TEST_ARRAY(reg, 0, mask, write)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   760
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   761
#define REG_SET_AND_CHECK(reg, mask, write)                                    \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   762
	do {                                                                   \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   763
		if (reg_set_and_check(adapter, data, reg, mask, write))        \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   764
			return 1;                                              \
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   765
	} while (0)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   766
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   767
static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   768
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   769
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   770
	struct e1000_mac_info *mac = &adapter->hw.mac;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   771
	u32 value;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   772
	u32 before;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   773
	u32 after;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   774
	u32 i;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   775
	u32 toggle;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   776
	u32 mask;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   777
	u32 wlock_mac = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   778
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   779
	/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   780
	 * The status register is Read Only, so a write should fail.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   781
	 * Some bits that get toggled are ignored.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   782
	 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   783
	switch (mac->type) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   784
	/* there are several bits on newer hardware that are r/w */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   785
	case e1000_82571:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   786
	case e1000_82572:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   787
	case e1000_80003es2lan:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   788
		toggle = 0x7FFFF3FF;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   789
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   790
        default:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   791
		toggle = 0x7FFFF033;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   792
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   793
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   794
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   795
	before = er32(STATUS);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   796
	value = (er32(STATUS) & toggle);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   797
	ew32(STATUS, toggle);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   798
	after = er32(STATUS) & toggle;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   799
	if (value != after) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   800
		e_err("failed STATUS register test got: 0x%08X expected: 0x%08X\n",
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   801
		      after, value);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   802
		*data = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   803
		return 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   804
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   805
	/* restore previous status */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   806
	ew32(STATUS, before);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   807
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   808
	if (!(adapter->flags & FLAG_IS_ICH)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   809
		REG_PATTERN_TEST(E1000_FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   810
		REG_PATTERN_TEST(E1000_FCAH, 0x0000FFFF, 0xFFFFFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   811
		REG_PATTERN_TEST(E1000_FCT, 0x0000FFFF, 0xFFFFFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   812
		REG_PATTERN_TEST(E1000_VET, 0x0000FFFF, 0xFFFFFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   813
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   814
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   815
	REG_PATTERN_TEST(E1000_RDTR, 0x0000FFFF, 0xFFFFFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   816
	REG_PATTERN_TEST(E1000_RDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   817
	REG_PATTERN_TEST(E1000_RDLEN(0), 0x000FFF80, 0x000FFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   818
	REG_PATTERN_TEST(E1000_RDH(0), 0x0000FFFF, 0x0000FFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   819
	REG_PATTERN_TEST(E1000_RDT(0), 0x0000FFFF, 0x0000FFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   820
	REG_PATTERN_TEST(E1000_FCRTH, 0x0000FFF8, 0x0000FFF8);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   821
	REG_PATTERN_TEST(E1000_FCTTV, 0x0000FFFF, 0x0000FFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   822
	REG_PATTERN_TEST(E1000_TIPG, 0x3FFFFFFF, 0x3FFFFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   823
	REG_PATTERN_TEST(E1000_TDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   824
	REG_PATTERN_TEST(E1000_TDLEN(0), 0x000FFF80, 0x000FFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   825
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   826
	REG_SET_AND_CHECK(E1000_RCTL, 0xFFFFFFFF, 0x00000000);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   827
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   828
	before = ((adapter->flags & FLAG_IS_ICH) ? 0x06C3B33E : 0x06DFB3FE);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   829
	REG_SET_AND_CHECK(E1000_RCTL, before, 0x003FFFFB);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   830
	REG_SET_AND_CHECK(E1000_TCTL, 0xFFFFFFFF, 0x00000000);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   831
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   832
	REG_SET_AND_CHECK(E1000_RCTL, before, 0xFFFFFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   833
	REG_PATTERN_TEST(E1000_RDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   834
	if (!(adapter->flags & FLAG_IS_ICH))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   835
		REG_PATTERN_TEST(E1000_TXCW, 0xC000FFFF, 0x0000FFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   836
	REG_PATTERN_TEST(E1000_TDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   837
	REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   838
	mask = 0x8003FFFF;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   839
	switch (mac->type) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   840
	case e1000_ich10lan:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   841
	case e1000_pchlan:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   842
	case e1000_pch2lan:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   843
	case e1000_pch_lpt:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   844
		mask |= (1 << 18);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   845
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   846
	default:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   847
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   848
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   849
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   850
	if (mac->type == e1000_pch_lpt)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   851
		wlock_mac = (er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK) >>
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   852
		    E1000_FWSM_WLOCK_MAC_SHIFT;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   853
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   854
	for (i = 0; i < mac->rar_entry_count; i++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   855
		/* Cannot test write-protected SHRAL[n] registers */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   856
		if ((wlock_mac == 1) || (wlock_mac && (i > wlock_mac)))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   857
			continue;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   858
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   859
		REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   860
				       mask, 0xFFFFFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   861
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   862
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   863
	for (i = 0; i < mac->mta_reg_count; i++)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   864
		REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   865
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   866
	*data = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   867
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   868
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   869
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   870
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   871
static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   872
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   873
	u16 temp;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   874
	u16 checksum = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   875
	u16 i;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   876
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   877
	*data = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   878
	/* Read and add up the contents of the EEPROM */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   879
	for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   880
		if ((e1000_read_nvm(&adapter->hw, i, 1, &temp)) < 0) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   881
			*data = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   882
			return *data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   883
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   884
		checksum += temp;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   885
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   886
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   887
	/* If Checksum is not Correct return error else test passed */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   888
	if ((checksum != (u16) NVM_SUM) && !(*data))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   889
		*data = 2;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   890
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   891
	return *data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   892
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   893
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   894
static irqreturn_t e1000_test_intr(int irq, void *data)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   895
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   896
	struct net_device *netdev = (struct net_device *) data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   897
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   898
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   899
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   900
	adapter->test_icr |= er32(ICR);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   901
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   902
	return IRQ_HANDLED;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   903
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   904
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   905
static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   906
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   907
	struct net_device *netdev = adapter->netdev;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   908
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   909
	u32 mask;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   910
	u32 shared_int = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   911
	u32 irq = adapter->pdev->irq;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   912
	int i;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   913
	int ret_val = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   914
	int int_mode = E1000E_INT_MODE_LEGACY;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   915
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   916
	*data = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   917
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   918
	/* NOTE: we don't test MSI/MSI-X interrupts here, yet */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   919
	if (adapter->int_mode == E1000E_INT_MODE_MSIX) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   920
		int_mode = adapter->int_mode;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   921
		e1000e_reset_interrupt_capability(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   922
		adapter->int_mode = E1000E_INT_MODE_LEGACY;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   923
		e1000e_set_interrupt_capability(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   924
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   925
	/* Hook up test interrupt handler just for this test */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   926
	if (!request_irq(irq, e1000_test_intr, IRQF_PROBE_SHARED, netdev->name,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   927
			 netdev)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   928
		shared_int = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   929
	} else if (request_irq(irq, e1000_test_intr, IRQF_SHARED,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   930
		 netdev->name, netdev)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   931
		*data = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   932
		ret_val = -1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   933
		goto out;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   934
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   935
	e_info("testing %s interrupt\n", (shared_int ? "shared" : "unshared"));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   936
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   937
	/* Disable all the interrupts */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   938
	ew32(IMC, 0xFFFFFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   939
	e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   940
	usleep_range(10000, 20000);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   941
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   942
	/* Test each interrupt */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   943
	for (i = 0; i < 10; i++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   944
		/* Interrupt to test */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   945
		mask = 1 << i;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   946
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   947
		if (adapter->flags & FLAG_IS_ICH) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   948
			switch (mask) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   949
			case E1000_ICR_RXSEQ:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   950
				continue;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   951
			case 0x00000100:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   952
				if (adapter->hw.mac.type == e1000_ich8lan ||
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   953
				    adapter->hw.mac.type == e1000_ich9lan)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   954
					continue;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   955
				break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   956
			default:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   957
				break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   958
			}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   959
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   960
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   961
		if (!shared_int) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   962
			/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   963
			 * Disable the interrupt to be reported in
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   964
			 * the cause register and then force the same
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   965
			 * interrupt and see if one gets posted.  If
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   966
			 * an interrupt was posted to the bus, the
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   967
			 * test failed.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   968
			 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   969
			adapter->test_icr = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   970
			ew32(IMC, mask);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   971
			ew32(ICS, mask);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   972
			e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   973
			usleep_range(10000, 20000);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   974
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   975
			if (adapter->test_icr & mask) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   976
				*data = 3;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   977
				break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   978
			}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   979
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   980
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   981
		/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   982
		 * Enable the interrupt to be reported in
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   983
		 * the cause register and then force the same
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   984
		 * interrupt and see if one gets posted.  If
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   985
		 * an interrupt was not posted to the bus, the
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   986
		 * test failed.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   987
		 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   988
		adapter->test_icr = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   989
		ew32(IMS, mask);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   990
		ew32(ICS, mask);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   991
		e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   992
		usleep_range(10000, 20000);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   993
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   994
		if (!(adapter->test_icr & mask)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   995
			*data = 4;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   996
			break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   997
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   998
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   999
		if (!shared_int) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1000
			/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1001
			 * Disable the other interrupts to be reported in
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1002
			 * the cause register and then force the other
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1003
			 * interrupts and see if any get posted.  If
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1004
			 * an interrupt was posted to the bus, the
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1005
			 * test failed.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1006
			 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1007
			adapter->test_icr = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1008
			ew32(IMC, ~mask & 0x00007FFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1009
			ew32(ICS, ~mask & 0x00007FFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1010
			e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1011
			usleep_range(10000, 20000);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1012
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1013
			if (adapter->test_icr) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1014
				*data = 5;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1015
				break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1016
			}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1017
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1018
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1019
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1020
	/* Disable all the interrupts */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1021
	ew32(IMC, 0xFFFFFFFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1022
	e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1023
	usleep_range(10000, 20000);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1024
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1025
	/* Unhook test interrupt handler */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1026
	free_irq(irq, netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1027
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1028
out:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1029
	if (int_mode == E1000E_INT_MODE_MSIX) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1030
		e1000e_reset_interrupt_capability(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1031
		adapter->int_mode = int_mode;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1032
		e1000e_set_interrupt_capability(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1033
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1034
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1035
	return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1036
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1037
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1038
static void e1000_free_desc_rings(struct e1000_adapter *adapter)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1039
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1040
	struct e1000_ring *tx_ring = &adapter->test_tx_ring;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1041
	struct e1000_ring *rx_ring = &adapter->test_rx_ring;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1042
	struct pci_dev *pdev = adapter->pdev;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1043
	int i;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1044
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1045
	if (tx_ring->desc && tx_ring->buffer_info) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1046
		for (i = 0; i < tx_ring->count; i++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1047
			if (tx_ring->buffer_info[i].dma)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1048
				dma_unmap_single(&pdev->dev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1049
					tx_ring->buffer_info[i].dma,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1050
					tx_ring->buffer_info[i].length,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1051
					DMA_TO_DEVICE);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1052
			if (tx_ring->buffer_info[i].skb)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1053
				dev_kfree_skb(tx_ring->buffer_info[i].skb);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1054
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1055
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1056
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1057
	if (rx_ring->desc && rx_ring->buffer_info) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1058
		for (i = 0; i < rx_ring->count; i++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1059
			if (rx_ring->buffer_info[i].dma)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1060
				dma_unmap_single(&pdev->dev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1061
					rx_ring->buffer_info[i].dma,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1062
					2048, DMA_FROM_DEVICE);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1063
			if (rx_ring->buffer_info[i].skb)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1064
				dev_kfree_skb(rx_ring->buffer_info[i].skb);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1065
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1066
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1067
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1068
	if (tx_ring->desc) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1069
		dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1070
				  tx_ring->dma);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1071
		tx_ring->desc = NULL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1072
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1073
	if (rx_ring->desc) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1074
		dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1075
				  rx_ring->dma);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1076
		rx_ring->desc = NULL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1077
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1078
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1079
	kfree(tx_ring->buffer_info);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1080
	tx_ring->buffer_info = NULL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1081
	kfree(rx_ring->buffer_info);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1082
	rx_ring->buffer_info = NULL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1083
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1084
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1085
static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1086
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1087
	struct e1000_ring *tx_ring = &adapter->test_tx_ring;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1088
	struct e1000_ring *rx_ring = &adapter->test_rx_ring;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1089
	struct pci_dev *pdev = adapter->pdev;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1090
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1091
	u32 rctl;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1092
	int i;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1093
	int ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1094
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1095
	/* Setup Tx descriptor ring and Tx buffers */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1096
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1097
	if (!tx_ring->count)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1098
		tx_ring->count = E1000_DEFAULT_TXD;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1099
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1100
	tx_ring->buffer_info = kcalloc(tx_ring->count,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1101
				       sizeof(struct e1000_buffer),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1102
				       GFP_KERNEL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1103
	if (!tx_ring->buffer_info) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1104
		ret_val = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1105
		goto err_nomem;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1106
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1107
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1108
	tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1109
	tx_ring->size = ALIGN(tx_ring->size, 4096);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1110
	tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1111
					   &tx_ring->dma, GFP_KERNEL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1112
	if (!tx_ring->desc) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1113
		ret_val = 2;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1114
		goto err_nomem;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1115
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1116
	tx_ring->next_to_use = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1117
	tx_ring->next_to_clean = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1118
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1119
	ew32(TDBAL(0), ((u64) tx_ring->dma & 0x00000000FFFFFFFF));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1120
	ew32(TDBAH(0), ((u64) tx_ring->dma >> 32));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1121
	ew32(TDLEN(0), tx_ring->count * sizeof(struct e1000_tx_desc));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1122
	ew32(TDH(0), 0);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1123
	ew32(TDT(0), 0);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1124
	ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN | E1000_TCTL_MULR |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1125
	     E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1126
	     E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1127
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1128
	for (i = 0; i < tx_ring->count; i++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1129
		struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1130
		struct sk_buff *skb;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1131
		unsigned int skb_size = 1024;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1132
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1133
		skb = alloc_skb(skb_size, GFP_KERNEL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1134
		if (!skb) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1135
			ret_val = 3;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1136
			goto err_nomem;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1137
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1138
		skb_put(skb, skb_size);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1139
		tx_ring->buffer_info[i].skb = skb;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1140
		tx_ring->buffer_info[i].length = skb->len;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1141
		tx_ring->buffer_info[i].dma =
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1142
			dma_map_single(&pdev->dev, skb->data, skb->len,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1143
				       DMA_TO_DEVICE);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1144
		if (dma_mapping_error(&pdev->dev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1145
				      tx_ring->buffer_info[i].dma)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1146
			ret_val = 4;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1147
			goto err_nomem;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1148
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1149
		tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1150
		tx_desc->lower.data = cpu_to_le32(skb->len);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1151
		tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1152
						   E1000_TXD_CMD_IFCS |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1153
						   E1000_TXD_CMD_RS);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1154
		tx_desc->upper.data = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1155
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1156
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1157
	/* Setup Rx descriptor ring and Rx buffers */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1158
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1159
	if (!rx_ring->count)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1160
		rx_ring->count = E1000_DEFAULT_RXD;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1161
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1162
	rx_ring->buffer_info = kcalloc(rx_ring->count,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1163
				       sizeof(struct e1000_buffer),
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1164
				       GFP_KERNEL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1165
	if (!rx_ring->buffer_info) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1166
		ret_val = 5;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1167
		goto err_nomem;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1168
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1169
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1170
	rx_ring->size = rx_ring->count * sizeof(union e1000_rx_desc_extended);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1171
	rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1172
					   &rx_ring->dma, GFP_KERNEL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1173
	if (!rx_ring->desc) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1174
		ret_val = 6;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1175
		goto err_nomem;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1176
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1177
	rx_ring->next_to_use = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1178
	rx_ring->next_to_clean = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1179
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1180
	rctl = er32(RCTL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1181
	if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1182
		ew32(RCTL, rctl & ~E1000_RCTL_EN);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1183
	ew32(RDBAL(0), ((u64) rx_ring->dma & 0xFFFFFFFF));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1184
	ew32(RDBAH(0), ((u64) rx_ring->dma >> 32));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1185
	ew32(RDLEN(0), rx_ring->size);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1186
	ew32(RDH(0), 0);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1187
	ew32(RDT(0), 0);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1188
	rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1189
		E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1190
		E1000_RCTL_SBP | E1000_RCTL_SECRC |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1191
		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1192
		(adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1193
	ew32(RCTL, rctl);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1194
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1195
	for (i = 0; i < rx_ring->count; i++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1196
		union e1000_rx_desc_extended *rx_desc;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1197
		struct sk_buff *skb;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1198
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1199
		skb = alloc_skb(2048 + NET_IP_ALIGN, GFP_KERNEL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1200
		if (!skb) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1201
			ret_val = 7;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1202
			goto err_nomem;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1203
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1204
		skb_reserve(skb, NET_IP_ALIGN);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1205
		rx_ring->buffer_info[i].skb = skb;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1206
		rx_ring->buffer_info[i].dma =
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1207
			dma_map_single(&pdev->dev, skb->data, 2048,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1208
				       DMA_FROM_DEVICE);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1209
		if (dma_mapping_error(&pdev->dev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1210
				      rx_ring->buffer_info[i].dma)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1211
			ret_val = 8;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1212
			goto err_nomem;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1213
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1214
		rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1215
		rx_desc->read.buffer_addr =
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1216
		    cpu_to_le64(rx_ring->buffer_info[i].dma);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1217
		memset(skb->data, 0x00, skb->len);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1218
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1219
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1220
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1221
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1222
err_nomem:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1223
	e1000_free_desc_rings(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1224
	return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1225
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1226
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1227
static void e1000_phy_disable_receiver(struct e1000_adapter *adapter)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1228
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1229
	/* Write out to PHY registers 29 and 30 to disable the Receiver. */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1230
	e1e_wphy(&adapter->hw, 29, 0x001F);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1231
	e1e_wphy(&adapter->hw, 30, 0x8FFC);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1232
	e1e_wphy(&adapter->hw, 29, 0x001A);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1233
	e1e_wphy(&adapter->hw, 30, 0x8FF0);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1234
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1235
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1236
static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1237
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1238
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1239
	u32 ctrl_reg = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1240
	u16 phy_reg = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1241
	s32 ret_val = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1242
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1243
	hw->mac.autoneg = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1244
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1245
	if (hw->phy.type == e1000_phy_ife) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1246
		/* force 100, set loopback */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1247
		e1e_wphy(hw, PHY_CONTROL, 0x6100);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1248
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1249
		/* Now set up the MAC to the same speed/duplex as the PHY. */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1250
		ctrl_reg = er32(CTRL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1251
		ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1252
		ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1253
			     E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1254
			     E1000_CTRL_SPD_100 |/* Force Speed to 100 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1255
			     E1000_CTRL_FD);	 /* Force Duplex to FULL */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1256
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1257
		ew32(CTRL, ctrl_reg);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1258
		e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1259
		udelay(500);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1260
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1261
		return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1262
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1263
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1264
	/* Specific PHY configuration for loopback */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1265
	switch (hw->phy.type) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1266
	case e1000_phy_m88:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1267
		/* Auto-MDI/MDIX Off */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1268
		e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1269
		/* reset to update Auto-MDI/MDIX */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1270
		e1e_wphy(hw, PHY_CONTROL, 0x9140);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1271
		/* autoneg off */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1272
		e1e_wphy(hw, PHY_CONTROL, 0x8140);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1273
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1274
	case e1000_phy_gg82563:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1275
		e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1276
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1277
	case e1000_phy_bm:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1278
		/* Set Default MAC Interface speed to 1GB */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1279
		e1e_rphy(hw, PHY_REG(2, 21), &phy_reg);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1280
		phy_reg &= ~0x0007;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1281
		phy_reg |= 0x006;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1282
		e1e_wphy(hw, PHY_REG(2, 21), phy_reg);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1283
		/* Assert SW reset for above settings to take effect */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1284
		e1000e_commit_phy(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1285
		mdelay(1);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1286
		/* Force Full Duplex */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1287
		e1e_rphy(hw, PHY_REG(769, 16), &phy_reg);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1288
		e1e_wphy(hw, PHY_REG(769, 16), phy_reg | 0x000C);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1289
		/* Set Link Up (in force link) */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1290
		e1e_rphy(hw, PHY_REG(776, 16), &phy_reg);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1291
		e1e_wphy(hw, PHY_REG(776, 16), phy_reg | 0x0040);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1292
		/* Force Link */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1293
		e1e_rphy(hw, PHY_REG(769, 16), &phy_reg);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1294
		e1e_wphy(hw, PHY_REG(769, 16), phy_reg | 0x0040);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1295
		/* Set Early Link Enable */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1296
		e1e_rphy(hw, PHY_REG(769, 20), &phy_reg);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1297
		e1e_wphy(hw, PHY_REG(769, 20), phy_reg | 0x0400);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1298
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1299
	case e1000_phy_82577:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1300
	case e1000_phy_82578:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1301
		/* Workaround: K1 must be disabled for stable 1Gbps operation */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1302
		ret_val = hw->phy.ops.acquire(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1303
		if (ret_val) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1304
			e_err("Cannot setup 1Gbps loopback.\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1305
			return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1306
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1307
		e1000_configure_k1_ich8lan(hw, false);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1308
		hw->phy.ops.release(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1309
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1310
	case e1000_phy_82579:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1311
		/* Disable PHY energy detect power down */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1312
		e1e_rphy(hw, PHY_REG(0, 21), &phy_reg);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1313
		e1e_wphy(hw, PHY_REG(0, 21), phy_reg & ~(1 << 3));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1314
		/* Disable full chip energy detect */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1315
		e1e_rphy(hw, PHY_REG(776, 18), &phy_reg);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1316
		e1e_wphy(hw, PHY_REG(776, 18), phy_reg | 1);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1317
		/* Enable loopback on the PHY */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1318
#define I82577_PHY_LBK_CTRL          19
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1319
		e1e_wphy(hw, I82577_PHY_LBK_CTRL, 0x8001);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1320
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1321
	default:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1322
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1323
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1324
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1325
	/* force 1000, set loopback */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1326
	e1e_wphy(hw, PHY_CONTROL, 0x4140);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1327
	mdelay(250);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1328
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1329
	/* Now set up the MAC to the same speed/duplex as the PHY. */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1330
	ctrl_reg = er32(CTRL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1331
	ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1332
	ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1333
		     E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1334
		     E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1335
		     E1000_CTRL_FD);	 /* Force Duplex to FULL */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1336
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1337
	if (adapter->flags & FLAG_IS_ICH)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1338
		ctrl_reg |= E1000_CTRL_SLU;	/* Set Link Up */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1339
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1340
	if (hw->phy.media_type == e1000_media_type_copper &&
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1341
	    hw->phy.type == e1000_phy_m88) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1342
		ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1343
	} else {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1344
		/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1345
		 * Set the ILOS bit on the fiber Nic if half duplex link is
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1346
		 * detected.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1347
		 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1348
		if ((er32(STATUS) & E1000_STATUS_FD) == 0)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1349
			ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1350
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1351
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1352
	ew32(CTRL, ctrl_reg);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1353
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1354
	/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1355
	 * Disable the receiver on the PHY so when a cable is plugged in, the
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1356
	 * PHY does not begin to autoneg when a cable is reconnected to the NIC.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1357
	 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1358
	if (hw->phy.type == e1000_phy_m88)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1359
		e1000_phy_disable_receiver(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1360
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1361
	udelay(500);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1362
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1363
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1364
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1365
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1366
static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1367
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1368
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1369
	u32 ctrl = er32(CTRL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1370
	int link = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1371
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1372
	/* special requirements for 82571/82572 fiber adapters */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1373
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1374
	/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1375
	 * jump through hoops to make sure link is up because serdes
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1376
	 * link is hardwired up
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1377
	 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1378
	ctrl |= E1000_CTRL_SLU;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1379
	ew32(CTRL, ctrl);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1380
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1381
	/* disable autoneg */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1382
	ctrl = er32(TXCW);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1383
	ctrl &= ~(1 << 31);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1384
	ew32(TXCW, ctrl);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1385
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1386
	link = (er32(STATUS) & E1000_STATUS_LU);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1387
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1388
	if (!link) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1389
		/* set invert loss of signal */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1390
		ctrl = er32(CTRL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1391
		ctrl |= E1000_CTRL_ILOS;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1392
		ew32(CTRL, ctrl);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1393
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1394
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1395
	/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1396
	 * special write to serdes control register to enable SerDes analog
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1397
	 * loopback
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1398
	 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1399
#define E1000_SERDES_LB_ON 0x410
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1400
	ew32(SCTL, E1000_SERDES_LB_ON);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1401
	e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1402
	usleep_range(10000, 20000);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1403
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1404
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1405
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1406
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1407
/* only call this for fiber/serdes connections to es2lan */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1408
static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1409
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1410
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1411
	u32 ctrlext = er32(CTRL_EXT);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1412
	u32 ctrl = er32(CTRL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1413
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1414
	/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1415
	 * save CTRL_EXT to restore later, reuse an empty variable (unused
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1416
	 * on mac_type 80003es2lan)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1417
	 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1418
	adapter->tx_fifo_head = ctrlext;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1419
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1420
	/* clear the serdes mode bits, putting the device into mac loopback */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1421
	ctrlext &= ~E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1422
	ew32(CTRL_EXT, ctrlext);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1423
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1424
	/* force speed to 1000/FD, link up */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1425
	ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1426
	ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1427
		 E1000_CTRL_SPD_1000 | E1000_CTRL_FD);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1428
	ew32(CTRL, ctrl);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1429
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1430
	/* set mac loopback */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1431
	ctrl = er32(RCTL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1432
	ctrl |= E1000_RCTL_LBM_MAC;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1433
	ew32(RCTL, ctrl);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1434
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1435
	/* set testing mode parameters (no need to reset later) */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1436
#define KMRNCTRLSTA_OPMODE (0x1F << 16)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1437
#define KMRNCTRLSTA_OPMODE_1GB_FD_GMII 0x0582
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1438
	ew32(KMRNCTRLSTA,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1439
	     (KMRNCTRLSTA_OPMODE | KMRNCTRLSTA_OPMODE_1GB_FD_GMII));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1440
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1441
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1442
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1443
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1444
static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1445
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1446
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1447
	u32 rctl;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1448
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1449
	if (hw->phy.media_type == e1000_media_type_fiber ||
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1450
	    hw->phy.media_type == e1000_media_type_internal_serdes) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1451
		switch (hw->mac.type) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1452
		case e1000_80003es2lan:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1453
			return e1000_set_es2lan_mac_loopback(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1454
			break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1455
		case e1000_82571:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1456
		case e1000_82572:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1457
			return e1000_set_82571_fiber_loopback(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1458
			break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1459
		default:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1460
			rctl = er32(RCTL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1461
			rctl |= E1000_RCTL_LBM_TCVR;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1462
			ew32(RCTL, rctl);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1463
			return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1464
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1465
	} else if (hw->phy.media_type == e1000_media_type_copper) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1466
		return e1000_integrated_phy_loopback(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1467
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1468
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1469
	return 7;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1470
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1471
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1472
static void e1000_loopback_cleanup(struct e1000_adapter *adapter)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1473
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1474
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1475
	u32 rctl;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1476
	u16 phy_reg;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1477
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1478
	rctl = er32(RCTL);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1479
	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1480
	ew32(RCTL, rctl);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1481
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1482
	switch (hw->mac.type) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1483
	case e1000_80003es2lan:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1484
		if (hw->phy.media_type == e1000_media_type_fiber ||
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1485
		    hw->phy.media_type == e1000_media_type_internal_serdes) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1486
			/* restore CTRL_EXT, stealing space from tx_fifo_head */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1487
			ew32(CTRL_EXT, adapter->tx_fifo_head);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1488
			adapter->tx_fifo_head = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1489
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1490
		/* fall through */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1491
	case e1000_82571:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1492
	case e1000_82572:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1493
		if (hw->phy.media_type == e1000_media_type_fiber ||
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1494
		    hw->phy.media_type == e1000_media_type_internal_serdes) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1495
#define E1000_SERDES_LB_OFF 0x400
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1496
			ew32(SCTL, E1000_SERDES_LB_OFF);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1497
			e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1498
			usleep_range(10000, 20000);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1499
			break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1500
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1501
		/* Fall Through */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1502
	default:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1503
		hw->mac.autoneg = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1504
		if (hw->phy.type == e1000_phy_gg82563)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1505
			e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x180);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1506
		e1e_rphy(hw, PHY_CONTROL, &phy_reg);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1507
		if (phy_reg & MII_CR_LOOPBACK) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1508
			phy_reg &= ~MII_CR_LOOPBACK;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1509
			e1e_wphy(hw, PHY_CONTROL, phy_reg);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1510
			e1000e_commit_phy(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1511
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1512
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1513
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1514
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1515
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1516
static void e1000_create_lbtest_frame(struct sk_buff *skb,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1517
				      unsigned int frame_size)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1518
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1519
	memset(skb->data, 0xFF, frame_size);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1520
	frame_size &= ~1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1521
	memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1522
	memset(&skb->data[frame_size / 2 + 10], 0xBE, 1);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1523
	memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1524
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1525
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1526
static int e1000_check_lbtest_frame(struct sk_buff *skb,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1527
				    unsigned int frame_size)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1528
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1529
	frame_size &= ~1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1530
	if (*(skb->data + 3) == 0xFF)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1531
		if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1532
		   (*(skb->data + frame_size / 2 + 12) == 0xAF))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1533
			return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1534
	return 13;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1535
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1536
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1537
static int e1000_run_loopback_test(struct e1000_adapter *adapter)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1538
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1539
	struct e1000_ring *tx_ring = &adapter->test_tx_ring;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1540
	struct e1000_ring *rx_ring = &adapter->test_rx_ring;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1541
	struct pci_dev *pdev = adapter->pdev;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1542
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1543
	int i, j, k, l;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1544
	int lc;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1545
	int good_cnt;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1546
	int ret_val = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1547
	unsigned long time;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1548
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1549
	ew32(RDT(0), rx_ring->count - 1);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1550
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1551
	/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1552
	 * Calculate the loop count based on the largest descriptor ring
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1553
	 * The idea is to wrap the largest ring a number of times using 64
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1554
	 * send/receive pairs during each loop
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1555
	 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1556
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1557
	if (rx_ring->count <= tx_ring->count)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1558
		lc = ((tx_ring->count / 64) * 2) + 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1559
	else
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1560
		lc = ((rx_ring->count / 64) * 2) + 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1561
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1562
	k = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1563
	l = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1564
	for (j = 0; j <= lc; j++) { /* loop count loop */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1565
		for (i = 0; i < 64; i++) { /* send the packets */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1566
			e1000_create_lbtest_frame(tx_ring->buffer_info[k].skb,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1567
						  1024);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1568
			dma_sync_single_for_device(&pdev->dev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1569
					tx_ring->buffer_info[k].dma,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1570
					tx_ring->buffer_info[k].length,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1571
					DMA_TO_DEVICE);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1572
			k++;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1573
			if (k == tx_ring->count)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1574
				k = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1575
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1576
		ew32(TDT(0), k);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1577
		e1e_flush();
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1578
		msleep(200);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1579
		time = jiffies; /* set the start time for the receive */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1580
		good_cnt = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1581
		do { /* receive the sent packets */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1582
			dma_sync_single_for_cpu(&pdev->dev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1583
					rx_ring->buffer_info[l].dma, 2048,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1584
					DMA_FROM_DEVICE);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1585
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1586
			ret_val = e1000_check_lbtest_frame(
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1587
					rx_ring->buffer_info[l].skb, 1024);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1588
			if (!ret_val)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1589
				good_cnt++;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1590
			l++;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1591
			if (l == rx_ring->count)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1592
				l = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1593
			/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1594
			 * time + 20 msecs (200 msecs on 2.4) is more than
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1595
			 * enough time to complete the receives, if it's
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1596
			 * exceeded, break and error off
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1597
			 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1598
		} while ((good_cnt < 64) && !time_after(jiffies, time + 20));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1599
		if (good_cnt != 64) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1600
			ret_val = 13; /* ret_val is the same as mis-compare */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1601
			break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1602
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1603
		if (jiffies >= (time + 20)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1604
			ret_val = 14; /* error code for time out error */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1605
			break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1606
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1607
	} /* end loop count loop */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1608
	return ret_val;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1609
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1610
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1611
static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1612
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1613
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1614
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1615
	/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1616
	 * PHY loopback cannot be performed if SoL/IDER
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1617
	 * sessions are active
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1618
	 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1619
	if (hw->phy.ops.check_reset_block &&
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1620
	    hw->phy.ops.check_reset_block(hw)) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1621
		e_err("Cannot do PHY loopback test when SoL/IDER is active.\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1622
		*data = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1623
		goto out;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1624
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1625
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1626
	*data = e1000_setup_desc_rings(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1627
	if (*data)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1628
		goto out;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1629
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1630
	*data = e1000_setup_loopback_test(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1631
	if (*data)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1632
		goto err_loopback;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1633
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1634
	*data = e1000_run_loopback_test(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1635
	e1000_loopback_cleanup(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1636
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1637
err_loopback:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1638
	e1000_free_desc_rings(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1639
out:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1640
	return *data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1641
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1642
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1643
static int e1000_link_test(struct e1000_adapter *adapter, u64 *data)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1644
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1645
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1646
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1647
	*data = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1648
	if (hw->phy.media_type == e1000_media_type_internal_serdes) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1649
		int i = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1650
		hw->mac.serdes_has_link = false;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1651
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1652
		/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1653
		 * On some blade server designs, link establishment
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1654
		 * could take as long as 2-3 minutes
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1655
		 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1656
		do {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1657
			hw->mac.ops.check_for_link(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1658
			if (hw->mac.serdes_has_link)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1659
				return *data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1660
			msleep(20);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1661
		} while (i++ < 3750);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1662
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1663
		*data = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1664
	} else {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1665
		hw->mac.ops.check_for_link(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1666
		if (hw->mac.autoneg)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1667
			/*
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1668
			 * On some Phy/switch combinations, link establishment
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1669
			 * can take a few seconds more than expected.
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1670
			 */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1671
			msleep(5000);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1672
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1673
		if (!(er32(STATUS) & E1000_STATUS_LU))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1674
			*data = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1675
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1676
	return *data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1677
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1678
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1679
static int e1000e_get_sset_count(struct net_device *netdev, int sset)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1680
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1681
	switch (sset) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1682
	case ETH_SS_TEST:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1683
		return E1000_TEST_LEN;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1684
	case ETH_SS_STATS:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1685
		return E1000_STATS_LEN;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1686
	default:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1687
		return -EOPNOTSUPP;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1688
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1689
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1690
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1691
static void e1000_diag_test(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1692
			    struct ethtool_test *eth_test, u64 *data)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1693
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1694
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1695
	u16 autoneg_advertised;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1696
	u8 forced_speed_duplex;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1697
	u8 autoneg;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1698
	bool if_running = netif_running(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1699
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1700
	set_bit(__E1000_TESTING, &adapter->state);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1701
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1702
	if (!if_running) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1703
		/* Get control of and reset hardware */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1704
		if (adapter->flags & FLAG_HAS_AMT)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1705
			e1000e_get_hw_control(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1706
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1707
		e1000e_power_up_phy(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1708
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1709
		adapter->hw.phy.autoneg_wait_to_complete = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1710
		e1000e_reset(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1711
		adapter->hw.phy.autoneg_wait_to_complete = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1712
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1713
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1714
	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1715
		/* Offline tests */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1716
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1717
		/* save speed, duplex, autoneg settings */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1718
		autoneg_advertised = adapter->hw.phy.autoneg_advertised;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1719
		forced_speed_duplex = adapter->hw.mac.forced_speed_duplex;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1720
		autoneg = adapter->hw.mac.autoneg;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1721
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1722
		e_info("offline testing starting\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1723
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1724
		if (if_running)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1725
			/* indicate we're in test mode */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1726
			dev_close(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1727
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1728
		if (e1000_reg_test(adapter, &data[0]))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1729
			eth_test->flags |= ETH_TEST_FL_FAILED;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1730
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1731
		e1000e_reset(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1732
		if (e1000_eeprom_test(adapter, &data[1]))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1733
			eth_test->flags |= ETH_TEST_FL_FAILED;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1734
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1735
		e1000e_reset(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1736
		if (e1000_intr_test(adapter, &data[2]))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1737
			eth_test->flags |= ETH_TEST_FL_FAILED;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1738
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1739
		e1000e_reset(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1740
		if (e1000_loopback_test(adapter, &data[3]))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1741
			eth_test->flags |= ETH_TEST_FL_FAILED;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1742
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1743
		/* force this routine to wait until autoneg complete/timeout */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1744
		adapter->hw.phy.autoneg_wait_to_complete = 1;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1745
		e1000e_reset(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1746
		adapter->hw.phy.autoneg_wait_to_complete = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1747
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1748
		if (e1000_link_test(adapter, &data[4]))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1749
			eth_test->flags |= ETH_TEST_FL_FAILED;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1750
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1751
		/* restore speed, duplex, autoneg settings */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1752
		adapter->hw.phy.autoneg_advertised = autoneg_advertised;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1753
		adapter->hw.mac.forced_speed_duplex = forced_speed_duplex;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1754
		adapter->hw.mac.autoneg = autoneg;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1755
		e1000e_reset(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1756
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1757
		clear_bit(__E1000_TESTING, &adapter->state);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1758
		if (if_running)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1759
			dev_open(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1760
	} else {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1761
		/* Online tests */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1762
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1763
		e_info("online testing starting\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1764
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1765
		/* register, eeprom, intr and loopback tests not run online */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1766
		data[0] = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1767
		data[1] = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1768
		data[2] = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1769
		data[3] = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1770
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1771
		if (e1000_link_test(adapter, &data[4]))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1772
			eth_test->flags |= ETH_TEST_FL_FAILED;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1773
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1774
		clear_bit(__E1000_TESTING, &adapter->state);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1775
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1776
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1777
	if (!if_running) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1778
		e1000e_reset(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1779
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1780
		if (adapter->flags & FLAG_HAS_AMT)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1781
			e1000e_release_hw_control(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1782
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1783
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1784
	msleep_interruptible(4 * 1000);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1785
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1786
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1787
static void e1000_get_wol(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1788
			  struct ethtool_wolinfo *wol)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1789
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1790
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1791
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1792
	wol->supported = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1793
	wol->wolopts = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1794
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1795
	if (!(adapter->flags & FLAG_HAS_WOL) ||
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1796
	    !device_can_wakeup(&adapter->pdev->dev))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1797
		return;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1798
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1799
	wol->supported = WAKE_UCAST | WAKE_MCAST |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1800
	    WAKE_BCAST | WAKE_MAGIC | WAKE_PHY;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1801
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1802
	/* apply any specific unsupported masks here */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1803
	if (adapter->flags & FLAG_NO_WAKE_UCAST) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1804
		wol->supported &= ~WAKE_UCAST;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1805
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1806
		if (adapter->wol & E1000_WUFC_EX)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1807
			e_err("Interface does not support directed (unicast) frame wake-up packets\n");
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1808
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1809
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1810
	if (adapter->wol & E1000_WUFC_EX)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1811
		wol->wolopts |= WAKE_UCAST;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1812
	if (adapter->wol & E1000_WUFC_MC)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1813
		wol->wolopts |= WAKE_MCAST;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1814
	if (adapter->wol & E1000_WUFC_BC)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1815
		wol->wolopts |= WAKE_BCAST;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1816
	if (adapter->wol & E1000_WUFC_MAG)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1817
		wol->wolopts |= WAKE_MAGIC;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1818
	if (adapter->wol & E1000_WUFC_LNKC)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1819
		wol->wolopts |= WAKE_PHY;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1820
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1821
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1822
static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1823
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1824
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1825
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1826
	if (!(adapter->flags & FLAG_HAS_WOL) ||
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1827
	    !device_can_wakeup(&adapter->pdev->dev) ||
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1828
	    (wol->wolopts & ~(WAKE_UCAST | WAKE_MCAST | WAKE_BCAST |
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1829
			      WAKE_MAGIC | WAKE_PHY)))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1830
		return -EOPNOTSUPP;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1831
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1832
	/* these settings will always override what we currently have */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1833
	adapter->wol = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1834
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1835
	if (wol->wolopts & WAKE_UCAST)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1836
		adapter->wol |= E1000_WUFC_EX;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1837
	if (wol->wolopts & WAKE_MCAST)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1838
		adapter->wol |= E1000_WUFC_MC;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1839
	if (wol->wolopts & WAKE_BCAST)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1840
		adapter->wol |= E1000_WUFC_BC;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1841
	if (wol->wolopts & WAKE_MAGIC)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1842
		adapter->wol |= E1000_WUFC_MAG;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1843
	if (wol->wolopts & WAKE_PHY)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1844
		adapter->wol |= E1000_WUFC_LNKC;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1845
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1846
	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1847
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1848
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1849
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1850
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1851
static int e1000_set_phys_id(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1852
			     enum ethtool_phys_id_state state)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1853
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1854
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1855
	struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1856
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1857
	switch (state) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1858
	case ETHTOOL_ID_ACTIVE:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1859
		if (!hw->mac.ops.blink_led)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1860
			return 2;	/* cycle on/off twice per second */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1861
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1862
		hw->mac.ops.blink_led(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1863
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1864
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1865
	case ETHTOOL_ID_INACTIVE:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1866
		if (hw->phy.type == e1000_phy_ife)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1867
			e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1868
		hw->mac.ops.led_off(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1869
		hw->mac.ops.cleanup_led(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1870
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1871
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1872
	case ETHTOOL_ID_ON:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1873
		hw->mac.ops.led_on(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1874
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1875
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1876
	case ETHTOOL_ID_OFF:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1877
		hw->mac.ops.led_off(hw);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1878
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1879
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1880
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1881
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1882
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1883
static int e1000_get_coalesce(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1884
			      struct ethtool_coalesce *ec)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1885
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1886
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1887
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1888
	if (adapter->itr_setting <= 4)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1889
		ec->rx_coalesce_usecs = adapter->itr_setting;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1890
	else
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1891
		ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1892
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1893
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1894
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1895
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1896
static int e1000_set_coalesce(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1897
			      struct ethtool_coalesce *ec)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1898
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1899
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1900
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1901
	if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) ||
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1902
	    ((ec->rx_coalesce_usecs > 4) &&
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1903
	     (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) ||
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1904
	    (ec->rx_coalesce_usecs == 2))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1905
		return -EINVAL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1906
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1907
	if (ec->rx_coalesce_usecs == 4) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1908
		adapter->itr = adapter->itr_setting = 4;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1909
	} else if (ec->rx_coalesce_usecs <= 3) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1910
		adapter->itr = 20000;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1911
		adapter->itr_setting = ec->rx_coalesce_usecs;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1912
	} else {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1913
		adapter->itr = (1000000 / ec->rx_coalesce_usecs);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1914
		adapter->itr_setting = adapter->itr & ~3;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1915
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1916
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1917
	if (adapter->itr_setting != 0)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1918
		e1000e_write_itr(adapter, adapter->itr);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1919
	else
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1920
		e1000e_write_itr(adapter, 0);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1921
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1922
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1923
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1924
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1925
static int e1000_nway_reset(struct net_device *netdev)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1926
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1927
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1928
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1929
	if (!netif_running(netdev))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1930
		return -EAGAIN;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1931
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1932
	if (!adapter->hw.mac.autoneg)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1933
		return -EINVAL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1934
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1935
	e1000e_reinit_locked(adapter);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1936
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1937
	return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1938
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1939
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1940
static void e1000_get_ethtool_stats(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1941
				    struct ethtool_stats *stats,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1942
				    u64 *data)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1943
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1944
	struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1945
	struct rtnl_link_stats64 net_stats;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1946
	int i;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1947
	char *p = NULL;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1948
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1949
	e1000e_get_stats64(netdev, &net_stats);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1950
	for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1951
		switch (e1000_gstrings_stats[i].type) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1952
		case NETDEV_STATS:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1953
			p = (char *) &net_stats +
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1954
					e1000_gstrings_stats[i].stat_offset;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1955
			break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1956
		case E1000_STATS:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1957
			p = (char *) adapter +
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1958
					e1000_gstrings_stats[i].stat_offset;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1959
			break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1960
		default:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1961
			data[i] = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1962
			continue;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1963
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1964
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1965
		data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1966
			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1967
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1968
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1969
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1970
static void e1000_get_strings(struct net_device *netdev, u32 stringset,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1971
			      u8 *data)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1972
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1973
	u8 *p = data;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1974
	int i;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1975
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1976
	switch (stringset) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1977
	case ETH_SS_TEST:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1978
		memcpy(data, e1000_gstrings_test, sizeof(e1000_gstrings_test));
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1979
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1980
	case ETH_SS_STATS:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1981
		for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1982
			memcpy(p, e1000_gstrings_stats[i].stat_string,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1983
			       ETH_GSTRING_LEN);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1984
			p += ETH_GSTRING_LEN;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1985
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1986
		break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1987
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1988
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1989
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1990
static int e1000_get_rxnfc(struct net_device *netdev,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1991
			   struct ethtool_rxnfc *info, u32 *rule_locs)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1992
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1993
	info->data = 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1994
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1995
	switch (info->cmd) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1996
	case ETHTOOL_GRXFH: {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1997
		struct e1000_adapter *adapter = netdev_priv(netdev);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1998
		struct e1000_hw *hw = &adapter->hw;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1999
		u32 mrqc = er32(MRQC);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2000
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2001
		if (!(mrqc & E1000_MRQC_RSS_FIELD_MASK))
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2002
			return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2003
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2004
		switch (info->flow_type) {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2005
		case TCP_V4_FLOW:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2006
			if (mrqc & E1000_MRQC_RSS_FIELD_IPV4_TCP)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2007
				info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2008
			/* fall through */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2009
		case UDP_V4_FLOW:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2010
		case SCTP_V4_FLOW:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2011
		case AH_ESP_V4_FLOW:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2012
		case IPV4_FLOW:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2013
			if (mrqc & E1000_MRQC_RSS_FIELD_IPV4)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2014
				info->data |= RXH_IP_SRC | RXH_IP_DST;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2015
			break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2016
		case TCP_V6_FLOW:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2017
			if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_TCP)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2018
				info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2019
			/* fall through */
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2020
		case UDP_V6_FLOW:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2021
		case SCTP_V6_FLOW:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2022
		case AH_ESP_V6_FLOW:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2023
		case IPV6_FLOW:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2024
			if (mrqc & E1000_MRQC_RSS_FIELD_IPV6)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2025
				info->data |= RXH_IP_SRC | RXH_IP_DST;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2026
			break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2027
		default:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2028
			break;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2029
		}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2030
		return 0;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2031
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2032
	default:
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2033
		return -EOPNOTSUPP;
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2034
	}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2035
}
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2036
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2037
static const struct ethtool_ops e1000_ethtool_ops = {
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2038
	.get_settings		= e1000_get_settings,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2039
	.set_settings		= e1000_set_settings,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2040
	.get_drvinfo		= e1000_get_drvinfo,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2041
	.get_regs_len		= e1000_get_regs_len,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2042
	.get_regs		= e1000_get_regs,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2043
	.get_wol		= e1000_get_wol,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2044
	.set_wol		= e1000_set_wol,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2045
	.get_msglevel		= e1000_get_msglevel,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2046
	.set_msglevel		= e1000_set_msglevel,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2047
	.nway_reset		= e1000_nway_reset,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2048
	.get_link		= ethtool_op_get_link,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2049
	.get_eeprom_len		= e1000_get_eeprom_len,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2050
	.get_eeprom		= e1000_get_eeprom,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2051
	.set_eeprom		= e1000_set_eeprom,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2052
	.get_ringparam		= e1000_get_ringparam,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2053
	.set_ringparam		= e1000_set_ringparam,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2054
	.get_pauseparam		= e1000_get_pauseparam,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2055
	.set_pauseparam		= e1000_set_pauseparam,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2056
	.self_test		= e1000_diag_test,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2057
	.get_strings		= e1000_get_strings,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2058
	.set_phys_id		= e1000_set_phys_id,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2059
	.get_ethtool_stats	= e1000_get_ethtool_stats,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2060
	.get_sset_count		= e1000e_get_sset_count,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2061
	.get_coalesce		= e1000_get_coalesce,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2062
	.set_coalesce		= e1000_set_coalesce,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2063
	.get_rxnfc		= e1000_get_rxnfc,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2064
	.get_ts_info		= ethtool_op_get_ts_info,
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2065
};
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2066
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2067
void e1000e_set_ethtool_ops(struct net_device *netdev)
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2068
{
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2069
	SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops);
2fa43746d972 Added e1000e driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2070
}