devices/e1000/e1000_main-3.0-ethercat.c
author Knud Baastrup <kba@deif.com>
Tue, 14 Apr 2015 13:12:24 -0400
changeset 2629 a2701af27fde
parent 2589 2b9c78543663
permissions -rw-r--r--
Internal SDO requests now synchronized with external requests.
Internal SDO requests are managed by master FSM and can conflict with
external requests managed by slave FSM. The internal SDO requests
includes SDO requests created by an application and external request are
typical created by EtherCAT Tool for SDO upload/download or a directory
fetch initiated with ethercat sdos command. The conflict will cause a
FPWR from an external request to be overwritten by a FPWR from an
internal SDO request (or oppersite) in the same "train" of datagrams.
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
  vim: noexpandtab
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
*******************************************************************************/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    30
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    31
#include "e1000-3.0-ethercat.h"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    32
#include <net/ip6_checksum.h>
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    33
#include <linux/io.h>
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    34
#include <linux/prefetch.h>
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    35
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    36
/* 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
    37
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
    38
/* 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
    39
void __iomem *ce4100_gbe_mdio_base_virt;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    40
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    41
char e1000_driver_name[] = "ec_e1000";
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    42
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
    43
#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
    44
const char e1000_driver_version[] = DRV_VERSION;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    45
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
    46
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    47
/* e1000_pci_tbl - PCI Device ID Table
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
 * Last entry must be all 0s
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    50
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    51
 * Macro expands to...
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    52
 *   {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
    53
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    54
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
    55
	INTEL_E1000_ETHERNET_DEVICE(0x1000),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    56
	INTEL_E1000_ETHERNET_DEVICE(0x1001),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    57
	INTEL_E1000_ETHERNET_DEVICE(0x1004),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    58
	INTEL_E1000_ETHERNET_DEVICE(0x1008),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    59
	INTEL_E1000_ETHERNET_DEVICE(0x1009),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    60
	INTEL_E1000_ETHERNET_DEVICE(0x100C),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    61
	INTEL_E1000_ETHERNET_DEVICE(0x100D),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    62
	INTEL_E1000_ETHERNET_DEVICE(0x100E),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    63
	INTEL_E1000_ETHERNET_DEVICE(0x100F),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    64
	INTEL_E1000_ETHERNET_DEVICE(0x1010),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    65
	INTEL_E1000_ETHERNET_DEVICE(0x1011),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    66
	INTEL_E1000_ETHERNET_DEVICE(0x1012),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    67
	INTEL_E1000_ETHERNET_DEVICE(0x1013),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    68
	INTEL_E1000_ETHERNET_DEVICE(0x1014),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    69
	INTEL_E1000_ETHERNET_DEVICE(0x1015),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    70
	INTEL_E1000_ETHERNET_DEVICE(0x1016),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    71
	INTEL_E1000_ETHERNET_DEVICE(0x1017),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    72
	INTEL_E1000_ETHERNET_DEVICE(0x1018),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    73
	INTEL_E1000_ETHERNET_DEVICE(0x1019),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    74
	INTEL_E1000_ETHERNET_DEVICE(0x101A),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    75
	INTEL_E1000_ETHERNET_DEVICE(0x101D),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    76
	INTEL_E1000_ETHERNET_DEVICE(0x101E),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    77
	INTEL_E1000_ETHERNET_DEVICE(0x1026),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    78
	INTEL_E1000_ETHERNET_DEVICE(0x1027),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    79
	INTEL_E1000_ETHERNET_DEVICE(0x1028),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    80
	INTEL_E1000_ETHERNET_DEVICE(0x1075),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    81
	INTEL_E1000_ETHERNET_DEVICE(0x1076),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    82
	INTEL_E1000_ETHERNET_DEVICE(0x1077),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    83
	INTEL_E1000_ETHERNET_DEVICE(0x1078),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    84
	INTEL_E1000_ETHERNET_DEVICE(0x1079),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    85
	INTEL_E1000_ETHERNET_DEVICE(0x107A),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    86
	INTEL_E1000_ETHERNET_DEVICE(0x107B),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    87
	INTEL_E1000_ETHERNET_DEVICE(0x107C),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    88
	INTEL_E1000_ETHERNET_DEVICE(0x108A),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    89
	INTEL_E1000_ETHERNET_DEVICE(0x1099),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    90
	INTEL_E1000_ETHERNET_DEVICE(0x10B5),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    91
	INTEL_E1000_ETHERNET_DEVICE(0x2E6E),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    92
	/* required last entry */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    93
	{0,}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    94
};
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
// do not auto-load driver
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    97
// MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    98
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    99
int e1000_up(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   100
void e1000_down(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   101
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
   102
void e1000_reset(struct e1000_adapter *adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   103
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
   104
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
   105
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
   106
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
   107
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
   108
                             struct e1000_tx_ring *txdr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   109
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
   110
                             struct e1000_rx_ring *rxdr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   111
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
   112
                             struct e1000_tx_ring *tx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   113
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
   114
                             struct e1000_rx_ring *rx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   115
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
   116
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   117
static int e1000_init_module(void);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   118
static void e1000_exit_module(void);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   119
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
   120
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
   121
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
   122
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
   123
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
   124
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
   125
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
   126
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
   127
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
   128
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
   129
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
   130
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
   131
                                struct e1000_tx_ring *tx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   132
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
   133
                                struct e1000_rx_ring *rx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   134
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
   135
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
   136
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
   137
static void e1000_watchdog(unsigned long data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   138
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
   139
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
   140
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
   141
				    struct net_device *netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   142
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
   143
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
   144
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
   145
void ec_poll(struct net_device *);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   146
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
   147
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
   148
			       struct e1000_tx_ring *tx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   149
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
   150
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
   151
			       struct e1000_rx_ring *rx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   152
			       int *work_done, int work_to_do);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   153
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
   154
				     struct e1000_rx_ring *rx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   155
				     int *work_done, int work_to_do);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   156
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
   157
				   struct e1000_rx_ring *rx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   158
				   int cleaned_count);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   159
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
   160
					 struct e1000_rx_ring *rx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   161
					 int cleaned_count);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   162
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
   163
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
   164
			   int cmd);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   165
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
   166
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
   167
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
   168
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
   169
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
   170
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
   171
                                       struct sk_buff *skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   172
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   173
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
   174
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
   175
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
   176
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
   177
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   178
#ifdef CONFIG_PM
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   179
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
   180
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
   181
#endif
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   182
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
   183
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   184
#ifdef CONFIG_NET_POLL_CONTROLLER
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   185
/* for netdump / net console */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   186
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
   187
#endif
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   188
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   189
#define COPYBREAK_DEFAULT 256
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   190
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
   191
module_param(copybreak, uint, 0644);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   192
MODULE_PARM_DESC(copybreak,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   193
	"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
   194
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   195
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
   196
                     pci_channel_state_t state);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   197
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
   198
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
   199
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   200
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
   201
	.error_detected = e1000_io_error_detected,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   202
	.slot_reset = e1000_io_slot_reset,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   203
	.resume = e1000_io_resume,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   204
};
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   205
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   206
static struct pci_driver e1000_driver = {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   207
	.name     = e1000_driver_name,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   208
	.id_table = e1000_pci_tbl,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   209
	.probe    = e1000_probe,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   210
	.remove   = __devexit_p(e1000_remove),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   211
#ifdef CONFIG_PM
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   212
	/* Power Management Hooks */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   213
	.suspend  = e1000_suspend,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   214
	.resume   = e1000_resume,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   215
#endif
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   216
	.shutdown = e1000_shutdown,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   217
	.err_handler = &e1000_err_handler
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   218
};
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   219
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   220
MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   221
MODULE_DESCRIPTION("EtherCAT-capable Intel(R) PRO/1000 Network Driver");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   222
MODULE_LICENSE("GPL");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   223
MODULE_VERSION(DRV_VERSION);
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
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
   226
