kni: initial import

Signed-off-by: Intel
This commit is contained in:
Intel 2012-12-20 00:00:00 +01:00 committed by Thomas Monjalon
parent 2656baa8b7
commit 3fc5ca2f63
78 changed files with 68246 additions and 8 deletions

View File

@ -211,6 +211,11 @@ CONFIG_RTE_LIBRTE_LPM_DEBUG=n
#
CONFIG_RTE_LIBRTE_NET=y
#
# Compile librte_kni
#
CONFIG_RTE_LIBRTE_KNI=y
#
# Enable warning directives
#

View File

@ -211,6 +211,11 @@ CONFIG_RTE_LIBRTE_LPM_DEBUG=n
#
CONFIG_RTE_LIBRTE_NET=y
#
# Compile librte_kni
#
CONFIG_RTE_LIBRTE_KNI=y
#
# Enable warning directives
#

View File

@ -211,6 +211,11 @@ CONFIG_RTE_LIBRTE_LPM_DEBUG=n
#
CONFIG_RTE_LIBRTE_NET=y
#
# Compile librte_kni
#
CONFIG_RTE_LIBRTE_KNI=y
#
# Enable warning directives
#

View File

@ -211,6 +211,11 @@ CONFIG_RTE_LIBRTE_LPM_DEBUG=n
#
CONFIG_RTE_LIBRTE_NET=y
#
# Compile librte_kni
#
CONFIG_RTE_LIBRTE_KNI=y
#
# Enable warning directives
#

56
examples/kni/Makefile Normal file
View File

@ -0,0 +1,56 @@
# BSD LICENSE
#
# Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
ifeq ($(RTE_SDK),)
$(error "Please define RTE_SDK environment variable")
endif
# Default target, can be overriden by command line or environment
RTE_TARGET ?= x86_64-default-linuxapp-gcc
include $(RTE_SDK)/mk/rte.vars.mk
ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp")
$(error This application can only operate in a linuxapp environment, \
please change the definition of the RTE_TARGET environment variable)
endif
# binary name
APP = kni
# all source are stored in SRCS-y
SRCS-y := main.c
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)
include $(RTE_SDK)/mk/rte.extapp.mk

797
examples/kni/main.c Normal file
View File

@ -0,0 +1,797 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <sys/queue.h>
#include <stdarg.h>
#include <errno.h>
#include <getopt.h>
#include <netinet/in.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <signal.h>
#include <rte_common.h>
#include <rte_log.h>
#include <rte_memory.h>
#include <rte_memcpy.h>
#include <rte_memzone.h>
#include <rte_tailq.h>
#include <rte_eal.h>
#include <rte_per_lcore.h>
#include <rte_launch.h>
#include <rte_atomic.h>
#include <rte_lcore.h>
#include <rte_branch_prediction.h>
#include <rte_interrupts.h>
#include <rte_pci.h>
#include <rte_debug.h>
#include <rte_ether.h>
#include <rte_ethdev.h>
#include <rte_ring.h>
#include <rte_log.h>
#include <rte_mempool.h>
#include <rte_mbuf.h>
#include <rte_string_fns.h>
#include <rte_cycles.h>
#include <rte_malloc.h>
#include <rte_kni.h>
/* Macros for printing using RTE_LOG */
#define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1
/* NUMA socket to allocate mbuf pool on */
#define SOCKET 0
/* Max size of a single packet */
#define MAX_PACKET_SZ 2048
/* Number of bytes needed for each mbuf */
#define MBUF_SZ \
(MAX_PACKET_SZ + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
/* Number of mbufs in mempool that is created */
#define NB_MBUF (8192 * 16)
/* How many packets to attempt to read from NIC in one go */
#define PKT_BURST_SZ 32
/* How many objects (mbufs) to keep in per-lcore mempool cache */
#define MEMPOOL_CACHE_SZ PKT_BURST_SZ
/* Number of RX ring descriptors */
#define NB_RXD 128
/* Number of TX ring descriptors */
#define NB_TXD 512
/* Total octets in ethernet header */
#define KNI_ENET_HEADER_SIZE 14
/* Total octets in the FCS */
#define KNI_ENET_FCS_SIZE 4
/*
* RX and TX Prefetch, Host, and Write-back threshold values should be
* carefully set for optimal performance. Consult the network
* controller's datasheet and supporting DPDK documentation for guidance
* on how these parameters should be set.
*/
/* RX ring configuration */
static const struct rte_eth_rxconf rx_conf = {
.rx_thresh = {
.pthresh = 8, /* Ring prefetch threshold */
.hthresh = 8, /* Ring host threshold */
.wthresh = 4, /* Ring writeback threshold */
},
.rx_free_thresh = 0, /* Immediately free RX descriptors */
};
/*
* These default values are optimized for use with the Intel(R) 82599 10 GbE
* Controller and the DPDK ixgbe PMD. Consider using other values for other
* network controllers and/or network drivers.
*/
/* TX ring configuration */
static const struct rte_eth_txconf tx_conf = {
.tx_thresh = {
.pthresh = 36, /* Ring prefetch threshold */
.hthresh = 0, /* Ring host threshold */
.wthresh = 0, /* Ring writeback threshold */
},
.tx_free_thresh = 0, /* Use PMD default values */
.tx_rs_thresh = 0, /* Use PMD default values */
};
/* Options for configuring ethernet port */
static struct rte_eth_conf port_conf = {
.rxmode = {
.header_split = 0, /* Header Split disabled */
.hw_ip_checksum = 0, /* IP checksum offload disabled */
.hw_vlan_filter = 0, /* VLAN filtering disabled */
.jumbo_frame = 0, /* Jumbo Frame Support disabled */
.hw_strip_crc = 0, /* CRC stripped by hardware */
},
.txmode = {
.mq_mode = ETH_DCB_NONE,
},
};
/* Mempool for mbufs */
static struct rte_mempool * pktmbuf_pool = NULL;
/* Mask of enabled ports */
static uint32_t ports_mask = 0;
/* Mask of cores that read from NIC and write to tap */
static uint32_t input_cores_mask = 0;
/* Mask of cores that read from tap and write to NIC */
static uint32_t output_cores_mask = 0;
/* Structure type for recording kni interface specific stats */
struct kni_interface_stats {
/* number of pkts received from NIC, and sent to KNI */
uint64_t rx_packets;
/* number of pkts received from NIC, but failed to send to KNI */
uint64_t rx_dropped;
/* number of pkts received from KNI, and sent to NIC */
uint64_t tx_packets;
/* number of pkts received from KNI, but failed to send to NIC */
uint64_t tx_dropped;
};
/* Structure type for recording port specific information */
struct kni_port_info_t {
/* lcore id for ingress */
unsigned lcore_id_ingress;
/* lcore id for egress */
unsigned lcore_id_egress;
/* pointer to kni interface */
struct rte_kni *kni;
};
/* kni port specific information array*/
static struct kni_port_info_t kni_port_info[RTE_MAX_ETHPORTS];
/* kni device statistics array */
static struct kni_interface_stats kni_stats[RTE_MAX_ETHPORTS];
/* Get the pointer to kni interface */
static struct rte_kni * kni_lcore_to_kni(unsigned lcore_id);
static int kni_change_mtu(uint8_t port_id, unsigned new_mtu);
static int kni_config_network_interface(uint8_t port_id, uint8_t if_up);
static struct rte_kni_ops kni_ops = {
.change_mtu = kni_change_mtu,
.config_network_if = kni_config_network_interface,
};
/* Print out statistics on packets handled */
static void
print_stats(void)
{
uint8_t i;
printf("\n**KNI example application statistics**\n"
"====== ============== ============ ============ ============ ============\n"
" Port Lcore(RX/TX) rx_packets rx_dropped tx_packets tx_dropped\n"
"------ -------------- ------------ ------------ ------------ ------------\n");
for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
if (kni_port_info[i].kni == NULL)
continue;
printf("%7d %10u/%2u %13"PRIu64" %13"PRIu64" %13"PRIu64" "
"%13"PRIu64"\n", i,
kni_port_info[i].lcore_id_ingress,
kni_port_info[i].lcore_id_egress,
kni_stats[i].rx_packets,
kni_stats[i].rx_dropped,
kni_stats[i].tx_packets,
kni_stats[i].tx_dropped);
}
printf("====== ============== ============ ============ ============ ============\n");
}
/* Custom handling of signals to handle stats */
static void
signal_handler(int signum)
{
/* When we receive a USR1 signal, print stats */
if (signum == SIGUSR1) {
print_stats();
}
/* When we receive a USR2 signal, reset stats */
if (signum == SIGUSR2) {
memset(&kni_stats, 0, sizeof(kni_stats));
printf("\n**Statistics have been reset**\n");
return;
}
}
static void
kni_burst_free_mbufs(struct rte_mbuf **pkts, unsigned num)
{
unsigned i;
if (pkts == NULL)
return;
for (i = 0; i < num; i++) {
rte_pktmbuf_free(pkts[i]);
pkts[i] = NULL;
}
}
/**
* Interface to burst rx and enqueue mbufs into rx_q
*/
static void
kni_ingress(struct rte_kni *kni)
{
uint8_t port_id = rte_kni_get_port_id(kni);
unsigned nb_rx, num;
struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
if (kni == NULL || port_id >= RTE_MAX_ETHPORTS)
return;
/* Burst rx from eth */
nb_rx = rte_eth_rx_burst(port_id, 0, pkts_burst, PKT_BURST_SZ);
if (nb_rx > PKT_BURST_SZ) {
RTE_LOG(ERR, APP, "Error receiving from eth\n");
return;
}
/* Burst tx to kni */
num = rte_kni_tx_burst(kni, pkts_burst, nb_rx);
kni_stats[port_id].rx_packets += num;
if (unlikely(num < nb_rx)) {
/* Free mbufs not tx to kni interface */
kni_burst_free_mbufs(&pkts_burst[num], nb_rx - num);
kni_stats[port_id].rx_dropped += nb_rx - num;
}
}
/**
* Interface to dequeue mbufs from tx_q and burst tx
*/
static void
kni_egress(struct rte_kni *kni)
{
uint8_t port_id = rte_kni_get_port_id(kni);;
unsigned nb_tx, num;
struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
if (kni == NULL || port_id >= RTE_MAX_ETHPORTS)
return;
/* Burst rx from kni */
num = rte_kni_rx_burst(kni, pkts_burst, PKT_BURST_SZ);
if (num > PKT_BURST_SZ) {
RTE_LOG(ERR, APP, "Error receiving from KNI\n");
return;
}
/* Burst tx to eth */
nb_tx = rte_eth_tx_burst(port_id, 0, pkts_burst, (uint16_t)num);
kni_stats[port_id].tx_packets += nb_tx;
if (unlikely(nb_tx < num)) {
/* Free mbufs not tx to NIC */
kni_burst_free_mbufs(&pkts_burst[nb_tx], num - nb_tx);
kni_stats[port_id].tx_dropped += num - nb_tx;
}
}
/* Main processing loop */
static __attribute__((noreturn)) int
main_loop(__rte_unused void *arg)
{
uint8_t pid;
const unsigned lcore_id = rte_lcore_id();
struct rte_kni *kni = kni_lcore_to_kni(lcore_id);
if (kni == NULL) {
RTE_LOG(INFO, APP, "Lcore %u has nothing to do\n", lcore_id);
for (;;)
; /* loop doing nothing */
} else {
pid = rte_kni_get_port_id(kni);
if (pid >= RTE_MAX_ETHPORTS)
rte_exit(EXIT_FAILURE, "Failure: port id >= %d\n",
RTE_MAX_ETHPORTS);
if (kni_port_info[pid].lcore_id_ingress == lcore_id) {
/* Running on lcores for input packets */
RTE_LOG(INFO, APP, "Lcore %u is reading from "
"port %d\n", lcore_id, pid);
fflush(stdout);
/* rx loop */
while (1)
kni_ingress(kni);
} else if (kni_port_info[pid].lcore_id_egress == lcore_id) {
/* Running on lcores for output packets */
RTE_LOG(INFO, APP, "Lcore %u is writing to port %d\n",
lcore_id, pid);
fflush(stdout);
/* tx loop */
while (1)
kni_egress(kni);
} else {
RTE_LOG(INFO, APP, "Lcore %u has nothing to do\n",
lcore_id);
for (;;)
; /* loop doing nothing */
}
}
}
/* Display usage instructions */
static void
print_usage(const char *prgname)
{
RTE_LOG(INFO, APP, "\nUsage: %s [EAL options] -- -p PORTMASK "
"-i IN_CORES -o OUT_CORES\n"
" -p PORTMASK: hex bitmask of ports to use\n"
" -i IN_CORES: hex bitmask of cores which read "
"from NIC\n"
" -o OUT_CORES: hex bitmask of cores which write to NIC\n",
prgname);
}
/* Convert string to unsigned number. 0 is returned if error occurs */
static uint32_t
parse_unsigned(const char *portmask)
{
char *end = NULL;
unsigned long num;
num = strtoul(portmask, &end, 16);
if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
return 0;
return (uint32_t)num;
}
static int
kni_setup_port_affinities(uint8_t nb_port)
{
unsigned i;
uint32_t in_lcore, out_lcore;
uint8_t rx_port = 0, tx_port = 0;
uint8_t pid;
if (nb_port > RTE_MAX_ETHPORTS) {
RTE_LOG(ERR, APP, "The number of ports exceeds the maximum "
"number of 0x%x\n", RTE_MAX_ETHPORTS);
return -1;
}
RTE_LCORE_FOREACH(i) {
in_lcore = input_cores_mask & (1 << i);
out_lcore = output_cores_mask & (1 << i);
/* Check if it is in input lcore or output lcore mask */
if (in_lcore == 0 && out_lcore == 0)
continue;
/* Check if it is in both input lcore and output lcore mask */
if (in_lcore != 0 && out_lcore != 0) {
RTE_LOG(ERR, APP, "Lcore 0x%x can not be used in both "
"input lcore and output lcore mask\n", i);
return -1;
}
/* Check if the lcore is enabled or not */
if (rte_lcore_is_enabled(i) == 0) {
RTE_LOG(ERR, APP, "Lcore 0x%x is not enabled\n", i);
return -1;
}
if (in_lcore != 0) {
/* It is be for packet receiving */
while ((rx_port < nb_port) &&
((ports_mask & (1 << rx_port)) == 0))
rx_port++;
if (rx_port >= nb_port) {
RTE_LOG(ERR, APP, "There is no enough ports "
"for ingress lcores\n");
return -1;
}
kni_port_info[rx_port].lcore_id_ingress = i;
rx_port++;
} else {
/* It is for packet transmitting */
while ((tx_port < nb_port) &&
((ports_mask & (1 << tx_port)) == 0))
tx_port++;
if (tx_port >= nb_port) {
RTE_LOG(ERR, APP, "There is no enough ports "
"for engree lcores\n");
return -1;
}
kni_port_info[tx_port].lcore_id_egress = i;
tx_port++;
}
}
/* Display all the port/lcore affinity */
for (pid = 0; pid < nb_port; pid++) {
RTE_LOG(INFO, APP, "Port%d, ingress lcore id: %u, "
"egress lcore id: %u\n", pid,
kni_port_info[pid].lcore_id_ingress,
kni_port_info[pid].lcore_id_egress);
}
return 0;
}
static struct rte_kni *
kni_lcore_to_kni(unsigned lcore_id)
{
uint8_t pid;
struct kni_port_info_t *p = kni_port_info;
for (pid = 0; pid < RTE_MAX_ETHPORTS; pid++) {
if (p[pid].kni != NULL && (p[pid].lcore_id_ingress == lcore_id
|| p[pid].lcore_id_egress == lcore_id))
return p[pid].kni;
}
return NULL;
}
/* Parse the arguments given in the command line of the application */
static void
parse_args(int argc, char **argv)
{
int opt;
const char *prgname = argv[0];
/* Disable printing messages within getopt() */
opterr = 0;
/* Parse command line */
while ((opt = getopt(argc, argv, "i:o:p:")) != EOF) {
switch (opt) {
case 'i':
input_cores_mask = parse_unsigned(optarg);
break;
case 'o':
output_cores_mask = parse_unsigned(optarg);
break;
case 'p':
ports_mask = parse_unsigned(optarg);
break;
default:
print_usage(prgname);
rte_exit(EXIT_FAILURE, "Invalid option specified");
}
}
/* Check that options were parsed ok */
if (input_cores_mask == 0) {
print_usage(prgname);
rte_exit(EXIT_FAILURE, "IN_CORES not specified correctly");
}
if (output_cores_mask == 0) {
print_usage(prgname);
rte_exit(EXIT_FAILURE, "OUT_CORES not specified correctly");
}
if (ports_mask == 0) {
print_usage(prgname);
rte_exit(EXIT_FAILURE, "PORTMASK not specified correctly");
}
}
/* Initialise a single port on an Ethernet device */
static void
init_port(uint8_t port)
{
int ret;
/* Initialise device and RX/TX queues */
RTE_LOG(INFO, APP, "Initialising port %u ...\n", (unsigned)port);
fflush(stdout);
ret = rte_eth_dev_configure(port, 1, 1, &port_conf);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Could not configure port%u (%d)",
(unsigned)port, ret);
ret = rte_eth_rx_queue_setup(port, 0, NB_RXD, SOCKET, &rx_conf,
pktmbuf_pool);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Could not setup up RX queue for "
"port%u (%d)", (unsigned)port, ret);
ret = rte_eth_tx_queue_setup(port, 0, NB_TXD, SOCKET, &tx_conf);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Could not setup up TX queue for "
"port%u (%d)", (unsigned)port, ret);
ret = rte_eth_dev_start(port);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Could not start port%u (%d)",
(unsigned)port, ret);
rte_eth_promiscuous_enable(port);
}
/* Check the link status of all ports in up to 9s, and print them finally */
static void
check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
{
#define CHECK_INTERVAL 100 /* 100ms */
#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
uint8_t portid, count, all_ports_up, print_flag = 0;
struct rte_eth_link link;
printf("\nChecking link status");
fflush(stdout);
for (count = 0; count <= MAX_CHECK_TIME; count++) {
all_ports_up = 1;
for (portid = 0; portid < port_num; portid++) {
if ((port_mask & (1 << portid)) == 0)
continue;
memset(&link, 0, sizeof(link));
rte_eth_link_get_nowait(portid, &link);
/* print link status if flag set */
if (print_flag == 1) {
if (link.link_status)
printf("Port %d Link Up - speed %u "
"Mbps - %s\n", (uint8_t)portid,
(unsigned)link.link_speed,
(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
("full-duplex") : ("half-duplex\n"));
else
printf("Port %d Link Down\n",
(uint8_t)portid);
continue;
}
/* clear all_ports_up flag if any link down */
if (link.link_status == 0) {
all_ports_up = 0;
break;
}
}
/* after finally printing all link status, get out */
if (print_flag == 1)
break;
if (all_ports_up == 0) {
printf(".");
fflush(stdout);
rte_delay_ms(CHECK_INTERVAL);
}
/* set the print_flag if all ports up or timeout */
if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
print_flag = 1;
printf("done\n");
}
}
}
/* Callback for request of changing MTU */
static int
kni_change_mtu(uint8_t port_id, unsigned new_mtu)
{
int ret;
struct rte_eth_conf conf;
if (port_id >= rte_eth_dev_count()) {
RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id);
return -EINVAL;
}
RTE_LOG(INFO, APP, "Change MTU of port %d to %u\n", port_id, new_mtu);
/* Stop specific port */
rte_eth_dev_stop(port_id);
memcpy(&conf, &port_conf, sizeof(conf));
/* Set new MTU */
if (new_mtu > ETHER_MAX_LEN)
conf.rxmode.jumbo_frame = 1;
else
conf.rxmode.jumbo_frame = 0;
/* mtu + length of header + length of FCS = max pkt length */
conf.rxmode.max_rx_pkt_len = new_mtu + KNI_ENET_HEADER_SIZE +
KNI_ENET_FCS_SIZE;
ret = rte_eth_dev_configure(port_id, 1, 1, &conf);
if (ret < 0) {
RTE_LOG(ERR, APP, "Fail to reconfigure port %d\n", port_id);
return ret;
}
/* Restart specific port */
ret = rte_eth_dev_start(port_id);
if (ret < 0) {
RTE_LOG(ERR, APP, "Fail to restart port %d\n", port_id);
return ret;
}
return 0;
}
/* Callback for request of configuring network interface up/down */
static int
kni_config_network_interface(uint8_t port_id, uint8_t if_up)
{
int ret = 0;
if (port_id >= rte_eth_dev_count() || port_id >= RTE_MAX_ETHPORTS) {
RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id);
return -EINVAL;
}
RTE_LOG(INFO, APP, "Configure network interface of %d %s\n",
port_id, if_up ? "up" : "down");
if (if_up != 0) { /* Configure network interface up */
rte_eth_dev_stop(port_id);
ret = rte_eth_dev_start(port_id);
} else /* Configure network interface down */
rte_eth_dev_stop(port_id);
if (ret < 0)
RTE_LOG(ERR, APP, "Failed to start port %d\n", port_id);
return ret;
}
/* Initialise ports/queues etc. and start main loop on each core */
int
main(int argc, char** argv)
{
int ret;
unsigned i, cfg_ports = 0;
uint8_t nb_sys_ports, port;
/* Associate signal_hanlder function with USR signals */
signal(SIGUSR1, signal_handler);
signal(SIGUSR2, signal_handler);
/* Initialise EAL */
ret = rte_eal_init(argc, argv);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Could not initialise EAL (%d)", ret);
argc -= ret;
argv += ret;
/* Parse application arguments (after the EAL ones) */
parse_args(argc, argv);
/* Create the mbuf pool */
pktmbuf_pool = rte_mempool_create("mbuf_pool", NB_MBUF, MBUF_SZ,
MEMPOOL_CACHE_SZ,
sizeof(struct rte_pktmbuf_pool_private),
rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL,
SOCKET, 0);
if (pktmbuf_pool == NULL) {
rte_exit(EXIT_FAILURE, "Could not initialise mbuf pool");
return -1;
}
/* Initialise PMD driver(s) */
#ifdef RTE_LIBRTE_IGB_PMD
ret = rte_igb_pmd_init();
if (ret < 0)
rte_exit(EXIT_FAILURE, "Could not initialise igb PMD (%d)",
ret);
#endif
#ifdef RTE_LIBRTE_IXGBE_PMD
ret = rte_ixgbe_pmd_init();
if (ret < 0)
rte_exit(EXIT_FAILURE, "Could not initialise ixgbe PMD (%d)",
ret);
#endif
/* Scan PCI bus for recognised devices */
ret = rte_eal_pci_probe();
if (ret < 0)
rte_exit(EXIT_FAILURE, "Could not probe PCI (%d)", ret);
/* Get number of ports found in scan */
nb_sys_ports = rte_eth_dev_count();
if (nb_sys_ports == 0)
rte_exit(EXIT_FAILURE, "No supported Ethernet devices found - "
"check that CONFIG_RTE_LIBRTE_IGB_PMD=y and/or "
"CONFIG_RTE_LIBRTE_IXGBE_PMD=y in the config file");
/* Find the number of configured ports in the port mask */
for (i = 0; i < sizeof(ports_mask) * 8; i++)
cfg_ports += !! (ports_mask & (1 << i));
if (cfg_ports > nb_sys_ports)
rte_exit(EXIT_FAILURE, "Port mask requires more ports than "
"available");
if (kni_setup_port_affinities(nb_sys_ports) < 0)
rte_exit(EXIT_FAILURE, "Fail to setup port affinities\n");
/* Initialise each port */
for (port = 0; port < nb_sys_ports; port++) {
struct rte_kni *kni;
/* Skip ports that are not enabled */
if ((ports_mask & (1 << port)) == 0) {
continue;
}
init_port(port);
if (port >= RTE_MAX_ETHPORTS)
rte_exit(EXIT_FAILURE, "Can not use more than "
"%d ports for kni\n", RTE_MAX_ETHPORTS);
kni = rte_kni_create(port, MAX_PACKET_SZ, pktmbuf_pool,
&kni_ops);
if (kni == NULL)
rte_exit(EXIT_FAILURE, "Fail to create kni dev "
"for port: %d\n", port);
kni_port_info[port].kni = kni;
}
check_all_ports_link_status(nb_sys_ports, ports_mask);
/* Launch per-lcore function on every lcore */
rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER);
RTE_LCORE_FOREACH_SLAVE(i) {
if (rte_eal_wait_lcore(i) < 0)
return -1;
}
return 0;
}

View File

@ -47,4 +47,8 @@ DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
DIRS-$(CONFIG_RTE_LIBRTE_NET) += librte_net
ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
endif
include $(RTE_SDK)/mk/rte.subdir.mk

View File

@ -70,6 +70,7 @@ extern struct rte_logs rte_logs;
#define RTE_LOGTYPE_PMD 0x00000020 /**< Log related to poll mode driver. */
#define RTE_LOGTYPE_HASH 0x00000040 /**< Log related to hash table. */
#define RTE_LOGTYPE_LPM 0x00000080 /**< Log related to LPM. */
#define RTE_LOGTYPE_KNI 0X00000100 /**< Log related to KNI. */
/* these log types can be used in an application */
#define RTE_LOGTYPE_USER1 0x01000000 /**< User-defined log type 1. */

View File

@ -34,5 +34,6 @@ include $(RTE_SDK)/mk/rte.vars.mk
DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += igb_uio
DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal
DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += kni
include $(RTE_SDK)/mk/rte.subdir.mk

View File

@ -79,7 +79,7 @@ CFLAGS_eal_thread.o += -Wno-return-type
CFLAGS_eal_hpet.o += -Wno-return-type
endif
INC := rte_per_lcore.h rte_lcore.h rte_interrupts.h
INC := rte_per_lcore.h rte_lcore.h rte_interrupts.h rte_kni_common.h
SYMLINK-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP)-include/exec-env := \
$(addprefix include/exec-env/,$(INC))

View File

@ -0,0 +1,157 @@
/*-
* This file is provided under a dual BSD/LGPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GNU LESSER GENERAL PUBLIC LICENSE
*
* Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2.1 of the GNU Lesser General Public License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Contact Information:
* Intel Corporation
*
*
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
*/
#ifndef _RTE_KNI_COMMON_H_
#define _RTE_KNI_COMMON_H_
#ifdef __KERNEL__
#include <linux/if.h>
#endif
/*
* Request id.
*/
enum rte_kni_req_id {
RTE_KNI_REQ_UNKNOWN = 0,
RTE_KNI_REQ_CHANGE_MTU,
RTE_KNI_REQ_CFG_NETWORK_IF,
RTE_KNI_REQ_MAX,
};
/*
* Structure for KNI request.
*/
struct rte_kni_request {
uint32_t req_id; /**< Request id */
union {
uint32_t new_mtu; /**< New MTU */
uint8_t if_up; /**< 1: interface up, 0: interface down */
};
int32_t result; /**< Result for processing request */
} __attribute__((__packed__));
/*
* Fifo struct mapped in a shared memory. It describes a circular buffer FIFO
* Write and read should wrap arround. Fifo is empty when write == read
* Writing should never overwrite the read position
*/
struct rte_kni_fifo {
volatile unsigned write; /**< Next position to be written*/
volatile unsigned read; /**< Next position to be read */
unsigned len; /**< Circular buffer length */
unsigned elem_size; /**< Pointer size - for 32/64 bit OS */
void * volatile buffer[0]; /**< The buffer contains mbuf pointers */
};
/*
* The kernel image of the rte_mbuf struct, with only the relevant fields.
* Padding is necessary to assure the offsets of these fields
*/
struct rte_kni_mbuf {
void *pool;
void *buf_addr;
char pad0[14];
uint16_t ol_flags; /**< Offload features. */
void *next;
void *data; /**< Start address of data in segment buffer. */
uint16_t data_len; /**< Amount of data in segment buffer. */
char pad2[2];
uint16_t pkt_len; /**< Total pkt len: sum of all segment data_len. */
} __attribute__((__aligned__(64)));
/*
* Struct used to create a KNI device. Passed to the kernel in IOCTL call
*/
struct rte_kni_device_info
{
char name[IFNAMSIZ];
phys_addr_t tx_phys;
phys_addr_t rx_phys;
phys_addr_t alloc_phys;
phys_addr_t free_phys;
/* Used by Ethtool */
phys_addr_t req_phys;
phys_addr_t resp_phys;
phys_addr_t sync_phys;
void * sync_va;
/* mbuf mempool */
void * mbuf_va;
phys_addr_t mbuf_phys;
/* PCI info */
uint16_t vendor_id; /**< Vendor ID or PCI_ANY_ID. */
uint16_t device_id; /**< Device ID or PCI_ANY_ID. */
uint8_t bus; /**< Device bus */
uint8_t devid; /**< Device ID */
uint8_t function; /**< Device function. */
/* mbuf size */
unsigned mbuf_size;
};
#define KNI_DEVICE "kni"
#define RTE_KNI_IOCTL_TEST _IOWR(0, 1, int)
#define RTE_KNI_IOCTL_CREATE _IOWR(0, 2, struct rte_kni_device_info)
#endif /* _RTE_KNI_COMMON_H_ */

View File

@ -0,0 +1,82 @@
# BSD LICENSE
#
# Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
include $(RTE_SDK)/mk/rte.vars.mk
#
# module name and path
#
MODULE = rte_kni
#
# CFLAGS
#
MODULE_CFLAGS += -I$(SRCDIR) --param max-inline-insns-single=50
MODULE_CFLAGS += -I$(RTE_OUTPUT)/include -I$(SRCDIR)/ethtool/ixgbe -I$(SRCDIR)/ethtool/igb
MODULE_CFLAGS += -Wall -Werror
# this lib needs main eal
DEPDIRS-y += lib/librte_eal/linuxapp/eal
#
# all source are stored in SRCS-y
#
SRCS-y := ethtool/ixgbe/ixgbe_main.c
SRCS-y += ethtool/ixgbe/ixgbe_api.c
SRCS-y += ethtool/ixgbe/ixgbe_common.c
SRCS-y += ethtool/ixgbe/ixgbe_ethtool.c
SRCS-y += ethtool/ixgbe/ixgbe_82599.c
SRCS-y += ethtool/ixgbe/ixgbe_82598.c
SRCS-y += ethtool/ixgbe/ixgbe_x540.c
SRCS-y += ethtool/ixgbe/ixgbe_phy.c
SRCS-y += ethtool/ixgbe/kcompat.c
SRCS-y += ethtool/igb/e1000_82575.c
SRCS-y += ethtool/igb/e1000_api.c
SRCS-y += ethtool/igb/e1000_mac.c
SRCS-y += ethtool/igb/e1000_manage.c
SRCS-y += ethtool/igb/e1000_mbx.c
SRCS-y += ethtool/igb/e1000_nvm.c
SRCS-y += ethtool/igb/e1000_phy.c
SRCS-y += ethtool/igb/igb_ethtool.c
SRCS-y += ethtool/igb/igb_main.c
SRCS-y += ethtool/igb/igb_param.c
SRCS-y += ethtool/igb/igb_procfs.c
SRCS-y += ethtool/igb/igb_sysfs.c
SRCS-y += ethtool/igb/igb_vmdq.c
#SRCS-y += ethtool/igb/kcompat.c
SRCS-y += kni_misc.c
SRCS-y += kni_net.c
SRCS-y += kni_ethtool.c
include $(RTE_SDK)/mk/rte.module.mk

View File

@ -0,0 +1,101 @@
..
BSD LICENSE
Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Description
In order to support ethtool in Kernel NIC Interface, the standard Linux kernel
drivers of ixgbe/igb are needed to be reused here. ixgbe-3.9.17 is the version
modified from in kernel NIC interface kernel module to support ixgbe NIC, and
igb-3.4.8 is the version modified from in kernel NIC interface kernel module to
support igb NIC.
The source code package of ixgbe can be downloaded from sourceforge.net as below.
http://sourceforge.net/projects/e1000/files/ixgbe%20stable/
Below source files are copied or modified from ixgbe.
ixgbe_82598.h
ixgbe_82599.c
ixgbe_82599.h
ixgbe_api.c
ixgbe_api.h
ixgbe_common.c
ixgbe_common.h
ixgbe_dcb.h
ixgbe_ethtool.c
ixgbe_fcoe.h
ixgbe.h
ixgbe_main.c
ixgbe_mbx.h
ixgbe_osdep.h
ixgbe_phy.c
ixgbe_phy.h
ixgbe_sriov.h
ixgbe_type.h
kcompat.c
kcompat.h
The source code package of igb can be downloaded from sourceforge.net as below.
http://sourceforge.net/projects/e1000/files/igb%20stable/
Below source files are copied or modified from igb.
e1000_82575.c
e1000_82575.h
e1000_api.c
e1000_api.h
e1000_defines.h
e1000_hw.h
e1000_mac.c
e1000_mac.h
e1000_manage.c
e1000_manage.h
e1000_mbx.c
e1000_mbx.h
e1000_nvm.c
e1000_nvm.h
e1000_osdep.h
e1000_phy.c
e1000_phy.h
e1000_regs.h
igb_ethtool.c
igb.h
igb_main.c
igb_param.c
igb_procfs.c
igb_regtest.h
igb_sysfs.c
igb_vmdq.c
igb_vmdq.h
kcompat.c
kcompat_ethtool.c
kcompat.h

View File

@ -0,0 +1,339 @@
"This software program is licensed subject to the GNU General Public License
(GPL). Version 2, June 1991, available at
<http://www.fsf.org/copyleft/gpl.html>"
GNU General Public License
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your freedom to
share and change it. By contrast, the GNU General Public License is intended
to guarantee your freedom to share and change free software--to make sure
the software is free for all its users. This General Public License applies
to most of the Free Software Foundation's software and to any other program
whose authors commit to using it. (Some other Free Software Foundation
software is covered by the GNU Library General Public License instead.) You
can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our
General Public Licenses are designed to make sure that you have the freedom
to distribute copies of free software (and charge for this service if you
wish), that you receive source code or can get it if you want it, that you
can change the software or use pieces of it in new free programs; and that
you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to
deny you these rights or to ask you to surrender the rights. These
restrictions translate to certain responsibilities for you if you distribute
copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or
for a fee, you must give the recipients all the rights that you have. You
must make sure that they, too, receive or can get the source code. And you
must show them these terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2)
offer you this license which gives you legal permission to copy, distribute
and/or modify the software.
Also, for each author's protection and ours, we want to make certain that
everyone understands that there is no warranty for this free software. If
the software is modified by someone else and passed on, we want its
recipients to know that what they have is not the original, so that any
problems introduced by others will not reflect on the original authors'
reputations.
Finally, any free program is threatened constantly by software patents. We
wish to avoid the danger that redistributors of a free program will
individually obtain patent licenses, in effect making the program
proprietary. To prevent this, we have made it clear that any patent must be
licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification
follow.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains a notice
placed by the copyright holder saying it may be distributed under the
terms of this General Public License. The "Program", below, refers to any
such program or work, and a "work based on the Program" means either the
Program or any derivative work under copyright law: that is to say, a
work containing the Program or a portion of it, either verbatim or with
modifications and/or translated into another language. (Hereinafter,
translation is included without limitation in the term "modification".)
Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of running
the Program is not restricted, and the output from the Program is covered
only if its contents constitute a work based on the Program (independent
of having been made by running the Program). Whether that is true depends
on what the Program does.
1. You may copy and distribute verbatim copies of the Program's source code
as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this
License and to the absence of any warranty; and give any other recipients
of the Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you
may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it,
thus forming a work based on the Program, and copy and distribute such
modifications or work under the terms of Section 1 above, provided that
you also meet all of these conditions:
* a) You must cause the modified files to carry prominent notices stating
that you changed the files and the date of any change.
* b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any part
thereof, to be licensed as a whole at no charge to all third parties
under the terms of this License.
* c) If the modified program normally reads commands interactively when
run, you must cause it, when started running for such interactive
use in the most ordinary way, to print or display an announcement
including an appropriate copyright notice and a notice that there is
no warranty (or else, saying that you provide a warranty) and that
users may redistribute the program under these conditions, and
telling the user how to view a copy of this License. (Exception: if
the Program itself is interactive but does not normally print such
an announcement, your work based on the Program is not required to
print an announcement.)
These requirements apply to the modified work as a whole. If identifiable
sections of that work are not derived from the Program, and can be
reasonably considered independent and separate works in themselves, then
this License, and its terms, do not apply to those sections when you
distribute them as separate works. But when you distribute the same
sections as part of a whole which is a work based on the Program, the
distribution of the whole must be on the terms of this License, whose
permissions for other licensees extend to the entire whole, and thus to
each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of a
storage or distribution medium does not bring the other work under the
scope of this License.
3. You may copy and distribute the Program (or a work based on it, under
Section 2) in object code or executable form under the terms of Sections
1 and 2 above provided that you also do one of the following:
* a) Accompany it with the complete corresponding machine-readable source
code, which must be distributed under the terms of Sections 1 and 2
above on a medium customarily used for software interchange; or,
* b) Accompany it with a written offer, valid for at least three years,
to give any third party, for a charge no more than your cost of
physically performing source distribution, a complete machine-
readable copy of the corresponding source code, to be distributed
under the terms of Sections 1 and 2 above on a medium customarily
used for software interchange; or,
* c) Accompany it with the information you received as to the offer to
distribute corresponding source code. (This alternative is allowed
only for noncommercial distribution and only if you received the
program in object code or executable form with such an offer, in
accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source code
means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to control
compilation and installation of the executable. However, as a special
exception, the source code distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on which
the executable runs, unless that component itself accompanies the
executable.
If distribution of executable or object code is made by offering access
to copy from a designated place, then offering equivalent access to copy
the source code from the same place counts as distribution of the source
code, even though third parties are not compelled to copy the source
along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as
expressly provided under this License. Any attempt otherwise to copy,
modify, sublicense or distribute the Program is void, and will
automatically terminate your rights under this License. However, parties
who have received copies, or rights, from you under this License will not
have their licenses terminated so long as such parties remain in full
compliance.
5. You are not required to accept this License, since you have not signed
it. However, nothing else grants you permission to modify or distribute
the Program or its derivative works. These actions are prohibited by law
if you do not accept this License. Therefore, by modifying or
distributing the Program (or any work based on the Program), you
indicate your acceptance of this License to do so, and all its terms and
conditions for copying, distributing or modifying the Program or works
based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further restrictions
on the recipients' exercise of the rights granted herein. You are not
responsible for enforcing compliance by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot distribute
so as to satisfy simultaneously your obligations under this License and
any other pertinent obligations, then as a consequence you may not
distribute the Program at all. For example, if a patent license would
not permit royalty-free redistribution of the Program by all those who
receive copies directly or indirectly through you, then the only way you
could satisfy both it and this License would be to refrain entirely from
distribution of the Program.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is implemented
by public license practices. Many people have made generous contributions
to the wide range of software distributed through that system in
reliance on consistent application of that system; it is up to the
author/donor to decide if he or she is willing to distribute software
through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be
a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain
countries either by patents or by copyrighted interfaces, the original
copyright holder who places the Program under this License may add an
explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions of
the General Public License from time to time. Such new versions will be
similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Program does not specify a version
number of this License, you may choose any version ever published by the
Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs
whose distribution conditions are different, write to the author to ask
for permission. For software which is copyrighted by the Free Software
Foundation, write to the Free Software Foundation; we sometimes make
exceptions for this. Our decision will be guided by the two goals of
preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR
OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it free
software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively convey the
exclusion of warranty; and each file should have at least the "copyright"
line and a pointer to where the full notice is found.
one line to give the program's name and an idea of what it does.
Copyright (C) yyyy name of author
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when
it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free
software, and you are welcome to redistribute it under certain conditions;
type 'show c' for details.
The hypothetical commands 'show w' and 'show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may be
called something other than 'show w' and 'show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
'Gnomovision' (which makes passes at compilers) written by James Hacker.
signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General Public
License instead of this License.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,503 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _E1000_82575_H_
#define _E1000_82575_H_
#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \
(ID_LED_DEF1_DEF2 << 8) | \
(ID_LED_DEF1_DEF2 << 4) | \
(ID_LED_OFF1_ON2))
/*
* Receive Address Register Count
* Number of high/low register pairs in the RAR. The RAR (Receive Address
* Registers) holds the directed and multicast addresses that we monitor.
* These entries are also used for MAC-based filtering.
*/
/*
* For 82576, there are an additional set of RARs that begin at an offset
* separate from the first set of RARs.
*/
#define E1000_RAR_ENTRIES_82575 16
#define E1000_RAR_ENTRIES_82576 24
#define E1000_RAR_ENTRIES_82580 24
#define E1000_RAR_ENTRIES_I350 32
#define E1000_SW_SYNCH_MB 0x00000100
#define E1000_STAT_DEV_RST_SET 0x00100000
#define E1000_CTRL_DEV_RST 0x20000000
struct e1000_adv_data_desc {
__le64 buffer_addr; /* Address of the descriptor's data buffer */
union {
u32 data;
struct {
u32 datalen:16; /* Data buffer length */
u32 rsvd:4;
u32 dtyp:4; /* Descriptor type */
u32 dcmd:8; /* Descriptor command */
} config;
} lower;
union {
u32 data;
struct {
u32 status:4; /* Descriptor status */
u32 idx:4;
u32 popts:6; /* Packet Options */
u32 paylen:18; /* Payload length */
} options;
} upper;
};
#define E1000_TXD_DTYP_ADV_C 0x2 /* Advanced Context Descriptor */
#define E1000_TXD_DTYP_ADV_D 0x3 /* Advanced Data Descriptor */
#define E1000_ADV_TXD_CMD_DEXT 0x20 /* Descriptor extension (0 = legacy) */
#define E1000_ADV_TUCMD_IPV4 0x2 /* IP Packet Type: 1=IPv4 */
#define E1000_ADV_TUCMD_IPV6 0x0 /* IP Packet Type: 0=IPv6 */
#define E1000_ADV_TUCMD_L4T_UDP 0x0 /* L4 Packet TYPE of UDP */
#define E1000_ADV_TUCMD_L4T_TCP 0x4 /* L4 Packet TYPE of TCP */
#define E1000_ADV_TUCMD_MKRREQ 0x10 /* Indicates markers are required */
#define E1000_ADV_DCMD_EOP 0x1 /* End of Packet */
#define E1000_ADV_DCMD_IFCS 0x2 /* Insert FCS (Ethernet CRC) */
#define E1000_ADV_DCMD_RS 0x8 /* Report Status */
#define E1000_ADV_DCMD_VLE 0x40 /* Add VLAN tag */
#define E1000_ADV_DCMD_TSE 0x80 /* TCP Seg enable */
/* Extended Device Control */
#define E1000_CTRL_EXT_NSICR 0x00000001 /* Disable Intr Clear all on read */
struct e1000_adv_context_desc {
union {
u32 ip_config;
struct {
u32 iplen:9;
u32 maclen:7;
u32 vlan_tag:16;
} fields;
} ip_setup;
u32 seq_num;
union {
u64 l4_config;
struct {
u32 mkrloc:9;
u32 tucmd:11;
u32 dtyp:4;
u32 adv:8;
u32 rsvd:4;
u32 idx:4;
u32 l4len:8;
u32 mss:16;
} fields;
} l4_setup;
};
/* SRRCTL bit definitions */
#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
#define E1000_SRRCTL_BSIZEHDRSIZE_MASK 0x00000F00
#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
#define E1000_SRRCTL_DESCTYPE_LEGACY 0x00000000
#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION 0x06000000
#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000
#define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000
#define E1000_SRRCTL_TIMESTAMP 0x40000000
#define E1000_SRRCTL_DROP_EN 0x80000000
#define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F
#define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00
#define E1000_TX_HEAD_WB_ENABLE 0x1
#define E1000_TX_SEQNUM_WB_ENABLE 0x2
#define E1000_MRQC_ENABLE_RSS_4Q 0x00000002
#define E1000_MRQC_ENABLE_VMDQ 0x00000003
#define E1000_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005
#define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
#define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000
#define E1000_MRQC_ENABLE_RSS_8Q 0x00000002
#define E1000_VMRCTL_MIRROR_PORT_SHIFT 8
#define E1000_VMRCTL_MIRROR_DSTPORT_MASK (7 << \
E1000_VMRCTL_MIRROR_PORT_SHIFT)
#define E1000_VMRCTL_POOL_MIRROR_ENABLE (1 << 0)
#define E1000_VMRCTL_UPLINK_MIRROR_ENABLE (1 << 1)
#define E1000_VMRCTL_DOWNLINK_MIRROR_ENABLE (1 << 2)
#define E1000_EICR_TX_QUEUE ( \
E1000_EICR_TX_QUEUE0 | \
E1000_EICR_TX_QUEUE1 | \
E1000_EICR_TX_QUEUE2 | \
E1000_EICR_TX_QUEUE3)
#define E1000_EICR_RX_QUEUE ( \
E1000_EICR_RX_QUEUE0 | \
E1000_EICR_RX_QUEUE1 | \
E1000_EICR_RX_QUEUE2 | \
E1000_EICR_RX_QUEUE3)
#define E1000_EIMS_RX_QUEUE E1000_EICR_RX_QUEUE
#define E1000_EIMS_TX_QUEUE E1000_EICR_TX_QUEUE
#define EIMS_ENABLE_MASK ( \
E1000_EIMS_RX_QUEUE | \
E1000_EIMS_TX_QUEUE | \
E1000_EIMS_TCP_TIMER | \
E1000_EIMS_OTHER)
/* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */
#define E1000_IMIR_PORT_IM_EN 0x00010000 /* TCP port enable */
#define E1000_IMIR_PORT_BP 0x00020000 /* TCP port check bypass */
#define E1000_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */
#define E1000_IMIREXT_CTRL_URG 0x00002000 /* Check URG bit in header */
#define E1000_IMIREXT_CTRL_ACK 0x00004000 /* Check ACK bit in header */
#define E1000_IMIREXT_CTRL_PSH 0x00008000 /* Check PSH bit in header */
#define E1000_IMIREXT_CTRL_RST 0x00010000 /* Check RST bit in header */
#define E1000_IMIREXT_CTRL_SYN 0x00020000 /* Check SYN bit in header */
#define E1000_IMIREXT_CTRL_FIN 0x00040000 /* Check FIN bit in header */
#define E1000_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */
/* Receive Descriptor - Advanced */
union e1000_adv_rx_desc {
struct {
__le64 pkt_addr; /* Packet buffer address */
__le64 hdr_addr; /* Header buffer address */
} read;
struct {
struct {
union {
__le32 data;
struct {
__le16 pkt_info; /*RSS type, Pkt type*/
/* Split Header, header buffer len */
__le16 hdr_info;
} hs_rss;
} lo_dword;
union {
__le32 rss; /* RSS Hash */
struct {
__le16 ip_id; /* IP id */
__le16 csum; /* Packet Checksum */
} csum_ip;
} hi_dword;
} lower;
struct {
__le32 status_error; /* ext status/error */
__le16 length; /* Packet length */
__le16 vlan; /* VLAN tag */
} upper;
} wb; /* writeback */
};
#define E1000_RXDADV_RSSTYPE_MASK 0x0000000F
#define E1000_RXDADV_RSSTYPE_SHIFT 12
#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
#define E1000_RXDADV_SPLITHEADER_EN 0x00001000
#define E1000_RXDADV_SPH 0x8000
#define E1000_RXDADV_STAT_TS 0x10000 /* Pkt was time stamped */
#define E1000_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */
#define E1000_RXDADV_ERR_HBO 0x00800000
/* RSS Hash results */
#define E1000_RXDADV_RSSTYPE_NONE 0x00000000
#define E1000_RXDADV_RSSTYPE_IPV4_TCP 0x00000001
#define E1000_RXDADV_RSSTYPE_IPV4 0x00000002
#define E1000_RXDADV_RSSTYPE_IPV6_TCP 0x00000003
#define E1000_RXDADV_RSSTYPE_IPV6_EX 0x00000004
#define E1000_RXDADV_RSSTYPE_IPV6 0x00000005
#define E1000_RXDADV_RSSTYPE_IPV6_TCP_EX 0x00000006
#define E1000_RXDADV_RSSTYPE_IPV4_UDP 0x00000007
#define E1000_RXDADV_RSSTYPE_IPV6_UDP 0x00000008
#define E1000_RXDADV_RSSTYPE_IPV6_UDP_EX 0x00000009
/* RSS Packet Types as indicated in the receive descriptor */
#define E1000_RXDADV_PKTTYPE_NONE 0x00000000
#define E1000_RXDADV_PKTTYPE_IPV4 0x00000010 /* IPV4 hdr present */
#define E1000_RXDADV_PKTTYPE_IPV4_EX 0x00000020 /* IPV4 hdr + extensions */
#define E1000_RXDADV_PKTTYPE_IPV6 0x00000040 /* IPV6 hdr present */
#define E1000_RXDADV_PKTTYPE_IPV6_EX 0x00000080 /* IPV6 hdr + extensions */
#define E1000_RXDADV_PKTTYPE_TCP 0x00000100 /* TCP hdr present */
#define E1000_RXDADV_PKTTYPE_UDP 0x00000200 /* UDP hdr present */
#define E1000_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */
#define E1000_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */
#define E1000_RXDADV_PKTTYPE_IPSEC_ESP 0x00001000 /* IPSec ESP */
#define E1000_RXDADV_PKTTYPE_IPSEC_AH 0x00002000 /* IPSec AH */
#define E1000_RXDADV_PKTTYPE_LINKSEC 0x00004000 /* LinkSec Encap */
#define E1000_RXDADV_PKTTYPE_ETQF 0x00008000 /* PKTTYPE is ETQF index */
#define E1000_RXDADV_PKTTYPE_ETQF_MASK 0x00000070 /* ETQF has 8 indices */
#define E1000_RXDADV_PKTTYPE_ETQF_SHIFT 4 /* Right-shift 4 bits */
/* LinkSec results */
/* Security Processing bit Indication */
#define E1000_RXDADV_LNKSEC_STATUS_SECP 0x00020000
#define E1000_RXDADV_LNKSEC_ERROR_BIT_MASK 0x18000000
#define E1000_RXDADV_LNKSEC_ERROR_NO_SA_MATCH 0x08000000
#define E1000_RXDADV_LNKSEC_ERROR_REPLAY_ERROR 0x10000000
#define E1000_RXDADV_LNKSEC_ERROR_BAD_SIG 0x18000000
#define E1000_RXDADV_IPSEC_STATUS_SECP 0x00020000
#define E1000_RXDADV_IPSEC_ERROR_BIT_MASK 0x18000000
#define E1000_RXDADV_IPSEC_ERROR_INVALID_PROTOCOL 0x08000000
#define E1000_RXDADV_IPSEC_ERROR_INVALID_LENGTH 0x10000000
#define E1000_RXDADV_IPSEC_ERROR_AUTHENTICATION_FAILED 0x18000000
/* Transmit Descriptor - Advanced */
union e1000_adv_tx_desc {
struct {
__le64 buffer_addr; /* Address of descriptor's data buf */
__le32 cmd_type_len;
__le32 olinfo_status;
} read;
struct {
__le64 rsvd; /* Reserved */
__le32 nxtseq_seed;
__le32 status;
} wb;
};
/* Adv Transmit Descriptor Config Masks */
#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
#define E1000_ADVTXD_DCMD_DDTYP_ISCSI 0x10000000 /* DDP hdr type or iSCSI */
#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
#define E1000_ADVTXD_MAC_LINKSEC 0x00040000 /* Apply LinkSec on pkt */
#define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp pkt */
#define E1000_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED prsnt in WB */
#define E1000_ADVTXD_IDX_SHIFT 4 /* Adv desc Index shift */
#define E1000_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */
#define E1000_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */
#define E1000_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */
/* 1st & Last TSO-full iSCSI PDU*/
#define E1000_ADVTXD_POPTS_ISCO_FULL 0x00001800
#define E1000_ADVTXD_POPTS_IPSEC 0x00000400 /* IPSec offload request */
#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
/* Context descriptors */
struct e1000_adv_tx_context_desc {
__le32 vlan_macip_lens;
__le32 seqnum_seed;
__le32 type_tucmd_mlhl;
__le32 mss_l4len_idx;
};
#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
#define E1000_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */
#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
#define E1000_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */
#define E1000_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */
#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */
#define E1000_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */
/* IPSec Encrypt Enable for ESP */
#define E1000_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000
/* Req requires Markers and CRC */
#define E1000_ADVTXD_TUCMD_MKRREQ 0x00002000
#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
/* Adv ctxt IPSec SA IDX mask */
#define E1000_ADVTXD_IPSEC_SA_INDEX_MASK 0x000000FF
/* Adv ctxt IPSec ESP len mask */
#define E1000_ADVTXD_IPSEC_ESP_LEN_MASK 0x000000FF
/* Additional Transmit Descriptor Control definitions */
#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */
#define E1000_TXDCTL_SWFLSH 0x04000000 /* Tx Desc. wbk flushing */
/* Tx Queue Arbitration Priority 0=low, 1=high */
#define E1000_TXDCTL_PRIORITY 0x08000000
/* Additional Receive Descriptor Control definitions */
#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */
#define E1000_RXDCTL_SWFLSH 0x04000000 /* Rx Desc. wbk flushing */
/* Direct Cache Access (DCA) definitions */
#define E1000_DCA_CTRL_DCA_ENABLE 0x00000000 /* DCA Enable */
#define E1000_DCA_CTRL_DCA_DISABLE 0x00000001 /* DCA Disable */
#define E1000_DCA_CTRL_DCA_MODE_CB1 0x00 /* DCA Mode CB1 */
#define E1000_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */
#define E1000_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */
#define E1000_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */
#define E1000_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header ena */
#define E1000_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload ena */
#define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
#define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */
#define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
#define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */
#define E1000_DCA_RXCTRL_CPUID_MASK_82576 0xFF000000 /* Rx CPUID Mask */
#define E1000_DCA_TXCTRL_CPUID_SHIFT_82576 24 /* Tx CPUID */
#define E1000_DCA_RXCTRL_CPUID_SHIFT_82576 24 /* Rx CPUID */
/* Additional interrupt register bit definitions */
#define E1000_ICR_LSECPNS 0x00000020 /* PN threshold - server */
#define E1000_IMS_LSECPNS E1000_ICR_LSECPNS /* PN threshold - server */
#define E1000_ICS_LSECPNS E1000_ICR_LSECPNS /* PN threshold - server */
/* ETQF register bit definitions */
#define E1000_ETQF_FILTER_ENABLE (1 << 26)
#define E1000_ETQF_IMM_INT (1 << 29)
#define E1000_ETQF_1588 (1 << 30)
#define E1000_ETQF_QUEUE_ENABLE (1 << 31)
/*
* ETQF filter list: one static filter per filter consumer. This is
* to avoid filter collisions later. Add new filters
* here!!
*
* Current filters:
* EAPOL 802.1x (0x888e): Filter 0
*/
#define E1000_ETQF_FILTER_EAPOL 0
#define E1000_FTQF_VF_BP 0x00008000
#define E1000_FTQF_1588_TIME_STAMP 0x08000000
#define E1000_FTQF_MASK 0xF0000000
#define E1000_FTQF_MASK_PROTO_BP 0x10000000
#define E1000_FTQF_MASK_SOURCE_ADDR_BP 0x20000000
#define E1000_FTQF_MASK_DEST_ADDR_BP 0x40000000
#define E1000_FTQF_MASK_SOURCE_PORT_BP 0x80000000
#define E1000_NVM_APME_82575 0x0400
#define MAX_NUM_VFS 7
#define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof cntrl */
#define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof cntrl */
#define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */
#define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8
#define E1000_DTXSWC_LLE_SHIFT 16
#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */
/* Easy defines for setting default pool, would normally be left a zero */
#define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7
#define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT)
/* Other useful VMD_CTL register defines */
#define E1000_VT_CTL_IGNORE_MAC (1 << 28)
#define E1000_VT_CTL_DISABLE_DEF_POOL (1 << 29)
#define E1000_VT_CTL_VM_REPL_EN (1 << 30)
/* Per VM Offload register setup */
#define E1000_VMOLR_RLPML_MASK 0x00003FFF /* Long Packet Maximum Length mask */
#define E1000_VMOLR_LPE 0x00010000 /* Accept Long packet */
#define E1000_VMOLR_RSSE 0x00020000 /* Enable RSS */
#define E1000_VMOLR_AUPE 0x01000000 /* Accept untagged packets */
#define E1000_VMOLR_ROMPE 0x02000000 /* Accept overflow multicast */
#define E1000_VMOLR_ROPE 0x04000000 /* Accept overflow unicast */
#define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */
#define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */
#define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
#define E1000_VMOLR_STRCRC 0x80000000 /* CRC stripping enable */
#define E1000_VMOLR_VPE 0x00800000 /* VLAN promiscuous enable */
#define E1000_VMOLR_UPE 0x20000000 /* Unicast promisuous enable */
#define E1000_DVMOLR_HIDVLAN 0x20000000 /* Vlan hiding enable */
#define E1000_DVMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
#define E1000_DVMOLR_STRCRC 0x80000000 /* CRC stripping enable */
#define E1000_PBRWAC_WALPB 0x00000007 /* Wrap around event on LAN Rx PB */
#define E1000_PBRWAC_PBE 0x00000008 /* Rx packet buffer empty */
#define E1000_VLVF_ARRAY_SIZE 32
#define E1000_VLVF_VLANID_MASK 0x00000FFF
#define E1000_VLVF_POOLSEL_SHIFT 12
#define E1000_VLVF_POOLSEL_MASK (0xFF << E1000_VLVF_POOLSEL_SHIFT)
#define E1000_VLVF_LVLAN 0x00100000
#define E1000_VLVF_VLANID_ENABLE 0x80000000
#define E1000_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */
#define E1000_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */
#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
#define E1000_IOVCTL 0x05BBC
#define E1000_IOVCTL_REUSE_VFQ 0x00000001
#define E1000_RPLOLR_STRVLAN 0x40000000
#define E1000_RPLOLR_STRCRC 0x80000000
#define E1000_TCTL_EXT_COLD 0x000FFC00
#define E1000_TCTL_EXT_COLD_SHIFT 10
#define E1000_DTXCTL_8023LL 0x0004
#define E1000_DTXCTL_VLAN_ADDED 0x0008
#define E1000_DTXCTL_OOS_ENABLE 0x0010
#define E1000_DTXCTL_MDP_EN 0x0020
#define E1000_DTXCTL_SPOOF_INT 0x0040
#define E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT (1 << 14)
#define ALL_QUEUES 0xFFFF
/* Rx packet buffer size defines */
#define E1000_RXPBS_SIZE_MASK_82576 0x0000007F
void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable);
void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf);
void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable);
s32 e1000_init_nvm_params_82575(struct e1000_hw *hw);
u16 e1000_rxpbs_adjust_82580(u32 data);
s32 e1000_set_eee_i350(struct e1000_hw *);
#define E1000_I2C_THERMAL_SENSOR_ADDR 0xF8
#define E1000_EMC_INTERNAL_DATA 0x00
#define E1000_EMC_INTERNAL_THERM_LIMIT 0x20
#define E1000_EMC_DIODE1_DATA 0x01
#define E1000_EMC_DIODE1_THERM_LIMIT 0x19
#define E1000_EMC_DIODE2_DATA 0x23
#define E1000_EMC_DIODE2_THERM_LIMIT 0x1A
#define E1000_EMC_DIODE3_DATA 0x2A
#define E1000_EMC_DIODE3_THERM_LIMIT 0x30
s32 e1000_get_thermal_sensor_data_generic(struct e1000_hw *hw);
s32 e1000_init_thermal_sensor_thresh_generic(struct e1000_hw *hw);
/* I2C SDA and SCL timing parameters for standard mode */
#define E1000_I2C_T_HD_STA 4
#define E1000_I2C_T_LOW 5
#define E1000_I2C_T_HIGH 4
#define E1000_I2C_T_SU_STA 5
#define E1000_I2C_T_HD_DATA 5
#define E1000_I2C_T_SU_DATA 1
#define E1000_I2C_T_RISE 1
#define E1000_I2C_T_FALL 1
#define E1000_I2C_T_SU_STO 4
#define E1000_I2C_T_BUF 5
s32 e1000_set_i2c_bb(struct e1000_hw *hw);
s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
u8 dev_addr, u8 *data);
s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
u8 dev_addr, u8 data);
void e1000_i2c_bus_clear(struct e1000_hw *hw);
#endif /* _E1000_82575_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,150 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _E1000_API_H_
#define _E1000_API_H_
#include "e1000_hw.h"
extern void e1000_init_function_pointers_82575(struct e1000_hw *hw);
extern void e1000_rx_fifo_flush_82575(struct e1000_hw *hw);
extern void e1000_init_function_pointers_vf(struct e1000_hw *hw);
extern void e1000_power_up_fiber_serdes_link(struct e1000_hw *hw);
extern void e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw);
s32 e1000_set_mac_type(struct e1000_hw *hw);
s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device);
s32 e1000_init_mac_params(struct e1000_hw *hw);
s32 e1000_init_nvm_params(struct e1000_hw *hw);
s32 e1000_init_phy_params(struct e1000_hw *hw);
s32 e1000_init_mbx_params(struct e1000_hw *hw);
s32 e1000_get_bus_info(struct e1000_hw *hw);
void e1000_clear_vfta(struct e1000_hw *hw);
void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value);
s32 e1000_force_mac_fc(struct e1000_hw *hw);
s32 e1000_check_for_link(struct e1000_hw *hw);
s32 e1000_reset_hw(struct e1000_hw *hw);
s32 e1000_init_hw(struct e1000_hw *hw);
s32 e1000_setup_link(struct e1000_hw *hw);
s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex);
s32 e1000_disable_pcie_master(struct e1000_hw *hw);
void e1000_config_collision_dist(struct e1000_hw *hw);
void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr);
void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list,
u32 mc_addr_count);
s32 e1000_setup_led(struct e1000_hw *hw);
s32 e1000_cleanup_led(struct e1000_hw *hw);
s32 e1000_check_reset_block(struct e1000_hw *hw);
s32 e1000_blink_led(struct e1000_hw *hw);
s32 e1000_led_on(struct e1000_hw *hw);
s32 e1000_led_off(struct e1000_hw *hw);
s32 e1000_id_led_init(struct e1000_hw *hw);
void e1000_reset_adaptive(struct e1000_hw *hw);
void e1000_update_adaptive(struct e1000_hw *hw);
s32 e1000_get_cable_length(struct e1000_hw *hw);
s32 e1000_validate_mdi_setting(struct e1000_hw *hw);
s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, u32 offset,
u8 data);
s32 e1000_get_phy_info(struct e1000_hw *hw);
void e1000_release_phy(struct e1000_hw *hw);
s32 e1000_acquire_phy(struct e1000_hw *hw);
s32 e1000_phy_hw_reset(struct e1000_hw *hw);
s32 e1000_phy_commit(struct e1000_hw *hw);
void e1000_power_up_phy(struct e1000_hw *hw);
void e1000_power_down_phy(struct e1000_hw *hw);
s32 e1000_read_mac_addr(struct e1000_hw *hw);
s32 e1000_read_pba_string(struct e1000_hw *hw, u8 *pba_num, u32 pba_num_size);
s32 e1000_read_pba_length(struct e1000_hw *hw, u32 *pba_num_size);
void e1000_reload_nvm(struct e1000_hw *hw);
s32 e1000_update_nvm_checksum(struct e1000_hw *hw);
s32 e1000_validate_nvm_checksum(struct e1000_hw *hw);
s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
s32 e1000_wait_autoneg(struct e1000_hw *hw);
s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
bool e1000_check_mng_mode(struct e1000_hw *hw);
bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
s32 e1000_mng_enable_host_if(struct e1000_hw *hw);
s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length,
u16 offset, u8 *sum);
s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
struct e1000_host_mng_command_header *hdr);
s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length);
s32 e1000_get_thermal_sensor_data(struct e1000_hw *hw);
s32 e1000_init_thermal_sensor_thresh(struct e1000_hw *hw);
/*
* TBI_ACCEPT macro definition:
*
* This macro requires:
* adapter = a pointer to struct e1000_hw
* status = the 8 bit status field of the Rx descriptor with EOP set
* error = the 8 bit error field of the Rx descriptor with EOP set
* length = the sum of all the length fields of the Rx descriptors that
* make up the current frame
* last_byte = the last byte of the frame DMAed by the hardware
* max_frame_length = the maximum frame length we want to accept.
* min_frame_length = the minimum frame length we want to accept.
*
* This macro is a conditional that should be used in the interrupt
* handler's Rx processing routine when RxErrors have been detected.
*
* Typical use:
* ...
* if (TBI_ACCEPT) {
* accept_frame = true;
* e1000_tbi_adjust_stats(adapter, MacAddress);
* frame_length--;
* } else {
* accept_frame = false;
* }
* ...
*/
/* The carrier extension symbol, as received by the NIC. */
#define CARRIER_EXTENSION 0x0F
#define TBI_ACCEPT(a, status, errors, length, last_byte, \
min_frame_size, max_frame_size) \
(e1000_tbi_sbp_enabled_82543(a) && \
(((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \
((last_byte) == CARRIER_EXTENSION) && \
(((status) & E1000_RXD_STAT_VP) ? \
(((length) > (min_frame_size - VLAN_TAG_SIZE)) && \
((length) <= (max_frame_size + 1))) : \
(((length) > min_frame_size) && \
((length) <= (max_frame_size + VLAN_TAG_SIZE + 1)))))
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,770 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _E1000_HW_H_
#define _E1000_HW_H_
#include "e1000_osdep.h"
#include "e1000_regs.h"
#include "e1000_defines.h"
struct e1000_hw;
#define E1000_DEV_ID_82576 0x10C9
#define E1000_DEV_ID_82576_FIBER 0x10E6
#define E1000_DEV_ID_82576_SERDES 0x10E7
#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8
#define E1000_DEV_ID_82576_QUAD_COPPER_ET2 0x1526
#define E1000_DEV_ID_82576_NS 0x150A
#define E1000_DEV_ID_82576_NS_SERDES 0x1518
#define E1000_DEV_ID_82576_SERDES_QUAD 0x150D
#define E1000_DEV_ID_82575EB_COPPER 0x10A7
#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9
#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6
#define E1000_DEV_ID_82580_COPPER 0x150E
#define E1000_DEV_ID_82580_FIBER 0x150F
#define E1000_DEV_ID_82580_SERDES 0x1510
#define E1000_DEV_ID_82580_SGMII 0x1511
#define E1000_DEV_ID_82580_COPPER_DUAL 0x1516
#define E1000_DEV_ID_82580_QUAD_FIBER 0x1527
#define E1000_DEV_ID_I350_COPPER 0x1521
#define E1000_DEV_ID_I350_FIBER 0x1522
#define E1000_DEV_ID_I350_SERDES 0x1523
#define E1000_DEV_ID_I350_SGMII 0x1524
#define E1000_DEV_ID_I350_DA4 0x1546
#define E1000_DEV_ID_DH89XXCC_SGMII 0x0438
#define E1000_DEV_ID_DH89XXCC_SERDES 0x043A
#define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C
#define E1000_DEV_ID_DH89XXCC_SFP 0x0440
#define E1000_REVISION_0 0
#define E1000_REVISION_1 1
#define E1000_REVISION_2 2
#define E1000_REVISION_3 3
#define E1000_REVISION_4 4
#define E1000_FUNC_0 0
#define E1000_FUNC_1 1
#define E1000_FUNC_2 2
#define E1000_FUNC_3 3
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN2 6
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN3 9
enum e1000_mac_type {
e1000_undefined = 0,
e1000_82575,
e1000_82576,
e1000_82580,
e1000_i350,
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
};
enum e1000_media_type {
e1000_media_type_unknown = 0,
e1000_media_type_copper = 1,
e1000_media_type_fiber = 2,
e1000_media_type_internal_serdes = 3,
e1000_num_media_types
};
enum e1000_nvm_type {
e1000_nvm_unknown = 0,
e1000_nvm_none,
e1000_nvm_eeprom_spi,
e1000_nvm_flash_hw,
e1000_nvm_flash_sw
};
enum e1000_nvm_override {
e1000_nvm_override_none = 0,
e1000_nvm_override_spi_small,
e1000_nvm_override_spi_large,
};
enum e1000_phy_type {
e1000_phy_unknown = 0,
e1000_phy_none,
e1000_phy_m88,
e1000_phy_igp,
e1000_phy_igp_2,
e1000_phy_gg82563,
e1000_phy_igp_3,
e1000_phy_ife,
e1000_phy_82580,
e1000_phy_vf,
};
enum e1000_bus_type {
e1000_bus_type_unknown = 0,
e1000_bus_type_pci,
e1000_bus_type_pcix,
e1000_bus_type_pci_express,
e1000_bus_type_reserved
};
enum e1000_bus_speed {
e1000_bus_speed_unknown = 0,
e1000_bus_speed_33,
e1000_bus_speed_66,
e1000_bus_speed_100,
e1000_bus_speed_120,
e1000_bus_speed_133,
e1000_bus_speed_2500,
e1000_bus_speed_5000,
e1000_bus_speed_reserved
};
enum e1000_bus_width {
e1000_bus_width_unknown = 0,
e1000_bus_width_pcie_x1,
e1000_bus_width_pcie_x2,
e1000_bus_width_pcie_x4 = 4,
e1000_bus_width_pcie_x8 = 8,
e1000_bus_width_32,
e1000_bus_width_64,
e1000_bus_width_reserved
};
enum e1000_1000t_rx_status {
e1000_1000t_rx_status_not_ok = 0,
e1000_1000t_rx_status_ok,
e1000_1000t_rx_status_undefined = 0xFF
};
enum e1000_rev_polarity {
e1000_rev_polarity_normal = 0,
e1000_rev_polarity_reversed,
e1000_rev_polarity_undefined = 0xFF
};
enum e1000_fc_mode {
e1000_fc_none = 0,
e1000_fc_rx_pause,
e1000_fc_tx_pause,
e1000_fc_full,
e1000_fc_default = 0xFF
};
enum e1000_ms_type {
e1000_ms_hw_default = 0,
e1000_ms_force_master,
e1000_ms_force_slave,
e1000_ms_auto
};
enum e1000_smart_speed {
e1000_smart_speed_default = 0,
e1000_smart_speed_on,
e1000_smart_speed_off
};
enum e1000_serdes_link_state {
e1000_serdes_link_down = 0,
e1000_serdes_link_autoneg_progress,
e1000_serdes_link_autoneg_complete,
e1000_serdes_link_forced_up
};
#ifndef __le16
#define __le16 u16
#endif
#ifndef __le32
#define __le32 u32
#endif
#ifndef __le64
#define __le64 u64
#endif
/* Receive Descriptor */
struct e1000_rx_desc {
__le64 buffer_addr; /* Address of the descriptor's data buffer */
__le16 length; /* Length of data DMAed into data buffer */
__le16 csum; /* Packet checksum */
u8 status; /* Descriptor status */
u8 errors; /* Descriptor Errors */
__le16 special;
};
/* Receive Descriptor - Extended */
union e1000_rx_desc_extended {
struct {
__le64 buffer_addr;
__le64 reserved;
} read;
struct {
struct {
__le32 mrq; /* Multiple Rx Queues */
union {
__le32 rss; /* RSS Hash */
struct {
__le16 ip_id; /* IP id */
__le16 csum; /* Packet Checksum */
} csum_ip;
} hi_dword;
} lower;
struct {
__le32 status_error; /* ext status/error */
__le16 length;
__le16 vlan; /* VLAN tag */
} upper;
} wb; /* writeback */
};
#define MAX_PS_BUFFERS 4
/* Receive Descriptor - Packet Split */
union e1000_rx_desc_packet_split {
struct {
/* one buffer for protocol header(s), three data buffers */
__le64 buffer_addr[MAX_PS_BUFFERS];
} read;
struct {
struct {
__le32 mrq; /* Multiple Rx Queues */
union {
__le32 rss; /* RSS Hash */
struct {
__le16 ip_id; /* IP id */
__le16 csum; /* Packet Checksum */
} csum_ip;
} hi_dword;
} lower;
struct {
__le32 status_error; /* ext status/error */
__le16 length0; /* length of buffer 0 */
__le16 vlan; /* VLAN tag */
} middle;
struct {
__le16 header_status;
__le16 length[3]; /* length of buffers 1-3 */
} upper;
__le64 reserved;
} wb; /* writeback */
};
/* Transmit Descriptor */
struct e1000_tx_desc {
__le64 buffer_addr; /* Address of the descriptor's data buffer */
union {
__le32 data;
struct {
__le16 length; /* Data buffer length */
u8 cso; /* Checksum offset */
u8 cmd; /* Descriptor control */
} flags;
} lower;
union {
__le32 data;
struct {
u8 status; /* Descriptor status */
u8 css; /* Checksum start */
__le16 special;
} fields;
} upper;
};
/* Offload Context Descriptor */
struct e1000_context_desc {
union {
__le32 ip_config;
struct {
u8 ipcss; /* IP checksum start */
u8 ipcso; /* IP checksum offset */
__le16 ipcse; /* IP checksum end */
} ip_fields;
} lower_setup;
union {
__le32 tcp_config;
struct {
u8 tucss; /* TCP checksum start */
u8 tucso; /* TCP checksum offset */
__le16 tucse; /* TCP checksum end */
} tcp_fields;
} upper_setup;
__le32 cmd_and_length;
union {
__le32 data;
struct {
u8 status; /* Descriptor status */
u8 hdr_len; /* Header length */
__le16 mss; /* Maximum segment size */
} fields;
} tcp_seg_setup;
};
/* Offload data descriptor */
struct e1000_data_desc {
__le64 buffer_addr; /* Address of the descriptor's buffer address */
union {
__le32 data;
struct {
__le16 length; /* Data buffer length */
u8 typ_len_ext;
u8 cmd;
} flags;
} lower;
union {
__le32 data;
struct {
u8 status; /* Descriptor status */
u8 popts; /* Packet Options */
__le16 special;
} fields;
} upper;
};
/* Statistics counters collected by the MAC */
struct e1000_hw_stats {
u64 crcerrs;
u64 algnerrc;
u64 symerrs;
u64 rxerrc;
u64 mpc;
u64 scc;
u64 ecol;
u64 mcc;
u64 latecol;
u64 colc;
u64 dc;
u64 tncrs;
u64 sec;
u64 cexterr;
u64 rlec;
u64 xonrxc;
u64 xontxc;
u64 xoffrxc;
u64 xofftxc;
u64 fcruc;
u64 prc64;
u64 prc127;
u64 prc255;
u64 prc511;
u64 prc1023;
u64 prc1522;
u64 gprc;
u64 bprc;
u64 mprc;
u64 gptc;
u64 gorc;
u64 gotc;
u64 rnbc;
u64 ruc;
u64 rfc;
u64 roc;
u64 rjc;
u64 mgprc;
u64 mgpdc;
u64 mgptc;
u64 tor;
u64 tot;
u64 tpr;
u64 tpt;
u64 ptc64;
u64 ptc127;
u64 ptc255;
u64 ptc511;
u64 ptc1023;
u64 ptc1522;
u64 mptc;
u64 bptc;
u64 tsctc;
u64 tsctfc;
u64 iac;
u64 icrxptc;
u64 icrxatc;
u64 ictxptc;
u64 ictxatc;
u64 ictxqec;
u64 ictxqmtc;
u64 icrxdmtc;
u64 icrxoc;
u64 cbtmpc;
u64 htdpmc;
u64 cbrdpc;
u64 cbrmpc;
u64 rpthc;
u64 hgptc;
u64 htcbdpc;
u64 hgorc;
u64 hgotc;
u64 lenerrs;
u64 scvpc;
u64 hrmpc;
u64 doosync;
u64 o2bgptc;
u64 o2bspc;
u64 b2ospc;
u64 b2ogprc;
};
struct e1000_phy_stats {
u32 idle_errors;
u32 receive_errors;
};
struct e1000_host_mng_dhcp_cookie {
u32 signature;
u8 status;
u8 reserved0;
u16 vlan_id;
u32 reserved1;
u16 reserved2;
u8 reserved3;
u8 checksum;
};
/* Host Interface "Rev 1" */
struct e1000_host_command_header {
u8 command_id;
u8 command_length;
u8 command_options;
u8 checksum;
};
#define E1000_HI_MAX_DATA_LENGTH 252
struct e1000_host_command_info {
struct e1000_host_command_header command_header;
u8 command_data[E1000_HI_MAX_DATA_LENGTH];
};
/* Host Interface "Rev 2" */
struct e1000_host_mng_command_header {
u8 command_id;
u8 checksum;
u16 reserved1;
u16 reserved2;
u16 command_length;
};
#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8
struct e1000_host_mng_command_info {
struct e1000_host_mng_command_header command_header;
u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH];
};
#include "e1000_mac.h"
#include "e1000_phy.h"
#include "e1000_nvm.h"
#include "e1000_manage.h"
#include "e1000_mbx.h"
struct e1000_mac_operations {
/* Function pointers for the MAC. */
s32 (*init_params)(struct e1000_hw *);
s32 (*id_led_init)(struct e1000_hw *);
s32 (*blink_led)(struct e1000_hw *);
s32 (*check_for_link)(struct e1000_hw *);
bool (*check_mng_mode)(struct e1000_hw *hw);
s32 (*cleanup_led)(struct e1000_hw *);
void (*clear_hw_cntrs)(struct e1000_hw *);
void (*clear_vfta)(struct e1000_hw *);
s32 (*get_bus_info)(struct e1000_hw *);
void (*set_lan_id)(struct e1000_hw *);
s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
s32 (*led_on)(struct e1000_hw *);
s32 (*led_off)(struct e1000_hw *);
void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32);
s32 (*reset_hw)(struct e1000_hw *);
s32 (*init_hw)(struct e1000_hw *);
void (*shutdown_serdes)(struct e1000_hw *);
void (*power_up_serdes)(struct e1000_hw *);
s32 (*setup_link)(struct e1000_hw *);
s32 (*setup_physical_interface)(struct e1000_hw *);
s32 (*setup_led)(struct e1000_hw *);
void (*write_vfta)(struct e1000_hw *, u32, u32);
void (*config_collision_dist)(struct e1000_hw *);
void (*rar_set)(struct e1000_hw *, u8*, u32);
s32 (*read_mac_addr)(struct e1000_hw *);
s32 (*validate_mdi_setting)(struct e1000_hw *);
s32 (*mng_host_if_write)(struct e1000_hw *, u8*, u16, u16, u8*);
s32 (*mng_write_cmd_header)(struct e1000_hw *hw,
struct e1000_host_mng_command_header*);
s32 (*mng_enable_host_if)(struct e1000_hw *);
s32 (*wait_autoneg)(struct e1000_hw *);
s32 (*get_thermal_sensor_data)(struct e1000_hw *);
s32 (*init_thermal_sensor_thresh)(struct e1000_hw *);
s32 (*acquire_swfw_sync)(struct e1000_hw *, u16);
void (*release_swfw_sync)(struct e1000_hw *, u16);
};
/*
* When to use various PHY register access functions:
*
* Func Caller
* Function Does Does When to use
* ~~~~~~~~~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* X_reg L,P,A n/a for simple PHY reg accesses
* X_reg_locked P,A L for multiple accesses of different regs
* on different pages
* X_reg_page A L,P for multiple accesses of different regs
* on the same page
*
* Where X=[read|write], L=locking, P=sets page, A=register access
*
*/
struct e1000_phy_operations {
s32 (*init_params)(struct e1000_hw *);
s32 (*acquire)(struct e1000_hw *);
s32 (*check_polarity)(struct e1000_hw *);
s32 (*check_reset_block)(struct e1000_hw *);
s32 (*commit)(struct e1000_hw *);
s32 (*force_speed_duplex)(struct e1000_hw *);
s32 (*get_cfg_done)(struct e1000_hw *hw);
s32 (*get_cable_length)(struct e1000_hw *);
s32 (*get_info)(struct e1000_hw *);
s32 (*set_page)(struct e1000_hw *, u16);
s32 (*read_reg)(struct e1000_hw *, u32, u16 *);
s32 (*read_reg_locked)(struct e1000_hw *, u32, u16 *);
s32 (*read_reg_page)(struct e1000_hw *, u32, u16 *);
void (*release)(struct e1000_hw *);
s32 (*reset)(struct e1000_hw *);
s32 (*set_d0_lplu_state)(struct e1000_hw *, bool);
s32 (*set_d3_lplu_state)(struct e1000_hw *, bool);
s32 (*write_reg)(struct e1000_hw *, u32, u16);
s32 (*write_reg_locked)(struct e1000_hw *, u32, u16);
s32 (*write_reg_page)(struct e1000_hw *, u32, u16);
void (*power_up)(struct e1000_hw *);
void (*power_down)(struct e1000_hw *);
s32 (*read_i2c_byte)(struct e1000_hw *, u8, u8, u8 *);
s32 (*write_i2c_byte)(struct e1000_hw *, u8, u8, u8);
};
struct e1000_nvm_operations {
s32 (*init_params)(struct e1000_hw *);
s32 (*acquire)(struct e1000_hw *);
s32 (*read)(struct e1000_hw *, u16, u16, u16 *);
void (*release)(struct e1000_hw *);
void (*reload)(struct e1000_hw *);
s32 (*update)(struct e1000_hw *);
s32 (*valid_led_default)(struct e1000_hw *, u16 *);
s32 (*validate)(struct e1000_hw *);
s32 (*write)(struct e1000_hw *, u16, u16, u16 *);
};
#define E1000_MAX_SENSORS 3
struct e1000_thermal_diode_data {
u8 location;
u8 temp;
u8 caution_thresh;
u8 max_op_thresh;
};
struct e1000_thermal_sensor_data {
struct e1000_thermal_diode_data sensor[E1000_MAX_SENSORS];
};
struct e1000_mac_info {
struct e1000_mac_operations ops;
u8 addr[ETH_ADDR_LEN];
u8 perm_addr[ETH_ADDR_LEN];
enum e1000_mac_type type;
u32 collision_delta;
u32 ledctl_default;
u32 ledctl_mode1;
u32 ledctl_mode2;
u32 mc_filter_type;
u32 tx_packet_delta;
u32 txcw;
u16 current_ifs_val;
u16 ifs_max_val;
u16 ifs_min_val;
u16 ifs_ratio;
u16 ifs_step_size;
u16 mta_reg_count;
u16 uta_reg_count;
/* Maximum size of the MTA register table in all supported adapters */
#define MAX_MTA_REG 128
u32 mta_shadow[MAX_MTA_REG];
u16 rar_entry_count;
u8 forced_speed_duplex;
bool adaptive_ifs;
bool has_fwsm;
bool arc_subsystem_valid;
bool asf_firmware_present;
bool autoneg;
bool autoneg_failed;
bool get_link_status;
bool in_ifs_mode;
enum e1000_serdes_link_state serdes_link_state;
bool serdes_has_link;
bool tx_pkt_filtering;
struct e1000_thermal_sensor_data thermal_sensor_data;
};
struct e1000_phy_info {
struct e1000_phy_operations ops;
enum e1000_phy_type type;
enum e1000_1000t_rx_status local_rx;
enum e1000_1000t_rx_status remote_rx;
enum e1000_ms_type ms_type;
enum e1000_ms_type original_ms_type;
enum e1000_rev_polarity cable_polarity;
enum e1000_smart_speed smart_speed;
u32 addr;
u32 id;
u32 reset_delay_us; /* in usec */
u32 revision;
enum e1000_media_type media_type;
u16 autoneg_advertised;
u16 autoneg_mask;
u16 cable_length;
u16 max_cable_length;
u16 min_cable_length;
u8 mdix;
bool disable_polarity_correction;
bool is_mdix;
bool polarity_correction;
bool reset_disable;
bool speed_downgraded;
bool autoneg_wait_to_complete;
};
struct e1000_nvm_info {
struct e1000_nvm_operations ops;
enum e1000_nvm_type type;
enum e1000_nvm_override override;
u32 flash_bank_size;
u32 flash_base_addr;
u16 word_size;
u16 delay_usec;
u16 address_bits;
u16 opcode_bits;
u16 page_size;
};
struct e1000_bus_info {
enum e1000_bus_type type;
enum e1000_bus_speed speed;
enum e1000_bus_width width;
u16 func;
u16 pci_cmd_word;
};
struct e1000_fc_info {
u32 high_water; /* Flow control high-water mark */
u32 low_water; /* Flow control low-water mark */
u16 pause_time; /* Flow control pause timer */
u16 refresh_time; /* Flow control refresh timer */
bool send_xon; /* Flow control send XON */
bool strict_ieee; /* Strict IEEE mode */
enum e1000_fc_mode current_mode; /* FC mode in effect */
enum e1000_fc_mode requested_mode; /* FC mode requested by caller */
};
struct e1000_mbx_operations {
s32 (*init_params)(struct e1000_hw *hw);
s32 (*read)(struct e1000_hw *, u32 *, u16, u16);
s32 (*write)(struct e1000_hw *, u32 *, u16, u16);
s32 (*read_posted)(struct e1000_hw *, u32 *, u16, u16);
s32 (*write_posted)(struct e1000_hw *, u32 *, u16, u16);
s32 (*check_for_msg)(struct e1000_hw *, u16);
s32 (*check_for_ack)(struct e1000_hw *, u16);
s32 (*check_for_rst)(struct e1000_hw *, u16);
};
struct e1000_mbx_stats {
u32 msgs_tx;
u32 msgs_rx;
u32 acks;
u32 reqs;
u32 rsts;
};
struct e1000_mbx_info {
struct e1000_mbx_operations ops;
struct e1000_mbx_stats stats;
u32 timeout;
u32 usec_delay;
u16 size;
};
struct e1000_dev_spec_82575 {
bool sgmii_active;
bool global_device_reset;
bool eee_disable;
bool module_plugged;
u32 mtu;
};
struct e1000_dev_spec_vf {
u32 vf_number;
u32 v2p_mailbox;
};
struct e1000_hw {
void *back;
u8 __iomem *hw_addr;
u8 __iomem *flash_address;
unsigned long io_base;
struct e1000_mac_info mac;
struct e1000_fc_info fc;
struct e1000_phy_info phy;
struct e1000_nvm_info nvm;
struct e1000_bus_info bus;
struct e1000_mbx_info mbx;
struct e1000_host_mng_dhcp_cookie mng_cookie;
union {
struct e1000_dev_spec_82575 _82575;
struct e1000_dev_spec_vf vf;
} dev_spec;
u16 device_id;
u16 subsystem_vendor_id;
u16 subsystem_device_id;
u16 vendor_id;
u8 revision_id;
};
#include "e1000_82575.h"
/* These functions must be implemented by drivers */
s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
s32 e1000_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,85 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _E1000_MAC_H_
#define _E1000_MAC_H_
/*
* Functions that should not be called directly from drivers but can be used
* by other files in this 'shared code'
*/
void e1000_init_mac_ops_generic(struct e1000_hw *hw);
void e1000_null_mac_generic(struct e1000_hw *hw);
s32 e1000_null_ops_generic(struct e1000_hw *hw);
s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d);
bool e1000_null_mng_mode(struct e1000_hw *hw);
void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a);
void e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b);
void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a);
s32 e1000_blink_led_generic(struct e1000_hw *hw);
s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw);
s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw);
s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw);
s32 e1000_cleanup_led_generic(struct e1000_hw *hw);
s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw);
s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw);
s32 e1000_force_mac_fc_generic(struct e1000_hw *hw);
s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw);
s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw);
void e1000_set_lan_id_single_port(struct e1000_hw *hw);
s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw);
s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
u16 *duplex);
s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,
u16 *speed, u16 *duplex);
s32 e1000_id_led_init_generic(struct e1000_hw *hw);
s32 e1000_led_on_generic(struct e1000_hw *hw);
s32 e1000_led_off_generic(struct e1000_hw *hw);
void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
u8 *mc_addr_list, u32 mc_addr_count);
s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw);
s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw);
s32 e1000_setup_led_generic(struct e1000_hw *hw);
s32 e1000_setup_link_generic(struct e1000_hw *hw);
s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg,
u32 offset, u8 data);
u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr);
void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw);
void e1000_clear_vfta_generic(struct e1000_hw *hw);
void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count);
void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw);
void e1000_put_hw_semaphore_generic(struct e1000_hw *hw);
void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index);
s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw);
void e1000_reset_adaptive_generic(struct e1000_hw *hw);
void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop);
void e1000_update_adaptive_generic(struct e1000_hw *hw);
void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value);
#endif

View File

@ -0,0 +1,441 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#include "e1000_api.h"
/**
* e1000_calculate_checksum - Calculate checksum for buffer
* @buffer: pointer to EEPROM
* @length: size of EEPROM to calculate a checksum for
*
* Calculates the checksum for some buffer on a specified length. The
* checksum calculated is returned.
**/
u8 e1000_calculate_checksum(u8 *buffer, u32 length)
{
u32 i;
u8 sum = 0;
DEBUGFUNC("e1000_calculate_checksum");
if (!buffer)
return 0;
for (i = 0; i < length; i++)
sum += buffer[i];
return (u8) (0 - sum);
}
/**
* e1000_mng_enable_host_if_generic - Checks host interface is enabled
* @hw: pointer to the HW structure
*
* Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
*
* This function checks whether the HOST IF is enabled for command operation
* and also checks whether the previous command is completed. It busy waits
* in case of previous command is not completed.
**/
s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
{
u32 hicr;
u8 i;
DEBUGFUNC("e1000_mng_enable_host_if_generic");
if (!hw->mac.arc_subsystem_valid) {
DEBUGOUT("ARC subsystem not valid.\n");
return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
/* Check that the host interface is enabled. */
hicr = E1000_READ_REG(hw, E1000_HICR);
if ((hicr & E1000_HICR_EN) == 0) {
DEBUGOUT("E1000_HOST_EN bit disabled.\n");
return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
/* check the previous command is completed */
for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
hicr = E1000_READ_REG(hw, E1000_HICR);
if (!(hicr & E1000_HICR_C))
break;
msec_delay_irq(1);
}
if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
DEBUGOUT("Previous command timeout failed .\n");
return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
return E1000_SUCCESS;
}
/**
* e1000_check_mng_mode_generic - Generic check management mode
* @hw: pointer to the HW structure
*
* Reads the firmware semaphore register and returns true (>0) if
* manageability is enabled, else false (0).
**/
bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
{
u32 fwsm = E1000_READ_REG(hw, E1000_FWSM);
DEBUGFUNC("e1000_check_mng_mode_generic");
return (fwsm & E1000_FWSM_MODE_MASK) ==
(E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
}
/**
* e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on Tx
* @hw: pointer to the HW structure
*
* Enables packet filtering on transmit packets if manageability is enabled
* and host interface is enabled.
**/
bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
{
struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
u32 *buffer = (u32 *)&hw->mng_cookie;
u32 offset;
s32 ret_val, hdr_csum, csum;
u8 i, len;
DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
hw->mac.tx_pkt_filtering = true;
/* No manageability, no filtering */
if (!hw->mac.ops.check_mng_mode(hw)) {
hw->mac.tx_pkt_filtering = false;
return hw->mac.tx_pkt_filtering;
}
/*
* If we can't read from the host interface for whatever
* reason, disable filtering.
*/
ret_val = hw->mac.ops.mng_enable_host_if(hw);
if (ret_val != E1000_SUCCESS) {
hw->mac.tx_pkt_filtering = false;
return hw->mac.tx_pkt_filtering;
}
/* Read in the header. Length and offset are in dwords. */
len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
for (i = 0; i < len; i++)
*(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
offset + i);
hdr_csum = hdr->checksum;
hdr->checksum = 0;
csum = e1000_calculate_checksum((u8 *)hdr,
E1000_MNG_DHCP_COOKIE_LENGTH);
/*
* If either the checksums or signature don't match, then
* the cookie area isn't considered valid, in which case we
* take the safe route of assuming Tx filtering is enabled.
*/
if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
hw->mac.tx_pkt_filtering = true;
return hw->mac.tx_pkt_filtering;
}
/* Cookie area is valid, make the final check for filtering. */
if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
hw->mac.tx_pkt_filtering = false;
return hw->mac.tx_pkt_filtering;
}
/**
* e1000_mng_write_cmd_header_generic - Writes manageability command header
* @hw: pointer to the HW structure
* @hdr: pointer to the host interface command header
*
* Writes the command header after does the checksum calculation.
**/
s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
struct e1000_host_mng_command_header *hdr)
{
u16 i, length = sizeof(struct e1000_host_mng_command_header);
DEBUGFUNC("e1000_mng_write_cmd_header_generic");
/* Write the whole command header structure with new checksum. */
hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
length >>= 2;
/* Write the relevant command block into the ram area. */
for (i = 0; i < length; i++) {
E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
*((u32 *) hdr + i));
E1000_WRITE_FLUSH(hw);
}
return E1000_SUCCESS;
}
/**
* e1000_mng_host_if_write_generic - Write to the manageability host interface
* @hw: pointer to the HW structure
* @buffer: pointer to the host interface buffer
* @length: size of the buffer
* @offset: location in the buffer to write to
* @sum: sum of the data (not checksum)
*
* This function writes the buffer content at the offset given on the host if.
* It also does alignment considerations to do the writes in most efficient
* way. Also fills up the sum of the buffer in *buffer parameter.
**/
s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
u16 length, u16 offset, u8 *sum)
{
u8 *tmp;
u8 *bufptr = buffer;
u32 data = 0;
u16 remaining, i, j, prev_bytes;
DEBUGFUNC("e1000_mng_host_if_write_generic");
/* sum = only sum of the data and it is not checksum */
if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH)
return -E1000_ERR_PARAM;
tmp = (u8 *)&data;
prev_bytes = offset & 0x3;
offset >>= 2;
if (prev_bytes) {
data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
for (j = prev_bytes; j < sizeof(u32); j++) {
*(tmp + j) = *bufptr++;
*sum += *(tmp + j);
}
E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
length -= j - prev_bytes;
offset++;
}
remaining = length & 0x3;
length -= remaining;
/* Calculate length in DWORDs */
length >>= 2;
/*
* The device driver writes the relevant command block into the
* ram area.
*/
for (i = 0; i < length; i++) {
for (j = 0; j < sizeof(u32); j++) {
*(tmp + j) = *bufptr++;
*sum += *(tmp + j);
}
E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
data);
}
if (remaining) {
for (j = 0; j < sizeof(u32); j++) {
if (j < remaining)
*(tmp + j) = *bufptr++;
else
*(tmp + j) = 0;
*sum += *(tmp + j);
}
E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
data);
}
return E1000_SUCCESS;
}
/**
* e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
* @hw: pointer to the HW structure
* @buffer: pointer to the host interface
* @length: size of the buffer
*
* Writes the DHCP information to the host interface.
**/
s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
u16 length)
{
struct e1000_host_mng_command_header hdr;
s32 ret_val;
u32 hicr;
DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
hdr.command_length = length;
hdr.reserved1 = 0;
hdr.reserved2 = 0;
hdr.checksum = 0;
/* Enable the host interface */
ret_val = hw->mac.ops.mng_enable_host_if(hw);
if (ret_val)
return ret_val;
/* Populate the host interface with the contents of "buffer". */
ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
sizeof(hdr), &(hdr.checksum));
if (ret_val)
return ret_val;
/* Write the manageability command header */
ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
if (ret_val)
return ret_val;
/* Tell the ARC a new command is pending. */
hicr = E1000_READ_REG(hw, E1000_HICR);
E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
return E1000_SUCCESS;
}
/**
* e1000_enable_mng_pass_thru - Check if management passthrough is needed
* @hw: pointer to the HW structure
*
* Verifies the hardware needs to leave interface enabled so that frames can
* be directed to and from the management interface.
**/
bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
{
u32 manc;
u32 fwsm, factps;
DEBUGFUNC("e1000_enable_mng_pass_thru");
if (!hw->mac.asf_firmware_present)
return false;
manc = E1000_READ_REG(hw, E1000_MANC);
if (!(manc & E1000_MANC_RCV_TCO_EN))
return false;
if (hw->mac.has_fwsm) {
fwsm = E1000_READ_REG(hw, E1000_FWSM);
factps = E1000_READ_REG(hw, E1000_FACTPS);
if (!(factps & E1000_FACTPS_MNGCG) &&
((fwsm & E1000_FWSM_MODE_MASK) ==
(e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT)))
return true;
} else if ((manc & E1000_MANC_SMBUS_EN) &&
!(manc & E1000_MANC_ASF_EN)) {
return true;
}
return false;
}
/**
* e1000_host_interface_command - Writes buffer to host interface
* @hw: pointer to the HW structure
* @buffer: contains a command to write
* @length: the byte length of the buffer, must be multiple of 4 bytes
*
* Writes a buffer to the Host Interface. Upon success, returns E1000_SUCCESS
* else returns E1000_ERR_HOST_INTERFACE_COMMAND.
**/
s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length)
{
u32 hicr, i;
DEBUGFUNC("e1000_host_interface_command");
if (!(hw->mac.arc_subsystem_valid)) {
DEBUGOUT("Hardware doesn't support host interface command.\n");
return E1000_SUCCESS;
}
if (!hw->mac.asf_firmware_present) {
DEBUGOUT("Firmware is not present.\n");
return E1000_SUCCESS;
}
if (length == 0 || length & 0x3 ||
length > E1000_HI_MAX_BLOCK_BYTE_LENGTH) {
DEBUGOUT("Buffer length failure.\n");
return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
/* Check that the host interface is enabled. */
hicr = E1000_READ_REG(hw, E1000_HICR);
if ((hicr & E1000_HICR_EN) == 0) {
DEBUGOUT("E1000_HOST_EN bit disabled.\n");
return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
/* Calculate length in DWORDs */
length >>= 2;
/*
* The device driver writes the relevant command block
* into the ram area.
*/
for (i = 0; i < length; i++)
E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
*((u32 *)buffer + i));
/* Setting this bit tells the ARC that a new command is pending. */
E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
hicr = E1000_READ_REG(hw, E1000_HICR);
if (!(hicr & E1000_HICR_C))
break;
msec_delay(1);
}
/* Check command successful completion. */
if (i == E1000_HI_COMMAND_TIMEOUT ||
(!(E1000_READ_REG(hw, E1000_HICR) & E1000_HICR_SV))) {
DEBUGOUT("Command has failed with no status valid.\n");
return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
for (i = 0; i < length; i++)
*((u32 *)buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
E1000_HOST_IF,
i);
return E1000_SUCCESS;
}

View File

@ -0,0 +1,82 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _E1000_MANAGE_H_
#define _E1000_MANAGE_H_
bool e1000_check_mng_mode_generic(struct e1000_hw *hw);
bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw);
s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw);
s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
u16 length, u16 offset, u8 *sum);
s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
struct e1000_host_mng_command_header *hdr);
s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw,
u8 *buffer, u16 length);
bool e1000_enable_mng_pass_thru(struct e1000_hw *hw);
u8 e1000_calculate_checksum(u8 *buffer, u32 length);
s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length);
enum e1000_mng_mode {
e1000_mng_mode_none = 0,
e1000_mng_mode_asf,
e1000_mng_mode_pt,
e1000_mng_mode_ipmi,
e1000_mng_mode_host_if_only
};
#define E1000_FACTPS_MNGCG 0x20000000
#define E1000_FWSM_MODE_MASK 0xE
#define E1000_FWSM_MODE_SHIFT 1
#define E1000_MNG_IAMT_MODE 0x3
#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10
#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0
#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10
#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64
#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING 0x1
#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2
#define E1000_VFTA_ENTRY_SHIFT 5
#define E1000_VFTA_ENTRY_MASK 0x7F
#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F
#define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Num of bytes in range */
#define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Num of dwords in range */
#define E1000_HI_COMMAND_TIMEOUT 500 /* Process HI cmd limit */
#define E1000_HICR_EN 0x01 /* Enable bit - RO */
/* Driver sets this bit when done to put command in RAM */
#define E1000_HICR_C 0x02
#define E1000_HICR_SV 0x04 /* Status Validity */
#define E1000_HICR_FW_RESET_ENABLE 0x40
#define E1000_HICR_FW_RESET 0x80
/* Intel(R) Active Management Technology signature */
#define E1000_IAMT_SIGNATURE 0x544D4149
#endif

View File

@ -0,0 +1,522 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#include "e1000_mbx.h"
/**
* e1000_null_mbx_check_for_flag - No-op function, return 0
* @hw: pointer to the HW structure
**/
static s32 e1000_null_mbx_check_for_flag(struct e1000_hw *hw, u16 mbx_id)
{
DEBUGFUNC("e1000_null_mbx_check_flag");
return E1000_SUCCESS;
}
/**
* e1000_null_mbx_transact - No-op function, return 0
* @hw: pointer to the HW structure
**/
static s32 e1000_null_mbx_transact(struct e1000_hw *hw, u32 *msg, u16 size,
u16 mbx_id)
{
DEBUGFUNC("e1000_null_mbx_rw_msg");
return E1000_SUCCESS;
}
/**
* e1000_read_mbx - Reads a message from the mailbox
* @hw: pointer to the HW structure
* @msg: The message buffer
* @size: Length of buffer
* @mbx_id: id of mailbox to read
*
* returns SUCCESS if it successfuly read message from buffer
**/
s32 e1000_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
{
struct e1000_mbx_info *mbx = &hw->mbx;
s32 ret_val = -E1000_ERR_MBX;
DEBUGFUNC("e1000_read_mbx");
/* limit read to size of mailbox */
if (size > mbx->size)
size = mbx->size;
if (mbx->ops.read)
ret_val = mbx->ops.read(hw, msg, size, mbx_id);
return ret_val;
}
/**
* e1000_write_mbx - Write a message to the mailbox
* @hw: pointer to the HW structure
* @msg: The message buffer
* @size: Length of buffer
* @mbx_id: id of mailbox to write
*
* returns SUCCESS if it successfully copied message into the buffer
**/
s32 e1000_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
{
struct e1000_mbx_info *mbx = &hw->mbx;
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_write_mbx");
if (size > mbx->size)
ret_val = -E1000_ERR_MBX;
else if (mbx->ops.write)
ret_val = mbx->ops.write(hw, msg, size, mbx_id);
return ret_val;
}
/**
* e1000_check_for_msg - checks to see if someone sent us mail
* @hw: pointer to the HW structure
* @mbx_id: id of mailbox to check
*
* returns SUCCESS if the Status bit was found or else ERR_MBX
**/
s32 e1000_check_for_msg(struct e1000_hw *hw, u16 mbx_id)
{
struct e1000_mbx_info *mbx = &hw->mbx;
s32 ret_val = -E1000_ERR_MBX;
DEBUGFUNC("e1000_check_for_msg");
if (mbx->ops.check_for_msg)
ret_val = mbx->ops.check_for_msg(hw, mbx_id);
return ret_val;
}
/**
* e1000_check_for_ack - checks to see if someone sent us ACK
* @hw: pointer to the HW structure
* @mbx_id: id of mailbox to check
*
* returns SUCCESS if the Status bit was found or else ERR_MBX
**/
s32 e1000_check_for_ack(struct e1000_hw *hw, u16 mbx_id)
{
struct e1000_mbx_info *mbx = &hw->mbx;
s32 ret_val = -E1000_ERR_MBX;
DEBUGFUNC("e1000_check_for_ack");
if (mbx->ops.check_for_ack)
ret_val = mbx->ops.check_for_ack(hw, mbx_id);
return ret_val;
}
/**
* e1000_check_for_rst - checks to see if other side has reset
* @hw: pointer to the HW structure
* @mbx_id: id of mailbox to check
*
* returns SUCCESS if the Status bit was found or else ERR_MBX
**/
s32 e1000_check_for_rst(struct e1000_hw *hw, u16 mbx_id)
{
struct e1000_mbx_info *mbx = &hw->mbx;
s32 ret_val = -E1000_ERR_MBX;
DEBUGFUNC("e1000_check_for_rst");
if (mbx->ops.check_for_rst)
ret_val = mbx->ops.check_for_rst(hw, mbx_id);
return ret_val;
}
/**
* e1000_poll_for_msg - Wait for message notification
* @hw: pointer to the HW structure
* @mbx_id: id of mailbox to write
*
* returns SUCCESS if it successfully received a message notification
**/
static s32 e1000_poll_for_msg(struct e1000_hw *hw, u16 mbx_id)
{
struct e1000_mbx_info *mbx = &hw->mbx;
int countdown = mbx->timeout;
DEBUGFUNC("e1000_poll_for_msg");
if (!countdown || !mbx->ops.check_for_msg)
goto out;
while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
countdown--;
if (!countdown)
break;
usec_delay(mbx->usec_delay);
}
/* if we failed, all future posted messages fail until reset */
if (!countdown)
mbx->timeout = 0;
out:
return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
}
/**
* e1000_poll_for_ack - Wait for message acknowledgement
* @hw: pointer to the HW structure
* @mbx_id: id of mailbox to write
*
* returns SUCCESS if it successfully received a message acknowledgement
**/
static s32 e1000_poll_for_ack(struct e1000_hw *hw, u16 mbx_id)
{
struct e1000_mbx_info *mbx = &hw->mbx;
int countdown = mbx->timeout;
DEBUGFUNC("e1000_poll_for_ack");
if (!countdown || !mbx->ops.check_for_ack)
goto out;
while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
countdown--;
if (!countdown)
break;
usec_delay(mbx->usec_delay);
}
/* if we failed, all future posted messages fail until reset */
if (!countdown)
mbx->timeout = 0;
out:
return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
}
/**
* e1000_read_posted_mbx - Wait for message notification and receive message
* @hw: pointer to the HW structure
* @msg: The message buffer
* @size: Length of buffer
* @mbx_id: id of mailbox to write
*
* returns SUCCESS if it successfully received a message notification and
* copied it into the receive buffer.
**/
s32 e1000_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
{
struct e1000_mbx_info *mbx = &hw->mbx;
s32 ret_val = -E1000_ERR_MBX;
DEBUGFUNC("e1000_read_posted_mbx");
if (!mbx->ops.read)
goto out;
ret_val = e1000_poll_for_msg(hw, mbx_id);
/* if ack received read message, otherwise we timed out */
if (!ret_val)
ret_val = mbx->ops.read(hw, msg, size, mbx_id);
out:
return ret_val;
}
/**
* e1000_write_posted_mbx - Write a message to the mailbox, wait for ack
* @hw: pointer to the HW structure
* @msg: The message buffer
* @size: Length of buffer
* @mbx_id: id of mailbox to write
*
* returns SUCCESS if it successfully copied message into the buffer and
* received an ack to that message within delay * timeout period
**/
s32 e1000_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
{
struct e1000_mbx_info *mbx = &hw->mbx;
s32 ret_val = -E1000_ERR_MBX;
DEBUGFUNC("e1000_write_posted_mbx");
/* exit if either we can't write or there isn't a defined timeout */
if (!mbx->ops.write || !mbx->timeout)
goto out;
/* send msg */
ret_val = mbx->ops.write(hw, msg, size, mbx_id);
/* if msg sent wait until we receive an ack */
if (!ret_val)
ret_val = e1000_poll_for_ack(hw, mbx_id);
out:
return ret_val;
}
/**
* e1000_init_mbx_ops_generic - Initialize mbx function pointers
* @hw: pointer to the HW structure
*
* Sets the function pointers to no-op functions
**/
void e1000_init_mbx_ops_generic(struct e1000_hw *hw)
{
struct e1000_mbx_info *mbx = &hw->mbx;
mbx->ops.init_params = e1000_null_ops_generic;
mbx->ops.read = e1000_null_mbx_transact;
mbx->ops.write = e1000_null_mbx_transact;
mbx->ops.check_for_msg = e1000_null_mbx_check_for_flag;
mbx->ops.check_for_ack = e1000_null_mbx_check_for_flag;
mbx->ops.check_for_rst = e1000_null_mbx_check_for_flag;
mbx->ops.read_posted = e1000_read_posted_mbx;
mbx->ops.write_posted = e1000_write_posted_mbx;
}
static s32 e1000_check_for_bit_pf(struct e1000_hw *hw, u32 mask)
{
u32 mbvficr = E1000_READ_REG(hw, E1000_MBVFICR);
s32 ret_val = -E1000_ERR_MBX;
if (mbvficr & mask) {
ret_val = E1000_SUCCESS;
E1000_WRITE_REG(hw, E1000_MBVFICR, mask);
}
return ret_val;
}
/**
* e1000_check_for_msg_pf - checks to see if the VF has sent mail
* @hw: pointer to the HW structure
* @vf_number: the VF index
*
* returns SUCCESS if the VF has set the Status bit or else ERR_MBX
**/
static s32 e1000_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number)
{
s32 ret_val = -E1000_ERR_MBX;
DEBUGFUNC("e1000_check_for_msg_pf");
if (!e1000_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) {
ret_val = E1000_SUCCESS;
hw->mbx.stats.reqs++;
}
return ret_val;
}
/**
* e1000_check_for_ack_pf - checks to see if the VF has ACKed
* @hw: pointer to the HW structure
* @vf_number: the VF index
*
* returns SUCCESS if the VF has set the Status bit or else ERR_MBX
**/
static s32 e1000_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number)
{
s32 ret_val = -E1000_ERR_MBX;
DEBUGFUNC("e1000_check_for_ack_pf");
if (!e1000_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) {
ret_val = E1000_SUCCESS;
hw->mbx.stats.acks++;
}
return ret_val;
}
/**
* e1000_check_for_rst_pf - checks to see if the VF has reset
* @hw: pointer to the HW structure
* @vf_number: the VF index
*
* returns SUCCESS if the VF has set the Status bit or else ERR_MBX
**/
static s32 e1000_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number)
{
u32 vflre = E1000_READ_REG(hw, E1000_VFLRE);
s32 ret_val = -E1000_ERR_MBX;
DEBUGFUNC("e1000_check_for_rst_pf");
if (vflre & (1 << vf_number)) {
ret_val = E1000_SUCCESS;
E1000_WRITE_REG(hw, E1000_VFLRE, (1 << vf_number));
hw->mbx.stats.rsts++;
}
return ret_val;
}
/**
* e1000_obtain_mbx_lock_pf - obtain mailbox lock
* @hw: pointer to the HW structure
* @vf_number: the VF index
*
* return SUCCESS if we obtained the mailbox lock
**/
static s32 e1000_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
{
s32 ret_val = -E1000_ERR_MBX;
u32 p2v_mailbox;
DEBUGFUNC("e1000_obtain_mbx_lock_pf");
/* Take ownership of the buffer */
E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU);
/* reserve mailbox for vf use */
p2v_mailbox = E1000_READ_REG(hw, E1000_P2VMAILBOX(vf_number));
if (p2v_mailbox & E1000_P2VMAILBOX_PFU)
ret_val = E1000_SUCCESS;
return ret_val;
}
/**
* e1000_write_mbx_pf - Places a message in the mailbox
* @hw: pointer to the HW structure
* @msg: The message buffer
* @size: Length of buffer
* @vf_number: the VF index
*
* returns SUCCESS if it successfully copied message into the buffer
**/
static s32 e1000_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
u16 vf_number)
{
s32 ret_val;
u16 i;
DEBUGFUNC("e1000_write_mbx_pf");
/* lock the mailbox to prevent pf/vf race condition */
ret_val = e1000_obtain_mbx_lock_pf(hw, vf_number);
if (ret_val)
goto out_no_write;
/* flush msg and acks as we are overwriting the message buffer */
e1000_check_for_msg_pf(hw, vf_number);
e1000_check_for_ack_pf(hw, vf_number);
/* copy the caller specified message to the mailbox memory buffer */
for (i = 0; i < size; i++)
E1000_WRITE_REG_ARRAY(hw, E1000_VMBMEM(vf_number), i, msg[i]);
/* Interrupt VF to tell it a message has been sent and release buffer*/
E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS);
/* update stats */
hw->mbx.stats.msgs_tx++;
out_no_write:
return ret_val;
}
/**
* e1000_read_mbx_pf - Read a message from the mailbox
* @hw: pointer to the HW structure
* @msg: The message buffer
* @size: Length of buffer
* @vf_number: the VF index
*
* This function copies a message from the mailbox buffer to the caller's
* memory buffer. The presumption is that the caller knows that there was
* a message due to a VF request so no polling for message is needed.
**/
static s32 e1000_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
u16 vf_number)
{
s32 ret_val;
u16 i;
DEBUGFUNC("e1000_read_mbx_pf");
/* lock the mailbox to prevent pf/vf race condition */
ret_val = e1000_obtain_mbx_lock_pf(hw, vf_number);
if (ret_val)
goto out_no_read;
/* copy the message to the mailbox memory buffer */
for (i = 0; i < size; i++)
msg[i] = E1000_READ_REG_ARRAY(hw, E1000_VMBMEM(vf_number), i);
/* Acknowledge the message and release buffer */
E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK);
/* update stats */
hw->mbx.stats.msgs_rx++;
out_no_read:
return ret_val;
}
/**
* e1000_init_mbx_params_pf - set initial values for pf mailbox
* @hw: pointer to the HW structure
*
* Initializes the hw->mbx struct to correct values for pf mailbox
*/
s32 e1000_init_mbx_params_pf(struct e1000_hw *hw)
{
struct e1000_mbx_info *mbx = &hw->mbx;
switch (hw->mac.type) {
case e1000_82576:
case e1000_i350:
mbx->timeout = 0;
mbx->usec_delay = 0;
mbx->size = E1000_VFMAILBOX_SIZE;
mbx->ops.read = e1000_read_mbx_pf;
mbx->ops.write = e1000_write_mbx_pf;
mbx->ops.read_posted = e1000_read_posted_mbx;
mbx->ops.write_posted = e1000_write_posted_mbx;
mbx->ops.check_for_msg = e1000_check_for_msg_pf;
mbx->ops.check_for_ack = e1000_check_for_ack_pf;
mbx->ops.check_for_rst = e1000_check_for_rst_pf;
mbx->stats.msgs_tx = 0;
mbx->stats.msgs_rx = 0;
mbx->stats.reqs = 0;
mbx->stats.acks = 0;
mbx->stats.rsts = 0;
default:
return E1000_SUCCESS;
}
}

View File

@ -0,0 +1,87 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _E1000_MBX_H_
#define _E1000_MBX_H_
#include "e1000_api.h"
#define E1000_P2VMAILBOX_STS 0x00000001 /* Initiate message send to VF */
#define E1000_P2VMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */
#define E1000_P2VMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
#define E1000_P2VMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
#define E1000_P2VMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */
#define E1000_MBVFICR_VFREQ_MASK 0x000000FF /* bits for VF messages */
#define E1000_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */
#define E1000_MBVFICR_VFACK_MASK 0x00FF0000 /* bits for VF acks */
#define E1000_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */
#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */
/* If it's a E1000_VF_* msg then it originates in the VF and is sent to the
* PF. The reverse is true if it is E1000_PF_*.
* Message ACK's are the value or'd with 0xF0000000
*/
/* Msgs below or'd with this are the ACK */
#define E1000_VT_MSGTYPE_ACK 0x80000000
/* Msgs below or'd with this are the NACK */
#define E1000_VT_MSGTYPE_NACK 0x40000000
/* Indicates that VF is still clear to send requests */
#define E1000_VT_MSGTYPE_CTS 0x20000000
#define E1000_VT_MSGINFO_SHIFT 16
/* bits 23:16 are used for extra info for certain messages */
#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT)
#define E1000_VF_RESET 0x01 /* VF requests reset */
#define E1000_VF_SET_MAC_ADDR 0x02 /* VF requests to set MAC addr */
#define E1000_VF_SET_MULTICAST 0x03 /* VF requests to set MC addr */
#define E1000_VF_SET_MULTICAST_COUNT_MASK (0x1F << E1000_VT_MSGINFO_SHIFT)
#define E1000_VF_SET_MULTICAST_OVERFLOW (0x80 << E1000_VT_MSGINFO_SHIFT)
#define E1000_VF_SET_VLAN 0x04 /* VF requests to set VLAN */
#define E1000_VF_SET_VLAN_ADD (0x01 << E1000_VT_MSGINFO_SHIFT)
#define E1000_VF_SET_LPE 0x05 /* reqs to set VMOLR.LPE */
#define E1000_VF_SET_PROMISC 0x06 /* reqs to clear VMOLR.ROPE/MPME*/
#define E1000_VF_SET_PROMISC_UNICAST (0x01 << E1000_VT_MSGINFO_SHIFT)
#define E1000_VF_SET_PROMISC_MULTICAST (0x02 << E1000_VT_MSGINFO_SHIFT)
#define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */
#define E1000_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */
#define E1000_VF_MBX_INIT_DELAY 500 /* microseconds between retries */
s32 e1000_read_mbx(struct e1000_hw *, u32 *, u16, u16);
s32 e1000_write_mbx(struct e1000_hw *, u32 *, u16, u16);
s32 e1000_read_posted_mbx(struct e1000_hw *, u32 *, u16, u16);
s32 e1000_write_posted_mbx(struct e1000_hw *, u32 *, u16, u16);
s32 e1000_check_for_msg(struct e1000_hw *, u16);
s32 e1000_check_for_ack(struct e1000_hw *, u16);
s32 e1000_check_for_rst(struct e1000_hw *, u16);
void e1000_init_mbx_ops_generic(struct e1000_hw *hw);
s32 e1000_init_mbx_params_pf(struct e1000_hw *);
#endif /* _E1000_MBX_H_ */

View File

@ -0,0 +1,859 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#include "e1000_api.h"
static void e1000_reload_nvm_generic(struct e1000_hw *hw);
/**
* e1000_init_nvm_ops_generic - Initialize NVM function pointers
* @hw: pointer to the HW structure
*
* Setups up the function pointers to no-op functions
**/
void e1000_init_nvm_ops_generic(struct e1000_hw *hw)
{
struct e1000_nvm_info *nvm = &hw->nvm;
DEBUGFUNC("e1000_init_nvm_ops_generic");
/* Initialize function pointers */
nvm->ops.init_params = e1000_null_ops_generic;
nvm->ops.acquire = e1000_null_ops_generic;
nvm->ops.read = e1000_null_read_nvm;
nvm->ops.release = e1000_null_nvm_generic;
nvm->ops.reload = e1000_reload_nvm_generic;
nvm->ops.update = e1000_null_ops_generic;
nvm->ops.valid_led_default = e1000_null_led_default;
nvm->ops.validate = e1000_null_ops_generic;
nvm->ops.write = e1000_null_write_nvm;
}
/**
* e1000_null_nvm_read - No-op function, return 0
* @hw: pointer to the HW structure
**/
s32 e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c)
{
DEBUGFUNC("e1000_null_read_nvm");
return E1000_SUCCESS;
}
/**
* e1000_null_nvm_generic - No-op function, return void
* @hw: pointer to the HW structure
**/
void e1000_null_nvm_generic(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_null_nvm_generic");
return;
}
/**
* e1000_null_led_default - No-op function, return 0
* @hw: pointer to the HW structure
**/
s32 e1000_null_led_default(struct e1000_hw *hw, u16 *data)
{
DEBUGFUNC("e1000_null_led_default");
return E1000_SUCCESS;
}
/**
* e1000_null_write_nvm - No-op function, return 0
* @hw: pointer to the HW structure
**/
s32 e1000_null_write_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c)
{
DEBUGFUNC("e1000_null_write_nvm");
return E1000_SUCCESS;
}
/**
* e1000_raise_eec_clk - Raise EEPROM clock
* @hw: pointer to the HW structure
* @eecd: pointer to the EEPROM
*
* Enable/Raise the EEPROM clock bit.
**/
static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd)
{
*eecd = *eecd | E1000_EECD_SK;
E1000_WRITE_REG(hw, E1000_EECD, *eecd);
E1000_WRITE_FLUSH(hw);
usec_delay(hw->nvm.delay_usec);
}
/**
* e1000_lower_eec_clk - Lower EEPROM clock
* @hw: pointer to the HW structure
* @eecd: pointer to the EEPROM
*
* Clear/Lower the EEPROM clock bit.
**/
static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd)
{
*eecd = *eecd & ~E1000_EECD_SK;
E1000_WRITE_REG(hw, E1000_EECD, *eecd);
E1000_WRITE_FLUSH(hw);
usec_delay(hw->nvm.delay_usec);
}
/**
* e1000_shift_out_eec_bits - Shift data bits our to the EEPROM
* @hw: pointer to the HW structure
* @data: data to send to the EEPROM
* @count: number of bits to shift out
*
* We need to shift 'count' bits out to the EEPROM. So, the value in the
* "data" parameter will be shifted out to the EEPROM one bit at a time.
* In order to do this, "data" must be broken down into bits.
**/
static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count)
{
struct e1000_nvm_info *nvm = &hw->nvm;
u32 eecd = E1000_READ_REG(hw, E1000_EECD);
u32 mask;
DEBUGFUNC("e1000_shift_out_eec_bits");
mask = 0x01 << (count - 1);
if (nvm->type == e1000_nvm_eeprom_spi)
eecd |= E1000_EECD_DO;
do {
eecd &= ~E1000_EECD_DI;
if (data & mask)
eecd |= E1000_EECD_DI;
E1000_WRITE_REG(hw, E1000_EECD, eecd);
E1000_WRITE_FLUSH(hw);
usec_delay(nvm->delay_usec);
e1000_raise_eec_clk(hw, &eecd);
e1000_lower_eec_clk(hw, &eecd);
mask >>= 1;
} while (mask);
eecd &= ~E1000_EECD_DI;
E1000_WRITE_REG(hw, E1000_EECD, eecd);
}
/**
* e1000_shift_in_eec_bits - Shift data bits in from the EEPROM
* @hw: pointer to the HW structure
* @count: number of bits to shift in
*
* In order to read a register from the EEPROM, we need to shift 'count' bits
* in from the EEPROM. Bits are "shifted in" by raising the clock input to
* the EEPROM (setting the SK bit), and then reading the value of the data out
* "DO" bit. During this "shifting in" process the data in "DI" bit should
* always be clear.
**/
static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count)
{
u32 eecd;
u32 i;
u16 data;
DEBUGFUNC("e1000_shift_in_eec_bits");
eecd = E1000_READ_REG(hw, E1000_EECD);
eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
data = 0;
for (i = 0; i < count; i++) {
data <<= 1;
e1000_raise_eec_clk(hw, &eecd);
eecd = E1000_READ_REG(hw, E1000_EECD);
eecd &= ~E1000_EECD_DI;
if (eecd & E1000_EECD_DO)
data |= 1;
e1000_lower_eec_clk(hw, &eecd);
}
return data;
}
/**
* e1000_poll_eerd_eewr_done - Poll for EEPROM read/write completion
* @hw: pointer to the HW structure
* @ee_reg: EEPROM flag for polling
*
* Polls the EEPROM status bit for either read or write completion based
* upon the value of 'ee_reg'.
**/
s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
{
u32 attempts = 100000;
u32 i, reg = 0;
DEBUGFUNC("e1000_poll_eerd_eewr_done");
for (i = 0; i < attempts; i++) {
if (ee_reg == E1000_NVM_POLL_READ)
reg = E1000_READ_REG(hw, E1000_EERD);
else
reg = E1000_READ_REG(hw, E1000_EEWR);
if (reg & E1000_NVM_RW_REG_DONE)
return E1000_SUCCESS;
usec_delay(5);
}
return -E1000_ERR_NVM;
}
/**
* e1000_acquire_nvm_generic - Generic request for access to EEPROM
* @hw: pointer to the HW structure
*
* Set the EEPROM access request bit and wait for EEPROM access grant bit.
* Return successful if access grant bit set, else clear the request for
* EEPROM access and return -E1000_ERR_NVM (-1).
**/
s32 e1000_acquire_nvm_generic(struct e1000_hw *hw)
{
u32 eecd = E1000_READ_REG(hw, E1000_EECD);
s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
DEBUGFUNC("e1000_acquire_nvm_generic");
E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_REQ);
eecd = E1000_READ_REG(hw, E1000_EECD);
while (timeout) {
if (eecd & E1000_EECD_GNT)
break;
usec_delay(5);
eecd = E1000_READ_REG(hw, E1000_EECD);
timeout--;
}
if (!timeout) {
eecd &= ~E1000_EECD_REQ;
E1000_WRITE_REG(hw, E1000_EECD, eecd);
DEBUGOUT("Could not acquire NVM grant\n");
return -E1000_ERR_NVM;
}
return E1000_SUCCESS;
}
/**
* e1000_standby_nvm - Return EEPROM to standby state
* @hw: pointer to the HW structure
*
* Return the EEPROM to a standby state.
**/
static void e1000_standby_nvm(struct e1000_hw *hw)
{
struct e1000_nvm_info *nvm = &hw->nvm;
u32 eecd = E1000_READ_REG(hw, E1000_EECD);
DEBUGFUNC("e1000_standby_nvm");
if (nvm->type == e1000_nvm_eeprom_spi) {
/* Toggle CS to flush commands */
eecd |= E1000_EECD_CS;
E1000_WRITE_REG(hw, E1000_EECD, eecd);
E1000_WRITE_FLUSH(hw);
usec_delay(nvm->delay_usec);
eecd &= ~E1000_EECD_CS;
E1000_WRITE_REG(hw, E1000_EECD, eecd);
E1000_WRITE_FLUSH(hw);
usec_delay(nvm->delay_usec);
}
}
/**
* e1000_stop_nvm - Terminate EEPROM command
* @hw: pointer to the HW structure
*
* Terminates the current command by inverting the EEPROM's chip select pin.
**/
static void e1000_stop_nvm(struct e1000_hw *hw)
{
u32 eecd;
DEBUGFUNC("e1000_stop_nvm");
eecd = E1000_READ_REG(hw, E1000_EECD);
if (hw->nvm.type == e1000_nvm_eeprom_spi) {
/* Pull CS high */
eecd |= E1000_EECD_CS;
e1000_lower_eec_clk(hw, &eecd);
}
}
/**
* e1000_release_nvm_generic - Release exclusive access to EEPROM
* @hw: pointer to the HW structure
*
* Stop any current commands to the EEPROM and clear the EEPROM request bit.
**/
void e1000_release_nvm_generic(struct e1000_hw *hw)
{
u32 eecd;
DEBUGFUNC("e1000_release_nvm_generic");
e1000_stop_nvm(hw);
eecd = E1000_READ_REG(hw, E1000_EECD);
eecd &= ~E1000_EECD_REQ;
E1000_WRITE_REG(hw, E1000_EECD, eecd);
}
/**
* e1000_ready_nvm_eeprom - Prepares EEPROM for read/write
* @hw: pointer to the HW structure
*
* Setups the EEPROM for reading and writing.
**/
static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
{
struct e1000_nvm_info *nvm = &hw->nvm;
u32 eecd = E1000_READ_REG(hw, E1000_EECD);
u8 spi_stat_reg;
DEBUGFUNC("e1000_ready_nvm_eeprom");
if (nvm->type == e1000_nvm_eeprom_spi) {
u16 timeout = NVM_MAX_RETRY_SPI;
/* Clear SK and CS */
eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
E1000_WRITE_REG(hw, E1000_EECD, eecd);
E1000_WRITE_FLUSH(hw);
usec_delay(1);
/*
* Read "Status Register" repeatedly until the LSB is cleared.
* The EEPROM will signal that the command has been completed
* by clearing bit 0 of the internal status register. If it's
* not cleared within 'timeout', then error out.
*/
while (timeout) {
e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
hw->nvm.opcode_bits);
spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8);
if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
break;
usec_delay(5);
e1000_standby_nvm(hw);
timeout--;
}
if (!timeout) {
DEBUGOUT("SPI NVM Status error\n");
return -E1000_ERR_NVM;
}
}
return E1000_SUCCESS;
}
/**
* e1000_read_nvm_spi - Read EEPROM's using SPI
* @hw: pointer to the HW structure
* @offset: offset of word in the EEPROM to read
* @words: number of words to read
* @data: word read from the EEPROM
*
* Reads a 16 bit word from the EEPROM.
**/
s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
{
struct e1000_nvm_info *nvm = &hw->nvm;
u32 i = 0;
s32 ret_val;
u16 word_in;
u8 read_opcode = NVM_READ_OPCODE_SPI;
DEBUGFUNC("e1000_read_nvm_spi");
/*
* A check for invalid values: offset too large, too many words,
* and not enough words.
*/
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
(words == 0)) {
DEBUGOUT("nvm parameter(s) out of bounds\n");
return -E1000_ERR_NVM;
}
ret_val = nvm->ops.acquire(hw);
if (ret_val)
return ret_val;
ret_val = e1000_ready_nvm_eeprom(hw);
if (ret_val)
goto release;
e1000_standby_nvm(hw);
if ((nvm->address_bits == 8) && (offset >= 128))
read_opcode |= NVM_A8_OPCODE_SPI;
/* Send the READ command (opcode + addr) */
e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits);
/*
* Read the data. SPI NVMs increment the address with each byte
* read and will roll over if reading beyond the end. This allows
* us to read the whole NVM from any offset
*/
for (i = 0; i < words; i++) {
word_in = e1000_shift_in_eec_bits(hw, 16);
data[i] = (word_in >> 8) | (word_in << 8);
}
release:
nvm->ops.release(hw);
return ret_val;
}
/**
* e1000_read_nvm_eerd - Reads EEPROM using EERD register
* @hw: pointer to the HW structure
* @offset: offset of word in the EEPROM to read
* @words: number of words to read
* @data: word read from the EEPROM
*
* Reads a 16 bit word from the EEPROM using the EERD register.
**/
s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
{
struct e1000_nvm_info *nvm = &hw->nvm;
u32 i, eerd = 0;
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_read_nvm_eerd");
/*
* A check for invalid values: offset too large, too many words,
* too many words for the offset, and not enough words.
*/
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
(words == 0)) {
DEBUGOUT("nvm parameter(s) out of bounds\n");
return -E1000_ERR_NVM;
}
for (i = 0; i < words; i++) {
eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) +
E1000_NVM_RW_REG_START;
E1000_WRITE_REG(hw, E1000_EERD, eerd);
ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ);
if (ret_val)
break;
data[i] = (E1000_READ_REG(hw, E1000_EERD) >>
E1000_NVM_RW_REG_DATA);
}
return ret_val;
}
/**
* e1000_write_nvm_spi - Write to EEPROM using SPI
* @hw: pointer to the HW structure
* @offset: offset within the EEPROM to be written to
* @words: number of words to write
* @data: 16 bit word(s) to be written to the EEPROM
*
* Writes data to EEPROM at offset using SPI interface.
*
* If e1000_update_nvm_checksum is not called after this function , the
* EEPROM will most likely contain an invalid checksum.
**/
s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
{
struct e1000_nvm_info *nvm = &hw->nvm;
s32 ret_val;
u16 widx = 0;
DEBUGFUNC("e1000_write_nvm_spi");
/*
* A check for invalid values: offset too large, too many words,
* and not enough words.
*/
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
(words == 0)) {
DEBUGOUT("nvm parameter(s) out of bounds\n");
return -E1000_ERR_NVM;
}
ret_val = nvm->ops.acquire(hw);
if (ret_val)
return ret_val;
while (widx < words) {
u8 write_opcode = NVM_WRITE_OPCODE_SPI;
ret_val = e1000_ready_nvm_eeprom(hw);
if (ret_val)
goto release;
e1000_standby_nvm(hw);
/* Send the WRITE ENABLE command (8 bit opcode) */
e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
nvm->opcode_bits);
e1000_standby_nvm(hw);
/*
* Some SPI eeproms use the 8th address bit embedded in the
* opcode
*/
if ((nvm->address_bits == 8) && (offset >= 128))
write_opcode |= NVM_A8_OPCODE_SPI;
/* Send the Write command (8-bit opcode + addr) */
e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
nvm->address_bits);
/* Loop to allow for up to whole page write of eeprom */
while (widx < words) {
u16 word_out = data[widx];
word_out = (word_out >> 8) | (word_out << 8);
e1000_shift_out_eec_bits(hw, word_out, 16);
widx++;
if ((((offset + widx) * 2) % nvm->page_size) == 0) {
e1000_standby_nvm(hw);
break;
}
}
}
msec_delay(10);
release:
nvm->ops.release(hw);
return ret_val;
}
/**
* e1000_read_pba_string_generic - Read device part number
* @hw: pointer to the HW structure
* @pba_num: pointer to device part number
* @pba_num_size: size of part number buffer
*
* Reads the product board assembly (PBA) number from the EEPROM and stores
* the value in pba_num.
**/
s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
u32 pba_num_size)
{
s32 ret_val;
u16 nvm_data;
u16 pba_ptr;
u16 offset;
u16 length;
DEBUGFUNC("e1000_read_pba_string_generic");
if (pba_num == NULL) {
DEBUGOUT("PBA string buffer was null\n");
return -E1000_ERR_INVALID_ARGUMENT;
}
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
return ret_val;
}
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
return ret_val;
}
/*
* if nvm_data is not ptr guard the PBA must be in legacy format which
* means pba_ptr is actually our second data word for the PBA number
* and we can decode it into an ascii string
*/
if (nvm_data != NVM_PBA_PTR_GUARD) {
DEBUGOUT("NVM PBA number is not stored as string\n");
/* we will need 11 characters to store the PBA */
if (pba_num_size < 11) {
DEBUGOUT("PBA string buffer too small\n");
return E1000_ERR_NO_SPACE;
}
/* extract hex string from data and pba_ptr */
pba_num[0] = (nvm_data >> 12) & 0xF;
pba_num[1] = (nvm_data >> 8) & 0xF;
pba_num[2] = (nvm_data >> 4) & 0xF;
pba_num[3] = nvm_data & 0xF;
pba_num[4] = (pba_ptr >> 12) & 0xF;
pba_num[5] = (pba_ptr >> 8) & 0xF;
pba_num[6] = '-';
pba_num[7] = 0;
pba_num[8] = (pba_ptr >> 4) & 0xF;
pba_num[9] = pba_ptr & 0xF;
/* put a null character on the end of our string */
pba_num[10] = '\0';
/* switch all the data but the '-' to hex char */
for (offset = 0; offset < 10; offset++) {
if (pba_num[offset] < 0xA)
pba_num[offset] += '0';
else if (pba_num[offset] < 0x10)
pba_num[offset] += 'A' - 0xA;
}
return E1000_SUCCESS;
}
ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
return ret_val;
}
if (length == 0xFFFF || length == 0) {
DEBUGOUT("NVM PBA number section invalid length\n");
return -E1000_ERR_NVM_PBA_SECTION;
}
/* check if pba_num buffer is big enough */
if (pba_num_size < (((u32)length * 2) - 1)) {
DEBUGOUT("PBA string buffer too small\n");
return -E1000_ERR_NO_SPACE;
}
/* trim pba length from start of string */
pba_ptr++;
length--;
for (offset = 0; offset < length; offset++) {
ret_val = hw->nvm.ops.read(hw, pba_ptr + offset, 1, &nvm_data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
return ret_val;
}
pba_num[offset * 2] = (u8)(nvm_data >> 8);
pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
}
pba_num[offset * 2] = '\0';
return E1000_SUCCESS;
}
/**
* e1000_read_pba_length_generic - Read device part number length
* @hw: pointer to the HW structure
* @pba_num_size: size of part number buffer
*
* Reads the product board assembly (PBA) number length from the EEPROM and
* stores the value in pba_num_size.
**/
s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size)
{
s32 ret_val;
u16 nvm_data;
u16 pba_ptr;
u16 length;
DEBUGFUNC("e1000_read_pba_length_generic");
if (pba_num_size == NULL) {
DEBUGOUT("PBA buffer size was null\n");
return -E1000_ERR_INVALID_ARGUMENT;
}
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
return ret_val;
}
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
return ret_val;
}
/* if data is not ptr guard the PBA must be in legacy format */
if (nvm_data != NVM_PBA_PTR_GUARD) {
*pba_num_size = 11;
return E1000_SUCCESS;
}
ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
return ret_val;
}
if (length == 0xFFFF || length == 0) {
DEBUGOUT("NVM PBA number section invalid length\n");
return -E1000_ERR_NVM_PBA_SECTION;
}
/*
* Convert from length in u16 values to u8 chars, add 1 for NULL,
* and subtract 2 because length field is included in length.
*/
*pba_num_size = ((u32)length * 2) - 1;
return E1000_SUCCESS;
}
/**
* e1000_read_mac_addr_generic - Read device MAC address
* @hw: pointer to the HW structure
*
* Reads the device MAC address from the EEPROM and stores the value.
* Since devices with two ports use the same EEPROM, we increment the
* last bit in the MAC address for the second port.
**/
s32 e1000_read_mac_addr_generic(struct e1000_hw *hw)
{
u32 rar_high;
u32 rar_low;
u16 i;
rar_high = E1000_READ_REG(hw, E1000_RAH(0));
rar_low = E1000_READ_REG(hw, E1000_RAL(0));
for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));
for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));
for (i = 0; i < ETH_ADDR_LEN; i++)
hw->mac.addr[i] = hw->mac.perm_addr[i];
return E1000_SUCCESS;
}
/**
* e1000_validate_nvm_checksum_generic - Validate EEPROM checksum
* @hw: pointer to the HW structure
*
* Calculates the EEPROM checksum by reading/adding each word of the EEPROM
* and then verifies that the sum of the EEPROM is equal to 0xBABA.
**/
s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw)
{
s32 ret_val;
u16 checksum = 0;
u16 i, nvm_data;
DEBUGFUNC("e1000_validate_nvm_checksum_generic");
for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
return ret_val;
}
checksum += nvm_data;
}
if (checksum != (u16) NVM_SUM) {
DEBUGOUT("NVM Checksum Invalid\n");
return -E1000_ERR_NVM;
}
return E1000_SUCCESS;
}
/**
* e1000_update_nvm_checksum_generic - Update EEPROM checksum
* @hw: pointer to the HW structure
*
* Updates the EEPROM checksum by reading/adding each word of the EEPROM
* up to the checksum. Then calculates the EEPROM checksum and writes the
* value to the EEPROM.
**/
s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw)
{
s32 ret_val;
u16 checksum = 0;
u16 i, nvm_data;
DEBUGFUNC("e1000_update_nvm_checksum");
for (i = 0; i < NVM_CHECKSUM_REG; i++) {
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
if (ret_val) {
DEBUGOUT("NVM Read Error while updating checksum.\n");
return ret_val;
}
checksum += nvm_data;
}
checksum = (u16) NVM_SUM - checksum;
ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
if (ret_val)
DEBUGOUT("NVM Write Error while updating checksum.\n");
return ret_val;
}
/**
* e1000_reload_nvm_generic - Reloads EEPROM
* @hw: pointer to the HW structure
*
* Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
* extended control register.
**/
static void e1000_reload_nvm_generic(struct e1000_hw *hw)
{
u32 ctrl_ext;
DEBUGFUNC("e1000_reload_nvm_generic");
usec_delay(10);
ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_EE_RST;
E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
E1000_WRITE_FLUSH(hw);
}

View File

@ -0,0 +1,54 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _E1000_NVM_H_
#define _E1000_NVM_H_
void e1000_init_nvm_ops_generic(struct e1000_hw *hw);
s32 e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c);
void e1000_null_nvm_generic(struct e1000_hw *hw);
s32 e1000_null_led_default(struct e1000_hw *hw, u16 *data);
s32 e1000_null_write_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c);
s32 e1000_acquire_nvm_generic(struct e1000_hw *hw);
s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg);
s32 e1000_read_mac_addr_generic(struct e1000_hw *hw);
s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
u32 pba_num_size);
s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size);
s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words,
u16 *data);
s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data);
s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw);
s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words,
u16 *data);
s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw);
void e1000_release_nvm_generic(struct e1000_hw *hw);
#define E1000_STM_OPCODE 0xDB00
#endif

View File

@ -0,0 +1,126 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
/* glue for the OS independent part of e1000
* includes register access macros
*/
#ifndef _E1000_OSDEP_H_
#define _E1000_OSDEP_H_
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/if_ether.h>
#include <linux/sched.h>
#include "kcompat.h"
#ifndef __INTEL_COMPILER
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#define usec_delay(x) udelay(x)
#ifndef msec_delay
#define msec_delay(x) do { \
/* Don't mdelay in interrupt context! */ \
if (in_interrupt()) \
BUG(); \
else \
msleep(x); \
} while (0)
/* Some workarounds require millisecond delays and are run during interrupt
* context. Most notably, when establishing link, the phy may need tweaking
* but cannot process phy register reads/writes faster than millisecond
* intervals...and we establish link due to a "link status change" interrupt.
*/
#define msec_delay_irq(x) mdelay(x)
#endif
#define PCI_COMMAND_REGISTER PCI_COMMAND
#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE
#define ETH_ADDR_LEN ETH_ALEN
#ifdef __BIG_ENDIAN
#define E1000_BIG_ENDIAN __BIG_ENDIAN
#endif
#define DEBUGOUT(S)
#define DEBUGOUT1(S, A...)
#define DEBUGFUNC(F)
#define DEBUGOUT2 DEBUGOUT1
#define DEBUGOUT3 DEBUGOUT2
#define DEBUGOUT7 DEBUGOUT3
#define E1000_REGISTER(a, reg) reg
#define E1000_WRITE_REG(a, reg, value) ( \
writel((value), ((a)->hw_addr + E1000_REGISTER(a, reg))))
#define E1000_READ_REG(a, reg) (readl((a)->hw_addr + E1000_REGISTER(a, reg)))
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
writel((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 2))))
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
readl((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 2)))
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
writew((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 1))))
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
readw((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 1)))
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
writeb((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + (offset))))
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
readb((a)->hw_addr + E1000_REGISTER(a, reg) + (offset)))
#define E1000_WRITE_REG_IO(a, reg, offset) do { \
outl(reg, ((a)->io_base)); \
outl(offset, ((a)->io_base + 4)); } while (0)
#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, E1000_STATUS)
#define E1000_WRITE_FLASH_REG(a, reg, value) ( \
writel((value), ((a)->flash_address + reg)))
#define E1000_WRITE_FLASH_REG16(a, reg, value) ( \
writew((value), ((a)->flash_address + reg)))
#define E1000_READ_FLASH_REG(a, reg) (readl((a)->flash_address + reg))
#define E1000_READ_FLASH_REG16(a, reg) (readw((a)->flash_address + reg))
#endif /* _E1000_OSDEP_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,244 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _E1000_PHY_H_
#define _E1000_PHY_H_
void e1000_init_phy_ops_generic(struct e1000_hw *hw);
s32 e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data);
void e1000_null_phy_generic(struct e1000_hw *hw);
s32 e1000_null_lplu_state(struct e1000_hw *hw, bool active);
s32 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_null_set_page(struct e1000_hw *hw, u16 data);
s32 e1000_read_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
u8 dev_addr, u8 *data);
s32 e1000_write_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
u8 dev_addr, u8 data);
s32 e1000_check_downshift_generic(struct e1000_hw *hw);
s32 e1000_check_polarity_m88(struct e1000_hw *hw);
s32 e1000_check_polarity_igp(struct e1000_hw *hw);
s32 e1000_check_polarity_ife(struct e1000_hw *hw);
s32 e1000_check_reset_block_generic(struct e1000_hw *hw);
s32 e1000_copper_link_setup_igp(struct e1000_hw *hw);
s32 e1000_copper_link_setup_m88(struct e1000_hw *hw);
s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw);
s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw);
s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw);
s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw);
s32 e1000_get_cable_length_m88(struct e1000_hw *hw);
s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw);
s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw);
s32 e1000_get_cfg_done_generic(struct e1000_hw *hw);
s32 e1000_get_phy_id(struct e1000_hw *hw);
s32 e1000_get_phy_info_igp(struct e1000_hw *hw);
s32 e1000_get_phy_info_m88(struct e1000_hw *hw);
s32 e1000_get_phy_info_ife(struct e1000_hw *hw);
s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw);
void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl);
s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw);
s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw);
s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page);
s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active);
s32 e1000_setup_copper_link_generic(struct e1000_hw *hw);
s32 e1000_wait_autoneg_generic(struct e1000_hw *hw);
s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_phy_reset_dsp(struct e1000_hw *hw);
s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
u32 usec_interval, bool *success);
s32 e1000_phy_init_script_igp3(struct e1000_hw *hw);
enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id);
s32 e1000_determine_phy_address(struct e1000_hw *hw);
s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg);
s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg);
void e1000_power_up_phy_copper(struct e1000_hw *hw);
void e1000_power_down_phy_copper(struct e1000_hw *hw);
s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data);
s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data);
s32 e1000_copper_link_setup_82577(struct e1000_hw *hw);
s32 e1000_check_polarity_82577(struct e1000_hw *hw);
s32 e1000_get_phy_info_82577(struct e1000_hw *hw);
s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw);
s32 e1000_get_cable_length_82577(struct e1000_hw *hw);
#define E1000_MAX_PHY_ADDR 8
/* IGP01E1000 Specific Registers */
#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */
#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */
#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */
#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */
#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO */
#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality */
#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */
#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */
#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */
#define IGP_PAGE_SHIFT 5
#define PHY_REG_MASK 0x1F
#define HV_INTC_FC_PAGE_START 768
#define I82578_ADDR_REG 29
#define I82577_ADDR_REG 16
#define I82577_CFG_REG 22
#define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15)
#define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift 100/10 */
#define I82577_CTRL_REG 23
/* 82577 specific PHY registers */
#define I82577_PHY_CTRL_2 18
#define I82577_PHY_LBK_CTRL 19
#define I82577_PHY_STATUS_2 26
#define I82577_PHY_DIAG_STATUS 31
/* I82577 PHY Status 2 */
#define I82577_PHY_STATUS2_REV_POLARITY 0x0400
#define I82577_PHY_STATUS2_MDIX 0x0800
#define I82577_PHY_STATUS2_SPEED_MASK 0x0300
#define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200
#define I82577_PHY_STATUS2_SPEED_100MBPS 0x0100
/* I82577 PHY Control 2 */
#define I82577_PHY_CTRL2_AUTO_MDIX 0x0400
#define I82577_PHY_CTRL2_FORCE_MDI_MDIX 0x0200
/* I82577 PHY Diagnostics Status */
#define I82577_DSTATUS_CABLE_LENGTH 0x03FC
#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2
/* 82580 PHY Power Management */
#define E1000_82580_PHY_POWER_MGMT 0xE14
#define E1000_82580_PM_SPD 0x0001 /* Smart Power Down */
#define E1000_82580_PM_D0_LPLU 0x0002 /* For D0a states */
#define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */
#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4
#define IGP01E1000_PHY_POLARITY_MASK 0x0078
#define IGP01E1000_PSCR_AUTO_MDIX 0x1000
#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */
#define IGP01E1000_PSCFR_SMART_SPEED 0x0080
/* Enable flexible speed on link-up */
#define IGP01E1000_GMII_FLEX_SPD 0x0010
#define IGP01E1000_GMII_SPD 0x0020 /* Enable SPD */
#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */
#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */
#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */
#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000
#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002
#define IGP01E1000_PSSR_MDIX 0x0800
#define IGP01E1000_PSSR_SPEED_MASK 0xC000
#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000
#define IGP02E1000_PHY_CHANNEL_NUM 4
#define IGP02E1000_PHY_AGC_A 0x11B1
#define IGP02E1000_PHY_AGC_B 0x12B1
#define IGP02E1000_PHY_AGC_C 0x14B1
#define IGP02E1000_PHY_AGC_D 0x18B1
#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */
#define IGP02E1000_AGC_LENGTH_MASK 0x7F
#define IGP02E1000_AGC_RANGE 15
#define IGP03E1000_PHY_MISC_CTRL 0x1B
#define IGP03E1000_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Manually Set Duplex */
#define E1000_CABLE_LENGTH_UNDEFINED 0xFF
#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000
#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16
#define E1000_KMRNCTRLSTA_REN 0x00200000
#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */
#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */
#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */
#define E1000_KMRNCTRLSTA_IBIST_DISABLE 0x0200 /* Kumeran IBIST Disable */
#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */
#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10
#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */
#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Control */
#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */
/* IFE PHY Extended Status Control */
#define IFE_PESC_POLARITY_REVERSED 0x0100
/* IFE PHY Special Control */
#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010
#define IFE_PSC_FORCE_POLARITY 0x0020
#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100
/* IFE PHY Special Control and LED Control */
#define IFE_PSCL_PROBE_MODE 0x0020
#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */
#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */
/* IFE PHY MDIX Control */
#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */
#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */
#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto, 0=disable */
/* SFP modules ID memory locations */
#define E1000_SFF_IDENTIFIER_OFFSET 0x00
#define E1000_SFF_IDENTIFIER_SFF 0x02
#define E1000_SFF_IDENTIFIER_SFP 0x03
#define E1000_SFF_ETH_FLAGS_OFFSET 0x06
/* Flags for SFP modules compatible with ETH up to 1Gb */
struct sfp_e1000_flags {
u8 e1000_base_sx:1;
u8 e1000_base_lx:1;
u8 e1000_base_cx:1;
u8 e1000_base_t:1;
u8 e100_base_lx:1;
u8 e100_base_fx:1;
u8 e10_base_bx10:1;
u8 e10_base_px:1;
};
/* Vendor OUIs: format of OUI is 0x[byte0][byte1][byte2][00] */
#define E1000_SFF_VENDOR_OUI_TYCO 0x00407600
#define E1000_SFF_VENDOR_OUI_FTL 0x00906500
#define E1000_SFF_VENDOR_OUI_AVAGO 0x00176A00
#define E1000_SFF_VENDOR_OUI_INTEL 0x001B2100
#endif

View File

@ -0,0 +1,594 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _E1000_REGS_H_
#define _E1000_REGS_H_
#define E1000_CTRL 0x00000 /* Device Control - RW */
#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */
#define E1000_STATUS 0x00008 /* Device Status - RO */
#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */
#define E1000_EERD 0x00014 /* EEPROM Read - RW */
#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
#define E1000_FLA 0x0001C /* Flash Access - RW */
#define E1000_MDIC 0x00020 /* MDI Control - RW */
#define E1000_MDICNFG 0x00E04 /* MDI Config - RW */
#define E1000_REGISTER_SET_SIZE 0x20000 /* CSR Size */
#define E1000_EEPROM_INIT_CTRL_WORD_2 0x0F /* EEPROM Init Ctrl Word 2 */
#define E1000_EEPROM_PCIE_CTRL_WORD_2 0x28 /* EEPROM PCIe Ctrl Word 2 */
#define E1000_BARCTRL 0x5BBC /* BAR ctrl reg */
#define E1000_BARCTRL_FLSIZE 0x0700 /* BAR ctrl Flsize */
#define E1000_BARCTRL_CSRSIZE 0x2000 /* BAR ctrl CSR size */
#define E1000_I350_BARCTRL 0x5BFC /* BAR ctrl reg */
#define E1000_I350_DTXMXPKTSZ 0x355C /* Maximum sent packet size reg*/
#define E1000_SCTL 0x00024 /* SerDes Control - RW */
#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
#define E1000_FEXT 0x0002C /* Future Extended - RW */
#define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */
#define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */
#define E1000_FCT 0x00030 /* Flow Control Type - RW */
#define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */
#define E1000_VET 0x00038 /* VLAN Ether Type - RW */
#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */
#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */
#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */
#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
#define E1000_RCTL 0x00100 /* Rx Control - RW */
#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
#define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */
#define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */
#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */
#define E1000_EITR(_n) (0x01680 + (0x4 * (_n)))
#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
#define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
#define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
#define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */
#define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */
#define E1000_GPIE 0x01514 /* General Purpose Interrupt Enable - RW */
#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */
#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
#define E1000_TCTL 0x00400 /* Tx Control - RW */
#define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */
#define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */
#define E1000_TBT 0x00448 /* Tx Burst Timer - RW */
#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */
#define E1000_LEDCTL 0x00E00 /* LED Control - RW */
#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */
#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */
#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */
#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
#define E1000_PBS 0x01008 /* Packet Buffer Size */
#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */
#define E1000_FLASHT 0x01028 /* FLASH Timer Register */
#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */
#define E1000_FLSWCTL 0x01030 /* FLASH control register */
#define E1000_FLSWDATA 0x01034 /* FLASH data register */
#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */
#define E1000_FLOP 0x0103C /* FLASH Opcode Register */
#define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */
#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */
#define E1000_I2CBB_EN 0x00000100 /* I2C - Bit Bang Enable */
#define E1000_I2C_CLK_OUT 0x00000200 /* I2C- Clock */
#define E1000_I2C_DATA_OUT 0x00000400 /* I2C- Data Out */
#define E1000_I2C_DATA_OE_N 0x00000800 /* I2C- Data Output Enable */
#define E1000_I2C_DATA_IN 0x00001000 /* I2C- Data In */
#define E1000_I2C_CLK_OE_N 0x00002000 /* I2C- Clock Output Enable */
#define E1000_I2C_CLK_IN 0x00004000 /* I2C- Clock In */
#define E1000_I2C_CLK_STRETCH_DIS 0x00008000 /* I2C- Dis Clk Stretching */
#define E1000_WDSTP 0x01040 /* Watchdog Setup - RW */
#define E1000_SWDSTS 0x01044 /* SW Device Status - RW */
#define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */
#define E1000_TCPTIMER 0x0104C /* TCP Timer - RW */
#define E1000_VPDDIAG 0x01060 /* VPD Diagnostic - RO */
#define E1000_ICR_V2 0x01500 /* Intr Cause - new location - RC */
#define E1000_ICS_V2 0x01504 /* Intr Cause Set - new location - WO */
#define E1000_IMS_V2 0x01508 /* Intr Mask Set/Read - new location - RW */
#define E1000_IMC_V2 0x0150C /* Intr Mask Clear - new location - WO */
#define E1000_IAM_V2 0x01510 /* Intr Ack Auto Mask - new location - RW */
#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */
#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */
#define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n)))
#define E1000_PBRTH 0x02458 /* PB Rx Arbitration Threshold - RW */
#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */
/* Split and Replication Rx Control - RW */
#define E1000_RDPUMB 0x025CC /* DMA Rx Descriptor uC Mailbox - RW */
#define E1000_RDPUAD 0x025D0 /* DMA Rx Descriptor uC Addr Command - RW */
#define E1000_RDPUWD 0x025D4 /* DMA Rx Descriptor uC Data Write - RW */
#define E1000_RDPURD 0x025D8 /* DMA Rx Descriptor uC Data Read - RW */
#define E1000_RDPUCTL 0x025DC /* DMA Rx Descriptor uC Control - RW */
#define E1000_PBDIAG 0x02458 /* Packet Buffer Diagnostic - RW */
#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */
#define E1000_IRPBS 0x02404 /* Same as RXPBS, renamed for newer Si - RW */
#define E1000_PBRWAC 0x024E8 /* Rx packet buffer wrap around counter - RO */
#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */
#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */
/*
* Convenience macros
*
* Note: "_n" is the queue number of the register to be written to.
*
* Example usage:
* E1000_RDBAL_REG(current_rx_queue)
*/
#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \
(0x0C000 + ((_n) * 0x40)))
#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \
(0x0C004 + ((_n) * 0x40)))
#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \
(0x0C008 + ((_n) * 0x40)))
#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \
(0x0C00C + ((_n) * 0x40)))
#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \
(0x0C010 + ((_n) * 0x40)))
#define E1000_RXCTL(_n) ((_n) < 4 ? (0x02814 + ((_n) * 0x100)) : \
(0x0C014 + ((_n) * 0x40)))
#define E1000_DCA_RXCTRL(_n) E1000_RXCTL(_n)
#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \
(0x0C018 + ((_n) * 0x40)))
#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \
(0x0C028 + ((_n) * 0x40)))
#define E1000_RQDPC(_n) ((_n) < 4 ? (0x02830 + ((_n) * 0x100)) : \
(0x0C030 + ((_n) * 0x40)))
#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \
(0x0E000 + ((_n) * 0x40)))
#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \
(0x0E004 + ((_n) * 0x40)))
#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \
(0x0E008 + ((_n) * 0x40)))
#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \
(0x0E010 + ((_n) * 0x40)))
#define E1000_TXCTL(_n) ((_n) < 4 ? (0x03814 + ((_n) * 0x100)) : \
(0x0E014 + ((_n) * 0x40)))
#define E1000_DCA_TXCTRL(_n) E1000_TXCTL(_n)
#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \
(0x0E018 + ((_n) * 0x40)))
#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \
(0x0E028 + ((_n) * 0x40)))
#define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : \
(0x0E038 + ((_n) * 0x40)))
#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : \
(0x0E03C + ((_n) * 0x40)))
#define E1000_TARC(_n) (0x03840 + ((_n) * 0x100))
#define E1000_RSRPD 0x02C00 /* Rx Small Packet Detect - RW */
#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */
#define E1000_TXDMAC 0x03000 /* Tx DMA Control - RW */
#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */
#define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4))
#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
(0x054E0 + ((_i - 16) * 8)))
#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
(0x054E4 + ((_i - 16) * 8)))
#define E1000_SHRAL(_i) (0x05438 + ((_i) * 8))
#define E1000_SHRAH(_i) (0x0543C + ((_i) * 8))
#define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8))
#define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4))
#define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4))
#define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8))
#define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8))
#define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8))
#define E1000_PBSLAC 0x03100 /* Pkt Buffer Slave Access Control */
#define E1000_PBSLAD(_n) (0x03110 + (0x4 * (_n))) /* Pkt Buffer DWORD */
#define E1000_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */
/* Same as TXPBS, renamed for newer Si - RW */
#define E1000_ITPBS 0x03404
#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */
#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */
#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */
#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */
#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */
#define E1000_TDPUMB 0x0357C /* DMA Tx Desc uC Mail Box - RW */
#define E1000_TDPUAD 0x03580 /* DMA Tx Desc uC Addr Command - RW */
#define E1000_TDPUWD 0x03584 /* DMA Tx Desc uC Data Write - RW */
#define E1000_TDPURD 0x03588 /* DMA Tx Desc uC Data Read - RW */
#define E1000_TDPUCTL 0x0358C /* DMA Tx Desc uC Control - RW */
#define E1000_DTXCTL 0x03590 /* DMA Tx Control - RW */
#define E1000_DTXTCPFLGL 0x0359C /* DMA Tx Control flag low - RW */
#define E1000_DTXTCPFLGH 0x035A0 /* DMA Tx Control flag high - RW */
/* DMA Tx Max Total Allow Size Reqs - RW */
#define E1000_DTXMXSZRQ 0x03540
#define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */
#define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */
#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */
#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */
#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */
#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */
#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */
#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */
#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */
#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */
#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */
#define E1000_COLC 0x04028 /* Collision Count - R/clr */
#define E1000_DC 0x04030 /* Defer Count - R/clr */
#define E1000_TNCRS 0x04034 /* Tx-No CRS - R/clr */
#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */
#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */
#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */
#define E1000_XONRXC 0x04048 /* XON Rx Count - R/clr */
#define E1000_XONTXC 0x0404C /* XON Tx Count - R/clr */
#define E1000_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */
#define E1000_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */
#define E1000_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */
#define E1000_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */
#define E1000_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */
#define E1000_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */
#define E1000_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */
#define E1000_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */
#define E1000_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */
#define E1000_GPRC 0x04074 /* Good Packets Rx Count - R/clr */
#define E1000_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */
#define E1000_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */
#define E1000_GPTC 0x04080 /* Good Packets Tx Count - R/clr */
#define E1000_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */
#define E1000_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */
#define E1000_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */
#define E1000_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */
#define E1000_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */
#define E1000_RUC 0x040A4 /* Rx Undersize Count - R/clr */
#define E1000_RFC 0x040A8 /* Rx Fragment Count - R/clr */
#define E1000_ROC 0x040AC /* Rx Oversize Count - R/clr */
#define E1000_RJC 0x040B0 /* Rx Jabber Count - R/clr */
#define E1000_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */
#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */
#define E1000_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */
#define E1000_TORL 0x040C0 /* Total Octets Rx Low - R/clr */
#define E1000_TORH 0x040C4 /* Total Octets Rx High - R/clr */
#define E1000_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */
#define E1000_TOTH 0x040CC /* Total Octets Tx High - R/clr */
#define E1000_TPR 0x040D0 /* Total Packets Rx - R/clr */
#define E1000_TPT 0x040D4 /* Total Packets Tx - R/clr */
#define E1000_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */
#define E1000_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */
#define E1000_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */
#define E1000_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */
#define E1000_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */
#define E1000_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */
#define E1000_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */
#define E1000_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */
#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */
#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */
#define E1000_IAC 0x04100 /* Interrupt Assertion Count */
#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Pkt Timer Expire Count */
#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Abs Timer Expire Count */
#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Pkt Timer Expire Count */
#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Abs Timer Expire Count */
#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */
#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Min Thresh Count */
#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Desc Min Thresh Count */
#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
/* Virtualization statistical counters */
#define E1000_PFVFGPRC(_n) (0x010010 + (0x100 * (_n)))
#define E1000_PFVFGPTC(_n) (0x010014 + (0x100 * (_n)))
#define E1000_PFVFGORC(_n) (0x010018 + (0x100 * (_n)))
#define E1000_PFVFGOTC(_n) (0x010034 + (0x100 * (_n)))
#define E1000_PFVFMPRC(_n) (0x010038 + (0x100 * (_n)))
#define E1000_PFVFGPRLBC(_n) (0x010040 + (0x100 * (_n)))
#define E1000_PFVFGPTLBC(_n) (0x010044 + (0x100 * (_n)))
#define E1000_PFVFGORLBC(_n) (0x010048 + (0x100 * (_n)))
#define E1000_PFVFGOTLBC(_n) (0x010050 + (0x100 * (_n)))
/* LinkSec */
#define E1000_LSECTXUT 0x04300 /* Tx Untagged Pkt Cnt */
#define E1000_LSECTXPKTE 0x04304 /* Encrypted Tx Pkts Cnt */
#define E1000_LSECTXPKTP 0x04308 /* Protected Tx Pkt Cnt */
#define E1000_LSECTXOCTE 0x0430C /* Encrypted Tx Octets Cnt */
#define E1000_LSECTXOCTP 0x04310 /* Protected Tx Octets Cnt */
#define E1000_LSECRXUT 0x04314 /* Untagged non-Strict Rx Pkt Cnt */
#define E1000_LSECRXOCTD 0x0431C /* Rx Octets Decrypted Count */
#define E1000_LSECRXOCTV 0x04320 /* Rx Octets Validated */
#define E1000_LSECRXBAD 0x04324 /* Rx Bad Tag */
#define E1000_LSECRXNOSCI 0x04328 /* Rx Packet No SCI Count */
#define E1000_LSECRXUNSCI 0x0432C /* Rx Packet Unknown SCI Count */
#define E1000_LSECRXUNCH 0x04330 /* Rx Unchecked Packets Count */
#define E1000_LSECRXDELAY 0x04340 /* Rx Delayed Packet Count */
#define E1000_LSECRXLATE 0x04350 /* Rx Late Packets Count */
#define E1000_LSECRXOK(_n) (0x04360 + (0x04 * (_n))) /* Rx Pkt OK Cnt */
#define E1000_LSECRXINV(_n) (0x04380 + (0x04 * (_n))) /* Rx Invalid Cnt */
#define E1000_LSECRXNV(_n) (0x043A0 + (0x04 * (_n))) /* Rx Not Valid Cnt */
#define E1000_LSECRXUNSA 0x043C0 /* Rx Unused SA Count */
#define E1000_LSECRXNUSA 0x043D0 /* Rx Not Using SA Count */
#define E1000_LSECTXCAP 0x0B000 /* Tx Capabilities Register - RO */
#define E1000_LSECRXCAP 0x0B300 /* Rx Capabilities Register - RO */
#define E1000_LSECTXCTRL 0x0B004 /* Tx Control - RW */
#define E1000_LSECRXCTRL 0x0B304 /* Rx Control - RW */
#define E1000_LSECTXSCL 0x0B008 /* Tx SCI Low - RW */
#define E1000_LSECTXSCH 0x0B00C /* Tx SCI High - RW */
#define E1000_LSECTXSA 0x0B010 /* Tx SA0 - RW */
#define E1000_LSECTXPN0 0x0B018 /* Tx SA PN 0 - RW */
#define E1000_LSECTXPN1 0x0B01C /* Tx SA PN 1 - RW */
#define E1000_LSECRXSCL 0x0B3D0 /* Rx SCI Low - RW */
#define E1000_LSECRXSCH 0x0B3E0 /* Rx SCI High - RW */
/* LinkSec Tx 128-bit Key 0 - WO */
#define E1000_LSECTXKEY0(_n) (0x0B020 + (0x04 * (_n)))
/* LinkSec Tx 128-bit Key 1 - WO */
#define E1000_LSECTXKEY1(_n) (0x0B030 + (0x04 * (_n)))
#define E1000_LSECRXSA(_n) (0x0B310 + (0x04 * (_n))) /* Rx SAs - RW */
#define E1000_LSECRXPN(_n) (0x0B330 + (0x04 * (_n))) /* Rx SAs - RW */
/*
* LinkSec Rx Keys - where _n is the SA no. and _m the 4 dwords of the 128 bit
* key - RW.
*/
#define E1000_LSECRXKEY(_n, _m) (0x0B350 + (0x10 * (_n)) + (0x04 * (_m)))
#define E1000_SSVPC 0x041A0 /* Switch Security Violation Pkt Cnt */
#define E1000_IPSCTRL 0xB430 /* IpSec Control Register */
#define E1000_IPSRXCMD 0x0B408 /* IPSec Rx Command Register - RW */
#define E1000_IPSRXIDX 0x0B400 /* IPSec Rx Index - RW */
/* IPSec Rx IPv4/v6 Address - RW */
#define E1000_IPSRXIPADDR(_n) (0x0B420 + (0x04 * (_n)))
/* IPSec Rx 128-bit Key - RW */
#define E1000_IPSRXKEY(_n) (0x0B410 + (0x04 * (_n)))
#define E1000_IPSRXSALT 0x0B404 /* IPSec Rx Salt - RW */
#define E1000_IPSRXSPI 0x0B40C /* IPSec Rx SPI - RW */
/* IPSec Tx 128-bit Key - RW */
#define E1000_IPSTXKEY(_n) (0x0B460 + (0x04 * (_n)))
#define E1000_IPSTXSALT 0x0B454 /* IPSec Tx Salt - RW */
#define E1000_IPSTXIDX 0x0B450 /* IPSec Tx SA IDX - RW */
#define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */
#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */
#define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */
#define E1000_CBTMPC 0x0402C /* Circuit Breaker Tx Packet Count */
#define E1000_HTDPMC 0x0403C /* Host Transmit Discarded Packets */
#define E1000_CBRDPC 0x04044 /* Circuit Breaker Rx Dropped Count */
#define E1000_CBRMPC 0x040FC /* Circuit Breaker Rx Packet Count */
#define E1000_RPTHC 0x04104 /* Rx Packets To Host */
#define E1000_HGPTC 0x04118 /* Host Good Packets Tx Count */
#define E1000_HTCBDPC 0x04124 /* Host Tx Circuit Breaker Dropped Count */
#define E1000_HGORCL 0x04128 /* Host Good Octets Received Count Low */
#define E1000_HGORCH 0x0412C /* Host Good Octets Received Count High */
#define E1000_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */
#define E1000_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */
#define E1000_LENERRS 0x04138 /* Length Errors Count */
#define E1000_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */
#define E1000_HRMPC 0x0A018 /* Header Redirection Missed Packet Count */
#define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */
#define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */
#define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */
#define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Pg - RW */
#define E1000_1GSTAT_RCV 0x04228 /* 1GSTAT Code Violation Pkt Cnt - RW */
#define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */
#define E1000_RLPML 0x05004 /* Rx Long Packet Max Length */
#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
#define E1000_RA 0x05400 /* Receive Address - RW Array */
#define E1000_RA2 0x054E0 /* 2nd half of Rx address array - RW Array */
#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
#define E1000_VT_CTL 0x0581C /* VMDq Control - RW */
#define E1000_CIAA 0x05B88 /* Config Indirect Access Address - RW */
#define E1000_CIAD 0x05B8C /* Config Indirect Access Data - RW */
#define E1000_VFQA0 0x0B000 /* VLAN Filter Queue Array 0 - RW Array */
#define E1000_VFQA1 0x0B200 /* VLAN Filter Queue Array 1 - RW Array */
#define E1000_WUC 0x05800 /* Wakeup Control - RW */
#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */
#define E1000_WUS 0x05810 /* Wakeup Status - RO */
#define E1000_MANC 0x05820 /* Management Control - RW */
#define E1000_IPAV 0x05838 /* IP Address Valid - RW */
#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */
#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */
#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */
#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */
#define E1000_PBACL 0x05B68 /* MSIx PBA Clear - Read/Write 1's to clear */
#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */
#define E1000_HOST_IF 0x08800 /* Host Interface */
#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */
#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */
/* Flexible Host Filter Table */
#define E1000_FHFT(_n) (0x09000 + ((_n) * 0x100))
/* Ext Flexible Host Filter Table */
#define E1000_FHFT_EXT(_n) (0x09A00 + ((_n) * 0x100))
#define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */
#define E1000_MDPHYA 0x0003C /* PHY address - RW */
#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */
/* Management Decision Filters */
#define E1000_MDEF(_n) (0x05890 + (4 * (_n)))
#define E1000_SW_FW_SYNC 0x05B5C /* SW-FW Synchronization - RW */
#define E1000_CCMCTL 0x05B48 /* CCM Control Register */
#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */
#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */
#define E1000_GCR 0x05B00 /* PCI-Ex Control */
#define E1000_GCR2 0x05B64 /* PCI-Ex Control #2 */
#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */
#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */
#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */
#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */
#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
#define E1000_SWSM 0x05B50 /* SW Semaphore */
#define E1000_FWSM 0x05B54 /* FW Semaphore */
/* Driver-only SW semaphore (not used by BOOT agents) */
#define E1000_SWSM2 0x05B58
#define E1000_DCA_ID 0x05B70 /* DCA Requester ID Information - RO */
#define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */
#define E1000_UFUSE 0x05B78 /* UFUSE - RO */
#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
#define E1000_HICR 0x08F00 /* Host Interface Control */
#define E1000_FWSTS 0x08F0C /* FW Status */
/* RSS registers */
#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
#define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */
#define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate INTR Ext*/
#define E1000_IMIRVP 0x05AC0 /* Immediate INT Rx VLAN Priority -RW */
#define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Alloc Reg -RW */
/* MSI-X Table entry addr low reg - RW */
#define E1000_MSIXTADD(_i) (0x0C000 + ((_i) * 0x10))
/* MSI-X Table entry addr upper reg - RW */
#define E1000_MSIXTUADD(_i) (0x0C004 + ((_i) * 0x10))
/* MSI-X Table entry message reg - RW */
#define E1000_MSIXTMSG(_i) (0x0C008 + ((_i) * 0x10))
/* MSI-X Table entry vector ctrl reg - RW */
#define E1000_MSIXVCTRL(_i) (0x0C00C + ((_i) * 0x10))
#define E1000_MSIXPBA 0x0E000 /* MSI-X Pending bit array */
#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */
#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */
#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */
#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */
/* VT Registers */
#define E1000_SWPBS 0x03004 /* Switch Packet Buffer Size - RW */
#define E1000_MBVFICR 0x00C80 /* Mailbox VF Cause - RWC */
#define E1000_MBVFIMR 0x00C84 /* Mailbox VF int Mask - RW */
#define E1000_VFLRE 0x00C88 /* VF Register Events - RWC */
#define E1000_VFRE 0x00C8C /* VF Receive Enables */
#define E1000_VFTE 0x00C90 /* VF Transmit Enables */
#define E1000_QDE 0x02408 /* Queue Drop Enable - RW */
#define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */
#define E1000_WVBR 0x03554 /* VM Wrong Behavior - RWS */
#define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */
#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */
#define E1000_IOVTCL 0x05BBC /* IOV Control Register */
#define E1000_VMRCTL 0X05D80 /* Virtual Mirror Rule Control */
#define E1000_VMRVLAN 0x05D90 /* Virtual Mirror Rule VLAN */
#define E1000_VMRVM 0x05DA0 /* Virtual Mirror Rule VM */
#define E1000_MDFB 0x03558 /* Malicious Driver free block */
#define E1000_LVMMC 0x03548 /* Last VM Misbehavior cause */
#define E1000_TXSWC 0x05ACC /* Tx Switch Control */
#define E1000_SCCRL 0x05DB0 /* Storm Control Control */
#define E1000_BSCTRH 0x05DB8 /* Broadcast Storm Control Threshold */
#define E1000_MSCTRH 0x05DBC /* Multicast Storm Control Threshold */
/* These act per VF so an array friendly macro is used */
#define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n)))
#define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n)))
#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
#define E1000_VFVMBMEM(_n) (0x00800 + (_n))
#define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n)))
/* VLAN Virtual Machine Filter - RW */
#define E1000_VLVF(_n) (0x05D00 + (4 * (_n)))
#define E1000_VMVIR(_n) (0x03700 + (4 * (_n)))
#define E1000_DVMOLR(_n) (0x0C038 + (0x40 * (_n))) /* DMA VM offload */
#define E1000_VTCTRL(_n) (0x10000 + (0x100 * (_n))) /* VT Control */
#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
#define E1000_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */
#define E1000_RXSTMPL 0x0B624 /* Rx timestamp Low - RO */
#define E1000_RXSTMPH 0x0B628 /* Rx timestamp High - RO */
#define E1000_RXSATRL 0x0B62C /* Rx timestamp attribute low - RO */
#define E1000_RXSATRH 0x0B630 /* Rx timestamp attribute high - RO */
#define E1000_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */
#define E1000_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */
#define E1000_SYSTIML 0x0B600 /* System time register Low - RO */
#define E1000_SYSTIMH 0x0B604 /* System time register High - RO */
#define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */
#define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */
#define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */
/* Filtering Registers */
#define E1000_SAQF(_n) (0x05980 + (4 * (_n))) /* Source Address Queue Fltr */
#define E1000_DAQF(_n) (0x059A0 + (4 * (_n))) /* Dest Address Queue Fltr */
#define E1000_SPQF(_n) (0x059C0 + (4 * (_n))) /* Source Port Queue Fltr */
#define E1000_FTQF(_n) (0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */
#define E1000_TTQF(_n) (0x059E0 + (4 * (_n))) /* 2-tuple Queue Fltr */
#define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */
#define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */
#define E1000_RTTDCS 0x3600 /* Reedtown Tx Desc plane control and status */
#define E1000_RTTPCS 0x3474 /* Reedtown Tx Packet Plane control and status */
#define E1000_RTRPCS 0x2474 /* Rx packet plane control and status */
#define E1000_RTRUP2TC 0x05AC4 /* Rx User Priority to Traffic Class */
#define E1000_RTTUP2TC 0x0418 /* Transmit User Priority to Traffic Class */
/* Tx Desc plane TC Rate-scheduler config */
#define E1000_RTTDTCRC(_n) (0x3610 + ((_n) * 4))
/* Tx Packet plane TC Rate-Scheduler Config */
#define E1000_RTTPTCRC(_n) (0x3480 + ((_n) * 4))
/* Rx Packet plane TC Rate-Scheduler Config */
#define E1000_RTRPTCRC(_n) (0x2480 + ((_n) * 4))
/* Tx Desc Plane TC Rate-Scheduler Status */
#define E1000_RTTDTCRS(_n) (0x3630 + ((_n) * 4))
/* Tx Desc Plane TC Rate-Scheduler MMW */
#define E1000_RTTDTCRM(_n) (0x3650 + ((_n) * 4))
/* Tx Packet plane TC Rate-Scheduler Status */
#define E1000_RTTPTCRS(_n) (0x34A0 + ((_n) * 4))
/* Tx Packet plane TC Rate-scheduler MMW */
#define E1000_RTTPTCRM(_n) (0x34C0 + ((_n) * 4))
/* Rx Packet plane TC Rate-Scheduler Status */
#define E1000_RTRPTCRS(_n) (0x24A0 + ((_n) * 4))
/* Rx Packet plane TC Rate-Scheduler MMW */
#define E1000_RTRPTCRM(_n) (0x24C0 + ((_n) * 4))
/* Tx Desc plane VM Rate-Scheduler MMW*/
#define E1000_RTTDVMRM(_n) (0x3670 + ((_n) * 4))
/* Tx BCN Rate-Scheduler MMW */
#define E1000_RTTBCNRM(_n) (0x3690 + ((_n) * 4))
#define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select */
#define E1000_RTTDVMRC 0x3608 /* Tx Desc Plane VM Rate-Scheduler Config */
#define E1000_RTTDVMRS 0x360C /* Tx Desc Plane VM Rate-Scheduler Status */
#define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config */
#define E1000_RTTBCNRS 0x36B4 /* Tx BCN Rate-Scheduler Status */
#define E1000_RTTBCNCR 0xB200 /* Tx BCN Control Register */
#define E1000_RTTBCNTG 0x35A4 /* Tx BCN Tagging */
#define E1000_RTTBCNCP 0xB208 /* Tx BCN Congestion point */
#define E1000_RTRBCNCR 0xB20C /* Rx BCN Control Register */
#define E1000_RTTBCNRD 0x36B8 /* Tx BCN Rate Drift */
#define E1000_PFCTOP 0x1080 /* Priority Flow Control Type and Opcode */
#define E1000_RTTBCNIDX 0xB204 /* Tx BCN Congestion Point */
#define E1000_RTTBCNACH 0x0B214 /* Tx BCN Control High */
#define E1000_RTTBCNACL 0x0B210 /* Tx BCN Control Low */
/* DMA Coalescing registers */
#define E1000_DMACR 0x02508 /* Control Register */
#define E1000_DMCTXTH 0x03550 /* Transmit Threshold */
#define E1000_DMCTLX 0x02514 /* Time to Lx Request */
#define E1000_DMCRTRH 0x05DD0 /* Receive Packet Rate Threshold */
#define E1000_DMCCNT 0x05DD4 /* Current Rx Count */
#define E1000_FCRTC 0x02170 /* Flow Control Rx high watermark */
#define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */
/* PCIe Parity Status Register */
#define E1000_PCIEERRSTS 0x05BA8
#define E1000_PROXYS 0x5F64 /* Proxying Status */
#define E1000_PROXYFC 0x5F60 /* Proxying Filter Control */
/* Thermal sensor configuration and status registers */
#define E1000_THMJT 0x08100 /* Junction Temperature */
#define E1000_THLOWTC 0x08104 /* Low Threshold Control */
#define E1000_THMIDTC 0x08108 /* Mid Threshold Control */
#define E1000_THHIGHTC 0x0810C /* High Threshold Control */
#define E1000_THSTAT 0x08110 /* Thermal Sensor Status */
/* Energy Efficient Ethernet "EEE" registers */
#define E1000_IPCNFG 0x0E38 /* Internal PHY Configuration */
#define E1000_LTRC 0x01A0 /* Latency Tolerance Reporting Control */
#define E1000_EEER 0x0E30 /* Energy Efficient Ethernet "EEE"*/
#define E1000_EEE_SU 0x0E34 /* EEE Setup */
#define E1000_TLPIC 0x4148 /* EEE Tx LPI Count - TLPIC */
#define E1000_RLPIC 0x414C /* EEE Rx LPI Count - RLPIC */
/* OS2BMC Registers */
#define E1000_B2OSPC 0x08FE0 /* BMC2OS packets sent by BMC */
#define E1000_B2OGPRC 0x04158 /* BMC2OS packets received by host */
#define E1000_O2BGPTC 0x08FE4 /* OS2BMC packets received by BMC */
#define E1000_O2BSPC 0x0415C /* OS2BMC packets transmitted by host */
#endif

View File

@ -0,0 +1,717 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
/* Linux PRO/1000 Ethernet Driver main header file */
#ifndef _IGB_H_
#define _IGB_H_
#include <linux/kobject.h>
#ifndef IGB_NO_LRO
#include <net/tcp.h>
#endif
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
#ifdef SIOCETHTOOL
#include <linux/ethtool.h>
#endif
#ifdef HAVE_HW_TIME_STAMP
#include <linux/clocksource.h>
#include <linux/timecompare.h>
#include <linux/net_tstamp.h>
#endif
struct igb_adapter;
#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
#define IGB_DCA
#endif
#ifdef IGB_DCA
#include <linux/dca.h>
#endif
#ifndef HAVE_HW_TIME_STAMP
#undef IGB_PER_PKT_TIMESTAMP
#endif
#include "kcompat.h"
#ifdef HAVE_SCTP
#include <linux/sctp.h>
#endif
#include "e1000_api.h"
#include "e1000_82575.h"
#include "e1000_manage.h"
#include "e1000_mbx.h"
#define IGB_ERR(args...) printk(KERN_ERR "igb: " args)
#define PFX "igb: "
#define DPRINTK(nlevel, klevel, fmt, args...) \
(void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \
printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \
__FUNCTION__ , ## args))
/* Interrupt defines */
#define IGB_START_ITR 648 /* ~6000 ints/sec */
#define IGB_4K_ITR 980
#define IGB_20K_ITR 196
#define IGB_70K_ITR 56
/* Interrupt modes, as used by the IntMode paramter */
#define IGB_INT_MODE_LEGACY 0
#define IGB_INT_MODE_MSI 1
#define IGB_INT_MODE_MSIX 2
/* TX/RX descriptor defines */
#define IGB_DEFAULT_TXD 256
#define IGB_DEFAULT_TX_WORK 128
#define IGB_MIN_TXD 80
#define IGB_MAX_TXD 4096
#define IGB_DEFAULT_RXD 256
#define IGB_MIN_RXD 80
#define IGB_MAX_RXD 4096
#define IGB_MIN_ITR_USECS 10 /* 100k irq/sec */
#define IGB_MAX_ITR_USECS 8191 /* 120 irq/sec */
#define NON_Q_VECTORS 1
#define MAX_Q_VECTORS 10
/* Transmit and receive queues */
#define IGB_MAX_RX_QUEUES 16
#define IGB_MAX_TX_QUEUES 16
#define IGB_MAX_VF_MC_ENTRIES 30
#define IGB_MAX_VF_FUNCTIONS 8
#define IGB_82576_VF_DEV_ID 0x10CA
#define IGB_I350_VF_DEV_ID 0x1520
#define IGB_MAX_UTA_ENTRIES 128
#define MAX_EMULATION_MAC_ADDRS 16
#define OUI_LEN 3
#define IGB_MAX_VMDQ_QUEUES 8
struct vf_data_storage {
unsigned char vf_mac_addresses[ETH_ALEN];
u16 vf_mc_hashes[IGB_MAX_VF_MC_ENTRIES];
u16 num_vf_mc_hashes;
u16 default_vf_vlan_id;
u16 vlans_enabled;
unsigned char em_mac_addresses[MAX_EMULATION_MAC_ADDRS * ETH_ALEN];
u32 uta_table_copy[IGB_MAX_UTA_ENTRIES];
u32 flags;
unsigned long last_nack;
#ifdef IFLA_VF_MAX
u16 pf_vlan; /* When set, guest VLAN config not allowed. */
u16 pf_qos;
u16 tx_rate;
#endif
struct pci_dev *vfdev;
};
#define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */
#define IGB_VF_FLAG_UNI_PROMISC 0x00000002 /* VF has unicast promisc */
#define IGB_VF_FLAG_MULTI_PROMISC 0x00000004 /* VF has multicast promisc */
#define IGB_VF_FLAG_PF_SET_MAC 0x00000008 /* PF has set MAC address */
/* RX descriptor control thresholds.
* PTHRESH - MAC will consider prefetch if it has fewer than this number of
* descriptors available in its onboard memory.
* Setting this to 0 disables RX descriptor prefetch.
* HTHRESH - MAC will only prefetch if there are at least this many descriptors
* available in host memory.
* If PTHRESH is 0, this should also be 0.
* WTHRESH - RX descriptor writeback threshold - MAC will delay writing back
* descriptors until either it has this many to write back, or the
* ITR timer expires.
*/
#define IGB_RX_PTHRESH 8
#define IGB_RX_HTHRESH 8
#define IGB_TX_PTHRESH 8
#define IGB_TX_HTHRESH 1
#define IGB_RX_WTHRESH ((hw->mac.type == e1000_82576 && \
adapter->msix_entries) ? 1 : 4)
#define IGB_TX_WTHRESH ((hw->mac.type == e1000_82576 && \
adapter->msix_entries) ? 1 : 16)
/* this is the size past which hardware will drop packets when setting LPE=0 */
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
/* NOTE: netdev_alloc_skb reserves 16 bytes, NET_IP_ALIGN means we
* reserve 2 more, and skb_shared_info adds an additional 384 more,
* this adds roughly 448 bytes of extra data meaning the smallest
* allocation we could have is 1K.
* i.e. RXBUFFER_512 --> size-1024 slab
*/
/* Supported Rx Buffer Sizes */
#define IGB_RXBUFFER_512 512
#define IGB_RXBUFFER_16384 16384
#define IGB_RX_HDR_LEN IGB_RXBUFFER_512
/* Packet Buffer allocations */
#define IGB_PBA_BYTES_SHIFT 0xA
#define IGB_TX_HEAD_ADDR_SHIFT 7
#define IGB_PBA_TX_MASK 0xFFFF0000
#define IGB_FC_PAUSE_TIME 0x0680 /* 858 usec */
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
#define IGB_TX_QUEUE_WAKE 32
/* How many Rx Buffers do we bundle into one write to the hardware ? */
#define IGB_RX_BUFFER_WRITE 16 /* Must be power of 2 */
#define IGB_EEPROM_APME 0x0400
#ifndef ETH_TP_MDI_X
#define AUTO_ALL_MODES 0
#endif
#ifndef IGB_MASTER_SLAVE
/* Switch to override PHY master/slave setting */
#define IGB_MASTER_SLAVE e1000_ms_hw_default
#endif
#define IGB_MNG_VLAN_NONE -1
#ifndef IGB_NO_LRO
#define IGB_LRO_MAX 32 /*Maximum number of LRO descriptors*/
struct igb_lro_stats {
u32 flushed;
u32 coal;
u32 recycled;
};
/*
* igb_lro_header - header format to be aggregated by LRO
* @iph: IP header without options
* @tcp: TCP header
* @ts: Optional TCP timestamp data in TCP options
*
* This structure relies on the check above that verifies that the header
* is IPv4 and does not contain any options.
*/
struct igb_lrohdr {
struct iphdr iph;
struct tcphdr th;
__be32 ts[0];
};
struct igb_lro_list {
struct sk_buff_head active;
struct igb_lro_stats stats;
};
#endif /* IGB_NO_LRO */
struct igb_cb {
#ifndef IGB_NO_LRO
union { /* Union defining head/tail partner */
struct sk_buff *head;
struct sk_buff *tail;
};
__be32 tsecr; /* timestamp echo response */
u32 tsval; /* timestamp value in host order */
u32 next_seq; /* next expected sequence number */
u16 free; /* 65521 minus total size */
u16 mss; /* size of data portion of packet */
u16 append_cnt; /* number of skb's appended */
#endif /* IGB_NO_LRO */
#ifdef HAVE_VLAN_RX_REGISTER
u16 vid; /* VLAN tag */
#endif
};
#define IGB_CB(skb) ((struct igb_cb *)(skb)->cb)
#define IGB_TX_FLAGS_CSUM 0x00000001
#define IGB_TX_FLAGS_VLAN 0x00000002
#define IGB_TX_FLAGS_TSO 0x00000004
#define IGB_TX_FLAGS_IPV4 0x00000008
#define IGB_TX_FLAGS_TSTAMP 0x00000010
#define IGB_TX_FLAGS_VLAN_MASK 0xffff0000
#define IGB_TX_FLAGS_VLAN_SHIFT 16
/* wrapper around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer */
struct igb_tx_buffer {
union e1000_adv_tx_desc *next_to_watch;
unsigned long time_stamp;
struct sk_buff *skb;
unsigned int bytecount;
u16 gso_segs;
__be16 protocol;
DEFINE_DMA_UNMAP_ADDR(dma);
DEFINE_DMA_UNMAP_LEN(len);
u32 tx_flags;
};
struct igb_rx_buffer {
struct sk_buff *skb;
dma_addr_t dma;
#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT
struct page *page;
dma_addr_t page_dma;
u32 page_offset;
#endif
};
struct igb_tx_queue_stats {
u64 packets;
u64 bytes;
u64 restart_queue;
};
struct igb_rx_queue_stats {
u64 packets;
u64 bytes;
u64 drops;
u64 csum_err;
u64 alloc_failed;
};
struct igb_ring_container {
struct igb_ring *ring; /* pointer to linked list of rings */
unsigned int total_bytes; /* total bytes processed this int */
unsigned int total_packets; /* total packets processed this int */
u16 work_limit; /* total work allowed per interrupt */
u8 count; /* total number of rings in vector */
u8 itr; /* current ITR setting for ring */
};
struct igb_q_vector {
struct igb_adapter *adapter; /* backlink */
int cpu; /* CPU for DCA */
u32 eims_value; /* EIMS mask value */
struct igb_ring_container rx, tx;
struct napi_struct napi;
int numa_node;
u16 itr_val;
u8 set_itr;
void __iomem *itr_register;
#ifndef IGB_NO_LRO
struct igb_lro_list *lrolist; /* LRO list for queue vector*/
#endif
char name[IFNAMSIZ + 9];
#ifndef HAVE_NETDEV_NAPI_LIST
struct net_device poll_dev;
#endif
} ____cacheline_internodealigned_in_smp;
struct igb_ring {
struct igb_q_vector *q_vector; /* backlink to q_vector */
struct net_device *netdev; /* back pointer to net_device */
struct device *dev; /* device for dma mapping */
union { /* array of buffer info structs */
struct igb_tx_buffer *tx_buffer_info;
struct igb_rx_buffer *rx_buffer_info;
};
void *desc; /* descriptor ring memory */
unsigned long flags; /* ring specific flags */
void __iomem *tail; /* pointer to ring tail register */
u16 count; /* number of desc. in the ring */
u8 queue_index; /* logical index of the ring*/
u8 reg_idx; /* physical index of the ring */
u32 size; /* length of desc. ring in bytes */
/* everything past this point are written often */
u16 next_to_clean ____cacheline_aligned_in_smp;
u16 next_to_use;
union {
/* TX */
struct {
struct igb_tx_queue_stats tx_stats;
};
/* RX */
struct {
struct igb_rx_queue_stats rx_stats;
#ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT
u16 rx_buffer_len;
#endif
};
};
#ifdef CONFIG_IGB_VMDQ_NETDEV
struct net_device *vmdq_netdev;
int vqueue_index; /* queue index for virtual netdev */
#endif
/* Items past this point are only used during ring alloc / free */
dma_addr_t dma; /* phys address of the ring */
int numa_node; /* node to alloc ring memory on */
} ____cacheline_internodealigned_in_smp;
enum e1000_ring_flags_t {
#ifndef HAVE_NDO_SET_FEATURES
IGB_RING_FLAG_RX_CSUM,
#endif
IGB_RING_FLAG_RX_SCTP_CSUM,
IGB_RING_FLAG_RX_LB_VLAN_BSWAP,
IGB_RING_FLAG_TX_CTX_IDX,
IGB_RING_FLAG_TX_DETECT_HANG,
};
struct igb_mac_addr {
u8 addr[ETH_ALEN];
u16 queue;
u16 state; /* bitmask */
};
#define IGB_MAC_STATE_DEFAULT 0x1
#define IGB_MAC_STATE_MODIFIED 0x2
#define IGB_MAC_STATE_IN_USE 0x4
#define IGB_TXD_DCMD (E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_RS)
#define IGB_RX_DESC(R, i) \
(&(((union e1000_adv_rx_desc *)((R)->desc))[i]))
#define IGB_TX_DESC(R, i) \
(&(((union e1000_adv_tx_desc *)((R)->desc))[i]))
#define IGB_TX_CTXTDESC(R, i) \
(&(((struct e1000_adv_tx_context_desc *)((R)->desc))[i]))
#ifdef CONFIG_IGB_VMDQ_NETDEV
#define netdev_ring(ring) \
((ring->vmdq_netdev ? ring->vmdq_netdev : ring->netdev))
#define ring_queue_index(ring) \
((ring->vmdq_netdev ? ring->vqueue_index : ring->queue_index))
#else
#define netdev_ring(ring) (ring->netdev)
#define ring_queue_index(ring) (ring->queue_index)
#endif /* CONFIG_IGB_VMDQ_NETDEV */
/* igb_test_staterr - tests bits within Rx descriptor status and error fields */
static inline __le32 igb_test_staterr(union e1000_adv_rx_desc *rx_desc,
const u32 stat_err_bits)
{
return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits);
}
/* igb_desc_unused - calculate if we have unused descriptors */
static inline u16 igb_desc_unused(const struct igb_ring *ring)
{
u16 ntc = ring->next_to_clean;
u16 ntu = ring->next_to_use;
return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1;
}
#ifdef CONFIG_BQL
static inline struct netdev_queue *txring_txq(const struct igb_ring *tx_ring)
{
return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
}
#endif /* CONFIG_BQL */
// #ifdef EXT_THERMAL_SENSOR_SUPPORT
// #ifdef IGB_PROCFS
struct igb_therm_proc_data
{
struct e1000_hw *hw;
struct e1000_thermal_diode_data *sensor_data;
};
// #endif /* IGB_PROCFS */
// #endif /* EXT_THERMAL_SENSOR_SUPPORT */
/* board specific private data structure */
struct igb_adapter {
#ifdef HAVE_VLAN_RX_REGISTER
/* vlgrp must be first member of structure */
struct vlan_group *vlgrp;
#else
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
#endif
struct net_device *netdev;
unsigned long state;
unsigned int flags;
unsigned int num_q_vectors;
struct msix_entry *msix_entries;
/* TX */
u16 tx_work_limit;
u32 tx_timeout_count;
int num_tx_queues;
struct igb_ring *tx_ring[IGB_MAX_TX_QUEUES];
/* RX */
int num_rx_queues;
struct igb_ring *rx_ring[IGB_MAX_RX_QUEUES];
struct timer_list watchdog_timer;
struct timer_list dma_err_timer;
struct timer_list phy_info_timer;
u16 mng_vlan_id;
u32 bd_number;
u32 wol;
u32 en_mng_pt;
u16 link_speed;
u16 link_duplex;
u8 port_num;
/* Interrupt Throttle Rate */
u32 rx_itr_setting;
u32 tx_itr_setting;
struct work_struct reset_task;
struct work_struct watchdog_task;
struct work_struct dma_err_task;
bool fc_autoneg;
u8 tx_timeout_factor;
u32 max_frame_size;
/* OS defined structs */
struct pci_dev *pdev;
#ifndef HAVE_NETDEV_STATS_IN_NETDEV
struct net_device_stats net_stats;
#endif
#ifndef IGB_NO_LRO
struct igb_lro_stats lro_stats;
#endif
#ifdef HAVE_HW_TIME_STAMP
struct cyclecounter cycles;
struct timecounter clock;
struct timecompare compare;
struct hwtstamp_config hwtstamp_config;
#endif
/* structs defined in e1000_hw.h */
struct e1000_hw hw;
struct e1000_hw_stats stats;
struct e1000_phy_info phy_info;
struct e1000_phy_stats phy_stats;
#ifdef ETHTOOL_TEST
u32 test_icr;
struct igb_ring test_tx_ring;
struct igb_ring test_rx_ring;
#endif
int msg_enable;
struct igb_q_vector *q_vector[MAX_Q_VECTORS];
u32 eims_enable_mask;
u32 eims_other;
/* to not mess up cache alignment, always add to the bottom */
u32 eeprom_wol;
u32 *config_space;
u16 tx_ring_count;
u16 rx_ring_count;
struct vf_data_storage *vf_data;
#ifdef IFLA_VF_MAX
int vf_rate_link_speed;
#endif
u32 lli_port;
u32 lli_size;
unsigned int vfs_allocated_count;
/* Malicious Driver Detection flag. Valid only when SR-IOV is enabled */
bool mdd;
int int_mode;
u32 rss_queues;
u32 vmdq_pools;
u16 fw_version;
int node;
u32 wvbr;
struct igb_mac_addr *mac_table;
#ifdef CONFIG_IGB_VMDQ_NETDEV
struct net_device *vmdq_netdev[IGB_MAX_VMDQ_QUEUES];
#endif
int vferr_refcount;
int dmac;
u32 *shadow_vfta;
/* External Thermal Sensor support flag */
bool ets;
#ifdef IGB_SYSFS
struct kobject *info_kobj;
struct kobject *therm_kobj[E1000_MAX_SENSORS];
#else /* IGB_SYSFS */
#ifdef IGB_PROCFS
struct proc_dir_entry *eth_dir;
struct proc_dir_entry *info_dir;
struct proc_dir_entry *therm_dir[E1000_MAX_SENSORS];
struct igb_therm_proc_data therm_data[E1000_MAX_SENSORS];
#endif /* IGB_PROCFS */
#endif /* IGB_SYSFS */
};
#ifdef CONFIG_IGB_VMDQ_NETDEV
struct igb_vmdq_adapter {
#ifdef HAVE_VLAN_RX_REGISTER
/* vlgrp must be first member of structure */
struct vlan_group *vlgrp;
#else
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
#endif
struct igb_adapter *real_adapter;
struct net_device *vnetdev;
struct net_device_stats net_stats;
struct igb_ring *tx_ring;
struct igb_ring *rx_ring;
};
#endif
#define IGB_FLAG_HAS_MSI (1 << 0)
#define IGB_FLAG_MSI_ENABLE (1 << 1)
#define IGB_FLAG_DCA_ENABLED (1 << 2)
#define IGB_FLAG_LLI_PUSH (1 << 3)
#define IGB_FLAG_QUAD_PORT_A (1 << 4)
#define IGB_FLAG_QUEUE_PAIRS (1 << 5)
#define IGB_FLAG_EEE (1 << 6)
#define IGB_FLAG_DMAC (1 << 7)
#define IGB_FLAG_DETECT_BAD_DMA (1 << 8)
#define IGB_MIN_TXPBSIZE 20408
#define IGB_TX_BUF_4096 4096
#define IGB_DMCTLX_DCFLUSH_DIS 0x80000000 /* Disable DMA Coal Flush */
/* DMA Coalescing defines */
#define IGB_DMAC_DISABLE 0
#define IGB_DMAC_MIN 250
#define IGB_DMAC_500 500
#define IGB_DMAC_EN_DEFAULT 1000
#define IGB_DMAC_2000 2000
#define IGB_DMAC_3000 3000
#define IGB_DMAC_4000 4000
#define IGB_DMAC_5000 5000
#define IGB_DMAC_6000 6000
#define IGB_DMAC_7000 7000
#define IGB_DMAC_8000 8000
#define IGB_DMAC_9000 9000
#define IGB_DMAC_MAX 10000
#define IGB_82576_TSYNC_SHIFT 19
#define IGB_82580_TSYNC_SHIFT 24
#define IGB_TS_HDR_LEN 16
/* CEM Support */
#define FW_HDR_LEN 0x4
#define FW_CMD_DRV_INFO 0xDD
#define FW_CMD_DRV_INFO_LEN 0x5
#define FW_CMD_RESERVED 0X0
#define FW_RESP_SUCCESS 0x1
#define FW_UNUSED_VER 0x0
#define FW_MAX_RETRIES 3
#define FW_STATUS_SUCCESS 0x1
#define FW_FAMILY_DRV_VER 0Xffffffff
#define IGB_MAX_LINK_TRIES 20
struct e1000_fw_hdr {
u8 cmd;
u8 buf_len;
union
{
u8 cmd_resv;
u8 ret_status;
} cmd_or_resp;
u8 checksum;
};
struct e1000_fw_drv_info {
struct e1000_fw_hdr hdr;
u8 port_num;
u32 drv_version;
u16 pad; /* end spacing to ensure length is mult. of dword */
u8 pad2; /* end spacing to ensure length is mult. of dword2 */
};
enum e1000_state_t {
__IGB_TESTING,
__IGB_RESETTING,
__IGB_DOWN
};
extern char igb_driver_name[];
extern char igb_driver_version[];
extern int igb_up(struct igb_adapter *);
extern void igb_down(struct igb_adapter *);
extern void igb_reinit_locked(struct igb_adapter *);
extern void igb_reset(struct igb_adapter *);
extern int igb_set_spd_dplx(struct igb_adapter *, u16);
extern int igb_setup_tx_resources(struct igb_ring *);
extern int igb_setup_rx_resources(struct igb_ring *);
extern void igb_free_tx_resources(struct igb_ring *);
extern void igb_free_rx_resources(struct igb_ring *);
extern void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *);
extern void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *);
extern void igb_setup_tctl(struct igb_adapter *);
extern void igb_setup_rctl(struct igb_adapter *);
extern netdev_tx_t igb_xmit_frame_ring(struct sk_buff *, struct igb_ring *);
extern void igb_unmap_and_free_tx_resource(struct igb_ring *,
struct igb_tx_buffer *);
extern void igb_alloc_rx_buffers(struct igb_ring *, u16);
extern void igb_clean_rx_ring(struct igb_ring *);
extern void igb_update_stats(struct igb_adapter *);
extern bool igb_has_link(struct igb_adapter *adapter);
extern void igb_set_ethtool_ops(struct net_device *);
extern void igb_check_options(struct igb_adapter *);
extern void igb_power_up_link(struct igb_adapter *);
#ifdef ETHTOOL_OPS_COMPAT
extern int ethtool_ioctl(struct ifreq *);
#endif
extern int igb_write_mc_addr_list(struct net_device *netdev);
extern int igb_add_mac_filter(struct igb_adapter *adapter, u8 *addr, u16 queue);
extern int igb_del_mac_filter(struct igb_adapter *adapter, u8* addr, u16 queue);
extern int igb_available_rars(struct igb_adapter *adapter);
extern s32 igb_vlvf_set(struct igb_adapter *, u32, bool, u32);
extern void igb_configure_vt_default_pool(struct igb_adapter *adapter);
extern void igb_enable_vlan_tags(struct igb_adapter *adapter);
#ifndef HAVE_VLAN_RX_REGISTER
extern void igb_vlan_mode(struct net_device *, u32);
#endif
#ifdef IGB_SYSFS
void igb_sysfs_exit(struct igb_adapter *adapter);
int igb_sysfs_init(struct igb_adapter *adapter);
#else
#ifdef IGB_PROCFS
int igb_procfs_init(struct igb_adapter* adapter);
void igb_procfs_exit(struct igb_adapter* adapter);
int igb_procfs_topdir_init(void);
void igb_procfs_topdir_exit(void);
#endif /* IGB_PROCFS */
#endif /* IGB_SYSFS */
#endif /* _IGB_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,835 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#include <linux/netdevice.h>
#include "igb.h"
/* This is the only thing that needs to be changed to adjust the
* maximum number of ports that the driver can manage.
*/
#define IGB_MAX_NIC 32
#define OPTION_UNSET -1
#define OPTION_DISABLED 0
#define OPTION_ENABLED 1
#define MAX_NUM_LIST_OPTS 15
/* All parameters are treated the same, as an integer array of values.
* This macro just reduces the need to repeat the same declaration code
* over and over (plus this helps to avoid typo bugs).
*/
#define IGB_PARAM_INIT { [0 ... IGB_MAX_NIC] = OPTION_UNSET }
#ifndef module_param_array
/* Module Parameters are always initialized to -1, so that the driver
* can tell the difference between no user specified value or the
* user asking for the default value.
* The true default values are loaded in when igb_check_options is called.
*
* This is a GCC extension to ANSI C.
* See the item "Labeled Elements in Initializers" in the section
* "Extensions to the C Language Family" of the GCC documentation.
*/
#define IGB_PARAM(X, desc) \
static const int __devinitdata X[IGB_MAX_NIC+1] = IGB_PARAM_INIT; \
MODULE_PARM(X, "1-" __MODULE_STRING(IGB_MAX_NIC) "i"); \
MODULE_PARM_DESC(X, desc);
#else
#define IGB_PARAM(X, desc) \
static int __devinitdata X[IGB_MAX_NIC+1] = IGB_PARAM_INIT; \
static unsigned int num_##X; \
module_param_array_named(X, X, int, &num_##X, 0); \
MODULE_PARM_DESC(X, desc);
#endif
/* Interrupt Throttle Rate (interrupts/sec)
*
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
*/
IGB_PARAM(InterruptThrottleRate,
"Maximum interrupts per second, per vector, (max 100000), default 3=adaptive");
#define DEFAULT_ITR 3
#define MAX_ITR 100000
/* #define MIN_ITR 120 */
#define MIN_ITR 0
/* IntMode (Interrupt Mode)
*
* Valid Range: 0 - 2
*
* Default Value: 2 (MSI-X)
*/
IGB_PARAM(IntMode, "Change Interrupt Mode (0=Legacy, 1=MSI, 2=MSI-X), default 2");
#define MAX_INTMODE IGB_INT_MODE_MSIX
#define MIN_INTMODE IGB_INT_MODE_LEGACY
IGB_PARAM(Node, "set the starting node to allocate memory on, default -1");
/* LLIPort (Low Latency Interrupt TCP Port)
*
* Valid Range: 0 - 65535
*
* Default Value: 0 (disabled)
*/
IGB_PARAM(LLIPort, "Low Latency Interrupt TCP Port (0-65535), default 0=off");
#define DEFAULT_LLIPORT 0
#define MAX_LLIPORT 0xFFFF
#define MIN_LLIPORT 0
/* LLIPush (Low Latency Interrupt on TCP Push flag)
*
* Valid Range: 0, 1
*
* Default Value: 0 (disabled)
*/
IGB_PARAM(LLIPush, "Low Latency Interrupt on TCP Push flag (0,1), default 0=off");
#define DEFAULT_LLIPUSH 0
#define MAX_LLIPUSH 1
#define MIN_LLIPUSH 0
/* LLISize (Low Latency Interrupt on Packet Size)
*
* Valid Range: 0 - 1500
*
* Default Value: 0 (disabled)
*/
IGB_PARAM(LLISize, "Low Latency Interrupt on Packet Size (0-1500), default 0=off");
#define DEFAULT_LLISIZE 0
#define MAX_LLISIZE 1500
#define MIN_LLISIZE 0
/* RSS (Enable RSS multiqueue receive)
*
* Valid Range: 0 - 8
*
* Default Value: 1
*/
IGB_PARAM(RSS, "Number of Receive-Side Scaling Descriptor Queues (0-8), default 1=number of cpus");
#define DEFAULT_RSS 1
#define MAX_RSS 8
#define MIN_RSS 0
/* VMDQ (Enable VMDq multiqueue receive)
*
* Valid Range: 0 - 8
*
* Default Value: 0
*/
IGB_PARAM(VMDQ, "Number of Virtual Machine Device Queues: 0-1 = disable, 2-8 enable, default 0");
#define DEFAULT_VMDQ 0
#define MAX_VMDQ MAX_RSS
#define MIN_VMDQ 0
/* max_vfs (Enable SR-IOV VF devices)
*
* Valid Range: 0 - 7
*
* Default Value: 0
*/
IGB_PARAM(max_vfs, "Number of Virtual Functions: 0 = disable, 1-7 enable, default 0");
#define DEFAULT_SRIOV 0
#define MAX_SRIOV 7
#define MIN_SRIOV 0
/* MDD (Enable Malicious Driver Detection)
*
* Only available when SR-IOV is enabled - max_vfs is greater than 0
*
* Valid Range: 0, 1
*
* Default Value: 1
*/
IGB_PARAM(MDD, "Malicious Driver Detection (0/1), default 1 = enabled. "
"Only available when max_vfs is greater than 0");
/* QueuePairs (Enable TX/RX queue pairs for interrupt handling)
*
* Valid Range: 0 - 1
*
* Default Value: 1
*/
IGB_PARAM(QueuePairs, "Enable TX/RX queue pairs for interrupt handling (0,1), default 1=on");
#define DEFAULT_QUEUE_PAIRS 1
#define MAX_QUEUE_PAIRS 1
#define MIN_QUEUE_PAIRS 0
/* Enable/disable EEE (a.k.a. IEEE802.3az)
*
* Valid Range: 0, 1
*
* Default Value: 1
*/
IGB_PARAM(EEE, "Enable/disable on parts that support the feature");
/* Enable/disable DMA Coalescing
*
* Valid Values: 0(off), 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000,
* 9000, 10000(msec), 250(usec), 500(usec)
*
* Default Value: 0
*/
IGB_PARAM(DMAC, "Disable or set latency for DMA Coalescing ((0=off, 1000-10000(msec), 250, 500 (usec))");
#ifndef IGB_NO_LRO
/* Enable/disable Large Receive Offload
*
* Valid Values: 0(off), 1(on)
*
* Default Value: 0
*/
IGB_PARAM(LRO, "Large Receive Offload (0,1), default 0=off");
#endif
struct igb_opt_list {
int i;
char *str;
};
struct igb_option {
enum { enable_option, range_option, list_option } type;
const char *name;
const char *err;
int def;
union {
struct { /* range_option info */
int min;
int max;
} r;
struct { /* list_option info */
int nr;
struct igb_opt_list *p;
} l;
} arg;
};
static int __devinit igb_validate_option(unsigned int *value,
struct igb_option *opt,
struct igb_adapter *adapter)
{
if (*value == OPTION_UNSET) {
*value = opt->def;
return 0;
}
switch (opt->type) {
case enable_option:
switch (*value) {
case OPTION_ENABLED:
DPRINTK(PROBE, INFO, "%s Enabled\n", opt->name);
return 0;
case OPTION_DISABLED:
DPRINTK(PROBE, INFO, "%s Disabled\n", opt->name);
return 0;
}
break;
case range_option:
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
DPRINTK(PROBE, INFO,
"%s set to %d\n", opt->name, *value);
return 0;
}
break;
case list_option: {
int i;
struct igb_opt_list *ent;
for (i = 0; i < opt->arg.l.nr; i++) {
ent = &opt->arg.l.p[i];
if (*value == ent->i) {
if (ent->str[0] != '\0')
DPRINTK(PROBE, INFO, "%s\n", ent->str);
return 0;
}
}
}
break;
default:
BUG();
}
DPRINTK(PROBE, INFO, "Invalid %s value specified (%d) %s\n",
opt->name, *value, opt->err);
*value = opt->def;
return -1;
}
/**
* igb_check_options - Range Checking for Command Line Parameters
* @adapter: board private structure
*
* This routine checks all command line parameters for valid user
* input. If an invalid value is given, or if no user specified
* value exists, a default value is used. The final value is stored
* in a variable in the adapter structure.
**/
void __devinit igb_check_options(struct igb_adapter *adapter)
{
int bd = adapter->bd_number;
struct e1000_hw *hw = &adapter->hw;
if (bd >= IGB_MAX_NIC) {
DPRINTK(PROBE, NOTICE,
"Warning: no configuration for board #%d\n", bd);
DPRINTK(PROBE, NOTICE, "Using defaults for all values\n");
#ifndef module_param_array
bd = IGB_MAX_NIC;
#endif
}
{ /* Interrupt Throttling Rate */
struct igb_option opt = {
.type = range_option,
.name = "Interrupt Throttling Rate (ints/sec)",
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
.def = DEFAULT_ITR,
.arg = { .r = { .min = MIN_ITR,
.max = MAX_ITR } }
};
#ifdef module_param_array
if (num_InterruptThrottleRate > bd) {
#endif
unsigned int itr = InterruptThrottleRate[bd];
switch (itr) {
case 0:
DPRINTK(PROBE, INFO, "%s turned off\n",
opt.name);
if(hw->mac.type >= e1000_i350)
adapter->dmac = IGB_DMAC_DISABLE;
adapter->rx_itr_setting = itr;
break;
case 1:
DPRINTK(PROBE, INFO, "%s set to dynamic mode\n",
opt.name);
adapter->rx_itr_setting = itr;
break;
case 3:
DPRINTK(PROBE, INFO,
"%s set to dynamic conservative mode\n",
opt.name);
adapter->rx_itr_setting = itr;
break;
default:
igb_validate_option(&itr, &opt, adapter);
/* Save the setting, because the dynamic bits
* change itr. In case of invalid user value,
* default to conservative mode, else need to
* clear the lower two bits because they are
* used as control */
if (itr == 3) {
adapter->rx_itr_setting = itr;
} else {
adapter->rx_itr_setting = 1000000000 /
(itr * 256);
adapter->rx_itr_setting &= ~3;
}
break;
}
#ifdef module_param_array
} else {
adapter->rx_itr_setting = opt.def;
}
#endif
adapter->tx_itr_setting = adapter->rx_itr_setting;
}
{ /* Interrupt Mode */
struct igb_option opt = {
.type = range_option,
.name = "Interrupt Mode",
.err = "defaulting to 2 (MSI-X)",
.def = IGB_INT_MODE_MSIX,
.arg = { .r = { .min = MIN_INTMODE,
.max = MAX_INTMODE } }
};
#ifdef module_param_array
if (num_IntMode > bd) {
#endif
unsigned int int_mode = IntMode[bd];
igb_validate_option(&int_mode, &opt, adapter);
adapter->int_mode = int_mode;
#ifdef module_param_array
} else {
adapter->int_mode = opt.def;
}
#endif
}
{ /* Low Latency Interrupt TCP Port */
struct igb_option opt = {
.type = range_option,
.name = "Low Latency Interrupt TCP Port",
.err = "using default of " __MODULE_STRING(DEFAULT_LLIPORT),
.def = DEFAULT_LLIPORT,
.arg = { .r = { .min = MIN_LLIPORT,
.max = MAX_LLIPORT } }
};
#ifdef module_param_array
if (num_LLIPort > bd) {
#endif
adapter->lli_port = LLIPort[bd];
if (adapter->lli_port) {
igb_validate_option(&adapter->lli_port, &opt,
adapter);
} else {
DPRINTK(PROBE, INFO, "%s turned off\n",
opt.name);
}
#ifdef module_param_array
} else {
adapter->lli_port = opt.def;
}
#endif
}
{ /* Low Latency Interrupt on Packet Size */
struct igb_option opt = {
.type = range_option,
.name = "Low Latency Interrupt on Packet Size",
.err = "using default of " __MODULE_STRING(DEFAULT_LLISIZE),
.def = DEFAULT_LLISIZE,
.arg = { .r = { .min = MIN_LLISIZE,
.max = MAX_LLISIZE } }
};
#ifdef module_param_array
if (num_LLISize > bd) {
#endif
adapter->lli_size = LLISize[bd];
if (adapter->lli_size) {
igb_validate_option(&adapter->lli_size, &opt,
adapter);
} else {
DPRINTK(PROBE, INFO, "%s turned off\n",
opt.name);
}
#ifdef module_param_array
} else {
adapter->lli_size = opt.def;
}
#endif
}
{ /* Low Latency Interrupt on TCP Push flag */
struct igb_option opt = {
.type = enable_option,
.name = "Low Latency Interrupt on TCP Push flag",
.err = "defaulting to Disabled",
.def = OPTION_DISABLED
};
#ifdef module_param_array
if (num_LLIPush > bd) {
#endif
unsigned int lli_push = LLIPush[bd];
igb_validate_option(&lli_push, &opt, adapter);
adapter->flags |= lli_push ? IGB_FLAG_LLI_PUSH : 0;
#ifdef module_param_array
} else {
adapter->flags |= opt.def ? IGB_FLAG_LLI_PUSH : 0;
}
#endif
}
{ /* SRIOV - Enable SR-IOV VF devices */
struct igb_option opt = {
.type = range_option,
.name = "max_vfs - SR-IOV VF devices",
.err = "using default of " __MODULE_STRING(DEFAULT_SRIOV),
.def = DEFAULT_SRIOV,
.arg = { .r = { .min = MIN_SRIOV,
.max = MAX_SRIOV } }
};
#ifdef module_param_array
if (num_max_vfs > bd) {
#endif
adapter->vfs_allocated_count = max_vfs[bd];
igb_validate_option(&adapter->vfs_allocated_count, &opt, adapter);
#ifdef module_param_array
} else {
adapter->vfs_allocated_count = opt.def;
}
#endif
if (adapter->vfs_allocated_count) {
switch (hw->mac.type) {
case e1000_82575:
case e1000_82580:
adapter->vfs_allocated_count = 0;
DPRINTK(PROBE, INFO, "SR-IOV option max_vfs not supported.\n");
default:
break;
}
}
}
{ /* VMDQ - Enable VMDq multiqueue receive */
struct igb_option opt = {
.type = range_option,
.name = "VMDQ - VMDq multiqueue queue count",
.err = "using default of " __MODULE_STRING(DEFAULT_VMDQ),
.def = DEFAULT_VMDQ,
.arg = { .r = { .min = MIN_VMDQ,
.max = (MAX_VMDQ - adapter->vfs_allocated_count) } }
};
#ifdef module_param_array
if (num_VMDQ > bd) {
#endif
adapter->vmdq_pools = (VMDQ[bd] == 1 ? 0 : VMDQ[bd]);
if (adapter->vfs_allocated_count && !adapter->vmdq_pools) {
DPRINTK(PROBE, INFO, "Enabling SR-IOV requires VMDq be set to at least 1\n");
adapter->vmdq_pools = 1;
}
igb_validate_option(&adapter->vmdq_pools, &opt, adapter);
#ifdef module_param_array
} else {
if (!adapter->vfs_allocated_count)
adapter->vmdq_pools = (opt.def == 1 ? 0 : opt.def);
else
adapter->vmdq_pools = 1;
}
#endif
#ifdef CONFIG_IGB_VMDQ_NETDEV
if (hw->mac.type == e1000_82575 && adapter->vmdq_pools) {
DPRINTK(PROBE, INFO, "VMDq not supported on this part.\n");
adapter->vmdq_pools = 0;
}
#endif
}
{ /* RSS - Enable RSS multiqueue receives */
struct igb_option opt = {
.type = range_option,
.name = "RSS - RSS multiqueue receive count",
.err = "using default of " __MODULE_STRING(DEFAULT_RSS),
.def = DEFAULT_RSS,
.arg = { .r = { .min = MIN_RSS,
.max = MAX_RSS } }
};
if (adapter->vmdq_pools) {
switch (hw->mac.type) {
#ifndef CONFIG_IGB_VMDQ_NETDEV
case e1000_82576:
opt.arg.r.max = 2;
break;
case e1000_82575:
if (adapter->vmdq_pools == 2)
opt.arg.r.max = 3;
if (adapter->vmdq_pools <= 2)
break;
#endif
default:
opt.arg.r.max = 1;
break;
}
}
switch (hw->mac.type) {
case e1000_82575:
opt.arg.r.max = 4;
break;
default:
break;
}
#ifdef module_param_array
if (num_RSS > bd) {
#endif
adapter->rss_queues = RSS[bd];
switch (adapter->rss_queues) {
case 1:
break;
default:
igb_validate_option(&adapter->rss_queues, &opt, adapter);
if (adapter->rss_queues)
break;
case 0:
adapter->rss_queues = min_t(u32, opt.arg.r.max, num_online_cpus());
break;
}
#ifdef module_param_array
} else {
adapter->rss_queues = opt.def;
}
#endif
}
{ /* QueuePairs - Enable TX/RX queue pairs for interrupt handling */
struct igb_option opt = {
.type = enable_option,
.name = "QueuePairs - TX/RX queue pairs for interrupt handling",
.err = "defaulting to Enabled",
.def = OPTION_ENABLED
};
#ifdef module_param_array
if (num_QueuePairs > bd) {
#endif
unsigned int qp = QueuePairs[bd];
/*
* we must enable queue pairs if the number of queues
* exceeds the number of avaialble interrupts. We are
* limited to 10, or 3 per unallocated vf.
*/
if ((adapter->rss_queues > 4) ||
(adapter->vmdq_pools > 4) ||
((adapter->rss_queues > 1) &&
((adapter->vmdq_pools > 3) ||
(adapter->vfs_allocated_count > 6)))) {
if (qp == OPTION_DISABLED) {
qp = OPTION_ENABLED;
DPRINTK(PROBE, INFO,
"Number of queues exceeds available interrupts, %s\n",opt.err);
}
}
igb_validate_option(&qp, &opt, adapter);
adapter->flags |= qp ? IGB_FLAG_QUEUE_PAIRS : 0;
#ifdef module_param_array
} else {
adapter->flags |= opt.def ? IGB_FLAG_QUEUE_PAIRS : 0;
}
#endif
}
{ /* EEE - Enable EEE for capable adapters */
if (hw->mac.type >= e1000_i350) {
struct igb_option opt = {
.type = enable_option,
.name = "EEE Support",
.err = "defaulting to Enabled",
.def = OPTION_ENABLED
};
#ifdef module_param_array
if (num_EEE > bd) {
#endif
unsigned int eee = EEE[bd];
igb_validate_option(&eee, &opt, adapter);
adapter->flags |= eee ? IGB_FLAG_EEE : 0;
if (eee)
hw->dev_spec._82575.eee_disable = false;
else
hw->dev_spec._82575.eee_disable = true;
#ifdef module_param_array
} else {
adapter->flags |= opt.def ? IGB_FLAG_EEE : 0;
if (adapter->flags & IGB_FLAG_EEE)
hw->dev_spec._82575.eee_disable = false;
else
hw->dev_spec._82575.eee_disable = true;
}
#endif
}
}
{ /* DMAC - Enable DMA Coalescing for capable adapters */
if (hw->mac.type >= e1000_i350) {
struct igb_opt_list list [] = {
{ IGB_DMAC_DISABLE, "DMAC Disable"},
{ IGB_DMAC_MIN, "DMAC 250 usec"},
{ IGB_DMAC_500, "DMAC 500 usec"},
{ IGB_DMAC_EN_DEFAULT, "DMAC 1000 usec"},
{ IGB_DMAC_2000, "DMAC 2000 usec"},
{ IGB_DMAC_3000, "DMAC 3000 usec"},
{ IGB_DMAC_4000, "DMAC 4000 usec"},
{ IGB_DMAC_5000, "DMAC 5000 usec"},
{ IGB_DMAC_6000, "DMAC 6000 usec"},
{ IGB_DMAC_7000, "DMAC 7000 usec"},
{ IGB_DMAC_8000, "DMAC 8000 usec"},
{ IGB_DMAC_9000, "DMAC 9000 usec"},
{ IGB_DMAC_MAX, "DMAC 10000 usec"}
};
struct igb_option opt = {
.type = list_option,
.name = "DMA Coalescing",
.err = "using default of "__MODULE_STRING(IGB_DMAC_DISABLE),
.def = IGB_DMAC_DISABLE,
.arg = { .l = { .nr = 13,
.p = list
}
}
};
#ifdef module_param_array
if (num_DMAC > bd) {
#endif
unsigned int dmac = DMAC[bd];
if (adapter->rx_itr_setting == IGB_DMAC_DISABLE)
dmac = IGB_DMAC_DISABLE;
igb_validate_option(&dmac, &opt, adapter);
switch (dmac) {
case IGB_DMAC_DISABLE:
adapter->dmac = dmac;
break;
case IGB_DMAC_MIN:
adapter->dmac = dmac;
break;
case IGB_DMAC_500:
adapter->dmac = dmac;
break;
case IGB_DMAC_EN_DEFAULT:
adapter->dmac = dmac;
break;
case IGB_DMAC_2000:
adapter->dmac = dmac;
break;
case IGB_DMAC_3000:
adapter->dmac = dmac;
break;
case IGB_DMAC_4000:
adapter->dmac = dmac;
break;
case IGB_DMAC_5000:
adapter->dmac = dmac;
break;
case IGB_DMAC_6000:
adapter->dmac = dmac;
break;
case IGB_DMAC_7000:
adapter->dmac = dmac;
break;
case IGB_DMAC_8000:
adapter->dmac = dmac;
break;
case IGB_DMAC_9000:
adapter->dmac = dmac;
break;
case IGB_DMAC_MAX:
adapter->dmac = dmac;
break;
default:
adapter->dmac = opt.def;
DPRINTK(PROBE, INFO,
"Invalid DMAC setting, "
"resetting DMAC to %d\n", opt.def);
}
#ifdef module_param_array
} else
adapter->dmac = opt.def;
#endif
}
}
#ifndef IGB_NO_LRO
{ /* LRO - Enable Large Receive Offload */
struct igb_option opt = {
.type = enable_option,
.name = "LRO - Large Receive Offload",
.err = "defaulting to Disabled",
.def = OPTION_DISABLED
};
struct net_device *netdev = adapter->netdev;
#ifdef module_param_array
if (num_LRO > bd) {
#endif
unsigned int lro = LRO[bd];
igb_validate_option(&lro, &opt, adapter);
netdev->features |= lro ? NETIF_F_LRO : 0;
#ifdef module_param_array
} else if (opt.def == OPTION_ENABLED) {
netdev->features |= NETIF_F_LRO;
}
#endif
}
#endif /* IGB_NO_LRO */
{ /* Node assignment */
static struct igb_option opt = {
.type = range_option,
.name = "Node to start on",
.err = "defaulting to -1",
#ifdef HAVE_EARLY_VMALLOC_NODE
.def = 0,
#else
.def = -1,
#endif
.arg = { .r = { .min = 0,
.max = (MAX_NUMNODES - 1)}}
};
int node_param = opt.def;
/* if the default was zero then we need to set the
* default value to an online node, which is not
* necessarily zero, and the constant initializer
* above can't take first_online_node */
if (node_param == 0)
/* must set opt.def for validate */
opt.def = node_param = first_online_node;
#ifdef module_param_array
if (num_Node > bd) {
#endif
node_param = Node[bd];
igb_validate_option((uint *)&node_param, &opt, adapter);
if (node_param != OPTION_UNSET) {
DPRINTK(PROBE, INFO, "node set to %d\n", node_param);
}
#ifdef module_param_array
}
#endif
/* check sanity of the value */
if (node_param != -1 && !node_online(node_param)) {
DPRINTK(PROBE, INFO,
"ignoring node set to invalid value %d\n",
node_param);
node_param = opt.def;
}
adapter->node = node_param;
}
{ /* MDD - Enable Malicious Driver Detection. Only available when
SR-IOV is enabled. */
struct igb_option opt = {
.type = enable_option,
.name = "Malicious Driver Detection",
.err = "defaulting to 1",
.def = OPTION_ENABLED,
.arg = { .r = { .min = OPTION_DISABLED,
.max = OPTION_ENABLED } }
};
#ifdef module_param_array
if (num_MDD > bd) {
#endif
adapter->mdd = MDD[bd];
igb_validate_option((uint *)&adapter->mdd, &opt,
adapter);
#ifdef module_param_array
} else {
adapter->mdd = opt.def;
}
#endif
}
}

View File

@ -0,0 +1,951 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#include "igb.h"
#include "e1000_82575.h"
#include "e1000_hw.h"
#ifdef IGB_PROCFS
#ifndef IGB_SYSFS
#include <linux/module.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/device.h>
#include <linux/netdevice.h>
static struct proc_dir_entry *igb_top_dir = NULL;
static struct net_device_stats *procfs_get_stats(struct net_device *netdev)
{
#ifndef HAVE_NETDEV_STATS_IN_NETDEV
struct igb_adapter *adapter;
#endif
if (netdev == NULL)
return NULL;
#ifdef HAVE_NETDEV_STATS_IN_NETDEV
/* only return the current stats */
return &netdev->stats;
#else
adapter = netdev_priv(netdev);
/* only return the current stats */
return &adapter->net_stats;
#endif /* HAVE_NETDEV_STATS_IN_NETDEV */
}
bool igb_thermal_present(struct igb_adapter *adapter)
{
s32 status;
struct e1000_hw *hw;
if (adapter == NULL)
return false;
hw = &adapter->hw;
/*
* Only set I2C bit-bang mode if an external thermal sensor is
* supported on this device.
*/
if (adapter->ets) {
status = e1000_set_i2c_bb(hw);
if (status != E1000_SUCCESS)
return false;
}
status = hw->mac.ops.init_thermal_sensor_thresh(hw);
if (status != E1000_SUCCESS)
return false;
return true;
}
static int igb_fwbanner(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
return snprintf(page, count, "%d.%d-%d\n",
(adapter->fw_version & 0xF000) >> 12,
(adapter->fw_version & 0x0FF0) >> 4,
adapter->fw_version & 0x000F);
}
static int igb_numeports(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct e1000_hw *hw;
int ports;
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
hw = &adapter->hw;
if (hw == NULL)
return snprintf(page, count, "error: no hw data\n");
ports = 4;
return snprintf(page, count, "%d\n", ports);
}
static int igb_porttype(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
return snprintf(page, count, "%d\n",
test_bit(__IGB_DOWN, &adapter->state));
}
static int igb_portspeed(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
int speed = 0;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
switch (adapter->link_speed) {
case E1000_STATUS_SPEED_10:
speed = 10;
break;
case E1000_STATUS_SPEED_100:
speed = 100;
break;
case E1000_STATUS_SPEED_1000:
speed = 1000;
break;
}
return snprintf(page, count, "%d\n", speed);
}
static int igb_wqlflag(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
return snprintf(page, count, "%d\n", adapter->wol);
}
static int igb_xflowctl(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct e1000_hw *hw;
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
hw = &adapter->hw;
if (hw == NULL)
return snprintf(page, count, "error: no hw data\n");
return snprintf(page, count, "%d\n", hw->fc.current_mode);
}
static int igb_rxdrops(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
struct net_device_stats *net_stats;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
net_stats = procfs_get_stats(adapter->netdev);
if (net_stats == NULL)
return snprintf(page, count, "error: no net stats\n");
return snprintf(page, count, "%lu\n",
net_stats->rx_dropped);
}
static int igb_rxerrors(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
struct net_device_stats *net_stats;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
net_stats = procfs_get_stats(adapter->netdev);
if (net_stats == NULL)
return snprintf(page, count, "error: no net stats\n");
return snprintf(page, count, "%lu\n", net_stats->rx_errors);
}
static int igb_rxupacks(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct e1000_hw *hw;
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
hw = &adapter->hw;
if (hw == NULL)
return snprintf(page, count, "error: no hw data\n");
return snprintf(page, count, "%d\n", E1000_READ_REG(hw, E1000_TPR));
}
static int igb_rxmpacks(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct e1000_hw *hw;
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
hw = &adapter->hw;
if (hw == NULL)
return snprintf(page, count, "error: no hw data\n");
return snprintf(page, count, "%d\n",
E1000_READ_REG(hw, E1000_MPRC));
}
static int igb_rxbpacks(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct e1000_hw *hw;
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
hw = &adapter->hw;
if (hw == NULL)
return snprintf(page, count, "error: no hw data\n");
return snprintf(page, count, "%d\n",
E1000_READ_REG(hw, E1000_BPRC));
}
static int igb_txupacks(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct e1000_hw *hw;
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
hw = &adapter->hw;
if (hw == NULL)
return snprintf(page, count, "error: no hw data\n");
return snprintf(page, count, "%d\n", E1000_READ_REG(hw, E1000_TPT));
}
static int igb_txmpacks(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct e1000_hw *hw;
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
hw = &adapter->hw;
if (hw == NULL)
return snprintf(page, count, "error: no hw data\n");
return snprintf(page, count, "%d\n",
E1000_READ_REG(hw, E1000_MPTC));
}
static int igb_txbpacks(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct e1000_hw *hw;
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
hw = &adapter->hw;
if (hw == NULL)
return snprintf(page, count, "error: no hw data\n");
return snprintf(page, count, "%d\n",
E1000_READ_REG(hw, E1000_BPTC));
}
static int igb_txerrors(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
struct net_device_stats *net_stats;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
net_stats = procfs_get_stats(adapter->netdev);
if (net_stats == NULL)
return snprintf(page, count, "error: no net stats\n");
return snprintf(page, count, "%lu\n",
net_stats->tx_errors);
}
static int igb_txdrops(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
struct net_device_stats *net_stats;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
net_stats = procfs_get_stats(adapter->netdev);
if (net_stats == NULL)
return snprintf(page, count, "error: no net stats\n");
return snprintf(page, count, "%lu\n",
net_stats->tx_dropped);
}
static int igb_rxframes(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
struct net_device_stats *net_stats;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
net_stats = procfs_get_stats(adapter->netdev);
if (net_stats == NULL)
return snprintf(page, count, "error: no net stats\n");
return snprintf(page, count, "%lu\n",
net_stats->rx_packets);
}
static int igb_rxbytes(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
struct net_device_stats *net_stats;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
net_stats = procfs_get_stats(adapter->netdev);
if (net_stats == NULL)
return snprintf(page, count, "error: no net stats\n");
return snprintf(page, count, "%lu\n",
net_stats->rx_bytes);
}
static int igb_txframes(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
struct net_device_stats *net_stats;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
net_stats = procfs_get_stats(adapter->netdev);
if (net_stats == NULL)
return snprintf(page, count, "error: no net stats\n");
return snprintf(page, count, "%lu\n",
net_stats->tx_packets);
}
static int igb_txbytes(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
struct net_device_stats *net_stats;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
net_stats = procfs_get_stats(adapter->netdev);
if (net_stats == NULL)
return snprintf(page, count, "error: no net stats\n");
return snprintf(page, count, "%lu\n",
net_stats->tx_bytes);
}
static int igb_linkstat(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
int bitmask = 0;
struct e1000_hw *hw;
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
hw = &adapter->hw;
if (hw == NULL)
return snprintf(page, count, "error: no hw data\n");
if (test_bit(__IGB_DOWN, &adapter->state))
bitmask |= 1;
if (igb_has_link(adapter))
bitmask |= 2;
return snprintf(page, count, "0x%X\n", bitmask);
}
static int igb_funcid(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
struct net_device* netdev;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
netdev = adapter->netdev;
if (netdev == NULL)
return snprintf(page, count, "error: no net device\n");
return snprintf(page, count, "0x%lX\n", netdev->base_addr);
}
static int igb_funcvers(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
struct net_device* netdev;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
netdev = adapter->netdev;
if (netdev == NULL)
return snprintf(page, count, "error: no net device\n");
return snprintf(page, count, "%s\n", igb_driver_version);
}
static int igb_macburn(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct e1000_hw *hw;
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
hw = &adapter->hw;
if (hw == NULL)
return snprintf(page, count, "error: no hw data\n");
return snprintf(page, count, "0x%X%X%X%X%X%X\n",
(unsigned int)hw->mac.perm_addr[0],
(unsigned int)hw->mac.perm_addr[1],
(unsigned int)hw->mac.perm_addr[2],
(unsigned int)hw->mac.perm_addr[3],
(unsigned int)hw->mac.perm_addr[4],
(unsigned int)hw->mac.perm_addr[5]);
}
static int igb_macadmn(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct e1000_hw *hw;
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
hw = &adapter->hw;
if (hw == NULL)
return snprintf(page, count, "error: no hw data\n");
return snprintf(page, count, "0x%X%X%X%X%X%X\n",
(unsigned int)hw->mac.addr[0],
(unsigned int)hw->mac.addr[1],
(unsigned int)hw->mac.addr[2],
(unsigned int)hw->mac.addr[3],
(unsigned int)hw->mac.addr[4],
(unsigned int)hw->mac.addr[5]);
}
static int igb_maclla1(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct e1000_hw *hw;
u16 eeprom_buff[6];
int first_word = 0x37;
int word_count = 6;
int rc;
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
hw = &adapter->hw;
if (hw == NULL)
return snprintf(page, count, "error: no hw data\n");
rc = e1000_read_nvm(hw, first_word, word_count,
eeprom_buff);
if (rc != E1000_SUCCESS)
return 0;
switch (hw->bus.func) {
case 0:
return snprintf(page, count, "0x%04X%04X%04X\n",
eeprom_buff[0],
eeprom_buff[1],
eeprom_buff[2]);
case 1:
return snprintf(page, count, "0x%04X%04X%04X\n",
eeprom_buff[3],
eeprom_buff[4],
eeprom_buff[5]);
}
return snprintf(page, count, "unexpected port %d\n", hw->bus.func);
}
static int igb_mtusize(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
struct net_device* netdev;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
netdev = adapter->netdev;
if (netdev == NULL)
return snprintf(page, count, "error: no net device\n");
return snprintf(page, count, "%d\n", netdev->mtu);
}
static int igb_featflag(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
int bitmask = 0;
#ifndef HAVE_NDO_SET_FEATURES
struct igb_ring *ring;
#endif
struct igb_adapter *adapter = (struct igb_adapter *)data;
struct net_device *netdev;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
netdev = adapter->netdev;
if (netdev == NULL)
return snprintf(page, count, "error: no net device\n");
#ifndef HAVE_NDO_SET_FEATURES
/* igb_get_rx_csum(netdev) doesn't compile so hard code */
ring = adapter->rx_ring[0];
bitmask = test_bit(IGB_RING_FLAG_RX_CSUM, &ring->flags);
return snprintf(page, count, "%d\n", bitmask);
#else
if (netdev->features & NETIF_F_RXCSUM)
bitmask |= 1;
return snprintf(page, count, "%d\n", bitmask);
#endif
}
static int igb_lsominct(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
return snprintf(page, count, "%d\n", 1);
}
static int igb_prommode(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
struct net_device *netdev;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
netdev = adapter->netdev;
if (netdev == NULL)
return snprintf(page, count, "error: no net device\n");
return snprintf(page, count, "%d\n",
netdev->flags & IFF_PROMISC);
}
static int igb_txdscqsz(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
return snprintf(page, count, "%d\n", adapter->tx_ring[0]->count);
}
static int igb_rxdscqsz(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
return snprintf(page, count, "%d\n", adapter->rx_ring[0]->count);
}
static int igb_rxqavg(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
int index;
int totaldiff = 0;
u16 ntc;
u16 ntu;
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
if (adapter->num_rx_queues <= 0)
return snprintf(page, count,
"can't calculate, number of queues %d\n",
adapter->num_rx_queues);
for (index = 0; index < adapter->num_rx_queues; index++) {
ntc = adapter->rx_ring[index]->next_to_clean;
ntu = adapter->rx_ring[index]->next_to_use;
if (ntc >= ntu)
totaldiff += (ntc - ntu);
else
totaldiff += (adapter->rx_ring[index]->count
- ntu + ntc);
}
if (adapter->num_rx_queues <= 0)
return snprintf(page, count,
"can't calculate, number of queues %d\n",
adapter->num_rx_queues);
return snprintf(page, count, "%d\n", totaldiff/adapter->num_rx_queues);
}
static int igb_txqavg(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
int index;
int totaldiff = 0;
u16 ntc;
u16 ntu;
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
if (adapter->num_tx_queues <= 0)
return snprintf(page, count,
"can't calculate, number of queues %d\n",
adapter->num_tx_queues);
for (index = 0; index < adapter->num_tx_queues; index++) {
ntc = adapter->tx_ring[index]->next_to_clean;
ntu = adapter->tx_ring[index]->next_to_use;
if (ntc >= ntu)
totaldiff += (ntc - ntu);
else
totaldiff += (adapter->tx_ring[index]->count
- ntu + ntc);
}
if (adapter->num_tx_queues <= 0)
return snprintf(page, count,
"can't calculate, number of queues %d\n",
adapter->num_tx_queues);
return snprintf(page, count, "%d\n",
totaldiff/adapter->num_tx_queues);
}
static int igb_iovotype(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
return snprintf(page, count, "2\n");
}
static int igb_funcnbr(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct igb_adapter *adapter = (struct igb_adapter *)data;
if (adapter == NULL)
return snprintf(page, count, "error: no adapter\n");
return snprintf(page, count, "%d\n", adapter->vfs_allocated_count);
}
static int igb_therm_location(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct igb_therm_proc_data *therm_data =
(struct igb_therm_proc_data *)data;
if (therm_data == NULL)
return snprintf(page, count, "error: no therm_data\n");
return snprintf(page, count, "%d\n", therm_data->sensor_data->location);
}
static int igb_therm_maxopthresh(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct igb_therm_proc_data *therm_data =
(struct igb_therm_proc_data *)data;
if (therm_data == NULL)
return snprintf(page, count, "error: no therm_data\n");
return snprintf(page, count, "%d\n",
therm_data->sensor_data->max_op_thresh);
}
static int igb_therm_cautionthresh(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct igb_therm_proc_data *therm_data =
(struct igb_therm_proc_data *)data;
if (therm_data == NULL)
return snprintf(page, count, "error: no therm_data\n");
return snprintf(page, count, "%d\n",
therm_data->sensor_data->caution_thresh);
}
static int igb_therm_temp(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
s32 status;
struct igb_therm_proc_data *therm_data =
(struct igb_therm_proc_data *)data;
if (therm_data == NULL)
return snprintf(page, count, "error: no therm_data\n");
status = e1000_get_thermal_sensor_data(therm_data->hw);
if (status != E1000_SUCCESS)
snprintf(page, count, "error: status %d returned\n", status);
return snprintf(page, count, "%d\n", therm_data->sensor_data->temp);
}
struct igb_proc_type{
char name[32];
int (*read)(char*, char**, off_t, int, int*, void*);
};
struct igb_proc_type igb_proc_entries[] = {
{"fwbanner", &igb_fwbanner},
{"numeports", &igb_numeports},
{"porttype", &igb_porttype},
{"portspeed", &igb_portspeed},
{"wqlflag", &igb_wqlflag},
{"xflowctl", &igb_xflowctl},
{"rxdrops", &igb_rxdrops},
{"rxerrors", &igb_rxerrors},
{"rxupacks", &igb_rxupacks},
{"rxmpacks", &igb_rxmpacks},
{"rxbpacks", &igb_rxbpacks},
{"txdrops", &igb_txdrops},
{"txerrors", &igb_txerrors},
{"txupacks", &igb_txupacks},
{"txmpacks", &igb_txmpacks},
{"txbpacks", &igb_txbpacks},
{"rxframes", &igb_rxframes},
{"rxbytes", &igb_rxbytes},
{"txframes", &igb_txframes},
{"txbytes", &igb_txbytes},
{"linkstat", &igb_linkstat},
{"funcid", &igb_funcid},
{"funcvers", &igb_funcvers},
{"macburn", &igb_macburn},
{"macadmn", &igb_macadmn},
{"maclla1", &igb_maclla1},
{"mtusize", &igb_mtusize},
{"featflag", &igb_featflag},
{"lsominct", &igb_lsominct},
{"prommode", &igb_prommode},
{"txdscqsz", &igb_txdscqsz},
{"rxdscqsz", &igb_rxdscqsz},
{"txqavg", &igb_txqavg},
{"rxqavg", &igb_rxqavg},
{"iovotype", &igb_iovotype},
{"funcnbr", &igb_funcnbr},
{"", NULL}
};
struct igb_proc_type igb_internal_entries[] = {
{"location", &igb_therm_location},
{"temp", &igb_therm_temp},
{"cautionthresh", &igb_therm_cautionthresh},
{"maxopthresh", &igb_therm_maxopthresh},
{"", NULL}
};
void igb_del_proc_entries(struct igb_adapter *adapter)
{
int index, i;
char buf[16]; /* much larger than the sensor number will ever be */
if (igb_top_dir == NULL)
return;
for (i = 0; i < E1000_MAX_SENSORS; i++) {
if (adapter->therm_dir[i] == NULL)
continue;
for (index = 0; ; index++) {
if (igb_internal_entries[index].read == NULL)
break;
remove_proc_entry(igb_internal_entries[index].name,
adapter->therm_dir[i]);
}
snprintf(buf, sizeof(buf), "sensor_%d", i);
remove_proc_entry(buf, adapter->info_dir);
}
if (adapter->info_dir != NULL) {
for (index = 0; ; index++) {
if (igb_proc_entries[index].read == NULL)
break;
remove_proc_entry(igb_proc_entries[index].name,
adapter->info_dir);
}
remove_proc_entry("info", adapter->eth_dir);
}
if (adapter->eth_dir != NULL)
remove_proc_entry(pci_name(adapter->pdev), igb_top_dir);
}
/* called from igb_main.c */
void igb_procfs_exit(struct igb_adapter *adapter)
{
igb_del_proc_entries(adapter);
}
int igb_procfs_topdir_init(void)
{
igb_top_dir = proc_mkdir("driver/igb", NULL);
if (igb_top_dir == NULL)
return (-ENOMEM);
return 0;
}
void igb_procfs_topdir_exit(void)
{
// remove_proc_entry("driver", proc_root_driver);
remove_proc_entry("driver/igb", NULL);
}
/* called from igb_main.c */
int igb_procfs_init(struct igb_adapter *adapter)
{
int rc = 0;
int i;
int index;
char buf[16]; /* much larger than the sensor number will ever be */
adapter->eth_dir = NULL;
adapter->info_dir = NULL;
for (i = 0; i < E1000_MAX_SENSORS; i++)
adapter->therm_dir[i] = NULL;
if ( igb_top_dir == NULL ) {
rc = -ENOMEM;
goto fail;
}
adapter->eth_dir = proc_mkdir(pci_name(adapter->pdev), igb_top_dir);
if (adapter->eth_dir == NULL) {
rc = -ENOMEM;
goto fail;
}
adapter->info_dir = proc_mkdir("info", adapter->eth_dir);
if (adapter->info_dir == NULL) {
rc = -ENOMEM;
goto fail;
}
for (index = 0; ; index++) {
if (igb_proc_entries[index].read == NULL) {
break;
}
if (!(create_proc_read_entry(igb_proc_entries[index].name,
0444,
adapter->info_dir,
igb_proc_entries[index].read,
adapter))) {
rc = -ENOMEM;
goto fail;
}
}
if (igb_thermal_present(adapter) == false)
goto exit;
for (i = 0; i < E1000_MAX_SENSORS; i++) {
if (adapter->hw.mac.thermal_sensor_data.sensor[i].location== 0)
continue;
snprintf(buf, sizeof(buf), "sensor_%d", i);
adapter->therm_dir[i] = proc_mkdir(buf, adapter->info_dir);
if (adapter->therm_dir[i] == NULL) {
rc = -ENOMEM;
goto fail;
}
for (index = 0; ; index++) {
if (igb_internal_entries[index].read == NULL)
break;
/*
* therm_data struct contains pointer the read func
* will be needing
*/
adapter->therm_data[i].hw = &adapter->hw;
adapter->therm_data[i].sensor_data =
&adapter->hw.mac.thermal_sensor_data.sensor[i];
if (!(create_proc_read_entry(
igb_internal_entries[index].name,
0444,
adapter->therm_dir[i],
igb_internal_entries[index].read,
&adapter->therm_data[i]))) {
rc = -ENOMEM;
goto fail;
}
}
}
goto exit;
fail:
igb_del_proc_entries(adapter);
exit:
return rc;
}
#endif /* !IGB_SYSFS */
#endif /* IGB_PROCFS */

View File

@ -0,0 +1,221 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
/* ethtool register test data */
struct igb_reg_test {
u16 reg;
u16 reg_offset;
u16 array_len;
u16 test_type;
u32 mask;
u32 write;
};
/* In the hardware, registers are laid out either singly, in arrays
* spaced 0x100 bytes apart, or in contiguous tables. We assume
* most tests take place on arrays or single registers (handled
* as a single-element array) and special-case the tables.
* Table tests are always pattern tests.
*
* We also make provision for some required setup steps by specifying
* registers to be written without any read-back testing.
*/
#define PATTERN_TEST 1
#define SET_READ_TEST 2
#define WRITE_NO_TEST 3
#define TABLE32_TEST 4
#define TABLE64_TEST_LO 5
#define TABLE64_TEST_HI 6
/* i350 reg test */
static struct igb_reg_test reg_test_i350[] = {
{ E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_FCAH, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
{ E1000_FCT, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
/* VET is readonly on i350 */
{ E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
{ E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
{ E1000_RDBAL(4), 0x40, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
{ E1000_RDBAH(4), 0x40, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RDLEN(4), 0x40, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
/* RDH is read-only for i350, only test RDT. */
{ E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_RDT(4), 0x40, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 },
{ E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
{ E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
{ E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
{ E1000_TDBAL(4), 0x40, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
{ E1000_TDBAH(4), 0x40, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_TDLEN(4), 0x40, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
{ E1000_TDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_TDT(4), 0x40, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
{ E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB },
{ E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF },
{ E1000_TCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
{ E1000_RA, 0, 16, TABLE64_TEST_LO,
0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RA, 0, 16, TABLE64_TEST_HI,
0xC3FFFFFF, 0xFFFFFFFF },
{ E1000_RA2, 0, 16, TABLE64_TEST_LO,
0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RA2, 0, 16, TABLE64_TEST_HI,
0xC3FFFFFF, 0xFFFFFFFF },
{ E1000_MTA, 0, 128, TABLE32_TEST,
0xFFFFFFFF, 0xFFFFFFFF },
{ 0, 0, 0, 0 }
};
/* 82580 reg test */
static struct igb_reg_test reg_test_82580[] = {
{ E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_FCAH, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
{ E1000_FCT, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
{ E1000_VET, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
{ E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
{ E1000_RDBAL(4), 0x40, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
{ E1000_RDBAH(4), 0x40, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RDLEN(4), 0x40, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
/* RDH is read-only for 82580, only test RDT. */
{ E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_RDT(4), 0x40, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 },
{ E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
{ E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
{ E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
{ E1000_TDBAL(4), 0x40, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
{ E1000_TDBAH(4), 0x40, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_TDLEN(4), 0x40, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
{ E1000_TDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_TDT(4), 0x40, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
{ E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB },
{ E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF },
{ E1000_TCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
{ E1000_RA, 0, 16, TABLE64_TEST_LO,
0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RA, 0, 16, TABLE64_TEST_HI,
0x83FFFFFF, 0xFFFFFFFF },
{ E1000_RA2, 0, 8, TABLE64_TEST_LO,
0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RA2, 0, 8, TABLE64_TEST_HI,
0x83FFFFFF, 0xFFFFFFFF },
{ E1000_MTA, 0, 128, TABLE32_TEST,
0xFFFFFFFF, 0xFFFFFFFF },
{ 0, 0, 0, 0 }
};
/* 82576 reg test */
static struct igb_reg_test reg_test_82576[] = {
{ E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_FCAH, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
{ E1000_FCT, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
{ E1000_VET, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
{ E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
{ E1000_RDBAL(4), 0x40, 12, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
{ E1000_RDBAH(4), 0x40, 12, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RDLEN(4), 0x40, 12, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
/* Enable all queues before testing. */
{ E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE },
{ E1000_RXDCTL(4), 0x40, 12, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE },
/* RDH is read-only for 82576, only test RDT. */
{ E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_RDT(4), 0x40, 12, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, 0 },
{ E1000_RXDCTL(4), 0x40, 12, WRITE_NO_TEST, 0, 0 },
{ E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 },
{ E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
{ E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
{ E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
{ E1000_TDBAL(4), 0x40, 12, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
{ E1000_TDBAH(4), 0x40, 12, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_TDLEN(4), 0x40, 12, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
{ E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
{ E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB },
{ E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF },
{ E1000_TCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
{ E1000_RA, 0, 16, TABLE64_TEST_LO,
0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RA, 0, 16, TABLE64_TEST_HI,
0x83FFFFFF, 0xFFFFFFFF },
{ E1000_RA2, 0, 8, TABLE64_TEST_LO,
0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RA2, 0, 8, TABLE64_TEST_HI,
0x83FFFFFF, 0xFFFFFFFF },
{ E1000_MTA, 0, 128, TABLE32_TEST,
0xFFFFFFFF, 0xFFFFFFFF },
{ 0, 0, 0, 0 }
};
/* 82575 register test */
static struct igb_reg_test reg_test_82575[] = {
{ E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_FCAH, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
{ E1000_FCT, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
{ E1000_VET, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
{ E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
/* Enable all four RX queues before testing. */
{ E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE },
/* RDH is read-only for 82575, only test RDT. */
{ E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, 0 },
{ E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 },
{ E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
{ E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
{ E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
{ E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
{ E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB3FE, 0x003FFFFB },
{ E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB3FE, 0xFFFFFFFF },
{ E1000_TCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
{ E1000_TXCW, 0x100, 1, PATTERN_TEST, 0xC000FFFF, 0x0000FFFF },
{ E1000_RA, 0, 16, TABLE64_TEST_LO,
0xFFFFFFFF, 0xFFFFFFFF },
{ E1000_RA, 0, 16, TABLE64_TEST_HI,
0x800FFFFF, 0xFFFFFFFF },
{ E1000_MTA, 0, 128, TABLE32_TEST,
0xFFFFFFFF, 0xFFFFFFFF },
{ 0, 0, 0, 0 }
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,437 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#include <linux/tcp.h>
#include "igb.h"
#include "igb_vmdq.h"
#include <linux/if_vlan.h>
#ifdef CONFIG_IGB_VMDQ_NETDEV
int igb_vmdq_open(struct net_device *dev)
{
struct igb_vmdq_adapter *vadapter = netdev_priv(dev);
struct igb_adapter *adapter = vadapter->real_adapter;
struct net_device *main_netdev = adapter->netdev;
int hw_queue = vadapter->rx_ring->queue_index +
adapter->vfs_allocated_count;
if (test_bit(__IGB_DOWN, &adapter->state)) {
DPRINTK(DRV, WARNING,
"Open %s before opening this device.\n",
main_netdev->name);
return -EAGAIN;
}
netif_carrier_off(dev);
vadapter->tx_ring->vmdq_netdev = dev;
vadapter->rx_ring->vmdq_netdev = dev;
if (is_valid_ether_addr(dev->dev_addr)) {
igb_del_mac_filter(adapter, dev->dev_addr, hw_queue);
igb_add_mac_filter(adapter, dev->dev_addr, hw_queue);
}
netif_carrier_on(dev);
return 0;
}
int igb_vmdq_close(struct net_device *dev)
{
struct igb_vmdq_adapter *vadapter = netdev_priv(dev);
struct igb_adapter *adapter = vadapter->real_adapter;
int hw_queue = vadapter->rx_ring->queue_index +
adapter->vfs_allocated_count;
netif_carrier_off(dev);
igb_del_mac_filter(adapter, dev->dev_addr, hw_queue);
vadapter->tx_ring->vmdq_netdev = NULL;
vadapter->rx_ring->vmdq_netdev = NULL;
return 0;
}
netdev_tx_t igb_vmdq_xmit_frame(struct sk_buff *skb, struct net_device *dev)
{
struct igb_vmdq_adapter *vadapter = netdev_priv(dev);
return igb_xmit_frame_ring(skb, vadapter->tx_ring);
}
struct net_device_stats *igb_vmdq_get_stats(struct net_device *dev)
{
struct igb_vmdq_adapter *vadapter = netdev_priv(dev);
struct igb_adapter *adapter = vadapter->real_adapter;
struct e1000_hw *hw = &adapter->hw;
int hw_queue = vadapter->rx_ring->queue_index +
adapter->vfs_allocated_count;
vadapter->net_stats.rx_packets +=
E1000_READ_REG(hw, E1000_PFVFGPRC(hw_queue));
E1000_WRITE_REG(hw, E1000_PFVFGPRC(hw_queue), 0);
vadapter->net_stats.tx_packets +=
E1000_READ_REG(hw, E1000_PFVFGPTC(hw_queue));
E1000_WRITE_REG(hw, E1000_PFVFGPTC(hw_queue), 0);
vadapter->net_stats.rx_bytes +=
E1000_READ_REG(hw, E1000_PFVFGORC(hw_queue));
E1000_WRITE_REG(hw, E1000_PFVFGORC(hw_queue), 0);
vadapter->net_stats.tx_bytes +=
E1000_READ_REG(hw, E1000_PFVFGOTC(hw_queue));
E1000_WRITE_REG(hw, E1000_PFVFGOTC(hw_queue), 0);
vadapter->net_stats.multicast +=
E1000_READ_REG(hw, E1000_PFVFMPRC(hw_queue));
E1000_WRITE_REG(hw, E1000_PFVFMPRC(hw_queue), 0);
/* only return the current stats */
return &vadapter->net_stats;
}
/**
* igb_write_vm_addr_list - write unicast addresses to RAR table
* @netdev: network interface device structure
*
* Writes unicast address list to the RAR table.
* Returns: -ENOMEM on failure/insufficient address space
* 0 on no addresses written
* X on writing X addresses to the RAR table
**/
static int igb_write_vm_addr_list(struct net_device *netdev)
{
struct igb_vmdq_adapter *vadapter = netdev_priv(netdev);
struct igb_adapter *adapter = vadapter->real_adapter;
int count = 0;
int hw_queue = vadapter->rx_ring->queue_index +
adapter->vfs_allocated_count;
/* return ENOMEM indicating insufficient memory for addresses */
if (netdev_uc_count(netdev) > igb_available_rars(adapter))
return -ENOMEM;
if (!netdev_uc_empty(netdev)) {
#ifdef NETDEV_HW_ADDR_T_UNICAST
struct netdev_hw_addr *ha;
#else
struct dev_mc_list *ha;
#endif
netdev_for_each_uc_addr(ha, netdev) {
#ifdef NETDEV_HW_ADDR_T_UNICAST
igb_del_mac_filter(adapter, ha->addr, hw_queue);
igb_add_mac_filter(adapter, ha->addr, hw_queue);
#else
igb_del_mac_filter(adapter, ha->da_addr, hw_queue);
igb_add_mac_filter(adapter, ha->da_addr, hw_queue);
#endif
count++;
}
}
return count;
}
#define E1000_VMOLR_UPE 0x20000000 /* Unicast promiscuous mode */
void igb_vmdq_set_rx_mode(struct net_device *dev)
{
struct igb_vmdq_adapter *vadapter = netdev_priv(dev);
struct igb_adapter *adapter = vadapter->real_adapter;
struct e1000_hw *hw = &adapter->hw;
u32 vmolr, rctl;
int hw_queue = vadapter->rx_ring->queue_index +
adapter->vfs_allocated_count;
/* Check for Promiscuous and All Multicast modes */
vmolr = E1000_READ_REG(hw, E1000_VMOLR(hw_queue));
/* clear the affected bits */
vmolr &= ~(E1000_VMOLR_UPE | E1000_VMOLR_MPME |
E1000_VMOLR_ROPE | E1000_VMOLR_ROMPE);
if (dev->flags & IFF_PROMISC) {
vmolr |= E1000_VMOLR_UPE;
rctl = E1000_READ_REG(hw, E1000_RCTL);
rctl |= E1000_RCTL_UPE;
E1000_WRITE_REG(hw, E1000_RCTL, rctl);
} else {
rctl = E1000_READ_REG(hw, E1000_RCTL);
rctl &= ~E1000_RCTL_UPE;
E1000_WRITE_REG(hw, E1000_RCTL, rctl);
if (dev->flags & IFF_ALLMULTI) {
vmolr |= E1000_VMOLR_MPME;
} else {
/*
* Write addresses to the MTA, if the attempt fails
* then we should just turn on promiscous mode so
* that we can at least receive multicast traffic
*/
if (igb_write_mc_addr_list(adapter->netdev) != 0)
vmolr |= E1000_VMOLR_ROMPE;
}
#ifdef HAVE_SET_RX_MODE
/*
* Write addresses to available RAR registers, if there is not
* sufficient space to store all the addresses then enable
* unicast promiscous mode
*/
if (igb_write_vm_addr_list(dev) < 0)
vmolr |= E1000_VMOLR_UPE;
#endif
}
E1000_WRITE_REG(hw, E1000_VMOLR(hw_queue), vmolr);
return;
}
int igb_vmdq_set_mac(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
struct igb_vmdq_adapter *vadapter = netdev_priv(dev);
struct igb_adapter *adapter = vadapter->real_adapter;
int hw_queue = vadapter->rx_ring->queue_index +
adapter->vfs_allocated_count;
igb_del_mac_filter(adapter, dev->dev_addr, hw_queue);
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
return igb_add_mac_filter(adapter, dev->dev_addr, hw_queue);
}
int igb_vmdq_change_mtu(struct net_device *dev, int new_mtu)
{
struct igb_vmdq_adapter *vadapter = netdev_priv(dev);
struct igb_adapter *adapter = vadapter->real_adapter;
if (adapter->netdev->mtu < new_mtu) {
DPRINTK(PROBE, INFO,
"Set MTU on %s to >= %d "
"before changing MTU on %s\n",
adapter->netdev->name, new_mtu, dev->name);
return -EINVAL;
}
dev->mtu = new_mtu;
return 0;
}
void igb_vmdq_tx_timeout(struct net_device *dev)
{
return;
}
void igb_vmdq_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
{
struct igb_vmdq_adapter *vadapter = netdev_priv(dev);
struct igb_adapter *adapter = vadapter->real_adapter;
struct e1000_hw *hw = &adapter->hw;
int hw_queue = vadapter->rx_ring->queue_index +
adapter->vfs_allocated_count;
vadapter->vlgrp = grp;
igb_enable_vlan_tags(adapter);
E1000_WRITE_REG(hw, E1000_VMVIR(hw_queue), 0);
return;
}
void igb_vmdq_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
{
struct igb_vmdq_adapter *vadapter = netdev_priv(dev);
struct igb_adapter *adapter = vadapter->real_adapter;
#ifndef HAVE_NETDEV_VLAN_FEATURES
struct net_device *v_netdev;
#endif
int hw_queue = vadapter->rx_ring->queue_index +
adapter->vfs_allocated_count;
/* attempt to add filter to vlvf array */
igb_vlvf_set(adapter, vid, TRUE, hw_queue);
#ifndef HAVE_NETDEV_VLAN_FEATURES
/* Copy feature flags from netdev to the vlan netdev for this vid.
* This allows things like TSO to bubble down to our vlan device.
*/
v_netdev = vlan_group_get_device(vadapter->vlgrp, vid);
v_netdev->features |= adapter->netdev->features;
vlan_group_set_device(vadapter->vlgrp, vid, v_netdev);
#endif
return;
}
void igb_vmdq_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
{
struct igb_vmdq_adapter *vadapter = netdev_priv(dev);
struct igb_adapter *adapter = vadapter->real_adapter;
int hw_queue = vadapter->rx_ring->queue_index +
adapter->vfs_allocated_count;
vlan_group_set_device(vadapter->vlgrp, vid, NULL);
/* remove vlan from VLVF table array */
igb_vlvf_set(adapter, vid, FALSE, hw_queue);
return;
}
static int igb_vmdq_get_settings(struct net_device *netdev,
struct ethtool_cmd *ecmd)
{
struct igb_vmdq_adapter *vadapter = netdev_priv(netdev);
struct igb_adapter *adapter = vadapter->real_adapter;
struct e1000_hw *hw = &adapter->hw;
u32 status;
if (hw->phy.media_type == e1000_media_type_copper) {
ecmd->supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Full|
SUPPORTED_Autoneg |
SUPPORTED_TP);
ecmd->advertising = ADVERTISED_TP;
if (hw->mac.autoneg == 1) {
ecmd->advertising |= ADVERTISED_Autoneg;
/* the e1000 autoneg seems to match ethtool nicely */
ecmd->advertising |= hw->phy.autoneg_advertised;
}
ecmd->port = PORT_TP;
ecmd->phy_address = hw->phy.addr;
} else {
ecmd->supported = (SUPPORTED_1000baseT_Full |
SUPPORTED_FIBRE |
SUPPORTED_Autoneg);
ecmd->advertising = (ADVERTISED_1000baseT_Full |
ADVERTISED_FIBRE |
ADVERTISED_Autoneg);
ecmd->port = PORT_FIBRE;
}
ecmd->transceiver = XCVR_INTERNAL;
status = E1000_READ_REG(hw, E1000_STATUS);
if (status & E1000_STATUS_LU) {
if ((status & E1000_STATUS_SPEED_1000) ||
hw->phy.media_type != e1000_media_type_copper)
ecmd->speed = SPEED_1000;
else if (status & E1000_STATUS_SPEED_100)
ecmd->speed = SPEED_100;
else
ecmd->speed = SPEED_10;
if ((status & E1000_STATUS_FD) ||
hw->phy.media_type != e1000_media_type_copper)
ecmd->duplex = DUPLEX_FULL;
else
ecmd->duplex = DUPLEX_HALF;
} else {
ecmd->speed = -1;
ecmd->duplex = -1;
}
ecmd->autoneg = hw->mac.autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
return 0;
}
static u32 igb_vmdq_get_msglevel(struct net_device *netdev)
{
struct igb_vmdq_adapter *vadapter = netdev_priv(netdev);
struct igb_adapter *adapter = vadapter->real_adapter;
return adapter->msg_enable;
}
static void igb_vmdq_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
struct igb_vmdq_adapter *vadapter = netdev_priv(netdev);
struct igb_adapter *adapter = vadapter->real_adapter;
struct net_device *main_netdev = adapter->netdev;
strncpy(drvinfo->driver, igb_driver_name, 32);
strncpy(drvinfo->version, igb_driver_version, 32);
strncpy(drvinfo->fw_version, "N/A", 4);
snprintf(drvinfo->bus_info, 32, "%s VMDQ %d", main_netdev->name,
vadapter->rx_ring->queue_index);
drvinfo->n_stats = 0;
drvinfo->testinfo_len = 0;
drvinfo->regdump_len = 0;
}
static void igb_vmdq_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
struct igb_vmdq_adapter *vadapter = netdev_priv(netdev);
struct igb_ring *tx_ring = vadapter->tx_ring;
struct igb_ring *rx_ring = vadapter->rx_ring;
ring->rx_max_pending = IGB_MAX_RXD;
ring->tx_max_pending = IGB_MAX_TXD;
ring->rx_mini_max_pending = 0;
ring->rx_jumbo_max_pending = 0;
ring->rx_pending = rx_ring->count;
ring->tx_pending = tx_ring->count;
ring->rx_mini_pending = 0;
ring->rx_jumbo_pending = 0;
}
static u32 igb_vmdq_get_rx_csum(struct net_device *netdev)
{
struct igb_vmdq_adapter *vadapter = netdev_priv(netdev);
struct igb_adapter *adapter = vadapter->real_adapter;
return test_bit(IGB_RING_FLAG_RX_CSUM, &adapter->rx_ring[0]->flags);
}
static struct ethtool_ops igb_vmdq_ethtool_ops = {
.get_settings = igb_vmdq_get_settings,
.get_drvinfo = igb_vmdq_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_ringparam = igb_vmdq_get_ringparam,
.get_rx_csum = igb_vmdq_get_rx_csum,
.get_tx_csum = ethtool_op_get_tx_csum,
.get_sg = ethtool_op_get_sg,
.set_sg = ethtool_op_set_sg,
.get_msglevel = igb_vmdq_get_msglevel,
#ifdef NETIF_F_TSO
.get_tso = ethtool_op_get_tso,
#endif
#ifdef HAVE_ETHTOOL_GET_PERM_ADDR
.get_perm_addr = ethtool_op_get_perm_addr,
#endif
};
void igb_vmdq_set_ethtool_ops(struct net_device *netdev)
{
SET_ETHTOOL_OPS(netdev, &igb_vmdq_ethtool_ops);
}
#endif /* CONFIG_IGB_VMDQ_NETDEV */

View File

@ -0,0 +1,46 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IGB_VMDQ_H_
#define _IGB_VMDQ_H_
#ifdef CONFIG_IGB_VMDQ_NETDEV
int igb_vmdq_open(struct net_device *dev);
int igb_vmdq_close(struct net_device *dev);
netdev_tx_t igb_vmdq_xmit_frame(struct sk_buff *skb, struct net_device *dev);
struct net_device_stats *igb_vmdq_get_stats(struct net_device *dev);
void igb_vmdq_set_rx_mode(struct net_device *dev);
int igb_vmdq_set_mac(struct net_device *dev, void *addr);
int igb_vmdq_change_mtu(struct net_device *dev, int new_mtu);
void igb_vmdq_tx_timeout(struct net_device *dev);
void igb_vmdq_vlan_rx_register(struct net_device *dev,
struct vlan_group *grp);
void igb_vmdq_vlan_rx_add_vid(struct net_device *dev, unsigned short vid);
void igb_vmdq_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid);
void igb_vmdq_set_ethtool_ops(struct net_device *netdev);
#endif /* CONFIG_IGB_VMDQ_NETDEV */
#endif /* _IGB_VMDQ_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,339 @@
"This software program is licensed subject to the GNU General Public License
(GPL). Version 2, June 1991, available at
<http://www.fsf.org/copyleft/gpl.html>"
GNU General Public License
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your freedom to
share and change it. By contrast, the GNU General Public License is intended
to guarantee your freedom to share and change free software--to make sure
the software is free for all its users. This General Public License applies
to most of the Free Software Foundation's software and to any other program
whose authors commit to using it. (Some other Free Software Foundation
software is covered by the GNU Library General Public License instead.) You
can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our
General Public Licenses are designed to make sure that you have the freedom
to distribute copies of free software (and charge for this service if you
wish), that you receive source code or can get it if you want it, that you
can change the software or use pieces of it in new free programs; and that
you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to
deny you these rights or to ask you to surrender the rights. These
restrictions translate to certain responsibilities for you if you distribute
copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or
for a fee, you must give the recipients all the rights that you have. You
must make sure that they, too, receive or can get the source code. And you
must show them these terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2)
offer you this license which gives you legal permission to copy, distribute
and/or modify the software.
Also, for each author's protection and ours, we want to make certain that
everyone understands that there is no warranty for this free software. If
the software is modified by someone else and passed on, we want its
recipients to know that what they have is not the original, so that any
problems introduced by others will not reflect on the original authors'
reputations.
Finally, any free program is threatened constantly by software patents. We
wish to avoid the danger that redistributors of a free program will
individually obtain patent licenses, in effect making the program
proprietary. To prevent this, we have made it clear that any patent must be
licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification
follow.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains a notice
placed by the copyright holder saying it may be distributed under the
terms of this General Public License. The "Program", below, refers to any
such program or work, and a "work based on the Program" means either the
Program or any derivative work under copyright law: that is to say, a
work containing the Program or a portion of it, either verbatim or with
modifications and/or translated into another language. (Hereinafter,
translation is included without limitation in the term "modification".)
Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of running
the Program is not restricted, and the output from the Program is covered
only if its contents constitute a work based on the Program (independent
of having been made by running the Program). Whether that is true depends
on what the Program does.
1. You may copy and distribute verbatim copies of the Program's source code
as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this
License and to the absence of any warranty; and give any other recipients
of the Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you
may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it,
thus forming a work based on the Program, and copy and distribute such
modifications or work under the terms of Section 1 above, provided that
you also meet all of these conditions:
* a) You must cause the modified files to carry prominent notices stating
that you changed the files and the date of any change.
* b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any part
thereof, to be licensed as a whole at no charge to all third parties
under the terms of this License.
* c) If the modified program normally reads commands interactively when
run, you must cause it, when started running for such interactive
use in the most ordinary way, to print or display an announcement
including an appropriate copyright notice and a notice that there is
no warranty (or else, saying that you provide a warranty) and that
users may redistribute the program under these conditions, and
telling the user how to view a copy of this License. (Exception: if
the Program itself is interactive but does not normally print such
an announcement, your work based on the Program is not required to
print an announcement.)
These requirements apply to the modified work as a whole. If identifiable
sections of that work are not derived from the Program, and can be
reasonably considered independent and separate works in themselves, then
this License, and its terms, do not apply to those sections when you
distribute them as separate works. But when you distribute the same
sections as part of a whole which is a work based on the Program, the
distribution of the whole must be on the terms of this License, whose
permissions for other licensees extend to the entire whole, and thus to
each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of a
storage or distribution medium does not bring the other work under the
scope of this License.
3. You may copy and distribute the Program (or a work based on it, under
Section 2) in object code or executable form under the terms of Sections
1 and 2 above provided that you also do one of the following:
* a) Accompany it with the complete corresponding machine-readable source
code, which must be distributed under the terms of Sections 1 and 2
above on a medium customarily used for software interchange; or,
* b) Accompany it with a written offer, valid for at least three years,
to give any third party, for a charge no more than your cost of
physically performing source distribution, a complete machine-
readable copy of the corresponding source code, to be distributed
under the terms of Sections 1 and 2 above on a medium customarily
used for software interchange; or,
* c) Accompany it with the information you received as to the offer to
distribute corresponding source code. (This alternative is allowed
only for noncommercial distribution and only if you received the
program in object code or executable form with such an offer, in
accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source code
means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to control
compilation and installation of the executable. However, as a special
exception, the source code distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on which
the executable runs, unless that component itself accompanies the
executable.
If distribution of executable or object code is made by offering access
to copy from a designated place, then offering equivalent access to copy
the source code from the same place counts as distribution of the source
code, even though third parties are not compelled to copy the source
along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as
expressly provided under this License. Any attempt otherwise to copy,
modify, sublicense or distribute the Program is void, and will
automatically terminate your rights under this License. However, parties
who have received copies, or rights, from you under this License will not
have their licenses terminated so long as such parties remain in full
compliance.
5. You are not required to accept this License, since you have not signed
it. However, nothing else grants you permission to modify or distribute
the Program or its derivative works. These actions are prohibited by law
if you do not accept this License. Therefore, by modifying or
distributing the Program (or any work based on the Program), you
indicate your acceptance of this License to do so, and all its terms and
conditions for copying, distributing or modifying the Program or works
based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further restrictions
on the recipients' exercise of the rights granted herein. You are not
responsible for enforcing compliance by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot distribute
so as to satisfy simultaneously your obligations under this License and
any other pertinent obligations, then as a consequence you may not
distribute the Program at all. For example, if a patent license would
not permit royalty-free redistribution of the Program by all those who
receive copies directly or indirectly through you, then the only way you
could satisfy both it and this License would be to refrain entirely from
distribution of the Program.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is implemented
by public license practices. Many people have made generous contributions
to the wide range of software distributed through that system in
reliance on consistent application of that system; it is up to the
author/donor to decide if he or she is willing to distribute software
through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be
a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain
countries either by patents or by copyrighted interfaces, the original
copyright holder who places the Program under this License may add an
explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions of
the General Public License from time to time. Such new versions will be
similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Program does not specify a version
number of this License, you may choose any version ever published by the
Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs
whose distribution conditions are different, write to the author to ask
for permission. For software which is copyrighted by the Free Software
Foundation, write to the Free Software Foundation; we sometimes make
exceptions for this. Our decision will be guided by the two goals of
preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR
OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it free
software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively convey the
exclusion of warranty; and each file should have at least the "copyright"
line and a pointer to where the full notice is found.
one line to give the program's name and an idea of what it does.
Copyright (C) yyyy name of author
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when
it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free
software, and you are welcome to redistribute it under certain conditions;
type 'show c' for details.
The hypothetical commands 'show w' and 'show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may be
called something other than 'show w' and 'show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
'Gnomovision' (which makes passes at compilers) written by James Hacker.
signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General Public
License instead of this License.

View File

@ -0,0 +1,925 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IXGBE_H_
#define _IXGBE_H_
#ifndef IXGBE_NO_LRO
#include <net/tcp.h>
#endif
#include <linux/pci.h>
#include <linux/netdevice.h>
#ifdef HAVE_IRQ_AFFINITY_HINT
#include <linux/cpumask.h>
#endif /* HAVE_IRQ_AFFINITY_HINT */
#include <linux/vmalloc.h>
#ifdef SIOCETHTOOL
#include <linux/ethtool.h>
#endif
#ifdef NETIF_F_HW_VLAN_TX
#include <linux/if_vlan.h>
#endif
#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
#define IXGBE_DCA
#include <linux/dca.h>
#endif
#include "ixgbe_dcb.h"
#include "kcompat.h"
#ifdef HAVE_SCTP
#include <linux/sctp.h>
#endif
#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
#define IXGBE_FCOE
#include "ixgbe_fcoe.h"
#endif /* CONFIG_FCOE or CONFIG_FCOE_MODULE */
#if defined(CONFIG_PTP_1588_CLOCK) || defined(CONFIG_PTP_1588_CLOCK_MODULE)
#define HAVE_IXGBE_PTP
#endif
#include "ixgbe_api.h"
#define PFX "ixgbe: "
#define DPRINTK(nlevel, klevel, fmt, args...) \
((void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \
printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \
__func__ , ## args)))
/* TX/RX descriptor defines */
#define IXGBE_DEFAULT_TXD 512
#define IXGBE_DEFAULT_TX_WORK 256
#define IXGBE_MAX_TXD 4096
#define IXGBE_MIN_TXD 64
#define IXGBE_DEFAULT_RXD 512
#define IXGBE_DEFAULT_RX_WORK 256
#define IXGBE_MAX_RXD 4096
#define IXGBE_MIN_RXD 64
/* flow control */
#define IXGBE_MIN_FCRTL 0x40
#define IXGBE_MAX_FCRTL 0x7FF80
#define IXGBE_MIN_FCRTH 0x600
#define IXGBE_MAX_FCRTH 0x7FFF0
#define IXGBE_DEFAULT_FCPAUSE 0xFFFF
#define IXGBE_MIN_FCPAUSE 0
#define IXGBE_MAX_FCPAUSE 0xFFFF
/* Supported Rx Buffer Sizes */
#define IXGBE_RXBUFFER_512 512 /* Used for packet split */
#ifdef CONFIG_IXGBE_DISABLE_PACKET_SPLIT
#define IXGBE_RXBUFFER_1536 1536
#define IXGBE_RXBUFFER_2K 2048
#define IXGBE_RXBUFFER_3K 3072
#define IXGBE_RXBUFFER_4K 4096
#define IXGBE_RXBUFFER_7K 7168
#define IXGBE_RXBUFFER_8K 8192
#define IXGBE_RXBUFFER_15K 15360
#endif /* CONFIG_IXGBE_DISABLE_PACKET_SPLIT */
#define IXGBE_MAX_RXBUFFER 16384 /* largest size for single descriptor */
/*
* NOTE: netdev_alloc_skb reserves up to 64 bytes, NET_IP_ALIGN mans we
* reserve 2 more, and skb_shared_info adds an additional 384 bytes more,
* this adds up to 512 bytes of extra data meaning the smallest allocation
* we could have is 1K.
* i.e. RXBUFFER_512 --> size-1024 slab
*/
#define IXGBE_RX_HDR_SIZE IXGBE_RXBUFFER_512
#define MAXIMUM_ETHERNET_VLAN_SIZE (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)
/* How many Rx Buffers do we bundle into one write to the hardware ? */
#define IXGBE_RX_BUFFER_WRITE 16 /* Must be power of 2 */
#define IXGBE_TX_FLAGS_CSUM (u32)(1)
#define IXGBE_TX_FLAGS_HW_VLAN (u32)(1 << 1)
#define IXGBE_TX_FLAGS_SW_VLAN (u32)(1 << 2)
#define IXGBE_TX_FLAGS_TSO (u32)(1 << 3)
#define IXGBE_TX_FLAGS_IPV4 (u32)(1 << 4)
#define IXGBE_TX_FLAGS_FCOE (u32)(1 << 5)
#define IXGBE_TX_FLAGS_FSO (u32)(1 << 6)
#define IXGBE_TX_FLAGS_TXSW (u32)(1 << 7)
#define IXGBE_TX_FLAGS_TSTAMP (u32)(1 << 8)
#define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000
#define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0xe0000000
#define IXGBE_TX_FLAGS_VLAN_PRIO_SHIFT 29
#define IXGBE_TX_FLAGS_VLAN_SHIFT 16
#define IXGBE_MAX_RX_DESC_POLL 10
#define IXGBE_MAX_VF_MC_ENTRIES 30
#define IXGBE_MAX_VF_FUNCTIONS 64
#define IXGBE_MAX_VFTA_ENTRIES 128
#define MAX_EMULATION_MAC_ADDRS 16
#define IXGBE_MAX_PF_MACVLANS 15
#define IXGBE_82599_VF_DEVICE_ID 0x10ED
#define IXGBE_X540_VF_DEVICE_ID 0x1515
#ifdef CONFIG_PCI_IOV
#define VMDQ_P(p) ((p) + adapter->num_vfs)
#else
#define VMDQ_P(p) (p)
#endif
#define UPDATE_VF_COUNTER_32bit(reg, last_counter, counter) \
{ \
u32 current_counter = IXGBE_READ_REG(hw, reg); \
if (current_counter < last_counter) \
counter += 0x100000000LL; \
last_counter = current_counter; \
counter &= 0xFFFFFFFF00000000LL; \
counter |= current_counter; \
}
#define UPDATE_VF_COUNTER_36bit(reg_lsb, reg_msb, last_counter, counter) \
{ \
u64 current_counter_lsb = IXGBE_READ_REG(hw, reg_lsb); \
u64 current_counter_msb = IXGBE_READ_REG(hw, reg_msb); \
u64 current_counter = (current_counter_msb << 32) | \
current_counter_lsb; \
if (current_counter < last_counter) \
counter += 0x1000000000LL; \
last_counter = current_counter; \
counter &= 0xFFFFFFF000000000LL; \
counter |= current_counter; \
}
struct vf_stats {
u64 gprc;
u64 gorc;
u64 gptc;
u64 gotc;
u64 mprc;
};
struct vf_data_storage {
unsigned char vf_mac_addresses[ETH_ALEN];
u16 vf_mc_hashes[IXGBE_MAX_VF_MC_ENTRIES];
u16 num_vf_mc_hashes;
u16 default_vf_vlan_id;
u16 vlans_enabled;
bool clear_to_send;
struct vf_stats vfstats;
struct vf_stats last_vfstats;
struct vf_stats saved_rst_vfstats;
bool pf_set_mac;
u16 pf_vlan; /* When set, guest VLAN config not allowed. */
u16 pf_qos;
u16 tx_rate;
u16 vlan_count;
u8 spoofchk_enabled;
struct pci_dev *vfdev;
};
struct vf_macvlans {
struct list_head l;
int vf;
bool free;
bool is_macvlan;
u8 vf_macvlan[ETH_ALEN];
};
#ifndef IXGBE_NO_LRO
#define IXGBE_LRO_MAX 32 /*Maximum number of LRO descriptors*/
#define IXGBE_LRO_GLOBAL 10
struct ixgbe_lro_stats {
u32 flushed;
u32 coal;
};
/*
* ixgbe_lro_header - header format to be aggregated by LRO
* @iph: IP header without options
* @tcp: TCP header
* @ts: Optional TCP timestamp data in TCP options
*
* This structure relies on the check above that verifies that the header
* is IPv4 and does not contain any options.
*/
struct ixgbe_lrohdr {
struct iphdr iph;
struct tcphdr th;
__be32 ts[0];
};
struct ixgbe_lro_list {
struct sk_buff_head active;
struct ixgbe_lro_stats stats;
};
#endif /* IXGBE_NO_LRO */
#define IXGBE_MAX_TXD_PWR 14
#define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR)
/* Tx Descriptors needed, worst case */
#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IXGBE_MAX_DATA_PER_TXD)
#ifdef MAX_SKB_FRAGS
#define DESC_NEEDED ((MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE)) + 4)
#else
#define DESC_NEEDED 4
#endif
/* wrapper around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer */
struct ixgbe_tx_buffer {
union ixgbe_adv_tx_desc *next_to_watch;
unsigned long time_stamp;
struct sk_buff *skb;
unsigned int bytecount;
unsigned short gso_segs;
__be16 protocol;
DEFINE_DMA_UNMAP_ADDR(dma);
DEFINE_DMA_UNMAP_LEN(len);
u32 tx_flags;
};
struct ixgbe_rx_buffer {
struct sk_buff *skb;
dma_addr_t dma;
#ifndef CONFIG_IXGBE_DISABLE_PACKET_SPLIT
struct page *page;
unsigned int page_offset;
#endif
};
struct ixgbe_queue_stats {
u64 packets;
u64 bytes;
};
struct ixgbe_tx_queue_stats {
u64 restart_queue;
u64 tx_busy;
u64 tx_done_old;
};
struct ixgbe_rx_queue_stats {
u64 rsc_count;
u64 rsc_flush;
u64 non_eop_descs;
u64 alloc_rx_page_failed;
u64 alloc_rx_buff_failed;
u64 csum_err;
};
enum ixgbe_ring_state_t {
__IXGBE_TX_FDIR_INIT_DONE,
__IXGBE_TX_DETECT_HANG,
__IXGBE_HANG_CHECK_ARMED,
__IXGBE_RX_RSC_ENABLED,
#ifndef HAVE_NDO_SET_FEATURES
__IXGBE_RX_CSUM_ENABLED,
#endif
__IXGBE_RX_CSUM_UDP_ZERO_ERR,
#ifdef IXGBE_FCOE
__IXGBE_RX_FCOE_BUFSZ,
#endif
};
#define check_for_tx_hang(ring) \
test_bit(__IXGBE_TX_DETECT_HANG, &(ring)->state)
#define set_check_for_tx_hang(ring) \
set_bit(__IXGBE_TX_DETECT_HANG, &(ring)->state)
#define clear_check_for_tx_hang(ring) \
clear_bit(__IXGBE_TX_DETECT_HANG, &(ring)->state)
#ifndef IXGBE_NO_HW_RSC
#define ring_is_rsc_enabled(ring) \
test_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state)
#else
#define ring_is_rsc_enabled(ring) false
#endif
#define set_ring_rsc_enabled(ring) \
set_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state)
#define clear_ring_rsc_enabled(ring) \
clear_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state)
#define netdev_ring(ring) (ring->netdev)
#define ring_queue_index(ring) (ring->queue_index)
struct ixgbe_ring {
struct ixgbe_ring *next; /* pointer to next ring in q_vector */
struct ixgbe_q_vector *q_vector; /* backpointer to host q_vector */
struct net_device *netdev; /* netdev ring belongs to */
struct device *dev; /* device for DMA mapping */
void *desc; /* descriptor ring memory */
union {
struct ixgbe_tx_buffer *tx_buffer_info;
struct ixgbe_rx_buffer *rx_buffer_info;
};
unsigned long state;
u8 __iomem *tail;
dma_addr_t dma; /* phys. address of descriptor ring */
unsigned int size; /* length in bytes */
u16 count; /* amount of descriptors */
u8 queue_index; /* needed for multiqueue queue management */
u8 reg_idx; /* holds the special value that gets
* the hardware register offset
* associated with this ring, which is
* different for DCB and RSS modes
*/
u16 next_to_use;
u16 next_to_clean;
union {
#ifdef CONFIG_IXGBE_DISABLE_PACKET_SPLIT
u16 rx_buf_len;
#else
u16 next_to_alloc;
#endif
struct {
u8 atr_sample_rate;
u8 atr_count;
};
};
u8 dcb_tc;
struct ixgbe_queue_stats stats;
union {
struct ixgbe_tx_queue_stats tx_stats;
struct ixgbe_rx_queue_stats rx_stats;
};
} ____cacheline_internodealigned_in_smp;
enum ixgbe_ring_f_enum {
RING_F_NONE = 0,
RING_F_VMDQ, /* SR-IOV uses the same ring feature */
RING_F_RSS,
RING_F_FDIR,
#ifdef IXGBE_FCOE
RING_F_FCOE,
#endif /* IXGBE_FCOE */
RING_F_ARRAY_SIZE /* must be last in enum set */
};
#define IXGBE_MAX_DCB_INDICES 8
#define IXGBE_MAX_RSS_INDICES 16
#define IXGBE_MAX_VMDQ_INDICES 64
#define IXGBE_MAX_FDIR_INDICES 64
#ifdef IXGBE_FCOE
#define IXGBE_MAX_FCOE_INDICES 8
#define MAX_RX_QUEUES (IXGBE_MAX_FDIR_INDICES + IXGBE_MAX_FCOE_INDICES)
#define MAX_TX_QUEUES (IXGBE_MAX_FDIR_INDICES + IXGBE_MAX_FCOE_INDICES)
#else
#define MAX_RX_QUEUES IXGBE_MAX_FDIR_INDICES
#define MAX_TX_QUEUES IXGBE_MAX_FDIR_INDICES
#endif /* IXGBE_FCOE */
struct ixgbe_ring_feature {
int indices;
int mask;
};
#ifndef CONFIG_IXGBE_DISABLE_PACKET_SPLIT
/*
* FCoE requires that all Rx buffers be over 2200 bytes in length. Since
* this is twice the size of a half page we need to double the page order
* for FCoE enabled Rx queues.
*/
#if defined(IXGBE_FCOE) && (PAGE_SIZE < 8192)
static inline unsigned int ixgbe_rx_pg_order(struct ixgbe_ring *ring)
{
return test_bit(__IXGBE_RX_FCOE_BUFSZ, &ring->state) ? 1 : 0;
}
#else
#define ixgbe_rx_pg_order(_ring) 0
#endif
#define ixgbe_rx_pg_size(_ring) (PAGE_SIZE << ixgbe_rx_pg_order(_ring))
#define ixgbe_rx_bufsz(_ring) ((PAGE_SIZE / 2) << ixgbe_rx_pg_order(_ring))
#endif
struct ixgbe_ring_container {
struct ixgbe_ring *ring; /* pointer to linked list of rings */
unsigned int total_bytes; /* total bytes processed this int */
unsigned int total_packets; /* total packets processed this int */
u16 work_limit; /* total work allowed per interrupt */
u8 count; /* total number of rings in vector */
u8 itr; /* current ITR setting for ring */
};
/* iterator for handling rings in ring container */
#define ixgbe_for_each_ring(pos, head) \
for (pos = (head).ring; pos != NULL; pos = pos->next)
#define MAX_RX_PACKET_BUFFERS ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) \
? 8 : 1)
#define MAX_TX_PACKET_BUFFERS MAX_RX_PACKET_BUFFERS
/* MAX_MSIX_Q_VECTORS of these are allocated,
* but we only use one per queue-specific vector.
*/
struct ixgbe_q_vector {
struct ixgbe_adapter *adapter;
int cpu; /* CPU for DCA */
u16 v_idx; /* index of q_vector within array, also used for
* finding the bit in EICR and friends that
* represents the vector for this ring */
u16 itr; /* Interrupt throttle rate written to EITR */
struct ixgbe_ring_container rx, tx;
#ifdef CONFIG_IXGBE_NAPI
struct napi_struct napi;
#endif
#ifndef HAVE_NETDEV_NAPI_LIST
struct net_device poll_dev;
#endif
#ifdef HAVE_IRQ_AFFINITY_HINT
cpumask_t affinity_mask;
#endif
#ifndef IXGBE_NO_LRO
struct ixgbe_lro_list lrolist; /* LRO list for queue vector*/
#endif
int numa_node;
char name[IFNAMSIZ + 9];
/* for dynamic allocation of rings associated with this q_vector */
struct ixgbe_ring ring[0] ____cacheline_internodealigned_in_smp;
};
/*
* microsecond values for various ITR rates shifted by 2 to fit itr register
* with the first 3 bits reserved 0
*/
#define IXGBE_MIN_RSC_ITR 24
#define IXGBE_100K_ITR 40
#define IXGBE_20K_ITR 200
#define IXGBE_16K_ITR 248
#define IXGBE_10K_ITR 400
#define IXGBE_8K_ITR 500
/* ixgbe_test_staterr - tests bits in Rx descriptor status and error fields */
static inline __le32 ixgbe_test_staterr(union ixgbe_adv_rx_desc *rx_desc,
const u32 stat_err_bits)
{
return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits);
}
/* ixgbe_desc_unused - calculate if we have unused descriptors */
static inline u16 ixgbe_desc_unused(struct ixgbe_ring *ring)
{
u16 ntc = ring->next_to_clean;
u16 ntu = ring->next_to_use;
return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1;
}
#define IXGBE_RX_DESC(R, i) \
(&(((union ixgbe_adv_rx_desc *)((R)->desc))[i]))
#define IXGBE_TX_DESC(R, i) \
(&(((union ixgbe_adv_tx_desc *)((R)->desc))[i]))
#define IXGBE_TX_CTXTDESC(R, i) \
(&(((struct ixgbe_adv_tx_context_desc *)((R)->desc))[i]))
#define IXGBE_MAX_JUMBO_FRAME_SIZE 16128
#ifdef IXGBE_FCOE
/* use 3K as the baby jumbo frame size for FCoE */
#define IXGBE_FCOE_JUMBO_FRAME_SIZE 3072
#endif /* IXGBE_FCOE */
#define TCP_TIMER_VECTOR 0
#define OTHER_VECTOR 1
#define NON_Q_VECTORS (OTHER_VECTOR + TCP_TIMER_VECTOR)
#define IXGBE_MAX_MSIX_Q_VECTORS_82599 64
#define IXGBE_MAX_MSIX_Q_VECTORS_82598 16
struct ixgbe_mac_addr {
u8 addr[ETH_ALEN];
u16 queue;
u16 state; /* bitmask */
};
#define IXGBE_MAC_STATE_DEFAULT 0x1
#define IXGBE_MAC_STATE_MODIFIED 0x2
#define IXGBE_MAC_STATE_IN_USE 0x4
#ifdef IXGBE_PROCFS
struct ixgbe_therm_proc_data {
struct ixgbe_hw *hw;
struct ixgbe_thermal_diode_data *sensor_data;
};
#endif /* IXGBE_PROCFS */
/*
* Only for array allocations in our adapter struct. On 82598, there will be
* unused entries in the array, but that's not a big deal. Also, in 82599,
* we can actually assign 64 queue vectors based on our extended-extended
* interrupt registers. This is different than 82598, which is limited to 16.
*/
#define MAX_MSIX_Q_VECTORS IXGBE_MAX_MSIX_Q_VECTORS_82599
#define MAX_MSIX_COUNT IXGBE_MAX_MSIX_VECTORS_82599
#define MIN_MSIX_Q_VECTORS 1
#define MIN_MSIX_COUNT (MIN_MSIX_Q_VECTORS + NON_Q_VECTORS)
/* default to trying for four seconds */
#define IXGBE_TRY_LINK_TIMEOUT (4 * HZ)
/* board specific private data structure */
struct ixgbe_adapter {
#ifdef NETIF_F_HW_VLAN_TX
#ifdef HAVE_VLAN_RX_REGISTER
struct vlan_group *vlgrp; /* must be first, see ixgbe_receive_skb */
#else
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
#endif
#endif /* NETIF_F_HW_VLAN_TX */
/* OS defined structs */
struct net_device *netdev;
struct pci_dev *pdev;
unsigned long state;
/* Some features need tri-state capability,
* thus the additional *_CAPABLE flags.
*/
u32 flags;
#define IXGBE_FLAG_MSI_CAPABLE (u32)(1 << 0)
#define IXGBE_FLAG_MSI_ENABLED (u32)(1 << 1)
#define IXGBE_FLAG_MSIX_CAPABLE (u32)(1 << 2)
#define IXGBE_FLAG_MSIX_ENABLED (u32)(1 << 3)
#ifndef IXGBE_NO_LLI
#define IXGBE_FLAG_LLI_PUSH (u32)(1 << 4)
#endif
#define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 8)
#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
#define IXGBE_FLAG_DCA_ENABLED (u32)(1 << 9)
#define IXGBE_FLAG_DCA_CAPABLE (u32)(1 << 10)
#define IXGBE_FLAG_DCA_ENABLED_DATA (u32)(1 << 11)
#else
#define IXGBE_FLAG_DCA_ENABLED (u32)0
#define IXGBE_FLAG_DCA_CAPABLE (u32)0
#define IXGBE_FLAG_DCA_ENABLED_DATA (u32)0
#endif
#define IXGBE_FLAG_MQ_CAPABLE (u32)(1 << 12)
#define IXGBE_FLAG_DCB_ENABLED (u32)(1 << 13)
#define IXGBE_FLAG_DCB_CAPABLE (u32)(1 << 14)
#define IXGBE_FLAG_RSS_ENABLED (u32)(1 << 15)
#define IXGBE_FLAG_RSS_CAPABLE (u32)(1 << 16)
#define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 18)
#define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 19)
#define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 20)
#define IXGBE_FLAG_NEED_LINK_CONFIG (u32)(1 << 21)
#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 22)
#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 23)
#ifdef IXGBE_FCOE
#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 24)
#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 25)
#endif /* IXGBE_FCOE */
#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 26)
#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 27)
#define IXGBE_FLAG_SRIOV_REPLICATION_ENABLE (u32)(1 << 28)
#define IXGBE_FLAG_SRIOV_L2SWITCH_ENABLE (u32)(1 << 29)
#define IXGBE_FLAG_SRIOV_L2LOOPBACK_ENABLE (u32)(1 << 30)
#define IXGBE_FLAG_RX_BB_CAPABLE (u32)(1 << 31)
u32 flags2;
#ifndef IXGBE_NO_HW_RSC
#define IXGBE_FLAG2_RSC_CAPABLE (u32)(1)
#define IXGBE_FLAG2_RSC_ENABLED (u32)(1 << 1)
#else
#define IXGBE_FLAG2_RSC_CAPABLE 0
#define IXGBE_FLAG2_RSC_ENABLED 0
#endif
#define IXGBE_FLAG2_VMDQ_DEFAULT_OVERRIDE (u32)(1 << 2)
#define IXGBE_FLAG2_TEMP_SENSOR_CAPABLE (u32)(1 << 4)
#define IXGBE_FLAG2_TEMP_SENSOR_EVENT (u32)(1 << 5)
#define IXGBE_FLAG2_SEARCH_FOR_SFP (u32)(1 << 6)
#define IXGBE_FLAG2_SFP_NEEDS_RESET (u32)(1 << 7)
#define IXGBE_FLAG2_RESET_REQUESTED (u32)(1 << 8)
#define IXGBE_FLAG2_FDIR_REQUIRES_REINIT (u32)(1 << 9)
#define IXGBE_FLAG2_RSS_FIELD_IPV4_UDP (u32)(1 << 10)
#define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP (u32)(1 << 11)
#define IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED (u32)(1 << 12)
/* Tx fast path data */
int num_tx_queues;
u16 tx_itr_setting;
u16 tx_work_limit;
/* Rx fast path data */
int num_rx_queues;
u16 rx_itr_setting;
u16 rx_work_limit;
/* TX */
struct ixgbe_ring *tx_ring[MAX_TX_QUEUES] ____cacheline_aligned_in_smp;
u64 restart_queue;
u64 lsc_int;
u32 tx_timeout_count;
/* RX */
struct ixgbe_ring *rx_ring[MAX_RX_QUEUES];
int num_rx_pools; /* == num_rx_queues in 82598 */
int num_rx_queues_per_pool; /* 1 if 82598, can be many if 82599 */
u64 hw_csum_rx_error;
u64 hw_rx_no_dma_resources;
u64 rsc_total_count;
u64 rsc_total_flush;
u64 non_eop_descs;
#ifndef CONFIG_IXGBE_NAPI
u64 rx_dropped_backlog; /* count drops from rx intr handler */
#endif
u32 alloc_rx_page_failed;
u32 alloc_rx_buff_failed;
struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
#ifdef HAVE_DCBNL_IEEE
struct ieee_pfc *ixgbe_ieee_pfc;
struct ieee_ets *ixgbe_ieee_ets;
#endif
struct ixgbe_dcb_config dcb_cfg;
struct ixgbe_dcb_config temp_dcb_cfg;
u8 dcb_set_bitmap;
u8 dcbx_cap;
#ifndef HAVE_MQPRIO
u8 tc;
#endif
enum ixgbe_fc_mode last_lfc_mode;
int num_msix_vectors;
int max_msix_q_vectors; /* true count of q_vectors for device */
struct ixgbe_ring_feature ring_feature[RING_F_ARRAY_SIZE];
struct msix_entry *msix_entries;
#ifndef HAVE_NETDEV_STATS_IN_NETDEV
struct net_device_stats net_stats;
#endif
#ifndef IXGBE_NO_LRO
struct ixgbe_lro_stats lro_stats;
#endif
#ifdef ETHTOOL_TEST
u32 test_icr;
struct ixgbe_ring test_tx_ring;
struct ixgbe_ring test_rx_ring;
#endif
/* structs defined in ixgbe_hw.h */
struct ixgbe_hw hw;
u16 msg_enable;
struct ixgbe_hw_stats stats;
#ifndef IXGBE_NO_LLI
u32 lli_port;
u32 lli_size;
u32 lli_etype;
u32 lli_vlan_pri;
#endif /* IXGBE_NO_LLI */
u32 *config_space;
u64 tx_busy;
unsigned int tx_ring_count;
unsigned int rx_ring_count;
u32 link_speed;
bool link_up;
unsigned long link_check_timeout;
struct timer_list service_timer;
struct work_struct service_task;
struct hlist_head fdir_filter_list;
unsigned long fdir_overflow; /* number of times ATR was backed off */
union ixgbe_atr_input fdir_mask;
int fdir_filter_count;
u32 fdir_pballoc;
u32 atr_sample_rate;
spinlock_t fdir_perfect_lock;
#ifdef IXGBE_FCOE
struct ixgbe_fcoe fcoe;
#endif /* IXGBE_FCOE */
u32 wol;
u16 bd_number;
char eeprom_id[32];
u16 eeprom_cap;
bool netdev_registered;
u32 interrupt_event;
#ifdef HAVE_ETHTOOL_SET_PHYS_ID
u32 led_reg;
#endif
DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS);
unsigned int num_vfs;
struct vf_data_storage *vfinfo;
int vf_rate_link_speed;
struct vf_macvlans vf_mvs;
struct vf_macvlans *mv_list;
#ifdef CONFIG_PCI_IOV
u32 timer_event_accumulator;
u32 vferr_refcount;
#endif
struct ixgbe_mac_addr *mac_table;
#ifdef IXGBE_SYSFS
struct kobject *info_kobj;
struct kobject *therm_kobj[IXGBE_MAX_SENSORS];
#else /* IXGBE_SYSFS */
#ifdef IXGBE_PROCFS
struct proc_dir_entry *eth_dir;
struct proc_dir_entry *info_dir;
struct proc_dir_entry *therm_dir[IXGBE_MAX_SENSORS];
struct ixgbe_therm_proc_data therm_data[IXGBE_MAX_SENSORS];
#endif /* IXGBE_PROCFS */
#endif /* IXGBE_SYSFS */
};
struct ixgbe_fdir_filter {
struct hlist_node fdir_node;
union ixgbe_atr_input filter;
u16 sw_idx;
u16 action;
};
enum ixgbe_state_t {
__IXGBE_TESTING,
__IXGBE_RESETTING,
__IXGBE_DOWN,
__IXGBE_SERVICE_SCHED,
__IXGBE_IN_SFP_INIT,
};
struct ixgbe_cb {
#ifdef CONFIG_IXGBE_DISABLE_PACKET_SPLIT
union { /* Union defining head/tail partner */
struct sk_buff *head;
struct sk_buff *tail;
};
#endif
dma_addr_t dma;
#ifndef IXGBE_NO_LRO
__be32 tsecr; /* timestamp echo response */
u32 tsval; /* timestamp value in host order */
u32 next_seq; /* next expected sequence number */
u16 free; /* 65521 minus total size */
u16 mss; /* size of data portion of packet */
#endif /* IXGBE_NO_LRO */
#ifdef HAVE_VLAN_RX_REGISTER
u16 vid; /* VLAN tag */
#endif
u16 append_cnt; /* number of skb's appended */
#ifndef CONFIG_IXGBE_DISABLE_PACKET_SPLIT
bool page_released;
#endif
};
#define IXGBE_CB(skb) ((struct ixgbe_cb *)(skb)->cb)
#ifdef IXGBE_SYSFS
void ixgbe_sysfs_exit(struct ixgbe_adapter *adapter);
int ixgbe_sysfs_init(struct ixgbe_adapter *adapter);
#endif /* IXGBE_SYSFS */
#ifdef IXGBE_PROCFS
void ixgbe_procfs_exit(struct ixgbe_adapter *adapter);
int ixgbe_procfs_init(struct ixgbe_adapter *adapter);
int ixgbe_procfs_topdir_init(void);
void ixgbe_procfs_topdir_exit(void);
#endif /* IXGBE_PROCFS */
extern struct dcbnl_rtnl_ops dcbnl_ops;
extern int ixgbe_copy_dcb_cfg(struct ixgbe_adapter *adapter, int tc_max);
extern u8 ixgbe_dcb_txq_to_tc(struct ixgbe_adapter *adapter, u8 index);
/* needed by ixgbe_main.c */
extern int ixgbe_validate_mac_addr(u8 *mc_addr);
extern void ixgbe_check_options(struct ixgbe_adapter *adapter);
extern void ixgbe_assign_netdev_ops(struct net_device *netdev);
/* needed by ixgbe_ethtool.c */
extern char ixgbe_driver_name[];
extern const char ixgbe_driver_version[];
extern void ixgbe_up(struct ixgbe_adapter *adapter);
extern void ixgbe_down(struct ixgbe_adapter *adapter);
extern void ixgbe_reinit_locked(struct ixgbe_adapter *adapter);
extern void ixgbe_reset(struct ixgbe_adapter *adapter);
extern void ixgbe_set_ethtool_ops(struct net_device *netdev);
extern int ixgbe_setup_rx_resources(struct ixgbe_ring *);
extern int ixgbe_setup_tx_resources(struct ixgbe_ring *);
extern void ixgbe_free_rx_resources(struct ixgbe_ring *);
extern void ixgbe_free_tx_resources(struct ixgbe_ring *);
extern void ixgbe_configure_rx_ring(struct ixgbe_adapter *,
struct ixgbe_ring *);
extern void ixgbe_configure_tx_ring(struct ixgbe_adapter *,
struct ixgbe_ring *);
extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter);
extern bool ixgbe_is_ixgbe(struct pci_dev *pcidev);
extern netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *,
struct ixgbe_adapter *,
struct ixgbe_ring *);
extern void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *,
struct ixgbe_tx_buffer *);
extern void ixgbe_alloc_rx_buffers(struct ixgbe_ring *, u16);
extern void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
struct ixgbe_ring *);
extern void ixgbe_clear_rscctl(struct ixgbe_adapter *adapter,
struct ixgbe_ring *);
extern void ixgbe_set_rx_mode(struct net_device *netdev);
extern int ixgbe_write_mc_addr_list(struct net_device *netdev);
extern int ixgbe_setup_tc(struct net_device *dev, u8 tc);
#ifdef IXGBE_FCOE
extern void ixgbe_tx_ctxtdesc(struct ixgbe_ring *, u32, u32, u32, u32);
#endif /* IXGBE_FCOE */
extern void ixgbe_do_reset(struct net_device *netdev);
extern void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector);
extern void ixgbe_disable_rx_queue(struct ixgbe_adapter *adapter,
struct ixgbe_ring *);
extern void ixgbe_vlan_stripping_enable(struct ixgbe_adapter *adapter);
extern void ixgbe_vlan_stripping_disable(struct ixgbe_adapter *adapter);
#ifdef ETHTOOL_OPS_COMPAT
extern int ethtool_ioctl(struct ifreq *ifr);
#endif
#ifdef IXGBE_FCOE
extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
extern int ixgbe_fso(struct ixgbe_ring *tx_ring,
struct ixgbe_tx_buffer *first,
u8 *hdr_len);
extern void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter);
extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
union ixgbe_adv_rx_desc *rx_desc,
struct sk_buff *skb);
extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
struct scatterlist *sgl, unsigned int sgc);
#ifdef HAVE_NETDEV_OPS_FCOE_DDP_TARGET
extern int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
struct scatterlist *sgl, unsigned int sgc);
#endif /* HAVE_NETDEV_OPS_FCOE_DDP_TARGET */
extern int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid);
#ifdef HAVE_NETDEV_OPS_FCOE_ENABLE
extern int ixgbe_fcoe_enable(struct net_device *netdev);
extern int ixgbe_fcoe_disable(struct net_device *netdev);
#endif /* HAVE_NETDEV_OPS_FCOE_ENABLE */
#ifdef CONFIG_DCB
#ifdef HAVE_DCBNL_OPS_GETAPP
extern u8 ixgbe_fcoe_getapp(struct net_device *netdev);
#endif /* HAVE_DCBNL_OPS_GETAPP */
extern u8 ixgbe_fcoe_setapp(struct ixgbe_adapter *adapter, u8 up);
#endif /* CONFIG_DCB */
#ifdef HAVE_NETDEV_OPS_FCOE_GETWWN
extern int ixgbe_fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type);
#endif
#endif /* IXGBE_FCOE */
#ifdef CONFIG_DCB
#ifdef HAVE_DCBNL_IEEE
s32 ixgbe_dcb_hw_ets(struct ixgbe_hw *hw, struct ieee_ets *ets, int max_frame);
#endif /* HAVE_DCBNL_IEEE */
#endif /* CONFIG_DCB */
extern void ixgbe_clean_rx_ring(struct ixgbe_ring *rx_ring);
extern int ixgbe_get_settings(struct net_device *netdev,
struct ethtool_cmd *ecmd);
extern int ixgbe_write_uc_addr_list(struct ixgbe_adapter *adapter,
struct net_device *netdev, unsigned int vfn);
extern void ixgbe_full_sync_mac_table(struct ixgbe_adapter *adapter);
extern int ixgbe_add_mac_filter(struct ixgbe_adapter *adapter,
u8 *addr, u16 queue);
extern int ixgbe_del_mac_filter(struct ixgbe_adapter *adapter,
u8 *addr, u16 queue);
extern int ixgbe_available_rars(struct ixgbe_adapter *adapter);
#ifndef HAVE_VLAN_RX_REGISTER
extern void ixgbe_vlan_mode(struct net_device *, u32);
#endif
#ifndef ixgbe_get_netdev_tc_txq
#define ixgbe_get_netdev_tc_txq(dev, tc) (&dev->tc_to_txq[tc])
#endif
extern void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter);
#endif /* _IXGBE_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IXGBE_82598_H_
#define _IXGBE_82598_H_
u32 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw);
s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw);
s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw);
s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on);
s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val);
s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val);
s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
u8 *eeprom_data);
u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw);
s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw);
void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw);
void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw);
#endif /* _IXGBE_82598_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IXGBE_82599_H_
#define _IXGBE_82599_H_
s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
ixgbe_link_speed *speed, bool *autoneg);
enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw);
void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
ixgbe_link_speed speed, bool autoneg,
bool autoneg_wait_to_complete);
s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
ixgbe_link_speed speed, bool autoneg,
bool autoneg_wait_to_complete);
s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
bool autoneg_wait_to_complete);
s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed,
bool autoneg, bool autoneg_wait_to_complete);
s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw);
void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw);
s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw);
s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val);
s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val);
s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw);
s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw);
s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw);
u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw);
s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval);
bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
#endif /* _IXGBE_82599_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,168 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IXGBE_API_H_
#define _IXGBE_API_H_
#include "ixgbe_type.h"
s32 ixgbe_init_shared_code(struct ixgbe_hw *hw);
extern s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw);
extern s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw);
extern s32 ixgbe_init_ops_X540(struct ixgbe_hw *hw);
s32 ixgbe_set_mac_type(struct ixgbe_hw *hw);
s32 ixgbe_init_hw(struct ixgbe_hw *hw);
s32 ixgbe_reset_hw(struct ixgbe_hw *hw);
s32 ixgbe_start_hw(struct ixgbe_hw *hw);
s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw);
enum ixgbe_media_type ixgbe_get_media_type(struct ixgbe_hw *hw);
s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr);
s32 ixgbe_get_bus_info(struct ixgbe_hw *hw);
u32 ixgbe_get_num_of_tx_queues(struct ixgbe_hw *hw);
u32 ixgbe_get_num_of_rx_queues(struct ixgbe_hw *hw);
s32 ixgbe_stop_adapter(struct ixgbe_hw *hw);
s32 ixgbe_read_pba_string(struct ixgbe_hw *hw, u8 *pba_num, u32 pba_num_size);
s32 ixgbe_identify_phy(struct ixgbe_hw *hw);
s32 ixgbe_reset_phy(struct ixgbe_hw *hw);
s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type,
u16 *phy_data);
s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type,
u16 phy_data);
s32 ixgbe_setup_phy_link(struct ixgbe_hw *hw);
s32 ixgbe_check_phy_link(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
bool *link_up);
s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
void ixgbe_disable_tx_laser(struct ixgbe_hw *hw);
void ixgbe_enable_tx_laser(struct ixgbe_hw *hw);
void ixgbe_flap_tx_laser(struct ixgbe_hw *hw);
s32 ixgbe_setup_link(struct ixgbe_hw *hw, ixgbe_link_speed speed,
bool autoneg, bool autoneg_wait_to_complete);
s32 ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
bool *link_up, bool link_up_wait_to_complete);
s32 ixgbe_get_link_capabilities(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
bool *autoneg);
s32 ixgbe_led_on(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_led_off(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_blink_led_start(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_blink_led_stop(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_init_eeprom_params(struct ixgbe_hw *hw);
s32 ixgbe_write_eeprom(struct ixgbe_hw *hw, u16 offset, u16 data);
s32 ixgbe_write_eeprom_buffer(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data);
s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data);
s32 ixgbe_read_eeprom_buffer(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data);
s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val);
s32 ixgbe_update_eeprom_checksum(struct ixgbe_hw *hw);
s32 ixgbe_insert_mac_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
s32 ixgbe_set_rar(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
u32 enable_addr);
s32 ixgbe_clear_rar(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_set_vmdq(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
s32 ixgbe_set_vmdq_san_mac(struct ixgbe_hw *hw, u32 vmdq);
s32 ixgbe_clear_vmdq(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw);
u32 ixgbe_get_num_rx_addrs(struct ixgbe_hw *hw);
s32 ixgbe_update_uc_addr_list(struct ixgbe_hw *hw, u8 *addr_list,
u32 addr_count, ixgbe_mc_addr_itr func);
s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list,
u32 mc_addr_count, ixgbe_mc_addr_itr func,
bool clear);
void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr_list, u32 vmdq);
s32 ixgbe_enable_mc(struct ixgbe_hw *hw);
s32 ixgbe_disable_mc(struct ixgbe_hw *hw);
s32 ixgbe_clear_vfta(struct ixgbe_hw *hw);
s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan,
u32 vind, bool vlan_on);
s32 ixgbe_set_vlvf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
bool vlan_on, bool *vfta_changed);
s32 ixgbe_fc_enable(struct ixgbe_hw *hw);
s32 ixgbe_set_fw_drv_ver(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build,
u8 ver);
s32 ixgbe_get_thermal_sensor_data(struct ixgbe_hw *hw);
s32 ixgbe_init_thermal_sensor_thresh(struct ixgbe_hw *hw);
void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr);
s32 ixgbe_get_phy_firmware_version(struct ixgbe_hw *hw,
u16 *firmware_version);
s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val);
s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val);
s32 ixgbe_init_uta_tables(struct ixgbe_hw *hw);
s32 ixgbe_read_i2c_eeprom(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data);
u32 ixgbe_get_supported_physical_layer(struct ixgbe_hw *hw);
s32 ixgbe_enable_rx_dma(struct ixgbe_hw *hw, u32 regval);
s32 ixgbe_disable_sec_rx_path(struct ixgbe_hw *hw);
s32 ixgbe_enable_sec_rx_path(struct ixgbe_hw *hw);
s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl);
s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl);
s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
union ixgbe_atr_hash_dword input,
union ixgbe_atr_hash_dword common,
u8 queue);
s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
union ixgbe_atr_input *input_mask);
s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
union ixgbe_atr_input *input,
u16 soft_id, u8 queue);
s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
union ixgbe_atr_input *input,
u16 soft_id);
s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
union ixgbe_atr_input *input,
union ixgbe_atr_input *mask,
u16 soft_id,
u8 queue);
void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
union ixgbe_atr_input *mask);
u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,
union ixgbe_atr_hash_dword common);
s32 ixgbe_read_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr,
u8 *data);
s32 ixgbe_write_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr,
u8 data);
s32 ixgbe_write_i2c_eeprom(struct ixgbe_hw *hw, u8 byte_offset, u8 eeprom_data);
s32 ixgbe_get_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr);
s32 ixgbe_set_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr);
s32 ixgbe_get_device_caps(struct ixgbe_hw *hw, u16 *device_caps);
s32 ixgbe_acquire_swfw_semaphore(struct ixgbe_hw *hw, u16 mask);
void ixgbe_release_swfw_semaphore(struct ixgbe_hw *hw, u16 mask);
s32 ixgbe_get_wwn_prefix(struct ixgbe_hw *hw, u16 *wwnn_prefix,
u16 *wwpn_prefix);
s32 ixgbe_get_fcoe_boot_status(struct ixgbe_hw *hw, u16 *bs);
#endif /* _IXGBE_API_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,140 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IXGBE_COMMON_H_
#define _IXGBE_COMMON_H_
#include "ixgbe_type.h"
u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw);
s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw);
s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw);
s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw);
s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw);
s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw);
s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num,
u32 pba_num_size);
s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr);
s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw);
void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw);
s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw);
s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw);
s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data);
s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data);
s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data);
s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data);
s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data);
s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data);
s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
u16 *data);
s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data);
u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw);
s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
u16 *checksum_val);
s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw);
s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg);
s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
u32 enable_addr);
s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw);
s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
u32 mc_addr_count,
ixgbe_mc_addr_itr func, bool clear);
s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
u32 addr_count, ixgbe_mc_addr_itr func);
s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw);
s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw);
s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval);
s32 ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw *hw);
s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw);
s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw);
void ixgbe_fc_autoneg(struct ixgbe_hw *hw);
s32 ixgbe_validate_mac_addr(u8 *mac_addr);
s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask);
void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask);
s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr);
s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr);
s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
s32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq);
s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw);
s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan,
u32 vind, bool vlan_on);
s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
bool vlan_on, bool *vfta_changed);
s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw);
s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan);
s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
bool *link_up, bool link_up_wait_to_complete);
s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
u16 *wwpn_prefix);
s32 ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw *hw, u16 *bs);
void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf);
void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf);
s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps);
void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom,
int strategy);
s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
u8 build, u8 ver);
void ixgbe_clear_tx_pending(struct ixgbe_hw *hw);
#define IXGBE_I2C_THERMAL_SENSOR_ADDR 0xF8
#define IXGBE_EMC_INTERNAL_DATA 0x00
#define IXGBE_EMC_INTERNAL_THERM_LIMIT 0x20
#define IXGBE_EMC_DIODE1_DATA 0x01
#define IXGBE_EMC_DIODE1_THERM_LIMIT 0x19
#define IXGBE_EMC_DIODE2_DATA 0x23
#define IXGBE_EMC_DIODE2_THERM_LIMIT 0x1A
#define IXGBE_EMC_DIODE3_DATA 0x2A
#define IXGBE_EMC_DIODE3_THERM_LIMIT 0x30
s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw);
s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw);
#endif /* IXGBE_COMMON */

View File

@ -0,0 +1,168 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IXGBE_DCB_H_
#define _IXGBE_DCB_H_
#include "ixgbe_type.h"
/* DCB defines */
/* DCB credit calculation defines */
#define IXGBE_DCB_CREDIT_QUANTUM 64
#define IXGBE_DCB_MAX_CREDIT_REFILL 200 /* 200 * 64B = 12800B */
#define IXGBE_DCB_MAX_TSO_SIZE (32 * 1024) /* Max TSO pkt size in DCB*/
#define IXGBE_DCB_MAX_CREDIT (2 * IXGBE_DCB_MAX_CREDIT_REFILL)
/* 513 for 32KB TSO packet */
#define IXGBE_DCB_MIN_TSO_CREDIT \
((IXGBE_DCB_MAX_TSO_SIZE / IXGBE_DCB_CREDIT_QUANTUM) + 1)
/* DCB configuration defines */
#define IXGBE_DCB_MAX_USER_PRIORITY 8
#define IXGBE_DCB_MAX_BW_GROUP 8
#define IXGBE_DCB_BW_PERCENT 100
#define IXGBE_DCB_TX_CONFIG 0
#define IXGBE_DCB_RX_CONFIG 1
/* DCB capability defines */
#define IXGBE_DCB_PG_SUPPORT 0x00000001
#define IXGBE_DCB_PFC_SUPPORT 0x00000002
#define IXGBE_DCB_BCN_SUPPORT 0x00000004
#define IXGBE_DCB_UP2TC_SUPPORT 0x00000008
#define IXGBE_DCB_GSP_SUPPORT 0x00000010
struct ixgbe_dcb_support {
u32 capabilities; /* DCB capabilities */
/* Each bit represents a number of TCs configurable in the hw.
* If 8 traffic classes can be configured, the value is 0x80. */
u8 traffic_classes;
u8 pfc_traffic_classes;
};
enum ixgbe_dcb_tsa {
ixgbe_dcb_tsa_ets = 0,
ixgbe_dcb_tsa_group_strict_cee,
ixgbe_dcb_tsa_strict
};
/* Traffic class bandwidth allocation per direction */
struct ixgbe_dcb_tc_path {
u8 bwg_id; /* Bandwidth Group (BWG) ID */
u8 bwg_percent; /* % of BWG's bandwidth */
u8 link_percent; /* % of link bandwidth */
u8 up_to_tc_bitmap; /* User Priority to Traffic Class mapping */
u16 data_credits_refill; /* Credit refill amount in 64B granularity */
u16 data_credits_max; /* Max credits for a configured packet buffer
* in 64B granularity.*/
enum ixgbe_dcb_tsa tsa; /* Link or Group Strict Priority */
};
enum ixgbe_dcb_pfc {
ixgbe_dcb_pfc_disabled = 0,
ixgbe_dcb_pfc_enabled,
ixgbe_dcb_pfc_enabled_txonly,
ixgbe_dcb_pfc_enabled_rxonly
};
/* Traffic class configuration */
struct ixgbe_dcb_tc_config {
struct ixgbe_dcb_tc_path path[2]; /* One each for Tx/Rx */
enum ixgbe_dcb_pfc pfc; /* Class based flow control setting */
u16 desc_credits_max; /* For Tx Descriptor arbitration */
u8 tc; /* Traffic class (TC) */
};
enum ixgbe_dcb_pba {
/* PBA[0-7] each use 64KB FIFO */
ixgbe_dcb_pba_equal = PBA_STRATEGY_EQUAL,
/* PBA[0-3] each use 80KB, PBA[4-7] each use 48KB */
ixgbe_dcb_pba_80_48 = PBA_STRATEGY_WEIGHTED
};
struct ixgbe_dcb_num_tcs {
u8 pg_tcs;
u8 pfc_tcs;
};
struct ixgbe_dcb_config {
struct ixgbe_dcb_tc_config tc_config[IXGBE_DCB_MAX_TRAFFIC_CLASS];
struct ixgbe_dcb_support support;
struct ixgbe_dcb_num_tcs num_tcs;
u8 bw_percentage[2][IXGBE_DCB_MAX_BW_GROUP]; /* One each for Tx/Rx */
bool pfc_mode_enable;
bool round_robin_enable;
enum ixgbe_dcb_pba rx_pba_cfg;
u32 dcb_cfg_version; /* Not used...OS-specific? */
u32 link_speed; /* For bandwidth allocation validation purpose */
bool vt_mode;
};
/* DCB driver APIs */
/* DCB rule checking */
s32 ixgbe_dcb_check_config_cee(struct ixgbe_dcb_config *);
/* DCB credits calculation */
s32 ixgbe_dcb_calculate_tc_credits(u8 *, u16 *, u16 *, int);
s32 ixgbe_dcb_calculate_tc_credits_cee(struct ixgbe_hw *,
struct ixgbe_dcb_config *, u32, u8);
/* DCB PFC */
s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *, u8, u8 *);
s32 ixgbe_dcb_config_pfc_cee(struct ixgbe_hw *, struct ixgbe_dcb_config *);
/* DCB stats */
s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *);
s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8);
s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8);
/* DCB config arbiters */
s32 ixgbe_dcb_config_tx_desc_arbiter_cee(struct ixgbe_hw *,
struct ixgbe_dcb_config *);
s32 ixgbe_dcb_config_tx_data_arbiter_cee(struct ixgbe_hw *,
struct ixgbe_dcb_config *);
s32 ixgbe_dcb_config_rx_arbiter_cee(struct ixgbe_hw *,
struct ixgbe_dcb_config *);
/* DCB unpack routines */
void ixgbe_dcb_unpack_pfc_cee(struct ixgbe_dcb_config *, u8 *, u8 *);
void ixgbe_dcb_unpack_refill_cee(struct ixgbe_dcb_config *, int, u16 *);
void ixgbe_dcb_unpack_max_cee(struct ixgbe_dcb_config *, u16 *);
void ixgbe_dcb_unpack_bwgid_cee(struct ixgbe_dcb_config *, int, u8 *);
void ixgbe_dcb_unpack_tsa_cee(struct ixgbe_dcb_config *, int, u8 *);
void ixgbe_dcb_unpack_map_cee(struct ixgbe_dcb_config *, int, u8 *);
/* DCB initialization */
s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, u16 *, u16 *, u8 *, u8 *, u8 *);
s32 ixgbe_dcb_hw_config_cee(struct ixgbe_hw *, struct ixgbe_dcb_config *);
#endif /* _IXGBE_DCB_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,91 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IXGBE_FCOE_H
#define _IXGBE_FCOE_H
#ifdef IXGBE_FCOE
#include <scsi/fc/fc_fs.h>
#include <scsi/fc/fc_fcoe.h>
/* shift bits within STAT fo FCSTAT */
#define IXGBE_RXDADV_FCSTAT_SHIFT 4
/* ddp user buffer */
#define IXGBE_BUFFCNT_MAX 256 /* 8 bits bufcnt */
#define IXGBE_FCPTR_ALIGN 16
#define IXGBE_FCPTR_MAX (IXGBE_BUFFCNT_MAX * sizeof(dma_addr_t))
#define IXGBE_FCBUFF_4KB 0x0
#define IXGBE_FCBUFF_8KB 0x1
#define IXGBE_FCBUFF_16KB 0x2
#define IXGBE_FCBUFF_64KB 0x3
#define IXGBE_FCBUFF_MAX 65536 /* 64KB max */
#define IXGBE_FCBUFF_MIN 4096 /* 4KB min */
#define IXGBE_FCOE_DDP_MAX 512 /* 9 bits xid */
/* Default traffic class to use for FCoE */
#define IXGBE_FCOE_DEFTC 3
/* fcerr */
#define IXGBE_FCERR_BADCRC 0x00100000
#define IXGBE_FCERR_EOFSOF 0x00200000
#define IXGBE_FCERR_NOFIRST 0x00300000
#define IXGBE_FCERR_OOOSEQ 0x00400000
#define IXGBE_FCERR_NODMA 0x00500000
#define IXGBE_FCERR_PKTLOST 0x00600000
/* FCoE DDP for target mode */
#define __IXGBE_FCOE_TARGET 1
struct ixgbe_fcoe_ddp {
int len;
u32 err;
unsigned int sgc;
struct scatterlist *sgl;
dma_addr_t udp;
u64 *udl;
struct pci_pool *pool;
};
struct ixgbe_fcoe {
struct pci_pool **pool;
atomic_t refcnt;
spinlock_t lock;
struct ixgbe_fcoe_ddp ddp[IXGBE_FCOE_DDP_MAX];
unsigned char *extra_ddp_buffer;
dma_addr_t extra_ddp_buffer_dma;
u64 __percpu *pcpu_noddp;
u64 __percpu *pcpu_noddp_ext_buff;
unsigned long mode;
u8 tc;
u8 up;
u8 up_set;
};
#endif /* IXGBE_FCOE */
#endif /* _IXGBE_FCOE_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,105 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IXGBE_MBX_H_
#define _IXGBE_MBX_H_
#include "ixgbe_type.h"
#define IXGBE_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */
#define IXGBE_ERR_MBX -100
#define IXGBE_VFMAILBOX 0x002FC
#define IXGBE_VFMBMEM 0x00200
/* Define mailbox register bits */
#define IXGBE_VFMAILBOX_REQ 0x00000001 /* Request for PF Ready bit */
#define IXGBE_VFMAILBOX_ACK 0x00000002 /* Ack PF message received */
#define IXGBE_VFMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
#define IXGBE_VFMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
#define IXGBE_VFMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */
#define IXGBE_VFMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */
#define IXGBE_VFMAILBOX_RSTI 0x00000040 /* PF has reset indication */
#define IXGBE_VFMAILBOX_RSTD 0x00000080 /* PF has indicated reset done */
#define IXGBE_VFMAILBOX_R2C_BITS 0x000000B0 /* All read to clear bits */
#define IXGBE_PFMAILBOX_STS 0x00000001 /* Initiate message send to VF */
#define IXGBE_PFMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */
#define IXGBE_PFMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
#define IXGBE_PFMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
#define IXGBE_PFMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */
#define IXGBE_MBVFICR_VFREQ_MASK 0x0000FFFF /* bits for VF messages */
#define IXGBE_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */
#define IXGBE_MBVFICR_VFACK_MASK 0xFFFF0000 /* bits for VF acks */
#define IXGBE_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */
/* If it's a IXGBE_VF_* msg then it originates in the VF and is sent to the
* PF. The reverse is true if it is IXGBE_PF_*.
* Message ACK's are the value or'd with 0xF0000000
*/
#define IXGBE_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with
* this are the ACK */
#define IXGBE_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with
* this are the NACK */
#define IXGBE_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still
* clear to send requests */
#define IXGBE_VT_MSGINFO_SHIFT 16
/* bits 23:16 are used for extra info for certain messages */
#define IXGBE_VT_MSGINFO_MASK (0xFF << IXGBE_VT_MSGINFO_SHIFT)
#define IXGBE_VF_RESET 0x01 /* VF requests reset */
#define IXGBE_VF_SET_MAC_ADDR 0x02 /* VF requests PF to set MAC addr */
#define IXGBE_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */
#define IXGBE_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */
#define IXGBE_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */
#define IXGBE_VF_SET_MACVLAN 0x06 /* VF requests PF for unicast filter */
/* length of permanent address message returned from PF */
#define IXGBE_VF_PERMADDR_MSG_LEN 4
/* word in permanent address message with the current multicast type */
#define IXGBE_VF_MC_TYPE_WORD 3
#define IXGBE_PF_CONTROL_MSG 0x0100 /* PF control message */
#define IXGBE_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */
#define IXGBE_VF_MBX_INIT_DELAY 500 /* microseconds between retries */
s32 ixgbe_read_mbx(struct ixgbe_hw *, u32 *, u16, u16);
s32 ixgbe_write_mbx(struct ixgbe_hw *, u32 *, u16, u16);
s32 ixgbe_read_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16);
s32 ixgbe_write_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16);
s32 ixgbe_check_for_msg(struct ixgbe_hw *, u16);
s32 ixgbe_check_for_ack(struct ixgbe_hw *, u16);
s32 ixgbe_check_for_rst(struct ixgbe_hw *, u16);
void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw);
void ixgbe_init_mbx_params_vf(struct ixgbe_hw *);
void ixgbe_init_mbx_params_pf(struct ixgbe_hw *);
#endif /* _IXGBE_MBX_H_ */

View File

@ -0,0 +1,132 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
/* glue for the OS independent part of ixgbe
* includes register access macros
*/
#ifndef _IXGBE_OSDEP_H_
#define _IXGBE_OSDEP_H_
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/if_ether.h>
#include <linux/sched.h>
#include "kcompat.h"
#ifndef msleep
#define msleep(x) do { if (in_interrupt()) { \
/* Don't mdelay in interrupt context! */ \
BUG(); \
} else { \
msleep(x); \
} } while (0)
#endif
#undef ASSERT
#ifdef DBG
#define hw_dbg(hw, S, A...) printk(KERN_DEBUG S, ## A)
#else
#define hw_dbg(hw, S, A...) do {} while (0)
#endif
#define e_dev_info(format, arg...) \
dev_info(pci_dev_to_dev(adapter->pdev), format, ## arg)
#define e_dev_warn(format, arg...) \
dev_warn(pci_dev_to_dev(adapter->pdev), format, ## arg)
#define e_dev_err(format, arg...) \
dev_err(pci_dev_to_dev(adapter->pdev), format, ## arg)
#define e_dev_notice(format, arg...) \
dev_notice(pci_dev_to_dev(adapter->pdev), format, ## arg)
#define e_info(msglvl, format, arg...) \
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
#define e_err(msglvl, format, arg...) \
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
#define e_warn(msglvl, format, arg...) \
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
#define e_crit(msglvl, format, arg...) \
netif_crit(adapter, msglvl, adapter->netdev, format, ## arg)
#ifdef DBG
#define IXGBE_WRITE_REG(a, reg, value) do {\
switch (reg) { \
case IXGBE_EIMS: \
case IXGBE_EIMC: \
case IXGBE_EIAM: \
case IXGBE_EIAC: \
case IXGBE_EICR: \
case IXGBE_EICS: \
printk("%s: Reg - 0x%05X, value - 0x%08X\n", __func__, \
reg, (u32)(value)); \
default: \
break; \
} \
writel((value), ((a)->hw_addr + (reg))); \
} while (0)
#else
#define IXGBE_WRITE_REG(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
#endif
#define IXGBE_READ_REG(a, reg) readl((a)->hw_addr + (reg))
#define IXGBE_WRITE_REG_ARRAY(a, reg, offset, value) ( \
writel((value), ((a)->hw_addr + (reg) + ((offset) << 2))))
#define IXGBE_READ_REG_ARRAY(a, reg, offset) ( \
readl((a)->hw_addr + (reg) + ((offset) << 2)))
#ifndef writeq
#define writeq(val, addr) do { writel((u32) (val), addr); \
writel((u32) (val >> 32), (addr + 4)); \
} while (0);
#endif
#define IXGBE_WRITE_REG64(a, reg, value) writeq((value), ((a)->hw_addr + (reg)))
#define IXGBE_WRITE_FLUSH(a) IXGBE_READ_REG(a, IXGBE_STATUS)
struct ixgbe_hw;
extern u16 ixgbe_read_pci_cfg_word(struct ixgbe_hw *hw, u32 reg);
extern void ixgbe_write_pci_cfg_word(struct ixgbe_hw *hw, u32 reg, u16 value);
extern void ewarn(struct ixgbe_hw *hw, const char *str, u32 status);
#define IXGBE_READ_PCIE_WORD ixgbe_read_pci_cfg_word
#define IXGBE_WRITE_PCIE_WORD ixgbe_write_pci_cfg_word
#define IXGBE_EEPROM_GRANT_ATTEMPS 100
#define IXGBE_HTONL(_i) htonl(_i)
#define IXGBE_NTOHL(_i) ntohl(_i)
#define IXGBE_NTOHS(_i) ntohs(_i)
#define IXGBE_CPU_TO_LE32(_i) cpu_to_le32(_i)
#define IXGBE_LE32_TO_CPUS(_i) le32_to_cpus(_i)
#define EWARN(H, W, S) ewarn(H, W, S)
#endif /* _IXGBE_OSDEP_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,137 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IXGBE_PHY_H_
#define _IXGBE_PHY_H_
#include "ixgbe_type.h"
#define IXGBE_I2C_EEPROM_DEV_ADDR 0xA0
/* EEPROM byte offsets */
#define IXGBE_SFF_IDENTIFIER 0x0
#define IXGBE_SFF_IDENTIFIER_SFP 0x3
#define IXGBE_SFF_VENDOR_OUI_BYTE0 0x25
#define IXGBE_SFF_VENDOR_OUI_BYTE1 0x26
#define IXGBE_SFF_VENDOR_OUI_BYTE2 0x27
#define IXGBE_SFF_1GBE_COMP_CODES 0x6
#define IXGBE_SFF_10GBE_COMP_CODES 0x3
#define IXGBE_SFF_CABLE_TECHNOLOGY 0x8
#define IXGBE_SFF_CABLE_SPEC_COMP 0x3C
/* Bitmasks */
#define IXGBE_SFF_DA_PASSIVE_CABLE 0x4
#define IXGBE_SFF_DA_ACTIVE_CABLE 0x8
#define IXGBE_SFF_DA_SPEC_ACTIVE_LIMITING 0x4
#define IXGBE_SFF_1GBASESX_CAPABLE 0x1
#define IXGBE_SFF_1GBASELX_CAPABLE 0x2
#define IXGBE_SFF_1GBASET_CAPABLE 0x8
#define IXGBE_SFF_10GBASESR_CAPABLE 0x10
#define IXGBE_SFF_10GBASELR_CAPABLE 0x20
#define IXGBE_I2C_EEPROM_READ_MASK 0x100
#define IXGBE_I2C_EEPROM_STATUS_MASK 0x3
#define IXGBE_I2C_EEPROM_STATUS_NO_OPERATION 0x0
#define IXGBE_I2C_EEPROM_STATUS_PASS 0x1
#define IXGBE_I2C_EEPROM_STATUS_FAIL 0x2
#define IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS 0x3
/* Flow control defines */
#define IXGBE_TAF_SYM_PAUSE 0x400
#define IXGBE_TAF_ASM_PAUSE 0x800
/* Bit-shift macros */
#define IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT 24
#define IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT 16
#define IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT 8
/* Vendor OUIs: format of OUI is 0x[byte0][byte1][byte2][00] */
#define IXGBE_SFF_VENDOR_OUI_TYCO 0x00407600
#define IXGBE_SFF_VENDOR_OUI_FTL 0x00906500
#define IXGBE_SFF_VENDOR_OUI_AVAGO 0x00176A00
#define IXGBE_SFF_VENDOR_OUI_INTEL 0x001B2100
/* I2C SDA and SCL timing parameters for standard mode */
#define IXGBE_I2C_T_HD_STA 4
#define IXGBE_I2C_T_LOW 5
#define IXGBE_I2C_T_HIGH 4
#define IXGBE_I2C_T_SU_STA 5
#define IXGBE_I2C_T_HD_DATA 5
#define IXGBE_I2C_T_SU_DATA 1
#define IXGBE_I2C_T_RISE 1
#define IXGBE_I2C_T_FALL 1
#define IXGBE_I2C_T_SU_STO 4
#define IXGBE_I2C_T_BUF 5
#define IXGBE_TN_LASI_STATUS_REG 0x9005
#define IXGBE_TN_LASI_STATUS_TEMP_ALARM 0x0008
s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw);
bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr);
enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id);
s32 ixgbe_get_phy_id(struct ixgbe_hw *hw);
s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw);
s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw);
s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
u32 device_type, u16 *phy_data);
s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
u32 device_type, u16 phy_data);
s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw);
s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
bool *autoneg);
/* PHY specific */
s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
bool *link_up);
s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw);
s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
u16 *firmware_version);
s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
u16 *firmware_version);
s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw);
s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw);
s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw);
s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw);
s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
u16 *list_offset,
u16 *data_offset);
s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw);
s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 *data);
s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 data);
s32 ixgbe_read_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
u8 *eeprom_data);
s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
u8 eeprom_data);
void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw);
#endif /* _IXGBE_PHY_H_ */

View File

@ -0,0 +1,74 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IXGBE_SRIOV_H_
#define _IXGBE_SRIOV_H_
int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
int entries, u16 *hash_list, u32 vf);
void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter);
int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, u32 vf);
void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe);
void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf);
void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf);
void ixgbe_msg_task(struct ixgbe_adapter *adapter);
int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
int vf, unsigned char *mac_addr);
void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter);
void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter);
#ifdef IFLA_VF_MAX
int ixgbe_ndo_set_vf_mac(struct net_device *netdev, int queue, u8 *mac);
int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int queue, u16 vlan,
u8 qos);
int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate);
#ifdef HAVE_VF_SPOOFCHK_CONFIGURE
int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting);
#endif
int ixgbe_ndo_get_vf_config(struct net_device *netdev,
int vf, struct ifla_vf_info *ivi);
#endif
void ixgbe_disable_sriov(struct ixgbe_adapter *adapter);
#ifdef CONFIG_PCI_IOV
int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask);
void ixgbe_enable_sriov(struct ixgbe_adapter *adapter);
#endif
int ixgbe_check_vf_assignment(struct ixgbe_adapter *adapter);
#ifdef IFLA_VF_MAX
void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter);
#endif /* IFLA_VF_MAX */
void ixgbe_dump_registers(struct ixgbe_adapter *adapter);
/*
* These are defined in ixgbe_type.h on behalf of the VF driver
* but we need them here unwrapped for the PF driver.
*/
#define IXGBE_DEV_ID_82599_VF 0x10ED
#define IXGBE_DEV_ID_X540_VF 0x1515
#endif /* _IXGBE_SRIOV_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,929 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#include "ixgbe_x540.h"
#include "ixgbe_type.h"
#include "ixgbe_api.h"
#include "ixgbe_common.h"
#include "ixgbe_phy.h"
static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw);
static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw);
static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw);
static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw);
/**
* ixgbe_init_ops_X540 - Inits func ptrs and MAC type
* @hw: pointer to hardware structure
*
* Initialize the function pointers and assign the MAC type for X540.
* Does not touch the hardware.
**/
s32 ixgbe_init_ops_X540(struct ixgbe_hw *hw)
{
struct ixgbe_mac_info *mac = &hw->mac;
struct ixgbe_phy_info *phy = &hw->phy;
struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
s32 ret_val;
ret_val = ixgbe_init_phy_ops_generic(hw);
ret_val = ixgbe_init_ops_generic(hw);
/* EEPROM */
eeprom->ops.init_params = &ixgbe_init_eeprom_params_X540;
eeprom->ops.read = &ixgbe_read_eerd_X540;
eeprom->ops.read_buffer = &ixgbe_read_eerd_buffer_X540;
eeprom->ops.write = &ixgbe_write_eewr_X540;
eeprom->ops.write_buffer = &ixgbe_write_eewr_buffer_X540;
eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_X540;
eeprom->ops.validate_checksum = &ixgbe_validate_eeprom_checksum_X540;
eeprom->ops.calc_checksum = &ixgbe_calc_eeprom_checksum_X540;
/* PHY */
phy->ops.init = &ixgbe_init_phy_ops_generic;
phy->ops.reset = NULL;
/* MAC */
mac->ops.reset_hw = &ixgbe_reset_hw_X540;
mac->ops.get_media_type = &ixgbe_get_media_type_X540;
mac->ops.get_supported_physical_layer =
&ixgbe_get_supported_physical_layer_X540;
mac->ops.read_analog_reg8 = NULL;
mac->ops.write_analog_reg8 = NULL;
mac->ops.start_hw = &ixgbe_start_hw_X540;
mac->ops.get_san_mac_addr = &ixgbe_get_san_mac_addr_generic;
mac->ops.set_san_mac_addr = &ixgbe_set_san_mac_addr_generic;
mac->ops.get_device_caps = &ixgbe_get_device_caps_generic;
mac->ops.get_wwn_prefix = &ixgbe_get_wwn_prefix_generic;
mac->ops.get_fcoe_boot_status = &ixgbe_get_fcoe_boot_status_generic;
mac->ops.acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540;
mac->ops.release_swfw_sync = &ixgbe_release_swfw_sync_X540;
mac->ops.disable_sec_rx_path = &ixgbe_disable_sec_rx_path_generic;
mac->ops.enable_sec_rx_path = &ixgbe_enable_sec_rx_path_generic;
/* RAR, Multicast, VLAN */
mac->ops.set_vmdq = &ixgbe_set_vmdq_generic;
mac->ops.set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic;
mac->ops.clear_vmdq = &ixgbe_clear_vmdq_generic;
mac->ops.insert_mac_addr = &ixgbe_insert_mac_addr_generic;
mac->rar_highwater = 1;
mac->ops.set_vfta = &ixgbe_set_vfta_generic;
mac->ops.set_vlvf = &ixgbe_set_vlvf_generic;
mac->ops.clear_vfta = &ixgbe_clear_vfta_generic;
mac->ops.init_uta_tables = &ixgbe_init_uta_tables_generic;
mac->ops.set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing;
mac->ops.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing;
/* Link */
mac->ops.get_link_capabilities =
&ixgbe_get_copper_link_capabilities_generic;
mac->ops.setup_link = &ixgbe_setup_mac_link_X540;
mac->ops.setup_rxpba = &ixgbe_set_rxpba_generic;
mac->ops.check_link = &ixgbe_check_mac_link_generic;
mac->mcft_size = 128;
mac->vft_size = 128;
mac->num_rar_entries = 128;
mac->rx_pb_size = 384;
mac->max_tx_queues = 128;
mac->max_rx_queues = 128;
mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw);
/*
* FWSM register
* ARC supported; valid only if manageability features are
* enabled.
*/
mac->arc_subsystem_valid = (IXGBE_READ_REG(hw, IXGBE_FWSM) &
IXGBE_FWSM_MODE_MASK) ? true : false;
//hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
/* LEDs */
mac->ops.blink_led_start = ixgbe_blink_led_start_X540;
mac->ops.blink_led_stop = ixgbe_blink_led_stop_X540;
/* Manageability interface */
mac->ops.set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic;
return ret_val;
}
/**
* ixgbe_get_link_capabilities_X540 - Determines link capabilities
* @hw: pointer to hardware structure
* @speed: pointer to link speed
* @autoneg: true when autoneg or autotry is enabled
*
* Determines the link capabilities by reading the AUTOC register.
**/
s32 ixgbe_get_link_capabilities_X540(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
bool *autoneg)
{
ixgbe_get_copper_link_capabilities_generic(hw, speed, autoneg);
return 0;
}
/**
* ixgbe_get_media_type_X540 - Get media type
* @hw: pointer to hardware structure
*
* Returns the media type (fiber, copper, backplane)
**/
enum ixgbe_media_type ixgbe_get_media_type_X540(struct ixgbe_hw *hw)
{
return ixgbe_media_type_copper;
}
/**
* ixgbe_setup_mac_link_X540 - Sets the auto advertised capabilities
* @hw: pointer to hardware structure
* @speed: new link speed
* @autoneg: true if autonegotiation enabled
* @autoneg_wait_to_complete: true when waiting for completion is needed
**/
s32 ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw,
ixgbe_link_speed speed, bool autoneg,
bool autoneg_wait_to_complete)
{
return hw->phy.ops.setup_link_speed(hw, speed, autoneg,
autoneg_wait_to_complete);
}
/**
* ixgbe_reset_hw_X540 - Perform hardware reset
* @hw: pointer to hardware structure
*
* Resets the hardware by resetting the transmit and receive units, masks
* and clears all interrupts, and perform a reset.
**/
s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
{
s32 status;
u32 ctrl, i;
/* Call adapter stop to disable tx/rx and clear interrupts */
status = hw->mac.ops.stop_adapter(hw);
if (status != 0)
goto reset_hw_out;
/* flush pending Tx transactions */
ixgbe_clear_tx_pending(hw);
mac_reset_top:
ctrl = IXGBE_CTRL_RST;
ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
IXGBE_WRITE_FLUSH(hw);
/* Poll for reset bit to self-clear indicating reset is complete */
for (i = 0; i < 10; i++) {
udelay(1);
ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
if (!(ctrl & IXGBE_CTRL_RST_MASK))
break;
}
if (ctrl & IXGBE_CTRL_RST_MASK) {
status = IXGBE_ERR_RESET_FAILED;
hw_dbg(hw, "Reset polling failed to complete.\n");
}
msleep(100);
/*
* Double resets are required for recovery from certain error
* conditions. Between resets, it is necessary to stall to allow time
* for any pending HW events to complete.
*/
if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
goto mac_reset_top;
}
/* Set the Rx packet buffer size. */
IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 384 << IXGBE_RXPBSIZE_SHIFT);
/* Store the permanent mac address */
hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
/*
* Store MAC address from RAR0, clear receive address registers, and
* clear the multicast table. Also reset num_rar_entries to 128,
* since we modify this value when programming the SAN MAC address.
*/
hw->mac.num_rar_entries = 128;
hw->mac.ops.init_rx_addrs(hw);
/* Store the permanent SAN mac address */
hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
/* Add the SAN MAC address to the RAR only if it's a valid address */
if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
hw->mac.san_addr, 0, IXGBE_RAH_AV);
/* Save the SAN MAC RAR index */
hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1;
/* Reserve the last RAR for the SAN MAC address */
hw->mac.num_rar_entries--;
}
/* Store the alternative WWNN/WWPN prefix */
hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
&hw->mac.wwpn_prefix);
reset_hw_out:
return status;
}
/**
* ixgbe_start_hw_X540 - Prepare hardware for Tx/Rx
* @hw: pointer to hardware structure
*
* Starts the hardware using the generic start_hw function
* and the generation start_hw function.
* Then performs revision-specific operations, if any.
**/
s32 ixgbe_start_hw_X540(struct ixgbe_hw *hw)
{
s32 ret_val = 0;
ret_val = ixgbe_start_hw_generic(hw);
if (ret_val != 0)
goto out;
ret_val = ixgbe_start_hw_gen2(hw);
out:
return ret_val;
}
/**
* ixgbe_get_supported_physical_layer_X540 - Returns physical layer type
* @hw: pointer to hardware structure
*
* Determines physical layer capabilities of the current configuration.
**/
u32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw)
{
u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
u16 ext_ability = 0;
hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY)
physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
return physical_layer;
}
/**
* ixgbe_init_eeprom_params_X540 - Initialize EEPROM params
* @hw: pointer to hardware structure
*
* Initializes the EEPROM parameters ixgbe_eeprom_info within the
* ixgbe_hw struct in order to set up EEPROM access.
**/
s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw)
{
struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
u32 eec;
u16 eeprom_size;
if (eeprom->type == ixgbe_eeprom_uninitialized) {
eeprom->semaphore_delay = 10;
eeprom->type = ixgbe_flash;
eec = IXGBE_READ_REG(hw, IXGBE_EEC);
eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
IXGBE_EEC_SIZE_SHIFT);
eeprom->word_size = 1 << (eeprom_size +
IXGBE_EEPROM_WORD_SIZE_SHIFT);
hw_dbg(hw, "Eeprom params: type = %d, size = %d\n",
eeprom->type, eeprom->word_size);
}
return 0;
}
/**
* ixgbe_read_eerd_X540- Read EEPROM word using EERD
* @hw: pointer to hardware structure
* @offset: offset of word in the EEPROM to read
* @data: word read from the EEPROM
*
* Reads a 16 bit word from the EEPROM using the EERD register.
**/
s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data)
{
s32 status = 0;
if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
0)
status = ixgbe_read_eerd_generic(hw, offset, data);
else
status = IXGBE_ERR_SWFW_SYNC;
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
return status;
}
/**
* ixgbe_read_eerd_buffer_X540- Read EEPROM word(s) using EERD
* @hw: pointer to hardware structure
* @offset: offset of word in the EEPROM to read
* @words: number of words
* @data: word(s) read from the EEPROM
*
* Reads a 16 bit word(s) from the EEPROM using the EERD register.
**/
s32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw,
u16 offset, u16 words, u16 *data)
{
s32 status = 0;
if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
0)
status = ixgbe_read_eerd_buffer_generic(hw, offset,
words, data);
else
status = IXGBE_ERR_SWFW_SYNC;
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
return status;
}
/**
* ixgbe_write_eewr_X540 - Write EEPROM word using EEWR
* @hw: pointer to hardware structure
* @offset: offset of word in the EEPROM to write
* @data: word write to the EEPROM
*
* Write a 16 bit word to the EEPROM using the EEWR register.
**/
s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data)
{
s32 status = 0;
if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
0)
status = ixgbe_write_eewr_generic(hw, offset, data);
else
status = IXGBE_ERR_SWFW_SYNC;
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
return status;
}
/**
* ixgbe_write_eewr_buffer_X540 - Write EEPROM word(s) using EEWR
* @hw: pointer to hardware structure
* @offset: offset of word in the EEPROM to write
* @words: number of words
* @data: word(s) write to the EEPROM
*
* Write a 16 bit word(s) to the EEPROM using the EEWR register.
**/
s32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw,
u16 offset, u16 words, u16 *data)
{
s32 status = 0;
if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
0)
status = ixgbe_write_eewr_buffer_generic(hw, offset,
words, data);
else
status = IXGBE_ERR_SWFW_SYNC;
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
return status;
}
/**
* ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum
*
* This function does not use synchronization for EERD and EEWR. It can
* be used internally by function which utilize ixgbe_acquire_swfw_sync_X540.
*
* @hw: pointer to hardware structure
**/
u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
{
u16 i;
u16 j;
u16 checksum = 0;
u16 length = 0;
u16 pointer = 0;
u16 word = 0;
/*
* Do not use hw->eeprom.ops.read because we do not want to take
* the synchronization semaphores here. Instead use
* ixgbe_read_eerd_generic
*/
/* Include 0x0-0x3F in the checksum */
for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
if (ixgbe_read_eerd_generic(hw, i, &word) != 0) {
hw_dbg(hw, "EEPROM read failed\n");
break;
}
checksum += word;
}
/*
* Include all data from pointers 0x3, 0x6-0xE. This excludes the
* FW, PHY module, and PCIe Expansion/Option ROM pointers.
*/
for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
continue;
if (ixgbe_read_eerd_generic(hw, i, &pointer) != 0) {
hw_dbg(hw, "EEPROM read failed\n");
break;
}
/* Skip pointer section if the pointer is invalid. */
if (pointer == 0xFFFF || pointer == 0 ||
pointer >= hw->eeprom.word_size)
continue;
if (ixgbe_read_eerd_generic(hw, pointer, &length) !=
0) {
hw_dbg(hw, "EEPROM read failed\n");
break;
}
/* Skip pointer section if length is invalid. */
if (length == 0xFFFF || length == 0 ||
(pointer + length) >= hw->eeprom.word_size)
continue;
for (j = pointer+1; j <= pointer+length; j++) {
if (ixgbe_read_eerd_generic(hw, j, &word) !=
0) {
hw_dbg(hw, "EEPROM read failed\n");
break;
}
checksum += word;
}
}
checksum = (u16)IXGBE_EEPROM_SUM - checksum;
return checksum;
}
/**
* ixgbe_validate_eeprom_checksum_X540 - Validate EEPROM checksum
* @hw: pointer to hardware structure
* @checksum_val: calculated checksum
*
* Performs checksum calculation and validates the EEPROM checksum. If the
* caller does not need checksum_val, the value can be NULL.
**/
s32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw,
u16 *checksum_val)
{
s32 status;
u16 checksum;
u16 read_checksum = 0;
/*
* Read the first word from the EEPROM. If this times out or fails, do
* not continue or we could be in for a very long wait while every
* EEPROM read fails
*/
status = hw->eeprom.ops.read(hw, 0, &checksum);
if (status != 0) {
hw_dbg(hw, "EEPROM read failed\n");
goto out;
}
if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
0) {
checksum = hw->eeprom.ops.calc_checksum(hw);
/*
* Do not use hw->eeprom.ops.read because we do not want to take
* the synchronization semaphores twice here.
*/
ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM,
&read_checksum);
/*
* Verify read checksum from EEPROM is the same as
* calculated checksum
*/
if (read_checksum != checksum)
status = IXGBE_ERR_EEPROM_CHECKSUM;
/* If the user cares, return the calculated checksum */
if (checksum_val)
*checksum_val = checksum;
} else {
status = IXGBE_ERR_SWFW_SYNC;
}
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
out:
return status;
}
/**
* ixgbe_update_eeprom_checksum_X540 - Updates the EEPROM checksum and flash
* @hw: pointer to hardware structure
*
* After writing EEPROM to shadow RAM using EEWR register, software calculates
* checksum and updates the EEPROM and instructs the hardware to update
* the flash.
**/
s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw)
{
s32 status;
u16 checksum;
/*
* Read the first word from the EEPROM. If this times out or fails, do
* not continue or we could be in for a very long wait while every
* EEPROM read fails
*/
status = hw->eeprom.ops.read(hw, 0, &checksum);
if (status != 0)
hw_dbg(hw, "EEPROM read failed\n");
if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
0) {
checksum = hw->eeprom.ops.calc_checksum(hw);
/*
* Do not use hw->eeprom.ops.write because we do not want to
* take the synchronization semaphores twice here.
*/
status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM,
checksum);
if (status == 0)
status = ixgbe_update_flash_X540(hw);
else
status = IXGBE_ERR_SWFW_SYNC;
}
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
return status;
}
/**
* ixgbe_update_flash_X540 - Instruct HW to copy EEPROM to Flash device
* @hw: pointer to hardware structure
*
* Set FLUP (bit 23) of the EEC register to instruct Hardware to copy
* EEPROM from shadow RAM to the flash device.
**/
static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw)
{
u32 flup;
s32 status = IXGBE_ERR_EEPROM;
status = ixgbe_poll_flash_update_done_X540(hw);
if (status == IXGBE_ERR_EEPROM) {
hw_dbg(hw, "Flash update time out\n");
goto out;
}
flup = IXGBE_READ_REG(hw, IXGBE_EEC) | IXGBE_EEC_FLUP;
IXGBE_WRITE_REG(hw, IXGBE_EEC, flup);
status = ixgbe_poll_flash_update_done_X540(hw);
if (status == 0)
hw_dbg(hw, "Flash update complete\n");
else
hw_dbg(hw, "Flash update time out\n");
if (hw->revision_id == 0) {
flup = IXGBE_READ_REG(hw, IXGBE_EEC);
if (flup & IXGBE_EEC_SEC1VAL) {
flup |= IXGBE_EEC_FLUP;
IXGBE_WRITE_REG(hw, IXGBE_EEC, flup);
}
status = ixgbe_poll_flash_update_done_X540(hw);
if (status == 0)
hw_dbg(hw, "Flash update complete\n");
else
hw_dbg(hw, "Flash update time out\n");
}
out:
return status;
}
/**
* ixgbe_poll_flash_update_done_X540 - Poll flash update status
* @hw: pointer to hardware structure
*
* Polls the FLUDONE (bit 26) of the EEC Register to determine when the
* flash update is done.
**/
static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw)
{
u32 i;
u32 reg;
s32 status = IXGBE_ERR_EEPROM;
for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) {
reg = IXGBE_READ_REG(hw, IXGBE_EEC);
if (reg & IXGBE_EEC_FLUDONE) {
status = 0;
break;
}
udelay(5);
}
return status;
}
/**
* ixgbe_acquire_swfw_sync_X540 - Acquire SWFW semaphore
* @hw: pointer to hardware structure
* @mask: Mask to specify which semaphore to acquire
*
* Acquires the SWFW semaphore thought the SW_FW_SYNC register for
* the specified function (CSR, PHY0, PHY1, NVM, Flash)
**/
s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask)
{
u32 swfw_sync;
u32 swmask = mask;
u32 fwmask = mask << 5;
u32 hwmask = 0;
u32 timeout = 200;
u32 i;
s32 ret_val = 0;
if (swmask == IXGBE_GSSR_EEP_SM)
hwmask = IXGBE_GSSR_FLASH_SM;
/* SW only mask doesn't have FW bit pair */
if (swmask == IXGBE_GSSR_SW_MNG_SM)
fwmask = 0;
for (i = 0; i < timeout; i++) {
/*
* SW NVM semaphore bit is used for access to all
* SW_FW_SYNC bits (not just NVM)
*/
if (ixgbe_get_swfw_sync_semaphore(hw)) {
ret_val = IXGBE_ERR_SWFW_SYNC;
goto out;
}
swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
if (!(swfw_sync & (fwmask | swmask | hwmask))) {
swfw_sync |= swmask;
IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
ixgbe_release_swfw_sync_semaphore(hw);
msleep(5);
goto out;
} else {
/*
* Firmware currently using resource (fwmask), hardware
* currently using resource (hwmask), or other software
* thread currently using resource (swmask)
*/
ixgbe_release_swfw_sync_semaphore(hw);
msleep(5);
}
}
/* Failed to get SW only semaphore */
if (swmask == IXGBE_GSSR_SW_MNG_SM) {
ret_val = IXGBE_ERR_SWFW_SYNC;
goto out;
}
/* If the resource is not released by the FW/HW the SW can assume that
* the FW/HW malfunctions. In that case the SW should sets the SW bit(s)
* of the requested resource(s) while ignoring the corresponding FW/HW
* bits in the SW_FW_SYNC register.
*/
swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
if (swfw_sync & (fwmask | hwmask)) {
if (ixgbe_get_swfw_sync_semaphore(hw)) {
ret_val = IXGBE_ERR_SWFW_SYNC;
goto out;
}
swfw_sync |= swmask;
IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
ixgbe_release_swfw_sync_semaphore(hw);
msleep(5);
}
out:
return ret_val;
}
/**
* ixgbe_release_swfw_sync_X540 - Release SWFW semaphore
* @hw: pointer to hardware structure
* @mask: Mask to specify which semaphore to release
*
* Releases the SWFW semaphore through the SW_FW_SYNC register
* for the specified function (CSR, PHY0, PHY1, EVM, Flash)
**/
void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask)
{
u32 swfw_sync;
u32 swmask = mask;
ixgbe_get_swfw_sync_semaphore(hw);
swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
swfw_sync &= ~swmask;
IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
ixgbe_release_swfw_sync_semaphore(hw);
msleep(5);
}
/**
* ixgbe_get_nvm_semaphore - Get hardware semaphore
* @hw: pointer to hardware structure
*
* Sets the hardware semaphores so SW/FW can gain control of shared resources
**/
static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw)
{
s32 status = IXGBE_ERR_EEPROM;
u32 timeout = 2000;
u32 i;
u32 swsm;
/* Get SMBI software semaphore between device drivers first */
for (i = 0; i < timeout; i++) {
/*
* If the SMBI bit is 0 when we read it, then the bit will be
* set and we have the semaphore
*/
swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
if (!(swsm & IXGBE_SWSM_SMBI)) {
status = 0;
break;
}
udelay(50);
}
/* Now get the semaphore between SW/FW through the REGSMP bit */
if (status == 0) {
for (i = 0; i < timeout; i++) {
swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
if (!(swsm & IXGBE_SWFW_REGSMP))
break;
udelay(50);
}
/*
* Release semaphores and return error if SW NVM semaphore
* was not granted because we don't have access to the EEPROM
*/
if (i >= timeout) {
hw_dbg(hw, "REGSMP Software NVM semaphore not "
"granted.\n");
ixgbe_release_swfw_sync_semaphore(hw);
status = IXGBE_ERR_EEPROM;
}
} else {
hw_dbg(hw, "Software semaphore SMBI between device drivers "
"not granted.\n");
}
return status;
}
/**
* ixgbe_release_nvm_semaphore - Release hardware semaphore
* @hw: pointer to hardware structure
*
* This function clears hardware semaphore bits.
**/
static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw)
{
u32 swsm;
/* Release both semaphores by writing 0 to the bits REGSMP and SMBI */
swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
swsm &= ~IXGBE_SWSM_SMBI;
IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
swsm &= ~IXGBE_SWFW_REGSMP;
IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swsm);
IXGBE_WRITE_FLUSH(hw);
}
/**
* ixgbe_blink_led_start_X540 - Blink LED based on index.
* @hw: pointer to hardware structure
* @index: led number to blink
*
* Devices that implement the version 2 interface:
* X540
**/
s32 ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, u32 index)
{
u32 macc_reg;
u32 ledctl_reg;
ixgbe_link_speed speed;
bool link_up;
/*
* Link should be up in order for the blink bit in the LED control
* register to work. Force link and speed in the MAC if link is down.
* This will be reversed when we stop the blinking.
*/
hw->mac.ops.check_link(hw, &speed, &link_up, false);
if (link_up == false) {
macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC);
macc_reg |= IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS;
IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg);
}
/* Set the LED to LINK_UP + BLINK. */
ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
ledctl_reg &= ~IXGBE_LED_MODE_MASK(index);
ledctl_reg |= IXGBE_LED_BLINK(index);
IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg);
IXGBE_WRITE_FLUSH(hw);
return 0;
}
/**
* ixgbe_blink_led_stop_X540 - Stop blinking LED based on index.
* @hw: pointer to hardware structure
* @index: led number to stop blinking
*
* Devices that implement the version 2 interface:
* X540
**/
s32 ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, u32 index)
{
u32 macc_reg;
u32 ledctl_reg;
/* Restore the LED to its default value. */
ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
ledctl_reg &= ~IXGBE_LED_MODE_MASK(index);
ledctl_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
ledctl_reg &= ~IXGBE_LED_BLINK(index);
IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg);
/* Unforce link and speed in the MAC. */
macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC);
macc_reg &= ~(IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS);
IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg);
IXGBE_WRITE_FLUSH(hw);
return 0;
}

View File

@ -0,0 +1,58 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IXGBE_X540_H_
#define _IXGBE_X540_H_
#include "ixgbe_type.h"
s32 ixgbe_get_link_capabilities_X540(struct ixgbe_hw *hw,
ixgbe_link_speed *speed, bool *autoneg);
enum ixgbe_media_type ixgbe_get_media_type_X540(struct ixgbe_hw *hw);
s32 ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw, ixgbe_link_speed speed,
bool autoneg, bool link_up_wait_to_complete);
s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw);
s32 ixgbe_start_hw_X540(struct ixgbe_hw *hw);
u32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw);
s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw);
s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data);
s32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw, u16 offset, u16 words,
u16 *data);
s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data);
s32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw, u16 offset, u16 words,
u16 *data);
s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw);
s32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw, u16 *checksum_val);
u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw);
s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask);
void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask);
s32 ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, u32 index);
#endif /* _IXGBE_X540_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
/*-
* GPL LICENSE SUMMARY
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* Contact Information:
* Intel Corporation
*
*/
#ifndef _KNI_DEV_H_
#define _KNI_DEV_H_
#include <linux/if.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/netdevice.h>
#include <linux/spinlock.h>
#define KNI_KTHREAD_RESCHEDULE_INTERVAL 10 /* us */
/**
* A structure describing the private information for a kni device.
*/
struct kni_dev {
struct net_device_stats stats;
int status;
int idx;
/* wait queue for req/resp */
wait_queue_head_t wq;
struct mutex sync_lock;
/* PCI device id */
uint16_t device_id;
/* kni device */
struct net_device *net_dev;
struct net_device *lad_dev;
struct pci_dev *pci_dev;
/* queue for packets to be sent out */
void *tx_q;
/* queue for the packets received */
void *rx_q;
/* queue for the allocated mbufs those can be used to save sk buffs */
void *alloc_q;
/* free queue for the mbufs to be freed */
void *free_q;
/* request queue */
void *req_q;
/* response queue */
void *resp_q;
void * sync_kva;
void *sync_va;
void *mbuf_kva;
void *mbuf_va;
/* mbuf size */
unsigned mbuf_size;
/* synchro for request processing */
unsigned long synchro;
};
#define DEBUG_KNI
#define KNI_ERR(args...) printk(KERN_DEBUG "KNI: Error: " args)
#define KNI_PRINT(args...) printk(KERN_DEBUG "KNI: " args)
#ifdef DEBUG_KNI
#define KNI_DBG(args...) printk(KERN_DEBUG "KNI: " args)
#else
#define KNI_DBG(args...)
#endif
#endif

View File

@ -0,0 +1,218 @@
/*-
* GPL LICENSE SUMMARY
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* Contact Information:
* Intel Corporation
*
*/
#include <linux/device.h>
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include "kni_dev.h"
static int
kni_check_if_running(struct net_device *dev)
{
struct kni_dev *priv = netdev_priv(dev);
if (priv->lad_dev)
return 0;
else
return -EOPNOTSUPP;
}
static void
kni_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
struct kni_dev *priv = netdev_priv(dev);
priv->lad_dev->ethtool_ops->get_drvinfo(priv->lad_dev, info);
}
static int
kni_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
struct kni_dev *priv = netdev_priv(dev);
return priv->lad_dev->ethtool_ops->get_settings(priv->lad_dev, ecmd);
}
static int
kni_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
struct kni_dev *priv = netdev_priv(dev);
return priv->lad_dev->ethtool_ops->set_settings(priv->lad_dev, ecmd);
}
static void
kni_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct kni_dev *priv = netdev_priv(dev);
priv->lad_dev->ethtool_ops->get_wol(priv->lad_dev, wol);
}
static int
kni_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct kni_dev *priv = netdev_priv(dev);
return priv->lad_dev->ethtool_ops->set_wol(priv->lad_dev, wol);
}
static int
kni_nway_reset(struct net_device *dev)
{
struct kni_dev *priv = netdev_priv(dev);
return priv->lad_dev->ethtool_ops->nway_reset(priv->lad_dev);
}
static int
kni_get_eeprom_len(struct net_device *dev)
{
struct kni_dev *priv = netdev_priv(dev);
return priv->lad_dev->ethtool_ops->get_eeprom_len(priv->lad_dev);
}
static int
kni_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
u8 *bytes)
{
struct kni_dev *priv = netdev_priv(dev);
return priv->lad_dev->ethtool_ops->get_eeprom(priv->lad_dev, eeprom,
bytes);
}
static int
kni_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
u8 *bytes)
{
struct kni_dev *priv = netdev_priv(dev);
return priv->lad_dev->ethtool_ops->set_eeprom(priv->lad_dev, eeprom,
bytes);
}
static void
kni_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
{
struct kni_dev *priv = netdev_priv(dev);
priv->lad_dev->ethtool_ops->get_ringparam(priv->lad_dev, ring);
}
static int
kni_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
{
struct kni_dev *priv = netdev_priv(dev);
return priv->lad_dev->ethtool_ops->set_ringparam(priv->lad_dev, ring);
}
static void
kni_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *pause)
{
struct kni_dev *priv = netdev_priv(dev);
priv->lad_dev->ethtool_ops->get_pauseparam(priv->lad_dev, pause);
}
static int
kni_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *pause)
{
struct kni_dev *priv = netdev_priv(dev);
return priv->lad_dev->ethtool_ops->set_pauseparam(priv->lad_dev,
pause);
}
static u32
kni_get_msglevel(struct net_device *dev)
{
struct kni_dev *priv = netdev_priv(dev);
return priv->lad_dev->ethtool_ops->get_msglevel(priv->lad_dev);
}
static void
kni_set_msglevel(struct net_device *dev, u32 data)
{
struct kni_dev *priv = netdev_priv(dev);
priv->lad_dev->ethtool_ops->set_msglevel(priv->lad_dev, data);
}
static int
kni_get_regs_len(struct net_device *dev)
{
struct kni_dev *priv = netdev_priv(dev);
return priv->lad_dev->ethtool_ops->get_regs_len(priv->lad_dev);
}
static void
kni_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
{
struct kni_dev *priv = netdev_priv(dev);
priv->lad_dev->ethtool_ops->get_regs(priv->lad_dev, regs, p);
}
static void
kni_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{
struct kni_dev *priv = netdev_priv(dev);
priv->lad_dev->ethtool_ops->get_strings(priv->lad_dev, stringset,
data);
}
static int
kni_get_sset_count(struct net_device *dev, int sset)
{
struct kni_dev *priv = netdev_priv(dev);
return priv->lad_dev->ethtool_ops->get_sset_count(priv->lad_dev, sset);
}
static void
kni_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats,
u64 *data)
{
struct kni_dev *priv = netdev_priv(dev);
priv->lad_dev->ethtool_ops->get_ethtool_stats(priv->lad_dev, stats,
data);
}
struct ethtool_ops kni_ethtool_ops = {
.begin = kni_check_if_running,
.get_drvinfo = kni_get_drvinfo,
.get_settings = kni_get_settings,
.set_settings = kni_set_settings,
.get_regs_len = kni_get_regs_len,
.get_regs = kni_get_regs,
.get_wol = kni_get_wol,
.set_wol = kni_set_wol,
.nway_reset = kni_nway_reset,
.get_link = ethtool_op_get_link,
.get_eeprom_len = kni_get_eeprom_len,
.get_eeprom = kni_get_eeprom,
.set_eeprom = kni_set_eeprom,
.get_ringparam = kni_get_ringparam,
.set_ringparam = kni_set_ringparam,
.get_pauseparam = kni_get_pauseparam,
.set_pauseparam = kni_set_pauseparam,
.get_msglevel = kni_get_msglevel,
.set_msglevel = kni_set_msglevel,
.get_strings = kni_get_strings,
.get_sset_count = kni_get_sset_count,
.get_ethtool_stats = kni_get_ethtool_stats,
};
void
kni_set_ethtool_ops(struct net_device *netdev)
{
SET_ETHTOOL_OPS(netdev, &kni_ethtool_ops);
}

View File

@ -0,0 +1,433 @@
/*-
* GPL LICENSE SUMMARY
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* Contact Information:
* Intel Corporation
*
*/
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/kthread.h>
#include <exec-env/rte_kni_common.h>
#include "kni_dev.h"
#include <rte_config.h>
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Intel Corporation");
MODULE_DESCRIPTION("Kernel Module for managing kni devices");
#define KNI_RX_LOOP_NUM 1000
#define KNI_MAX_DEVICES 32
extern void kni_net_rx(struct kni_dev *kni);
extern void kni_net_init(struct net_device *dev);
extern void kni_net_config_lo_mode(char *lo_str);
extern void kni_net_poll_resp(struct kni_dev *kni);
extern void kni_set_ethtool_ops(struct net_device *netdev);
extern int ixgbe_kni_probe(struct pci_dev *pdev, struct net_device **lad_dev);
extern void ixgbe_kni_remove(struct pci_dev *pdev);
extern int igb_kni_probe(struct pci_dev *pdev, struct net_device **lad_dev);
extern void igb_kni_remove(struct pci_dev *pdev);
static int kni_open(struct inode *inode, struct file *file);
static int kni_release(struct inode *inode, struct file *file);
static int kni_ioctl(struct inode *inode, unsigned int ioctl_num,
unsigned long ioctl_param);
static int kni_compat_ioctl(struct inode *inode, unsigned int ioctl_num,
unsigned long ioctl_param);
/* kni kernel thread for rx */
static int kni_thread(void *unused);
static struct file_operations kni_fops = {
.owner = THIS_MODULE,
.open = kni_open,
.release = kni_release,
.unlocked_ioctl = (void *)kni_ioctl,
.compat_ioctl = (void *)kni_compat_ioctl,
};
static struct miscdevice kni_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = KNI_DEVICE,
.fops = &kni_fops,
};
/* Array of the kni supported PCI device ids */
static struct pci_device_id kni_pci_ids[] = {
/* EM and IGB to be supported in future */
//#define RTE_PCI_DEV_ID_DECL_EM(vend, dev) {PCI_DEVICE(vend, dev)},
#define RTE_PCI_DEV_ID_DECL_IGB(vend, dev) {PCI_DEVICE(vend, dev)},
#define RTE_PCI_DEV_ID_DECL_IXGBE(vend, dev) {PCI_DEVICE(vend, dev)},
#include <rte_pci_dev_ids.h>
{ 0, },
};
MODULE_DEVICE_TABLE(pci, kni_pci_ids);
/* loopback mode */
static char *lo_mode = NULL;
static struct kni_dev *kni_devs[KNI_MAX_DEVICES];
static volatile int num_devs; /* number of kni devices */
#define KNI_DEV_IN_USE_BIT_NUM 0 /* Bit number for device in use */
static volatile unsigned long device_in_use; /* device in use flag */
static struct task_struct *kni_kthread;
static int __init
kni_init(void)
{
KNI_PRINT("######## DPDK kni module loading ########\n");
if (misc_register(&kni_misc) != 0) {
KNI_ERR("Misc registration failed\n");
return 1;
}
/* Clear the bit of device in use */
clear_bit(KNI_DEV_IN_USE_BIT_NUM, &device_in_use);
/* Configure the lo mode according to the input parameter */
kni_net_config_lo_mode(lo_mode);
KNI_PRINT("######## DPDK kni module loaded ########\n");
return 0;
}
static void __exit
kni_exit(void)
{
misc_deregister(&kni_misc);
KNI_PRINT("####### DPDK kni module unloaded #######\n");
}
static int
kni_open(struct inode *inode, struct file *file)
{
/* kni device can be opened by one user only, test and set bit */
if (test_and_set_bit(KNI_DEV_IN_USE_BIT_NUM, &device_in_use))
return -EBUSY;
memset(kni_devs, 0, sizeof(kni_devs));
num_devs = 0;
/* Create kernel thread for RX */
kni_kthread = kthread_run(kni_thread, NULL, "kni_thread");
if (IS_ERR(kni_kthread)) {
KNI_ERR("Unable to create kernel threaed\n");
return PTR_ERR(kni_kthread);
}
KNI_PRINT("/dev/kni opened\n");
return 0;
}
static int
kni_release(struct inode *inode, struct file *file)
{
int i;
KNI_PRINT("Stopping KNI thread...");
/* Stop kernel thread */
kthread_stop(kni_kthread);
kni_kthread = NULL;
for (i = 0; i < KNI_MAX_DEVICES; i++) {
if (kni_devs[i] != NULL) {
/* Call the remove part to restore pci dev */
switch (kni_devs[i]->device_id) {
#define RTE_PCI_DEV_ID_DECL_IGB(vend, dev) case (dev):
#include <rte_pci_dev_ids.h>
igb_kni_remove(kni_devs[i]->pci_dev);
break;
#define RTE_PCI_DEV_ID_DECL_IXGBE(vend, dev) case (dev):
#include <rte_pci_dev_ids.h>
ixgbe_kni_remove(kni_devs[i]->pci_dev);
break;
default:
break;
}
unregister_netdev(kni_devs[i]->net_dev);
free_netdev(kni_devs[i]->net_dev);
kni_devs[i] = NULL;
}
}
num_devs = 0;
/* Clear the bit of device in use */
clear_bit(KNI_DEV_IN_USE_BIT_NUM, &device_in_use);
KNI_PRINT("/dev/kni closed\n");
return 0;
}
static int
kni_thread(void *unused)
{
int i, j;
KNI_PRINT("Kernel thread for KNI started\n");
while (!kthread_should_stop()) {
int n_devs = num_devs;
for (j = 0; j < KNI_RX_LOOP_NUM; j++) {
for (i = 0; i < n_devs; i++) {
/* This shouldn't be needed */
if (kni_devs[i]) {
kni_net_rx(kni_devs[i]);
kni_net_poll_resp(kni_devs[i]);
}
else
KNI_ERR("kni_thread -no kni found!!!");
}
}
/* reschedule out for a while */
schedule_timeout_interruptible(usecs_to_jiffies( \
KNI_KTHREAD_RESCHEDULE_INTERVAL));
}
KNI_PRINT("Kernel thread for KNI stopped\n");
return 0;
}
static int
kni_check_pci_device_id(uint16_t vendor_id, uint16_t device_id)
{
int i, total = sizeof(kni_pci_ids)/sizeof(struct pci_device_id);
struct pci_device_id *p;
/* Check if the vendor id/device id are supported */
for (i = 0; i < total; i++) {
p = &kni_pci_ids[i];
if (p->vendor != vendor_id && p->vendor != PCI_ANY_ID)
continue;
if (p->device != device_id && p->device != PCI_ANY_ID)
continue;
return 0;
}
return -1;
}
static int
kni_ioctl_create(unsigned int ioctl_num, unsigned long ioctl_param)
{
int ret;
struct rte_kni_device_info dev_info;
struct pci_dev *pci = NULL;
struct pci_dev *found_pci = NULL;
struct net_device *net_dev = NULL;
struct net_device *lad_dev = NULL;
struct kni_dev *kni;
if (num_devs == KNI_MAX_DEVICES)
return -EBUSY;
/* Check the buffer size, to avoid warning */
if (_IOC_SIZE(ioctl_num) > sizeof(dev_info))
return -EINVAL;
/* Copy kni info from user space */
ret = copy_from_user(&dev_info, (void *)ioctl_param,
_IOC_SIZE(ioctl_num));
if (ret) {
KNI_ERR("copy_from_user");
return -EIO;
}
/* Check if the PCI id is supported by KNI */
ret = kni_check_pci_device_id(dev_info.vendor_id, dev_info.device_id);
if (ret < 0) {
KNI_ERR("Invalid vendor_id: %x or device_id: %x\n",
dev_info.vendor_id, dev_info.device_id);
return -EINVAL;
}
net_dev = alloc_netdev(sizeof(struct kni_dev), dev_info.name,
kni_net_init);
if (net_dev == NULL) {
KNI_ERR("error allocating device \"%s\"\n", dev_info.name);
return -EBUSY;
}
kni = netdev_priv(net_dev);
kni->net_dev = net_dev;
kni->idx = num_devs;
/* Translate user space info into kernel space info */
kni->tx_q = phys_to_virt(dev_info.tx_phys);
kni->rx_q = phys_to_virt(dev_info.rx_phys);
kni->alloc_q = phys_to_virt(dev_info.alloc_phys);
kni->free_q = phys_to_virt(dev_info.free_phys);
kni->req_q = phys_to_virt(dev_info.req_phys);
kni->resp_q = phys_to_virt(dev_info.resp_phys);
kni->sync_va = dev_info.sync_va;
kni->sync_kva = phys_to_virt(dev_info.sync_phys);
kni->mbuf_kva = phys_to_virt(dev_info.mbuf_phys);
kni->mbuf_va = dev_info.mbuf_va;
kni->mbuf_size = dev_info.mbuf_size;
KNI_PRINT("tx_phys: 0x%016llx, tx_q addr: 0x%p\n",
dev_info.tx_phys, kni->tx_q);
KNI_PRINT("rx_phys: 0x%016llx, rx_q addr: 0x%p\n",
dev_info.rx_phys, kni->rx_q);
KNI_PRINT("alloc_phys: 0x%016llx, alloc_q addr: 0x%p\n",
dev_info.alloc_phys, kni->alloc_q);
KNI_PRINT("free_phys: 0x%016llx, free_q addr: 0x%p\n",
dev_info.free_phys, kni->free_q);
KNI_PRINT("req_phys: 0x%016llx, req_q addr: 0x%p\n",
dev_info.req_phys, kni->req_q);
KNI_PRINT("resp_phys: 0x%016llx, resp_q addr: 0x%p\n",
dev_info.resp_phys, kni->resp_q);
KNI_PRINT("mbuf_phys: 0x%016llx, mbuf_kva: 0x%p\n",
dev_info.mbuf_phys, kni->mbuf_kva);
KNI_PRINT("mbuf_va: 0x%p\n", dev_info.mbuf_va);
KNI_PRINT("mbuf_size: %u\n", kni->mbuf_size);
KNI_DBG("PCI: %02x:%02x.%02x %04x:%04x\n", dev_info.bus, dev_info.devid,
dev_info.function, dev_info.vendor_id, dev_info.device_id);
pci = pci_get_device(dev_info.vendor_id, dev_info.device_id, NULL);
/* Support Ethtool */
while (pci) {
KNI_PRINT("pci_bus: %02x:%02x:%02x \n", pci->bus->number,
PCI_SLOT(pci->devfn), PCI_FUNC(pci->devfn));
if ((pci->bus->number == dev_info.bus) &&
(PCI_SLOT(pci->devfn) == dev_info.devid) &&
(PCI_FUNC(pci->devfn) == dev_info.function)) {
found_pci = pci;
switch (dev_info.device_id) {
#define RTE_PCI_DEV_ID_DECL_IGB(vend, dev) case (dev):
#include <rte_pci_dev_ids.h>
ret = igb_kni_probe(found_pci, &lad_dev);
break;
#define RTE_PCI_DEV_ID_DECL_IXGBE(vend, dev) case (dev):
#include <rte_pci_dev_ids.h>
ret = ixgbe_kni_probe(found_pci, &lad_dev);
break;
default:
ret = -1;
break;
}
KNI_DBG("PCI found: pci=0x%p, lad_dev=0x%p\n", pci, lad_dev);
if (ret == 0) {
kni->lad_dev = lad_dev;
kni_set_ethtool_ops(kni->net_dev);
}
else {
KNI_ERR("Device not supported by ethtool");
kni->lad_dev = NULL;
}
kni->pci_dev = found_pci;
kni->device_id = dev_info.device_id;
break;
}
pci = pci_get_device(dev_info.vendor_id, dev_info.device_id,
pci);
}
if (pci)
pci_dev_put(pci);
ret = register_netdev(net_dev);
if (ret) {
KNI_ERR("error %i registering device \"%s\"\n", ret,
dev_info.name);
free_netdev(net_dev);
return -ENODEV;
}
kni_devs[num_devs++] = kni;
return 0;
}
static int
kni_ioctl(struct inode *inode,
unsigned int ioctl_num,
unsigned long ioctl_param)
{
int ret = -EINVAL;
KNI_DBG("IOCTL num=0x%0x param=0x%0lx \n", ioctl_num, ioctl_param);
/*
* Switch according to the ioctl called
*/
switch (_IOC_NR(ioctl_num)) {
case _IOC_NR(RTE_KNI_IOCTL_TEST):
/* For test only, not used */
break;
case _IOC_NR(RTE_KNI_IOCTL_CREATE):
ret = kni_ioctl_create(ioctl_num, ioctl_param);
break;
default:
KNI_DBG("IOCTL default \n");
break;
}
return ret;
}
static int
kni_compat_ioctl(struct inode *inode,
unsigned int ioctl_num,
unsigned long ioctl_param)
{
/* 32 bits app on 64 bits OS to be supported later */
KNI_PRINT("Not implemented.\n");
return -EINVAL;
}
module_init(kni_init);
module_exit(kni_exit);
module_param(lo_mode, charp, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(lo_mode,
"KNI loopback mode (default=lo_mode_none):\n"
" lo_mode_none Kernel loopback disabled\n"
" lo_mode_fifo Enable kernel loopback with fifo\n"
" lo_mode_fifo_skb Enable kernel loopback with fifo and skb buffer\n"
"\n"
);

View File

@ -0,0 +1,730 @@
/*-
* GPL LICENSE SUMMARY
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* Contact Information:
* Intel Corporation
*
*/
/*
* This code is inspired from the book "Linux Device Drivers" by
* Alessandro Rubini and Jonathan Corbet, published by O'Reilly & Associates
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h> /* eth_type_trans */
#include <linux/skbuff.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <rte_config.h>
#include <exec-env/rte_kni_common.h>
#include "kni_dev.h"
#define WD_TIMEOUT 5 /*jiffies */
#define MBUF_BURST_SZ 32
#define KNI_WAIT_RESPONSE_TIMEOUT 300 /* 3 seconds */
/* typedef for rx function */
typedef void (*kni_net_rx_t)(struct kni_dev *kni);
static int kni_net_tx(struct sk_buff *skb, struct net_device *dev);
static void kni_net_rx_normal(struct kni_dev *kni);
static void kni_net_rx_lo_fifo(struct kni_dev *kni);
static void kni_net_rx_lo_fifo_skb(struct kni_dev *kni);
static int kni_net_process_request(struct kni_dev *kni,
struct rte_kni_request *req);
/* kni rx function pointer, with default to normal rx */
static kni_net_rx_t kni_net_rx_func = kni_net_rx_normal;
/**
* Adds num elements into the fifo. Return the number actually written
*/
static inline unsigned
kni_fifo_put(struct rte_kni_fifo *fifo, void **data, unsigned num)
{
unsigned i = 0;
unsigned fifo_write = fifo->write;
unsigned fifo_read = fifo->read;
unsigned new_write = fifo_write;
for (i = 0; i < num; i++) {
new_write = (new_write + 1) & (fifo->len - 1);
if (new_write == fifo_read)
break;
fifo->buffer[fifo_write] = data[i];
fifo_write = new_write;
}
fifo->write = fifo_write;
return i;
}
/**
* Get up to num elements from the fifo. Return the number actully read
*/
static inline unsigned
kni_fifo_get(struct rte_kni_fifo *fifo, void **data, unsigned num)
{
unsigned i = 0;
unsigned new_read = fifo->read;
unsigned fifo_write = fifo->write;
for (i = 0; i < num; i++) {
if (new_read == fifo_write)
break;
data[i] = fifo->buffer[new_read];
new_read = (new_read + 1) & (fifo->len - 1);
}
fifo->read = new_read;
return i;
}
/**
* Get the num of elements in the fifo
*/
static inline unsigned
kni_fifo_count(struct rte_kni_fifo *fifo)
{
return (fifo->len + fifo->write - fifo->read) &( fifo->len - 1);
}
/**
* Get the num of available lements in the fifo
*/
static inline unsigned
kni_fifo_free_count(struct rte_kni_fifo *fifo)
{
return (fifo->read - fifo->write - 1) & (fifo->len - 1);
}
/*
* Open and close
*/
static int
kni_net_open(struct net_device *dev)
{
int ret;
struct rte_kni_request req;
struct kni_dev *kni = netdev_priv(dev);
KNI_DBG("kni_net_open %d\n", kni->idx);
/*
* Assign the hardware address of the board: use "\0KNIx", where
* x is KNI index. The first byte is '\0' to avoid being a multicast
* address (the first byte of multicast addrs is odd).
*/
if (kni->lad_dev)
memcpy(dev->dev_addr, kni->lad_dev->dev_addr, ETH_ALEN);
else {
memcpy(dev->dev_addr, "\0KNI0", ETH_ALEN);
dev->dev_addr[ETH_ALEN-1] += kni->idx; /* \0KNI1 */
}
netif_start_queue(dev);
memset(&req, 0, sizeof(req));
req.req_id = RTE_KNI_REQ_CFG_NETWORK_IF;
/* Setting if_up to non-zero means up */
req.if_up = 1;
ret = kni_net_process_request(kni, &req);
return (ret == 0 ? req.result : ret);
}
static int
kni_net_release(struct net_device *dev)
{
int ret;
struct rte_kni_request req;
struct kni_dev *kni = netdev_priv(dev);
netif_stop_queue(dev); /* can't transmit any more */
memset(&req, 0, sizeof(req));
req.req_id = RTE_KNI_REQ_CFG_NETWORK_IF;
/* Setting if_up to 0 means down */
req.if_up = 0;
ret = kni_net_process_request(kni, &req);
return (ret == 0 ? req.result : ret);
}
/*
* Configuration changes (passed on by ifconfig)
*/
static int
kni_net_config(struct net_device *dev, struct ifmap *map)
{
if (dev->flags & IFF_UP) /* can't act on a running interface */
return -EBUSY;
/* ignore other fields */
return 0;
}
/*
* RX: normal working mode
*/
static void
kni_net_rx_normal(struct kni_dev *kni)
{
unsigned ret;
uint32_t len;
unsigned i, num, num_rq, num_fq;
struct rte_kni_mbuf *kva;
struct rte_kni_mbuf *va[MBUF_BURST_SZ];
void * data_kva;
struct sk_buff *skb;
struct net_device *dev = kni->net_dev;
/* Get the number of entries in rx_q */
num_rq = kni_fifo_count(kni->rx_q);
/* Get the number of free entries in free_q */
num_fq = kni_fifo_free_count(kni->free_q);
/* Calculate the number of entries to dequeue in rx_q */
num = min(num_rq, num_fq);
num = min(num, (unsigned)MBUF_BURST_SZ);
/* Return if no entry in rx_q and no free entry in free_q */
if (num == 0)
return;
/* Burst dequeue from rx_q */
ret = kni_fifo_get(kni->rx_q, (void **)va, num);
if (ret == 0)
return; /* Failing should not happen */
/* Transfer received packets to netif */
for (i = 0; i < num; i++) {
kva = (void *)va[i] - kni->mbuf_va + kni->mbuf_kva;
len = kva->data_len;
data_kva = kva->data - kni->mbuf_va + kni->mbuf_kva;
skb = dev_alloc_skb(len + 2);
if (!skb) {
KNI_ERR("Out of mem, dropping pkts\n");
/* Update statistics */
kni->stats.rx_dropped++;
}
else {
/* Align IP on 16B boundary */
skb_reserve(skb, 2);
memcpy(skb_put(skb, len), data_kva, len);
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev);
skb->ip_summed = CHECKSUM_UNNECESSARY;
/* Call netif interface */
netif_rx(skb);
/* Update statistics */
kni->stats.rx_bytes += len;
kni->stats.rx_packets++;
}
}
/* Burst enqueue mbufs into free_q */
ret = kni_fifo_put(kni->free_q, (void **)va, num);
if (ret != num)
/* Failing should not happen */
KNI_ERR("Fail to enqueue entries into free_q\n");
}
/*
* RX: loopback with enqueue/dequeue fifos.
*/
static void
kni_net_rx_lo_fifo(struct kni_dev *kni)
{
unsigned ret;
uint32_t len;
unsigned i, num, num_rq, num_tq, num_aq, num_fq;
struct rte_kni_mbuf *kva;
struct rte_kni_mbuf *va[MBUF_BURST_SZ];
void * data_kva;
struct rte_kni_mbuf *alloc_kva;
struct rte_kni_mbuf *alloc_va[MBUF_BURST_SZ];
void *alloc_data_kva;
/* Get the number of entries in rx_q */
num_rq = kni_fifo_count(kni->rx_q);
/* Get the number of free entrie in tx_q */
num_tq = kni_fifo_free_count(kni->tx_q);
/* Get the number of entries in alloc_q */
num_aq = kni_fifo_count(kni->alloc_q);
/* Get the number of free entries in free_q */
num_fq = kni_fifo_free_count(kni->free_q);
/* Calculate the number of entries to be dequeued from rx_q */
num = min(num_rq, num_tq);
num = min(num, num_aq);
num = min(num, num_fq);
num = min(num, (unsigned)MBUF_BURST_SZ);
/* Return if no entry to dequeue from rx_q */
if (num == 0)
return;
/* Burst dequeue from rx_q */
ret = kni_fifo_get(kni->rx_q, (void **)va, num);
if (ret == 0)
return; /* Failing should not happen */
/* Dequeue entries from alloc_q */
ret = kni_fifo_get(kni->alloc_q, (void **)alloc_va, num);
if (ret) {
num = ret;
/* Copy mbufs */
for (i = 0; i < num; i++) {
kva = (void *)va[i] - kni->mbuf_va + kni->mbuf_kva;
len = kva->pkt_len;
data_kva = kva->data - kni->mbuf_va +
kni->mbuf_kva;
alloc_kva = (void *)alloc_va[i] - kni->mbuf_va +
kni->mbuf_kva;
alloc_data_kva = alloc_kva->data - kni->mbuf_va +
kni->mbuf_kva;
memcpy(alloc_data_kva, data_kva, len);
alloc_kva->pkt_len = len;
alloc_kva->data_len = len;
kni->stats.tx_bytes += len;
kni->stats.rx_bytes += len;
}
/* Burst enqueue mbufs into tx_q */
ret = kni_fifo_put(kni->tx_q, (void **)alloc_va, num);
if (ret != num)
/* Failing should not happen */
KNI_ERR("Fail to enqueue mbufs into tx_q\n");
}
/* Burst enqueue mbufs into free_q */
ret = kni_fifo_put(kni->free_q, (void **)va, num);
if (ret != num)
/* Failing should not happen */
KNI_ERR("Fail to enqueue mbufs into free_q\n");
/**
* Update statistic, and enqueue/dequeue failure is impossible,
* as all queues are checked at first.
*/
kni->stats.tx_packets += num;
kni->stats.rx_packets += num;
}
/*
* RX: loopback with enqueue/dequeue fifos and sk buffer copies.
*/
static void
kni_net_rx_lo_fifo_skb(struct kni_dev *kni)
{
unsigned ret;
uint32_t len;
unsigned i, num_rq, num_fq, num;
struct rte_kni_mbuf *kva;
struct rte_kni_mbuf *va[MBUF_BURST_SZ];
void * data_kva;
struct sk_buff *skb;
struct net_device *dev = kni->net_dev;
/* Get the number of entries in rx_q */
num_rq = kni_fifo_count(kni->rx_q);
/* Get the number of free entries in free_q */
num_fq = kni_fifo_free_count(kni->free_q);
/* Calculate the number of entries to dequeue from rx_q */
num = min(num_rq, num_fq);
num = min(num, (unsigned)MBUF_BURST_SZ);
/* Return if no entry to dequeue from rx_q */
if (num == 0)
return;
/* Burst dequeue mbufs from rx_q */
ret = kni_fifo_get(kni->rx_q, (void **)va, num);
if (ret == 0)
return;
/* Copy mbufs to sk buffer and then call tx interface */
for (i = 0; i < num; i++) {
kva = (void *)va[i] - kni->mbuf_va + kni->mbuf_kva;
len = kva->data_len;
data_kva = kva->data - kni->mbuf_va + kni->mbuf_kva;
skb = dev_alloc_skb(len + 2);
if (skb == NULL)
KNI_ERR("Out of mem, dropping pkts\n");
else {
/* Align IP on 16B boundary */
skb_reserve(skb, 2);
memcpy(skb_put(skb, len), data_kva, len);
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev);
skb->ip_summed = CHECKSUM_UNNECESSARY;
dev_kfree_skb(skb);
}
/* Simulate real usage, allocate/copy skb twice */
skb = dev_alloc_skb(len + 2);
if (skb == NULL) {
KNI_ERR("Out of mem, dropping pkts\n");
kni->stats.rx_dropped++;
}
else {
/* Align IP on 16B boundary */
skb_reserve(skb, 2);
memcpy(skb_put(skb, len), data_kva, len);
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev);
skb->ip_summed = CHECKSUM_UNNECESSARY;
kni->stats.rx_bytes += len;
kni->stats.rx_packets++;
/* call tx interface */
kni_net_tx(skb, dev);
}
}
/* enqueue all the mbufs from rx_q into free_q */
ret = kni_fifo_put(kni->free_q, (void **)&va, num);
if (ret != num)
/* Failing should not happen */
KNI_ERR("Fail to enqueue mbufs into free_q\n");
}
/* rx interface */
void
kni_net_rx(struct kni_dev *kni)
{
/**
* It doesn't need to check if it is NULL pointer,
* as it has a default value
*/
(*kni_net_rx_func)(kni);
}
/*
* Transmit a packet (called by the kernel)
*/
static int
kni_net_tx(struct sk_buff *skb, struct net_device *dev)
{
int len = 0;
unsigned ret;
struct kni_dev *kni = netdev_priv(dev);
struct rte_kni_mbuf *pkt_kva = NULL;
struct rte_kni_mbuf *pkt_va = NULL;
dev->trans_start = jiffies; /* save the timestamp */
/* Check if the length of skb is less than mbuf size */
if (skb->len > kni->mbuf_size)
goto drop;
/**
* Check if it has at least one free entry in tx_q and
* one entry in alloc_q.
*/
if (kni_fifo_free_count(kni->tx_q) == 0 ||
kni_fifo_count(kni->alloc_q) == 0) {
/**
* If no free entry in tx_q or no entry in alloc_q,
* drops skb and goes out.
*/
goto drop;
}
/* dequeue a mbuf from alloc_q */
ret = kni_fifo_get(kni->alloc_q, (void **)&pkt_va, 1);
if (likely(ret == 1)) {
void *data_kva;
pkt_kva = (void *)pkt_va - kni->mbuf_va + kni->mbuf_kva;
data_kva = pkt_kva->data - kni->mbuf_va + kni->mbuf_kva;
len = skb->len;
memcpy(data_kva, skb->data, len);
if (unlikely(len < ETH_ZLEN)) {
memset(data_kva + len, 0, ETH_ZLEN - len);
len = ETH_ZLEN;
}
pkt_kva->pkt_len = len;
pkt_kva->data_len = len;
/* enqueue mbuf into tx_q */
ret = kni_fifo_put(kni->tx_q, (void **)&pkt_va, 1);
if (unlikely(ret != 1)) {
/* Failing should not happen */
KNI_ERR("Fail to enqueue mbuf into tx_q\n");
goto drop;
}
} else {
/* Failing should not happen */
KNI_ERR("Fail to dequeue mbuf from alloc_q\n");
goto drop;
}
/* Free skb and update statistics */
dev_kfree_skb(skb);
kni->stats.tx_bytes += len;
kni->stats.tx_packets++;
return NETDEV_TX_OK;
drop:
/* Free skb and update statistics */
dev_kfree_skb(skb);
kni->stats.tx_dropped++;
return NETDEV_TX_OK;
}
/*
* Deal with a transmit timeout.
*/
static void
kni_net_tx_timeout (struct net_device *dev)
{
struct kni_dev *kni = netdev_priv(dev);
KNI_DBG("Transmit timeout at %ld, latency %ld\n", jiffies,
jiffies - dev->trans_start);
kni->stats.tx_errors++;
netif_wake_queue(dev);
return;
}
/*
* Ioctl commands
*/
static int
kni_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct kni_dev *kni = netdev_priv(dev);
KNI_DBG("kni_net_ioctl %d\n", kni->idx);
return 0;
}
static int
kni_net_change_mtu(struct net_device *dev, int new_mtu)
{
int ret;
struct rte_kni_request req;
struct kni_dev *kni = netdev_priv(dev);
KNI_DBG("kni_net_change_mtu new mtu %d to be set\n", new_mtu);
memset(&req, 0, sizeof(req));
req.req_id = RTE_KNI_REQ_CHANGE_MTU;
req.new_mtu = new_mtu;
ret = kni_net_process_request(kni, &req);
if (ret == 0 && req.result == 0)
dev->mtu = new_mtu;
return (ret == 0 ? req.result : ret);
}
/*
* Checks if the user space application provided the resp message
*/
void
kni_net_poll_resp(struct kni_dev *kni)
{
int i = kni_fifo_count(kni->resp_q);
if (i) {
wake_up_interruptible(&kni->wq);
}
}
/*
* It can be called to process the request.
*/
static int
kni_net_process_request(struct kni_dev *kni, struct rte_kni_request *req)
{
int ret = -1;
void *resp_va;
unsigned num;
int ret_val;
if (!kni || !req) {
KNI_ERR("No kni instance or request\n");
return -EINVAL;
}
mutex_lock(&kni->sync_lock);
/* Construct data */
memcpy(kni->sync_kva, req, sizeof(struct rte_kni_request));
num = kni_fifo_put(kni->req_q, &kni->sync_va, 1);
if (num < 1) {
KNI_ERR("Cannot send to req_q\n");
ret = -EBUSY;
goto fail;
}
ret_val = wait_event_interruptible_timeout(kni->wq,
kni_fifo_count(kni->resp_q), 3 * HZ);
if (signal_pending(current) || ret_val <= 0) {
ret = -ETIME;
goto fail;
}
num = kni_fifo_get(kni->resp_q, (void **)&resp_va, 1);
if (num != 1 || resp_va != kni->sync_va) {
/* This should never happen */
KNI_ERR("No data in resp_q\n");
ret = -ENODATA;
goto fail;
}
memcpy(req, kni->sync_kva, sizeof(struct rte_kni_request));
ret = 0;
fail:
mutex_unlock(&kni->sync_lock);
return ret;
}
/*
* Return statistics to the caller
*/
static struct net_device_stats *
kni_net_stats(struct net_device *dev)
{
struct kni_dev *kni = netdev_priv(dev);
return &kni->stats;
}
/*
* Fill the eth header
*/
static int
kni_net_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, const void *daddr,
const void *saddr, unsigned int len)
{
struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
memcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len);
memcpy(eth->h_dest, daddr ? daddr : dev->dev_addr, dev->addr_len);
eth->h_proto = htons(type);
return (dev->hard_header_len);
}
/*
* Re-fill the eth header
*/
static int
kni_net_rebuild_header(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
struct ethhdr *eth = (struct ethhdr *) skb->data;
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
memcpy(eth->h_dest, dev->dev_addr, dev->addr_len);
return 0;
}
static const struct header_ops kni_net_header_ops = {
.create = kni_net_header,
.rebuild = kni_net_rebuild_header,
.cache = NULL, /* disable caching */
};
static const struct net_device_ops kni_net_netdev_ops = {
.ndo_open = kni_net_open,
.ndo_stop = kni_net_release,
.ndo_set_config = kni_net_config,
.ndo_start_xmit = kni_net_tx,
.ndo_change_mtu = kni_net_change_mtu,
.ndo_do_ioctl = kni_net_ioctl,
.ndo_get_stats = kni_net_stats,
.ndo_tx_timeout = kni_net_tx_timeout,
};
void
kni_net_init(struct net_device *dev)
{
struct kni_dev *kni = netdev_priv(dev);
KNI_DBG("kni_net_init\n");
init_waitqueue_head(&kni->wq);
mutex_init(&kni->sync_lock);
ether_setup(dev); /* assign some of the fields */
dev->netdev_ops = &kni_net_netdev_ops;
dev->header_ops = &kni_net_header_ops;
dev->watchdog_timeo = WD_TIMEOUT;
}
void
kni_net_config_lo_mode(char *lo_str)
{
if (!lo_str) {
KNI_PRINT("loopback disabled");
return;
}
if (!strcmp(lo_str, "lo_mode_none"))
KNI_PRINT("loopback disabled");
else if (!strcmp(lo_str, "lo_mode_fifo")) {
KNI_PRINT("loopback mode=lo_mode_fifo enabled");
kni_net_rx_func = kni_net_rx_lo_fifo;
} else if (!strcmp(lo_str, "lo_mode_fifo_skb")) {
KNI_PRINT("loopback mode=lo_mode_fifo_skb enabled");
kni_net_rx_func = kni_net_rx_lo_fifo_skb;
} else
KNI_PRINT("Incognizant parameter, loopback disabled");
}

50
lib/librte_kni/Makefile Normal file
View File

@ -0,0 +1,50 @@
# BSD LICENSE
#
# Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
include $(RTE_SDK)/mk/rte.vars.mk
# library name
LIB = librte_kni.a
CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 -fno-strict-aliasing
# all source are stored in SRCS-y
SRCS-$(CONFIG_RTE_LIBRTE_KNI) := rte_kni.c
# install includes
SYMLINK-$(CONFIG_RTE_LIBRTE_KNI)-include := rte_kni.h
# this lib needs eal
DEPDIRS-$(CONFIG_RTE_LIBRTE_KNI) += lib/librte_eal lib/librte_mbuf
DEPDIRS-$(CONFIG_RTE_LIBRTE_KNI) += lib/librte_ether
include $(RTE_SDK)/mk/rte.lib.mk

367
lib/librte_kni/rte_kni.c Executable file
View File

@ -0,0 +1,367 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef RTE_EXEC_ENV_LINUXAPP
#error "KNI is not supported"
#endif
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <linux/if.h>
#include <rte_string_fns.h>
#include <rte_ethdev.h>
#include <rte_malloc.h>
#include <rte_log.h>
#include <rte_kni.h>
#include <rte_memzone.h>
#include <exec-env/rte_kni_common.h>
#include "rte_kni_fifo.h"
#define MAX_MBUF_BURST_NUM 32
/* Maximum number of ring entries */
#define KNI_FIFO_COUNT_MAX 1024
#define KNI_FIFO_SIZE (KNI_FIFO_COUNT_MAX * sizeof(void *) + \
sizeof(struct rte_kni_fifo))
#define KNI_REQUEST_MBUF_NUM_MAX 32
/**
* KNI context
*/
struct rte_kni {
char name[IFNAMSIZ]; /**< KNI interface name */
uint8_t port_id; /**< Port id KNI associate with */
struct rte_mempool *pktmbuf_pool; /**< pkt mbuf mempool */
unsigned mbuf_size; /**< mbuf size */
struct rte_kni_fifo *tx_q; /**< TX queue */
struct rte_kni_fifo *rx_q; /**< RX queue */
struct rte_kni_fifo *alloc_q; /**< Allocated mbufs queue */
struct rte_kni_fifo *free_q; /**< To be freed mbufs queue */
/* For request & response */
struct rte_kni_fifo *req_q; /**< Request queue */
struct rte_kni_fifo *resp_q; /**< Response queue */
void * sync_addr; /**< Req/Resp Mem address */
struct rte_kni_ops ops; /**< operations for request */
};
static void kni_free_mbufs(struct rte_kni *kni);
static void kni_allocate_mbufs(struct rte_kni *kni);
static int kni_fd = -1;
struct rte_kni *
rte_kni_create(uint8_t port_id,
unsigned mbuf_size,
struct rte_mempool *pktmbuf_pool,
struct rte_kni_ops *ops)
{
struct rte_kni_device_info dev_info;
struct rte_eth_dev_info eth_dev_info;
struct rte_kni *ctx;
char itf_name[IFNAMSIZ];
#define OBJNAMSIZ 32
char obj_name[OBJNAMSIZ];
const struct rte_memzone *mz;
if (port_id >= RTE_MAX_ETHPORTS || pktmbuf_pool == NULL || !ops)
return NULL;
/* Check FD and open once */
if (kni_fd < 0) {
kni_fd = open("/dev/" KNI_DEVICE, O_RDWR);
if (kni_fd < 0) {
RTE_LOG(ERR, KNI, "Can not open /dev/%s\n",
KNI_DEVICE);
return NULL;
}
}
rte_eth_dev_info_get(port_id, &eth_dev_info);
RTE_LOG(INFO, KNI, "pci: %02x:%02x:%02x \t %02x:%02x\n",
eth_dev_info.pci_dev->addr.bus,
eth_dev_info.pci_dev->addr.devid,
eth_dev_info.pci_dev->addr.function,
eth_dev_info.pci_dev->id.vendor_id,
eth_dev_info.pci_dev->id.device_id);
dev_info.bus = eth_dev_info.pci_dev->addr.bus;
dev_info.devid = eth_dev_info.pci_dev->addr.devid;
dev_info.function = eth_dev_info.pci_dev->addr.function;
dev_info.vendor_id = eth_dev_info.pci_dev->id.vendor_id;
dev_info.device_id = eth_dev_info.pci_dev->id.device_id;
ctx = rte_zmalloc("kni devs", sizeof(struct rte_kni), 0);
if (ctx == NULL)
rte_panic("Cannot allocate memory for kni dev\n");
memcpy(&ctx->ops, ops, sizeof(struct rte_kni_ops));
rte_snprintf(itf_name, IFNAMSIZ, "vEth%u", port_id);
rte_snprintf(ctx->name, IFNAMSIZ, itf_name);
rte_snprintf(dev_info.name, IFNAMSIZ, itf_name);
/* TX RING */
rte_snprintf(obj_name, OBJNAMSIZ, "kni_tx_%d", port_id);
mz = rte_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
if (mz == NULL || mz->addr == NULL)
rte_panic("Cannot create kni_tx_%d queue\n", port_id);
ctx->tx_q = mz->addr;
kni_fifo_init(ctx->tx_q, KNI_FIFO_COUNT_MAX);
dev_info.tx_phys = mz->phys_addr;
/* RX RING */
rte_snprintf(obj_name, OBJNAMSIZ, "kni_rx_%d", port_id);
mz = rte_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
if (mz == NULL || mz->addr == NULL)
rte_panic("Cannot create kni_rx_%d queue\n", port_id);
ctx->rx_q = mz->addr;
kni_fifo_init(ctx->rx_q, KNI_FIFO_COUNT_MAX);
dev_info.rx_phys = mz->phys_addr;
/* ALLOC RING */
rte_snprintf(obj_name, OBJNAMSIZ, "kni_alloc_%d", port_id);
mz = rte_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
if (mz == NULL || mz->addr == NULL)
rte_panic("Cannot create kni_alloc_%d queue\n", port_id);
ctx->alloc_q = mz->addr;
kni_fifo_init(ctx->alloc_q, KNI_FIFO_COUNT_MAX);
dev_info.alloc_phys = mz->phys_addr;
/* FREE RING */
rte_snprintf(obj_name, OBJNAMSIZ, "kni_free_%d", port_id);
mz = rte_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
if (mz == NULL || mz->addr == NULL)
rte_panic("Cannot create kni_free_%d queue\n", port_id);
ctx->free_q = mz->addr;
kni_fifo_init(ctx->free_q, KNI_FIFO_COUNT_MAX);
dev_info.free_phys = mz->phys_addr;
/* Request RING */
rte_snprintf(obj_name, OBJNAMSIZ, "kni_req_%d", port_id);
mz = rte_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
if (mz == NULL || mz->addr == NULL)
rte_panic("Cannot create kni_req_%d ring\n", port_id);
ctx->req_q = mz->addr;
kni_fifo_init(ctx->req_q, KNI_FIFO_COUNT_MAX);
dev_info.req_phys = mz->phys_addr;
/* Response RING */
rte_snprintf(obj_name, OBJNAMSIZ, "kni_resp_%d", port_id);
mz = rte_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
if (mz == NULL || mz->addr == NULL)
rte_panic("Cannot create kni_resp_%d ring\n", port_id);
ctx->resp_q = mz->addr;
kni_fifo_init(ctx->resp_q, KNI_FIFO_COUNT_MAX);
dev_info.resp_phys = mz->phys_addr;
/* Req/Resp sync mem area */
rte_snprintf(obj_name, OBJNAMSIZ, "kni_sync_%d", port_id);
mz = rte_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
if (mz == NULL || mz->addr == NULL)
rte_panic("Cannot create kni_sync_%d mem\n", port_id);
ctx->sync_addr = mz->addr;
dev_info.sync_va = mz->addr;
dev_info.sync_phys = mz->phys_addr;
/* MBUF mempool */
mz = rte_memzone_lookup("MP_mbuf_pool");
if (mz == NULL) {
RTE_LOG(ERR, KNI, "Can not find MP_mbuf_pool\n");
goto fail;
}
dev_info.mbuf_va = mz->addr;
dev_info.mbuf_phys = mz->phys_addr;
ctx->pktmbuf_pool = pktmbuf_pool;
ctx->port_id = port_id;
ctx->mbuf_size = mbuf_size;
/* Configure the buffer size which will be checked in kernel module */
dev_info.mbuf_size = ctx->mbuf_size;
if (ioctl(kni_fd, RTE_KNI_IOCTL_CREATE, &dev_info) < 0) {
RTE_LOG(ERR, KNI, "Fail to create kni device\n");
goto fail;
}
return ctx;
fail:
if (ctx != NULL)
rte_free(ctx);
return NULL;
}
/**
* It is called in the same lcore of receiving packets, and polls the request
* mbufs sent from kernel space. Then analyzes it and calls the specific
* actions for the specific requests. Finally constructs the response mbuf and
* puts it back to the resp_q.
*/
static int
kni_request_handler(struct rte_kni *kni)
{
unsigned ret;
struct rte_kni_request *req;
if (kni == NULL)
return -1;
/* Get request mbuf */
ret = kni_fifo_get(kni->req_q, (void **)&req, 1);
if (ret != 1)
return 0; /* It is OK of can not getting the request mbuf */
if (req != kni->sync_addr) {
rte_panic("Wrong req pointer %p\n", req);
}
/* Analyze the request and call the relevant actions for it */
switch (req->req_id) {
case RTE_KNI_REQ_CHANGE_MTU: /* Change MTU */
if (kni->ops.change_mtu)
req->result = kni->ops.change_mtu(kni->port_id,
req->new_mtu);
break;
case RTE_KNI_REQ_CFG_NETWORK_IF: /* Set network interface up/down */
if (kni->ops.config_network_if)
req->result = kni->ops.config_network_if(kni->port_id,
req->if_up);
break;
default:
RTE_LOG(ERR, KNI, "Unknown request id %u\n", req->req_id);
req->result = -EINVAL;
break;
}
/* Construct response mbuf and put it back to resp_q */
ret = kni_fifo_put(kni->resp_q, (void **)&req, 1);
if (ret != 1) {
RTE_LOG(ERR, KNI, "Fail to put the muf back to resp_q\n");
return -1; /* It is an error of can't putting the mbuf back */
}
return 0;
}
unsigned
rte_kni_tx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned num)
{
unsigned ret = kni_fifo_put(kni->rx_q, (void **)mbufs, num);
/* Get mbufs from free_q and then free them */
kni_free_mbufs(kni);
/* Handle the requests from kernel space */
kni_request_handler(kni);
return ret;
}
unsigned
rte_kni_rx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned num)
{
unsigned ret = kni_fifo_get(kni->tx_q, (void **)mbufs, num);
/* Allocate mbufs and then put them into alloc_q */
kni_allocate_mbufs(kni);
return ret;
}
static void
kni_free_mbufs(struct rte_kni *kni)
{
int i, ret;
struct rte_mbuf *pkts[MAX_MBUF_BURST_NUM];
ret = kni_fifo_get(kni->free_q, (void **)pkts, MAX_MBUF_BURST_NUM);
if (likely(ret > 0)) {
for (i = 0; i < ret; i++)
rte_pktmbuf_free(pkts[i]);
}
}
static void
kni_allocate_mbufs(struct rte_kni *kni)
{
int i, ret;
struct rte_mbuf *pkts[MAX_MBUF_BURST_NUM];
/* Check if pktmbuf pool has been configured */
if (kni->pktmbuf_pool == NULL) {
RTE_LOG(ERR, KNI, "No valid mempool for allocating mbufs\n");
return;
}
for (i = 0; i < MAX_MBUF_BURST_NUM; i++) {
pkts[i] = rte_pktmbuf_alloc(kni->pktmbuf_pool);
if (unlikely(pkts[i] == NULL)) {
/* Out of memory */
RTE_LOG(ERR, KNI, "Out of memory\n");
break;
}
}
/* No pkt mbuf alocated */
if (i <= 0)
return;
ret = kni_fifo_put(kni->alloc_q, (void **)pkts, i);
/* Check if any mbufs not put into alloc_q, and then free them */
if (ret >= 0 && ret < i && ret < MAX_MBUF_BURST_NUM) {
int j;
for (j = ret; j < i; j++)
rte_pktmbuf_free(pkts[j]);
}
}
uint8_t
rte_kni_get_port_id(struct rte_kni *kni)
{
if (kni == NULL)
return ~0x0;
return kni->port_id;
}

144
lib/librte_kni/rte_kni.h Normal file
View File

@ -0,0 +1,144 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _RTE_KNI_H_
#define _RTE_KNI_H_
/**
* @file
* RTE KNI
*
* The KNI library provides the ability to create and destroy kernel NIC
* interfaces that may be used by the RTE application to receive/transmit
* packets from/to Linux kernel net interfaces.
*
* This library provide two APIs to burst receive packets from KNI interfaces,
* and burst transmit packets to KNI interfaces.
*/
#include <rte_mbuf.h>
#ifdef __cplusplus
extern "C" {
#endif
struct rte_kni;
/**
* Structure which has the function pointers for KNI interface.
*/
struct rte_kni_ops {
/* Pointer to function of changing MTU */
int (*change_mtu)(uint8_t port_id, unsigned new_mtu);
/* Pointer to function of configuring network interface */
int (*config_network_if)(uint8_t port_id, uint8_t if_up);
};
/**
* Create kni interface according to the port id. It will create a paired KNI
* interface in the kernel space for each NIC port. The KNI interface created
* in the kernel space is the net interface the traditional Linux application
* talking to.
*
* @param port_id
* The port id.
* @param pktmbuf_pool
* The mempool for allocting mbufs for packets.
* @param mbuf_size
* The mbuf size to store a packet.
*
* @return
* - The pointer to the context of a kni interface.
* - NULL indicate error.
*/
extern struct rte_kni *rte_kni_create(uint8_t port_id, unsigned mbuf_size,
struct rte_mempool *pktmbuf_pool, struct rte_kni_ops *ops);
/**
* Retrieve a burst of packets from a kni interface. The retrieved packets are
* stored in rte_mbuf structures whose pointers are supplied in the array of
* mbufs, and the maximum number is indicated by num. It handles the freeing of
* the mbufs in the free queue of kni interface.
*
* @param kni
* The kni interface context.
* @param mbufs
* The array to store the pointers of mbufs.
* @param num
* The maximum number per burst.
*
* @return
* The actual number of packets retrieved.
*/
extern unsigned rte_kni_rx_burst(struct rte_kni *kni,
struct rte_mbuf **mbufs, unsigned num);
/**
* Send a burst of packets to a kni interface. The packets to be sent out are
* stored in rte_mbuf structures whose pointers are supplied in the array of
* mbufs, and the maximum number is indicated by num. It handles allocating
* the mbufs for kni interface alloc queue.
*
* @param kni
* The kni interface context.
* @param mbufs
* The array to store the pointers of mbufs.
* @param num
* The maximum number per burst.
*
* @return
* The actual number of packets sent.
*/
extern unsigned rte_kni_tx_burst(struct rte_kni *kni,
struct rte_mbuf **mbufs, unsigned num);
/**
* Get the port id from kni interface.
*
* @param kni
* The kni interface context.
*
* @return
* On success: The port id.
* On failure: ~0x0
*/
extern uint8_t rte_kni_get_port_id(struct rte_kni *kni);
#ifdef __cplusplus
}
#endif
#endif /* _RTE_KNI_H_ */

View File

@ -0,0 +1,94 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* Initializes the kni fifo structure
*/
static void
kni_fifo_init(struct rte_kni_fifo *fifo, unsigned size)
{
/* Ensure size is power of 2 */
if (size & (size - 1))
rte_panic("KNI fifo size must be power of 2\n");
fifo->write = 0;
fifo->read = 0;
fifo->len = size;
fifo->elem_size = sizeof(void *);
}
/**
* Adds num elements into the fifo. Return the number actually written
*/
static inline unsigned
kni_fifo_put(struct rte_kni_fifo *fifo, void **data, unsigned num)
{
unsigned i = 0;
unsigned fifo_write = fifo->write;
unsigned fifo_read = fifo->read;
unsigned new_write = fifo_write;
for (i = 0; i < num; i++) {
new_write = (new_write + 1) & (fifo->len - 1);
if (new_write == fifo_read)
break;
fifo->buffer[fifo_write] = data[i];
fifo_write = new_write;
}
fifo->write = fifo_write;
return i;
}
/**
* Get up to num elements from the fifo. Return the number actully read
*/
static inline unsigned
kni_fifo_get(struct rte_kni_fifo *fifo, void **data, unsigned num)
{
unsigned i = 0;
unsigned new_read = fifo->read;
unsigned fifo_write = fifo->write;
for (i = 0; i < num; i++) {
if (new_read == fifo_write)
break;
data[i] = fifo->buffer[new_read];
new_read = (new_read + 1) & (fifo->len - 1);
}
fifo->read = new_read;
return i;
}

View File

@ -59,6 +59,12 @@ LDLIBS += -L$(RTE_SDK_BIN)/lib
#
ifeq ($(NO_AUTOLIBS),)
ifeq ($(CONFIG_RTE_LIBRTE_KNI),y)
ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
LDLIBS += -lrte_kni
endif
endif
ifeq ($(CONFIG_RTE_LIBRTE_IGB_PMD),y)
LDLIBS += -lrte_pmd_igb
endif

View File

@ -59,7 +59,7 @@ quit()
}
#
# Sets up envronment variables for ICC.
# Sets up environmental variables for ICC.
#
setup_icc()
{
@ -187,6 +187,42 @@ load_igb_uio_module()
fi
}
#
# Unloads the rte_kni.ko module.
#
remove_kni_module()
{
echo "Unloading any existing DPDK KNI module"
/sbin/lsmod | grep -s rte_kni > /dev/null
if [ $? -eq 0 ] ; then
sudo /sbin/rmmod rte_kni
fi
}
#
# Loads the rte_kni.ko module.
#
load_kni_module()
{
# Check that the KNI module is already built.
if [ ! -f $RTE_SDK/$RTE_TARGET/kmod/rte_kni.ko ];then
echo "## ERROR: Target does not have the DPDK KNI Module."
echo " To fix, please try to rebuild target."
return
fi
# Unload existing version if present.
remove_kni_module
# Now try load the KNI module.
echo "Loading DPDK KNI module"
sudo /sbin/insmod $RTE_SDK/$RTE_TARGET/kmod/rte_kni.ko
if [ $? -ne 0 ] ; then
echo "## ERROR: Could not load kmod/rte_kni.ko."
quit
fi
}
#
# Removes all reserved hugepages.
#
@ -324,11 +360,14 @@ step2_func()
TEXT[1]="Insert IGB UIO module"
FUNC[1]="load_igb_uio_module"
TEXT[2]="Setup hugepage mappings for non-NUMA systems"
FUNC[2]="set_non_numa_pages"
TEXT[2]="Insert KNI module"
FUNC[2]="load_kni_module"
TEXT[3]="Setup hugepage mappings for NUMA systems"
FUNC[3]="set_numa_pages"
TEXT[3]="Setup hugepage mappings for non-NUMA systems"
FUNC[3]="set_non_numa_pages"
TEXT[4]="Setup hugepage mappings for NUMA systems"
FUNC[4]="set_numa_pages"
}
#
@ -372,8 +411,11 @@ step5_func()
TEXT[2]="Remove IGB UIO module"
FUNC[2]="remove_igb_uio_module"
TEXT[3]="Remove hugepage mappings"
FUNC[3]="clear_huge_pages"
TEXT[3]="Remove KNI module"
FUNC[3]="remove_kni_module"
TEXT[4]="Remove hugepage mappings"
FUNC[4]="clear_huge_pages"
}
STEPS[1]="step1_func"