devices/e1000/e1000_main-3.0-orig.c
author Gavin Lambert <gavinl@compacsort.com>
Tue, 14 Apr 2015 09:33:24 -0400
changeset 2618 3affe9cd0b66
parent 2395 f7451c2c274f
permissions -rw-r--r--
Ignore NXIO error otherwise this causes spam if network is empty or refclk not
selected yet, and syncing refclk time to master.
2395
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     1
/*******************************************************************************
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     2
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     3
  Intel PRO/1000 Linux driver
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     4
  Copyright(c) 1999 - 2006 Intel Corporation.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     5
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     6
  This program is free software; you can redistribute it and/or modify it
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     7
  under the terms and conditions of the GNU General Public License,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     8
  version 2, as published by the Free Software Foundation.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     9
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    10
  This program is distributed in the hope it will be useful, but WITHOUT
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    11
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    12
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    13
  more details.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    14
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    15
  You should have received a copy of the GNU General Public License along with
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    16
  this program; if not, write to the Free Software Foundation, Inc.,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    17
  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    18
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    19
  The full GNU General Public License is included in this distribution in
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    20
  the file called "COPYING".
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    21
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    22
  Contact Information:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    23
  Linux NICS <linux.nics@intel.com>
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    24
  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    25
  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    26
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    27
*******************************************************************************/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    28
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    29
#include "e1000.h"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    30
#include <net/ip6_checksum.h>
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    31
#include <linux/io.h>
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    32
#include <linux/prefetch.h>
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    33
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    34
/* Intel Media SOC GbE MDIO physical base address */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    35
static unsigned long ce4100_gbe_mdio_base_phy;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    36
/* Intel Media SOC GbE MDIO virtual base address */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    37
void __iomem *ce4100_gbe_mdio_base_virt;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    38
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    39
char e1000_driver_name[] = "e1000";
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    40
static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    41
#define DRV_VERSION "7.3.21-k8-NAPI"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    42
const char e1000_driver_version[] = DRV_VERSION;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    43
static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    44
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    45
/* e1000_pci_tbl - PCI Device ID Table
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    46
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    47
 * Last entry must be all 0s
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    48
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    49
 * Macro expands to...
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    50
 *   {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    51
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    52
static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    53
	INTEL_E1000_ETHERNET_DEVICE(0x1000),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    54
	INTEL_E1000_ETHERNET_DEVICE(0x1001),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    55
	INTEL_E1000_ETHERNET_DEVICE(0x1004),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    56
	INTEL_E1000_ETHERNET_DEVICE(0x1008),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    57
	INTEL_E1000_ETHERNET_DEVICE(0x1009),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    58
	INTEL_E1000_ETHERNET_DEVICE(0x100C),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    59
	INTEL_E1000_ETHERNET_DEVICE(0x100D),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    60
	INTEL_E1000_ETHERNET_DEVICE(0x100E),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    61
	INTEL_E1000_ETHERNET_DEVICE(0x100F),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    62
	INTEL_E1000_ETHERNET_DEVICE(0x1010),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    63
	INTEL_E1000_ETHERNET_DEVICE(0x1011),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    64
	INTEL_E1000_ETHERNET_DEVICE(0x1012),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    65
	INTEL_E1000_ETHERNET_DEVICE(0x1013),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    66
	INTEL_E1000_ETHERNET_DEVICE(0x1014),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    67
	INTEL_E1000_ETHERNET_DEVICE(0x1015),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    68
	INTEL_E1000_ETHERNET_DEVICE(0x1016),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    69
	INTEL_E1000_ETHERNET_DEVICE(0x1017),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    70
	INTEL_E1000_ETHERNET_DEVICE(0x1018),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    71
	INTEL_E1000_ETHERNET_DEVICE(0x1019),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    72
	INTEL_E1000_ETHERNET_DEVICE(0x101A),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    73
	INTEL_E1000_ETHERNET_DEVICE(0x101D),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    74
	INTEL_E1000_ETHERNET_DEVICE(0x101E),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    75
	INTEL_E1000_ETHERNET_DEVICE(0x1026),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    76
	INTEL_E1000_ETHERNET_DEVICE(0x1027),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    77
	INTEL_E1000_ETHERNET_DEVICE(0x1028),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    78
	INTEL_E1000_ETHERNET_DEVICE(0x1075),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    79
	INTEL_E1000_ETHERNET_DEVICE(0x1076),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    80
	INTEL_E1000_ETHERNET_DEVICE(0x1077),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    81
	INTEL_E1000_ETHERNET_DEVICE(0x1078),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    82
	INTEL_E1000_ETHERNET_DEVICE(0x1079),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    83
	INTEL_E1000_ETHERNET_DEVICE(0x107A),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    84
	INTEL_E1000_ETHERNET_DEVICE(0x107B),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    85
	INTEL_E1000_ETHERNET_DEVICE(0x107C),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    86
	INTEL_E1000_ETHERNET_DEVICE(0x108A),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    87
	INTEL_E1000_ETHERNET_DEVICE(0x1099),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    88
	INTEL_E1000_ETHERNET_DEVICE(0x10B5),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    89
	INTEL_E1000_ETHERNET_DEVICE(0x2E6E),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    90
	/* required last entry */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    91
	{0,}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    92
};
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    93
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    94
MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    95
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    96
int e1000_up(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    97
void e1000_down(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    98
void e1000_reinit_locked(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    99
void e1000_reset(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   100
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   101
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   102
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   103
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   104
static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   105
                             struct e1000_tx_ring *txdr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   106
static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   107
                             struct e1000_rx_ring *rxdr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   108
static void e1000_free_tx_resources(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   109
                             struct e1000_tx_ring *tx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   110
static void e1000_free_rx_resources(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   111
                             struct e1000_rx_ring *rx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   112
void e1000_update_stats(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   113
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   114
static int e1000_init_module(void);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   115
static void e1000_exit_module(void);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   116
static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   117
static void __devexit e1000_remove(struct pci_dev *pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   118
static int e1000_alloc_queues(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   119
static int e1000_sw_init(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   120
static int e1000_open(struct net_device *netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   121
static int e1000_close(struct net_device *netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   122
static void e1000_configure_tx(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   123
static void e1000_configure_rx(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   124
static void e1000_setup_rctl(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   125
static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   126
static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   127
static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   128
                                struct e1000_tx_ring *tx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   129
static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   130
                                struct e1000_rx_ring *rx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   131
static void e1000_set_rx_mode(struct net_device *netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   132
static void e1000_update_phy_info(unsigned long data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   133
static void e1000_update_phy_info_task(struct work_struct *work);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   134
static void e1000_watchdog(unsigned long data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   135
static void e1000_82547_tx_fifo_stall(unsigned long data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   136
static void e1000_82547_tx_fifo_stall_task(struct work_struct *work);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   137
static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   138
				    struct net_device *netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   139
static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   140
static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   141
static int e1000_set_mac(struct net_device *netdev, void *p);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   142
static irqreturn_t e1000_intr(int irq, void *data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   143
static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   144
			       struct e1000_tx_ring *tx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   145
static int e1000_clean(struct napi_struct *napi, int budget);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   146
static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   147
			       struct e1000_rx_ring *rx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   148
			       int *work_done, int work_to_do);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   149
static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   150
				     struct e1000_rx_ring *rx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   151
				     int *work_done, int work_to_do);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   152
static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   153
				   struct e1000_rx_ring *rx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   154
				   int cleaned_count);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   155
static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   156
					 struct e1000_rx_ring *rx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   157
					 int cleaned_count);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   158
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   159
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   160
			   int cmd);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   161
static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   162
static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   163
static void e1000_tx_timeout(struct net_device *dev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   164
static void e1000_reset_task(struct work_struct *work);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   165
static void e1000_smartspeed(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   166
static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   167
                                       struct sk_buff *skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   168
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   169
static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   170
static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   171
static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   172
static void e1000_restore_vlan(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   173
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   174
#ifdef CONFIG_PM
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   175
static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   176
static int e1000_resume(struct pci_dev *pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   177
#endif
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   178
static void e1000_shutdown(struct pci_dev *pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   179
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   180
#ifdef CONFIG_NET_POLL_CONTROLLER
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   181
/* for netdump / net console */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   182
static void e1000_netpoll (struct net_device *netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   183
#endif
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   184
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   185
#define COPYBREAK_DEFAULT 256
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   186
static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   187
module_param(copybreak, uint, 0644);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   188
MODULE_PARM_DESC(copybreak,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   189
	"Maximum size of packet that is copied to a new buffer on receive");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   190
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   191
static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   192
                     pci_channel_state_t state);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   193
static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   194
static void e1000_io_resume(struct pci_dev *pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   195
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   196
static struct pci_error_handlers e1000_err_handler = {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   197
	.error_detected = e1000_io_error_detected,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   198
	.slot_reset = e1000_io_slot_reset,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   199
	.resume = e1000_io_resume,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   200
};
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   201
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   202
static struct pci_driver e1000_driver = {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   203
	.name     = e1000_driver_name,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   204
	.id_table = e1000_pci_tbl,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   205
	.probe    = e1000_probe,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   206
	.remove   = __devexit_p(e1000_remove),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   207
#ifdef CONFIG_PM
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   208
	/* Power Management Hooks */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   209
	.suspend  = e1000_suspend,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   210
	.resume   = e1000_resume,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   211
#endif
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   212
	.shutdown = e1000_shutdown,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   213
	.err_handler = &e1000_err_handler
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   214
};
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   215
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   216
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   217
MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   218
MODULE_LICENSE("GPL");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   219
MODULE_VERSION(DRV_VERSION);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   220
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   221
static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   222
module_param(debug, int, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   223
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   224
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   225
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   226
 * e1000_get_hw_dev - return device
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   227
 * used by hardware layer to print debugging information
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   228
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   229
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   230
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   231
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   232
	struct e1000_adapter *adapter = hw->back;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   233
	return adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   234
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   235
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   236
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   237
 * e1000_init_module - Driver Registration Routine
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   238
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   239
 * e1000_init_module is the first routine called when the driver is
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   240
 * loaded. All it does is register with the PCI subsystem.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   241
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   242
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   243
static int __init e1000_init_module(void)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   244
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   245
	int ret;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   246
	pr_info("%s - version %s\n", e1000_driver_string, e1000_driver_version);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   247
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   248
	pr_info("%s\n", e1000_copyright);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   249
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   250
	ret = pci_register_driver(&e1000_driver);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   251
	if (copybreak != COPYBREAK_DEFAULT) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   252
		if (copybreak == 0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   253
			pr_info("copybreak disabled\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   254
		else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   255
			pr_info("copybreak enabled for "
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   256
				   "packets <= %u bytes\n", copybreak);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   257
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   258
	return ret;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   259
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   260
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   261
module_init(e1000_init_module);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   262
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   263
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   264
 * e1000_exit_module - Driver Exit Cleanup Routine
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   265
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   266
 * e1000_exit_module is called just before the driver is removed
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   267
 * from memory.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   268
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   269
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   270
static void __exit e1000_exit_module(void)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   271
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   272
	pci_unregister_driver(&e1000_driver);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   273
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   274
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   275
module_exit(e1000_exit_module);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   276
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   277
static int e1000_request_irq(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   278
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   279
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   280
	irq_handler_t handler = e1000_intr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   281
	int irq_flags = IRQF_SHARED;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   282
	int err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   283
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   284
	err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   285
	                  netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   286
	if (err) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   287
		e_err(probe, "Unable to allocate interrupt Error: %d\n", err);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   288
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   289
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   290
	return err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   291
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   292
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   293
static void e1000_free_irq(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   294
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   295
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   296
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   297
	free_irq(adapter->pdev->irq, netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   298
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   299
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   300
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   301
 * e1000_irq_disable - Mask off interrupt generation on the NIC
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   302
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   303
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   304
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   305
static void e1000_irq_disable(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   306
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   307
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   308
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   309
	ew32(IMC, ~0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   310
	E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   311
	synchronize_irq(adapter->pdev->irq);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   312
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   313
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   314
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   315
 * e1000_irq_enable - Enable default interrupt generation settings
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   316
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   317
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   318
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   319
static void e1000_irq_enable(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   320
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   321
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   322
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   323
	ew32(IMS, IMS_ENABLE_MASK);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   324
	E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   325
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   326
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   327
static void e1000_update_mng_vlan(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   328
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   329
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   330
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   331
	u16 vid = hw->mng_cookie.vlan_id;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   332
	u16 old_vid = adapter->mng_vlan_id;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   333
	if (adapter->vlgrp) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   334
		if (!vlan_group_get_device(adapter->vlgrp, vid)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   335
			if (hw->mng_cookie.status &
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   336
				E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   337
				e1000_vlan_rx_add_vid(netdev, vid);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   338
				adapter->mng_vlan_id = vid;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   339
			} else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   340
				adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   341
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   342
			if ((old_vid != (u16)E1000_MNG_VLAN_NONE) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   343
					(vid != old_vid) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   344
			    !vlan_group_get_device(adapter->vlgrp, old_vid))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   345
				e1000_vlan_rx_kill_vid(netdev, old_vid);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   346
		} else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   347
			adapter->mng_vlan_id = vid;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   348
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   349
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   350
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   351
static void e1000_init_manageability(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   352
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   353
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   354
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   355
	if (adapter->en_mng_pt) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   356
		u32 manc = er32(MANC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   357
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   358
		/* disable hardware interception of ARP */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   359
		manc &= ~(E1000_MANC_ARP_EN);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   360
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   361
		ew32(MANC, manc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   362
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   363
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   364
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   365
static void e1000_release_manageability(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   366
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   367
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   368
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   369
	if (adapter->en_mng_pt) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   370
		u32 manc = er32(MANC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   371
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   372
		/* re-enable hardware interception of ARP */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   373
		manc |= E1000_MANC_ARP_EN;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   374
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   375
		ew32(MANC, manc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   376
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   377
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   378
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   379
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   380
 * e1000_configure - configure the hardware for RX and TX
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   381
 * @adapter = private board structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   382
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   383
static void e1000_configure(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   384
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   385
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   386
	int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   387
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   388
	e1000_set_rx_mode(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   389
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   390
	e1000_restore_vlan(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   391
	e1000_init_manageability(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   392
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   393
	e1000_configure_tx(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   394
	e1000_setup_rctl(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   395
	e1000_configure_rx(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   396
	/* call E1000_DESC_UNUSED which always leaves
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   397
	 * at least 1 descriptor unused to make sure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   398
	 * next_to_use != next_to_clean */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   399
	for (i = 0; i < adapter->num_rx_queues; i++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   400
		struct e1000_rx_ring *ring = &adapter->rx_ring[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   401
		adapter->alloc_rx_buf(adapter, ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   402
		                      E1000_DESC_UNUSED(ring));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   403
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   404
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   405
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   406
int e1000_up(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   407
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   408
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   409
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   410
	/* hardware has been reset, we need to reload some things */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   411
	e1000_configure(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   412
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   413
	clear_bit(__E1000_DOWN, &adapter->flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   414
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   415
	napi_enable(&adapter->napi);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   416
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   417
	e1000_irq_enable(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   418
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   419
	netif_wake_queue(adapter->netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   420
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   421
	/* fire a link change interrupt to start the watchdog */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   422
	ew32(ICS, E1000_ICS_LSC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   423
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   424
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   425
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   426
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   427
 * e1000_power_up_phy - restore link in case the phy was powered down
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   428
 * @adapter: address of board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   429
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   430
 * The phy may be powered down to save power and turn off link when the
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   431
 * driver is unloaded and wake on lan is not enabled (among others)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   432
 * *** this routine MUST be followed by a call to e1000_reset ***
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   433
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   434
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   435
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   436
void e1000_power_up_phy(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   437
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   438
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   439
	u16 mii_reg = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   440
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   441
	/* Just clear the power down bit to wake the phy back up */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   442
	if (hw->media_type == e1000_media_type_copper) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   443
		/* according to the manual, the phy will retain its
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   444
		 * settings across a power-down/up cycle */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   445
		e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   446
		mii_reg &= ~MII_CR_POWER_DOWN;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   447
		e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   448
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   449
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   450
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   451
static void e1000_power_down_phy(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   452
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   453
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   454
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   455
	/* Power down the PHY so no link is implied when interface is down *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   456
	 * The PHY cannot be powered down if any of the following is true *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   457
	 * (a) WoL is enabled
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   458
	 * (b) AMT is active
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   459
	 * (c) SoL/IDER session is active */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   460
	if (!adapter->wol && hw->mac_type >= e1000_82540 &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   461
	   hw->media_type == e1000_media_type_copper) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   462
		u16 mii_reg = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   463
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   464
		switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   465
		case e1000_82540:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   466
		case e1000_82545:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   467
		case e1000_82545_rev_3:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   468
		case e1000_82546:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   469
		case e1000_ce4100:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   470
		case e1000_82546_rev_3:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   471
		case e1000_82541:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   472
		case e1000_82541_rev_2:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   473
		case e1000_82547:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   474
		case e1000_82547_rev_2:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   475
			if (er32(MANC) & E1000_MANC_SMBUS_EN)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   476
				goto out;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   477
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   478
		default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   479
			goto out;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   480
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   481
		e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   482
		mii_reg |= MII_CR_POWER_DOWN;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   483
		e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   484
		mdelay(1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   485
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   486
out:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   487
	return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   488
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   489
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   490
void e1000_down(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   491
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   492
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   493
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   494
	u32 rctl, tctl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   495
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   496
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   497
	/* disable receives in the hardware */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   498
	rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   499
	ew32(RCTL, rctl & ~E1000_RCTL_EN);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   500
	/* flush and sleep below */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   501
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   502
	netif_tx_disable(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   503
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   504
	/* disable transmits in the hardware */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   505
	tctl = er32(TCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   506
	tctl &= ~E1000_TCTL_EN;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   507
	ew32(TCTL, tctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   508
	/* flush both disables and wait for them to finish */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   509
	E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   510
	msleep(10);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   511
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   512
	napi_disable(&adapter->napi);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   513
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   514
	e1000_irq_disable(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   515
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   516
	/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   517
	 * Setting DOWN must be after irq_disable to prevent
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   518
	 * a screaming interrupt.  Setting DOWN also prevents
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   519
	 * timers and tasks from rescheduling.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   520
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   521
	set_bit(__E1000_DOWN, &adapter->flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   522
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   523
	del_timer_sync(&adapter->tx_fifo_stall_timer);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   524
	del_timer_sync(&adapter->watchdog_timer);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   525
	del_timer_sync(&adapter->phy_info_timer);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   526
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   527
	adapter->link_speed = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   528
	adapter->link_duplex = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   529
	netif_carrier_off(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   530
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   531
	e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   532
	e1000_clean_all_tx_rings(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   533
	e1000_clean_all_rx_rings(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   534
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   535
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   536
static void e1000_reinit_safe(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   537
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   538
	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   539
		msleep(1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   540
	rtnl_lock();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   541
	e1000_down(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   542
	e1000_up(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   543
	rtnl_unlock();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   544
	clear_bit(__E1000_RESETTING, &adapter->flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   545
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   546
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   547
void e1000_reinit_locked(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   548
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   549
	/* if rtnl_lock is not held the call path is bogus */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   550
	ASSERT_RTNL();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   551
	WARN_ON(in_interrupt());
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   552
	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   553
		msleep(1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   554
	e1000_down(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   555
	e1000_up(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   556
	clear_bit(__E1000_RESETTING, &adapter->flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   557
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   558
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   559
void e1000_reset(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   560
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   561
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   562
	u32 pba = 0, tx_space, min_tx_space, min_rx_space;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   563
	bool legacy_pba_adjust = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   564
	u16 hwm;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   565
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   566
	/* Repartition Pba for greater than 9k mtu
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   567
	 * To take effect CTRL.RST is required.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   568
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   569
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   570
	switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   571
	case e1000_82542_rev2_0:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   572
	case e1000_82542_rev2_1:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   573
	case e1000_82543:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   574
	case e1000_82544:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   575
	case e1000_82540:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   576
	case e1000_82541:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   577
	case e1000_82541_rev_2:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   578
		legacy_pba_adjust = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   579
		pba = E1000_PBA_48K;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   580
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   581
	case e1000_82545:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   582
	case e1000_82545_rev_3:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   583
	case e1000_82546:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   584
	case e1000_ce4100:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   585
	case e1000_82546_rev_3:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   586
		pba = E1000_PBA_48K;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   587
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   588
	case e1000_82547:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   589
	case e1000_82547_rev_2:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   590
		legacy_pba_adjust = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   591
		pba = E1000_PBA_30K;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   592
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   593
	case e1000_undefined:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   594
	case e1000_num_macs:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   595
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   596
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   597
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   598
	if (legacy_pba_adjust) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   599
		if (hw->max_frame_size > E1000_RXBUFFER_8192)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   600
			pba -= 8; /* allocate more FIFO for Tx */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   601
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   602
		if (hw->mac_type == e1000_82547) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   603
			adapter->tx_fifo_head = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   604
			adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   605
			adapter->tx_fifo_size =
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   606
				(E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   607
			atomic_set(&adapter->tx_fifo_stall, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   608
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   609
	} else if (hw->max_frame_size >  ETH_FRAME_LEN + ETH_FCS_LEN) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   610
		/* adjust PBA for jumbo frames */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   611
		ew32(PBA, pba);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   612
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   613
		/* To maintain wire speed transmits, the Tx FIFO should be
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   614
		 * large enough to accommodate two full transmit packets,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   615
		 * rounded up to the next 1KB and expressed in KB.  Likewise,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   616
		 * the Rx FIFO should be large enough to accommodate at least
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   617
		 * one full receive packet and is similarly rounded up and
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   618
		 * expressed in KB. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   619
		pba = er32(PBA);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   620
		/* upper 16 bits has Tx packet buffer allocation size in KB */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   621
		tx_space = pba >> 16;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   622
		/* lower 16 bits has Rx packet buffer allocation size in KB */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   623
		pba &= 0xffff;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   624
		/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   625
		 * the tx fifo also stores 16 bytes of information about the tx
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   626
		 * but don't include ethernet FCS because hardware appends it
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   627
		 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   628
		min_tx_space = (hw->max_frame_size +
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   629
		                sizeof(struct e1000_tx_desc) -
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   630
		                ETH_FCS_LEN) * 2;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   631
		min_tx_space = ALIGN(min_tx_space, 1024);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   632
		min_tx_space >>= 10;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   633
		/* software strips receive CRC, so leave room for it */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   634
		min_rx_space = hw->max_frame_size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   635
		min_rx_space = ALIGN(min_rx_space, 1024);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   636
		min_rx_space >>= 10;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   637
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   638
		/* If current Tx allocation is less than the min Tx FIFO size,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   639
		 * and the min Tx FIFO size is less than the current Rx FIFO
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   640
		 * allocation, take space away from current Rx allocation */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   641
		if (tx_space < min_tx_space &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   642
		    ((min_tx_space - tx_space) < pba)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   643
			pba = pba - (min_tx_space - tx_space);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   644
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   645
			/* PCI/PCIx hardware has PBA alignment constraints */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   646
			switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   647
			case e1000_82545 ... e1000_82546_rev_3:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   648
				pba &= ~(E1000_PBA_8K - 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   649
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   650
			default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   651
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   652
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   653
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   654
			/* if short on rx space, rx wins and must trump tx
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   655
			 * adjustment or use Early Receive if available */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   656
			if (pba < min_rx_space)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   657
				pba = min_rx_space;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   658
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   659
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   660
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   661
	ew32(PBA, pba);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   662
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   663
	/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   664
	 * flow control settings:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   665
	 * The high water mark must be low enough to fit one full frame
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   666
	 * (or the size used for early receive) above it in the Rx FIFO.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   667
	 * Set it to the lower of:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   668
	 * - 90% of the Rx FIFO size, and
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   669
	 * - the full Rx FIFO size minus the early receive size (for parts
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   670
	 *   with ERT support assuming ERT set to E1000_ERT_2048), or
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   671
	 * - the full Rx FIFO size minus one full frame
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   672
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   673
	hwm = min(((pba << 10) * 9 / 10),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   674
		  ((pba << 10) - hw->max_frame_size));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   675
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   676
	hw->fc_high_water = hwm & 0xFFF8;	/* 8-byte granularity */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   677
	hw->fc_low_water = hw->fc_high_water - 8;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   678
	hw->fc_pause_time = E1000_FC_PAUSE_TIME;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   679
	hw->fc_send_xon = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   680
	hw->fc = hw->original_fc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   681
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   682
	/* Allow time for pending master requests to run */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   683
	e1000_reset_hw(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   684
	if (hw->mac_type >= e1000_82544)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   685
		ew32(WUC, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   686
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   687
	if (e1000_init_hw(hw))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   688
		e_dev_err("Hardware Error\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   689
	e1000_update_mng_vlan(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   690
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   691
	/* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   692
	if (hw->mac_type >= e1000_82544 &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   693
	    hw->autoneg == 1 &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   694
	    hw->autoneg_advertised == ADVERTISE_1000_FULL) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   695
		u32 ctrl = er32(CTRL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   696
		/* clear phy power management bit if we are in gig only mode,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   697
		 * which if enabled will attempt negotiation to 100Mb, which
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   698
		 * can cause a loss of link at power off or driver unload */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   699
		ctrl &= ~E1000_CTRL_SWDPIN3;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   700
		ew32(CTRL, ctrl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   701
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   702
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   703
	/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   704
	ew32(VET, ETHERNET_IEEE_VLAN_TYPE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   705
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   706
	e1000_reset_adaptive(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   707
	e1000_phy_get_info(hw, &adapter->phy_info);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   708
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   709
	e1000_release_manageability(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   710
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   711
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   712
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   713
 *  Dump the eeprom for users having checksum issues
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   714
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   715
static void e1000_dump_eeprom(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   716
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   717
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   718
	struct ethtool_eeprom eeprom;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   719
	const struct ethtool_ops *ops = netdev->ethtool_ops;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   720
	u8 *data;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   721
	int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   722
	u16 csum_old, csum_new = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   723
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   724
	eeprom.len = ops->get_eeprom_len(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   725
	eeprom.offset = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   726
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   727
	data = kmalloc(eeprom.len, GFP_KERNEL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   728
	if (!data) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   729
		pr_err("Unable to allocate memory to dump EEPROM data\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   730
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   731
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   732
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   733
	ops->get_eeprom(netdev, &eeprom, data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   734
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   735
	csum_old = (data[EEPROM_CHECKSUM_REG * 2]) +
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   736
		   (data[EEPROM_CHECKSUM_REG * 2 + 1] << 8);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   737
	for (i = 0; i < EEPROM_CHECKSUM_REG * 2; i += 2)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   738
		csum_new += data[i] + (data[i + 1] << 8);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   739
	csum_new = EEPROM_SUM - csum_new;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   740
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   741
	pr_err("/*********************/\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   742
	pr_err("Current EEPROM Checksum : 0x%04x\n", csum_old);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   743
	pr_err("Calculated              : 0x%04x\n", csum_new);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   744
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   745
	pr_err("Offset    Values\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   746
	pr_err("========  ======\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   747
	print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, data, 128, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   748
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   749
	pr_err("Include this output when contacting your support provider.\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   750
	pr_err("This is not a software error! Something bad happened to\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   751
	pr_err("your hardware or EEPROM image. Ignoring this problem could\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   752
	pr_err("result in further problems, possibly loss of data,\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   753
	pr_err("corruption or system hangs!\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   754
	pr_err("The MAC Address will be reset to 00:00:00:00:00:00,\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   755
	pr_err("which is invalid and requires you to set the proper MAC\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   756
	pr_err("address manually before continuing to enable this network\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   757
	pr_err("device. Please inspect the EEPROM dump and report the\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   758
	pr_err("issue to your hardware vendor or Intel Customer Support.\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   759
	pr_err("/*********************/\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   760
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   761
	kfree(data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   762
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   763
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   764
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   765
 * e1000_is_need_ioport - determine if an adapter needs ioport resources or not
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   766
 * @pdev: PCI device information struct
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   767
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   768
 * Return true if an adapter needs ioport resources
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   769
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   770
static int e1000_is_need_ioport(struct pci_dev *pdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   771
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   772
	switch (pdev->device) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   773
	case E1000_DEV_ID_82540EM:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   774
	case E1000_DEV_ID_82540EM_LOM:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   775
	case E1000_DEV_ID_82540EP:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   776
	case E1000_DEV_ID_82540EP_LOM:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   777
	case E1000_DEV_ID_82540EP_LP:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   778
	case E1000_DEV_ID_82541EI:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   779
	case E1000_DEV_ID_82541EI_MOBILE:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   780
	case E1000_DEV_ID_82541ER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   781
	case E1000_DEV_ID_82541ER_LOM:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   782
	case E1000_DEV_ID_82541GI:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   783
	case E1000_DEV_ID_82541GI_LF:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   784
	case E1000_DEV_ID_82541GI_MOBILE:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   785
	case E1000_DEV_ID_82544EI_COPPER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   786
	case E1000_DEV_ID_82544EI_FIBER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   787
	case E1000_DEV_ID_82544GC_COPPER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   788
	case E1000_DEV_ID_82544GC_LOM:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   789
	case E1000_DEV_ID_82545EM_COPPER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   790
	case E1000_DEV_ID_82545EM_FIBER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   791
	case E1000_DEV_ID_82546EB_COPPER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   792
	case E1000_DEV_ID_82546EB_FIBER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   793
	case E1000_DEV_ID_82546EB_QUAD_COPPER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   794
		return true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   795
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   796
		return false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   797
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   798
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   799
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   800
static const struct net_device_ops e1000_netdev_ops = {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   801
	.ndo_open		= e1000_open,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   802
	.ndo_stop		= e1000_close,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   803
	.ndo_start_xmit		= e1000_xmit_frame,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   804
	.ndo_get_stats		= e1000_get_stats,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   805
	.ndo_set_rx_mode	= e1000_set_rx_mode,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   806
	.ndo_set_mac_address	= e1000_set_mac,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   807
	.ndo_tx_timeout 	= e1000_tx_timeout,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   808
	.ndo_change_mtu		= e1000_change_mtu,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   809
	.ndo_do_ioctl		= e1000_ioctl,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   810
	.ndo_validate_addr	= eth_validate_addr,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   811
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   812
	.ndo_vlan_rx_register	= e1000_vlan_rx_register,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   813
	.ndo_vlan_rx_add_vid	= e1000_vlan_rx_add_vid,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   814
	.ndo_vlan_rx_kill_vid	= e1000_vlan_rx_kill_vid,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   815
#ifdef CONFIG_NET_POLL_CONTROLLER
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   816
	.ndo_poll_controller	= e1000_netpoll,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   817
#endif
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   818
};
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   819
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   820
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   821
 * e1000_init_hw_struct - initialize members of hw struct
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   822
 * @adapter: board private struct
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   823
 * @hw: structure used by e1000_hw.c
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   824
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   825
 * Factors out initialization of the e1000_hw struct to its own function
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   826
 * that can be called very early at init (just after struct allocation).
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   827
 * Fields are initialized based on PCI device information and
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   828
 * OS network device settings (MTU size).
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   829
 * Returns negative error codes if MAC type setup fails.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   830
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   831
static int e1000_init_hw_struct(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   832
				struct e1000_hw *hw)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   833
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   834
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   835
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   836
	/* PCI config space info */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   837
	hw->vendor_id = pdev->vendor;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   838
	hw->device_id = pdev->device;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   839
	hw->subsystem_vendor_id = pdev->subsystem_vendor;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   840
	hw->subsystem_id = pdev->subsystem_device;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   841
	hw->revision_id = pdev->revision;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   842
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   843
	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   844
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   845
	hw->max_frame_size = adapter->netdev->mtu +
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   846
			     ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   847
	hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   848
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   849
	/* identify the MAC */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   850
	if (e1000_set_mac_type(hw)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   851
		e_err(probe, "Unknown MAC Type\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   852
		return -EIO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   853
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   854
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   855
	switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   856
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   857
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   858
	case e1000_82541:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   859
	case e1000_82547:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   860
	case e1000_82541_rev_2:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   861
	case e1000_82547_rev_2:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   862
		hw->phy_init_script = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   863
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   864
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   865
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   866
	e1000_set_media_type(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   867
	e1000_get_bus_info(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   868
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   869
	hw->wait_autoneg_complete = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   870
	hw->tbi_compatibility_en = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   871
	hw->adaptive_ifs = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   872
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   873
	/* Copper options */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   874
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   875
	if (hw->media_type == e1000_media_type_copper) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   876
		hw->mdix = AUTO_ALL_MODES;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   877
		hw->disable_polarity_correction = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   878
		hw->master_slave = E1000_MASTER_SLAVE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   879
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   880
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   881
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   882
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   883
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   884
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   885
 * e1000_probe - Device Initialization Routine
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   886
 * @pdev: PCI device information struct
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   887
 * @ent: entry in e1000_pci_tbl
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   888
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   889
 * Returns 0 on success, negative on failure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   890
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   891
 * e1000_probe initializes an adapter identified by a pci_dev structure.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   892
 * The OS initialization, configuring of the adapter private structure,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   893
 * and a hardware reset occur.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   894
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   895
static int __devinit e1000_probe(struct pci_dev *pdev,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   896
				 const struct pci_device_id *ent)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   897
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   898
	struct net_device *netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   899
	struct e1000_adapter *adapter;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   900
	struct e1000_hw *hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   901
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   902
	static int cards_found = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   903
	static int global_quad_port_a = 0; /* global ksp3 port a indication */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   904
	int i, err, pci_using_dac;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   905
	u16 eeprom_data = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   906
	u16 tmp = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   907
	u16 eeprom_apme_mask = E1000_EEPROM_APME;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   908
	int bars, need_ioport;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   909
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   910
	/* do not allocate ioport bars when not needed */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   911
	need_ioport = e1000_is_need_ioport(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   912
	if (need_ioport) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   913
		bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   914
		err = pci_enable_device(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   915
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   916
		bars = pci_select_bars(pdev, IORESOURCE_MEM);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   917
		err = pci_enable_device_mem(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   918
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   919
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   920
		return err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   921
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   922
	err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   923
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   924
		goto err_pci_reg;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   925
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   926
	pci_set_master(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   927
	err = pci_save_state(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   928
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   929
		goto err_alloc_etherdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   930
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   931
	err = -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   932
	netdev = alloc_etherdev(sizeof(struct e1000_adapter));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   933
	if (!netdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   934
		goto err_alloc_etherdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   935
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   936
	SET_NETDEV_DEV(netdev, &pdev->dev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   937
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   938
	pci_set_drvdata(pdev, netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   939
	adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   940
	adapter->netdev = netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   941
	adapter->pdev = pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   942
	adapter->msg_enable = (1 << debug) - 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   943
	adapter->bars = bars;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   944
	adapter->need_ioport = need_ioport;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   945
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   946
	hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   947
	hw->back = adapter;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   948
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   949
	err = -EIO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   950
	hw->hw_addr = pci_ioremap_bar(pdev, BAR_0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   951
	if (!hw->hw_addr)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   952
		goto err_ioremap;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   953
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   954
	if (adapter->need_ioport) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   955
		for (i = BAR_1; i <= BAR_5; i++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   956
			if (pci_resource_len(pdev, i) == 0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   957
				continue;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   958
			if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   959
				hw->io_base = pci_resource_start(pdev, i);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   960
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   961
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   962
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   963
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   964
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   965
	/* make ready for any if (hw->...) below */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   966
	err = e1000_init_hw_struct(adapter, hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   967
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   968
		goto err_sw_init;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   969
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   970
	/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   971
	 * there is a workaround being applied below that limits
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   972
	 * 64-bit DMA addresses to 64-bit hardware.  There are some
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   973
	 * 32-bit adapters that Tx hang when given 64-bit DMA addresses
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   974
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   975
	pci_using_dac = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   976
	if ((hw->bus_type == e1000_bus_type_pcix) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   977
	    !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   978
		/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   979
		 * according to DMA-API-HOWTO, coherent calls will always
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   980
		 * succeed if the set call did
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   981
		 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   982
		dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   983
		pci_using_dac = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   984
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   985
		err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   986
		if (err) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   987
			pr_err("No usable DMA config, aborting\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   988
			goto err_dma;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   989
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   990
		dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   991
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   992
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   993
	netdev->netdev_ops = &e1000_netdev_ops;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   994
	e1000_set_ethtool_ops(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   995
	netdev->watchdog_timeo = 5 * HZ;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   996
	netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   997
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   998
	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   999
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1000
	adapter->bd_number = cards_found;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1001
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1002
	/* setup the private structure */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1003
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1004
	err = e1000_sw_init(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1005
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1006
		goto err_sw_init;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1007
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1008
	err = -EIO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1009
	if (hw->mac_type == e1000_ce4100) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1010
		ce4100_gbe_mdio_base_phy = pci_resource_start(pdev, BAR_1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1011
		ce4100_gbe_mdio_base_virt = ioremap(ce4100_gbe_mdio_base_phy,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1012
		                                pci_resource_len(pdev, BAR_1));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1013
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1014
		if (!ce4100_gbe_mdio_base_virt)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1015
			goto err_mdio_ioremap;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1016
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1017
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1018
	if (hw->mac_type >= e1000_82543) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1019
		netdev->features = NETIF_F_SG |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1020
				   NETIF_F_HW_CSUM |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1021
				   NETIF_F_HW_VLAN_TX |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1022
				   NETIF_F_HW_VLAN_RX |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1023
				   NETIF_F_HW_VLAN_FILTER;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1024
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1025
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1026
	if ((hw->mac_type >= e1000_82544) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1027
	   (hw->mac_type != e1000_82547))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1028
		netdev->features |= NETIF_F_TSO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1029
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1030
	if (pci_using_dac) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1031
		netdev->features |= NETIF_F_HIGHDMA;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1032
		netdev->vlan_features |= NETIF_F_HIGHDMA;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1033
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1034
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1035
	netdev->vlan_features |= NETIF_F_TSO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1036
	netdev->vlan_features |= NETIF_F_HW_CSUM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1037
	netdev->vlan_features |= NETIF_F_SG;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1038
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1039
	adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1040
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1041
	/* initialize eeprom parameters */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1042
	if (e1000_init_eeprom_params(hw)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1043
		e_err(probe, "EEPROM initialization failed\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1044
		goto err_eeprom;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1045
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1046
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1047
	/* before reading the EEPROM, reset the controller to
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1048
	 * put the device in a known good starting state */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1049
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1050
	e1000_reset_hw(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1051
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1052
	/* make sure the EEPROM is good */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1053
	if (e1000_validate_eeprom_checksum(hw) < 0) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1054
		e_err(probe, "The EEPROM Checksum Is Not Valid\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1055
		e1000_dump_eeprom(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1056
		/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1057
		 * set MAC address to all zeroes to invalidate and temporary
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1058
		 * disable this device for the user. This blocks regular
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1059
		 * traffic while still permitting ethtool ioctls from reaching
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1060
		 * the hardware as well as allowing the user to run the
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1061
		 * interface after manually setting a hw addr using
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1062
		 * `ip set address`
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1063
		 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1064
		memset(hw->mac_addr, 0, netdev->addr_len);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1065
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1066
		/* copy the MAC address out of the EEPROM */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1067
		if (e1000_read_mac_addr(hw))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1068
			e_err(probe, "EEPROM Read Error\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1069
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1070
	/* don't block initalization here due to bad MAC address */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1071
	memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1072
	memcpy(netdev->perm_addr, hw->mac_addr, netdev->addr_len);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1073
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1074
	if (!is_valid_ether_addr(netdev->perm_addr))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1075
		e_err(probe, "Invalid MAC Address\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1076
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1077
	init_timer(&adapter->tx_fifo_stall_timer);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1078
	adapter->tx_fifo_stall_timer.function = e1000_82547_tx_fifo_stall;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1079
	adapter->tx_fifo_stall_timer.data = (unsigned long)adapter;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1080
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1081
	init_timer(&adapter->watchdog_timer);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1082
	adapter->watchdog_timer.function = e1000_watchdog;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1083
	adapter->watchdog_timer.data = (unsigned long) adapter;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1084
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1085
	init_timer(&adapter->phy_info_timer);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1086
	adapter->phy_info_timer.function = e1000_update_phy_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1087
	adapter->phy_info_timer.data = (unsigned long)adapter;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1088
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1089
	INIT_WORK(&adapter->fifo_stall_task, e1000_82547_tx_fifo_stall_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1090
	INIT_WORK(&adapter->reset_task, e1000_reset_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1091
	INIT_WORK(&adapter->phy_info_task, e1000_update_phy_info_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1092
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1093
	e1000_check_options(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1094
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1095
	/* Initial Wake on LAN setting
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1096
	 * If APM wake is enabled in the EEPROM,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1097
	 * enable the ACPI Magic Packet filter
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1098
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1099
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1100
	switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1101
	case e1000_82542_rev2_0:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1102
	case e1000_82542_rev2_1:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1103
	case e1000_82543:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1104
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1105
	case e1000_82544:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1106
		e1000_read_eeprom(hw,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1107
			EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1108
		eeprom_apme_mask = E1000_EEPROM_82544_APM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1109
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1110
	case e1000_82546:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1111
	case e1000_82546_rev_3:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1112
		if (er32(STATUS) & E1000_STATUS_FUNC_1){
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1113
			e1000_read_eeprom(hw,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1114
				EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1115
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1116
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1117
		/* Fall Through */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1118
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1119
		e1000_read_eeprom(hw,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1120
			EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1121
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1122
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1123
	if (eeprom_data & eeprom_apme_mask)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1124
		adapter->eeprom_wol |= E1000_WUFC_MAG;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1125
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1126
	/* now that we have the eeprom settings, apply the special cases
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1127
	 * where the eeprom may be wrong or the board simply won't support
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1128
	 * wake on lan on a particular port */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1129
	switch (pdev->device) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1130
	case E1000_DEV_ID_82546GB_PCIE:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1131
		adapter->eeprom_wol = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1132
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1133
	case E1000_DEV_ID_82546EB_FIBER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1134
	case E1000_DEV_ID_82546GB_FIBER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1135
		/* Wake events only supported on port A for dual fiber
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1136
		 * regardless of eeprom setting */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1137
		if (er32(STATUS) & E1000_STATUS_FUNC_1)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1138
			adapter->eeprom_wol = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1139
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1140
	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1141
		/* if quad port adapter, disable WoL on all but port A */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1142
		if (global_quad_port_a != 0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1143
			adapter->eeprom_wol = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1144
		else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1145
			adapter->quad_port_a = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1146
		/* Reset for multiple quad port adapters */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1147
		if (++global_quad_port_a == 4)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1148
			global_quad_port_a = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1149
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1150
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1151
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1152
	/* initialize the wol settings based on the eeprom settings */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1153
	adapter->wol = adapter->eeprom_wol;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1154
	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1155
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1156
	/* Auto detect PHY address */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1157
	if (hw->mac_type == e1000_ce4100) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1158
		for (i = 0; i < 32; i++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1159
			hw->phy_addr = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1160
			e1000_read_phy_reg(hw, PHY_ID2, &tmp);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1161
			if (tmp == 0 || tmp == 0xFF) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1162
				if (i == 31)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1163
					goto err_eeprom;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1164
				continue;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1165
			} else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1166
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1167
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1168
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1169
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1170
	/* reset the hardware with the new settings */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1171
	e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1172
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1173
	strcpy(netdev->name, "eth%d");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1174
	err = register_netdev(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1175
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1176
		goto err_register;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1177
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1178
	/* print bus type/speed/width info */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1179
	e_info(probe, "(PCI%s:%dMHz:%d-bit) %pM\n",
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1180
	       ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1181
	       ((hw->bus_speed == e1000_bus_speed_133) ? 133 :
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1182
		(hw->bus_speed == e1000_bus_speed_120) ? 120 :
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1183
		(hw->bus_speed == e1000_bus_speed_100) ? 100 :
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1184
		(hw->bus_speed == e1000_bus_speed_66) ? 66 : 33),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1185
	       ((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1186
	       netdev->dev_addr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1187
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1188
	/* carrier off reporting is important to ethtool even BEFORE open */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1189
	netif_carrier_off(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1190
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1191
	e_info(probe, "Intel(R) PRO/1000 Network Connection\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1192
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1193
	cards_found++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1194
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1195
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1196
err_register:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1197
err_eeprom:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1198
	e1000_phy_hw_reset(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1199
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1200
	if (hw->flash_address)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1201
		iounmap(hw->flash_address);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1202
	kfree(adapter->tx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1203
	kfree(adapter->rx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1204
err_dma:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1205
err_sw_init:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1206
err_mdio_ioremap:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1207
	iounmap(ce4100_gbe_mdio_base_virt);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1208
	iounmap(hw->hw_addr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1209
err_ioremap:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1210
	free_netdev(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1211
err_alloc_etherdev:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1212
	pci_release_selected_regions(pdev, bars);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1213
err_pci_reg:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1214
	pci_disable_device(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1215
	return err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1216
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1217
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1218
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1219
 * e1000_remove - Device Removal Routine
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1220
 * @pdev: PCI device information struct
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1221
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1222
 * e1000_remove is called by the PCI subsystem to alert the driver
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1223
 * that it should release a PCI device.  The could be caused by a
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1224
 * Hot-Plug event, or because the driver is going to be removed from
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1225
 * memory.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1226
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1227
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1228
static void __devexit e1000_remove(struct pci_dev *pdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1229
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1230
	struct net_device *netdev = pci_get_drvdata(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1231
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1232
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1233
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1234
	set_bit(__E1000_DOWN, &adapter->flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1235
	del_timer_sync(&adapter->tx_fifo_stall_timer);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1236
	del_timer_sync(&adapter->watchdog_timer);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1237
	del_timer_sync(&adapter->phy_info_timer);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1238
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1239
	cancel_work_sync(&adapter->reset_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1240
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1241
	e1000_release_manageability(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1242
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1243
	unregister_netdev(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1244
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1245
	e1000_phy_hw_reset(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1246
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1247
	kfree(adapter->tx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1248
	kfree(adapter->rx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1249
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1250
	iounmap(hw->hw_addr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1251
	if (hw->flash_address)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1252
		iounmap(hw->flash_address);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1253
	pci_release_selected_regions(pdev, adapter->bars);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1254
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1255
	free_netdev(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1256
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1257
	pci_disable_device(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1258
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1259
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1260
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1261
 * e1000_sw_init - Initialize general software structures (struct e1000_adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1262
 * @adapter: board private structure to initialize
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1263
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1264
 * e1000_sw_init initializes the Adapter private data structure.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1265
 * e1000_init_hw_struct MUST be called before this function
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1266
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1267
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1268
static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1269
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1270
	adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1271
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1272
	adapter->num_tx_queues = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1273
	adapter->num_rx_queues = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1274
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1275
	if (e1000_alloc_queues(adapter)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1276
		e_err(probe, "Unable to allocate memory for queues\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1277
		return -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1278
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1279
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1280
	/* Explicitly disable IRQ since the NIC can be in any state. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1281
	e1000_irq_disable(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1282
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1283
	spin_lock_init(&adapter->stats_lock);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1284
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1285
	set_bit(__E1000_DOWN, &adapter->flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1286
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1287
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1288
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1289
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1290
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1291
 * e1000_alloc_queues - Allocate memory for all rings
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1292
 * @adapter: board private structure to initialize
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1293
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1294
 * We allocate one ring per queue at run-time since we don't know the
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1295
 * number of queues at compile-time.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1296
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1297
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1298
static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1299
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1300
	adapter->tx_ring = kcalloc(adapter->num_tx_queues,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1301
	                           sizeof(struct e1000_tx_ring), GFP_KERNEL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1302
	if (!adapter->tx_ring)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1303
		return -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1304
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1305
	adapter->rx_ring = kcalloc(adapter->num_rx_queues,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1306
	                           sizeof(struct e1000_rx_ring), GFP_KERNEL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1307
	if (!adapter->rx_ring) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1308
		kfree(adapter->tx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1309
		return -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1310
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1311
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1312
	return E1000_SUCCESS;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1313
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1314
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1315
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1316
 * e1000_open - Called when a network interface is made active
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1317
 * @netdev: network interface device structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1318
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1319
 * Returns 0 on success, negative value on failure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1320
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1321
 * The open entry point is called when a network interface is made
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1322
 * active by the system (IFF_UP).  At this point all resources needed
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1323
 * for transmit and receive operations are allocated, the interrupt
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1324
 * handler is registered with the OS, the watchdog timer is started,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1325
 * and the stack is notified that the interface is ready.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1326
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1327
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1328
static int e1000_open(struct net_device *netdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1329
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1330
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1331
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1332
	int err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1333
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1334
	/* disallow open during test */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1335
	if (test_bit(__E1000_TESTING, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1336
		return -EBUSY;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1337
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1338
	netif_carrier_off(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1339
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1340
	/* allocate transmit descriptors */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1341
	err = e1000_setup_all_tx_resources(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1342
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1343
		goto err_setup_tx;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1344
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1345
	/* allocate receive descriptors */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1346
	err = e1000_setup_all_rx_resources(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1347
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1348
		goto err_setup_rx;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1349
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1350
	e1000_power_up_phy(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1351
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1352
	adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1353
	if ((hw->mng_cookie.status &
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1354
			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1355
		e1000_update_mng_vlan(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1356
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1357
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1358
	/* before we allocate an interrupt, we must be ready to handle it.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1359
	 * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1360
	 * as soon as we call pci_request_irq, so we have to setup our
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1361
	 * clean_rx handler before we do so.  */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1362
	e1000_configure(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1363
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1364
	err = e1000_request_irq(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1365
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1366
		goto err_req_irq;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1367
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1368
	/* From here on the code is the same as e1000_up() */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1369
	clear_bit(__E1000_DOWN, &adapter->flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1370
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1371
	napi_enable(&adapter->napi);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1372
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1373
	e1000_irq_enable(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1374
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1375
	netif_start_queue(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1376
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1377
	/* fire a link status change interrupt to start the watchdog */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1378
	ew32(ICS, E1000_ICS_LSC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1379
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1380
	return E1000_SUCCESS;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1381
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1382
err_req_irq:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1383
	e1000_power_down_phy(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1384
	e1000_free_all_rx_resources(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1385
err_setup_rx:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1386
	e1000_free_all_tx_resources(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1387
err_setup_tx:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1388
	e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1389
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1390
	return err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1391
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1392
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1393
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1394
 * e1000_close - Disables a network interface
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1395
 * @netdev: network interface device structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1396
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1397
 * Returns 0, this is not allowed to fail
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1398
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1399
 * The close entry point is called when an interface is de-activated
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1400
 * by the OS.  The hardware is still under the drivers control, but
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1401
 * needs to be disabled.  A global MAC reset is issued to stop the
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1402
 * hardware, and all transmit and receive resources are freed.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1403
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1404
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1405
static int e1000_close(struct net_device *netdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1406
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1407
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1408
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1409
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1410
	WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1411
	e1000_down(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1412
	e1000_power_down_phy(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1413
	e1000_free_irq(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1414
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1415
	e1000_free_all_tx_resources(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1416
	e1000_free_all_rx_resources(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1417
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1418
	/* kill manageability vlan ID if supported, but not if a vlan with
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1419
	 * the same ID is registered on the host OS (let 8021q kill it) */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1420
	if ((hw->mng_cookie.status &
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1421
			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1422
	     !(adapter->vlgrp &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1423
	       vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1424
		e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1425
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1426
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1427
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1428
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1429
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1430
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1431
 * e1000_check_64k_bound - check that memory doesn't cross 64kB boundary
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1432
 * @adapter: address of board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1433
 * @start: address of beginning of memory
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1434
 * @len: length of memory
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1435
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1436
static bool e1000_check_64k_bound(struct e1000_adapter *adapter, void *start,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1437
				  unsigned long len)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1438
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1439
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1440
	unsigned long begin = (unsigned long)start;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1441
	unsigned long end = begin + len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1442
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1443
	/* First rev 82545 and 82546 need to not allow any memory
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1444
	 * write location to cross 64k boundary due to errata 23 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1445
	if (hw->mac_type == e1000_82545 ||
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1446
	    hw->mac_type == e1000_ce4100 ||
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1447
	    hw->mac_type == e1000_82546) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1448
		return ((begin ^ (end - 1)) >> 16) != 0 ? false : true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1449
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1450
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1451
	return true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1452
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1453
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1454
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1455
 * e1000_setup_tx_resources - allocate Tx resources (Descriptors)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1456
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1457
 * @txdr:    tx descriptor ring (for a specific queue) to setup
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1458
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1459
 * Return 0 on success, negative on failure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1460
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1461
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1462
static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1463
				    struct e1000_tx_ring *txdr)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1464
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1465
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1466
	int size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1467
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1468
	size = sizeof(struct e1000_buffer) * txdr->count;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1469
	txdr->buffer_info = vzalloc(size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1470
	if (!txdr->buffer_info) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1471
		e_err(probe, "Unable to allocate memory for the Tx descriptor "
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1472
		      "ring\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1473
		return -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1474
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1475
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1476
	/* round up to nearest 4K */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1477
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1478
	txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1479
	txdr->size = ALIGN(txdr->size, 4096);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1480
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1481
	txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1482
					GFP_KERNEL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1483
	if (!txdr->desc) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1484
setup_tx_desc_die:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1485
		vfree(txdr->buffer_info);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1486
		e_err(probe, "Unable to allocate memory for the Tx descriptor "
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1487
		      "ring\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1488
		return -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1489
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1490
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1491
	/* Fix for errata 23, can't cross 64kB boundary */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1492
	if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1493
		void *olddesc = txdr->desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1494
		dma_addr_t olddma = txdr->dma;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1495
		e_err(tx_err, "txdr align check failed: %u bytes at %p\n",
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1496
		      txdr->size, txdr->desc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1497
		/* Try again, without freeing the previous */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1498
		txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1499
						&txdr->dma, GFP_KERNEL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1500
		/* Failed allocation, critical failure */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1501
		if (!txdr->desc) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1502
			dma_free_coherent(&pdev->dev, txdr->size, olddesc,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1503
					  olddma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1504
			goto setup_tx_desc_die;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1505
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1506
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1507
		if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1508
			/* give up */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1509
			dma_free_coherent(&pdev->dev, txdr->size, txdr->desc,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1510
					  txdr->dma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1511
			dma_free_coherent(&pdev->dev, txdr->size, olddesc,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1512
					  olddma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1513
			e_err(probe, "Unable to allocate aligned memory "
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1514
			      "for the transmit descriptor ring\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1515
			vfree(txdr->buffer_info);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1516
			return -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1517
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1518
			/* Free old allocation, new allocation was successful */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1519
			dma_free_coherent(&pdev->dev, txdr->size, olddesc,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1520
					  olddma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1521
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1522
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1523
	memset(txdr->desc, 0, txdr->size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1524
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1525
	txdr->next_to_use = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1526
	txdr->next_to_clean = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1527
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1528
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1529
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1530
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1531
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1532
 * e1000_setup_all_tx_resources - wrapper to allocate Tx resources
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1533
 * 				  (Descriptors) for all queues
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1534
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1535
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1536
 * Return 0 on success, negative on failure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1537
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1538
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1539
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1540
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1541
	int i, err = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1542
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1543
	for (i = 0; i < adapter->num_tx_queues; i++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1544
		err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1545
		if (err) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1546
			e_err(probe, "Allocation for Tx Queue %u failed\n", i);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1547
			for (i-- ; i >= 0; i--)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1548
				e1000_free_tx_resources(adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1549
							&adapter->tx_ring[i]);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1550
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1551
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1552
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1553
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1554
	return err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1555
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1556
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1557
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1558
 * e1000_configure_tx - Configure 8254x Transmit Unit after Reset
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1559
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1560
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1561
 * Configure the Tx unit of the MAC after a reset.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1562
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1563
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1564
static void e1000_configure_tx(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1565
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1566
	u64 tdba;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1567
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1568
	u32 tdlen, tctl, tipg;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1569
	u32 ipgr1, ipgr2;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1570
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1571
	/* Setup the HW Tx Head and Tail descriptor pointers */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1572
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1573
	switch (adapter->num_tx_queues) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1574
	case 1:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1575
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1576
		tdba = adapter->tx_ring[0].dma;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1577
		tdlen = adapter->tx_ring[0].count *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1578
			sizeof(struct e1000_tx_desc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1579
		ew32(TDLEN, tdlen);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1580
		ew32(TDBAH, (tdba >> 32));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1581
		ew32(TDBAL, (tdba & 0x00000000ffffffffULL));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1582
		ew32(TDT, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1583
		ew32(TDH, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1584
		adapter->tx_ring[0].tdh = ((hw->mac_type >= e1000_82543) ? E1000_TDH : E1000_82542_TDH);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1585
		adapter->tx_ring[0].tdt = ((hw->mac_type >= e1000_82543) ? E1000_TDT : E1000_82542_TDT);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1586
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1587
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1588
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1589
	/* Set the default values for the Tx Inter Packet Gap timer */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1590
	if ((hw->media_type == e1000_media_type_fiber ||
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1591
	     hw->media_type == e1000_media_type_internal_serdes))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1592
		tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1593
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1594
		tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1595
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1596
	switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1597
	case e1000_82542_rev2_0:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1598
	case e1000_82542_rev2_1:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1599
		tipg = DEFAULT_82542_TIPG_IPGT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1600
		ipgr1 = DEFAULT_82542_TIPG_IPGR1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1601
		ipgr2 = DEFAULT_82542_TIPG_IPGR2;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1602
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1603
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1604
		ipgr1 = DEFAULT_82543_TIPG_IPGR1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1605
		ipgr2 = DEFAULT_82543_TIPG_IPGR2;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1606
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1607
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1608
	tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1609
	tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1610
	ew32(TIPG, tipg);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1611
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1612
	/* Set the Tx Interrupt Delay register */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1613
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1614
	ew32(TIDV, adapter->tx_int_delay);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1615
	if (hw->mac_type >= e1000_82540)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1616
		ew32(TADV, adapter->tx_abs_int_delay);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1617
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1618
	/* Program the Transmit Control Register */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1619
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1620
	tctl = er32(TCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1621
	tctl &= ~E1000_TCTL_CT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1622
	tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1623
		(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1624
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1625
	e1000_config_collision_dist(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1626
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1627
	/* Setup Transmit Descriptor Settings for eop descriptor */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1628
	adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1629
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1630
	/* only set IDE if we are delaying interrupts using the timers */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1631
	if (adapter->tx_int_delay)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1632
		adapter->txd_cmd |= E1000_TXD_CMD_IDE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1633
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1634
	if (hw->mac_type < e1000_82543)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1635
		adapter->txd_cmd |= E1000_TXD_CMD_RPS;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1636
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1637
		adapter->txd_cmd |= E1000_TXD_CMD_RS;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1638
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1639
	/* Cache if we're 82544 running in PCI-X because we'll
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1640
	 * need this to apply a workaround later in the send path. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1641
	if (hw->mac_type == e1000_82544 &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1642
	    hw->bus_type == e1000_bus_type_pcix)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1643
		adapter->pcix_82544 = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1644
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1645
	ew32(TCTL, tctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1646
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1647
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1648
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1649
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1650
 * e1000_setup_rx_resources - allocate Rx resources (Descriptors)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1651
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1652
 * @rxdr:    rx descriptor ring (for a specific queue) to setup
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1653
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1654
 * Returns 0 on success, negative on failure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1655
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1656
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1657
static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1658
				    struct e1000_rx_ring *rxdr)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1659
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1660
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1661
	int size, desc_len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1662
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1663
	size = sizeof(struct e1000_buffer) * rxdr->count;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1664
	rxdr->buffer_info = vzalloc(size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1665
	if (!rxdr->buffer_info) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1666
		e_err(probe, "Unable to allocate memory for the Rx descriptor "
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1667
		      "ring\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1668
		return -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1669
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1670
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1671
	desc_len = sizeof(struct e1000_rx_desc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1672
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1673
	/* Round up to nearest 4K */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1674
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1675
	rxdr->size = rxdr->count * desc_len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1676
	rxdr->size = ALIGN(rxdr->size, 4096);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1677
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1678
	rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1679
					GFP_KERNEL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1680
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1681
	if (!rxdr->desc) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1682
		e_err(probe, "Unable to allocate memory for the Rx descriptor "
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1683
		      "ring\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1684
setup_rx_desc_die:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1685
		vfree(rxdr->buffer_info);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1686
		return -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1687
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1688
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1689
	/* Fix for errata 23, can't cross 64kB boundary */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1690
	if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1691
		void *olddesc = rxdr->desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1692
		dma_addr_t olddma = rxdr->dma;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1693
		e_err(rx_err, "rxdr align check failed: %u bytes at %p\n",
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1694
		      rxdr->size, rxdr->desc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1695
		/* Try again, without freeing the previous */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1696
		rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1697
						&rxdr->dma, GFP_KERNEL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1698
		/* Failed allocation, critical failure */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1699
		if (!rxdr->desc) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1700
			dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1701
					  olddma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1702
			e_err(probe, "Unable to allocate memory for the Rx "
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1703
			      "descriptor ring\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1704
			goto setup_rx_desc_die;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1705
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1706
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1707
		if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1708
			/* give up */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1709
			dma_free_coherent(&pdev->dev, rxdr->size, rxdr->desc,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1710
					  rxdr->dma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1711
			dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1712
					  olddma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1713
			e_err(probe, "Unable to allocate aligned memory for "
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1714
			      "the Rx descriptor ring\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1715
			goto setup_rx_desc_die;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1716
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1717
			/* Free old allocation, new allocation was successful */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1718
			dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1719
					  olddma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1720
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1721
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1722
	memset(rxdr->desc, 0, rxdr->size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1723
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1724
	rxdr->next_to_clean = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1725
	rxdr->next_to_use = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1726
	rxdr->rx_skb_top = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1727
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1728
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1729
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1730
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1731
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1732
 * e1000_setup_all_rx_resources - wrapper to allocate Rx resources
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1733
 * 				  (Descriptors) for all queues
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1734
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1735
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1736
 * Return 0 on success, negative on failure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1737
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1738
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1739
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1740
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1741
	int i, err = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1742
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1743
	for (i = 0; i < adapter->num_rx_queues; i++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1744
		err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1745
		if (err) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1746
			e_err(probe, "Allocation for Rx Queue %u failed\n", i);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1747
			for (i-- ; i >= 0; i--)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1748
				e1000_free_rx_resources(adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1749
							&adapter->rx_ring[i]);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1750
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1751
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1752
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1753
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1754
	return err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1755
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1756
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1757
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1758
 * e1000_setup_rctl - configure the receive control registers
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1759
 * @adapter: Board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1760
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1761
static void e1000_setup_rctl(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1762
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1763
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1764
	u32 rctl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1765
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1766
	rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1767
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1768
	rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1769
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1770
	rctl |= E1000_RCTL_EN | E1000_RCTL_BAM |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1771
		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1772
		(hw->mc_filter_type << E1000_RCTL_MO_SHIFT);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1773
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1774
	if (hw->tbi_compatibility_on == 1)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1775
		rctl |= E1000_RCTL_SBP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1776
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1777
		rctl &= ~E1000_RCTL_SBP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1778
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1779
	if (adapter->netdev->mtu <= ETH_DATA_LEN)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1780
		rctl &= ~E1000_RCTL_LPE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1781
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1782
		rctl |= E1000_RCTL_LPE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1783
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1784
	/* Setup buffer sizes */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1785
	rctl &= ~E1000_RCTL_SZ_4096;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1786
	rctl |= E1000_RCTL_BSEX;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1787
	switch (adapter->rx_buffer_len) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1788
		case E1000_RXBUFFER_2048:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1789
		default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1790
			rctl |= E1000_RCTL_SZ_2048;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1791
			rctl &= ~E1000_RCTL_BSEX;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1792
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1793
		case E1000_RXBUFFER_4096:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1794
			rctl |= E1000_RCTL_SZ_4096;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1795
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1796
		case E1000_RXBUFFER_8192:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1797
			rctl |= E1000_RCTL_SZ_8192;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1798
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1799
		case E1000_RXBUFFER_16384:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1800
			rctl |= E1000_RCTL_SZ_16384;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1801
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1802
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1803
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1804
	ew32(RCTL, rctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1805
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1806
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1807
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1808
 * e1000_configure_rx - Configure 8254x Receive Unit after Reset
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1809
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1810
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1811
 * Configure the Rx unit of the MAC after a reset.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1812
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1813
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1814
static void e1000_configure_rx(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1815
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1816
	u64 rdba;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1817
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1818
	u32 rdlen, rctl, rxcsum;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1819
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1820
	if (adapter->netdev->mtu > ETH_DATA_LEN) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1821
		rdlen = adapter->rx_ring[0].count *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1822
		        sizeof(struct e1000_rx_desc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1823
		adapter->clean_rx = e1000_clean_jumbo_rx_irq;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1824
		adapter->alloc_rx_buf = e1000_alloc_jumbo_rx_buffers;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1825
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1826
		rdlen = adapter->rx_ring[0].count *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1827
		        sizeof(struct e1000_rx_desc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1828
		adapter->clean_rx = e1000_clean_rx_irq;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1829
		adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1830
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1831
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1832
	/* disable receives while setting up the descriptors */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1833
	rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1834
	ew32(RCTL, rctl & ~E1000_RCTL_EN);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1835
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1836
	/* set the Receive Delay Timer Register */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1837
	ew32(RDTR, adapter->rx_int_delay);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1838
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1839
	if (hw->mac_type >= e1000_82540) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1840
		ew32(RADV, adapter->rx_abs_int_delay);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1841
		if (adapter->itr_setting != 0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1842
			ew32(ITR, 1000000000 / (adapter->itr * 256));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1843
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1844
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1845
	/* Setup the HW Rx Head and Tail Descriptor Pointers and
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1846
	 * the Base and Length of the Rx Descriptor Ring */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1847
	switch (adapter->num_rx_queues) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1848
	case 1:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1849
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1850
		rdba = adapter->rx_ring[0].dma;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1851
		ew32(RDLEN, rdlen);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1852
		ew32(RDBAH, (rdba >> 32));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1853
		ew32(RDBAL, (rdba & 0x00000000ffffffffULL));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1854
		ew32(RDT, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1855
		ew32(RDH, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1856
		adapter->rx_ring[0].rdh = ((hw->mac_type >= e1000_82543) ? E1000_RDH : E1000_82542_RDH);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1857
		adapter->rx_ring[0].rdt = ((hw->mac_type >= e1000_82543) ? E1000_RDT : E1000_82542_RDT);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1858
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1859
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1860
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1861
	/* Enable 82543 Receive Checksum Offload for TCP and UDP */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1862
	if (hw->mac_type >= e1000_82543) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1863
		rxcsum = er32(RXCSUM);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1864
		if (adapter->rx_csum)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1865
			rxcsum |= E1000_RXCSUM_TUOFL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1866
		else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1867
			/* don't need to clear IPPCSE as it defaults to 0 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1868
			rxcsum &= ~E1000_RXCSUM_TUOFL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1869
		ew32(RXCSUM, rxcsum);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1870
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1871
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1872
	/* Enable Receives */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1873
	ew32(RCTL, rctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1874
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1875
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1876
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1877
 * e1000_free_tx_resources - Free Tx Resources per Queue
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1878
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1879
 * @tx_ring: Tx descriptor ring for a specific queue
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1880
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1881
 * Free all transmit software resources
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1882
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1883
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1884
static void e1000_free_tx_resources(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1885
				    struct e1000_tx_ring *tx_ring)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1886
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1887
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1888
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1889
	e1000_clean_tx_ring(adapter, tx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1890
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1891
	vfree(tx_ring->buffer_info);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1892
	tx_ring->buffer_info = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1893
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1894
	dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1895
			  tx_ring->dma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1896
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1897
	tx_ring->desc = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1898
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1899
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1900
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1901
 * e1000_free_all_tx_resources - Free Tx Resources for All Queues
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1902
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1903
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1904
 * Free all transmit software resources
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1905
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1906
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1907
void e1000_free_all_tx_resources(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1908
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1909
	int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1910
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1911
	for (i = 0; i < adapter->num_tx_queues; i++)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1912
		e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1913
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1914
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1915
static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1916
					     struct e1000_buffer *buffer_info)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1917
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1918
	if (buffer_info->dma) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1919
		if (buffer_info->mapped_as_page)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1920
			dma_unmap_page(&adapter->pdev->dev, buffer_info->dma,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1921
				       buffer_info->length, DMA_TO_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1922
		else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1923
			dma_unmap_single(&adapter->pdev->dev, buffer_info->dma,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1924
					 buffer_info->length,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1925
					 DMA_TO_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1926
		buffer_info->dma = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1927
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1928
	if (buffer_info->skb) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1929
		dev_kfree_skb_any(buffer_info->skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1930
		buffer_info->skb = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1931
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1932
	buffer_info->time_stamp = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1933
	/* buffer_info must be completely set up in the transmit path */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1934
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1935
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1936
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1937
 * e1000_clean_tx_ring - Free Tx Buffers
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1938
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1939
 * @tx_ring: ring to be cleaned
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1940
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1941
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1942
static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1943
				struct e1000_tx_ring *tx_ring)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1944
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1945
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1946
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1947
	unsigned long size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1948
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1949
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1950
	/* Free all the Tx ring sk_buffs */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1951
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1952
	for (i = 0; i < tx_ring->count; i++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1953
		buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1954
		e1000_unmap_and_free_tx_resource(adapter, buffer_info);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1955
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1956
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1957
	size = sizeof(struct e1000_buffer) * tx_ring->count;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1958
	memset(tx_ring->buffer_info, 0, size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1959
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1960
	/* Zero out the descriptor ring */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1961
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1962
	memset(tx_ring->desc, 0, tx_ring->size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1963
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1964
	tx_ring->next_to_use = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1965
	tx_ring->next_to_clean = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1966
	tx_ring->last_tx_tso = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1967
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1968
	writel(0, hw->hw_addr + tx_ring->tdh);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1969
	writel(0, hw->hw_addr + tx_ring->tdt);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1970
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1971
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1972
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1973
 * e1000_clean_all_tx_rings - Free Tx Buffers for all queues
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1974
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1975
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1976
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1977
static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1978
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1979
	int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1980
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1981
	for (i = 0; i < adapter->num_tx_queues; i++)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1982
		e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1983
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1984
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1985
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1986
 * e1000_free_rx_resources - Free Rx Resources
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1987
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1988
 * @rx_ring: ring to clean the resources from
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1989
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1990
 * Free all receive software resources
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1991
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1992
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1993
static void e1000_free_rx_resources(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1994
				    struct e1000_rx_ring *rx_ring)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1995
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1996
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1997
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1998
	e1000_clean_rx_ring(adapter, rx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1999
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2000
	vfree(rx_ring->buffer_info);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2001
	rx_ring->buffer_info = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2002
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2003
	dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2004
			  rx_ring->dma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2005
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2006
	rx_ring->desc = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2007
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2008
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2009
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2010
 * e1000_free_all_rx_resources - Free Rx Resources for All Queues
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2011
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2012
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2013
 * Free all receive software resources
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2014
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2015
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2016
void e1000_free_all_rx_resources(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2017
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2018
	int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2019
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2020
	for (i = 0; i < adapter->num_rx_queues; i++)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2021
		e1000_free_rx_resources(adapter, &adapter->rx_ring[i]);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2022
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2023
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2024
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2025
 * e1000_clean_rx_ring - Free Rx Buffers per Queue
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2026
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2027
 * @rx_ring: ring to free buffers from
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2028
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2029
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2030
static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2031
				struct e1000_rx_ring *rx_ring)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2032
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2033
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2034
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2035
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2036
	unsigned long size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2037
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2038
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2039
	/* Free all the Rx ring sk_buffs */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2040
	for (i = 0; i < rx_ring->count; i++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2041
		buffer_info = &rx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2042
		if (buffer_info->dma &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2043
		    adapter->clean_rx == e1000_clean_rx_irq) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2044
			dma_unmap_single(&pdev->dev, buffer_info->dma,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2045
			                 buffer_info->length,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2046
					 DMA_FROM_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2047
		} else if (buffer_info->dma &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2048
		           adapter->clean_rx == e1000_clean_jumbo_rx_irq) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2049
			dma_unmap_page(&pdev->dev, buffer_info->dma,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2050
				       buffer_info->length,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2051
				       DMA_FROM_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2052
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2053
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2054
		buffer_info->dma = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2055
		if (buffer_info->page) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2056
			put_page(buffer_info->page);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2057
			buffer_info->page = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2058
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2059
		if (buffer_info->skb) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2060
			dev_kfree_skb(buffer_info->skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2061
			buffer_info->skb = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2062
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2063
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2064
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2065
	/* there also may be some cached data from a chained receive */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2066
	if (rx_ring->rx_skb_top) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2067
		dev_kfree_skb(rx_ring->rx_skb_top);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2068
		rx_ring->rx_skb_top = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2069
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2070
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2071
	size = sizeof(struct e1000_buffer) * rx_ring->count;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2072
	memset(rx_ring->buffer_info, 0, size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2073
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2074
	/* Zero out the descriptor ring */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2075
	memset(rx_ring->desc, 0, rx_ring->size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2076
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2077
	rx_ring->next_to_clean = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2078
	rx_ring->next_to_use = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2079
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2080
	writel(0, hw->hw_addr + rx_ring->rdh);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2081
	writel(0, hw->hw_addr + rx_ring->rdt);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2082
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2083
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2084
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2085
 * e1000_clean_all_rx_rings - Free Rx Buffers for all queues
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2086
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2087
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2088
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2089
static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2090
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2091
	int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2092
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2093
	for (i = 0; i < adapter->num_rx_queues; i++)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2094
		e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2095
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2096
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2097
/* The 82542 2.0 (revision 2) needs to have the receive unit in reset
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2098
 * and memory write and invalidate disabled for certain operations
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2099
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2100
static void e1000_enter_82542_rst(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2101
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2102
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2103
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2104
	u32 rctl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2105
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2106
	e1000_pci_clear_mwi(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2107
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2108
	rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2109
	rctl |= E1000_RCTL_RST;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2110
	ew32(RCTL, rctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2111
	E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2112
	mdelay(5);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2113
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2114
	if (netif_running(netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2115
		e1000_clean_all_rx_rings(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2116
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2117
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2118
static void e1000_leave_82542_rst(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2119
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2120
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2121
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2122
	u32 rctl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2123
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2124
	rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2125
	rctl &= ~E1000_RCTL_RST;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2126
	ew32(RCTL, rctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2127
	E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2128
	mdelay(5);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2129
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2130
	if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2131
		e1000_pci_set_mwi(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2132
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2133
	if (netif_running(netdev)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2134
		/* No need to loop, because 82542 supports only 1 queue */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2135
		struct e1000_rx_ring *ring = &adapter->rx_ring[0];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2136
		e1000_configure_rx(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2137
		adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2138
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2139
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2140
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2141
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2142
 * e1000_set_mac - Change the Ethernet Address of the NIC
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2143
 * @netdev: network interface device structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2144
 * @p: pointer to an address structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2145
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2146
 * Returns 0 on success, negative on failure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2147
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2148
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2149
static int e1000_set_mac(struct net_device *netdev, void *p)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2150
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2151
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2152
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2153
	struct sockaddr *addr = p;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2154
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2155
	if (!is_valid_ether_addr(addr->sa_data))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2156
		return -EADDRNOTAVAIL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2157
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2158
	/* 82542 2.0 needs to be in reset to write receive address registers */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2159
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2160
	if (hw->mac_type == e1000_82542_rev2_0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2161
		e1000_enter_82542_rst(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2162
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2163
	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2164
	memcpy(hw->mac_addr, addr->sa_data, netdev->addr_len);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2165
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2166
	e1000_rar_set(hw, hw->mac_addr, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2167
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2168
	if (hw->mac_type == e1000_82542_rev2_0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2169
		e1000_leave_82542_rst(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2170
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2171
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2172
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2173
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2174
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2175
 * e1000_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2176
 * @netdev: network interface device structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2177
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2178
 * The set_rx_mode entry point is called whenever the unicast or multicast
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2179
 * address lists or the network interface flags are updated. This routine is
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2180
 * responsible for configuring the hardware for proper unicast, multicast,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2181
 * promiscuous mode, and all-multi behavior.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2182
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2183
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2184
static void e1000_set_rx_mode(struct net_device *netdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2185
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2186
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2187
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2188
	struct netdev_hw_addr *ha;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2189
	bool use_uc = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2190
	u32 rctl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2191
	u32 hash_value;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2192
	int i, rar_entries = E1000_RAR_ENTRIES;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2193
	int mta_reg_count = E1000_NUM_MTA_REGISTERS;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2194
	u32 *mcarray = kcalloc(mta_reg_count, sizeof(u32), GFP_ATOMIC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2195
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2196
	if (!mcarray) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2197
		e_err(probe, "memory allocation failed\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2198
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2199
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2200
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2201
	/* Check for Promiscuous and All Multicast modes */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2202
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2203
	rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2204
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2205
	if (netdev->flags & IFF_PROMISC) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2206
		rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2207
		rctl &= ~E1000_RCTL_VFE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2208
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2209
		if (netdev->flags & IFF_ALLMULTI)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2210
			rctl |= E1000_RCTL_MPE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2211
		else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2212
			rctl &= ~E1000_RCTL_MPE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2213
		/* Enable VLAN filter if there is a VLAN */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2214
		if (adapter->vlgrp)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2215
			rctl |= E1000_RCTL_VFE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2216
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2217
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2218
	if (netdev_uc_count(netdev) > rar_entries - 1) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2219
		rctl |= E1000_RCTL_UPE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2220
	} else if (!(netdev->flags & IFF_PROMISC)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2221
		rctl &= ~E1000_RCTL_UPE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2222
		use_uc = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2223
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2224
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2225
	ew32(RCTL, rctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2226
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2227
	/* 82542 2.0 needs to be in reset to write receive address registers */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2228
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2229
	if (hw->mac_type == e1000_82542_rev2_0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2230
		e1000_enter_82542_rst(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2231
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2232
	/* load the first 14 addresses into the exact filters 1-14. Unicast
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2233
	 * addresses take precedence to avoid disabling unicast filtering
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2234
	 * when possible.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2235
	 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2236
	 * RAR 0 is used for the station MAC address
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2237
	 * if there are not 14 addresses, go ahead and clear the filters
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2238
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2239
	i = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2240
	if (use_uc)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2241
		netdev_for_each_uc_addr(ha, netdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2242
			if (i == rar_entries)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2243
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2244
			e1000_rar_set(hw, ha->addr, i++);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2245
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2246
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2247
	netdev_for_each_mc_addr(ha, netdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2248
		if (i == rar_entries) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2249
			/* load any remaining addresses into the hash table */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2250
			u32 hash_reg, hash_bit, mta;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2251
			hash_value = e1000_hash_mc_addr(hw, ha->addr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2252
			hash_reg = (hash_value >> 5) & 0x7F;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2253
			hash_bit = hash_value & 0x1F;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2254
			mta = (1 << hash_bit);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2255
			mcarray[hash_reg] |= mta;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2256
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2257
			e1000_rar_set(hw, ha->addr, i++);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2258
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2259
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2260
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2261
	for (; i < rar_entries; i++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2262
		E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2263
		E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2264
		E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2265
		E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2266
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2267
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2268
	/* write the hash table completely, write from bottom to avoid
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2269
	 * both stupid write combining chipsets, and flushing each write */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2270
	for (i = mta_reg_count - 1; i >= 0 ; i--) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2271
		/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2272
		 * If we are on an 82544 has an errata where writing odd
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2273
		 * offsets overwrites the previous even offset, but writing
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2274
		 * backwards over the range solves the issue by always
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2275
		 * writing the odd offset first
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2276
		 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2277
		E1000_WRITE_REG_ARRAY(hw, MTA, i, mcarray[i]);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2278
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2279
	E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2280
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2281
	if (hw->mac_type == e1000_82542_rev2_0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2282
		e1000_leave_82542_rst(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2283
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2284
	kfree(mcarray);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2285
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2286
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2287
/* Need to wait a few seconds after link up to get diagnostic information from
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2288
 * the phy */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2289
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2290
static void e1000_update_phy_info(unsigned long data)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2291
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2292
	struct e1000_adapter *adapter = (struct e1000_adapter *)data;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2293
	schedule_work(&adapter->phy_info_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2294
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2295
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2296
static void e1000_update_phy_info_task(struct work_struct *work)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2297
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2298
	struct e1000_adapter *adapter = container_of(work,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2299
	                                             struct e1000_adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2300
	                                             phy_info_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2301
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2302
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2303
	rtnl_lock();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2304
	e1000_phy_get_info(hw, &adapter->phy_info);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2305
	rtnl_unlock();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2306
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2307
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2308
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2309
 * e1000_82547_tx_fifo_stall - Timer Call-back
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2310
 * @data: pointer to adapter cast into an unsigned long
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2311
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2312
static void e1000_82547_tx_fifo_stall(unsigned long data)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2313
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2314
	struct e1000_adapter *adapter = (struct e1000_adapter *)data;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2315
	schedule_work(&adapter->fifo_stall_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2316
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2317
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2318
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2319
 * e1000_82547_tx_fifo_stall_task - task to complete work
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2320
 * @work: work struct contained inside adapter struct
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2321
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2322
static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2323
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2324
	struct e1000_adapter *adapter = container_of(work,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2325
	                                             struct e1000_adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2326
	                                             fifo_stall_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2327
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2328
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2329
	u32 tctl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2330
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2331
	rtnl_lock();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2332
	if (atomic_read(&adapter->tx_fifo_stall)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2333
		if ((er32(TDT) == er32(TDH)) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2334
		   (er32(TDFT) == er32(TDFH)) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2335
		   (er32(TDFTS) == er32(TDFHS))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2336
			tctl = er32(TCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2337
			ew32(TCTL, tctl & ~E1000_TCTL_EN);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2338
			ew32(TDFT, adapter->tx_head_addr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2339
			ew32(TDFH, adapter->tx_head_addr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2340
			ew32(TDFTS, adapter->tx_head_addr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2341
			ew32(TDFHS, adapter->tx_head_addr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2342
			ew32(TCTL, tctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2343
			E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2344
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2345
			adapter->tx_fifo_head = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2346
			atomic_set(&adapter->tx_fifo_stall, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2347
			netif_wake_queue(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2348
		} else if (!test_bit(__E1000_DOWN, &adapter->flags)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2349
			mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2350
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2351
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2352
	rtnl_unlock();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2353
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2354
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2355
bool e1000_has_link(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2356
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2357
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2358
	bool link_active = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2359
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2360
	/* get_link_status is set on LSC (link status) interrupt or
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2361
	 * rx sequence error interrupt.  get_link_status will stay
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2362
	 * false until the e1000_check_for_link establishes link
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2363
	 * for copper adapters ONLY
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2364
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2365
	switch (hw->media_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2366
	case e1000_media_type_copper:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2367
		if (hw->get_link_status) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2368
			e1000_check_for_link(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2369
			link_active = !hw->get_link_status;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2370
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2371
			link_active = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2372
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2373
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2374
	case e1000_media_type_fiber:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2375
		e1000_check_for_link(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2376
		link_active = !!(er32(STATUS) & E1000_STATUS_LU);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2377
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2378
	case e1000_media_type_internal_serdes:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2379
		e1000_check_for_link(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2380
		link_active = hw->serdes_has_link;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2381
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2382
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2383
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2384
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2385
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2386
	return link_active;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2387
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2388
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2389
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2390
 * e1000_watchdog - Timer Call-back
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2391
 * @data: pointer to adapter cast into an unsigned long
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2392
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2393
static void e1000_watchdog(unsigned long data)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2394
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2395
	struct e1000_adapter *adapter = (struct e1000_adapter *)data;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2396
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2397
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2398
	struct e1000_tx_ring *txdr = adapter->tx_ring;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2399
	u32 link, tctl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2400
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2401
	link = e1000_has_link(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2402
	if ((netif_carrier_ok(netdev)) && link)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2403
		goto link_up;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2404
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2405
	if (link) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2406
		if (!netif_carrier_ok(netdev)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2407
			u32 ctrl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2408
			bool txb2b = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2409
			/* update snapshot of PHY registers on LSC */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2410
			e1000_get_speed_and_duplex(hw,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2411
			                           &adapter->link_speed,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2412
			                           &adapter->link_duplex);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2413
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2414
			ctrl = er32(CTRL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2415
			pr_info("%s NIC Link is Up %d Mbps %s, "
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2416
				"Flow Control: %s\n",
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2417
				netdev->name,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2418
				adapter->link_speed,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2419
				adapter->link_duplex == FULL_DUPLEX ?
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2420
				"Full Duplex" : "Half Duplex",
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2421
				((ctrl & E1000_CTRL_TFCE) && (ctrl &
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2422
				E1000_CTRL_RFCE)) ? "RX/TX" : ((ctrl &
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2423
				E1000_CTRL_RFCE) ? "RX" : ((ctrl &
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2424
				E1000_CTRL_TFCE) ? "TX" : "None")));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2425
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2426
			/* adjust timeout factor according to speed/duplex */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2427
			adapter->tx_timeout_factor = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2428
			switch (adapter->link_speed) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2429
			case SPEED_10:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2430
				txb2b = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2431
				adapter->tx_timeout_factor = 16;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2432
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2433
			case SPEED_100:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2434
				txb2b = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2435
				/* maybe add some timeout factor ? */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2436
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2437
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2438
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2439
			/* enable transmits in the hardware */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2440
			tctl = er32(TCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2441
			tctl |= E1000_TCTL_EN;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2442
			ew32(TCTL, tctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2443
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2444
			netif_carrier_on(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2445
			if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2446
				mod_timer(&adapter->phy_info_timer,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2447
				          round_jiffies(jiffies + 2 * HZ));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2448
			adapter->smartspeed = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2449
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2450
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2451
		if (netif_carrier_ok(netdev)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2452
			adapter->link_speed = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2453
			adapter->link_duplex = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2454
			pr_info("%s NIC Link is Down\n",
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2455
				netdev->name);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2456
			netif_carrier_off(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2457
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2458
			if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2459
				mod_timer(&adapter->phy_info_timer,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2460
				          round_jiffies(jiffies + 2 * HZ));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2461
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2462
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2463
		e1000_smartspeed(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2464
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2465
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2466
link_up:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2467
	e1000_update_stats(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2468
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2469
	hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2470
	adapter->tpt_old = adapter->stats.tpt;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2471
	hw->collision_delta = adapter->stats.colc - adapter->colc_old;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2472
	adapter->colc_old = adapter->stats.colc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2473
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2474
	adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2475
	adapter->gorcl_old = adapter->stats.gorcl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2476
	adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2477
	adapter->gotcl_old = adapter->stats.gotcl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2478
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2479
	e1000_update_adaptive(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2480
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2481
	if (!netif_carrier_ok(netdev)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2482
		if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2483
			/* We've lost link, so the controller stops DMA,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2484
			 * but we've got queued Tx work that's never going
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2485
			 * to get done, so reset controller to flush Tx.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2486
			 * (Do the reset outside of interrupt context). */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2487
			adapter->tx_timeout_count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2488
			schedule_work(&adapter->reset_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2489
			/* return immediately since reset is imminent */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2490
			return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2491
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2492
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2493
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2494
	/* Simple mode for Interrupt Throttle Rate (ITR) */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2495
	if (hw->mac_type >= e1000_82540 && adapter->itr_setting == 4) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2496
		/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2497
		 * Symmetric Tx/Rx gets a reduced ITR=2000;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2498
		 * Total asymmetrical Tx or Rx gets ITR=8000;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2499
		 * everyone else is between 2000-8000.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2500
		 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2501
		u32 goc = (adapter->gotcl + adapter->gorcl) / 10000;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2502
		u32 dif = (adapter->gotcl > adapter->gorcl ?
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2503
			    adapter->gotcl - adapter->gorcl :
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2504
			    adapter->gorcl - adapter->gotcl) / 10000;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2505
		u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2506
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2507
		ew32(ITR, 1000000000 / (itr * 256));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2508
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2509
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2510
	/* Cause software interrupt to ensure rx ring is cleaned */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2511
	ew32(ICS, E1000_ICS_RXDMT0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2512
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2513
	/* Force detection of hung controller every watchdog period */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2514
	adapter->detect_tx_hung = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2515
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2516
	/* Reset the timer */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2517
	if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2518
		mod_timer(&adapter->watchdog_timer,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2519
		          round_jiffies(jiffies + 2 * HZ));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2520
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2521
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2522
enum latency_range {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2523
	lowest_latency = 0,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2524
	low_latency = 1,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2525
	bulk_latency = 2,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2526
	latency_invalid = 255
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2527
};
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2528
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2529
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2530
 * e1000_update_itr - update the dynamic ITR value based on statistics
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2531
 * @adapter: pointer to adapter
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2532
 * @itr_setting: current adapter->itr
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2533
 * @packets: the number of packets during this measurement interval
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2534
 * @bytes: the number of bytes during this measurement interval
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2535
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2536
 *      Stores a new ITR value based on packets and byte
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2537
 *      counts during the last interrupt.  The advantage of per interrupt
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2538
 *      computation is faster updates and more accurate ITR for the current
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2539
 *      traffic pattern.  Constants in this function were computed
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2540
 *      based on theoretical maximum wire speed and thresholds were set based
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2541
 *      on testing data as well as attempting to minimize response time
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2542
 *      while increasing bulk throughput.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2543
 *      this functionality is controlled by the InterruptThrottleRate module
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2544
 *      parameter (see e1000_param.c)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2545
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2546
static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2547
				     u16 itr_setting, int packets, int bytes)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2548
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2549
	unsigned int retval = itr_setting;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2550
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2551
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2552
	if (unlikely(hw->mac_type < e1000_82540))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2553
		goto update_itr_done;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2554
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2555
	if (packets == 0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2556
		goto update_itr_done;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2557
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2558
	switch (itr_setting) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2559
	case lowest_latency:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2560
		/* jumbo frames get bulk treatment*/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2561
		if (bytes/packets > 8000)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2562
			retval = bulk_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2563
		else if ((packets < 5) && (bytes > 512))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2564
			retval = low_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2565
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2566
	case low_latency:  /* 50 usec aka 20000 ints/s */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2567
		if (bytes > 10000) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2568
			/* jumbo frames need bulk latency setting */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2569
			if (bytes/packets > 8000)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2570
				retval = bulk_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2571
			else if ((packets < 10) || ((bytes/packets) > 1200))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2572
				retval = bulk_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2573
			else if ((packets > 35))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2574
				retval = lowest_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2575
		} else if (bytes/packets > 2000)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2576
			retval = bulk_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2577
		else if (packets <= 2 && bytes < 512)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2578
			retval = lowest_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2579
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2580
	case bulk_latency: /* 250 usec aka 4000 ints/s */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2581
		if (bytes > 25000) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2582
			if (packets > 35)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2583
				retval = low_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2584
		} else if (bytes < 6000) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2585
			retval = low_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2586
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2587
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2588
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2589
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2590
update_itr_done:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2591
	return retval;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2592
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2593
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2594
static void e1000_set_itr(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2595
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2596
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2597
	u16 current_itr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2598
	u32 new_itr = adapter->itr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2599
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2600
	if (unlikely(hw->mac_type < e1000_82540))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2601
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2602
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2603
	/* for non-gigabit speeds, just fix the interrupt rate at 4000 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2604
	if (unlikely(adapter->link_speed != SPEED_1000)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2605
		current_itr = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2606
		new_itr = 4000;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2607
		goto set_itr_now;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2608
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2609
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2610
	adapter->tx_itr = e1000_update_itr(adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2611
	                            adapter->tx_itr,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2612
	                            adapter->total_tx_packets,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2613
	                            adapter->total_tx_bytes);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2614
	/* conservative mode (itr 3) eliminates the lowest_latency setting */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2615
	if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2616
		adapter->tx_itr = low_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2617
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2618
	adapter->rx_itr = e1000_update_itr(adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2619
	                            adapter->rx_itr,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2620
	                            adapter->total_rx_packets,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2621
	                            adapter->total_rx_bytes);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2622
	/* conservative mode (itr 3) eliminates the lowest_latency setting */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2623
	if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2624
		adapter->rx_itr = low_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2625
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2626
	current_itr = max(adapter->rx_itr, adapter->tx_itr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2627
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2628
	switch (current_itr) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2629
	/* counts and packets in update_itr are dependent on these numbers */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2630
	case lowest_latency:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2631
		new_itr = 70000;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2632
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2633
	case low_latency:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2634
		new_itr = 20000; /* aka hwitr = ~200 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2635
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2636
	case bulk_latency:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2637
		new_itr = 4000;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2638
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2639
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2640
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2641
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2642
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2643
set_itr_now:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2644
	if (new_itr != adapter->itr) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2645
		/* this attempts to bias the interrupt rate towards Bulk
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2646
		 * by adding intermediate steps when interrupt rate is
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2647
		 * increasing */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2648
		new_itr = new_itr > adapter->itr ?
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2649
		             min(adapter->itr + (new_itr >> 2), new_itr) :
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2650
		             new_itr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2651
		adapter->itr = new_itr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2652
		ew32(ITR, 1000000000 / (new_itr * 256));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2653
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2654
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2655
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2656
#define E1000_TX_FLAGS_CSUM		0x00000001
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2657
#define E1000_TX_FLAGS_VLAN		0x00000002
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2658
#define E1000_TX_FLAGS_TSO		0x00000004
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2659
#define E1000_TX_FLAGS_IPV4		0x00000008
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2660
#define E1000_TX_FLAGS_VLAN_MASK	0xffff0000
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2661
#define E1000_TX_FLAGS_VLAN_SHIFT	16
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2662
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2663
static int e1000_tso(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2664
		     struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2665
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2666
	struct e1000_context_desc *context_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2667
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2668
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2669
	u32 cmd_length = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2670
	u16 ipcse = 0, tucse, mss;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2671
	u8 ipcss, ipcso, tucss, tucso, hdr_len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2672
	int err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2673
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2674
	if (skb_is_gso(skb)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2675
		if (skb_header_cloned(skb)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2676
			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2677
			if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2678
				return err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2679
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2680
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2681
		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2682
		mss = skb_shinfo(skb)->gso_size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2683
		if (skb->protocol == htons(ETH_P_IP)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2684
			struct iphdr *iph = ip_hdr(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2685
			iph->tot_len = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2686
			iph->check = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2687
			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2688
								 iph->daddr, 0,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2689
								 IPPROTO_TCP,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2690
								 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2691
			cmd_length = E1000_TXD_CMD_IP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2692
			ipcse = skb_transport_offset(skb) - 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2693
		} else if (skb->protocol == htons(ETH_P_IPV6)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2694
			ipv6_hdr(skb)->payload_len = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2695
			tcp_hdr(skb)->check =
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2696
				~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2697
						 &ipv6_hdr(skb)->daddr,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2698
						 0, IPPROTO_TCP, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2699
			ipcse = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2700
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2701
		ipcss = skb_network_offset(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2702
		ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2703
		tucss = skb_transport_offset(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2704
		tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2705
		tucse = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2706
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2707
		cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2708
			       E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2709
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2710
		i = tx_ring->next_to_use;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2711
		context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2712
		buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2713
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2714
		context_desc->lower_setup.ip_fields.ipcss  = ipcss;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2715
		context_desc->lower_setup.ip_fields.ipcso  = ipcso;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2716
		context_desc->lower_setup.ip_fields.ipcse  = cpu_to_le16(ipcse);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2717
		context_desc->upper_setup.tcp_fields.tucss = tucss;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2718
		context_desc->upper_setup.tcp_fields.tucso = tucso;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2719
		context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2720
		context_desc->tcp_seg_setup.fields.mss     = cpu_to_le16(mss);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2721
		context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2722
		context_desc->cmd_and_length = cpu_to_le32(cmd_length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2723
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2724
		buffer_info->time_stamp = jiffies;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2725
		buffer_info->next_to_watch = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2726
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2727
		if (++i == tx_ring->count) i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2728
		tx_ring->next_to_use = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2729
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2730
		return true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2731
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2732
	return false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2733
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2734
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2735
static bool e1000_tx_csum(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2736
			  struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2737
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2738
	struct e1000_context_desc *context_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2739
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2740
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2741
	u8 css;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2742
	u32 cmd_len = E1000_TXD_CMD_DEXT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2743
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2744
	if (skb->ip_summed != CHECKSUM_PARTIAL)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2745
		return false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2746
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2747
	switch (skb->protocol) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2748
	case cpu_to_be16(ETH_P_IP):
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2749
		if (ip_hdr(skb)->protocol == IPPROTO_TCP)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2750
			cmd_len |= E1000_TXD_CMD_TCP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2751
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2752
	case cpu_to_be16(ETH_P_IPV6):
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2753
		/* XXX not handling all IPV6 headers */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2754
		if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2755
			cmd_len |= E1000_TXD_CMD_TCP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2756
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2757
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2758
		if (unlikely(net_ratelimit()))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2759
			e_warn(drv, "checksum_partial proto=%x!\n",
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2760
			       skb->protocol);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2761
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2762
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2763
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2764
	css = skb_checksum_start_offset(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2765
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2766
	i = tx_ring->next_to_use;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2767
	buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2768
	context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2769
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2770
	context_desc->lower_setup.ip_config = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2771
	context_desc->upper_setup.tcp_fields.tucss = css;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2772
	context_desc->upper_setup.tcp_fields.tucso =
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2773
		css + skb->csum_offset;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2774
	context_desc->upper_setup.tcp_fields.tucse = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2775
	context_desc->tcp_seg_setup.data = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2776
	context_desc->cmd_and_length = cpu_to_le32(cmd_len);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2777
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2778
	buffer_info->time_stamp = jiffies;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2779
	buffer_info->next_to_watch = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2780
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2781
	if (unlikely(++i == tx_ring->count)) i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2782
	tx_ring->next_to_use = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2783
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2784
	return true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2785
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2786
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2787
#define E1000_MAX_TXD_PWR	12
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2788
#define E1000_MAX_DATA_PER_TXD	(1<<E1000_MAX_TXD_PWR)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2789
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2790
static int e1000_tx_map(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2791
			struct e1000_tx_ring *tx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2792
			struct sk_buff *skb, unsigned int first,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2793
			unsigned int max_per_txd, unsigned int nr_frags,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2794
			unsigned int mss)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2795
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2796
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2797
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2798
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2799
	unsigned int len = skb_headlen(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2800
	unsigned int offset = 0, size, count = 0, i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2801
	unsigned int f;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2802
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2803
	i = tx_ring->next_to_use;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2804
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2805
	while (len) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2806
		buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2807
		size = min(len, max_per_txd);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2808
		/* Workaround for Controller erratum --
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2809
		 * descriptor for non-tso packet in a linear SKB that follows a
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2810
		 * tso gets written back prematurely before the data is fully
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2811
		 * DMA'd to the controller */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2812
		if (!skb->data_len && tx_ring->last_tx_tso &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2813
		    !skb_is_gso(skb)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2814
			tx_ring->last_tx_tso = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2815
			size -= 4;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2816
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2817
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2818
		/* Workaround for premature desc write-backs
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2819
		 * in TSO mode.  Append 4-byte sentinel desc */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2820
		if (unlikely(mss && !nr_frags && size == len && size > 8))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2821
			size -= 4;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2822
		/* work-around for errata 10 and it applies
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2823
		 * to all controllers in PCI-X mode
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2824
		 * The fix is to make sure that the first descriptor of a
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2825
		 * packet is smaller than 2048 - 16 - 16 (or 2016) bytes
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2826
		 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2827
		if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2828
		                (size > 2015) && count == 0))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2829
		        size = 2015;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2830
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2831
		/* Workaround for potential 82544 hang in PCI-X.  Avoid
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2832
		 * terminating buffers within evenly-aligned dwords. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2833
		if (unlikely(adapter->pcix_82544 &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2834
		   !((unsigned long)(skb->data + offset + size - 1) & 4) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2835
		   size > 4))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2836
			size -= 4;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2837
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2838
		buffer_info->length = size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2839
		/* set time_stamp *before* dma to help avoid a possible race */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2840
		buffer_info->time_stamp = jiffies;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2841
		buffer_info->mapped_as_page = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2842
		buffer_info->dma = dma_map_single(&pdev->dev,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2843
						  skb->data + offset,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2844
						  size,	DMA_TO_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2845
		if (dma_mapping_error(&pdev->dev, buffer_info->dma))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2846
			goto dma_error;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2847
		buffer_info->next_to_watch = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2848
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2849
		len -= size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2850
		offset += size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2851
		count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2852
		if (len) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2853
			i++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2854
			if (unlikely(i == tx_ring->count))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2855
				i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2856
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2857
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2858
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2859
	for (f = 0; f < nr_frags; f++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2860
		struct skb_frag_struct *frag;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2861
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2862
		frag = &skb_shinfo(skb)->frags[f];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2863
		len = frag->size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2864
		offset = frag->page_offset;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2865
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2866
		while (len) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2867
			i++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2868
			if (unlikely(i == tx_ring->count))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2869
				i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2870
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2871
			buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2872
			size = min(len, max_per_txd);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2873
			/* Workaround for premature desc write-backs
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2874
			 * in TSO mode.  Append 4-byte sentinel desc */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2875
			if (unlikely(mss && f == (nr_frags-1) && size == len && size > 8))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2876
				size -= 4;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2877
			/* Workaround for potential 82544 hang in PCI-X.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2878
			 * Avoid terminating buffers within evenly-aligned
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2879
			 * dwords. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2880
			if (unlikely(adapter->pcix_82544 &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2881
			    !((unsigned long)(page_to_phys(frag->page) + offset
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2882
			                      + size - 1) & 4) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2883
			    size > 4))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2884
				size -= 4;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2885
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2886
			buffer_info->length = size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2887
			buffer_info->time_stamp = jiffies;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2888
			buffer_info->mapped_as_page = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2889
			buffer_info->dma = dma_map_page(&pdev->dev, frag->page,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2890
							offset,	size,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2891
							DMA_TO_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2892
			if (dma_mapping_error(&pdev->dev, buffer_info->dma))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2893
				goto dma_error;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2894
			buffer_info->next_to_watch = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2895
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2896
			len -= size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2897
			offset += size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2898
			count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2899
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2900
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2901
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2902
	tx_ring->buffer_info[i].skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2903
	tx_ring->buffer_info[first].next_to_watch = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2904
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2905
	return count;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2906
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2907
dma_error:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2908
	dev_err(&pdev->dev, "TX DMA map failed\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2909
	buffer_info->dma = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2910
	if (count)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2911
		count--;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2912
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2913
	while (count--) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2914
		if (i==0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2915
			i += tx_ring->count;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2916
		i--;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2917
		buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2918
		e1000_unmap_and_free_tx_resource(adapter, buffer_info);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2919
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2920
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2921
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2922
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2923
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2924
static void e1000_tx_queue(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2925
			   struct e1000_tx_ring *tx_ring, int tx_flags,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2926
			   int count)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2927
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2928
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2929
	struct e1000_tx_desc *tx_desc = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2930
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2931
	u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2932
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2933
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2934
	if (likely(tx_flags & E1000_TX_FLAGS_TSO)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2935
		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2936
		             E1000_TXD_CMD_TSE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2937
		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2938
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2939
		if (likely(tx_flags & E1000_TX_FLAGS_IPV4))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2940
			txd_upper |= E1000_TXD_POPTS_IXSM << 8;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2941
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2942
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2943
	if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2944
		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2945
		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2946
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2947
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2948
	if (unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2949
		txd_lower |= E1000_TXD_CMD_VLE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2950
		txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2951
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2952
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2953
	i = tx_ring->next_to_use;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2954
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2955
	while (count--) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2956
		buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2957
		tx_desc = E1000_TX_DESC(*tx_ring, i);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2958
		tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2959
		tx_desc->lower.data =
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2960
			cpu_to_le32(txd_lower | buffer_info->length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2961
		tx_desc->upper.data = cpu_to_le32(txd_upper);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2962
		if (unlikely(++i == tx_ring->count)) i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2963
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2964
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2965
	tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2966
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2967
	/* Force memory writes to complete before letting h/w
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2968
	 * know there are new descriptors to fetch.  (Only
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2969
	 * applicable for weak-ordered memory model archs,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2970
	 * such as IA-64). */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2971
	wmb();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2972
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2973
	tx_ring->next_to_use = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2974
	writel(i, hw->hw_addr + tx_ring->tdt);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2975
	/* we need this if more than one processor can write to our tail
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2976
	 * at a time, it syncronizes IO on IA64/Altix systems */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2977
	mmiowb();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2978
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2979
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2980
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2981
 * 82547 workaround to avoid controller hang in half-duplex environment.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2982
 * The workaround is to avoid queuing a large packet that would span
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2983
 * the internal Tx FIFO ring boundary by notifying the stack to resend
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2984
 * the packet at a later time.  This gives the Tx FIFO an opportunity to
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2985
 * flush all packets.  When that occurs, we reset the Tx FIFO pointers
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2986
 * to the beginning of the Tx FIFO.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2987
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2988
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2989
#define E1000_FIFO_HDR			0x10
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2990
#define E1000_82547_PAD_LEN		0x3E0
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2991
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2992
static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2993
				       struct sk_buff *skb)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2994
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2995
	u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2996
	u32 skb_fifo_len = skb->len + E1000_FIFO_HDR;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2997
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2998
	skb_fifo_len = ALIGN(skb_fifo_len, E1000_FIFO_HDR);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2999
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3000
	if (adapter->link_duplex != HALF_DUPLEX)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3001
		goto no_fifo_stall_required;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3002
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3003
	if (atomic_read(&adapter->tx_fifo_stall))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3004
		return 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3005
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3006
	if (skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3007
		atomic_set(&adapter->tx_fifo_stall, 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3008
		return 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3009
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3010
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3011
no_fifo_stall_required:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3012
	adapter->tx_fifo_head += skb_fifo_len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3013
	if (adapter->tx_fifo_head >= adapter->tx_fifo_size)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3014
		adapter->tx_fifo_head -= adapter->tx_fifo_size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3015
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3016
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3017
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3018
static int __e1000_maybe_stop_tx(struct net_device *netdev, int size)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3019
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3020
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3021
	struct e1000_tx_ring *tx_ring = adapter->tx_ring;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3022
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3023
	netif_stop_queue(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3024
	/* Herbert's original patch had:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3025
	 *  smp_mb__after_netif_stop_queue();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3026
	 * but since that doesn't exist yet, just open code it. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3027
	smp_mb();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3028
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3029
	/* We need to check again in a case another CPU has just
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3030
	 * made room available. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3031
	if (likely(E1000_DESC_UNUSED(tx_ring) < size))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3032
		return -EBUSY;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3033
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3034
	/* A reprieve! */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3035
	netif_start_queue(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3036
	++adapter->restart_queue;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3037
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3038
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3039
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3040
static int e1000_maybe_stop_tx(struct net_device *netdev,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3041
                               struct e1000_tx_ring *tx_ring, int size)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3042
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3043
	if (likely(E1000_DESC_UNUSED(tx_ring) >= size))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3044
		return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3045
	return __e1000_maybe_stop_tx(netdev, size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3046
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3047
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3048
#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 )
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3049
static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3050
				    struct net_device *netdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3051
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3052
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3053
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3054
	struct e1000_tx_ring *tx_ring;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3055
	unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3056
	unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3057
	unsigned int tx_flags = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3058
	unsigned int len = skb_headlen(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3059
	unsigned int nr_frags;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3060
	unsigned int mss;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3061
	int count = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3062
	int tso;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3063
	unsigned int f;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3064
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3065
	/* This goes back to the question of how to logically map a tx queue
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3066
	 * to a flow.  Right now, performance is impacted slightly negatively
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3067
	 * if using multiple tx queues.  If the stack breaks away from a
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3068
	 * single qdisc implementation, we can look at this again. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3069
	tx_ring = adapter->tx_ring;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3070
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3071
	if (unlikely(skb->len <= 0)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3072
		dev_kfree_skb_any(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3073
		return NETDEV_TX_OK;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3074
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3075
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3076
	mss = skb_shinfo(skb)->gso_size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3077
	/* The controller does a simple calculation to
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3078
	 * make sure there is enough room in the FIFO before
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3079
	 * initiating the DMA for each buffer.  The calc is:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3080
	 * 4 = ceil(buffer len/mss).  To make sure we don't
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3081
	 * overrun the FIFO, adjust the max buffer len if mss
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3082
	 * drops. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3083
	if (mss) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3084
		u8 hdr_len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3085
		max_per_txd = min(mss << 2, max_per_txd);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3086
		max_txd_pwr = fls(max_per_txd) - 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3087
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3088
		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3089
		if (skb->data_len && hdr_len == len) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3090
			switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3091
				unsigned int pull_size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3092
			case e1000_82544:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3093
				/* Make sure we have room to chop off 4 bytes,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3094
				 * and that the end alignment will work out to
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3095
				 * this hardware's requirements
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3096
				 * NOTE: this is a TSO only workaround
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3097
				 * if end byte alignment not correct move us
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3098
				 * into the next dword */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3099
				if ((unsigned long)(skb_tail_pointer(skb) - 1) & 4)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3100
					break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3101
				/* fall through */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3102
				pull_size = min((unsigned int)4, skb->data_len);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3103
				if (!__pskb_pull_tail(skb, pull_size)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3104
					e_err(drv, "__pskb_pull_tail "
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3105
					      "failed.\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3106
					dev_kfree_skb_any(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3107
					return NETDEV_TX_OK;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3108
				}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3109
				len = skb_headlen(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3110
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3111
			default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3112
				/* do nothing */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3113
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3114
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3115
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3116
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3117
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3118
	/* reserve a descriptor for the offload context */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3119
	if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3120
		count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3121
	count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3122
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3123
	/* Controller Erratum workaround */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3124
	if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3125
		count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3126
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3127
	count += TXD_USE_COUNT(len, max_txd_pwr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3128
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3129
	if (adapter->pcix_82544)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3130
		count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3131
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3132
	/* work-around for errata 10 and it applies to all controllers
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3133
	 * in PCI-X mode, so add one more descriptor to the count
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3134
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3135
	if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3136
			(len > 2015)))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3137
		count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3138
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3139
	nr_frags = skb_shinfo(skb)->nr_frags;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3140
	for (f = 0; f < nr_frags; f++)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3141
		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3142
				       max_txd_pwr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3143
	if (adapter->pcix_82544)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3144
		count += nr_frags;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3145
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3146
	/* need: count + 2 desc gap to keep tail from touching
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3147
	 * head, otherwise try next time */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3148
	if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2)))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3149
		return NETDEV_TX_BUSY;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3150
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3151
	if (unlikely(hw->mac_type == e1000_82547)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3152
		if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3153
			netif_stop_queue(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3154
			if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3155
				mod_timer(&adapter->tx_fifo_stall_timer,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3156
				          jiffies + 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3157
			return NETDEV_TX_BUSY;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3158
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3159
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3160
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3161
	if (unlikely(vlan_tx_tag_present(skb))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3162
		tx_flags |= E1000_TX_FLAGS_VLAN;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3163
		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3164
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3165
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3166
	first = tx_ring->next_to_use;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3167
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3168
	tso = e1000_tso(adapter, tx_ring, skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3169
	if (tso < 0) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3170
		dev_kfree_skb_any(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3171
		return NETDEV_TX_OK;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3172
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3173
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3174
	if (likely(tso)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3175
		if (likely(hw->mac_type != e1000_82544))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3176
			tx_ring->last_tx_tso = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3177
		tx_flags |= E1000_TX_FLAGS_TSO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3178
	} else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3179
		tx_flags |= E1000_TX_FLAGS_CSUM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3180
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3181
	if (likely(skb->protocol == htons(ETH_P_IP)))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3182
		tx_flags |= E1000_TX_FLAGS_IPV4;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3183
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3184
	count = e1000_tx_map(adapter, tx_ring, skb, first, max_per_txd,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3185
	                     nr_frags, mss);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3186
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3187
	if (count) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3188
		e1000_tx_queue(adapter, tx_ring, tx_flags, count);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3189
		/* Make sure there is space in the ring for the next send. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3190
		e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3191
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3192
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3193
		dev_kfree_skb_any(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3194
		tx_ring->buffer_info[first].time_stamp = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3195
		tx_ring->next_to_use = first;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3196
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3197
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3198
	return NETDEV_TX_OK;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3199
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3200
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3201
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3202
 * e1000_tx_timeout - Respond to a Tx Hang
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3203
 * @netdev: network interface device structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3204
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3205
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3206
static void e1000_tx_timeout(struct net_device *netdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3207
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3208
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3209
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3210
	/* Do the reset outside of interrupt context */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3211
	adapter->tx_timeout_count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3212
	schedule_work(&adapter->reset_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3213
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3214
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3215
static void e1000_reset_task(struct work_struct *work)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3216
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3217
	struct e1000_adapter *adapter =
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3218
		container_of(work, struct e1000_adapter, reset_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3219
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3220
	e1000_reinit_safe(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3221
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3222
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3223
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3224
 * e1000_get_stats - Get System Network Statistics
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3225
 * @netdev: network interface device structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3226
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3227
 * Returns the address of the device statistics structure.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3228
 * The statistics are actually updated from the timer callback.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3229
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3230
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3231
static struct net_device_stats *e1000_get_stats(struct net_device *netdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3232
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3233
	/* only return the current stats */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3234
	return &netdev->stats;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3235
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3236
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3237
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3238
 * e1000_change_mtu - Change the Maximum Transfer Unit
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3239
 * @netdev: network interface device structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3240
 * @new_mtu: new value for maximum frame size
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3241
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3242
 * Returns 0 on success, negative on failure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3243
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3244
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3245
static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3246
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3247
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3248
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3249
	int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3250
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3251
	if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3252
	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3253
		e_err(probe, "Invalid MTU setting\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3254
		return -EINVAL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3255
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3256
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3257
	/* Adapter-specific max frame size limits. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3258
	switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3259
	case e1000_undefined ... e1000_82542_rev2_1:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3260
		if (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3261
			e_err(probe, "Jumbo Frames not supported.\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3262
			return -EINVAL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3263
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3264
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3265
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3266
		/* Capable of supporting up to MAX_JUMBO_FRAME_SIZE limit. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3267
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3268
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3269
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3270
	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3271
		msleep(1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3272
	/* e1000_down has a dependency on max_frame_size */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3273
	hw->max_frame_size = max_frame;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3274
	if (netif_running(netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3275
		e1000_down(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3276
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3277
	/* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3278
	 * means we reserve 2 more, this pushes us to allocate from the next
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3279
	 * larger slab size.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3280
	 * i.e. RXBUFFER_2048 --> size-4096 slab
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3281
	 *  however with the new *_jumbo_rx* routines, jumbo receives will use
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3282
	 *  fragmented skbs */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3283
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3284
	if (max_frame <= E1000_RXBUFFER_2048)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3285
		adapter->rx_buffer_len = E1000_RXBUFFER_2048;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3286
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3287
#if (PAGE_SIZE >= E1000_RXBUFFER_16384)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3288
		adapter->rx_buffer_len = E1000_RXBUFFER_16384;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3289
#elif (PAGE_SIZE >= E1000_RXBUFFER_4096)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3290
		adapter->rx_buffer_len = PAGE_SIZE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3291
#endif
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3292
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3293
	/* adjust allocation if LPE protects us, and we aren't using SBP */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3294
	if (!hw->tbi_compatibility_on &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3295
	    ((max_frame == (ETH_FRAME_LEN + ETH_FCS_LEN)) ||
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3296
	     (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3297
		adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3298
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3299
	pr_info("%s changing MTU from %d to %d\n",
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3300
		netdev->name, netdev->mtu, new_mtu);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3301
	netdev->mtu = new_mtu;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3302
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3303
	if (netif_running(netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3304
		e1000_up(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3305
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3306
		e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3307
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3308
	clear_bit(__E1000_RESETTING, &adapter->flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3309
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3310
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3311
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3312
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3313
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3314
 * e1000_update_stats - Update the board statistics counters
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3315
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3316
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3317
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3318
void e1000_update_stats(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3319
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3320
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3321
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3322
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3323
	unsigned long flags;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3324
	u16 phy_tmp;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3325
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3326
#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3327
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3328
	/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3329
	 * Prevent stats update while adapter is being reset, or if the pci
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3330
	 * connection is down.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3331
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3332
	if (adapter->link_speed == 0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3333
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3334
	if (pci_channel_offline(pdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3335
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3336
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3337
	spin_lock_irqsave(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3338
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3339
	/* these counters are modified from e1000_tbi_adjust_stats,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3340
	 * called from the interrupt context, so they must only
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3341
	 * be written while holding adapter->stats_lock
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3342
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3343
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3344
	adapter->stats.crcerrs += er32(CRCERRS);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3345
	adapter->stats.gprc += er32(GPRC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3346
	adapter->stats.gorcl += er32(GORCL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3347
	adapter->stats.gorch += er32(GORCH);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3348
	adapter->stats.bprc += er32(BPRC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3349
	adapter->stats.mprc += er32(MPRC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3350
	adapter->stats.roc += er32(ROC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3351
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3352
	adapter->stats.prc64 += er32(PRC64);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3353
	adapter->stats.prc127 += er32(PRC127);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3354
	adapter->stats.prc255 += er32(PRC255);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3355
	adapter->stats.prc511 += er32(PRC511);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3356
	adapter->stats.prc1023 += er32(PRC1023);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3357
	adapter->stats.prc1522 += er32(PRC1522);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3358
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3359
	adapter->stats.symerrs += er32(SYMERRS);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3360
	adapter->stats.mpc += er32(MPC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3361
	adapter->stats.scc += er32(SCC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3362
	adapter->stats.ecol += er32(ECOL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3363
	adapter->stats.mcc += er32(MCC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3364
	adapter->stats.latecol += er32(LATECOL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3365
	adapter->stats.dc += er32(DC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3366
	adapter->stats.sec += er32(SEC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3367
	adapter->stats.rlec += er32(RLEC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3368
	adapter->stats.xonrxc += er32(XONRXC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3369
	adapter->stats.xontxc += er32(XONTXC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3370
	adapter->stats.xoffrxc += er32(XOFFRXC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3371
	adapter->stats.xofftxc += er32(XOFFTXC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3372
	adapter->stats.fcruc += er32(FCRUC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3373
	adapter->stats.gptc += er32(GPTC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3374
	adapter->stats.gotcl += er32(GOTCL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3375
	adapter->stats.gotch += er32(GOTCH);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3376
	adapter->stats.rnbc += er32(RNBC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3377
	adapter->stats.ruc += er32(RUC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3378
	adapter->stats.rfc += er32(RFC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3379
	adapter->stats.rjc += er32(RJC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3380
	adapter->stats.torl += er32(TORL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3381
	adapter->stats.torh += er32(TORH);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3382
	adapter->stats.totl += er32(TOTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3383
	adapter->stats.toth += er32(TOTH);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3384
	adapter->stats.tpr += er32(TPR);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3385
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3386
	adapter->stats.ptc64 += er32(PTC64);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3387
	adapter->stats.ptc127 += er32(PTC127);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3388
	adapter->stats.ptc255 += er32(PTC255);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3389
	adapter->stats.ptc511 += er32(PTC511);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3390
	adapter->stats.ptc1023 += er32(PTC1023);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3391
	adapter->stats.ptc1522 += er32(PTC1522);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3392
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3393
	adapter->stats.mptc += er32(MPTC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3394
	adapter->stats.bptc += er32(BPTC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3395
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3396
	/* used for adaptive IFS */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3397
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3398
	hw->tx_packet_delta = er32(TPT);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3399
	adapter->stats.tpt += hw->tx_packet_delta;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3400
	hw->collision_delta = er32(COLC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3401
	adapter->stats.colc += hw->collision_delta;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3402
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3403
	if (hw->mac_type >= e1000_82543) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3404
		adapter->stats.algnerrc += er32(ALGNERRC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3405
		adapter->stats.rxerrc += er32(RXERRC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3406
		adapter->stats.tncrs += er32(TNCRS);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3407
		adapter->stats.cexterr += er32(CEXTERR);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3408
		adapter->stats.tsctc += er32(TSCTC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3409
		adapter->stats.tsctfc += er32(TSCTFC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3410
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3411
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3412
	/* Fill out the OS statistics structure */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3413
	netdev->stats.multicast = adapter->stats.mprc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3414
	netdev->stats.collisions = adapter->stats.colc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3415
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3416
	/* Rx Errors */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3417
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3418
	/* RLEC on some newer hardware can be incorrect so build
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3419
	* our own version based on RUC and ROC */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3420
	netdev->stats.rx_errors = adapter->stats.rxerrc +
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3421
		adapter->stats.crcerrs + adapter->stats.algnerrc +
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3422
		adapter->stats.ruc + adapter->stats.roc +
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3423
		adapter->stats.cexterr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3424
	adapter->stats.rlerrc = adapter->stats.ruc + adapter->stats.roc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3425
	netdev->stats.rx_length_errors = adapter->stats.rlerrc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3426
	netdev->stats.rx_crc_errors = adapter->stats.crcerrs;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3427
	netdev->stats.rx_frame_errors = adapter->stats.algnerrc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3428
	netdev->stats.rx_missed_errors = adapter->stats.mpc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3429
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3430
	/* Tx Errors */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3431
	adapter->stats.txerrc = adapter->stats.ecol + adapter->stats.latecol;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3432
	netdev->stats.tx_errors = adapter->stats.txerrc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3433
	netdev->stats.tx_aborted_errors = adapter->stats.ecol;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3434
	netdev->stats.tx_window_errors = adapter->stats.latecol;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3435
	netdev->stats.tx_carrier_errors = adapter->stats.tncrs;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3436
	if (hw->bad_tx_carr_stats_fd &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3437
	    adapter->link_duplex == FULL_DUPLEX) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3438
		netdev->stats.tx_carrier_errors = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3439
		adapter->stats.tncrs = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3440
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3441
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3442
	/* Tx Dropped needs to be maintained elsewhere */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3443
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3444
	/* Phy Stats */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3445
	if (hw->media_type == e1000_media_type_copper) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3446
		if ((adapter->link_speed == SPEED_1000) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3447
		   (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3448
			phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3449
			adapter->phy_stats.idle_errors += phy_tmp;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3450
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3451
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3452
		if ((hw->mac_type <= e1000_82546) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3453
		   (hw->phy_type == e1000_phy_m88) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3454
		   !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3455
			adapter->phy_stats.receive_errors += phy_tmp;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3456
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3457
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3458
	/* Management Stats */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3459
	if (hw->has_smbus) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3460
		adapter->stats.mgptc += er32(MGTPTC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3461
		adapter->stats.mgprc += er32(MGTPRC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3462
		adapter->stats.mgpdc += er32(MGTPDC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3463
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3464
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3465
	spin_unlock_irqrestore(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3466
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3467
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3468
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3469
 * e1000_intr - Interrupt Handler
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3470
 * @irq: interrupt number
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3471
 * @data: pointer to a network interface device structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3472
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3473
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3474
static irqreturn_t e1000_intr(int irq, void *data)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3475
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3476
	struct net_device *netdev = data;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3477
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3478
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3479
	u32 icr = er32(ICR);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3480
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3481
	if (unlikely((!icr)))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3482
		return IRQ_NONE;  /* Not our interrupt */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3483
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3484
	/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3485
	 * we might have caused the interrupt, but the above
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3486
	 * read cleared it, and just in case the driver is
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3487
	 * down there is nothing to do so return handled
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3488
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3489
	if (unlikely(test_bit(__E1000_DOWN, &adapter->flags)))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3490
		return IRQ_HANDLED;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3491
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3492
	if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3493
		hw->get_link_status = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3494
		/* guard against interrupt when we're going down */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3495
		if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3496
			mod_timer(&adapter->watchdog_timer, jiffies + 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3497
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3498
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3499
	/* disable interrupts, without the synchronize_irq bit */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3500
	ew32(IMC, ~0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3501
	E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3502
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3503
	if (likely(napi_schedule_prep(&adapter->napi))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3504
		adapter->total_tx_bytes = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3505
		adapter->total_tx_packets = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3506
		adapter->total_rx_bytes = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3507
		adapter->total_rx_packets = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3508
		__napi_schedule(&adapter->napi);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3509
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3510
		/* this really should not happen! if it does it is basically a
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3511
		 * bug, but not a hard error, so enable ints and continue */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3512
		if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3513
			e1000_irq_enable(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3514
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3515
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3516
	return IRQ_HANDLED;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3517
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3518
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3519
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3520
 * e1000_clean - NAPI Rx polling callback
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3521
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3522
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3523
static int e1000_clean(struct napi_struct *napi, int budget)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3524
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3525
	struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3526
	int tx_clean_complete = 0, work_done = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3527
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3528
	tx_clean_complete = e1000_clean_tx_irq(adapter, &adapter->tx_ring[0]);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3529
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3530
	adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3531
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3532
	if (!tx_clean_complete)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3533
		work_done = budget;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3534
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3535
	/* If budget not fully consumed, exit the polling mode */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3536
	if (work_done < budget) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3537
		if (likely(adapter->itr_setting & 3))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3538
			e1000_set_itr(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3539
		napi_complete(napi);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3540
		if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3541
			e1000_irq_enable(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3542
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3543
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3544
	return work_done;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3545
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3546
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3547
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3548
 * e1000_clean_tx_irq - Reclaim resources after transmit completes
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3549
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3550
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3551
static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3552
			       struct e1000_tx_ring *tx_ring)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3553
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3554
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3555
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3556
	struct e1000_tx_desc *tx_desc, *eop_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3557
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3558
	unsigned int i, eop;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3559
	unsigned int count = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3560
	unsigned int total_tx_bytes=0, total_tx_packets=0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3561
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3562
	i = tx_ring->next_to_clean;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3563
	eop = tx_ring->buffer_info[i].next_to_watch;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3564
	eop_desc = E1000_TX_DESC(*tx_ring, eop);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3565
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3566
	while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3567
	       (count < tx_ring->count)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3568
		bool cleaned = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3569
		rmb();	/* read buffer_info after eop_desc */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3570
		for ( ; !cleaned; count++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3571
			tx_desc = E1000_TX_DESC(*tx_ring, i);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3572
			buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3573
			cleaned = (i == eop);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3574
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3575
			if (cleaned) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3576
				struct sk_buff *skb = buffer_info->skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3577
				unsigned int segs, bytecount;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3578
				segs = skb_shinfo(skb)->gso_segs ?: 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3579
				/* multiply data chunks by size of headers */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3580
				bytecount = ((segs - 1) * skb_headlen(skb)) +
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3581
				            skb->len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3582
				total_tx_packets += segs;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3583
				total_tx_bytes += bytecount;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3584
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3585
			e1000_unmap_and_free_tx_resource(adapter, buffer_info);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3586
			tx_desc->upper.data = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3587
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3588
			if (unlikely(++i == tx_ring->count)) i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3589
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3590
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3591
		eop = tx_ring->buffer_info[i].next_to_watch;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3592
		eop_desc = E1000_TX_DESC(*tx_ring, eop);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3593
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3594
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3595
	tx_ring->next_to_clean = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3596
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3597
#define TX_WAKE_THRESHOLD 32
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3598
	if (unlikely(count && netif_carrier_ok(netdev) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3599
		     E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3600
		/* Make sure that anybody stopping the queue after this
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3601
		 * sees the new next_to_clean.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3602
		 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3603
		smp_mb();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3604
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3605
		if (netif_queue_stopped(netdev) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3606
		    !(test_bit(__E1000_DOWN, &adapter->flags))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3607
			netif_wake_queue(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3608
			++adapter->restart_queue;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3609
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3610
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3611
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3612
	if (adapter->detect_tx_hung) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3613
		/* Detect a transmit hang in hardware, this serializes the
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3614
		 * check with the clearing of time_stamp and movement of i */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3615
		adapter->detect_tx_hung = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3616
		if (tx_ring->buffer_info[eop].time_stamp &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3617
		    time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3618
		               (adapter->tx_timeout_factor * HZ)) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3619
		    !(er32(STATUS) & E1000_STATUS_TXOFF)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3620
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3621
			/* detected Tx unit hang */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3622
			e_err(drv, "Detected Tx Unit Hang\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3623
			      "  Tx Queue             <%lu>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3624
			      "  TDH                  <%x>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3625
			      "  TDT                  <%x>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3626
			      "  next_to_use          <%x>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3627
			      "  next_to_clean        <%x>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3628
			      "buffer_info[next_to_clean]\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3629
			      "  time_stamp           <%lx>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3630
			      "  next_to_watch        <%x>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3631
			      "  jiffies              <%lx>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3632
			      "  next_to_watch.status <%x>\n",
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3633
				(unsigned long)((tx_ring - adapter->tx_ring) /
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3634
					sizeof(struct e1000_tx_ring)),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3635
				readl(hw->hw_addr + tx_ring->tdh),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3636
				readl(hw->hw_addr + tx_ring->tdt),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3637
				tx_ring->next_to_use,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3638
				tx_ring->next_to_clean,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3639
				tx_ring->buffer_info[eop].time_stamp,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3640
				eop,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3641
				jiffies,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3642
				eop_desc->upper.fields.status);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3643
			netif_stop_queue(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3644
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3645
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3646
	adapter->total_tx_bytes += total_tx_bytes;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3647
	adapter->total_tx_packets += total_tx_packets;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3648
	netdev->stats.tx_bytes += total_tx_bytes;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3649
	netdev->stats.tx_packets += total_tx_packets;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3650
	return count < tx_ring->count;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3651
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3652
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3653
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3654
 * e1000_rx_checksum - Receive Checksum Offload for 82543
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3655
 * @adapter:     board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3656
 * @status_err:  receive descriptor status and error fields
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3657
 * @csum:        receive descriptor csum field
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3658
 * @sk_buff:     socket buffer with received data
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3659
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3660
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3661
static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3662
			      u32 csum, struct sk_buff *skb)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3663
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3664
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3665
	u16 status = (u16)status_err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3666
	u8 errors = (u8)(status_err >> 24);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3667
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3668
	skb_checksum_none_assert(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3669
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3670
	/* 82543 or newer only */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3671
	if (unlikely(hw->mac_type < e1000_82543)) return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3672
	/* Ignore Checksum bit is set */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3673
	if (unlikely(status & E1000_RXD_STAT_IXSM)) return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3674
	/* TCP/UDP checksum error bit is set */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3675
	if (unlikely(errors & E1000_RXD_ERR_TCPE)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3676
		/* let the stack verify checksum errors */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3677
		adapter->hw_csum_err++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3678
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3679
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3680
	/* TCP/UDP Checksum has not been calculated */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3681
	if (!(status & E1000_RXD_STAT_TCPCS))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3682
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3683
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3684
	/* It must be a TCP or UDP packet with a valid checksum */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3685
	if (likely(status & E1000_RXD_STAT_TCPCS)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3686
		/* TCP checksum is good */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3687
		skb->ip_summed = CHECKSUM_UNNECESSARY;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3688
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3689
	adapter->hw_csum_good++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3690
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3691
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3692
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3693
 * e1000_consume_page - helper function
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3694
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3695
static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3696
                               u16 length)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3697
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3698
	bi->page = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3699
	skb->len += length;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3700
	skb->data_len += length;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3701
	skb->truesize += length;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3702
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3703
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3704
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3705
 * e1000_receive_skb - helper function to handle rx indications
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3706
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3707
 * @status: descriptor status field as written by hardware
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3708
 * @vlan: descriptor vlan field as written by hardware (no le/be conversion)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3709
 * @skb: pointer to sk_buff to be indicated to stack
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3710
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3711
static void e1000_receive_skb(struct e1000_adapter *adapter, u8 status,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3712
			      __le16 vlan, struct sk_buff *skb)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3713
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3714
	skb->protocol = eth_type_trans(skb, adapter->netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3715
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3716
	if ((unlikely(adapter->vlgrp && (status & E1000_RXD_STAT_VP))))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3717
		vlan_gro_receive(&adapter->napi, adapter->vlgrp,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3718
				 le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3719
				 skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3720
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3721
		napi_gro_receive(&adapter->napi, skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3722
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3723
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3724
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3725
 * e1000_clean_jumbo_rx_irq - Send received data up the network stack; legacy
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3726
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3727
 * @rx_ring: ring to clean
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3728
 * @work_done: amount of napi work completed this call
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3729
 * @work_to_do: max amount of work allowed for this call to do
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3730
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3731
 * the return value indicates whether actual cleaning was done, there
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3732
 * is no guarantee that everything was cleaned
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3733
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3734
static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3735
				     struct e1000_rx_ring *rx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3736
				     int *work_done, int work_to_do)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3737
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3738
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3739
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3740
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3741
	struct e1000_rx_desc *rx_desc, *next_rxd;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3742
	struct e1000_buffer *buffer_info, *next_buffer;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3743
	unsigned long irq_flags;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3744
	u32 length;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3745
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3746
	int cleaned_count = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3747
	bool cleaned = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3748
	unsigned int total_rx_bytes=0, total_rx_packets=0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3749
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3750
	i = rx_ring->next_to_clean;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3751
	rx_desc = E1000_RX_DESC(*rx_ring, i);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3752
	buffer_info = &rx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3753
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3754
	while (rx_desc->status & E1000_RXD_STAT_DD) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3755
		struct sk_buff *skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3756
		u8 status;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3757
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3758
		if (*work_done >= work_to_do)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3759
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3760
		(*work_done)++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3761
		rmb(); /* read descriptor and rx_buffer_info after status DD */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3762
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3763
		status = rx_desc->status;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3764
		skb = buffer_info->skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3765
		buffer_info->skb = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3766
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3767
		if (++i == rx_ring->count) i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3768
		next_rxd = E1000_RX_DESC(*rx_ring, i);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3769
		prefetch(next_rxd);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3770
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3771
		next_buffer = &rx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3772
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3773
		cleaned = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3774
		cleaned_count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3775
		dma_unmap_page(&pdev->dev, buffer_info->dma,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3776
			       buffer_info->length, DMA_FROM_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3777
		buffer_info->dma = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3778
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3779
		length = le16_to_cpu(rx_desc->length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3780
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3781
		/* errors is only valid for DD + EOP descriptors */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3782
		if (unlikely((status & E1000_RXD_STAT_EOP) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3783
		    (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3784
			u8 last_byte = *(skb->data + length - 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3785
			if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3786
				       last_byte)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3787
				spin_lock_irqsave(&adapter->stats_lock,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3788
				                  irq_flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3789
				e1000_tbi_adjust_stats(hw, &adapter->stats,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3790
				                       length, skb->data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3791
				spin_unlock_irqrestore(&adapter->stats_lock,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3792
				                       irq_flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3793
				length--;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3794
			} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3795
				/* recycle both page and skb */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3796
				buffer_info->skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3797
				/* an error means any chain goes out the window
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3798
				 * too */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3799
				if (rx_ring->rx_skb_top)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3800
					dev_kfree_skb(rx_ring->rx_skb_top);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3801
				rx_ring->rx_skb_top = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3802
				goto next_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3803
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3804
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3805
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3806
#define rxtop rx_ring->rx_skb_top
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3807
		if (!(status & E1000_RXD_STAT_EOP)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3808
			/* this descriptor is only the beginning (or middle) */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3809
			if (!rxtop) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3810
				/* this is the beginning of a chain */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3811
				rxtop = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3812
				skb_fill_page_desc(rxtop, 0, buffer_info->page,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3813
				                   0, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3814
			} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3815
				/* this is the middle of a chain */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3816
				skb_fill_page_desc(rxtop,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3817
				    skb_shinfo(rxtop)->nr_frags,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3818
				    buffer_info->page, 0, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3819
				/* re-use the skb, only consumed the page */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3820
				buffer_info->skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3821
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3822
			e1000_consume_page(buffer_info, rxtop, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3823
			goto next_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3824
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3825
			if (rxtop) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3826
				/* end of the chain */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3827
				skb_fill_page_desc(rxtop,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3828
				    skb_shinfo(rxtop)->nr_frags,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3829
				    buffer_info->page, 0, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3830
				/* re-use the current skb, we only consumed the
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3831
				 * page */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3832
				buffer_info->skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3833
				skb = rxtop;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3834
				rxtop = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3835
				e1000_consume_page(buffer_info, skb, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3836
			} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3837
				/* no chain, got EOP, this buf is the packet
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3838
				 * copybreak to save the put_page/alloc_page */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3839
				if (length <= copybreak &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3840
				    skb_tailroom(skb) >= length) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3841
					u8 *vaddr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3842
					vaddr = kmap_atomic(buffer_info->page,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3843
					                    KM_SKB_DATA_SOFTIRQ);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3844
					memcpy(skb_tail_pointer(skb), vaddr, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3845
					kunmap_atomic(vaddr,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3846
					              KM_SKB_DATA_SOFTIRQ);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3847
					/* re-use the page, so don't erase
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3848
					 * buffer_info->page */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3849
					skb_put(skb, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3850
				} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3851
					skb_fill_page_desc(skb, 0,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3852
					                   buffer_info->page, 0,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3853
				                           length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3854
					e1000_consume_page(buffer_info, skb,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3855
					                   length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3856
				}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3857
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3858
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3859
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3860
		/* Receive Checksum Offload XXX recompute due to CRC strip? */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3861
		e1000_rx_checksum(adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3862
		                  (u32)(status) |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3863
		                  ((u32)(rx_desc->errors) << 24),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3864
		                  le16_to_cpu(rx_desc->csum), skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3865
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3866
		pskb_trim(skb, skb->len - 4);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3867
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3868
		/* probably a little skewed due to removing CRC */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3869
		total_rx_bytes += skb->len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3870
		total_rx_packets++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3871
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3872
		/* eth type trans needs skb->data to point to something */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3873
		if (!pskb_may_pull(skb, ETH_HLEN)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3874
			e_err(drv, "pskb_may_pull failed.\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3875
			dev_kfree_skb(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3876
			goto next_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3877
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3878
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3879
		e1000_receive_skb(adapter, status, rx_desc->special, skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3880
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3881
next_desc:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3882
		rx_desc->status = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3883
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3884
		/* return some buffers to hardware, one at a time is too slow */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3885
		if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3886
			adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3887
			cleaned_count = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3888
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3889
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3890
		/* use prefetched values */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3891
		rx_desc = next_rxd;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3892
		buffer_info = next_buffer;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3893
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3894
	rx_ring->next_to_clean = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3895
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3896
	cleaned_count = E1000_DESC_UNUSED(rx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3897
	if (cleaned_count)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3898
		adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3899
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3900
	adapter->total_rx_packets += total_rx_packets;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3901
	adapter->total_rx_bytes += total_rx_bytes;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3902
	netdev->stats.rx_bytes += total_rx_bytes;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3903
	netdev->stats.rx_packets += total_rx_packets;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3904
	return cleaned;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3905
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3906
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3907
/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3908
 * this should improve performance for small packets with large amounts
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3909
 * of reassembly being done in the stack
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3910
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3911
static void e1000_check_copybreak(struct net_device *netdev,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3912
				 struct e1000_buffer *buffer_info,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3913
				 u32 length, struct sk_buff **skb)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3914
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3915
	struct sk_buff *new_skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3916
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3917
	if (length > copybreak)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3918
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3919
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3920
	new_skb = netdev_alloc_skb_ip_align(netdev, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3921
	if (!new_skb)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3922
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3923
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3924
	skb_copy_to_linear_data_offset(new_skb, -NET_IP_ALIGN,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3925
				       (*skb)->data - NET_IP_ALIGN,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3926
				       length + NET_IP_ALIGN);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3927
	/* save the skb in buffer_info as good */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3928
	buffer_info->skb = *skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3929
	*skb = new_skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3930
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3931
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3932
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3933
 * e1000_clean_rx_irq - Send received data up the network stack; legacy
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3934
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3935
 * @rx_ring: ring to clean
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3936
 * @work_done: amount of napi work completed this call
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3937
 * @work_to_do: max amount of work allowed for this call to do
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3938
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3939
static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3940
			       struct e1000_rx_ring *rx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3941
			       int *work_done, int work_to_do)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3942
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3943
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3944
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3945
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3946
	struct e1000_rx_desc *rx_desc, *next_rxd;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3947
	struct e1000_buffer *buffer_info, *next_buffer;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3948
	unsigned long flags;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3949
	u32 length;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3950
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3951
	int cleaned_count = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3952
	bool cleaned = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3953
	unsigned int total_rx_bytes=0, total_rx_packets=0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3954
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3955
	i = rx_ring->next_to_clean;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3956
	rx_desc = E1000_RX_DESC(*rx_ring, i);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3957
	buffer_info = &rx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3958
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3959
	while (rx_desc->status & E1000_RXD_STAT_DD) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3960
		struct sk_buff *skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3961
		u8 status;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3962
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3963
		if (*work_done >= work_to_do)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3964
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3965
		(*work_done)++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3966
		rmb(); /* read descriptor and rx_buffer_info after status DD */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3967
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3968
		status = rx_desc->status;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3969
		skb = buffer_info->skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3970
		buffer_info->skb = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3971
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3972
		prefetch(skb->data - NET_IP_ALIGN);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3973
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3974
		if (++i == rx_ring->count) i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3975
		next_rxd = E1000_RX_DESC(*rx_ring, i);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3976
		prefetch(next_rxd);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3977
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3978
		next_buffer = &rx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3979
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3980
		cleaned = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3981
		cleaned_count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3982
		dma_unmap_single(&pdev->dev, buffer_info->dma,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3983
				 buffer_info->length, DMA_FROM_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3984
		buffer_info->dma = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3985
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3986
		length = le16_to_cpu(rx_desc->length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3987
		/* !EOP means multiple descriptors were used to store a single
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3988
		 * packet, if thats the case we need to toss it.  In fact, we
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3989
		 * to toss every packet with the EOP bit clear and the next
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3990
		 * frame that _does_ have the EOP bit set, as it is by
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3991
		 * definition only a frame fragment
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3992
		 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3993
		if (unlikely(!(status & E1000_RXD_STAT_EOP)))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3994
			adapter->discarding = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3995
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3996
		if (adapter->discarding) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3997
			/* All receives must fit into a single buffer */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3998
			e_dbg("Receive packet consumed multiple buffers\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3999
			/* recycle */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4000
			buffer_info->skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4001
			if (status & E1000_RXD_STAT_EOP)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4002
				adapter->discarding = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4003
			goto next_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4004
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4005
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4006
		if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4007
			u8 last_byte = *(skb->data + length - 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4008
			if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4009
				       last_byte)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4010
				spin_lock_irqsave(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4011
				e1000_tbi_adjust_stats(hw, &adapter->stats,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4012
				                       length, skb->data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4013
				spin_unlock_irqrestore(&adapter->stats_lock,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4014
				                       flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4015
				length--;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4016
			} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4017
				/* recycle */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4018
				buffer_info->skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4019
				goto next_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4020
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4021
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4022
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4023
		/* adjust length to remove Ethernet CRC, this must be
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4024
		 * done after the TBI_ACCEPT workaround above */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4025
		length -= 4;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4026
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4027
		/* probably a little skewed due to removing CRC */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4028
		total_rx_bytes += length;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4029
		total_rx_packets++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4030
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4031
		e1000_check_copybreak(netdev, buffer_info, length, &skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4032
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4033
		skb_put(skb, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4034
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4035
		/* Receive Checksum Offload */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4036
		e1000_rx_checksum(adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4037
				  (u32)(status) |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4038
				  ((u32)(rx_desc->errors) << 24),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4039
				  le16_to_cpu(rx_desc->csum), skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4040
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4041
		e1000_receive_skb(adapter, status, rx_desc->special, skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4042
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4043
next_desc:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4044
		rx_desc->status = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4045
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4046
		/* return some buffers to hardware, one at a time is too slow */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4047
		if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4048
			adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4049
			cleaned_count = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4050
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4051
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4052
		/* use prefetched values */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4053
		rx_desc = next_rxd;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4054
		buffer_info = next_buffer;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4055
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4056
	rx_ring->next_to_clean = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4057
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4058
	cleaned_count = E1000_DESC_UNUSED(rx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4059
	if (cleaned_count)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4060
		adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4061
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4062
	adapter->total_rx_packets += total_rx_packets;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4063
	adapter->total_rx_bytes += total_rx_bytes;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4064
	netdev->stats.rx_bytes += total_rx_bytes;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4065
	netdev->stats.rx_packets += total_rx_packets;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4066
	return cleaned;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4067
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4068
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4069
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4070
 * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4071
 * @adapter: address of board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4072
 * @rx_ring: pointer to receive ring structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4073
 * @cleaned_count: number of buffers to allocate this pass
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4074
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4075
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4076
static void
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4077
e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4078
                             struct e1000_rx_ring *rx_ring, int cleaned_count)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4079
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4080
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4081
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4082
	struct e1000_rx_desc *rx_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4083
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4084
	struct sk_buff *skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4085
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4086
	unsigned int bufsz = 256 - 16 /*for skb_reserve */ ;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4087
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4088
	i = rx_ring->next_to_use;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4089
	buffer_info = &rx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4090
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4091
	while (cleaned_count--) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4092
		skb = buffer_info->skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4093
		if (skb) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4094
			skb_trim(skb, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4095
			goto check_page;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4096
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4097
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4098
		skb = netdev_alloc_skb_ip_align(netdev, bufsz);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4099
		if (unlikely(!skb)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4100
			/* Better luck next round */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4101
			adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4102
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4103
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4104
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4105
		/* Fix for errata 23, can't cross 64kB boundary */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4106
		if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4107
			struct sk_buff *oldskb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4108
			e_err(rx_err, "skb align check failed: %u bytes at "
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4109
			      "%p\n", bufsz, skb->data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4110
			/* Try again, without freeing the previous */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4111
			skb = netdev_alloc_skb_ip_align(netdev, bufsz);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4112
			/* Failed allocation, critical failure */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4113
			if (!skb) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4114
				dev_kfree_skb(oldskb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4115
				adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4116
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4117
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4118
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4119
			if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4120
				/* give up */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4121
				dev_kfree_skb(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4122
				dev_kfree_skb(oldskb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4123
				break; /* while (cleaned_count--) */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4124
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4125
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4126
			/* Use new allocation */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4127
			dev_kfree_skb(oldskb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4128
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4129
		buffer_info->skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4130
		buffer_info->length = adapter->rx_buffer_len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4131
check_page:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4132
		/* allocate a new page if necessary */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4133
		if (!buffer_info->page) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4134
			buffer_info->page = alloc_page(GFP_ATOMIC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4135
			if (unlikely(!buffer_info->page)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4136
				adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4137
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4138
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4139
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4140
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4141
		if (!buffer_info->dma) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4142
			buffer_info->dma = dma_map_page(&pdev->dev,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4143
			                                buffer_info->page, 0,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4144
							buffer_info->length,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4145
							DMA_FROM_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4146
			if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4147
				put_page(buffer_info->page);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4148
				dev_kfree_skb(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4149
				buffer_info->page = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4150
				buffer_info->skb = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4151
				buffer_info->dma = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4152
				adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4153
				break; /* while !buffer_info->skb */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4154
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4155
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4156
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4157
		rx_desc = E1000_RX_DESC(*rx_ring, i);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4158
		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4159
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4160
		if (unlikely(++i == rx_ring->count))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4161
			i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4162
		buffer_info = &rx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4163
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4164
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4165
	if (likely(rx_ring->next_to_use != i)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4166
		rx_ring->next_to_use = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4167
		if (unlikely(i-- == 0))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4168
			i = (rx_ring->count - 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4169
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4170
		/* Force memory writes to complete before letting h/w
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4171
		 * know there are new descriptors to fetch.  (Only
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4172
		 * applicable for weak-ordered memory model archs,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4173
		 * such as IA-64). */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4174
		wmb();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4175
		writel(i, adapter->hw.hw_addr + rx_ring->rdt);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4176
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4177
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4178
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4179
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4180
 * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4181
 * @adapter: address of board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4182
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4183
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4184
static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4185
				   struct e1000_rx_ring *rx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4186
				   int cleaned_count)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4187
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4188
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4189
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4190
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4191
	struct e1000_rx_desc *rx_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4192
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4193
	struct sk_buff *skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4194
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4195
	unsigned int bufsz = adapter->rx_buffer_len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4196
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4197
	i = rx_ring->next_to_use;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4198
	buffer_info = &rx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4199
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4200
	while (cleaned_count--) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4201
		skb = buffer_info->skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4202
		if (skb) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4203
			skb_trim(skb, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4204
			goto map_skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4205
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4206
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4207
		skb = netdev_alloc_skb_ip_align(netdev, bufsz);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4208
		if (unlikely(!skb)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4209
			/* Better luck next round */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4210
			adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4211
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4212
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4213
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4214
		/* Fix for errata 23, can't cross 64kB boundary */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4215
		if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4216
			struct sk_buff *oldskb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4217
			e_err(rx_err, "skb align check failed: %u bytes at "
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4218
			      "%p\n", bufsz, skb->data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4219
			/* Try again, without freeing the previous */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4220
			skb = netdev_alloc_skb_ip_align(netdev, bufsz);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4221
			/* Failed allocation, critical failure */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4222
			if (!skb) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4223
				dev_kfree_skb(oldskb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4224
				adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4225
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4226
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4227
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4228
			if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4229
				/* give up */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4230
				dev_kfree_skb(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4231
				dev_kfree_skb(oldskb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4232
				adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4233
				break; /* while !buffer_info->skb */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4234
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4235
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4236
			/* Use new allocation */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4237
			dev_kfree_skb(oldskb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4238
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4239
		buffer_info->skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4240
		buffer_info->length = adapter->rx_buffer_len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4241
map_skb:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4242
		buffer_info->dma = dma_map_single(&pdev->dev,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4243
						  skb->data,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4244
						  buffer_info->length,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4245
						  DMA_FROM_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4246
		if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4247
			dev_kfree_skb(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4248
			buffer_info->skb = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4249
			buffer_info->dma = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4250
			adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4251
			break; /* while !buffer_info->skb */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4252
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4253
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4254
		/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4255
		 * XXX if it was allocated cleanly it will never map to a
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4256
		 * boundary crossing
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4257
		 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4258
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4259
		/* Fix for errata 23, can't cross 64kB boundary */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4260
		if (!e1000_check_64k_bound(adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4261
					(void *)(unsigned long)buffer_info->dma,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4262
					adapter->rx_buffer_len)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4263
			e_err(rx_err, "dma align check failed: %u bytes at "
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4264
			      "%p\n", adapter->rx_buffer_len,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4265
			      (void *)(unsigned long)buffer_info->dma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4266
			dev_kfree_skb(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4267
			buffer_info->skb = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4268
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4269
			dma_unmap_single(&pdev->dev, buffer_info->dma,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4270
					 adapter->rx_buffer_len,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4271
					 DMA_FROM_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4272
			buffer_info->dma = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4273
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4274
			adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4275
			break; /* while !buffer_info->skb */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4276
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4277
		rx_desc = E1000_RX_DESC(*rx_ring, i);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4278
		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4279
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4280
		if (unlikely(++i == rx_ring->count))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4281
			i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4282
		buffer_info = &rx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4283
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4284
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4285
	if (likely(rx_ring->next_to_use != i)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4286
		rx_ring->next_to_use = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4287
		if (unlikely(i-- == 0))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4288
			i = (rx_ring->count - 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4289
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4290
		/* Force memory writes to complete before letting h/w
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4291
		 * know there are new descriptors to fetch.  (Only
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4292
		 * applicable for weak-ordered memory model archs,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4293
		 * such as IA-64). */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4294
		wmb();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4295
		writel(i, hw->hw_addr + rx_ring->rdt);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4296
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4297
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4298
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4299
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4300
 * e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4301
 * @adapter:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4302
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4303
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4304
static void e1000_smartspeed(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4305
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4306
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4307
	u16 phy_status;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4308
	u16 phy_ctrl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4309
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4310
	if ((hw->phy_type != e1000_phy_igp) || !hw->autoneg ||
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4311
	   !(hw->autoneg_advertised & ADVERTISE_1000_FULL))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4312
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4313
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4314
	if (adapter->smartspeed == 0) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4315
		/* If Master/Slave config fault is asserted twice,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4316
		 * we assume back-to-back */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4317
		e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4318
		if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4319
		e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4320
		if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4321
		e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4322
		if (phy_ctrl & CR_1000T_MS_ENABLE) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4323
			phy_ctrl &= ~CR_1000T_MS_ENABLE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4324
			e1000_write_phy_reg(hw, PHY_1000T_CTRL,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4325
					    phy_ctrl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4326
			adapter->smartspeed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4327
			if (!e1000_phy_setup_autoneg(hw) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4328
			   !e1000_read_phy_reg(hw, PHY_CTRL,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4329
				   	       &phy_ctrl)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4330
				phy_ctrl |= (MII_CR_AUTO_NEG_EN |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4331
					     MII_CR_RESTART_AUTO_NEG);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4332
				e1000_write_phy_reg(hw, PHY_CTRL,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4333
						    phy_ctrl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4334
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4335
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4336
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4337
	} else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4338
		/* If still no link, perhaps using 2/3 pair cable */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4339
		e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4340
		phy_ctrl |= CR_1000T_MS_ENABLE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4341
		e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_ctrl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4342
		if (!e1000_phy_setup_autoneg(hw) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4343
		   !e1000_read_phy_reg(hw, PHY_CTRL, &phy_ctrl)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4344
			phy_ctrl |= (MII_CR_AUTO_NEG_EN |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4345
				     MII_CR_RESTART_AUTO_NEG);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4346
			e1000_write_phy_reg(hw, PHY_CTRL, phy_ctrl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4347
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4348
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4349
	/* Restart process after E1000_SMARTSPEED_MAX iterations */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4350
	if (adapter->smartspeed++ == E1000_SMARTSPEED_MAX)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4351
		adapter->smartspeed = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4352
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4353
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4354
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4355
 * e1000_ioctl -
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4356
 * @netdev:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4357
 * @ifreq:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4358
 * @cmd:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4359
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4360
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4361
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4362
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4363
	switch (cmd) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4364
	case SIOCGMIIPHY:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4365
	case SIOCGMIIREG:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4366
	case SIOCSMIIREG:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4367
		return e1000_mii_ioctl(netdev, ifr, cmd);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4368
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4369
		return -EOPNOTSUPP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4370
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4371
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4372
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4373
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4374
 * e1000_mii_ioctl -
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4375
 * @netdev:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4376
 * @ifreq:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4377
 * @cmd:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4378
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4379
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4380
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4381
			   int cmd)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4382
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4383
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4384
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4385
	struct mii_ioctl_data *data = if_mii(ifr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4386
	int retval;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4387
	u16 mii_reg;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4388
	unsigned long flags;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4389
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4390
	if (hw->media_type != e1000_media_type_copper)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4391
		return -EOPNOTSUPP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4392
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4393
	switch (cmd) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4394
	case SIOCGMIIPHY:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4395
		data->phy_id = hw->phy_addr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4396
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4397
	case SIOCGMIIREG:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4398
		spin_lock_irqsave(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4399
		if (e1000_read_phy_reg(hw, data->reg_num & 0x1F,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4400
				   &data->val_out)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4401
			spin_unlock_irqrestore(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4402
			return -EIO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4403
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4404
		spin_unlock_irqrestore(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4405
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4406
	case SIOCSMIIREG:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4407
		if (data->reg_num & ~(0x1F))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4408
			return -EFAULT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4409
		mii_reg = data->val_in;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4410
		spin_lock_irqsave(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4411
		if (e1000_write_phy_reg(hw, data->reg_num,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4412
					mii_reg)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4413
			spin_unlock_irqrestore(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4414
			return -EIO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4415
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4416
		spin_unlock_irqrestore(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4417
		if (hw->media_type == e1000_media_type_copper) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4418
			switch (data->reg_num) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4419
			case PHY_CTRL:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4420
				if (mii_reg & MII_CR_POWER_DOWN)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4421
					break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4422
				if (mii_reg & MII_CR_AUTO_NEG_EN) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4423
					hw->autoneg = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4424
					hw->autoneg_advertised = 0x2F;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4425
				} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4426
					u32 speed;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4427
					if (mii_reg & 0x40)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4428
						speed = SPEED_1000;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4429
					else if (mii_reg & 0x2000)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4430
						speed = SPEED_100;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4431
					else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4432
						speed = SPEED_10;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4433
					retval = e1000_set_spd_dplx(
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4434
						adapter, speed,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4435
						((mii_reg & 0x100)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4436
						 ? DUPLEX_FULL :
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4437
						 DUPLEX_HALF));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4438
					if (retval)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4439
						return retval;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4440
				}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4441
				if (netif_running(adapter->netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4442
					e1000_reinit_locked(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4443
				else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4444
					e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4445
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4446
			case M88E1000_PHY_SPEC_CTRL:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4447
			case M88E1000_EXT_PHY_SPEC_CTRL:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4448
				if (e1000_phy_reset(hw))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4449
					return -EIO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4450
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4451
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4452
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4453
			switch (data->reg_num) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4454
			case PHY_CTRL:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4455
				if (mii_reg & MII_CR_POWER_DOWN)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4456
					break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4457
				if (netif_running(adapter->netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4458
					e1000_reinit_locked(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4459
				else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4460
					e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4461
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4462
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4463
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4464
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4465
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4466
		return -EOPNOTSUPP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4467
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4468
	return E1000_SUCCESS;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4469
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4470
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4471
void e1000_pci_set_mwi(struct e1000_hw *hw)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4472
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4473
	struct e1000_adapter *adapter = hw->back;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4474
	int ret_val = pci_set_mwi(adapter->pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4475
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4476
	if (ret_val)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4477
		e_err(probe, "Error in setting MWI\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4478
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4479
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4480
void e1000_pci_clear_mwi(struct e1000_hw *hw)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4481
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4482
	struct e1000_adapter *adapter = hw->back;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4483
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4484
	pci_clear_mwi(adapter->pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4485
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4486
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4487
int e1000_pcix_get_mmrbc(struct e1000_hw *hw)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4488
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4489
	struct e1000_adapter *adapter = hw->back;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4490
	return pcix_get_mmrbc(adapter->pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4491
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4492
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4493
void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4494
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4495
	struct e1000_adapter *adapter = hw->back;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4496
	pcix_set_mmrbc(adapter->pdev, mmrbc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4497
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4498
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4499
void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4500
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4501
	outl(value, port);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4502
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4503
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4504
static void e1000_vlan_rx_register(struct net_device *netdev,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4505
				   struct vlan_group *grp)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4506
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4507
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4508
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4509
	u32 ctrl, rctl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4510
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4511
	if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4512
		e1000_irq_disable(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4513
	adapter->vlgrp = grp;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4514
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4515
	if (grp) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4516
		/* enable VLAN tag insert/strip */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4517
		ctrl = er32(CTRL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4518
		ctrl |= E1000_CTRL_VME;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4519
		ew32(CTRL, ctrl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4520
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4521
		/* enable VLAN receive filtering */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4522
		rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4523
		rctl &= ~E1000_RCTL_CFIEN;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4524
		if (!(netdev->flags & IFF_PROMISC))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4525
			rctl |= E1000_RCTL_VFE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4526
		ew32(RCTL, rctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4527
		e1000_update_mng_vlan(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4528
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4529
		/* disable VLAN tag insert/strip */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4530
		ctrl = er32(CTRL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4531
		ctrl &= ~E1000_CTRL_VME;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4532
		ew32(CTRL, ctrl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4533
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4534
		/* disable VLAN receive filtering */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4535
		rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4536
		rctl &= ~E1000_RCTL_VFE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4537
		ew32(RCTL, rctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4538
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4539
		if (adapter->mng_vlan_id != (u16)E1000_MNG_VLAN_NONE) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4540
			e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4541
			adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4542
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4543
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4544
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4545
	if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4546
		e1000_irq_enable(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4547
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4548
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4549
static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4550
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4551
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4552
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4553
	u32 vfta, index;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4554
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4555
	if ((hw->mng_cookie.status &
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4556
	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4557
	    (vid == adapter->mng_vlan_id))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4558
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4559
	/* add VID to filter table */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4560
	index = (vid >> 5) & 0x7F;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4561
	vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4562
	vfta |= (1 << (vid & 0x1F));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4563
	e1000_write_vfta(hw, index, vfta);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4564
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4565
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4566
static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4567
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4568
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4569
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4570
	u32 vfta, index;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4571
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4572
	if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4573
		e1000_irq_disable(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4574
	vlan_group_set_device(adapter->vlgrp, vid, NULL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4575
	if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4576
		e1000_irq_enable(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4577
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4578
	/* remove VID from filter table */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4579
	index = (vid >> 5) & 0x7F;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4580
	vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4581
	vfta &= ~(1 << (vid & 0x1F));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4582
	e1000_write_vfta(hw, index, vfta);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4583
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4584
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4585
static void e1000_restore_vlan(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4586
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4587
	e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4588
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4589
	if (adapter->vlgrp) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4590
		u16 vid;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4591
		for (vid = 0; vid < VLAN_N_VID; vid++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4592
			if (!vlan_group_get_device(adapter->vlgrp, vid))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4593
				continue;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4594
			e1000_vlan_rx_add_vid(adapter->netdev, vid);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4595
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4596
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4597
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4598
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4599
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4600
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4601
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4602
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4603
	hw->autoneg = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4604
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4605
	/* Make sure dplx is at most 1 bit and lsb of speed is not set
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4606
	 * for the switch() below to work */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4607
	if ((spd & 1) || (dplx & ~1))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4608
		goto err_inval;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4609
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4610
	/* Fiber NICs only allow 1000 gbps Full duplex */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4611
	if ((hw->media_type == e1000_media_type_fiber) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4612
	    spd != SPEED_1000 &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4613
	    dplx != DUPLEX_FULL)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4614
		goto err_inval;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4615
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4616
	switch (spd + dplx) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4617
	case SPEED_10 + DUPLEX_HALF:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4618
		hw->forced_speed_duplex = e1000_10_half;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4619
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4620
	case SPEED_10 + DUPLEX_FULL:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4621
		hw->forced_speed_duplex = e1000_10_full;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4622
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4623
	case SPEED_100 + DUPLEX_HALF:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4624
		hw->forced_speed_duplex = e1000_100_half;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4625
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4626
	case SPEED_100 + DUPLEX_FULL:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4627
		hw->forced_speed_duplex = e1000_100_full;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4628
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4629
	case SPEED_1000 + DUPLEX_FULL:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4630
		hw->autoneg = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4631
		hw->autoneg_advertised = ADVERTISE_1000_FULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4632
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4633
	case SPEED_1000 + DUPLEX_HALF: /* not supported */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4634
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4635
		goto err_inval;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4636
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4637
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4638
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4639
err_inval:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4640
	e_err(probe, "Unsupported Speed/Duplex configuration\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4641
	return -EINVAL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4642
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4643
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4644
static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4645
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4646
	struct net_device *netdev = pci_get_drvdata(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4647
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4648
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4649
	u32 ctrl, ctrl_ext, rctl, status;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4650
	u32 wufc = adapter->wol;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4651
#ifdef CONFIG_PM
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4652
	int retval = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4653
#endif
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4654
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4655
	netif_device_detach(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4656
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4657
	if (netif_running(netdev)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4658
		WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4659
		e1000_down(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4660
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4661
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4662
#ifdef CONFIG_PM
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4663
	retval = pci_save_state(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4664
	if (retval)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4665
		return retval;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4666
#endif
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4667
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4668
	status = er32(STATUS);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4669
	if (status & E1000_STATUS_LU)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4670
		wufc &= ~E1000_WUFC_LNKC;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4671
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4672
	if (wufc) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4673
		e1000_setup_rctl(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4674
		e1000_set_rx_mode(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4675
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4676
		/* turn on all-multi mode if wake on multicast is enabled */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4677
		if (wufc & E1000_WUFC_MC) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4678
			rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4679
			rctl |= E1000_RCTL_MPE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4680
			ew32(RCTL, rctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4681
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4682
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4683
		if (hw->mac_type >= e1000_82540) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4684
			ctrl = er32(CTRL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4685
			/* advertise wake from D3Cold */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4686
			#define E1000_CTRL_ADVD3WUC 0x00100000
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4687
			/* phy power management enable */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4688
			#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4689
			ctrl |= E1000_CTRL_ADVD3WUC |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4690
				E1000_CTRL_EN_PHY_PWR_MGMT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4691
			ew32(CTRL, ctrl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4692
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4693
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4694
		if (hw->media_type == e1000_media_type_fiber ||
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4695
		    hw->media_type == e1000_media_type_internal_serdes) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4696
			/* keep the laser running in D3 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4697
			ctrl_ext = er32(CTRL_EXT);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4698
			ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4699
			ew32(CTRL_EXT, ctrl_ext);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4700
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4701
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4702
		ew32(WUC, E1000_WUC_PME_EN);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4703
		ew32(WUFC, wufc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4704
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4705
		ew32(WUC, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4706
		ew32(WUFC, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4707
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4708
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4709
	e1000_release_manageability(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4710
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4711
	*enable_wake = !!wufc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4712
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4713
	/* make sure adapter isn't asleep if manageability is enabled */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4714
	if (adapter->en_mng_pt)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4715
		*enable_wake = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4716
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4717
	if (netif_running(netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4718
		e1000_free_irq(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4719
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4720
	pci_disable_device(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4721
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4722
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4723
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4724
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4725
#ifdef CONFIG_PM
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4726
static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4727
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4728
	int retval;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4729
	bool wake;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4730
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4731
	retval = __e1000_shutdown(pdev, &wake);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4732
	if (retval)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4733
		return retval;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4734
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4735
	if (wake) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4736
		pci_prepare_to_sleep(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4737
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4738
		pci_wake_from_d3(pdev, false);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4739
		pci_set_power_state(pdev, PCI_D3hot);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4740
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4741
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4742
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4743
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4744
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4745
static int e1000_resume(struct pci_dev *pdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4746
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4747
	struct net_device *netdev = pci_get_drvdata(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4748
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4749
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4750
	u32 err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4751
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4752
	pci_set_power_state(pdev, PCI_D0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4753
	pci_restore_state(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4754
	pci_save_state(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4755
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4756
	if (adapter->need_ioport)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4757
		err = pci_enable_device(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4758
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4759
		err = pci_enable_device_mem(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4760
	if (err) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4761
		pr_err("Cannot enable PCI device from suspend\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4762
		return err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4763
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4764
	pci_set_master(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4765
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4766
	pci_enable_wake(pdev, PCI_D3hot, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4767
	pci_enable_wake(pdev, PCI_D3cold, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4768
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4769
	if (netif_running(netdev)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4770
		err = e1000_request_irq(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4771
		if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4772
			return err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4773
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4774
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4775
	e1000_power_up_phy(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4776
	e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4777
	ew32(WUS, ~0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4778
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4779
	e1000_init_manageability(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4780
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4781
	if (netif_running(netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4782
		e1000_up(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4783
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4784
	netif_device_attach(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4785
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4786
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4787
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4788
#endif
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4789
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4790
static void e1000_shutdown(struct pci_dev *pdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4791
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4792
	bool wake;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4793
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4794
	__e1000_shutdown(pdev, &wake);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4795
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4796
	if (system_state == SYSTEM_POWER_OFF) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4797
		pci_wake_from_d3(pdev, wake);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4798
		pci_set_power_state(pdev, PCI_D3hot);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4799
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4800
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4801
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4802
#ifdef CONFIG_NET_POLL_CONTROLLER
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4803
/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4804
 * Polling 'interrupt' - used by things like netconsole to send skbs
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4805
 * without having to re-enable interrupts. It's not called while
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4806
 * the interrupt routine is executing.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4807
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4808
static void e1000_netpoll(struct net_device *netdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4809
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4810
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4811
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4812
	disable_irq(adapter->pdev->irq);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4813
	e1000_intr(adapter->pdev->irq, netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4814
	enable_irq(adapter->pdev->irq);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4815
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4816
#endif
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4817
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4818
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4819
 * e1000_io_error_detected - called when PCI error is detected
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4820
 * @pdev: Pointer to PCI device
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4821
 * @state: The current pci connection state
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4822
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4823
 * This function is called after a PCI bus error affecting
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4824
 * this device has been detected.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4825
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4826
static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4827
						pci_channel_state_t state)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4828
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4829
	struct net_device *netdev = pci_get_drvdata(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4830
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4831
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4832
	netif_device_detach(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4833
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4834
	if (state == pci_channel_io_perm_failure)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4835
		return PCI_ERS_RESULT_DISCONNECT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4836
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4837
	if (netif_running(netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4838
		e1000_down(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4839
	pci_disable_device(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4840
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4841
	/* Request a slot slot reset. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4842
	return PCI_ERS_RESULT_NEED_RESET;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4843
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4844
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4845
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4846
 * e1000_io_slot_reset - called after the pci bus has been reset.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4847
 * @pdev: Pointer to PCI device
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4848
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4849
 * Restart the card from scratch, as if from a cold-boot. Implementation
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4850
 * resembles the first-half of the e1000_resume routine.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4851
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4852
static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4853
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4854
	struct net_device *netdev = pci_get_drvdata(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4855
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4856
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4857
	int err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4858
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4859
	if (adapter->need_ioport)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4860
		err = pci_enable_device(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4861
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4862
		err = pci_enable_device_mem(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4863
	if (err) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4864
		pr_err("Cannot re-enable PCI device after reset.\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4865
		return PCI_ERS_RESULT_DISCONNECT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4866
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4867
	pci_set_master(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4868
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4869
	pci_enable_wake(pdev, PCI_D3hot, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4870
	pci_enable_wake(pdev, PCI_D3cold, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4871
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4872
	e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4873
	ew32(WUS, ~0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4874
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4875
	return PCI_ERS_RESULT_RECOVERED;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4876
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4877
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4878
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4879
 * e1000_io_resume - called when traffic can start flowing again.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4880
 * @pdev: Pointer to PCI device
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4881
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4882
 * This callback is called when the error recovery driver tells us that
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4883
 * its OK to resume normal operation. Implementation resembles the
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4884
 * second-half of the e1000_resume routine.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4885
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4886
static void e1000_io_resume(struct pci_dev *pdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4887
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4888
	struct net_device *netdev = pci_get_drvdata(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4889
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4890
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4891
	e1000_init_manageability(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4892
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4893
	if (netif_running(netdev)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4894
		if (e1000_up(adapter)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4895
			pr_info("can't bring device back up after reset\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4896
			return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4897
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4898
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4899
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4900
	netif_device_attach(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4901
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4902
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4903
/* e1000_main.c */