module_param(debug, int, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   227
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
   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
 * e1000_get_hw_dev - return device
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   231
 * 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
   232
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   233
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   234
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
   235
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   236
	struct e1000_adapter *adapter = hw->back;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   237
	return adapter->netdev;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   240
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   241
 * e1000_init_module - Driver Registration Routine
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
 * 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
   244
 * 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
   245
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   246
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   247
static int __init e1000_init_module(void)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   248
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   249
	int ret;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   250
	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
   251
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   252
	pr_info("%s\n", e1000_copyright);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   253
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   254
	ret = pci_register_driver(&e1000_driver);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   255
	if (copybreak != COPYBREAK_DEFAULT) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   256
		if (copybreak == 0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   257
			pr_info("copybreak disabled\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   258
		else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   259
			pr_info("copybreak enabled for "
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   260
				   "packets <= %u bytes\n", copybreak);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   261
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   262
	return ret;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   265
module_init(e1000_init_module);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   266
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   267
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   268
 * e1000_exit_module - Driver Exit Cleanup Routine
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
 * 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
   271
 * from memory.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   272
 **/
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
static void __exit e1000_exit_module(void)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   275
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   276
	pci_unregister_driver(&e1000_driver);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   277
}
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
module_exit(e1000_exit_module);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   280
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   281
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
   282
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   283
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   284
	irq_handler_t handler = e1000_intr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   285
	int irq_flags = IRQF_SHARED;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   286
	int err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   287
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   288
	if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   289
		return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   290
	}
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
	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
   293
	                  netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   294
	if (err) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   295
		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
   296
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   297
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   298
	return err;
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
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
   302
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   303
	struct net_device *netdev = adapter->netdev;
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
	if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   306
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   307
	}
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
	free_irq(adapter->pdev->irq, netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   310
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   311
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
 * 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
   314
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   315
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   316
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   317
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
   318
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   319
	struct e1000_hw *hw = &adapter->hw;
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
	if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   322
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   323
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   324
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   325
	ew32(IMC, ~0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   326
	E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   327
	synchronize_irq(adapter->pdev->irq);
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   330
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   331
 * 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
   332
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   333
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   334
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   335
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
   336
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   337
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   338
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   339
	if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   340
		return;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   343
	ew32(IMS, IMS_ENABLE_MASK);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   344
	E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   345
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   346
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   347
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
   348
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   349
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   350
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   351
	u16 vid = hw->mng_cookie.vlan_id;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   352
	u16 old_vid = adapter->mng_vlan_id;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   353
	if (adapter->vlgrp) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   354
		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
   355
			if (hw->mng_cookie.status &
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   356
				E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   357
				e1000_vlan_rx_add_vid(netdev, vid);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   358
				adapter->mng_vlan_id = vid;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   359
			} else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   360
				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
   361
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   362
			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
   363
					(vid != old_vid) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   364
			    !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
   365
				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
   366
		} else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   367
			adapter->mng_vlan_id = vid;
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
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   370
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   371
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
   372
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   373
	struct e1000_hw *hw = &adapter->hw;
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
	if (adapter->en_mng_pt) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   376
		u32 manc = er32(MANC);
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
		/* disable hardware interception of ARP */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   379
		manc &= ~(E1000_MANC_ARP_EN);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   380
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   381
		ew32(MANC, manc);
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
}
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
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
   386
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   387
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   388
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   389
	if (adapter->en_mng_pt) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   390
		u32 manc = er32(MANC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   391
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   392
		/* re-enable hardware interception of ARP */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   393
		manc |= E1000_MANC_ARP_EN;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   394
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   395
		ew32(MANC, manc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   396
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   397
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   398
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   399
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   400
 * 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
   401
 * @adapter = private board structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   402
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   403
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
   404
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   405
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   406
	int i;
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
	e1000_set_rx_mode(netdev);
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
	e1000_restore_vlan(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   411
	e1000_init_manageability(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
	e1000_configure_tx(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   414
	e1000_setup_rctl(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   415
	e1000_configure_rx(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   416
	/* call E1000_DESC_UNUSED which always leaves
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   417
	 * 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
   418
	 * next_to_use != next_to_clean */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   419
	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
   420
		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
   421
		if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   422
			/* fill rx ring completely! */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   423
			adapter->alloc_rx_buf(adapter, ring, ring->count);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   424
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   425
			/* this one leaves the last ring element unallocated! */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   426
			adapter->alloc_rx_buf(adapter, ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   427
					E1000_DESC_UNUSED(ring));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   428
		}
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
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   431
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   432
int e1000_up(struct e1000_adapter *adapter)
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
	struct e1000_hw *hw = &adapter->hw;
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
	/* 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
   437
	e1000_configure(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   438
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   439
	clear_bit(__E1000_DOWN, &adapter->flags);
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
	if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   442
		napi_enable(&adapter->napi);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   443
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   444
		e1000_irq_enable(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   445
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   446
		netif_wake_queue(adapter->netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   447
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   448
		/* 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
   449
		ew32(ICS, E1000_ICS_LSC);
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
	return 0;
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
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
 * 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
   456
 * @adapter: address of board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   457
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   458
 * 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
   459
 * 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
   460
 * *** 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
   461
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   462
 **/
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
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
   465
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   466
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   467
	u16 mii_reg = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   468
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   469
	/* 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
   470
	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
   471
		/* 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
   472
		 * settings across a power-down/up cycle */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   473
		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
   474
		mii_reg &= ~MII_CR_POWER_DOWN;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   475
		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
   476
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   477
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   478
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   479
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
   480
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   481
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   482
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   483
	/* 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
   484
	 * 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
   485
	 * (a) WoL is enabled
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   486
	 * (b) AMT is active
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   487
	 * (c) SoL/IDER session is active */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   488
	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
   489
	   hw->media_type == e1000_media_type_copper) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   490
		u16 mii_reg = 0;
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
		switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   493
		case e1000_82540:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   494
		case e1000_82545:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   495
		case e1000_82545_rev_3:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   496
		case e1000_82546:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   497
		case e1000_ce4100:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   498
		case e1000_82546_rev_3:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   499
		case e1000_82541:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   500
		case e1000_82541_rev_2:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   501
		case e1000_82547:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   502
		case e1000_82547_rev_2:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   503
			if (er32(MANC) & E1000_MANC_SMBUS_EN)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   504
				goto out;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   505
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   506
		default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   507
			goto out;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   508
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   509
		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
   510
		mii_reg |= MII_CR_POWER_DOWN;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   511
		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
   512
		mdelay(1);
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
out:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   515
	return;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   518
void e1000_down(struct e1000_adapter *adapter)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   519
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   520
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   521
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   522
	u32 rctl, tctl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   523
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   524
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   525
	/* disable receives in the hardware */	
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   526
	rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   527
	ew32(RCTL, rctl & ~E1000_RCTL_EN);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   528
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   529
	if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   530
		/* flush and sleep below */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   531
		netif_tx_disable(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   532
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   533
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   534
	/* disable transmits in the hardware */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   535
	tctl = er32(TCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   536
	tctl &= ~E1000_TCTL_EN;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   537
	ew32(TCTL, tctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   538
	/* 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
   539
	E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   540
	msleep(10);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   541
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   542
	if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   543
		napi_disable(&adapter->napi);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   544
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   545
		e1000_irq_disable(adapter);
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
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
	 * 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
   550
	 * a screaming interrupt.  Setting DOWN also prevents
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   551
	 * timers and tasks from rescheduling.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   552
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   553
	set_bit(__E1000_DOWN, &adapter->flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   554
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   555
	if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   556
		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
   557
		del_timer_sync(&adapter->watchdog_timer);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   558
		del_timer_sync(&adapter->phy_info_timer);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   559
	}
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
	adapter->link_speed = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   562
	adapter->link_duplex = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   563
	if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   564
		netif_carrier_off(netdev);
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   567
	e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   568
	e1000_clean_all_tx_rings(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   569
	e1000_clean_all_rx_rings(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   570
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   571
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   572
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
   573
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   574
	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
   575
		msleep(1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   576
	rtnl_lock();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   577
	e1000_down(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   578
	e1000_up(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   579
	rtnl_unlock();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   580
	clear_bit(__E1000_RESETTING, &adapter->flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   581
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   582
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   583
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
   584
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   585
	/* 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
   586
	ASSERT_RTNL();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   587
	WARN_ON(in_interrupt());
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   588
	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
   589
		msleep(1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   590
	e1000_down(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   591
	e1000_up(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   592
	clear_bit(__E1000_RESETTING, &adapter->flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   593
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   594
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   595
void e1000_reset(struct e1000_adapter *adapter)
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
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   598
	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
   599
	bool legacy_pba_adjust = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   600
	u16 hwm;
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
	/* Repartition Pba for greater than 9k mtu
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   603
	 * To take effect CTRL.RST is required.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   604
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   605
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   606
	switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   607
	case e1000_82542_rev2_0:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   608
	case e1000_82542_rev2_1:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   609
	case e1000_82543:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   610
	case e1000_82544:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   611
	case e1000_82540:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   612
	case e1000_82541:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   613
	case e1000_82541_rev_2:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   614
		legacy_pba_adjust = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   615
		pba = E1000_PBA_48K;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   616
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   617
	case e1000_82545:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   618
	case e1000_82545_rev_3:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   619
	case e1000_82546:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   620
	case e1000_ce4100:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   621
	case e1000_82546_rev_3:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   622
		pba = E1000_PBA_48K;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   623
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   624
	case e1000_82547:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   625
	case e1000_82547_rev_2:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   626
		legacy_pba_adjust = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   627
		pba = E1000_PBA_30K;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   628
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   629
	case e1000_undefined:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   630
	case e1000_num_macs:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   631
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   632
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   633
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   634
	if (legacy_pba_adjust) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   635
		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
   636
			pba -= 8; /* allocate more FIFO for Tx */
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 (hw->mac_type == e1000_82547) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   639
			adapter->tx_fifo_head = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   640
			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
   641
			adapter->tx_fifo_size =
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   642
				(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
   643
			atomic_set(&adapter->tx_fifo_stall, 0);
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
	} 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
   646
		/* adjust PBA for jumbo frames */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   647
		ew32(PBA, pba);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   648
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   649
		/* 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
   650
		 * 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
   651
		 * 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
   652
		 * 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
   653
		 * 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
   654
		 * expressed in KB. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   655
		pba = er32(PBA);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   656
		/* 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
   657
		tx_space = pba >> 16;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   658
		/* 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
   659
		pba &= 0xffff;
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
		 * 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
   662
		 * 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
   663
		 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   664
		min_tx_space = (hw->max_frame_size +
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   665
		                sizeof(struct e1000_tx_desc) -
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   666
		                ETH_FCS_LEN) * 2;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   667
		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
   668
		min_tx_space >>= 10;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   669
		/* 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
   670
		min_rx_space = hw->max_frame_size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   671
		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
   672
		min_rx_space >>= 10;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   673
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   674
		/* 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
   675
		 * 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
   676
		 * 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
   677
		if (tx_space < min_tx_space &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   678
		    ((min_tx_space - tx_space) < pba)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   679
			pba = pba - (min_tx_space - tx_space);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   680
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   681
			/* PCI/PCIx hardware has PBA alignment constraints */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   682
			switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   683
			case e1000_82545 ... e1000_82546_rev_3:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   684
				pba &= ~(E1000_PBA_8K - 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   685
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   686
			default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   687
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   688
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   689
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   690
			/* 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
   691
			 * adjustment or use Early Receive if available */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   692
			if (pba < min_rx_space)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   693
				pba = min_rx_space;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   694
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   695
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   696
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   697
	ew32(PBA, pba);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   698
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   699
	/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   700
	 * flow control settings:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   701
	 * 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
   702
	 * (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
   703
	 * Set it to the lower of:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   704
	 * - 90% of the Rx FIFO size, and
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   705
	 * - 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
   706
	 *   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
   707
	 * - 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
   708
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   709
	hwm = min(((pba << 10) * 9 / 10),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   710
		  ((pba << 10) - hw->max_frame_size));
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
	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
   713
	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
   714
	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
   715
	hw->fc_send_xon = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   716
	hw->fc = hw->original_fc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   717
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   718
	/* 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
   719
	e1000_reset_hw(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   720
	if (hw->mac_type >= e1000_82544)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   721
		ew32(WUC, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   722
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   723
	if (e1000_init_hw(hw))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   724
		e_dev_err("Hardware Error\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   725
	e1000_update_mng_vlan(adapter);
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
	/* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   728
	if (hw->mac_type >= e1000_82544 &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   729
	    hw->autoneg == 1 &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   730
	    hw->autoneg_advertised == ADVERTISE_1000_FULL) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   731
		u32 ctrl = er32(CTRL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   732
		/* 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
   733
		 * 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
   734
		 * 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
   735
		ctrl &= ~E1000_CTRL_SWDPIN3;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   736
		ew32(CTRL, ctrl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   737
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   738
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   739
	/* 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
   740
	ew32(VET, ETHERNET_IEEE_VLAN_TYPE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   741
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   742
	e1000_reset_adaptive(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   743
	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
   744
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   745
	e1000_release_manageability(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   746
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   747
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
 *  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
   750
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   751
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
   752
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   753
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   754
	struct ethtool_eeprom eeprom;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   755
	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
   756
	u8 *data;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   757
	int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   758
	u16 csum_old, csum_new = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   759
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   760
	eeprom.len = ops->get_eeprom_len(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   761
	eeprom.offset = 0;
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
	data = kmalloc(eeprom.len, GFP_KERNEL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   764
	if (!data) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   765
		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
   766
		return;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   769
	ops->get_eeprom(netdev, &eeprom, data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   770
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   771
	csum_old = (data[EEPROM_CHECKSUM_REG * 2]) +
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   772
		   (data[EEPROM_CHECKSUM_REG * 2 + 1] << 8);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   773
	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
   774
		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
   775
	csum_new = EEPROM_SUM - csum_new;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   776
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   777
	pr_err("/*********************/\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   778
	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
   779
	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
   780
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   781
	pr_err("Offset    Values\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   782
	pr_err("========  ======\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   783
	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
   784
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   785
	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
   786
	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
   787
	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
   788
	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
   789
	pr_err("corruption or system hangs!\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   790
	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
   791
	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
   792
	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
   793
	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
   794
	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
   795
	pr_err("/*********************/\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   796
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   797
	kfree(data);
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
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   801
 * 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
   802
 * @pdev: PCI device information struct
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   803
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   804
 * 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
   805
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   806
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
   807
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   808
	switch (pdev->device) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   809
	case E1000_DEV_ID_82540EM:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   810
	case E1000_DEV_ID_82540EM_LOM:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   811
	case E1000_DEV_ID_82540EP:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   812
	case E1000_DEV_ID_82540EP_LOM:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   813
	case E1000_DEV_ID_82540EP_LP:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   814
	case E1000_DEV_ID_82541EI:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   815
	case E1000_DEV_ID_82541EI_MOBILE:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   816
	case E1000_DEV_ID_82541ER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   817
	case E1000_DEV_ID_82541ER_LOM:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   818
	case E1000_DEV_ID_82541GI:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   819
	case E1000_DEV_ID_82541GI_LF:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   820
	case E1000_DEV_ID_82541GI_MOBILE:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   821
	case E1000_DEV_ID_82544EI_COPPER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   822
	case E1000_DEV_ID_82544EI_FIBER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   823
	case E1000_DEV_ID_82544GC_COPPER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   824
	case E1000_DEV_ID_82544GC_LOM:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   825
	case E1000_DEV_ID_82545EM_COPPER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   826
	case E1000_DEV_ID_82545EM_FIBER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   827
	case E1000_DEV_ID_82546EB_COPPER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   828
	case E1000_DEV_ID_82546EB_FIBER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   829
	case E1000_DEV_ID_82546EB_QUAD_COPPER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   830
		return true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   831
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   832
		return false;
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
}
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
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
   837
	.ndo_open		= e1000_open,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   838
	.ndo_stop		= e1000_close,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   839
	.ndo_start_xmit		= e1000_xmit_frame,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   840
	.ndo_get_stats		= e1000_get_stats,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   841
	.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
   842
	.ndo_set_mac_address	= e1000_set_mac,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   843
	.ndo_tx_timeout 	= e1000_tx_timeout,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   844
	.ndo_change_mtu		= e1000_change_mtu,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   845
	.ndo_do_ioctl		= e1000_ioctl,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   846
	.ndo_validate_addr	= eth_validate_addr,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   847
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   848
	.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
   849
	.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
   850
	.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
   851
#ifdef CONFIG_NET_POLL_CONTROLLER
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   852
	.ndo_poll_controller	= e1000_netpoll,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   853
#endif
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   856
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   857
 * 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
   858
 * @adapter: board private struct
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   859
 * @hw: structure used by e1000_hw.c
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   860
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   861
 * 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
   862
 * 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
   863
 * 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
   864
 * OS network device settings (MTU size).
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   865
 * 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
   866
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   867
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
   868
				struct e1000_hw *hw)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   869
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   870
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   871
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   872
	/* PCI config space info */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   873
	hw->vendor_id = pdev->vendor;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   874
	hw->device_id = pdev->device;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   875
	hw->subsystem_vendor_id = pdev->subsystem_vendor;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   876
	hw->subsystem_id = pdev->subsystem_device;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   877
	hw->revision_id = pdev->revision;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   878
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   879
	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
   880
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   881
	hw->max_frame_size = adapter->netdev->mtu +
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   882
			     ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   883
	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
   884
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   885
	/* identify the MAC */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   886
	if (e1000_set_mac_type(hw)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   887
		e_err(probe, "Unknown MAC Type\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   888
		return -EIO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   889
	}
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
	switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   892
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   893
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   894
	case e1000_82541:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   895
	case e1000_82547:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   896
	case e1000_82541_rev_2:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   897
	case e1000_82547_rev_2:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   898
		hw->phy_init_script = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   899
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   900
	}
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
	e1000_set_media_type(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   903
	e1000_get_bus_info(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   904
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   905
	hw->wait_autoneg_complete = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   906
	hw->tbi_compatibility_en = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   907
	hw->adaptive_ifs = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   908
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   909
	/* Copper options */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   910
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   911
	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
   912
		hw->mdix = AUTO_ALL_MODES;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   913
		hw->disable_polarity_correction = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   914
		hw->master_slave = E1000_MASTER_SLAVE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   915
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   916
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   917
	return 0;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   920
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   921
 * e1000_probe - Device Initialization Routine
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   922
 * @pdev: PCI device information struct
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   923
 * @ent: entry in e1000_pci_tbl
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   924
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   925
 * Returns 0 on success, negative on failure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   926
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   927
 * 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
   928
 * 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
   929
 * and a hardware reset occur.
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
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
   932
				 const struct pci_device_id *ent)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   933
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   934
	struct net_device *netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   935
	struct e1000_adapter *adapter;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   936
	struct e1000_hw *hw;
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
	static int cards_found = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   939
	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
   940
	int i, err, pci_using_dac;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   941
	u16 eeprom_data = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   942
	u16 tmp = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   943
	u16 eeprom_apme_mask = E1000_EEPROM_APME;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   944
	int bars, 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
	/* 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
   947
	need_ioport = e1000_is_need_ioport(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   948
	if (need_ioport) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   949
		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
   950
		err = pci_enable_device(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   951
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   952
		bars = pci_select_bars(pdev, IORESOURCE_MEM);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   953
		err = pci_enable_device_mem(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   954
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   955
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   956
		return err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   957
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   958
	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
   959
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   960
		goto err_pci_reg;
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
	pci_set_master(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   963
	err = pci_save_state(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   964
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   965
		goto err_alloc_etherdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   966
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   967
	err = -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   968
	netdev = alloc_etherdev(sizeof(struct e1000_adapter));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   969
	if (!netdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   970
		goto err_alloc_etherdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   971
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   972
	SET_NETDEV_DEV(netdev, &pdev->dev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   973
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   974
	pci_set_drvdata(pdev, netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   975
	adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   976
	adapter->netdev = netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   977
	adapter->pdev = pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   978
	adapter->msg_enable = (1 << debug) - 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   979
	adapter->bars = bars;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   980
	adapter->need_ioport = need_ioport;
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
	hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   983
	hw->back = adapter;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   984
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   985
	err = -EIO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   986
	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
   987
	if (!hw->hw_addr)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   988
		goto err_ioremap;
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
	if (adapter->need_ioport) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   991
		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
   992
			if (pci_resource_len(pdev, i) == 0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   993
				continue;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   994
			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
   995
				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
   996
				break;
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
		}
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1001
	/* make ready for any if (hw->...) below */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1002
	err = e1000_init_hw_struct(adapter, hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1003
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1004
		goto err_sw_init;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1005
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1006
	/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1007
	 * 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
  1008
	 * 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
  1009
	 * 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
  1010
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1011
	pci_using_dac = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1012
	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
  1013
	    !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
  1014
		/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1015
		 * 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
  1016
		 * succeed if the set call did
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
		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
  1019
		pci_using_dac = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1020
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1021
		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
  1022
		if (err) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1023
			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
  1024
			goto err_dma;
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
		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
  1027
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1028
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1029
	netdev->netdev_ops = &e1000_netdev_ops;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1030
	e1000_set_ethtool_ops(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1031
	netdev->watchdog_timeo = 5 * HZ;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1032
	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
  1033
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1034
	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
  1035
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1036
	adapter->bd_number = cards_found;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1037
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1038
	/* setup the private structure */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1039
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1040
	err = e1000_sw_init(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1041
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1042
		goto err_sw_init;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1043
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1044
	err = -EIO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1045
	if (hw->mac_type == e1000_ce4100) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1046
		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
  1047
		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
  1048
		                                pci_resource_len(pdev, BAR_1));
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
		if (!ce4100_gbe_mdio_base_virt)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1051
			goto err_mdio_ioremap;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1052
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1053
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1054
	if (hw->mac_type >= e1000_82543) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1055
		netdev->features = NETIF_F_SG |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1056
				   NETIF_F_HW_CSUM |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1057
				   NETIF_F_HW_VLAN_TX |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1058
				   NETIF_F_HW_VLAN_RX |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1059
				   NETIF_F_HW_VLAN_FILTER;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1060
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1061
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1062
	if ((hw->mac_type >= e1000_82544) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1063
	   (hw->mac_type != e1000_82547))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1064
		netdev->features |= NETIF_F_TSO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1065
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1066
	if (pci_using_dac) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1067
		netdev->features |= NETIF_F_HIGHDMA;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1068
		netdev->vlan_features |= NETIF_F_HIGHDMA;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1071
	netdev->vlan_features |= NETIF_F_TSO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1072
	netdev->vlan_features |= NETIF_F_HW_CSUM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1073
	netdev->vlan_features |= NETIF_F_SG;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1074
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1075
	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
  1076
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1077
	/* initialize eeprom parameters */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1078
	if (e1000_init_eeprom_params(hw)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1079
		e_err(probe, "EEPROM initialization failed\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1080
		goto err_eeprom;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1081
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1082
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1083
	/* 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
  1084
	 * 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
  1085
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1086
	e1000_reset_hw(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1087
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1088
	/* make sure the EEPROM is good */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1089
	if (e1000_validate_eeprom_checksum(hw) < 0) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1090
		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
  1091
		e1000_dump_eeprom(adapter);
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
		 * 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
  1094
		 * 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
  1095
		 * 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
  1096
		 * 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
  1097
		 * 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
  1098
		 * `ip set address`
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
		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
  1101
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1102
		/* 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
  1103
		if (e1000_read_mac_addr(hw))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1104
			e_err(probe, "EEPROM Read Error\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1105
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1106
	/* 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
  1107
	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
  1108
	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
  1109
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1110
	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
  1111
		e_err(probe, "Invalid MAC Address\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1112
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1113
	init_timer(&adapter->tx_fifo_stall_timer);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1114
	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
  1115
	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
  1116
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1117
	init_timer(&adapter->watchdog_timer);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1118
	adapter->watchdog_timer.function = e1000_watchdog;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1119
	adapter->watchdog_timer.data = (unsigned long) adapter;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1120
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1121
	init_timer(&adapter->phy_info_timer);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1122
	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
  1123
	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
  1124
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1125
	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
  1126
	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
  1127
	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
  1128
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1129
	e1000_check_options(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1130
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1131
	/* Initial Wake on LAN setting
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1132
	 * 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
  1133
	 * enable the ACPI Magic Packet filter
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1134
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1135
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1136
	switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1137
	case e1000_82542_rev2_0:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1138
	case e1000_82542_rev2_1:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1139
	case e1000_82543:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1140
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1141
	case e1000_82544:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1142
		e1000_read_eeprom(hw,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1143
			EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1144
		eeprom_apme_mask = E1000_EEPROM_82544_APM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1145
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1146
	case e1000_82546:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1147
	case e1000_82546_rev_3:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1148
		if (er32(STATUS) & E1000_STATUS_FUNC_1){
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1149
			e1000_read_eeprom(hw,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1150
				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
  1151
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1152
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1153
		/* Fall Through */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1154
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1155
		e1000_read_eeprom(hw,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1156
			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
  1157
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1158
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1159
	if (eeprom_data & eeprom_apme_mask)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1160
		adapter->eeprom_wol |= E1000_WUFC_MAG;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1161
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1162
	/* 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
  1163
	 * 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
  1164
	 * wake on lan on a particular port */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1165
	switch (pdev->device) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1166
	case E1000_DEV_ID_82546GB_PCIE:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1167
		adapter->eeprom_wol = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1168
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1169
	case E1000_DEV_ID_82546EB_FIBER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1170
	case E1000_DEV_ID_82546GB_FIBER:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1171
		/* 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
  1172
		 * regardless of eeprom setting */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1173
		if (er32(STATUS) & E1000_STATUS_FUNC_1)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1174
			adapter->eeprom_wol = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1175
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1176
	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
  1177
		/* 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
  1178
		if (global_quad_port_a != 0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1179
			adapter->eeprom_wol = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1180
		else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1181
			adapter->quad_port_a = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1182
		/* Reset for multiple quad port adapters */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1183
		if (++global_quad_port_a == 4)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1184
			global_quad_port_a = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1185
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1186
	}
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
	/* 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
  1189
	adapter->wol = adapter->eeprom_wol;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1190
	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
  1191
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1192
	/* Auto detect PHY address */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1193
	if (hw->mac_type == e1000_ce4100) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1194
		for (i = 0; i < 32; i++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1195
			hw->phy_addr = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1196
			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
  1197
			if (tmp == 0 || tmp == 0xFF) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1198
				if (i == 31)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1199
					goto err_eeprom;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1200
				continue;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1201
			} else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1202
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1203
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1204
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1205
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1206
	/* reset the hardware with the new settings */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1207
	e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1208
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1209
 	// offer device to EtherCAT master module
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1210
	adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1211
	if (adapter->ecdev) {
2589
2b9c78543663 Reverted default branch to stable-1.5.
Florian Pose <fp@igh-essen.com>
parents: 2395
diff changeset
  1212
		err = ecdev_open(adapter->ecdev);
2b9c78543663 Reverted default branch to stable-1.5.
Florian Pose <fp@igh-essen.com>
parents: 2395
diff changeset
  1213
		if (err) {
2395
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1214
			ecdev_withdraw(adapter->ecdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1215
			goto err_register;
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
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1218
		strcpy(netdev->name, "eth%d");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1219
		err = register_netdev(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1220
		if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1221
			goto err_register;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1222
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1223
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1224
	/* print bus type/speed/width info */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1225
	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
  1226
	       ((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
  1227
	       ((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
  1228
		(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
  1229
		(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
  1230
		(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
  1231
	       ((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
  1232
	       netdev->dev_addr);
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
	if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1235
		/* 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
  1236
		netif_carrier_off(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1237
	}
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
	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
  1240
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1241
	cards_found++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1242
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1243
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1244
err_register:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1245
err_eeprom:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1246
	e1000_phy_hw_reset(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1247
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1248
	if (hw->flash_address)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1249
		iounmap(hw->flash_address);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1250
	kfree(adapter->tx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1251
	kfree(adapter->rx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1252
err_dma:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1253
err_sw_init:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1254
err_mdio_ioremap:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1255
	iounmap(ce4100_gbe_mdio_base_virt);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1256
	iounmap(hw->hw_addr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1257
err_ioremap:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1258
	free_netdev(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1259
err_alloc_etherdev:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1260
	pci_release_selected_regions(pdev, bars);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1261
err_pci_reg:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1262
	pci_disable_device(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1263
	return err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1264
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1265
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
 * e1000_remove - Device Removal Routine
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1268
 * @pdev: PCI device information struct
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
 * 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
  1271
 * 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
  1272
 * 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
  1273
 * memory.
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1276
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
  1277
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1278
	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
  1279
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1280
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1281
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1282
	set_bit(__E1000_DOWN, &adapter->flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1283
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1284
	if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1285
		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
  1286
		del_timer_sync(&adapter->watchdog_timer);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1287
		del_timer_sync(&adapter->phy_info_timer);
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
	cancel_work_sync(&adapter->reset_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1291
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1292
	e1000_release_manageability(adapter);
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
	if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1295
		ecdev_close(adapter->ecdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1296
		ecdev_withdraw(adapter->ecdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1297
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1298
		unregister_netdev(netdev);
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1301
	e1000_phy_hw_reset(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1302
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1303
	kfree(adapter->tx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1304
	kfree(adapter->rx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1305
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1306
	iounmap(hw->hw_addr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1307
	if (hw->flash_address)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1308
		iounmap(hw->flash_address);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1309
	pci_release_selected_regions(pdev, adapter->bars);
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
	free_netdev(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1312
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1313
	pci_disable_device(pdev);
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
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1317
 * 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
  1318
 * @adapter: board private structure to initialize
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1319
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1320
 * 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
  1321
 * 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
  1322
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1323
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1324
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
  1325
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1326
	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
  1327
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1328
	adapter->num_tx_queues = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1329
	adapter->num_rx_queues = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1330
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1331
	if (e1000_alloc_queues(adapter)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1332
		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
  1333
		return -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1334
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1335
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1336
	/* 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
  1337
	e1000_irq_disable(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1338
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1339
	spin_lock_init(&adapter->stats_lock);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1340
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1341
	set_bit(__E1000_DOWN, &adapter->flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1342
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1343
	return 0;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1346
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1347
 * 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
  1348
 * @adapter: board private structure to initialize
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
 * 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
  1351
 * number of queues at compile-time.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1352
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1353
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1354
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
  1355
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1356
	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
  1357
	                           sizeof(struct e1000_tx_ring), GFP_KERNEL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1358
	if (!adapter->tx_ring)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1359
		return -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1360
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1361
	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
  1362
	                           sizeof(struct e1000_rx_ring), GFP_KERNEL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1363
	if (!adapter->rx_ring) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1364
		kfree(adapter->tx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1365
		return -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1366
	}
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
	return E1000_SUCCESS;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1369
}
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
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1372
 * 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
  1373
 * @netdev: network interface device structure
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
 * 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
  1376
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1377
 * 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
  1378
 * 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
  1379
 * 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
  1380
 * 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
  1381
 * 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
  1382
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1383
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1384
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
  1385
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1386
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1387
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1388
	int err;
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
	/* disallow open during test */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1391
	if (test_bit(__E1000_TESTING, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1392
		return -EBUSY;
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
	netif_carrier_off(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1395
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1396
	/* allocate transmit descriptors */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1397
	err = e1000_setup_all_tx_resources(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1398
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1399
		goto err_setup_tx;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1400
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1401
	/* allocate receive descriptors */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1402
	err = e1000_setup_all_rx_resources(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1403
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1404
		goto err_setup_rx;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1405
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1406
	e1000_power_up_phy(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1407
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1408
	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
  1409
	if ((hw->mng_cookie.status &
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1410
			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1411
		e1000_update_mng_vlan(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1412
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1413
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1414
	/* 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
  1415
	 * 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
  1416
	 * 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
  1417
	 * clean_rx handler before we do so.  */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1418
	e1000_configure(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1419
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1420
	err = e1000_request_irq(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1421
	if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1422
		goto err_req_irq;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1423
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1424
	/* 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
  1425
	clear_bit(__E1000_DOWN, &adapter->flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1426
2589
2b9c78543663 Reverted default branch to stable-1.5.
Florian Pose <fp@igh-essen.com>
parents: 2395
diff changeset
  1427
	if (!adapter->ecdev) {
2b9c78543663 Reverted default branch to stable-1.5.
Florian Pose <fp@igh-essen.com>
parents: 2395
diff changeset
  1428
		napi_enable(&adapter->napi);
2b9c78543663 Reverted default branch to stable-1.5.
Florian Pose <fp@igh-essen.com>
parents: 2395
diff changeset
  1429
2b9c78543663 Reverted default branch to stable-1.5.
Florian Pose <fp@igh-essen.com>
parents: 2395
diff changeset
  1430
		e1000_irq_enable(adapter);
2b9c78543663 Reverted default branch to stable-1.5.
Florian Pose <fp@igh-essen.com>
parents: 2395
diff changeset
  1431
2b9c78543663 Reverted default branch to stable-1.5.
Florian Pose <fp@igh-essen.com>
parents: 2395
diff changeset
  1432
		netif_start_queue(netdev);
2b9c78543663 Reverted default branch to stable-1.5.
Florian Pose <fp@igh-essen.com>
parents: 2395
diff changeset
  1433
	}
2395
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1434
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1435
	/* 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
  1436
	ew32(ICS, E1000_ICS_LSC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1437
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1438
	return E1000_SUCCESS;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1439
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1440
err_req_irq:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1441
	e1000_power_down_phy(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1442
	e1000_free_all_rx_resources(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1443
err_setup_rx:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1444
	e1000_free_all_tx_resources(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1445
err_setup_tx:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1446
	e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1447
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1448
	return err;
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
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1452
 * e1000_close - Disables a network interface
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1453
 * @netdev: network interface device structure
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
 * 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
  1456
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1457
 * 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
  1458
 * 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
  1459
 * 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
  1460
 * 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
  1461
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1462
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1463
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
  1464
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1465
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1466
	struct e1000_hw *hw = &adapter->hw;
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
	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
  1469
	e1000_down(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1470
	e1000_power_down_phy(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1471
	e1000_free_irq(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1472
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1473
	e1000_free_all_tx_resources(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1474
	e1000_free_all_rx_resources(adapter);
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
	/* 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
  1477
	 * 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
  1478
	if ((hw->mng_cookie.status &
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1479
			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1480
	     !(adapter->vlgrp &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1481
	       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
  1482
		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
  1483
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1484
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1485
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1486
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1487
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1488
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1489
 * 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
  1490
 * @adapter: address of board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1491
 * @start: address of beginning of memory
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1492
 * @len: length of memory
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1493
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1494
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
  1495
				  unsigned long len)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1496
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1497
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1498
	unsigned long begin = (unsigned long)start;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1499
	unsigned long end = begin + len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1500
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1501
	/* 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
  1502
	 * 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
  1503
	if (hw->mac_type == e1000_82545 ||
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1504
	    hw->mac_type == e1000_ce4100 ||
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1505
	    hw->mac_type == e1000_82546) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1506
		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
  1507
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1508
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1509
	return true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1510
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1511
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1512
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1513
 * 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
  1514
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1515
 * @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
  1516
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1517
 * Return 0 on success, negative on failure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1518
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1519
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1520
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
  1521
				    struct e1000_tx_ring *txdr)
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
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1524
	int size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1525
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1526
	size = sizeof(struct e1000_buffer) * txdr->count;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1527
	txdr->buffer_info = vzalloc(size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1528
	if (!txdr->buffer_info) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1529
		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
  1530
		      "ring\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1531
		return -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1532
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1533
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1534
	/* round up to nearest 4K */
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
	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
  1537
	txdr->size = ALIGN(txdr->size, 4096);
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
	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
  1540
					GFP_KERNEL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1541
	if (!txdr->desc) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1542
setup_tx_desc_die:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1543
		vfree(txdr->buffer_info);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1544
		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
  1545
		      "ring\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1546
		return -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1547
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1548
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1549
	/* 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
  1550
	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
  1551
		void *olddesc = txdr->desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1552
		dma_addr_t olddma = txdr->dma;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1553
		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
  1554
		      txdr->size, txdr->desc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1555
		/* Try again, without freeing the previous */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1556
		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
  1557
						&txdr->dma, GFP_KERNEL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1558
		/* Failed allocation, critical failure */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1559
		if (!txdr->desc) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1560
			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
  1561
					  olddma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1562
			goto setup_tx_desc_die;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1565
		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
  1566
			/* give up */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1567
			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
  1568
					  txdr->dma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1569
			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
  1570
					  olddma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1571
			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
  1572
			      "for the transmit descriptor ring\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1573
			vfree(txdr->buffer_info);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1574
			return -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1575
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1576
			/* Free old allocation, new allocation was successful */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1577
			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
  1578
					  olddma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1579
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1580
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1581
	memset(txdr->desc, 0, txdr->size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1582
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1583
	txdr->next_to_use = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1584
	txdr->next_to_clean = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1585
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1586
	return 0;
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
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1590
 * 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
  1591
 * 				  (Descriptors) for all queues
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1592
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1593
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1594
 * Return 0 on success, negative on failure
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1597
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
  1598
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1599
	int i, err = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1600
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1601
	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
  1602
		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
  1603
		if (err) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1604
			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
  1605
			for (i-- ; i >= 0; i--)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1606
				e1000_free_tx_resources(adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1607
							&adapter->tx_ring[i]);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1608
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1609
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1610
	}
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
	return err;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1615
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1616
 * 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
  1617
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1618
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1619
 * 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
  1620
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1621
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1622
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
  1623
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1624
	u64 tdba;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1625
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1626
	u32 tdlen, tctl, tipg;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1627
	u32 ipgr1, ipgr2;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1628
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1629
	/* 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
  1630
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1631
	switch (adapter->num_tx_queues) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1632
	case 1:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1633
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1634
		tdba = adapter->tx_ring[0].dma;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1635
		tdlen = adapter->tx_ring[0].count *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1636
			sizeof(struct e1000_tx_desc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1637
		ew32(TDLEN, tdlen);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1638
		ew32(TDBAH, (tdba >> 32));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1639
		ew32(TDBAL, (tdba & 0x00000000ffffffffULL));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1640
		ew32(TDT, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1641
		ew32(TDH, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1642
		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
  1643
		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
  1644
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1645
	}
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
	/* 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
  1648
	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
  1649
	     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
  1650
		tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1651
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1652
		tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
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
	switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1655
	case e1000_82542_rev2_0:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1656
	case e1000_82542_rev2_1:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1657
		tipg = DEFAULT_82542_TIPG_IPGT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1658
		ipgr1 = DEFAULT_82542_TIPG_IPGR1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1659
		ipgr2 = DEFAULT_82542_TIPG_IPGR2;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1660
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1661
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1662
		ipgr1 = DEFAULT_82543_TIPG_IPGR1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1663
		ipgr2 = DEFAULT_82543_TIPG_IPGR2;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1664
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1665
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1666
	tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1667
	tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1668
	ew32(TIPG, tipg);
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
	/* Set the Tx Interrupt Delay register */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1671
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1672
	ew32(TIDV, adapter->tx_int_delay);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1673
	if (hw->mac_type >= e1000_82540)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1674
		ew32(TADV, adapter->tx_abs_int_delay);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1675
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1676
	/* Program the Transmit Control Register */
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
	tctl = er32(TCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1679
	tctl &= ~E1000_TCTL_CT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1680
	tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1681
		(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1682
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1683
	e1000_config_collision_dist(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1684
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1685
	/* Setup Transmit Descriptor Settings for eop descriptor */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1686
	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
  1687
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1688
	/* 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
  1689
	if (adapter->tx_int_delay)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1690
		adapter->txd_cmd |= E1000_TXD_CMD_IDE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1691
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1692
	if (hw->mac_type < e1000_82543)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1693
		adapter->txd_cmd |= E1000_TXD_CMD_RPS;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1694
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1695
		adapter->txd_cmd |= E1000_TXD_CMD_RS;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1696
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1697
	/* 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
  1698
	 * 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
  1699
	if (hw->mac_type == e1000_82544 &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1700
	    hw->bus_type == e1000_bus_type_pcix)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1701
		adapter->pcix_82544 = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1702
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1703
	ew32(TCTL, tctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1704
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
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1708
 * 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
  1709
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1710
 * @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
  1711
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1712
 * Returns 0 on success, negative on failure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1713
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1714
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1715
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
  1716
				    struct e1000_rx_ring *rxdr)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1717
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1718
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1719
	int size, desc_len;
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
	size = sizeof(struct e1000_buffer) * rxdr->count;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1722
	rxdr->buffer_info = vzalloc(size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1723
	if (!rxdr->buffer_info) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1724
		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
  1725
		      "ring\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1726
		return -ENOMEM;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1729
	desc_len = sizeof(struct e1000_rx_desc);
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
	/* Round up to nearest 4K */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1732
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1733
	rxdr->size = rxdr->count * desc_len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1734
	rxdr->size = ALIGN(rxdr->size, 4096);
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
	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
  1737
					GFP_KERNEL);
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
	if (!rxdr->desc) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1740
		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
  1741
		      "ring\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1742
setup_rx_desc_die:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1743
		vfree(rxdr->buffer_info);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1744
		return -ENOMEM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1745
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1746
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1747
	/* 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
  1748
	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
  1749
		void *olddesc = rxdr->desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1750
		dma_addr_t olddma = rxdr->dma;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1751
		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
  1752
		      rxdr->size, rxdr->desc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1753
		/* Try again, without freeing the previous */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1754
		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
  1755
						&rxdr->dma, GFP_KERNEL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1756
		/* Failed allocation, critical failure */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1757
		if (!rxdr->desc) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1758
			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
  1759
					  olddma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1760
			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
  1761
			      "descriptor ring\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1762
			goto setup_rx_desc_die;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1763
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1764
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1765
		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
  1766
			/* give up */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1767
			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
  1768
					  rxdr->dma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1769
			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
  1770
					  olddma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1771
			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
  1772
			      "the Rx descriptor ring\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1773
			goto setup_rx_desc_die;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1774
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1775
			/* Free old allocation, new allocation was successful */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1776
			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
  1777
					  olddma);
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
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1780
	memset(rxdr->desc, 0, rxdr->size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1781
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1782
	rxdr->next_to_clean = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1783
	rxdr->next_to_use = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1784
	rxdr->rx_skb_top = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1785
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1786
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1787
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1788
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1789
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1790
 * 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
  1791
 * 				  (Descriptors) for all queues
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1792
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1793
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1794
 * Return 0 on success, negative on failure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1795
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1796
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1797
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
  1798
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1799
	int i, err = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1800
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1801
	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
  1802
		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
  1803
		if (err) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1804
			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
  1805
			for (i-- ; i >= 0; i--)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1806
				e1000_free_rx_resources(adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1807
							&adapter->rx_ring[i]);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1808
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1809
		}
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1812
	return err;
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
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
 * 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
  1817
 * @adapter: Board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1818
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1819
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
  1820
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1821
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1822
	u32 rctl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1823
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1824
	rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1825
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1826
	rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1827
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1828
	rctl |= E1000_RCTL_EN | E1000_RCTL_BAM |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1829
		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
  1830
		(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
  1831
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1832
	if (hw->tbi_compatibility_on == 1)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1833
		rctl |= E1000_RCTL_SBP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1834
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1835
		rctl &= ~E1000_RCTL_SBP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1836
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1837
	if (adapter->netdev->mtu <= ETH_DATA_LEN)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1838
		rctl &= ~E1000_RCTL_LPE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1839
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1840
		rctl |= E1000_RCTL_LPE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1841
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1842
	/* Setup buffer sizes */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1843
	rctl &= ~E1000_RCTL_SZ_4096;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1844
	rctl |= E1000_RCTL_BSEX;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1845
	switch (adapter->rx_buffer_len) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1846
		case E1000_RXBUFFER_2048:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1847
		default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1848
			rctl |= E1000_RCTL_SZ_2048;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1849
			rctl &= ~E1000_RCTL_BSEX;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1850
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1851
		case E1000_RXBUFFER_4096:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1852
			rctl |= E1000_RCTL_SZ_4096;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1853
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1854
		case E1000_RXBUFFER_8192:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1855
			rctl |= E1000_RCTL_SZ_8192;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1856
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1857
		case E1000_RXBUFFER_16384:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1858
			rctl |= E1000_RCTL_SZ_16384;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1859
			break;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1862
	ew32(RCTL, rctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1863
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1864
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1865
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1866
 * 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
  1867
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1868
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1869
 * 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
  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
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
  1873
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1874
	u64 rdba;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1875
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1876
	u32 rdlen, rctl, rxcsum;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1877
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1878
	if (adapter->netdev->mtu > ETH_DATA_LEN) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1879
		rdlen = adapter->rx_ring[0].count *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1880
		        sizeof(struct e1000_rx_desc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1881
		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
  1882
		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
  1883
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1884
		rdlen = adapter->rx_ring[0].count *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1885
		        sizeof(struct e1000_rx_desc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1886
		adapter->clean_rx = e1000_clean_rx_irq;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1887
		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
  1888
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1889
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1890
	/* disable receives while setting up the descriptors */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1891
	rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1892
	ew32(RCTL, rctl & ~E1000_RCTL_EN);
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
	/* set the Receive Delay Timer Register */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1895
	ew32(RDTR, adapter->rx_int_delay);
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
	if (hw->mac_type >= e1000_82540) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1898
		ew32(RADV, adapter->rx_abs_int_delay);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1899
		if (adapter->itr_setting != 0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1900
			ew32(ITR, 1000000000 / (adapter->itr * 256));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1901
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1902
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1903
	/* 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
  1904
	 * 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
  1905
	switch (adapter->num_rx_queues) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1906
	case 1:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1907
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1908
		rdba = adapter->rx_ring[0].dma;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1909
		ew32(RDLEN, rdlen);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1910
		ew32(RDBAH, (rdba >> 32));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1911
		ew32(RDBAL, (rdba & 0x00000000ffffffffULL));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1912
		ew32(RDT, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1913
		ew32(RDH, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1914
		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
  1915
		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
  1916
		break;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1919
	/* 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
  1920
	if (hw->mac_type >= e1000_82543) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1921
		rxcsum = er32(RXCSUM);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1922
		if (adapter->rx_csum)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1923
			rxcsum |= E1000_RXCSUM_TUOFL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1924
		else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1925
			/* 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
  1926
			rxcsum &= ~E1000_RXCSUM_TUOFL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1927
		ew32(RXCSUM, rxcsum);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1928
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1929
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1930
	/* Enable Receives */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1931
	ew32(RCTL, rctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1932
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1933
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
 * 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
  1936
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1937
 * @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
  1938
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1939
 * Free all transmit software resources
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_free_tx_resources(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 pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1946
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1947
	e1000_clean_tx_ring(adapter, tx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1948
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1949
	vfree(tx_ring->buffer_info);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1950
	tx_ring->buffer_info = NULL;
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
	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
  1953
			  tx_ring->dma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1954
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1955
	tx_ring->desc = NULL;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1958
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1959
 * 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
  1960
 * @adapter: board private structure
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
 * Free all transmit software resources
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1965
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
  1966
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1967
	int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1968
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1969
	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
  1970
		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
  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
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
  1974
					     struct e1000_buffer *buffer_info)
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
	if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1977
		return;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1980
	if (buffer_info->dma) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1981
		if (buffer_info->mapped_as_page)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1982
			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
  1983
				       buffer_info->length, DMA_TO_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1984
		else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1985
			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
  1986
					 buffer_info->length,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1987
					 DMA_TO_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1988
		buffer_info->dma = 0;
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
	if (buffer_info->skb) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1991
		dev_kfree_skb_any(buffer_info->skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1992
		buffer_info->skb = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1993
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1994
	buffer_info->time_stamp = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1995
	/* 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
  1996
}
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
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1999
 * e1000_clean_tx_ring - Free Tx Buffers
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2000
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2001
 * @tx_ring: ring to be cleaned
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2004
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
  2005
				struct e1000_tx_ring *tx_ring)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2006
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2007
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2008
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2009
	unsigned long size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2010
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2011
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2012
	/* Free all the Tx ring sk_buffs */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2013
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2014
	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
  2015
		buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2016
		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
  2017
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2018
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2019
	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
  2020
	memset(tx_ring->buffer_info, 0, size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2021
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2022
	/* Zero out the descriptor ring */
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
	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
  2025
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2026
	tx_ring->next_to_use = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2027
	tx_ring->next_to_clean = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2028
	tx_ring->last_tx_tso = 0;
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
	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
  2031
	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
  2032
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2033
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2034
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2035
 * 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
  2036
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2037
 **/
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
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
  2040
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2041
	int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2042
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2043
	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
  2044
		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
  2045
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2046
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2047
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2048
 * e1000_free_rx_resources - Free Rx Resources
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2049
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2050
 * @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
  2051
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2052
 * Free all receive software resources
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2055
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
  2056
				    struct e1000_rx_ring *rx_ring)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2057
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2058
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2059
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2060
	e1000_clean_rx_ring(adapter, rx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2061
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2062
	vfree(rx_ring->buffer_info);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2063
	rx_ring->buffer_info = NULL;
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
	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
  2066
			  rx_ring->dma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2067
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2068
	rx_ring->desc = 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
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2072
 * 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
  2073
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2074
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2075
 * Free all receive software resources
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2078
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
  2079
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2080
	int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2081
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2082
	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
  2083
		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
  2084
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2085
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2086
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2087
 * 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
  2088
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2089
 * @rx_ring: ring to free buffers from
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2092
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
  2093
				struct e1000_rx_ring *rx_ring)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2094
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2095
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2096
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2097
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2098
	unsigned long size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2099
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2100
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2101
	/* Free all the Rx ring sk_buffs */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2102
	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
  2103
		buffer_info = &rx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2104
		if (buffer_info->dma &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2105
		    adapter->clean_rx == e1000_clean_rx_irq) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2106
			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
  2107
			                 buffer_info->length,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2108
					 DMA_FROM_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2109
		} else if (buffer_info->dma &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2110
		           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
  2111
			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
  2112
				       buffer_info->length,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2113
				       DMA_FROM_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2114
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2115
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2116
		buffer_info->dma = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2117
		if (buffer_info->page) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2118
			put_page(buffer_info->page);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2119
			buffer_info->page = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2120
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2121
		if (buffer_info->skb) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2122
			dev_kfree_skb(buffer_info->skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2123
			buffer_info->skb = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2124
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2125
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2126
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2127
	/* 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
  2128
	if (rx_ring->rx_skb_top) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2129
		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
  2130
		rx_ring->rx_skb_top = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2131
	}
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
	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
  2134
	memset(rx_ring->buffer_info, 0, size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2135
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2136
	/* Zero out the descriptor ring */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2137
	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
  2138
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2139
	rx_ring->next_to_clean = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2140
	rx_ring->next_to_use = 0;
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
	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
  2143
	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
  2144
}
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
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2147
 * 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
  2148
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2149
 **/
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
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
  2152
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2153
	int i;
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
	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
  2156
		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
  2157
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2158
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2159
/* 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
  2160
 * 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
  2161
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2162
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
  2163
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2164
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2165
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2166
	u32 rctl;
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
	e1000_pci_clear_mwi(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2169
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2170
	rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2171
	rctl |= E1000_RCTL_RST;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2172
	ew32(RCTL, rctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2173
	E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2174
	mdelay(5);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2175
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2176
	if (!adapter->ecdev && netif_running(netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2177
		e1000_clean_all_rx_rings(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2178
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2179
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2180
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
  2181
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2182
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2183
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2184
	u32 rctl;
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
	rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2187
	rctl &= ~E1000_RCTL_RST;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2188
	ew32(RCTL, rctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2189
	E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2190
	mdelay(5);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2191
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2192
	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
  2193
		e1000_pci_set_mwi(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2194
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2195
	if (!adapter->netdev && netif_running(netdev)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2196
		/* 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
  2197
		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
  2198
		e1000_configure_rx(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2199
		if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2200
			/* fill rx ring completely! */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2201
			adapter->alloc_rx_buf(adapter, ring, ring->count);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2202
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2203
			/* this one leaves the last ring element unallocated! */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2204
			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
  2205
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2206
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2207
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2208
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2209
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2210
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2211
 * 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
  2212
 * @netdev: network interface device structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2213
 * @p: pointer to an address structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2214
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2215
 * Returns 0 on success, negative on failure
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
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
  2219
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2220
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2221
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2222
	struct sockaddr *addr = p;
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
	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
  2225
		return -EADDRNOTAVAIL;
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
	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
  2233
	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
  2234
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2235
	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
  2236
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2237
	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
  2238
		e1000_leave_82542_rst(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2239
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2240
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2241
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2242
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2243
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2244
 * 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
  2245
 * @netdev: network interface device structure
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
 * 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
  2248
 * 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
  2249
 * 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
  2250
 * promiscuous mode, and all-multi behavior.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2251
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2252
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2253
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
  2254
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2255
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2256
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2257
	struct netdev_hw_addr *ha;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2258
	bool use_uc = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2259
	u32 rctl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2260
	u32 hash_value;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2261
	int i, rar_entries = E1000_RAR_ENTRIES;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2262
	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
  2263
	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
  2264
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2265
	if (!mcarray) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2266
		e_err(probe, "memory allocation failed\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2267
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2268
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2269
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2270
	/* Check for Promiscuous and All Multicast modes */
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
	rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2273
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2274
	if (netdev->flags & IFF_PROMISC) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2275
		rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2276
		rctl &= ~E1000_RCTL_VFE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2277
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2278
		if (netdev->flags & IFF_ALLMULTI)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2279
			rctl |= E1000_RCTL_MPE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2280
		else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2281
			rctl &= ~E1000_RCTL_MPE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2282
		/* 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
  2283
		if (adapter->vlgrp)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2284
			rctl |= E1000_RCTL_VFE;
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
	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
  2288
		rctl |= E1000_RCTL_UPE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2289
	} else if (!(netdev->flags & IFF_PROMISC)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2290
		rctl &= ~E1000_RCTL_UPE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2291
		use_uc = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2292
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2293
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2294
	ew32(RCTL, rctl);
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
	/* 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
  2297
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2298
	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
  2299
		e1000_enter_82542_rst(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2300
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2301
	/* 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
  2302
	 * 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
  2303
	 * when possible.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2304
	 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2305
	 * 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
  2306
	 * 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
  2307
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2308
	i = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2309
	if (use_uc)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2310
		netdev_for_each_uc_addr(ha, netdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2311
			if (i == rar_entries)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2312
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2313
			e1000_rar_set(hw, ha->addr, i++);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2314
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2315
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2316
	netdev_for_each_mc_addr(ha, netdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2317
		if (i == rar_entries) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2318
			/* 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
  2319
			u32 hash_reg, hash_bit, mta;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2320
			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
  2321
			hash_reg = (hash_value >> 5) & 0x7F;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2322
			hash_bit = hash_value & 0x1F;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2323
			mta = (1 << hash_bit);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2324
			mcarray[hash_reg] |= mta;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2325
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2326
			e1000_rar_set(hw, ha->addr, i++);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2327
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2328
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2329
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2330
	for (; i < rar_entries; i++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2331
		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
  2332
		E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2333
		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
  2334
		E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2335
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2336
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2337
	/* 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
  2338
	 * 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
  2339
	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
  2340
		/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2341
		 * 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
  2342
		 * 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
  2343
		 * 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
  2344
		 * writing the odd offset first
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2345
		 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2346
		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
  2347
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2348
	E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2349
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2350
	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
  2351
		e1000_leave_82542_rst(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2352
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2353
	kfree(mcarray);
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2356
/* 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
  2357
 * the phy */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2358
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2359
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
  2360
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2361
	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
  2362
	schedule_work(&adapter->phy_info_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2363
}
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
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
  2366
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2367
	struct e1000_adapter *adapter = container_of(work,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2368
	                                             struct e1000_adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2369
	                                             phy_info_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2370
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2371
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2372
	rtnl_lock();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2373
	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
  2374
	rtnl_unlock();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2375
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2376
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2377
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2378
 * 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
  2379
 * @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
  2380
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2381
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
  2382
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2383
	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
  2384
	schedule_work(&adapter->fifo_stall_task);
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
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
 * 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
  2389
 * @work: work struct contained inside adapter struct
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2390
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2391
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
  2392
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2393
	struct e1000_adapter *adapter = container_of(work,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2394
	                                             struct e1000_adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2395
	                                             fifo_stall_task);
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
	u32 tctl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2399
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2400
	rtnl_lock();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2401
	if (atomic_read(&adapter->tx_fifo_stall)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2402
		if ((er32(TDT) == er32(TDH)) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2403
		   (er32(TDFT) == er32(TDFH)) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2404
		   (er32(TDFTS) == er32(TDFHS))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2405
			tctl = er32(TCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2406
			ew32(TCTL, tctl & ~E1000_TCTL_EN);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2407
			ew32(TDFT, adapter->tx_head_addr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2408
			ew32(TDFH, adapter->tx_head_addr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2409
			ew32(TDFTS, adapter->tx_head_addr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2410
			ew32(TDFHS, adapter->tx_head_addr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2411
			ew32(TCTL, tctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2412
			E1000_WRITE_FLUSH();
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
			adapter->tx_fifo_head = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2415
			atomic_set(&adapter->tx_fifo_stall, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2416
			if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2417
				netif_wake_queue(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2418
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2419
		} 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
  2420
			if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2421
				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
  2422
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2423
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2424
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2425
	rtnl_unlock();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2426
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2427
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2428
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
  2429
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2430
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2431
	bool link_active = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2432
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2433
	/* 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
  2434
	 * 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
  2435
	 * 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
  2436
	 * for copper adapters ONLY
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
	switch (hw->media_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2439
	case e1000_media_type_copper:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2440
		if (hw->get_link_status) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2441
			e1000_check_for_link(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2442
			link_active = !hw->get_link_status;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2443
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2444
			link_active = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2445
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2446
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2447
	case e1000_media_type_fiber:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2448
		e1000_check_for_link(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2449
		link_active = !!(er32(STATUS) & E1000_STATUS_LU);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2450
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2451
	case e1000_media_type_internal_serdes:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2452
		e1000_check_for_link(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2453
		link_active = hw->serdes_has_link;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2454
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2455
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2456
		break;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2459
	return link_active;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2460
}
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_watchdog - Timer Call-back
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2464
 * @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
  2465
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2466
static void e1000_watchdog(unsigned long data)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2467
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2468
	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
  2469
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2470
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2471
	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
  2472
	u32 link, tctl;
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
	link = e1000_has_link(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2475
	if (!adapter->ecdev && (netif_carrier_ok(netdev)) && link)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2476
		goto link_up;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2477
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2478
	if (link) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2479
		if ((adapter->ecdev && !ecdev_get_link(adapter->ecdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2480
				|| (!adapter->ecdev && !netif_carrier_ok(netdev))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2481
			u32 ctrl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2482
			bool txb2b __attribute__ ((unused)) = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2483
			/* update snapshot of PHY registers on LSC */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2484
			e1000_get_speed_and_duplex(hw,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2485
			                           &adapter->link_speed,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2486
			                           &adapter->link_duplex);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2487
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2488
			ctrl = er32(CTRL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2489
			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
  2490
				"Flow Control: %s\n",
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2491
				netdev->name,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2492
				adapter->link_speed,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2493
				adapter->link_duplex == FULL_DUPLEX ?
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2494
				"Full Duplex" : "Half Duplex",
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2495
				((ctrl & E1000_CTRL_TFCE) && (ctrl &
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2496
				E1000_CTRL_RFCE)) ? "RX/TX" : ((ctrl &
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2497
				E1000_CTRL_RFCE) ? "RX" : ((ctrl &
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2498
				E1000_CTRL_TFCE) ? "TX" : "None")));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2499
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2500
			/* adjust timeout factor according to speed/duplex */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2501
			adapter->tx_timeout_factor = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2502
			switch (adapter->link_speed) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2503
			case SPEED_10:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2504
				txb2b = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2505
				adapter->tx_timeout_factor = 16;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2506
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2507
			case SPEED_100:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2508
				txb2b = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2509
				/* maybe add some timeout factor ? */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2510
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2511
			}
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
			/* enable transmits in the hardware */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2514
			tctl = er32(TCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2515
			tctl |= E1000_TCTL_EN;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2516
			ew32(TCTL, tctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2517
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2518
			if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2519
				ecdev_set_link(adapter->ecdev, 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2520
			} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2521
				netif_carrier_on(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2522
				if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2523
					mod_timer(&adapter->phy_info_timer,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2524
							round_jiffies(jiffies + 2 * HZ));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2525
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2526
			adapter->smartspeed = 0;
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
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2529
		if ((adapter->ecdev && ecdev_get_link(adapter->ecdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2530
				|| (!adapter->ecdev && netif_carrier_ok(netdev))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2531
			adapter->link_speed = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2532
			adapter->link_duplex = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2533
			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
  2534
				netdev->name);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2535
			if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2536
				ecdev_set_link(adapter->ecdev, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2537
			} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2538
				netif_carrier_off(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2539
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2540
				if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2541
					mod_timer(&adapter->phy_info_timer,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2542
							round_jiffies(jiffies + 2 * HZ));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2543
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2544
		}
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
		e1000_smartspeed(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2547
	}
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
link_up:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2550
	e1000_update_stats(adapter);
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
	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
  2553
	adapter->tpt_old = adapter->stats.tpt;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2554
	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
  2555
	adapter->colc_old = adapter->stats.colc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2556
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2557
	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
  2558
	adapter->gorcl_old = adapter->stats.gorcl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2559
	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
  2560
	adapter->gotcl_old = adapter->stats.gotcl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2561
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2562
	e1000_update_adaptive(hw);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2563
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2564
	if (!adapter->ecdev && !netif_carrier_ok(netdev)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2565
		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
  2566
			/* 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
  2567
			 * 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
  2568
			 * 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
  2569
			 * (Do the reset outside of interrupt context). */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2570
			adapter->tx_timeout_count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2571
			schedule_work(&adapter->reset_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2572
			/* return immediately since reset is imminent */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2573
			return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2574
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2575
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2576
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2577
	/* Simple mode for Interrupt Throttle Rate (ITR) */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2578
	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
  2579
		/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2580
		 * 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
  2581
		 * 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
  2582
		 * everyone else is between 2000-8000.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2583
		 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2584
		u32 goc = (adapter->gotcl + adapter->gorcl) / 10000;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2585
		u32 dif = (adapter->gotcl > adapter->gorcl ?
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2586
			    adapter->gotcl - adapter->gorcl :
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2587
			    adapter->gorcl - adapter->gotcl) / 10000;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2588
		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
  2589
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2590
		ew32(ITR, 1000000000 / (itr * 256));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2591
	}
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
	/* 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
  2594
	ew32(ICS, E1000_ICS_RXDMT0);
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
	/* 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
  2597
	if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2598
		adapter->detect_tx_hung = true;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2601
	/* Reset the timer */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2602
	if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2603
		if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2604
			mod_timer(&adapter->watchdog_timer,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2605
			          round_jiffies(jiffies + 2 * HZ));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2606
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2607
}
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
enum latency_range {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2610
	lowest_latency = 0,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2611
	low_latency = 1,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2612
	bulk_latency = 2,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2613
	latency_invalid = 255
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2614
};
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2615
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2616
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2617
 * 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
  2618
 * @adapter: pointer to adapter
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2619
 * @itr_setting: current adapter->itr
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2620
 * @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
  2621
 * @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
  2622
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2623
 *      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
  2624
 *      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
  2625
 *      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
  2626
 *      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
  2627
 *      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
  2628
 *      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
  2629
 *      while increasing bulk throughput.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2630
 *      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
  2631
 *      parameter (see e1000_param.c)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2632
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2633
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
  2634
				     u16 itr_setting, int packets, int bytes)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2635
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2636
	unsigned int retval = itr_setting;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2637
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2638
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2639
	if (unlikely(hw->mac_type < e1000_82540))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2640
		goto update_itr_done;
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
	if (packets == 0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2643
		goto update_itr_done;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2644
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2645
	switch (itr_setting) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2646
	case lowest_latency:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2647
		/* jumbo frames get bulk treatment*/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2648
		if (bytes/packets > 8000)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2649
			retval = bulk_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2650
		else if ((packets < 5) && (bytes > 512))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2651
			retval = low_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2652
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2653
	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
  2654
		if (bytes > 10000) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2655
			/* jumbo frames need bulk latency setting */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2656
			if (bytes/packets > 8000)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2657
				retval = bulk_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2658
			else if ((packets < 10) || ((bytes/packets) > 1200))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2659
				retval = bulk_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2660
			else if ((packets > 35))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2661
				retval = lowest_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2662
		} else if (bytes/packets > 2000)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2663
			retval = bulk_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2664
		else if (packets <= 2 && bytes < 512)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2665
			retval = lowest_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2666
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2667
	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
  2668
		if (bytes > 25000) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2669
			if (packets > 35)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2670
				retval = low_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2671
		} else if (bytes < 6000) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2672
			retval = low_latency;
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
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2675
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2676
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2677
update_itr_done:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2678
	return retval;
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
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
  2682
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2683
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2684
	u16 current_itr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2685
	u32 new_itr = adapter->itr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2686
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2687
	if (unlikely(hw->mac_type < e1000_82540))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2688
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2689
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2690
	/* 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
  2691
	if (unlikely(adapter->link_speed != SPEED_1000)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2692
		current_itr = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2693
		new_itr = 4000;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2694
		goto set_itr_now;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2695
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2696
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2697
	adapter->tx_itr = e1000_update_itr(adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2698
	                            adapter->tx_itr,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2699
	                            adapter->total_tx_packets,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2700
	                            adapter->total_tx_bytes);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2701
	/* 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
  2702
	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
  2703
		adapter->tx_itr = low_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2704
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2705
	adapter->rx_itr = e1000_update_itr(adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2706
	                            adapter->rx_itr,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2707
	                            adapter->total_rx_packets,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2708
	                            adapter->total_rx_bytes);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2709
	/* 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
  2710
	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
  2711
		adapter->rx_itr = low_latency;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2712
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2713
	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
  2714
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2715
	switch (current_itr) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2716
	/* 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
  2717
	case lowest_latency:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2718
		new_itr = 70000;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2719
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2720
	case low_latency:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2721
		new_itr = 20000; /* aka hwitr = ~200 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2722
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2723
	case bulk_latency:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2724
		new_itr = 4000;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2725
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2726
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2727
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2728
	}
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
set_itr_now:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2731
	if (new_itr != adapter->itr) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2732
		/* 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
  2733
		 * 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
  2734
		 * increasing */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2735
		new_itr = new_itr > adapter->itr ?
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2736
		             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
  2737
		             new_itr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2738
		adapter->itr = new_itr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2739
		ew32(ITR, 1000000000 / (new_itr * 256));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2740
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2741
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2742
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2743
#define E1000_TX_FLAGS_CSUM		0x00000001
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2744
#define E1000_TX_FLAGS_VLAN		0x00000002
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2745
#define E1000_TX_FLAGS_TSO		0x00000004
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2746
#define E1000_TX_FLAGS_IPV4		0x00000008
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2747
#define E1000_TX_FLAGS_VLAN_MASK	0xffff0000
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2748
#define E1000_TX_FLAGS_VLAN_SHIFT	16
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2749
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2750
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
  2751
		     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
  2752
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2753
	struct e1000_context_desc *context_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2754
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2755
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2756
	u32 cmd_length = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2757
	u16 ipcse = 0, tucse, mss;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2758
	u8 ipcss, ipcso, tucss, tucso, hdr_len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2759
	int err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2760
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2761
	if (skb_is_gso(skb)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2762
		if (skb_header_cloned(skb)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2763
			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
  2764
			if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2765
				return err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2766
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2767
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2768
		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
  2769
		mss = skb_shinfo(skb)->gso_size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2770
		if (skb->protocol == htons(ETH_P_IP)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2771
			struct iphdr *iph = ip_hdr(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2772
			iph->tot_len = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2773
			iph->check = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2774
			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
  2775
								 iph->daddr, 0,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2776
								 IPPROTO_TCP,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2777
								 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2778
			cmd_length = E1000_TXD_CMD_IP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2779
			ipcse = skb_transport_offset(skb) - 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2780
		} 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
  2781
			ipv6_hdr(skb)->payload_len = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2782
			tcp_hdr(skb)->check =
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2783
				~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2784
						 &ipv6_hdr(skb)->daddr,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2785
						 0, IPPROTO_TCP, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2786
			ipcse = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2787
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2788
		ipcss = skb_network_offset(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2789
		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
  2790
		tucss = skb_transport_offset(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2791
		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
  2792
		tucse = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2793
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2794
		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
  2795
			       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
  2796
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2797
		i = tx_ring->next_to_use;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2798
		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
  2799
		buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2800
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2801
		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
  2802
		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
  2803
		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
  2804
		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
  2805
		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
  2806
		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
  2807
		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
  2808
		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
  2809
		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
  2810
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2811
		buffer_info->time_stamp = jiffies;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2812
		buffer_info->next_to_watch = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2813
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2814
		if (++i == tx_ring->count) i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2815
		tx_ring->next_to_use = i;
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
		return true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2818
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2819
	return false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2820
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2821
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2822
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
  2823
			  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
  2824
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2825
	struct e1000_context_desc *context_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2826
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2827
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2828
	u8 css;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2829
	u32 cmd_len = E1000_TXD_CMD_DEXT;
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
	if (skb->ip_summed != CHECKSUM_PARTIAL)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2832
		return false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2833
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2834
	switch (skb->protocol) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2835
	case cpu_to_be16(ETH_P_IP):
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2836
		if (ip_hdr(skb)->protocol == IPPROTO_TCP)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2837
			cmd_len |= E1000_TXD_CMD_TCP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2838
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2839
	case cpu_to_be16(ETH_P_IPV6):
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2840
		/* XXX not handling all IPV6 headers */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2841
		if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2842
			cmd_len |= E1000_TXD_CMD_TCP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2843
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2844
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2845
		if (unlikely(net_ratelimit()))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2846
			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
  2847
			       skb->protocol);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2848
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2849
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2850
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2851
	css = skb_checksum_start_offset(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2852
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2853
	i = tx_ring->next_to_use;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2854
	buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2855
	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
  2856
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2857
	context_desc->lower_setup.ip_config = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2858
	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
  2859
	context_desc->upper_setup.tcp_fields.tucso =
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2860
		css + skb->csum_offset;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2861
	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
  2862
	context_desc->tcp_seg_setup.data = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2863
	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
  2864
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2865
	buffer_info->time_stamp = jiffies;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2866
	buffer_info->next_to_watch = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2867
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2868
	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
  2869
	tx_ring->next_to_use = i;
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
	return true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2872
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2873
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2874
#define E1000_MAX_TXD_PWR	12
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2875
#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
  2876
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2877
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
  2878
			struct e1000_tx_ring *tx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2879
			struct sk_buff *skb, unsigned int first,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2880
			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
  2881
			unsigned int mss)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2882
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2883
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2884
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2885
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2886
	unsigned int len = skb_headlen(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2887
	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
  2888
	unsigned int f;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2889
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2890
	i = tx_ring->next_to_use;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2891
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2892
	while (len) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2893
		buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2894
		size = min(len, max_per_txd);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2895
		/* Workaround for Controller erratum --
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2896
		 * 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
  2897
		 * 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
  2898
		 * DMA'd to the controller */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2899
		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
  2900
		    !skb_is_gso(skb)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2901
			tx_ring->last_tx_tso = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2902
			size -= 4;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2903
		}
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
		/* Workaround for premature desc write-backs
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2906
		 * 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
  2907
		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
  2908
			size -= 4;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2909
		/* 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
  2910
		 * to all controllers in PCI-X mode
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2911
		 * 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
  2912
		 * 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
  2913
		 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2914
		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
  2915
		                (size > 2015) && count == 0))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2916
		        size = 2015;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2917
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2918
		/* 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
  2919
		 * terminating buffers within evenly-aligned dwords. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2920
		if (unlikely(adapter->pcix_82544 &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2921
		   !((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
  2922
		   size > 4))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2923
			size -= 4;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2924
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2925
		buffer_info->length = size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2926
		/* 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
  2927
		buffer_info->time_stamp = jiffies;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2928
		buffer_info->mapped_as_page = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2929
		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
  2930
						  skb->data + offset,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2931
						  size,	DMA_TO_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2932
		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
  2933
			goto dma_error;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2934
		buffer_info->next_to_watch = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2935
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2936
		len -= size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2937
		offset += size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2938
		count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2939
		if (len) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2940
			i++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2941
			if (unlikely(i == tx_ring->count))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2942
				i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2943
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2944
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2945
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2946
	for (f = 0; f < nr_frags; f++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2947
		struct skb_frag_struct *frag;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2948
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2949
		frag = &skb_shinfo(skb)->frags[f];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2950
		len = frag->size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2951
		offset = frag->page_offset;
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
		while (len) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2954
			i++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2955
			if (unlikely(i == tx_ring->count))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2956
				i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2957
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2958
			buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2959
			size = min(len, max_per_txd);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2960
			/* Workaround for premature desc write-backs
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2961
			 * 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
  2962
			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
  2963
				size -= 4;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2964
			/* 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
  2965
			 * Avoid terminating buffers within evenly-aligned
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2966
			 * dwords. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2967
			if (unlikely(adapter->pcix_82544 &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2968
			    !((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
  2969
			                      + size - 1) & 4) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2970
			    size > 4))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2971
				size -= 4;
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
			buffer_info->length = size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2974
			buffer_info->time_stamp = jiffies;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2975
			buffer_info->mapped_as_page = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2976
			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
  2977
							offset,	size,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2978
							DMA_TO_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2979
			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
  2980
				goto dma_error;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2981
			buffer_info->next_to_watch = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2982
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2983
			len -= size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2984
			offset += size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2985
			count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2986
		}
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
	tx_ring->buffer_info[i].skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2990
	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
  2991
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2992
	return count;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2993
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2994
dma_error:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2995
	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
  2996
	buffer_info->dma = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2997
	if (count)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2998
		count--;
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
	while (count--) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3001
		if (i==0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3002
			i += tx_ring->count;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3003
		i--;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3004
		buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3005
		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
  3006
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3007
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3008
	return 0;
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
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
  3012
			   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
  3013
			   int count)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3014
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3015
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3016
	struct e1000_tx_desc *tx_desc = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3017
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3018
	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
  3019
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3020
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3021
	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
  3022
		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
  3023
		             E1000_TXD_CMD_TSE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3024
		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3025
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3026
		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
  3027
			txd_upper |= E1000_TXD_POPTS_IXSM << 8;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3030
	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
  3031
		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
  3032
		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3035
	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
  3036
		txd_lower |= E1000_TXD_CMD_VLE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3037
		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
  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
	i = tx_ring->next_to_use;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3041
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3042
	while (count--) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3043
		buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3044
		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
  3045
		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
  3046
		tx_desc->lower.data =
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3047
			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
  3048
		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
  3049
		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
  3050
	}
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
	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
  3053
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3054
	/* 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
  3055
	 * 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
  3056
	 * applicable for weak-ordered memory model archs,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3057
	 * such as IA-64). */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3058
	wmb();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3059
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3060
	tx_ring->next_to_use = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3061
	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
  3062
	/* 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
  3063
	 * 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
  3064
	mmiowb();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3065
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3066
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3067
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3068
 * 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
  3069
 * 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
  3070
 * 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
  3071
 * 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
  3072
 * 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
  3073
 * to the beginning of the Tx FIFO.
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
#define E1000_FIFO_HDR			0x10
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3077
#define E1000_82547_PAD_LEN		0x3E0
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3078
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3079
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
  3080
				       struct sk_buff *skb)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3081
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3082
	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
  3083
	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
  3084
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3085
	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
  3086
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3087
	if (adapter->link_duplex != HALF_DUPLEX)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3088
		goto no_fifo_stall_required;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3089
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3090
	if (atomic_read(&adapter->tx_fifo_stall))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3091
		return 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3092
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3093
	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
  3094
		atomic_set(&adapter->tx_fifo_stall, 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3095
		return 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3096
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3097
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3098
no_fifo_stall_required:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3099
	adapter->tx_fifo_head += skb_fifo_len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3100
	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
  3101
		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
  3102
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3103
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3104
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3105
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
  3106
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3107
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3108
	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
  3109
2589
2b9c78543663 Reverted default branch to stable-1.5.
Florian Pose <fp@igh-essen.com>
parents: 2395
diff changeset
  3110
	if (adapter->ecdev) {
2b9c78543663 Reverted default branch to stable-1.5.
Florian Pose <fp@igh-essen.com>
parents: 2395
diff changeset
  3111
		return -EBUSY;
2b9c78543663 Reverted default branch to stable-1.5.
Florian Pose <fp@igh-essen.com>
parents: 2395
diff changeset
  3112
	}
2b9c78543663 Reverted default branch to stable-1.5.
Florian Pose <fp@igh-essen.com>
parents: 2395
diff changeset
  3113
2395
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3114
	netif_stop_queue(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3115
	/* Herbert's original patch had:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3116
	 *  smp_mb__after_netif_stop_queue();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3117
	 * 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
  3118
	smp_mb();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3119
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3120
	/* 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
  3121
	 * made room available. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3122
	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
  3123
		return -EBUSY;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3124
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3125
	/* A reprieve! */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3126
	netif_start_queue(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3127
	++adapter->restart_queue;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3128
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3129
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3130
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3131
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
  3132
                               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
  3133
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3134
	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
  3135
		return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3136
	return __e1000_maybe_stop_tx(netdev, size);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3137
}
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
#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
  3140
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
  3141
				    struct net_device *netdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3142
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3143
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3144
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3145
	struct e1000_tx_ring *tx_ring;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3146
	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
  3147
	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
  3148
	unsigned int tx_flags = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3149
	unsigned int len = skb_headlen(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3150
	unsigned int nr_frags;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3151
	unsigned int mss;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3152
	int count = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3153
	int tso;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3154
	unsigned int f;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3155
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3156
	/* 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
  3157
	 * 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
  3158
	 * 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
  3159
	 * 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
  3160
	tx_ring = adapter->tx_ring;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3161
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3162
	if (unlikely(skb->len <= 0)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3163
		if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3164
			dev_kfree_skb_any(skb);
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
		return NETDEV_TX_OK;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3169
	mss = skb_shinfo(skb)->gso_size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3170
	/* The controller does a simple calculation to
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3171
	 * 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
  3172
	 * 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
  3173
	 * 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
  3174
	 * 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
  3175
	 * drops. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3176
	if (mss) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3177
		u8 hdr_len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3178
		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
  3179
		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
  3180
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3181
		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
  3182
		if (skb->data_len && hdr_len == len) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3183
			switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3184
				unsigned int pull_size;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3185
			case e1000_82544:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3186
				/* 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
  3187
				 * 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
  3188
				 * this hardware's requirements
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3189
				 * NOTE: this is a TSO only workaround
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3190
				 * 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
  3191
				 * into the next dword */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3192
				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
  3193
					break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3194
				/* fall through */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3195
				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
  3196
				if (!__pskb_pull_tail(skb, pull_size)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3197
					e_err(drv, "__pskb_pull_tail "
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3198
					      "failed.\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3199
					dev_kfree_skb_any(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3200
					return NETDEV_TX_OK;
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
				len = skb_headlen(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3203
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3204
			default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3205
				/* do nothing */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3206
				break;
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
		}
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3211
	/* reserve a descriptor for the offload context */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3212
	if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3213
		count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3214
	count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3215
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3216
	/* Controller Erratum workaround */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3217
	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
  3218
		count++;
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
	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
  3221
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3222
	if (adapter->pcix_82544)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3223
		count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3224
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3225
	/* 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
  3226
	 * 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
  3227
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3228
	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
  3229
			(len > 2015)))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3230
		count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3231
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3232
	nr_frags = skb_shinfo(skb)->nr_frags;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3233
	for (f = 0; f < nr_frags; f++)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3234
		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
  3235
				       max_txd_pwr);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3236
	if (adapter->pcix_82544)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3237
		count += nr_frags;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3238
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3239
	/* 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
  3240
	 * head, otherwise try next time */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3241
	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
  3242
		return NETDEV_TX_BUSY;
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
	if (unlikely(hw->mac_type == e1000_82547)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3245
		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
  3246
			if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3247
				netif_stop_queue(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3248
				if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3249
					mod_timer(&adapter->tx_fifo_stall_timer,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3250
					          jiffies + 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3251
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3252
			return NETDEV_TX_BUSY;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3253
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3254
	}
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
	if (unlikely(vlan_tx_tag_present(skb))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3257
		tx_flags |= E1000_TX_FLAGS_VLAN;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3258
		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
  3259
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3260
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3261
	first = tx_ring->next_to_use;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3262
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3263
	tso = e1000_tso(adapter, tx_ring, skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3264
	if (tso < 0) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3265
		if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3266
			dev_kfree_skb_any(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3267
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3268
		return NETDEV_TX_OK;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3271
	if (likely(tso)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3272
		if (likely(hw->mac_type != e1000_82544))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3273
			tx_ring->last_tx_tso = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3274
		tx_flags |= E1000_TX_FLAGS_TSO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3275
	} 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
  3276
		tx_flags |= E1000_TX_FLAGS_CSUM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3277
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3278
	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
  3279
		tx_flags |= E1000_TX_FLAGS_IPV4;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3280
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3281
	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
  3282
	                     nr_frags, mss);
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 (count) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3285
		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
  3286
		if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3287
			/* 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
  3288
			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
  3289
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3290
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3291
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3292
		if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3293
			dev_kfree_skb_any(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3294
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3295
		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
  3296
		tx_ring->next_to_use = first;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3297
	}
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
	return NETDEV_TX_OK;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3300
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3301
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
 * 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
  3304
 * @netdev: network interface device structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3305
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3306
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3307
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
  3308
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3309
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3310
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3311
	/* Do the reset outside of interrupt context */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3312
	adapter->tx_timeout_count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3313
	schedule_work(&adapter->reset_task);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3314
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3315
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3316
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
  3317
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3318
	struct e1000_adapter *adapter =
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3319
		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
  3320
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3321
	e1000_reinit_safe(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3322
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3323
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3324
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3325
 * e1000_get_stats - Get System Network Statistics
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3326
 * @netdev: network interface device structure
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
 * 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
  3329
 * 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
  3330
 **/
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
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
  3333
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3334
	/* only return the current stats */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3335
	return &netdev->stats;
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
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
 * 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
  3340
 * @netdev: network interface device structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3341
 * @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
  3342
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3343
 * Returns 0 on success, negative on failure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3344
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3345
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3346
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
  3347
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3348
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3349
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3350
	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
  3351
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3352
	if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3353
		return -EBUSY;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3354
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3355
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3356
	if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3357
	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3358
		e_err(probe, "Invalid MTU setting\n");
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3359
		return -EINVAL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3360
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3361
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3362
	/* Adapter-specific max frame size limits. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3363
	switch (hw->mac_type) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3364
	case e1000_undefined ... e1000_82542_rev2_1:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3365
		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
  3366
			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
  3367
			return -EINVAL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3368
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3369
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3370
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3371
		/* 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
  3372
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3373
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3374
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3375
	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
  3376
		msleep(1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3377
	/* 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
  3378
	hw->max_frame_size = max_frame;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3379
	if (netif_running(netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3380
		e1000_down(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3381
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3382
	/* 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
  3383
	 * 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
  3384
	 * larger slab size.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3385
	 * i.e. RXBUFFER_2048 --> size-4096 slab
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3386
	 *  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
  3387
	 *  fragmented skbs */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3388
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3389
	if (max_frame <= E1000_RXBUFFER_2048)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3390
		adapter->rx_buffer_len = E1000_RXBUFFER_2048;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3391
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3392
#if (PAGE_SIZE >= E1000_RXBUFFER_16384)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3393
		adapter->rx_buffer_len = E1000_RXBUFFER_16384;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3394
#elif (PAGE_SIZE >= E1000_RXBUFFER_4096)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3395
		adapter->rx_buffer_len = PAGE_SIZE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3396
#endif
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
	/* 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
  3399
	if (!hw->tbi_compatibility_on &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3400
	    ((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
  3401
	     (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3402
		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
  3403
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3404
	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
  3405
		netdev->name, netdev->mtu, new_mtu);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3406
	netdev->mtu = new_mtu;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3407
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3408
	if (netif_running(netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3409
		e1000_up(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3410
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3411
		e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3412
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3413
	clear_bit(__E1000_RESETTING, &adapter->flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3414
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3415
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3416
}
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
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3419
 * 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
  3420
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3421
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3422
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3423
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
  3424
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3425
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3426
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3427
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3428
	unsigned long flags = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3429
	u16 phy_tmp;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3430
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3431
#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3432
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3433
	/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3434
	 * 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
  3435
	 * connection is down.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3436
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3437
	if (adapter->link_speed == 0)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3438
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3439
	if (pci_channel_offline(pdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3440
		return;
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
	if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3443
		spin_lock_irqsave(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3444
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3445
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3446
	/* 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
  3447
	 * 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
  3448
	 * be written while holding adapter->stats_lock
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3449
	 */
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
	adapter->stats.crcerrs += er32(CRCERRS);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3452
	adapter->stats.gprc += er32(GPRC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3453
	adapter->stats.gorcl += er32(GORCL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3454
	adapter->stats.gorch += er32(GORCH);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3455
	adapter->stats.bprc += er32(BPRC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3456
	adapter->stats.mprc += er32(MPRC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3457
	adapter->stats.roc += er32(ROC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3458
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3459
	adapter->stats.prc64 += er32(PRC64);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3460
	adapter->stats.prc127 += er32(PRC127);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3461
	adapter->stats.prc255 += er32(PRC255);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3462
	adapter->stats.prc511 += er32(PRC511);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3463
	adapter->stats.prc1023 += er32(PRC1023);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3464
	adapter->stats.prc1522 += er32(PRC1522);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3465
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3466
	adapter->stats.symerrs += er32(SYMERRS);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3467
	adapter->stats.mpc += er32(MPC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3468
	adapter->stats.scc += er32(SCC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3469
	adapter->stats.ecol += er32(ECOL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3470
	adapter->stats.mcc += er32(MCC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3471
	adapter->stats.latecol += er32(LATECOL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3472
	adapter->stats.dc += er32(DC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3473
	adapter->stats.sec += er32(SEC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3474
	adapter->stats.rlec += er32(RLEC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3475
	adapter->stats.xonrxc += er32(XONRXC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3476
	adapter->stats.xontxc += er32(XONTXC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3477
	adapter->stats.xoffrxc += er32(XOFFRXC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3478
	adapter->stats.xofftxc += er32(XOFFTXC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3479
	adapter->stats.fcruc += er32(FCRUC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3480
	adapter->stats.gptc += er32(GPTC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3481
	adapter->stats.gotcl += er32(GOTCL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3482
	adapter->stats.gotch += er32(GOTCH);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3483
	adapter->stats.rnbc += er32(RNBC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3484
	adapter->stats.ruc += er32(RUC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3485
	adapter->stats.rfc += er32(RFC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3486
	adapter->stats.rjc += er32(RJC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3487
	adapter->stats.torl += er32(TORL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3488
	adapter->stats.torh += er32(TORH);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3489
	adapter->stats.totl += er32(TOTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3490
	adapter->stats.toth += er32(TOTH);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3491
	adapter->stats.tpr += er32(TPR);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3492
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3493
	adapter->stats.ptc64 += er32(PTC64);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3494
	adapter->stats.ptc127 += er32(PTC127);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3495
	adapter->stats.ptc255 += er32(PTC255);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3496
	adapter->stats.ptc511 += er32(PTC511);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3497
	adapter->stats.ptc1023 += er32(PTC1023);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3498
	adapter->stats.ptc1522 += er32(PTC1522);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3499
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3500
	adapter->stats.mptc += er32(MPTC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3501
	adapter->stats.bptc += er32(BPTC);
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
	/* used for adaptive IFS */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3504
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3505
	hw->tx_packet_delta = er32(TPT);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3506
	adapter->stats.tpt += hw->tx_packet_delta;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3507
	hw->collision_delta = er32(COLC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3508
	adapter->stats.colc += hw->collision_delta;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3509
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3510
	if (hw->mac_type >= e1000_82543) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3511
		adapter->stats.algnerrc += er32(ALGNERRC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3512
		adapter->stats.rxerrc += er32(RXERRC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3513
		adapter->stats.tncrs += er32(TNCRS);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3514
		adapter->stats.cexterr += er32(CEXTERR);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3515
		adapter->stats.tsctc += er32(TSCTC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3516
		adapter->stats.tsctfc += er32(TSCTFC);
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
	/* Fill out the OS statistics structure */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3520
	netdev->stats.multicast = adapter->stats.mprc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3521
	netdev->stats.collisions = adapter->stats.colc;
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
	/* Rx Errors */
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
	/* 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
  3526
	* 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
  3527
	netdev->stats.rx_errors = adapter->stats.rxerrc +
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3528
		adapter->stats.crcerrs + adapter->stats.algnerrc +
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3529
		adapter->stats.ruc + adapter->stats.roc +
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3530
		adapter->stats.cexterr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3531
	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
  3532
	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
  3533
	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
  3534
	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
  3535
	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
  3536
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3537
	/* Tx Errors */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3538
	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
  3539
	netdev->stats.tx_errors = adapter->stats.txerrc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3540
	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
  3541
	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
  3542
	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
  3543
	if (hw->bad_tx_carr_stats_fd &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3544
	    adapter->link_duplex == FULL_DUPLEX) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3545
		netdev->stats.tx_carrier_errors = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3546
		adapter->stats.tncrs = 0;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3549
	/* Tx Dropped needs to be maintained elsewhere */
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
	/* Phy Stats */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3552
	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
  3553
		if ((adapter->link_speed == SPEED_1000) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3554
		   (!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
  3555
			phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3556
			adapter->phy_stats.idle_errors += phy_tmp;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3557
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3558
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3559
		if ((hw->mac_type <= e1000_82546) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3560
		   (hw->phy_type == e1000_phy_m88) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3561
		   !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
  3562
			adapter->phy_stats.receive_errors += phy_tmp;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3563
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3564
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3565
	/* Management Stats */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3566
	if (hw->has_smbus) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3567
		adapter->stats.mgptc += er32(MGTPTC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3568
		adapter->stats.mgprc += er32(MGTPRC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3569
		adapter->stats.mgpdc += er32(MGTPDC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3570
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3571
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3572
	if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3573
		spin_unlock_irqrestore(&adapter->stats_lock, flags);
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
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3576
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3577
void ec_poll(struct net_device *netdev)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3578
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3579
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3580
	if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3581
		e1000_watchdog((unsigned long) adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3582
		adapter->ec_watchdog_jiffies = jiffies;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3583
	}
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_intr(0, netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3586
}
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
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3589
 * e1000_intr - Interrupt Handler
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3590
 * @irq: interrupt number
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3591
 * @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
  3592
 **/
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
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
  3595
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3596
	struct net_device *netdev = data;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3597
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3598
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3599
	u32 icr = er32(ICR);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3600
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3601
	if (unlikely((!icr)))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3602
		return IRQ_NONE;  /* Not our interrupt */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3603
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
	 * 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
  3606
	 * 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
  3607
	 * 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
  3608
	 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3609
	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
  3610
		return IRQ_HANDLED;
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 (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
  3613
		hw->get_link_status = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3614
		/* 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
  3615
		if (!adapter->ecdev && !test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3616
			mod_timer(&adapter->watchdog_timer, jiffies + 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3617
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3618
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3619
	if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3620
		int i, ec_work_done = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3621
		for (i = 0; i < E1000_MAX_INTR; i++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3622
			if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3623
							&ec_work_done, 100) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3624
						!e1000_clean_tx_irq(adapter, adapter->tx_ring))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3625
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3626
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3627
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3628
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3629
		/* disable interrupts, without the synchronize_irq bit */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3630
		ew32(IMC, ~0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3631
		E1000_WRITE_FLUSH();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3632
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3633
		if (likely(napi_schedule_prep(&adapter->napi))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3634
			adapter->total_tx_bytes = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3635
			adapter->total_tx_packets = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3636
			adapter->total_rx_bytes = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3637
			adapter->total_rx_packets = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3638
			__napi_schedule(&adapter->napi);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3639
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3640
			/* 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
  3641
			 * 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
  3642
			if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3643
				e1000_irq_enable(adapter);
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3647
	return IRQ_HANDLED;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3648
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3649
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3650
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3651
 * e1000_clean - NAPI Rx polling callback
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3652
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3653
 * EtherCAT: never called
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3654
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3655
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
  3656
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3657
	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
  3658
	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
  3659
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3660
	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
  3661
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3662
	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
  3663
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3664
	if (!tx_clean_complete)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3665
		work_done = budget;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3666
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3667
	/* 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
  3668
	if (work_done < budget) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3669
		if (likely(adapter->itr_setting & 3))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3670
			e1000_set_itr(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3671
		napi_complete(napi);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3672
		if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3673
			e1000_irq_enable(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3674
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3675
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3676
	return work_done;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3677
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3678
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
 * 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
  3681
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3682
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3683
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
  3684
			       struct e1000_tx_ring *tx_ring)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3685
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3686
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3687
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3688
	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
  3689
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3690
	unsigned int i, eop;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3691
	unsigned int count = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3692
	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
  3693
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3694
	i = tx_ring->next_to_clean;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3695
	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
  3696
	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
  3697
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3698
	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
  3699
	       (count < tx_ring->count)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3700
		bool cleaned = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3701
		rmb();	/* read buffer_info after eop_desc */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3702
		for ( ; !cleaned; count++) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3703
			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
  3704
			buffer_info = &tx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3705
			cleaned = (i == eop);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3706
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3707
			if (cleaned) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3708
				struct sk_buff *skb = buffer_info->skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3709
				unsigned int segs, bytecount;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3710
				segs = skb_shinfo(skb)->gso_segs ?: 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3711
				/* multiply data chunks by size of headers */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3712
				bytecount = ((segs - 1) * skb_headlen(skb)) +
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3713
				            skb->len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3714
				total_tx_packets += segs;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3715
				total_tx_bytes += bytecount;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3716
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3717
			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
  3718
			tx_desc->upper.data = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3719
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3720
			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
  3721
		}
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
		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
  3724
		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
  3725
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3726
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3727
	tx_ring->next_to_clean = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3728
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3729
#define TX_WAKE_THRESHOLD 32
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3730
	if (!adapter->ecdev && unlikely(count && netif_carrier_ok(netdev) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3731
		     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
  3732
		/* 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
  3733
		 * sees the new next_to_clean.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3734
		 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3735
		smp_mb();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3736
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3737
		if (netif_queue_stopped(netdev) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3738
		    !(test_bit(__E1000_DOWN, &adapter->flags))) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3739
			netif_wake_queue(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3740
			++adapter->restart_queue;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3741
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3742
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3743
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3744
	if (!adapter->ecdev && adapter->detect_tx_hung) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3745
		/* 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
  3746
		 * 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
  3747
		adapter->detect_tx_hung = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3748
		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
  3749
		    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
  3750
		               (adapter->tx_timeout_factor * HZ)) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3751
		    !(er32(STATUS) & E1000_STATUS_TXOFF)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3752
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3753
			/* detected Tx unit hang */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3754
			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
  3755
			      "  Tx Queue             <%lu>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3756
			      "  TDH                  <%x>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3757
			      "  TDT                  <%x>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3758
			      "  next_to_use          <%x>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3759
			      "  next_to_clean        <%x>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3760
			      "buffer_info[next_to_clean]\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3761
			      "  time_stamp           <%lx>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3762
			      "  next_to_watch        <%x>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3763
			      "  jiffies              <%lx>\n"
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3764
			      "  next_to_watch.status <%x>\n",
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3765
				(unsigned long)((tx_ring - adapter->tx_ring) /
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3766
					sizeof(struct e1000_tx_ring)),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3767
				readl(hw->hw_addr + tx_ring->tdh),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3768
				readl(hw->hw_addr + tx_ring->tdt),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3769
				tx_ring->next_to_use,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3770
				tx_ring->next_to_clean,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3771
				tx_ring->buffer_info[eop].time_stamp,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3772
				eop,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3773
				jiffies,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3774
				eop_desc->upper.fields.status);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3775
			netif_stop_queue(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3776
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3777
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3778
	adapter->total_tx_bytes += total_tx_bytes;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3779
	adapter->total_tx_packets += total_tx_packets;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3780
	netdev->stats.tx_bytes += total_tx_bytes;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3781
	netdev->stats.tx_packets += total_tx_packets;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3782
	return count < tx_ring->count;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3783
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3784
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3785
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3786
 * 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
  3787
 * @adapter:     board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3788
 * @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
  3789
 * @csum:        receive descriptor csum field
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3790
 * @sk_buff:     socket buffer with received data
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3791
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3792
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3793
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
  3794
			      u32 csum, struct sk_buff *skb)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3795
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3796
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3797
	u16 status = (u16)status_err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3798
	u8 errors = (u8)(status_err >> 24);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3799
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3800
	skb_checksum_none_assert(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3801
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3802
	/* 82543 or newer only */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3803
	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
  3804
	/* Ignore Checksum bit is set */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3805
	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
  3806
	/* TCP/UDP checksum error bit is set */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3807
	if (unlikely(errors & E1000_RXD_ERR_TCPE)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3808
		/* let the stack verify checksum errors */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3809
		adapter->hw_csum_err++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3810
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3811
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3812
	/* TCP/UDP Checksum has not been calculated */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3813
	if (!(status & E1000_RXD_STAT_TCPCS))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3814
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3815
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3816
	/* 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
  3817
	if (likely(status & E1000_RXD_STAT_TCPCS)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3818
		/* TCP checksum is good */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3819
		skb->ip_summed = CHECKSUM_UNNECESSARY;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3820
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3821
	adapter->hw_csum_good++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3822
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3823
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3824
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3825
 * e1000_consume_page - helper function
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3826
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3827
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
  3828
                               u16 length)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3829
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3830
	bi->page = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3831
	skb->len += length;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3832
	skb->data_len += length;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3833
	skb->truesize += length;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3834
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3835
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3836
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3837
 * 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
  3838
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3839
 * @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
  3840
 * @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
  3841
 * @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
  3842
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3843
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
  3844
			      __le16 vlan, struct sk_buff *skb)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3845
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3846
	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
  3847
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3848
	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
  3849
		vlan_gro_receive(&adapter->napi, adapter->vlgrp,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3850
				 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
  3851
				 skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3852
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3853
		napi_gro_receive(&adapter->napi, skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3854
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3855
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
 * 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
  3858
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3859
 * @rx_ring: ring to clean
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3860
 * @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
  3861
 * @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
  3862
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3863
 * 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
  3864
 * is no guarantee that everything was cleaned
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
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
  3867
				     struct e1000_rx_ring *rx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3868
				     int *work_done, int work_to_do)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3869
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3870
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3871
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3872
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3873
	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
  3874
	struct e1000_buffer *buffer_info, *next_buffer;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3875
	unsigned long irq_flags;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3876
	u32 length;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3877
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3878
	int cleaned_count = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3879
	bool cleaned = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3880
	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
  3881
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3882
	i = rx_ring->next_to_clean;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3883
	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
  3884
	buffer_info = &rx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3885
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3886
	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
  3887
		struct sk_buff *skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3888
		u8 status;
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
		if (*work_done >= work_to_do)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3891
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3892
		(*work_done)++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3893
		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
  3894
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3895
		status = rx_desc->status;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3896
		skb = buffer_info->skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3897
		if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3898
			buffer_info->skb = NULL;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3901
		if (++i == rx_ring->count) i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3902
		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
  3903
		prefetch(next_rxd);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3904
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3905
		next_buffer = &rx_ring->buffer_info[i];
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
		cleaned = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3908
		cleaned_count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3909
		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
  3910
			       buffer_info->length, DMA_FROM_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3911
		buffer_info->dma = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3912
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3913
		length = le16_to_cpu(rx_desc->length);
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
		/* 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
  3916
		if (!adapter->ecdev &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3917
		    unlikely((status & E1000_RXD_STAT_EOP) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3918
		    (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
  3919
			u8 last_byte = *(skb->data + length - 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3920
			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
  3921
				       last_byte)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3922
				spin_lock_irqsave(&adapter->stats_lock,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3923
				                  irq_flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3924
				e1000_tbi_adjust_stats(hw, &adapter->stats,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3925
				                       length, skb->data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3926
				spin_unlock_irqrestore(&adapter->stats_lock,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3927
				                       irq_flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3928
				length--;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3929
			} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3930
				/* recycle both page and skb */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3931
				buffer_info->skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3932
				/* 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
  3933
				 * too */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3934
				if (rx_ring->rx_skb_top)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3935
					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
  3936
				rx_ring->rx_skb_top = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3937
				goto next_desc;
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
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3940
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3941
#define rxtop rx_ring->rx_skb_top
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3942
		if (!(status & E1000_RXD_STAT_EOP)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3943
			/* 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
  3944
			if (!rxtop) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3945
				/* this is the beginning of a chain */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3946
				rxtop = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3947
				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
  3948
				                   0, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3949
			} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3950
				/* this is the middle of a chain */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3951
				skb_fill_page_desc(rxtop,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3952
				    skb_shinfo(rxtop)->nr_frags,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3953
				    buffer_info->page, 0, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3954
				/* 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
  3955
				buffer_info->skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3956
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3957
			e1000_consume_page(buffer_info, rxtop, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3958
			goto next_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3959
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3960
			if (rxtop) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3961
				/* end of the chain */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3962
				skb_fill_page_desc(rxtop,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3963
				    skb_shinfo(rxtop)->nr_frags,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3964
				    buffer_info->page, 0, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3965
				/* 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
  3966
				 * page */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3967
				buffer_info->skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3968
				skb = rxtop;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3969
				rxtop = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3970
				e1000_consume_page(buffer_info, skb, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3971
			} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3972
				/* 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
  3973
				 * 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
  3974
				if (length <= copybreak &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3975
				    skb_tailroom(skb) >= length) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3976
					u8 *vaddr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3977
					vaddr = kmap_atomic(buffer_info->page,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3978
					                    KM_SKB_DATA_SOFTIRQ);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3979
					memcpy(skb_tail_pointer(skb), vaddr, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3980
					kunmap_atomic(vaddr,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3981
					              KM_SKB_DATA_SOFTIRQ);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3982
					/* 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
  3983
					 * buffer_info->page */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3984
					skb_put(skb, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3985
				} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3986
					skb_fill_page_desc(skb, 0,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3987
					                   buffer_info->page, 0,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3988
				                           length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3989
					e1000_consume_page(buffer_info, skb,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3990
					                   length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3991
				}
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
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3994
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3995
		/* 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
  3996
		e1000_rx_checksum(adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3997
		                  (u32)(status) |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3998
		                  ((u32)(rx_desc->errors) << 24),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3999
		                  le16_to_cpu(rx_desc->csum), skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4000
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4001
		pskb_trim(skb, skb->len - 4);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4002
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4003
		/* 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
  4004
		total_rx_bytes += skb->len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4005
		total_rx_packets++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4006
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4007
		/* 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
  4008
		if (!pskb_may_pull(skb, ETH_HLEN)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4009
			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
  4010
			if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4011
				dev_kfree_skb(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4012
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4013
			goto next_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4014
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4015
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4016
		if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4017
			ecdev_receive(adapter->ecdev, skb->data, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4018
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4019
			// No need to detect link status as
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4020
			// long as frames are received: Reset watchdog.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4021
			adapter->ec_watchdog_jiffies = jiffies;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4022
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4023
			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
  4024
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4025
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4026
next_desc:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4027
		rx_desc->status = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4028
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4029
		/* 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
  4030
		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
  4031
			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
  4032
			cleaned_count = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4033
		}
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
		/* use prefetched values */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4036
		rx_desc = next_rxd;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4037
		buffer_info = next_buffer;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4038
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4039
	rx_ring->next_to_clean = i;
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
	cleaned_count = E1000_DESC_UNUSED(rx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4042
	if (cleaned_count)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4043
		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
  4044
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4045
	adapter->total_rx_packets += total_rx_packets;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4046
	adapter->total_rx_bytes += total_rx_bytes;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4047
	netdev->stats.rx_bytes += total_rx_bytes;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4048
	netdev->stats.rx_packets += total_rx_packets;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4049
	return cleaned;
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
/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4053
 * 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
  4054
 * of reassembly being done in the stack
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
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
  4057
				 struct e1000_buffer *buffer_info,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4058
				 u32 length, struct sk_buff **skb)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4059
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4060
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4061
	struct sk_buff *new_skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4062
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4063
	if (adapter->ecdev || length > copybreak)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4064
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4065
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4066
	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
  4067
	if (!new_skb)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4068
		return;
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
	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
  4071
				       (*skb)->data - NET_IP_ALIGN,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4072
				       length + NET_IP_ALIGN);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4073
	/* 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
  4074
	buffer_info->skb = *skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4075
	*skb = new_skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4076
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4077
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4078
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4079
 * 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
  4080
 * @adapter: board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4081
 * @rx_ring: ring to clean
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4082
 * @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
  4083
 * @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
  4084
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4085
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
  4086
			       struct e1000_rx_ring *rx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4087
			       int *work_done, int work_to_do)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4088
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4089
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4090
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4091
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4092
	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
  4093
	struct e1000_buffer *buffer_info, *next_buffer;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4094
	unsigned long flags;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4095
	u32 length;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4096
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4097
	int cleaned_count = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4098
	bool cleaned = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4099
	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
  4100
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4101
	i = rx_ring->next_to_clean;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4102
	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
  4103
	buffer_info = &rx_ring->buffer_info[i];
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
	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
  4106
		struct sk_buff *skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4107
		u8 status;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4108
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4109
		if (*work_done >= work_to_do)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4110
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4111
		(*work_done)++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4112
		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
  4113
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4114
		status = rx_desc->status;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4115
		skb = buffer_info->skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4116
		if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4117
			buffer_info->skb = NULL;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4120
		prefetch(skb->data - NET_IP_ALIGN);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4121
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4122
		if (++i == rx_ring->count) i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4123
		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
  4124
		prefetch(next_rxd);
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
		next_buffer = &rx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4127
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4128
		cleaned = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4129
		cleaned_count++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4130
		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
  4131
				 buffer_info->length, DMA_FROM_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4132
		buffer_info->dma = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4133
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4134
		length = le16_to_cpu(rx_desc->length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4135
		/* !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
  4136
		 * 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
  4137
		 * 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
  4138
		 * 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
  4139
		 * definition only a frame fragment
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 (unlikely(!(status & E1000_RXD_STAT_EOP)))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4142
			adapter->discarding = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4143
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4144
		if (adapter->discarding) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4145
			/* 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
  4146
			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
  4147
			/* recycle */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4148
			buffer_info->skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4149
			if (status & E1000_RXD_STAT_EOP)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4150
				adapter->discarding = false;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4151
			goto next_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4152
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4153
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4154
		if (!adapter->ecdev &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4155
		    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
  4156
			u8 last_byte = *(skb->data + length - 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4157
			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
  4158
				       last_byte)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4159
				spin_lock_irqsave(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4160
				e1000_tbi_adjust_stats(hw, &adapter->stats,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4161
				                       length, skb->data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4162
				spin_unlock_irqrestore(&adapter->stats_lock,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4163
				                       flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4164
				length--;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4165
			} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4166
				/* recycle */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4167
				buffer_info->skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4168
				goto next_desc;
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
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4171
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4172
		/* 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
  4173
		 * done after the TBI_ACCEPT workaround above */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4174
		length -= 4;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4175
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4176
		/* 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
  4177
		total_rx_bytes += length;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4178
		total_rx_packets++;
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_check_copybreak(netdev, buffer_info, length, &skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4181
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4182
		skb_put(skb, length);
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
		/* Receive Checksum Offload */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4185
		e1000_rx_checksum(adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4186
				  (u32)(status) |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4187
				  ((u32)(rx_desc->errors) << 24),
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4188
				  le16_to_cpu(rx_desc->csum), skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4189
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4190
		if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4191
			ecdev_receive(adapter->ecdev, skb->data, length);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4192
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4193
			// No need to detect link status as
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4194
			// long as frames are received: Reset watchdog.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4195
			adapter->ec_watchdog_jiffies = jiffies;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4196
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4197
			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
  4198
		}
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
next_desc:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4201
		rx_desc->status = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4202
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4203
		/* 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
  4204
		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
  4205
			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
  4206
			cleaned_count = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4207
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4208
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4209
		/* use prefetched values */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4210
		rx_desc = next_rxd;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4211
		buffer_info = next_buffer;
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
	rx_ring->next_to_clean = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4214
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4215
	cleaned_count = E1000_DESC_UNUSED(rx_ring);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4216
	if (cleaned_count)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4217
		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
  4218
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4219
	adapter->total_rx_packets += total_rx_packets;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4220
	adapter->total_rx_bytes += total_rx_bytes;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4221
	netdev->stats.rx_bytes += total_rx_bytes;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4222
	netdev->stats.rx_packets += total_rx_packets;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4223
	return cleaned;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4224
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4225
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
 * 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
  4228
 * @adapter: address of board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4229
 * @rx_ring: pointer to receive ring structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4230
 * @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
  4231
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4232
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4233
static void
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4234
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
  4235
                             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
  4236
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4237
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4238
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4239
	struct e1000_rx_desc *rx_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4240
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4241
	struct sk_buff *skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4242
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4243
	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
  4244
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4245
	i = rx_ring->next_to_use;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4246
	buffer_info = &rx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4247
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4248
	while (cleaned_count--) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4249
		skb = buffer_info->skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4250
		if (skb) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4251
			skb_trim(skb, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4252
			goto check_page;
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
		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
  4256
		if (unlikely(!skb)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4257
			/* Better luck next round */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4258
			adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4259
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4260
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4261
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4262
		/* 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
  4263
		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
  4264
			struct sk_buff *oldskb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4265
			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
  4266
			      "%p\n", bufsz, skb->data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4267
			/* Try again, without freeing the previous */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4268
			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
  4269
			/* Failed allocation, critical failure */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4270
			if (!skb) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4271
				dev_kfree_skb(oldskb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4272
				adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4273
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4274
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4275
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4276
			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
  4277
				/* give up */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4278
				dev_kfree_skb(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4279
				dev_kfree_skb(oldskb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4280
				break; /* while (cleaned_count--) */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4281
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4282
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4283
			/* Use new allocation */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4284
			dev_kfree_skb(oldskb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4285
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4286
		buffer_info->skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4287
		buffer_info->length = adapter->rx_buffer_len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4288
check_page:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4289
		/* allocate a new page if necessary */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4290
		if (!buffer_info->page) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4291
			buffer_info->page = alloc_page(GFP_ATOMIC);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4292
			if (unlikely(!buffer_info->page)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4293
				adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4294
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4295
			}
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
		if (!buffer_info->dma) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4299
			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
  4300
			                                buffer_info->page, 0,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4301
							buffer_info->length,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4302
							DMA_FROM_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4303
			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
  4304
				put_page(buffer_info->page);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4305
				dev_kfree_skb(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4306
				buffer_info->page = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4307
				buffer_info->skb = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4308
				buffer_info->dma = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4309
				adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4310
				break; /* while !buffer_info->skb */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4311
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4312
		}
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
		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
  4315
		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
  4316
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4317
		if (unlikely(++i == rx_ring->count))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4318
			i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4319
		buffer_info = &rx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4320
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4321
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4322
	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
  4323
		rx_ring->next_to_use = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4324
		if (unlikely(i-- == 0))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4325
			i = (rx_ring->count - 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4326
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4327
		/* 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
  4328
		 * 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
  4329
		 * applicable for weak-ordered memory model archs,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4330
		 * such as IA-64). */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4331
		wmb();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4332
		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
  4333
	}
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
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4337
 * 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
  4338
 * @adapter: address of board private structure
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4339
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4340
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4341
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
  4342
				   struct e1000_rx_ring *rx_ring,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4343
				   int cleaned_count)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4344
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4345
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4346
	struct net_device *netdev = adapter->netdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4347
	struct pci_dev *pdev = adapter->pdev;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4348
	struct e1000_rx_desc *rx_desc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4349
	struct e1000_buffer *buffer_info;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4350
	struct sk_buff *skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4351
	unsigned int i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4352
	unsigned int bufsz = adapter->rx_buffer_len;
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
	i = rx_ring->next_to_use;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4355
	buffer_info = &rx_ring->buffer_info[i];
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4356
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4357
	while (cleaned_count--) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4358
		skb = buffer_info->skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4359
		if (skb) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4360
			skb_trim(skb, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4361
			goto map_skb;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4364
		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
  4365
		if (unlikely(!skb)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4366
			/* Better luck next round */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4367
			adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4368
			break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4369
		}
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
		/* 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
  4372
		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
  4373
			struct sk_buff *oldskb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4374
			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
  4375
			      "%p\n", bufsz, skb->data);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4376
			/* Try again, without freeing the previous */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4377
			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
  4378
			/* Failed allocation, critical failure */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4379
			if (!skb) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4380
				dev_kfree_skb(oldskb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4381
				adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4382
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4383
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4384
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4385
			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
  4386
				/* give up */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4387
				dev_kfree_skb(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4388
				dev_kfree_skb(oldskb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4389
				adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4390
				break; /* while !buffer_info->skb */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4391
			}
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
			/* Use new allocation */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4394
			dev_kfree_skb(oldskb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4395
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4396
		buffer_info->skb = skb;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4397
		buffer_info->length = adapter->rx_buffer_len;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4398
map_skb:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4399
		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
  4400
						  skb->data,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4401
						  buffer_info->length,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4402
						  DMA_FROM_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4403
		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
  4404
			dev_kfree_skb(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4405
			buffer_info->skb = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4406
			buffer_info->dma = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4407
			adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4408
			break; /* while !buffer_info->skb */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4409
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4410
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4411
		/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4412
		 * 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
  4413
		 * boundary crossing
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4414
		 */
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
		/* 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
  4417
		if (!e1000_check_64k_bound(adapter,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4418
					(void *)(unsigned long)buffer_info->dma,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4419
					adapter->rx_buffer_len)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4420
			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
  4421
			      "%p\n", adapter->rx_buffer_len,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4422
			      (void *)(unsigned long)buffer_info->dma);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4423
			dev_kfree_skb(skb);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4424
			buffer_info->skb = NULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4425
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4426
			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
  4427
					 adapter->rx_buffer_len,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4428
					 DMA_FROM_DEVICE);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4429
			buffer_info->dma = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4430
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4431
			adapter->alloc_rx_buff_failed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4432
			break; /* while !buffer_info->skb */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4433
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4434
		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
  4435
		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
  4436
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4437
		if (unlikely(++i == rx_ring->count))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4438
			i = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4439
		buffer_info = &rx_ring->buffer_info[i];
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4442
	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
  4443
		rx_ring->next_to_use = i;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4444
		if (unlikely(i-- == 0))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4445
			i = (rx_ring->count - 1);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4446
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4447
		/* 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
  4448
		 * 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
  4449
		 * applicable for weak-ordered memory model archs,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4450
		 * such as IA-64). */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4451
		wmb();
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4452
		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
  4453
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4454
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4455
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4456
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4457
 * 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
  4458
 * @adapter:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4459
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4460
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4461
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
  4462
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4463
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4464
	u16 phy_status;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4465
	u16 phy_ctrl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4466
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4467
	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
  4468
	   !(hw->autoneg_advertised & ADVERTISE_1000_FULL))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4469
		return;
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
	if (adapter->smartspeed == 0) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4472
		/* 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
  4473
		 * we assume back-to-back */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4474
		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
  4475
		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
  4476
		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
  4477
		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
  4478
		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
  4479
		if (phy_ctrl & CR_1000T_MS_ENABLE) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4480
			phy_ctrl &= ~CR_1000T_MS_ENABLE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4481
			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
  4482
					    phy_ctrl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4483
			adapter->smartspeed++;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4484
			if (!e1000_phy_setup_autoneg(hw) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4485
			   !e1000_read_phy_reg(hw, PHY_CTRL,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4486
				   	       &phy_ctrl)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4487
				phy_ctrl |= (MII_CR_AUTO_NEG_EN |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4488
					     MII_CR_RESTART_AUTO_NEG);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4489
				e1000_write_phy_reg(hw, PHY_CTRL,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4490
						    phy_ctrl);
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
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4494
	} else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4495
		/* 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
  4496
		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
  4497
		phy_ctrl |= CR_1000T_MS_ENABLE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4498
		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
  4499
		if (!e1000_phy_setup_autoneg(hw) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4500
		   !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
  4501
			phy_ctrl |= (MII_CR_AUTO_NEG_EN |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4502
				     MII_CR_RESTART_AUTO_NEG);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4503
			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
  4504
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4505
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4506
	/* Restart process after E1000_SMARTSPEED_MAX iterations */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4507
	if (adapter->smartspeed++ == E1000_SMARTSPEED_MAX)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4508
		adapter->smartspeed = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4509
}
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
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4512
 * e1000_ioctl -
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4513
 * @netdev:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4514
 * @ifreq:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4515
 * @cmd:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4516
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4517
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4518
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
  4519
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4520
	switch (cmd) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4521
	case SIOCGMIIPHY:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4522
	case SIOCGMIIREG:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4523
	case SIOCSMIIREG:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4524
		return e1000_mii_ioctl(netdev, ifr, cmd);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4525
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4526
		return -EOPNOTSUPP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4527
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4528
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4529
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4530
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4531
 * e1000_mii_ioctl -
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4532
 * @netdev:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4533
 * @ifreq:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4534
 * @cmd:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4535
 **/
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4536
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4537
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
  4538
			   int cmd)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4539
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4540
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4541
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4542
	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
  4543
	int retval;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4544
	u16 mii_reg;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4545
	unsigned long flags;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4546
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4547
	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
  4548
		return -EOPNOTSUPP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4549
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4550
	switch (cmd) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4551
	case SIOCGMIIPHY:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4552
		data->phy_id = hw->phy_addr;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4553
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4554
	case SIOCGMIIREG:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4555
		if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4556
			return -EPERM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4557
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4558
		spin_lock_irqsave(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4559
		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
  4560
				   &data->val_out)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4561
			spin_unlock_irqrestore(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4562
			return -EIO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4563
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4564
		spin_unlock_irqrestore(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4565
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4566
	case SIOCSMIIREG:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4567
		if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4568
			return -EPERM;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4569
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4570
		if (data->reg_num & ~(0x1F))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4571
			return -EFAULT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4572
		mii_reg = data->val_in;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4573
		spin_lock_irqsave(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4574
		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
  4575
					mii_reg)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4576
			spin_unlock_irqrestore(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4577
			return -EIO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4578
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4579
		spin_unlock_irqrestore(&adapter->stats_lock, flags);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4580
		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
  4581
			switch (data->reg_num) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4582
			case PHY_CTRL:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4583
				if (mii_reg & MII_CR_POWER_DOWN)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4584
					break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4585
				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
  4586
					hw->autoneg = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4587
					hw->autoneg_advertised = 0x2F;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4588
				} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4589
					u32 speed;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4590
					if (mii_reg & 0x40)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4591
						speed = SPEED_1000;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4592
					else if (mii_reg & 0x2000)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4593
						speed = SPEED_100;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4594
					else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4595
						speed = SPEED_10;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4596
					retval = e1000_set_spd_dplx(
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4597
						adapter, speed,
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4598
						((mii_reg & 0x100)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4599
						 ? DUPLEX_FULL :
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4600
						 DUPLEX_HALF));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4601
					if (retval)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4602
						return retval;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4603
				}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4604
				if (netif_running(adapter->netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4605
					e1000_reinit_locked(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4606
				else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4607
					e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4608
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4609
			case M88E1000_PHY_SPEC_CTRL:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4610
			case M88E1000_EXT_PHY_SPEC_CTRL:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4611
				if (e1000_phy_reset(hw))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4612
					return -EIO;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4613
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4614
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4615
		} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4616
			switch (data->reg_num) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4617
			case PHY_CTRL:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4618
				if (mii_reg & MII_CR_POWER_DOWN)
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
				if (netif_running(adapter->netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4621
					e1000_reinit_locked(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4622
				else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4623
					e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4624
				break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4625
			}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4626
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4627
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4628
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4629
		return -EOPNOTSUPP;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4630
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4631
	return E1000_SUCCESS;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4632
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4633
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4634
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
  4635
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4636
	struct e1000_adapter *adapter = hw->back;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4637
	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
  4638
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4639
	if (ret_val)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4640
		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
  4641
}
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
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
  4644
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4645
	struct e1000_adapter *adapter = hw->back;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4646
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4647
	pci_clear_mwi(adapter->pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4648
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4649
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4650
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
  4651
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4652
	struct e1000_adapter *adapter = hw->back;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4653
	return pcix_get_mmrbc(adapter->pdev);
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4656
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
  4657
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4658
	struct e1000_adapter *adapter = hw->back;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4659
	pcix_set_mmrbc(adapter->pdev, mmrbc);
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
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
  4663
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4664
	outl(value, port);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4665
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4666
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4667
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
  4668
				   struct vlan_group *grp)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4669
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4670
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4671
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4672
	u32 ctrl, rctl;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4673
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4674
	if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4675
		e1000_irq_disable(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4676
	adapter->vlgrp = grp;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4677
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4678
	if (grp) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4679
		/* enable VLAN tag insert/strip */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4680
		ctrl = er32(CTRL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4681
		ctrl |= E1000_CTRL_VME;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4682
		ew32(CTRL, ctrl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4683
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4684
		/* enable VLAN receive filtering */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4685
		rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4686
		rctl &= ~E1000_RCTL_CFIEN;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4687
		if (!(netdev->flags & IFF_PROMISC))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4688
			rctl |= E1000_RCTL_VFE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4689
		ew32(RCTL, rctl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4690
		e1000_update_mng_vlan(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4691
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4692
		/* disable VLAN tag insert/strip */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4693
		ctrl = er32(CTRL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4694
		ctrl &= ~E1000_CTRL_VME;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4695
		ew32(CTRL, ctrl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4696
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4697
		/* disable VLAN receive filtering */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4698
		rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4699
		rctl &= ~E1000_RCTL_VFE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4700
		ew32(RCTL, rctl);
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
		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
  4703
			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
  4704
			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
  4705
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4706
	}
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
	if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4709
		e1000_irq_enable(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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4712
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
  4713
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4714
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4715
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4716
	u32 vfta, index;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4717
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4718
	if ((hw->mng_cookie.status &
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4719
	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4720
	    (vid == adapter->mng_vlan_id))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4721
		return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4722
	/* add VID to filter table */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4723
	index = (vid >> 5) & 0x7F;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4724
	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
  4725
	vfta |= (1 << (vid & 0x1F));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4726
	e1000_write_vfta(hw, index, vfta);
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4729
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
  4730
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4731
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4732
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4733
	u32 vfta, index;
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 (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4736
		e1000_irq_disable(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4737
	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
  4738
	if (!test_bit(__E1000_DOWN, &adapter->flags))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4739
		e1000_irq_enable(adapter);
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
	/* remove VID from filter table */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4742
	index = (vid >> 5) & 0x7F;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4743
	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
  4744
	vfta &= ~(1 << (vid & 0x1F));
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4745
	e1000_write_vfta(hw, index, vfta);
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4748
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
  4749
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4750
	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
  4751
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4752
	if (adapter->vlgrp) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4753
		u16 vid;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4754
		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
  4755
			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
  4756
				continue;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4757
			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
  4758
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4759
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4760
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4761
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4762
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
  4763
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4764
	struct e1000_hw *hw = &adapter->hw;
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
	hw->autoneg = 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4767
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4768
	/* 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
  4769
	 * for the switch() below to work */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4770
	if ((spd & 1) || (dplx & ~1))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4771
		goto err_inval;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4772
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4773
	/* 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
  4774
	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
  4775
	    spd != SPEED_1000 &&
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4776
	    dplx != DUPLEX_FULL)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4777
		goto err_inval;
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
	switch (spd + dplx) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4780
	case SPEED_10 + DUPLEX_HALF:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4781
		hw->forced_speed_duplex = e1000_10_half;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4782
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4783
	case SPEED_10 + DUPLEX_FULL:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4784
		hw->forced_speed_duplex = e1000_10_full;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4785
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4786
	case SPEED_100 + DUPLEX_HALF:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4787
		hw->forced_speed_duplex = e1000_100_half;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4788
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4789
	case SPEED_100 + DUPLEX_FULL:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4790
		hw->forced_speed_duplex = e1000_100_full;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4791
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4792
	case SPEED_1000 + DUPLEX_FULL:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4793
		hw->autoneg = 1;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4794
		hw->autoneg_advertised = ADVERTISE_1000_FULL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4795
		break;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4796
	case SPEED_1000 + DUPLEX_HALF: /* not supported */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4797
	default:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4798
		goto err_inval;
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
	return 0;
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
err_inval:
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4803
	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
  4804
	return -EINVAL;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4805
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4806
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4807
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
  4808
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4809
	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
  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
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4812
	u32 ctrl, ctrl_ext, rctl, status;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4813
	u32 wufc = adapter->wol;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4814
#ifdef CONFIG_PM
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4815
	int retval = 0;
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
	if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4819
		return -EBUSY;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4820
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4821
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4822
	netif_device_detach(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4823
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4824
	if (netif_running(netdev)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4825
		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
  4826
		e1000_down(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4827
	}
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
#ifdef CONFIG_PM
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4830
	retval = pci_save_state(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4831
	if (retval)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4832
		return retval;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4833
#endif
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4834
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4835
	status = er32(STATUS);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4836
	if (status & E1000_STATUS_LU)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4837
		wufc &= ~E1000_WUFC_LNKC;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4838
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4839
	if (wufc) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4840
		e1000_setup_rctl(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4841
		e1000_set_rx_mode(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4842
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4843
		/* 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
  4844
		if (wufc & E1000_WUFC_MC) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4845
			rctl = er32(RCTL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4846
			rctl |= E1000_RCTL_MPE;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4847
			ew32(RCTL, rctl);
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4850
		if (hw->mac_type >= e1000_82540) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4851
			ctrl = er32(CTRL);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4852
			/* advertise wake from D3Cold */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4853
			#define E1000_CTRL_ADVD3WUC 0x00100000
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4854
			/* phy power management enable */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4855
			#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
  4856
			ctrl |= E1000_CTRL_ADVD3WUC |
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4857
				E1000_CTRL_EN_PHY_PWR_MGMT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4858
			ew32(CTRL, ctrl);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4859
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4860
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4861
		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
  4862
		    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
  4863
			/* keep the laser running in D3 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4864
			ctrl_ext = er32(CTRL_EXT);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4865
			ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4866
			ew32(CTRL_EXT, ctrl_ext);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4867
		}
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
		ew32(WUC, E1000_WUC_PME_EN);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4870
		ew32(WUFC, wufc);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4871
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4872
		ew32(WUC, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4873
		ew32(WUFC, 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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4876
	e1000_release_manageability(adapter);
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
	*enable_wake = !!wufc;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4879
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4880
	/* 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
  4881
	if (adapter->en_mng_pt)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4882
		*enable_wake = true;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4883
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4884
	if (netif_running(netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4885
		e1000_free_irq(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4886
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4887
	pci_disable_device(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4888
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4889
	return 0;
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
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4892
#ifdef CONFIG_PM
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4893
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
  4894
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4895
	int retval;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4896
	bool wake;
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
	retval = __e1000_shutdown(pdev, &wake);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4899
	if (retval)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4900
		return retval;
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
	if (wake) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4903
		pci_prepare_to_sleep(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4904
	} else {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4905
		pci_wake_from_d3(pdev, false);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4906
		pci_set_power_state(pdev, PCI_D3hot);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4907
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4908
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4909
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4910
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4911
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4912
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
  4913
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4914
	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
  4915
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4916
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4917
	u32 err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4918
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4919
	if (adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4920
		return -EBUSY;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4921
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4922
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4923
	pci_set_power_state(pdev, PCI_D0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4924
	pci_restore_state(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4925
	pci_save_state(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4926
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4927
	if (adapter->need_ioport)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4928
		err = pci_enable_device(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4929
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4930
		err = pci_enable_device_mem(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4931
	if (err) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4932
		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
  4933
		return err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4934
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4935
	pci_set_master(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4936
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4937
	pci_enable_wake(pdev, PCI_D3hot, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4938
	pci_enable_wake(pdev, PCI_D3cold, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4939
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4940
	if (netif_running(netdev)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4941
		err = e1000_request_irq(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4942
		if (err)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4943
			return err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4944
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4945
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4946
	e1000_power_up_phy(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4947
	e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4948
	ew32(WUS, ~0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4949
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4950
	e1000_init_manageability(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4951
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4952
	if (netif_running(netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4953
		e1000_up(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4954
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4955
	if (!adapter->ecdev) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4956
		netif_device_attach(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4957
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4958
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4959
	return 0;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4960
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4961
#endif
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4962
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4963
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
  4964
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4965
	bool wake;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4966
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4967
	__e1000_shutdown(pdev, &wake);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4968
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4969
	if (system_state == SYSTEM_POWER_OFF) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4970
		pci_wake_from_d3(pdev, wake);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4971
		pci_set_power_state(pdev, PCI_D3hot);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4972
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4973
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4974
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4975
#ifdef CONFIG_NET_POLL_CONTROLLER
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4976
/*
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4977
 * 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
  4978
 * 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
  4979
 * the interrupt routine is executing.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4980
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4981
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
  4982
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4983
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4984
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4985
	disable_irq(adapter->pdev->irq);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4986
	e1000_intr(adapter->pdev->irq, netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4987
	enable_irq(adapter->pdev->irq);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4988
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4989
#endif
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4990
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4991
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4992
 * 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
  4993
 * @pdev: Pointer to PCI device
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4994
 * @state: The current pci connection state
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4995
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4996
 * 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
  4997
 * this device has been detected.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4998
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4999
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
  5000
						pci_channel_state_t state)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5001
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5002
	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
  5003
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5004
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5005
	netif_device_detach(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5006
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5007
	if (state == pci_channel_io_perm_failure)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5008
		return PCI_ERS_RESULT_DISCONNECT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5009
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5010
	if (netif_running(netdev))
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5011
		e1000_down(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5012
	pci_disable_device(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5013
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5014
	/* Request a slot slot reset. */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5015
	return PCI_ERS_RESULT_NEED_RESET;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5016
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5017
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5018
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5019
 * 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
  5020
 * @pdev: Pointer to PCI device
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5021
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5022
 * 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
  5023
 * 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
  5024
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5025
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
  5026
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5027
	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
  5028
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5029
	struct e1000_hw *hw = &adapter->hw;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5030
	int err;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5031
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5032
	if (adapter->need_ioport)
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5033
		err = pci_enable_device(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5034
	else
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5035
		err = pci_enable_device_mem(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5036
	if (err) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5037
		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
  5038
		return PCI_ERS_RESULT_DISCONNECT;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5039
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5040
	pci_set_master(pdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5041
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5042
	pci_enable_wake(pdev, PCI_D3hot, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5043
	pci_enable_wake(pdev, PCI_D3cold, 0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5044
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5045
	e1000_reset(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5046
	ew32(WUS, ~0);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5047
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5048
	return PCI_ERS_RESULT_RECOVERED;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5049
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5050
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5051
/**
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5052
 * 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
  5053
 * @pdev: Pointer to PCI device
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5054
 *
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5055
 * 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
  5056
 * 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
  5057
 * second-half of the e1000_resume routine.
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5058
 */
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5059
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
  5060
{
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5061
	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
  5062
	struct e1000_adapter *adapter = netdev_priv(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5063
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5064
	e1000_init_manageability(adapter);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5065
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5066
	if (netif_running(netdev)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5067
		if (e1000_up(adapter)) {
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5068
			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
  5069
			return;
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5070
		}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5071
	}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5072
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5073
	netif_device_attach(netdev);
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5074
}
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5075
f7451c2c274f Added e1000 driver for kernel 3.0.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5076
/* e1000_main.c */