devices/e1000/e1000_main-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 2545 80177f7aa836
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.
2545
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     1
/*******************************************************************************
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     2
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     3
  Intel PRO/1000 Linux driver
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     4
  Copyright(c) 1999 - 2006 Intel Corporation.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     5
80177f7aa836 Added e1000 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
80177f7aa836 Added e1000 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,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     8
  version 2, as published by the Free Software Foundation.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     9
80177f7aa836 Added e1000 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
80177f7aa836 Added e1000 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
80177f7aa836 Added e1000 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
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    13
  more details.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    14
80177f7aa836 Added e1000 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
80177f7aa836 Added e1000 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.,
80177f7aa836 Added e1000 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.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    18
80177f7aa836 Added e1000 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
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    20
  the file called "COPYING".
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    21
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    22
  Contact Information:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    23
  Linux NICS <linux.nics@intel.com>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    24
  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
80177f7aa836 Added e1000 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
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    26
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    27
*******************************************************************************/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    28
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    29
#include "e1000.h"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    30
#include <net/ip6_checksum.h>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    31
#include <linux/io.h>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    32
#include <linux/prefetch.h>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    33
#include <linux/bitops.h>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    34
#include <linux/if_vlan.h>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    35
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    36
char e1000_driver_name[] = "e1000";
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    37
static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    38
#define DRV_VERSION "7.3.21-k8-NAPI"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    39
const char e1000_driver_version[] = DRV_VERSION;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    40
static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    41
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    42
/* e1000_pci_tbl - PCI Device ID Table
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    43
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    44
 * Last entry must be all 0s
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    45
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    46
 * Macro expands to...
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    47
 *   {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    48
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    49
static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    50
	INTEL_E1000_ETHERNET_DEVICE(0x1000),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    51
	INTEL_E1000_ETHERNET_DEVICE(0x1001),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    52
	INTEL_E1000_ETHERNET_DEVICE(0x1004),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    53
	INTEL_E1000_ETHERNET_DEVICE(0x1008),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    54
	INTEL_E1000_ETHERNET_DEVICE(0x1009),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    55
	INTEL_E1000_ETHERNET_DEVICE(0x100C),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    56
	INTEL_E1000_ETHERNET_DEVICE(0x100D),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    57
	INTEL_E1000_ETHERNET_DEVICE(0x100E),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    58
	INTEL_E1000_ETHERNET_DEVICE(0x100F),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    59
	INTEL_E1000_ETHERNET_DEVICE(0x1010),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    60
	INTEL_E1000_ETHERNET_DEVICE(0x1011),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    61
	INTEL_E1000_ETHERNET_DEVICE(0x1012),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    62
	INTEL_E1000_ETHERNET_DEVICE(0x1013),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    63
	INTEL_E1000_ETHERNET_DEVICE(0x1014),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    64
	INTEL_E1000_ETHERNET_DEVICE(0x1015),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    65
	INTEL_E1000_ETHERNET_DEVICE(0x1016),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    66
	INTEL_E1000_ETHERNET_DEVICE(0x1017),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    67
	INTEL_E1000_ETHERNET_DEVICE(0x1018),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    68
	INTEL_E1000_ETHERNET_DEVICE(0x1019),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    69
	INTEL_E1000_ETHERNET_DEVICE(0x101A),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    70
	INTEL_E1000_ETHERNET_DEVICE(0x101D),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    71
	INTEL_E1000_ETHERNET_DEVICE(0x101E),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    72
	INTEL_E1000_ETHERNET_DEVICE(0x1026),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    73
	INTEL_E1000_ETHERNET_DEVICE(0x1027),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    74
	INTEL_E1000_ETHERNET_DEVICE(0x1028),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    75
	INTEL_E1000_ETHERNET_DEVICE(0x1075),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    76
	INTEL_E1000_ETHERNET_DEVICE(0x1076),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    77
	INTEL_E1000_ETHERNET_DEVICE(0x1077),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    78
	INTEL_E1000_ETHERNET_DEVICE(0x1078),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    79
	INTEL_E1000_ETHERNET_DEVICE(0x1079),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    80
	INTEL_E1000_ETHERNET_DEVICE(0x107A),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    81
	INTEL_E1000_ETHERNET_DEVICE(0x107B),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    82
	INTEL_E1000_ETHERNET_DEVICE(0x107C),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    83
	INTEL_E1000_ETHERNET_DEVICE(0x108A),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    84
	INTEL_E1000_ETHERNET_DEVICE(0x1099),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    85
	INTEL_E1000_ETHERNET_DEVICE(0x10B5),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    86
	INTEL_E1000_ETHERNET_DEVICE(0x2E6E),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    87
	/* required last entry */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    88
	{0,}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    89
};
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    90
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    91
MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    92
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    93
int e1000_up(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    94
void e1000_down(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    95
void e1000_reinit_locked(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    96
void e1000_reset(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    97
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    98
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    99
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   100
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   101
static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   102
                             struct e1000_tx_ring *txdr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   103
static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   104
                             struct e1000_rx_ring *rxdr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   105
static void e1000_free_tx_resources(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   106
                             struct e1000_tx_ring *tx_ring);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   107
static void e1000_free_rx_resources(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   108
                             struct e1000_rx_ring *rx_ring);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   109
void e1000_update_stats(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   110
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   111
static int e1000_init_module(void);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   112
static void e1000_exit_module(void);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   113
static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   114
static void __devexit e1000_remove(struct pci_dev *pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   115
static int e1000_alloc_queues(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   116
static int e1000_sw_init(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   117
static int e1000_open(struct net_device *netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   118
static int e1000_close(struct net_device *netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   119
static void e1000_configure_tx(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   120
static void e1000_configure_rx(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   121
static void e1000_setup_rctl(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   122
static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   123
static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   124
static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   125
                                struct e1000_tx_ring *tx_ring);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   126
static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   127
                                struct e1000_rx_ring *rx_ring);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   128
static void e1000_set_rx_mode(struct net_device *netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   129
static void e1000_update_phy_info_task(struct work_struct *work);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   130
static void e1000_watchdog(struct work_struct *work);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   131
static void e1000_82547_tx_fifo_stall_task(struct work_struct *work);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   132
static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   133
				    struct net_device *netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   134
static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   135
static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   136
static int e1000_set_mac(struct net_device *netdev, void *p);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   137
static irqreturn_t e1000_intr(int irq, void *data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   138
static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   139
			       struct e1000_tx_ring *tx_ring);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   140
static int e1000_clean(struct napi_struct *napi, int budget);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   141
static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   142
			       struct e1000_rx_ring *rx_ring,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   143
			       int *work_done, int work_to_do);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   144
static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   145
				     struct e1000_rx_ring *rx_ring,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   146
				     int *work_done, int work_to_do);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   147
static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   148
				   struct e1000_rx_ring *rx_ring,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   149
				   int cleaned_count);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   150
static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   151
					 struct e1000_rx_ring *rx_ring,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   152
					 int cleaned_count);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   153
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   154
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   155
			   int cmd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   156
static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   157
static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   158
static void e1000_tx_timeout(struct net_device *dev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   159
static void e1000_reset_task(struct work_struct *work);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   160
static void e1000_smartspeed(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   161
static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   162
                                       struct sk_buff *skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   163
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   164
static bool e1000_vlan_used(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   165
static void e1000_vlan_mode(struct net_device *netdev,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   166
			    netdev_features_t features);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   167
static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   168
				     bool filter_on);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   169
static int e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   170
static int e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   171
static void e1000_restore_vlan(struct e1000_adapter *adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   172
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   173
#ifdef CONFIG_PM
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   174
static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   175
static int e1000_resume(struct pci_dev *pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   176
#endif
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   177
static void e1000_shutdown(struct pci_dev *pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   178
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   179
#ifdef CONFIG_NET_POLL_CONTROLLER
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   180
/* for netdump / net console */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   181
static void e1000_netpoll (struct net_device *netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   182
#endif
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   183
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   184
#define COPYBREAK_DEFAULT 256
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   185
static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   186
module_param(copybreak, uint, 0644);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   187
MODULE_PARM_DESC(copybreak,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   188
	"Maximum size of packet that is copied to a new buffer on receive");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   189
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   190
static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   191
                     pci_channel_state_t state);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   192
static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   193
static void e1000_io_resume(struct pci_dev *pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   194
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   195
static struct pci_error_handlers e1000_err_handler = {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   196
	.error_detected = e1000_io_error_detected,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   197
	.slot_reset = e1000_io_slot_reset,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   198
	.resume = e1000_io_resume,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   199
};
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   200
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   201
static struct pci_driver e1000_driver = {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   202
	.name     = e1000_driver_name,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   203
	.id_table = e1000_pci_tbl,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   204
	.probe    = e1000_probe,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   205
	.remove   = __devexit_p(e1000_remove),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   206
#ifdef CONFIG_PM
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   207
	/* Power Management Hooks */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   208
	.suspend  = e1000_suspend,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   209
	.resume   = e1000_resume,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   210
#endif
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   211
	.shutdown = e1000_shutdown,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   212
	.err_handler = &e1000_err_handler
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   213
};
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   214
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   215
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   216
MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   217
MODULE_LICENSE("GPL");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   218
MODULE_VERSION(DRV_VERSION);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   219
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   220
#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   221
static int debug = -1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   222
module_param(debug, int, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   223
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   224
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   225
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   226
 * e1000_get_hw_dev - return device
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   227
 * used by hardware layer to print debugging information
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   228
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   229
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   230
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   231
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   232
	struct e1000_adapter *adapter = hw->back;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   233
	return adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   234
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   235
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   236
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   237
 * e1000_init_module - Driver Registration Routine
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   238
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   239
 * e1000_init_module is the first routine called when the driver is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   240
 * loaded. All it does is register with the PCI subsystem.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   241
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   242
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   243
static int __init e1000_init_module(void)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   244
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   245
	int ret;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   246
	pr_info("%s - version %s\n", e1000_driver_string, e1000_driver_version);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   247
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   248
	pr_info("%s\n", e1000_copyright);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   249
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   250
	ret = pci_register_driver(&e1000_driver);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   251
	if (copybreak != COPYBREAK_DEFAULT) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   252
		if (copybreak == 0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   253
			pr_info("copybreak disabled\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   254
		else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   255
			pr_info("copybreak enabled for "
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   256
				   "packets <= %u bytes\n", copybreak);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   257
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   258
	return ret;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   259
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   260
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   261
module_init(e1000_init_module);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   262
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   263
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   264
 * e1000_exit_module - Driver Exit Cleanup Routine
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   265
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   266
 * e1000_exit_module is called just before the driver is removed
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   267
 * from memory.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   268
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   269
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   270
static void __exit e1000_exit_module(void)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   271
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   272
	pci_unregister_driver(&e1000_driver);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   273
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   274
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   275
module_exit(e1000_exit_module);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   276
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   277
static int e1000_request_irq(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   278
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   279
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   280
	irq_handler_t handler = e1000_intr;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   281
	int irq_flags = IRQF_SHARED;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   282
	int err;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   283
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   284
	err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   285
	                  netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   286
	if (err) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   287
		e_err(probe, "Unable to allocate interrupt Error: %d\n", err);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   288
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   289
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   290
	return err;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   291
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   292
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   293
static void e1000_free_irq(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   294
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   295
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   296
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   297
	free_irq(adapter->pdev->irq, netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   298
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   299
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   300
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   301
 * e1000_irq_disable - Mask off interrupt generation on the NIC
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   302
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   303
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   304
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   305
static void e1000_irq_disable(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   306
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   307
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   308
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   309
	ew32(IMC, ~0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   310
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   311
	synchronize_irq(adapter->pdev->irq);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   312
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   313
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   314
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   315
 * e1000_irq_enable - Enable default interrupt generation settings
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   316
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   317
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   318
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   319
static void e1000_irq_enable(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   320
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   321
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   322
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   323
	ew32(IMS, IMS_ENABLE_MASK);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   324
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   325
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   326
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   327
static void e1000_update_mng_vlan(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   328
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   329
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   330
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   331
	u16 vid = hw->mng_cookie.vlan_id;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   332
	u16 old_vid = adapter->mng_vlan_id;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   333
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   334
	if (!e1000_vlan_used(adapter))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   335
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   336
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   337
	if (!test_bit(vid, adapter->active_vlans)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   338
		if (hw->mng_cookie.status &
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   339
		    E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   340
			e1000_vlan_rx_add_vid(netdev, vid);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   341
			adapter->mng_vlan_id = vid;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   342
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   343
			adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   344
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   345
		if ((old_vid != (u16)E1000_MNG_VLAN_NONE) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   346
		    (vid != old_vid) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   347
		    !test_bit(old_vid, adapter->active_vlans))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   348
			e1000_vlan_rx_kill_vid(netdev, old_vid);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   349
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   350
		adapter->mng_vlan_id = vid;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   351
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   352
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   353
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   354
static void e1000_init_manageability(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   355
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   356
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   357
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   358
	if (adapter->en_mng_pt) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   359
		u32 manc = er32(MANC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   360
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   361
		/* disable hardware interception of ARP */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   362
		manc &= ~(E1000_MANC_ARP_EN);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   363
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   364
		ew32(MANC, manc);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   365
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   366
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   367
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   368
static void e1000_release_manageability(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   369
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   370
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   371
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   372
	if (adapter->en_mng_pt) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   373
		u32 manc = er32(MANC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   374
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   375
		/* re-enable hardware interception of ARP */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   376
		manc |= E1000_MANC_ARP_EN;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   377
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   378
		ew32(MANC, manc);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   379
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   380
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   381
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   382
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   383
 * e1000_configure - configure the hardware for RX and TX
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   384
 * @adapter = private board structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   385
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   386
static void e1000_configure(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   387
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   388
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   389
	int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   390
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   391
	e1000_set_rx_mode(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   392
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   393
	e1000_restore_vlan(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   394
	e1000_init_manageability(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   395
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   396
	e1000_configure_tx(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   397
	e1000_setup_rctl(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   398
	e1000_configure_rx(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   399
	/* call E1000_DESC_UNUSED which always leaves
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   400
	 * at least 1 descriptor unused to make sure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   401
	 * next_to_use != next_to_clean */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   402
	for (i = 0; i < adapter->num_rx_queues; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   403
		struct e1000_rx_ring *ring = &adapter->rx_ring[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   404
		adapter->alloc_rx_buf(adapter, ring,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   405
		                      E1000_DESC_UNUSED(ring));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   406
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   407
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   408
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   409
int e1000_up(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   410
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   411
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   412
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   413
	/* hardware has been reset, we need to reload some things */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   414
	e1000_configure(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   415
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   416
	clear_bit(__E1000_DOWN, &adapter->flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   417
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   418
	napi_enable(&adapter->napi);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   419
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   420
	e1000_irq_enable(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   421
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   422
	netif_wake_queue(adapter->netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   423
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   424
	/* fire a link change interrupt to start the watchdog */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   425
	ew32(ICS, E1000_ICS_LSC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   426
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   427
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   428
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   429
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   430
 * e1000_power_up_phy - restore link in case the phy was powered down
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   431
 * @adapter: address of board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   432
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   433
 * The phy may be powered down to save power and turn off link when the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   434
 * driver is unloaded and wake on lan is not enabled (among others)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   435
 * *** this routine MUST be followed by a call to e1000_reset ***
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   436
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   437
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   438
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   439
void e1000_power_up_phy(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   440
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   441
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   442
	u16 mii_reg = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   443
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   444
	/* Just clear the power down bit to wake the phy back up */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   445
	if (hw->media_type == e1000_media_type_copper) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   446
		/* according to the manual, the phy will retain its
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   447
		 * settings across a power-down/up cycle */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   448
		e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   449
		mii_reg &= ~MII_CR_POWER_DOWN;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   450
		e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   451
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   452
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   453
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   454
static void e1000_power_down_phy(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   455
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   456
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   457
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   458
	/* Power down the PHY so no link is implied when interface is down *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   459
	 * The PHY cannot be powered down if any of the following is true *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   460
	 * (a) WoL is enabled
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   461
	 * (b) AMT is active
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   462
	 * (c) SoL/IDER session is active */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   463
	if (!adapter->wol && hw->mac_type >= e1000_82540 &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   464
	   hw->media_type == e1000_media_type_copper) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   465
		u16 mii_reg = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   466
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   467
		switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   468
		case e1000_82540:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   469
		case e1000_82545:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   470
		case e1000_82545_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   471
		case e1000_82546:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   472
		case e1000_ce4100:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   473
		case e1000_82546_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   474
		case e1000_82541:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   475
		case e1000_82541_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   476
		case e1000_82547:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   477
		case e1000_82547_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   478
			if (er32(MANC) & E1000_MANC_SMBUS_EN)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   479
				goto out;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   480
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   481
		default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   482
			goto out;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   483
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   484
		e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   485
		mii_reg |= MII_CR_POWER_DOWN;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   486
		e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   487
		msleep(1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   488
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   489
out:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   490
	return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   491
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   492
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   493
static void e1000_down_and_stop(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   494
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   495
	set_bit(__E1000_DOWN, &adapter->flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   496
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   497
	/* Only kill reset task if adapter is not resetting */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   498
	if (!test_bit(__E1000_RESETTING, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   499
		cancel_work_sync(&adapter->reset_task);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   500
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   501
	cancel_delayed_work_sync(&adapter->watchdog_task);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   502
	cancel_delayed_work_sync(&adapter->phy_info_task);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   503
	cancel_delayed_work_sync(&adapter->fifo_stall_task);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   504
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   505
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   506
void e1000_down(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   507
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   508
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   509
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   510
	u32 rctl, tctl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   511
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   512
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   513
	/* disable receives in the hardware */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   514
	rctl = er32(RCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   515
	ew32(RCTL, rctl & ~E1000_RCTL_EN);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   516
	/* flush and sleep below */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   517
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   518
	netif_tx_disable(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   519
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   520
	/* disable transmits in the hardware */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   521
	tctl = er32(TCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   522
	tctl &= ~E1000_TCTL_EN;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   523
	ew32(TCTL, tctl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   524
	/* flush both disables and wait for them to finish */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   525
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   526
	msleep(10);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   527
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   528
	napi_disable(&adapter->napi);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   529
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   530
	e1000_irq_disable(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   531
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   532
	/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   533
	 * Setting DOWN must be after irq_disable to prevent
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   534
	 * a screaming interrupt.  Setting DOWN also prevents
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   535
	 * tasks from rescheduling.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   536
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   537
	e1000_down_and_stop(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   538
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   539
	adapter->link_speed = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   540
	adapter->link_duplex = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   541
	netif_carrier_off(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   542
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   543
	e1000_reset(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   544
	e1000_clean_all_tx_rings(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   545
	e1000_clean_all_rx_rings(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   546
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   547
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   548
static void e1000_reinit_safe(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   549
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   550
	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   551
		msleep(1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   552
	mutex_lock(&adapter->mutex);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   553
	e1000_down(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   554
	e1000_up(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   555
	mutex_unlock(&adapter->mutex);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   556
	clear_bit(__E1000_RESETTING, &adapter->flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   557
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   558
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   559
void e1000_reinit_locked(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   560
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   561
	/* if rtnl_lock is not held the call path is bogus */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   562
	ASSERT_RTNL();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   563
	WARN_ON(in_interrupt());
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   564
	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   565
		msleep(1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   566
	e1000_down(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   567
	e1000_up(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   568
	clear_bit(__E1000_RESETTING, &adapter->flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   569
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   570
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   571
void e1000_reset(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   572
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   573
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   574
	u32 pba = 0, tx_space, min_tx_space, min_rx_space;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   575
	bool legacy_pba_adjust = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   576
	u16 hwm;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   577
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   578
	/* Repartition Pba for greater than 9k mtu
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   579
	 * To take effect CTRL.RST is required.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   580
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   581
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   582
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   583
	case e1000_82542_rev2_0:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   584
	case e1000_82542_rev2_1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   585
	case e1000_82543:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   586
	case e1000_82544:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   587
	case e1000_82540:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   588
	case e1000_82541:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   589
	case e1000_82541_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   590
		legacy_pba_adjust = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   591
		pba = E1000_PBA_48K;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   592
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   593
	case e1000_82545:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   594
	case e1000_82545_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   595
	case e1000_82546:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   596
	case e1000_ce4100:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   597
	case e1000_82546_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   598
		pba = E1000_PBA_48K;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   599
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   600
	case e1000_82547:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   601
	case e1000_82547_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   602
		legacy_pba_adjust = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   603
		pba = E1000_PBA_30K;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   604
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   605
	case e1000_undefined:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   606
	case e1000_num_macs:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   607
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   608
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   609
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   610
	if (legacy_pba_adjust) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   611
		if (hw->max_frame_size > E1000_RXBUFFER_8192)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   612
			pba -= 8; /* allocate more FIFO for Tx */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   613
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   614
		if (hw->mac_type == e1000_82547) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   615
			adapter->tx_fifo_head = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   616
			adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   617
			adapter->tx_fifo_size =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   618
				(E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   619
			atomic_set(&adapter->tx_fifo_stall, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   620
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   621
	} else if (hw->max_frame_size >  ETH_FRAME_LEN + ETH_FCS_LEN) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   622
		/* adjust PBA for jumbo frames */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   623
		ew32(PBA, pba);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   624
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   625
		/* To maintain wire speed transmits, the Tx FIFO should be
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   626
		 * large enough to accommodate two full transmit packets,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   627
		 * rounded up to the next 1KB and expressed in KB.  Likewise,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   628
		 * the Rx FIFO should be large enough to accommodate at least
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   629
		 * one full receive packet and is similarly rounded up and
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   630
		 * expressed in KB. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   631
		pba = er32(PBA);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   632
		/* upper 16 bits has Tx packet buffer allocation size in KB */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   633
		tx_space = pba >> 16;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   634
		/* lower 16 bits has Rx packet buffer allocation size in KB */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   635
		pba &= 0xffff;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   636
		/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   637
		 * the tx fifo also stores 16 bytes of information about the tx
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   638
		 * but don't include ethernet FCS because hardware appends it
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   639
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   640
		min_tx_space = (hw->max_frame_size +
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   641
		                sizeof(struct e1000_tx_desc) -
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   642
		                ETH_FCS_LEN) * 2;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   643
		min_tx_space = ALIGN(min_tx_space, 1024);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   644
		min_tx_space >>= 10;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   645
		/* software strips receive CRC, so leave room for it */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   646
		min_rx_space = hw->max_frame_size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   647
		min_rx_space = ALIGN(min_rx_space, 1024);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   648
		min_rx_space >>= 10;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   649
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   650
		/* If current Tx allocation is less than the min Tx FIFO size,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   651
		 * and the min Tx FIFO size is less than the current Rx FIFO
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   652
		 * allocation, take space away from current Rx allocation */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   653
		if (tx_space < min_tx_space &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   654
		    ((min_tx_space - tx_space) < pba)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   655
			pba = pba - (min_tx_space - tx_space);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   656
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   657
			/* PCI/PCIx hardware has PBA alignment constraints */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   658
			switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   659
			case e1000_82545 ... e1000_82546_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   660
				pba &= ~(E1000_PBA_8K - 1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   661
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   662
			default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   663
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   664
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   665
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   666
			/* if short on rx space, rx wins and must trump tx
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   667
			 * adjustment or use Early Receive if available */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   668
			if (pba < min_rx_space)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   669
				pba = min_rx_space;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   670
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   671
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   672
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   673
	ew32(PBA, pba);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   674
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   675
	/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   676
	 * flow control settings:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   677
	 * The high water mark must be low enough to fit one full frame
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   678
	 * (or the size used for early receive) above it in the Rx FIFO.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   679
	 * Set it to the lower of:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   680
	 * - 90% of the Rx FIFO size, and
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   681
	 * - the full Rx FIFO size minus the early receive size (for parts
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   682
	 *   with ERT support assuming ERT set to E1000_ERT_2048), or
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   683
	 * - the full Rx FIFO size minus one full frame
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   684
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   685
	hwm = min(((pba << 10) * 9 / 10),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   686
		  ((pba << 10) - hw->max_frame_size));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   687
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   688
	hw->fc_high_water = hwm & 0xFFF8;	/* 8-byte granularity */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   689
	hw->fc_low_water = hw->fc_high_water - 8;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   690
	hw->fc_pause_time = E1000_FC_PAUSE_TIME;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   691
	hw->fc_send_xon = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   692
	hw->fc = hw->original_fc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   693
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   694
	/* Allow time for pending master requests to run */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   695
	e1000_reset_hw(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   696
	if (hw->mac_type >= e1000_82544)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   697
		ew32(WUC, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   698
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   699
	if (e1000_init_hw(hw))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   700
		e_dev_err("Hardware Error\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   701
	e1000_update_mng_vlan(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   702
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   703
	/* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   704
	if (hw->mac_type >= e1000_82544 &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   705
	    hw->autoneg == 1 &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   706
	    hw->autoneg_advertised == ADVERTISE_1000_FULL) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   707
		u32 ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   708
		/* clear phy power management bit if we are in gig only mode,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   709
		 * which if enabled will attempt negotiation to 100Mb, which
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   710
		 * can cause a loss of link at power off or driver unload */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   711
		ctrl &= ~E1000_CTRL_SWDPIN3;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   712
		ew32(CTRL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   713
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   714
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   715
	/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   716
	ew32(VET, ETHERNET_IEEE_VLAN_TYPE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   717
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   718
	e1000_reset_adaptive(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   719
	e1000_phy_get_info(hw, &adapter->phy_info);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   720
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   721
	e1000_release_manageability(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   722
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   723
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   724
/* Dump the eeprom for users having checksum issues */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   725
static void e1000_dump_eeprom(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   726
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   727
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   728
	struct ethtool_eeprom eeprom;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   729
	const struct ethtool_ops *ops = netdev->ethtool_ops;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   730
	u8 *data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   731
	int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   732
	u16 csum_old, csum_new = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   733
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   734
	eeprom.len = ops->get_eeprom_len(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   735
	eeprom.offset = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   736
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   737
	data = kmalloc(eeprom.len, GFP_KERNEL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   738
	if (!data)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   739
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   740
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   741
	ops->get_eeprom(netdev, &eeprom, data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   742
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   743
	csum_old = (data[EEPROM_CHECKSUM_REG * 2]) +
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   744
		   (data[EEPROM_CHECKSUM_REG * 2 + 1] << 8);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   745
	for (i = 0; i < EEPROM_CHECKSUM_REG * 2; i += 2)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   746
		csum_new += data[i] + (data[i + 1] << 8);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   747
	csum_new = EEPROM_SUM - csum_new;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   748
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   749
	pr_err("/*********************/\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   750
	pr_err("Current EEPROM Checksum : 0x%04x\n", csum_old);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   751
	pr_err("Calculated              : 0x%04x\n", csum_new);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   752
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   753
	pr_err("Offset    Values\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   754
	pr_err("========  ======\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   755
	print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, data, 128, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   756
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   757
	pr_err("Include this output when contacting your support provider.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   758
	pr_err("This is not a software error! Something bad happened to\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   759
	pr_err("your hardware or EEPROM image. Ignoring this problem could\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   760
	pr_err("result in further problems, possibly loss of data,\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   761
	pr_err("corruption or system hangs!\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   762
	pr_err("The MAC Address will be reset to 00:00:00:00:00:00,\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   763
	pr_err("which is invalid and requires you to set the proper MAC\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   764
	pr_err("address manually before continuing to enable this network\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   765
	pr_err("device. Please inspect the EEPROM dump and report the\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   766
	pr_err("issue to your hardware vendor or Intel Customer Support.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   767
	pr_err("/*********************/\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   768
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   769
	kfree(data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   770
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   771
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   772
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   773
 * e1000_is_need_ioport - determine if an adapter needs ioport resources or not
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   774
 * @pdev: PCI device information struct
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   775
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   776
 * Return true if an adapter needs ioport resources
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   777
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   778
static int e1000_is_need_ioport(struct pci_dev *pdev)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   779
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   780
	switch (pdev->device) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   781
	case E1000_DEV_ID_82540EM:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   782
	case E1000_DEV_ID_82540EM_LOM:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   783
	case E1000_DEV_ID_82540EP:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   784
	case E1000_DEV_ID_82540EP_LOM:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   785
	case E1000_DEV_ID_82540EP_LP:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   786
	case E1000_DEV_ID_82541EI:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   787
	case E1000_DEV_ID_82541EI_MOBILE:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   788
	case E1000_DEV_ID_82541ER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   789
	case E1000_DEV_ID_82541ER_LOM:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   790
	case E1000_DEV_ID_82541GI:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   791
	case E1000_DEV_ID_82541GI_LF:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   792
	case E1000_DEV_ID_82541GI_MOBILE:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   793
	case E1000_DEV_ID_82544EI_COPPER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   794
	case E1000_DEV_ID_82544EI_FIBER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   795
	case E1000_DEV_ID_82544GC_COPPER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   796
	case E1000_DEV_ID_82544GC_LOM:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   797
	case E1000_DEV_ID_82545EM_COPPER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   798
	case E1000_DEV_ID_82545EM_FIBER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   799
	case E1000_DEV_ID_82546EB_COPPER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   800
	case E1000_DEV_ID_82546EB_FIBER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   801
	case E1000_DEV_ID_82546EB_QUAD_COPPER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   802
		return true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   803
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   804
		return false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   805
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   806
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   807
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   808
static netdev_features_t e1000_fix_features(struct net_device *netdev,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   809
	netdev_features_t features)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   810
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   811
	/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   812
	 * Since there is no support for separate rx/tx vlan accel
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   813
	 * enable/disable make sure tx flag is always in same state as rx.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   814
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   815
	if (features & NETIF_F_HW_VLAN_RX)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   816
		features |= NETIF_F_HW_VLAN_TX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   817
	else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   818
		features &= ~NETIF_F_HW_VLAN_TX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   819
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   820
	return features;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   821
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   822
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   823
static int e1000_set_features(struct net_device *netdev,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   824
	netdev_features_t features)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   825
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   826
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   827
	netdev_features_t changed = features ^ netdev->features;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   828
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   829
	if (changed & NETIF_F_HW_VLAN_RX)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   830
		e1000_vlan_mode(netdev, features);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   831
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   832
	if (!(changed & (NETIF_F_RXCSUM | NETIF_F_RXALL)))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   833
		return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   834
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   835
	netdev->features = features;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   836
	adapter->rx_csum = !!(features & NETIF_F_RXCSUM);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   837
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   838
	if (netif_running(netdev))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   839
		e1000_reinit_locked(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   840
	else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   841
		e1000_reset(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   842
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   843
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   844
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   845
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   846
static const struct net_device_ops e1000_netdev_ops = {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   847
	.ndo_open		= e1000_open,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   848
	.ndo_stop		= e1000_close,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   849
	.ndo_start_xmit		= e1000_xmit_frame,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   850
	.ndo_get_stats		= e1000_get_stats,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   851
	.ndo_set_rx_mode	= e1000_set_rx_mode,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   852
	.ndo_set_mac_address	= e1000_set_mac,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   853
	.ndo_tx_timeout		= e1000_tx_timeout,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   854
	.ndo_change_mtu		= e1000_change_mtu,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   855
	.ndo_do_ioctl		= e1000_ioctl,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   856
	.ndo_validate_addr	= eth_validate_addr,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   857
	.ndo_vlan_rx_add_vid	= e1000_vlan_rx_add_vid,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   858
	.ndo_vlan_rx_kill_vid	= e1000_vlan_rx_kill_vid,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   859
#ifdef CONFIG_NET_POLL_CONTROLLER
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   860
	.ndo_poll_controller	= e1000_netpoll,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   861
#endif
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   862
	.ndo_fix_features	= e1000_fix_features,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   863
	.ndo_set_features	= e1000_set_features,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   864
};
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   865
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   866
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   867
 * e1000_init_hw_struct - initialize members of hw struct
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   868
 * @adapter: board private struct
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   869
 * @hw: structure used by e1000_hw.c
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   870
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   871
 * Factors out initialization of the e1000_hw struct to its own function
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   872
 * that can be called very early at init (just after struct allocation).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   873
 * Fields are initialized based on PCI device information and
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   874
 * OS network device settings (MTU size).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   875
 * Returns negative error codes if MAC type setup fails.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   876
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   877
static int e1000_init_hw_struct(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   878
				struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   879
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   880
	struct pci_dev *pdev = adapter->pdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   881
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   882
	/* PCI config space info */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   883
	hw->vendor_id = pdev->vendor;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   884
	hw->device_id = pdev->device;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   885
	hw->subsystem_vendor_id = pdev->subsystem_vendor;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   886
	hw->subsystem_id = pdev->subsystem_device;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   887
	hw->revision_id = pdev->revision;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   888
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   889
	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   890
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   891
	hw->max_frame_size = adapter->netdev->mtu +
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   892
			     ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   893
	hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   894
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   895
	/* identify the MAC */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   896
	if (e1000_set_mac_type(hw)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   897
		e_err(probe, "Unknown MAC Type\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   898
		return -EIO;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   899
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   900
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   901
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   902
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   903
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   904
	case e1000_82541:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   905
	case e1000_82547:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   906
	case e1000_82541_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   907
	case e1000_82547_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   908
		hw->phy_init_script = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   909
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   910
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   911
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   912
	e1000_set_media_type(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   913
	e1000_get_bus_info(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   914
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   915
	hw->wait_autoneg_complete = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   916
	hw->tbi_compatibility_en = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   917
	hw->adaptive_ifs = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   918
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   919
	/* Copper options */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   920
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   921
	if (hw->media_type == e1000_media_type_copper) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   922
		hw->mdix = AUTO_ALL_MODES;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   923
		hw->disable_polarity_correction = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   924
		hw->master_slave = E1000_MASTER_SLAVE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   925
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   926
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   927
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   928
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   929
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   930
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   931
 * e1000_probe - Device Initialization Routine
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   932
 * @pdev: PCI device information struct
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   933
 * @ent: entry in e1000_pci_tbl
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   934
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   935
 * Returns 0 on success, negative on failure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   936
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   937
 * e1000_probe initializes an adapter identified by a pci_dev structure.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   938
 * The OS initialization, configuring of the adapter private structure,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   939
 * and a hardware reset occur.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   940
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   941
static int __devinit e1000_probe(struct pci_dev *pdev,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   942
				 const struct pci_device_id *ent)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   943
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   944
	struct net_device *netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   945
	struct e1000_adapter *adapter;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   946
	struct e1000_hw *hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   947
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   948
	static int cards_found = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   949
	static int global_quad_port_a = 0; /* global ksp3 port a indication */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   950
	int i, err, pci_using_dac;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   951
	u16 eeprom_data = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   952
	u16 tmp = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   953
	u16 eeprom_apme_mask = E1000_EEPROM_APME;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   954
	int bars, need_ioport;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   955
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   956
	/* do not allocate ioport bars when not needed */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   957
	need_ioport = e1000_is_need_ioport(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   958
	if (need_ioport) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   959
		bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   960
		err = pci_enable_device(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   961
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   962
		bars = pci_select_bars(pdev, IORESOURCE_MEM);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   963
		err = pci_enable_device_mem(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   964
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   965
	if (err)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   966
		return err;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   967
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   968
	err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   969
	if (err)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   970
		goto err_pci_reg;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   971
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   972
	pci_set_master(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   973
	err = pci_save_state(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   974
	if (err)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   975
		goto err_alloc_etherdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   976
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   977
	err = -ENOMEM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   978
	netdev = alloc_etherdev(sizeof(struct e1000_adapter));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   979
	if (!netdev)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   980
		goto err_alloc_etherdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   981
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   982
	SET_NETDEV_DEV(netdev, &pdev->dev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   983
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   984
	pci_set_drvdata(pdev, netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   985
	adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   986
	adapter->netdev = netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   987
	adapter->pdev = pdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   988
	adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   989
	adapter->bars = bars;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   990
	adapter->need_ioport = need_ioport;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   991
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   992
	hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   993
	hw->back = adapter;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   994
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   995
	err = -EIO;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   996
	hw->hw_addr = pci_ioremap_bar(pdev, BAR_0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   997
	if (!hw->hw_addr)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   998
		goto err_ioremap;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   999
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1000
	if (adapter->need_ioport) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1001
		for (i = BAR_1; i <= BAR_5; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1002
			if (pci_resource_len(pdev, i) == 0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1003
				continue;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1004
			if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1005
				hw->io_base = pci_resource_start(pdev, i);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1006
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1007
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1008
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1009
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1010
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1011
	/* make ready for any if (hw->...) below */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1012
	err = e1000_init_hw_struct(adapter, hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1013
	if (err)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1014
		goto err_sw_init;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1015
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1016
	/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1017
	 * there is a workaround being applied below that limits
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1018
	 * 64-bit DMA addresses to 64-bit hardware.  There are some
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1019
	 * 32-bit adapters that Tx hang when given 64-bit DMA addresses
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1020
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1021
	pci_using_dac = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1022
	if ((hw->bus_type == e1000_bus_type_pcix) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1023
	    !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1024
		/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1025
		 * according to DMA-API-HOWTO, coherent calls will always
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1026
		 * succeed if the set call did
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1027
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1028
		dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1029
		pci_using_dac = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1030
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1031
		err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1032
		if (err) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1033
			pr_err("No usable DMA config, aborting\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1034
			goto err_dma;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1035
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1036
		dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1037
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1038
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1039
	netdev->netdev_ops = &e1000_netdev_ops;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1040
	e1000_set_ethtool_ops(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1041
	netdev->watchdog_timeo = 5 * HZ;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1042
	netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1043
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1044
	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1045
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1046
	adapter->bd_number = cards_found;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1047
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1048
	/* setup the private structure */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1049
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1050
	err = e1000_sw_init(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1051
	if (err)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1052
		goto err_sw_init;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1053
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1054
	err = -EIO;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1055
	if (hw->mac_type == e1000_ce4100) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1056
		hw->ce4100_gbe_mdio_base_virt =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1057
					ioremap(pci_resource_start(pdev, BAR_1),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1058
		                                pci_resource_len(pdev, BAR_1));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1059
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1060
		if (!hw->ce4100_gbe_mdio_base_virt)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1061
			goto err_mdio_ioremap;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1062
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1063
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1064
	if (hw->mac_type >= e1000_82543) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1065
		netdev->hw_features = NETIF_F_SG |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1066
				   NETIF_F_HW_CSUM |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1067
				   NETIF_F_HW_VLAN_RX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1068
		netdev->features = NETIF_F_HW_VLAN_TX |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1069
				   NETIF_F_HW_VLAN_FILTER;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1070
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1071
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1072
	if ((hw->mac_type >= e1000_82544) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1073
	   (hw->mac_type != e1000_82547))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1074
		netdev->hw_features |= NETIF_F_TSO;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1075
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1076
	netdev->priv_flags |= IFF_SUPP_NOFCS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1077
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1078
	netdev->features |= netdev->hw_features;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1079
	netdev->hw_features |= (NETIF_F_RXCSUM |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1080
				NETIF_F_RXALL |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1081
				NETIF_F_RXFCS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1082
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1083
	if (pci_using_dac) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1084
		netdev->features |= NETIF_F_HIGHDMA;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1085
		netdev->vlan_features |= NETIF_F_HIGHDMA;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1086
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1087
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1088
	netdev->vlan_features |= (NETIF_F_TSO |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1089
				  NETIF_F_HW_CSUM |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1090
				  NETIF_F_SG);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1091
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1092
	netdev->priv_flags |= IFF_UNICAST_FLT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1093
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1094
	adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1095
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1096
	/* initialize eeprom parameters */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1097
	if (e1000_init_eeprom_params(hw)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1098
		e_err(probe, "EEPROM initialization failed\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1099
		goto err_eeprom;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1100
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1101
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1102
	/* before reading the EEPROM, reset the controller to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1103
	 * put the device in a known good starting state */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1104
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1105
	e1000_reset_hw(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1106
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1107
	/* make sure the EEPROM is good */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1108
	if (e1000_validate_eeprom_checksum(hw) < 0) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1109
		e_err(probe, "The EEPROM Checksum Is Not Valid\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1110
		e1000_dump_eeprom(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1111
		/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1112
		 * set MAC address to all zeroes to invalidate and temporary
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1113
		 * disable this device for the user. This blocks regular
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1114
		 * traffic while still permitting ethtool ioctls from reaching
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1115
		 * the hardware as well as allowing the user to run the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1116
		 * interface after manually setting a hw addr using
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1117
		 * `ip set address`
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1118
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1119
		memset(hw->mac_addr, 0, netdev->addr_len);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1120
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1121
		/* copy the MAC address out of the EEPROM */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1122
		if (e1000_read_mac_addr(hw))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1123
			e_err(probe, "EEPROM Read Error\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1124
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1125
	/* don't block initalization here due to bad MAC address */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1126
	memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1127
	memcpy(netdev->perm_addr, hw->mac_addr, netdev->addr_len);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1128
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1129
	if (!is_valid_ether_addr(netdev->perm_addr))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1130
		e_err(probe, "Invalid MAC Address\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1131
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1132
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1133
	INIT_DELAYED_WORK(&adapter->watchdog_task, e1000_watchdog);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1134
	INIT_DELAYED_WORK(&adapter->fifo_stall_task,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1135
			  e1000_82547_tx_fifo_stall_task);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1136
	INIT_DELAYED_WORK(&adapter->phy_info_task, e1000_update_phy_info_task);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1137
	INIT_WORK(&adapter->reset_task, e1000_reset_task);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1138
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1139
	e1000_check_options(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1140
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1141
	/* Initial Wake on LAN setting
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1142
	 * If APM wake is enabled in the EEPROM,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1143
	 * enable the ACPI Magic Packet filter
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1144
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1145
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1146
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1147
	case e1000_82542_rev2_0:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1148
	case e1000_82542_rev2_1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1149
	case e1000_82543:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1150
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1151
	case e1000_82544:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1152
		e1000_read_eeprom(hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1153
			EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1154
		eeprom_apme_mask = E1000_EEPROM_82544_APM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1155
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1156
	case e1000_82546:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1157
	case e1000_82546_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1158
		if (er32(STATUS) & E1000_STATUS_FUNC_1){
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1159
			e1000_read_eeprom(hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1160
				EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1161
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1162
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1163
		/* Fall Through */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1164
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1165
		e1000_read_eeprom(hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1166
			EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1167
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1168
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1169
	if (eeprom_data & eeprom_apme_mask)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1170
		adapter->eeprom_wol |= E1000_WUFC_MAG;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1171
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1172
	/* now that we have the eeprom settings, apply the special cases
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1173
	 * where the eeprom may be wrong or the board simply won't support
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1174
	 * wake on lan on a particular port */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1175
	switch (pdev->device) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1176
	case E1000_DEV_ID_82546GB_PCIE:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1177
		adapter->eeprom_wol = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1178
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1179
	case E1000_DEV_ID_82546EB_FIBER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1180
	case E1000_DEV_ID_82546GB_FIBER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1181
		/* Wake events only supported on port A for dual fiber
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1182
		 * regardless of eeprom setting */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1183
		if (er32(STATUS) & E1000_STATUS_FUNC_1)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1184
			adapter->eeprom_wol = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1185
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1186
	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1187
		/* if quad port adapter, disable WoL on all but port A */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1188
		if (global_quad_port_a != 0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1189
			adapter->eeprom_wol = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1190
		else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1191
			adapter->quad_port_a = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1192
		/* Reset for multiple quad port adapters */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1193
		if (++global_quad_port_a == 4)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1194
			global_quad_port_a = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1195
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1196
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1197
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1198
	/* initialize the wol settings based on the eeprom settings */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1199
	adapter->wol = adapter->eeprom_wol;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1200
	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1201
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1202
	/* Auto detect PHY address */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1203
	if (hw->mac_type == e1000_ce4100) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1204
		for (i = 0; i < 32; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1205
			hw->phy_addr = i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1206
			e1000_read_phy_reg(hw, PHY_ID2, &tmp);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1207
			if (tmp == 0 || tmp == 0xFF) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1208
				if (i == 31)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1209
					goto err_eeprom;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1210
				continue;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1211
			} else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1212
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1213
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1214
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1215
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1216
	/* reset the hardware with the new settings */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1217
	e1000_reset(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1218
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1219
	strcpy(netdev->name, "eth%d");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1220
	err = register_netdev(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1221
	if (err)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1222
		goto err_register;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1223
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1224
	e1000_vlan_filter_on_off(adapter, false);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1225
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1226
	/* print bus type/speed/width info */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1227
	e_info(probe, "(PCI%s:%dMHz:%d-bit) %pM\n",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1228
	       ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1229
	       ((hw->bus_speed == e1000_bus_speed_133) ? 133 :
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1230
		(hw->bus_speed == e1000_bus_speed_120) ? 120 :
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1231
		(hw->bus_speed == e1000_bus_speed_100) ? 100 :
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1232
		(hw->bus_speed == e1000_bus_speed_66) ? 66 : 33),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1233
	       ((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1234
	       netdev->dev_addr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1235
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1236
	/* carrier off reporting is important to ethtool even BEFORE open */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1237
	netif_carrier_off(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1238
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1239
	e_info(probe, "Intel(R) PRO/1000 Network Connection\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1240
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1241
	cards_found++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1242
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1243
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1244
err_register:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1245
err_eeprom:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1246
	e1000_phy_hw_reset(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1247
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1248
	if (hw->flash_address)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1249
		iounmap(hw->flash_address);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1250
	kfree(adapter->tx_ring);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1251
	kfree(adapter->rx_ring);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1252
err_dma:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1253
err_sw_init:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1254
err_mdio_ioremap:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1255
	iounmap(hw->ce4100_gbe_mdio_base_virt);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1256
	iounmap(hw->hw_addr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1257
err_ioremap:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1258
	free_netdev(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1259
err_alloc_etherdev:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1260
	pci_release_selected_regions(pdev, bars);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1261
err_pci_reg:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1262
	pci_disable_device(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1263
	return err;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1264
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1265
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1266
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1267
 * e1000_remove - Device Removal Routine
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1268
 * @pdev: PCI device information struct
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1269
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1270
 * e1000_remove is called by the PCI subsystem to alert the driver
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1271
 * that it should release a PCI device.  The could be caused by a
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1272
 * Hot-Plug event, or because the driver is going to be removed from
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1273
 * memory.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1274
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1275
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1276
static void __devexit e1000_remove(struct pci_dev *pdev)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1277
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1278
	struct net_device *netdev = pci_get_drvdata(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1279
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1280
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1281
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1282
	e1000_down_and_stop(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1283
	e1000_release_manageability(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1284
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1285
	unregister_netdev(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1286
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1287
	e1000_phy_hw_reset(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1288
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1289
	kfree(adapter->tx_ring);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1290
	kfree(adapter->rx_ring);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1291
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1292
	if (hw->mac_type == e1000_ce4100)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1293
		iounmap(hw->ce4100_gbe_mdio_base_virt);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1294
	iounmap(hw->hw_addr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1295
	if (hw->flash_address)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1296
		iounmap(hw->flash_address);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1297
	pci_release_selected_regions(pdev, adapter->bars);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1298
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1299
	free_netdev(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1300
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1301
	pci_disable_device(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1302
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1303
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1304
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1305
 * e1000_sw_init - Initialize general software structures (struct e1000_adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1306
 * @adapter: board private structure to initialize
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1307
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1308
 * e1000_sw_init initializes the Adapter private data structure.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1309
 * e1000_init_hw_struct MUST be called before this function
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1310
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1311
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1312
static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1313
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1314
	adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1315
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1316
	adapter->num_tx_queues = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1317
	adapter->num_rx_queues = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1318
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1319
	if (e1000_alloc_queues(adapter)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1320
		e_err(probe, "Unable to allocate memory for queues\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1321
		return -ENOMEM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1322
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1323
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1324
	/* Explicitly disable IRQ since the NIC can be in any state. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1325
	e1000_irq_disable(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1326
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1327
	spin_lock_init(&adapter->stats_lock);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1328
	mutex_init(&adapter->mutex);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1329
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1330
	set_bit(__E1000_DOWN, &adapter->flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1331
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1332
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1333
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1334
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1335
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1336
 * e1000_alloc_queues - Allocate memory for all rings
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1337
 * @adapter: board private structure to initialize
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1338
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1339
 * We allocate one ring per queue at run-time since we don't know the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1340
 * number of queues at compile-time.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1341
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1342
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1343
static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1344
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1345
	adapter->tx_ring = kcalloc(adapter->num_tx_queues,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1346
	                           sizeof(struct e1000_tx_ring), GFP_KERNEL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1347
	if (!adapter->tx_ring)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1348
		return -ENOMEM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1349
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1350
	adapter->rx_ring = kcalloc(adapter->num_rx_queues,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1351
	                           sizeof(struct e1000_rx_ring), GFP_KERNEL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1352
	if (!adapter->rx_ring) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1353
		kfree(adapter->tx_ring);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1354
		return -ENOMEM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1355
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1356
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1357
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1358
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1359
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1360
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1361
 * e1000_open - Called when a network interface is made active
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1362
 * @netdev: network interface device structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1363
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1364
 * Returns 0 on success, negative value on failure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1365
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1366
 * The open entry point is called when a network interface is made
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1367
 * active by the system (IFF_UP).  At this point all resources needed
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1368
 * for transmit and receive operations are allocated, the interrupt
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1369
 * handler is registered with the OS, the watchdog task is started,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1370
 * and the stack is notified that the interface is ready.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1371
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1372
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1373
static int e1000_open(struct net_device *netdev)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1374
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1375
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1376
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1377
	int err;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1378
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1379
	/* disallow open during test */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1380
	if (test_bit(__E1000_TESTING, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1381
		return -EBUSY;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1382
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1383
	netif_carrier_off(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1384
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1385
	/* allocate transmit descriptors */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1386
	err = e1000_setup_all_tx_resources(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1387
	if (err)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1388
		goto err_setup_tx;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1389
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1390
	/* allocate receive descriptors */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1391
	err = e1000_setup_all_rx_resources(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1392
	if (err)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1393
		goto err_setup_rx;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1394
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1395
	e1000_power_up_phy(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1396
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1397
	adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1398
	if ((hw->mng_cookie.status &
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1399
			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1400
		e1000_update_mng_vlan(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1401
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1402
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1403
	/* before we allocate an interrupt, we must be ready to handle it.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1404
	 * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1405
	 * as soon as we call pci_request_irq, so we have to setup our
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1406
	 * clean_rx handler before we do so.  */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1407
	e1000_configure(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1408
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1409
	err = e1000_request_irq(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1410
	if (err)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1411
		goto err_req_irq;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1412
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1413
	/* From here on the code is the same as e1000_up() */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1414
	clear_bit(__E1000_DOWN, &adapter->flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1415
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1416
	napi_enable(&adapter->napi);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1417
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1418
	e1000_irq_enable(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1419
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1420
	netif_start_queue(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1421
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1422
	/* fire a link status change interrupt to start the watchdog */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1423
	ew32(ICS, E1000_ICS_LSC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1424
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1425
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1426
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1427
err_req_irq:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1428
	e1000_power_down_phy(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1429
	e1000_free_all_rx_resources(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1430
err_setup_rx:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1431
	e1000_free_all_tx_resources(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1432
err_setup_tx:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1433
	e1000_reset(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1434
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1435
	return err;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1436
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1437
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1438
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1439
 * e1000_close - Disables a network interface
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1440
 * @netdev: network interface device structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1441
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1442
 * Returns 0, this is not allowed to fail
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1443
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1444
 * The close entry point is called when an interface is de-activated
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1445
 * by the OS.  The hardware is still under the drivers control, but
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1446
 * needs to be disabled.  A global MAC reset is issued to stop the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1447
 * hardware, and all transmit and receive resources are freed.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1448
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1449
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1450
static int e1000_close(struct net_device *netdev)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1451
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1452
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1453
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1454
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1455
	WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1456
	e1000_down(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1457
	e1000_power_down_phy(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1458
	e1000_free_irq(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1459
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1460
	e1000_free_all_tx_resources(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1461
	e1000_free_all_rx_resources(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1462
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1463
	/* kill manageability vlan ID if supported, but not if a vlan with
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1464
	 * the same ID is registered on the host OS (let 8021q kill it) */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1465
	if ((hw->mng_cookie.status &
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1466
			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1467
	     !test_bit(adapter->mng_vlan_id, adapter->active_vlans)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1468
		e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1469
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1470
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1471
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1472
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1473
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1474
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1475
 * e1000_check_64k_bound - check that memory doesn't cross 64kB boundary
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1476
 * @adapter: address of board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1477
 * @start: address of beginning of memory
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1478
 * @len: length of memory
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1479
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1480
static bool e1000_check_64k_bound(struct e1000_adapter *adapter, void *start,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1481
				  unsigned long len)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1482
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1483
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1484
	unsigned long begin = (unsigned long)start;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1485
	unsigned long end = begin + len;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1486
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1487
	/* First rev 82545 and 82546 need to not allow any memory
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1488
	 * write location to cross 64k boundary due to errata 23 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1489
	if (hw->mac_type == e1000_82545 ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1490
	    hw->mac_type == e1000_ce4100 ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1491
	    hw->mac_type == e1000_82546) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1492
		return ((begin ^ (end - 1)) >> 16) != 0 ? false : true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1493
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1494
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1495
	return true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1496
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1497
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1498
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1499
 * e1000_setup_tx_resources - allocate Tx resources (Descriptors)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1500
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1501
 * @txdr:    tx descriptor ring (for a specific queue) to setup
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1502
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1503
 * Return 0 on success, negative on failure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1504
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1505
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1506
static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1507
				    struct e1000_tx_ring *txdr)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1508
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1509
	struct pci_dev *pdev = adapter->pdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1510
	int size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1511
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1512
	size = sizeof(struct e1000_buffer) * txdr->count;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1513
	txdr->buffer_info = vzalloc(size);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1514
	if (!txdr->buffer_info) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1515
		e_err(probe, "Unable to allocate memory for the Tx descriptor "
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1516
		      "ring\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1517
		return -ENOMEM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1518
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1519
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1520
	/* round up to nearest 4K */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1521
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1522
	txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1523
	txdr->size = ALIGN(txdr->size, 4096);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1524
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1525
	txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1526
					GFP_KERNEL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1527
	if (!txdr->desc) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1528
setup_tx_desc_die:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1529
		vfree(txdr->buffer_info);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1530
		e_err(probe, "Unable to allocate memory for the Tx descriptor "
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1531
		      "ring\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1532
		return -ENOMEM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1533
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1534
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1535
	/* Fix for errata 23, can't cross 64kB boundary */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1536
	if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1537
		void *olddesc = txdr->desc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1538
		dma_addr_t olddma = txdr->dma;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1539
		e_err(tx_err, "txdr align check failed: %u bytes at %p\n",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1540
		      txdr->size, txdr->desc);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1541
		/* Try again, without freeing the previous */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1542
		txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1543
						&txdr->dma, GFP_KERNEL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1544
		/* Failed allocation, critical failure */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1545
		if (!txdr->desc) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1546
			dma_free_coherent(&pdev->dev, txdr->size, olddesc,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1547
					  olddma);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1548
			goto setup_tx_desc_die;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1549
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1550
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1551
		if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1552
			/* give up */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1553
			dma_free_coherent(&pdev->dev, txdr->size, txdr->desc,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1554
					  txdr->dma);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1555
			dma_free_coherent(&pdev->dev, txdr->size, olddesc,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1556
					  olddma);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1557
			e_err(probe, "Unable to allocate aligned memory "
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1558
			      "for the transmit descriptor ring\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1559
			vfree(txdr->buffer_info);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1560
			return -ENOMEM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1561
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1562
			/* Free old allocation, new allocation was successful */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1563
			dma_free_coherent(&pdev->dev, txdr->size, olddesc,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1564
					  olddma);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1565
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1566
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1567
	memset(txdr->desc, 0, txdr->size);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1568
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1569
	txdr->next_to_use = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1570
	txdr->next_to_clean = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1571
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1572
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1573
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1574
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1575
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1576
 * e1000_setup_all_tx_resources - wrapper to allocate Tx resources
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1577
 * 				  (Descriptors) for all queues
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1578
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1579
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1580
 * Return 0 on success, negative on failure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1581
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1582
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1583
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1584
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1585
	int i, err = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1586
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1587
	for (i = 0; i < adapter->num_tx_queues; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1588
		err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1589
		if (err) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1590
			e_err(probe, "Allocation for Tx Queue %u failed\n", i);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1591
			for (i-- ; i >= 0; i--)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1592
				e1000_free_tx_resources(adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1593
							&adapter->tx_ring[i]);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1594
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1595
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1596
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1597
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1598
	return err;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1599
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1600
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1601
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1602
 * e1000_configure_tx - Configure 8254x Transmit Unit after Reset
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1603
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1604
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1605
 * Configure the Tx unit of the MAC after a reset.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1606
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1607
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1608
static void e1000_configure_tx(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1609
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1610
	u64 tdba;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1611
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1612
	u32 tdlen, tctl, tipg;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1613
	u32 ipgr1, ipgr2;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1614
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1615
	/* Setup the HW Tx Head and Tail descriptor pointers */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1616
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1617
	switch (adapter->num_tx_queues) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1618
	case 1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1619
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1620
		tdba = adapter->tx_ring[0].dma;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1621
		tdlen = adapter->tx_ring[0].count *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1622
			sizeof(struct e1000_tx_desc);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1623
		ew32(TDLEN, tdlen);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1624
		ew32(TDBAH, (tdba >> 32));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1625
		ew32(TDBAL, (tdba & 0x00000000ffffffffULL));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1626
		ew32(TDT, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1627
		ew32(TDH, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1628
		adapter->tx_ring[0].tdh = ((hw->mac_type >= e1000_82543) ? E1000_TDH : E1000_82542_TDH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1629
		adapter->tx_ring[0].tdt = ((hw->mac_type >= e1000_82543) ? E1000_TDT : E1000_82542_TDT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1630
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1631
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1632
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1633
	/* Set the default values for the Tx Inter Packet Gap timer */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1634
	if ((hw->media_type == e1000_media_type_fiber ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1635
	     hw->media_type == e1000_media_type_internal_serdes))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1636
		tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1637
	else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1638
		tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1639
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1640
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1641
	case e1000_82542_rev2_0:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1642
	case e1000_82542_rev2_1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1643
		tipg = DEFAULT_82542_TIPG_IPGT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1644
		ipgr1 = DEFAULT_82542_TIPG_IPGR1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1645
		ipgr2 = DEFAULT_82542_TIPG_IPGR2;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1646
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1647
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1648
		ipgr1 = DEFAULT_82543_TIPG_IPGR1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1649
		ipgr2 = DEFAULT_82543_TIPG_IPGR2;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1650
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1651
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1652
	tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1653
	tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1654
	ew32(TIPG, tipg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1655
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1656
	/* Set the Tx Interrupt Delay register */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1657
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1658
	ew32(TIDV, adapter->tx_int_delay);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1659
	if (hw->mac_type >= e1000_82540)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1660
		ew32(TADV, adapter->tx_abs_int_delay);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1661
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1662
	/* Program the Transmit Control Register */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1663
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1664
	tctl = er32(TCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1665
	tctl &= ~E1000_TCTL_CT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1666
	tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1667
		(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1668
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1669
	e1000_config_collision_dist(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1670
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1671
	/* Setup Transmit Descriptor Settings for eop descriptor */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1672
	adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1673
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1674
	/* only set IDE if we are delaying interrupts using the timers */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1675
	if (adapter->tx_int_delay)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1676
		adapter->txd_cmd |= E1000_TXD_CMD_IDE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1677
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1678
	if (hw->mac_type < e1000_82543)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1679
		adapter->txd_cmd |= E1000_TXD_CMD_RPS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1680
	else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1681
		adapter->txd_cmd |= E1000_TXD_CMD_RS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1682
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1683
	/* Cache if we're 82544 running in PCI-X because we'll
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1684
	 * need this to apply a workaround later in the send path. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1685
	if (hw->mac_type == e1000_82544 &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1686
	    hw->bus_type == e1000_bus_type_pcix)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1687
		adapter->pcix_82544 = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1688
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1689
	ew32(TCTL, tctl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1690
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1691
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1692
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1693
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1694
 * e1000_setup_rx_resources - allocate Rx resources (Descriptors)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1695
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1696
 * @rxdr:    rx descriptor ring (for a specific queue) to setup
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1697
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1698
 * Returns 0 on success, negative on failure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1699
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1700
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1701
static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1702
				    struct e1000_rx_ring *rxdr)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1703
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1704
	struct pci_dev *pdev = adapter->pdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1705
	int size, desc_len;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1706
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1707
	size = sizeof(struct e1000_buffer) * rxdr->count;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1708
	rxdr->buffer_info = vzalloc(size);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1709
	if (!rxdr->buffer_info) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1710
		e_err(probe, "Unable to allocate memory for the Rx descriptor "
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1711
		      "ring\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1712
		return -ENOMEM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1713
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1714
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1715
	desc_len = sizeof(struct e1000_rx_desc);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1716
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1717
	/* Round up to nearest 4K */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1718
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1719
	rxdr->size = rxdr->count * desc_len;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1720
	rxdr->size = ALIGN(rxdr->size, 4096);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1721
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1722
	rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1723
					GFP_KERNEL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1724
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1725
	if (!rxdr->desc) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1726
		e_err(probe, "Unable to allocate memory for the Rx descriptor "
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1727
		      "ring\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1728
setup_rx_desc_die:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1729
		vfree(rxdr->buffer_info);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1730
		return -ENOMEM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1731
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1732
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1733
	/* Fix for errata 23, can't cross 64kB boundary */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1734
	if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1735
		void *olddesc = rxdr->desc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1736
		dma_addr_t olddma = rxdr->dma;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1737
		e_err(rx_err, "rxdr align check failed: %u bytes at %p\n",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1738
		      rxdr->size, rxdr->desc);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1739
		/* Try again, without freeing the previous */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1740
		rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1741
						&rxdr->dma, GFP_KERNEL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1742
		/* Failed allocation, critical failure */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1743
		if (!rxdr->desc) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1744
			dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1745
					  olddma);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1746
			e_err(probe, "Unable to allocate memory for the Rx "
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1747
			      "descriptor ring\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1748
			goto setup_rx_desc_die;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1749
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1750
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1751
		if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1752
			/* give up */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1753
			dma_free_coherent(&pdev->dev, rxdr->size, rxdr->desc,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1754
					  rxdr->dma);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1755
			dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1756
					  olddma);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1757
			e_err(probe, "Unable to allocate aligned memory for "
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1758
			      "the Rx descriptor ring\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1759
			goto setup_rx_desc_die;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1760
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1761
			/* Free old allocation, new allocation was successful */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1762
			dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1763
					  olddma);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1764
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1765
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1766
	memset(rxdr->desc, 0, rxdr->size);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1767
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1768
	rxdr->next_to_clean = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1769
	rxdr->next_to_use = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1770
	rxdr->rx_skb_top = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1771
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1772
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1773
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1774
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1775
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1776
 * e1000_setup_all_rx_resources - wrapper to allocate Rx resources
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1777
 * 				  (Descriptors) for all queues
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1778
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1779
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1780
 * Return 0 on success, negative on failure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1781
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1782
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1783
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1784
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1785
	int i, err = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1786
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1787
	for (i = 0; i < adapter->num_rx_queues; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1788
		err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1789
		if (err) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1790
			e_err(probe, "Allocation for Rx Queue %u failed\n", i);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1791
			for (i-- ; i >= 0; i--)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1792
				e1000_free_rx_resources(adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1793
							&adapter->rx_ring[i]);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1794
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1795
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1796
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1797
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1798
	return err;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1799
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1800
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1801
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1802
 * e1000_setup_rctl - configure the receive control registers
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1803
 * @adapter: Board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1804
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1805
static void e1000_setup_rctl(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1806
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1807
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1808
	u32 rctl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1809
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1810
	rctl = er32(RCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1811
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1812
	rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1813
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1814
	rctl |= E1000_RCTL_BAM | E1000_RCTL_LBM_NO |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1815
		E1000_RCTL_RDMTS_HALF |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1816
		(hw->mc_filter_type << E1000_RCTL_MO_SHIFT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1817
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1818
	if (hw->tbi_compatibility_on == 1)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1819
		rctl |= E1000_RCTL_SBP;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1820
	else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1821
		rctl &= ~E1000_RCTL_SBP;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1822
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1823
	if (adapter->netdev->mtu <= ETH_DATA_LEN)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1824
		rctl &= ~E1000_RCTL_LPE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1825
	else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1826
		rctl |= E1000_RCTL_LPE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1827
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1828
	/* Setup buffer sizes */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1829
	rctl &= ~E1000_RCTL_SZ_4096;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1830
	rctl |= E1000_RCTL_BSEX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1831
	switch (adapter->rx_buffer_len) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1832
		case E1000_RXBUFFER_2048:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1833
		default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1834
			rctl |= E1000_RCTL_SZ_2048;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1835
			rctl &= ~E1000_RCTL_BSEX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1836
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1837
		case E1000_RXBUFFER_4096:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1838
			rctl |= E1000_RCTL_SZ_4096;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1839
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1840
		case E1000_RXBUFFER_8192:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1841
			rctl |= E1000_RCTL_SZ_8192;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1842
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1843
		case E1000_RXBUFFER_16384:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1844
			rctl |= E1000_RCTL_SZ_16384;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1845
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1846
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1847
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1848
	/* This is useful for sniffing bad packets. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1849
	if (adapter->netdev->features & NETIF_F_RXALL) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1850
		/* UPE and MPE will be handled by normal PROMISC logic
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1851
		 * in e1000e_set_rx_mode */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1852
		rctl |= (E1000_RCTL_SBP | /* Receive bad packets */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1853
			 E1000_RCTL_BAM | /* RX All Bcast Pkts */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1854
			 E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1855
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1856
		rctl &= ~(E1000_RCTL_VFE | /* Disable VLAN filter */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1857
			  E1000_RCTL_DPF | /* Allow filtered pause */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1858
			  E1000_RCTL_CFIEN); /* Dis VLAN CFIEN Filter */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1859
		/* Do not mess with E1000_CTRL_VME, it affects transmit as well,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1860
		 * and that breaks VLANs.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1861
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1862
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1863
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1864
	ew32(RCTL, rctl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1865
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1866
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1867
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1868
 * e1000_configure_rx - Configure 8254x Receive Unit after Reset
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1869
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1870
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1871
 * Configure the Rx unit of the MAC after a reset.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1872
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1873
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1874
static void e1000_configure_rx(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1875
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1876
	u64 rdba;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1877
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1878
	u32 rdlen, rctl, rxcsum;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1879
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1880
	if (adapter->netdev->mtu > ETH_DATA_LEN) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1881
		rdlen = adapter->rx_ring[0].count *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1882
		        sizeof(struct e1000_rx_desc);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1883
		adapter->clean_rx = e1000_clean_jumbo_rx_irq;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1884
		adapter->alloc_rx_buf = e1000_alloc_jumbo_rx_buffers;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1885
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1886
		rdlen = adapter->rx_ring[0].count *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1887
		        sizeof(struct e1000_rx_desc);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1888
		adapter->clean_rx = e1000_clean_rx_irq;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1889
		adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1890
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1891
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1892
	/* disable receives while setting up the descriptors */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1893
	rctl = er32(RCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1894
	ew32(RCTL, rctl & ~E1000_RCTL_EN);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1895
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1896
	/* set the Receive Delay Timer Register */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1897
	ew32(RDTR, adapter->rx_int_delay);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1898
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1899
	if (hw->mac_type >= e1000_82540) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1900
		ew32(RADV, adapter->rx_abs_int_delay);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1901
		if (adapter->itr_setting != 0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1902
			ew32(ITR, 1000000000 / (adapter->itr * 256));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1903
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1904
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1905
	/* Setup the HW Rx Head and Tail Descriptor Pointers and
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1906
	 * the Base and Length of the Rx Descriptor Ring */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1907
	switch (adapter->num_rx_queues) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1908
	case 1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1909
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1910
		rdba = adapter->rx_ring[0].dma;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1911
		ew32(RDLEN, rdlen);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1912
		ew32(RDBAH, (rdba >> 32));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1913
		ew32(RDBAL, (rdba & 0x00000000ffffffffULL));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1914
		ew32(RDT, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1915
		ew32(RDH, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1916
		adapter->rx_ring[0].rdh = ((hw->mac_type >= e1000_82543) ? E1000_RDH : E1000_82542_RDH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1917
		adapter->rx_ring[0].rdt = ((hw->mac_type >= e1000_82543) ? E1000_RDT : E1000_82542_RDT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1918
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1919
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1920
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1921
	/* Enable 82543 Receive Checksum Offload for TCP and UDP */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1922
	if (hw->mac_type >= e1000_82543) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1923
		rxcsum = er32(RXCSUM);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1924
		if (adapter->rx_csum)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1925
			rxcsum |= E1000_RXCSUM_TUOFL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1926
		else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1927
			/* don't need to clear IPPCSE as it defaults to 0 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1928
			rxcsum &= ~E1000_RXCSUM_TUOFL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1929
		ew32(RXCSUM, rxcsum);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1930
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1931
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1932
	/* Enable Receives */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1933
	ew32(RCTL, rctl | E1000_RCTL_EN);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1934
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1935
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1936
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1937
 * e1000_free_tx_resources - Free Tx Resources per Queue
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1938
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1939
 * @tx_ring: Tx descriptor ring for a specific queue
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1940
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1941
 * Free all transmit software resources
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1942
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1943
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1944
static void e1000_free_tx_resources(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1945
				    struct e1000_tx_ring *tx_ring)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1946
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1947
	struct pci_dev *pdev = adapter->pdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1948
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1949
	e1000_clean_tx_ring(adapter, tx_ring);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1950
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1951
	vfree(tx_ring->buffer_info);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1952
	tx_ring->buffer_info = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1953
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1954
	dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1955
			  tx_ring->dma);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1956
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1957
	tx_ring->desc = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1958
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1959
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1960
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1961
 * e1000_free_all_tx_resources - Free Tx Resources for All Queues
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1962
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1963
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1964
 * Free all transmit software resources
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1965
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1966
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1967
void e1000_free_all_tx_resources(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1968
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1969
	int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1970
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1971
	for (i = 0; i < adapter->num_tx_queues; i++)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1972
		e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1973
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1974
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1975
static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1976
					     struct e1000_buffer *buffer_info)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1977
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1978
	if (buffer_info->dma) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1979
		if (buffer_info->mapped_as_page)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1980
			dma_unmap_page(&adapter->pdev->dev, buffer_info->dma,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1981
				       buffer_info->length, DMA_TO_DEVICE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1982
		else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1983
			dma_unmap_single(&adapter->pdev->dev, buffer_info->dma,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1984
					 buffer_info->length,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1985
					 DMA_TO_DEVICE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1986
		buffer_info->dma = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1987
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1988
	if (buffer_info->skb) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1989
		dev_kfree_skb_any(buffer_info->skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1990
		buffer_info->skb = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1991
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1992
	buffer_info->time_stamp = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1993
	/* buffer_info must be completely set up in the transmit path */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1994
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1995
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1996
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1997
 * e1000_clean_tx_ring - Free Tx Buffers
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1998
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1999
 * @tx_ring: ring to be cleaned
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2000
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2001
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2002
static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2003
				struct e1000_tx_ring *tx_ring)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2004
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2005
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2006
	struct e1000_buffer *buffer_info;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2007
	unsigned long size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2008
	unsigned int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2009
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2010
	/* Free all the Tx ring sk_buffs */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2011
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2012
	for (i = 0; i < tx_ring->count; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2013
		buffer_info = &tx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2014
		e1000_unmap_and_free_tx_resource(adapter, buffer_info);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2015
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2016
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2017
	size = sizeof(struct e1000_buffer) * tx_ring->count;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2018
	memset(tx_ring->buffer_info, 0, size);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2019
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2020
	/* Zero out the descriptor ring */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2021
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2022
	memset(tx_ring->desc, 0, tx_ring->size);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2023
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2024
	tx_ring->next_to_use = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2025
	tx_ring->next_to_clean = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2026
	tx_ring->last_tx_tso = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2027
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2028
	writel(0, hw->hw_addr + tx_ring->tdh);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2029
	writel(0, hw->hw_addr + tx_ring->tdt);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2030
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2031
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2032
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2033
 * e1000_clean_all_tx_rings - Free Tx Buffers for all queues
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2034
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2035
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2036
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2037
static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2038
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2039
	int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2040
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2041
	for (i = 0; i < adapter->num_tx_queues; i++)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2042
		e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2043
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2044
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2045
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2046
 * e1000_free_rx_resources - Free Rx Resources
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2047
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2048
 * @rx_ring: ring to clean the resources from
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2049
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2050
 * Free all receive software resources
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2051
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2052
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2053
static void e1000_free_rx_resources(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2054
				    struct e1000_rx_ring *rx_ring)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2055
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2056
	struct pci_dev *pdev = adapter->pdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2057
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2058
	e1000_clean_rx_ring(adapter, rx_ring);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2059
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2060
	vfree(rx_ring->buffer_info);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2061
	rx_ring->buffer_info = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2062
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2063
	dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2064
			  rx_ring->dma);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2065
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2066
	rx_ring->desc = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2067
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2068
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2069
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2070
 * e1000_free_all_rx_resources - Free Rx Resources for All Queues
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2071
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2072
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2073
 * Free all receive software resources
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2074
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2075
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2076
void e1000_free_all_rx_resources(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2077
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2078
	int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2079
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2080
	for (i = 0; i < adapter->num_rx_queues; i++)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2081
		e1000_free_rx_resources(adapter, &adapter->rx_ring[i]);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2082
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2083
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2084
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2085
 * e1000_clean_rx_ring - Free Rx Buffers per Queue
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2086
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2087
 * @rx_ring: ring to free buffers from
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2088
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2089
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2090
static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2091
				struct e1000_rx_ring *rx_ring)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2092
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2093
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2094
	struct e1000_buffer *buffer_info;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2095
	struct pci_dev *pdev = adapter->pdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2096
	unsigned long size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2097
	unsigned int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2098
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2099
	/* Free all the Rx ring sk_buffs */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2100
	for (i = 0; i < rx_ring->count; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2101
		buffer_info = &rx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2102
		if (buffer_info->dma &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2103
		    adapter->clean_rx == e1000_clean_rx_irq) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2104
			dma_unmap_single(&pdev->dev, buffer_info->dma,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2105
			                 buffer_info->length,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2106
					 DMA_FROM_DEVICE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2107
		} else if (buffer_info->dma &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2108
		           adapter->clean_rx == e1000_clean_jumbo_rx_irq) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2109
			dma_unmap_page(&pdev->dev, buffer_info->dma,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2110
				       buffer_info->length,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2111
				       DMA_FROM_DEVICE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2112
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2113
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2114
		buffer_info->dma = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2115
		if (buffer_info->page) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2116
			put_page(buffer_info->page);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2117
			buffer_info->page = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2118
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2119
		if (buffer_info->skb) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2120
			dev_kfree_skb(buffer_info->skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2121
			buffer_info->skb = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2122
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2123
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2124
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2125
	/* there also may be some cached data from a chained receive */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2126
	if (rx_ring->rx_skb_top) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2127
		dev_kfree_skb(rx_ring->rx_skb_top);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2128
		rx_ring->rx_skb_top = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2129
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2130
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2131
	size = sizeof(struct e1000_buffer) * rx_ring->count;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2132
	memset(rx_ring->buffer_info, 0, size);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2133
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2134
	/* Zero out the descriptor ring */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2135
	memset(rx_ring->desc, 0, rx_ring->size);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2136
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2137
	rx_ring->next_to_clean = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2138
	rx_ring->next_to_use = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2139
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2140
	writel(0, hw->hw_addr + rx_ring->rdh);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2141
	writel(0, hw->hw_addr + rx_ring->rdt);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2142
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2143
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2144
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2145
 * e1000_clean_all_rx_rings - Free Rx Buffers for all queues
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2146
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2147
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2148
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2149
static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2150
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2151
	int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2152
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2153
	for (i = 0; i < adapter->num_rx_queues; i++)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2154
		e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2155
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2156
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2157
/* The 82542 2.0 (revision 2) needs to have the receive unit in reset
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2158
 * and memory write and invalidate disabled for certain operations
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2159
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2160
static void e1000_enter_82542_rst(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2161
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2162
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2163
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2164
	u32 rctl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2165
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2166
	e1000_pci_clear_mwi(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2167
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2168
	rctl = er32(RCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2169
	rctl |= E1000_RCTL_RST;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2170
	ew32(RCTL, rctl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2171
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2172
	mdelay(5);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2173
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2174
	if (netif_running(netdev))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2175
		e1000_clean_all_rx_rings(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2176
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2177
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2178
static void e1000_leave_82542_rst(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2179
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2180
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2181
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2182
	u32 rctl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2183
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2184
	rctl = er32(RCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2185
	rctl &= ~E1000_RCTL_RST;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2186
	ew32(RCTL, rctl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2187
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2188
	mdelay(5);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2189
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2190
	if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2191
		e1000_pci_set_mwi(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2192
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2193
	if (netif_running(netdev)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2194
		/* No need to loop, because 82542 supports only 1 queue */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2195
		struct e1000_rx_ring *ring = &adapter->rx_ring[0];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2196
		e1000_configure_rx(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2197
		adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2198
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2199
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2200
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2201
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2202
 * e1000_set_mac - Change the Ethernet Address of the NIC
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2203
 * @netdev: network interface device structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2204
 * @p: pointer to an address structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2205
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2206
 * Returns 0 on success, negative on failure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2207
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2208
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2209
static int e1000_set_mac(struct net_device *netdev, void *p)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2210
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2211
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2212
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2213
	struct sockaddr *addr = p;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2214
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2215
	if (!is_valid_ether_addr(addr->sa_data))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2216
		return -EADDRNOTAVAIL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2217
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2218
	/* 82542 2.0 needs to be in reset to write receive address registers */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2219
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2220
	if (hw->mac_type == e1000_82542_rev2_0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2221
		e1000_enter_82542_rst(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2222
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2223
	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2224
	memcpy(hw->mac_addr, addr->sa_data, netdev->addr_len);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2225
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2226
	e1000_rar_set(hw, hw->mac_addr, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2227
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2228
	if (hw->mac_type == e1000_82542_rev2_0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2229
		e1000_leave_82542_rst(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2230
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2231
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2232
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2233
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2234
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2235
 * e1000_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2236
 * @netdev: network interface device structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2237
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2238
 * The set_rx_mode entry point is called whenever the unicast or multicast
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2239
 * address lists or the network interface flags are updated. This routine is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2240
 * responsible for configuring the hardware for proper unicast, multicast,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2241
 * promiscuous mode, and all-multi behavior.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2242
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2243
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2244
static void e1000_set_rx_mode(struct net_device *netdev)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2245
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2246
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2247
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2248
	struct netdev_hw_addr *ha;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2249
	bool use_uc = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2250
	u32 rctl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2251
	u32 hash_value;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2252
	int i, rar_entries = E1000_RAR_ENTRIES;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2253
	int mta_reg_count = E1000_NUM_MTA_REGISTERS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2254
	u32 *mcarray = kcalloc(mta_reg_count, sizeof(u32), GFP_ATOMIC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2255
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2256
	if (!mcarray) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2257
		e_err(probe, "memory allocation failed\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2258
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2259
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2260
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2261
	/* Check for Promiscuous and All Multicast modes */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2262
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2263
	rctl = er32(RCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2264
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2265
	if (netdev->flags & IFF_PROMISC) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2266
		rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2267
		rctl &= ~E1000_RCTL_VFE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2268
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2269
		if (netdev->flags & IFF_ALLMULTI)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2270
			rctl |= E1000_RCTL_MPE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2271
		else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2272
			rctl &= ~E1000_RCTL_MPE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2273
		/* Enable VLAN filter if there is a VLAN */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2274
		if (e1000_vlan_used(adapter))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2275
			rctl |= E1000_RCTL_VFE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2276
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2277
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2278
	if (netdev_uc_count(netdev) > rar_entries - 1) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2279
		rctl |= E1000_RCTL_UPE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2280
	} else if (!(netdev->flags & IFF_PROMISC)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2281
		rctl &= ~E1000_RCTL_UPE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2282
		use_uc = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2283
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2284
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2285
	ew32(RCTL, rctl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2286
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2287
	/* 82542 2.0 needs to be in reset to write receive address registers */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2288
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2289
	if (hw->mac_type == e1000_82542_rev2_0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2290
		e1000_enter_82542_rst(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2291
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2292
	/* load the first 14 addresses into the exact filters 1-14. Unicast
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2293
	 * addresses take precedence to avoid disabling unicast filtering
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2294
	 * when possible.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2295
	 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2296
	 * RAR 0 is used for the station MAC address
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2297
	 * if there are not 14 addresses, go ahead and clear the filters
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2298
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2299
	i = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2300
	if (use_uc)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2301
		netdev_for_each_uc_addr(ha, netdev) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2302
			if (i == rar_entries)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2303
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2304
			e1000_rar_set(hw, ha->addr, i++);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2305
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2306
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2307
	netdev_for_each_mc_addr(ha, netdev) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2308
		if (i == rar_entries) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2309
			/* load any remaining addresses into the hash table */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2310
			u32 hash_reg, hash_bit, mta;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2311
			hash_value = e1000_hash_mc_addr(hw, ha->addr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2312
			hash_reg = (hash_value >> 5) & 0x7F;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2313
			hash_bit = hash_value & 0x1F;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2314
			mta = (1 << hash_bit);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2315
			mcarray[hash_reg] |= mta;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2316
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2317
			e1000_rar_set(hw, ha->addr, i++);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2318
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2319
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2320
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2321
	for (; i < rar_entries; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2322
		E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2323
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2324
		E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2325
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2326
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2327
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2328
	/* write the hash table completely, write from bottom to avoid
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2329
	 * both stupid write combining chipsets, and flushing each write */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2330
	for (i = mta_reg_count - 1; i >= 0 ; i--) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2331
		/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2332
		 * If we are on an 82544 has an errata where writing odd
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2333
		 * offsets overwrites the previous even offset, but writing
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2334
		 * backwards over the range solves the issue by always
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2335
		 * writing the odd offset first
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2336
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2337
		E1000_WRITE_REG_ARRAY(hw, MTA, i, mcarray[i]);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2338
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2339
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2340
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2341
	if (hw->mac_type == e1000_82542_rev2_0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2342
		e1000_leave_82542_rst(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2343
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2344
	kfree(mcarray);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2345
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2346
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2347
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2348
 * e1000_update_phy_info_task - get phy info
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2349
 * @work: work struct contained inside adapter struct
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2350
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2351
 * Need to wait a few seconds after link up to get diagnostic information from
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2352
 * the phy
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2353
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2354
static void e1000_update_phy_info_task(struct work_struct *work)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2355
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2356
	struct e1000_adapter *adapter = container_of(work,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2357
						     struct e1000_adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2358
						     phy_info_task.work);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2359
	if (test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2360
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2361
	mutex_lock(&adapter->mutex);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2362
	e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2363
	mutex_unlock(&adapter->mutex);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2364
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2365
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2366
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2367
 * e1000_82547_tx_fifo_stall_task - task to complete work
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2368
 * @work: work struct contained inside adapter struct
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2369
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2370
static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2371
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2372
	struct e1000_adapter *adapter = container_of(work,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2373
						     struct e1000_adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2374
						     fifo_stall_task.work);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2375
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2376
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2377
	u32 tctl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2378
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2379
	if (test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2380
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2381
	mutex_lock(&adapter->mutex);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2382
	if (atomic_read(&adapter->tx_fifo_stall)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2383
		if ((er32(TDT) == er32(TDH)) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2384
		   (er32(TDFT) == er32(TDFH)) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2385
		   (er32(TDFTS) == er32(TDFHS))) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2386
			tctl = er32(TCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2387
			ew32(TCTL, tctl & ~E1000_TCTL_EN);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2388
			ew32(TDFT, adapter->tx_head_addr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2389
			ew32(TDFH, adapter->tx_head_addr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2390
			ew32(TDFTS, adapter->tx_head_addr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2391
			ew32(TDFHS, adapter->tx_head_addr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2392
			ew32(TCTL, tctl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2393
			E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2394
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2395
			adapter->tx_fifo_head = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2396
			atomic_set(&adapter->tx_fifo_stall, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2397
			netif_wake_queue(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2398
		} else if (!test_bit(__E1000_DOWN, &adapter->flags)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2399
			schedule_delayed_work(&adapter->fifo_stall_task, 1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2400
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2401
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2402
	mutex_unlock(&adapter->mutex);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2403
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2404
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2405
bool e1000_has_link(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2406
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2407
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2408
	bool link_active = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2409
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2410
	/* get_link_status is set on LSC (link status) interrupt or rx
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2411
	 * sequence error interrupt (except on intel ce4100).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2412
	 * get_link_status will stay false until the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2413
	 * e1000_check_for_link establishes link for copper adapters
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2414
	 * ONLY
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2415
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2416
	switch (hw->media_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2417
	case e1000_media_type_copper:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2418
		if (hw->mac_type == e1000_ce4100)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2419
			hw->get_link_status = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2420
		if (hw->get_link_status) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2421
			e1000_check_for_link(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2422
			link_active = !hw->get_link_status;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2423
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2424
			link_active = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2425
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2426
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2427
	case e1000_media_type_fiber:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2428
		e1000_check_for_link(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2429
		link_active = !!(er32(STATUS) & E1000_STATUS_LU);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2430
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2431
	case e1000_media_type_internal_serdes:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2432
		e1000_check_for_link(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2433
		link_active = hw->serdes_has_link;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2434
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2435
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2436
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2437
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2438
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2439
	return link_active;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2440
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2441
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2442
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2443
 * e1000_watchdog - work function
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2444
 * @work: work struct contained inside adapter struct
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2445
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2446
static void e1000_watchdog(struct work_struct *work)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2447
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2448
	struct e1000_adapter *adapter = container_of(work,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2449
						     struct e1000_adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2450
						     watchdog_task.work);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2451
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2452
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2453
	struct e1000_tx_ring *txdr = adapter->tx_ring;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2454
	u32 link, tctl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2455
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2456
	if (test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2457
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2458
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2459
	mutex_lock(&adapter->mutex);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2460
	link = e1000_has_link(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2461
	if ((netif_carrier_ok(netdev)) && link)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2462
		goto link_up;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2463
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2464
	if (link) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2465
		if (!netif_carrier_ok(netdev)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2466
			u32 ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2467
			bool txb2b = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2468
			/* update snapshot of PHY registers on LSC */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2469
			e1000_get_speed_and_duplex(hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2470
			                           &adapter->link_speed,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2471
			                           &adapter->link_duplex);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2472
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2473
			ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2474
			pr_info("%s NIC Link is Up %d Mbps %s, "
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2475
				"Flow Control: %s\n",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2476
				netdev->name,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2477
				adapter->link_speed,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2478
				adapter->link_duplex == FULL_DUPLEX ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2479
				"Full Duplex" : "Half Duplex",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2480
				((ctrl & E1000_CTRL_TFCE) && (ctrl &
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2481
				E1000_CTRL_RFCE)) ? "RX/TX" : ((ctrl &
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2482
				E1000_CTRL_RFCE) ? "RX" : ((ctrl &
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2483
				E1000_CTRL_TFCE) ? "TX" : "None")));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2484
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2485
			/* adjust timeout factor according to speed/duplex */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2486
			adapter->tx_timeout_factor = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2487
			switch (adapter->link_speed) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2488
			case SPEED_10:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2489
				txb2b = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2490
				adapter->tx_timeout_factor = 16;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2491
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2492
			case SPEED_100:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2493
				txb2b = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2494
				/* maybe add some timeout factor ? */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2495
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2496
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2497
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2498
			/* enable transmits in the hardware */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2499
			tctl = er32(TCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2500
			tctl |= E1000_TCTL_EN;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2501
			ew32(TCTL, tctl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2502
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2503
			netif_carrier_on(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2504
			if (!test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2505
				schedule_delayed_work(&adapter->phy_info_task,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2506
						      2 * HZ);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2507
			adapter->smartspeed = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2508
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2509
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2510
		if (netif_carrier_ok(netdev)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2511
			adapter->link_speed = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2512
			adapter->link_duplex = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2513
			pr_info("%s NIC Link is Down\n",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2514
				netdev->name);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2515
			netif_carrier_off(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2516
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2517
			if (!test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2518
				schedule_delayed_work(&adapter->phy_info_task,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2519
						      2 * HZ);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2520
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2521
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2522
		e1000_smartspeed(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2523
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2524
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2525
link_up:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2526
	e1000_update_stats(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2527
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2528
	hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2529
	adapter->tpt_old = adapter->stats.tpt;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2530
	hw->collision_delta = adapter->stats.colc - adapter->colc_old;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2531
	adapter->colc_old = adapter->stats.colc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2532
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2533
	adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2534
	adapter->gorcl_old = adapter->stats.gorcl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2535
	adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2536
	adapter->gotcl_old = adapter->stats.gotcl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2537
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2538
	e1000_update_adaptive(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2539
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2540
	if (!netif_carrier_ok(netdev)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2541
		if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2542
			/* We've lost link, so the controller stops DMA,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2543
			 * but we've got queued Tx work that's never going
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2544
			 * to get done, so reset controller to flush Tx.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2545
			 * (Do the reset outside of interrupt context). */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2546
			adapter->tx_timeout_count++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2547
			schedule_work(&adapter->reset_task);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2548
			/* exit immediately since reset is imminent */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2549
			goto unlock;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2550
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2551
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2552
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2553
	/* Simple mode for Interrupt Throttle Rate (ITR) */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2554
	if (hw->mac_type >= e1000_82540 && adapter->itr_setting == 4) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2555
		/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2556
		 * Symmetric Tx/Rx gets a reduced ITR=2000;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2557
		 * Total asymmetrical Tx or Rx gets ITR=8000;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2558
		 * everyone else is between 2000-8000.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2559
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2560
		u32 goc = (adapter->gotcl + adapter->gorcl) / 10000;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2561
		u32 dif = (adapter->gotcl > adapter->gorcl ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2562
			    adapter->gotcl - adapter->gorcl :
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2563
			    adapter->gorcl - adapter->gotcl) / 10000;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2564
		u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2565
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2566
		ew32(ITR, 1000000000 / (itr * 256));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2567
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2568
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2569
	/* Cause software interrupt to ensure rx ring is cleaned */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2570
	ew32(ICS, E1000_ICS_RXDMT0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2571
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2572
	/* Force detection of hung controller every watchdog period */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2573
	adapter->detect_tx_hung = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2574
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2575
	/* Reschedule the task */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2576
	if (!test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2577
		schedule_delayed_work(&adapter->watchdog_task, 2 * HZ);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2578
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2579
unlock:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2580
	mutex_unlock(&adapter->mutex);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2581
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2582
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2583
enum latency_range {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2584
	lowest_latency = 0,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2585
	low_latency = 1,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2586
	bulk_latency = 2,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2587
	latency_invalid = 255
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2588
};
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2589
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2590
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2591
 * e1000_update_itr - update the dynamic ITR value based on statistics
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2592
 * @adapter: pointer to adapter
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2593
 * @itr_setting: current adapter->itr
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2594
 * @packets: the number of packets during this measurement interval
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2595
 * @bytes: the number of bytes during this measurement interval
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2596
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2597
 *      Stores a new ITR value based on packets and byte
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2598
 *      counts during the last interrupt.  The advantage of per interrupt
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2599
 *      computation is faster updates and more accurate ITR for the current
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2600
 *      traffic pattern.  Constants in this function were computed
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2601
 *      based on theoretical maximum wire speed and thresholds were set based
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2602
 *      on testing data as well as attempting to minimize response time
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2603
 *      while increasing bulk throughput.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2604
 *      this functionality is controlled by the InterruptThrottleRate module
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2605
 *      parameter (see e1000_param.c)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2606
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2607
static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2608
				     u16 itr_setting, int packets, int bytes)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2609
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2610
	unsigned int retval = itr_setting;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2611
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2612
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2613
	if (unlikely(hw->mac_type < e1000_82540))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2614
		goto update_itr_done;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2615
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2616
	if (packets == 0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2617
		goto update_itr_done;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2618
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2619
	switch (itr_setting) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2620
	case lowest_latency:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2621
		/* jumbo frames get bulk treatment*/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2622
		if (bytes/packets > 8000)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2623
			retval = bulk_latency;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2624
		else if ((packets < 5) && (bytes > 512))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2625
			retval = low_latency;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2626
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2627
	case low_latency:  /* 50 usec aka 20000 ints/s */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2628
		if (bytes > 10000) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2629
			/* jumbo frames need bulk latency setting */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2630
			if (bytes/packets > 8000)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2631
				retval = bulk_latency;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2632
			else if ((packets < 10) || ((bytes/packets) > 1200))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2633
				retval = bulk_latency;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2634
			else if ((packets > 35))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2635
				retval = lowest_latency;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2636
		} else if (bytes/packets > 2000)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2637
			retval = bulk_latency;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2638
		else if (packets <= 2 && bytes < 512)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2639
			retval = lowest_latency;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2640
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2641
	case bulk_latency: /* 250 usec aka 4000 ints/s */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2642
		if (bytes > 25000) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2643
			if (packets > 35)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2644
				retval = low_latency;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2645
		} else if (bytes < 6000) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2646
			retval = low_latency;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2647
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2648
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2649
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2650
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2651
update_itr_done:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2652
	return retval;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2653
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2654
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2655
static void e1000_set_itr(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2656
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2657
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2658
	u16 current_itr;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2659
	u32 new_itr = adapter->itr;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2660
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2661
	if (unlikely(hw->mac_type < e1000_82540))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2662
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2663
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2664
	/* for non-gigabit speeds, just fix the interrupt rate at 4000 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2665
	if (unlikely(adapter->link_speed != SPEED_1000)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2666
		current_itr = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2667
		new_itr = 4000;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2668
		goto set_itr_now;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2669
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2670
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2671
	adapter->tx_itr = e1000_update_itr(adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2672
	                            adapter->tx_itr,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2673
	                            adapter->total_tx_packets,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2674
	                            adapter->total_tx_bytes);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2675
	/* conservative mode (itr 3) eliminates the lowest_latency setting */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2676
	if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2677
		adapter->tx_itr = low_latency;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2678
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2679
	adapter->rx_itr = e1000_update_itr(adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2680
	                            adapter->rx_itr,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2681
	                            adapter->total_rx_packets,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2682
	                            adapter->total_rx_bytes);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2683
	/* conservative mode (itr 3) eliminates the lowest_latency setting */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2684
	if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2685
		adapter->rx_itr = low_latency;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2686
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2687
	current_itr = max(adapter->rx_itr, adapter->tx_itr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2688
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2689
	switch (current_itr) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2690
	/* counts and packets in update_itr are dependent on these numbers */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2691
	case lowest_latency:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2692
		new_itr = 70000;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2693
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2694
	case low_latency:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2695
		new_itr = 20000; /* aka hwitr = ~200 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2696
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2697
	case bulk_latency:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2698
		new_itr = 4000;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2699
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2700
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2701
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2702
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2703
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2704
set_itr_now:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2705
	if (new_itr != adapter->itr) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2706
		/* this attempts to bias the interrupt rate towards Bulk
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2707
		 * by adding intermediate steps when interrupt rate is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2708
		 * increasing */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2709
		new_itr = new_itr > adapter->itr ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2710
		             min(adapter->itr + (new_itr >> 2), new_itr) :
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2711
		             new_itr;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2712
		adapter->itr = new_itr;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2713
		ew32(ITR, 1000000000 / (new_itr * 256));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2714
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2715
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2716
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2717
#define E1000_TX_FLAGS_CSUM		0x00000001
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2718
#define E1000_TX_FLAGS_VLAN		0x00000002
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2719
#define E1000_TX_FLAGS_TSO		0x00000004
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2720
#define E1000_TX_FLAGS_IPV4		0x00000008
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2721
#define E1000_TX_FLAGS_NO_FCS		0x00000010
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2722
#define E1000_TX_FLAGS_VLAN_MASK	0xffff0000
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2723
#define E1000_TX_FLAGS_VLAN_SHIFT	16
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2724
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2725
static int e1000_tso(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2726
		     struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2727
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2728
	struct e1000_context_desc *context_desc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2729
	struct e1000_buffer *buffer_info;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2730
	unsigned int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2731
	u32 cmd_length = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2732
	u16 ipcse = 0, tucse, mss;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2733
	u8 ipcss, ipcso, tucss, tucso, hdr_len;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2734
	int err;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2735
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2736
	if (skb_is_gso(skb)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2737
		if (skb_header_cloned(skb)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2738
			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2739
			if (err)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2740
				return err;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2741
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2742
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2743
		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2744
		mss = skb_shinfo(skb)->gso_size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2745
		if (skb->protocol == htons(ETH_P_IP)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2746
			struct iphdr *iph = ip_hdr(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2747
			iph->tot_len = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2748
			iph->check = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2749
			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2750
								 iph->daddr, 0,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2751
								 IPPROTO_TCP,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2752
								 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2753
			cmd_length = E1000_TXD_CMD_IP;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2754
			ipcse = skb_transport_offset(skb) - 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2755
		} else if (skb->protocol == htons(ETH_P_IPV6)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2756
			ipv6_hdr(skb)->payload_len = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2757
			tcp_hdr(skb)->check =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2758
				~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2759
						 &ipv6_hdr(skb)->daddr,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2760
						 0, IPPROTO_TCP, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2761
			ipcse = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2762
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2763
		ipcss = skb_network_offset(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2764
		ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2765
		tucss = skb_transport_offset(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2766
		tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2767
		tucse = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2768
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2769
		cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2770
			       E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2771
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2772
		i = tx_ring->next_to_use;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2773
		context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2774
		buffer_info = &tx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2775
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2776
		context_desc->lower_setup.ip_fields.ipcss  = ipcss;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2777
		context_desc->lower_setup.ip_fields.ipcso  = ipcso;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2778
		context_desc->lower_setup.ip_fields.ipcse  = cpu_to_le16(ipcse);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2779
		context_desc->upper_setup.tcp_fields.tucss = tucss;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2780
		context_desc->upper_setup.tcp_fields.tucso = tucso;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2781
		context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2782
		context_desc->tcp_seg_setup.fields.mss     = cpu_to_le16(mss);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2783
		context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2784
		context_desc->cmd_and_length = cpu_to_le32(cmd_length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2785
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2786
		buffer_info->time_stamp = jiffies;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2787
		buffer_info->next_to_watch = i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2788
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2789
		if (++i == tx_ring->count) i = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2790
		tx_ring->next_to_use = i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2791
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2792
		return true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2793
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2794
	return false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2795
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2796
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2797
static bool e1000_tx_csum(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2798
			  struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2799
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2800
	struct e1000_context_desc *context_desc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2801
	struct e1000_buffer *buffer_info;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2802
	unsigned int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2803
	u8 css;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2804
	u32 cmd_len = E1000_TXD_CMD_DEXT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2805
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2806
	if (skb->ip_summed != CHECKSUM_PARTIAL)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2807
		return false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2808
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2809
	switch (skb->protocol) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2810
	case cpu_to_be16(ETH_P_IP):
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2811
		if (ip_hdr(skb)->protocol == IPPROTO_TCP)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2812
			cmd_len |= E1000_TXD_CMD_TCP;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2813
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2814
	case cpu_to_be16(ETH_P_IPV6):
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2815
		/* XXX not handling all IPV6 headers */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2816
		if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2817
			cmd_len |= E1000_TXD_CMD_TCP;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2818
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2819
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2820
		if (unlikely(net_ratelimit()))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2821
			e_warn(drv, "checksum_partial proto=%x!\n",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2822
			       skb->protocol);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2823
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2824
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2825
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2826
	css = skb_checksum_start_offset(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2827
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2828
	i = tx_ring->next_to_use;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2829
	buffer_info = &tx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2830
	context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2831
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2832
	context_desc->lower_setup.ip_config = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2833
	context_desc->upper_setup.tcp_fields.tucss = css;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2834
	context_desc->upper_setup.tcp_fields.tucso =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2835
		css + skb->csum_offset;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2836
	context_desc->upper_setup.tcp_fields.tucse = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2837
	context_desc->tcp_seg_setup.data = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2838
	context_desc->cmd_and_length = cpu_to_le32(cmd_len);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2839
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2840
	buffer_info->time_stamp = jiffies;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2841
	buffer_info->next_to_watch = i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2842
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2843
	if (unlikely(++i == tx_ring->count)) i = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2844
	tx_ring->next_to_use = i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2845
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2846
	return true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2847
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2848
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2849
#define E1000_MAX_TXD_PWR	12
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2850
#define E1000_MAX_DATA_PER_TXD	(1<<E1000_MAX_TXD_PWR)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2851
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2852
static int e1000_tx_map(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2853
			struct e1000_tx_ring *tx_ring,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2854
			struct sk_buff *skb, unsigned int first,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2855
			unsigned int max_per_txd, unsigned int nr_frags,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2856
			unsigned int mss)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2857
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2858
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2859
	struct pci_dev *pdev = adapter->pdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2860
	struct e1000_buffer *buffer_info;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2861
	unsigned int len = skb_headlen(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2862
	unsigned int offset = 0, size, count = 0, i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2863
	unsigned int f, bytecount, segs;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2864
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2865
	i = tx_ring->next_to_use;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2866
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2867
	while (len) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2868
		buffer_info = &tx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2869
		size = min(len, max_per_txd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2870
		/* Workaround for Controller erratum --
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2871
		 * descriptor for non-tso packet in a linear SKB that follows a
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2872
		 * tso gets written back prematurely before the data is fully
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2873
		 * DMA'd to the controller */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2874
		if (!skb->data_len && tx_ring->last_tx_tso &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2875
		    !skb_is_gso(skb)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2876
			tx_ring->last_tx_tso = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2877
			size -= 4;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2878
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2879
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2880
		/* Workaround for premature desc write-backs
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2881
		 * in TSO mode.  Append 4-byte sentinel desc */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2882
		if (unlikely(mss && !nr_frags && size == len && size > 8))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2883
			size -= 4;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2884
		/* work-around for errata 10 and it applies
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2885
		 * to all controllers in PCI-X mode
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2886
		 * The fix is to make sure that the first descriptor of a
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2887
		 * packet is smaller than 2048 - 16 - 16 (or 2016) bytes
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2888
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2889
		if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2890
		                (size > 2015) && count == 0))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2891
		        size = 2015;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2892
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2893
		/* Workaround for potential 82544 hang in PCI-X.  Avoid
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2894
		 * terminating buffers within evenly-aligned dwords. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2895
		if (unlikely(adapter->pcix_82544 &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2896
		   !((unsigned long)(skb->data + offset + size - 1) & 4) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2897
		   size > 4))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2898
			size -= 4;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2899
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2900
		buffer_info->length = size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2901
		/* set time_stamp *before* dma to help avoid a possible race */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2902
		buffer_info->time_stamp = jiffies;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2903
		buffer_info->mapped_as_page = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2904
		buffer_info->dma = dma_map_single(&pdev->dev,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2905
						  skb->data + offset,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2906
						  size,	DMA_TO_DEVICE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2907
		if (dma_mapping_error(&pdev->dev, buffer_info->dma))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2908
			goto dma_error;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2909
		buffer_info->next_to_watch = i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2910
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2911
		len -= size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2912
		offset += size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2913
		count++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2914
		if (len) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2915
			i++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2916
			if (unlikely(i == tx_ring->count))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2917
				i = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2918
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2919
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2920
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2921
	for (f = 0; f < nr_frags; f++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2922
		const struct skb_frag_struct *frag;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2923
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2924
		frag = &skb_shinfo(skb)->frags[f];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2925
		len = skb_frag_size(frag);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2926
		offset = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2927
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2928
		while (len) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2929
			unsigned long bufend;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2930
			i++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2931
			if (unlikely(i == tx_ring->count))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2932
				i = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2933
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2934
			buffer_info = &tx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2935
			size = min(len, max_per_txd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2936
			/* Workaround for premature desc write-backs
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2937
			 * in TSO mode.  Append 4-byte sentinel desc */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2938
			if (unlikely(mss && f == (nr_frags-1) && size == len && size > 8))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2939
				size -= 4;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2940
			/* Workaround for potential 82544 hang in PCI-X.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2941
			 * Avoid terminating buffers within evenly-aligned
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2942
			 * dwords. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2943
			bufend = (unsigned long)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2944
				page_to_phys(skb_frag_page(frag));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2945
			bufend += offset + size - 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2946
			if (unlikely(adapter->pcix_82544 &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2947
				     !(bufend & 4) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2948
				     size > 4))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2949
				size -= 4;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2950
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2951
			buffer_info->length = size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2952
			buffer_info->time_stamp = jiffies;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2953
			buffer_info->mapped_as_page = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2954
			buffer_info->dma = skb_frag_dma_map(&pdev->dev, frag,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2955
						offset, size, DMA_TO_DEVICE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2956
			if (dma_mapping_error(&pdev->dev, buffer_info->dma))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2957
				goto dma_error;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2958
			buffer_info->next_to_watch = i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2959
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2960
			len -= size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2961
			offset += size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2962
			count++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2963
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2964
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2965
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2966
	segs = skb_shinfo(skb)->gso_segs ?: 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2967
	/* multiply data chunks by size of headers */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2968
	bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2969
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2970
	tx_ring->buffer_info[i].skb = skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2971
	tx_ring->buffer_info[i].segs = segs;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2972
	tx_ring->buffer_info[i].bytecount = bytecount;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2973
	tx_ring->buffer_info[first].next_to_watch = i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2974
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2975
	return count;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2976
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2977
dma_error:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2978
	dev_err(&pdev->dev, "TX DMA map failed\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2979
	buffer_info->dma = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2980
	if (count)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2981
		count--;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2982
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2983
	while (count--) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2984
		if (i==0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2985
			i += tx_ring->count;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2986
		i--;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2987
		buffer_info = &tx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2988
		e1000_unmap_and_free_tx_resource(adapter, buffer_info);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2989
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2990
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2991
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2992
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2993
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2994
static void e1000_tx_queue(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2995
			   struct e1000_tx_ring *tx_ring, int tx_flags,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2996
			   int count)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2997
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2998
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2999
	struct e1000_tx_desc *tx_desc = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3000
	struct e1000_buffer *buffer_info;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3001
	u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3002
	unsigned int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3003
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3004
	if (likely(tx_flags & E1000_TX_FLAGS_TSO)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3005
		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3006
		             E1000_TXD_CMD_TSE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3007
		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3008
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3009
		if (likely(tx_flags & E1000_TX_FLAGS_IPV4))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3010
			txd_upper |= E1000_TXD_POPTS_IXSM << 8;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3011
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3012
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3013
	if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3014
		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3015
		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3016
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3017
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3018
	if (unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3019
		txd_lower |= E1000_TXD_CMD_VLE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3020
		txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3021
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3022
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3023
	if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3024
		txd_lower &= ~(E1000_TXD_CMD_IFCS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3025
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3026
	i = tx_ring->next_to_use;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3027
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3028
	while (count--) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3029
		buffer_info = &tx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3030
		tx_desc = E1000_TX_DESC(*tx_ring, i);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3031
		tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3032
		tx_desc->lower.data =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3033
			cpu_to_le32(txd_lower | buffer_info->length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3034
		tx_desc->upper.data = cpu_to_le32(txd_upper);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3035
		if (unlikely(++i == tx_ring->count)) i = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3036
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3037
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3038
	tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3039
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3040
	/* txd_cmd re-enables FCS, so we'll re-disable it here as desired. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3041
	if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3042
		tx_desc->lower.data &= ~(cpu_to_le32(E1000_TXD_CMD_IFCS));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3043
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3044
	/* Force memory writes to complete before letting h/w
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3045
	 * know there are new descriptors to fetch.  (Only
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3046
	 * applicable for weak-ordered memory model archs,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3047
	 * such as IA-64). */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3048
	wmb();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3049
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3050
	tx_ring->next_to_use = i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3051
	writel(i, hw->hw_addr + tx_ring->tdt);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3052
	/* we need this if more than one processor can write to our tail
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3053
	 * at a time, it syncronizes IO on IA64/Altix systems */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3054
	mmiowb();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3055
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3056
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3057
/* 82547 workaround to avoid controller hang in half-duplex environment.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3058
 * The workaround is to avoid queuing a large packet that would span
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3059
 * the internal Tx FIFO ring boundary by notifying the stack to resend
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3060
 * the packet at a later time.  This gives the Tx FIFO an opportunity to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3061
 * flush all packets.  When that occurs, we reset the Tx FIFO pointers
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3062
 * to the beginning of the Tx FIFO.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3063
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3064
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3065
#define E1000_FIFO_HDR			0x10
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3066
#define E1000_82547_PAD_LEN		0x3E0
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3067
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3068
static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3069
				       struct sk_buff *skb)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3070
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3071
	u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3072
	u32 skb_fifo_len = skb->len + E1000_FIFO_HDR;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3073
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3074
	skb_fifo_len = ALIGN(skb_fifo_len, E1000_FIFO_HDR);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3075
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3076
	if (adapter->link_duplex != HALF_DUPLEX)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3077
		goto no_fifo_stall_required;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3078
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3079
	if (atomic_read(&adapter->tx_fifo_stall))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3080
		return 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3081
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3082
	if (skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3083
		atomic_set(&adapter->tx_fifo_stall, 1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3084
		return 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3085
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3086
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3087
no_fifo_stall_required:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3088
	adapter->tx_fifo_head += skb_fifo_len;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3089
	if (adapter->tx_fifo_head >= adapter->tx_fifo_size)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3090
		adapter->tx_fifo_head -= adapter->tx_fifo_size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3091
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3092
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3093
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3094
static int __e1000_maybe_stop_tx(struct net_device *netdev, int size)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3095
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3096
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3097
	struct e1000_tx_ring *tx_ring = adapter->tx_ring;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3098
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3099
	netif_stop_queue(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3100
	/* Herbert's original patch had:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3101
	 *  smp_mb__after_netif_stop_queue();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3102
	 * but since that doesn't exist yet, just open code it. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3103
	smp_mb();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3104
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3105
	/* We need to check again in a case another CPU has just
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3106
	 * made room available. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3107
	if (likely(E1000_DESC_UNUSED(tx_ring) < size))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3108
		return -EBUSY;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3109
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3110
	/* A reprieve! */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3111
	netif_start_queue(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3112
	++adapter->restart_queue;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3113
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3114
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3115
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3116
static int e1000_maybe_stop_tx(struct net_device *netdev,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3117
                               struct e1000_tx_ring *tx_ring, int size)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3118
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3119
	if (likely(E1000_DESC_UNUSED(tx_ring) >= size))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3120
		return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3121
	return __e1000_maybe_stop_tx(netdev, size);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3122
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3123
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3124
#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 )
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3125
static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3126
				    struct net_device *netdev)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3127
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3128
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3129
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3130
	struct e1000_tx_ring *tx_ring;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3131
	unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3132
	unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3133
	unsigned int tx_flags = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3134
	unsigned int len = skb_headlen(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3135
	unsigned int nr_frags;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3136
	unsigned int mss;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3137
	int count = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3138
	int tso;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3139
	unsigned int f;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3140
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3141
	/* This goes back to the question of how to logically map a tx queue
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3142
	 * to a flow.  Right now, performance is impacted slightly negatively
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3143
	 * if using multiple tx queues.  If the stack breaks away from a
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3144
	 * single qdisc implementation, we can look at this again. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3145
	tx_ring = adapter->tx_ring;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3146
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3147
	if (unlikely(skb->len <= 0)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3148
		dev_kfree_skb_any(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3149
		return NETDEV_TX_OK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3150
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3151
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3152
	/* On PCI/PCI-X HW, if packet size is less than ETH_ZLEN,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3153
	 * packets may get corrupted during padding by HW.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3154
	 * To WA this issue, pad all small packets manually.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3155
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3156
	if (skb->len < ETH_ZLEN) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3157
		if (skb_pad(skb, ETH_ZLEN - skb->len))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3158
			return NETDEV_TX_OK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3159
		skb->len = ETH_ZLEN;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3160
		skb_set_tail_pointer(skb, ETH_ZLEN);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3161
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3162
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3163
	mss = skb_shinfo(skb)->gso_size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3164
	/* The controller does a simple calculation to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3165
	 * make sure there is enough room in the FIFO before
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3166
	 * initiating the DMA for each buffer.  The calc is:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3167
	 * 4 = ceil(buffer len/mss).  To make sure we don't
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3168
	 * overrun the FIFO, adjust the max buffer len if mss
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3169
	 * drops. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3170
	if (mss) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3171
		u8 hdr_len;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3172
		max_per_txd = min(mss << 2, max_per_txd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3173
		max_txd_pwr = fls(max_per_txd) - 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3174
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3175
		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3176
		if (skb->data_len && hdr_len == len) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3177
			switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3178
				unsigned int pull_size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3179
			case e1000_82544:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3180
				/* Make sure we have room to chop off 4 bytes,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3181
				 * and that the end alignment will work out to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3182
				 * this hardware's requirements
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3183
				 * NOTE: this is a TSO only workaround
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3184
				 * if end byte alignment not correct move us
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3185
				 * into the next dword */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3186
				if ((unsigned long)(skb_tail_pointer(skb) - 1) & 4)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3187
					break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3188
				/* fall through */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3189
				pull_size = min((unsigned int)4, skb->data_len);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3190
				if (!__pskb_pull_tail(skb, pull_size)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3191
					e_err(drv, "__pskb_pull_tail "
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3192
					      "failed.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3193
					dev_kfree_skb_any(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3194
					return NETDEV_TX_OK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3195
				}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3196
				len = skb_headlen(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3197
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3198
			default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3199
				/* do nothing */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3200
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3201
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3202
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3203
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3204
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3205
	/* reserve a descriptor for the offload context */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3206
	if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3207
		count++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3208
	count++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3209
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3210
	/* Controller Erratum workaround */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3211
	if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3212
		count++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3213
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3214
	count += TXD_USE_COUNT(len, max_txd_pwr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3215
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3216
	if (adapter->pcix_82544)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3217
		count++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3218
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3219
	/* work-around for errata 10 and it applies to all controllers
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3220
	 * in PCI-X mode, so add one more descriptor to the count
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3221
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3222
	if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3223
			(len > 2015)))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3224
		count++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3225
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3226
	nr_frags = skb_shinfo(skb)->nr_frags;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3227
	for (f = 0; f < nr_frags; f++)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3228
		count += TXD_USE_COUNT(skb_frag_size(&skb_shinfo(skb)->frags[f]),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3229
				       max_txd_pwr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3230
	if (adapter->pcix_82544)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3231
		count += nr_frags;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3232
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3233
	/* need: count + 2 desc gap to keep tail from touching
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3234
	 * head, otherwise try next time */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3235
	if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2)))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3236
		return NETDEV_TX_BUSY;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3237
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3238
	if (unlikely((hw->mac_type == e1000_82547) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3239
		     (e1000_82547_fifo_workaround(adapter, skb)))) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3240
		netif_stop_queue(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3241
		if (!test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3242
			schedule_delayed_work(&adapter->fifo_stall_task, 1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3243
		return NETDEV_TX_BUSY;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3244
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3245
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3246
	if (vlan_tx_tag_present(skb)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3247
		tx_flags |= E1000_TX_FLAGS_VLAN;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3248
		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3249
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3250
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3251
	first = tx_ring->next_to_use;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3252
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3253
	tso = e1000_tso(adapter, tx_ring, skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3254
	if (tso < 0) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3255
		dev_kfree_skb_any(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3256
		return NETDEV_TX_OK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3257
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3258
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3259
	if (likely(tso)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3260
		if (likely(hw->mac_type != e1000_82544))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3261
			tx_ring->last_tx_tso = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3262
		tx_flags |= E1000_TX_FLAGS_TSO;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3263
	} else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3264
		tx_flags |= E1000_TX_FLAGS_CSUM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3265
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3266
	if (likely(skb->protocol == htons(ETH_P_IP)))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3267
		tx_flags |= E1000_TX_FLAGS_IPV4;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3268
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3269
	if (unlikely(skb->no_fcs))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3270
		tx_flags |= E1000_TX_FLAGS_NO_FCS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3271
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3272
	count = e1000_tx_map(adapter, tx_ring, skb, first, max_per_txd,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3273
	                     nr_frags, mss);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3274
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3275
	if (count) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3276
		skb_tx_timestamp(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3277
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3278
		e1000_tx_queue(adapter, tx_ring, tx_flags, count);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3279
		/* Make sure there is space in the ring for the next send. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3280
		e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3281
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3282
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3283
		dev_kfree_skb_any(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3284
		tx_ring->buffer_info[first].time_stamp = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3285
		tx_ring->next_to_use = first;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3286
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3287
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3288
	return NETDEV_TX_OK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3289
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3290
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3291
#define NUM_REGS 38 /* 1 based count */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3292
static void e1000_regdump(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3293
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3294
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3295
	u32 regs[NUM_REGS];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3296
	u32 *regs_buff = regs;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3297
	int i = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3298
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3299
	static const char * const reg_name[] = {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3300
		"CTRL",  "STATUS",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3301
		"RCTL", "RDLEN", "RDH", "RDT", "RDTR",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3302
		"TCTL", "TDBAL", "TDBAH", "TDLEN", "TDH", "TDT",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3303
		"TIDV", "TXDCTL", "TADV", "TARC0",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3304
		"TDBAL1", "TDBAH1", "TDLEN1", "TDH1", "TDT1",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3305
		"TXDCTL1", "TARC1",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3306
		"CTRL_EXT", "ERT", "RDBAL", "RDBAH",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3307
		"TDFH", "TDFT", "TDFHS", "TDFTS", "TDFPC",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3308
		"RDFH", "RDFT", "RDFHS", "RDFTS", "RDFPC"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3309
	};
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3310
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3311
	regs_buff[0]  = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3312
	regs_buff[1]  = er32(STATUS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3313
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3314
	regs_buff[2]  = er32(RCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3315
	regs_buff[3]  = er32(RDLEN);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3316
	regs_buff[4]  = er32(RDH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3317
	regs_buff[5]  = er32(RDT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3318
	regs_buff[6]  = er32(RDTR);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3319
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3320
	regs_buff[7]  = er32(TCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3321
	regs_buff[8]  = er32(TDBAL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3322
	regs_buff[9]  = er32(TDBAH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3323
	regs_buff[10] = er32(TDLEN);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3324
	regs_buff[11] = er32(TDH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3325
	regs_buff[12] = er32(TDT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3326
	regs_buff[13] = er32(TIDV);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3327
	regs_buff[14] = er32(TXDCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3328
	regs_buff[15] = er32(TADV);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3329
	regs_buff[16] = er32(TARC0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3330
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3331
	regs_buff[17] = er32(TDBAL1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3332
	regs_buff[18] = er32(TDBAH1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3333
	regs_buff[19] = er32(TDLEN1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3334
	regs_buff[20] = er32(TDH1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3335
	regs_buff[21] = er32(TDT1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3336
	regs_buff[22] = er32(TXDCTL1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3337
	regs_buff[23] = er32(TARC1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3338
	regs_buff[24] = er32(CTRL_EXT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3339
	regs_buff[25] = er32(ERT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3340
	regs_buff[26] = er32(RDBAL0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3341
	regs_buff[27] = er32(RDBAH0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3342
	regs_buff[28] = er32(TDFH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3343
	regs_buff[29] = er32(TDFT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3344
	regs_buff[30] = er32(TDFHS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3345
	regs_buff[31] = er32(TDFTS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3346
	regs_buff[32] = er32(TDFPC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3347
	regs_buff[33] = er32(RDFH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3348
	regs_buff[34] = er32(RDFT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3349
	regs_buff[35] = er32(RDFHS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3350
	regs_buff[36] = er32(RDFTS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3351
	regs_buff[37] = er32(RDFPC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3352
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3353
	pr_info("Register dump\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3354
	for (i = 0; i < NUM_REGS; i++)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3355
		pr_info("%-15s  %08x\n", reg_name[i], regs_buff[i]);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3356
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3357
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3358
/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3359
 * e1000_dump: Print registers, tx ring and rx ring
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3360
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3361
static void e1000_dump(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3362
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3363
	/* this code doesn't handle multiple rings */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3364
	struct e1000_tx_ring *tx_ring = adapter->tx_ring;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3365
	struct e1000_rx_ring *rx_ring = adapter->rx_ring;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3366
	int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3367
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3368
	if (!netif_msg_hw(adapter))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3369
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3370
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3371
	/* Print Registers */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3372
	e1000_regdump(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3373
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3374
	/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3375
	 * transmit dump
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3376
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3377
	pr_info("TX Desc ring0 dump\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3378
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3379
	/* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3380
	 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3381
	 * Legacy Transmit Descriptor
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3382
	 *   +--------------------------------------------------------------+
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3383
	 * 0 |         Buffer Address [63:0] (Reserved on Write Back)       |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3384
	 *   +--------------------------------------------------------------+
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3385
	 * 8 | Special  |    CSS     | Status |  CMD    |  CSO   |  Length  |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3386
	 *   +--------------------------------------------------------------+
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3387
	 *   63       48 47        36 35    32 31     24 23    16 15        0
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3388
	 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3389
	 * Extended Context Descriptor (DTYP=0x0) for TSO or checksum offload
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3390
	 *   63      48 47    40 39       32 31             16 15    8 7      0
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3391
	 *   +----------------------------------------------------------------+
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3392
	 * 0 |  TUCSE  | TUCS0  |   TUCSS   |     IPCSE       | IPCS0 | IPCSS |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3393
	 *   +----------------------------------------------------------------+
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3394
	 * 8 |   MSS   | HDRLEN | RSV | STA | TUCMD | DTYP |      PAYLEN      |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3395
	 *   +----------------------------------------------------------------+
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3396
	 *   63      48 47    40 39 36 35 32 31   24 23  20 19                0
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3397
	 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3398
	 * Extended Data Descriptor (DTYP=0x1)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3399
	 *   +----------------------------------------------------------------+
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3400
	 * 0 |                     Buffer Address [63:0]                      |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3401
	 *   +----------------------------------------------------------------+
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3402
	 * 8 | VLAN tag |  POPTS  | Rsvd | Status | Command | DTYP |  DTALEN  |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3403
	 *   +----------------------------------------------------------------+
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3404
	 *   63       48 47     40 39  36 35    32 31     24 23  20 19        0
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3405
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3406
	pr_info("Tc[desc]     [Ce CoCsIpceCoS] [MssHlRSCm0Plen] [bi->dma       ] leng  ntw timestmp         bi->skb\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3407
	pr_info("Td[desc]     [address 63:0  ] [VlaPoRSCm1Dlen] [bi->dma       ] leng  ntw timestmp         bi->skb\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3408
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3409
	if (!netif_msg_tx_done(adapter))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3410
		goto rx_ring_summary;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3411
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3412
	for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3413
		struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3414
		struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3415
		struct my_u { __le64 a; __le64 b; };
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3416
		struct my_u *u = (struct my_u *)tx_desc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3417
		const char *type;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3418
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3419
		if (i == tx_ring->next_to_use && i == tx_ring->next_to_clean)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3420
			type = "NTC/U";
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3421
		else if (i == tx_ring->next_to_use)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3422
			type = "NTU";
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3423
		else if (i == tx_ring->next_to_clean)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3424
			type = "NTC";
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3425
		else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3426
			type = "";
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3427
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3428
		pr_info("T%c[0x%03X]    %016llX %016llX %016llX %04X  %3X %016llX %p %s\n",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3429
			((le64_to_cpu(u->b) & (1<<20)) ? 'd' : 'c'), i,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3430
			le64_to_cpu(u->a), le64_to_cpu(u->b),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3431
			(u64)buffer_info->dma, buffer_info->length,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3432
			buffer_info->next_to_watch,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3433
			(u64)buffer_info->time_stamp, buffer_info->skb, type);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3434
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3435
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3436
rx_ring_summary:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3437
	/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3438
	 * receive dump
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3439
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3440
	pr_info("\nRX Desc ring dump\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3441
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3442
	/* Legacy Receive Descriptor Format
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3443
	 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3444
	 * +-----------------------------------------------------+
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3445
	 * |                Buffer Address [63:0]                |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3446
	 * +-----------------------------------------------------+
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3447
	 * | VLAN Tag | Errors | Status 0 | Packet csum | Length |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3448
	 * +-----------------------------------------------------+
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3449
	 * 63       48 47    40 39      32 31         16 15      0
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3450
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3451
	pr_info("R[desc]      [address 63:0  ] [vl er S cks ln] [bi->dma       ] [bi->skb]\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3452
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3453
	if (!netif_msg_rx_status(adapter))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3454
		goto exit;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3455
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3456
	for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3457
		struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3458
		struct e1000_buffer *buffer_info = &rx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3459
		struct my_u { __le64 a; __le64 b; };
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3460
		struct my_u *u = (struct my_u *)rx_desc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3461
		const char *type;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3462
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3463
		if (i == rx_ring->next_to_use)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3464
			type = "NTU";
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3465
		else if (i == rx_ring->next_to_clean)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3466
			type = "NTC";
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3467
		else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3468
			type = "";
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3469
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3470
		pr_info("R[0x%03X]     %016llX %016llX %016llX %p %s\n",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3471
			i, le64_to_cpu(u->a), le64_to_cpu(u->b),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3472
			(u64)buffer_info->dma, buffer_info->skb, type);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3473
	} /* for */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3474
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3475
	/* dump the descriptor caches */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3476
	/* rx */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3477
	pr_info("Rx descriptor cache in 64bit format\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3478
	for (i = 0x6000; i <= 0x63FF ; i += 0x10) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3479
		pr_info("R%04X: %08X|%08X %08X|%08X\n",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3480
			i,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3481
			readl(adapter->hw.hw_addr + i+4),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3482
			readl(adapter->hw.hw_addr + i),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3483
			readl(adapter->hw.hw_addr + i+12),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3484
			readl(adapter->hw.hw_addr + i+8));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3485
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3486
	/* tx */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3487
	pr_info("Tx descriptor cache in 64bit format\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3488
	for (i = 0x7000; i <= 0x73FF ; i += 0x10) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3489
		pr_info("T%04X: %08X|%08X %08X|%08X\n",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3490
			i,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3491
			readl(adapter->hw.hw_addr + i+4),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3492
			readl(adapter->hw.hw_addr + i),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3493
			readl(adapter->hw.hw_addr + i+12),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3494
			readl(adapter->hw.hw_addr + i+8));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3495
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3496
exit:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3497
	return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3498
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3499
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3500
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3501
 * e1000_tx_timeout - Respond to a Tx Hang
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3502
 * @netdev: network interface device structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3503
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3504
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3505
static void e1000_tx_timeout(struct net_device *netdev)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3506
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3507
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3508
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3509
	/* Do the reset outside of interrupt context */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3510
	adapter->tx_timeout_count++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3511
	schedule_work(&adapter->reset_task);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3512
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3513
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3514
static void e1000_reset_task(struct work_struct *work)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3515
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3516
	struct e1000_adapter *adapter =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3517
		container_of(work, struct e1000_adapter, reset_task);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3518
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3519
	if (test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3520
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3521
	e_err(drv, "Reset adapter\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3522
	e1000_reinit_safe(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3523
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3524
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3525
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3526
 * e1000_get_stats - Get System Network Statistics
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3527
 * @netdev: network interface device structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3528
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3529
 * Returns the address of the device statistics structure.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3530
 * The statistics are actually updated from the watchdog.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3531
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3532
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3533
static struct net_device_stats *e1000_get_stats(struct net_device *netdev)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3534
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3535
	/* only return the current stats */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3536
	return &netdev->stats;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3537
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3538
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3539
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3540
 * e1000_change_mtu - Change the Maximum Transfer Unit
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3541
 * @netdev: network interface device structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3542
 * @new_mtu: new value for maximum frame size
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3543
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3544
 * Returns 0 on success, negative on failure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3545
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3546
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3547
static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3548
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3549
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3550
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3551
	int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3552
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3553
	if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3554
	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3555
		e_err(probe, "Invalid MTU setting\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3556
		return -EINVAL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3557
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3558
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3559
	/* Adapter-specific max frame size limits. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3560
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3561
	case e1000_undefined ... e1000_82542_rev2_1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3562
		if (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3563
			e_err(probe, "Jumbo Frames not supported.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3564
			return -EINVAL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3565
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3566
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3567
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3568
		/* Capable of supporting up to MAX_JUMBO_FRAME_SIZE limit. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3569
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3570
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3571
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3572
	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3573
		msleep(1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3574
	/* e1000_down has a dependency on max_frame_size */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3575
	hw->max_frame_size = max_frame;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3576
	if (netif_running(netdev))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3577
		e1000_down(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3578
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3579
	/* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3580
	 * means we reserve 2 more, this pushes us to allocate from the next
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3581
	 * larger slab size.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3582
	 * i.e. RXBUFFER_2048 --> size-4096 slab
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3583
	 *  however with the new *_jumbo_rx* routines, jumbo receives will use
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3584
	 *  fragmented skbs */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3585
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3586
	if (max_frame <= E1000_RXBUFFER_2048)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3587
		adapter->rx_buffer_len = E1000_RXBUFFER_2048;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3588
	else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3589
#if (PAGE_SIZE >= E1000_RXBUFFER_16384)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3590
		adapter->rx_buffer_len = E1000_RXBUFFER_16384;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3591
#elif (PAGE_SIZE >= E1000_RXBUFFER_4096)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3592
		adapter->rx_buffer_len = PAGE_SIZE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3593
#endif
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3594
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3595
	/* adjust allocation if LPE protects us, and we aren't using SBP */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3596
	if (!hw->tbi_compatibility_on &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3597
	    ((max_frame == (ETH_FRAME_LEN + ETH_FCS_LEN)) ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3598
	     (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3599
		adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3600
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3601
	pr_info("%s changing MTU from %d to %d\n",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3602
		netdev->name, netdev->mtu, new_mtu);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3603
	netdev->mtu = new_mtu;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3604
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3605
	if (netif_running(netdev))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3606
		e1000_up(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3607
	else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3608
		e1000_reset(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3609
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3610
	clear_bit(__E1000_RESETTING, &adapter->flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3611
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3612
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3613
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3614
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3615
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3616
 * e1000_update_stats - Update the board statistics counters
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3617
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3618
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3619
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3620
void e1000_update_stats(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3621
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3622
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3623
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3624
	struct pci_dev *pdev = adapter->pdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3625
	unsigned long flags;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3626
	u16 phy_tmp;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3627
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3628
#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3629
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3630
	/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3631
	 * Prevent stats update while adapter is being reset, or if the pci
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3632
	 * connection is down.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3633
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3634
	if (adapter->link_speed == 0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3635
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3636
	if (pci_channel_offline(pdev))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3637
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3638
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3639
	spin_lock_irqsave(&adapter->stats_lock, flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3640
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3641
	/* these counters are modified from e1000_tbi_adjust_stats,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3642
	 * called from the interrupt context, so they must only
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3643
	 * be written while holding adapter->stats_lock
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3644
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3645
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3646
	adapter->stats.crcerrs += er32(CRCERRS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3647
	adapter->stats.gprc += er32(GPRC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3648
	adapter->stats.gorcl += er32(GORCL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3649
	adapter->stats.gorch += er32(GORCH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3650
	adapter->stats.bprc += er32(BPRC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3651
	adapter->stats.mprc += er32(MPRC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3652
	adapter->stats.roc += er32(ROC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3653
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3654
	adapter->stats.prc64 += er32(PRC64);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3655
	adapter->stats.prc127 += er32(PRC127);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3656
	adapter->stats.prc255 += er32(PRC255);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3657
	adapter->stats.prc511 += er32(PRC511);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3658
	adapter->stats.prc1023 += er32(PRC1023);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3659
	adapter->stats.prc1522 += er32(PRC1522);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3660
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3661
	adapter->stats.symerrs += er32(SYMERRS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3662
	adapter->stats.mpc += er32(MPC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3663
	adapter->stats.scc += er32(SCC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3664
	adapter->stats.ecol += er32(ECOL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3665
	adapter->stats.mcc += er32(MCC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3666
	adapter->stats.latecol += er32(LATECOL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3667
	adapter->stats.dc += er32(DC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3668
	adapter->stats.sec += er32(SEC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3669
	adapter->stats.rlec += er32(RLEC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3670
	adapter->stats.xonrxc += er32(XONRXC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3671
	adapter->stats.xontxc += er32(XONTXC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3672
	adapter->stats.xoffrxc += er32(XOFFRXC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3673
	adapter->stats.xofftxc += er32(XOFFTXC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3674
	adapter->stats.fcruc += er32(FCRUC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3675
	adapter->stats.gptc += er32(GPTC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3676
	adapter->stats.gotcl += er32(GOTCL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3677
	adapter->stats.gotch += er32(GOTCH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3678
	adapter->stats.rnbc += er32(RNBC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3679
	adapter->stats.ruc += er32(RUC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3680
	adapter->stats.rfc += er32(RFC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3681
	adapter->stats.rjc += er32(RJC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3682
	adapter->stats.torl += er32(TORL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3683
	adapter->stats.torh += er32(TORH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3684
	adapter->stats.totl += er32(TOTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3685
	adapter->stats.toth += er32(TOTH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3686
	adapter->stats.tpr += er32(TPR);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3687
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3688
	adapter->stats.ptc64 += er32(PTC64);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3689
	adapter->stats.ptc127 += er32(PTC127);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3690
	adapter->stats.ptc255 += er32(PTC255);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3691
	adapter->stats.ptc511 += er32(PTC511);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3692
	adapter->stats.ptc1023 += er32(PTC1023);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3693
	adapter->stats.ptc1522 += er32(PTC1522);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3694
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3695
	adapter->stats.mptc += er32(MPTC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3696
	adapter->stats.bptc += er32(BPTC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3697
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3698
	/* used for adaptive IFS */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3699
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3700
	hw->tx_packet_delta = er32(TPT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3701
	adapter->stats.tpt += hw->tx_packet_delta;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3702
	hw->collision_delta = er32(COLC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3703
	adapter->stats.colc += hw->collision_delta;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3704
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3705
	if (hw->mac_type >= e1000_82543) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3706
		adapter->stats.algnerrc += er32(ALGNERRC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3707
		adapter->stats.rxerrc += er32(RXERRC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3708
		adapter->stats.tncrs += er32(TNCRS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3709
		adapter->stats.cexterr += er32(CEXTERR);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3710
		adapter->stats.tsctc += er32(TSCTC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3711
		adapter->stats.tsctfc += er32(TSCTFC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3712
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3713
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3714
	/* Fill out the OS statistics structure */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3715
	netdev->stats.multicast = adapter->stats.mprc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3716
	netdev->stats.collisions = adapter->stats.colc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3717
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3718
	/* Rx Errors */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3719
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3720
	/* RLEC on some newer hardware can be incorrect so build
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3721
	* our own version based on RUC and ROC */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3722
	netdev->stats.rx_errors = adapter->stats.rxerrc +
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3723
		adapter->stats.crcerrs + adapter->stats.algnerrc +
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3724
		adapter->stats.ruc + adapter->stats.roc +
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3725
		adapter->stats.cexterr;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3726
	adapter->stats.rlerrc = adapter->stats.ruc + adapter->stats.roc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3727
	netdev->stats.rx_length_errors = adapter->stats.rlerrc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3728
	netdev->stats.rx_crc_errors = adapter->stats.crcerrs;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3729
	netdev->stats.rx_frame_errors = adapter->stats.algnerrc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3730
	netdev->stats.rx_missed_errors = adapter->stats.mpc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3731
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3732
	/* Tx Errors */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3733
	adapter->stats.txerrc = adapter->stats.ecol + adapter->stats.latecol;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3734
	netdev->stats.tx_errors = adapter->stats.txerrc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3735
	netdev->stats.tx_aborted_errors = adapter->stats.ecol;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3736
	netdev->stats.tx_window_errors = adapter->stats.latecol;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3737
	netdev->stats.tx_carrier_errors = adapter->stats.tncrs;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3738
	if (hw->bad_tx_carr_stats_fd &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3739
	    adapter->link_duplex == FULL_DUPLEX) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3740
		netdev->stats.tx_carrier_errors = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3741
		adapter->stats.tncrs = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3742
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3743
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3744
	/* Tx Dropped needs to be maintained elsewhere */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3745
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3746
	/* Phy Stats */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3747
	if (hw->media_type == e1000_media_type_copper) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3748
		if ((adapter->link_speed == SPEED_1000) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3749
		   (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3750
			phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3751
			adapter->phy_stats.idle_errors += phy_tmp;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3752
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3753
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3754
		if ((hw->mac_type <= e1000_82546) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3755
		   (hw->phy_type == e1000_phy_m88) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3756
		   !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3757
			adapter->phy_stats.receive_errors += phy_tmp;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3758
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3759
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3760
	/* Management Stats */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3761
	if (hw->has_smbus) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3762
		adapter->stats.mgptc += er32(MGTPTC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3763
		adapter->stats.mgprc += er32(MGTPRC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3764
		adapter->stats.mgpdc += er32(MGTPDC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3765
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3766
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3767
	spin_unlock_irqrestore(&adapter->stats_lock, flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3768
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3769
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3770
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3771
 * e1000_intr - Interrupt Handler
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3772
 * @irq: interrupt number
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3773
 * @data: pointer to a network interface device structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3774
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3775
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3776
static irqreturn_t e1000_intr(int irq, void *data)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3777
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3778
	struct net_device *netdev = data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3779
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3780
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3781
	u32 icr = er32(ICR);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3782
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3783
	if (unlikely((!icr)))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3784
		return IRQ_NONE;  /* Not our interrupt */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3785
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3786
	/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3787
	 * we might have caused the interrupt, but the above
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3788
	 * read cleared it, and just in case the driver is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3789
	 * down there is nothing to do so return handled
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3790
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3791
	if (unlikely(test_bit(__E1000_DOWN, &adapter->flags)))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3792
		return IRQ_HANDLED;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3793
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3794
	if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3795
		hw->get_link_status = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3796
		/* guard against interrupt when we're going down */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3797
		if (!test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3798
			schedule_delayed_work(&adapter->watchdog_task, 1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3799
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3800
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3801
	/* disable interrupts, without the synchronize_irq bit */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3802
	ew32(IMC, ~0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3803
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3804
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3805
	if (likely(napi_schedule_prep(&adapter->napi))) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3806
		adapter->total_tx_bytes = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3807
		adapter->total_tx_packets = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3808
		adapter->total_rx_bytes = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3809
		adapter->total_rx_packets = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3810
		__napi_schedule(&adapter->napi);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3811
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3812
		/* this really should not happen! if it does it is basically a
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3813
		 * bug, but not a hard error, so enable ints and continue */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3814
		if (!test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3815
			e1000_irq_enable(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3816
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3817
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3818
	return IRQ_HANDLED;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3819
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3820
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3821
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3822
 * e1000_clean - NAPI Rx polling callback
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3823
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3824
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3825
static int e1000_clean(struct napi_struct *napi, int budget)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3826
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3827
	struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3828
	int tx_clean_complete = 0, work_done = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3829
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3830
	tx_clean_complete = e1000_clean_tx_irq(adapter, &adapter->tx_ring[0]);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3831
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3832
	adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3833
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3834
	if (!tx_clean_complete)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3835
		work_done = budget;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3836
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3837
	/* If budget not fully consumed, exit the polling mode */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3838
	if (work_done < budget) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3839
		if (likely(adapter->itr_setting & 3))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3840
			e1000_set_itr(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3841
		napi_complete(napi);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3842
		if (!test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3843
			e1000_irq_enable(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3844
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3845
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3846
	return work_done;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3847
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3848
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3849
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3850
 * e1000_clean_tx_irq - Reclaim resources after transmit completes
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3851
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3852
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3853
static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3854
			       struct e1000_tx_ring *tx_ring)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3855
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3856
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3857
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3858
	struct e1000_tx_desc *tx_desc, *eop_desc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3859
	struct e1000_buffer *buffer_info;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3860
	unsigned int i, eop;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3861
	unsigned int count = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3862
	unsigned int total_tx_bytes=0, total_tx_packets=0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3863
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3864
	i = tx_ring->next_to_clean;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3865
	eop = tx_ring->buffer_info[i].next_to_watch;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3866
	eop_desc = E1000_TX_DESC(*tx_ring, eop);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3867
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3868
	while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3869
	       (count < tx_ring->count)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3870
		bool cleaned = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3871
		rmb();	/* read buffer_info after eop_desc */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3872
		for ( ; !cleaned; count++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3873
			tx_desc = E1000_TX_DESC(*tx_ring, i);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3874
			buffer_info = &tx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3875
			cleaned = (i == eop);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3876
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3877
			if (cleaned) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3878
				total_tx_packets += buffer_info->segs;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3879
				total_tx_bytes += buffer_info->bytecount;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3880
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3881
			e1000_unmap_and_free_tx_resource(adapter, buffer_info);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3882
			tx_desc->upper.data = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3883
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3884
			if (unlikely(++i == tx_ring->count)) i = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3885
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3886
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3887
		eop = tx_ring->buffer_info[i].next_to_watch;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3888
		eop_desc = E1000_TX_DESC(*tx_ring, eop);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3889
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3890
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3891
	tx_ring->next_to_clean = i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3892
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3893
#define TX_WAKE_THRESHOLD 32
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3894
	if (unlikely(count && netif_carrier_ok(netdev) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3895
		     E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3896
		/* Make sure that anybody stopping the queue after this
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3897
		 * sees the new next_to_clean.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3898
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3899
		smp_mb();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3900
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3901
		if (netif_queue_stopped(netdev) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3902
		    !(test_bit(__E1000_DOWN, &adapter->flags))) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3903
			netif_wake_queue(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3904
			++adapter->restart_queue;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3905
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3906
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3907
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3908
	if (adapter->detect_tx_hung) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3909
		/* Detect a transmit hang in hardware, this serializes the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3910
		 * check with the clearing of time_stamp and movement of i */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3911
		adapter->detect_tx_hung = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3912
		if (tx_ring->buffer_info[eop].time_stamp &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3913
		    time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3914
		               (adapter->tx_timeout_factor * HZ)) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3915
		    !(er32(STATUS) & E1000_STATUS_TXOFF)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3916
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3917
			/* detected Tx unit hang */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3918
			e_err(drv, "Detected Tx Unit Hang\n"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3919
			      "  Tx Queue             <%lu>\n"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3920
			      "  TDH                  <%x>\n"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3921
			      "  TDT                  <%x>\n"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3922
			      "  next_to_use          <%x>\n"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3923
			      "  next_to_clean        <%x>\n"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3924
			      "buffer_info[next_to_clean]\n"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3925
			      "  time_stamp           <%lx>\n"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3926
			      "  next_to_watch        <%x>\n"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3927
			      "  jiffies              <%lx>\n"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3928
			      "  next_to_watch.status <%x>\n",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3929
				(unsigned long)((tx_ring - adapter->tx_ring) /
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3930
					sizeof(struct e1000_tx_ring)),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3931
				readl(hw->hw_addr + tx_ring->tdh),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3932
				readl(hw->hw_addr + tx_ring->tdt),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3933
				tx_ring->next_to_use,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3934
				tx_ring->next_to_clean,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3935
				tx_ring->buffer_info[eop].time_stamp,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3936
				eop,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3937
				jiffies,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3938
				eop_desc->upper.fields.status);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3939
			e1000_dump(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3940
			netif_stop_queue(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3941
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3942
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3943
	adapter->total_tx_bytes += total_tx_bytes;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3944
	adapter->total_tx_packets += total_tx_packets;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3945
	netdev->stats.tx_bytes += total_tx_bytes;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3946
	netdev->stats.tx_packets += total_tx_packets;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3947
	return count < tx_ring->count;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3948
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3949
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3950
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3951
 * e1000_rx_checksum - Receive Checksum Offload for 82543
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3952
 * @adapter:     board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3953
 * @status_err:  receive descriptor status and error fields
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3954
 * @csum:        receive descriptor csum field
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3955
 * @sk_buff:     socket buffer with received data
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3956
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3957
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3958
static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3959
			      u32 csum, struct sk_buff *skb)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3960
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3961
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3962
	u16 status = (u16)status_err;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3963
	u8 errors = (u8)(status_err >> 24);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3964
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3965
	skb_checksum_none_assert(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3966
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3967
	/* 82543 or newer only */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3968
	if (unlikely(hw->mac_type < e1000_82543)) return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3969
	/* Ignore Checksum bit is set */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3970
	if (unlikely(status & E1000_RXD_STAT_IXSM)) return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3971
	/* TCP/UDP checksum error bit is set */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3972
	if (unlikely(errors & E1000_RXD_ERR_TCPE)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3973
		/* let the stack verify checksum errors */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3974
		adapter->hw_csum_err++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3975
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3976
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3977
	/* TCP/UDP Checksum has not been calculated */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3978
	if (!(status & E1000_RXD_STAT_TCPCS))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3979
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3980
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3981
	/* It must be a TCP or UDP packet with a valid checksum */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3982
	if (likely(status & E1000_RXD_STAT_TCPCS)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3983
		/* TCP checksum is good */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3984
		skb->ip_summed = CHECKSUM_UNNECESSARY;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3985
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3986
	adapter->hw_csum_good++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3987
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3988
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3989
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3990
 * e1000_consume_page - helper function
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3991
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3992
static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3993
                               u16 length)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3994
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3995
	bi->page = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3996
	skb->len += length;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3997
	skb->data_len += length;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3998
	skb->truesize += PAGE_SIZE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3999
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4000
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4001
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4002
 * e1000_receive_skb - helper function to handle rx indications
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4003
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4004
 * @status: descriptor status field as written by hardware
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4005
 * @vlan: descriptor vlan field as written by hardware (no le/be conversion)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4006
 * @skb: pointer to sk_buff to be indicated to stack
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4007
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4008
static void e1000_receive_skb(struct e1000_adapter *adapter, u8 status,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4009
			      __le16 vlan, struct sk_buff *skb)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4010
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4011
	skb->protocol = eth_type_trans(skb, adapter->netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4012
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4013
	if (status & E1000_RXD_STAT_VP) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4014
		u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4015
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4016
		__vlan_hwaccel_put_tag(skb, vid);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4017
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4018
	napi_gro_receive(&adapter->napi, skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4019
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4020
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4021
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4022
 * e1000_clean_jumbo_rx_irq - Send received data up the network stack; legacy
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4023
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4024
 * @rx_ring: ring to clean
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4025
 * @work_done: amount of napi work completed this call
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4026
 * @work_to_do: max amount of work allowed for this call to do
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4027
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4028
 * the return value indicates whether actual cleaning was done, there
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4029
 * is no guarantee that everything was cleaned
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4030
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4031
static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4032
				     struct e1000_rx_ring *rx_ring,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4033
				     int *work_done, int work_to_do)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4034
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4035
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4036
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4037
	struct pci_dev *pdev = adapter->pdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4038
	struct e1000_rx_desc *rx_desc, *next_rxd;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4039
	struct e1000_buffer *buffer_info, *next_buffer;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4040
	unsigned long irq_flags;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4041
	u32 length;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4042
	unsigned int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4043
	int cleaned_count = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4044
	bool cleaned = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4045
	unsigned int total_rx_bytes=0, total_rx_packets=0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4046
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4047
	i = rx_ring->next_to_clean;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4048
	rx_desc = E1000_RX_DESC(*rx_ring, i);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4049
	buffer_info = &rx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4050
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4051
	while (rx_desc->status & E1000_RXD_STAT_DD) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4052
		struct sk_buff *skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4053
		u8 status;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4054
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4055
		if (*work_done >= work_to_do)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4056
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4057
		(*work_done)++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4058
		rmb(); /* read descriptor and rx_buffer_info after status DD */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4059
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4060
		status = rx_desc->status;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4061
		skb = buffer_info->skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4062
		buffer_info->skb = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4063
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4064
		if (++i == rx_ring->count) i = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4065
		next_rxd = E1000_RX_DESC(*rx_ring, i);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4066
		prefetch(next_rxd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4067
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4068
		next_buffer = &rx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4069
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4070
		cleaned = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4071
		cleaned_count++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4072
		dma_unmap_page(&pdev->dev, buffer_info->dma,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4073
			       buffer_info->length, DMA_FROM_DEVICE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4074
		buffer_info->dma = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4075
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4076
		length = le16_to_cpu(rx_desc->length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4077
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4078
		/* errors is only valid for DD + EOP descriptors */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4079
		if (unlikely((status & E1000_RXD_STAT_EOP) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4080
		    (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK))) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4081
			u8 *mapped;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4082
			u8 last_byte;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4083
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4084
			mapped = page_address(buffer_info->page);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4085
			last_byte = *(mapped + length - 1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4086
			if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4087
				       last_byte)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4088
				spin_lock_irqsave(&adapter->stats_lock,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4089
				                  irq_flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4090
				e1000_tbi_adjust_stats(hw, &adapter->stats,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4091
						       length, mapped);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4092
				spin_unlock_irqrestore(&adapter->stats_lock,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4093
				                       irq_flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4094
				length--;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4095
			} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4096
				if (netdev->features & NETIF_F_RXALL)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4097
					goto process_skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4098
				/* recycle both page and skb */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4099
				buffer_info->skb = skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4100
				/* an error means any chain goes out the window
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4101
				 * too */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4102
				if (rx_ring->rx_skb_top)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4103
					dev_kfree_skb(rx_ring->rx_skb_top);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4104
				rx_ring->rx_skb_top = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4105
				goto next_desc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4106
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4107
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4108
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4109
#define rxtop rx_ring->rx_skb_top
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4110
process_skb:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4111
		if (!(status & E1000_RXD_STAT_EOP)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4112
			/* this descriptor is only the beginning (or middle) */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4113
			if (!rxtop) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4114
				/* this is the beginning of a chain */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4115
				rxtop = skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4116
				skb_fill_page_desc(rxtop, 0, buffer_info->page,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4117
				                   0, length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4118
			} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4119
				/* this is the middle of a chain */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4120
				skb_fill_page_desc(rxtop,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4121
				    skb_shinfo(rxtop)->nr_frags,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4122
				    buffer_info->page, 0, length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4123
				/* re-use the skb, only consumed the page */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4124
				buffer_info->skb = skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4125
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4126
			e1000_consume_page(buffer_info, rxtop, length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4127
			goto next_desc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4128
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4129
			if (rxtop) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4130
				/* end of the chain */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4131
				skb_fill_page_desc(rxtop,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4132
				    skb_shinfo(rxtop)->nr_frags,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4133
				    buffer_info->page, 0, length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4134
				/* re-use the current skb, we only consumed the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4135
				 * page */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4136
				buffer_info->skb = skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4137
				skb = rxtop;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4138
				rxtop = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4139
				e1000_consume_page(buffer_info, skb, length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4140
			} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4141
				/* no chain, got EOP, this buf is the packet
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4142
				 * copybreak to save the put_page/alloc_page */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4143
				if (length <= copybreak &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4144
				    skb_tailroom(skb) >= length) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4145
					u8 *vaddr;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4146
					vaddr = kmap_atomic(buffer_info->page);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4147
					memcpy(skb_tail_pointer(skb), vaddr, length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4148
					kunmap_atomic(vaddr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4149
					/* re-use the page, so don't erase
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4150
					 * buffer_info->page */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4151
					skb_put(skb, length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4152
				} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4153
					skb_fill_page_desc(skb, 0,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4154
					                   buffer_info->page, 0,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4155
				                           length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4156
					e1000_consume_page(buffer_info, skb,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4157
					                   length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4158
				}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4159
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4160
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4161
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4162
		/* Receive Checksum Offload XXX recompute due to CRC strip? */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4163
		e1000_rx_checksum(adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4164
		                  (u32)(status) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4165
		                  ((u32)(rx_desc->errors) << 24),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4166
		                  le16_to_cpu(rx_desc->csum), skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4167
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4168
		total_rx_bytes += (skb->len - 4); /* don't count FCS */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4169
		if (likely(!(netdev->features & NETIF_F_RXFCS)))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4170
			pskb_trim(skb, skb->len - 4);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4171
		total_rx_packets++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4172
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4173
		/* eth type trans needs skb->data to point to something */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4174
		if (!pskb_may_pull(skb, ETH_HLEN)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4175
			e_err(drv, "pskb_may_pull failed.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4176
			dev_kfree_skb(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4177
			goto next_desc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4178
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4179
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4180
		e1000_receive_skb(adapter, status, rx_desc->special, skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4181
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4182
next_desc:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4183
		rx_desc->status = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4184
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4185
		/* return some buffers to hardware, one at a time is too slow */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4186
		if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4187
			adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4188
			cleaned_count = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4189
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4190
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4191
		/* use prefetched values */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4192
		rx_desc = next_rxd;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4193
		buffer_info = next_buffer;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4194
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4195
	rx_ring->next_to_clean = i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4196
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4197
	cleaned_count = E1000_DESC_UNUSED(rx_ring);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4198
	if (cleaned_count)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4199
		adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4200
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4201
	adapter->total_rx_packets += total_rx_packets;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4202
	adapter->total_rx_bytes += total_rx_bytes;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4203
	netdev->stats.rx_bytes += total_rx_bytes;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4204
	netdev->stats.rx_packets += total_rx_packets;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4205
	return cleaned;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4206
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4207
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4208
/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4209
 * this should improve performance for small packets with large amounts
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4210
 * of reassembly being done in the stack
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4211
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4212
static void e1000_check_copybreak(struct net_device *netdev,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4213
				 struct e1000_buffer *buffer_info,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4214
				 u32 length, struct sk_buff **skb)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4215
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4216
	struct sk_buff *new_skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4217
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4218
	if (length > copybreak)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4219
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4220
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4221
	new_skb = netdev_alloc_skb_ip_align(netdev, length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4222
	if (!new_skb)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4223
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4224
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4225
	skb_copy_to_linear_data_offset(new_skb, -NET_IP_ALIGN,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4226
				       (*skb)->data - NET_IP_ALIGN,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4227
				       length + NET_IP_ALIGN);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4228
	/* save the skb in buffer_info as good */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4229
	buffer_info->skb = *skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4230
	*skb = new_skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4231
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4232
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4233
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4234
 * e1000_clean_rx_irq - Send received data up the network stack; legacy
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4235
 * @adapter: board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4236
 * @rx_ring: ring to clean
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4237
 * @work_done: amount of napi work completed this call
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4238
 * @work_to_do: max amount of work allowed for this call to do
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4239
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4240
static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4241
			       struct e1000_rx_ring *rx_ring,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4242
			       int *work_done, int work_to_do)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4243
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4244
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4245
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4246
	struct pci_dev *pdev = adapter->pdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4247
	struct e1000_rx_desc *rx_desc, *next_rxd;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4248
	struct e1000_buffer *buffer_info, *next_buffer;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4249
	unsigned long flags;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4250
	u32 length;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4251
	unsigned int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4252
	int cleaned_count = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4253
	bool cleaned = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4254
	unsigned int total_rx_bytes=0, total_rx_packets=0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4255
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4256
	i = rx_ring->next_to_clean;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4257
	rx_desc = E1000_RX_DESC(*rx_ring, i);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4258
	buffer_info = &rx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4259
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4260
	while (rx_desc->status & E1000_RXD_STAT_DD) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4261
		struct sk_buff *skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4262
		u8 status;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4263
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4264
		if (*work_done >= work_to_do)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4265
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4266
		(*work_done)++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4267
		rmb(); /* read descriptor and rx_buffer_info after status DD */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4268
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4269
		status = rx_desc->status;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4270
		skb = buffer_info->skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4271
		buffer_info->skb = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4272
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4273
		prefetch(skb->data - NET_IP_ALIGN);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4274
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4275
		if (++i == rx_ring->count) i = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4276
		next_rxd = E1000_RX_DESC(*rx_ring, i);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4277
		prefetch(next_rxd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4278
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4279
		next_buffer = &rx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4280
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4281
		cleaned = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4282
		cleaned_count++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4283
		dma_unmap_single(&pdev->dev, buffer_info->dma,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4284
				 buffer_info->length, DMA_FROM_DEVICE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4285
		buffer_info->dma = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4286
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4287
		length = le16_to_cpu(rx_desc->length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4288
		/* !EOP means multiple descriptors were used to store a single
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4289
		 * packet, if thats the case we need to toss it.  In fact, we
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4290
		 * to toss every packet with the EOP bit clear and the next
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4291
		 * frame that _does_ have the EOP bit set, as it is by
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4292
		 * definition only a frame fragment
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4293
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4294
		if (unlikely(!(status & E1000_RXD_STAT_EOP)))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4295
			adapter->discarding = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4296
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4297
		if (adapter->discarding) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4298
			/* All receives must fit into a single buffer */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4299
			e_dbg("Receive packet consumed multiple buffers\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4300
			/* recycle */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4301
			buffer_info->skb = skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4302
			if (status & E1000_RXD_STAT_EOP)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4303
				adapter->discarding = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4304
			goto next_desc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4305
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4306
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4307
		if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4308
			u8 last_byte = *(skb->data + length - 1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4309
			if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4310
				       last_byte)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4311
				spin_lock_irqsave(&adapter->stats_lock, flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4312
				e1000_tbi_adjust_stats(hw, &adapter->stats,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4313
				                       length, skb->data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4314
				spin_unlock_irqrestore(&adapter->stats_lock,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4315
				                       flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4316
				length--;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4317
			} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4318
				if (netdev->features & NETIF_F_RXALL)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4319
					goto process_skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4320
				/* recycle */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4321
				buffer_info->skb = skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4322
				goto next_desc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4323
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4324
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4325
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4326
process_skb:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4327
		total_rx_bytes += (length - 4); /* don't count FCS */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4328
		total_rx_packets++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4329
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4330
		if (likely(!(netdev->features & NETIF_F_RXFCS)))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4331
			/* adjust length to remove Ethernet CRC, this must be
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4332
			 * done after the TBI_ACCEPT workaround above
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4333
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4334
			length -= 4;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4335
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4336
		e1000_check_copybreak(netdev, buffer_info, length, &skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4337
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4338
		skb_put(skb, length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4339
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4340
		/* Receive Checksum Offload */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4341
		e1000_rx_checksum(adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4342
				  (u32)(status) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4343
				  ((u32)(rx_desc->errors) << 24),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4344
				  le16_to_cpu(rx_desc->csum), skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4345
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4346
		e1000_receive_skb(adapter, status, rx_desc->special, skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4347
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4348
next_desc:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4349
		rx_desc->status = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4350
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4351
		/* return some buffers to hardware, one at a time is too slow */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4352
		if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4353
			adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4354
			cleaned_count = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4355
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4356
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4357
		/* use prefetched values */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4358
		rx_desc = next_rxd;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4359
		buffer_info = next_buffer;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4360
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4361
	rx_ring->next_to_clean = i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4362
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4363
	cleaned_count = E1000_DESC_UNUSED(rx_ring);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4364
	if (cleaned_count)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4365
		adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4366
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4367
	adapter->total_rx_packets += total_rx_packets;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4368
	adapter->total_rx_bytes += total_rx_bytes;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4369
	netdev->stats.rx_bytes += total_rx_bytes;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4370
	netdev->stats.rx_packets += total_rx_packets;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4371
	return cleaned;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4372
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4373
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4374
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4375
 * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4376
 * @adapter: address of board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4377
 * @rx_ring: pointer to receive ring structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4378
 * @cleaned_count: number of buffers to allocate this pass
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4379
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4380
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4381
static void
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4382
e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4383
                             struct e1000_rx_ring *rx_ring, int cleaned_count)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4384
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4385
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4386
	struct pci_dev *pdev = adapter->pdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4387
	struct e1000_rx_desc *rx_desc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4388
	struct e1000_buffer *buffer_info;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4389
	struct sk_buff *skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4390
	unsigned int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4391
	unsigned int bufsz = 256 - 16 /*for skb_reserve */ ;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4392
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4393
	i = rx_ring->next_to_use;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4394
	buffer_info = &rx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4395
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4396
	while (cleaned_count--) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4397
		skb = buffer_info->skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4398
		if (skb) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4399
			skb_trim(skb, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4400
			goto check_page;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4401
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4402
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4403
		skb = netdev_alloc_skb_ip_align(netdev, bufsz);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4404
		if (unlikely(!skb)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4405
			/* Better luck next round */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4406
			adapter->alloc_rx_buff_failed++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4407
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4408
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4409
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4410
		buffer_info->skb = skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4411
		buffer_info->length = adapter->rx_buffer_len;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4412
check_page:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4413
		/* allocate a new page if necessary */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4414
		if (!buffer_info->page) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4415
			buffer_info->page = alloc_page(GFP_ATOMIC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4416
			if (unlikely(!buffer_info->page)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4417
				adapter->alloc_rx_buff_failed++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4418
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4419
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4420
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4421
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4422
		if (!buffer_info->dma) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4423
			buffer_info->dma = dma_map_page(&pdev->dev,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4424
			                                buffer_info->page, 0,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4425
							buffer_info->length,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4426
							DMA_FROM_DEVICE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4427
			if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4428
				put_page(buffer_info->page);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4429
				dev_kfree_skb(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4430
				buffer_info->page = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4431
				buffer_info->skb = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4432
				buffer_info->dma = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4433
				adapter->alloc_rx_buff_failed++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4434
				break; /* while !buffer_info->skb */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4435
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4436
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4437
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4438
		rx_desc = E1000_RX_DESC(*rx_ring, i);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4439
		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4440
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4441
		if (unlikely(++i == rx_ring->count))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4442
			i = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4443
		buffer_info = &rx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4444
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4445
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4446
	if (likely(rx_ring->next_to_use != i)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4447
		rx_ring->next_to_use = i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4448
		if (unlikely(i-- == 0))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4449
			i = (rx_ring->count - 1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4450
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4451
		/* Force memory writes to complete before letting h/w
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4452
		 * know there are new descriptors to fetch.  (Only
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4453
		 * applicable for weak-ordered memory model archs,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4454
		 * such as IA-64). */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4455
		wmb();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4456
		writel(i, adapter->hw.hw_addr + rx_ring->rdt);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4457
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4458
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4459
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4460
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4461
 * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4462
 * @adapter: address of board private structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4463
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4464
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4465
static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4466
				   struct e1000_rx_ring *rx_ring,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4467
				   int cleaned_count)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4468
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4469
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4470
	struct net_device *netdev = adapter->netdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4471
	struct pci_dev *pdev = adapter->pdev;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4472
	struct e1000_rx_desc *rx_desc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4473
	struct e1000_buffer *buffer_info;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4474
	struct sk_buff *skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4475
	unsigned int i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4476
	unsigned int bufsz = adapter->rx_buffer_len;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4477
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4478
	i = rx_ring->next_to_use;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4479
	buffer_info = &rx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4480
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4481
	while (cleaned_count--) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4482
		skb = buffer_info->skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4483
		if (skb) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4484
			skb_trim(skb, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4485
			goto map_skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4486
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4487
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4488
		skb = netdev_alloc_skb_ip_align(netdev, bufsz);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4489
		if (unlikely(!skb)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4490
			/* Better luck next round */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4491
			adapter->alloc_rx_buff_failed++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4492
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4493
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4494
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4495
		/* Fix for errata 23, can't cross 64kB boundary */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4496
		if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4497
			struct sk_buff *oldskb = skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4498
			e_err(rx_err, "skb align check failed: %u bytes at "
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4499
			      "%p\n", bufsz, skb->data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4500
			/* Try again, without freeing the previous */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4501
			skb = netdev_alloc_skb_ip_align(netdev, bufsz);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4502
			/* Failed allocation, critical failure */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4503
			if (!skb) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4504
				dev_kfree_skb(oldskb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4505
				adapter->alloc_rx_buff_failed++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4506
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4507
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4508
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4509
			if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4510
				/* give up */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4511
				dev_kfree_skb(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4512
				dev_kfree_skb(oldskb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4513
				adapter->alloc_rx_buff_failed++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4514
				break; /* while !buffer_info->skb */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4515
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4516
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4517
			/* Use new allocation */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4518
			dev_kfree_skb(oldskb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4519
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4520
		buffer_info->skb = skb;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4521
		buffer_info->length = adapter->rx_buffer_len;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4522
map_skb:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4523
		buffer_info->dma = dma_map_single(&pdev->dev,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4524
						  skb->data,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4525
						  buffer_info->length,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4526
						  DMA_FROM_DEVICE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4527
		if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4528
			dev_kfree_skb(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4529
			buffer_info->skb = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4530
			buffer_info->dma = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4531
			adapter->alloc_rx_buff_failed++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4532
			break; /* while !buffer_info->skb */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4533
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4534
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4535
		/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4536
		 * XXX if it was allocated cleanly it will never map to a
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4537
		 * boundary crossing
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4538
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4539
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4540
		/* Fix for errata 23, can't cross 64kB boundary */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4541
		if (!e1000_check_64k_bound(adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4542
					(void *)(unsigned long)buffer_info->dma,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4543
					adapter->rx_buffer_len)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4544
			e_err(rx_err, "dma align check failed: %u bytes at "
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4545
			      "%p\n", adapter->rx_buffer_len,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4546
			      (void *)(unsigned long)buffer_info->dma);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4547
			dev_kfree_skb(skb);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4548
			buffer_info->skb = NULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4549
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4550
			dma_unmap_single(&pdev->dev, buffer_info->dma,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4551
					 adapter->rx_buffer_len,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4552
					 DMA_FROM_DEVICE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4553
			buffer_info->dma = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4554
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4555
			adapter->alloc_rx_buff_failed++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4556
			break; /* while !buffer_info->skb */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4557
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4558
		rx_desc = E1000_RX_DESC(*rx_ring, i);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4559
		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4560
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4561
		if (unlikely(++i == rx_ring->count))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4562
			i = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4563
		buffer_info = &rx_ring->buffer_info[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4564
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4565
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4566
	if (likely(rx_ring->next_to_use != i)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4567
		rx_ring->next_to_use = i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4568
		if (unlikely(i-- == 0))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4569
			i = (rx_ring->count - 1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4570
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4571
		/* Force memory writes to complete before letting h/w
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4572
		 * know there are new descriptors to fetch.  (Only
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4573
		 * applicable for weak-ordered memory model archs,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4574
		 * such as IA-64). */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4575
		wmb();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4576
		writel(i, hw->hw_addr + rx_ring->rdt);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4577
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4578
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4579
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4580
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4581
 * e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4582
 * @adapter:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4583
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4584
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4585
static void e1000_smartspeed(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4586
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4587
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4588
	u16 phy_status;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4589
	u16 phy_ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4590
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4591
	if ((hw->phy_type != e1000_phy_igp) || !hw->autoneg ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4592
	   !(hw->autoneg_advertised & ADVERTISE_1000_FULL))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4593
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4594
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4595
	if (adapter->smartspeed == 0) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4596
		/* If Master/Slave config fault is asserted twice,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4597
		 * we assume back-to-back */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4598
		e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4599
		if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4600
		e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4601
		if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4602
		e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4603
		if (phy_ctrl & CR_1000T_MS_ENABLE) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4604
			phy_ctrl &= ~CR_1000T_MS_ENABLE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4605
			e1000_write_phy_reg(hw, PHY_1000T_CTRL,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4606
					    phy_ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4607
			adapter->smartspeed++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4608
			if (!e1000_phy_setup_autoneg(hw) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4609
			   !e1000_read_phy_reg(hw, PHY_CTRL,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4610
				   	       &phy_ctrl)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4611
				phy_ctrl |= (MII_CR_AUTO_NEG_EN |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4612
					     MII_CR_RESTART_AUTO_NEG);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4613
				e1000_write_phy_reg(hw, PHY_CTRL,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4614
						    phy_ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4615
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4616
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4617
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4618
	} else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4619
		/* If still no link, perhaps using 2/3 pair cable */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4620
		e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4621
		phy_ctrl |= CR_1000T_MS_ENABLE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4622
		e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4623
		if (!e1000_phy_setup_autoneg(hw) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4624
		   !e1000_read_phy_reg(hw, PHY_CTRL, &phy_ctrl)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4625
			phy_ctrl |= (MII_CR_AUTO_NEG_EN |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4626
				     MII_CR_RESTART_AUTO_NEG);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4627
			e1000_write_phy_reg(hw, PHY_CTRL, phy_ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4628
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4629
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4630
	/* Restart process after E1000_SMARTSPEED_MAX iterations */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4631
	if (adapter->smartspeed++ == E1000_SMARTSPEED_MAX)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4632
		adapter->smartspeed = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4633
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4634
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4635
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4636
 * e1000_ioctl -
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4637
 * @netdev:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4638
 * @ifreq:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4639
 * @cmd:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4640
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4641
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4642
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4643
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4644
	switch (cmd) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4645
	case SIOCGMIIPHY:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4646
	case SIOCGMIIREG:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4647
	case SIOCSMIIREG:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4648
		return e1000_mii_ioctl(netdev, ifr, cmd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4649
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4650
		return -EOPNOTSUPP;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4651
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4652
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4653
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4654
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4655
 * e1000_mii_ioctl -
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4656
 * @netdev:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4657
 * @ifreq:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4658
 * @cmd:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4659
 **/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4660
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4661
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4662
			   int cmd)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4663
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4664
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4665
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4666
	struct mii_ioctl_data *data = if_mii(ifr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4667
	int retval;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4668
	u16 mii_reg;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4669
	unsigned long flags;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4670
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4671
	if (hw->media_type != e1000_media_type_copper)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4672
		return -EOPNOTSUPP;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4673
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4674
	switch (cmd) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4675
	case SIOCGMIIPHY:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4676
		data->phy_id = hw->phy_addr;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4677
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4678
	case SIOCGMIIREG:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4679
		spin_lock_irqsave(&adapter->stats_lock, flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4680
		if (e1000_read_phy_reg(hw, data->reg_num & 0x1F,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4681
				   &data->val_out)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4682
			spin_unlock_irqrestore(&adapter->stats_lock, flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4683
			return -EIO;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4684
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4685
		spin_unlock_irqrestore(&adapter->stats_lock, flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4686
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4687
	case SIOCSMIIREG:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4688
		if (data->reg_num & ~(0x1F))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4689
			return -EFAULT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4690
		mii_reg = data->val_in;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4691
		spin_lock_irqsave(&adapter->stats_lock, flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4692
		if (e1000_write_phy_reg(hw, data->reg_num,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4693
					mii_reg)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4694
			spin_unlock_irqrestore(&adapter->stats_lock, flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4695
			return -EIO;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4696
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4697
		spin_unlock_irqrestore(&adapter->stats_lock, flags);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4698
		if (hw->media_type == e1000_media_type_copper) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4699
			switch (data->reg_num) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4700
			case PHY_CTRL:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4701
				if (mii_reg & MII_CR_POWER_DOWN)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4702
					break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4703
				if (mii_reg & MII_CR_AUTO_NEG_EN) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4704
					hw->autoneg = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4705
					hw->autoneg_advertised = 0x2F;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4706
				} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4707
					u32 speed;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4708
					if (mii_reg & 0x40)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4709
						speed = SPEED_1000;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4710
					else if (mii_reg & 0x2000)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4711
						speed = SPEED_100;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4712
					else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4713
						speed = SPEED_10;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4714
					retval = e1000_set_spd_dplx(
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4715
						adapter, speed,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4716
						((mii_reg & 0x100)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4717
						 ? DUPLEX_FULL :
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4718
						 DUPLEX_HALF));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4719
					if (retval)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4720
						return retval;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4721
				}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4722
				if (netif_running(adapter->netdev))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4723
					e1000_reinit_locked(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4724
				else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4725
					e1000_reset(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4726
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4727
			case M88E1000_PHY_SPEC_CTRL:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4728
			case M88E1000_EXT_PHY_SPEC_CTRL:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4729
				if (e1000_phy_reset(hw))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4730
					return -EIO;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4731
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4732
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4733
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4734
			switch (data->reg_num) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4735
			case PHY_CTRL:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4736
				if (mii_reg & MII_CR_POWER_DOWN)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4737
					break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4738
				if (netif_running(adapter->netdev))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4739
					e1000_reinit_locked(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4740
				else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4741
					e1000_reset(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4742
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4743
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4744
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4745
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4746
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4747
		return -EOPNOTSUPP;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4748
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4749
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4750
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4751
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4752
void e1000_pci_set_mwi(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4753
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4754
	struct e1000_adapter *adapter = hw->back;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4755
	int ret_val = pci_set_mwi(adapter->pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4756
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4757
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4758
		e_err(probe, "Error in setting MWI\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4759
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4760
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4761
void e1000_pci_clear_mwi(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4762
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4763
	struct e1000_adapter *adapter = hw->back;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4764
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4765
	pci_clear_mwi(adapter->pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4766
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4767
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4768
int e1000_pcix_get_mmrbc(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4769
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4770
	struct e1000_adapter *adapter = hw->back;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4771
	return pcix_get_mmrbc(adapter->pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4772
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4773
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4774
void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4775
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4776
	struct e1000_adapter *adapter = hw->back;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4777
	pcix_set_mmrbc(adapter->pdev, mmrbc);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4778
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4779
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4780
void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4781
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4782
	outl(value, port);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4783
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4784
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4785
static bool e1000_vlan_used(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4786
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4787
	u16 vid;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4788
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4789
	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4790
		return true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4791
	return false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4792
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4793
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4794
static void __e1000_vlan_mode(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4795
			      netdev_features_t features)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4796
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4797
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4798
	u32 ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4799
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4800
	ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4801
	if (features & NETIF_F_HW_VLAN_RX) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4802
		/* enable VLAN tag insert/strip */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4803
		ctrl |= E1000_CTRL_VME;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4804
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4805
		/* disable VLAN tag insert/strip */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4806
		ctrl &= ~E1000_CTRL_VME;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4807
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4808
	ew32(CTRL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4809
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4810
static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4811
				     bool filter_on)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4812
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4813
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4814
	u32 rctl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4815
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4816
	if (!test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4817
		e1000_irq_disable(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4818
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4819
	__e1000_vlan_mode(adapter, adapter->netdev->features);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4820
	if (filter_on) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4821
		/* enable VLAN receive filtering */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4822
		rctl = er32(RCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4823
		rctl &= ~E1000_RCTL_CFIEN;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4824
		if (!(adapter->netdev->flags & IFF_PROMISC))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4825
			rctl |= E1000_RCTL_VFE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4826
		ew32(RCTL, rctl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4827
		e1000_update_mng_vlan(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4828
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4829
		/* disable VLAN receive filtering */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4830
		rctl = er32(RCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4831
		rctl &= ~E1000_RCTL_VFE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4832
		ew32(RCTL, rctl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4833
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4834
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4835
	if (!test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4836
		e1000_irq_enable(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4837
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4838
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4839
static void e1000_vlan_mode(struct net_device *netdev,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4840
			    netdev_features_t features)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4841
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4842
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4843
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4844
	if (!test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4845
		e1000_irq_disable(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4846
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4847
	__e1000_vlan_mode(adapter, features);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4848
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4849
	if (!test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4850
		e1000_irq_enable(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4851
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4852
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4853
static int e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4854
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4855
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4856
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4857
	u32 vfta, index;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4858
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4859
	if ((hw->mng_cookie.status &
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4860
	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4861
	    (vid == adapter->mng_vlan_id))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4862
		return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4863
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4864
	if (!e1000_vlan_used(adapter))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4865
		e1000_vlan_filter_on_off(adapter, true);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4866
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4867
	/* add VID to filter table */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4868
	index = (vid >> 5) & 0x7F;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4869
	vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4870
	vfta |= (1 << (vid & 0x1F));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4871
	e1000_write_vfta(hw, index, vfta);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4872
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4873
	set_bit(vid, adapter->active_vlans);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4874
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4875
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4876
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4877
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4878
static int e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4879
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4880
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4881
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4882
	u32 vfta, index;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4883
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4884
	if (!test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4885
		e1000_irq_disable(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4886
	if (!test_bit(__E1000_DOWN, &adapter->flags))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4887
		e1000_irq_enable(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4888
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4889
	/* remove VID from filter table */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4890
	index = (vid >> 5) & 0x7F;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4891
	vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4892
	vfta &= ~(1 << (vid & 0x1F));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4893
	e1000_write_vfta(hw, index, vfta);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4894
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4895
	clear_bit(vid, adapter->active_vlans);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4896
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4897
	if (!e1000_vlan_used(adapter))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4898
		e1000_vlan_filter_on_off(adapter, false);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4899
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4900
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4901
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4902
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4903
static void e1000_restore_vlan(struct e1000_adapter *adapter)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4904
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4905
	u16 vid;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4906
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4907
	if (!e1000_vlan_used(adapter))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4908
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4909
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4910
	e1000_vlan_filter_on_off(adapter, true);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4911
	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4912
		e1000_vlan_rx_add_vid(adapter->netdev, vid);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4913
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4914
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4915
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4916
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4917
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4918
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4919
	hw->autoneg = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4920
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4921
	/* Make sure dplx is at most 1 bit and lsb of speed is not set
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4922
	 * for the switch() below to work */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4923
	if ((spd & 1) || (dplx & ~1))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4924
		goto err_inval;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4925
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4926
	/* Fiber NICs only allow 1000 gbps Full duplex */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4927
	if ((hw->media_type == e1000_media_type_fiber) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4928
	    spd != SPEED_1000 &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4929
	    dplx != DUPLEX_FULL)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4930
		goto err_inval;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4931
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4932
	switch (spd + dplx) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4933
	case SPEED_10 + DUPLEX_HALF:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4934
		hw->forced_speed_duplex = e1000_10_half;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4935
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4936
	case SPEED_10 + DUPLEX_FULL:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4937
		hw->forced_speed_duplex = e1000_10_full;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4938
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4939
	case SPEED_100 + DUPLEX_HALF:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4940
		hw->forced_speed_duplex = e1000_100_half;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4941
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4942
	case SPEED_100 + DUPLEX_FULL:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4943
		hw->forced_speed_duplex = e1000_100_full;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4944
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4945
	case SPEED_1000 + DUPLEX_FULL:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4946
		hw->autoneg = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4947
		hw->autoneg_advertised = ADVERTISE_1000_FULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4948
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4949
	case SPEED_1000 + DUPLEX_HALF: /* not supported */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4950
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4951
		goto err_inval;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4952
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4953
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4954
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4955
err_inval:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4956
	e_err(probe, "Unsupported Speed/Duplex configuration\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4957
	return -EINVAL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4958
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4959
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4960
static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4961
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4962
	struct net_device *netdev = pci_get_drvdata(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4963
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4964
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4965
	u32 ctrl, ctrl_ext, rctl, status;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4966
	u32 wufc = adapter->wol;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4967
#ifdef CONFIG_PM
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4968
	int retval = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4969
#endif
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4970
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4971
	netif_device_detach(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4972
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4973
	if (netif_running(netdev)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4974
		WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4975
		e1000_down(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4976
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4977
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4978
#ifdef CONFIG_PM
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4979
	retval = pci_save_state(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4980
	if (retval)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4981
		return retval;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4982
#endif
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4983
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4984
	status = er32(STATUS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4985
	if (status & E1000_STATUS_LU)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4986
		wufc &= ~E1000_WUFC_LNKC;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4987
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4988
	if (wufc) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4989
		e1000_setup_rctl(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4990
		e1000_set_rx_mode(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4991
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4992
		rctl = er32(RCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4993
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4994
		/* turn on all-multi mode if wake on multicast is enabled */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4995
		if (wufc & E1000_WUFC_MC)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4996
			rctl |= E1000_RCTL_MPE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4997
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4998
		/* enable receives in the hardware */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4999
		ew32(RCTL, rctl | E1000_RCTL_EN);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5000
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5001
		if (hw->mac_type >= e1000_82540) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5002
			ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5003
			/* advertise wake from D3Cold */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5004
			#define E1000_CTRL_ADVD3WUC 0x00100000
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5005
			/* phy power management enable */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5006
			#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5007
			ctrl |= E1000_CTRL_ADVD3WUC |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5008
				E1000_CTRL_EN_PHY_PWR_MGMT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5009
			ew32(CTRL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5010
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5011
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5012
		if (hw->media_type == e1000_media_type_fiber ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5013
		    hw->media_type == e1000_media_type_internal_serdes) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5014
			/* keep the laser running in D3 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5015
			ctrl_ext = er32(CTRL_EXT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5016
			ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5017
			ew32(CTRL_EXT, ctrl_ext);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5018
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5019
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5020
		ew32(WUC, E1000_WUC_PME_EN);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5021
		ew32(WUFC, wufc);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5022
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5023
		ew32(WUC, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5024
		ew32(WUFC, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5025
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5026
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5027
	e1000_release_manageability(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5028
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5029
	*enable_wake = !!wufc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5030
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5031
	/* make sure adapter isn't asleep if manageability is enabled */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5032
	if (adapter->en_mng_pt)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5033
		*enable_wake = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5034
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5035
	if (netif_running(netdev))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5036
		e1000_free_irq(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5037
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5038
	pci_disable_device(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5039
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5040
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5041
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5042
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5043
#ifdef CONFIG_PM
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5044
static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5045
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5046
	int retval;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5047
	bool wake;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5048
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5049
	retval = __e1000_shutdown(pdev, &wake);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5050
	if (retval)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5051
		return retval;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5052
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5053
	if (wake) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5054
		pci_prepare_to_sleep(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5055
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5056
		pci_wake_from_d3(pdev, false);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5057
		pci_set_power_state(pdev, PCI_D3hot);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5058
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5059
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5060
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5061
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5062
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5063
static int e1000_resume(struct pci_dev *pdev)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5064
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5065
	struct net_device *netdev = pci_get_drvdata(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5066
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5067
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5068
	u32 err;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5069
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5070
	pci_set_power_state(pdev, PCI_D0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5071
	pci_restore_state(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5072
	pci_save_state(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5073
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5074
	if (adapter->need_ioport)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5075
		err = pci_enable_device(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5076
	else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5077
		err = pci_enable_device_mem(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5078
	if (err) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5079
		pr_err("Cannot enable PCI device from suspend\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5080
		return err;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5081
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5082
	pci_set_master(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5083
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5084
	pci_enable_wake(pdev, PCI_D3hot, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5085
	pci_enable_wake(pdev, PCI_D3cold, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5086
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5087
	if (netif_running(netdev)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5088
		err = e1000_request_irq(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5089
		if (err)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5090
			return err;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5091
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5092
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5093
	e1000_power_up_phy(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5094
	e1000_reset(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5095
	ew32(WUS, ~0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5096
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5097
	e1000_init_manageability(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5098
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5099
	if (netif_running(netdev))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5100
		e1000_up(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5101
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5102
	netif_device_attach(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5103
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5104
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5105
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5106
#endif
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5107
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5108
static void e1000_shutdown(struct pci_dev *pdev)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5109
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5110
	bool wake;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5111
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5112
	__e1000_shutdown(pdev, &wake);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5113
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5114
	if (system_state == SYSTEM_POWER_OFF) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5115
		pci_wake_from_d3(pdev, wake);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5116
		pci_set_power_state(pdev, PCI_D3hot);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5117
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5118
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5119
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5120
#ifdef CONFIG_NET_POLL_CONTROLLER
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5121
/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5122
 * Polling 'interrupt' - used by things like netconsole to send skbs
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5123
 * without having to re-enable interrupts. It's not called while
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5124
 * the interrupt routine is executing.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5125
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5126
static void e1000_netpoll(struct net_device *netdev)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5127
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5128
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5129
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5130
	disable_irq(adapter->pdev->irq);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5131
	e1000_intr(adapter->pdev->irq, netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5132
	enable_irq(adapter->pdev->irq);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5133
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5134
#endif
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5135
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5136
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5137
 * e1000_io_error_detected - called when PCI error is detected
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5138
 * @pdev: Pointer to PCI device
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5139
 * @state: The current pci connection state
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5140
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5141
 * This function is called after a PCI bus error affecting
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5142
 * this device has been detected.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5143
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5144
static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5145
						pci_channel_state_t state)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5146
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5147
	struct net_device *netdev = pci_get_drvdata(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5148
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5149
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5150
	netif_device_detach(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5151
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5152
	if (state == pci_channel_io_perm_failure)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5153
		return PCI_ERS_RESULT_DISCONNECT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5154
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5155
	if (netif_running(netdev))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5156
		e1000_down(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5157
	pci_disable_device(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5158
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5159
	/* Request a slot slot reset. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5160
	return PCI_ERS_RESULT_NEED_RESET;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5161
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5162
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5163
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5164
 * e1000_io_slot_reset - called after the pci bus has been reset.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5165
 * @pdev: Pointer to PCI device
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5166
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5167
 * Restart the card from scratch, as if from a cold-boot. Implementation
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5168
 * resembles the first-half of the e1000_resume routine.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5169
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5170
static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5171
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5172
	struct net_device *netdev = pci_get_drvdata(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5173
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5174
	struct e1000_hw *hw = &adapter->hw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5175
	int err;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5176
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5177
	if (adapter->need_ioport)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5178
		err = pci_enable_device(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5179
	else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5180
		err = pci_enable_device_mem(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5181
	if (err) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5182
		pr_err("Cannot re-enable PCI device after reset.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5183
		return PCI_ERS_RESULT_DISCONNECT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5184
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5185
	pci_set_master(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5186
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5187
	pci_enable_wake(pdev, PCI_D3hot, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5188
	pci_enable_wake(pdev, PCI_D3cold, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5189
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5190
	e1000_reset(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5191
	ew32(WUS, ~0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5192
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5193
	return PCI_ERS_RESULT_RECOVERED;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5194
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5195
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5196
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5197
 * e1000_io_resume - called when traffic can start flowing again.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5198
 * @pdev: Pointer to PCI device
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5199
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5200
 * This callback is called when the error recovery driver tells us that
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5201
 * its OK to resume normal operation. Implementation resembles the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5202
 * second-half of the e1000_resume routine.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5203
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5204
static void e1000_io_resume(struct pci_dev *pdev)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5205
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5206
	struct net_device *netdev = pci_get_drvdata(pdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5207
	struct e1000_adapter *adapter = netdev_priv(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5208
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5209
	e1000_init_manageability(adapter);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5210
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5211
	if (netif_running(netdev)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5212
		if (e1000_up(adapter)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5213
			pr_info("can't bring device back up after reset\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5214
			return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5215
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5216
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5217
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5218
	netif_device_attach(netdev);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5219
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5220
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5221
/* e1000_main.c */